aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMustafa Quraish <[email protected]>2022-02-03 03:06:58 -0500
committerMustafa Quraish <[email protected]>2022-02-03 03:08:55 -0500
commit202fe666d4b5b69131a09a3911cf8c3828b720d8 (patch)
tree00d6e4165192b6f684e9f3dfad1fcdbd6cf13f80 /src
parentMove all common utilities to `std/common.cup` (diff)
downloadcup-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.c11
-rw-r--r--src/types.c23
-rw-r--r--src/types.h2
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;