From a7fcef62e0a9eac9df626ec9d036daa6ec5e3884 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 3 Sep 2018 01:13:07 +0200 Subject: [PATCH] compiler: implement comparing interfaces to nil Comparing an interface to nil is easy, as the dynamic type is also nil. Comparing the dynamic values (when the dynamic types match) is much harder and depends on reflection capabilities, so is not yet implemented. --- compiler.go | 11 +++++++++++ src/runtime/interface.go | 14 ++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/compiler.go b/compiler.go index 40c68928..41d48193 100644 --- a/compiler.go +++ b/compiler.go @@ -2219,6 +2219,17 @@ func (c *Compiler) parseBinOp(frame *Frame, binop *ssa.BinOp) (llvm.Value, error } else { return llvm.Value{}, errors.New("todo: unknown basic type in binop: " + typ.String()) } + case *types.Interface: + switch binop.Op { + case token.EQL, token.NEQ: // ==, != + result := c.builder.CreateCall(c.mod.NamedFunction("runtime.interfaceEqual"), []llvm.Value{x, y}, "") + if binop.Op == token.NEQ { + result = c.builder.CreateNot(result, "") + } + return result, nil + default: + return llvm.Value{}, errors.New("binop on interface: " + binop.Op.String()) + } case *types.Pointer: switch binop.Op { case token.EQL: // == diff --git a/src/runtime/interface.go b/src/runtime/interface.go index 98d8f954..aaaa575d 100644 --- a/src/runtime/interface.go +++ b/src/runtime/interface.go @@ -58,3 +58,17 @@ func interfaceMethod(itf _interface, method uint16) *uint8 { i++ } } + +// Return true iff both interfaces are equal. +func interfaceEqual(x, y _interface) bool { + if x.typecode != y.typecode { + // Different dynamic type so always unequal. + return false + } + if x.typecode == 0 { + // Both interfaces are nil, so they are equal. + return true + } + // TODO: depends on reflection. + panic("unimplemented: interface equality") +}