Repository: goplus/gop
Pull request #656 (2021-01-19 14:27:48)

operator EQ/NE check
fix https://github.com/goplus/gop/issues/637 
fix https://github.com/goplus/gop/issues/654

cl: add operator EQ/NE type matched check
bytecode: fix and support chan/func/slice/ptr/map/interface operator EQ/NE

Go+ cl check and dump error
```
var v int
println(v == nil)  // invalid operator: nil == v (mismatched types nil and int)
```
```
var a int
var b uint8
println(a == b) // invalid operator: a == b (mismatched types int and uint8)
```
```
var a int
switch a {
    case 0:
    case uint8(1): //invalid case uint8(1) in switch on a (mismatched types int and uint8)
}
```




Patch:
diff --git a/ast/astutil/ast_utils.go b/ast/astutil/ast_utils.go
index baeaf245..a69471fc 100644
--- a/ast/astutil/ast_utils.go
+++ b/ast/astutil/ast_utils.go
@@ -63,6 +63,8 @@ const (
 	ConstUnboundFloat = spec.ConstUnboundFloat
 	// ConstUnboundComplex - unbound complex type
 	ConstUnboundComplex = spec.ConstUnboundComplex
+	// ConstUnboundPtr - nil: unbound ptr
+	ConstUnboundPtr = spec.ConstUnboundPtr
 )
 
 // IsConstBound checks a const is bound or not.
diff --git a/cl/check_type.go b/cl/check_type.go
index 8f5ea602..4f17b431 100644
--- a/cl/check_type.go
+++ b/cl/check_type.go
@@ -18,6 +18,7 @@ package cl
 
 import (
 	"errors"
+	"fmt"
 	"reflect"
 
 	"github.com/goplus/gop/ast"
@@ -144,6 +145,33 @@ func checkBinaryOp(kind exec.Kind, op exec.Operator, x, y interface{}, b exec.Bu
 	}
 }
 
