Commit 65a51b401c

Andrew Kelley <superjoe30@gmail.com>
2018-02-20 22:42:14
add promise type
See #727
1 parent a06f3c7
src/all_types.hpp
@@ -1096,6 +1096,11 @@ struct TypeTableEntryBoundFn {
     TypeTableEntry *fn_type;
 };
 
+struct TypeTableEntryPromise {
+    // null if `promise` instead of `promise->T`
+    TypeTableEntry *result_type;
+};
+
 enum TypeTableEntryId {
     TypeTableEntryIdInvalid,
     TypeTableEntryIdVar,
@@ -1123,6 +1128,7 @@ enum TypeTableEntryId {
     TypeTableEntryIdBoundFn,
     TypeTableEntryIdArgTuple,
     TypeTableEntryIdOpaque,
+    TypeTableEntryIdPromise,
 };
 
 struct TypeTableEntry {
@@ -1149,11 +1155,13 @@ struct TypeTableEntry {
         TypeTableEntryUnion unionation;
         TypeTableEntryFn fn;
         TypeTableEntryBoundFn bound_fn;
+        TypeTableEntryPromise promise;
     } data;
 
     // use these fields to make sure we don't duplicate type table entries for the same type
     TypeTableEntry *pointer_parent[2]; // [0 - mut, 1 - const]
     TypeTableEntry *maybe_parent;
+    TypeTableEntry *promise_parent;
     // If we generate a constant name value for this type, we memoize it here.
     // The type of this is array
     ConstExprValue *cached_const_name_val;
src/analyze.cpp
@@ -230,6 +230,7 @@ bool type_is_complete(TypeTableEntry *type_entry) {
         case TypeTableEntryIdBlock:
         case TypeTableEntryIdBoundFn:
         case TypeTableEntryIdArgTuple:
+        case TypeTableEntryIdPromise:
             return true;
     }
     zig_unreachable();
@@ -267,6 +268,7 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) {
         case TypeTableEntryIdBoundFn:
         case TypeTableEntryIdArgTuple:
         case TypeTableEntryIdOpaque:
+        case TypeTableEntryIdPromise:
             return true;
     }
     zig_unreachable();
@@ -339,6 +341,32 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
     return get_int_type(g, false, bits_needed_for_unsigned(x));
 }
 
+TypeTableEntry *get_promise_type(CodeGen *g, TypeTableEntry *result_type) {
+    if (result_type != nullptr && result_type->promise_parent != nullptr) {
+        return result_type->promise_parent;
+    } else if (result_type == nullptr && g->builtin_types.entry_promise != nullptr) {
+        return g->builtin_types.entry_promise;
+    }
+
+    TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false);
+    TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPromise);
+    entry->type_ref = u8_ptr_type->type_ref;
+    entry->zero_bits = false;
+    entry->data.promise.result_type = result_type;
+    buf_init_from_str(&entry->name, "promise");
+    if (result_type != nullptr) {
+        buf_appendf(&entry->name, "->%s", buf_ptr(&result_type->name));
+    }
+    entry->di_type = u8_ptr_type->di_type;
+
+    if (result_type != nullptr) {
+        result_type->promise_parent = entry;
+    } else if (result_type == nullptr) {
+        g->builtin_types.entry_promise = entry;
+    }
+    return entry;
+}
+
 TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const,
         bool is_volatile, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count)
 {
@@ -1203,6 +1231,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
         case TypeTableEntryIdBoundFn:
         case TypeTableEntryIdArgTuple:
         case TypeTableEntryIdOpaque:
+        case TypeTableEntryIdPromise:
             return false;
         case TypeTableEntryIdVoid:
         case TypeTableEntryIdBool:
@@ -1243,6 +1272,7 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
         case TypeTableEntryIdBlock:
         case TypeTableEntryIdBoundFn:
         case TypeTableEntryIdArgTuple:
+        case TypeTableEntryIdPromise:
             return false;
         case TypeTableEntryIdOpaque:
         case TypeTableEntryIdUnreachable:
@@ -1383,7 +1413,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
             case TypeTableEntryIdBoundFn:
             case TypeTableEntryIdMetaType:
                 add_node_error(g, param_node->data.param_decl.type,
-                    buf_sprintf("parameter of type '%s' must be declared inline",
+                    buf_sprintf("parameter of type '%s' must be declared comptime",
                     buf_ptr(&type_entry->name)));
                 return g->builtin_types.entry_invalid;
             case TypeTableEntryIdVoid:
@@ -1399,6 +1429,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
             case TypeTableEntryIdEnum:
             case TypeTableEntryIdUnion:
             case TypeTableEntryIdFn:
+            case TypeTableEntryIdPromise:
                 ensure_complete_type(g, type_entry);
                 if (fn_type_id.cc == CallingConventionUnspecified && !type_is_copyable(g, type_entry)) {
                     add_node_error(g, param_node->data.param_decl.type,
@@ -1480,6 +1511,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
         case TypeTableEntryIdEnum:
         case TypeTableEntryIdUnion:
         case TypeTableEntryIdFn:
+        case TypeTableEntryIdPromise:
             break;
     }
 
@@ -3175,6 +3207,7 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt
         case TypeTableEntryIdUnion:
         case TypeTableEntryIdFn:
         case TypeTableEntryIdBoundFn:
+        case TypeTableEntryIdPromise:
             return type_entry;
     }
     zig_unreachable();
@@ -3553,6 +3586,7 @@ static bool is_container(TypeTableEntry *type_entry) {
         case TypeTableEntryIdBoundFn:
         case TypeTableEntryIdArgTuple:
         case TypeTableEntryIdOpaque:
+        case TypeTableEntryIdPromise:
             return false;
     }
     zig_unreachable();
@@ -3603,6 +3637,7 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
         case TypeTableEntryIdVar:
         case TypeTableEntryIdArgTuple:
         case TypeTableEntryIdOpaque:
+        case TypeTableEntryIdPromise:
             zig_unreachable();
     }
 }
