roza/lib/tysolver.c

147 lines
3.5 KiB
C
Raw Permalink Normal View History

#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;
2023-12-20 19:54:58 +00:00
sym_entry_t* entry = sym_try_find_by_name(tysolver->sym,
name,
tysolver->scope,
SYM_PRE | SYM_DECL,
2023-12-20 19:54:58 +00:00
node);
return entry ? entry->type : NULL;
} 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;
2023-12-20 19:54:58 +00:00
case NODE_IF:
case NODE_FUNCALL: {
2023-12-18 18:34:31 +00:00
return NULL;
} break;
2023-12-20 19:54:58 +00:00
case NODE_FUNDECL: {
type_t* ty = tysy_try_find_type(tysolver->tysy, "fun");
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();
}