summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen/codegen.c20
-rw-r--r--src/parser/parser_expr.c125
2 files changed, 137 insertions, 8 deletions
diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c
index 22cbc15..95e0ccd 100644
--- a/src/codegen/codegen.c
+++ b/src/codegen/codegen.c
@@ -603,7 +603,15 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
emit_auto_type(ctx, node->member.target, node->token, out);
fprintf(out, " _t = (");
codegen_expression(ctx, node->member.target, out);
- fprintf(out, "); _t ? _t->%s : 0; })", node->member.field);
+ char *field = node->member.field;
+ if (field && field[0] >= '0' && field[0] <= '9')
+ {
+ fprintf(out, "); _t ? _t->v%s : 0; })", field);
+ }
+ else
+ {
+ fprintf(out, "); _t ? _t->%s : 0; })", field);
+ }
}
else
{
@@ -619,7 +627,15 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
{
free(lt);
}
- fprintf(out, "%s%s", actually_ptr ? "->" : ".", node->member.field);
+ char *field = node->member.field;
+ if (field && field[0] >= '0' && field[0] <= '9')
+ {
+ fprintf(out, "%sv%s", actually_ptr ? "->" : ".", field);
+ }
+ else
+ {
+ fprintf(out, "%s%s", actually_ptr ? "->" : ".", field);
+ }
}
break;
case NODE_EXPR_INDEX:
diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c
index bfbdb28..990942d 100644
--- a/src/parser/parser_expr.c
+++ b/src/parser/parser_expr.c
@@ -20,6 +20,7 @@ int is_struct_type(ParserContext *ctx, const char *type_name)
}
Type *get_field_type(ParserContext *ctx, Type *struct_type, const char *field_name);
+char *infer_type(ParserContext *ctx, ASTNode *node); // from codegen
int is_type_copy(ParserContext *ctx, Type *t)
{
@@ -2387,11 +2388,123 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l)
l->pos = saved; // Reset if not a cast
ASTNode *expr = parse_expression(ctx, l);
- if (lexer_next(l).type != TOK_RPAREN)
+
+ // Check for tuple literal: (expr, expr, ...)
+ if (lexer_peek(l).type == TOK_COMMA)
+ {
+ // This is a tuple literal - collect all elements and infer types
+ ASTNode **elements = xmalloc(sizeof(ASTNode *) * 16);
+ char **type_strs = xmalloc(sizeof(char *) * 16);
+ int count = 0;
+
+ // First element
+ elements[count] = expr;
+ char *t1 = infer_type(ctx, expr);
+ type_strs[count] = t1 ? t1 : xstrdup("int");
+ count++;
+
+ // Parse remaining elements
+ while (lexer_peek(l).type == TOK_COMMA)
+ {
+ lexer_next(l); // eat comma
+ ASTNode *elem = parse_expression(ctx, l);
+ elements[count] = elem;
+ char *ti = infer_type(ctx, elem);
+ type_strs[count] = ti ? ti : xstrdup("int");
+ count++;
+ }
+
+ if (lexer_next(l).type != TOK_RPAREN)
+ {
+ zpanic_at(lexer_peek(l), "Expected ) after tuple");
+ }
+
+ // Build tuple signature
+ char sig[512];
+ sig[0] = 0;
+ for (int i = 0; i < count; i++)
+ {
+ if (i > 0)
+ {
+ strcat(sig, "_");
+ }
+ strcat(sig, type_strs[i]);
+ }
+
+ register_tuple(ctx, sig);
+
+ char tuple_name[256];
+ sprintf(tuple_name, "Tuple_%s", sig);
+
+ char *code = xmalloc(4096);
+ sprintf(code, "(%s){", tuple_name);
+
+ for (int i = 0; i < count; i++)
+ {
+ if (i > 0)
+ {
+ strcat(code, ", ");
+ }
+
+ if (elements[i]->type == NODE_EXPR_LITERAL)
+ {
+ char buf[256];
+ if (elements[i]->literal.type_kind == 0) // int
+ {
+ sprintf(buf, "%lld", elements[i]->literal.int_val);
+ }
+ else if (elements[i]->literal.type_kind == 1) // float
+ {
+ sprintf(buf, "%f", elements[i]->literal.float_val);
+ }
+ else if (elements[i]->literal.type_kind == 2) // string
+ {
+ sprintf(buf, "\"%s\"", elements[i]->literal.string_val);
+ }
+ else
+ {
+ sprintf(buf, "0");
+ }
+ strcat(code, buf);
+ }
+ else if (elements[i]->type == NODE_EXPR_VAR)
+ {
+ strcat(code, elements[i]->var_ref.name);
+ }
+ else
+ {
+ // For complex expressions, we need a different approach
+ // For now, just put a placeholder - this won't work for all cases
+ // So it's a TODO...
+ strcat(code, "/* complex expr */0");
+ }
+ }
+ strcat(code, "}");
+
+ node = ast_create(NODE_RAW_STMT);
+ node->raw_stmt.content = code;
+
+ // Set type info
+ Type *tuple_type = type_new(TYPE_STRUCT);
+ tuple_type->name = xstrdup(tuple_name);
+ node->type_info = tuple_type;
+
+ // Cleanup
+ free(elements);
+ for (int i = 0; i < count; i++)
+ {
+ free(type_strs[i]);
+ }
+ free(type_strs);
+ }
+ else
{
- zpanic_at(lexer_peek(l), "Expected )");
+ if (lexer_next(l).type != TOK_RPAREN)
+ {
+ zpanic_at(lexer_peek(l), "Expected )");
+ }
+ node = expr;
}
- node = expr;
}
else if (t.type == TOK_LBRACKET)
@@ -3488,7 +3601,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
{
lexer_next(l);
Token field = lexer_next(l);
- if (field.type != TOK_IDENT)
+ if (field.type != TOK_IDENT && field.type != TOK_INT)
{
zpanic_at(field, "Expected field name after ->");
break;
@@ -3517,7 +3630,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
{
lexer_next(l);
Token field = lexer_next(l);
- if (field.type != TOK_IDENT)
+ if (field.type != TOK_IDENT && field.type != TOK_INT)
{
zpanic_at(field, "Expected field name after ?.");
break;
@@ -4080,7 +4193,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
if (op.type == TOK_OP && is_token(op, "."))
{
Token field = lexer_next(l);
- if (field.type != TOK_IDENT)
+ if (field.type != TOK_IDENT && field.type != TOK_INT)
{
zpanic_at(field, "Expected field name after .");
break;