From df2fc21324ea86463b340cee4235dc099d2aac76 Mon Sep 17 00:00:00 2001 From: mappu Date: Fri, 10 Apr 2020 17:37:59 +1200 Subject: [PATCH] implement walkMutate(*node); completely transform AltIf->If --- fixtures/0012-if-else.php | 8 ++++ main.go | 3 +- mutatingwalker.go | 54 ++++++++++++++++++++++++++ normalisealts.go | 82 ++++++--------------------------------- 4 files changed, 74 insertions(+), 73 deletions(-) create mode 100644 mutatingwalker.go diff --git a/fixtures/0012-if-else.php b/fixtures/0012-if-else.php index 5bc53a1..704a213 100644 --- a/fixtures/0012-if-else.php +++ b/fixtures/0012-if-else.php @@ -28,3 +28,11 @@ endif; // Unbraced if (true) echo "100"; + +// Colon style within deeper scope + +{{{{ + if (1 == 1): + echo "asdf"; + endif; +}}}} \ No newline at end of file diff --git a/main.go b/main.go index 2b4450a..f876288 100644 --- a/main.go +++ b/main.go @@ -48,8 +48,7 @@ func ConvertFile(filename string) (string, error) { } // Pass 1: Normalise Alt** Stmt types - normPass := normaliseAltsPass{} - n.Walk(&normPass) // can't modify root node, but that's fine + walkMutate(&n, normaliseAltCb) // Debug pass: Walk and print JSON... if fh, err := os.OpenFile(filename+`.parse2.json`, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644); err == nil { diff --git a/mutatingwalker.go b/mutatingwalker.go new file mode 100644 index 0000000..4af95e8 --- /dev/null +++ b/mutatingwalker.go @@ -0,0 +1,54 @@ +package main + +import ( + // "fmt" + //"io/ioutil" + + "github.com/z7zmey/php-parser/node" + "github.com/z7zmey/php-parser/node/stmt" + //"github.com/z7zmey/php-parser/walker" +) + +func walkMutate(n_ *node.Node, cb func(*node.Node)) { + + // Mutate in-place, non recursive... + cb(n_) + + // Walk on the mutated version + // We must reimplement .Walk() in order to get pointer behaviour + + switch n := (*n_).(type) { + case *stmt.StmtList: + for i, _ := range n.Stmts { + walkMutate(&n.Stmts[i], cb) + } + + case *node.Root: + for i, _ := range n.Stmts { + walkMutate(&n.Stmts[i], cb) + } + + case *stmt.If: + walkMutate(&n.Cond, cb) + walkMutate(&n.Else, cb) + for i, _ := range n.ElseIf { + walkMutate(&n.ElseIf[i], cb) + } + walkMutate(&n.Stmt, cb) + + case *stmt.Else: + walkMutate(&n.Stmt, cb) + + case *stmt.ElseIf: + walkMutate(&n.Cond, cb) + walkMutate(&n.Stmt, cb) + + default: + // FIXME need to implement Walk() for all node types, to ensure that + // we can perform mutation transforms in nested contexts + // bail + //panic(fmt.Sprintf("walkMutate: unimplemented type '%t'", n)) + + } + +} diff --git a/normalisealts.go b/normalisealts.go index db719c2..c7c7437 100644 --- a/normalisealts.go +++ b/normalisealts.go @@ -1,101 +1,41 @@ package main import ( - "fmt" + //"fmt" //"io/ioutil" "github.com/z7zmey/php-parser/node" "github.com/z7zmey/php-parser/node/stmt" - "github.com/z7zmey/php-parser/walker" + //"github.com/z7zmey/php-parser/walker" ) -type normaliseAltsPass struct { -} +func normaliseAltCb(n_ *node.Node) { -func (np *normaliseAltsPass) transformNonRecursive(n node.Node) (node.Node, bool) { - - switch n := n.(type) { + switch n := (*n_).(type) { case *stmt.AltIf: // Build replacement node ifStmt := stmt.NewIf(n.Cond, n.Stmt, n.ElseIf, n.Else) ifStmt.FreeFloating = n.FreeFloating ifStmt.Position = n.Position // ifStmt has no .Attributes prop - return ifStmt, true + + *n_ = ifStmt case *stmt.AltElse: elseStmt := stmt.NewElse(n.Stmt) elseStmt.FreeFloating = n.FreeFloating elseStmt.Position = n.Position - return elseStmt, true + + *n_ = elseStmt case *stmt.AltElseIf: elifStmt := stmt.NewElseIf(n.Cond, n.Stmt) elifStmt.FreeFloating = n.FreeFloating elifStmt.Position = n.Position - return elifStmt, true + + *n_ = elifStmt default: - return n, false // no change + return // no change } } - -func (np *normaliseAltsPass) walkMutateArray(stmts []node.Node) { - for i, _ := range stmts { - np.walkMutate(&stmts[i]) - } -} - -func (np *normaliseAltsPass) walkMutate(child *node.Node) { - - v2, didChange := np.transformNonRecursive(*child) - if didChange { - v2.Walk(np) - *child = v2 - } else { - (*child).Walk(np) - } -} - -func (np *normaliseAltsPass) EnterNode(w walker.Walkable) bool { - n, ok := w.(node.Node) - if !ok { - panic(fmt.Errorf("Tried to walk non-node '%t'", w)) - } - - // We need to override the .Walk() behaviour for all possible *parents* - // of affected nodes. This is because the .Walk() interface does not give - // us any opportunity to override single elements by the time we get there - // Our custom Walk() implementation is not firing all EnterChildList/LeaveNode - // visitors - but - that's fine since they're all noops anyway - - switch n := n.(type) { - case *stmt.StmtList: - np.walkMutateArray(n.Stmts) // mutate slice in place - return false // Signal not to use upstream .Walk() implementation - - case *node.Root: - np.walkMutateArray(n.Stmts) // mutate slice in place - return false // Signal not to use upstream .Walk() implementation - - case *stmt.AltIf: - panic("altif") - np.walkMutate(&n.Cond) - np.walkMutateArray(n.ElseIf) - np.walkMutate(&n.Else) - return false - - default: - // No normalisation needed for this node type - // Recurse deeper - return true - } -} - -func (np *normaliseAltsPass) LeaveNode(w walker.Walkable) {} -func (np *normaliseAltsPass) EnterChildNode(key string, w walker.Walkable) {} -func (np *normaliseAltsPass) LeaveChildNode(key string, w walker.Walkable) {} -func (np *normaliseAltsPass) EnterChildList(key string, w walker.Walkable) {} -func (np *normaliseAltsPass) LeaveChildList(key string, w walker.Walkable) {} - -var _ walker.Visitor = &normaliseAltsPass{} // interface assertion