{"id":13726324,"url":"https://github.com/jordwalke/rehp","last_synced_at":"2026-02-08T23:32:54.559Z","repository":{"id":40000499,"uuid":"135995485","full_name":"jordwalke/rehp","owner":"jordwalke","description":"ReHp","archived":false,"fork":false,"pushed_at":"2021-02-28T08:20:31.000Z","size":20592,"stargazers_count":224,"open_issues_count":25,"forks_count":15,"subscribers_count":16,"default_branch":"master","last_synced_at":"2024-04-15T15:08:37.863Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"OCaml","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jordwalke.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-04T08:37:39.000Z","updated_at":"2024-01-21T16:16:39.000Z","dependencies_parsed_at":"2022-06-26T06:02:17.819Z","dependency_job_id":null,"html_url":"https://github.com/jordwalke/rehp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jordwalke/rehp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jordwalke%2Frehp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jordwalke%2Frehp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jordwalke%2Frehp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jordwalke%2Frehp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jordwalke","download_url":"https://codeload.github.com/jordwalke/rehp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jordwalke%2Frehp/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268629589,"owners_count":24281172,"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","status":"online","status_checked_at":"2025-08-03T02:00:12.545Z","response_time":2577,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":"2024-08-03T01:02:59.272Z","updated_at":"2026-02-08T23:32:49.524Z","avatar_url":"https://github.com/jordwalke.png","language":"OCaml","funding_links":[],"categories":["OCaml"],"sub_categories":[],"readme":"# ReHP: Compile Reason/OCaml to PHP.\n\n`rehp` makes it easier to write new language backends for\nReason/OCaml that integrate well into existing languages.\n\n\n`rehp` takes opam/esy packages that would normally compile natively, and\ninstead compiles them to PHP. Currently, `rehp` compiles to the\n[Hack](https://hhvm.com/) variant of PHP, but we plan on outputing pure PHP5 as\nwell. In either case, the output is very simple and doesn't used advanced\nlanguage features.\n\nUnder the hood, `rehp` is a fork of\n[js_of_ocaml](https://github.com/ocsigen/js_of_ocaml), refactored to make\nsupporting other language backends easier. Most of this project can be merged\nupstream into `js_of_ocaml`, aside from the parts that are specific to only one\nlanguage backend. \n\n### Who\n\n[jordwalke](https://twitter.com/jordwalke) and\n[robbynevels](https://twitter.com/robbynevels) have contributed the commits on\ntop of `js_of_ocaml` (`git` blame is not representative for those commits)\n\n\n## Goals:\n\nOur first focus will remain on the PHP/Hack backend for Reason applications\nuntil that is sufficiently stable, however we can begin sending pull requests\nto `js_of_ocaml` for the earliest commits.\n\nIf many of the changes are merged (after addressing any feedback), the time\nrequired to add additional language backends for Reason/OCaml will be cut down\ndramatically (Java, VimScript).\n\n# Features:\n\n- Working PHP/Hack language backend for Reason/OCaml projects.\n- Integrates with arbitrary language module loaders via a special template\n  format that describes the style of module output, and how dependencies should\n  be required.\n- Compiles package dependencies (`.cma` libraries) into individual module\n  outputs. `rehp` adds a feature for decomposing compiled\n  libraries into individual module outputs, instead of having them be bundled\n  together in the output.\n- Allows writing multiple backend implementations of C stubs in one file. In\n  addition to `// @Provides`, you may now also supply `// @ForBackend`.\n\n# Try Running Tests\n\nMake sure you have `esy --version` \u003e `0.5.4`. If not install using the\ninstructions on [the esy site](https://esy.sh).\n\nThen `git clone` this repo and run the following to install/build then test.\n\n```\nesy\nesy test\n```\n\n# Try From Your Project:\n\nYou can try out `rehp` on your project, by using [esy](https://esy.sh) to\ndirectly consume this repo. See [hello-rehp](https://github.com/robz/hello-rehp) \nas an example.\n\nJust add the following to your `package.json` and then run `esy` from your project \nroot as usual. \n\n```json\n\"dependencies\": {\n  \"@opam/js_of_ocaml\": \"*\"\n},\n\"resolutions\": {\n  \"@opam/js_of_ocaml\": \"jordwalke/rehp:js_of_ocaml.opam#f65bbc\",\n  \"@opam/js_of_ocaml-compiler\": \"jordwalke/rehp:js_of_ocaml-compiler.opam#f65bbc\"\n},\n```\n\nThen you can try the PHP compiler by doing:\n\n```sh\nFLAGS=\"--backend php --enable excwrap --enable wrapped-exceptions\"\n\n# Compile a library to individual php files.\nesy js_of_ocaml $FLAGS someFile.cma -o someOutput.cma.php\n\n# Compile a bytecode app to one monolithic output.\nesy js_of_ocaml $FLAGS someFile.bc -o someOutput.bc.php\n```\n\n## Module Templates:\n\n`rehp` allows you to pass strings to `--custom-header` that determine how each\nindividual input `.re` file is compiled into each individual output file, and\nhow it should pull in dependencies. The custom header param is a string\ntemplate with a mini-DSL to help you describe how to pull in each dependency,\nand where to put the main compiled output for each module.\n\nThis was implemented to work with PHP module loaders, but it will work with any\nlanguage, and the example below demonstrates it with JS modules for\nillustration.\n\nFor example if you had a file `js-module-template.js`, with the following\ncontent:\n\n```javascript\n/**\n * ____CompilationUnitName\n */\nvar ____ForEachDependencyCompilationUnitName = require('____ForEachDependencyCompilationUnitName.js');\nvar runtime = require('runtime.js');\n\n/*____CompilationOutput*/\nmodule.exports = global.jsoo_runtime.caml_get_global_data().____CompilationUnitName;\n```\n\nThen if you passed it as a parameter to compilation:\n\n```bash\n# Read the file into a variable\n$TEMPLATE=\"$(\u003c ./js-module-template.js)\"\nesy js_of_ocaml --custom-header=$TEMPLATE Array.cmo -o Array.js\n```\n\nThen you would have a module compiled as:\n\n```javascript\n/**\n * Array\n */\nvar Pervasives = require('Pervasives.js');\nvar List = require('List.js');\nvar runtime = require('runtime.js');\n\n// \u003c Compiled output here \u003e\n\nmodule.exports = global.jsoo_runtime.caml_get_global_data().Array;\n```\n\nEach line that has a `____ForEachDependencyCompilationUnitName` is expanded\ninto several lines, one line for each dependency of the module, where\n`____ForEachDependencyCompilationUnitName` is replaced with the capitalized\ndependency name.\n\nThere are other variables that are substituted in the template:\n\n- `____CompilationUnitName` The name of the current compilation unit,\n  capitalized.\n- `____compilationUnitName` The name of the current compilation unit,\n  lowercased.\n- `____ForEachDependencyCompilationUnitName` : Expanded into multiple lines,\n  one line for dependency (capitalized).\n- `____forEachDependencyCompilationUnitName` : Expanded into multiple lines,\n  one line for dependency (lowercased).\n- `/*____CompilationOutput*/` : Where the compilation output will be placed.\n\n\n## Collaborating:\n\nWe are actively welcoming collaboration in helping with the overall design, and\nimplementation of this project and the changes to the `js_of_ocaml` compiler.\nA quick coordination with `@jordwalke` on the [Reason\nDiscord](https://discord.gg/reasonml) or any other chat system will help us\nmake sure we aren't developing improvements redundantly.\n\n\nTo build this project, and collaborate, you can use opam or `esy`.  If using\n`esy`, make sure `esy --version` is \u003e `0.5.4`. Just run `esy` from the top\nlevel directory of this project, then run `esy test` to see compiled outputs of\nvarious tests.\n\n\n# How\n\nWe introduce a new intermediate representation in the compiler called\n`Rehp`(name to be changed).\n\n**`Rehp`**: A constrained intermediate language with the purpose of targeting\nhigher level languages (such as PHP).\n\nRehp's semantics are similar to a narrow subset of JavaScript, with the\naddition of special nodes that have type specific operations, externs, and\nretain shapes of structures emitted by the ocaml compiler.\n\nCurrently, Rehp contains too many forms, because JavaScript stubs have to be\nconverted to Rehp. The This project aims to remove that architectural feature\nof js_of_ocaml, so that js_of_ocaml treats hand written JavaScript stubs as raw\nstrings, without ever doing any analysis on them. Then we can remove many parts\nof Rehp - as a result compilation will be much faster as well.\n\n# Status:\n\nThe earliest commits are easy to upstream, and the later commits are\napproaching an upstreamable state.\n\n\n# Helping Out:\nHere are some ways you can help out:\n\n- Get it building locally.\n- If you have a problem getting it build/tested locally, fix it and send a PR.\n- If you see something that can be improved, do it.\n- If you see something that can be upstreamed to `js_of_ocaml`, break it off\n  into a PR to `js_of_ocaml`.\n- The later commits which still need some organization are not upstreamable but\n  some of them could be with your help. The code that switches between JS and\n  PHP mode should be functorized or turned into Dune virtual libraries.\n- If you see something you don't like, start a discussion about changing it, or\n  just try changing it.\n\n# Next Steps:\n\n- Give back as much as possible upstream to `js_of_ocaml`.\n- Treat all language stubs as raw text, performing no analysis on them (except\n  arity and dependency tracking).\n  - This allows us to greatly simplify the Rehp tree, trimming it down to only\n    what is needed to compile bytecode to other languages, not analyze\n    JavaScript source stubs.\n  - Requires another solution to track arity optimizations.\n    - Encode arity in function names?\n- We also aim to formalize the semantics of Rehp, as well as specify language\n  requirements.\n  - Variable scoping.\n  - Reference semantics.\n  - Function arity / application.\n  - And more.\n- Rewrite the PHP stubs by hand. Currently, we include a compiler from JS to\n  PHP just to automate writing the existing JS stubs, but this is only\n  temporary.\n- Have each extern stub implementation exist in its own file.\n- Remove packaging / minifying features of `js_of_ocaml`, and delegate that to\n  conventional tools. (This makes it easier to add new language backends). \n- Remove a lot of the code that tries to detect missing stubs. Module loaders\n  and bundlers will typically do so. It adds a lot of complexity that makes it\n  difficult to abstract to multiple language backends.\n\nThe approach taken in `rehp` is to simplify `js_of_ocaml` so that it can apply\nto many languages. Part of that means getting `js_of_ocaml` out of the\nbundling/module game and letting the output integrate better with the target\nlanguage. It also makes some steps (not enough yet) to make `js_of_ocaml` treat\nstubs as raw code and not do any analysis on it (other than arity analysis for\noptimization).\n\nIn order to do this, we recommend further simplifying how runtime dependencies\nare pulled in, also using language modules to represent them. Currently, it is\nnot the case and there is one large runtime file generated.\n\nAlso, `js_of_ocaml` currently supports three modes:\n\n1. Individual modules / libraries.\n2. Monolithic compilation of bytecode executables with embedded runtime.\n3. Monolithic compilation of bytecode executables without embedded runtime.\n\nWe suggest that supporting the second mode adds little benefit but adds a lot\nof additional complexity to the implementation. It should likely be removed.\nThe third mode has some benefits over mode `1`(individual modules/library\ncompilation). That is, monolithic mode allows additional optimizations and\ninlining. It is worth keeping monolithic compilation in general.\n\n\n\n## Contents of the distribution\n| Filename    | Description                                  |\n|-----------  |----------------------------------------------|\n| LICENSE     | license and copyright notice                 |\n| README      | this file                                    |\n| compiler/   | compiler                                     |\n| examples/   | small examples                               |\n| lib/        | library for interfacing with JavaScript APIs |\n| ppx/        | ppx syntax extensions                        |\n| runtime/    | runtime system                               |\n| toplevel/   | web-based OCaml toplevel                     |\n| ocamlbuild/ | ocamlbuild plugin for js_of_ocaml            |\n\n## Thanks:\n\nThank you to everyone who answered questions, and has provided guidance about\nthe overall approach.\n\n- [hhugo](https://github.com/hhugo)\n- [vouillon](https://github.com/vouillon)\n- [let-def](https://github.com/let-def)\n- [vincentbalat](https://twitter.com/vincentbalat)\n- [diml](https://github.com/diml)\n\n\nAlso, thank you to everyone who created / improved `js_of_ocaml` over the\nyears.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjordwalke%2Frehp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjordwalke%2Frehp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjordwalke%2Frehp/lists"}