added fully anonymous struct literals
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 25 May 2022 22:18:30 +0000 (17:18 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 25 May 2022 22:18:30 +0000 (17:18 -0500)
include/types.h
src/astnodes.c
src/checker.c
src/types.c
src/wasm_type_table.h
tests/no_types [new file with mode: 0644]
tests/no_types.onyx [new file with mode: 0644]

index 9ed77e5343e92b81e2b770df135e64c572242f15..5c2b5e69784d0e461da849fde23471e1c74a2c64 100644 (file)
@@ -188,6 +188,7 @@ extern Type basic_types[];
 struct AstType;
 struct AstFunction;
 struct AstCompound;
+struct AstStructLiteral;
 
 void types_init();
 void types_dump_type_info();
@@ -196,6 +197,7 @@ b32 types_are_compatible(Type* t1, Type* t2);
 u32 type_size_of(Type* type);
 u32 type_alignment_of(Type* type);
 Type* type_build_from_ast(bh_allocator alloc, struct AstType* type_node);
+Type* type_build_implicit_type_of_struct_literal(bh_allocator alloc, struct AstStructLiteral* lit);
 
 Type* type_build_function_type(bh_allocator alloc, struct AstFunction* func);
 Type* type_build_compound_type(bh_allocator alloc, struct AstCompound* compound);
index a2068921a64a05957c7f579eb48522c4b0edfa0e..9fa20585115024d4c86c62b5d6df1cf9189336f1 100644 (file)
@@ -854,6 +854,26 @@ Type* resolve_expression_type(AstTyped* node) {
         }
     }
 
+    if (node->kind == Ast_Kind_Struct_Literal && node->type == NULL) {
+        AstStructLiteral* sl = (AstStructLiteral *) node;
+        assert(sl->stnode == NULL);
+        assert(sl->type_node == NULL);
+
+        // If values without names are given to a struct literal without
+        // a type, then we cannot implicitly build the type of the struct
+        // literal, as the name of every member cannot be known. Maybe we
+        // could implicitly do something like _1, _2, ... for the members
+        // that we not given names?
+        if (bh_arr_length(sl->args.values) > 0) {
+            return NULL;
+        }
+
+        sl->type = type_build_implicit_type_of_struct_literal(context.ast_alloc, sl);
+        if (sl->type) {
+            add_entities_for_node(NULL, (AstNode *) sl, NULL, NULL);
+        }
+    }
+
     // If polymorphic procedures HAVE to have a type, most likely
     // because they are part of a `typeof` expression, they are
     // assigned a void type. This is cleared before the procedure
@@ -1348,4 +1368,4 @@ AstPolyCallType* convert_call_to_polycall(AstCall* call) {
     }
 
     return pct;
