ADD: type addition and multiplication.

main
bog 2023-08-25 01:50:18 +02:00
parent 0b44732961
commit 9ca893dff5
10 changed files with 239 additions and 19 deletions

View File

@ -56,6 +56,11 @@ void compile_node(compiler* self, node* root, program* prog)
compile_node(self, root->children.data[0], prog); compile_node(self, root->children.data[0], prog);
program_add_instr(prog, OP_AMUL, NO_PARAM); program_add_instr(prog, OP_AMUL, NO_PARAM);
} }
else if (rhs == TY_TYPE && lhs == TY_TYPE)
{
compile_children(self, root, prog);
program_add_instr(prog, OP_TMUL, NO_PARAM);
}
else else
{ {
compile_number(self, root, prog, OP_IMUL, OP_FMUL); compile_number(self, root, prog, OP_IMUL, OP_FMUL);
@ -81,6 +86,11 @@ void compile_node(compiler* self, node* root, program* prog)
compile_children(self, root, prog); compile_children(self, root, prog);
program_add_instr(prog, OP_ACAT, NO_PARAM); program_add_instr(prog, OP_ACAT, NO_PARAM);
} }
else if (lhs == rhs && lhs == TY_TYPE)
{
compile_children(self, root, prog);
program_add_instr(prog, OP_TADD, NO_PARAM);
}
else else
{ {
compile_number(self, root, prog, OP_IADD, OP_FADD); compile_number(self, root, prog, OP_IADD, OP_FADD);
@ -89,13 +99,12 @@ void compile_node(compiler* self, node* root, program* prog)
else if (root->type == NODE_TYPE) else if (root->type == NODE_TYPE)
{ {
type* ty = compile_get_type(self, root); type* ty = compile_get_type(self, root);
value val; value val;
value_init_type(&val, value_init_type(&val,
ty, ty,
root->lineno); root->lineno);
size_t idx = program_add_pool(prog, &val); size_t idx = program_add_pool(prog, &val);
program_add_instr(prog, OP_PUSH, idx); program_add_instr(prog, OP_PUSH, idx);
@ -255,14 +264,24 @@ type* compile_get_type(compiler* self, node* root)
else if (strcmp(root->value, "array") == 0) else if (strcmp(root->value, "array") == 0)
{ {
type_init(ty, TY_ARRAY); type_init(ty, TY_ARRAY);
ty->kind = KIND_SEQUENTIAL;
}
else if (root->type == NODE_ADD)
{
type_init(ty, TY_TYPE);
ty->kind = KIND_DISJUNCTION;
}
else if (root->type == NODE_MUL)
{
type_init(ty, TY_TYPE);
ty->kind = KIND_CONJUNCTION;
} }
else else
{ {
fprintf(stderr, fprintf(stderr,
"E(%d): cannot compile unknown type '%s'.'\n", "E(%d): cannot compile unknown type '%s'.\n",
root->lineno, root->lineno,
root->value); NodeTypeStr[root->type]);
} }
for (size_t i=0; i<root->children.size; i++) for (size_t i=0; i<root->children.size; i++)

View File

@ -35,6 +35,18 @@ type* cstatic_resolve_new(cstatic* self, node* ast)
assert(self); assert(self);
assert(ast); assert(ast);
if (ast->type == NODE_ADD)
{
type* lhs = cstatic_resolve_new(self, ast->children.data[0]);
type* rhs = cstatic_resolve_new(self, ast->children.data[1]);
if (lhs->base_type == TY_TYPE && rhs->base_type == TY_TYPE)
{
type_free(rhs); free(rhs);
return lhs;
}
}
if (ast->type == NODE_MUL) if (ast->type == NODE_MUL)
{ {
int lhs = cstatic_resolve_base_type(self, ast->children.data[0]); int lhs = cstatic_resolve_base_type(self, ast->children.data[0]);
@ -67,6 +79,14 @@ type* cstatic_resolve_new(cstatic* self, node* ast)
return lhs; return lhs;
} }
if (lhs->base_type == TY_TYPE
&& rhs->base_type == TY_TYPE)
{
type_free(rhs);
free(rhs);
return lhs;
}
type_free(lhs); type_free(lhs);
free(lhs); free(lhs);
type_free(rhs); type_free(rhs);
@ -237,7 +257,39 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
return 1; return 1;
} }
// Types Operations
if (ast->type == NODE_MUL)
{
type* lhs = cstatic_resolve_new(self, ast->children.data[0]);
type* rhs = cstatic_resolve_new(self, ast->children.data[1]);
if (lhs->base_type == TY_TYPE && rhs->base_type == TY_TYPE)
{
type_free(lhs); free(lhs);
type_free(rhs); free(rhs);
return 1;
}
type_free(lhs); free(lhs);
type_free(rhs); free(rhs);
}
if (ast->type == NODE_ADD)
{
type* lhs = cstatic_resolve_new(self, ast->children.data[0]);
type* rhs = cstatic_resolve_new(self, ast->children.data[1]);
if (lhs->base_type == TY_TYPE && rhs->base_type == TY_TYPE)
{
type_free(lhs); free(lhs);
type_free(rhs); free(rhs);
return 1;
}
type_free(lhs); free(lhs);
type_free(rhs); free(rhs);
}
// Array Operations // Array Operations
if (ast->type == NODE_ADD) if (ast->type == NODE_ADD)
{ {

View File

@ -31,7 +31,9 @@
G(OP_MKARRAY), \ G(OP_MKARRAY), \
G(OP_ADEREF), \ G(OP_ADEREF), \
G(OP_ACAT), \ G(OP_ACAT), \
G(OP_AMUL) G(OP_AMUL), \
G(OP_TMUL), \
G(OP_TADD)
enum Opcodes { enum Opcodes {
OPCODES(GEN_ENUM) OPCODES(GEN_ENUM)

View File

@ -34,9 +34,11 @@
%left MUL DIV MOD %left MUL DIV MOD
%left POW %left POW
%left NOT %left NOT
%token OPAR CPAR OSQUARE CSQUARE COMMA %token OPAR CPAR
%token OSQUARE CSQUARE COMMA
%type <n_children> expr_unop %type <n_children> expr_unop
%% %%
prog: prog:
@ -118,7 +120,7 @@ expr:
| expr_unop {} | expr_unop {}
| expr ADD expr{ | expr ADD expr{
node *n = malloc(sizeof(node)); node *n = malloc(sizeof(node));
node_init(n, NODE_ADD, "", line); node_init(n, NODE_ADD, "", line);
node* rhs = stack_pop(); node* rhs = stack_pop();
@ -263,8 +265,8 @@ expr_unop:
; ;
type_list: type_list:
type { $$ = $1; } expr { $$ = $1; }
| type_list COMMA type { $$ = $1 + $3; } | type_list COMMA expr { $$ = $1 + $3; }
; ;

View File

@ -6,7 +6,7 @@ void type_init(type* self, int base_type)
{ {
assert(self); assert(self);
self->base_type = base_type; self->base_type = base_type;
self->kind = KIND_CONJUNCTION;
self->sub_types.size = 0; self->sub_types.size = 0;
self->sub_types.capacity = 1; self->sub_types.capacity = 1;
self->sub_types.data = malloc(sizeof(type*)); self->sub_types.data = malloc(sizeof(type*));
@ -18,6 +18,7 @@ void type_init_array(type* self, type* array_type)
assert(array_type); assert(array_type);
type_init(self, TY_ARRAY); type_init(self, TY_ARRAY);
type_add_sub_type(self, array_type); type_add_sub_type(self, array_type);
self->kind = KIND_SEQUENTIAL;
} }
void type_free(type* self) void type_free(type* self)
@ -66,6 +67,8 @@ type* type_new_clone(type* self)
type_add_sub_type(clone, self->sub_types.data[i]); type_add_sub_type(clone, self->sub_types.data[i]);
} }
clone->kind = self->kind;
return clone; return clone;
} }
@ -84,12 +87,30 @@ int type_equals(type* self, type* rhs)
return 0; return 0;
} }
for (size_t i=0; i<self->sub_types.size; i++) if (self->kind != rhs->kind)
{ {
if (!type_equals(self->sub_types.data[i], return 0;
rhs->sub_types.data[i])) }
if (self->kind != KIND_SEQUENTIAL)
{
for (int i=0; i<TY_TYPE_COUNT; i++)
{ {
return 0; if (type_count(self, i) != type_count(rhs, i))
{
return 0;
}
}
}
else
{
for (size_t i=0; i<self->sub_types.size; i++)
{
if (!type_equals(self->sub_types.data[i],
rhs->sub_types.data[i]))
{
return 0;
}
} }
} }
@ -104,7 +125,18 @@ size_t type_str(type* self, char* buffer, size_t size)
if (self->sub_types.size > 0) if (self->sub_types.size > 0)
{ {
sz += snprintf(buffer + sz, size - sz, "<"); if (self->kind == KIND_CONJUNCTION)
{
sz += snprintf(buffer + sz, size - sz, "(");
}
else if (self->kind == KIND_DISJUNCTION)
{
sz += snprintf(buffer + sz, size - sz, "[");
}
else
{
sz += snprintf(buffer + sz, size - sz, "<");
}
} }
for (size_t i=0; i<self->sub_types.size; i++) for (size_t i=0; i<self->sub_types.size; i++)
@ -119,8 +151,37 @@ size_t type_str(type* self, char* buffer, size_t size)
if (self->sub_types.size > 0) if (self->sub_types.size > 0)
{ {
sz += snprintf(buffer + sz, size - sz, ">"); if (self->kind == KIND_CONJUNCTION)
{
sz += snprintf(buffer + sz, size - sz, ")");
}
else if (self->kind == KIND_DISJUNCTION)
{
sz += snprintf(buffer + sz, size - sz, "]");
}
else
{
sz += snprintf(buffer + sz, size - sz, ">");
}
} }
return sz; return sz;
} }
int type_count(type* self, int base_type)
{
assert(self);
int n = 0;
if (self->base_type == base_type)
{
n = 1;
}
for (size_t i=0; i<self->sub_types.size; i++)
{
n += type_count(self->sub_types.data[i], base_type);
}
return n;
}

