fix: catch mismatched types in binary operator expressions (#109)
The types of operands are checked prior to generate closures. - test: improve evalCheck() to check against expected output and/or expected errors.
This commit is contained in:
committed by
Ludovic Fernandez
parent
0fb2370c33
commit
005a3cf93c
@@ -428,6 +428,9 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
|
||||
wireChild(n)
|
||||
n.findex = scope.inc(interp)
|
||||
nilSym := interp.universe.sym["nil"]
|
||||
if t0, t1 := n.child[0].typ, n.child[1].typ; !t0.untyped && !t1.untyped && t0.id() != t1.id() {
|
||||
err = n.cfgError("mismatched types %s and %s", t0.id(), t1.id())
|
||||
}
|
||||
switch n.action {
|
||||
case NotEqual:
|
||||
n.typ = scope.getType("bool")
|
||||
|
||||
@@ -163,7 +163,7 @@ func initUniverse() *Scope {
|
||||
"iota": &Symbol{kind: Const, typ: &Type{cat: IntT}},
|
||||
|
||||
// predefined Go zero value
|
||||
"nil": &Symbol{typ: &Type{cat: NilT}},
|
||||
"nil": &Symbol{typ: &Type{cat: NilT, untyped: true}},
|
||||
|
||||
// predefined Go builtins
|
||||
"append": &Symbol{kind: Bltn, builtin: _append},
|
||||
|
||||
@@ -209,6 +209,18 @@ func Foo() {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvalComparison(t *testing.T) {
|
||||
i := interp.New(interp.Opt{})
|
||||
evalCheck(t, i, `
|
||||
type Foo string
|
||||
type Bar string
|
||||
|
||||
var a = Foo("test")
|
||||
var b = Bar("test")
|
||||
var c = a == b
|
||||
`, "", "7:9: mismatched types _.Foo and _.Bar")
|
||||
}
|
||||
|
||||
func TestEvalCompositeArray0(t *testing.T) {
|
||||
i := interp.New(interp.Opt{})
|
||||
v := evalCheck(t, i, `a := []int{1, 2, 7: 20, 30}`)
|
||||
@@ -226,12 +238,27 @@ func TestEvalUnary0(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func evalCheck(t *testing.T, i *interp.Interpreter, src string) reflect.Value {
|
||||
func evalCheck(t *testing.T, i *interp.Interpreter, src string, expect ...string) reflect.Value {
|
||||
t.Helper()
|
||||
|
||||
res, err := i.Eval(src)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
if len(expect) == 0 {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return res
|
||||
}
|
||||
if expect[0] != "" && expect[0] != fmt.Sprintf("%v", res) {
|
||||
t.Fatalf("expected %v, got %v", expect[0], res)
|
||||
}
|
||||
if len(expect) == 1 {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return res
|
||||
}
|
||||
if expect[1] != err.Error() {
|
||||
t.Fatalf("expected error %v, got %v", expect[1], err.Error())
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -386,9 +386,9 @@ func (t *Type) id() string {
|
||||
|
||||
res := ""
|
||||
if t.cat == ValueT {
|
||||
res = t.rtype.PkgPath() + t.rtype.Name()
|
||||
res = t.rtype.PkgPath() + "." + t.rtype.Name()
|
||||
} else {
|
||||
res = t.pkgPath + t.name
|
||||
res = t.pkgPath + "." + t.name
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user