Skip to content

Instantly share code, notes, and snippets.

@mikdusan
Created April 15, 2020 02:15
Show Gist options
  • Save mikdusan/371fdf4b327671d7e0c332303d12bb51 to your computer and use it in GitHub Desktop.
Save mikdusan/371fdf4b327671d7e0c332303d12bb51 to your computer and use it in GitHub Desktop.
some progress on #1332
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 27bc6a04f..f9e336295 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -329,6 +329,9 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
set(EXE_CFLAGS "${EXE_CFLAGS} /w")
else()
set(EXE_CFLAGS "${EXE_CFLAGS} -Werror -Wall -Werror=implicit-fallthrough")
+ set(EXE_CFLAGS "${EXE_CFLAGS} -fcolor-diagnostics")
+ set(EXE_CFLAGS "${EXE_CFLAGS} -Wno-error=unused-variable")
+ set(EXE_CFLAGS "${EXE_CFLAGS} -Wno-error=unused-label")
endif()
endif()
diff --git a/src/ir.cpp b/src/ir.cpp
index b9438dda3..04c84150b 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -16394,6 +16394,82 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i
IrBinOp op_id = bin_op_instruction->op_id;
bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq);
+
+#if 1 // TODO: mike
+ // unwrap_equality_operands: (?T == ?T) and combinations
+ if (is_equality_cmp &&
+ op1->value->type->id != ZigTypeIdNull &&
+ op2->value->type->id != ZigTypeIdNull)
+ {
+ if (instr_is_comptime(op1) && instr_is_comptime(op2)) {
+ for (;;) {
+ bool repeat = false;
+
+ if (op1->value->type->id == ZigTypeIdOptional) {
+ if (optional_value_is_null(op1->value)) {
+ bool answer = (op2->value->type->id == ZigTypeIdOptional && optional_value_is_null(op2->value))
+ ? true : false;
+ return ir_const_bool(ira, &bin_op_instruction->base.base, answer);
+ }
+
+ ZigValue *tmp = ir_resolve_const(ira, op1, UndefBad);
+ if (!tmp)
+ return ira->codegen->invalid_inst_gen;
+ op1->value = tmp->data.x_optional;
+ repeat = true;
+// op1->dump();
+ }
+
+ if (op2->value->type->id == ZigTypeIdOptional) {
+ if (optional_value_is_null(op2->value)) {
+ bool answer = (op1->value->type->id == ZigTypeIdOptional && optional_value_is_null(op1->value))
+ ? true : false;
+ return ir_const_bool(ira, &bin_op_instruction->base.base, answer);
+ }
+
+ ZigValue *tmp = ir_resolve_const(ira, op2, UndefBad);
+ if (!tmp)
+ return ira->codegen->invalid_inst_gen;
+ op2->value = tmp->data.x_optional;
+ repeat = true;
+// op2->dump();
+ }
+
+ if (!repeat) break;
+ }
+ } else for (;;) {
+ bool repeat = false;
+
+ if (op1->value->type->id == ZigTypeIdOptional) {
+ IrInstGen *op1_ref = ir_get_ref(ira, &op1->base, op1, true, false);
+ ZigType *op1_child_ptr_type = get_pointer_to_type_extra(ira->codegen,
+ op1->value->type->data.maybe.child_type, true, false,
+ PtrLenSingle, 0, 0, 0, false);
+
+ IrInstGen *op1_unwrap_ptr = ir_build_optional_unwrap_ptr_gen(ira, &op1->base, op1_ref,
+ false, false, op1_child_ptr_type);
+ op1 = ir_get_deref(ira, &op1->base, op1_unwrap_ptr, nullptr);
+ repeat = true;
+// op1->dump();
+ }
+
+ if (op2->value->type->id == ZigTypeIdOptional) {
+ IrInstGen *op2_ref = ir_get_ref(ira, &op2->base, op2, true, false);
+ ZigType *op2_child_ptr_type = get_pointer_to_type_extra(ira->codegen,
+ op2->value->type->data.maybe.child_type, true, false,
+ PtrLenSingle, 0, 0, 0, false);
+ IrInstGen *op2_unwrap_ptr = ir_build_optional_unwrap_ptr_gen(ira, &op2->base, op2_ref,
+ false, false, op2_child_ptr_type);
+ op2 = ir_get_deref(ira, &op2->base, op2_unwrap_ptr, nullptr);
+ repeat = true;
+// op2->dump();
+ }
+
+ if (!repeat) break;
+ }
+ }
+#endif
+
if (is_equality_cmp && op1->value->type->id == ZigTypeIdNull && op2->value->type->id == ZigTypeIdNull) {
return ir_const_bool(ira, &bin_op_instruction->base.base, (op_id == IrBinOpCmpEq));
} else if (is_equality_cmp &&
diff --git a/test/stage1/behavior/optional.zig b/test/stage1/behavior/optional.zig
index 7dd48769d..5f7af65c8 100644
--- a/test/stage1/behavior/optional.zig
+++ b/test/stage1/behavior/optional.zig
@@ -198,3 +198,63 @@ test "0-bit child type coerced to optional" {
S.doTheTest();
comptime S.doTheTest();
}
+
+test "unwrap equality operands" {
+ const S = struct {
+ fn doTheTest() void {
+ var i: u32 = 11;
+ var oi: ?u32 = 11;
+ var ooi: ??u32 = 11;
+
+ var j: u32 = 11;
+ var oj: ?u32 = 11;
+ var ooj: ??u32 = 11;
+
+ var k: u32 = 22;
+ var ok: ?u32 = 22;
+ var ook: ??u32 = 22;
+
+ expect(i == oj);
+ expect(i == ooj);
+ expect(oj == i);
+ expect(ooj == i);
+ expect(oi == oj);
+ expect(oi == ooj);
+ expect(ooi == ooj);
+
+ expect(i != ok);
+ expect(i != ook);
+ expect(ok != i);
+ expect(ook != i);
+ expect(oi != ok);
+ expect(oi != ook);
+ expect(ooi != ook);
+
+ var oin: ?u32 = null;
+ var ooin: ??u32 = null;
+ var ojn: ?u32 = null;
+ var oojn: ??u32 = null;
+
+ expect(oi != ojn);
+ expect(oin == ojn);
+ expect(oj != oin);
+ expect(ojn == oin);
+
+ expect(i == 11);
+ expect(11 == i);
+ expect(oi == 11);
+ expect(11 == oi);
+ expect(ooi == 11);
+ expect(11 == ooi);
+
+ expect(i != 22);
+ expect(22 != i);
+ expect(oi != 22);
+ expect(22 != oi);
+ expect(ooi != 22);
+ expect(22 != ooi);
+ }
+ };
+ S.doTheTest();
+ comptime S.doTheTest();
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment