diff --git a/meson.build b/meson.build index da5972d..589b88c 100644 --- a/meson.build +++ b/meson.build @@ -48,6 +48,8 @@ executable( 'src/compiler.c', 'src/cstatic.c', 'src/vm.c', + + 'src/symtable.c', ], dependencies: [ m_dep diff --git a/src/compiler.c b/src/compiler.c index d30d944..4b763db 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -4,11 +4,18 @@ void compiler_init(compiler* self) { assert(self); + self->sym = malloc(sizeof(symtable)); + symtable_init(self->sym); + } void compiler_free(compiler* self) { assert(self); + + symtable_free(self->sym); + free(self->sym); + self->sym = NULL; } void compile_node(compiler* self, node* root, program* prog) @@ -22,13 +29,54 @@ void compile_node(compiler* self, node* root, program* prog) compile_children(self, root, prog); program_add_instr(prog, OP_ADEREF, NO_PARAM); } + // Variables stuff + else if (root->type == NODE_VARDECL) + { + cstatic cs; + cstatic_init(&cs); + + type* ty = cstatic_resolve_new(&cs, + self->sym, + root->children.data[1]); + + size_t id = symtable_declare( + self->sym, + root->children.data[0]->value, + ty + ); + + compile_node(self, root->children.data[1], prog); + program_add_instr(prog, OP_STORE, id); + + type_free(ty); + free(ty); + cstatic_free(&cs); + } + else if (root->type == NODE_IDENT) + { + symentry* entry = symtable_find(self->sym, root->value); + + if (!entry) + { + fprintf(stderr, "E(%d): variable '%s' not declared.\n", + root->lineno, + root->value); + exit(-1); + } + + + program_add_instr(prog, OP_LOAD, entry->id); + } else if (root->type == NODE_MUL) { cstatic cs; cstatic_init(&cs); - int lhs = cstatic_resolve_base_type(&cs, root->children.data[0]); - int rhs = cstatic_resolve_base_type(&cs, root->children.data[1]); + int lhs = cstatic_resolve_base_type(&cs, + self->sym, + root->children.data[0]); + int rhs = cstatic_resolve_base_type(&cs, self->sym, + root->children.data[1]); cstatic_free(&cs); @@ -71,8 +119,10 @@ void compile_node(compiler* self, node* root, program* prog) cstatic cs; cstatic_init(&cs); - int lhs = cstatic_resolve_base_type(&cs, root->children.data[0]); - int rhs = cstatic_resolve_base_type(&cs, root->children.data[1]); + int lhs = cstatic_resolve_base_type(&cs, + self->sym, root->children.data[0]); + int rhs = cstatic_resolve_base_type(&cs, + self->sym, root->children.data[1]); cstatic_free(&cs); @@ -164,6 +214,7 @@ void compile_node(compiler* self, node* root, program* prog) cstatic cs; cstatic_init(&cs); int base_type = cstatic_resolve_base_type(&cs, + self->sym, root->children.data[0]); cstatic_free(&cs); @@ -186,6 +237,7 @@ void compile_node(compiler* self, node* root, program* prog) cstatic cs; cstatic_init(&cs); int base_type = cstatic_resolve_base_type(&cs, + self->sym, root->children.data[0]); cstatic_free(&cs); @@ -208,6 +260,7 @@ void compile_node(compiler* self, node* root, program* prog) cstatic cs; cstatic_init(&cs); int base_type = cstatic_resolve_base_type(&cs, + self->sym, root->children.data[0]); cstatic_free(&cs); @@ -230,6 +283,7 @@ void compile_node(compiler* self, node* root, program* prog) cstatic cs; cstatic_init(&cs); int base_type = cstatic_resolve_base_type(&cs, + self->sym, root->children.data[0]); cstatic_free(&cs); @@ -392,7 +446,7 @@ void compile_number(compiler* self, node* root, program* prog, cstatic cs; cstatic_init(&cs); - int ty = cstatic_resolve_base_type(&cs, root); + int ty = cstatic_resolve_base_type(&cs, self->sym, root); switch (ty) { diff --git a/src/compiler.h b/src/compiler.h index eed284a..c3bd407 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -4,9 +4,11 @@ #include "commons.h" #include "program.h" #include "node.h" +#include "symtable.h" typedef struct { - int _unused; + symtable* sym; + } compiler; void compiler_init(compiler* self); diff --git a/src/cstatic.c b/src/cstatic.c index 5ba0804..01c35c5 100644 --- a/src/cstatic.c +++ b/src/cstatic.c @@ -19,10 +19,10 @@ type* cstatic_new_type(cstatic* self, int base_type) return ty; } -int cstatic_resolve_base_type(cstatic* self, node* ast) +int cstatic_resolve_base_type(cstatic* self, symtable* sym, node* ast) { assert(self); - type* ty = cstatic_resolve_new(self, ast); + type* ty = cstatic_resolve_new(self, sym, ast); int res = ty->base_type; type_free(ty); free(ty); @@ -30,27 +30,48 @@ int cstatic_resolve_base_type(cstatic* self, node* ast) return res; } -type* cstatic_resolve_new(cstatic* self, node* ast) +type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast) { assert(self); assert(ast); + + if (ast->type == NODE_IDENT) + { + symentry* entry = symtable_find(sym, + ast->value); + type* ty = type_new_clone(entry->ty); + return ty; + } + + if (ast->type == NODE_VARDECL) + { + type* ty = cstatic_resolve_new(self, + sym, + ast->children.data[1]); + return ty; + } 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]); + type* lhs = cstatic_resolve_new(self, sym, ast->children.data[0]); + type* rhs = cstatic_resolve_new(self, sym, ast->children.data[1]); if (lhs->base_type == TY_TYPE && rhs->base_type == TY_TYPE) { type_free(rhs); free(rhs); return lhs; } + + type_free(rhs); free(rhs); + type_free(lhs); free(lhs); } if (ast->type == NODE_MUL) { - int lhs = cstatic_resolve_base_type(self, ast->children.data[0]); - int rhs = cstatic_resolve_base_type(self, ast->children.data[1]); + int lhs = cstatic_resolve_base_type(self, sym, + ast->children.data[0]); + int rhs = cstatic_resolve_base_type(self, sym, + ast->children.data[1]); if (lhs == TY_STRING || rhs == TY_STRING) { @@ -60,8 +81,8 @@ type* cstatic_resolve_new(cstatic* self, node* ast) 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]); + type* lhs = cstatic_resolve_new(self, sym, ast->children.data[0]); + type* rhs = cstatic_resolve_new(self, sym, ast->children.data[1]); if (lhs->base_type == TY_INTEGER && rhs->base_type == TY_ARRAY) @@ -104,7 +125,7 @@ type* cstatic_resolve_new(cstatic* self, node* ast) iter = iter->children.data[0]; } - return cstatic_resolve_new(self, iter); + return cstatic_resolve_new(self, sym, iter); } else if (ast->type == NODE_INTEGER) { @@ -117,7 +138,7 @@ type* cstatic_resolve_new(cstatic* self, node* ast) else if (ast->type == NODE_ADD) { - return cstatic_resolve_new(self, ast->children.data[0]); + return cstatic_resolve_new(self, sym, ast->children.data[0]); } else if (ast->type == NODE_STRING) @@ -133,7 +154,7 @@ type* cstatic_resolve_new(cstatic* self, node* ast) else if (ast->type == NODE_ARRAY) { assert(ast->children.size > 0); - type* child = cstatic_resolve_new(self, ast->children.data[0]); + type* child = cstatic_resolve_new(self, sym, ast->children.data[0]); type* ty = malloc(sizeof(type)); type_init_array(ty, child); @@ -159,7 +180,8 @@ type* cstatic_resolve_new(cstatic* self, node* ast) { for (size_t i=0; ichildren.size; i++) { - type* ty = cstatic_resolve_new(self, ast->children.data[i]); + type* ty = cstatic_resolve_new(self, sym, + ast->children.data[i]); if (ty != NULL) { @@ -171,7 +193,7 @@ type* cstatic_resolve_new(cstatic* self, node* ast) return NULL; } -int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) +int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t size) { assert(self); assert(ast); @@ -180,6 +202,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) for (size_t i=0; ichildren.size; i++) { int status = cstatic_check(self, ast->children.data[i], + sym, msg, size); if (!status) @@ -219,6 +242,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) int status = cstatic_check_type_base( self, ast->children.data[1]->children.data[i], + sym, msg, size, TY_INTEGER, @@ -236,13 +260,14 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) else if (ast->type == NODE_ARRAY) { assert(ast->children.size > 0); - type* ty = cstatic_resolve_new(self, ast->children.data[0]); + type* ty = cstatic_resolve_new(self, sym, ast->children.data[0]); for (size_t i=1; ichildren.size; i++) { int status = cstatic_check_type( self, ast->children.data[i], + sym, msg, size, ty, @@ -263,11 +288,37 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) return 1; } + // Vars Operations + if (ast->type == NODE_IDENT) + { + return 1; + } + + if (ast->type == NODE_VARDECL) + { + char const* name = ast->children.data[0]->value; + + if (symtable_find(sym, name)) + { + fprintf(stderr, "E(%d): '%s' is already defined.\n", + ast->lineno, + name); + exit(-1); + } + + type* ty = cstatic_resolve_new(self, sym, ast->children.data[1]); + assert(ty); + symtable_declare(sym, name, ty); + type_free(ty); + free(ty); + 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]); + type* lhs = cstatic_resolve_new(self, sym, ast->children.data[0]); + type* rhs = cstatic_resolve_new(self, sym, ast->children.data[1]); if (lhs->base_type == TY_TYPE && rhs->base_type == TY_TYPE) { @@ -282,8 +333,8 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) 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]); + type* lhs = cstatic_resolve_new(self, sym, ast->children.data[0]); + type* rhs = cstatic_resolve_new(self, sym, ast->children.data[1]); if (lhs->base_type == TY_TYPE && rhs->base_type == TY_TYPE) { @@ -298,8 +349,8 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) // Array Operations 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]); + type* lhs = cstatic_resolve_new(self, sym, ast->children.data[0]); + type* rhs = cstatic_resolve_new(self, sym, ast->children.data[1]); if (lhs->base_type == TY_ARRAY && type_equals(lhs, rhs)) @@ -315,8 +366,8 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) 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]); + type* lhs = cstatic_resolve_new(self, sym, ast->children.data[0]); + type* rhs = cstatic_resolve_new(self, sym, ast->children.data[1]); if ( (lhs->base_type == TY_ARRAY && rhs->base_type == TY_INTEGER) || (lhs->base_type == TY_INTEGER && rhs->base_type == TY_ARRAY)) @@ -333,8 +384,8 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) // String Operations if (ast->type == NODE_ADD) { - int lhs = cstatic_resolve_base_type(self, ast->children.data[0]); - int rhs = cstatic_resolve_base_type(self, ast->children.data[1]); + int lhs = cstatic_resolve_base_type(self, sym, ast->children.data[0]); + int rhs = cstatic_resolve_base_type(self, sym, ast->children.data[1]); if (lhs == rhs && lhs == TY_STRING) @@ -345,8 +396,8 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) if (ast->type == NODE_MUL) { - int lhs = cstatic_resolve_base_type(self, ast->children.data[0]); - int rhs = cstatic_resolve_base_type(self, ast->children.data[1]); + int lhs = cstatic_resolve_base_type(self, sym, ast->children.data[0]); + int rhs = cstatic_resolve_base_type(self, sym, ast->children.data[1]); if ((lhs == TY_STRING && rhs == TY_INTEGER) || (lhs == TY_INTEGER && rhs == TY_STRING)) @@ -362,6 +413,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) int status = cstatic_check_same_type(self, ast->children.data[0], ast->children.data[1], + sym, msg, size); @@ -377,6 +429,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) { int status = cstatic_check_type_base(self, ast->children.data[0], + sym, msg, size, TY_BOOLEAN, @@ -395,6 +448,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) int status = cstatic_check_same_type(self, ast->children.data[0], ast->children.data[1], + sym, msg, size); @@ -405,6 +459,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) status = cstatic_check_type_base(self, ast->children.data[0], + sym, msg, size, TY_BOOLEAN, @@ -421,6 +476,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) { int status = cstatic_check_type_base(self, ast->children.data[0], + sym, msg, size, TY_INTEGER, @@ -443,6 +499,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) int status = cstatic_check_same_type(self, ast->children.data[0], ast->children.data[1], + sym, msg, size); @@ -453,6 +510,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) status = cstatic_check_type_base(self, ast->children.data[0], + sym, msg, size, TY_INTEGER, @@ -473,6 +531,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) int status = cstatic_check_same_type(self, ast->children.data[0], ast->children.data[1], + sym, msg, size); @@ -483,6 +542,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) status = cstatic_check_type_base(self, ast->children.data[0], + sym, msg, size, TY_INTEGER, @@ -497,7 +557,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size) return 1; } -int cstatic_check_type(cstatic* self, node* lhs, +int cstatic_check_type(cstatic* self, node* lhs, symtable* sym, char* msg, size_t size, type* types, ...) { assert(self); @@ -509,7 +569,7 @@ int cstatic_check_type(cstatic* self, node* lhs, va_start(args, types); type* rhs = types; - type* left = cstatic_resolve_new(self, lhs); + type* left = cstatic_resolve_new(self, sym, lhs); type* all_types[TY_TYPE_COUNT]; @@ -558,7 +618,7 @@ int cstatic_check_type(cstatic* self, node* lhs, return 0; } -int cstatic_check_type_base(cstatic* self, node* lhs, +int cstatic_check_type_base(cstatic* self, node* lhs, symtable* sym, char* msg, size_t size, int types, ...) { assert(self); @@ -570,7 +630,7 @@ int cstatic_check_type_base(cstatic* self, node* lhs, va_start(args, types); int rhs = types; - int left = cstatic_resolve_base_type(self, lhs); + int left = cstatic_resolve_base_type(self, sym, lhs); int all_types[TY_TYPE_COUNT]; memset(all_types, TYPE_END, TY_TYPE_COUNT * sizeof(int)); @@ -610,15 +670,15 @@ int cstatic_check_type_base(cstatic* self, node* lhs, return 0; } -int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs, +int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs, symtable* sym, char* msg, size_t size) { assert(self); assert(lhs); assert(rhs); - type* left = cstatic_resolve_new(self, lhs); - type* right = cstatic_resolve_new(self, rhs); + type* left = cstatic_resolve_new(self, sym, lhs); + type* right = cstatic_resolve_new(self, sym, rhs); if (!type_equals(left, right)) { diff --git a/src/cstatic.h b/src/cstatic.h index c5962ed..b596423 100644 --- a/src/cstatic.h +++ b/src/cstatic.h @@ -3,7 +3,7 @@ #include "commons.h" #include "node.h" -#include "type.h" +#include "symtable.h" #define TYPE_END (-1) @@ -15,18 +15,18 @@ void cstatic_init(cstatic* self); void cstatic_free(cstatic* self); type* cstatic_new_type(cstatic* self, int base_type); -int cstatic_resolve_base_type(cstatic* self, node* ast); +int cstatic_resolve_base_type(cstatic* self, symtable* sym, node* ast); -type* cstatic_resolve_new(cstatic* self, node* ast); -int cstatic_check(cstatic* self, node* ast, char* msg, size_t size); +type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast); +int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t size); -int cstatic_check_type(cstatic* self, node* lhs, +int cstatic_check_type(cstatic* self, node* lhs, symtable* sym, char* msg, size_t size, type* types, ...); -int cstatic_check_type_base(cstatic* self, node* lhs, +int cstatic_check_type_base(cstatic* self, node* lhs, symtable* sym, char* msg, size_t size, int types, ...); -int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs, +int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs, symtable* sym, char* msg, size_t size); #endif diff --git a/src/lex.l b/src/lex.l index 6b422b8..aa89604 100644 --- a/src/lex.l +++ b/src/lex.l @@ -14,6 +14,7 @@ INTEGER -?[0-9]+ FLOAT -?[0-9]+\.[0-9]+ STRING \"[^"]*\" TYPE (int|float|bool|str|array) +IDENT [_A-Za-z][_A-Za-z0-9]* %% {COMMENT} {} @@ -25,6 +26,7 @@ TYPE (int|float|bool|str|array) return TYPE; } +"let" { return LET; } "assert" { return ASSERT; } "<=" { return LE; } ">=" { return GE; } @@ -47,6 +49,7 @@ TYPE (int|float|bool|str|array) ")" { return CPAR; } "[" { return OSQUARE; } "]" { return CSQUARE; } +"=" { return ASSIGN; } {BOOLEAN} { yylval.str = yytext; @@ -68,6 +71,10 @@ TYPE (int|float|bool|str|array) return INTEGER; } +{IDENT} { + yylval.str = yytext; + return IDENT; +} . { fprintf(stderr, "E(%d): Lexical error near '%s'.\n", line, yytext); diff --git a/src/main.c b/src/main.c index e37ad0a..482f279 100644 --- a/src/main.c +++ b/src/main.c @@ -28,19 +28,21 @@ int main(int argc, char** argv) stack_free(); // Static checking + symtable sym; + symtable_init(&sym); cstatic cs; cstatic_init(&cs); size_t const SZ = 512; char msg[SZ]; - int status = cstatic_check(&cs, ast, msg, SZ); - + int status = cstatic_check(&cs, ast, &sym, msg, SZ); + symtable_free(&sym); if (!status) { fprintf(stderr, "%s\n", msg); exit(-1); } - + // Compilation compiler comp; compiler_init(&comp); diff --git a/src/node.h b/src/node.h index 9d0d8f5..5313322 100644 --- a/src/node.h +++ b/src/node.h @@ -11,7 +11,7 @@ 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_INDEX), G(NODE_LT), G(NODE_LE), \ - G(NODE_GT), G(NODE_GE) + G(NODE_GT), G(NODE_GE), G(NODE_VARDECL), G(NODE_IDENT) #include "mutils.h" diff --git a/src/opcodes.h b/src/opcodes.h index 10d2d20..ad67f42 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -41,7 +41,9 @@ G(OP_FLT), \ G(OP_FLE), \ G(OP_FGT), \ - G(OP_FGE) \ + G(OP_FGE), \ + G(OP_STORE), \ + G(OP_LOAD) enum Opcodes { OPCODES(GEN_ENUM) diff --git a/src/parser.y b/src/parser.y index e2187eb..8b39a66 100644 --- a/src/parser.y +++ b/src/parser.y @@ -22,9 +22,9 @@ }; %left ASSERT -%token TYPE BOOLEAN INTEGER FLOAT STRING +%token TYPE BOOLEAN INTEGER FLOAT STRING IDENT %type expr exprs prog array builtins -%type expr_list type type_list +%type expr_list type type_list ident %left EQ NE %left LT GT LE GE %left AND @@ -35,7 +35,7 @@ %left NOT %token OPAR CPAR %token OSQUARE CSQUARE COMMA - +%token LET ASSIGN %type expr_unop %% @@ -97,6 +97,25 @@ expr: stack_push(n); $$ = 1; } + + // VARIABLES + | ident { + } + + | LET ident ASSIGN expr { + node* n = malloc(sizeof(node)); + node_init(n, NODE_VARDECL, "", line); + + node* rhs = stack_pop(); + node* lhs = stack_pop(); + + node_add_child(n, lhs); + node_add_child(n, rhs); + + stack_push(n); + + $$ = 1; + } // EXPRESSIONS | array { @@ -363,6 +382,14 @@ type: } ; +ident: IDENT { + node* n = malloc(sizeof(node)); + node_init(n, NODE_IDENT, $1, line); + stack_push(n); + $$ = 1; +} +; + builtins: type {} diff --git a/src/symtable.c b/src/symtable.c new file mode 100644 index 0000000..5657a76 --- /dev/null +++ b/src/symtable.c @@ -0,0 +1,73 @@ +#include "symtable.h" + +void symtable_init(symtable* self) +{ + assert(self); + self->id = 0; + + self->entries.size = 0; + self->entries.capacity = 1; + self->entries.data = malloc(sizeof(symentry*) + * self->entries.capacity); +} + +void symtable_free(symtable* self) +{ + assert(self); + + for (size_t i=0; ientries.size; i++) + { + free(self->entries.data[i]->name); + type_free(self->entries.data[i]->ty); + free(self->entries.data[i]->ty); + free(self->entries.data[i]); + } + + free(self->entries.data); + + self->entries.size = 0; + self->entries.capacity = 0; + self->entries.data = NULL; +} + +size_t symtable_declare(symtable* self, char const* name, type* ty) +{ + assert(self); + + if (self->entries.size >= self->entries.capacity) + { + self->entries.capacity *= 2; + + self->entries.data = realloc( + self->entries.data, + sizeof(symentry*) + * self->entries.capacity + ); + } + + self->entries.data[self->entries.size] = + malloc(sizeof(symentry)); + + + self->entries.data[self->entries.size]->name = str_new(name); + self->entries.data[self->entries.size]->ty = type_new_clone(ty); + self->entries.data[self->entries.size]->id = self->id; + self->entries.size++; + + return self->id++; +} + +symentry* symtable_find(symtable* self, char const* name) +{ + assert(self); + + for (size_t i=0; ientries.size; i++) + { + if (strcmp(self->entries.data[i]->name, name) == 0) + { + return self->entries.data[i]; + } + } + + return NULL; +} diff --git a/src/symtable.h b/src/symtable.h new file mode 100644 index 0000000..bcf93b3 --- /dev/null +++ b/src/symtable.h @@ -0,0 +1,29 @@ +#ifndef SYMTABLE_H +#define SYMTABLE_H + +#include "commons.h" +#include "type.h" + +typedef struct { + size_t id; + char* name; + type* ty; +} symentry; + +typedef struct { + struct { + size_t size; + size_t capacity; + symentry** data; + } entries; + + size_t id; +} symtable; + +void symtable_init(symtable* self); +void symtable_free(symtable* self); + +size_t symtable_declare(symtable* self, char const* name, type* ty); +symentry* symtable_find(symtable* self, char const* name); + +#endif diff --git a/src/vm.c b/src/vm.c index e8ee8e5..05aea5c 100644 --- a/src/vm.c +++ b/src/vm.c @@ -8,6 +8,10 @@ void vm_init(vm* self) self->stack.capacity = 1; self->stack.data = malloc(sizeof(value*) * self->stack.capacity); + self->vars.size = 0; + self->vars.capacity = 1; + self->vars.data = malloc(sizeof(var*) * self->vars.capacity); + self->prog = NULL; self->pc = 0; } @@ -15,6 +19,16 @@ void vm_init(vm* self) void vm_free(vm* self) { assert(self); + + for (size_t i=0; ivars.size; i++) + { + value_free(self->vars.data[i]->val); + free(self->vars.data[i]->val); + free(self->vars.data[i]); + } + + free(self->vars.data); + for (size_t i=0; istack.size; i++) { value_free(self->stack.data[i]); @@ -86,6 +100,9 @@ void vm_exec(vm* self, program* prog) case OP_FGT: vm_fgt(self); break; case OP_FGE: vm_fge(self); break; + case OP_LOAD: vm_load(self, param); break; + case OP_STORE: vm_store(self, param); break; + default: { fprintf(stderr, "unknown opcode %s\n", OpcodesStr[opcode]); @@ -145,6 +162,41 @@ size_t vm_str(vm* self, char* buffer, size_t size) return sz; } +void vm_set(vm* self, size_t addr, value* val) +{ + assert(self); + assert(val); + + if (self->vars.size > self->vars.capacity) + { + self->vars.capacity *= 2; + self->vars.data = realloc( + self->vars.data, + sizeof(var*) * self->vars.capacity + ); + } + + self->vars.data[self->vars.size] = malloc(sizeof(var)); + self->vars.data[self->vars.size]->addr = addr; + self->vars.data[self->vars.size]->val = value_new_clone(val); + self->vars.size++; +} + +value* vm_get(vm* self, size_t addr) +{ + assert(self); + + for (size_t i=0; ivars.size; i++) + { + if (self->vars.data[i]->addr == addr) + { + return value_new_clone(self->vars.data[i]->val); + } + } + + return NULL; +} + void vm_push(vm* self, int param) { assert(self); @@ -902,3 +954,28 @@ void vm_ige(vm* self) self->pc++; } + +void vm_store(vm* self, int param) +{ + assert(self); + + value* val = vm_pop_value(self); + + vm_set(self, param, val); + + value_free(val); + free(val); + + self->pc++; +} + +void vm_load(vm* self, int param) +{ + assert(self); + + value* val = vm_get(self, param); + assert(val); + vm_push_value(self, val); + + self->pc++; +} diff --git a/src/vm.h b/src/vm.h index 9e188bc..36f7c9a 100644 --- a/src/vm.h +++ b/src/vm.h @@ -5,12 +5,23 @@ #include "value.h" #include "program.h" +typedef struct { + size_t addr; + value* val; +} var; + typedef struct { struct { size_t capacity; size_t size; value** data; } stack; + + struct { + size_t capacity; + size_t size; + var** data; + } vars; size_t pc; program* prog; @@ -24,6 +35,9 @@ void vm_push_value(vm* self, value* val); value* vm_pop_value(vm* self); size_t vm_str(vm* self, char* buffer, size_t size); +void vm_set(vm* self, size_t addr, value* val); +value* vm_get(vm* self, size_t addr); + void vm_push(vm* self, int param); void vm_and(vm* self); void vm_or(vm* self); @@ -70,4 +84,7 @@ void vm_fle(vm* self); void vm_fgt(vm* self); void vm_fge(vm* self); +void vm_store(vm* self, int param); +void vm_load(vm* self, int param); + #endif diff --git a/tests/err_vars.wuz b/tests/err_vars.wuz new file mode 100644 index 0000000..646c10e --- /dev/null +++ b/tests/err_vars.wuz @@ -0,0 +1,3 @@ +let x = 0 x + 1.2 +let x = false x + "false" +let x=0 let x=7 diff --git a/tests/test_vars.wuz b/tests/test_vars.wuz new file mode 100644 index 0000000..9bfceb2 --- /dev/null +++ b/tests/test_vars.wuz @@ -0,0 +1,5 @@ +let a = 4 +let b = 7 +let c = a * b + 1 + +assert 29 == c