summaryrefslogtreecommitdiff
path: root/src/parser/parser_expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser/parser_expr.c')
-rw-r--r--src/parser/parser_expr.c245
1 files changed, 226 insertions, 19 deletions
diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c
index 1556ee7..e21c983 100644
--- a/src/parser/parser_expr.c
+++ b/src/parser/parser_expr.c
@@ -203,7 +203,7 @@ static void check_format_string(ASTNode *call, Token t)
return;
}
- if (fmt_arg->type != NODE_EXPR_LITERAL || fmt_arg->literal.type_kind != TOK_STRING)
+ if (fmt_arg->type != NODE_EXPR_LITERAL || fmt_arg->literal.type_kind != 2)
{
return;
}
@@ -991,7 +991,7 @@ static ASTNode *create_fstring_block(ParserContext *ctx, const char *content)
char *fmt_str = xmalloc(strlen(fmt) + 3);
sprintf(fmt_str, "%%%s", fmt);
arg_fmt = ast_create(NODE_EXPR_LITERAL);
- arg_fmt->literal.type_kind = 2;
+ arg_fmt->literal.type_kind = LITERAL_STRING;
arg_fmt->literal.string_val = fmt_str;
arg_fmt->type_info = type_new(TYPE_STRING);
}
@@ -1045,7 +1045,7 @@ static ASTNode *create_fstring_block(ParserContext *ctx, const char *content)
static ASTNode *parse_int_literal(Token t)
{
ASTNode *node = ast_create(NODE_EXPR_LITERAL);
- node->literal.type_kind = 0;
+ node->literal.type_kind = LITERAL_INT;
node->type_info = type_new(TYPE_INT);
char *s = token_strdup(t);
unsigned long long val;
@@ -1066,7 +1066,7 @@ static ASTNode *parse_int_literal(Token t)
static ASTNode *parse_float_literal(Token t)
{
ASTNode *node = ast_create(NODE_EXPR_LITERAL);
- node->literal.type_kind = 1;
+ node->literal.type_kind = LITERAL_FLOAT;
node->literal.float_val = atof(t.start);
node->type_info = type_new(TYPE_F64);
return node;
@@ -1076,7 +1076,7 @@ static ASTNode *parse_float_literal(Token t)
static ASTNode *parse_string_literal(Token t)
{
ASTNode *node = ast_create(NODE_EXPR_LITERAL);
- node->literal.type_kind = TOK_STRING;
+ node->literal.type_kind = LITERAL_STRING;
node->literal.string_val = xmalloc(t.len);
strncpy(node->literal.string_val, t.start + 1, t.len - 2);
node->literal.string_val[t.len - 2] = 0;
@@ -1099,7 +1099,7 @@ static ASTNode *parse_fstring_literal(ParserContext *ctx, Token t)
static ASTNode *parse_char_literal(Token t)
{
ASTNode *node = ast_create(NODE_EXPR_LITERAL);
- node->literal.type_kind = TOK_CHAR;
+ node->literal.type_kind = LITERAL_CHAR;
node->literal.string_val = token_strdup(t);
node->type_info = type_new(TYPE_I8);
return node;
@@ -2046,7 +2046,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l)
node->type_info = type_new(TYPE_INT); // Returns count
ASTNode *fmt_node = ast_create(NODE_EXPR_LITERAL);
- fmt_node->literal.type_kind = 2; // string
+ fmt_node->literal.type_kind = LITERAL_STRING; // string
fmt_node->literal.string_val = xstrdup(fmt);
ASTNode *head = fmt_node, *tail = fmt_node;
@@ -2095,6 +2095,119 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l)
ASTNode *arg = parse_expression(ctx, l);
+ // Implicit trait cast logic
+ if (sig && args_provided < sig->total_args && arg)
+ {
+ Type *expected = sig->arg_types[args_provided];
+
+ if (expected && expected->name && is_trait(expected->name))
+ {
+ // Check if we are passing a struct pointer
+ Type *arg_type =
+ arg->type_info
+ ? arg->type_info
+ : ((arg->type == NODE_EXPR_VAR)
+ ? find_symbol_type_info(ctx, arg->var_ref.name)
+ : NULL);
+
+ if (!arg_type && arg->type == NODE_EXPR_UNARY &&
+ strcmp(arg->unary.op, "&") == 0)
+ {
+ // Handle &struct
+ if (arg->unary.operand->type == NODE_EXPR_VAR)
+ {
+ Type *inner = find_symbol_type_info(
+ ctx, arg->unary.operand->var_ref.name);
+ if (inner && inner->kind == TYPE_STRUCT)
+ {
+ if (check_impl(ctx, expected->name, inner->name))
+ {
+ // FOUND MATCH: &Struct -> Trait
+ // Construct Trait Object: (Trait){.self = arg, .vtable
+ // = &_Struct_Trait_VTable}
+
+ ASTNode *init = ast_create(NODE_EXPR_STRUCT_INIT);
+ init->struct_init.struct_name = xstrdup(expected->name);
+
+ Type *trait_type = type_new(TYPE_STRUCT);
+ trait_type->name = xstrdup(expected->name);
+ init->type_info = trait_type;
+
+ // Field: self
+ ASTNode *f_self = ast_create(NODE_VAR_DECL);
+ f_self->var_decl.name = xstrdup("self");
+ f_self->var_decl.init_expr = arg;
+
+ // Field: vtable
+ char vtable_name[256];
+ sprintf(vtable_name, "%s_%s_VTable", inner->name,
+ expected->name);
+
+ ASTNode *vtable_var = ast_create(NODE_EXPR_VAR);
+ vtable_var->var_ref.name = xstrdup(vtable_name);
+
+ ASTNode *vtable_ref = ast_create(NODE_EXPR_UNARY);
+ vtable_ref->unary.op = xstrdup("&");
+ vtable_ref->unary.operand = vtable_var;
+
+ ASTNode *f_vtable = ast_create(NODE_VAR_DECL);
+ f_vtable->var_decl.name = xstrdup("vtable");
+ f_vtable->var_decl.init_expr = vtable_ref;
+
+ f_self->next = f_vtable;
+ init->struct_init.fields = f_self;
+
+ arg = init;
+ }
+ }
+ }
+ }
+ else if (arg_type && arg_type->kind == TYPE_POINTER &&
+ arg_type->inner && arg_type->inner->kind == TYPE_STRUCT)
+ {
+ // Pointer variable or expression
+ if (check_impl(ctx, expected->name, arg_type->inner->name))
+ {
+ // Construct Trait Object: (Trait){.self = arg, .vtable =
+ // &_Struct_Trait_VTable}
+
+ ASTNode *init = ast_create(NODE_EXPR_STRUCT_INIT);
+ init->struct_init.struct_name = xstrdup(expected->name);
+
+ Type *trait_type = type_new(TYPE_STRUCT);
+ trait_type->name = xstrdup(expected->name);
+ init->type_info = trait_type;
+
+ // Field: self
+ ASTNode *f_self = ast_create(NODE_VAR_DECL);
+ f_self->var_decl.name = xstrdup("self");
+ f_self->var_decl.init_expr = arg;
+
+ // Field: vtable
+ char vtable_name[256];
+ sprintf(vtable_name, "%s_%s_VTable", arg_type->inner->name,
+ expected->name);
+
+ ASTNode *vtable_var = ast_create(NODE_EXPR_VAR);
+ vtable_var->var_ref.name = xstrdup(vtable_name);
+
+ ASTNode *vtable_ref = ast_create(NODE_EXPR_UNARY);
+ vtable_ref->unary.op = xstrdup("&");
+ vtable_ref->unary.operand = vtable_var;
+
+ ASTNode *f_vtable = ast_create(NODE_VAR_DECL);
+ f_vtable->var_decl.name = xstrdup("vtable");
+ f_vtable->var_decl.init_expr = vtable_ref;
+
+ f_self->next = f_vtable;
+ init->struct_init.fields = f_self;
+
+ arg = init;
+ }
+ }
+ }
+ }
+
// Move Semantics Logic (Added for known funcs)
check_move_usage(ctx, arg, arg ? arg->token : t1);
if (arg && arg->type == NODE_EXPR_VAR)
@@ -2159,6 +2272,100 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l)
lexer_init(&def_l, sig->defaults[i]);
ASTNode *def = parse_expression(ctx, &def_l);
+ // Implicit trait cast logic for default values
+ Type *expected = sig->arg_types[i];
+ if (expected && expected->name && is_trait(expected->name))
+ {
+ Type *arg_type = def->type_info
+ ? def->type_info
+ : ((def->type == NODE_EXPR_VAR)
+ ? find_symbol_type_info(ctx, def->var_ref.name)
+ : NULL);
+
+ if (!arg_type && def->type == NODE_EXPR_UNARY &&
+ strcmp(def->unary.op, "&") == 0)
+ {
+ if (def->unary.operand->type == NODE_EXPR_VAR)
+ {
+ Type *inner =
+ find_symbol_type_info(ctx, def->unary.operand->var_ref.name);
+ if (inner && inner->kind == TYPE_STRUCT)
+ {
+ if (check_impl(ctx, expected->name, inner->name))
+ {
+ ASTNode *init = ast_create(NODE_EXPR_STRUCT_INIT);
+ init->struct_init.struct_name = xstrdup(expected->name);
+
+ Type *trait_type = type_new(TYPE_STRUCT);
+ trait_type->name = xstrdup(expected->name);
+ init->type_info = trait_type;
+
+ ASTNode *f_self = ast_create(NODE_VAR_DECL);
+ f_self->var_decl.name = xstrdup("self");
+ f_self->var_decl.init_expr = def;
+
+ char vtable_name[256];
+ sprintf(vtable_name, "%s_%s_VTable", inner->name,
+ expected->name);
+
+ ASTNode *vtable_var = ast_create(NODE_EXPR_VAR);
+ vtable_var->var_ref.name = xstrdup(vtable_name);
+
+ ASTNode *vtable_ref = ast_create(NODE_EXPR_UNARY);
+ vtable_ref->unary.op = xstrdup("&");
+ vtable_ref->unary.operand = vtable_var;
+
+ ASTNode *f_vtable = ast_create(NODE_VAR_DECL);
+ f_vtable->var_decl.name = xstrdup("vtable");
+ f_vtable->var_decl.init_expr = vtable_ref;
+
+ f_self->next = f_vtable;
+ init->struct_init.fields = f_self;
+
+ def = init;
+ }
+ }
+ }
+ }
+ else if (arg_type && arg_type->kind == TYPE_POINTER && arg_type->inner &&
+ arg_type->inner->kind == TYPE_STRUCT)
+ {
+ if (check_impl(ctx, expected->name, arg_type->inner->name))
+ {
+ ASTNode *init = ast_create(NODE_EXPR_STRUCT_INIT);
+ init->struct_init.struct_name = xstrdup(expected->name);
+
+ Type *trait_type = type_new(TYPE_STRUCT);
+ trait_type->name = xstrdup(expected->name);
+ init->type_info = trait_type;
+
+ ASTNode *f_self = ast_create(NODE_VAR_DECL);
+ f_self->var_decl.name = xstrdup("self");
+ f_self->var_decl.init_expr = def;
+
+ char vtable_name[256];
+ sprintf(vtable_name, "%s_%s_VTable", arg_type->inner->name,
+ expected->name);
+
+ ASTNode *vtable_var = ast_create(NODE_EXPR_VAR);
+ vtable_var->var_ref.name = xstrdup(vtable_name);
+
+ ASTNode *vtable_ref = ast_create(NODE_EXPR_UNARY);
+ vtable_ref->unary.op = xstrdup("&");
+ vtable_ref->unary.operand = vtable_var;
+
+ ASTNode *f_vtable = ast_create(NODE_VAR_DECL);
+ f_vtable->var_decl.name = xstrdup("vtable");
+ f_vtable->var_decl.init_expr = vtable_ref;
+
+ f_self->next = f_vtable;
+ init->struct_init.fields = f_self;
+
+ def = init;
+ }
+ }
+ }
+
if (!head)
{
head = def;
@@ -2333,7 +2540,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l)
// Constant Folding for 'def', emits literal
node = ast_create(NODE_EXPR_LITERAL);
node->token = t;
- node->literal.type_kind = 0; // INT (assumed for now from const_int_val)
+ node->literal.type_kind = LITERAL_INT; // INT (assumed for now from const_int_val)
node->literal.int_val = sym->const_int_val;
node->type_info = type_new(TYPE_INT);
// No need for resolution
@@ -2533,15 +2740,15 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l)
if (elements[i]->type == NODE_EXPR_LITERAL)
{
char buf[256];
- if (elements[i]->literal.type_kind == 0) // int
+ if (elements[i]->literal.type_kind == LITERAL_INT) // int
{
sprintf(buf, "%lld", elements[i]->literal.int_val);
}
- else if (elements[i]->literal.type_kind == 1) // float
+ else if (elements[i]->literal.type_kind == LITERAL_FLOAT) // float
{
sprintf(buf, "%f", elements[i]->literal.float_val);
}
- else if (elements[i]->literal.type_kind == 2) // string
+ else if (elements[i]->literal.type_kind == LITERAL_STRING) // string
{
sprintf(buf, "\"%s\"", elements[i]->literal.string_val);
}
@@ -2762,7 +2969,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l)
if (node->type_info && node->type_info->kind == TYPE_ARRAY &&
node->type_info->array_size > 0)
{
- if (index->type == NODE_EXPR_LITERAL && index->literal.type_kind == 0)
+ if (index->type == NODE_EXPR_LITERAL && index->literal.type_kind == LITERAL_INT)
{
int idx = index->literal.int_val;
if (idx < 0 || idx >= node->type_info->array_size)
@@ -3291,7 +3498,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
call->type_info = type_new(TYPE_INT);
ASTNode *fmt_node = ast_create(NODE_EXPR_LITERAL);
- fmt_node->literal.type_kind = TOK_STRING;
+ fmt_node->literal.type_kind = LITERAL_STRING;
fmt_node->literal.string_val = xstrdup(fmt);
ASTNode *head = fmt_node, *tail = fmt_node;
@@ -4234,7 +4441,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
if (lhs->type_info && lhs->type_info->kind == TYPE_ARRAY &&
lhs->type_info->array_size > 0)
{
- if (start->type == NODE_EXPR_LITERAL && start->literal.type_kind == 0)
+ if (start->type == NODE_EXPR_LITERAL && start->literal.type_kind == LITERAL_INT)
{
int idx = start->literal.int_val;
if (idx < 0 || idx >= lhs->type_info->array_size)
@@ -4357,7 +4564,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
if (find_func(ctx, trait_mangled))
{
strcpy(mangled, trait_mangled); // Update mangled name
- sig = find_func(ctx, mangled);
+ sig = find_func(ctx, trait_mangled);
break;
}
}
@@ -4612,7 +4819,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
if (strcmp(bin->binary.op, "/") == 0 || strcmp(bin->binary.op, "%") == 0)
{
- if (rhs->type == NODE_EXPR_LITERAL && rhs->literal.type_kind == 0 &&
+ if (rhs->type == NODE_EXPR_LITERAL && rhs->literal.type_kind == LITERAL_INT &&
rhs->literal.int_val == 0)
{
warn_division_by_zero(op);
@@ -4638,8 +4845,8 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
}
}
}
- else if (lhs->type == NODE_EXPR_LITERAL && lhs->literal.type_kind == 0 &&
- rhs->type == NODE_EXPR_LITERAL && rhs->literal.type_kind == 0)
+ else if (lhs->type == NODE_EXPR_LITERAL && lhs->literal.type_kind == LITERAL_INT &&
+ rhs->type == NODE_EXPR_LITERAL && rhs->literal.type_kind == LITERAL_INT)
{
// Check if literals make sense (e.g. 5 > 5)
if (lhs->literal.int_val == rhs->literal.int_val)
@@ -4658,7 +4865,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
if (lhs->type_info && type_is_unsigned(lhs->type_info))
{
- if (rhs->type == NODE_EXPR_LITERAL && rhs->literal.type_kind == 0 &&
+ if (rhs->type == NODE_EXPR_LITERAL && rhs->literal.type_kind == LITERAL_INT &&
rhs->literal.int_val == 0)
{
if (strcmp(bin->binary.op, ">=") == 0)