mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 05:20:34 +00:00
parent
9851a943ed
commit
b483db4868
@ -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;
|
||||
|
||||
|
||||
154
src/analyze.cpp
154
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();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
113
src/ir.cpp
113
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:
|
||||
{
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
33
std/fmt.zig
33
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) ++ "'");
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
39
std/math.zig
39
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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user