node: convert use of strlen/cound/sizeof/explode/implode

This commit is contained in:
mappu 2020-04-10 20:08:40 +12:00
parent 92abcfe5b9
commit 7461bfe187
1 changed files with 33 additions and 9 deletions

42
node.go
View File

@ -610,7 +610,7 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
// No need to use a child scope for the temporary name - // No need to use a child scope for the temporary name -
// super() is a reserved name in PHP anyway // super() is a reserved name in PHP anyway
ret := "super, err := " + constructorName(this.currentClassParentName) + funcArgs + "\n" ret := "super, err := " + constructorName(this.currentClassParentName) + "(" + strings.Join(funcArgs, ", ") + ")\n"
ret += "if err != nil {\n" ret += "if err != nil {\n"
ret += this.currentErrHandler //"return err\n" ret += this.currentErrHandler //"return err\n"
ret += "}\n" ret += "}\n"
@ -931,7 +931,31 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
// FIXME need to support `this.currentErrHandler` // FIXME need to support `this.currentErrHandler`
return funcName + callParams, nil // expr only, no semicolon/newline // Transform some PHP standard library functions to their Go equivalents
// TODO check namespacing for collision prevention
if funcName == `strlen` || funcName == `count` || funcName == `sizeof` {
funcName = `len`
} else if funcName == `explode` {
if len(callParams) != 2 {
return "", parseErr{n, fmt.Errorf("Call to \\explode() should have 2 arguments, got %d", len(callParams))}
}
this.importPackages["strings"] = struct{}{}
funcName = `strings.Split`
callParams[0], callParams[1] = callParams[1], callParams[2] // need to reverse function argument order
} else if funcName == `implode` {
if len(callParams) != 2 {
return "", parseErr{n, fmt.Errorf("Call to \\implode() should have 2 arguments, got %d", len(callParams))}
}
this.importPackages["strings"] = struct{}{}
funcName = `strings.Join`
callParams[0], callParams[1] = callParams[1], callParams[2] // need to reverse function argument order
}
return funcName + "(" + strings.Join(callParams, ", ") + ")", nil // expr only, no semicolon/newline
case *expr.StaticCall: case *expr.StaticCall:
className, err := this.resolveName(n.Class) className, err := this.resolveName(n.Class)
@ -960,7 +984,7 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
// FIXME need to support `this.currentErrHandler` // FIXME need to support `this.currentErrHandler`
return callTarget + callParams, nil // expr only, no semicolon/newline return callTarget + "(" + strings.Join(callParams, ", ") + ")", nil // expr only, no semicolon/newline
case *expr.New: case *expr.New:
// new foo(xx) // new foo(xx)
@ -1054,7 +1078,7 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
// FIXME need to support `this.currentErrHandler` // FIXME need to support `this.currentErrHandler`
return parent + "." + child + args, nil return parent + "." + child + "(" + strings.Join(args, ", ") + ")", nil
case *expr.PropertyFetch: case *expr.PropertyFetch:
// Foo->Bar // Foo->Bar
@ -1397,7 +1421,7 @@ func constructorName(className string) string {
// This is only safe in cases where there is ambiguously a single rvalue wanted, // This is only safe in cases where there is ambiguously a single rvalue wanted,
// e.g. between ( and , in a function call argument // e.g. between ( and , in a function call argument
func removeParens(expr string) string { func removeParens(expr string) string {
for len(expr) > 2 && expr[0] == '(' && expr[len(expr)-1] == ')' { for len(expr) > 2 && expr[0] == '(' && expr[len(expr)-1] == ')' && !strings.HasSuffix(expr, `()`) {
expr = expr[1 : len(expr)-1] expr = expr[1 : len(expr)-1]
} }
return expr return expr
@ -1567,18 +1591,18 @@ func (this *conversionState) convertBinaryCommon(left, right node.Node, goBinary
return "(" + lhs + " " + goBinaryOperator + " " + rhs + ")", nil return "(" + lhs + " " + goBinaryOperator + " " + rhs + ")", nil
} }
func (this *conversionState) 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 {
arg, ok := arg_.(*node.Argument) arg, ok := arg_.(*node.Argument)
if !ok { if !ok {
return "", parseErr{arg_, fmt.Errorf("expected node.Argument")} return nil, parseErr{arg_, fmt.Errorf("expected node.Argument")}
} }
rvalue, err := this.convert(arg.Expr) rvalue, err := this.convert(arg.Expr)
if err != nil { if err != nil {
return "", parseErr{arg, err} return nil, parseErr{arg, err}
} }
if arg.IsReference { if arg.IsReference {
rvalue = "&" + rvalue rvalue = "&" + rvalue
@ -1590,7 +1614,7 @@ func (this *conversionState) convertFuncCallArgsCommon(args *node.ArgumentList)
callParams = append(callParams, removeParens(rvalue)) callParams = append(callParams, removeParens(rvalue))
} }
return "(" + strings.Join(callParams, `, `) + ")", nil // expr only, no semicolon/newline return callParams, nil
} }
func (this *conversionState) convertArrayLiteralCommon(items []node.Node) (string, error) { func (this *conversionState) convertArrayLiteralCommon(items []node.Node) (string, error) {