From 9bb5a60b2a8a5cfcb40854151b78440bb2b3bdd9 Mon Sep 17 00:00:00 2001 From: bog Date: Sat, 26 Aug 2023 11:26:51 +0200 Subject: [PATCH] ADD: 'is' keyword to test an expression against a type. --- src/compiler.c | 10 ++++++++++ src/cstatic.c | 3 ++- src/lex.l | 4 ++-- src/node.h | 2 +- src/opcodes.h | 3 ++- src/parser.y | 20 ++++++++++++++++++-- src/vm.c | 24 ++++++++++++++++++++++++ src/vm.h | 2 ++ tests/test_is.wuz | 16 ++++++++++++++++ 9 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 tests/test_is.wuz diff --git a/src/compiler.c b/src/compiler.c index 0d4a3e5..dc6fa75 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -60,6 +60,11 @@ void compile_node(compiler* self, node* root, program* prog) free(ty); cstatic_free(&cs); } + else if (root->type == NODE_IS) + { + compile_children(self, root, prog); + program_add_instr(prog, OP_TEQ, NO_PARAM); + } else if (root->type == NODE_VARDECL) { cstatic cs; @@ -463,6 +468,11 @@ type* compile_get_type(compiler* self, node* root) type_init(ty, TY_BOOLEAN); } + else if (strcmp(root->value, "type") == 0) + { + type_init(ty, TY_TYPE); + } + else if (strcmp(root->value, "array") == 0) { type_init(ty, TY_ARRAY); diff --git a/src/cstatic.c b/src/cstatic.c index 02a0492..7f41ed3 100644 --- a/src/cstatic.c +++ b/src/cstatic.c @@ -201,7 +201,8 @@ type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast) || ast->type == NODE_GT || ast->type == NODE_GE || ast->type == NODE_EQ - || ast->type == NODE_NE) + || ast->type == NODE_NE + || ast->type == NODE_IS) { return cstatic_new_type(self, TY_BOOLEAN); diff --git a/src/lex.l b/src/lex.l index 70ffb13..4db861d 100644 --- a/src/lex.l +++ b/src/lex.l @@ -13,7 +13,7 @@ BOOLEAN true|false INTEGER -?[0-9]+ FLOAT -?[0-9]+\.[0-9]+ STRING \"[^"]*\" -TYPE (int|float|bool|str|array) +TYPE (int|float|bool|str|array|type) IDENT [_A-Za-z][_A-Za-z0-9]* %% @@ -25,7 +25,7 @@ IDENT [_A-Za-z][_A-Za-z0-9]* yylval.str = str_new(yytext); return TYPE; } - +"is" { return IS; } "do" { return DO; } "end" { return END; } "let!" { return LET_MUT; } diff --git a/src/node.h b/src/node.h index 580c4e1..68d323d 100644 --- a/src/node.h +++ b/src/node.h @@ -12,7 +12,7 @@ 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_VARDECL), G(NODE_IDENT), \ - G(NODE_CONSTDECL), G(NODE_ASSIGN), G(NODE_DO) + G(NODE_CONSTDECL), G(NODE_ASSIGN), G(NODE_DO), G(NODE_IS) #include "mutils.h" diff --git a/src/opcodes.h b/src/opcodes.h index 8c73fec..afa97ad 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -44,7 +44,8 @@ G(OP_FGE), \ G(OP_STORE), \ G(OP_LOAD), \ - G(OP_ASTORE) + G(OP_ASTORE), \ + G(OP_TEQ) enum Opcodes { diff --git a/src/parser.y b/src/parser.y index ab867fb..febaf7b 100644 --- a/src/parser.y +++ b/src/parser.y @@ -37,6 +37,7 @@ %token OSQUARE CSQUARE COMMA %token LET LET_MUT ASSIGN DO END %type expr_unop +%left IS %% @@ -78,9 +79,24 @@ exprs: expr: + // TYPE OPERATORS + expr IS type { + node* n = malloc(sizeof(node)); + node_init(n, NODE_IS, "", line); + + node* rhs = stack_pop(); + node* lhs = stack_pop(); + + node_add_child(n, lhs); + node_add_child(n, rhs); + + stack_push(n); + $$ = 1; + } + // BLOCK - DO exprs END { - node *n = malloc(sizeof(node)); + | DO exprs END { + node* n = malloc(sizeof(node)); node_init(n, NODE_DO, "", line); size_t const SZ = $2; diff --git a/src/vm.c b/src/vm.c index 86ee598..54d4ea9 100644 --- a/src/vm.c +++ b/src/vm.c @@ -104,6 +104,8 @@ void vm_exec(vm* self, program* prog) case OP_STORE: vm_store(self, param); break; case OP_ASTORE: vm_astore(self, param); break; + case OP_TEQ: vm_teq(self); break; + default: { fprintf(stderr, "unknown opcode %s\n", OpcodesStr[opcode]); @@ -1093,3 +1095,25 @@ void vm_astore(vm* self, int param) self->pc++; } +void vm_teq(vm* self) +{ + assert(self); + + value* type_val = vm_pop_value(self); + value* expr_val = vm_pop_value(self); + + type* ty = type_val->val.type_val; + + int equals = type_equals(ty, expr_val->type); + + value* val = malloc(sizeof(value)); + value_init_boolean(val, equals, expr_val->lineno); + + vm_push_value(self, val); + + value_free(type_val); free(type_val); + value_free(expr_val); free(expr_val); + + self->pc++; +} + diff --git a/src/vm.h b/src/vm.h index bf91284..0119718 100644 --- a/src/vm.h +++ b/src/vm.h @@ -90,4 +90,6 @@ void vm_store(vm* self, int param); void vm_load(vm* self, int param); void vm_astore(vm* self, int param); +void vm_teq(vm* self); + #endif diff --git a/tests/test_is.wuz b/tests/test_is.wuz new file mode 100644 index 0000000..fbb618f --- /dev/null +++ b/tests/test_is.wuz @@ -0,0 +1,16 @@ +assert 5 is int +assert 5.9 is float +assert false is bool +assert "salut" is str + +assert !(5 is float) +assert !(5.9 is bool) +assert !(false is str) +assert !("salut" is int) + +assert [2, 4, 6] is array +assert [[2, 4], [7, 9]] is array> + +assert int is type +assert type is type +assert (5.2 is int) is bool