-}
\ No newline at end of file
+}
index b170e5341102df091c2951b4d8d6dbf032c4c01e..ef038ecdae34a0b94ceb63ff0cd21aab7d870f22 100644 (file)
@@ -1202,12 +1202,17 @@ CheckStatus check_unaryop(AstUnaryOp** punop) {
 }
 
 CheckStatus check_struct_literal(AstStructLiteral* sl) {
+
     if (sl->type == NULL) {
         // NOTE: This is used for automatically typed struct literals. If there is no provided
         // type for the struct literal, assume that it is passes successfully. When it is used
         // elsewhere, it will be added as an expression entity that will be processed once the
         // stnode is filled out.
-        if (sl->stnode == NULL) return Check_Success;
+        if (sl->stnode == NULL) {
+            CHECK(arguments, &sl->args);
+
+            return Check_Success;
+        }
 
         CHECK(expression, &sl->stnode);
         if (!node_is_type((AstNode *) sl->stnode)) {
@@ -1288,12 +1293,8 @@ CheckStatus check_struct_literal(AstStructLiteral* sl) {
         Type* formal = smem.type;
 
         CHECK(expression, actual);
-
-        // HACK HACK HACK
-        if ((*actual)->type == NULL &&
-            (*actual)->entity != NULL &&
-            (*actual)->entity->state <= Entity_State_Check_Types) {
-            YIELD_((*actual)->token->pos, "Trying to resolve type of expression for member '%s'.", smem.name);
+        if ((*actual)->type == NULL && (*actual)->entity != NULL && (*actual)->entity->state <= Entity_State_Check_Types) {
+            YIELD((*actual)->token->pos, "Trying to resolve type of expression for member.");
         }
 
         TYPE_CHECK(actual, formal) {
index ec750c46058b8a96de0bbeb34958b085ed74d979..50d592929dc58145f9b835edeb4f6838bb9c425b 100644 (file)
@@ -697,6 +697,80 @@ Type* type_build_compound_type(bh_allocator alloc, AstCompound* compound) {
     return comp_type;
 }
 
+Type* type_build_implicit_type_of_struct_literal(bh_allocator alloc, AstStructLiteral* lit) {
+    Type* type = type_create(Type_Kind_Struct, alloc, 0);
+    type->ast_type = NULL;
+    type->Struct.name = NULL;
+    type->Struct.mem_count = bh_arr_length(lit->args.named_values);
+    type->Struct.meta_tags = NULL;
+    type->Struct.constructed_from = NULL;
+    type->Struct.status = SPS_Start;
+    type->Struct.poly_sln = NULL;
+    type_register(type);
+
+    type->Struct.memarr = NULL;
+    sh_new_arena(type->Struct.members);
+    bh_arr_new(global_heap_allocator, type->Struct.memarr, type->Struct.mem_count);
+
+    u32 size = 0;
+    u32 offset = 0;
+    u32 alignment = 1;
+    u32 idx = 0;
+    bh_arr_each(AstNamedValue *, pnv, lit->args.named_values) {
+        AstNamedValue *nv = *pnv;
+
+        Type* member_type = resolve_expression_type(nv->value);
+        if (member_type == NULL) {
+            return NULL;
+        }
+
+        u32 mem_alignment = type_alignment_of(member_type);
+        if (mem_alignment <= 0) {
+            return NULL;
+        }
+
+        alignment = bh_max(alignment, mem_alignment);
+        
+        // Should these structs be packed or not?
+        bh_align(offset, mem_alignment);
+
+        token_toggle_end(nv->token);
+        if (shgeti(type->Struct.members, nv->token->text) != -1) {
+            token_toggle_end(nv->token);
+            return NULL;
+        }
+
+        StructMember *smem = bh_alloc_item(alloc, StructMember);
+        smem->offset = offset;
+        smem->type = member_type;
+        smem->idx = idx;
+        smem->name = bh_strdup(alloc, nv->token->text);
+        smem->token = nv->token;
+        smem->initial_value = &nv->value;
+        smem->meta_tags = NULL;
+        smem->included_through_use = 0;
+        smem->used = 0;
+        smem->use_through_pointer_index = -1;
+        shput(type->Struct.members, nv->token->text, smem);
+        bh_arr_push(type->Struct.memarr, smem);
+        token_toggle_end(nv->token);
+
+        u32 type_size = type_size_of(member_type);
+        offset += type_size;
+        size = offset;
+        idx++;
+    }
+
+    type->Struct.alignment = alignment;
+    type->Struct.size = size;
+    type->Struct.linear_members = NULL;
+    bh_arr_new(global_heap_allocator, type->Struct.linear_members, type->Struct.mem_count);
+    build_linear_types_with_offset(type, &type->Struct.linear_members, 0);
+
+    type->Struct.status = SPS_Uses_Done;
+    return type;
+}
+
 Type* type_make_pointer(bh_allocator alloc, Type* to) {
     if (to == NULL) return NULL;
     if (to == (Type *) &node_that_signals_failure) return to;
index d92537d7de7b6a2ffd0ab16ca7f24f0ee0821a4b..6ce7112a5e314410fc8a159d3366a83da459f735 100644 (file)
@@ -380,7 +380,7 @@ static u64 build_type_table(OnyxWasmModule* module) {
                 // Struct methods
                 bh_arr(StructMethodData) method_data=NULL;
                 AstType *ast_type = type->ast_type;
-                if (ast_type->kind == Ast_Kind_Struct_Type) {
+                if (ast_type && ast_type->kind == Ast_Kind_Struct_Type) {
                     AstStructType *struct_type  = (AstStructType *) ast_type;
                     Scope*         struct_scope = struct_type->scope;
 
diff --git a/tests/no_types b/tests/no_types
new file mode 100644 (file)
index 0000000..8c64808
--- /dev/null
@@ -0,0 +1,40 @@
+{ x = 0.0990, y = 0.0950, vx = 9.8000, vy = 9.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 0.1959, y = 0.1799, vx = 9.6000, vy = 8.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 0.2910, y = 0.2549, vx = 9.4000, vy = 7.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 0.3840, y = 0.3200, vx = 9.2000, vy = 6.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 0.4750, y = 0.3750, vx = 9.0000, vy = 5.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 0.5640, y = 0.4200, vx = 8.8000, vy = 4.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 0.6510, y = 0.4549, vx = 8.6000, vy = 3.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 0.7360, y = 0.4799, vx = 8.4000, vy = 2.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 0.8190, y = 0.4950, vx = 8.2000, vy = 1.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 0.9000, y = 0.5000, vx = 8.0000, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 0.9790, y = 0.4950, vx = 7.8000, vy = -1.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.0560, y = 0.4799, vx = 7.6000, vy = -2.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.1310, y = 0.4549, vx = 7.4000, vy = -3.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.2040, y = 0.4200, vx = 7.2000, vy = -4.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.2750, y = 0.3750, vx = 7.0000, vy = -5.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.3440, y = 0.3200, vx = 6.8000, vy = -6.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.4110, y = 0.2549, vx = 6.6000, vy = -7.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.4760, y = 0.1799, vx = 6.4000, vy = -8.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5390, y = 0.0949, vx = 6.2000, vy = -9.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.6000, y = 0.0000, vx = 0.3000, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.6020, y = 0.0000, vx = 0.0050, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.6010, y = 0.0000, vx = -0.0097, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5999, y = 0.0000, vx = -0.0104, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5988, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5977, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5966, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5955, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5944, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5933, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5922, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5911, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5900, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5889, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5877, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5866, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5855, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5844, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5833, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5822, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
+{ x = 1.5811, y = 0.0000, vx = -0.0105, vy = 0.0000, ax = -20.0000, ay = -100.0000 }
diff --git a/tests/no_types.onyx b/tests/no_types.onyx
new file mode 100644 (file)
index 0000000..4bc7058
--- /dev/null
@@ -0,0 +1,33 @@
+//
+// No types are written throughout this entire program.
+//
+
+#load "core/std"
+
+use core
+
+main :: () {
+    object := .{
+        x  = 0.0,    y = 0.0,
+        vx = 10.0,  vy = 10.0,
+        ax = -20.0, ay = -100.0
+    };
+
+    for 40 {
+        step_physics(^object, 0.01);
+        printf("{}\n", object);
+    }
+}
+
+step_physics :: (obj, dt) => {
+    obj.x += 0.5 * obj.ax * dt * dt + obj.vx * dt;
+    obj.y += 0.5 * obj.ay * dt * dt + obj.vy * dt;
+    obj.vx += obj.ax * dt;
+    obj.vy += obj.ay * dt;
+
+    if obj.y < 0 {
+        obj.y = 0;
+        obj.vy = 0;
+        obj.vx *= 0.05;
+    }
+}