node: support php predefined constants

This commit is contained in:
mappu 2020-04-16 19:13:23 +12:00
parent 9b88dee9ef
commit 3ed24028f4
3 changed files with 71 additions and 2 deletions

View File

@ -8,6 +8,8 @@ echo __Line__;
echo __DIR__; echo __DIR__;
echo PHP_INT_MAX . PHP_EOL ;
echo __NAMESPACE__; echo __NAMESPACE__;
function Foo() { function Foo() {

View File

@ -14,6 +14,13 @@ import (
"php2go/parseutil" "php2go/parseutil"
) )
const (
phpVersionMajor = 7
phpVersionMinor = 4
phpVersionPatch = 0
phpVersionExtra = `-php2go`
)
func ConvertFile(filename string) (string, error) { func ConvertFile(filename string) (string, error) {
inputFile, err := ioutil.ReadFile(filename) inputFile, err := ioutil.ReadFile(filename)
@ -27,7 +34,7 @@ func ConvertFile(filename string) (string, error) {
importPackages: make(map[string]struct{}), importPackages: make(map[string]struct{}),
} }
p, err := parser.NewParser([]byte(inputFile), "7.4") p, err := parser.NewParser([]byte(inputFile), fmt.Sprintf("%d.%d", phpVersionMajor, phpVersionMinor))
if err != nil { if err != nil {
panic(err) panic(err)
} }

62
node.go
View File

@ -1502,7 +1502,67 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
return n.VarName.(*node.Identifier).Value, nil return n.VarName.(*node.Identifier).Value, nil
case *expr.ConstFetch: case *expr.ConstFetch:
return this.resolveName(n.Constant) constRef, err := this.resolveName(n.Constant)
if err != nil {
return "", err
}
// Handle PHP reserved constants
// @ref https://www.php.net/manual/en/reserved.constants.php
if constRef == `PHP_EOL` {
// Not 100% accurate, but realistically this works on Windows too nowadays
return `"\n"`, nil
} else if constRef == `PHP_INT_MAX` {
// Go has math.MaxInt64 in the Math package, etc
// But we don't know if this package will maybe be built on a 32-bit platform
// And we are generating plain `int` types, not necessarily int64 everywhere
// @ref https://stackoverflow.com/a/54421330
this.importPackages["math/bits"] = struct{}{}
return `((1 << bits.UintSize) / -2 /* INT_MAX */)`, nil
} else if constRef == `PHP_VERSION` {
return quoteGoString(fmt.Sprintf("%d.%d.%d%s", phpVersionMajor, phpVersionMinor, phpVersionPatch, phpVersionExtra)), nil
} else if constRef == `PHP_MAJOR_VERSION` {
return fmt.Sprintf("%d", phpVersionMajor), nil
} else if constRef == `PHP_MINOR_VERSION` {
return fmt.Sprintf("%d", phpVersionMinor), nil
} else if constRef == `PHP_RELEASE_VERSION` {
return fmt.Sprintf("%d", phpVersionPatch), nil
} else if constRef == `PHP_VERSION_ID` {
return fmt.Sprintf("%d%02d%02d", phpVersionMajor, phpVersionMinor, phpVersionPatch), nil
} else if constRef == `PHP_EXTRA_VERSION` {
return quoteGoString(phpVersionExtra), nil
} else if constRef == `PHP_ZTS` {
return "true /* PHP_ZTS */", nil
} else if constRef == `PHP_DEBUG` {
return "false /* PHP_DEBUG */", nil
} else if constRef == `PHP_MAXPATHLEN` {
// Not 100% accurate
// Go filesystem functions can transparently handle long paths
// PHP on Linux has a max path of 4096 by default
// Just use that
return "4096 /* MAXPATHLEN */", nil
} else if constRef == `PHP_OS` || constRef == `PHP_OS_FAMILY` {
// Not 100% accurate, but the right idea
this.importPackages["runtime"] = struct{}{}
return `runtime.GOOS`, nil
}
// No const transformation was required
return constRef, nil
case *expr.Array: case *expr.Array:
return this.convertArrayLiteralCommon(n.Items) return this.convertArrayLiteralCommon(n.Items)