From 9ca893dff50e4c0b5399add3f48a4a47f41b657a Mon Sep 17 00:00:00 2001 From: bog Date: Fri, 25 Aug 2023 01:50:18 +0200 Subject: [PATCH] ADD: type addition and multiplication. --- src/compiler.c | 31 ++++++++++++++---- src/cstatic.c | 54 ++++++++++++++++++++++++++++++- src/opcodes.h | 4 ++- src/parser.y | 10 +++--- src/type.c | 75 +++++++++++++++++++++++++++++++++++++++---- src/type.h | 9 ++++++ src/vm.c | 51 +++++++++++++++++++++++++++++ src/vm.h | 2 ++ tests/err_ty_type.wuz | 4 +++ tests/test_types.wuz | 18 +++++++++++ 10 files changed, 239 insertions(+), 19 deletions(-) create mode 100644 tests/err_ty_type.wuz diff --git a/src/compiler.c b/src/compiler.c index a0cf42d..7ce0307 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -56,6 +56,11 @@ void compile_node(compiler* self, node* root, program* prog) compile_node(self, root->children.data[0], prog); 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 { 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); 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 { 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) { type* ty = compile_get_type(self, root); - - + value val; value_init_type(&val, ty, root->lineno); - + size_t idx = program_add_pool(prog, &val); 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) { 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 { fprintf(stderr, - "E(%d): cannot compile unknown type '%s'.'\n", + "E(%d): cannot compile unknown type '%s'.\n", root->lineno, - root->value); + NodeTypeStr[root->type]); } for (size_t i=0; ichildren.size; i++) diff --git a/src/cstatic.c b/src/cstatic.c index 55b0cf2..81b8aee 100644 --- a/src/cstatic.c +++ b/src/cstatic.c @@ -35,6 +35,18 @@ type* cstatic_resolve_new(cstatic* self, node* ast) assert(self); 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) { 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; } + if (lhs->base_type == TY_TYPE + && rhs->base_type == TY_TYPE) + { + type_free(rhs); + free(rhs); + return lhs; + } + type_free(lhs); free(lhs); type_free(rhs); @@ -237,7 +257,39 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) 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 if (ast->type == NODE_ADD) { diff --git a/src/opcodes.h b/src/opcodes.h index c62f31d..c6c2aa1 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -31,7 +31,9 @@ G(OP_MKARRAY), \ G(OP_ADEREF), \ G(OP_ACAT), \ - G(OP_AMUL) + G(OP_AMUL), \ + G(OP_TMUL), \ + G(OP_TADD) enum Opcodes { OPCODES(GEN_ENUM) diff --git a/src/parser.y b/src/parser.y index c9d3514..d34a21d 100644 --- a/src/parser.y +++ b/src/parser.y @@ -34,9 +34,11 @@ %left MUL DIV MOD %left POW %left NOT -%token OPAR CPAR OSQUARE CSQUARE COMMA +%token OPAR CPAR +%token OSQUARE CSQUARE COMMA %type expr_unop + %% prog: @@ -118,7 +120,7 @@ expr: | expr_unop {} - | expr ADD expr{ + | expr ADD expr{ node *n = malloc(sizeof(node)); node_init(n, NODE_ADD, "", line); node* rhs = stack_pop(); @@ -263,8 +265,8 @@ expr_unop: ; type_list: - type { $$ = $1; } - | type_list COMMA type { $$ = $1 + $3; } + expr { $$ = $1; } + | type_list COMMA expr { $$ = $1 + $3; } ; diff --git a/src/type.c b/src/type.c index 691cc4a..7e47884 100644 --- a/src/type.c +++ b/src/type.c @@ -6,7 +6,7 @@ void type_init(type* self, int base_type) { assert(self); self->base_type = base_type; - + self->kind = KIND_CONJUNCTION; self->sub_types.size = 0; self->sub_types.capacity = 1; self->sub_types.data = malloc(sizeof(type*)); @@ -18,6 +18,7 @@ void type_init_array(type* self, type* array_type) assert(array_type); type_init(self, TY_ARRAY); type_add_sub_type(self, array_type); + self->kind = KIND_SEQUENTIAL; } 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]); } + clone->kind = self->kind; + return clone; } @@ -84,12 +87,30 @@ int type_equals(type* self, type* rhs) return 0; } - for (size_t i=0; isub_types.size; i++) + if (self->kind != rhs->kind) { - if (!type_equals(self->sub_types.data[i], - rhs->sub_types.data[i])) + return 0; + } + + if (self->kind != KIND_SEQUENTIAL) + { + for (int i=0; isub_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) { - 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; isub_types.size; i++) @@ -119,8 +151,37 @@ size_t type_str(type* self, char* buffer, size_t size) 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; } + +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; isub_types.size; i++) + { + n += type_count(self->sub_types.data[i], base_type); + } + + return n; +} diff --git a/src/type.h b/src/type.h index 4f1a850..559f389 100644 --- a/src/type.h +++ b/src/type.h @@ -19,8 +19,16 @@ enum Types { extern char const* TypesStr[]; +enum TypeKind { + KIND_DISJUNCTION, + KIND_CONJUNCTION, + KIND_SEQUENTIAL +}; + typedef struct type { int base_type; + int kind; + struct { size_t size; size_t capacity; @@ -38,4 +46,5 @@ type* type_new_clone(type* self); int type_equals(type* self, type* rhs); size_t type_str(type* self, char* buffer, size_t size); +int type_count(type* self, int base_type); #endif diff --git a/src/vm.c b/src/vm.c index 175e38d..3a7b1bd 100644 --- a/src/vm.c +++ b/src/vm.c @@ -73,6 +73,8 @@ void vm_exec(vm* self, program* prog) case OP_ADEREF: vm_aderef(self); break; case OP_ACAT: vm_acat(self); break; case OP_AMUL: vm_amul(self); break; + case OP_TMUL: vm_tmul(self); break; + case OP_TADD: vm_tadd(self); break; default: { fprintf(stderr, "unknown opcode %s\n", @@ -657,6 +659,7 @@ void vm_acat(vm* self) self->pc++; } + void vm_amul(vm* self) { assert(self); @@ -689,3 +692,51 @@ void vm_amul(vm* self) 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++; +} diff --git a/src/vm.h b/src/vm.h index f819d5b..7f460ca 100644 --- a/src/vm.h +++ b/src/vm.h @@ -57,5 +57,7 @@ void vm_mkarray(vm* self, int param); void vm_aderef(vm* self); void vm_acat(vm* self); void vm_amul(vm* self); +void vm_tmul(vm* self); +void vm_tadd(vm* self); #endif diff --git a/tests/err_ty_type.wuz b/tests/err_ty_type.wuz new file mode 100644 index 0000000..1b87470 --- /dev/null +++ b/tests/err_ty_type.wuz @@ -0,0 +1,4 @@ +int * 5 +str * "salut" +str + "salut" +float + 1.2 diff --git a/tests/test_types.wuz b/tests/test_types.wuz index 2485eb7..9d53585 100644 --- a/tests/test_types.wuz +++ b/tests/test_types.wuz @@ -11,3 +11,21 @@ assert str != bool assert bool != int assert array != array assert array> != array + +assert str * float == str * float +assert str * float * array == str * float * array +assert str * float * array != str * float * array + +assert str + float == str + float +assert (str + float) * int == (str + float) * int +assert (float + float) * int != (str + float) * int + +assert array == array +assert array != array + +assert int + float == float + int +assert int * bool == bool * int +assert int * str * bool == bool * int * str +assert array != array + +