diff --git a/node.go b/node.go index d330bf0..c5e000d 100644 --- a/node.go +++ b/node.go @@ -610,7 +610,7 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error) // No need to use a child scope for the temporary name - // 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 += this.currentErrHandler //"return err\n" ret += "}\n" @@ -931,7 +931,31 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error) // 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: 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` - return callTarget + callParams, nil // expr only, no semicolon/newline + return callTarget + "(" + strings.Join(callParams, ", ") + ")", nil // expr only, no semicolon/newline case *expr.New: // new foo(xx) @@ -1054,7 +1078,7 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error) // FIXME need to support `this.currentErrHandler` - return parent + "." + child + args, nil + return parent + "." + child + "(" + strings.Join(args, ", ") + ")", nil case *expr.PropertyFetch: // 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, // e.g. between ( and , in a function call argument 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] } return expr @@ -1567,18 +1591,18 @@ func (this *conversionState) convertBinaryCommon(left, right node.Node, goBinary 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)) for _, arg_ := range args.Arguments { arg, ok := arg_.(*node.Argument) 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) if err != nil { - return "", parseErr{arg, err} + return nil, parseErr{arg, err} } if arg.IsReference { rvalue = "&" + rvalue @@ -1590,7 +1614,7 @@ func (this *conversionState) convertFuncCallArgsCommon(args *node.ArgumentList) 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) {