summaryrefslogtreecommitdiff
path: root/type_checker.c
diff options
context:
space:
mode:
Diffstat (limited to 'type_checker.c')
-rw-r--r--type_checker.c110
1 files changed, 63 insertions, 47 deletions
diff --git a/type_checker.c b/type_checker.c
index 5905c83..ccd816f 100644
--- a/type_checker.c
+++ b/type_checker.c
@@ -18,17 +18,28 @@ static void type_check_expr(struct expr_node* node);
static void type_check_stmt(struct stmt_node* node);
static void type_check_group(struct group_node* node);
+static const char* get_type_name(const struct type* type) {
+ switch (type->type) {
+ case TP_DATA:
+ return type->data.data_type->name;
+ case TP_PTR:
+ /* TODO: this is a stub */
+ return type->pointer.data_type->name;
+ }
+ TYPE_PANIC("unhandled type of type case");
+}
+
static void assert_cast_compatible(
- const struct type_def* lval_type,
- const struct type_def* rval_type
+ const struct type* lval_type,
+ const struct type* rval_type
) {
/* TODO: impl */
/* TODO: we should also insert cast nodes eventually */
if (false) {
TYPE_PANIC(
"cannot assign value of type '%s' to '%s'",
- lval_type->key.name,
- rval_type->key.name);
+ get_type_name(lval_type),
+ get_type_name(rval_type));
}
}
@@ -47,45 +58,52 @@ static void exit_scope(struct scope* child_scope) {
scope = child_scope->next_out;
}
-static const struct type_def* resolve_type_ref(struct type_ref_node* node) {
- /* TODO: support pointers and such */
- if (node->type.raw_type == NULL) TYPE_PANIC("use of unresolved type");
- if (node->type.ptr_level > 0) return ast_ref->pointer_type;
- return node->type.raw_type;
-}
-
-static const struct type_def* resolve_int_lit(struct int_lit_node* node) {
- return ast_ref->integral_type;
-}
-
-static const struct type_def* resolve_float_lit(struct float_lit_node* node) {
- return ast_ref->decimal_type;
+static struct type* allocate_data_type(
+ const struct data_type* data_type,
+ bool is_unsigned
+) {
+ if (is_unsigned && data_type->is_floating)
+ TYPE_PANIC("floating type '%s' cannot be unsigned", data_type->name);
+
+ struct type* type = ccc_alloc(sizeof(struct type));
+ type->type = TP_DATA;
+ type->data.data_type = data_type;
+ type->data.is_signed = !is_unsigned;
+ return type;
}
-static const struct type_def* resolve_char_lit(struct char_lit_node* node) {
- return ast_ref->char_type;
+static struct type* allocate_pointer_type(
+ const struct data_type* data_type,
+ integral_t ptr_level
+) {
+ struct type* type = ccc_alloc(sizeof(struct type));
+ type->type = TP_PTR;
+ type->pointer.data_type = data_type;
+ type->pointer.ptr_level = ptr_level;
+ return type;
}
-static const struct type_def* resolve_str_lit(struct str_lit_node* node) {
- return ast_ref->pointer_type;
+static struct type* copy_type(const struct type* source_type) {
+ struct type* type = ccc_alloc(sizeof(struct type));
+ *type = *source_type;
+ return type;
}
-static const struct type_def* resolve_var_ref(struct var_ref_node* node) {
- if (node->def_ref->resolved_type == NULL)
- TYPE_PANIC("variable '%s' has unresolved type.", node->def_ref->name);
- return node->def_ref->resolved_type;
+static struct type* resolve_var_ref(struct var_ref_node* node) {
+ if (node->def_ref->type == NULL)
+ TYPE_PANIC("variable '%s' has undefined type.", node->def_ref->name);
+ return copy_type(node->def_ref->type);
}
static void type_check_var_decl(struct var_decl_node* node) {
- const struct type_def* lval_type = resolve_type_ref(&node->type);
- node->def_ref->resolved_type = lval_type;
+ node->def_ref->type = &node->type;
if (node->initial_value != NULL) {
type_check_expr(node->initial_value);
- assert_cast_compatible(lval_type, node->initial_value->resolved_type);
+ assert_cast_compatible(&node->type, node->initial_value->resolved_type);
}
}
-static const struct type_def* resolve_assign(struct assign_node* node) {
+static struct type* resolve_assign(struct assign_node* node) {
switch (node->lval->type) {
case EXPR_VAR_REF:
break;
@@ -95,14 +113,14 @@ static const struct type_def* resolve_assign(struct assign_node* node) {
type_check_expr(node->lval);
type_check_expr(node->rval);
- const struct type_def* lval_type = node->lval->resolved_type;
- const struct type_def* rval_type = node->rval->resolved_type;
+ const struct type* lval_type = node->lval->resolved_type;
+ const struct type* rval_type = node->rval->resolved_type;
assert_cast_compatible(lval_type, rval_type);
- return lval_type;
+ return copy_type(lval_type);
}
-static const struct type_def* resolve_call(struct call_node* node) {
+static struct type* resolve_call(struct call_node* node) {
struct decl_list_node* arg_decl = node->called_fn_ref->args;
struct expr_list_node* arg_eval = node->args;
while (arg_decl != NULL && arg_eval != NULL) {
@@ -110,10 +128,10 @@ static const struct type_def* resolve_call(struct call_node* node) {
TYPE_PANIC("C does not support default arguments");
type_check_var_decl(arg_decl->decl);
- const struct type_def* decl_type =
- arg_decl->decl->def_ref->resolved_type;
+ const struct type* decl_type =
+ arg_decl->decl->def_ref->type;
type_check_expr(arg_eval->expr);
- const struct type_def* eval_type = arg_eval->expr->resolved_type;
+ const struct type* eval_type = arg_eval->expr->resolved_type;
assert_cast_compatible(decl_type, eval_type);
arg_decl = arg_decl->next;
@@ -124,36 +142,36 @@ static const struct type_def* resolve_call(struct call_node* node) {
"mismatched argument count in call to '%s'",
node->called_fn_ref->name);
- return resolve_type_ref(&node->called_fn_ref->return_type);
+ return copy_type(&node->called_fn_ref->return_type);
}
-static const struct type_def* resolve_unary(struct unary_node* node) {
+static struct type* resolve_unary(struct unary_node* node) {
type_check_expr(node->expr);
/* TODO: delegate by individual operation to prohibit shit like -"yes" */
- return node->expr->resolved_type;
+ return copy_type(node->expr->resolved_type);
}
-static const struct type_def* resolve_binary(struct binary_node* node) {
+static struct type* resolve_binary(struct binary_node* node) {
/* TODO: math rules and such lol */
type_check_expr(node->lhs);
type_check_expr(node->rhs);
assert_cast_compatible(node->lhs->resolved_type, node->rhs->resolved_type);
- return node->lhs->resolved_type;
+ return copy_type(node->lhs->resolved_type);
}
static void type_check_expr(struct expr_node* node) {
switch (node->type) {
case EXPR_INT_LIT:
- node->resolved_type = resolve_int_lit(&node->inner.int_lit);
+ node->resolved_type = allocate_data_type(integral_type, false);
break;
case EXPR_FLOAT_LIT:
- node->resolved_type = resolve_float_lit(&node->inner.float_lit);
+ node->resolved_type = allocate_data_type(floating_type, false);
break;
case EXPR_CHAR_LIT:
- node->resolved_type = resolve_char_lit(&node->inner.char_lit);
+ node->resolved_type = allocate_data_type(character_type, false);
break;
case EXPR_STR_LIT:
- node->resolved_type = resolve_str_lit(&node->inner.str_lit);
+ node->resolved_type = allocate_pointer_type(character_type, 1);
break;
case EXPR_VAR_REF:
node->resolved_type = resolve_var_ref(&node->inner.var_ref);
@@ -253,8 +271,6 @@ static void type_check_group(struct group_node* node) {
static void type_check_fn_decl(struct fn_decl_node* node) {
enter_scope(node->scope);
- node->resolved_return_type = resolve_type_ref(&node->return_type);
-
for (struct decl_list_node* arg_decl = node->args;
arg_decl != NULL;
arg_decl = arg_decl->next)