View File

@ -19,8 +19,16 @@ enum Types {
extern char const* TypesStr[]; extern char const* TypesStr[];
enum TypeKind {
KIND_DISJUNCTION,
KIND_CONJUNCTION,
KIND_SEQUENTIAL
};
typedef struct type { typedef struct type {
int base_type; int base_type;
int kind;
struct { struct {
size_t size; size_t size;
size_t capacity; size_t capacity;
@ -38,4 +46,5 @@ type* type_new_clone(type* self);
int type_equals(type* self, type* rhs); int type_equals(type* self, type* rhs);
size_t type_str(type* self, char* buffer, size_t size); size_t type_str(type* self, char* buffer, size_t size);
int type_count(type* self, int base_type);
#endif #endif

View File

@ -73,6 +73,8 @@ void vm_exec(vm* self, program* prog)
case OP_ADEREF: vm_aderef(self); break; case OP_ADEREF: vm_aderef(self); break;
case OP_ACAT: vm_acat(self); break; case OP_ACAT: vm_acat(self); break;
case OP_AMUL: vm_amul(self); break; case OP_AMUL: vm_amul(self); break;
case OP_TMUL: vm_tmul(self); break;
case OP_TADD: vm_tadd(self); break;
default: { default: {
fprintf(stderr, "unknown opcode %s\n", fprintf(stderr, "unknown opcode %s\n",
@ -657,6 +659,7 @@ void vm_acat(vm* self)
self->pc++; self->pc++;
} }
void vm_amul(vm* self) void vm_amul(vm* self)
{ {
assert(self); assert(self);
@ -689,3 +692,51 @@ void vm_amul(vm* self)
self->pc++; self->pc++;
} }
void vm_tmul(vm* self)
{
assert(self);
value* rhs = vm_pop_value(self);
value* lhs = vm_pop_value(self);
type ty;
type_init(&ty, TY_TYPE);
type_add_sub_type(&ty, lhs->val.type_val);
type_add_sub_type(&ty, rhs->val.type_val);
value* val = malloc(sizeof(value));
value_init_type(val, &ty, lhs->lineno);
vm_push_value(self, val);
type_free(&ty);
value_free(lhs); free(lhs);
value_free(rhs); free(rhs);
self->pc++;
}
void vm_tadd(vm* self)
{
assert(self);
value* rhs = vm_pop_value(self);
value* lhs = vm_pop_value(self);
type ty;
type_init(&ty, TY_TYPE);
ty.kind = KIND_DISJUNCTION;
type_add_sub_type(&ty, lhs->val.type_val);
type_add_sub_type(&ty, rhs->val.type_val);
value* val = malloc(sizeof(value));
value_init_type(val, &ty, lhs->lineno);
vm_push_value(self, val);
type_free(&ty);
value_free(lhs); free(lhs);
value_free(rhs); free(rhs);
self->pc++;
}

View File

@ -57,5 +57,7 @@ void vm_mkarray(vm* self, int param);
void vm_aderef(vm* self); void vm_aderef(vm* self);
void vm_acat(vm* self); void vm_acat(vm* self);
void vm_amul(vm* self); void vm_amul(vm* self);
void vm_tmul(vm* self);
void vm_tadd(vm* self);
#endif #endif

4
tests/err_ty_type.wuz Normal file
View File

@ -0,0 +1,4 @@
int * 5
str * "salut"
str + "salut"
float + 1.2

View File

@ -11,3 +11,21 @@ assert str != bool
assert bool != int assert bool != int
assert array<float> != array<int> assert array<float> != array<int>
assert array<array<int>> != array<int> assert array<array<int>> != array<int>
assert str * float == str * float
assert str * float * array<int> == str * float * array<int>
assert str * float * array<float> != str * float * array<int>
assert str + float == str + float
assert (str + float) * int == (str + float) * int
assert (float + float) * int != (str + float) * int
assert array<int + float> == array<int + float>
assert array<int * float> != array<int + float>
assert int + float == float + int
assert int * bool == bool * int
assert int * str * bool == bool * int * str
assert array<int, float> != array<float, int>