Implemented C variadic arguments
This commit is contained in:
@@ -68,6 +68,8 @@ main :: (): int
|
|||||||
guys: Array(Guy)
|
guys: Array(Guy)
|
||||||
Add(&guys, {pos = {100, 100}})
|
Add(&guys, {pos = {100, 100}})
|
||||||
|
|
||||||
|
Memes(32, 32, 32, 32.42, "ASD")
|
||||||
|
|
||||||
InitWindow(1280, 720, "Testing")
|
InitWindow(1280, 720, "Testing")
|
||||||
SetTargetFPS(60)
|
SetTargetFPS(60)
|
||||||
for !WindowShouldClose()
|
for !WindowShouldClose()
|
||||||
|
|||||||
@@ -339,6 +339,10 @@ gen_lambda(Intern_String name, Ast_Lambda *lambda, B32 generate_block = true) {
|
|||||||
gen("(");
|
gen("(");
|
||||||
if (lambda->args.len == 0) gen("void");
|
if (lambda->args.len == 0) gen("void");
|
||||||
For(lambda->args) {
|
For(lambda->args) {
|
||||||
|
if (it->name == pctx->intern("..."_s)) {
|
||||||
|
gen("...");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
gen_var(it, DONT_EMIT_VALUE, true);
|
gen_var(it, DONT_EMIT_VALUE, true);
|
||||||
if (&it != (lambda->args.end() - 1))
|
if (&it != (lambda->args.end() - 1))
|
||||||
gen(", ");
|
gen(", ");
|
||||||
@@ -935,6 +939,7 @@ compile_to_c_code() {
|
|||||||
global_indent++;
|
global_indent++;
|
||||||
For2(pctx->all_types, t) {
|
For2(pctx->all_types, t) {
|
||||||
if (t->kind == TYPE_POLYMORPH) continue;
|
if (t->kind == TYPE_POLYMORPH) continue;
|
||||||
|
// if (t->kind == TYPE_VARGS) continue;
|
||||||
|
|
||||||
genln("{/*%Q*/", typestring(t));
|
genln("{/*%Q*/", typestring(t));
|
||||||
global_indent += 1;
|
global_indent += 1;
|
||||||
|
|||||||
@@ -156,6 +156,9 @@ for i in meta.token_simple_expr:
|
|||||||
pctx->untyped_int = &pctx->type__untyped_int;
|
pctx->untyped_int = &pctx->type__untyped_int;
|
||||||
pctx->untyped_float = &pctx->type__untyped_float;
|
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_char = type_pointer(pctx->type_char);
|
||||||
pctx->type_pointer_to_void = type_pointer(pctx->type_void);
|
pctx->type_pointer_to_void = type_pointer(pctx->type_void);
|
||||||
|
|
||||||
|
|||||||
@@ -185,6 +185,9 @@ print(f"Ast_Operator_Info op_info_table[{size}];")
|
|||||||
Ast_Type *untyped_int = &type__untyped_int;
|
Ast_Type *untyped_int = &type__untyped_int;
|
||||||
Ast_Type *untyped_float = &type__untyped_float;
|
Ast_Type *untyped_float = &type__untyped_float;
|
||||||
|
|
||||||
|
Ast_Type type__vargs;
|
||||||
|
Ast_Type *type_vargs = &type__vargs;
|
||||||
|
|
||||||
Intern_String intern(String string) {
|
Intern_String intern(String string) {
|
||||||
assert(string.len > 0);
|
assert(string.len > 0);
|
||||||
return intern_string(&interns, string);
|
return intern_string(&interns, string);
|
||||||
|
|||||||
@@ -212,6 +212,7 @@ enum Ast_Type_Kind {
|
|||||||
TYPE_COMPLETING,
|
TYPE_COMPLETING,
|
||||||
TYPE_INCOMPLETE,
|
TYPE_INCOMPLETE,
|
||||||
TYPE_POLYMORPH,
|
TYPE_POLYMORPH,
|
||||||
|
TYPE_VARGS,
|
||||||
|
|
||||||
TYPE_UNTYPED_BOOL, // FIRST_TYPED_NUMERIC, FIRST_NUMERIC
|
TYPE_UNTYPED_BOOL, // FIRST_TYPED_NUMERIC, FIRST_NUMERIC
|
||||||
TYPE_UNTYPED_INT,
|
TYPE_UNTYPED_INT,
|
||||||
@@ -321,6 +322,7 @@ enum Ast_Kind : uint32_t {
|
|||||||
AST_LENGTH_OF,
|
AST_LENGTH_OF,
|
||||||
AST_ALIGN_OF,
|
AST_ALIGN_OF,
|
||||||
AST_TYPE_OF,
|
AST_TYPE_OF,
|
||||||
|
AST_VARGS_LAMBDA_PARAM,
|
||||||
|
|
||||||
AST_SWITCH,
|
AST_SWITCH,
|
||||||
AST_SWITCH_CASE,
|
AST_SWITCH_CASE,
|
||||||
|
|||||||
@@ -431,7 +431,7 @@ lex__stream(Core_Ctx *lexer) {
|
|||||||
case '.': {
|
case '.': {
|
||||||
if (lexc(s) == '.') {
|
if (lexc(s) == '.') {
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
if (lexci(s, 1) == '.') {
|
if (lexc(s) == '.') {
|
||||||
lex_advance(s);
|
lex_advance(s);
|
||||||
t.kind = TK_ThreeDots;
|
t.kind = TK_ThreeDots;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -468,9 +468,14 @@ parse_parameter_list(Arena *arena) {
|
|||||||
Array<Ast_Decl *> params = {arena};
|
Array<Ast_Decl *> params = {arena};
|
||||||
if (!token_is(TK_CloseParen)) {
|
if (!token_is(TK_CloseParen)) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Token *name = token_get();
|
Token *name = token_next();
|
||||||
if (name->kind == TK_Identifier || name->kind == TK_Polymorph) {
|
if (name->kind == TK_ThreeDots) {
|
||||||
token_next();
|
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);
|
token_expect(TK_Colon);
|
||||||
|
|
||||||
Ast_Decl *param = ast_new(Ast_Decl, AST_VAR, name, AST_DECL);
|
Ast_Decl *param = ast_new(Ast_Decl, AST_VAR, name, AST_DECL);
|
||||||
|
|||||||
@@ -401,7 +401,7 @@ make_sure_value_is_compatible_with_type(Token *pos, Operand *expr, Ast_Type *typ
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!type) {
|
if (!type || type->kind == TYPE_VARGS) {
|
||||||
assert(is_flag_set(debug_flag, TYPE_CAN_BE_NULL));
|
assert(is_flag_set(debug_flag, TYPE_CAN_BE_NULL));
|
||||||
assert(expr->type);
|
assert(expr->type);
|
||||||
try_converting_untyped_to_default_type(expr);
|
try_converting_untyped_to_default_type(expr);
|
||||||
@@ -914,12 +914,21 @@ resolve_lambda_type(Ast_Lambda *lambda) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
For(lambda->args) {
|
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);
|
Ast_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL);
|
||||||
Operand default_value = resolve_expr(it->expr, AST_CAN_BE_NULL, type, 0);
|
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);
|
make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL);
|
||||||
|
|
||||||
it->type = type;
|
it->type = type;
|
||||||
try_propagating_resolved_type_to_untyped_literals(it->expr, it->type);
|
try_propagating_resolved_type_to_untyped_literals(it->expr, it->type);
|
||||||
|
}
|
||||||
|
|
||||||
args.add(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!!!
|
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);
|
Scoped_Arena scratch(pctx->scratch);
|
||||||
Ast_Lambda *lambda = name.resolved_decl->lambda;
|
Ast_Lambda *lambda = name.resolved_decl->lambda;
|
||||||
struct Match {
|
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) {
|
For2(lambda->args, lambda_arg) {
|
||||||
// assert(lambda_arg->type); // @todo: maybe add this check at the end
|
// 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;
|
Ast_Call_Item *item = 0;
|
||||||
For(node->exprs) {
|
For(node->exprs) {
|
||||||
S64 it_index = node->exprs.get_index(it);
|
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_Call_Item *item = it.call_arg;
|
||||||
Ast_Decl *lambda_arg = it.lambda_arg;
|
Ast_Decl *lambda_arg = it.lambda_arg;
|
||||||
if (lambda_arg->flags & AST_IDENT_POLYMORPH) continue;
|
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);
|
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);
|
make_sure_value_is_compatible_with_type(item->pos, &expr, lambda_arg->type, TYPE_AND_EXPR_REQUIRED);
|
||||||
item->resolved_type = lambda_arg->type;
|
item->resolved_type = lambda_arg->type;
|
||||||
|
}
|
||||||
try_propagating_resolved_type_to_untyped_literals(item->item, item->resolved_type);
|
try_propagating_resolved_type_to_untyped_literals(item->item, item->resolved_type);
|
||||||
items.add(item);
|
items.add(item);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -346,6 +346,9 @@ typename_base(String_Builder *sb, Ast_Type *type) {
|
|||||||
sb->addf("%Q", name);
|
sb->addf("%Q", name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case TYPE_VARGS: {
|
||||||
|
sb->addf("...");
|
||||||
|
} break;
|
||||||
case TYPE_UNTYPED_BOOL: sb->addf("Untyped_Bool"); break;
|
case TYPE_UNTYPED_BOOL: sb->addf("Untyped_Bool"); break;
|
||||||
case TYPE_UNTYPED_INT: sb->addf("Untyped_Int"); break;
|
case TYPE_UNTYPED_INT: sb->addf("Untyped_Int"); break;
|
||||||
case TYPE_UNTYPED_FLOAT: sb->addf("Untyped_Float"); break;
|
case TYPE_UNTYPED_FLOAT: sb->addf("Untyped_Float"); break;
|
||||||
|
|||||||
Reference in New Issue
Block a user