Convert PHP source code to Go by AST walking
Go to file
2020-04-12 14:40:19 +12:00
fixtures node: basic support for *expr.Closure 2020-04-11 12:46:28 +12:00
vendor vendor: commit github.com/z7zmey/php-parser v0.7.0 (MIT license) 2020-04-05 16:36:06 +12:00
.gitignore fixtures: exclude *.parse.json from git 2020-04-05 16:37:34 +12:00
exhaustive.go create an exhaustive switch interface for node.Node 2020-04-10 18:23:42 +12:00
fixtures_test.go test: ensure fixtures are processed in order 2020-04-05 17:11:20 +12:00
go.mod initial commit 2020-04-05 16:35:44 +12:00
go.sum initial commit 2020-04-05 16:35:44 +12:00
gotype.go gotype: initial commit of Go type abstraction 2020-04-11 12:49:08 +12:00
literal.go initial commit 2020-04-05 16:35:44 +12:00
main.go implement walkMutate(*node); completely transform AltIf->If 2020-04-10 17:37:59 +12:00
miniwalker.go miniwalker: add interface assertion (noop) 2020-04-10 16:30:03 +12:00
mutatingwalker.go implement walkMutate(*node); completely transform AltIf->If 2020-04-10 17:37:59 +12:00
node.go node: implement heredocs + string interpolation 2020-04-12 14:40:19 +12:00
normalisealts.go implement walkMutate(*node); completely transform AltIf->If 2020-04-10 17:37:59 +12:00
quote.go node: use multiline quoting logic consistently in all places 2020-04-12 14:39:38 +12:00
README.md doc: update README status 2020-04-11 13:34:31 +12:00
scope.go gotype: initial commit of Go type abstraction 2020-04-11 12:49:08 +12:00

php2go

Convert PHP source code to Go by AST walking.

The goal is to produce idiomatic, maintainable Go code as part of a one-off conversion. This is not generally possible for highly dynamic PHP code, that may require manual fixups.

Progress

Phase 1

[X] Convert some small programs [X] Error handling - [X] All functions return (type, error) - [X] Convert throw to err return - [X] Non-leaf function calls need to check + bubble errors [X] Array handling - [X] Infer whether to use slice/map for PHP array [-] Namespaces - [X] Basic support for namespace -> package name transformation - [ ] Resolve namespace names in calls - [ ] Resolve use statements [X] if [X] for/foreach [ ] switch [ ] Generators [ ] Numbered break/continue [ ] Goto [X] null -> nil [X] Consts and define() - [X] Magic constants (__LINE__,__FILE__ etc) [ ] isset/unset [ ] instanceof [X] die [X] try/catch/finally - [X] Implement using err checks, not panic/recover - Any statements within the try block should capture the finally/catch to run within any interior err-check blocks - [ ] finally - Runs before any return statement inside the try block or catch block; also runs after the try block is complete - Maybe finally would be more concisely implemented as defer inside an IIFE, but that is not idiomatic, maintainable Go code [ ] Abandon upon sight of eval / extract / variable-variables ... [X] Detect assignment expressions - Go doesn't support assignment in rvalues, only as a statement - When walking below stmt level, need to first fully walk and check for any function calls + assignments that may need hoisting (and we can probably only do that correctly if there is no short-circuiting) - [X] Add subtree walk + catch error for this case [X] Closures - [ ] Handle value/reference captures [X] Convert top-level calls to init()/main() - [X] Wrap in function - [X] Determine init/main based on package name [ ] Class/object transformations - [X] Convert new X constructor calls to NewX - [X] Visibility - [X] Apply PHP visibility modifiers as Go case change - [ ] Call mangled function name at call sites - PHP variable names are case-sensitive, function names are case-insensitive - [X] Static methods - [X] Inheritance partial - [X] Interfaces - [X] Class constants - [X] super - [X] Need to track current conversion state through into function generator, to select the concrete parent - [X] parent:: - [X] self:: - [ ] static:: - [ ] Traits / use - [ ] Abstract methods [X] Track golang package imports [X] Variadic function parameters [X] Preserve comments

Productionize

[ ] Multi-file programs - [ ] Include/Require [ ] Infer whether to declare variable (var / :=) or reuse (=) - [ ] Track current visibility scope [ ] Comprehensive coverage of all AST node types - [X] Create full-coverage interface to implement - [ ] Node - [ ] Stmt - [ ] Expr - [ ] Assign - [X] Binary - [ ] Scalar - [ ] Heredocs/nowdocs [ ] Type inference - [ ] Type declarations for literals (string, slice/map with constant initializer, etc) - [ ] Convert known PHP typenames to Go equivalents - [ ] Parse extra types from phpdoc blocks [ ] Hoisting pass for rvalue expressions - [ ] Behaviour of function calls in rvalue cases where err cannot be checked - [ ] Assignment expressions - [ ] Alternately - we can support the form if foo := bar(); foo { - [ ] Ternarys [ ] Simple standard library transformations - [X] common string/array functions - [ ] More string/array functions - Top 100 from https://www.exakat.io/top-100-php-functions/ - [ ] substr -> slice index operator (although that doesn't have the same reference semantics) - [ ] error_reporting(E_ALL) --> just remove it - [ ] ini_set('display_errors', 'On') --> remove it when the parameter is known [ ] Elide error return for functions that cannot throw - ?? Could be a standalone Go refactoring tool

Wishlist

[ ] Extended library/environment transformations - [ ] Standard library transformations - [X] Track golang package imports - [ ] Handle conflicts between golang stdlib packages / local variable names - [ ] uasort -> sort.Slice - [ ] preg -> regexp - [ ] json -> encoding/json - [ ] Output buffering (ob_start / ob_get_clean) - Can push/pop os.Stdout onto a private stack, then we can keep using fmt.Print - [ ] PHP Superglobal transformations - [ ] $_SERVER['argv'] to os.Args - [ ] $_GET['name'] to r.FormValue('name') - [ ] Common 3rd party package transformations to popular equivalents (optional) - [ ] Guzzle - [ ] AWS SDK - [ ] PHPUnit -> Go Test - [ ] Replace Composer/PSR-4 autoloading with Go imports [ ] Preserve rough line spacing [ ] Somehow detect whether map use should be order-preserving [ ] Support scoped namespace (namespace { ... }) and multiple namespaces in file [ ] Validation on imported comment formats [ ] Convert wordpress / mediawiki / symfony - [ ] Option to convert with preset=cli, preset=web, webroot path - [ ] Option to generate built-in web server [ ] Generate source maps - The parser does have full positional information - exporting at the stmt level would be reasonable - But the gofmt pass may lose this information [ ] Command-line tool option to go run

Reference