Type assertion: add support for 2nd return value

This commit is contained in:
Marc Vertes
2018-12-01 17:56:55 +01:00
parent c75807dec9
commit 487e24e829
5 changed files with 110 additions and 4 deletions

22
_test/context2.go Normal file
View File

@@ -0,0 +1,22 @@
package main
import "context"
func get(ctx context.Context, k string) string {
var r string
var ok bool
if v := ctx.Value(k); v != nil {
r, ok = v.(string)
println(ok)
}
return r
}
func main() {
ctx := context.WithValue(context.Background(), "hello", "world")
println(get(ctx, "hello"))
}
// Output:
// true
// world

12
_test/type7.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import "fmt"
func main() {
var i interface{} = "hello"
s, ok := i.(string)
fmt.Println(s, ok)
}
// Output:
// hello

View File

@@ -318,7 +318,9 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
n.gen = nop
case TypeAssertExpr:
types = append(types, n.child[l].child[1].typ, scope.getType("error"))
types = append(types, n.child[l].child[1].typ, scope.getType("bool"))
n.child[l].gen = typeAssert2
n.gen = nop
default:
log.Fatalln(n.index, "Assign expression unsupported:", n.child[l].kind)
@@ -862,12 +864,13 @@ func (interp *Interpreter) Cfg(root *Node) []*Node {
scope = scope.pop()
case TypeAssertExpr:
// TODO: handle 2 return values variant
if n.child[1].typ == nil {
n.child[1].typ = scope.getType(n.child[1].ident)
}
n.typ = n.child[1].typ
n.findex = scope.inc(interp)
if n.anc.action != AssignX {
n.typ = n.child[1].typ
n.findex = scope.inc(interp)
}
case SliceExpr, UnaryExpr:
wireChild(n)

View File

@@ -1291,6 +1291,35 @@ func main() {
// world
}
func Example_context2() {
src := `
package main
import "context"
func get(ctx context.Context, k string) string {
var r string
var ok bool
if v := ctx.Value(k); v != nil {
r, ok = v.(string)
println(ok)
}
return r
}
func main() {
ctx := context.WithValue(context.Background(), "hello", "world")
println(get(ctx, "hello"))
}
`
i := NewInterpreter(Opt{Entry: "main"}, "context2.go")
i.Eval(src)
// Output:
// true
// world
}
func Example_export0() {
src := `
package main
@@ -4360,6 +4389,25 @@ type T int
// int
}
func Example_type7() {
src := `
package main
import "fmt"
func main() {
var i interface{} = "hello"
s, ok := i.(string)
fmt.Println(s, ok)
}
`
i := NewInterpreter(Opt{Entry: "main"}, "type7.go")
i.Eval(src)
// Output:
// hello
}
func Example_var() {
src := `
package main

View File

@@ -90,6 +90,27 @@ func typeAssert(n *Node) {
}
}
func typeAssert2(n *Node) {
value := genValue(n.child[0]) // input value
value0 := genValue(n.anc.child[0]) // returned result
value1 := genValue(n.anc.child[1]) // returned status
next := getExec(n.tnext)
if n.child[0].typ.cat == ValueT {
n.exec = func(f *Frame) Builtin {
value0(f).Set(value(f).Elem())
value1(f).SetBool(true)
return next
}
} else {
n.exec = func(f *Frame) Builtin {
value0(f).Set(value(f))
value1(f).SetBool(true)
return next
}
}
}
func convert(n *Node) {
i := n.findex
var value func(*Frame) reflect.Value