diff options
| author | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-23 12:22:57 +0000 |
|---|---|---|
| committer | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-23 12:22:57 +0000 |
| commit | f73df8d5de30a7f3f320fccf5f57c13094940a6a (patch) | |
| tree | 877fda85fa3c4a906d6943ac7b7836886bc4140a /src | |
| parent | 98623f2fdd63232edf0ebab1b9680cf4e33e6f10 (diff) | |
Variadic functions + more docs
Diffstat (limited to 'src')
| -rw-r--r-- | src/ast/ast.h | 29 | ||||
| -rw-r--r-- | src/codegen/codegen.c | 28 | ||||
| -rw-r--r-- | src/parser/parser_expr.c | 86 | ||||
| -rw-r--r-- | src/parser/parser_utils.c | 7 |
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) |
