fix: handle defer in builtins
This commit is contained in:
32
_test/defer5.go
Normal file
32
_test/defer5.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
func f1() {
|
||||
defer println("f1-begin")
|
||||
f2()
|
||||
defer println("f1-end")
|
||||
}
|
||||
|
||||
func f2() {
|
||||
defer println("f2-begin")
|
||||
f3()
|
||||
defer println("f2-end")
|
||||
}
|
||||
|
||||
func f3() {
|
||||
defer println("f3-begin")
|
||||
println("hello")
|
||||
defer println("f3-end")
|
||||
}
|
||||
|
||||
func main() {
|
||||
f1()
|
||||
}
|
||||
|
||||
// Output:
|
||||
// hello
|
||||
// f3-end
|
||||
// f3-begin
|
||||
// f2-end
|
||||
// f2-begin
|
||||
// f1-end
|
||||
// f1-begin
|
||||
27
_test/defer6.go
Normal file
27
_test/defer6.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
func f1() {
|
||||
defer print("f1-begin ")
|
||||
f2()
|
||||
defer print("f1-end ")
|
||||
}
|
||||
|
||||
func f2() {
|
||||
defer print("f2-begin ")
|
||||
f3()
|
||||
defer print("f2-end ")
|
||||
}
|
||||
|
||||
func f3() {
|
||||
defer print("f3-begin ")
|
||||
print("hello ")
|
||||
defer print("f3-end ")
|
||||
}
|
||||
|
||||
func main() {
|
||||
f1()
|
||||
println()
|
||||
}
|
||||
|
||||
// Output:
|
||||
// hello f3-end f3-begin f2-end f2-begin f1-end f1-begin
|
||||
18
_test/defer7.go
Normal file
18
_test/defer7.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func f1(in, out []string) {
|
||||
defer copy(out, in)
|
||||
}
|
||||
|
||||
func main() {
|
||||
in := []string{"foo", "bar"}
|
||||
out := make([]string, 2)
|
||||
f1(in, out)
|
||||
|
||||
fmt.Println(out)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// [foo bar]
|
||||
24
_test/defer8.go
Normal file
24
_test/defer8.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func f1(m map[string]string) {
|
||||
defer delete(m, "foo")
|
||||
defer delete(m, "test")
|
||||
|
||||
fmt.Println(m)
|
||||
}
|
||||
|
||||
func main() {
|
||||
m := map[string]string{
|
||||
"foo": "bar",
|
||||
"baz": "bat",
|
||||
}
|
||||
f1(m)
|
||||
|
||||
fmt.Println(m)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// map[baz:bat foo:bar]
|
||||
// map[baz:bat]
|
||||
21
_test/defer9.go
Normal file
21
_test/defer9.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func f1(ch chan string) {
|
||||
defer close(ch)
|
||||
|
||||
ch <- "foo"
|
||||
}
|
||||
|
||||
func main() {
|
||||
ch := make(chan string, 1)
|
||||
f1(ch)
|
||||
|
||||
for s := range ch {
|
||||
fmt.Println(s)
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// foo
|
||||
@@ -525,41 +525,39 @@ func deref(n *node) {
|
||||
|
||||
func _print(n *node) {
|
||||
child := n.child[1:]
|
||||
next := getExec(n.tnext)
|
||||
values := make([]func(*frame) reflect.Value, len(child))
|
||||
for i, c := range child {
|
||||
values[i] = genValue(c)
|
||||
}
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
for i, value := range values {
|
||||
genBuiltinDeferWrapper(n, values, nil, func(args []reflect.Value) []reflect.Value {
|
||||
for i, value := range args {
|
||||
if i > 0 {
|
||||
fmt.Printf(" ")
|
||||
}
|
||||
fmt.Printf("%v", value(f))
|
||||
fmt.Printf("%v", value)
|
||||
}
|
||||
return next
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func _println(n *node) {
|
||||
child := n.child[1:]
|
||||
next := getExec(n.tnext)
|
||||
values := make([]func(*frame) reflect.Value, len(child))
|
||||
for i, c := range child {
|
||||
values[i] = genValue(c)
|
||||
}
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
for i, value := range values {
|
||||
genBuiltinDeferWrapper(n, values, nil, func(args []reflect.Value) []reflect.Value {
|
||||
for i, value := range args {
|
||||
if i > 0 {
|
||||
fmt.Printf(" ")
|
||||
}
|
||||
fmt.Printf("%v", value(f))
|
||||
fmt.Printf("%v", value)
|
||||
}
|
||||
fmt.Println("")
|
||||
return next
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func _recover(n *node) {
|
||||
@@ -585,6 +583,45 @@ func _panic(n *node) {
|
||||
}
|
||||
}
|
||||
|
||||
func genBuiltinDeferWrapper(n *node, in, out []func(*frame) reflect.Value, fn func([]reflect.Value) []reflect.Value) {
|
||||
next := getExec(n.tnext)
|
||||
|
||||
if n.anc.kind == deferStmt {
|
||||
n.exec = func(f *frame) bltn {
|
||||
val := make([]reflect.Value, len(in)+1)
|
||||
inTypes := make([]reflect.Type, len(in))
|
||||
for i, v := range in {
|
||||
val[i+1] = v(f)
|
||||
inTypes[i] = val[i+1].Type()
|
||||
}
|
||||
outTypes := make([]reflect.Type, len(out))
|
||||
for i, v := range out {
|
||||
outTypes[i] = v(f).Type()
|
||||
}
|
||||
|
||||
funcType := reflect.FuncOf(inTypes, outTypes, false)
|
||||
val[0] = reflect.MakeFunc(funcType, fn)
|
||||
f.deferred = append([][]reflect.Value{val}, f.deferred...)
|
||||
return next
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
val := make([]reflect.Value, len(in))
|
||||
for i, v := range in {
|
||||
val[i] = v(f)
|
||||
}
|
||||
|
||||
dests := fn(val)
|
||||
|
||||
for i, dest := range dests {
|
||||
out[i](f).Set(dest)
|
||||
}
|
||||
return next
|
||||
}
|
||||
}
|
||||
|
||||
func genFunctionWrapper(n *node) func(*frame) reflect.Value {
|
||||
var def *node
|
||||
var ok bool
|
||||
@@ -2344,25 +2381,22 @@ func _cap(n *node) {
|
||||
}
|
||||
|
||||
func _copy(n *node) {
|
||||
dest := genValueOutput(n, reflect.TypeOf(int(0)))
|
||||
value0 := genValueArray(n.child[1])
|
||||
value1 := genValue(n.child[2])
|
||||
next := getExec(n.tnext)
|
||||
in := []func(*frame) reflect.Value{genValueArray(n.child[1]), genValue(n.child[2])}
|
||||
out := []func(*frame) reflect.Value{genValueOutput(n, reflect.TypeOf(0))}
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetInt(int64(reflect.Copy(value0(f), value1(f))))
|
||||
return next
|
||||
}
|
||||
genBuiltinDeferWrapper(n, in, out, func(args []reflect.Value) []reflect.Value {
|
||||
cnt := reflect.Copy(args[0], args[1])
|
||||
return []reflect.Value{reflect.ValueOf(cnt)}
|
||||
})
|
||||
}
|
||||
|
||||
func _close(n *node) {
|
||||
value := genValue(n.child[1])
|
||||
next := getExec(n.tnext)
|
||||
in := []func(*frame) reflect.Value{genValue(n.child[1])}
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
value(f).Close()
|
||||
return next
|
||||
}
|
||||
genBuiltinDeferWrapper(n, in, nil, func(args []reflect.Value) []reflect.Value {
|
||||
args[0].Close()
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func _complex(n *node) {
|
||||
@@ -2415,13 +2449,13 @@ func _real(n *node) {
|
||||
func _delete(n *node) {
|
||||
value0 := genValue(n.child[1]) // map
|
||||
value1 := genValue(n.child[2]) // key
|
||||
next := getExec(n.tnext)
|
||||
in := []func(*frame) reflect.Value{value0, value1}
|
||||
var z reflect.Value
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
value0(f).SetMapIndex(value1(f), z)
|
||||
return next
|
||||
}
|
||||
genBuiltinDeferWrapper(n, in, nil, func(args []reflect.Value) []reflect.Value {
|
||||
args[0].SetMapIndex(args[1], z)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func _len(n *node) {
|
||||
|
||||
Reference in New Issue
Block a user