Commit 8205253b2b

Andrew Kelley <superjoe30@gmail.com>
2016-01-16 04:01:49
support array literals
1 parent 8bc3fae
Changed files (3)
src/analyze.cpp
@@ -233,8 +233,7 @@ static TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
     }
 }
 
-static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import,
-        TypeTableEntry *child_type, uint64_t array_size)
+static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size)
 {
     auto existing_entry = child_type->arrays_by_size.maybe_get(array_size);
     if (existing_entry) {
@@ -1389,6 +1388,29 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
             }
         }
         return container_type;
+    } else if (container_type->id == TypeTableEntryIdStruct &&
+               container_type->data.structure.is_unknown_size_array &&
+               kind == ContainerInitKindArray)
+    {
+        int elem_count = container_init_expr->entries.length;
+
+        TypeTableEntry *pointer_type = container_type->data.structure.fields[0].type_entry;
+        assert(pointer_type->id == TypeTableEntryIdPointer);
+        TypeTableEntry *child_type = pointer_type->data.pointer.child_type;
+
+        for (int i = 0; i < elem_count; i += 1) {
+            AstNode *elem_node = container_init_expr->entries.at(i);
+            analyze_expression(g, import, context, child_type, elem_node);
+        }
+
+        TypeTableEntry *fixed_size_array_type = get_array_type(g, child_type, elem_count);
+
+        StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
+        codegen->type_entry = fixed_size_array_type;
+        codegen->source_node = node;
+        context->struct_val_expr_alloca_list.append(codegen);
+
+        return fixed_size_array_type;
     } else if (container_type->id == TypeTableEntryIdArray) {
         zig_panic("TODO array container init");
         return container_type;
@@ -2151,7 +2173,7 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,
         ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
         if (const_val->ok) {
             return resolve_expr_const_val_as_type(g, node,
-                    get_array_type(g, import, child_type, const_val->data.x_uint));
+                    get_array_type(g, child_type, const_val->data.x_uint));
         } else {
             add_node_error(g, size_node, buf_create_from_str("unable to resolve constant expression"));
             return g->builtin_types.entry_invalid;
@@ -2986,7 +3008,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
             if (node->data.string_literal.c) {
                 return_type = g->builtin_types.entry_c_string_literal;
             } else {
-                return_type = get_array_type(g, import, g->builtin_types.entry_u8,
+                return_type = get_array_type(g, g->builtin_types.entry_u8,
                         buf_len(&node->data.string_literal.buf));
             }
             break;
src/codegen.cpp
@@ -1132,7 +1132,8 @@ static LLVMValueRef gen_struct_memcpy(CodeGen *g, AstNode *source_node, LLVMValu
 {
     assert(type_entry->id == TypeTableEntryIdStruct ||
             type_entry->id == TypeTableEntryIdMaybe ||
-            (type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0));
+            (type_entry->id == TypeTableEntryIdEnum && type_entry->data.enumeration.gen_field_count != 0) ||
+            type_entry->id == TypeTableEntryIdArray);
 
     LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
 
@@ -1157,11 +1158,9 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
 {
     if (op1_type->id == TypeTableEntryIdStruct ||
         (op1_type->id == TypeTableEntryIdEnum && op1_type->data.enumeration.gen_field_count != 0) ||
-        op1_type->id == TypeTableEntryIdMaybe)
+        op1_type->id == TypeTableEntryIdMaybe ||
+        op1_type->id == TypeTableEntryIdArray)
     {
-        assert(op2_type->id == TypeTableEntryIdStruct ||
-                (op2_type->id == TypeTableEntryIdEnum && op2_type->data.enumeration.gen_field_count != 0) ||
-                op2_type->id == TypeTableEntryIdMaybe);
         assert(op1_type == op2_type);
         assert(bin_op == BinOpTypeAssign);
 
@@ -1633,6 +1632,27 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
     } else if (type_entry->id == TypeTableEntryIdVoid) {
         assert(node->data.container_init_expr.entries.length == 0);
         return nullptr;
+    } else if (type_entry->id == TypeTableEntryIdArray) {
+        StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr;
+        LLVMValueRef tmp_array_ptr = struct_val_expr_node->ptr;
+
+        int field_count = type_entry->data.array.len;
+        assert(field_count == node->data.container_init_expr.entries.length);
+
+        for (int i = 0; i < field_count; i += 1) {
+            AstNode *field_node = node->data.container_init_expr.entries.at(i);
+            LLVMValueRef elem_val = gen_expr(g, field_node);
+
+            LLVMValueRef indices[] = {
+                LLVMConstNull(g->builtin_types.entry_usize->type_ref),
+                LLVMConstInt(g->builtin_types.entry_usize->type_ref, i, false),
+            };
+            add_debug_source_node(g, field_node);
+            LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, "");
+            LLVMBuildStore(g->builder, elem_val, elem_ptr);
+        }
+
+        return tmp_array_ptr;
     } else {
         zig_unreachable();
     }
test/run_tests.cpp
@@ -1102,6 +1102,25 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
     return 0;
 }
     )SOURCE", "OK\n");
+
+    add_simple_case("array literal", R"SOURCE(
+import "std.zig";
+
+pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
+    const HEX_MULT = []u16{4096, 256, 16, 1};
+
+    if (HEX_MULT.len != 4) {
+        print_str("BAD\n");
+    }
+
+    if (HEX_MULT[1] != 256) {
+        print_str("BAD\n");
+    }
+
+    print_str("OK\n");
+    return 0;
+}
+    )SOURCE", "OK\n");
 }