All Projects → darklang → Philip2

darklang / Philip2

Licence: mit
An Elm to OCaml compiler

Programming Languages

ocaml
1615 projects
elm
856 projects
bucklescript
41 projects

Projects that are alternatives of or similar to Philip2

Enso
Hybrid visual and textual functional programming.
Stars: ✭ 5,238 (+2778.02%)
Mutual labels:  compiler, functional
tea-chess
A chess-themed tutorial on writing an SPA in Bucklescript-TEA
Stars: ✭ 28 (-84.62%)
Mutual labels:  elm-architecture, reasonml
Ddc
The Disco Discus Compiler
Stars: ✭ 164 (-9.89%)
Mutual labels:  compiler, functional
Enso Archive
Looking for Enso, the visual programming language? ➡️ https://github.com/enso-org/enso
Stars: ✭ 305 (+67.58%)
Mutual labels:  compiler, functional
Bubbletea
A powerful little TUI framework 🏗
Stars: ✭ 7,886 (+4232.97%)
Mutual labels:  elm-architecture, functional
Elementx
⚡️ Functionally create DOM elements and compose them to a tree quickly
Stars: ✭ 62 (-65.93%)
Mutual labels:  functional, frontend
Poprc
A Compiler for the Popr Language
Stars: ✭ 170 (-6.59%)
Mutual labels:  compiler, functional
C3c
Compiler for the C3 language
Stars: ✭ 178 (-2.2%)
Mutual labels:  compiler
Quasar
An experimental rust-to-{wasm,asmjs} frontend framework.
Stars: ✭ 180 (-1.1%)
Mutual labels:  frontend
Bootstrap Input Spinner
A Bootstrap 4 / jQuery plugin to create input spinner elements for number input
Stars: ✭ 176 (-3.3%)
Mutual labels:  frontend
Software Engineer Interview Questions
A lot of questions and links to prepare yourself for an interview.
Stars: ✭ 176 (-3.3%)
Mutual labels:  frontend
Alfredmagic
一个面向效率提升的中文Workflow
Stars: ✭ 178 (-2.2%)
Mutual labels:  frontend
Emuto
manipulate JSON files
Stars: ✭ 180 (-1.1%)
Mutual labels:  frontend
Wag
WebAssembly compiler implemented in Go
Stars: ✭ 177 (-2.75%)
Mutual labels:  compiler
Varjo
Lisp to GLSL Language Translator
Stars: ✭ 181 (-0.55%)
Mutual labels:  compiler
Command Block Assembly
Compile high-level code into Minecraft commands
Stars: ✭ 175 (-3.85%)
Mutual labels:  compiler
Stackoverflow Clone
Clone project of a famous Q/A website for developers which is stackoverflow built using MySQL-Express-React-Node 🌐
Stars: ✭ 182 (+0%)
Mutual labels:  frontend
Snapdragon
snapdragon is an extremely pluggable, powerful and easy-to-use parser-renderer factory.
Stars: ✭ 180 (-1.1%)
Mutual labels:  compiler
Angular Tslint Rules
Shared TSLint & codelyzer rules to enforce a consistent code style for Angular development
Stars: ✭ 181 (-0.55%)
Mutual labels:  frontend
Wp Nuxt
The module adds WP-API to your nuxt application.
Stars: ✭ 179 (-1.65%)
Mutual labels:  frontend

Philip2 ("fee-leap the second") is a compiler from Elm to OCaml, using the ReasonML/Bucklescript ecosystem. You can use it to do a semi-automated port of a codebase from Elm to Bucklescript/ReasonML.

Quickstart

To start translating your files:

npm install -g [email protected] # we build using esy
./install-elm-format # philip2 requires a modified version of elm-format.
esy install
esy build
esy test
./translate MyFile.elm > MyFile.ml