@@ -4095,6 +4130,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
         case TypeTableEntryIdErrorSet:
         case TypeTableEntryIdFn:
         case TypeTableEntryIdEnum:
+        case TypeTableEntryIdPromise:
              return false;
         case TypeTableEntryIdArray:
         case TypeTableEntryIdStruct:
@@ -4342,6 +4378,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
                 }
                 zig_unreachable();
             }
+        case TypeTableEntryIdPromise:
+            // TODO better hashing algorithm
+            return 223048345;
         case TypeTableEntryIdUndefLit:
             return 162837799;
         case TypeTableEntryIdNullLit:
@@ -4501,6 +4540,7 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
         case TypeTableEntryIdPointer:
         case TypeTableEntryIdVoid:
         case TypeTableEntryIdUnreachable:
+        case TypeTableEntryIdPromise:
             return false;
     }
     zig_unreachable();
@@ -4970,6 +5010,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
         case TypeTableEntryIdInvalid:
         case TypeTableEntryIdUnreachable:
         case TypeTableEntryIdVar:
+        case TypeTableEntryIdPromise:
             zig_unreachable();
     }
     zig_unreachable();
@@ -5244,6 +5285,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
                 buf_appendf(buf, "(args value)");
                 return;
             }
+        case TypeTableEntryIdPromise:
+            zig_unreachable();
     }
     zig_unreachable();
 }
@@ -5305,6 +5348,7 @@ uint32_t type_id_hash(TypeId x) {
         case TypeTableEntryIdBlock:
         case TypeTableEntryIdBoundFn:
         case TypeTableEntryIdArgTuple:
+        case TypeTableEntryIdPromise:
             zig_unreachable();
         case TypeTableEntryIdErrorUnion:
             return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type);
