Implemented C variadic arguments

This commit is contained in:
Krzosa Karol
2023-04-14 22:22:34 +02:00
parent fdcdc8ea86
commit 8c4975db35
9 changed files with 74 additions and 15 deletions

View File

@@ -68,6 +68,8 @@ main :: (): int
guys: Array(Guy)
Add(&guys, {pos = {100, 100}})
Memes(32, 32, 32, 32.42, "ASD")
InitWindow(1280, 720, "Testing")
SetTargetFPS(60)
for !WindowShouldClose()

View File

@@ -339,6 +339,10 @@ gen_lambda(Intern_String name, Ast_Lambda *lambda, B32 generate_block = true) {
gen("(");
if (lambda->args.len == 0) gen("void");
For(lambda->args) {
if (it->name == pctx->intern("..."_s)) {
gen("...");
continue;
}
gen_var(it, DONT_EMIT_VALUE, true);
if (&it != (lambda->args.end() - 1))
gen(", ");
@@ -935,6 +939,7 @@ compile_to_c_code() {
global_indent++;
For2(pctx->all_types, t) {
if (t->kind == TYPE_POLYMORPH) continue;
// if (t->kind == TYPE_VARGS) continue;
genln("{/*%Q*/", typestring(t));
global_indent += 1;

View File

@@ -156,6 +156,9 @@ for i in meta.token_simple_expr:
pctx->untyped_int = &pctx->type__untyped_int;
pctx->untyped_float = &pctx->type__untyped_float;
pctx->type__vargs = {TYPE_VARGS};
pctx->type_vargs = &pctx->type__vargs;
pctx->type_pointer_to_char = type_pointer(pctx->type_char);
pctx->type_pointer_to_void = type_pointer(pctx->type_void);

View File

@@ -185,6 +185,9 @@ print(f"Ast_Operator_Info op_info_table[{size}];")
Ast_Type *untyped_int = &type__untyped_int;
Ast_Type *untyped_float = &type__untyped_float;
Ast_Type type__vargs;
Ast_Type *type_vargs = &type__vargs;
Intern_String intern(String string) {
assert(string.len > 0);
return intern_string(&interns, string);

View File

@@ -212,6 +212,7 @@ enum Ast_Type_Kind {
TYPE_COMPLETING,
TYPE_INCOMPLETE,
TYPE_POLYMORPH,
TYPE_VARGS,
TYPE_UNTYPED_BOOL, // FIRST_TYPED_NUMERIC, FIRST_NUMERIC
TYPE_UNTYPED_INT,
@@ -321,6 +322,7 @@ enum Ast_Kind : uint32_t {
AST_LENGTH_OF,
AST_ALIGN_OF,
AST_TYPE_OF,
AST_VARGS_LAMBDA_PARAM,
AST_SWITCH,
AST_SWITCH_CASE,

View File

@@ -431,7 +431,7 @@ lex__stream(Core_Ctx *lexer) {
case '.': {
if (lexc(s) == '.') {
lex_advance(s);
if (lexci(s, 1) == '.') {
if (lexc(s) == '.') {
lex_advance(s);
t.kind = TK_ThreeDots;
}

View File

@@ -468,9 +468,14 @@ parse_parameter_list(Arena *arena) {
Array<Ast_Decl *> params = {arena};
if (!token_is(TK_CloseParen)) {
for (;;) {
Token *name = token_get();
if (name->kind == TK_Identifier || name->kind == TK_Polymorph) {
token_next();
Token *name = token_next();
if (name->kind == TK_ThreeDots) {
Ast_Decl *param = ast_new(Ast_Decl, AST_VARGS_LAMBDA_PARAM, name, AST_DECL);
param->name = pctx->intern("..."_s);
params.add(param);
break;
}
else if (name->kind == TK_Identifier || name->kind == TK_Polymorph) {
token_expect(TK_Colon);
Ast_Decl *param = ast_new(Ast_Decl, AST_VAR, name, AST_DECL);

View File

@@ -401,7 +401,7 @@ make_sure_value_is_compatible_with_type(Token *pos, Operand *expr, Ast_Type *typ
return;
}
if (!type) {
if (!type || type->kind == TYPE_VARGS) {
assert(is_flag_set(debug_flag, TYPE_CAN_BE_NULL));
assert(expr->type);
try_converting_untyped_to_default_type(expr);
@@ -914,12 +914,21 @@ resolve_lambda_type(Ast_Lambda *lambda) {
}
For(lambda->args) {
if (it->name == pctx->intern("..."_s)) {
it->type = pctx->type_vargs;
For2(lambda->args, arg) {
if (arg->expr != 0) compiler_error(arg->pos, "Default values in variadic functions are not allowed");
}
}
else {
Ast_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL);
Operand default_value = resolve_expr(it->expr, AST_CAN_BE_NULL, type, 0);
make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL);
it->type = type;
try_propagating_resolved_type_to_untyped_literals(it->expr, it->type);
}
args.add(it->type);
}
@@ -1639,6 +1648,12 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
Need to be careful!!!
*/
For(node->exprs) {
if (is_flag_set(it->call_flags, CALL_INDEX)) {
compiler_error(it->pos, "Index inside a call is not allowed!");
}
}
Scoped_Arena scratch(pctx->scratch);
Ast_Lambda *lambda = name.resolved_decl->lambda;
struct Match {
@@ -1661,6 +1676,21 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
For2(lambda->args, lambda_arg) {
// assert(lambda_arg->type); // @todo: maybe add this check at the end
// @todo: Change inside resolve lambda, no default arguments allowed!!!!!!
if (lambda_arg->kind == AST_VARGS_LAMBDA_PARAM) {
For(node->exprs) {
if (is_flag_set(it->call_flags, CALL_NAME)) {
compiler_error(it->pos, "Variadic function doesnt allow for named arguments!");
}
S64 idx = node->exprs.get_index(it);
if (idx >= default_iter) {
matches.add({lambda_arg, it});
}
}
break;
}
Ast_Call_Item *item = 0;
For(node->exprs) {
S64 it_index = node->exprs.get_index(it);
@@ -1737,11 +1767,17 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
Ast_Call_Item *item = it.call_arg;
Ast_Decl *lambda_arg = it.lambda_arg;
if (lambda_arg->flags & AST_IDENT_POLYMORPH) continue;
if (lambda_arg->kind == AST_VARGS_LAMBDA_PARAM) {
Operand expr = resolve_expr(item->item, AST_CANT_BE_NULL, lambda_arg->type, field_access_scope);
try_converting_untyped_to_default_type(&expr);
if (expr.type == pctx->type_string) expr.type = pctx->type_pointer_to_char;
item->resolved_type = expr.type;
}
else {
Operand expr = resolve_expr(item->item, AST_CANT_BE_NULL, lambda_arg->type, field_access_scope);
make_sure_value_is_compatible_with_type(item->pos, &expr, lambda_arg->type, TYPE_AND_EXPR_REQUIRED);
item->resolved_type = lambda_arg->type;
}
try_propagating_resolved_type_to_untyped_literals(item->item, item->resolved_type);
items.add(item);
}

View File

@@ -346,6 +346,9 @@ typename_base(String_Builder *sb, Ast_Type *type) {
sb->addf("%Q", name);
break;
}
case TYPE_VARGS: {
sb->addf("...");
} break;
case TYPE_UNTYPED_BOOL: sb->addf("Untyped_Bool"); break;
case TYPE_UNTYPED_INT: sb->addf("Untyped_Int"); break;
case TYPE_UNTYPED_FLOAT: sb->addf("Untyped_Float"); break;