diff options
| -rw-r--r-- | src/all_types.hpp | 18 | ||||
| -rw-r--r-- | src/analyze.cpp | 154 | ||||
| -rw-r--r-- | src/analyze.hpp | 5 | ||||
| -rw-r--r-- | src/codegen.cpp | 14 | ||||
| -rw-r--r-- | src/ir.cpp | 113 | ||||
| -rw-r--r-- | src/ir_print.cpp | 17 | ||||
| -rw-r--r-- | std/build.zig | 18 | ||||
| -rw-r--r-- | std/fmt.zig | 33 | ||||
| -rw-r--r-- | std/math.zig | 39 | ||||
| -rw-r--r-- | test/cases/misc.zig | 55 |
10 files changed, 329 insertions, 137 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp index b2e6321398..aaf5c248ef 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1194,8 +1194,6 @@ enum BuiltinFnId { BuiltinFnIdIntType, BuiltinFnIdSetDebugSafety, BuiltinFnIdTypeName, - BuiltinFnIdIsInteger, - BuiltinFnIdIsFloat, BuiltinFnIdCanImplicitCast, BuiltinFnIdSetGlobalAlign, BuiltinFnIdSetGlobalSection, @@ -1207,6 +1205,7 @@ enum BuiltinFnId { BuiltinFnIdFieldParentPtr, BuiltinFnIdOffsetOf, BuiltinFnIdInlineCall, + BuiltinFnIdTypeId, }; struct BuiltinFnEntry { @@ -1775,7 +1774,6 @@ enum IrInstructionId { IrInstructionIdErrToInt, IrInstructionIdCheckSwitchProngs, IrInstructionIdCheckStatementIsVoid, - IrInstructionIdTestType, IrInstructionIdTypeName, IrInstructionIdCanImplicitCast, IrInstructionIdSetGlobalAlign, @@ -1786,6 +1784,7 @@ enum IrInstructionId { IrInstructionIdEnumTagName, IrInstructionIdFieldParentPtr, IrInstructionIdOffsetOf, + IrInstructionIdTypeId, }; struct IrInstruction { @@ -2464,13 +2463,6 @@ struct IrInstructionCheckStatementIsVoid { IrInstruction *statement_value; }; -struct IrInstructionTestType { - IrInstruction base; - - IrInstruction *type_value; - TypeTableEntryId type_id; -}; - struct IrInstructionTypeName { IrInstruction base; @@ -2540,6 +2532,12 @@ struct IrInstructionOffsetOf { IrInstruction *field_name; }; +struct IrInstructionTypeId { + IrInstruction base; + + IrInstruction *type_value; +}; + static const size_t slice_ptr_index = 0; static const size_t slice_len_index = 1; diff --git a/src/analyze.cpp b/src/analyze.cpp index 8c27e2268f..678e0471a6 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4340,3 +4340,157 @@ FnTableEntry *get_extern_panic_fn(CodeGen *g) { return g->extern_panic_fn; } +static const TypeTableEntryId all_type_ids[] = { + TypeTableEntryIdMetaType, + TypeTableEntryIdVoid, + TypeTableEntryIdBool, + TypeTableEntryIdUnreachable, + TypeTableEntryIdInt, + TypeTableEntryIdFloat, + TypeTableEntryIdPointer, + TypeTableEntryIdArray, + TypeTableEntryIdStruct, + TypeTableEntryIdNumLitFloat, + TypeTableEntryIdNumLitInt, + TypeTableEntryIdUndefLit, + TypeTableEntryIdNullLit, + TypeTableEntryIdMaybe, + TypeTableEntryIdErrorUnion, + TypeTableEntryIdPureError, + TypeTableEntryIdEnum, + TypeTableEntryIdEnumTag, + TypeTableEntryIdUnion, + TypeTableEntryIdFn, + TypeTableEntryIdNamespace, + TypeTableEntryIdBlock, + TypeTableEntryIdBoundFn, + TypeTableEntryIdArgTuple, + TypeTableEntryIdOpaque, +}; + +TypeTableEntryId type_id_at_index(size_t index) { + assert(index < array_length(all_type_ids)); + return all_type_ids[index]; +} + +size_t type_id_len() { + return array_length(all_type_ids); +} + +size_t type_id_index(TypeTableEntryId id) { + switch (id) { + case TypeTableEntryIdInvalid: + case TypeTableEntryIdVar: + zig_unreachable(); + case TypeTableEntryIdMetaType: + return 0; + case TypeTableEntryIdVoid: + return 1; + case TypeTableEntryIdBool: + return 2; + case TypeTableEntryIdUnreachable: + return 3; + case TypeTableEntryIdInt: + return 4; + case TypeTableEntryIdFloat: + return 5; + case TypeTableEntryIdPointer: + return 6; + case TypeTableEntryIdArray: + return 7; + case TypeTableEntryIdStruct: + return 8; + case TypeTableEntryIdNumLitFloat: + return 9; + case TypeTableEntryIdNumLitInt: + return 10; + case TypeTableEntryIdUndefLit: + return 11; + case TypeTableEntryIdNullLit: + return 12; + case TypeTableEntryIdMaybe: + return 13; + case TypeTableEntryIdErrorUnion: + return 14; + case TypeTableEntryIdPureError: + return 15; + case TypeTableEntryIdEnum: + return 16; + case TypeTableEntryIdEnumTag: + return 17; + case TypeTableEntryIdUnion: + return 18; + case TypeTableEntryIdFn: + return 19; + case TypeTableEntryIdNamespace: + return 20; + case TypeTableEntryIdBlock: + return 21; + case TypeTableEntryIdBoundFn: + return 22; + case TypeTableEntryIdArgTuple: + return 23; + case TypeTableEntryIdOpaque: + return 24; + } + zig_unreachable(); +} + +const char *type_id_name(TypeTableEntryId id) { + switch (id) { + case TypeTableEntryIdInvalid: + case TypeTableEntryIdVar: + zig_unreachable(); + case TypeTableEntryIdMetaType: + return "Type"; + case TypeTableEntryIdVoid: + return "Void"; + case TypeTableEntryIdBool: + return "Bool"; + case TypeTableEntryIdUnreachable: + return "NoReturn"; + case TypeTableEntryIdInt: + return "Int"; + case TypeTableEntryIdFloat: + return "Float"; + case TypeTableEntryIdPointer: + return "Pointer"; + case TypeTableEntryIdArray: + return "Array"; + case TypeTableEntryIdStruct: + return "Struct"; + case TypeTableEntryIdNumLitFloat: + return "FloatLiteral"; + case TypeTableEntryIdNumLitInt: + return "IntLiteral"; + case TypeTableEntryIdUndefLit: + return "UndefinedLiteral"; + case TypeTableEntryIdNullLit: + return "NullLiteral"; + case TypeTableEntryIdMaybe: + return "Nullable"; + case TypeTableEntryIdErrorUnion: + return "ErrorUnion"; + case TypeTableEntryIdPureError: + return "Error"; + case TypeTableEntryIdEnum: + return "Enum"; + case TypeTableEntryIdEnumTag: + return "EnumTag"; + case TypeTableEntryIdUnion: + return "Union"; + case TypeTableEntryIdFn: + return "Fn"; + case TypeTableEntryIdNamespace: + return "Namespace"; + case TypeTableEntryIdBlock: + return "Block"; + case TypeTableEntryIdBoundFn: + return "BoundFn"; + case TypeTableEntryIdArgTuple: + return "ArgTuple"; + case TypeTableEntryIdOpaque: + return "Opaque"; + } + zig_unreachable(); +} diff --git a/src/analyze.hpp b/src/analyze.hpp index 946fa09b2f..71ef787909 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -160,4 +160,9 @@ TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, Type void expand_undef_array(CodeGen *g, ConstExprValue *const_val); void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value); +const char *type_id_name(TypeTableEntryId id); +TypeTableEntryId type_id_at_index(size_t index); +size_t type_id_len(); +size_t type_id_index(TypeTableEntryId id); + #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index e4799d63f1..5e752d9a69 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3009,7 +3009,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdTestComptime: case IrInstructionIdCheckSwitchProngs: case IrInstructionIdCheckStatementIsVoid: - case IrInstructionIdTestType: case IrInstructionIdTypeName: case IrInstructionIdCanImplicitCast: case IrInstructionIdSetGlobalAlign: @@ -3018,6 +3017,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdDeclRef: case IrInstructionIdSwitchVar: case IrInstructionIdOffsetOf: + case IrInstructionIdTypeId: zig_unreachable(); case IrInstructionIdReturn: return ir_render_return(g, executable, (IrInstructionReturn *)instruction); @@ -4423,8 +4423,6 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdCImport, "cImport", 1); create_builtin_fn(g, BuiltinFnIdErrName, "errorName", 1); create_builtin_fn(g, BuiltinFnIdTypeName, "typeName", 1); - create_builtin_fn(g, BuiltinFnIdIsInteger, "isInteger", 1); - create_builtin_fn(g, BuiltinFnIdIsFloat, "isFloat", 1); create_builtin_fn(g, BuiltinFnIdCanImplicitCast, "canImplicitCast", 2); create_builtin_fn(g, BuiltinFnIdEmbedFile, "embedFile", 1); create_builtin_fn(g, BuiltinFnIdCmpExchange, "cmpxchg", 5); @@ -4449,6 +4447,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdRem, "rem", 2); create_builtin_fn(g, BuiltinFnIdMod, "mod", 2); create_builtin_fn(g, BuiltinFnIdInlineCall, "inlineCall", SIZE_MAX); + create_builtin_fn(g, BuiltinFnIdTypeId, "typeId", 1); } static const char *bool_to_str(bool b) { @@ -4580,6 +4579,15 @@ static void define_builtin_compile_vars(CodeGen *g) { " ReleaseFast,\n" "};\n\n"); } + { + buf_appendf(contents, "pub const TypeId = enum {\n"); + size_t field_count = type_id_len(); + for (size_t i = 0; i < field_count; i += 1) { + const TypeTableEntryId id = type_id_at_index(i); + buf_appendf(contents, " %s,\n", type_id_name(id)); + } + buf_appendf(contents, "};\n\n"); + } buf_appendf(contents, "pub const is_big_endian = %s;\n", bool_to_str(g->is_big_endian)); buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build)); buf_appendf(contents, "pub const os = Os.%s;\n", cur_os); diff --git a/src/ir.cpp b/src/ir.cpp index 53c3d1e241..3c14d808db 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -517,10 +517,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckStatementIs return IrInstructionIdCheckStatementIsVoid; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionTestType *) { - return IrInstructionIdTestType; -} - static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeName *) { return IrInstructionIdTypeName; } @@ -561,6 +557,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionOffsetOf *) { return IrInstructionIdOffsetOf; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeId *) { + return IrInstructionIdTypeId; +} + template<typename T> static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { T *special_instruction = allocate<T>(1); @@ -2027,19 +2027,6 @@ static IrInstruction *ir_build_check_statement_is_void(IrBuilder *irb, Scope *sc return &instruction->base; } -static IrInstruction *ir_build_test_type(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *type_value, TypeTableEntryId type_id) -{ - IrInstructionTestType *instruction = ir_build_instruction<IrInstructionTestType>( - irb, scope, source_node); - instruction->type_value = type_value; - instruction->type_id = type_id; - - ir_ref_instruction(type_value, irb->current_basic_block); - - return &instruction->base; -} - static IrInstruction *ir_build_type_name(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value) { @@ -2168,6 +2155,17 @@ static IrInstruction *ir_build_offset_of(IrBuilder *irb, Scope *scope, AstNode * return &instruction->base; } +static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *type_value) +{ + IrInstructionTypeId *instruction = ir_build_instruction<IrInstructionTypeId>(irb, scope, source_node); + instruction->type_value = type_value; + + ir_ref_instruction(type_value, irb->current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) { return nullptr; } @@ -2761,13 +2759,6 @@ static IrInstruction *ir_instruction_checkstatementisvoid_get_dep(IrInstructionC } } -static IrInstruction *ir_instruction_testtype_get_dep(IrInstructionTestType *instruction, size_t index) { - switch (index) { - case 0: return instruction->type_value; - default: return nullptr; - } -} - static IrInstruction *ir_instruction_typename_get_dep(IrInstructionTypeName *instruction, size_t index) { switch (index) { case 0: return instruction->type_value; @@ -2839,6 +2830,13 @@ static IrInstruction *ir_instruction_offsetof_get_dep(IrInstructionOffsetOf *ins } } +static IrInstruction *ir_instruction_typeid_get_dep(IrInstructionTypeId *instruction, size_t index) { + switch (index) { + case 0: return instruction->type_value; + default: return nullptr; + } +} + static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { switch (instruction->id) { case IrInstructionIdInvalid: @@ -3007,8 +3005,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t return ir_instruction_checkswitchprongs_get_dep((IrInstructionCheckSwitchProngs *) instruction, index); case IrInstructionIdCheckStatementIsVoid: return ir_instruction_checkstatementisvoid_get_dep((IrInstructionCheckStatementIsVoid *) instruction, index); - case IrInstructionIdTestType: - return ir_instruction_testtype_get_dep((IrInstructionTestType *) instruction, index); case IrInstructionIdTypeName: return ir_instruction_typename_get_dep((IrInstructionTypeName *) instruction, index); case IrInstructionIdCanImplicitCast: @@ -3029,6 +3025,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t return ir_instruction_fieldparentptr_get_dep((IrInstructionFieldParentPtr *) instruction, index); case IrInstructionIdOffsetOf: return ir_instruction_offsetof_get_dep((IrInstructionOffsetOf *) instruction, index); + case IrInstructionIdTypeId: + return ir_instruction_typeid_get_dep((IrInstructionTypeId *) instruction, index); } zig_unreachable(); } @@ -3793,18 +3791,6 @@ static IrInstruction *ir_gen_overflow_op(IrBuilder *irb, Scope *scope, AstNode * return ir_build_overflow_op(irb, scope, node, op, type_value, op1, op2, result_ptr, nullptr); } -static IrInstruction *ir_gen_test_type(IrBuilder *irb, Scope *scope, AstNode *node, TypeTableEntryId type_id) { - assert(node->type == NodeTypeFnCallExpr); - - AstNode *type_node = node->data.fn_call_expr.params.at(0); - - IrInstruction *type_value = ir_gen_node(irb, type_node, scope); - if (type_value == irb->codegen->invalid_instruction) - return irb->codegen->invalid_instruction; - - return ir_build_test_type(irb, scope, node, type_value, type_id); -} - static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeFnCallExpr); @@ -4217,10 +4203,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo return ir_build_type_name(irb, scope, node, arg0_value); } - case BuiltinFnIdIsInteger: - return ir_gen_test_type(irb, scope, node, TypeTableEntryIdInt); - case BuiltinFnIdIsFloat: - return ir_gen_test_type(irb, scope, node, TypeTableEntryIdFloat); case BuiltinFnIdCanImplicitCast: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -4375,6 +4357,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, true); } + case BuiltinFnIdTypeId: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_instruction) + return arg0_value; + + return ir_build_type_id(irb, scope, node, arg0_value); + } } zig_unreachable(); } @@ -11865,6 +11856,27 @@ static TypeTableEntry *ir_analyze_instruction_offset_of(IrAnalyze *ira, return ira->codegen->builtin_types.entry_num_lit_int; } +static TypeTableEntry *ir_analyze_instruction_type_id(IrAnalyze *ira, + IrInstructionTypeId *instruction) +{ + IrInstruction *type_value = instruction->type_value->other; + TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); + if (type_is_invalid(type_entry)) + return ira->codegen->builtin_types.entry_invalid; + + Tld *tld = ira->codegen->compile_var_import->decls_scope->decl_table.get(buf_create_from_str("TypeId")); + resolve_top_level_decl(ira->codegen, tld, false); + assert(tld->id == TldIdVar); + TldVar *tld_var = (TldVar *)tld; + ConstExprValue *var_value = tld_var->var->value; + assert(var_value->type->id == TypeTableEntryIdMetaType); + TypeTableEntry *result_type = var_value->data.x_type; + + ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); + out_val->data.x_enum.tag = type_id_index(type_entry->id); + return result_type; +} + static TypeTableEntry *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstructionTypeName *instruction) { IrInstruction *type_value = instruction->type_value->other; TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); @@ -13025,17 +13037,6 @@ static TypeTableEntry *ir_analyze_instruction_check_statement_is_void(IrAnalyze return ira->codegen->builtin_types.entry_void; } -static TypeTableEntry *ir_analyze_instruction_test_type(IrAnalyze *ira, IrInstructionTestType *instruction) { - IrInstruction *type_value = instruction->type_value->other; - TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); - if (type_is_invalid(type_entry)) - return ira->codegen->builtin_types.entry_invalid; - - ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); - out_val->data.x_bool = (type_entry->id == instruction->type_id); - return ira->codegen->builtin_types.entry_bool; -} - static TypeTableEntry *ir_analyze_instruction_can_implicit_cast(IrAnalyze *ira, IrInstructionCanImplicitCast *instruction) { @@ -13368,8 +13369,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_check_switch_prongs(ira, (IrInstructionCheckSwitchProngs *)instruction); case IrInstructionIdCheckStatementIsVoid: return ir_analyze_instruction_check_statement_is_void(ira, (IrInstructionCheckStatementIsVoid *)instruction); - case IrInstructionIdTestType: - return ir_analyze_instruction_test_type(ira, (IrInstructionTestType *)instruction); case IrInstructionIdCanImplicitCast: return ir_analyze_instruction_can_implicit_cast(ira, (IrInstructionCanImplicitCast *)instruction); case IrInstructionIdDeclRef: @@ -13386,6 +13385,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_field_parent_ptr(ira, (IrInstructionFieldParentPtr *)instruction); case IrInstructionIdOffsetOf: return ir_analyze_instruction_offset_of(ira, (IrInstructionOffsetOf *)instruction); + case IrInstructionIdTypeId: + return ir_analyze_instruction_type_id(ira, (IrInstructionTypeId *)instruction); case IrInstructionIdMaybeWrap: case IrInstructionIdErrWrapCode: case IrInstructionIdErrWrapPayload: @@ -13556,7 +13557,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdIntToEnum: case IrInstructionIdIntToErr: case IrInstructionIdErrToInt: - case IrInstructionIdTestType: case IrInstructionIdCanImplicitCast: case IrInstructionIdDeclRef: case IrInstructionIdErrName: @@ -13564,6 +13564,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdEnumTagName: case IrInstructionIdFieldParentPtr: case IrInstructionIdOffsetOf: + case IrInstructionIdTypeId: return false; case IrInstructionIdAsm: { diff --git a/src/ir_print.cpp b/src/ir_print.cpp index e897bdbe33..6dd0009faf 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -811,11 +811,6 @@ static void ir_print_check_statement_is_void(IrPrint *irp, IrInstructionCheckSta fprintf(irp->f, ")"); } -static void ir_print_test_type(IrPrint *irp, IrInstructionTestType *instruction) { - fprintf(irp->f, "testtype "); - ir_print_other_instruction(irp, instruction->type_value); -} - static void ir_print_type_name(IrPrint *irp, IrInstructionTypeName *instruction) { fprintf(irp->f, "typename "); ir_print_other_instruction(irp, instruction->type_value); @@ -884,6 +879,12 @@ static void ir_print_offset_of(IrPrint *irp, IrInstructionOffsetOf *instruction) fprintf(irp->f, ")"); } +static void ir_print_type_id(IrPrint *irp, IrInstructionTypeId *instruction) { + fprintf(irp->f, "@typeId("); + ir_print_other_instruction(irp, instruction->type_value); + fprintf(irp->f, ")"); +} + static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { ir_print_prefix(irp, instruction); switch (instruction->id) { @@ -1135,9 +1136,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdCheckStatementIsVoid: ir_print_check_statement_is_void(irp, (IrInstructionCheckStatementIsVoid *)instruction); break; - case IrInstructionIdTestType: - ir_print_test_type(irp, (IrInstructionTestType *)instruction); - break; case IrInstructionIdTypeName: ir_print_type_name(irp, (IrInstructionTypeName *)instruction); break; @@ -1168,6 +1166,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdOffsetOf: ir_print_offset_of(irp, (IrInstructionOffsetOf *)instruction); break; + case IrInstructionIdTypeId: + ir_print_type_id(irp, (IrInstructionTypeId *)instruction); + break; } fprintf(irp->f, "\n"); } diff --git a/std/build.zig b/std/build.zig index f944133d5b..29837b4ba4 100644 --- a/std/build.zig +++ b/std/build.zig @@ -488,15 +488,15 @@ pub const Builder = struct { } fn typeToEnum(comptime T: type) -> TypeId { - if (@isInteger(T)) { - TypeId.Int - } else if (@isFloat(T)) { - TypeId.Float - } else switch (T) { - bool => TypeId.Bool, - []const u8 => TypeId.String, - []const []const u8 => TypeId.List, - else => @compileError("Unsupported type: " ++ @typeName(T)), + switch (@typeId(T)) { + builtin.TypeId.Int => TypeId.Int, + builtin.TypeId.Float => TypeId.Float, + builtin.TypeId.Bool => TypeId.Bool, + else => switch (T) { + []const u8 => TypeId.String, + []const []const u8 => TypeId.List, + else => @compileError("Unsupported type: " ++ @typeName(T)), + }, } } diff --git a/std/fmt.zig b/std/fmt.zig index d1b91b15f8..a42233cac2 100644 --- a/std/fmt.zig +++ b/std/fmt.zig @@ -2,6 +2,7 @@ const math = @import("math.zig"); const debug = @import("debug.zig"); const assert = debug.assert; const mem = @import("mem.zig"); +const builtin = @import("builtin"); const max_f64_digits = 65; const max_int_digits = 65; @@ -174,19 +175,25 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)->bool, pub fn formatValue(value: var, context: var, output: fn(@typeOf(context), []const u8)->bool) -> bool { const T = @typeOf(value); - if (@isInteger(T)) { - return formatInt(value, 10, false, 0, context, output); - } else if (@isFloat(T)) { - @compileError("TODO implement formatFloat"); - } else if (@canImplicitCast([]const u8, value)) { - const casted_value = ([]const u8)(value); - return output(context, casted_value); - } else if (T == void) { - return output(context, "void"); - } else if (T == bool) { - return output(context, if (value) "true" else "false"); - } else { - @compileError("Unable to format type '" ++ @typeName(T) ++ "'"); + switch (@typeId(T)) { + builtin.TypeId.Int => { + return formatInt(value, 10, false, 0, context, output); + }, + builtin.TypeId.Float => { + @compileError("TODO implement formatFloat"); + }, + builtin.TypeId.Void => { + return output(context, "void"); + }, + builtin.TypeId.Bool => { + return output(context, if (value) "true" else "false"); + }, + else => if (@canImplicitCast([]const u8, value)) { + const casted_value = ([]const u8)(value); + return output(context, casted_value); + } else { + @compileError("Unable to format type '" ++ @typeName(T) ++ "'"); + }, } } diff --git a/std/math.zig b/std/math.zig index c146272d62..4941f4060c 100644 --- a/std/math.zig +++ b/std/math.zig @@ -1,4 +1,5 @@ const assert = @import("debug.zig").assert; +const builtin = @import("builtin"); pub const Cmp = enum { Less, @@ -61,23 +62,27 @@ fn testOverflow() { pub fn log(comptime base: usize, value: var) -> @typeOf(value) { const T = @typeOf(value); - if (@isInteger(T)) { - if (base == 2) { - return T.bit_count - 1 - @clz(value); - } else { - @compileError("TODO implement log for non base 2 integers"); - } - } else if (@isFloat(T)) { - @compileError("TODO implement log for floats"); - } else { - @compileError("log expects integer or float, found '" ++ @typeName(T) ++ "'"); + switch (@typeId(T)) { + builtin.TypeId.Int => { + if (base == 2) { + return T.bit_count - 1 - @clz(value); + } else { + @compileError("TODO implement log for non base 2 integers"); + } + }, + builtin.TypeId.Float => { + @compileError("TODO implement log for floats"); + }, + else => { + @compileError("log expects integer or float, found '" ++ @typeName(T) ++ "'"); + }, } } error Overflow; pub fn absInt(x: var) -> %@typeOf(x) { const T = @typeOf(x); - comptime assert(@isInteger(T)); // must pass an integer to absInt + comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt comptime assert(T.is_signed); // must pass a signed integer to absInt if (x == @minValue(@typeOf(x))) return error.Overflow; @@ -97,7 +102,7 @@ fn testAbsInt() { } pub fn absFloat(x: var) -> @typeOf(x) { - comptime assert(@isFloat(@typeOf(x))); + comptime assert(@typeId(@typeOf(x)) == builtin.TypeId.Float); return if (x < 0) -x else x; } @@ -116,7 +121,7 @@ pub fn divTrunc(comptime T: type, numerator: T, denominator: T) -> %T { @setDebugSafety(this, false); if (denominator == 0) return error.DivisionByZero; - if (@isInteger(T) and T.is_signed and numerator == @minValue(T) and denominator == -1) + if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) return error.Overflow; return @divTrunc(numerator, denominator); } @@ -141,7 +146,7 @@ pub fn divFloor(comptime T: type, numerator: T, denominator: T) -> %T { @setDebugSafety(this, false); if (denominator == 0) return error.DivisionByZero; - if (@isInteger(T) and T.is_signed and numerator == @minValue(T) and denominator == -1) + if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) return error.Overflow; return @divFloor(numerator, denominator); } @@ -167,7 +172,7 @@ pub fn divExact(comptime T: type, numerator: T, denominator: T) -> %T { @setDebugSafety(this, false); if (denominator == 0) return error.DivisionByZero; - if (@isInteger(T) and T.is_signed and numerator == @minValue(T) and denominator == -1) + if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) return error.Overflow; const result = @divTrunc(numerator, denominator); if (result * denominator != numerator) @@ -246,7 +251,7 @@ fn testRem() { } fn isNan(comptime T: type, x: T) -> bool { - assert(@isFloat(T)); + assert(@typeId(T) == builtin.TypeId.Float); const bits = floatBits(x); if (T == f32) { return (bits & 0x7fffffff) > 0x7f800000; @@ -258,7 +263,7 @@ fn isNan(comptime T: type, x: T) -> bool { } fn floatBits(comptime T: type, x: T) -> @IntType(false, T.bit_count) { - assert(@isFloat(T)); + assert(@typeId(T) == builtin.TypeId.Float); const uint = @IntType(false, T.bit_count); return *@intToPtr(&const uint, &x); } diff --git a/test/cases/misc.zig b/test/cases/misc.zig index 3098390eb9..3f7a915f56 100644 --- a/test/cases/misc.zig +++ b/test/cases/misc.zig @@ -446,29 +446,42 @@ fn testArray2DConstDoublePtr(ptr: &const f32) { assert(ptr[1] == 2.0); } -test "@isInteger" { - comptime { - assert(@isInteger(i8)); - assert(@isInteger(u8)); - assert(@isInteger(i64)); - assert(@isInteger(u64)); - assert(!@isInteger(f32)); - assert(!@isInteger(f64)); - assert(!@isInteger(bool)); - assert(!@isInteger(&i32)); - } -} +const Tid = builtin.TypeId; +const AStruct = struct { x: i32, }; +const AnEnum = enum { One, Two, }; +const AnEnumWithPayload = enum { One: i32, Two, }; -test "@isFloat" { +test "@typeId" { comptime { - assert(!@isFloat(i8)); - assert(!@isFloat(u8)); - assert(!@isFloat(i64)); - assert(!@isFloat(u64)); - assert(@isFloat(f32)); - assert(@isFloat(f64)); - assert(!@isFloat(bool)); - assert(!@isFloat(&f32)); + assert(@typeId(type) == Tid.Type); + assert(@typeId(void) == Tid.Void); + assert(@typeId(bool) == Tid.Bool); + assert(@typeId(noreturn) == Tid.NoReturn); + assert(@typeId(i8) == Tid.Int); + assert(@typeId(u8) == Tid.Int); + assert(@typeId(i64) == Tid.Int); + assert(@typeId(u64) == Tid.Int); + assert(@typeId(f32) == Tid.Float); + assert(@typeId(f64) == Tid.Float); + assert(@typeId(&f32) == Tid.Pointer); + assert(@typeId([2]u8) == Tid.Array); + assert(@typeId(AStruct) == Tid.Struct); + assert(@typeId(@typeOf(1)) == Tid.IntLiteral); + assert(@typeId(@typeOf(1.0)) == Tid.FloatLiteral); + assert(@typeId(@typeOf(undefined)) == Tid.UndefinedLiteral); + assert(@typeId(@typeOf(null)) == Tid.NullLiteral); + assert(@typeId(?i32) == Tid.Nullable); + assert(@typeId(%i32) == Tid.ErrorUnion); + assert(@typeId(error) == Tid.Error); + assert(@typeId(AnEnum) == Tid.Enum); + assert(@typeId(@typeOf(AnEnumWithPayload.One)) == Tid.EnumTag); + // TODO union + assert(@typeId(fn()) == Tid.Fn); + assert(@typeId(@typeOf(builtin)) == Tid.Namespace); + assert(@typeId(@typeOf({this})) == Tid.Block); + // TODO bound fn + // TODO arg tuple + // TODO opaque } } |
