summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-22 16:30:59 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-22 16:30:59 +0000
commit3d1840e8690bef6e58a208d9ca33857a59a2e852 (patch)
tree3ffd423023e6347bd5217fe3285c81bbe110626f /src
parent5838f112be660a8fdfef731c74353fae82dd2c03 (diff)
Starting refactor
Diffstat (limited to 'src')
-rw-r--r--src/codegen/codegen.c189
-rw-r--r--src/parser/parser_expr.c342
2 files changed, 301 insertions, 230 deletions
diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c
index fa65aef..a43c902 100644
--- a/src/codegen/codegen.c
+++ b/src/codegen/codegen.c
@@ -538,6 +538,106 @@ static void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out,
}
}
+// Emit literal expression (int, float, string, char)
+static void codegen_literal_expr(ASTNode *node, FILE *out)
+{
+ if (node->literal.type_kind == TOK_STRING)
+ {
+ fprintf(out, "\"%s\"", node->literal.string_val);
+ }
+ else if (node->literal.type_kind == TOK_CHAR)
+ {
+ fprintf(out, "%s", node->literal.string_val);
+ }
+ else if (node->literal.type_kind == 1) // float
+ {
+ fprintf(out, "%f", node->literal.float_val);
+ }
+ else // int
+ {
+ if (node->literal.int_val > 9223372036854775807ULL)
+ {
+ fprintf(out, "%lluULL", (unsigned long long)node->literal.int_val);
+ }
+ else
+ {
+ fprintf(out, "%llu", (unsigned long long)node->literal.int_val);
+ }
+ }
+}
+
+// Emit variable reference expression
+static void codegen_var_expr(ParserContext *ctx, ASTNode *node, FILE *out)
+{
+ (void)ctx; // May be used for context lookup in future
+
+ if (g_current_lambda)
+ {
+ for (int i = 0; i < g_current_lambda->lambda.num_captures; i++)
+ {
+ if (strcmp(node->var_ref.name, g_current_lambda->lambda.captured_vars[i]) == 0)
+ {
+ fprintf(out, "ctx->%s", node->var_ref.name);
+ return;
+ }
+ }
+ }
+
+ if (node->resolved_type && strcmp(node->resolved_type, "unknown") == 0)
+ {
+ if (node->var_ref.suggestion)
+ {
+ char msg[256];
+ sprintf(msg, "Undefined variable '%s'", node->var_ref.name);
+ char help[256];
+ sprintf(help, "Did you mean '%s'?", node->var_ref.suggestion);
+ zwarn_at(node->token, "%s\n = help: %s", msg, help);
+ }
+ }
+ fprintf(out, "%s", node->var_ref.name);
+}
+
+// Emit lambda expression
+static void codegen_lambda_expr(ASTNode *node, FILE *out)
+{
+ if (node->lambda.num_captures > 0)
+ {
+ fprintf(out,
+ "({ struct Lambda_%d_Ctx *ctx = malloc(sizeof(struct "
+ "Lambda_%d_Ctx));\n",
+ node->lambda.lambda_id, node->lambda.lambda_id);
+ for (int i = 0; i < node->lambda.num_captures; i++)
+ {
+ fprintf(out, "ctx->%s = ", node->lambda.captured_vars[i]);
+ int found = 0;
+ if (g_current_lambda)
+ {
+ for (int k = 0; k < g_current_lambda->lambda.num_captures; k++)
+ {
+ if (strcmp(node->lambda.captured_vars[i],
+ g_current_lambda->lambda.captured_vars[k]) == 0)
+ {
+ fprintf(out, "ctx->%s", node->lambda.captured_vars[i]);
+ found = 1;
+ break;
+ }
+ }
+ }
+ if (!found)
+ {
+ fprintf(out, "%s", node->lambda.captured_vars[i]);
+ }
+ fprintf(out, ";\n");
+ }
+ fprintf(out, "(z_closure_T){.func = _lambda_%d, .ctx = ctx}; })", node->lambda.lambda_id);
+ }
+ else
+ {
+ fprintf(out, "((z_closure_T){.func = (void*)_lambda_%d, .ctx = NULL})",
+ node->lambda.lambda_id);
+ }
+}
+
void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
{
if (!node)
@@ -733,96 +833,13 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
}
break;
case NODE_EXPR_VAR:
- if (g_current_lambda)
- {
- for (int i = 0; i < g_current_lambda->lambda.num_captures; i++)
- {
- if (strcmp(node->var_ref.name, g_current_lambda->lambda.captured_vars[i]) == 0)
- {
- fprintf(out, "ctx->%s", node->var_ref.name);
- return;
- }
- }
- }
-
- if (node->resolved_type && strcmp(node->resolved_type, "unknown") == 0)
- {
- if (node->var_ref.suggestion)
- {
- char msg[256];
- sprintf(msg, "Undefined variable '%s'", node->var_ref.name);
- char help[256];
- sprintf(help, "Did you mean '%s'?", node->var_ref.suggestion);
-
- zwarn_at(node->token, "%s\n = help: %s", msg, help);
- }
- }
- fprintf(out, "%s", node->var_ref.name);
+ codegen_var_expr(ctx, node, out);
break;
case NODE_LAMBDA:
- if (node->lambda.num_captures > 0)
- {
- fprintf(out,
- "({ struct Lambda_%d_Ctx *ctx = malloc(sizeof(struct "
- "Lambda_%d_Ctx));\n",
- node->lambda.lambda_id, node->lambda.lambda_id);
- for (int i = 0; i < node->lambda.num_captures; i++)
- {
- fprintf(out, "ctx->%s = ", node->lambda.captured_vars[i]);
- int found = 0;
- if (g_current_lambda)
- {
- for (int k = 0; k < g_current_lambda->lambda.num_captures; k++)
- {
- if (strcmp(node->lambda.captured_vars[i],
- g_current_lambda->lambda.captured_vars[k]) == 0)
- {
- fprintf(out, "ctx->%s", node->lambda.captured_vars[i]);
- found = 1;
- break;
- }
- }
- }
- if (!found)
- {
- fprintf(out, "%s", node->lambda.captured_vars[i]);
- }
- fprintf(out, ";\n");
- }
- fprintf(out, "(z_closure_T){.func = _lambda_%d, .ctx = ctx}; })",
- node->lambda.lambda_id);
- }
- else
- {
- fprintf(out, "((z_closure_T){.func = (void*)_lambda_%d, .ctx = NULL})",
- node->lambda.lambda_id);
- }
+ codegen_lambda_expr(node, out);
break;
case NODE_EXPR_LITERAL:
- if (node->literal.type_kind == TOK_STRING)
- {
- fprintf(out, "\"%s\"", node->literal.string_val);
- }
- else if (node->literal.type_kind == TOK_CHAR)
- {
- fprintf(out, "%s", node->literal.string_val);
- }
- else if (node->literal.type_kind == 1)
- {
- fprintf(out, "%f", node->literal.float_val);
- }
-
- else
- {
- if (node->literal.int_val > 9223372036854775807ULL)
- {
- fprintf(out, "%lluULL", (unsigned long long)node->literal.int_val);
- }
- else
- {
- fprintf(out, "%llu", (unsigned long long)node->literal.int_val);
- }
- }
+ codegen_literal_expr(node, out);
break;
case NODE_EXPR_CALL:
{
diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c
index 9888701..7993423 100644
--- a/src/parser/parser_expr.c
+++ b/src/parser/parser_expr.c
@@ -984,6 +984,196 @@ static ASTNode *create_fstring_block(ParserContext *ctx, const char *content)
return block;
}
+// Parse integer literal (decimal, hex, binary)
+static ASTNode *parse_int_literal(Token t)
+{
+ ASTNode *node = ast_create(NODE_EXPR_LITERAL);
+ node->literal.type_kind = 0;
+ node->type_info = type_new(TYPE_INT);
+ char *s = token_strdup(t);
+ unsigned long long val;
+ if (t.len > 2 && s[0] == '0' && s[1] == 'b')
+ {
+ val = strtoull(s + 2, NULL, 2);
+ }
+ else
+ {
+ val = strtoull(s, NULL, 0);
+ }
+ node->literal.int_val = val;
+ free(s);
+ return node;
+}
+
+// Parse float literal
+static ASTNode *parse_float_literal(Token t)
+{
+ ASTNode *node = ast_create(NODE_EXPR_LITERAL);
+ node->literal.type_kind = 1;
+ node->literal.float_val = atof(t.start);
+ node->type_info = type_new(TYPE_F64);
+ return node;
+}
+
+// Parse string literal
+static ASTNode *parse_string_literal(Token t)
+{
+ ASTNode *node = ast_create(NODE_EXPR_LITERAL);
+ node->literal.type_kind = TOK_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;
+ node->type_info = type_new(TYPE_STRING);
+ return node;
+}
+
+// Parse f-string literal
+static ASTNode *parse_fstring_literal(ParserContext *ctx, Token t)
+{
+ char *inner = xmalloc(t.len);
+ strncpy(inner, t.start + 2, t.len - 3);
+ inner[t.len - 3] = 0;
+ ASTNode *node = create_fstring_block(ctx, inner);
+ free(inner);
+ return node;
+}
+
+// Parse character literal
+static ASTNode *parse_char_literal(Token t)
+{
+ ASTNode *node = ast_create(NODE_EXPR_LITERAL);
+ node->literal.type_kind = TOK_CHAR;
+ node->literal.string_val = token_strdup(t);
+ node->type_info = type_new(TYPE_I8);
+ return node;
+}
+
+// Parse sizeof expression: sizeof(type) or sizeof(expr)
+static ASTNode *parse_sizeof_expr(ParserContext *ctx, Lexer *l)
+{
+ if (lexer_peek(l).type != TOK_LPAREN)
+ {
+ zpanic_at(lexer_peek(l), "Expected ( after sizeof");
+ }
+ lexer_next(l);
+
+ int pos = l->pos;
+ int col = l->col;
+ int line = l->line;
+ Type *ty = parse_type_formal(ctx, l);
+
+ ASTNode *node;
+ if (ty->kind != TYPE_UNKNOWN && lexer_peek(l).type == TOK_RPAREN)
+ {
+ lexer_next(l);
+ char *ts = type_to_string(ty);
+ node = ast_create(NODE_EXPR_SIZEOF);
+ node->size_of.target_type = ts;
+ node->size_of.expr = NULL;
+ node->type_info = type_new(TYPE_USIZE);
+ }
+ else
+ {
+ l->pos = pos;
+ l->col = col;
+ l->line = line;
+ ASTNode *ex = parse_expression(ctx, l);
+ if (lexer_next(l).type != TOK_RPAREN)
+ {
+ zpanic_at(lexer_peek(l), "Expected ) after sizeof identifier");
+ }
+ node = ast_create(NODE_EXPR_SIZEOF);
+ node->size_of.target_type = NULL;
+ node->size_of.expr = ex;
+ node->type_info = type_new(TYPE_USIZE);
+ }
+ return node;
+}
+
+// Parse typeof expression: typeof(type) or typeof(expr)
+static ASTNode *parse_typeof_expr(ParserContext *ctx, Lexer *l)
+{
+ if (lexer_peek(l).type != TOK_LPAREN)
+ {
+ zpanic_at(lexer_peek(l), "Expected ( after typeof");
+ }
+ lexer_next(l);
+
+ int pos = l->pos;
+ int col = l->col;
+ int line = l->line;
+ Type *ty = parse_type_formal(ctx, l);
+
+ ASTNode *node;
+ if (ty->kind != TYPE_UNKNOWN && lexer_peek(l).type == TOK_RPAREN)
+ {
+ lexer_next(l);
+ char *ts = type_to_string(ty);
+ node = ast_create(NODE_TYPEOF);
+ node->size_of.target_type = ts;
+ node->size_of.expr = NULL;
+ }
+ else
+ {
+ l->pos = pos;
+ l->col = col;
+ l->line = line;
+ ASTNode *ex = parse_expression(ctx, l);
+ if (lexer_next(l).type != TOK_RPAREN)
+ {
+ zpanic_at(lexer_peek(l), "Expected ) after typeof expression");
+ }
+ node = ast_create(NODE_TYPEOF);
+ node->size_of.target_type = NULL;
+ node->size_of.expr = ex;
+ }
+ return node;
+}
+
+// Parse intrinsic expression: @type_name(T), @fields(T)
+static ASTNode *parse_intrinsic(ParserContext *ctx, Lexer *l)
+{
+ Token ident = lexer_next(l);
+ if (ident.type != TOK_IDENT)
+ {
+ zpanic_at(ident, "Expected intrinsic name after @");
+ }
+
+ int kind = -1;
+ if (strncmp(ident.start, "type_name", 9) == 0 && ident.len == 9)
+ {
+ kind = 0;
+ }
+ else if (strncmp(ident.start, "fields", 6) == 0 && ident.len == 6)
+ {
+ kind = 1;
+ }
+ else
+ {
+ zpanic_at(ident, "Unknown intrinsic @%.*s", ident.len, ident.start);
+ }
+
+ Token lparen = lexer_next(l);
+ if (lparen.type != TOK_LPAREN)
+ {
+ zpanic_at(lparen, "Expected ( after intrinsic");
+ }
+
+ Type *target = parse_type_formal(ctx, l);
+
+ Token rparen = lexer_next(l);
+ if (rparen.type != TOK_RPAREN)
+ {
+ zpanic_at(rparen, "Expected ) after intrinsic type");
+ }
+
+ ASTNode *node = ast_create(NODE_REFLECTION);
+ node->reflection.kind = kind;
+ node->reflection.target_type = target;
+ node->type_info = (kind == 0) ? type_new(TYPE_STRING) : type_new_ptr(type_new(TYPE_VOID));
+ return node;
+}
+
ASTNode *parse_primary(ParserContext *ctx, Lexer *l)
{
ASTNode *node = NULL;
@@ -994,174 +1184,38 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l)
// Literals
if (t.type == TOK_INT)
{
- node = ast_create(NODE_EXPR_LITERAL);
- node->literal.type_kind = 0;
- node->type_info = type_new(TYPE_INT);
- char *s = token_strdup(t);
- unsigned long long val;
- if (t.len > 2 && s[0] == '0' && s[1] == 'b')
- {
- val = strtoull(s + 2, NULL, 2);
- }
- else
- {
- val = strtoull(s, NULL, 0);
- }
- node->literal.int_val = (unsigned long long)val;
- free(s);
+ node = parse_int_literal(t);
}
else if (t.type == TOK_FLOAT)
{
- node = ast_create(NODE_EXPR_LITERAL);
- node->literal.type_kind = 1;
- node->literal.float_val = atof(t.start);
- node->type_info = type_new(TYPE_F64);
+ node = parse_float_literal(t);
}
else if (t.type == TOK_STRING)
{
- node = ast_create(NODE_EXPR_LITERAL);
- node->literal.type_kind = TOK_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;
- node->type_info = type_new(TYPE_STRING);
+ node = parse_string_literal(t);
}
else if (t.type == TOK_FSTRING)
{
- char *inner = xmalloc(t.len);
- strncpy(inner, t.start + 2, t.len - 3);
- inner[t.len - 3] = 0;
- node = create_fstring_block(ctx, inner);
- free(inner);
+ node = parse_fstring_literal(ctx, t);
}
else if (t.type == TOK_CHAR)
{
- node = ast_create(NODE_EXPR_LITERAL);
- node->literal.type_kind = TOK_CHAR;
- node->literal.string_val = token_strdup(t);
- node->type_info = type_new(TYPE_I8);
+ node = parse_char_literal(t);
}
else if (t.type == TOK_SIZEOF)
{
- if (lexer_peek(l).type != TOK_LPAREN)
- {
- zpanic_at(lexer_peek(l), "Expected ( after sizeof");
- }
- lexer_next(l);
-
- int pos = l->pos;
- int col = l->col;
- int line = l->line;
- Type *ty = parse_type_formal(ctx, l);
-
- if (ty->kind != TYPE_UNKNOWN && lexer_peek(l).type == TOK_RPAREN)
- {
- lexer_next(l);
- char *ts = type_to_string(ty);
- node = ast_create(NODE_EXPR_SIZEOF);
- node->size_of.target_type = ts;
- node->size_of.expr = NULL;
- node->type_info = type_new(TYPE_USIZE);
- }
- else
- {
- l->pos = pos;
- l->col = col;
- l->line = line;
- ASTNode *ex = parse_expression(ctx, l);
- if (lexer_next(l).type != TOK_RPAREN)
- {
- zpanic_at(lexer_peek(l), "Expected ) after sizeof identifier");
- }
- node = ast_create(NODE_EXPR_SIZEOF);
- node->size_of.target_type = NULL;
- node->size_of.expr = ex;
- node->type_info = type_new(TYPE_USIZE);
- }
+ node = parse_sizeof_expr(ctx, l);
}
else if (t.type == TOK_IDENT && strncmp(t.start, "typeof", 6) == 0 && t.len == 6)
{
- if (lexer_peek(l).type != TOK_LPAREN)
- {
- zpanic_at(lexer_peek(l), "Expected ( after typeof");
- }
- lexer_next(l);
-
- int pos = l->pos;
- int col = l->col;
- int line = l->line;
- Type *ty = parse_type_formal(ctx, l);
-
- if (ty->kind != TYPE_UNKNOWN && lexer_peek(l).type == TOK_RPAREN)
- {
- lexer_next(l);
- char *ts = type_to_string(ty);
- node = ast_create(NODE_TYPEOF);
- node->size_of.target_type = ts;
- node->size_of.expr = NULL;
- }
- else
- {
- l->pos = pos;
- l->col = col;
- l->line = line;
- ASTNode *ex = parse_expression(ctx, l);
- if (lexer_next(l).type != TOK_RPAREN)
- {
- zpanic_at(lexer_peek(l), "Expected ) after typeof expression");
- }
- node = ast_create(NODE_TYPEOF);
- node->size_of.target_type = NULL;
- node->size_of.expr = ex;
- }
+ node = parse_typeof_expr(ctx, l);
}
else if (t.type == TOK_AT)
{
- Token ident = lexer_next(l);
- if (ident.type != TOK_IDENT)
- {
- zpanic_at(ident, "Expected intrinsic name after @");
- }
-
- int kind = -1;
- if (strncmp(ident.start, "type_name", 9) == 0 && ident.len == 9)
- {
- kind = 0;
- }
- else if (strncmp(ident.start, "fields", 6) == 0 && ident.len == 6)
- {
- kind = 1;
- }
- else
- {
- zpanic_at(ident, "Unknown intrinsic @%.*s", ident.len, ident.start);
- }
-
- {
- Token t = lexer_next(l);
- if (t.type != TOK_LPAREN)
- {
- zpanic_at(t, "Expected ( after intrinsic");
- }
- }
-
- Type *target = parse_type_formal(ctx, l);
-
- {
- Token t = lexer_next(l);
- if (t.type != TOK_RPAREN)
- {
- zpanic_at(t, "Expected ) after intrinsic type");
- }
- }
-
- node = ast_create(NODE_REFLECTION);
- node->reflection.kind = kind;
- node->reflection.target_type = target;
- node->type_info = (kind == 0) ? type_new(TYPE_STRING) : type_new_ptr(type_new(TYPE_VOID));
+ node = parse_intrinsic(ctx, l);
}
else if (t.type == TOK_IDENT && strncmp(t.start, "match", 5) == 0 && t.len == 5)