started working on refactoring named arguments
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 14 Jan 2021 22:07:59 +0000 (16:07 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 14 Jan 2021 22:07:59 +0000 (16:07 -0600)
bin/onyx
include/onyxastnodes.h
onyx.exe
src/onyxastnodes.c
src/onyxchecker.c
src/onyxclone.c
src/onyxparser.c
src/onyxsymres.c
src/onyxutils.c

index 6bc20b20a56b4be667b315a74d4ae7ae20489c41..0ad6f33435017d8731130191be56555fa9b5415b 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 2deb3717f4c99df7c15d1a878bc84cb79b7c7df1..923600871ad39ebb665ecce3400b6673b3926c49 100644 (file)
@@ -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;
 
index b54fafb6e2d360fc095c72147792273feedb255f..2307f9647a4dd127cbe30aa8bfab4bc5ac96de78 100644 (file)
Binary files a/onyx.exe and b/onyx.exe differ
index f0a90ccaf5109d1434680eda27dd00018c376d5e..17dc02b1f98978675b7f9c9e0234eadf8976d838 100644 (file)
@@ -29,6 +29,7 @@ static const char* ast_node_names[] = {
     "BIN_OP",
 
     "COMPOUND",
+    "NAMED_VALUE"
 
     "TYPE_START (BAD)",
     "TYPE",
index 233917b71571db1379650ad51c25a6105c6801d3..6dd7d7f4d5fae0c9c496d4b38cc1a0a734b5e1d2 100644 (file)
@@ -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) {
index 31881815c8ca19012bb5d3ce5f66e44c4cefe9b2..14444d12a3c6c57295237fbcd9955f0dc1139242 100644 (file)
@@ -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));
index 6703c88fc97dcfdb40c6fabbf5a5feedf114a359..911cca108add6764703dd03c0eb48a6e6d45013a 100644 (file)
@@ -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);
index ea0d9e8e87eef139e7de3e31569cdc626bbec36f..1c5fbaa9fa92584c754bb477d49ab8db4663f9d3 100644 (file)
@@ -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);
         }
     }
 }
index 0fd12a0848dd17f2aa3b11033498ae97abf6dc6c..77d2d742547f2d76155811fb5953cd2d5ce416f1 100644 (file)
@@ -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