@@ -5342,6 +5386,7 @@ bool type_id_eql(TypeId a, TypeId b) {
         case TypeTableEntryIdUndefLit:
         case TypeTableEntryIdNullLit:
         case TypeTableEntryIdMaybe:
+        case TypeTableEntryIdPromise:
         case TypeTableEntryIdErrorSet:
         case TypeTableEntryIdEnum:
         case TypeTableEntryIdUnion:
@@ -5469,6 +5514,7 @@ static const TypeTableEntryId all_type_ids[] = {
     TypeTableEntryIdBoundFn,
     TypeTableEntryIdArgTuple,
     TypeTableEntryIdOpaque,
+    TypeTableEntryIdPromise,
 };
 
 TypeTableEntryId type_id_at_index(size_t index) {
@@ -5533,6 +5579,8 @@ size_t type_id_index(TypeTableEntryId id) {
             return 22;
         case TypeTableEntryIdOpaque:
             return 23;
+        case TypeTableEntryIdPromise:
+            return 24;
     }
     zig_unreachable();
 }
@@ -5590,6 +5638,8 @@ const char *type_id_name(TypeTableEntryId id) {
             return "ArgTuple";
         case TypeTableEntryIdOpaque:
             return "Opaque";
+        case TypeTableEntryIdPromise:
+            return "Promise";
     }
     zig_unreachable();
 }
src/analyze.hpp
@@ -35,6 +35,7 @@ TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry);
 TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name);
 TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[],
         TypeTableEntry *field_types[], size_t field_count);
+TypeTableEntry *get_promise_type(CodeGen *g, TypeTableEntry *result_type);
 TypeTableEntry *get_test_fn_type(CodeGen *g);
 bool handle_is_ptr(TypeTableEntry *type_entry);
 void find_libc_include_path(CodeGen *g);
src/codegen.cpp
@@ -4017,6 +4017,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
         case TypeTableEntryIdPointer:
         case TypeTableEntryIdFn:
         case TypeTableEntryIdMaybe:
+        case TypeTableEntryIdPromise:
             {
                 LLVMValueRef ptr_val = gen_const_val(g, const_val, "");
                 LLVMValueRef ptr_size_int_val = LLVMConstPtrToInt(ptr_val, g->builtin_types.entry_usize->type_ref);
@@ -4434,6 +4435,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
         case TypeTableEntryIdVar:
         case TypeTableEntryIdArgTuple:
         case TypeTableEntryIdOpaque:
+        case TypeTableEntryIdPromise:
             zig_unreachable();
 
     }
@@ -5280,13 +5282,7 @@ static void define_builtin_types(CodeGen *g) {
         g->primitive_type_table.put(&entry->name, entry);
     }
     {
-        TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false);
-        TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid);
-        entry->type_ref = u8_ptr_type->type_ref;
-        entry->zero_bits = false;
-        buf_init_from_str(&entry->name, "promise");
-        entry->di_type = u8_ptr_type->di_type;
-        g->builtin_types.entry_promise = entry;
+        TypeTableEntry *entry = get_promise_type(g, nullptr);
         g->primitive_type_table.put(&entry->name, entry);
     }
 
@@ -5916,6 +5912,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry
         case TypeTableEntryIdArgTuple:
         case TypeTableEntryIdErrorUnion:
         case TypeTableEntryIdErrorSet:
+        case TypeTableEntryIdPromise:
             zig_unreachable();
         case TypeTableEntryIdVoid:
         case TypeTableEntryIdUnreachable:
@@ -6102,6 +6099,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
         case TypeTableEntryIdNullLit:
         case TypeTableEntryIdVar:
         case TypeTableEntryIdArgTuple:
+        case TypeTableEntryIdPromise:
             zig_unreachable();
     }
 }