Useful scripts in the repo

  • debug: run and then type OCaml code to get pretty-printed OCaml AST. This is useful for figuring out how to generate the code you're trying to create an AST for. (run ./debug, then type your code, then press Ctrl-D)

  • parse: a script that parses an Elm file and dumps philip2's understanding of the parse tree.

  • translate: a script to translate a single file from Elm to OCaml.

  • port: a script to help you port your project over to OCaml. Often, you will have to change your Elm code to make the compiler work (for example, the compiler doesn't support the points-free style of function declaration). This script was helpful to me as I changed my code hundreds of times as I developed philip2.

Source files

  • elm.ml: a parser for the modified json output of elm-format, as well as type definitions which match the type definitions in elm-format.

  • translate.ml: the compiler's main file. Reads input, calls elm.ml, then translates from the Elm AST and prints out OCaml.

How to port your project

  • Create an empty bucklescript project using bucklescript-tea. A pretty good tutorial on this is: https://quernd.github.io/tutorials/tea-chess/index.html
  • Copy Porting.ml into your repo. (update: you should be able to use Tablecloth instead now)
  • Tweak Porting.ml until it you get it to convert something to Elm.
  • Run bsb with the watcher to see errors in the generated files.
  • Modify the source Elm until everything converts to OCaml cleanly. See tactics below. By doing this, you'll be able to make changes and validate that your old code continues to work, eg by running tests and unit tests.
  • At some point (hopefully quite quickly) it becomes easier to edit the generated OCaml than the Elm.
  • Edit the OCaml until it fully compiles.

Tactics for making elm compile to ocaml

  • There are a number of ways to tweak the code generated by the compiler, namely by changing the following variables in translate.ml:
    • config_function_patterns
    • config_module_patterns
    • config_post_process_patterns
    • config_type_patterns
    • post_process

These allow you to use regex to modify module, function, and type names, as well as a coarse-grained regex-across-the-whole-file (post_process).

  • Have a DontPort.elm file, in which you put things which don't make sense in OCaml, but which allow you make changes that don't exist in Elm.

  • You're probably going to take on some technical debt during the transition. Sorry.

  • Elm's dicts are more general than Belt's (Belt.Map.String.t vs Dict String v). Change your Elm Dict Str x to StrDict x and then add StrDict to config_module_patterns. You can use our definition in Elm and Ocaml

  • Because OCaml isn't great at errors, I found it useful to keep regenerating the OCaml code (using the port script) while tweaking things, esp file and type ordering. (However, this was necessary for me because I was writing the compiler alongside it; you may find it simpler to do a conversion once and update by hand afterwards).

  • The compiler will use type x = ... and y = ... for any types that are adjacent. This should simplify using recursive types.

  • The compiler doesn't do anything for recursive function definitions. Use post_process_patterns to rename let myFunc to let rec myFunc.

  • Many functions, especially if you plan to use Belt, take arguments in a different order than Elm. To avoid the hassle, use a Porting.ml file which you open everywhere. The compiler will add a open Porting! to every file regardless.

  • bs-json appears to be much nicer to use for decoders than Tea.Json.

  • You have to decide which standard libraries to use. We ended up porting lots of Elm code directly (eg using the compiler to translate it) rather than calling OCaml libraries (see https://reasonml.chat/t/advice-on-standard-library-to-use/1165) (update: you can now use Tablecloth for this)

  • Elm's Result takes parameters in a different order than Tea.Result and Belt.Result.

  • Check out the useful_elm and useful_ocaml directories (update: you can now use Tablecloth instead) .

Contributing

This project has a code of conduct - please read and abide by it.

Philip2 is extremely alpha quality. Contributions are welcome to improve this and make it more automated and less semi-automated. In order of priority:

  • add tests (read directory of Elm files, check that they are identical to the OCaml file of the same name)
  • add CI
  • fix bugs

PRs welcome!

Known bugs

PRs welcome (feel free to open an issue or PR to discuss your plans!)

  • Philip2 will strip all your comments.
  • Points-free style is not supported
  • .mli files are not generated
  • ++ does not take into account the type of its arguments: it just becomes ^ when sometimes it should become @. An easy improvement is to check the argument for list or string literals, or known list/string functions. I suspect we can also use the type system but I think this would be hard to make work.
  • Phillip2 generates OCaml syntax only. Add a flag for ReasonML syntax.
  • In the pattern below, i1 and i2 are incorrectly flipped by the compiler. This is true of all literal lists in pattern match clauses.
match x with
| [i2; i1] -> 5
  • Nested-else-ifs are reversed. Eg
if a then b
else if c then d
else if e then f
else g

becomes

if e then f
else if c then d
else if a then b
else g
  • We should add an ability to target "flavors": whether the generated code uses functions and modules from Bucklescript functions, OCaml pervasives, Jane Street Base, or ported Elm libraries.

License

Files in the toplevel directory use the MIT license. Elm.ml is somewhat based on avh4/elm-format, which has a BSD. Some functions in useful_ocaml/Porting.ml are based on elm/core (BSD), and from the *.Extra packages in elm-community, which use a BSD license). Others may derive from elsewhere and have unclear providence.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].