node: support magic __FILE__, __LINE__ etc constants
This commit is contained in:
parent
0dfabadcf2
commit
314d65a459
24
fixtures/0011-magic-consts.php
Normal file
24
fixtures/0011-magic-consts.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace myNamespace;
|
||||||
|
|
||||||
|
echo __file__;
|
||||||
|
|
||||||
|
echo __Line__;
|
||||||
|
|
||||||
|
echo __DIR__;
|
||||||
|
|
||||||
|
echo __NAMESPACE__;
|
||||||
|
|
||||||
|
function Foo() {
|
||||||
|
echo __FUNCTION__;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar {
|
||||||
|
function Baz() {
|
||||||
|
echo __CLASS__ . "::" . __METHOD__ ;
|
||||||
|
echo Baz::class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO __TRAIT__
|
62
node.go
62
node.go
@ -39,6 +39,10 @@ type conversionState struct {
|
|||||||
currentClassName string
|
currentClassName string
|
||||||
currentClassParentName string
|
currentClassParentName string
|
||||||
currentErrHandler string
|
currentErrHandler string
|
||||||
|
currentFunctionName string
|
||||||
|
currentMethodName string
|
||||||
|
currentNamespace string
|
||||||
|
currentTraitName string // TODO
|
||||||
importPackages map[string]struct{}
|
importPackages map[string]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,6 +129,7 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
packageName = namespace
|
packageName = namespace
|
||||||
|
this.currentNamespace = packageName
|
||||||
|
|
||||||
default:
|
default:
|
||||||
this.currentErrHandler = "panic(err)\n" // top-level init/main behaviour
|
this.currentErrHandler = "panic(err)\n" // top-level init/main behaviour
|
||||||
@ -273,6 +278,9 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
|||||||
return "", parseErr{s, err}
|
return "", parseErr{s, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prevMethodName := this.currentMethodName
|
||||||
|
this.currentMethodName = funcName
|
||||||
|
|
||||||
// TODO implement abstract methods as method functions
|
// TODO implement abstract methods as method functions
|
||||||
|
|
||||||
// Doc comment
|
// Doc comment
|
||||||
@ -322,6 +330,9 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reinstate stack
|
||||||
|
this.currentMethodName = prevMethodName
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "", parseErr{s, fmt.Errorf("Class '%s' contained unexpected AST node; expected PropertyList / ClassMethod", className)}
|
return "", parseErr{s, fmt.Errorf("Class '%s' contained unexpected AST node; expected PropertyList / ClassMethod", className)}
|
||||||
}
|
}
|
||||||
@ -407,11 +418,18 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
|||||||
funcName = toPublic(funcName)
|
funcName = toPublic(funcName)
|
||||||
|
|
||||||
// Convert body
|
// Convert body
|
||||||
|
prevFuncName := this.currentFunctionName
|
||||||
|
this.currentFunctionName = funcName
|
||||||
|
|
||||||
funcStmt, err := this.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 {
|
||||||
|
// FIXME an early-return will trash the `this` state around currentFunctionName, etc
|
||||||
|
// That's OK for now since we don't practically have any error handling than an unmitigated panic
|
||||||
return "", parseErr{n, err}
|
return "", parseErr{n, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.currentFunctionName = prevFuncName
|
||||||
|
|
||||||
ret := "func " + funcName + funcStmt + "\n"
|
ret := "func " + funcName + funcStmt + "\n"
|
||||||
return ret, nil
|
return ret, nil
|
||||||
|
|
||||||
@ -1188,6 +1206,50 @@ func (this *conversionState) convertNoFreeFloating(n_ node.Node) (string, error)
|
|||||||
|
|
||||||
return strconv.Quote(rawValue), nil // Go source code quoting format
|
return strconv.Quote(rawValue), nil // Go source code quoting format
|
||||||
|
|
||||||
|
case *scalar.MagicConstant:
|
||||||
|
// magic constants are case-insensitive
|
||||||
|
switch strings.ToLower(n.Value) {
|
||||||
|
case `__file__`, `__dir__`:
|
||||||
|
// These are normally used in PHP for finding the absolute webroot directory (e.g. dirname(__FILE__) in index.php)
|
||||||
|
// The letter of the law would be to replace them with the *.go file/dir
|
||||||
|
// We could even emit a runtime call to get the Go file/line: @ref https://github.com/golang/go/issues/12876#issuecomment-146878684
|
||||||
|
// But in practice, the current working directory might be preferable
|
||||||
|
return `""`, nil
|
||||||
|
|
||||||
|
case `__line__`:
|
||||||
|
return fmt.Sprintf("%d", n.Position.StartLine), nil
|
||||||
|
|
||||||
|
case `__namespace__`:
|
||||||
|
return this.currentNamespace, nil
|
||||||
|
|
||||||
|
case `__function__`:
|
||||||
|
if this.currentFunctionName == "" {
|
||||||
|
return "", parseErr{n, fmt.Errorf("use of __FUNCTION__ outside of a function")}
|
||||||
|
}
|
||||||
|
return this.currentFunctionName, nil
|
||||||
|
|
||||||
|
case `__class__`:
|
||||||
|
if this.currentClassName == "" {
|
||||||
|
return "", parseErr{n, fmt.Errorf("use of __CLASS__ outside of a class")}
|
||||||
|
}
|
||||||
|
return this.currentClassName, nil
|
||||||
|
|
||||||
|
case `__method__`:
|
||||||
|
if this.currentMethodName == "" {
|
||||||
|
return "", parseErr{n, fmt.Errorf("use of __METHOD__ outside of a class method")}
|
||||||
|
}
|
||||||
|
return this.currentMethodName, nil
|
||||||
|
|
||||||
|
case `__trait__`:
|
||||||
|
if this.currentTraitName == "" {
|
||||||
|
return "", parseErr{n, fmt.Errorf("use of __TRAIT__ outside of a trait")}
|
||||||
|
}
|
||||||
|
return this.currentTraitName, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "", parseErr{n, fmt.Errorf("unrecognized magic constant '%s'", n.Value)}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user