@@ -6262,6 +6260,7 @@ static void gen_h_file(CodeGen *g) {
             case TypeTableEntryIdArgTuple:
             case TypeTableEntryIdMaybe:
             case TypeTableEntryIdFn:
+            case TypeTableEntryIdPromise:
                 zig_unreachable();
             case TypeTableEntryIdEnum:
                 assert(type_entry->data.enumeration.layout == ContainerLayoutExtern);
src/ir.cpp
@@ -9589,6 +9589,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
         case TypeTableEntryIdBlock:
         case TypeTableEntryIdBoundFn:
         case TypeTableEntryIdArgTuple:
+        case TypeTableEntryIdPromise:
             if (!is_equality_cmp) {
                 ir_add_error_node(ira, source_node,
                     buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
@@ -10418,6 +10419,7 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) {
         case TypeTableEntryIdVoid:
         case TypeTableEntryIdErrorSet:
         case TypeTableEntryIdFn:
+        case TypeTableEntryIdPromise:
             return VarClassRequiredAny;
         case TypeTableEntryIdNumLitFloat:
         case TypeTableEntryIdNumLitInt:
@@ -10688,6 +10690,7 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi
                 case TypeTableEntryIdBoundFn:
                 case TypeTableEntryIdArgTuple:
                 case TypeTableEntryIdOpaque:
+                case TypeTableEntryIdPromise:
                     ir_add_error(ira, target,
                         buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name)));
                     break;
@@ -10712,6 +10715,7 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi
         case TypeTableEntryIdBoundFn:
         case TypeTableEntryIdArgTuple:
         case TypeTableEntryIdOpaque:
+        case TypeTableEntryIdPromise:
             ir_add_error(ira, target,
                     buf_sprintf("invalid export target type '%s'", buf_ptr(&target->value.type->name)));
             break;
@@ -11481,6 +11485,7 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op
         case TypeTableEntryIdBlock:
         case TypeTableEntryIdBoundFn:
         case TypeTableEntryIdArgTuple:
+        case TypeTableEntryIdPromise:
             {
                 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
                 out_val->data.x_type = get_maybe_type(ira->codegen, type_entry);
@@ -12710,6 +12715,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi
         case TypeTableEntryIdFn:
         case TypeTableEntryIdArgTuple:
         case TypeTableEntryIdOpaque:
+        case TypeTableEntryIdPromise:
             {
                 ConstExprValue *out_val = ir_build_const_from(ira, &typeof_instruction->base);
                 out_val->data.x_type = type_entry;
@@ -12977,6 +12983,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
         case TypeTableEntryIdFn:
         case TypeTableEntryIdNamespace:
         case TypeTableEntryIdBoundFn:
+        case TypeTableEntryIdPromise:
             {
                 type_ensure_zero_bits_known(ira->codegen, child_type);
                 TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
@@ -13085,6 +13092,7 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
         case TypeTableEntryIdFn:
         case TypeTableEntryIdNamespace:
         case TypeTableEntryIdBoundFn:
+        case TypeTableEntryIdPromise:
             {
                 TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size);
                 ConstExprValue *out_val = ir_build_const_from(ira, &array_type_instruction->base);
@@ -13136,6 +13144,7 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
         case TypeTableEntryIdEnum:
         case TypeTableEntryIdUnion:
         case TypeTableEntryIdFn:
+        case TypeTableEntryIdPromise:
             {
                 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
                 ConstExprValue *out_val = ir_build_const_from(ira, &size_of_instruction->base);
@@ -13465,6 +13474,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
         case TypeTableEntryIdNumLitFloat:
         case TypeTableEntryIdNumLitInt:
         case TypeTableEntryIdPointer:
+        case TypeTableEntryIdPromise:
         case TypeTableEntryIdFn:
         case TypeTableEntryIdNamespace:
         case TypeTableEntryIdErrorSet:
@@ -14053,6 +14063,7 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_
         case TypeTableEntryIdMetaType:
         case TypeTableEntryIdUnreachable:
         case TypeTableEntryIdPointer:
+        case TypeTableEntryIdPromise:
         case TypeTableEntryIdArray:
         case TypeTableEntryIdStruct:
         case TypeTableEntryIdNumLitFloat:
@@ -15313,6 +15324,7 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc
         case TypeTableEntryIdInt:
         case TypeTableEntryIdFloat:
         case TypeTableEntryIdPointer:
+        case TypeTableEntryIdPromise:
         case TypeTableEntryIdArray:
         case TypeTableEntryIdStruct:
         case TypeTableEntryIdMaybe:
@@ -16008,6 +16020,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
         case TypeTableEntryIdNumLitInt:
         case TypeTableEntryIdUndefLit:
         case TypeTableEntryIdNullLit:
+        case TypeTableEntryIdPromise:
             zig_unreachable();
         case TypeTableEntryIdVoid:
             return;
@@ -16075,6 +16088,7 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
         case TypeTableEntryIdNumLitInt:
         case TypeTableEntryIdUndefLit:
         case TypeTableEntryIdNullLit:
+        case TypeTableEntryIdPromise:
             zig_unreachable();
         case TypeTableEntryIdVoid:
             return;