From 7f5b5486c023322a3e703c3324b70462722cc09f Mon Sep 17 00:00:00 2001 From: bog Date: Thu, 24 Aug 2023 17:22:49 +0200 Subject: [PATCH] ADD: array index. --- src/array.c | 6 +++ src/array.h | 1 + src/compiler.c | 7 +++- src/cstatic.c | 92 +++++++++++++++++++++++++++++++++++++----- src/lex.l | 1 + src/main.c | 4 +- src/node.h | 2 +- src/opcodes.h | 3 +- src/parser.y | 87 +++++++++++++++++++++++++++++---------- src/vm.c | 39 +++++++++++++++++- src/vm.h | 2 + tests/err_ty_array.wuz | 9 ++++- tests/test_array.wuz | 28 +++++++++---- 13 files changed, 233 insertions(+), 48 deletions(-) diff --git a/src/array.c b/src/array.c index 431b23e..53516c7 100644 --- a/src/array.c +++ b/src/array.c @@ -30,6 +30,12 @@ void array_free(array* self) free(self->type); self->type = NULL; } +struct value* array_deref_copy(array* self, size_t index) +{ + assert(index < self->children.size); + return (struct value*) value_new_clone((value*)self->children.data[index]); +} + void array_push(array* self, struct value* element) { assert(self); diff --git a/src/array.h b/src/array.h index 865e561..39dbf60 100644 --- a/src/array.h +++ b/src/array.h @@ -18,6 +18,7 @@ typedef struct { void array_init(array* self, type* elements_type); void array_free(array* self); +struct value* array_deref_copy(array* self, size_t index); void array_push(array* self, struct value* element); size_t array_str(array* self, char* buffer, size_t size); diff --git a/src/compiler.c b/src/compiler.c index 3399725..5a71b59 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -17,7 +17,12 @@ void compile_node(compiler* self, node* root, program* prog) assert(root); assert(prog); - if (root->type == NODE_MUL) + if (root->type == NODE_INDEX) + { + compile_children(self, root, prog); + program_add_instr(prog, OP_ADEREF, NO_PARAM); + } + else if (root->type == NODE_MUL) { cstatic cs; cstatic_init(&cs); diff --git a/src/cstatic.c b/src/cstatic.c index 82fc217..fc34ad7 100644 --- a/src/cstatic.c +++ b/src/cstatic.c @@ -46,7 +46,20 @@ type* cstatic_resolve_new(cstatic* self, node* ast) } } - if (ast->type == NODE_INTEGER) + if (ast->type == NODE_INDEX) + { + // find inner type using first array element + size_t dim = ast->children.data[1]->children.size; + node* iter = ast->children.data[0]; + + for (size_t i=0; ichildren.data[0]; + } + + return cstatic_resolve_new(self, iter); + } + else if (ast->type == NODE_INTEGER) { return cstatic_new_type(self, TY_INTEGER); } @@ -126,8 +139,52 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) } } + // Arrays - if (ast->type == NODE_ARRAY) + if (ast->type == NODE_INDEX) + { + // check dimension + size_t dim = ast->children.data[1]->children.size; + size_t real_dim = 0; + + node* iter = ast->children.data[0]; + while (iter->type == NODE_ARRAY) + { + iter = iter->children.data[0]; + real_dim++; + } + + if (real_dim != dim) + { + snprintf(msg, size, + "E: array dimension mismatch:" + " expected '%ld', got '%ld'.", + real_dim, dim); + + return 0; + } + + // check that all indexes are integers + for (size_t i=0; ichildren.data[1]->children.data[i], + msg, + size, + TY_INTEGER, + TYPE_END + ); + + if (!status) + { + return 0; + } + } + + return 1; + } + else if (ast->type == NODE_ARRAY) { assert(ast->children.size > 0); type* ty = cstatic_resolve_new(self, ast->children.data[0]); @@ -151,6 +208,9 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) } } + type_free(ty); + free(ty); + return 1; } @@ -388,7 +448,7 @@ int cstatic_check_type_base(cstatic* self, node* lhs, size_t sz = snprintf(msg, size, "E(%d): type mismatch, got '%s', ", lhs->lineno, - TypesStr[left]); + TypesStr[left] + strlen("TY_")); sz += snprintf(msg + sz, size - sz, "expected: \n"); @@ -397,7 +457,7 @@ int cstatic_check_type_base(cstatic* self, node* lhs, while (all_types[j] != TYPE_END) { sz += snprintf(msg + sz, size - sz, "\t '%s'\n", - TypesStr[all_types[j]]); + TypesStr[all_types[j]] + strlen("TY_")); j++; } @@ -411,17 +471,27 @@ int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs, assert(lhs); assert(rhs); - int left = cstatic_resolve_base_type(self, lhs); - int right = cstatic_resolve_base_type(self, rhs); + type* left = cstatic_resolve_new(self, lhs); + type* right = cstatic_resolve_new(self, rhs); - if (left != right) + if (!type_equals(left, right)) { - snprintf(msg, size, "E(%d): expected '%s', got '%s'.", - lhs->lineno, - TypesStr[left], - TypesStr[right]); + size_t sz = 0; + + sz += snprintf(msg + sz, size - sz, "E(%d): expected '", lhs->lineno); + sz += type_str(left, msg + sz, size - sz); + sz += snprintf(msg + sz, size - sz, "', got '"); + sz += type_str(right, msg + sz, size - sz); + sz += snprintf(msg + sz, size - sz, "'"); + + type_free(left); free(left); + type_free(right); free(right); + return 0; } + type_free(left); free(left); + type_free(right); free(right); + return 1; } diff --git a/src/lex.l b/src/lex.l index 7ef0f48..4db3e1d 100644 --- a/src/lex.l +++ b/src/lex.l @@ -20,6 +20,7 @@ STRING \"[^"]*\" {WHITESPACES} {} "assert" { return ASSERT; } +"," { return COMMA; } "+" { return ADD; } "-" { return SUB; } "*" { return MUL; } diff --git a/src/main.c b/src/main.c index a590bb4..e37ad0a 100644 --- a/src/main.c +++ b/src/main.c @@ -60,13 +60,15 @@ int main(int argc, char** argv) { size_t const BUF = 1024; char buffer[BUF]; - + memset(buffer, 0, BUF); node_str(ast, buffer, BUF); printf("-- ast ---\n%s\n\n", buffer); + memset(buffer, 0, BUF); program_str(&prog, buffer, BUF); printf("--- program ---\n%s\n", buffer); + memset(buffer, 0, BUF); vm_str(&v, buffer, BUF); printf("--- stack ---\n%s\n", buffer); } diff --git a/src/node.h b/src/node.h index 2644ee9..7e73ca0 100644 --- a/src/node.h +++ b/src/node.h @@ -10,7 +10,7 @@ G(NODE_ASSERT), \ G(NODE_UADD), G(NODE_USUB), G(NODE_ADD), G(NODE_SUB), \ G(NODE_MUL), G(NODE_DIV), G(NODE_MOD), G(NODE_POW), \ - G(NODE_ARRAY) + G(NODE_ARRAY), G(NODE_INDEX) #include "mutils.h" diff --git a/src/opcodes.h b/src/opcodes.h index 3654898..848d375 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -28,7 +28,8 @@ G(OP_FUSUB), \ G(OP_CAT), \ G(OP_SMUL), \ - G(OP_MKARRAY) + G(OP_MKARRAY), \ + G(OP_ADEREF) enum Opcodes { OPCODES(GEN_ENUM) diff --git a/src/parser.y b/src/parser.y index 05f8843..0abcd5c 100644 --- a/src/parser.y +++ b/src/parser.y @@ -23,7 +23,8 @@ %left ASSERT %token BOOLEAN INTEGER FLOAT STRING -%type expr exprs prog; +%type expr exprs prog array arrays builtins +%type expr_list %left EQ NE %left AND %left OR @@ -31,7 +32,7 @@ %left MUL DIV MOD %left POW %left NOT -%token OPAR CPAR OSQUARE CSQUARE +%token OPAR CPAR OSQUARE CSQUARE COMMA %% @@ -66,7 +67,36 @@ exprs: expr: - ASSERT expr { + // INDEX + array array { + node *n = malloc(sizeof(node)); + node_init(n, NODE_INDEX, "", line); + size_t const SZ = $1 + $2; + node* all[SZ]; + for (size_t i=0; ilineno); + vm_push_value(self, arr_val); for (int i=0; ipc++; } + +void vm_aderef(vm* self) +{ + assert(self); + + value* idx = vm_pop_value(self); + value* arr = vm_pop_value(self); + + array* idx_array = idx->val.array_val; + + value* val = NULL; + + for (size_t i=0; ichildren.size; i++) + { + size_t index = ((value*) idx_array->children.data[i])->val.integer; + + val = (value*) array_deref_copy( + arr->val.array_val, + index); + + if (val->type->base_type == TY_ARRAY) + { + value_free(arr); + free(arr); + arr = val; + } + } + assert(val); + + vm_push_value(self, val); + + value_free(idx); free(idx); + value_free(arr); free(arr); + + self->pc++; +} diff --git a/src/vm.h b/src/vm.h index 0cfeedb..69ac1b0 100644 --- a/src/vm.h +++ b/src/vm.h @@ -54,4 +54,6 @@ void vm_smul(vm* self); void vm_cat(vm* self); void vm_mkarray(vm* self, int param); +void vm_aderef(vm* self); + #endif diff --git a/tests/err_ty_array.wuz b/tests/err_ty_array.wuz index e143c3f..5132e49 100644 --- a/tests/err_ty_array.wuz +++ b/tests/err_ty_array.wuz @@ -1,3 +1,8 @@ [] -[1 2 3 "4"] -[ [0 1] ["0" "1"] ] +[1, 2, 3, "4"] +[ [0, 1], ["0", "1"] ] +[1, 2, 3]["a"] +[1, 2, 3][false] +[1, 2, 3][3.14] +[1, 2, 3][ [0, 1] ] +[1, 2, 3][0, 0] diff --git a/tests/test_array.wuz b/tests/test_array.wuz index 76b942f..a5dab54 100644 --- a/tests/test_array.wuz +++ b/tests/test_array.wuz @@ -1,11 +1,23 @@ -assert [1 - 2 3] == [-1 3] -assert [1 -2 3] == [1 -2 3] +assert [1, 2, 3] == [1, 2, 3] +assert ["a", "b", "c"] == ["a", "b", "c"] + +assert [1, 2, 3] != [7, 2, 3] +assert [1, 2, 3] != [1, 2, 3, 4] + +assert ["a", "b", "c"] != ["ac", "b", "c"] +assert ["a", "b", "c"] != ["a", "b", "c", "d"] + +assert 3 == [3, 8, 9][0] +assert 8 == [3, 8, 9][1] +assert 9 == [3, 8, 9][2] + +assert "8" == ["3", "8", "9"][2 - 1] + +assert 7 == [[4, 6], [9, 2, 7], [3, 3, 2]][1, 2] +assert 9 == [[4, 6], [9, 2, 7], [3, 3, 2]][[2, 9, 1][2], 0] + + + -assert [1 2 3] == [1 2 3] -assert ["a" "b" "c"] == ["a" "b" "c"] -assert [1 2 3] != [7 2 3] -assert [1 2 3] != [1 2 3 4] -assert ["a" "b" "c"] != ["ac" "b" "c"] -assert ["a" "b" "c"] != ["a" "b" "c" "d"]