Skip to content

Commit

Permalink
Merge pull request #1130 from ziglang/remove-bool-casting-syntax
Browse files Browse the repository at this point in the history
remove bool to int syntax. add @boolToInt
  • Loading branch information
andrewrk committed Jun 18, 2018
2 parents d52ef95 + 4210f1f commit 7151d72
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 43 deletions.
90 changes: 70 additions & 20 deletions doc/langref.html.in
Expand Up @@ -4560,6 +4560,19 @@ comptime {
</p>
{#see_also|Alignment#}
{#header_close#}

{#header_open|@boolToInt#}
<pre><code class="zig">@boolToInt(value: bool) u1</code></pre>
<p>
Converts <code>true</code> to <code>u1(1)</code> and <code>false</code> to
<code>u1(0)</code>.
</p>
<p>
If the value is known at compile-time, the return type is <code>comptime_int</code>
instead of <code>u1</code>.
</p>
{#header_close#}

{#header_open|@cDefine#}
<pre><code class="zig">@cDefine(comptime name: []u8, value)</code></pre>
<p>
Expand Down Expand Up @@ -4834,21 +4847,6 @@ test "main" {
Creates a symbol in the output object file.
</p>
{#header_close#}
{#header_open|@tagName#}
<pre><code class="zig">@tagName(value: var) []const u8</code></pre>
<p>
Converts an enum value or union value to a slice of bytes representing the name.
</p>
{#header_close#}
{#header_open|@TagType#}
<pre><code class="zig">@TagType(T: type) type</code></pre>
<p>
For an enum, returns the integer type that is used to store the enumeration value.
</p>
<p>
For a union, returns the enum type that is used to store the tag value.
</p>
{#header_close#}
{#header_open|@errorName#}
<pre><code class="zig">@errorName(err: error) []u8</code></pre>
<p>
Expand Down Expand Up @@ -4883,13 +4881,36 @@ test "main" {
</p>
{#see_also|Compile Variables#}
{#header_close#}

{#header_open|@field#}
<pre><code class="zig">@field(lhs: var, comptime field_name: []const u8) (field)</code></pre>
<p>Preforms field access equivalent to <code>lhs.-&gtfield_name-&lt</code>.</p>
{#header_close#}

{#header_open|@fieldParentPtr#}
<pre><code class="zig">@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8,
field_ptr: *T) *ParentType</code></pre>
<p>
Given a pointer to a field, returns the base pointer of a struct.
</p>
{#header_close#}

{#header_open|@floatCast#}
<pre><code class="zig">@floatCast(comptime DestType: type, value: var) DestType</code></pre>
<p>
Convert from one float type to another. This cast is safe, but may cause the
numeric value to lose precision.
</p>
{#header_close#}

{#header_open|@floatToInt#}
<pre><code class="zig">@floatToInt(comptime DestType: type, float: var) DestType</code></pre>
<p>
Converts the integer part of a floating point number to the destination type.
To convert the other way, use {#link|@intToFloat#}. This cast is always safe.
</p>
{#header_close#}

{#header_open|@frameAddress#}
<pre><code class="zig">@frameAddress()</code></pre>
<p>
Expand Down Expand Up @@ -4944,12 +4965,30 @@ fn add(a: i32, b: i32) i32 { return a + b; }
</p>
{#see_also|@noInlineCall#}
{#header_close#}

{#header_open|@intCast#}
<pre><code class="zig">@intCast(comptime DestType: type, int: var) DestType</code></pre>
<p>
Converts an integer to another integer while keeping the same numerical value.
Attempting to convert a number which is out of range of the destination type results in
{#link|Undefined Behavior#}.
</p>
{#header_close#}

{#header_open|@intToFloat#}
<pre><code class="zig">@intToFloat(comptime DestType: type, int: var) DestType</code></pre>
<p>
Converts an integer to the closest floating point representation. To convert the other way, use {#link|@floatToInt#}. This cast is always safe.
</p>
{#header_close#}

{#header_open|@intToPtr#}
<pre><code class="zig">@intToPtr(comptime DestType: type, int: usize) DestType</code></pre>
<p>
Converts an integer to a pointer. To convert the other way, use {#link|@ptrToInt#}.
</p>
{#header_close#}

{#header_open|@IntType#}
<pre><code class="zig">@IntType(comptime is_signed: bool, comptime bit_count: u8) type</code></pre>
<p>
Expand Down Expand Up @@ -4987,10 +5026,6 @@ fn add(a: i32, b: i32) i32 { return a + b; }
It does not include functions, variables, or constants.
</p>
{#header_close#}
{#header_open|@field#}
<pre><code class="zig">@field(lhs: var, comptime field_name: []const u8) (field)</code></pre>
<p>Preforms field access equivalent to <code>lhs.-&gtfield_name-&lt</code>.</p>
{#header_close#}
{#header_open|@memberType#}
<pre><code class="zig">@memberType(comptime T: type, comptime index: usize) type</code></pre>
<p>Returns the field type of a struct or union.</p>
Expand Down Expand Up @@ -5370,6 +5405,21 @@ pub const FloatMode = enum {
If no overflow or underflow occurs, returns <code>false</code>.
</p>
{#header_close#}
{#header_open|@tagName#}
<pre><code class="zig">@tagName(value: var) []const u8</code></pre>
<p>
Converts an enum value or union value to a slice of bytes representing the name.
</p>
{#header_close#}
{#header_open|@TagType#}
<pre><code class="zig">@TagType(T: type) type</code></pre>
<p>
For an enum, returns the integer type that is used to store the enumeration value.
</p>
<p>
For a union, returns the enum type that is used to store the tag value.
</p>
{#header_close#}
{#header_open|@truncate#}
<pre><code class="zig">@truncate(comptime T: type, integer) T</code></pre>
<p>
Expand Down Expand Up @@ -6665,7 +6715,7 @@ hljs.registerLanguage("zig", function(t) {
a = t.IR + "\\s*\\(",
c = {
keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong resume cancel await async orelse",
built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo typeName newStackCall",
built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic ptrCast intCast floatCast intToFloat floatToInt boolToInt bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo typeName newStackCall",
literal: "true false null undefined"
},
n = [e, t.CLCM, t.CBCM, s, r];
Expand Down
8 changes: 8 additions & 0 deletions src/all_types.hpp
Expand Up @@ -1361,6 +1361,7 @@ enum BuiltinFnId {
BuiltinFnIdFloatCast,
BuiltinFnIdIntToFloat,
BuiltinFnIdFloatToInt,
BuiltinFnIdBoolToInt,
BuiltinFnIdIntType,
BuiltinFnIdSetCold,
BuiltinFnIdSetRuntimeSafety,
Expand Down Expand Up @@ -2048,6 +2049,7 @@ enum IrInstructionId {
IrInstructionIdFloatCast,
IrInstructionIdIntToFloat,
IrInstructionIdFloatToInt,
IrInstructionIdBoolToInt,
IrInstructionIdIntType,
IrInstructionIdBoolNot,
IrInstructionIdMemset,
Expand Down Expand Up @@ -2668,6 +2670,12 @@ struct IrInstructionFloatToInt {
IrInstruction *target;
};

struct IrInstructionBoolToInt {
IrInstruction base;

IrInstruction *target;
};

struct IrInstructionIntType {
IrInstruction base;

Expand Down
2 changes: 2 additions & 0 deletions src/codegen.cpp
Expand Up @@ -4726,6 +4726,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdFloatCast:
case IrInstructionIdIntToFloat:
case IrInstructionIdFloatToInt:
case IrInstructionIdBoolToInt:
zig_unreachable();

case IrInstructionIdReturn:
Expand Down Expand Up @@ -6318,6 +6319,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdFloatCast, "floatCast", 2);
create_builtin_fn(g, BuiltinFnIdIntToFloat, "intToFloat", 2);
create_builtin_fn(g, BuiltinFnIdFloatToInt, "floatToInt", 2);
create_builtin_fn(g, BuiltinFnIdBoolToInt, "boolToInt", 1);
create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
Expand Down
60 changes: 53 additions & 7 deletions src/ir.cpp
Expand Up @@ -476,6 +476,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFloatToInt *) {
return IrInstructionIdFloatToInt;
}

static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolToInt *) {
return IrInstructionIdBoolToInt;
}

static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) {
return IrInstructionIdIntType;
}
Expand Down Expand Up @@ -1959,6 +1963,15 @@ static IrInstruction *ir_build_float_to_int(IrBuilder *irb, Scope *scope, AstNod
return &instruction->base;
}

static IrInstruction *ir_build_bool_to_int(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target) {
IrInstructionBoolToInt *instruction = ir_build_instruction<IrInstructionBoolToInt>(irb, scope, source_node);
instruction->target = target;

ir_ref_instruction(target, irb->current_basic_block);

return &instruction->base;
}

static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *is_signed, IrInstruction *bit_count) {
IrInstructionIntType *instruction = ir_build_instruction<IrInstructionIntType>(irb, scope, source_node);
instruction->is_signed = is_signed;
Expand Down Expand Up @@ -4071,6 +4084,16 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
IrInstruction *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value);
return ir_lval_wrap(irb, scope, result, lval);
}
case BuiltinFnIdBoolToInt:
{
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;

IrInstruction *result = ir_build_bool_to_int(irb, scope, node, arg0_value);
return ir_lval_wrap(irb, scope, result, lval);
}
case BuiltinFnIdIntType:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
Expand Down Expand Up @@ -10055,13 +10078,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
}

// explicit cast from bool to int
if (wanted_type->id == TypeTableEntryIdInt &&
actual_type->id == TypeTableEntryIdBool)
{
return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpBoolToInt, false);
}

// explicit widening conversion
if (wanted_type->id == TypeTableEntryIdInt &&
actual_type->id == TypeTableEntryIdInt &&
Expand Down Expand Up @@ -17605,6 +17621,33 @@ static TypeTableEntry *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrIns
return dest_type;
}

static TypeTableEntry *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstructionBoolToInt *instruction) {
IrInstruction *target = instruction->target->other;
if (type_is_invalid(target->value.type))
return ira->codegen->builtin_types.entry_invalid;

if (target->value.type->id != TypeTableEntryIdBool) {
ir_add_error(ira, instruction->target, buf_sprintf("expected bool, found '%s'",
buf_ptr(&target->value.type->name)));
return ira->codegen->builtin_types.entry_invalid;
}

if (instr_is_comptime(target)) {
bool is_true;
if (!ir_resolve_bool(ira, target, &is_true))
return ira->codegen->builtin_types.entry_invalid;

ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
bigint_init_unsigned(&out_val->data.x_bigint, is_true ? 1 : 0);
return ira->codegen->builtin_types.entry_num_lit_int;
}

TypeTableEntry *u1_type = get_int_type(ira->codegen, false, 1);
IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, u1_type, CastOpBoolToInt, false);
ir_link_new_instruction(result, &instruction->base);
return u1_type;
}

static TypeTableEntry *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstructionIntType *instruction) {
IrInstruction *is_signed_value = instruction->is_signed->other;
bool is_signed;
Expand Down Expand Up @@ -20143,6 +20186,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_int_to_float(ira, (IrInstructionIntToFloat *)instruction);
case IrInstructionIdFloatToInt:
return ir_analyze_instruction_float_to_int(ira, (IrInstructionFloatToInt *)instruction);
case IrInstructionIdBoolToInt:
return ir_analyze_instruction_bool_to_int(ira, (IrInstructionBoolToInt *)instruction);
case IrInstructionIdIntType:
return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);
case IrInstructionIdBoolNot:
Expand Down Expand Up @@ -20490,6 +20535,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdFloatCast:
case IrInstructionIdIntToFloat:
case IrInstructionIdFloatToInt:
case IrInstructionIdBoolToInt:
return false;

case IrInstructionIdAsm:
Expand Down
9 changes: 9 additions & 0 deletions src/ir_print.cpp
Expand Up @@ -680,6 +680,12 @@ static void ir_print_float_to_int(IrPrint *irp, IrInstructionFloatToInt *instruc
fprintf(irp->f, ")");
}

static void ir_print_bool_to_int(IrPrint *irp, IrInstructionBoolToInt *instruction) {
fprintf(irp->f, "@boolToInt(");
ir_print_other_instruction(irp, instruction->target);
fprintf(irp->f, ")");
}

static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) {
fprintf(irp->f, "@IntType(");
ir_print_other_instruction(irp, instruction->is_signed);
Expand Down Expand Up @@ -1461,6 +1467,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdFloatToInt:
ir_print_float_to_int(irp, (IrInstructionFloatToInt *)instruction);
break;
case IrInstructionIdBoolToInt:
ir_print_bool_to_int(irp, (IrInstructionBoolToInt *)instruction);
break;
case IrInstructionIdIntType:
ir_print_int_type(irp, (IrInstructionIntType *)instruction);
break;
Expand Down
4 changes: 2 additions & 2 deletions std/fmt/errol/index.zig
Expand Up @@ -329,7 +329,7 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal {
var mi: i32 = mismatch10(l64, h64);
var x: u64 = 1;
{
var i = i32(lf == hf);
var i: i32 = @boolToInt(lf == hf);
while (i < mi) : (i += 1) {
x *= 10;
}
Expand All @@ -341,7 +341,7 @@ fn errolInt(val: f64, buffer: []u8) FloatDecimal {
var buf_index = u64toa(m64, buffer) - 1;

if (mi != 0) {
buffer[buf_index - 1] += u8(buffer[buf_index] >= '5');
buffer[buf_index - 1] += @boolToInt(buffer[buf_index] >= '5');
} else {
buf_index += 1;
}
Expand Down

0 comments on commit 7151d72

Please sign in to comment.