diff options
| author | Mustafa Quraish <[email protected]> | 2022-02-03 03:06:58 -0500 |
|---|---|---|
| committer | Mustafa Quraish <[email protected]> | 2022-02-03 03:08:55 -0500 |
| commit | 202fe666d4b5b69131a09a3911cf8c3828b720d8 (patch) | |
| tree | 00d6e4165192b6f684e9f3dfad1fcdbd6cf13f80 /src | |
| parent | Move all common utilities to `std/common.cup` (diff) | |
| download | cup-202fe666d4b5b69131a09a3911cf8c3828b720d8.tar.xz cup-202fe666d4b5b69131a09a3911cf8c3828b720d8.zip | |
Allow implicitly converting between integer-like-types
This design should also be useful for structs down the road.
Diffstat (limited to 'src')
| -rw-r--r-- | src/parser.c | 11 | ||||
| -rw-r--r-- | src/types.c | 23 | ||||
| -rw-r--r-- | src/types.h | 2 |
3 files changed, 32 insertions, 4 deletions
diff --git a/src/parser.c b/src/parser.c index 3ee8abf..13878d1 100644 --- a/src/parser.c +++ b/src/parser.c @@ -279,7 +279,7 @@ Node *parse_var_declaration(Lexer *lexer) node->var_decl.value = parse_expression(lexer); - if (!type_equals(node->var_decl.var.type, node->var_decl.value->expr_type)) { + if (!is_convertible(node->var_decl.var.type, node->var_decl.value->expr_type)) { fprintf(stderr, "- Variable type: %s\n", type_to_str(node->var_decl.var.type)); fprintf(stderr, "- Value type: %s\n", type_to_str(node->var_decl.value->expr_type)); die_location(token.loc, "Type mismatch for variable declaration `%s` initalizer", node->var_decl.var.name); @@ -318,7 +318,7 @@ Node *parse_function_call_args(Lexer *lexer, Node *func) if (call->call.num_args != func->func.num_args) die_location(identifier.loc, "Function `%s` expects %d arguments, got %d", func->func.name, func->func.num_args, call->call.num_args); for (int i = 0; i < call->call.num_args; i++) { - if (!type_equals(func->func.args[i].type, call->call.args[i]->expr_type)) { + if (!is_convertible(func->func.args[i].type, call->call.args[i]->expr_type)) { fprintf(stderr, "- Function argument %d: %s\n", i, type_to_str(func->func.args[i].type)); fprintf(stderr, "- Provided argument %d: %s\n", i, type_to_str(call->call.args[i]->expr_type)); die_location(identifier.loc, "Type mismatch for argument %d in function call `%s`", i, func->func.name); @@ -519,7 +519,7 @@ Node *parse_expression(Lexer *lexer) assign->assign.value = parse_expression(lexer); - if (!type_equals(node->expr_type, assign->assign.value->expr_type)) { + if (!is_convertible(node->expr_type, assign->assign.value->expr_type)) { fprintf(stderr, "- Variable type: %s\n", type_to_str(assign->assign.var->expr_type)); fprintf(stderr, "- Value type: %s\n", type_to_str(assign->assign.value->expr_type)); die_location(token.loc, "Type mismatch in assignment expression"); @@ -544,8 +544,11 @@ Node *parse_statement(Lexer *lexer) node = Node_new(AST_RETURN); node->unary_expr = parse_expression(lexer); - if (!type_equals(node->unary_expr->expr_type, current_function->func.return_type)) + if (!is_convertible(node->unary_expr->expr_type, current_function->func.return_type)) { + fprintf(stderr, "- Expected type: %s\n", type_to_str(node->unary_expr->expr_type)); + fprintf(stderr, "- Actual: %s\n", type_to_str(current_function->func.return_type)); die_location(token.loc, "Return expression does not match function's return type"); + } assert_token(Lexer_next(lexer), TOKEN_SEMICOLON); } else if (token.type == TOKEN_IF) { diff --git a/src/types.c b/src/types.c index 24458ff..31edc4b 100644 --- a/src/types.c +++ b/src/types.c @@ -17,6 +17,17 @@ bool type_equals(Type *a, Type *b) return a->type == b->type && type_equals(a->ptr, b->ptr); } +bool is_convertible(Type *from, Type *to) +{ + if (from->type == TYPE_ANY || to->type == TYPE_ANY) + return true; + // TODO: Should we rause a warning if the target type is narrower + // than the source type? + if (is_int_type(from) && is_int_type(to)) + return true; + return type_equals(from, to); +} + i64 size_for_type(Type *type) { switch (type->type) @@ -55,6 +66,18 @@ bool is_string_type(Type *type) && type->ptr->type == TYPE_CHAR; } +bool is_int_type(Type *type) +{ + switch (type->type) + { + case TYPE_INT: + case TYPE_CHAR: + return true; + default: + return false; + } +} + static char *data_type_to_str(DataType type) { switch (type) diff --git a/src/types.h b/src/types.h index 7aadd8d..a1f6923 100644 --- a/src/types.h +++ b/src/types.h @@ -23,7 +23,9 @@ i64 size_for_type(Type *type); char *type_to_str(Type *type); bool type_equals(Type *a, Type *b); +bool is_int_type(Type *type); bool is_string_type(Type *type); +bool is_convertible(Type *from, Type *to); // Type checking / casting expressions to right types typedef struct ast_node Node; |