binary: implement all remaining binary operators
This commit is contained in:
parent
8f921436ed
commit
d3f238cf01
123
node.go
123
node.go
@ -491,31 +491,122 @@ func convert(n_ node.Node) (string, error) {
|
||||
// binary
|
||||
//
|
||||
|
||||
case *binary.Plus:
|
||||
// PHP uses + for numbers, `.` for strings; Go uses `+` in both cases
|
||||
return convertBinaryCommon(n.Left, n.Right, `+`)
|
||||
case *binary.BitwiseAnd:
|
||||
return convertBinaryCommon(n.Left, n.Right, `&`)
|
||||
|
||||
case *binary.Smaller:
|
||||
return convertBinaryCommon(n.Left, n.Right, `<`)
|
||||
case *binary.BitwiseOr:
|
||||
return convertBinaryCommon(n.Left, n.Right, `|`)
|
||||
|
||||
case *binary.SmallerOrEqual:
|
||||
return convertBinaryCommon(n.Left, n.Right, `<=`)
|
||||
case *binary.BitwiseXor:
|
||||
return convertBinaryCommon(n.Left, n.Right, `^`) // n.b. Go only supports this for integers; PHP also supports it for bools
|
||||
|
||||
case *binary.Greater:
|
||||
return convertBinaryCommon(n.Left, n.Right, `>`)
|
||||
case *binary.BooleanAnd:
|
||||
return convertBinaryCommon(n.Left, n.Right, `&&`)
|
||||
|
||||
case *binary.BooleanOr:
|
||||
return convertBinaryCommon(n.Left, n.Right, `||`)
|
||||
|
||||
//case *binary.Coalesce:
|
||||
// TODO this can't be expressed in an rvalue context in Go (unless we create a typed closure..?)
|
||||
|
||||
case *binary.Concat:
|
||||
return convertBinaryCommon(n.Left, n.Right, `+`) // PHP uses + for numbers, `.` for strings; Go uses `+` in both cases
|
||||
|
||||
case *binary.Div:
|
||||
return convertBinaryCommon(n.Left, n.Right, `/`) // PHP will upgrade ints to floats, Go won't
|
||||
|
||||
case *binary.Equal:
|
||||
return convertBinaryCommon(n.Left, n.Right, `==`) // Type-lax equality comparator
|
||||
|
||||
case *binary.GreaterOrEqual:
|
||||
return convertBinaryCommon(n.Left, n.Right, `>=`)
|
||||
|
||||
case *binary.Equal:
|
||||
return convertBinaryCommon(n.Left, n.Right, `==`)
|
||||
case *binary.Greater:
|
||||
return convertBinaryCommon(n.Left, n.Right, `>`)
|
||||
|
||||
case *binary.Identical: // PHP triple-equals
|
||||
return convertBinaryCommon(n.Left, n.Right, `===`)
|
||||
case *binary.Identical:
|
||||
return convertBinaryCommon(n.Left, n.Right, `==`) // PHP uses `===`, Go is already type-safe
|
||||
|
||||
case *binary.Concat:
|
||||
// PHP uses + for numbers, `.` for strings; Go uses `+` in both cases
|
||||
return convertBinaryCommon(n.Left, n.Right, `+`)
|
||||
case *binary.LogicalAnd:
|
||||
// This is the lexer token when using `and` in PHP. It's equivalent to
|
||||
// `&&` but has different precedence
|
||||
// e.g. $a = $b && $c ==> $a = ($b && $c)
|
||||
// $a = $b and $c ==> ($a = $b) and $c
|
||||
// So far, we are relying on the PHP parser having already having handled
|
||||
// the precedence difference - transform to `&&` unconditionally
|
||||
return convertBinaryCommon(n.Left, n.Right, `&&`)
|
||||
|
||||
case *binary.LogicalOr:
|
||||
// As above
|
||||
return convertBinaryCommon(n.Left, n.Right, `||`)
|
||||
|
||||
case *binary.LogicalXor:
|
||||
// As above
|
||||
return convertBinaryCommon(n.Left, n.Right, `^`) // n.b. Go only supports this for integers; PHP also supports it for bools
|
||||
|
||||
case *binary.Minus:
|
||||
return convertBinaryCommon(n.Left, n.Right, `-`)
|
||||
|
||||
case *binary.Mod:
|
||||
// Go doesn't have a built-in operator for mod - convert to a call to math.Mod()
|
||||
rval, err := convert(n.Left)
|
||||
if err != nil {
|
||||
return "", parseErr{n, err}
|
||||
}
|
||||
|
||||
modulo, err := convert(n.Right)
|
||||
if err != nil {
|
||||
return "", parseErr{n, err}
|
||||
}
|
||||
|
||||
return `math.Mod(` + rval + `, ` + modulo + `)`, nil
|
||||
|
||||
case *binary.Mul:
|
||||
return convertBinaryCommon(n.Left, n.Right, `*`)
|
||||
|
||||
case *binary.NotEqual:
|
||||
return convertBinaryCommon(n.Left, n.Right, `!=`) // Type-lax equality comparator
|
||||
|
||||
case *binary.NotIdentical:
|
||||
return convertBinaryCommon(n.Left, n.Right, `!=`) // PHP uses `!==`, Go is already type-safe
|
||||
|
||||
case *binary.Plus:
|
||||
return convertBinaryCommon(n.Left, n.Right, `+`) // PHP uses + for numbers, `.` for strings; Go uses `+` in both cases
|
||||
|
||||
case *binary.Pow:
|
||||
// Go doesn't have a built-in operator for mod - convert to a call to math.Pow()
|
||||
|
||||
base, err := convert(n.Left)
|
||||
if err != nil {
|
||||
return "", parseErr{n, err}
|
||||
}
|
||||
|
||||
exponent, err := convert(n.Right)
|
||||
if err != nil {
|
||||
return "", parseErr{n, err}
|
||||
}
|
||||
|
||||
return `math.Pow(` + base + `, ` + exponent + `)`, nil
|
||||
|
||||
case *binary.ShiftLeft:
|
||||
return convertBinaryCommon(n.Left, n.Right, `<<`)
|
||||
|
||||
case *binary.ShiftRight:
|
||||
return convertBinaryCommon(n.Left, n.Right, `>>`)
|
||||
|
||||
case *binary.SmallerOrEqual:
|
||||
return convertBinaryCommon(n.Left, n.Right, `<=`)
|
||||
|
||||
case *binary.Smaller:
|
||||
return convertBinaryCommon(n.Left, n.Right, `<`)
|
||||
|
||||
case *binary.Spaceship:
|
||||
// The spaceship operator returns -1 / 0 / 1 based on a gteq/leq comparison
|
||||
// Go doesn't have a built-in spaceship operator
|
||||
// The primary use case is in user-definded sort comparators, where Go
|
||||
// uses bools instead ints anyway.
|
||||
// Subtraction is a reasonable substitute
|
||||
return convertBinaryCommon(n.Left, n.Right, `-`)
|
||||
|
||||
//
|
||||
// scalar
|
||||
|
Loading…
Reference in New Issue
Block a user