From 9f934cbc0f0fd60a6938ac1c4c84edc270de94ca Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Thu, 7 Apr 2022 12:41:34 -0300 Subject: Add initial implementation of typeclass resolution --- src/nodes.c | 1 + src/nodes.h | 9 ++++++ src/parser.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 94 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/nodes.c b/src/nodes.c index a5b67d1..5689d18 100644 --- a/src/nodes.c +++ b/src/nodes.c @@ -9,6 +9,7 @@ alloc_node(NodeType type) { node->line = 0; node->col = 0; node->scope = NULL; + node->type_class = TYPE_UNK; return node; } diff --git a/src/nodes.h b/src/nodes.h index acbe19e..853495a 100644 --- a/src/nodes.h +++ b/src/nodes.h @@ -15,11 +15,20 @@ typedef enum NodeType { NODE_IF, } NodeType; +typedef enum TypeClass { + TYPE_UNK, + TYPE_NONE, + TYPE_NUM, + TYPE_BOOL, + TYPE_STRING, +} TypeClass; + typedef struct Node { NodeType type; size_t line; size_t col; struct Scope *scope; + TypeClass type_class; union { // Numbers. diff --git a/src/parser.c b/src/parser.c index 841a516..cf7aebb 100644 --- a/src/parser.c +++ b/src/parser.c @@ -505,7 +505,9 @@ symbol_check(Parser *parser, Node *node) { case NODE_BUILTIN: { for (size_t i = 0; i < array_size(node->builtin.args); ++i) { Node *arg = node->builtin.args[i]; - symbol_check(parser, arg); + if (!symbol_check(parser, arg)) { + return false; + } } } break; case NODE_SYMBOL: { @@ -541,10 +543,14 @@ symbol_check(Parser *parser, Node *node) { body->scope = parser->parse_tree->current_scope; for (size_t i = 0; i < array_size(body->block.expr); ++i) { Node *expr = body->block.expr[i]; - symbol_check(parser, expr); + if (!symbol_check(parser, expr)) { + return false; + } } } else { - symbol_check(parser, body); + if (!symbol_check(parser, body)) { + return false; + } } parser->parse_tree->current_scope = prev_scope; } break; @@ -554,7 +560,9 @@ symbol_check(Parser *parser, Node *node) { node->scope = parser->parse_tree->current_scope; for (size_t i = 0; i < array_size(node->block.expr); ++i) { Node *expr = node->block.expr[i]; - symbol_check(parser, expr); + if (!symbol_check(parser, expr)) { + return false; + } } parser->parse_tree->current_scope = prev_scope; } break; @@ -584,6 +592,72 @@ symbol_check(Parser *parser, Node *node) { return true; } +bool +resolve_typeclass(Parser *parser, Node *node) { + switch (node->type) { + case NODE_BUILTIN: { + switch (node->builtin.type) { + // Numbers. + case TOKEN_ADD: + case TOKEN_SUB: + case TOKEN_MUL: + case TOKEN_DIV: + case TOKEN_MOD: { node->type_class = TYPE_NUM; } break; + // Bools. + case TOKEN_NOT: + case TOKEN_AND: + case TOKEN_OR: + case TOKEN_EQ: + case TOKEN_LT: + case TOKEN_GT: + case TOKEN_LE: + case TOKEN_GE: { node->type_class = TYPE_BOOL; } break; + default: break; + } + for (size_t i = 0; i < array_size(node->builtin.args); ++i) { + Node *arg = node->builtin.args[i]; + resolve_typeclass(parser, arg); + } + } break; + case NODE_SYMBOL: { + // TODO: Resolve symbol type? + } break; + case NODE_FUN: { + // TODO: Resolve `node->type_class` based on the return value. + resolve_typeclass(parser, node->fun.body); + } break; + case NODE_BLOCK: { + for (size_t i = 0; i < array_size(node->block.expr); ++i) { + Node *expr = node->block.expr[i]; + resolve_typeclass(parser, expr); + } + Node *last_expr = node->block.expr[array_size(node->block.expr) - 1]; + node->type_class = last_expr->type_class; + } break; + case NODE_IF: { + node->type_class = TYPE_NONE; + resolve_typeclass(parser, node->ifexpr.cond); + resolve_typeclass(parser, node->ifexpr.expr_true); + if (node->ifexpr.expr_false != NULL) { + resolve_typeclass(parser, node->ifexpr.expr_false); + } + } break; + case NODE_SET: { + node->type_class = TYPE_NONE; + resolve_typeclass(parser, node->set.value); + } break; + case NODE_DEF: { + node->type_class = TYPE_NONE; + resolve_typeclass(parser, node->def.value); + } break; + case NODE_NUMBER: { node->type_class = TYPE_NUM; } break; + case NODE_BOOL: { node->type_class = TYPE_BOOL; } break; + case NODE_STRING: { node->type_class = TYPE_STRING; } break; + case NODE_TYPE: { node->type_class = TYPE_NONE; } break; + } + return true; +} + bool semantic_analysis(Parser *parser) { // Fill up global function symbols. @@ -597,11 +671,16 @@ semantic_analysis(Parser *parser) { } } - // Fill up symbol tables in proper scope and check existance. for (size_t i = 0; i < array_size(parser->parse_tree->roots); ++i) { + // Fill up symbol tables in proper scope and check existance. symbol_check(parser, parser->parse_tree->roots[i]); + // Resolve TypeClass for all elements. + resolve_typeclass(parser, parser->parse_tree->roots[i]); } + // TODO: Resolve concrete types. + // TODO: Type check. + return true; } -- cgit v1.2.1