handle multiple assign/return statements

This commit is contained in:
Marc Vertes
2018-02-12 17:22:37 +01:00
parent 1bbf5b14f9
commit 592d1bc0ac
5 changed files with 46 additions and 6 deletions

6
assign.gi Normal file
View File

@@ -0,0 +1,6 @@
package main
func main() {
a, b := 1, 2 // Multiple assign
println(a, b)
}

View File

@@ -22,15 +22,25 @@ func Ast(src string) *Node {
var st nodestack
// Populate our own private ast from go ast. A stack of ancestor nodes
// is used to keep track of curent ancestor for each depth level
ast.Inspect(f, func(n ast.Node) bool {
ast.Inspect(f, func(node ast.Node) bool {
anc = st.top()
switch n.(type) {
switch n := node.(type) {
case nil:
anc = st.pop()
case *ast.AssignStmt:
index++
var i interface{}
nod := &Node{anc: anc, index: index, anode: &node, val: &i, lhs: len(n.Lhs)}
if anc == nil {
root = nod
} else {
anc.Child = append(anc.Child, nod)
}
st.push(nod)
default:
index++
var i interface{}
nod := &Node{anc: anc, index: index, anode: &n, val: &i}
nod := &Node{anc: anc, index: index, anode: &node, val: &i}
if anc == nil {
root = nod
} else {

View File

@@ -19,6 +19,7 @@ type Node struct {
findex int // index of value in frame or frame size (func def)
run RunFun // function to run at CFG execution
val interface{} // pointer on generic value (CFG execution)
lhs int // number of left hand side nodes, set if node is an assign statement
ident string // set if node is a var or func
isNop bool // node run function us a no-op
isConst bool // true if node value is constant

View File

@@ -43,7 +43,22 @@ func value(n *Node, f *Frame) interface{} {
}
func assign(n *Node, f *Frame) {
(*f)[n.findex] = value(n.Child[1], f)
// FIXME: should have different assign flavors set by CFG instead
if n.lhs > 1 {
if len(n.Child)-n.lhs > 1 {
// multiple single assign
for i := 0; i < n.lhs; i++ {
(*f)[n.Child[i].findex] = value(n.Child[len(n.Child)-n.lhs+i], f)
}
} else {
// Multiple vars set from a single call
for i := 0; i < n.lhs; i++ {
(*f)[n.Child[i].findex] = (*f)[n.Child[len(n.Child)-1].findex+i]
}
}
} else {
(*f)[n.findex] = value(n.Child[1], f)
}
}
func and(n *Node, f *Frame) {
@@ -52,7 +67,7 @@ func and(n *Node, f *Frame) {
func printa(n []*Node, f *Frame) {
for _, m := range n {
fmt.Printf("%v", value(m, f))
fmt.Printf("%v ", value(m, f))
}
fmt.Println("")
}
@@ -104,7 +119,7 @@ func nop(n *Node, i *Frame) {}
func _return(n *Node, f *Frame) {
for i, c := range n.Child {
(*f)[i] = (*f)[c.findex]
(*f)[i] = value(c, f)
}
// FIXME: should be done during compiling, not run
n.tnext = nil

8
ret2.gi Normal file
View File

@@ -0,0 +1,8 @@
package main
func main() {
a, b = r2()
println(a, b)
}
func r2() (int, int) {return 1, 2}