summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.h29
-rw-r--r--src/codegen/codegen.c28
-rw-r--r--src/parser/parser_expr.c86
-rw-r--r--src/parser/parser_utils.c7
4 files changed, 149 insertions, 1 deletions
diff --git a/src/ast/ast.h b/src/ast/ast.h
index 508a247..523c1fb 100644
--- a/src/ast/ast.h
+++ b/src/ast/ast.h
@@ -127,7 +127,11 @@ typedef enum
NODE_REFLECTION,
NODE_AWAIT,
NODE_REPL_PRINT,
- NODE_CUDA_LAUNCH
+ NODE_CUDA_LAUNCH,
+ NODE_VA_START,
+ NODE_VA_END,
+ NODE_VA_COPY,
+ NODE_VA_ARG
} NodeType;
// ** AST Node Structure **
@@ -560,6 +564,29 @@ struct ASTNode
ASTNode *shared_mem; // Optional shared memory size (NULL = default)
ASTNode *stream; // Optional CUDA stream (NULL = default)
} cuda_launch;
+
+ struct
+ {
+ ASTNode *ap;
+ ASTNode *last_arg;
+ } va_start;
+
+ struct
+ {
+ ASTNode *ap;
+ } va_end;
+
+ struct
+ {
+ ASTNode *dest;
+ ASTNode *src;
+ } va_copy;
+
+ struct
+ {
+ ASTNode *ap;
+ Type *type_info;
+ } va_arg;
};
};
diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c
index 3a93f91..22cbc15 100644
--- a/src/codegen/codegen.c
+++ b/src/codegen/codegen.c
@@ -896,6 +896,34 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
fprintf(out, ")");
}
break;
+ case NODE_VA_START:
+ fprintf(out, "va_start(");
+ codegen_expression(ctx, node->va_start.ap, out);
+ fprintf(out, ", ");
+ codegen_expression(ctx, node->va_start.last_arg, out);
+ fprintf(out, ")");
+ break;
+ case NODE_VA_END:
+ fprintf(out, "va_end(");
+ codegen_expression(ctx, node->va_end.ap, out);
+ fprintf(out, ")");
+ break;
+ case NODE_VA_COPY:
+ fprintf(out, "va_copy(");
+ codegen_expression(ctx, node->va_copy.dest, out);
+ fprintf(out, ", ");
+ codegen_expression(ctx, node->va_copy.src, out);
+ fprintf(out, ")");
+ break;
+ case NODE_VA_ARG:
+ {
+ char *type_str = codegen_type_to_string(node->va_arg.type_info);
+ fprintf(out, "va_arg(");
+ codegen_expression(ctx, node->va_arg.ap, out);
+ fprintf(out, ", %s)", type_str);
+ free(type_str);
+ break;
+ }
case NODE_EXPR_CAST:
fprintf(out, "(%s)(", node->cast.target_type);
codegen_expression(ctx, node->cast.expr, out);
diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c
index 4a4f906..be97707 100644
--- a/src/parser/parser_expr.c
+++ b/src/parser/parser_expr.c
@@ -3324,6 +3324,92 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
after_unary:; // Label to skip standard creation if overloaded
}
+ else if (is_token(t, "va_start"))
+ {
+ lexer_next(l);
+ if (lexer_peek(l).type != TOK_LPAREN)
+ {
+ zpanic_at(t, "Expected '(' after va_start");
+ }
+ lexer_next(l);
+ ASTNode *ap = parse_expression(ctx, l);
+ if (lexer_next(l).type != TOK_COMMA)
+ {
+ zpanic_at(t, "Expected ',' in va_start");
+ }
+ ASTNode *last = parse_expression(ctx, l);
+ if (lexer_next(l).type != TOK_RPAREN)
+ {
+ zpanic_at(t, "Expected ')' after va_start args");
+ }
+ lhs = ast_create(NODE_VA_START);
+ lhs->va_start.ap = ap;
+ lhs->va_start.last_arg = last;
+ }
+ else if (is_token(t, "va_end"))
+ {
+ lexer_next(l);
+ if (lexer_peek(l).type != TOK_LPAREN)
+ {
+ zpanic_at(t, "Expected '(' after va_end");
+ }
+ lexer_next(l);
+ ASTNode *ap = parse_expression(ctx, l);
+ if (lexer_next(l).type != TOK_RPAREN)
+ {
+ zpanic_at(t, "Expected ')' after va_end arg");
+ }
+ lhs = ast_create(NODE_VA_END);
+ lhs->va_end.ap = ap;
+ }
+ else if (is_token(t, "va_copy"))
+ {
+ lexer_next(l);
+ if (lexer_peek(l).type != TOK_LPAREN)
+ {
+ zpanic_at(t, "Expected '(' after va_copy");
+ }
+ lexer_next(l);
+ ASTNode *dest = parse_expression(ctx, l);
+ if (lexer_next(l).type != TOK_COMMA)
+ {
+ zpanic_at(t, "Expected ',' in va_copy");
+ }
+ ASTNode *src = parse_expression(ctx, l);
+ if (lexer_next(l).type != TOK_RPAREN)
+ {
+ zpanic_at(t, "Expected ')' after va_copy args");
+ }
+ lhs = ast_create(NODE_VA_COPY);
+ lhs->va_copy.dest = dest;
+ lhs->va_copy.src = src;
+ }
+ else if (is_token(t, "va_arg"))
+ {
+ lexer_next(l);
+ if (lexer_peek(l).type != TOK_LPAREN)
+ {
+ zpanic_at(t, "Expected '(' after va_arg");
+ }
+ lexer_next(l);
+ ASTNode *ap = parse_expression(ctx, l);
+ if (lexer_next(l).type != TOK_COMMA)
+ {
+ zpanic_at(t, "Expected ',' in va_arg");
+ }
+
+ Type *tinfo = parse_type_formal(ctx, l);
+
+ if (lexer_next(l).type != TOK_RPAREN)
+ {
+ zpanic_at(t, "Expected ')' after va_arg args");
+ }
+
+ lhs = ast_create(NODE_VA_ARG);
+ lhs->va_arg.ap = ap;
+ lhs->va_arg.type_info = tinfo;
+ lhs->type_info = tinfo; // The expression evaluates to this type
+ }
else if (is_token(t, "sizeof"))
{
lexer_next(l);
diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c
index d3d9027..918e8e1 100644
--- a/src/parser/parser_utils.c
+++ b/src/parser/parser_utils.c
@@ -496,7 +496,14 @@ void register_builtins(ParserContext *ctx)
add_symbol(ctx, "sprintf", "int", type_new(TYPE_INT));
add_symbol(ctx, "feof", "int", type_new(TYPE_INT));
add_symbol(ctx, "ferror", "int", type_new(TYPE_INT));
+ add_symbol(ctx, "feof", "int", type_new(TYPE_INT));
+ add_symbol(ctx, "ferror", "int", type_new(TYPE_INT));
add_symbol(ctx, "usleep", "int", type_new(TYPE_INT));
+
+ // Register va_list as opaque struct
+ ASTNode *va_def = ast_create(NODE_STRUCT);
+ va_def->strct.name = xstrdup("va_list");
+ register_struct_def(ctx, "va_list", va_def);
}
void add_instantiated_func(ParserContext *ctx, ASTNode *fn)