codegen almost finished
This commit is contained in:
parent
ed0ad1d095
commit
870cf8f0b4
15 changed files with 523 additions and 126 deletions
90
sema.c
90
sema.c
|
|
@ -152,17 +152,18 @@ static type *get_type(sema *s, ast_node *n)
|
|||
return t;
|
||||
case NODE_PTR_TYPE:
|
||||
t = malloc(sizeof(type));
|
||||
t->size = sizeof(usize);
|
||||
t->alignment = sizeof(usize);
|
||||
if (n->expr.ptr_type.flags & PTR_RAW) {
|
||||
t->name = "ptr";
|
||||
t->tag = TYPE_PTR;
|
||||
t->size = sizeof(usize);
|
||||
t->data.ptr.child = get_type(s, n->expr.ptr_type.type);
|
||||
t->data.ptr.is_const = (n->expr.ptr_type.flags & PTR_CONST) != 0;
|
||||
t->data.ptr.is_volatile = (n->expr.ptr_type.flags & PTR_VOLATILE) != 0;
|
||||
} else {
|
||||
t->name = "slice";
|
||||
t->tag = TYPE_SLICE;
|
||||
t->size = sizeof(usize) * 2; // ptr + len = 16 bytes
|
||||
t->data.slice.child = get_type(s, n->expr.ptr_type.type);
|
||||
t->data.slice.is_const = (n->expr.ptr_type.flags & PTR_CONST) != 0;
|
||||
t->data.slice.is_volatile = (n->expr.ptr_type.flags & PTR_VOLATILE) != 0;
|
||||
|
|
@ -377,8 +378,8 @@ static ast_node *get_def(sema *s, char *name)
|
|||
static type *get_string_type(sema *s, ast_node *node)
|
||||
{
|
||||
type *string_type = arena_alloc(s->allocator, sizeof(type));
|
||||
string_type->tag = TYPE_PTR;
|
||||
string_type->size = sizeof(usize);
|
||||
string_type->tag = TYPE_SLICE;
|
||||
string_type->size = sizeof(usize) * 2; // ptr + len = 16 bytes
|
||||
string_type->alignment = sizeof(usize);
|
||||
string_type->name = "slice";
|
||||
string_type->data.slice.child = shget(type_reg, "u8");
|
||||
|
|
@ -409,6 +410,33 @@ static type *get_access_type(sema *s, ast_node *node)
|
|||
ast_node *member = node->expr.access.member;
|
||||
char *name_start = member->expr.string.start;
|
||||
usize name_len = member->expr.string.len;
|
||||
|
||||
// Handle slice field access
|
||||
if (t && t->tag == TYPE_SLICE) {
|
||||
char *name = intern_string(s, name_start, name_len);
|
||||
if (strcmp(name, "ptr") == 0) {
|
||||
// Return pointer to element type
|
||||
type *ptr_type = arena_alloc(s->allocator, sizeof(type));
|
||||
ptr_type->tag = TYPE_PTR;
|
||||
ptr_type->size = 8;
|
||||
ptr_type->alignment = 8;
|
||||
ptr_type->name = "ptr";
|
||||
ptr_type->data.ptr.child = t->data.slice.child;
|
||||
ptr_type->data.ptr.is_const = t->data.slice.is_const;
|
||||
ptr_type->data.ptr.is_volatile = t->data.slice.is_volatile;
|
||||
free(name);
|
||||
return ptr_type;
|
||||
} else if (strcmp(name, "len") == 0) {
|
||||
// Return usize type
|
||||
free(name);
|
||||
return shget(type_reg, "usize");
|
||||
} else {
|
||||
error(node, "slice doesn't have that field");
|
||||
free(name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!t || (t->tag != TYPE_STRUCT && t->tag != TYPE_UNION)) {
|
||||
error(node, "invalid expression.");
|
||||
return NULL;
|
||||
|
|
@ -557,6 +585,36 @@ static type *get_expression_type(sema *s, ast_node *node)
|
|||
return t;
|
||||
case NODE_ARRAY_SUBSCRIPT:
|
||||
t = get_expression_type(s, node->expr.subscript.expr);
|
||||
|
||||
// Check if this is range subscripting (creates a slice)
|
||||
if (node->expr.subscript.index && node->expr.subscript.index->type == NODE_RANGE) {
|
||||
type *element_type = NULL;
|
||||
switch (t->tag) {
|
||||
case TYPE_SLICE:
|
||||
element_type = t->data.slice.child;
|
||||
break;
|
||||
case TYPE_PTR:
|
||||
element_type = t->data.ptr.child;
|
||||
break;
|
||||
default:
|
||||
error(node, "only pointers and slices can be indexed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Return a slice type
|
||||
type *slice_type = arena_alloc(s->allocator, sizeof(type));
|
||||
slice_type->tag = TYPE_SLICE;
|
||||
slice_type->size = sizeof(usize) * 2;
|
||||
slice_type->alignment = sizeof(usize);
|
||||
slice_type->data.slice.child = element_type;
|
||||
slice_type->data.slice.is_const = false;
|
||||
slice_type->data.slice.len = 0;
|
||||
|
||||
node->expr_type = slice_type;
|
||||
return slice_type;
|
||||
}
|
||||
|
||||
// Regular subscript - return element type
|
||||
switch (t->tag) {
|
||||
case TYPE_SLICE:
|
||||
t = t->data.slice.child;
|
||||
|
|
@ -732,6 +790,18 @@ static void check_statement(sema *s, ast_node *node)
|
|||
break;
|
||||
}
|
||||
if (t->tag == TYPE_STRUCT) {
|
||||
// Struct initialization with NODE_STRUCT_INIT is allowed
|
||||
} else if (node->expr.var_decl.value && node->expr.var_decl.value->type == NODE_STRUCT_INIT &&
|
||||
(t->tag == TYPE_SLICE || t->tag == TYPE_PTR)) {
|
||||
// Array/slice initialization with NODE_STRUCT_INIT is allowed
|
||||
} else if (node->expr.var_decl.value && node->expr.var_decl.value->type == NODE_RANGE &&
|
||||
t->tag == TYPE_SLICE) {
|
||||
// Range initialization for slices is allowed
|
||||
get_expression_type(s, node->expr.var_decl.value);
|
||||
} else if (node->expr.var_decl.value && node->expr.var_decl.value->type == NODE_STRING &&
|
||||
t->tag == TYPE_SLICE) {
|
||||
// String literal can be assigned to slice
|
||||
get_expression_type(s, node->expr.var_decl.value);
|
||||
} else if (!can_cast(get_expression_type(s, node->expr.var_decl.value), t) && !match(t, get_expression_type(s, node->expr.var_decl.value))) {
|
||||
error(node, "type mismatch (decl).");
|
||||
}
|
||||
|
|
@ -758,15 +828,18 @@ static void check_function(sema *s, ast_node *f)
|
|||
param_node->expr_type = p_type;
|
||||
param_node->address_taken = false;
|
||||
param_node->expr.var_decl.name = t_name;
|
||||
|
||||
|
||||
shput(current_scope->defs, t_name, param_node);
|
||||
param = param->next;
|
||||
}
|
||||
|
||||
ast_node *current = f->expr.function.body;
|
||||
while (current && current->type == NODE_UNIT) {
|
||||
check_statement(s, current->expr.unit_node.expr);
|
||||
current = current->expr.unit_node.next;
|
||||
// Skip body checking for extern functions
|
||||
if (!f->expr.function.is_extern && f->expr.function.body) {
|
||||
ast_node *current = f->expr.function.body;
|
||||
while (current && current->type == NODE_UNIT) {
|
||||
check_statement(s, current->expr.unit_node.expr);
|
||||
current = current->expr.unit_node.next;
|
||||
}
|
||||
}
|
||||
|
||||
pop_scope(s);
|
||||
|
|
@ -820,6 +893,7 @@ void sema_init(parser *p, arena *a)
|
|||
register_type(s, "u16", create_integer(s, "u16", 16, false));
|
||||
register_type(s, "u32", create_integer(s, "u32", 32, false));
|
||||
register_type(s, "u64", create_integer(s, "u64", 64, false));
|
||||
register_type(s, "usize", create_integer(s, "usize", 64, false));
|
||||
register_type(s, "i8", create_integer(s, "i8", 8, true));
|
||||
register_type(s, "i16", create_integer(s, "i16", 16, true));
|
||||
register_type(s, "i32", create_integer(s, "i32", 32, true));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue