{"id":24017805,"url":"https://github.com/m3m0r7/rubyvm-on-php","last_synced_at":"2025-06-16T12:39:13.730Z","repository":{"id":180731622,"uuid":"665544694","full_name":"m3m0r7/rubyvm-on-php","owner":"m3m0r7","description":"A RubyVM written in PHP","archived":false,"fork":false,"pushed_at":"2024-01-02T13:53:30.000Z","size":5607,"stargazers_count":25,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-15T16:33:44.632Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://i.mem.ooo","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/m3m0r7.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-07-12T12:46:59.000Z","updated_at":"2024-12-26T03:59:30.000Z","dependencies_parsed_at":"2023-09-24T12:28:52.477Z","dependency_job_id":"87a49d5c-6119-47d2-8681-698adfa97399","html_url":"https://github.com/m3m0r7/rubyvm-on-php","commit_stats":null,"previous_names":["m3m0r7/rubyvm-on-php"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/m3m0r7/rubyvm-on-php","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3m0r7%2Frubyvm-on-php","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3m0r7%2Frubyvm-on-php/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3m0r7%2Frubyvm-on-php/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3m0r7%2Frubyvm-on-php/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/m3m0r7","download_url":"https://codeload.github.com/m3m0r7/rubyvm-on-php/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m3m0r7%2Frubyvm-on-php/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260163250,"owners_count":22968224,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-08T09:53:10.002Z","updated_at":"2025-06-16T12:39:13.707Z","avatar_url":"https://github.com/m3m0r7.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RubyVM on PHP\n\n\nThe RubyVM on PHP is implementation RubyVM written in PHP 100%.\nCompletely documentation not exists how to implement RubyVM, and I was referred [Ruby source code](https://github.com/ruby/ruby) when contributing this project.\n\n_Notice: This project is very ultra super hyper maximum experimental implementation_\n\n_Notice: I tested Ruby version 3.2 and 3.3 only_\n\n### See also\n- https://github.com/ruby/ruby/blob/master/compile.c\n- https://github.com/ruby/ruby/blob/master/vm.c\n- https://github.com/ruby/ruby/blob/master/vm_exec.c\n\n## DEMO\n\n\u003cimg src=\"./docs/demo.gif\" width=\"100%\" /\u003e\n\n## Requirement\n\n- PHP 8.2+\n\n## Currently status\n\n- Implemented general syntax (define local variables, global variables, classes, methods, booleans, hashes, arrays and so on)\n- Implemented arithmetics (`+`, `-`, `*`, `/`), bit calculating (`|`, `\u0026`, `\u003c\u003c`, `\u003e\u003e`), some operator (`**`, `%`) and available overwrite it\n- Implemented the block syntax (`[].each do | var | ... end`) and non block syntax (`[].push`)\n- Implemented keyword arguments when calling a method (`keyword_argument(a: \"Hello\", c: \"!\", b: \"World\")`)\n- Implemented variadic arguments when using an array and calling a method (`[*var1, *var2]`, `keyword_argument(a, b, *c)`)\n- Implemented partially ruby methods (`to_s`, `to_i`, `[].push`, `foobar.nil?`)\n- Implemented case-when syntax\n- Implemented regexp syntax (`p /Hello/ =~ \"Hello World\"`)\n- Implemented raise/rescue\n- and anymore (see the tests' directory)\n\n## Quick start\n\n1. Install via composer as following\n\n```\n$ composer require m3m0r7/rubyvm-on-php\n```\n\n2. Save the below code as `HelloWorld.rb`\n\n```ruby\nputs RubyVM::InstructionSequence.compile(\"puts 'HelloWorld!\\n'\", \"HelloWorld.rb\").to_binary\n```\n\n3. Output `.yarv` file as following\n\n```shell\n$ ruby HelloWorld.rb \u003e HelloWorld.yarv\n```\n\n3. Create PHP file with below code and save as `HelloWorld.php`\n\n```php\n\u003c?php\nrequire __DIR__ . '/vendor/autoload.php';\n\n// Instantiate RubyVM class\n$rubyVM = new \\RubyVM\\VM\\Core\\Runtime\\RubyVM(\n    new \\RubyVM\\VM\\Core\\Runtime\\Option(\n        reader: new \\RubyVM\\Stream\\BinaryStreamReader(\n            streamHandler: new \\RubyVM\\Stream\\FileStreamHandler(\n                // Specify to want you to load YARV file\n                __DIR__ . '/HelloWorld.yarv',\n            ),\n        ),\n\n        // Choose Logger\n        logger: new \\Psr\\Log\\NullLogger(),\n    ),\n);\n\n// Disassemble instruction sequence binary formatted and get executor\n$executor = $rubyVM-\u003edisassemble();\n\n// You can choose to run ruby version if you needed\n// $executor = $rubyVM-\u003edisassemble(\n//    useVersion: \\RubyVM\\RubyVersion::VERSION_3_2,\n// );\n\n// Execute disassembled instruction sequence\n$executor-\u003eexecute();\n```\n\n4. Run `php HelloWorld.php` and you will get outputted `HelloWorld!` from RubyVM.\n\n## Call defined ruby method on PHP\n\n1. Create ruby code as below:\n\n```ruby\ndef callFromPHP\n  puts \"Hello World from Ruby!\"\nend\n```\n\nAnd then, save file as `test.rb`\n\n2. Compile to YARV as below:\n\n```\n$ ruby -e \"puts RubyVM::InstructionSequence.compile_file('test.rb').to_binary\" \u003e test.yarv\n```\n\n3. Call ruby method on PHP as below:\n```php\n\u003c?php\nrequire __DIR__ . '/vendor/autoload.php';\n\n// Instantiate RubyVM class\n$rubyVM = new \\RubyVM\\VM\\Core\\Runtime\\RubyVM(\n    new \\RubyVM\\VM\\Core\\Runtime\\Option(\n        reader: new \\RubyVM\\Stream\\BinaryStreamReader(\n            streamHandler: new \\RubyVM\\Stream\\FileStreamHandler(\n                // Specify to want you to load YARV file\n                __DIR__ . '/test.yarv',\n            ),\n        ),\n\n        // Choose Logger\n        logger: new \\Psr\\Log\\NullLogger(),\n    ),\n);\n\n// Disassemble instruction sequence binary formatted and get executor\n$executor = $rubyVM-\u003edisassemble();\n\n// Execute disassembled instruction sequence\n$executed = $executor-\u003eexecute();\n\n// Call Ruby method as below code.\n// In this case, you did define method name is `callFromPHP`.\n$executed-\u003econtext()-\u003ecallFromPHP();\n```\n\nYou will get to output `Hello World from Ruby!`.\nIn addition case, maybe you want to pass arguments. of course, it is available on.\nFirst time, to modify previous code as below.\n\n```ruby\ndef callFromPHP(text)\n  puts text\nend\n```\n\nSecond time, to modify PHP code `$executed-\u003econtext()-\u003ecallFromPHP()` as following:\n\n\n```php\n$executed-\u003econtext()-\u003ecallFromPHP('Hello World! Here is passed an argument from PHP!')\n```\n\nYou will get to output `Hello World! Here is passed an argument from PHP`.\n\n## Use an executor debugger\n\nThe RubyVM on PHP is provided an executor debugger that can display processed an INSN and anymore into a table as following:\n\n\n```\n+-----+--------------------------------+-------------------------------+--------------------------------+--------------+\n| PC  | CALLEE                         | INSN                          | CURRENT STACKS                 | LOCAL TABLES |\n+-----+--------------------------------+-------------------------------+--------------------------------+--------------+\n| 0   | \u003cmain\u003e                         | [0x12] putself                |                                |              |\n+-----+--------------------------------+-------------------------------+--------------------------------+--------------+\n| 1   | \u003cmain\u003e                         | [0x15] putstring              | Main#0                         |              |\n+-----+--------------------------------+-------------------------------+--------------------------------+--------------+\n| 3   | \u003cmain\u003e                         | [0x33] opt_send_without_block | Main#0, String(Hello World!)#1 |              |\n|     |                                | (Main#puts(Hello World!))     |                                |              |\n+-----+--------------------------------+-------------------------------+--------------------------------+--------------+\n| 5   | \u003cmain\u003e                         | [0x3c] leave                  | Nil(nil)#0                     |              |\n+-----+--------------------------------+-------------------------------+--------------------------------+--------------+\n```\n\nIf you want to display above table then add below code from the Quick start.\n\n_Notice: The executor debugger is using a lot of memories. We recommend to use disabling ordinarily. In depending on the case, may be using `-d memory_limit=NEEDING_MEMORY_BYTES` parameters to be working when calling `php` command_\n\n```php\n\n// You can display processed an INSN table when adding below code\n$executor-\u003econtext()-\u003eoption()-\u003edebugger()-\u003eshowExecutedOperations();\n```\n\n\n### Step by step debugging\n\nThe RubyVM on PHP is providing step by step debugger. It is available to confirm to process a sequence step by step.\nWhich collect previous stacks, registered local tables and so on. this is required debugging this project.\n\n```php\n// Use breakpoint debugger with option\n\n$rubyVM = new \\RubyVM\\VM\\Core\\Runtime\\RubyVM(\n    new \\RubyVM\\VM\\Core\\Runtime\\Option(\n        // excluded...\n\n        debugger: new \\RubyVM\\VM\\Core\\Runtime\\Executor\\Debugger\\StepByStepDebugger(),\n    ),\n);\n```\n\nWhen you enabled it, displays as below:\n\n```\n+-----+--------------------------------+-------------------------------+--------------------------------+--------------+\n| PC  | CALLEE                         | INSN                          | CURRENT STACKS                 | LOCAL TABLES |\n+-----+--------------------------------+-------------------------------+--------------------------------+--------------+\n| 0   | \u003cmain\u003e                         | [0x12] putself                |                                |              |\n+-----+--------------------------------+-------------------------------+--------------------------------+--------------+\n| 1   | \u003cmain\u003e                         | [0x15] putstring              | Main#0                         |              |\n+-----+--------------------------------+-------------------------------+--------------------------------+--------------+\nCurrent INSN: putstring(0x15)\nPrevious Stacks: [total: 1, OperandEntry\u003cMain\u003e]#966\nPrevious Local Tables: []\nCurrent Stacks: [total: 2, OperandEntry\u003cMain\u003e, OperandEntry\u003cStringSymbol@HelloWorld!\u003e]#561\nCurrent Local Tables: []\n\nEnter to next step (y/n/q): \u003cINPUT_YOU_EXPECTING_NEXT_STEP\u003e\n```\n\n\n## Custom method\n\nThe RubyVM on PHP has custom method in the main context.\nTry to call `phpinfo` as below Ruby code on the RubyVM on PHP:\n\n```ruby\nphpinfo\n```\n\nThen you got displayed `PHP Version: 8.2.7`\n\n## Test\n\n```\n$ ./vendor/bin/phpunit tests/\n```\n\n## Linter\n\n```\n./vendor/bin/php-cs-fixer fix --allow-risky=yes\n```\n\n## How to contribute\n\n1) Build your ruby environment from source code with `-DIBF_ISEQ_DEBUG` flag\n\nSee: https://docs.ruby-lang.org/en/master/contributing/building_ruby_md.html\n\n```\n$ git clone git@github.com:ruby/ruby.git\n$ mkdir build \u0026\u0026 cd build\n$ ../configure cppflags=\"-DIBF_ISEQ_DEBUG=1\"\n$ make -j$(nproc)\n```\n\n2) When you built ruby environment, you will got `vm.inc` file which is wrote how to execute each INSN commands\n\n3) You can get logging at `ibf_load_**` when running ruby code as following\n\n```\n...omitted\n\nibf_load_object: type=0x15 special=1 frozen=1 internal=1      // The type is a FIX_NUMBER (2)\nibf_load_object: index=0x3 obj=0x5\nibf_load_object: list=0xf0 offsets=0x12b80fcf0 offset=0xe1\nibf_load_object: type=0x15 special=1 frozen=1 internal=1      // The type is a FIX_NUMBER (3)\nibf_load_object: index=0x4 obj=0x7\nibf_load_object: list=0xf0 offsets=0x12b80fcf0 offset=0xcd\nibf_load_object: type=0x5 special=0 frozen=1 internal=0       // The type is a STRING SYMBOL (puts)\n\n...omitted\n```\n\nThe above logs is created below example code:\n\n```ruby\nputs 1 + 2 + 3\n```\n\n4) Refer it and now you can contribute to implement INSN command in the RubyVM on PHP\n\n## Other my toys\n\n- [PHPJava](https://github.com/php-java/php-java) - Implement a JVM written in PHP\n- [nfc-for-php](https://github.com/m3m0r7/nfc-for-php) - A NFC Reader (Control a NFC hardware) written in PHP\n- [PHPPython](https://github.com/m3m0r7/PHPPython) - Implement a PYC executor written in PHP\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm3m0r7%2Frubyvm-on-php","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fm3m0r7%2Frubyvm-on-php","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm3m0r7%2Frubyvm-on-php/lists"}