An experimental AOT implementation of PHP

Trunk

An experimental PHP implementation that transpiles PHP code into Go code.

Warning!

This is highly experimental. Chances are most of PHP's features can't be replicated in Go due to it's odd type-system.

Running

go run main.go -file ./examples/classes.php

This will produce a ./bin/cmd file that you can execute:

./bin/cmd
Comments
  • fix: new ast for some language constructs

    fix: new ast for some language constructs

    This is a work in progress to address the issue discussed here: https://github.com/php-rust-tools/parser/issues/258

    Some notes:

    1) Currently, die() and exit() are both expressions. I have kept them that way, but I am wondering whether it would be more concise to construct them as statements instead. This is tricky because they behave like functions, but they are not.

    I have coded the spans start and end using an Option<Span> for die() and exit(), as parentheses are optional for them: https://github.com/php-rust-tools/parser/commit/1a0fd301818da1db7e05a3d2236bdb893de8f5b8

    print() handles this differently with value: Parenthesized {:

    https://github.com/php-rust-tools/parser/blob/main/tests/fixtures/0269/ast.txt#L349-L355

    2) print is treated as an expression, but it was coded differently: https://github.com/php-rust-tools/parser/blob/main/src/parser/expressions.rs#L1099

    (The Precedence::Prefix shouldn´t be Precedence::Print?)

    I am wondering whether die() and exit() should follow the same ideas used in print() or if we need to change print() to follow die() and exit().

    3) isset() and unset() are special because they cannot accept all kind of argument. For example, isset(null) is not valid. Therefore, we need to create a new issue to describe the need for a new function to parse their parameters and throw parser errors when necessary. I think this could be work for another PR.

    Not trivial to decide those things. :sweat_smile:

  • fatal runtime error: stack overflow

    fatal runtime error: stack overflow

    When running the test suite on my computer (Linux, Intel I5 6 cores) I got this error:

    running 31 tests
    test composer ... ok
    test chubbyphp_framework ... ok
    test doctrine_dbal ... ok
    test api_platform ... ok
    
    thread 'mezzio-framework' has overflowed its stack
    fatal runtime error: stack overflow
    error: test failed, to rerun pass `--test third_party_tests`
    

    But, changing the stack size from:

    .stack_size(16 * 1024 * 1024)
    

    To:

    .stack_size(24 * 1024 * 1024)
    

    Fixes the issue.

    Are you guys planning some changes on this part or want me to make a PR for it (I mean, to change the stack size)?

  • chore: aesthetic updates to tests

    chore: aesthetic updates to tests

    Hi everyone!

    I'm excited to make my first contribution to the project. I recently started learning about parsers and interpreters, and I've been really interested in exploring the subject further. As a beginner in both the subject and Rust, working on this project is definitely a great way to learn.

    I noticed that there were some areas of the codebase where the style and formatting could be improved, so I took the time to make some changes.

    Are you guys open to accepting this kind of change?

    Cheers!

  • support more types

    support more types

    first commit: add support for more type nodes, don't allow combining standalone types, proper union and intersection type representations, add proper support for try block caught types

    second commit: add a small integration test runner, each test folder must contain code.php, if the code is will result in lexer errors, lexer-error.txt must be created next to code.php containing the formatted error, if the code is will result in parser errors, parser-error.txt must be created next to code.php containing the formatted error.

  • Parse readonly properties and classes

    Parse readonly properties and classes

    Readonly properties, which are required to have type declarations:

    <?php
    
    class C {
        readonly int $a;
        readonly protected string $b;
        readonly static stdClass $c;
    
        function __construct(readonly bool $d) {}
    }
    

    Readonly classes: (coming in PHP 8.2)

    <?php
    
    readonly class C {}
    
  • Lex and parse in terms of bytes rather than characters

    Lex and parse in terms of bytes rather than characters

    Fixes #26.

    I've tried to do as straightforward of conversion as possible so this might be non-optimal in some aspects, but I figure we can do further refactoring later. All tests pass.

    One thing that's worse now is test failures. The Debug impl for Vec<u8> prints things like [50, 51, 52] so it's not very human-readable.

    We could look at pulling in a dependency like bstr, or otherwise adding a custom Debug impl. Let me know what you think and I can either add it onto this PR or do it as a separate one.

  • chore: use `clap` to have command line arguments

    chore: use `clap` to have command line arguments

    This PR:

    • Let clap handle the command line arguments and options

    image

    I'm pretty new with rust, please let me know if I'm doing something wrong, I'm here to learn :)

  • feat: add support for generics

    feat: add support for generics

    • [x] class templates class Foo<T> {}
    • [x] interface templates interface Foo<T> {}
    • [x] method templates public function bar<T>(T $s): T {}
    • [x] function templates function bar<T>(T $s): T {}
    • [x] function call generics foo::<string>()
    • [x] method call generics Foo::bar::<string>()
    • [x] static method call generics $bar->foo::<string>()
    • [x] instance class with generics new Foo::<string>()
    • [x] generic types function foo(Bar<string> $s) {}
    • [x] covariance templates +T
    • [x] contravariance templates -T
    • [x] template sub-type constraint T as Foo
    • [x] template super-type constraint T super Foo
    • [x] template equal-type constraint T = Foo
  • Reflection

    Reflection

    Something I've experimented with a little bit is a reflection API provided by the parser.

    You provide it a generated AST (or multiple ASTs) and the struct is able to traverse the AST to search for function declarations, classes, etc.

    You would then be able to call methods on the struct to find a particular class, function, get type information, params etc.

    This would do a lot of heavy lifting for static analysis tools, dead code finders, interpreters etc.

  • lexer: first pass at string interpolation

    lexer: first pass at string interpolation

    This implements most of double-quoted string interpolation in the lexer. The parser hasn't been modified yet.

    A couple things may need further tweaking:

    The particular tokens that are produced in certain cases. The PHP interpreter has some very specialized tokens (T_STRING, T_NUM_STRING, T_STRING_VARNAME) for string interpolation that I'm going to see if we can do without, and instead push the logic into the parser. If I'm able to do that, it might be possible to get rid of one or two of the extra lexer states added in this PR. I also may end up finding out that there's a good reason for wanting to do this work in the lexer.

    One other difference is that in the PHP interpreter, an interpolated string always begins and ends with the token ". In my implementation here, it always begins with a (possibly empty) TokenKind::StringPart, and always ends with TokenKind::DoubleQuote. Beginning with double quote means having to backtrack on what we've consumed, and beginning with a string part still seem unambiguous.

    The number handling in var_offset is also not quite right. See the TODO. I'll revisit once we've implemented all integer literals.

    Partially addresses #97.

  • parser/lexer: support __halt_compiler token

    parser/lexer: support __halt_compiler token

    Closes #71.

    Introduces a new LexerState::Halted variant. This will tell the lexer to ensure that the token is followed by (); same as PHP itself.

    It then just collects the rest of the tokens into a single InlineHtml token (probably could have done this differently but it works for now) and breaks out of the tokenization loop.

  • keep comments

    keep comments

    currently comments are skipped everywhere, however, we should instead:

    1. collect comments on every state.next() call
    2. retrieve comments and place them on the next statement.
  • Add an AST printer

    Add an AST printer

    An AST printer should be able to take an AST generated by the parser and reconstruct the original PHP source code.

    This will be especially useful for some tools I have planned.

