From 4ad83f8abf0cc0050f53f70ff23c6c7cf17c1714 Mon Sep 17 00:00:00 2001 From: Dibyendu Majumdar Date: Sun, 25 Aug 2019 01:03:11 +0100 Subject: [PATCH] issue #98 typecheck expression statements --- include/ravi_ast.h | 5 ++- ravi-tests/ravi_test_ast2.expected | 2 +- src/ravi_ast_typecheck.c | 61 ++++++++++++++++++++++++++++-- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/include/ravi_ast.h b/include/ravi_ast.h index 063261c..0d8ea49 100644 --- a/include/ravi_ast.h +++ b/include/ravi_ast.h @@ -155,11 +155,11 @@ struct ast_node { struct { struct lua_symbol_list *var_list; struct ast_node_list *expr_list; - } local_stmt; + } local_stmt; /* local declarations */ struct { struct ast_node_list *var_expr_list; /* Optional var expressions, comma separated */ struct ast_node_list *expr_list; /* Comma separated expressions */ - } expression_stmt; /* Also covers assignments*/ + } expression_stmt; /* Also covers assignments */ struct { struct ast_node *name; /* base symbol to be looked up */ struct ast_node_list *selectors; /* Optional */ @@ -194,6 +194,7 @@ struct ast_node { struct { struct var_type type; } common_expr; /* To access the type field common to all expr objects */ + /* all expr types must be compatible with common_expr */ struct { struct var_type type; union { diff --git a/ravi-tests/ravi_test_ast2.expected b/ravi-tests/ravi_test_ast2.expected index 6b8a338..935c1dd 100644 --- a/ravi-tests/ravi_test_ast2.expected +++ b/ravi-tests/ravi_test_ast2.expected @@ -249,7 +249,7 @@ function() function() --[expression statement start] --[expression list start] - --[suffixed expr start] closure + --[suffixed expr start] any --[primary start] function() end diff --git a/src/ravi_ast_typecheck.c b/src/ravi_ast_typecheck.c index 147e93a..354cbe2 100644 --- a/src/ravi_ast_typecheck.c +++ b/src/ravi_ast_typecheck.c @@ -190,6 +190,28 @@ static void typecheck_suffixedexpr(struct ast_node *function, struct ast_node *n copy_type(node->suffixed_expr.type, prev_node->common_expr.type); } +static void typecheck_var_assignment(struct var_type *var_type, struct var_type *expr_type, const char *var_name) { + if (var_type->type_code == RAVI_TANY) + // Any value can be assigned to type ANY + return; + + if (var_type->type_code == RAVI_TNUMINT || var_type->type_code == RAVI_TNUMFLT) { + if (expr_type->type_code == RAVI_TNUMINT || expr_type->type_code == RAVI_TNUMFLT) { + // Okay + // TODO insert a typecast? + } + else { + fprintf(stderr, "Assignment to local symbol %s is not type compatible\n", var_name); + } + return; + } + + // all other types must strictly match + if (!is_type_same(*var_type, *expr_type)) { // We should probably check type convertability here + fprintf(stderr, "Assignment to local symbol %s is not type compatible\n", var_name); + } +} + static void typecheck_local_statement(struct ast_node *function, struct ast_node *node) { // The local vars should already be annotated // We need to typecheck the expressions to the right of = @@ -207,15 +229,47 @@ static void typecheck_local_statement(struct ast_node *function, struct ast_node if (!var || !expr) break; - if (var->value_type.type_code != RAVI_TANY && !is_type_same(var->value_type, expr->common_expr.type)) { // We should probably check type convertability here - fprintf(stderr, "Assignment to local symbol %s is not type compatible\n", getstr(var->var.var_name)); - } + struct var_type *var_type = &var->value_type; + struct var_type *expr_type = &expr->common_expr.type; + const char *var_name = getstr(var->var.var_name); + + typecheck_var_assignment(var_type, expr_type, var_name); + + NEXT_PTR_LIST(var); + NEXT_PTR_LIST(expr); + } +} + +static void typecheck_expr_statement(struct ast_node *function, struct ast_node *node) { + + if (node->expression_stmt.var_expr_list) + typecheck_ast_list(function, node->expression_stmt.var_expr_list); + typecheck_ast_list(function, node->expression_stmt.expr_list); + + if (!node->expression_stmt.var_expr_list) + return; + + struct ast_node *var; + struct ast_node *expr; + PREPARE_PTR_LIST(node->expression_stmt.var_expr_list, var); + PREPARE_PTR_LIST(node->local_stmt.expr_list, expr); + + for (;;) { + if (!var || !expr) + break; + + struct var_type *var_type = &var->common_expr.type; + struct var_type *expr_type = &expr->common_expr.type; + const char *var_name = ""; // FIXME how do we get this? + + typecheck_var_assignment(var_type, expr_type, var_name); NEXT_PTR_LIST(var); NEXT_PTR_LIST(expr); } } + /* Type checker - WIP */ static void typecheck_ast_node(struct ast_node *function, struct ast_node *node) { switch (node->type) { @@ -248,6 +302,7 @@ static void typecheck_ast_node(struct ast_node *function, struct ast_node *node) break; } case AST_EXPR_STMT: { + typecheck_expr_statement(function, node); break; } case AST_IF_STMT: {