From: Brendan Hansen Date: Thu, 14 Jan 2021 22:07:59 +0000 (-0600) Subject: started working on refactoring named arguments X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=fa3e2c0361b13eabb822e3c809cb1608023553e5;p=onyx.git started working on refactoring named arguments --- diff --git a/bin/onyx b/bin/onyx index 6bc20b20..0ad6f334 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 2deb3717..92360087 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -7,6 +7,7 @@ typedef struct AstNode AstNode; typedef struct AstTyped AstTyped; +typedef struct AstNamedValue AstNamedValue; typedef struct AstBinaryOp AstBinaryOp; typedef struct AstUnaryOp AstUnaryOp; typedef struct AstNumLit AstNumLit; @@ -110,6 +111,7 @@ typedef enum AstKind { Ast_Kind_Binary_Op, Ast_Kind_Compound, + Ast_Kind_Named_Value, Ast_Kind_Type_Start, Ast_Kind_Type, @@ -460,6 +462,7 @@ struct AstNode { AstNode_base; }; struct AstTyped { AstTyped_base; }; // Expression Nodes +struct AstNamedValue { AstTyped_base; AstNode* value; }; struct AstBinaryOp { AstTyped_base; BinaryOp operation; AstTyped *left, *right; }; struct AstUnaryOp { AstTyped_base; UnaryOp operation; AstTyped *expr; }; struct AstNumLit { AstTyped_base; union { i32 i; i64 l; f32 f; f64 d; } value; }; @@ -478,7 +481,7 @@ struct AstStructLiteral { AstTyped *stnode; - bh_arr(AstStructMember *) named_values; + bh_arr(AstNamedValue *) named_values; bh_arr(AstTyped *) values; }; struct AstArrayLiteral { @@ -509,6 +512,7 @@ struct AstCall { u64 arg_count; bh_arr(AstArgument *) arg_arr; + bh_arr(AstNamedValue *) named_args; // '.value' is a pointer to AstArgument. AstTyped *callee; @@ -519,6 +523,7 @@ struct AstIntrinsicCall { u64 arg_count; bh_arr(AstArgument *) arg_arr; + bh_arr(AstNamedValue *) named_args; OnyxIntrinsic intrinsic; diff --git a/onyx.exe b/onyx.exe index b54fafb6..2307f964 100644 Binary files a/onyx.exe and b/onyx.exe differ diff --git a/src/onyxastnodes.c b/src/onyxastnodes.c index f0a90cca..17dc02b1 100644 --- a/src/onyxastnodes.c +++ b/src/onyxastnodes.c @@ -29,6 +29,7 @@ static const char* ast_node_names[] = { "BIN_OP", "COMPOUND", + "NAMED_VALUE" "TYPE_START (BAD)", "TYPE", diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 233917b7..6dd7d7f4 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -969,27 +969,27 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) { bh_arr_zero(sl->values); StructMember s; - bh_arr_each(AstStructMember *, smem, sl->named_values) { - token_toggle_end((*smem)->token); - if (!type_lookup_member(sl->type, (*smem)->token->text, &s)) { - onyx_report_error((*smem)->token->pos, - "The field '%s' does not exist on type '%s'.", (*smem)->token->text, type_get_name(sl->type)); - token_toggle_end((*smem)->token); + bh_arr_each(AstNamedValue *, named_value, sl->named_values) { + token_toggle_end((*named_value)->token); + if (!type_lookup_member(sl->type, (*named_value)->token->text, &s)) { + onyx_report_error((*named_value)->token->pos, + "The field '%s' does not exist on type '%s'.", (*named_value)->token->text, type_get_name(sl->type)); + token_toggle_end((*named_value)->token); return Check_Error; } - token_toggle_end((*smem)->token); + token_toggle_end((*named_value)->token); if (s.included_through_use) { - onyx_report_error((*smem)->token->pos, "Cannot specify value for member '%s', which was included through a 'use' statement.", s.name); + onyx_report_error((*named_value)->token->pos, "Cannot specify value for member '%s', which was included through a 'use' statement.", s.name); return Check_Error; } if (sl->values[s.idx] != NULL) { - onyx_report_error((*smem)->token->pos, "Multiple values given for '%b'.", (*smem)->token->text, (*smem)->token->length); + onyx_report_error((*named_value)->token->pos, "Multiple values given for '%b'.", (*named_value)->token->text, (*named_value)->token->length); return Check_Error; } - sl->values[s.idx] = (*smem)->initial_value; + sl->values[s.idx] = (AstTyped *) (*named_value)->value; } if (sl->type->kind == Type_Kind_Struct) { diff --git a/src/onyxclone.c b/src/onyxclone.c index 31881815..14444d12 100644 --- a/src/onyxclone.c +++ b/src/onyxclone.c @@ -193,8 +193,8 @@ AstNode* ast_clone(bh_allocator a, void* n) { bh_arr_new(global_heap_allocator, dt->named_values, bh_arr_length(st->named_values)); bh_arr_new(global_heap_allocator, dt->values, bh_arr_length(st->values)); - bh_arr_each(AstStructMember *, smem, st->named_values) - bh_arr_push(dt->named_values, (AstStructMember *) ast_clone(a, *smem)); + bh_arr_each(AstNamedValue *, nv, st->named_values) + bh_arr_push(dt->named_values, (AstNamedValue *) ast_clone(a, *nv)); bh_arr_each(AstTyped *, val, st->values) bh_arr_push(dt->values, (AstTyped *) ast_clone(a, *val)); diff --git a/src/onyxparser.c b/src/onyxparser.c index 6703c88f..911cca10 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -199,11 +199,11 @@ static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, Ast AstTyped *expr = parse_expression(parser, 0); if (is_named) { - AstStructMember* sm = make_node(AstStructMember, Ast_Kind_Struct_Member); - sm->token = name; - sm->initial_value = expr; + AstNamedValue* nv = make_node(AstStructMember, Ast_Kind_Named_Value); + nv->token = name; + nv->value = (AstNode *) expr; - bh_arr_push(sl->named_values, sm); + bh_arr_push(sl->named_values, nv); } else { bh_arr_push(sl->values, expr); diff --git a/src/onyxsymres.c b/src/onyxsymres.c index ea0d9e8e..1c5fbaa9 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -332,9 +332,9 @@ static void symres_struct_literal(AstStructLiteral* sl) { } if (sl->named_values != NULL) { - bh_arr_each(AstStructMember *, smem, sl->named_values) { - if ((*smem)->initial_value == NULL) onyx_report_error(sl->token->pos, "Some kind of error occured with this struct literal."); - else symres_expression(&(*smem)->initial_value); + bh_arr_each(AstNamedValue *, smem, sl->named_values) { + if ((*smem)->value == NULL) onyx_report_error(sl->token->pos, "Some kind of error occured with this struct literal."); + else symres_expression((AstTyped **) &(*smem)->value); } } } diff --git a/src/onyxutils.c b/src/onyxutils.c index 0fd12a08..77d2d742 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -821,3 +821,106 @@ void entity_bring_to_state(Entity* ent, EntityState state) { if (onyx_has_errors()) return; } } + + +static i32 lookup_idx_by_name(AstNode* provider, char* name) { + switch (provider->kind) { + case Ast_Kind_Struct_Literal: { + AstStructLiteral* sl = (AstStructLiteral *) provider; + assert(sl->type); + + StructMember s; + if (!type_lookup_member(sl->type, name, &s)) return -1; // nocheckin: Report error + + if (s.included_through_use) return -1; // nocheckin: Report error + + return s.idx; + } + + case Ast_Kind_Function: { + AstFunction* func = (AstFunction *) provider; + + // CLEANUP nocheckin + i32 param_idx = -1; + i32 idx = 0; + bh_arr_each(AstParam, param, func->params) { + token_toggle_end(param->local->token); + + if (strncmp(param->local->token->text, name, param->local->token->length) == 0) { + param_idx = idx; + + token_toggle_end(param->local->token); + break; + } + + token_toggle_end(param->local->token); + + idx++; + } + + return param_idx; + } + + default: return -1; + } +} + +static AstNode* lookup_default_value_by_idx(AstNode* provider, i32 idx) { + switch (provider->kind) { + case Ast_Kind_Struct_Literal: { + AstStructLiteral* sl = (AstStructLiteral *) provider; + assert(sl->type); + + if (sl->type->kind == Type_Kind_Struct) { + bh_arr(StructMember *) memarr = sl->type->Struct.memarr; + if (idx >= bh_arr_length(memarr)) return NULL; + + return (AstNode *) *memarr[idx]->initial_value; + } + + return NULL; + } + + case Ast_Kind_Function: { + AstFunction* func = (AstFunction *) provider; + + return (AstNode *) func->params[idx].default_value; + } + + default: return NULL; + } +} + +// NOTE: The values array can be partially filled out, and is the resulting array. +// Returns if all the values were filled in. +b32 fill_in_arguments(bh_arr(AstNode *) values, bh_arr(AstNamedValue *) named_values, AstNode* provider) { + bh_arr_each(AstNamedValue *, p_named_value, named_values) { + AstNamedValue* named_value = *p_named_value; + + token_toggle_end(named_value->token); + i32 idx = lookup_idx_by_name(provider, named_value->token->text); + if (idx == -1) { + onyx_report_error(provider->token->pos, + "'%s' is not a valid named parameter here.", + named_value->token->text); + + token_toggle_end(named_value->token); + return 0; + } + + token_toggle_end(named_value->token); + + assert(idx < bh_arr_length(values)); + values[idx] = named_value->value; + } + + fori (idx, 0, bh_arr_length(values)) { + if (values[idx] == NULL) { + values[idx] = lookup_default_value_by_idx(provider, idx); + + if (values[idx] == NULL) return 0; + } + } + + return 1; +} \ No newline at end of file