Related tags
Grit is an experimental personal task manager that represents tasks as nodes of a multitree
Grit is an experimental personal task manager that represents tasks as nodes of a multitree

Grit is an experimental personal task manager that represents tasks as nodes of a multitree, a class of directed acyclic graphs. The structure en

Jan 2, 2023
Experimental go cli tool to track your open issues and PRs.
Experimental go cli tool to track your open issues and PRs.

git-sum cli tool See open issue and pull request counts for each repository of the user. Installation go install github.com/suadev/git-sum@latest Usa

Jan 21, 2022
K-Mesh is an experimental Knative distribution which provides a fresh, CLI-focused, holistic user experience of running and managing Knative.

K-Mesh is an experimental Knative distribution which provides a fresh, CLI-focused, holistic user experience of running and managing Knative. N

Feb 14, 2022
Rule engine implementation in Golang
Rule engine implementation in Golang

"Gopher Holds The Rules" Grule-Rule-Engine import "github.com/hyperjumptech/grule-rule-engine" Rule Engine for Go Grule is a Rule Engine library for t

Jan 3, 2023
An implementation of sed in Go. Just because!

Sed-Go An implementation of sed in Go. Just because! Status Command-Line processing: Done. It accepts '-e', '-f', '-n' and long versions of the same.

Aug 23, 2022
Readline is a pure go(golang) implementation for GNU-Readline kind library
Readline is a pure go(golang) implementation for GNU-Readline kind library

