#include "tysolver.h" #include "lib/tysy.h" void tysolver_init(tysolver_t* tysolver, sym_t* sym, tysy_t* tysy) { assert(tysolver); assert(sym); assert(tysy); tysolver->sym = sym; tysolver->tysy = tysy; tysolver->scope = 0; } void tysolver_free(tysolver_t* tysolver) { assert(tysolver); } /* #define NODE_TYPE(G) \ G(NODE_MOD), \ G(NODE_LET), G(NODE_IDENT), G(NODE_ASSIGN), G(NODE_VARDECL) */ type_t* tysolver_try_solve_node(tysolver_t* tysolver, node_t* node) { assert(tysolver); assert(node); switch (node->type) { case NODE_BLOCK: { tysolver->scope++; if (node->children.size > 0) { size_t last = node->children.size - 1; return tysolver_try_solve_node(tysolver, (node_t*) node->children.data[last]); } tysolver->scope--; } break; case NODE_VARDECL: { return tysolver_try_solve_node(tysolver, (node_t*) node->children.data[1]); } break; case NODE_IDENT: { char* name = node->value.data; node_t* block = node_try_find_parent(node, NODE_BLOCK); sym_entry_t* entry = sym_try_find_by_name(tysolver->sym, name, tysolver->scope, SYM_PRE | SYM_DECL, block); assert(entry); return entry->type; } break; case NODE_SUB: case NODE_DIV: case NODE_MODULO: case NODE_POW: case NODE_NUM: { type_t* ty = tysy_try_find_type(tysolver->tysy, "num"); assert(ty); return ty; } break; case NODE_ADD: { return tysolver_try_solve_node(tysolver, (node_t*) node->children.data[0]); } break; case NODE_MUL: { type_t* lhs = tysolver_try_solve_node(tysolver, (node_t*) node->children.data[0]); type_t* rhs = tysolver_try_solve_node(tysolver, (node_t*) node->children.data[1]); if (type_eq(lhs, rhs) && lhs->kind == TYPE_NUM) { return tysolver_try_solve_node(tysolver, (node_t*) node->children.data[0]); } else if ((lhs->kind == TYPE_NUM && rhs->kind == TYPE_STR) || (rhs->kind == TYPE_NUM && lhs->kind == TYPE_STR)) { return tysy_try_find_type(tysolver->tysy, "str"); } else { tysolver_error(tysolver, node); } } break; case NODE_ASSERT: case NODE_EQ: case NODE_NE: case NODE_LT: case NODE_LE: case NODE_GT: case NODE_GE: case NODE_AND: case NODE_OR: case NODE_NOT: case NODE_BOOL: { type_t* ty = tysy_try_find_type(tysolver->tysy, "bool"); assert(ty); return ty; } break; case NODE_STR: { type_t* ty = tysy_try_find_type(tysolver->tysy, "str"); assert(ty); return ty; } break; default: { tysolver_error(tysolver, node); } break; } return NULL; } void tysolver_error(tysolver_t* tysolver, node_t* node) { fprintf(stderr, "Cannot solve type of '%s'.\n", NodeTypeStr[node->type]); abort(); }