node: bail out upon assignment inside if-expression
This commit is contained in:
parent
49241e7a8c
commit
315174c79a
@ -37,6 +37,8 @@ The goal is to produce idiomatic, maintainable Go code as part of a one-off conv
|
||||
[ ] Assignment expressions
|
||||
- Go doesn't support assignment in rvalues, only as a statement
|
||||
- When walking below stmt level, need to first fully walk and check for any function calls + assignments that may need hoisting (and we can probably only do that correctly if there is no short-circuiting)
|
||||
- [X] Add subtree walk + catch error for this case
|
||||
- [ ] Add hoisting pass
|
||||
[ ] Closures
|
||||
- [ ] Handle value/reference captures
|
||||
[ ] Sort callbacks
|
||||
|
42
miniwalker.go
Normal file
42
miniwalker.go
Normal file
@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/z7zmey/php-parser/node"
|
||||
"github.com/z7zmey/php-parser/walker"
|
||||
)
|
||||
|
||||
type miniWalker struct {
|
||||
cb func(node.Node) error
|
||||
lastErr error
|
||||
}
|
||||
|
||||
func (mw *miniWalker) EnterNode(w walker.Walkable) bool {
|
||||
n, ok := w.(node.Node)
|
||||
if !ok {
|
||||
mw.lastErr = fmt.Errorf("Tried to walk non-node '%t'", w)
|
||||
return false
|
||||
}
|
||||
|
||||
err := mw.cb(n)
|
||||
if err != nil {
|
||||
mw.lastErr = err
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (mw *miniWalker) LeaveNode(w walker.Walkable) {}
|
||||
func (mw *miniWalker) EnterChildNode(key string, w walker.Walkable) {}
|
||||
func (mw *miniWalker) LeaveChildNode(key string, w walker.Walkable) {}
|
||||
func (mw *miniWalker) EnterChildList(key string, w walker.Walkable) {}
|
||||
func (mw *miniWalker) LeaveChildList(key string, w walker.Walkable) {}
|
||||
|
||||
func walk(n node.Node, cb func(node.Node) error) error {
|
||||
mw := miniWalker{cb: cb}
|
||||
n.Walk(&mw)
|
||||
|
||||
return mw.lastErr
|
||||
}
|
23
node.go
23
node.go
@ -511,6 +511,15 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
||||
return "fmt.Print(" + quoted + ")\n", nil // newline - standalone statement
|
||||
|
||||
case *stmt.If:
|
||||
|
||||
hasCondAssign, err := hasInteriorAssignment(n.Cond)
|
||||
if err != nil {
|
||||
return "", parseErr{n, err}
|
||||
}
|
||||
if hasCondAssign {
|
||||
return "", parseErr{n.Cond, fmt.Errorf("please remove assignment from if-expression")}
|
||||
}
|
||||
|
||||
cond, err := this.convert(n.Cond)
|
||||
if err != nil {
|
||||
return "", parseErr{n, err}
|
||||
@ -1158,3 +1167,17 @@ func (this *conversionState) convertFunctionCommon(params []node.Node, returnTyp
|
||||
// No extra trailing newline in case this is part of a large expression
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// hasInteriorAssignment recursively walks a node, to determine if it contains
|
||||
// any assignment expressions
|
||||
func hasInteriorAssignment(n node.Node) (hasAnyAssign bool, err error) {
|
||||
|
||||
err = walk(n, func(n node.Node) error {
|
||||
if _, ok := n.(*assign.Assign); ok {
|
||||
hasAnyAssign = true
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return // named return
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user