A powerful readline library in Linux macOS Windows Solaris Guide Demo Shortcut Repos using readline Feedback If you have any questions, please submit

Jan 8, 2023
Reference go implementation of globalDCE protocol

globalDCE-go This is the reference implementation of the command line interface of globalDCE coded in the go programming language. This project is sti

Nov 15, 2021
Reference implementation of globaldce protocol coded in go

globaldce This is the reference implementation of the command line interface of globaldce coded in the go programming language. This project is still

Nov 15, 2021
A go language implementation of a CLI, based on input directory files

A go language implementation of a CLI, based on input directory files, using tree output of all file names, based on input database links, dynamic reading of database table information, based on input swagger files to automate the generation of the RESTFUL API.

Aug 23, 2022
Simple trie based auto-completion engine implementation in golang.
Simple trie based auto-completion engine implementation in golang.

Simple auto-complete engine implementation in golang. Quick start $ git clone https://github.com/benbarron/trie-auto-completion-engine $ cd trie-auto-

Jul 12, 2022
Golang implementation of the research by @jonaslyk and the drafted PoC from @LloydLabs

Doge-SelfDelete Golang implementation of the research by @jonaslyk and the drafted PoC from @LloydLabs Golang 实现的文件自删除,来自@jonaslyk和@LloydLabs etc add

Oct 2, 2022
Golang implementation of Reflective load PE from memory

?? Frog For Automatic Scan ?? Doge For Defense Evasion & Offensive Security Doge-MemX Golang implementation of Reflective load PE from memory Only Sup

Dec 6, 2022
Nano API Implementation in Golang

nanoapi Nano API Implementation in GO TL;DR The idea is to create a very simple

Jan 9, 2022
An implementation of the Nano cryptocurrency protocol in golang

Go Nano An implementation of the Nano protocol written from scratch in Go (golang). About the Project A crypto currency has to be resilient to survive

Dec 7, 2022
Golisp-wtf - A lisp interpreter (still just a parser) implementation in golang. You may yell "What the fuck!?.." when you see the shitty code.

R6RS Scheme Lisp dialect interpreter This is an implementation of a subset of R6RS Scheme Lisp dialect in golang. The work is still in progress. At th

Jan 7, 2022
A TUI implementation of the popular word quiz wordle!

gordle A TUI implementation of the popular word quiz Wordle! Building Build the cli command: $ go build ./cmd/cli <Empty output on build success> Buil

Dec 21, 2022
A Go implementation of gnu-coreutils programs

Go-Coreutils A Go implementation of gnu-coreutils programs (https://www.gnu.org/software/coreutils/manual/coreutils.html) Build and Run In the root di

Jan 15, 2022
Doge-AddSSP - Load ssp dll golang implementation

Doge-AddSSP Load ssp dll golang implementation Administrator/System Privilege Us

Nov 9, 2022
Go-snake - Go CLI implementation of Snake game, using channels
Go-snake - Go CLI implementation of Snake game, using channels

go-snake ?? Go CLI implementation of Snake game, using channels. NB: this code w

Oct 19, 2022