aboutsummaryrefslogtreecommitdiff
path: root/src/types.c
diff options
context:
space:
mode:
authorMustafa Quraish <[email protected]>2022-02-03 21:01:03 -0500
committerMustafa Quraish <[email protected]>2022-02-03 21:01:03 -0500
commit9f3edcbeea51dd8841b9d89fa7ef98f11682a1c7 (patch)
treeb2a4b6fa51ad558b36facde2cf952a6af5a25669 /src/types.c
parentAdd automatic type inference for initialized variable declarations (diff)
downloadcup-9f3edcbeea51dd8841b9d89fa7ef98f11682a1c7.tar.xz
cup-9f3edcbeea51dd8841b9d89fa7ef98f11682a1c7.zip
Add support for basic structs
Structs for now (and probably for the near future) are not allowed to be passed by value, and instead you just pass a pointer to it. Nested structs can also be defined, and they can be either anonymous, or named (in which case only the members can access the type).
Diffstat (limited to 'src/types.c')
-rw-r--r--src/types.c54
1 files changed, 51 insertions, 3 deletions
diff --git a/src/types.c b/src/types.c
index abbba86..5138164 100644
--- a/src/types.c
+++ b/src/types.c
@@ -36,6 +36,7 @@ i64 size_for_type(Type *type)
case TYPE_PTR: return 8;
case TYPE_CHAR: return 1;
case TYPE_ARRAY: return type->array_size * size_for_type(type->ptr);
+ case TYPE_STRUCT: return type->fields.size;
default: {
printf("Unknown type: %d\n", type->type);
assert(false && "Unreachable type");
@@ -86,9 +87,18 @@ bool is_int_type(Type *type)
}
}
-static char *data_type_to_str(DataType type)
+bool is_struct_or_struct_ptr(Type *type)
{
- switch (type)
+ if (type->type == TYPE_STRUCT)
+ return true;
+ if (type->type == TYPE_PTR && type->ptr->type == TYPE_STRUCT)
+ return true;
+ return false;
+}
+
+static char *data_type_to_str(Type *type)
+{
+ switch (type->type)
{
case TYPE_NONE: return "void";
case TYPE_INT: return "int";
@@ -96,6 +106,7 @@ static char *data_type_to_str(DataType type)
case TYPE_ARRAY: return "array";
case TYPE_CHAR: return "char";
case TYPE_ANY: return "<@>";
+ case TYPE_STRUCT: return type->struct_name;
default: assert(false && "Unreachable");
}
}
@@ -114,16 +125,50 @@ char *type_to_str(Type *type)
// FIXME: This is inefficient as all hell but this will only really be
// used for error reporting.
- strcat(str, data_type_to_str(type->type));
+ strcat(str, data_type_to_str(type));
for (int i = 0; i < ptr_count; i++)
strcat(str, "*");
return str;
}
+i64 push_field(Type *type, char *field_name, Type *field_type)
+{
+ assert(type->type == TYPE_STRUCT);
+ type->fields.type = realloc(type->fields.type, sizeof(Type *) * (type->fields.num_fields + 1));
+ type->fields.offset = realloc(type->fields.offset, sizeof(i64) * (type->fields.num_fields + 1));
+ type->fields.name = realloc(type->fields.name, sizeof(char *) * (type->fields.num_fields + 1));
+
+ i64 field_size = size_for_type(field_type);
+ i64 offset_factor = i64min(field_size, 8);
+ i64 offset = align_up(type->fields.size, offset_factor);
+
+ type->fields.type[type->fields.num_fields] = field_type;
+ type->fields.offset[type->fields.num_fields] = offset;
+ type->fields.name[type->fields.num_fields] = field_name;
+ type->fields.size = offset + field_size;
+ type->fields.num_fields++;
+
+ return offset;
+}
+
+i64 find_field_index(Type *type, char *field_name)
+{
+ assert(type->type == TYPE_STRUCT);
+ for (int i = 0; i < type->fields.num_fields; i++) {
+ if (strcmp(type->fields.name[i], field_name) == 0)
+ return i;
+ }
+ return -1;
+}
+
+
Node *handle_unary_expr_types(Node *node, Token *token)
{
Type *old_type = node->unary_expr->expr_type;
+ if (node->type != OP_ADDROF && old_type->type == TYPE_STRUCT)
+ die_location(token->loc, "Performing invalid unary operation on struct type");
+
if (node->type == OP_NOT) {
node->expr_type = type_new(TYPE_INT);
} else if (node->type == OP_ADDROF) {
@@ -154,6 +199,9 @@ Node *handle_binary_expr_types(Node *node, Token *token)
{
Type *left = node->binary.left->expr_type;
Type *right = node->binary.right->expr_type;
+
+ if (left->type == TYPE_STRUCT || right->type == TYPE_STRUCT)
+ die_location(token->loc, "Performing invalid binary operation on struct type");
switch (node->type)
{