made range literals not turn into struct literals
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 23 Dec 2020 21:48:31 +0000 (15:48 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 23 Dec 2020 21:48:31 +0000 (15:48 -0600)
include/onyxastnodes.h
onyx
src/onyxchecker.c
src/onyxclone.c
src/onyxparser.c
src/onyxsymres.c
src/onyxwasm.c

index 35d32a216e3893aab175b6493be0ec8474f5e164..fd0813983f2ba5d4496e13d279ea7facf2b3b4cf 100644 (file)
@@ -7,7 +7,7 @@
 typedef struct AstNode AstNode;
 typedef struct AstTyped AstTyped;
 
-typedef struct AstBinOp AstBinaryOp;
+typedef struct AstBinaryOp AstBinaryOp;
 typedef struct AstUnaryOp AstUnaryOp;
 typedef struct AstNumLit AstNumLit;
 typedef struct AstStrLit AstStrLit;
@@ -24,6 +24,7 @@ typedef struct AstAlignOf AstAlignOf;
 typedef struct AstFileContents AstFileContents;
 typedef struct AstStructLiteral AstStructLiteral;
 typedef struct AstArrayLiteral AstArrayLiteral;
+typedef struct AstRangeLiteral AstRangeLiteral;
 
 typedef struct AstReturn AstReturn;
 typedef struct AstJump AstJump;
@@ -134,7 +135,7 @@ typedef enum AstKind {
     Ast_Kind_Slice,
     Ast_Kind_Field_Access,
     Ast_Kind_Pipe,
-    Ast_Kind_Range,
+    Ast_Kind_Range_Literal,
     Ast_Kind_Size_Of,
     Ast_Kind_Align_Of,
     Ast_Kind_File_Contents,
@@ -438,7 +439,7 @@ struct AstNode { AstNode_base };
 struct AstTyped { AstTyped_base };
 
 // Expression Nodes
-struct AstBinOp         { AstTyped_base; BinaryOp operation; AstTyped *left, *right; };
+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; };
 struct AstStrLit        { AstTyped_base; u64 addr; u64 length; };
@@ -466,6 +467,22 @@ struct AstArrayLiteral {
 
     bh_arr(AstTyped *) values;
 };
+struct AstRangeLiteral {
+    AstTyped_base; 
+
+    // HACK: Currently, range literals are parsed as binary operators, which means
+    // the first sizeof(AstBinaryOp) bytes of this structure must match that of
+    // AstBinaryOp, which means I need this dummy field here.
+    //                                              - brendanfh 2020/12/23
+    BinaryOp __unused_operation;
+    AstTyped *low, *high;
+
+    // Currently, there is no way to specify this in the grammar, but it is set
+    // to be the initial value of the `step` member of the range structure in
+    // core/builtin.onyx.
+    //                                              - brendanfh 2020/12/23
+    AstTyped *step;
+};
 struct AstCall {
     AstTyped_base;
 
diff --git a/onyx b/onyx
index a7f14b603b89bee19da1d0169673447dcc0ef583..dc37f1cd2da1ce2881ccb6d4faa19df9c91cc5e0 100755 (executable)
Binary files a/onyx and b/onyx differ
index e65982890642371c7c242aeed578fa1f3f67bbc5..dfbc9df3334b1df837db5ead0814e4281aa0d103 100644 (file)
@@ -18,12 +18,12 @@ CHECK(binaryop, AstBinaryOp** pbinop, b32 assignment_is_ok);
 CHECK(unaryop, AstUnaryOp** punop);
 CHECK(struct_literal, AstStructLiteral* sl);
 CHECK(array_literal, AstArrayLiteral* al);
+CHECK(range_literal, AstRangeLiteral** range);
 CHECK(expression, AstTyped** expr);
 CHECK(address_of, AstAddressOf* aof);
 CHECK(dereference, AstDereference* deref);
 CHECK(array_access, AstArrayAccess* expr);
 CHECK(field_access, AstFieldAccess** pfield);
-CHECK(range_literal, AstBinaryOp** range);
 CHECK(size_of, AstSizeOf* so);
 CHECK(align_of, AstAlignOf* ao);
 CHECK(global, AstGlobal* global);
@@ -961,6 +961,38 @@ b32 check_array_literal(AstArrayLiteral* al) {
     return 0;
 }
 
+b32 check_range_literal(AstRangeLiteral** prange) {
+    AstRangeLiteral* range = *prange;
+    if (check_expression(&range->low))  return 1;
+    if (check_expression(&range->high)) return 1;
+
+    Type* expected_range_type = builtin_range_type_type;
+    StructMember smem;
+
+    type_lookup_member(expected_range_type, "low", &smem);
+    if (!type_check_or_auto_cast(&range->low, smem.type)) {
+        onyx_report_error(range->token->pos, "Expected left side of range to be a 32-bit integer.");
+        return 1;
+    }
+
+    type_lookup_member(expected_range_type, "high", &smem);
+    if (!type_check_or_auto_cast(&range->high, smem.type)) {
+        onyx_report_error(range->token->pos, "Expected right side of range to be a 32-bit integer.");
+        return 1;
+    }
+
+    if (range->step == NULL) {
+        // HACK: This relies on the third member of the 'range' struct to exist, be the step,
+        // and have an initial_value.
+        AstStructMember* step_member = ((AstStructType *) builtin_range_type)->members[2];
+        if (check_expression(&step_member->initial_value)) return 1;
+
+        range->step = step_member->initial_value;
+    }
+
+    return 0;
+}
+
 b32 check_address_of(AstAddressOf* aof) {
     if (check_expression(&aof->expr)) return 1;
 
@@ -1116,55 +1148,6 @@ b32 check_field_access(AstFieldAccess** pfield) {
     return 0;
 }
 
-b32 check_range_literal(AstBinaryOp** prange) {
-    AstBinaryOp* range = *prange;
-    if (check_expression(&range->left))  return 1;
-    if (check_expression(&range->right)) return 1;
-
-    Type* expected_range_type = builtin_range_type_type;
-    StructMember smem;
-
-    type_lookup_member(expected_range_type, "low", &smem);
-    if (!type_check_or_auto_cast(&range->left, smem.type)) {
-        onyx_report_error(range->token->pos, "Expected left side of range to be a 32-bit integer.");
-        return 1;
-    }
-
-    type_lookup_member(expected_range_type, "high", &smem);
-    if (!type_check_or_auto_cast(&range->right, smem.type)) {
-        onyx_report_error(range->token->pos, "Expected right side of range to be a 32-bit integer.");
-        return 1;
-    }
-
-    // NOTE: Implicitly converting this to a struct literal because that makes the
-    // WASM generation easier and more robust for return a range from a procedure
-    // and the like. This could be improved as struct literals are made more throughout
-    // the code base.
-    //                                                          - brendanfh, 2020/09/03
-    AstStructLiteral* rsl = onyx_ast_node_new(semstate.node_allocator, sizeof(AstStructLiteral), Ast_Kind_Struct_Literal);
-    bh_arr_new(global_heap_allocator, rsl->values, 3);
-
-    bh_arr_insert_end(rsl->values, 2);
-    type_lookup_member(expected_range_type, "low", &smem);
-    rsl->values[smem.idx] = range->left;
-    type_lookup_member(expected_range_type, "high", &smem);
-    rsl->values[smem.idx] = range->right;
-
-    // HACK: This relies on the third member of the 'range' struct to exist, be the step,
-    // and have an intial_value.
-    AstStructMember* step_member = ((AstStructType *) builtin_range_type)->members[2];
-    if (check_expression(&step_member->initial_value)) return 1;
-    bh_arr_push(rsl->values, step_member->initial_value);
-
-    rsl->token = range->token;
-    rsl->type = expected_range_type;
-
-    // NOTE: Not a binary op
-    *prange = (AstBinaryOp *) rsl;
-
-    return 0;
-}
-
 b32 check_size_of(AstSizeOf* so) {
     fill_in_array_count(so->so_ast_type);
 
@@ -1224,14 +1207,14 @@ b32 check_expression(AstTyped** pexpr) {
 
         case Ast_Kind_Local: break;
 
-        case Ast_Kind_Address_Of:   retval = check_address_of((AstAddressOf *) expr); break;
-        case Ast_Kind_Dereference:  retval = check_dereference((AstDereference *) expr); break;
+        case Ast_Kind_Address_Of:    retval = check_address_of((AstAddressOf *) expr); break;
+        case Ast_Kind_Dereference:   retval = check_dereference((AstDereference *) expr); break;
         case Ast_Kind_Slice:
-        case Ast_Kind_Array_Access: retval = check_array_access((AstArrayAccess *) expr); break;
-        case Ast_Kind_Field_Access: retval = check_field_access((AstFieldAccess **) pexpr); break;
-        case Ast_Kind_Size_Of:      retval = check_size_of((AstSizeOf *) expr); break;
-        case Ast_Kind_Align_Of:     retval = check_align_of((AstAlignOf *) expr); break;
-        case Ast_Kind_Range:        retval = check_range_literal((AstBinaryOp **) pexpr); break;
+        case Ast_Kind_Array_Access:  retval = check_array_access((AstArrayAccess *) expr); break;
+        case Ast_Kind_Field_Access:  retval = check_field_access((AstFieldAccess **) pexpr); break;
+        case Ast_Kind_Size_Of:       retval = check_size_of((AstSizeOf *) expr); break;
+        case Ast_Kind_Align_Of:      retval = check_align_of((AstAlignOf *) expr); break;
+        case Ast_Kind_Range_Literal: retval = check_range_literal((AstRangeLiteral **) pexpr); break;
 
         case Ast_Kind_Global:
             if (expr->type == NULL) {
index 31cd7e75e7a12bb1fa67a06adc8027ea6d538790..6d4bf71c3632877e744958c8cdff2d7a8d7390b3 100644 (file)
@@ -74,11 +74,12 @@ static inline i32 ast_kind_to_size(AstNode* node) {
         case Ast_Kind_Slice: return sizeof(AstArrayAccess);
         case Ast_Kind_Field_Access: return sizeof(AstFieldAccess);
         case Ast_Kind_Pipe: return sizeof(AstBinaryOp);
-        case Ast_Kind_Range: return sizeof(AstBinaryOp);
+        case Ast_Kind_Range_Literal: return sizeof(AstRangeLiteral);
         case Ast_Kind_Size_Of: return sizeof(AstSizeOf);
         case Ast_Kind_Align_Of: return sizeof(AstAlignOf);
         case Ast_Kind_File_Contents: return sizeof(AstFileContents);
         case Ast_Kind_Struct_Literal: return sizeof(AstStructLiteral);
+        case Ast_Kind_Array_Literal: return sizeof(AstArrayLiteral);
         case Ast_Kind_If: return sizeof(AstIfWhile);
         case Ast_Kind_For: return sizeof(AstFor);
         case Ast_Kind_While: return sizeof(AstIfWhile);
@@ -124,7 +125,6 @@ AstNode* ast_clone(bh_allocator a, void* n) {
 
        switch ((u16) node->kind) {
                case Ast_Kind_Binary_Op:
-        case Ast_Kind_Range:
                        ((AstBinaryOp *) nn)->left  = (AstTyped *) ast_clone(a, ((AstBinaryOp *) node)->left);
                        ((AstBinaryOp *) nn)->right = (AstTyped *) ast_clone(a, ((AstBinaryOp *) node)->right);
                        break;
@@ -193,6 +193,26 @@ AstNode* ast_clone(bh_allocator a, void* n) {
                        break;
                }
 
+               case Ast_Kind_Array_Literal: {
+                       AstArrayLiteral* st = (AstArrayLiteral *) node;
+                       AstArrayLiteral* dt = (AstArrayLiteral *) nn;
+
+                       dt->atnode = (AstTyped *) ast_clone(a, st->atnode);
+
+                       dt->values = NULL;
+                       bh_arr_new(global_heap_allocator, dt->values, bh_arr_length(st->values));
+                       bh_arr_each(AstTyped *, val, st->values)
+                               bh_arr_push(dt->values, (AstTyped *) ast_clone(a, *val));
+
+                       break;
+               }
+
+        case Ast_Kind_Range_Literal:
+                       ((AstRangeLiteral *) nn)->low  = (AstTyped *) ast_clone(a, ((AstRangeLiteral *) node)->low); 
+                       ((AstRangeLiteral *) nn)->high = (AstTyped *) ast_clone(a, ((AstRangeLiteral *) node)->high); 
+                       ((AstRangeLiteral *) nn)->step = (AstTyped *) ast_clone(a, ((AstRangeLiteral *) node)->step); 
+               break;
+
                case Ast_Kind_Return:
                        ((AstReturn *) nn)->expr = (AstTyped *) ast_clone(a, ((AstReturn *) node)->expr);
                        break;
index 2f7e7a5bdb4dd9c944051342f44ae73f4fd07fb2..d393cea7ad951e067f1e3a45c01a7dd915bdaa45 100644 (file)
@@ -749,7 +749,7 @@ static AstTyped* parse_expression(OnyxParser* parser) {
                 bin_op = make_node(AstBinaryOp, Ast_Kind_Pipe);
 
             } else if (bin_op_kind == Binary_Op_Range) {
-                bin_op = make_node(AstBinaryOp, Ast_Kind_Range);
+                bin_op = (AstBinaryOp *) make_node(AstRangeLiteral, Ast_Kind_Range_Literal);
 
             } else {
                 bin_op = make_node(AstBinaryOp, Ast_Kind_Binary_Op);
index 0e7fe68c4e1f59e7cc58109438655c7c508a351a..fba688fa27de66678a1cc36627379c2852357945 100644 (file)
@@ -435,9 +435,9 @@ static void symres_expression(AstTyped** expr) {
         case Ast_Kind_Size_Of:      symres_size_of((AstSizeOf *)*expr); break;
         case Ast_Kind_Align_Of:     symres_align_of((AstAlignOf *)*expr); break;
 
-        case Ast_Kind_Range:
-            symres_expression(&((AstBinaryOp *)(*expr))->left);
-            symres_expression(&((AstBinaryOp *)(*expr))->right);
+        case Ast_Kind_Range_Literal:
+            symres_expression(&((AstRangeLiteral *)(*expr))->low);
+            symres_expression(&((AstRangeLiteral *)(*expr))->high);
 
             (*expr)->type_node = symres_type(builtin_range_type);
 
index 3ae39b74cc53153376d3f251a50885735470f008..9374d37289adaa1293e0c44fa6cb245e540c2aac 100644 (file)
@@ -391,6 +391,7 @@ EMIT_FUNC(struct_lval,                   AstTyped* lval);
 EMIT_FUNC(struct_store,                  Type* type, u64 offset);
 EMIT_FUNC(struct_literal,                AstStructLiteral* sl);
 EMIT_FUNC(array_literal,                 AstArrayLiteral* al);
+EMIT_FUNC(range_literal,                 AstRangeLiteral* range);
 EMIT_FUNC(expression,                    AstTyped* expr);
 EMIT_FUNC(cast,                          AstUnaryOp* cast);
 EMIT_FUNC(return,                        AstReturn* ret);
@@ -2130,6 +2131,16 @@ EMIT_FUNC(array_literal, AstArrayLiteral* al) {
     *pcode = code;
 }
 
+EMIT_FUNC(range_literal, AstRangeLiteral* range) {
+    bh_arr(WasmInstruction) code = *pcode;
+
+    emit_expression(mod, &code, range->low);
+    emit_expression(mod, &code, range->high);
+    emit_expression(mod, &code, range->step);
+
+    *pcode = code;
+}
+
 EMIT_FUNC(location, AstTyped* expr) {
     bh_arr(WasmInstruction) code = *pcode;
 
@@ -2292,6 +2303,11 @@ EMIT_FUNC(expression, AstTyped* expr) {
             break;
         }
 
+        case Ast_Kind_Range_Literal: {
+            emit_range_literal(mod, &code, (AstRangeLiteral *) expr);
+            break;
+        }
+
         case Ast_Kind_Function: {
             i32 elemidx = get_element_idx(mod, (AstFunction *) expr);
             WID(WI_I32_CONST, elemidx);