+func checkOpMatchType(op exec.Operator, x, y interface{}) error {
+	switch op {
+	case exec.OpEQ, exec.OpNE:
+		ix := x.(iValue)
+		iy := y.(iValue)
+		xkind, ykind := ix.Kind(), iy.Kind()
+		if xkind == exec.ConstUnboundPtr && ykind == exec.ConstUnboundPtr {
+			return nil
+		} else if xkind == exec.ConstUnboundPtr {
+			if !IsPtrKind(ykind) {
+				return fmt.Errorf("mismatched types nil and %v", boundType(iy))
+			}
+		} else if ykind == exec.ConstUnboundPtr {
+			if !IsPtrKind(xkind) {
+				return fmt.Errorf("mismatched types %v and nil", boundType(ix))
+			}
+		} else if tx, ty := boundType(ix), boundType(iy); tx != ty {
+			return fmt.Errorf("mismatched types %v and %v", tx, ty)
+		}
+	}
+	return nil
+}
+
+func IsPtrKind(kind reflect.Kind) bool {
+	return kind >= reflect.Chan && kind <= reflect.Slice || kind == reflect.UnsafePointer
+}
+
 func checkType(t reflect.Type, v interface{}, b exec.Builder) {
 	if cons, ok := v.(*constVal); ok {
 		cons.bound(t, b)
diff --git a/cl/expr.go b/cl/expr.go
index 1d33204c..ea59540c 100644
--- a/cl/expr.go
+++ b/cl/expr.go
@@ -681,6 +681,9 @@ func compileBinaryExpr(ctx *blockCtx, v *ast.BinaryExpr) func() {
 		}
 		exprY()
 		checkBinaryOp(kind, op, x, y, ctx.out)
+		if err := checkOpMatchType(op, x, y); err != nil {
+			log.Panicf("invalid operator: %v (%v)", ctx.code(v), err)
+		}
 		ctx.out.BuiltinOp(kind, op)
 		if label != nil {
 			ctx.out.Label(label)
diff --git a/cl/stmt.go b/cl/stmt.go
index 7c14feb3..25671345 100644
--- a/cl/stmt.go
+++ b/cl/stmt.go
@@ -399,7 +399,11 @@ func compileSwitchStmt(ctx *blockCtx, v *ast.SwitchStmt) {
 			hasCaseClause = true
 			for _, caseExp := range c.List {
 				compileExpr(ctxSw, caseExp)()
-				checkCaseCompare(tag, ctx.infer.Pop(), out)
+				xcase := ctx.infer.Pop()
+				checkCaseCompare(tag, xcase, out)
+				if err := checkOpMatchType(exec.OpEQ, tag, xcase); err != nil {
+					log.Panicf("invalid case %v in switch on %v (%v)", ctx.code(caseExp), ctx.code(v.Tag), err)
+				}
 			}
 			next := ctx.NewLabel("")
 			out.CaseNE(next, len(c.List))
diff --git a/cl/value.go b/cl/value.go
index 6cbd08c2..722bc586 100644
--- a/cl/value.go
+++ b/cl/value.go
@@ -20,6 +20,7 @@ import (
 	"math"
 	"reflect"
 	"strconv"
+	"unsafe"
 
 	"github.com/goplus/gop/ast/astutil"
 	"github.com/goplus/gop/exec.spec"
@@ -395,6 +396,8 @@ func boundConst(v interface{}, t reflect.Type) interface{} {
 	if v == nil {
 		if kind >= reflect.Chan && kind <= reflect.Slice {
 			return reflect.Zero(t).Interface()
+		} else if kind == reflect.UnsafePointer {
+			return reflect.ValueOf(unsafe.Pointer(nil)).Interface()
 		}
 		log.Panicln("boundConst: can't convert nil into", t)
 	}
@@ -468,6 +471,8 @@ func realKindOf(kind astutil.ConstKind) reflect.Kind {
 		return reflect.Float64
 	case astutil.ConstUnboundComplex:
 		return reflect.Complex128
+	case astutil.ConstUnboundPtr:
+		return reflect.UnsafePointer
 	default:
 		return kind
 	}
diff --git a/exec.spec/operator.go b/exec.spec/operator.go
index 79573587..dc05e699 100644
--- a/exec.spec/operator.go
+++ b/exec.spec/operator.go
@@ -145,9 +145,9 @@ var opInfos = [...]OperatorInfo{
 	OpLE:     {"<=", bitsAllReal | bitString | bitBigInt, bitSameAsFirst, Bool},
 	OpGT:     {">", bitsAllReal | bitString | bitBigInt, bitSameAsFirst, Bool},
 	OpGE:     {">=", bitsAllReal | bitString | bitBigInt, bitSameAsFirst, Bool},
-	OpEQ:     {"==", bitsAllNumber | bitString | bitBigInt, bitSameAsFirst, Bool},
+	OpEQ:     {"==", bitsAllNumber | bitString | bitBigInt | bitUnsafePointer, bitSameAsFirst, Bool},
 	OpEQNil:  {"== nil", bitUnsafePointer, bitNone, Bool},
-	OpNE:     {"!=", bitsAllNumber | bitString | bitBigInt, bitSameAsFirst, Bool},
+	OpNE:     {"!=", bitsAllNumber | bitString | bitBigInt | bitUnsafePointer, bitSameAsFirst, Bool},
 	OpNENil:  {"!= nil", bitUnsafePointer, bitNone, Bool},
 	OpLAnd:   {"&&", bitBool, bitBool, Bool},
 	OpLOr:    {"||", bitBool, bitBool, Bool},
diff --git a/exec/bytecode/exec_op_autogen.go b/exec/bytecode/exec_op_autogen.go
index e654ccd4..b9f0f031 100644
--- a/exec/bytecode/exec_op_autogen.go
+++ b/exec/bytecode/exec_op_autogen.go
@@ -2,313 +2,320 @@ package bytecode
 
 import (
 	"math/big"
+	"reflect"
 )
 
 var builtinOps = [...]func(i Instr, p *Context){
-	(int(BigInt) << bitsOperator) | int(OpQuo):     execQuoBigInt,
-	(int(Int) << bitsOperator) | int(OpAdd):        execAddInt,
-	(int(Int8) << bitsOperator) | int(OpAdd):       execAddInt8,
-	(int(Int16) << bitsOperator) | int(OpAdd):      execAddInt16,
-	(int(Int32) << bitsOperator) | int(OpAdd):      execAddInt32,
-	(int(Int64) << bitsOperator) | int(OpAdd):      execAddInt64,
-	(int(Uint) << bitsOperator) | int(OpAdd):       execAddUint,
-	(int(Uint8) << bitsOperator) | int(OpAdd):      execAddUint8,
-	(int(Uint16) << bitsOperator) | int(OpAdd):     execAddUint16,
-	(int(Uint32) << bitsOperator) | int(OpAdd):     execAddUint32,
-	(int(Uint64) << bitsOperator) | int(OpAdd):     execAddUint64,
-	(int(Uintptr) << bitsOperator) | int(OpAdd):    execAddUintptr,
-	(int(Float32) << bitsOperator) | int(OpAdd):    execAddFloat32,
-	(int(Float64) << bitsOperator) | int(OpAdd):    execAddFloat64,
-	(int(Complex64) << bitsOperator) | int(OpAdd):  execAddComplex64,
-	(int(Complex128) << bitsOperator) | int(OpAdd): execAddComplex128,
-	(int(String) << bitsOperator) | int(OpAdd):     execAddString,
-	(int(BigInt) << bitsOperator) | int(OpAdd):     execAddBigInt,
-	(int(BigRat) << bitsOperator) | int(OpAdd):     execAddBigRat,
-	(int(BigFloat) << bitsOperator) | int(OpAdd):   execAddBigFloat,
-	(int(Int) << bitsOperator) | int(OpSub):        execSubInt,
-	(int(Int8) << bitsOperator) | int(OpSub):       execSubInt8,
-	(int(Int16) << bitsOperator) | int(OpSub):      execSubInt16,
-	(int(Int32) << bitsOperator) | int(OpSub):      execSubInt32,
-	(int(Int64) << bitsOperator) | int(OpSub):      execSubInt64,
-	(int(Uint) << bitsOperator) | int(OpSub):       execSubUint,
-	(int(Uint8) << bitsOperator) | int(OpSub):      execSubUint8,
-	(int(Uint16) << bitsOperator) | int(OpSub):     execSubUint16,
-	(int(Uint32) << bitsOperator) | int(OpSub):     execSubUint32,
-	(int(Uint64) << bitsOperator) | int(OpSub):     execSubUint64,
-	(int(Uintptr) << bitsOperator) | int(OpSub):    execSubUintptr,
-	(int(Float32) << bitsOperator) | int(OpSub):    execSubFloat32,
-	(int(Float64) << bitsOperator) | int(OpSub):    execSubFloat64,
-	(int(Complex64) << bitsOperator) | int(OpSub):  execSubComplex64,
-	(int(Complex128) << bitsOperator) | int(OpSub): execSubComplex128,
-	(int(BigInt) << bitsOperator) | int(OpSub):     execSubBigInt,
-	(int(BigRat) << bitsOperator) | int(OpSub):     execSubBigRat,
-	(int(BigFloat) << bitsOperator) | int(OpSub):   execSubBigFloat,
-	(int(Int) << bitsOperator) | int(OpMul):        execMulInt,
-	(int(Int8) << bitsOperator) | int(OpMul):       execMulInt8,
-	(int(Int16) << bitsOperator) | int(OpMul):      execMulInt16,
-	(int(Int32) << bitsOperator) | int(OpMul):      execMulInt32,
-	(int(Int64) << bitsOperator) | int(OpMul):      execMulInt64,
-	(int(Uint) << bitsOperator) | int(OpMul):       execMulUint,
-	(int(Uint8) << bitsOperator) | int(OpMul):      execMulUint8,
-	(int(Uint16) << bitsOperator) | int(OpMul):     execMulUint16,
-	(int(Uint32) << bitsOperator) | int(OpMul):     execMulUint32,
-	(int(Uint64) << bitsOperator) | int(OpMul):     execMulUint64,
-	(int(Uintptr) << bitsOperator) | int(OpMul):    execMulUintptr,
-	(int(Float32) << bitsOperator) | int(OpMul):    execMulFloat32,
-	(int(Float64) << bitsOperator) | int(OpMul):    execMulFloat64,
-	(int(Complex64) << bitsOperator) | int(OpMul):  execMulComplex64,
-	(int(Complex128) << bitsOperator) | int(OpMul): execMulComplex128,
-	(int(BigInt) << bitsOperator) | int(OpMul):     execMulBigInt,
-	(int(BigRat) << bitsOperator) | int(OpMul):     execMulBigRat,
-	(int(BigFloat) << bitsOperator) | int(OpMul):   execMulBigFloat,
-	(int(Int) << bitsOperator) | int(OpQuo):        execQuoInt,
-	(int(Int8) << bitsOperator) | int(OpQuo):       execQuoInt8,
-	(int(Int16) << bitsOperator) | int(OpQuo):      execQuoInt16,
-	(int(Int32) << bitsOperator) | int(OpQuo):      execQuoInt32,
-	(int(Int64) << bitsOperator) | int(OpQuo):      execQuoInt64,
-	(int(Uint) << bitsOperator) | int(OpQuo):       execQuoUint,
-	(int(Uint8) << bitsOperator) | int(OpQuo):      execQuoUint8,
-	(int(Uint16) << bitsOperator) | int(OpQuo):     execQuoUint16,
-	(int(Uint32) << bitsOperator) | int(OpQuo):     execQuoUint32,
-	(int(Uint64) << bitsOperator) | int(OpQuo):     execQuoUint64,
-	(int(Uintptr) << bitsOperator) | int(OpQuo):    execQuoUintptr,
-	(int(Float32) << bitsOperator) | int(OpQuo):    execQuoFloat32,
-	(int(Float64) << bitsOperator) | int(OpQuo):    execQuoFloat64,
-	(int(Complex64) << bitsOperator) | int(OpQuo):  execQuoComplex64,
-	(int(Complex128) << bitsOperator) | int(OpQuo): execQuoComplex128,
-	(int(BigRat) << bitsOperator) | int(OpQuo):     execQuoBigRat,
-	(int(BigFloat) << bitsOperator) | int(OpQuo):   execQuoBigFloat,
-	(int(Int) << bitsOperator) | int(OpMod):        execModInt,
-	(int(Int8) << bitsOperator) | int(OpMod):       execModInt8,
-	(int(Int16) << bitsOperator) | int(OpMod):      execModInt16,
-	(int(Int32) << bitsOperator) | int(OpMod):      execModInt32,
-	(int(Int64) << bitsOperator) | int(OpMod):      execModInt64,
-	(int(Uint) << bitsOperator) | int(OpMod):       execModUint,
-	(int(Uint8) << bitsOperator) | int(OpMod):      execModUint8,
-	(int(Uint16) << bitsOperator) | int(OpMod):     execModUint16,
-	(int(Uint32) << bitsOperator) | int(OpMod):     execModUint32,
-	(int(Uint64) << bitsOperator) | int(OpMod):     execModUint64,
-	(int(Uintptr) << bitsOperator) | int(OpMod):    execModUintptr,
-	(int(BigInt) << bitsOperator) | int(OpMod):     execModBigInt,
-	(int(Int) << bitsOperator) | int(OpAnd):        execAndInt,
-	(int(Int8) << bitsOperator) | int(OpAnd):       execAndInt8,
-	(int(Int16) << bitsOperator) | int(OpAnd):      execAndInt16,
-	(int(Int32) << bitsOperator) | int(OpAnd):      execAndInt32,
-	(int(Int64) << bitsOperator) | int(OpAnd):      execAndInt64,
-	(int(Uint) << bitsOperator) | int(OpAnd):       execAndUint,
-	(int(Uint8) << bitsOperator) | int(OpAnd):      execAndUint8,
-	(int(Uint16) << bitsOperator) | int(OpAnd):     execAndUint16,
-	(int(Uint32) << bitsOperator) | int(OpAnd):     execAndUint32,
-	(int(Uint64) << bitsOperator) | int(OpAnd):     execAndUint64,
-	(int(Uintptr) << bitsOperator) | int(OpAnd):    execAndUintptr,
-	(int(BigInt) << bitsOperator) | int(OpAnd):     execAndBigInt,
-	(int(Int) << bitsOperator) | int(OpOr):         execOrInt,
-	(int(Int8) << bitsOperator) | int(OpOr):        execOrInt8,
-	(int(Int16) << bitsOperator) | int(OpOr):       execOrInt16,
-	(int(Int32) << bitsOperator) | int(OpOr):       execOrInt32,
-	(int(Int64) << bitsOperator) | int(OpOr):       execOrInt64,
-	(int(Uint) << bitsOperator) | int(OpOr):        execOrUint,
-	(int(Uint8) << bitsOperator) | int(OpOr):       execOrUint8,
-	(int(Uint16) << bitsOperator) | int(OpOr):      execOrUint16,
-	(int(Uint32) << bitsOperator) | int(OpOr):      execOrUint32,
-	(int(Uint64) << bitsOperator) | int(OpOr):      execOrUint64,
-	(int(Uintptr) << bitsOperator) | int(OpOr):     execOrUintptr,
-	(int(BigInt) << bitsOperator) | int(OpOr):      execOrBigInt,
-	(int(Int) << bitsOperator) | int(OpXor):        execXorInt,
-	(int(Int8) << bitsOperator) | int(OpXor):       execXorInt8,
-	(int(Int16) << bitsOperator) | int(OpXor):      execXorInt16,
-	(int(Int32) << bitsOperator) | int(OpXor):      execXorInt32,
-	(int(Int64) << bitsOperator) | int(OpXor):      execXorInt64,
-	(int(Uint) << bitsOperator) | int(OpXor):       execXorUint,
-	(int(Uint8) << bitsOperator) | int(OpXor):      execXorUint8,
-	(int(Uint16) << bitsOperator) | int(OpXor):     execXorUint16,
-	(int(Uint32) << bitsOperator) | int(OpXor):     execXorUint32,
-	(int(Uint64) << bitsOperator) | int(OpXor):     execXorUint64,
-	(int(Uintptr) << bitsOperator) | int(OpXor):    execXorUintptr,
-	(int(BigInt) << bitsOperator) | int(OpXor):     execXorBigInt,
-	(int(Int) << bitsOperator) | int(OpAndNot):     execAndNotInt,
-	(int(Int8) << bitsOperator) | int(OpAndNot):    execAndNotInt8,
-	(int(Int16) << bitsOperator) | int(OpAndNot):   execAndNotInt16,
-	(int(Int32) << bitsOperator) | int(OpAndNot):   execAndNotInt32,
-	(int(Int64) << bitsOperator) | int(OpAndNot):   execAndNotInt64,
-	(int(Uint) << bitsOperator) | int(OpAndNot):    execAndNotUint,
-	(int(Uint8) << bitsOperator) | int(OpAndNot):   execAndNotUint8,
-	(int(Uint16) << bitsOperator) | int(OpAndNot):  execAndNotUint16,
-	(int(Uint32) << bitsOperator) | int(OpAndNot):  execAndNotUint32,
-	(int(Uint64) << bitsOperator) | int(OpAndNot):  execAndNotUint64,
-	(int(Uintptr) << bitsOperator) | int(OpAndNot): execAndNotUintptr,
-	(int(BigInt) << bitsOperator) | int(OpAndNot):  execAndNotBigInt,
-	(int(Int) << bitsOperator) | int(OpLsh):        execLshInt,
-	(int(Int8) << bitsOperator) | int(OpLsh):       execLshInt8,
-	(int(Int16) << bitsOperator) | int(OpLsh):      execLshInt16,
-	(int(Int32) << bitsOperator) | int(OpLsh):      execLshInt32,
-	(int(Int64) << bitsOperator) | int(OpLsh):      execLshInt64,
-	(int(Uint) << bitsOperator) | int(OpLsh):       execLshUint,
-	(int(Uint8) << bitsOperator) | int(OpLsh):      execLshUint8,
-	(int(Uint16) << bitsOperator) | int(OpLsh):     execLshUint16,
-	(int(Uint32) << bitsOperator) | int(OpLsh):     execLshUint32,
-	(int(Uint64) << bitsOperator) | int(OpLsh):     execLshUint64,
-	(int(Uintptr) << bitsOperator) | int(OpLsh):    execLshUintptr,
-	(int(BigInt) << bitsOperator) | int(OpLsh):     execLshBigInt,
-	(int(Int) << bitsOperator) | int(OpRsh):        execRshInt,
-	(int(Int8) << bitsOperator) | int(OpRsh):       execRshInt8,
-	(int(Int16) << bitsOperator) | int(OpRsh):      execRshInt16,
-	(int(Int32) << bitsOperator) | int(OpRsh):      execRshInt32,
-	(int(Int64) << bitsOperator) | int(OpRsh):      execRshInt64,
-	(int(Uint) << bitsOperator) | int(OpRsh):       execRshUint,
-	(int(Uint8) << bitsOperator) | int(OpRsh):      execRshUint8,
-	(int(Uint16) << bitsOperator) | int(OpRsh):     execRshUint16,
-	(int(Uint32) << bitsOperator) | int(OpRsh):     execRshUint32,
-	(int(Uint64) << bitsOperator) | int(OpRsh):     execRshUint64,
-	(int(Uintptr) << bitsOperator) | int(OpRsh):    execRshUintptr,
-	(int(BigInt) << bitsOperator) | int(OpRsh):     execRshBigInt,
-	(int(Int) << bitsOperator) | int(OpLT):         execLTInt,
-	(int(Int8) << bitsOperator) | int(OpLT):        execLTInt8,
-	(int(Int16) << bitsOperator) | int(OpLT):       execLTInt16,
-	(int(Int32) << bitsOperator) | int(OpLT):       execLTInt32,
-	(int(Int64) << bitsOperator) | int(OpLT):       execLTInt64,
-	(int(Uint) << bitsOperator) | int(OpLT):        execLTUint,
-	(int(Uint8) << bitsOperator) | int(OpLT):       execLTUint8,
-	(int(Uint16) << bitsOperator) | int(OpLT):      execLTUint16,
-	(int(Uint32) << bitsOperator) | int(OpLT):      execLTUint32,
-	(int(Uint64) << bitsOperator) | int(OpLT):      execLTUint64,
-	(int(Uintptr) << bitsOperator) | int(OpLT):     execLTUintptr,
-	(int(Float32) << bitsOperator) | int(OpLT):     execLTFloat32,
-	(int(Float64) << bitsOperator) | int(OpLT):     execLTFloat64,
-	(int(String) << bitsOperator) | int(OpLT):      execLTString,
-	(int(BigInt) << bitsOperator) | int(OpLT):      execLTBigInt,
-	(int(BigRat) << bitsOperator) | int(OpLT):      execLTBigRat,
-	(int(BigFloat) << bitsOperator) | int(OpLT):    execLTBigFloat,
-	(int(Int) << bitsOperator) | int(OpLE):         execLEInt,
-	(int(Int8) << bitsOperator) | int(OpLE):        execLEInt8,
-	(int(Int16) << bitsOperator) | int(OpLE):       execLEInt16,
-	(int(Int32) << bitsOperator) | int(OpLE):       execLEInt32,
-	(int(Int64) << bitsOperator) | int(OpLE):       execLEInt64,
-	(int(Uint) << bitsOperator) | int(OpLE):        execLEUint,
-	(int(Uint8) << bitsOperator) | int(OpLE):       execLEUint8,
-	(int(Uint16) << bitsOperator) | int(OpLE):      execLEUint16,
-	(int(Uint32) << bitsOperator) | int(OpLE):      execLEUint32,
-	(int(Uint64) << bitsOperator) | int(OpLE):      execLEUint64,
-	(int(Uintptr) << bitsOperator) | int(OpLE):     execLEUintptr,
-	(int(Float32) << bitsOperator) | int(OpLE):     execLEFloat32,
-	(int(Float64) << bitsOperator) | int(OpLE):     execLEFloat64,
-	(int(String) << bitsOperator) | int(OpLE):      execLEString,
-	(int(BigInt) << bitsOperator) | int(OpLE):      execLEBigInt,
-	(int(BigRat) << bitsOperator) | int(OpLE):      execLEBigRat,
-	(int(BigFloat) << bitsOperator) | int(OpLE):    execLEBigFloat,
-	(int(Int) << bitsOperator) | int(OpGT):         execGTInt,
-	(int(Int8) << bitsOperator) | int(OpGT):        execGTInt8,
-	(int(Int16) << bitsOperator) | int(OpGT):       execGTInt16,
-	(int(Int32) << bitsOperator) | int(OpGT):       execGTInt32,
-	(int(Int64) << bitsOperator) | int(OpGT):       execGTInt64,
-	(int(Uint) << bitsOperator) | int(OpGT):        execGTUint,
-	(int(Uint8) << bitsOperator) | int(OpGT):       execGTUint8,
-	(int(Uint16) << bitsOperator) | int(OpGT):      execGTUint16,
-	(int(Uint32) << bitsOperator) | int(OpGT):      execGTUint32,
-	(int(Uint64) << bitsOperator) | int(OpGT):      execGTUint64,
-	(int(Uintptr) << bitsOperator) | int(OpGT):     execGTUintptr,
-	(int(Float32) << bitsOperator) | int(OpGT):     execGTFloat32,
-	(int(Float64) << bitsOperator) | int(OpGT):     execGTFloat64,
-	(int(String) << bitsOperator) | int(OpGT):      execGTString,
-	(int(BigInt) << bitsOperator) | int(OpGT):      execGTBigInt,
-	(int(BigRat) << bitsOperator) | int(OpGT):      execGTBigRat,
-	(int(BigFloat) << bitsOperator) | int(OpGT):    execGTBigFloat,
-	(int(Int) << bitsOperator) | int(OpGE):         execGEInt,
-	(int(Int8) << bitsOperator) | int(OpGE):        execGEInt8,
-	(int(Int16) << bitsOperator) | int(OpGE):       execGEInt16,
-	(int(Int32) << bitsOperator) | int(OpGE):       execGEInt32,
-	(int(Int64) << bitsOperator) | int(OpGE):       execGEInt64,
-	(int(Uint) << bitsOperator) | int(OpGE):        execGEUint,
-	(int(Uint8) << bitsOperator) | int(OpGE):       execGEUint8,
-	(int(Uint16) << bitsOperator) | int(OpGE):      execGEUint16,
-	(int(Uint32) << bitsOperator) | int(OpGE):      execGEUint32,
-	(int(Uint64) << bitsOperator) | int(OpGE):      execGEUint64,
-	(int(Uintptr) << bitsOperator) | int(OpGE):     execGEUintptr,
-	(int(Float32) << bitsOperator) | int(OpGE):     execGEFloat32,
-	(int(Float64) << bitsOperator) | int(OpGE):     execGEFloat64,
-	(int(String) << bitsOperator) | int(OpGE):      execGEString,
-	(int(BigInt) << bitsOperator) | int(OpGE):      execGEBigInt,
-	(int(BigRat) << bitsOperator) | int(OpGE):      execGEBigRat,
-	(int(BigFloat) << bitsOperator) | int(OpGE):    execGEBigFloat,
-	(int(Int) << bitsOperator) | int(OpEQ):         execEQInt,
-	(int(Int8) << bitsOperator) | int(OpEQ):        execEQInt8,
-	(int(Int16) << bitsOperator) | int(OpEQ):       execEQInt16,
-	(int(Int32) << bitsOperator) | int(OpEQ):       execEQInt32,
-	(int(Int64) << bitsOperator) | int(OpEQ):       execEQInt64,
-	(int(Uint) << bitsOperator) | int(OpEQ):        execEQUint,
-	(int(Uint8) << bitsOperator) | int(OpEQ):       execEQUint8,
-	(int(Uint16) << bitsOperator) | int(OpEQ):      execEQUint16,
-	(int(Uint32) << bitsOperator) | int(OpEQ):      execEQUint32,
-	(int(Uint64) << bitsOperator) | int(OpEQ):      execEQUint64,
-	(int(Uintptr) << bitsOperator) | int(OpEQ):     execEQUintptr,
-	(int(Float32) << bitsOperator) | int(OpEQ):     execEQFloat32,
-	(int(Float64) << bitsOperator) | int(OpEQ):     execEQFloat64,
-	(int(Complex64) << bitsOperator) | int(OpEQ):   execEQComplex64,
-	(int(Complex128) << bitsOperator) | int(OpEQ):  execEQComplex128,
-	(int(String) << bitsOperator) | int(OpEQ):      execEQString,
-	(int(BigInt) << bitsOperator) | int(OpEQ):      execEQBigInt,
-	(int(BigRat) << bitsOperator) | int(OpEQ):      execEQBigRat,
-	(int(BigFloat) << bitsOperator) | int(OpEQ):    execEQBigFloat,
-	(int(Int) << bitsOperator) | int(OpNE):         execNEInt,
-	(int(Int8) << bitsOperator) | int(OpNE):        execNEInt8,
-	(int(Int16) << bitsOperator) | int(OpNE):       execNEInt16,
-	(int(Int32) << bitsOperator) | int(OpNE):       execNEInt32,
-	(int(Int64) << bitsOperator) | int(OpNE):       execNEInt64,
-	(int(Uint) << bitsOperator) | int(OpNE):        execNEUint,
-	(int(Uint8) << bitsOperator) | int(OpNE):       execNEUint8,
-	(int(Uint16) << bitsOperator) | int(OpNE):      execNEUint16,
-	(int(Uint32) << bitsOperator) | int(OpNE):      execNEUint32,
-	(int(Uint64) << bitsOperator) | int(OpNE):      execNEUint64,
-	(int(Uintptr) << bitsOperator) | int(OpNE):     execNEUintptr,
-	(int(Float32) << bitsOperator) | int(OpNE):     execNEFloat32,
-	(int(Float64) << bitsOperator) | int(OpNE):     execNEFloat64,
-	(int(Complex64) << bitsOperator) | int(OpNE):   execNEComplex64,
-	(int(Complex128) << bitsOperator) | int(OpNE):  execNEComplex128,
-	(int(String) << bitsOperator) | int(OpNE):      execNEString,
-	(int(BigInt) << bitsOperator) | int(OpNE):      execNEBigInt,
-	(int(BigRat) << bitsOperator) | int(OpNE):      execNEBigRat,
-	(int(BigFloat) << bitsOperator) | int(OpNE):    execNEBigFloat,
-	(int(Bool) << bitsOperator) | int(OpLAnd):      execLAndBool,
-	(int(Bool) << bitsOperator) | int(OpLOr):       execLOrBool,
-	(int(Bool) << bitsOperator) | int(OpLNot):      execLNotBool,
-	(int(Int) << bitsOperator) | int(OpNeg):        execNegInt,
-	(int(Int8) << bitsOperator) | int(OpNeg):       execNegInt8,
-	(int(Int16) << bitsOperator) | int(OpNeg):      execNegInt16,
-	(int(Int32) << bitsOperator) | int(OpNeg):      execNegInt32,
-	(int(Int64) << bitsOperator) | int(OpNeg):      execNegInt64,
-	(int(Uint) << bitsOperator) | int(OpNeg):       execNegUint,
-	(int(Uint8) << bitsOperator) | int(OpNeg):      execNegUint8,
-	(int(Uint16) << bitsOperator) | int(OpNeg):     execNegUint16,
-	(int(Uint32) << bitsOperator) | int(OpNeg):     execNegUint32,
-	(int(Uint64) << bitsOperator) | int(OpNeg):     execNegUint64,
-	(int(Uintptr) << bitsOperator) | int(OpNeg):    execNegUintptr,
-	(int(Float32) << bitsOperator) | int(OpNeg):    execNegFloat32,
-	(int(Float64) << bitsOperator) | int(OpNeg):    execNegFloat64,
-	(int(Complex64) << bitsOperator) | int(OpNeg):  execNegComplex64,
-	(int(Complex128) << bitsOperator) | int(OpNeg): execNegComplex128,
-	(int(BigInt) << bitsOperator) | int(OpNeg):     execNegBigInt,
-	(int(BigRat) << bitsOperator) | int(OpNeg):     execNegBigRat,
-	(int(BigFloat) << bitsOperator) | int(OpNeg):   execNegBigFloat,
-	(int(Int) << bitsOperator) | int(OpBitNot):     execBitNotInt,
-	(int(Int8) << bitsOperator) | int(OpBitNot):    execBitNotInt8,
-	(int(Int16) << bitsOperator) | int(OpBitNot):   execBitNotInt16,
-	(int(Int32) << bitsOperator) | int(OpBitNot):   execBitNotInt32,
-	(int(Int64) << bitsOperator) | int(OpBitNot):   execBitNotInt64,
-	(int(Uint) << bitsOperator) | int(OpBitNot):    execBitNotUint,
-	(int(Uint8) << bitsOperator) | int(OpBitNot):   execBitNotUint8,
-	(int(Uint16) << bitsOperator) | int(OpBitNot):  execBitNotUint16,
-	(int(Uint32) << bitsOperator) | int(OpBitNot):  execBitNotUint32,
-	(int(Uint64) << bitsOperator) | int(OpBitNot):  execBitNotUint64,
-	(int(Uintptr) << bitsOperator) | int(OpBitNot): execBitNotUintptr,
-	(int(BigInt) << bitsOperator) | int(OpBitNot):  execBitNotBigInt,
-	(int(Slice) << bitsOperator) | int(OpEQ):       execRefTypeEQ,
-	(int(Map) << bitsOperator) | int(OpEQ):         execRefTypeEQ,
-	(int(Chan) << bitsOperator) | int(OpEQ):        execRefTypeEQ,
-	(int(Ptr) << bitsOperator) | int(OpEQ):         execRefTypeEQ,
-	(int(Slice) << bitsOperator) | int(OpNE):       execRefTypeNEQ,
-	(int(Map) << bitsOperator) | int(OpNE):         execRefTypeNEQ,
-	(int(Chan) << bitsOperator) | int(OpNE):        execRefTypeNEQ,
-	(int(Ptr) << bitsOperator) | int(OpNE):         execRefTypeNEQ,
+	(int(BigInt) << bitsOperator) | int(OpQuo):           execQuoBigInt,
+	(int(Int) << bitsOperator) | int(OpAdd):              execAddInt,
+	(int(Int8) << bitsOperator) | int(OpAdd):             execAddInt8,
+	(int(Int16) << bitsOperator) | int(OpAdd):            execAddInt16,
+	(int(Int32) << bitsOperator) | int(OpAdd):            execAddInt32,
+	(int(Int64) << bitsOperator) | int(OpAdd):            execAddInt64,
+	(int(Uint) << bitsOperator) | int(OpAdd):             execAddUint,
+	(int(Uint8) << bitsOperator) | int(OpAdd):            execAddUint8,
+	(int(Uint16) << bitsOperator) | int(OpAdd):           execAddUint16,
+	(int(Uint32) << bitsOperator) | int(OpAdd):           execAddUint32,
+	(int(Uint64) << bitsOperator) | int(OpAdd):           execAddUint64,
+	(int(Uintptr) << bitsOperator) | int(OpAdd):          execAddUintptr,
+	(int(Float32) << bitsOperator) | int(OpAdd):          execAddFloat32,
+	(int(Float64) << bitsOperator) | int(OpAdd):          execAddFloat64,
+	(int(Complex64) << bitsOperator) | int(OpAdd):        execAddComplex64,
+	(int(Complex128) << bitsOperator) | int(OpAdd):       execAddComplex128,
+	(int(String) << bitsOperator) | int(OpAdd):           execAddString,
+	(int(BigInt) << bitsOperator) | int(OpAdd):           execAddBigInt,
+	(int(BigRat) << bitsOperator) | int(OpAdd):           execAddBigRat,
+	(int(BigFloat) << bitsOperator) | int(OpAdd):         execAddBigFloat,
+	(int(Int) << bitsOperator) | int(OpSub):              execSubInt,
+	(int(Int8) << bitsOperator) | int(OpSub):             execSubInt8,
+	(int(Int16) << bitsOperator) | int(OpSub):            execSubInt16,
+	(int(Int32) << bitsOperator) | int(OpSub):            execSubInt32,
+	(int(Int64) << bitsOperator) | int(OpSub):            execSubInt64,
+	(int(Uint) << bitsOperator) | int(OpSub):             execSubUint,
+	(int(Uint8) << bitsOperator) | int(OpSub):            execSubUint8,
+	(int(Uint16) << bitsOperator) | int(OpSub):           execSubUint16,
+	(int(Uint32) << bitsOperator) | int(OpSub):           execSubUint32,
+	(int(Uint64) << bitsOperator) | int(OpSub):           execSubUint64,
+	(int(Uintptr) << bitsOperator) | int(OpSub):          execSubUintptr,
+	(int(Float32) << bitsOperator) | int(OpSub):          execSubFloat32,
+	(int(Float64) << bitsOperator) | int(OpSub):          execSubFloat64,
+	(int(Complex64) << bitsOperator) | int(OpSub):        execSubComplex64,
+	(int(Complex128) << bitsOperator) | int(OpSub):       execSubComplex128,
+	(int(BigInt) << bitsOperator) | int(OpSub):           execSubBigInt,
+	(int(BigRat) << bitsOperator) | int(OpSub):           execSubBigRat,
+	(int(BigFloat) << bitsOperator) | int(OpSub):         execSubBigFloat,
+	(int(Int) << bitsOperator) | int(OpMul):              execMulInt,
+	(int(Int8) << bitsOperator) | int(OpMul):             execMulInt8,
+	(int(Int16) << bitsOperator) | int(OpMul):            execMulInt16,
+	(int(Int32) << bitsOperator) | int(OpMul):            execMulInt32,
+	(int(Int64) << bitsOperator) | int(OpMul):            execMulInt64,
+	(int(Uint) << bitsOperator) | int(OpMul):             execMulUint,
+	(int(Uint8) << bitsOperator) | int(OpMul):            execMulUint8,
+	(int(Uint16) << bitsOperator) | int(OpMul):           execMulUint16,
+	(int(Uint32) << bitsOperator) | int(OpMul):           execMulUint32,
+	(int(Uint64) << bitsOperator) | int(OpMul):           execMulUint64,
+	(int(Uintptr) << bitsOperator) | int(OpMul):          execMulUintptr,
+	(int(Float32) << bitsOperator) | int(OpMul):          execMulFloat32,
+	(int(Float64) << bitsOperator) | int(OpMul):          execMulFloat64,
+	(int(Complex64) << bitsOperator) | int(OpMul):        execMulComplex64,
+	(int(Complex128) << bitsOperator) | int(OpMul):       execMulComplex128,
+	(int(BigInt) << bitsOperator) | int(OpMul):           execMulBigInt,
+	(int(BigRat) << bitsOperator) | int(OpMul):           execMulBigRat,
+	(int(BigFloat) << bitsOperator) | int(OpMul):         execMulBigFloat,
+	(int(Int) << bitsOperator) | int(OpQuo):              execQuoInt,
+	(int(Int8) << bitsOperator) | int(OpQuo):             execQuoInt8,
+	(int(Int16) << bitsOperator) | int(OpQuo):            execQuoInt16,
+	(int(Int32) << bitsOperator) | int(OpQuo):            execQuoInt32,
+	(int(Int64) << bitsOperator) | int(OpQuo):            execQuoInt64,
+	(int(Uint) << bitsOperator) | int(OpQuo):             execQuoUint,
+	(int(Uint8) << bitsOperator) | int(OpQuo):            execQuoUint8,
+	(int(Uint16) << bitsOperator) | int(OpQuo):           execQuoUint16,
+	(int(Uint32) << bitsOperator) | int(OpQuo):           execQuoUint32,
+	(int(Uint64) << bitsOperator) | int(OpQuo):           execQuoUint64,
+	(int(Uintptr) << bitsOperator) | int(OpQuo):          execQuoUintptr,
+	(int(Float32) << bitsOperator) | int(OpQuo):          execQuoFloat32,
+	(int(Float64) << bitsOperator) | int(OpQuo):          execQuoFloat64,
+	(int(Complex64) << bitsOperator) | int(OpQuo):        execQuoComplex64,
+	(int(Complex128) << bitsOperator) | int(OpQuo):       execQuoComplex128,
+	(int(BigRat) << bitsOperator) | int(OpQuo):           execQuoBigRat,
+	(int(BigFloat) << bitsOperator) | int(OpQuo):         execQuoBigFloat,
+	(int(Int) << bitsOperator) | int(OpMod):              execModInt,
+	(int(Int8) << bitsOperator) | int(OpMod):             execModInt8,
+	(int(Int16) << bitsOperator) | int(OpMod):            execModInt16,
+	(int(Int32) << bitsOperator) | int(OpMod):            execModInt32,
+	(int(Int64) << bitsOperator) | int(OpMod):            execModInt64,
+	(int(Uint) << bitsOperator) | int(OpMod):             execModUint,
+	(int(Uint8) << bitsOperator) | int(OpMod):            execModUint8,
+	(int(Uint16) << bitsOperator) | int(OpMod):           execModUint16,
+	(int(Uint32) << bitsOperator) | int(OpMod):           execModUint32,
+	(int(Uint64) << bitsOperator) | int(OpMod):           execModUint64,
+	(int(Uintptr) << bitsOperator) | int(OpMod):          execModUintptr,
+	(int(BigInt) << bitsOperator) | int(OpMod):           execModBigInt,
+	(int(Int) << bitsOperator) | int(OpAnd):              execAndInt,
+	(int(Int8) << bitsOperator) | int(OpAnd):             execAndInt8,
+	(int(Int16) << bitsOperator) | int(OpAnd):            execAndInt16,
+	(int(Int32) << bitsOperator) | int(OpAnd):            execAndInt32,
+	(int(Int64) << bitsOperator) | int(OpAnd):            execAndInt64,
+	(int(Uint) << bitsOperator) | int(OpAnd):             execAndUint,
+	(int(Uint8) << bitsOperator) | int(OpAnd):            execAndUint8,
+	(int(Uint16) << bitsOperator) | int(OpAnd):           execAndUint16,
+	(int(Uint32) << bitsOperator) | int(OpAnd):           execAndUint32,
+	(int(Uint64) << bitsOperator) | int(OpAnd):           execAndUint64,
+	(int(Uintptr) << bitsOperator) | int(OpAnd):          execAndUintptr,
+	(int(BigInt) << bitsOperator) | int(OpAnd):           execAndBigInt,
+	(int(Int) << bitsOperator) | int(OpOr):               execOrInt,
+	(int(Int8) << bitsOperator) | int(OpOr):              execOrInt8,
+	(int(Int16) << bitsOperator) | int(OpOr):             execOrInt16,
+	(int(Int32) << bitsOperator) | int(OpOr):             execOrInt32,
+	(int(Int64) << bitsOperator) | int(OpOr):             execOrInt64,
+	(int(Uint) << bitsOperator) | int(OpOr):              execOrUint,
+	(int(Uint8) << bitsOperator) | int(OpOr):             execOrUint8,
+	(int(Uint16) << bitsOperator) | int(OpOr):            execOrUint16,
+	(int(Uint32) << bitsOperator) | int(OpOr):            execOrUint32,
+	(int(Uint64) << bitsOperator) | int(OpOr):            execOrUint64,
+	(int(Uintptr) << bitsOperator) | int(OpOr):           execOrUintptr,
+	(int(BigInt) << bitsOperator) | int(OpOr):            execOrBigInt,
+	(int(Int) << bitsOperator) | int(OpXor):              execXorInt,
+	(int(Int8) << bitsOperator) | int(OpXor):             execXorInt8,
+	(int(Int16) << bitsOperator) | int(OpXor):            execXorInt16,
+	(int(Int32) << bitsOperator) | int(OpXor):            execXorInt32,
+	(int(Int64) << bitsOperator) | int(OpXor):            execXorInt64,
+	(int(Uint) << bitsOperator) | int(OpXor):             execXorUint,
+	(int(Uint8) << bitsOperator) | int(OpXor):            execXorUint8,
+	(int(Uint16) << bitsOperator) | int(OpXor):           execXorUint16,
+	(int(Uint32) << bitsOperator) | int(OpXor):           execXorUint32,
+	(int(Uint64) << bitsOperator) | int(OpXor):           execXorUint64,
+	(int(Uintptr) << bitsOperator) | int(OpXor):          execXorUintptr,
+	(int(BigInt) << bitsOperator) | int(OpXor):           execXorBigInt,
+	(int(Int) << bitsOperator) | int(OpAndNot):           execAndNotInt,
+	(int(Int8) << bitsOperator) | int(OpAndNot):          execAndNotInt8,
+	(int(Int16) << bitsOperator) | int(OpAndNot):         execAndNotInt16,
+	(int(Int32) << bitsOperator) | int(OpAndNot):         execAndNotInt32,
+	(int(Int64) << bitsOperator) | int(OpAndNot):         execAndNotInt64,
+	(int(Uint) << bitsOperator) | int(OpAndNot):          execAndNotUint,
+	(int(Uint8) << bitsOperator) | int(OpAndNot):         execAndNotUint8,
+	(int(Uint16) << bitsOperator) | int(OpAndNot):        execAndNotUint16,
+	(int(Uint32) << bitsOperator) | int(OpAndNot):        execAndNotUint32,
+	(int(Uint64) << bitsOperator) | int(OpAndNot):        execAndNotUint64,
+	(int(Uintptr) << bitsOperator) | int(OpAndNot):       execAndNotUintptr,
+	(int(BigInt) << bitsOperator) | int(OpAndNot):        execAndNotBigInt,
+	(int(Int) << bitsOperator) | int(OpLsh):              execLshInt,
+	(int(Int8) << bitsOperator) | int(OpLsh):             execLshInt8,
+	(int(Int16) << bitsOperator) | int(OpLsh):            execLshInt16,
+	(int(Int32) << bitsOperator) | int(OpLsh):            execLshInt32,
+	(int(Int64) << bitsOperator) | int(OpLsh):            execLshInt64,
+	(int(Uint) << bitsOperator) | int(OpLsh):             execLshUint,
+	(int(Uint8) << bitsOperator) | int(OpLsh):            execLshUint8,
+	(int(Uint16) << bitsOperator) | int(OpLsh):           execLshUint16,
+	(int(Uint32) << bitsOperator) | int(OpLsh):           execLshUint32,
+	(int(Uint64) << bitsOperator) | int(OpLsh):           execLshUint64,
+	(int(Uintptr) << bitsOperator) | int(OpLsh):          execLshUintptr,
+	(int(BigInt) << bitsOperator) | int(OpLsh):           execLshBigInt,
+	(int(Int) << bitsOperator) | int(OpRsh):              execRshInt,
+	(int(Int8) << bitsOperator) | int(OpRsh):             execRshInt8,
+	(int(Int16) << bitsOperator) | int(OpRsh):            execRshInt16,
+	(int(Int32) << bitsOperator) | int(OpRsh):            execRshInt32,
+	(int(Int64) << bitsOperator) | int(OpRsh):            execRshInt64,
+	(int(Uint) << bitsOperator) | int(OpRsh):             execRshUint,
+	(int(Uint8) << bitsOperator) | int(OpRsh):            execRshUint8,
+	(int(Uint16) << bitsOperator) | int(OpRsh):           execRshUint16,
+	(int(Uint32) << bitsOperator) | int(OpRsh):           execRshUint32,
+	(int(Uint64) << bitsOperator) | int(OpRsh):           execRshUint64,
+	(int(Uintptr) << bitsOperator) | int(OpRsh):          execRshUintptr,
+	(int(BigInt) << bitsOperator) | int(OpRsh):           execRshBigInt,
+	(int(Int) << bitsOperator) | int(OpLT):               execLTInt,
+	(int(Int8) << bitsOperator) | int(OpLT):              execLTInt8,
+	(int(Int16) << bitsOperator) | int(OpLT):             execLTInt16,
+	(int(Int32) << bitsOperator) | int(OpLT):             execLTInt32,
+	(int(Int64) << bitsOperator) | int(OpLT):             execLTInt64,
+	(int(Uint) << bitsOperator) | int(OpLT):              execLTUint,
+	(int(Uint8) << bitsOperator) | int(OpLT):             execLTUint8,
+	(int(Uint16) << bitsOperator) | int(OpLT):            execLTUint16,
+	(int(Uint32) << bitsOperator) | int(OpLT):            execLTUint32,
+	(int(Uint64) << bitsOperator) | int(OpLT):            execLTUint64,
+	(int(Uintptr) << bitsOperator) | int(OpLT):           execLTUintptr,
+	(int(Float32) << bitsOperator) | int(OpLT):           execLTFloat32,
+	(int(Float64) << bitsOperator) | int(OpLT):           execLTFloat64,
+	(int(String) << bitsOperator) | int(OpLT):            execLTString,
+	(int(BigInt) << bitsOperator) | int(OpLT):            execLTBigInt,
+	(int(BigRat) << bitsOperator) | int(OpLT):            execLTBigRat,
+	(int(BigFloat) << bitsOperator) | int(OpLT):          execLTBigFloat,
+	(int(Int) << bitsOperator) | int(OpLE):               execLEInt,
+	(int(Int8) << bitsOperator) | int(OpLE):              execLEInt8,
+	(int(Int16) << bitsOperator) | int(OpLE):             execLEInt16,
+	(int(Int32) << bitsOperator) | int(OpLE):             execLEInt32,
+	(int(Int64) << bitsOperator) | int(OpLE):             execLEInt64,
+	(int(Uint) << bitsOperator) | int(OpLE):              execLEUint,
+	(int(Uint8) << bitsOperator) | int(OpLE):             execLEUint8,
+	(int(Uint16) << bitsOperator) | int(OpLE):            execLEUint16,
+	(int(Uint32) << bitsOperator) | int(OpLE):            execLEUint32,
+	(int(Uint64) << bitsOperator) | int(OpLE):            execLEUint64,
+	(int(Uintptr) << bitsOperator) | int(OpLE):           execLEUintptr,
+	(int(Float32) << bitsOperator) | int(OpLE):           execLEFloat32,
+	(int(Float64) << bitsOperator) | int(OpLE):           execLEFloat64,
+	(int(String) << bitsOperator) | int(OpLE):            execLEString,
+	(int(BigInt) << bitsOperator) | int(OpLE):            execLEBigInt,
+	(int(BigRat) << bitsOperator) | int(OpLE):            execLEBigRat,
+	(int(BigFloat) << bitsOperator) | int(OpLE):          execLEBigFloat,
+	(int(Int) << bitsOperator) | int(OpGT):               execGTInt,
+	(int(Int8) << bitsOperator) | int(OpGT):              execGTInt8,
+	(int(Int16) << bitsOperator) | int(OpGT):             execGTInt16,
+	(int(Int32) << bitsOperator) | int(OpGT):             execGTInt32,
+	(int(Int64) << bitsOperator) | int(OpGT):             execGTInt64,
+	(int(Uint) << bitsOperator) | int(OpGT):              execGTUint,
+	(int(Uint8) << bitsOperator) | int(OpGT):             execGTUint8,
+	(int(Uint16) << bitsOperator) | int(OpGT):            execGTUint16,
+	(int(Uint32) << bitsOperator) | int(OpGT):            execGTUint32,
+	(int(Uint64) << bitsOperator) | int(OpGT):            execGTUint64,
+	(int(Uintptr) << bitsOperator) | int(OpGT):           execGTUintptr,
+	(int(Float32) << bitsOperator) | int(OpGT):           execGTFloat32,
+	(int(Float64) << bitsOperator) | int(OpGT):           execGTFloat64,
+	(int(String) << bitsOperator) | int(OpGT):            execGTString,
+	(int(BigInt) << bitsOperator) | int(OpGT):            execGTBigInt,
+	(int(BigRat) << bitsOperator) | int(OpGT):            execGTBigRat,
+	(int(BigFloat) << bitsOperator) | int(OpGT):          execGTBigFloat,
+	(int(Int) << bitsOperator) | int(OpGE):               execGEInt,
+	(int(Int8) << bitsOperator) | int(OpGE):              execGEInt8,
+	(int(Int16) << bitsOperator) | int(OpGE):             execGEInt16,
+	(int(Int32) << bitsOperator) | int(OpGE):             execGEInt32,
+	(int(Int64) << bitsOperator) | int(OpGE):             execGEInt64,
+	(int(Uint) << bitsOperator) | int(OpGE):              execGEUint,
+	(int(Uint8) << bitsOperator) | int(OpGE):             execGEUint8,
+	(int(Uint16) << bitsOperator) | int(OpGE):            execGEUint16,
+	(int(Uint32) << bitsOperator) | int(OpGE):            execGEUint32,
+	(int(Uint64) << bitsOperator) | int(OpGE):            execGEUint64,
+	(int(Uintptr) << bitsOperator) | int(OpGE):           execGEUintptr,
+	(int(Float32) << bitsOperator) | int(OpGE):           execGEFloat32,
+	(int(Float64) << bitsOperator) | int(OpGE):           execGEFloat64,
+	(int(String) << bitsOperator) | int(OpGE):            execGEString,
+	(int(BigInt) << bitsOperator) | int(OpGE):            execGEBigInt,
+	(int(BigRat) << bitsOperator) | int(OpGE):            execGEBigRat,
+	(int(BigFloat) << bitsOperator) | int(OpGE):          execGEBigFloat,
+	(int(Int) << bitsOperator) | int(OpEQ):               execEQInt,
+	(int(Int8) << bitsOperator) | int(OpEQ):              execEQInt8,
+	(int(Int16) << bitsOperator) | int(OpEQ):             execEQInt16,
+	(int(Int32) << bitsOperator) | int(OpEQ):             execEQInt32,
+	(int(Int64) << bitsOperator) | int(OpEQ):             execEQInt64,
+	(int(Uint) << bitsOperator) | int(OpEQ):              execEQUint,
+	(int(Uint8) << bitsOperator) | int(OpEQ):             execEQUint8,
+	(int(Uint16) << bitsOperator) | int(OpEQ):            execEQUint16,
+	(int(Uint32) << bitsOperator) | int(OpEQ):            execEQUint32,
+	(int(Uint64) << bitsOperator) | int(OpEQ):            execEQUint64,
+	(int(Uintptr) << bitsOperator) | int(OpEQ):           execEQUintptr,
+	(int(Float32) << bitsOperator) | int(OpEQ):           execEQFloat32,
+	(int(Float64) << bitsOperator) | int(OpEQ):           execEQFloat64,
+	(int(Complex64) << bitsOperator) | int(OpEQ):         execEQComplex64,
+	(int(Complex128) << bitsOperator) | int(OpEQ):        execEQComplex128,
+	(int(String) << bitsOperator) | int(OpEQ):            execEQString,
+	(int(BigInt) << bitsOperator) | int(OpEQ):            execEQBigInt,
+	(int(BigRat) << bitsOperator) | int(OpEQ):            execEQBigRat,
+	(int(BigFloat) << bitsOperator) | int(OpEQ):          execEQBigFloat,
+	(int(Int) << bitsOperator) | int(OpNE):               execNEInt,
+	(int(Int8) << bitsOperator) | int(OpNE):              execNEInt8,
+	(int(Int16) << bitsOperator) | int(OpNE):             execNEInt16,
+	(int(Int32) << bitsOperator) | int(OpNE):             execNEInt32,
+	(int(Int64) << bitsOperator) | int(OpNE):             execNEInt64,
+	(int(Uint) << bitsOperator) | int(OpNE):              execNEUint,
+	(int(Uint8) << bitsOperator) | int(OpNE):             execNEUint8,
+	(int(Uint16) << bitsOperator) | int(OpNE):            execNEUint16,
+	(int(Uint32) << bitsOperator) | int(OpNE):            execNEUint32,
+	(int(Uint64) << bitsOperator) | int(OpNE):            execNEUint64,
+	(int(Uintptr) << bitsOperator) | int(OpNE):           execNEUintptr,
+	(int(Float32) << bitsOperator) | int(OpNE):           execNEFloat32,
+	(int(Float64) << bitsOperator) | int(OpNE):           execNEFloat64,
+	(int(Complex64) << bitsOperator) | int(OpNE):         execNEComplex64,
+	(int(Complex128) << bitsOperator) | int(OpNE):        execNEComplex128,
+	(int(String) << bitsOperator) | int(OpNE):            execNEString,
+	(int(BigInt) << bitsOperator) | int(OpNE):            execNEBigInt,
+	(int(BigRat) << bitsOperator) | int(OpNE):            execNEBigRat,
+	(int(BigFloat) << bitsOperator) | int(OpNE):          execNEBigFloat,
+	(int(Bool) << bitsOperator) | int(OpLAnd):            execLAndBool,
+	(int(Bool) << bitsOperator) | int(OpLOr):             execLOrBool,
+	(int(Bool) << bitsOperator) | int(OpLNot):            execLNotBool,
+	(int(Int) << bitsOperator) | int(OpNeg):              execNegInt,
+	(int(Int8) << bitsOperator) | int(OpNeg):             execNegInt8,
+	(int(Int16) << bitsOperator) | int(OpNeg):            execNegInt16,
+	(int(Int32) << bitsOperator) | int(OpNeg):            execNegInt32,
+	(int(Int64) << bitsOperator) | int(OpNeg):            execNegInt64,
+	(int(Uint) << bitsOperator) | int(OpNeg):             execNegUint,
+	(int(Uint8) << bitsOperator) | int(OpNeg):            execNegUint8,
+	(int(Uint16) << bitsOperator) | int(OpNeg):           execNegUint16,
+	(int(Uint32) << bitsOperator) | int(OpNeg):           execNegUint32,
+	(int(Uint64) << bitsOperator) | int(OpNeg):           execNegUint64,
+	(int(Uintptr) << bitsOperator) | int(OpNeg):          execNegUintptr,
+	(int(Float32) << bitsOperator) | int(OpNeg):          execNegFloat32,
+	(int(Float64) << bitsOperator) | int(OpNeg):          execNegFloat64,
+	(int(Complex64) << bitsOperator) | int(OpNeg):        execNegComplex64,
+	(int(Complex128) << bitsOperator) | int(OpNeg):       execNegComplex128,
+	(int(BigInt) << bitsOperator) | int(OpNeg):           execNegBigInt,
+	(int(BigRat) << bitsOperator) | int(OpNeg):           execNegBigRat,
+	(int(BigFloat) << bitsOperator) | int(OpNeg):         execNegBigFloat,
+	(int(Int) << bitsOperator) | int(OpBitNot):           execBitNotInt,
+	(int(Int8) << bitsOperator) | int(OpBitNot):          execBitNotInt8,
+	(int(Int16) << bitsOperator) | int(OpBitNot):         execBitNotInt16,
+	(int(Int32) << bitsOperator) | int(OpBitNot):         execBitNotInt32,
+	(int(Int64) << bitsOperator) | int(OpBitNot):         execBitNotInt64,
+	(int(Uint) << bitsOperator) | int(OpBitNot):          execBitNotUint,
+	(int(Uint8) << bitsOperator) | int(OpBitNot):         execBitNotUint8,
+	(int(Uint16) << bitsOperator) | int(OpBitNot):        execBitNotUint16,
+	(int(Uint32) << bitsOperator) | int(OpBitNot):        execBitNotUint32,
+	(int(Uint64) << bitsOperator) | int(OpBitNot):        execBitNotUint64,
+	(int(Uintptr) << bitsOperator) | int(OpBitNot):       execBitNotUintptr,
+	(int(BigInt) << bitsOperator) | int(OpBitNot):        execBitNotBigInt,
+	(int(Slice) << bitsOperator) | int(OpEQ):             execRefTypeEQ,
+	(int(Map) << bitsOperator) | int(OpEQ):               execRefTypeEQ,
+	(int(Chan) << bitsOperator) | int(OpEQ):              execRefTypeEQ,
+	(int(Ptr) << bitsOperator) | int(OpEQ):               execRefTypeEQ,
+	(int(Slice) << bitsOperator) | int(OpNE):             execRefTypeNE,
+	(int(Map) << bitsOperator) | int(OpNE):               execRefTypeNE,
+	(int(Chan) << bitsOperator) | int(OpNE):              execRefTypeNE,
+	(int(Ptr) << bitsOperator) | int(OpNE):               execRefTypeNE,
+	(int(UnsafePointer) << bitsOperator) | int(OpEQ):     execRefTypeEQ,
+	(int(UnsafePointer) << bitsOperator) | int(OpNE):     execRefTypeNE,
+	(int(reflect.Func) << bitsOperator) | int(OpEQ):      execRefTypeEQ,
+	(int(reflect.Func) << bitsOperator) | int(OpNE):      execRefTypeNE,
+	(int(reflect.Interface) << bitsOperator) | int(OpEQ): execInterfaceEQ,
+	(int(reflect.Interface) << bitsOperator) | int(OpNE): execInterfaceNE,
 }
 
 func execAddInt(i Instr, p *Context) {
diff --git a/exec/bytecode/operator.go b/exec/bytecode/operator.go
index a7f82e2e..e49199e2 100644
--- a/exec/bytecode/operator.go
+++ b/exec/bytecode/operator.go
@@ -151,40 +151,40 @@ const (
 	Ptr = exec.Ptr
 )
 
+func execInterfaceEQ(i Instr, p *Context) {
+	n := len(p.data)
+	p.Ret(2, p.data[n-2] == p.data[n-1])
+}
+
+func execInterfaceNE(i Instr, p *Context) {
+	n := len(p.data)
+	p.Ret(2, p.data[n-2] != p.data[n-1])
+}
+
 // -------------------------------------------------------------------------
 func execRefTypeEQ(i Instr, p *Context) {
 	n := len(p.data)
-	arg1 := reflect.ValueOf(p.data[n-2])
-	arg2 := reflect.ValueOf(p.data[n-1])
-	if p.data[n-1] == nil && (arg1.Type().Kind() == reflect.Slice ||
-		arg1.Type().Kind() == reflect.Map ||
-		arg1.Type().Kind() == reflect.Chan ||
-		arg1.Type().Kind() == reflect.Ptr) {
-		p.Ret(2, arg1.IsNil())
-	}
-	if p.data[n-2] == nil && (arg2.Type().Kind() == reflect.Slice ||
-		arg2.Type().Kind() == reflect.Map ||
-		arg2.Type().Kind() == reflect.Chan ||
-		arg2.Type().Kind() == reflect.Ptr) {
-		p.Ret(2, arg2.IsNil())
+	v1 := p.data[n-2]
+	v2 := p.data[n-1]
+	if v1 == nil {
+		p.Ret(2, reflect.ValueOf(v2).IsNil())
+	} else if v2 == nil {
+		p.Ret(2, reflect.ValueOf(v1).IsNil())
+	} else {
+		p.Ret(2, reflect.ValueOf(v1).Pointer() == reflect.ValueOf(v2).Pointer())
 	}
 }
 
-func execRefTypeNEQ(i Instr, p *Context) {
+func execRefTypeNE(i Instr, p *Context) {
 	n := len(p.data)
-	arg1 := reflect.ValueOf(p.data[n-2])
-	arg2 := reflect.ValueOf(p.data[n-1])
-	if p.data[n-1] == nil && (arg1.Type().Kind() == reflect.Slice ||
-		arg1.Type().Kind() == reflect.Map ||
-		arg1.Type().Kind() == reflect.Chan ||
-		arg1.Type().Kind() == reflect.Ptr) {
-		p.Ret(2, !arg1.IsNil())
-	}
-	if p.data[n-2] == nil && (arg2.Type().Kind() == reflect.Slice ||
-		arg2.Type().Kind() == reflect.Map ||
-		arg2.Type().Kind() == reflect.Chan ||
-		arg2.Type().Kind() == reflect.Ptr) {
-		p.Ret(2, !arg2.IsNil())
+	v1 := p.data[n-2]
+	v2 := p.data[n-1]
+	if v1 == nil {
+		p.Ret(2, !reflect.ValueOf(v2).IsNil())
+	} else if v2 == nil {
+		p.Ret(2, !reflect.ValueOf(v1).IsNil())
+	} else {
+		p.Ret(2, reflect.ValueOf(v1).Pointer() != reflect.ValueOf(v2).Pointer())
 	}
 }
 


Test patch:
diff --git a/cl/expr_test.go b/cl/expr_test.go
index 5512c655..208c89d0 100644
--- a/cl/expr_test.go
+++ b/cl/expr_test.go
@@ -1815,6 +1815,56 @@ func TestRefType(t *testing.T) {
 	testScripts(t, "TestRefType", testRefTypeClauses)
 }
 
+func TestMatchType(t *testing.T) {
+	cltest.Expect(t, `
+		println(nil == nil,nil != nil)
+	`, "true false\n")
+	cltest.Expect(t, `
+		var i interface{}
+		println(i == nil,i != nil)
+	`, "true false\n")
+	cltest.Expect(t, `
+		var i *int
+		println(i == nil,i != nil)
+	`, "true false\n")
+	cltest.Expect(t, `
+		var i chan int
+		println(i == nil,i != nil)
+	`, "true false\n")
+	cltest.Expect(t, `
+		var i func()
+		println(i == nil,i != nil)
+	`, "true false\n")
+	cltest.Expect(t, `
+		var i []int
+		println(i == nil,i != nil)
+	`, "true false\n")
+	cltest.Expect(t, `
+		var i map[int]string
+		println(i == nil,i != nil)
+	`, "true false\n")
+	cltest.Expect(t, `
+		var v int
+		println(v == nil)
+	`, "", "invalid operator: v == nil (mismatched types int and nil)")
+	cltest.Expect(t, `
+		var v int
+		println(nil == v)
+	`, "", "invalid operator: nil == v (mismatched types nil and int)")
+	cltest.Expect(t, `
+		var a int
+		var b uint8
+		println(a == b)
+	`, "", "invalid operator: a == b (mismatched types int and uint8)")
+	cltest.Expect(t, `
+		var a int
+		switch a {
+			case 0:
+			case uint8(1):
+		}
+	`, "", "invalid case uint8(1) in switch on a (mismatched types int and uint8)")
+}
+
 func testScripts(t *testing.T, testName string, scripts map[string]testData) {
 	for name, script := range scripts {
 		t.Log("Run " + testName + "---" + name)
diff --git a/exec/bytecode/exec_autogen_test.go b/exec/bytecode/exec_autogen_test.go
index b17dd08c..baf82f0f 100644
--- a/exec/bytecode/exec_autogen_test.go
+++ b/exec/bytecode/exec_autogen_test.go
@@ -240,6 +240,12 @@ func newKindValue(kind Kind) reflect.Value {
 			t = reflect.ChanOf(reflect.BothDir, TyEmptyInterface)
 		} else if kind == reflect.Ptr {
 			t = TyUnsafePointer
+		} else if kind == reflect.Interface {
+			t = TyEmptyInterface
+		} else if kind == UnsafePointer {
+			t = TyUnsafePointer
+		} else if kind == reflect.Func {
+			t = reflect.FuncOf(nil, nil, false)
 		}
 	}
 	if t.Kind() == reflect.Ptr {