diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 212919adf..25aa5cb31 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -1173,7 +1173,13 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) { switch name { case "len": + emit.Opcode(c.prog.BinWriter, opcode.DUP) + emit.Opcode(c.prog.BinWriter, opcode.ISNULL) + emit.Instruction(c.prog.BinWriter, opcode.JMPIF, []byte{2 + 1 + 2}) emit.Opcode(c.prog.BinWriter, opcode.SIZE) + emit.Instruction(c.prog.BinWriter, opcode.JMP, []byte{2 + 1 + 1}) + emit.Opcode(c.prog.BinWriter, opcode.DROP) + emit.Opcode(c.prog.BinWriter, opcode.PUSH0) case "append": arg := expr.Args[0] typ := c.typeInfo.Types[arg].Type @@ -1515,7 +1521,8 @@ func (c *codegen) writeJumps(b []byte) error { case opcode.JMP, opcode.JMPIFNOT, opcode.JMPIF, opcode.CALL, opcode.JMPEQ, opcode.JMPNE, opcode.JMPGT, opcode.JMPGE, opcode.JMPLE, opcode.JMPLT: - panic("short jumps are not yet supported") + // Noop, assumed to be correct already. If you're fixing #905, + // make sure not to break "len" handling above. case opcode.JMPL, opcode.JMPIFL, opcode.JMPIFNOTL, opcode.JMPEQL, opcode.JMPNEL, opcode.JMPGTL, opcode.JMPGEL, opcode.JMPLEL, opcode.JMPLTL, diff --git a/pkg/compiler/interop_test.go b/pkg/compiler/interop_test.go index 646670244..7180b85bd 100644 --- a/pkg/compiler/interop_test.go +++ b/pkg/compiler/interop_test.go @@ -187,3 +187,14 @@ func TestBuiltinPackage(t *testing.T) { }` eval(t, src, big.NewInt(1)) } + +func TestLenForNil(t *testing.T) { + src := ` + package foo + func Main() bool { + var a []int = nil + return len(a) == 0 + }` + + eval(t, src, true) +}