Fix array type building not handling unary expressions for arrays; add test
authorJudah Caruso <judah@tuta.io>
Sun, 3 Dec 2023 22:49:29 +0000 (15:49 -0700)
committerJudah Caruso <judah@tuta.io>
Sun, 3 Dec 2023 22:49:29 +0000 (15:49 -0700)
.gitignore
compiler/src/astnodes.c
compiler/src/types.c
tests/bugs/array_lengths.onyx [new file with mode: 0644]

index 1fd5a472a432ca80fe14d54b817b79bc20e441e7..83b48b219d5b0460ca1093731856c880bac2f894 100644 (file)
@@ -1,4 +1,5 @@
 **/*.o
+**/*.DS_Store
 *.o
 tags
 *.wasm
index a8f12e1db5cdbf399a1c0f4378d018427f2b50f3..7665d68f140fb684c855474f2114146cbbb7fee2 100644 (file)
@@ -116,7 +116,7 @@ static const char* ast_node_names[] = {
 
     "FOREIGN BLOCK",
     "ZERO VALUE",
-    
+
     "AST_NODE_KIND_COUNT",
 };
 
@@ -138,7 +138,7 @@ const char *binaryop_string[Binary_Op_Count] = {
     "|>", "..", "->",
 
     "[]", "[]=", "^[]",
-    
+
     "??"
 };
 
@@ -772,7 +772,7 @@ TypeMatch unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
             return TYPE_MATCH_SUCCESS;
         }
     }
-    
+
     // String literals implicitly become c-strings for convience.
     if (node->kind == Ast_Kind_StrLit
         && type->kind == Type_Kind_MultiPointer
@@ -855,7 +855,7 @@ TypeMatch unify_node_and_type_(AstTyped** pnode, Type* type, b32 permanent) {
 
             return TYPE_MATCH_SUCCESS;
         }
-        
+
         if (match == TYPE_MATCH_YIELD) return TYPE_MATCH_YIELD;
     }
 
@@ -1223,6 +1223,10 @@ i64 get_expression_integer_value(AstTyped* node, b32 *is_valid) {
         return get_expression_integer_value(((AstEnumValue *) node)->value, is_valid);
     }
 
+    if (node->kind == Ast_Kind_Unary_Op && type_is_integer(node->type)) {
+        return get_expression_integer_value(((AstUnaryOp *) node)->expr, is_valid);
+    }
+
     if (node_is_type((AstNode*) node)) {
         Type* type = type_build_from_ast(context.ast_alloc, (AstType *) node);
         if (type) return type->id;
@@ -1489,27 +1493,27 @@ TypeMatch implicit_cast_to_bool(AstTyped **pnode) {
         *pnode = (AstTyped *) cmp;
         return TYPE_MATCH_SUCCESS;
     }
-    
+
     if (context.caches.implicit_cast_to_bool_cache.entries == NULL) {
         bh_imap_init(&context.caches.implicit_cast_to_bool_cache, global_heap_allocator, 8);
     }
 
     if (!bh_imap_has(&context.caches.implicit_cast_to_bool_cache, (u64) node)) {
         AstArgument *implicit_arg = make_argument(context.ast_alloc, node);
-        
+
         Arguments *args = bh_alloc_item(context.ast_alloc, Arguments);
         bh_arr_new(context.ast_alloc, args->values, 1);
         bh_arr_push(args->values, (AstTyped *) implicit_arg);
 
         bh_imap_put(&context.caches.implicit_cast_to_bool_cache, (u64) node, (u64) args);
     }
-    
+
     Arguments *args = (Arguments *) bh_imap_get(&context.caches.implicit_cast_to_bool_cache, (u64) node);
     AstFunction *overload = (AstFunction *) find_matching_overload_by_arguments(builtin_implicit_bool_cast->overloads, args);
 
     if (overload == NULL)                                       return TYPE_MATCH_FAILED;
     if (overload == (AstFunction *) &node_that_signals_a_yield) return TYPE_MATCH_YIELD;
-    
+
     AstCall *implicit_call = onyx_ast_node_new(context.ast_alloc, sizeof(AstCall), Ast_Kind_Call);
     implicit_call->token = node->token;
     implicit_call->callee = (AstTyped *) overload;
index 9ebd494e71ed0b9966e29a07ac77135d7723723a..7aceffb45546cf38621c335879ca653c43864f0a 100644 (file)
@@ -378,7 +378,19 @@ static Type* type_build_from_ast_inner(bh_allocator alloc, AstType* type_node, b
                     return NULL;
                 }
 
-                count = get_expression_integer_value(a_node->count_expr, NULL);
+                b32 valid = 0;
+                count = get_expression_integer_value(a_node->count_expr, &valid);
+
+                if (!valid) {
+                    onyx_report_error(a_node->token->pos, Error_Critical, "Array type size expression must be 'i32', got '%s'.",
+                        type_get_name(a_node->count_expr->type));
+                    return NULL;
+                }
+
+                if ((i32)count < 0) {
+                    onyx_report_error(a_node->token->pos, Error_Critical, "Array type size must be a positive integer.");
+                    return NULL;
+                }
             }
 
             Type* array_type = type_make_array(alloc, elem_type, count);
@@ -1129,7 +1141,7 @@ void build_linear_types_with_offset(Type* type, bh_arr(TypeWithOffset)* pdest, u
             build_linear_types_with_offset(type->Compound.types[i], pdest, offset + elem_offset);
             elem_offset += bh_max(type_size_of(type->Compound.types[i]), 4);
         }
-        
+
     } else if (type->kind == Type_Kind_Slice || type->kind == Type_Kind_VarArgs || type->kind == Type_Kind_Function) {
         u32 mem_count = type_structlike_mem_count(type);
         StructMember smem = { 0 };
diff --git a/tests/bugs/array_lengths.onyx b/tests/bugs/array_lengths.onyx
new file mode 100644 (file)
index 0000000..62c4e03
--- /dev/null
@@ -0,0 +1,29 @@
+#load "core/module"
+
+use core { * }
+
+An_Enum :: enum {
+   A;
+   B;
+   C;
+   D;
+
+   Count;
+}
+
+A_Struct :: struct {
+   a: i32;
+   b: i32;
+   c: i32;
+}
+
+main :: () {
+   arr1: [cast(i32)(3 * 4 - 5)]f32;
+   arr2: [cast(i32)An_Enum.Count]A_Struct;
+
+   assert(arr1.count == (3 * 4 - 5), "invalid count for arr1");
+   assert(sizeof(typeof(arr1)) == (3 * 4 - 5) * sizeof(f32), "invalid size for arr1");
+
+   assert(arr2.count == ~~An_Enum.Count, "invalid count for arr2");
+   assert(sizeof(typeof(arr2)) == ~~An_Enum.Count * sizeof(A_Struct), "invalid size for arr2");
+}