stmt: track conversion state in a struct
This commit is contained in:
parent
2a00699b2f
commit
45b694434d
3
main.go
3
main.go
@ -21,6 +21,7 @@ func ConvertFile(filename string) (string, error) {
|
|||||||
|
|
||||||
namespaces := visitor.NewNamespaceResolver()
|
namespaces := visitor.NewNamespaceResolver()
|
||||||
// scope := NewScope()
|
// scope := NewScope()
|
||||||
|
state := conversionState{}
|
||||||
|
|
||||||
p, err := parser.NewParser([]byte(inputFile), "7.4")
|
p, err := parser.NewParser([]byte(inputFile), "7.4")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -40,7 +41,7 @@ func ConvertFile(filename string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Walk and print (converted)
|
// Walk and print (converted)
|
||||||
ret, err := convert(p.GetRootNode())
|
ret, err := state.convert(p.GetRootNode())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
161
node.go
161
node.go
@ -36,7 +36,10 @@ func (pe parseErr) Unwrap() error {
|
|||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
func convert(n_ node.Node) (string, error) {
|
type conversionState struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *conversionState) convert(n_ node.Node) (string, error) {
|
||||||
switch n := n_.(type) {
|
switch n := n_.(type) {
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -50,7 +53,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
statements := []string{}
|
statements := []string{}
|
||||||
|
|
||||||
for _, s := range n.Stmts {
|
for _, s := range n.Stmts {
|
||||||
sm, err := convert(s)
|
sm, err := this.convert(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{s, err}
|
return "", parseErr{s, err}
|
||||||
}
|
}
|
||||||
@ -91,7 +94,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
|
|
||||||
ret := "{\n" // new variable scope
|
ret := "{\n" // new variable scope
|
||||||
for _, s := range n.Stmts {
|
for _, s := range n.Stmts {
|
||||||
line, err := convert(s)
|
line, err := this.convert(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{s, err}
|
return "", parseErr{s, err}
|
||||||
}
|
}
|
||||||
@ -167,7 +170,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
allStmts = append(allStmts, Literal{`return this, nil`})
|
allStmts = append(allStmts, Literal{`return this, nil`})
|
||||||
|
|
||||||
// Method body
|
// Method body
|
||||||
funcStmt, err := convertFunctionCommon(s.Params, returnType, true /* always use ptr return */, allStmts)
|
funcStmt, err := this.convertFunctionCommon(s.Params, returnType, true /* always use ptr return */, allStmts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{s, err}
|
return "", parseErr{s, err}
|
||||||
}
|
}
|
||||||
@ -183,7 +186,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Method body
|
// Method body
|
||||||
funcStmt, err := convertFunctionCommon(s.Params, s.ReturnType, s.ReturnsRef, s.Stmt.(*stmt.StmtList).Stmts)
|
funcStmt, err := this.convertFunctionCommon(s.Params, s.ReturnType, s.ReturnsRef, s.Stmt.(*stmt.StmtList).Stmts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{s, err}
|
return "", parseErr{s, err}
|
||||||
}
|
}
|
||||||
@ -223,7 +226,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
funcName = toPublic(funcName)
|
funcName = toPublic(funcName)
|
||||||
|
|
||||||
// Convert body
|
// Convert body
|
||||||
funcStmt, err := convertFunctionCommon(n.Params, n.ReturnType, n.ReturnsRef, n.Stmts)
|
funcStmt, err := this.convertFunctionCommon(n.Params, n.ReturnType, n.ReturnsRef, n.Stmts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -232,7 +235,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
|
|
||||||
case *stmt.Return:
|
case *stmt.Return:
|
||||||
child, err := convert(n.Expr)
|
child, err := this.convert(n.Expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -252,7 +255,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
return "return nil, errors.New(" + str.Value + ")\n", nil
|
return "return nil, errors.New(" + str.Value + ")\n", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
child, err := convert(n.Expr)
|
child, err := this.convert(n.Expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -268,7 +271,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
// No initialiser in loop
|
// No initialiser in loop
|
||||||
|
|
||||||
} else if len(n.Init) == 1 {
|
} else if len(n.Init) == 1 {
|
||||||
finit, err = convert(n.Init[0])
|
finit, err = this.convert(n.Init[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -279,7 +282,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
// it may cause an extra local variable after the loop that may result
|
// it may cause an extra local variable after the loop that may result
|
||||||
// in type mismatch (can be fixed by using an extra scope).
|
// in type mismatch (can be fixed by using an extra scope).
|
||||||
for _, initStmt := range n.Init {
|
for _, initStmt := range n.Init {
|
||||||
singleInitStmt, err := convert(initStmt)
|
singleInitStmt, err := this.convert(initStmt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{initStmt, err}
|
return "", parseErr{initStmt, err}
|
||||||
}
|
}
|
||||||
@ -291,7 +294,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
if len(n.Cond) != 1 {
|
if len(n.Cond) != 1 {
|
||||||
return "", parseErr{n, fmt.Errorf("for loop can only have 1 cond clause, found %d", len(n.Cond))}
|
return "", parseErr{n, fmt.Errorf("for loop can only have 1 cond clause, found %d", len(n.Cond))}
|
||||||
}
|
}
|
||||||
fcond, err := convert(n.Cond[0])
|
fcond, err := this.convert(n.Cond[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -308,12 +311,12 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
loopStmt = expr.NewPostDec(predec.Variable)
|
loopStmt = expr.NewPostDec(predec.Variable)
|
||||||
}
|
}
|
||||||
|
|
||||||
floop, err := convert(loopStmt)
|
floop, err := this.convert(loopStmt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := convert(convertToStmtList(n.Stmt))
|
body, err := this.convert(convertToStmtList(n.Stmt))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -321,25 +324,25 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
return preinit + "for " + finit + "; " + fcond + "; " + floop + " " + body + "\n", nil
|
return preinit + "for " + finit + "; " + fcond + "; " + floop + " " + body + "\n", nil
|
||||||
|
|
||||||
case *stmt.Foreach:
|
case *stmt.Foreach:
|
||||||
iterand, err := convert(n.Expr)
|
iterand, err := this.convert(n.Expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
valueReceiver, err := convert(n.Variable)
|
valueReceiver, err := this.convert(n.Variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
keyReceiver := `_`
|
keyReceiver := `_`
|
||||||
if n.Key != nil {
|
if n.Key != nil {
|
||||||
keyReceiver, err = convert(n.Key)
|
keyReceiver, err = this.convert(n.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := convert(convertToStmtList(n.Stmt))
|
body, err := this.convert(convertToStmtList(n.Stmt))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -347,12 +350,12 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
return "for " + keyReceiver + ", " + valueReceiver + " := range " + iterand + " " + body + "\n", nil
|
return "for " + keyReceiver + ", " + valueReceiver + " := range " + iterand + " " + body + "\n", nil
|
||||||
|
|
||||||
case *stmt.While:
|
case *stmt.While:
|
||||||
cond, err := convert(n.Cond)
|
cond, err := this.convert(n.Cond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := convert(convertToStmtList(n.Stmt))
|
body, err := this.convert(convertToStmtList(n.Stmt))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -360,7 +363,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
return "for " + cond + " " + body + "\n", nil
|
return "for " + cond + " " + body + "\n", nil
|
||||||
|
|
||||||
case *stmt.Do:
|
case *stmt.Do:
|
||||||
cond, err := convert(n.Cond)
|
cond, err := this.convert(n.Cond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -368,7 +371,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
bodyStmts := convertToStmtList(n.Stmt)
|
bodyStmts := convertToStmtList(n.Stmt)
|
||||||
bodyStmts.Stmts = append(bodyStmts.Stmts, Literal{"if " + cond + "{\nbreak\n}"})
|
bodyStmts.Stmts = append(bodyStmts.Stmts, Literal{"if " + cond + "{\nbreak\n}"})
|
||||||
|
|
||||||
body, err := convert(bodyStmts)
|
body, err := this.convert(bodyStmts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -376,7 +379,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
return "for " + cond + " " + body + "\n", nil
|
return "for " + cond + " " + body + "\n", nil
|
||||||
|
|
||||||
case *stmt.Expression:
|
case *stmt.Expression:
|
||||||
child, err := convert(n.Expr)
|
child, err := this.convert(n.Expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -388,7 +391,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
// Convert into fmt.Print
|
// Convert into fmt.Print
|
||||||
args := make([]string, 0, len(n.Exprs))
|
args := make([]string, 0, len(n.Exprs))
|
||||||
for _, expr := range n.Exprs {
|
for _, expr := range n.Exprs {
|
||||||
exprGo, err := convert(expr)
|
exprGo, err := this.convert(expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -420,7 +423,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
|
|
||||||
case *assign.Assign:
|
case *assign.Assign:
|
||||||
|
|
||||||
rvalue, err := convert(n.Expression)
|
rvalue, err := this.convert(n.Expression)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -428,7 +431,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
if dimf, ok := n.Variable.(*expr.ArrayDimFetch); ok && dimf.Dim == nil {
|
if dimf, ok := n.Variable.(*expr.ArrayDimFetch); ok && dimf.Dim == nil {
|
||||||
// Special handling for the case of foo[] = bar
|
// Special handling for the case of foo[] = bar
|
||||||
// Transform into append()
|
// Transform into append()
|
||||||
arrayVar, err := convert(dimf.Variable)
|
arrayVar, err := this.convert(dimf.Variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{dimf, err}
|
return "", parseErr{dimf, err}
|
||||||
}
|
}
|
||||||
@ -439,7 +442,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
|
|
||||||
// Normal assignment
|
// Normal assignment
|
||||||
|
|
||||||
lvalue, err := convert(n.Variable) // might be a more complicated lvalue
|
lvalue, err := this.convert(n.Variable) // might be a more complicated lvalue
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -461,7 +464,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
callParams, err := convertFuncCallArgsCommon(n.ArgumentList)
|
callParams, err := this.convertFuncCallArgsCommon(n.ArgumentList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -474,12 +477,12 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
funcName, err := convert(n.Call)
|
funcName, err := this.convert(n.Call)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
callParams, err := convertFuncCallArgsCommon(n.ArgumentList)
|
callParams, err := this.convertFuncCallArgsCommon(n.ArgumentList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -500,11 +503,11 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
// Convert resolved back to node.Name
|
// Convert resolved back to node.Name
|
||||||
transparentNameNode := name.NewName([]node.Node{name.NewNamePart(nn)})
|
transparentNameNode := name.NewName([]node.Node{name.NewNamePart(nn)})
|
||||||
|
|
||||||
return convert(expr.NewFunctionCall(transparentNameNode, n.ArgumentList))
|
return this.convert(expr.NewFunctionCall(transparentNameNode, n.ArgumentList))
|
||||||
|
|
||||||
case *expr.PreInc:
|
case *expr.PreInc:
|
||||||
// """In Go, i++ is a statement, not an expression. So you can't use its value in another expression such as a function call."""
|
// """In Go, i++ is a statement, not an expression. So you can't use its value in another expression such as a function call."""
|
||||||
v, err := convert(n.Variable)
|
v, err := this.convert(n.Variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -513,7 +516,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
|
|
||||||
case *expr.PostInc:
|
case *expr.PostInc:
|
||||||
// """In Go, i++ is a statement, not an expression. So you can't use its value in another expression such as a function call."""
|
// """In Go, i++ is a statement, not an expression. So you can't use its value in another expression such as a function call."""
|
||||||
v, err := convert(n.Variable)
|
v, err := this.convert(n.Variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -522,17 +525,17 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
|
|
||||||
case *expr.MethodCall:
|
case *expr.MethodCall:
|
||||||
// Foo->Bar(Baz)
|
// Foo->Bar(Baz)
|
||||||
parent, err := convert(n.Variable)
|
parent, err := this.convert(n.Variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
child, err := convert(n.Method)
|
child, err := this.convert(n.Method)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
args, err := convertFuncCallArgsCommon(n.ArgumentList)
|
args, err := this.convertFuncCallArgsCommon(n.ArgumentList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -541,12 +544,12 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
|
|
||||||
case *expr.PropertyFetch:
|
case *expr.PropertyFetch:
|
||||||
// Foo->Bar
|
// Foo->Bar
|
||||||
parent, err := convert(n.Variable)
|
parent, err := this.convert(n.Variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
child, err := convert(n.Property)
|
child, err := this.convert(n.Property)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -560,16 +563,16 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
return resolveName(n.Constant)
|
return resolveName(n.Constant)
|
||||||
|
|
||||||
case *expr.Array:
|
case *expr.Array:
|
||||||
return convertArrayLiteralCommon(n.Items)
|
return this.convertArrayLiteralCommon(n.Items)
|
||||||
|
|
||||||
case *expr.ShortArray:
|
case *expr.ShortArray:
|
||||||
return convertArrayLiteralCommon(n.Items)
|
return this.convertArrayLiteralCommon(n.Items)
|
||||||
|
|
||||||
case *expr.ArrayDimFetch:
|
case *expr.ArrayDimFetch:
|
||||||
// Might be x[foo], might be x[] (i.e. append() call)
|
// Might be x[foo], might be x[] (i.e. append() call)
|
||||||
// In order to make the append() transformation, we need to lookahead
|
// In order to make the append() transformation, we need to lookahead
|
||||||
// for ArrayDimFetch in the `*assign.Assign` case
|
// for ArrayDimFetch in the `*assign.Assign` case
|
||||||
vv, err := convert(n.Variable)
|
vv, err := this.convert(n.Variable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -578,7 +581,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
return "", parseErr{n, fmt.Errorf("found '%s[]' outside of lvalue assignment context", vv)}
|
return "", parseErr{n, fmt.Errorf("found '%s[]' outside of lvalue assignment context", vv)}
|
||||||
}
|
}
|
||||||
|
|
||||||
idx, err := convert(n.Dim)
|
idx, err := this.convert(n.Dim)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -590,40 +593,40 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
//
|
//
|
||||||
|
|
||||||
case *binary.BitwiseAnd:
|
case *binary.BitwiseAnd:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `&`)
|
return this.convertBinaryCommon(n.Left, n.Right, `&`)
|
||||||
|
|
||||||
case *binary.BitwiseOr:
|
case *binary.BitwiseOr:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `|`)
|
return this.convertBinaryCommon(n.Left, n.Right, `|`)
|
||||||
|
|
||||||
case *binary.BitwiseXor:
|
case *binary.BitwiseXor:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `^`) // n.b. Go only supports this for integers; PHP also supports it for bools
|
return this.convertBinaryCommon(n.Left, n.Right, `^`) // n.b. Go only supports this for integers; PHP also supports it for bools
|
||||||
|
|
||||||
case *binary.BooleanAnd:
|
case *binary.BooleanAnd:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `&&`)
|
return this.convertBinaryCommon(n.Left, n.Right, `&&`)
|
||||||
|
|
||||||
case *binary.BooleanOr:
|
case *binary.BooleanOr:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `||`)
|
return this.convertBinaryCommon(n.Left, n.Right, `||`)
|
||||||
|
|
||||||
//case *binary.Coalesce:
|
//case *binary.Coalesce:
|
||||||
// TODO this can't be expressed in an rvalue context in Go (unless we create a typed closure..?)
|
// TODO this can't be expressed in an rvalue context in Go (unless we create a typed closure..?)
|
||||||
|
|
||||||
case *binary.Concat:
|
case *binary.Concat:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `+`) // PHP uses + for numbers, `.` for strings; Go uses `+` in both cases
|
return this.convertBinaryCommon(n.Left, n.Right, `+`) // PHP uses + for numbers, `.` for strings; Go uses `+` in both cases
|
||||||
|
|
||||||
case *binary.Div:
|
case *binary.Div:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `/`) // PHP will upgrade ints to floats, Go won't
|
return this.convertBinaryCommon(n.Left, n.Right, `/`) // PHP will upgrade ints to floats, Go won't
|
||||||
|
|
||||||
case *binary.Equal:
|
case *binary.Equal:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `==`) // Type-lax equality comparator
|
return this.convertBinaryCommon(n.Left, n.Right, `==`) // Type-lax equality comparator
|
||||||
|
|
||||||
case *binary.GreaterOrEqual:
|
case *binary.GreaterOrEqual:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `>=`)
|
return this.convertBinaryCommon(n.Left, n.Right, `>=`)
|
||||||
|
|
||||||
case *binary.Greater:
|
case *binary.Greater:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `>`)
|
return this.convertBinaryCommon(n.Left, n.Right, `>`)
|
||||||
|
|
||||||
case *binary.Identical:
|
case *binary.Identical:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `==`) // PHP uses `===`, Go is already type-safe
|
return this.convertBinaryCommon(n.Left, n.Right, `==`) // PHP uses `===`, Go is already type-safe
|
||||||
|
|
||||||
case *binary.LogicalAnd:
|
case *binary.LogicalAnd:
|
||||||
// This is the lexer token when using `and` in PHP. It's equivalent to
|
// This is the lexer token when using `and` in PHP. It's equivalent to
|
||||||
@ -632,27 +635,27 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
// $a = $b and $c ==> ($a = $b) and $c
|
// $a = $b and $c ==> ($a = $b) and $c
|
||||||
// So far, we are relying on the PHP parser having already having handled
|
// So far, we are relying on the PHP parser having already having handled
|
||||||
// the precedence difference - transform to `&&` unconditionally
|
// the precedence difference - transform to `&&` unconditionally
|
||||||
return convertBinaryCommon(n.Left, n.Right, `&&`)
|
return this.convertBinaryCommon(n.Left, n.Right, `&&`)
|
||||||
|
|
||||||
case *binary.LogicalOr:
|
case *binary.LogicalOr:
|
||||||
// As above
|
// As above
|
||||||
return convertBinaryCommon(n.Left, n.Right, `||`)
|
return this.convertBinaryCommon(n.Left, n.Right, `||`)
|
||||||
|
|
||||||
case *binary.LogicalXor:
|
case *binary.LogicalXor:
|
||||||
// As above
|
// As above
|
||||||
return convertBinaryCommon(n.Left, n.Right, `^`) // n.b. Go only supports this for integers; PHP also supports it for bools
|
return this.convertBinaryCommon(n.Left, n.Right, `^`) // n.b. Go only supports this for integers; PHP also supports it for bools
|
||||||
|
|
||||||
case *binary.Minus:
|
case *binary.Minus:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `-`)
|
return this.convertBinaryCommon(n.Left, n.Right, `-`)
|
||||||
|
|
||||||
case *binary.Mod:
|
case *binary.Mod:
|
||||||
// Go doesn't have a built-in operator for mod - convert to a call to math.Mod()
|
// Go doesn't have a built-in operator for mod - convert to a call to math.Mod()
|
||||||
rval, err := convert(n.Left)
|
rval, err := this.convert(n.Left)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
modulo, err := convert(n.Right)
|
modulo, err := this.convert(n.Right)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -660,26 +663,26 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
return `math.Mod(` + rval + `, ` + modulo + `)`, nil
|
return `math.Mod(` + rval + `, ` + modulo + `)`, nil
|
||||||
|
|
||||||
case *binary.Mul:
|
case *binary.Mul:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `*`)
|
return this.convertBinaryCommon(n.Left, n.Right, `*`)
|
||||||
|
|
||||||
case *binary.NotEqual:
|
case *binary.NotEqual:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `!=`) // Type-lax equality comparator
|
return this.convertBinaryCommon(n.Left, n.Right, `!=`) // Type-lax equality comparator
|
||||||
|
|
||||||
case *binary.NotIdentical:
|
case *binary.NotIdentical:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `!=`) // PHP uses `!==`, Go is already type-safe
|
return this.convertBinaryCommon(n.Left, n.Right, `!=`) // PHP uses `!==`, Go is already type-safe
|
||||||
|
|
||||||
case *binary.Plus:
|
case *binary.Plus:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `+`) // PHP uses + for numbers, `.` for strings; Go uses `+` in both cases
|
return this.convertBinaryCommon(n.Left, n.Right, `+`) // PHP uses + for numbers, `.` for strings; Go uses `+` in both cases
|
||||||
|
|
||||||
case *binary.Pow:
|
case *binary.Pow:
|
||||||
// Go doesn't have a built-in operator for mod - convert to a call to math.Pow()
|
// Go doesn't have a built-in operator for mod - convert to a call to math.Pow()
|
||||||
|
|
||||||
base, err := convert(n.Left)
|
base, err := this.convert(n.Left)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
exponent, err := convert(n.Right)
|
exponent, err := this.convert(n.Right)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
@ -687,16 +690,16 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
return `math.Pow(` + base + `, ` + exponent + `)`, nil
|
return `math.Pow(` + base + `, ` + exponent + `)`, nil
|
||||||
|
|
||||||
case *binary.ShiftLeft:
|
case *binary.ShiftLeft:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `<<`)
|
return this.convertBinaryCommon(n.Left, n.Right, `<<`)
|
||||||
|
|
||||||
case *binary.ShiftRight:
|
case *binary.ShiftRight:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `>>`)
|
return this.convertBinaryCommon(n.Left, n.Right, `>>`)
|
||||||
|
|
||||||
case *binary.SmallerOrEqual:
|
case *binary.SmallerOrEqual:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `<=`)
|
return this.convertBinaryCommon(n.Left, n.Right, `<=`)
|
||||||
|
|
||||||
case *binary.Smaller:
|
case *binary.Smaller:
|
||||||
return convertBinaryCommon(n.Left, n.Right, `<`)
|
return this.convertBinaryCommon(n.Left, n.Right, `<`)
|
||||||
|
|
||||||
case *binary.Spaceship:
|
case *binary.Spaceship:
|
||||||
// The spaceship operator returns -1 / 0 / 1 based on a gteq/leq comparison
|
// The spaceship operator returns -1 / 0 / 1 based on a gteq/leq comparison
|
||||||
@ -704,7 +707,7 @@ func convert(n_ node.Node) (string, error) {
|
|||||||
// The primary use case is in user-definded sort comparators, where Go
|
// The primary use case is in user-definded sort comparators, where Go
|
||||||
// uses bools instead ints anyway.
|
// uses bools instead ints anyway.
|
||||||
// Subtraction is a reasonable substitute
|
// Subtraction is a reasonable substitute
|
||||||
return convertBinaryCommon(n.Left, n.Right, `-`)
|
return this.convertBinaryCommon(n.Left, n.Right, `-`)
|
||||||
|
|
||||||
//
|
//
|
||||||
// scalar
|
// scalar
|
||||||
@ -820,15 +823,15 @@ func convertToStmtList(n node.Node) *stmt.StmtList {
|
|||||||
return stmt.NewStmtList([]node.Node{n})
|
return stmt.NewStmtList([]node.Node{n})
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertBinaryCommon(left, right node.Node, goBinaryOperator string) (string, error) {
|
func (this *conversionState) convertBinaryCommon(left, right node.Node, goBinaryOperator string) (string, error) {
|
||||||
|
|
||||||
// PHP uses + for numbers, `.` for strings; Go uses `+` in both cases
|
// PHP uses + for numbers, `.` for strings; Go uses `+` in both cases
|
||||||
// Assume PHP/Go have the same associativity here
|
// Assume PHP/Go have the same associativity here
|
||||||
lhs, err := convert(left)
|
lhs, err := this.convert(left)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{left, err}
|
return "", parseErr{left, err}
|
||||||
}
|
}
|
||||||
rhs, err := convert(right)
|
rhs, err := this.convert(right)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{right, err}
|
return "", parseErr{right, err}
|
||||||
}
|
}
|
||||||
@ -836,7 +839,7 @@ func convertBinaryCommon(left, right node.Node, goBinaryOperator string) (string
|
|||||||
return "(" + lhs + " " + goBinaryOperator + " " + rhs + ")", nil
|
return "(" + lhs + " " + goBinaryOperator + " " + rhs + ")", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertFuncCallArgsCommon(args *node.ArgumentList) (string, error) {
|
func (this *conversionState) convertFuncCallArgsCommon(args *node.ArgumentList) (string, error) {
|
||||||
|
|
||||||
callParams := make([]string, 0, len(args.Arguments))
|
callParams := make([]string, 0, len(args.Arguments))
|
||||||
for _, arg_ := range args.Arguments {
|
for _, arg_ := range args.Arguments {
|
||||||
@ -845,7 +848,7 @@ func convertFuncCallArgsCommon(args *node.ArgumentList) (string, error) {
|
|||||||
return "", parseErr{arg_, fmt.Errorf("expected node.Argument")}
|
return "", parseErr{arg_, fmt.Errorf("expected node.Argument")}
|
||||||
}
|
}
|
||||||
|
|
||||||
rvalue, err := convert(arg.Expr)
|
rvalue, err := this.convert(arg.Expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{arg, err}
|
return "", parseErr{arg, err}
|
||||||
}
|
}
|
||||||
@ -862,7 +865,7 @@ func convertFuncCallArgsCommon(args *node.ArgumentList) (string, error) {
|
|||||||
return "(" + strings.Join(callParams, `, `) + ")", nil // expr only, no semicolon/newline
|
return "(" + strings.Join(callParams, `, `) + ")", nil // expr only, no semicolon/newline
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertArrayLiteralCommon(items []node.Node) (string, error) {
|
func (this *conversionState) convertArrayLiteralCommon(items []node.Node) (string, error) {
|
||||||
// Array literal
|
// Array literal
|
||||||
// We need to know the type. See if we can guess it from the first child element
|
// We need to know the type. See if we can guess it from the first child element
|
||||||
// At least, we may be able to determine if this is a map or an array
|
// At least, we may be able to determine if this is a map or an array
|
||||||
@ -886,13 +889,13 @@ func convertArrayLiteralCommon(items []node.Node) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vv, err := convert(itm.Val)
|
vv, err := this.convert(itm.Val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{itm, err}
|
return "", parseErr{itm, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
if itm.Key != nil {
|
if itm.Key != nil {
|
||||||
kv, err := convert(itm.Key)
|
kv, err := this.convert(itm.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", parseErr{itm, err}
|
return "", parseErr{itm, err}
|
||||||
}
|
}
|
||||||
@ -910,7 +913,7 @@ func convertArrayLiteralCommon(items []node.Node) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertFunctionCommon(params []node.Node, returnType node.Node, returnsRef bool, bodyStmts []node.Node) (string, error) {
|
func (this *conversionState) convertFunctionCommon(params []node.Node, returnType node.Node, returnsRef bool, bodyStmts []node.Node) (string, error) {
|
||||||
|
|
||||||
// TODO scan function and see if it contains any return statements at all
|
// TODO scan function and see if it contains any return statements at all
|
||||||
// If not, then we only need an err return parameter, not anything else
|
// If not, then we only need an err return parameter, not anything else
|
||||||
@ -954,7 +957,7 @@ func convertFunctionCommon(params []node.Node, returnType node.Node, returnsRef
|
|||||||
|
|
||||||
// Recurse through body statements
|
// Recurse through body statements
|
||||||
|
|
||||||
fullBody, err := convert(stmt.NewStmtList(bodyStmts))
|
fullBody, err := this.convert(stmt.NewStmtList(bodyStmts))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user