mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Default parameters for procedures
This commit is contained in:
+91
-27
@@ -255,13 +255,18 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
i64 assign_score_function(i64 distance) {
|
||||||
|
// TODO(bill): A decent score function
|
||||||
|
return gb_max(1000000 - distance*distance, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool check_is_assignable_to_with_score(Checker *c, Operand *operand, Type *type, i64 *score_) {
|
bool check_is_assignable_to_with_score(Checker *c, Operand *operand, Type *type, i64 *score_) {
|
||||||
i64 score = 0;
|
i64 score = 0;
|
||||||
i64 distance = check_distance_between_types(c, operand, type);
|
i64 distance = check_distance_between_types(c, operand, type);
|
||||||
bool ok = distance >= 0;
|
bool ok = distance >= 0;
|
||||||
if (ok) {
|
if (ok) {
|
||||||
// TODO(bill): A decent score function
|
score = assign_score_function(distance);
|
||||||
score = gb_max(1000000 - distance*distance, 0);
|
|
||||||
}
|
}
|
||||||
if (score_) *score_ = score;
|
if (score_) *score_ = score;
|
||||||
return ok;
|
return ok;
|
||||||
@@ -1051,7 +1056,22 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
|
|||||||
}
|
}
|
||||||
ast_node(p, Field, params[i]);
|
ast_node(p, Field, params[i]);
|
||||||
AstNode *type_expr = p->type;
|
AstNode *type_expr = p->type;
|
||||||
if (type_expr) {
|
Type *type = NULL;
|
||||||
|
AstNode *default_value = p->default_value;
|
||||||
|
ExactValue value = {};
|
||||||
|
|
||||||
|
if (type_expr == NULL) {
|
||||||
|
Operand o = {};
|
||||||
|
check_expr(c, &o, default_value);
|
||||||
|
|
||||||
|
if (o.mode != Addressing_Constant) {
|
||||||
|
error_node(default_value, "Default parameter must be a constant");
|
||||||
|
} else {
|
||||||
|
value = o.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = default_type(o.type);
|
||||||
|
} else {
|
||||||
if (type_expr->kind == AstNode_Ellipsis) {
|
if (type_expr->kind == AstNode_Ellipsis) {
|
||||||
type_expr = type_expr->Ellipsis.expr;
|
type_expr = type_expr->Ellipsis.expr;
|
||||||
if (i+1 == params.count) {
|
if (i+1 == params.count) {
|
||||||
@@ -1061,28 +1081,49 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *type = check_type(c, type_expr);
|
type = check_type(c, type_expr);
|
||||||
if (p->flags&FieldFlag_no_alias) {
|
|
||||||
if (!is_type_pointer(type)) {
|
if (default_value != NULL) {
|
||||||
error_node(params[i], "`no_alias` can only be applied to fields of pointer type");
|
Operand o = {};
|
||||||
p->flags &= ~FieldFlag_no_alias; // Remove the flag
|
check_expr(c, &o, default_value);
|
||||||
|
|
||||||
|
if (o.mode != Addressing_Constant) {
|
||||||
|
error_node(default_value, "Default parameter must be a constant");
|
||||||
|
} else {
|
||||||
|
value = o.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_is_assignable_to(c, &o, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
for_array(j, p->names) {
|
}
|
||||||
AstNode *name = p->names[j];
|
if (type == NULL) {
|
||||||
if (ast_node_expect(name, AstNode_Ident)) {
|
error_node(params[i], "Invalid parameter type");
|
||||||
Entity *param = make_entity_param(c->allocator, scope, name->Ident, type,
|
type = t_invalid;
|
||||||
(p->flags&FieldFlag_using) != 0, (p->flags&FieldFlag_immutable) != 0);
|
}
|
||||||
if (p->flags&FieldFlag_no_alias) {
|
|
||||||
param->flags |= EntityFlag_NoAlias;
|
if (p->flags&FieldFlag_no_alias) {
|
||||||
}
|
if (!is_type_pointer(type)) {
|
||||||
if (p->flags&FieldFlag_immutable) {
|
error_node(params[i], "`no_alias` can only be applied to fields of pointer type");
|
||||||
param->Variable.is_immutable = true;
|
p->flags &= ~FieldFlag_no_alias; // Remove the flag
|
||||||
}
|
}
|
||||||
add_entity(c, scope, name, param);
|
}
|
||||||
variables[variable_index++] = param;
|
|
||||||
|
for_array(j, p->names) {
|
||||||
|
AstNode *name = p->names[j];
|
||||||
|
if (ast_node_expect(name, AstNode_Ident)) {
|
||||||
|
Entity *param = make_entity_param(c->allocator, scope, name->Ident, type,
|
||||||
|
(p->flags&FieldFlag_using) != 0, (p->flags&FieldFlag_immutable) != 0);
|
||||||
|
if (p->flags&FieldFlag_no_alias) {
|
||||||
|
param->flags |= EntityFlag_NoAlias;
|
||||||
}
|
}
|
||||||
|
if (p->flags&FieldFlag_immutable) {
|
||||||
|
param->Variable.is_immutable = true;
|
||||||
|
}
|
||||||
|
param->Variable.default_value = value;
|
||||||
|
|
||||||
|
add_entity(c, scope, name, param);
|
||||||
|
variables[variable_index++] = param;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4775,18 +4816,35 @@ typedef CALL_ARGUMENT_CHECKER(CallArgumentCheckerType);
|
|||||||
CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
||||||
ast_node(ce, CallExpr, call);
|
ast_node(ce, CallExpr, call);
|
||||||
isize param_count = 0;
|
isize param_count = 0;
|
||||||
|
isize param_count_excluding_defaults = 0;
|
||||||
bool variadic = proc_type->Proc.variadic;
|
bool variadic = proc_type->Proc.variadic;
|
||||||
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
bool vari_expand = (ce->ellipsis.pos.line != 0);
|
||||||
i64 score = 0;
|
i64 score = 0;
|
||||||
bool show_error = show_error_mode == CallArgumentMode_ShowErrors;
|
bool show_error = show_error_mode == CallArgumentMode_ShowErrors;
|
||||||
|
|
||||||
|
TypeTuple *param_tuple = NULL;
|
||||||
|
|
||||||
if (proc_type->Proc.params != NULL) {
|
if (proc_type->Proc.params != NULL) {
|
||||||
param_count = proc_type->Proc.params->Tuple.variable_count;
|
param_tuple = &proc_type->Proc.params->Tuple;
|
||||||
|
|
||||||
|
param_count = param_tuple->variable_count;
|
||||||
if (variadic) {
|
if (variadic) {
|
||||||
param_count--;
|
param_count--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
param_count_excluding_defaults = param_count;
|
||||||
|
if (param_tuple != NULL) {
|
||||||
|
for (isize i = param_count-1; i >= 0; i--) {
|
||||||
|
Entity *e = param_tuple->variables[i];
|
||||||
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
|
if (e->Variable.default_value.kind == ExactValue_Invalid) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
param_count_excluding_defaults--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (vari_expand && !variadic) {
|
if (vari_expand && !variadic) {
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
error(ce->ellipsis,
|
error(ce->ellipsis,
|
||||||
@@ -4797,13 +4855,13 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
|||||||
return CallArgumentError_NonVariadicExpand;
|
return CallArgumentError_NonVariadicExpand;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operands.count == 0 && param_count == 0) {
|
if (operands.count == 0 && param_count_excluding_defaults == 0) {
|
||||||
if (score_) *score_ = score;
|
if (score_) *score_ = score;
|
||||||
return CallArgumentError_None;
|
return CallArgumentError_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 error_code = 0;
|
i32 error_code = 0;
|
||||||
if (operands.count < param_count) {
|
if (operands.count < param_count_excluding_defaults) {
|
||||||
error_code = -1;
|
error_code = -1;
|
||||||
} else if (!variadic && operands.count > param_count) {
|
} else if (!variadic && operands.count > param_count) {
|
||||||
error_code = +1;
|
error_code = +1;
|
||||||
@@ -4818,7 +4876,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
|||||||
|
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
gbString proc_str = expr_to_string(ce->proc);
|
gbString proc_str = expr_to_string(ce->proc);
|
||||||
error_node(call, err_fmt, proc_str, param_count);
|
error_node(call, err_fmt, proc_str, param_count_excluding_defaults);
|
||||||
gb_string_free(proc_str);
|
gb_string_free(proc_str);
|
||||||
}
|
}
|
||||||
if (score_) *score_ = score;
|
if (score_) *score_ = score;
|
||||||
@@ -4828,9 +4886,9 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
|
|||||||
CallArgumentError err = CallArgumentError_None;
|
CallArgumentError err = CallArgumentError_None;
|
||||||
|
|
||||||
GB_ASSERT(proc_type->Proc.params != NULL);
|
GB_ASSERT(proc_type->Proc.params != NULL);
|
||||||
Entity **sig_params = proc_type->Proc.params->Tuple.variables;
|
Entity **sig_params = param_tuple->variables;
|
||||||
isize operand_index = 0;
|
isize operand_index = 0;
|
||||||
for (; operand_index < param_count; operand_index++) {
|
for (; operand_index < param_count_excluding_defaults; operand_index++) {
|
||||||
Type *t = sig_params[operand_index]->type;
|
Type *t = sig_params[operand_index]->type;
|
||||||
Operand o = operands[operand_index];
|
Operand o = operands[operand_index];
|
||||||
if (variadic) {
|
if (variadic) {
|
||||||
@@ -4972,6 +5030,12 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
|||||||
if (e->token.string == "_") {
|
if (e->token.string == "_") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
|
if (e->Variable.default_value.kind != ExactValue_Invalid) {
|
||||||
|
score += assign_score_function(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
gbString str = type_to_string(e->type);
|
gbString str = type_to_string(e->type);
|
||||||
error_node(call, "Parameter `%.*s` of type `%s` is missing in procedure call",
|
error_node(call, "Parameter `%.*s` of type `%s` is missing in procedure call",
|
||||||
|
|||||||
+5
-4
@@ -81,10 +81,11 @@ struct Entity {
|
|||||||
ExactValue value;
|
ExactValue value;
|
||||||
} Constant;
|
} Constant;
|
||||||
struct {
|
struct {
|
||||||
i32 field_index;
|
i32 field_index;
|
||||||
i32 field_src_index;
|
i32 field_src_index;
|
||||||
bool is_immutable;
|
bool is_immutable;
|
||||||
bool is_thread_local;
|
bool is_thread_local;
|
||||||
|
ExactValue default_value;
|
||||||
} Variable;
|
} Variable;
|
||||||
struct {
|
struct {
|
||||||
bool is_type_alias;
|
bool is_type_alias;
|
||||||
|
|||||||
+31
-8
@@ -4616,16 +4616,20 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
|||||||
}
|
}
|
||||||
TypeTuple *pt = &type->params->Tuple;
|
TypeTuple *pt = &type->params->Tuple;
|
||||||
for (isize i = 0; i < param_count; i++) {
|
for (isize i = 0; i < param_count; i++) {
|
||||||
Type *param_type = pt->variables[i]->type;
|
Entity *e = pt->variables[i];
|
||||||
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
if (args[i] == NULL) {
|
if (args[i] == NULL) {
|
||||||
args[i] = ir_value_nil(proc->module->allocator, param_type);
|
if (e->Variable.default_value.kind != ExactValue_Invalid) {
|
||||||
|
args[i] = ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value);
|
||||||
|
} else {
|
||||||
|
args[i] = ir_value_nil(proc->module->allocator, e->type);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
args[i] = ir_emit_conv(proc, args[i], param_type);
|
args[i] = ir_emit_conv(proc, args[i], e->type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ir_emit_call(proc, value, args, param_count);
|
return ir_emit_call(proc, value, args, param_count);
|
||||||
// GB_PANIC("HERE!\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isize arg_index = 0;
|
isize arg_index = 0;
|
||||||
@@ -4640,7 +4644,9 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
|||||||
arg_count++;
|
arg_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, arg_count);
|
|
||||||
|
|
||||||
|
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, gb_max(type->param_count, arg_count));
|
||||||
bool variadic = type->variadic;
|
bool variadic = type->variadic;
|
||||||
bool vari_expand = ce->ellipsis.pos.line != 0;
|
bool vari_expand = ce->ellipsis.pos.line != 0;
|
||||||
|
|
||||||
@@ -4660,6 +4666,23 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
|||||||
|
|
||||||
TypeTuple *pt = &type->params->Tuple;
|
TypeTuple *pt = &type->params->Tuple;
|
||||||
|
|
||||||
|
if (arg_count < type->param_count) {
|
||||||
|
isize end = type->param_count;
|
||||||
|
if (variadic) {
|
||||||
|
end--;
|
||||||
|
}
|
||||||
|
while (arg_index < end) {
|
||||||
|
Entity *e = pt->variables[arg_index];
|
||||||
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
|
if (e->Variable.default_value.kind != ExactValue_Invalid) {
|
||||||
|
args[arg_index++] = ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value);
|
||||||
|
} else {
|
||||||
|
args[arg_index++] = ir_value_nil(proc->module->allocator, e->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (variadic) {
|
if (variadic) {
|
||||||
isize i = 0;
|
isize i = 0;
|
||||||
for (; i < type->param_count-1; i++) {
|
for (; i < type->param_count-1; i++) {
|
||||||
@@ -4674,7 +4697,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (isize i = 0; i < arg_count; i++) {
|
for (isize i = 0; i < type->param_count; i++) {
|
||||||
args[i] = ir_emit_conv(proc, args[i], pt->variables[i]->type);
|
args[i] = ir_emit_conv(proc, args[i], pt->variables[i]->type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4704,7 +4727,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
|||||||
args[arg_count-1] = ir_emit_load(proc, slice);
|
args[arg_count-1] = ir_emit_load(proc, slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ir_emit_call(proc, value, args, arg_count);
|
return ir_emit_call(proc, value, args, type->param_count);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(se, SliceExpr, expr);
|
case_ast_node(se, SliceExpr, expr);
|
||||||
@@ -6680,7 +6703,7 @@ void ir_number_proc_registers(irProcedure *proc) {
|
|||||||
b->index = i;
|
b->index = i;
|
||||||
for_array(j, b->instrs) {
|
for_array(j, b->instrs) {
|
||||||
irValue *value = b->instrs[j];
|
irValue *value = b->instrs[j];
|
||||||
GB_ASSERT(value->kind == irValue_Instr);
|
GB_ASSERT_MSG(value->kind == irValue_Instr, "%.*s", LIT(proc->name));
|
||||||
irInstr *instr = &value->Instr;
|
irInstr *instr = &value->Instr;
|
||||||
if (ir_instr_type(instr) == NULL) { // NOTE(bill): Ignore non-returning instructions
|
if (ir_instr_type(instr) == NULL) { // NOTE(bill): Ignore non-returning instructions
|
||||||
value->index = -1;
|
value->index = -1;
|
||||||
|
|||||||
+48
-12
@@ -326,9 +326,10 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
|
|||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(_DeclEnd, "", i32) \
|
AST_NODE_KIND(_DeclEnd, "", i32) \
|
||||||
AST_NODE_KIND(Field, "field", struct { \
|
AST_NODE_KIND(Field, "field", struct { \
|
||||||
Array<AstNode *> names; \
|
Array<AstNode *> names; \
|
||||||
AstNode * type; \
|
AstNode * type; \
|
||||||
u32 flags; \
|
AstNode * default_value; \
|
||||||
|
u32 flags; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(FieldList, "field list", struct { \
|
AST_NODE_KIND(FieldList, "field list", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
@@ -1276,10 +1277,11 @@ AstNode *ast_bad_decl(AstFile *f, Token begin, Token end) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *ast_field(AstFile *f, Array<AstNode *> names, AstNode *type, u32 flags) {
|
AstNode *ast_field(AstFile *f, Array<AstNode *> names, AstNode *type, AstNode *default_value, u32 flags) {
|
||||||
AstNode *result = make_ast_node(f, AstNode_Field);
|
AstNode *result = make_ast_node(f, AstNode_Field);
|
||||||
result->Field.names = names;
|
result->Field.names = names;
|
||||||
result->Field.type = type;
|
result->Field.type = type;
|
||||||
|
result->Field.default_value = default_value;
|
||||||
result->Field.flags = flags;
|
result->Field.flags = flags;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -2645,7 +2647,7 @@ AstNode *parse_results(AstFile *f) {
|
|||||||
Array<AstNode *> empty_names = {};
|
Array<AstNode *> empty_names = {};
|
||||||
Array<AstNode *> list = make_ast_node_array(f);
|
Array<AstNode *> list = make_ast_node_array(f);
|
||||||
AstNode *type = parse_type(f);
|
AstNode *type = parse_type(f);
|
||||||
array_add(&list, ast_field(f, empty_names, type, 0));
|
array_add(&list, ast_field(f, empty_names, type, NULL, 0));
|
||||||
return ast_field_list(f, begin_token, list);
|
return ast_field_list(f, begin_token, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2839,6 +2841,7 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
|
|||||||
Array<AstNodeAndFlags> list = {}; array_init(&list, heap_allocator()); // LEAK(bill):
|
Array<AstNodeAndFlags> list = {}; array_init(&list, heap_allocator()); // LEAK(bill):
|
||||||
isize total_name_count = 0;
|
isize total_name_count = 0;
|
||||||
bool allow_ellipsis = allowed_flags&FieldFlag_ellipsis;
|
bool allow_ellipsis = allowed_flags&FieldFlag_ellipsis;
|
||||||
|
bool is_procedure = (allowed_flags&FieldFlag_Signature) != 0;
|
||||||
|
|
||||||
while (f->curr_token.kind != follow &&
|
while (f->curr_token.kind != follow &&
|
||||||
f->curr_token.kind != Token_Colon &&
|
f->curr_token.kind != Token_Colon &&
|
||||||
@@ -2866,8 +2869,25 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
|
|||||||
total_name_count += names.count;
|
total_name_count += names.count;
|
||||||
|
|
||||||
expect_token_after(f, Token_Colon, "field list");
|
expect_token_after(f, Token_Colon, "field list");
|
||||||
AstNode *type = parse_var_type(f, allow_ellipsis);
|
AstNode *type = NULL;
|
||||||
AstNode *param = ast_field(f, names, type, set_flags);
|
AstNode *default_value = NULL;
|
||||||
|
|
||||||
|
if (f->curr_token.kind != Token_Eq) {
|
||||||
|
type = parse_var_type(f, allow_ellipsis);
|
||||||
|
}
|
||||||
|
if (allow_token(f, Token_Eq)) {
|
||||||
|
// TODO(bill): Should this be true==lhs or false==rhs?
|
||||||
|
default_value = parse_expr(f, true);
|
||||||
|
if (!is_procedure) {
|
||||||
|
syntax_error(f->curr_token, "Default parameters are only allowed for procedures");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (default_value != NULL && names.count > 1) {
|
||||||
|
syntax_error(f->curr_token, "Default parameters can only be applied to single values");
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode *param = ast_field(f, names, type, default_value, set_flags);
|
||||||
array_add(¶ms, param);
|
array_add(¶ms, param);
|
||||||
|
|
||||||
parse_expect_field_separator(f, type);
|
parse_expect_field_separator(f, type);
|
||||||
@@ -2884,8 +2904,24 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
|
|||||||
total_name_count += names.count;
|
total_name_count += names.count;
|
||||||
|
|
||||||
expect_token_after(f, Token_Colon, "field list");
|
expect_token_after(f, Token_Colon, "field list");
|
||||||
AstNode *type = parse_var_type(f, allow_ellipsis);
|
AstNode *type = NULL;
|
||||||
AstNode *param = ast_field(f, names, type, set_flags);
|
AstNode *default_value = NULL;
|
||||||
|
if (f->curr_token.kind != Token_Eq) {
|
||||||
|
type = parse_var_type(f, allow_ellipsis);
|
||||||
|
}
|
||||||
|
if (allow_token(f, Token_Eq)) {
|
||||||
|
// TODO(bill): Should this be true==lhs or false==rhs?
|
||||||
|
default_value = parse_expr(f, true);
|
||||||
|
if (!is_procedure) {
|
||||||
|
syntax_error(f->curr_token, "Default parameters are only allowed for procedures");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (default_value != NULL && names.count > 1) {
|
||||||
|
syntax_error(f->curr_token, "Default parameters can only be applied to single values");
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode *param = ast_field(f, names, type, default_value, set_flags);
|
||||||
array_add(¶ms, param);
|
array_add(¶ms, param);
|
||||||
|
|
||||||
if (!parse_expect_field_separator(f, param)) {
|
if (!parse_expect_field_separator(f, param)) {
|
||||||
@@ -2907,7 +2943,7 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
|
|||||||
names[0] = ast_ident(f, token);
|
names[0] = ast_ident(f, token);
|
||||||
u32 flags = check_field_prefixes(f, list.count, allowed_flags, list[i].flags);
|
u32 flags = check_field_prefixes(f, list.count, allowed_flags, list[i].flags);
|
||||||
|
|
||||||
AstNode *param = ast_field(f, names, list[i].node, flags);
|
AstNode *param = ast_field(f, names, list[i].node, NULL, flags);
|
||||||
array_add(¶ms, param);
|
array_add(¶ms, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3084,7 +3120,7 @@ AstNode *parse_type_or_ident(AstFile *f) {
|
|||||||
total_decl_name_count += names.count;
|
total_decl_name_count += names.count;
|
||||||
expect_token_after(f, Token_Colon, "field list");
|
expect_token_after(f, Token_Colon, "field list");
|
||||||
AstNode *type = parse_var_type(f, false);
|
AstNode *type = parse_var_type(f, false);
|
||||||
array_add(&decls, ast_field(f, names, type, set_flags));
|
array_add(&decls, ast_field(f, names, type, NULL, set_flags));
|
||||||
} else {
|
} else {
|
||||||
Array<AstNode *> names = parse_ident_list(f);
|
Array<AstNode *> names = parse_ident_list(f);
|
||||||
if (names.count == 0) {
|
if (names.count == 0) {
|
||||||
@@ -3095,7 +3131,7 @@ AstNode *parse_type_or_ident(AstFile *f) {
|
|||||||
total_decl_name_count += names.count;
|
total_decl_name_count += names.count;
|
||||||
expect_token_after(f, Token_Colon, "field list");
|
expect_token_after(f, Token_Colon, "field list");
|
||||||
AstNode *type = parse_var_type(f, false);
|
AstNode *type = parse_var_type(f, false);
|
||||||
array_add(&decls, ast_field(f, names, type, set_flags));
|
array_add(&decls, ast_field(f, names, type, NULL, set_flags));
|
||||||
} else {
|
} else {
|
||||||
AstNode *name = names[0];
|
AstNode *name = names[0];
|
||||||
Token open = expect_token(f, Token_OpenBrace);
|
Token open = expect_token(f, Token_OpenBrace);
|
||||||
|
|||||||
Reference in New Issue
Block a user