Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/gaultier/lox-ocaml
Implementation of the Lox language in OCaml
https://github.com/gaultier/lox-ocaml
compiler interpreter lox lox-language ocaml
Last synced: 3 months ago
JSON representation
Implementation of the Lox language in OCaml
- Host: GitHub
- URL: https://github.com/gaultier/lox-ocaml
- Owner: gaultier
- Archived: true
- Created: 2019-09-15T09:42:49.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2020-03-26T08:45:20.000Z (over 4 years ago)
- Last Synced: 2024-05-31T10:39:33.981Z (5 months ago)
- Topics: compiler, interpreter, lox, lox-language, ocaml
- Language: OCaml
- Homepage:
- Size: 473 KB
- Stars: 14
- Watchers: 4
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Lox
Implementation of the [Lox language](http://www.craftinginterpreters.com/) in
OCaml, comprised of a front-end compiler and an interpreter, in roughly 1KLOC !Big thanks to [Bob Nystrom](https://github.com/munificent)!! You're amazing.
*No further work is expected to happen on this project as it is feature-complete. The implementation is not optimal but still useful as a learning material.*
## Quickstart
Assuming `ocaml` (version `4.08.1`) and `opam` are installed and setup:
```sh
$ opam install .
$ lox run test/hello_world.lox
hello, world$ printf 'print 4 * 3 - 1;' | lox run
11$ lox repl
> 1+1;
2.
> ^C# The last field of an AST node is an internal unique id
$ echo "print 1 + 2;" | lox dump ast
((Print (Binary (Literal (Number 1) 1) Plus (Literal (Number 2) 2) 3) 4))```
## Implemented
- Numbers, strings, booleans, nil
- Comments
- Number arithmetic
- Statements & print
- Variables (scope based)
- Conditions (if/else)
- Boolean logic (and, or, not)
- Loops (while, for)
- All errors are reported with line and column number
- Functions (including recursion, closures)
- Object-oriented programming (classes, single inheritance)
- Shebang
- "Native" functions:
* clock()
* readLine()
* parseNumber()
- Basic static analysis:
* Return statement outside of a function body e.g `return 1;`
* Variables assigned to themselves e.g `var a = a;`
* Same-scope variable shadowing e.g `var a = 1; var a = 2;`
* Unused variables, functions, and function argumentsExample:
```javascript
fun fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 2) + fibonacci(n - 1);
}
for (var i = 0; i < 20; i = i + 1) {
print fibonacci(i);
}
```Example of objects:
```javascript
class Breakfast {}class BreakfastBuilder {
init() {
this.breakfast = Breakfast();
}withEggs(eggNumber) {
this.breakfast.eggNumber = eggNumber;
return this;
}withToasts(toastNumber) {
this.breakfast.toastNumber = toastNumber;
return this;
}build() {
return this.breakfast;
}
}var breakfast = BreakfastBuilder().withEggs(2).withToasts(5).build();
print breakfast.eggNumber;
print breakfast.toastNumber;
```## Test
*Requires GNU parallel*
`make test`
You can `opam install patdiff` for a better output, by default it uses `diff`.
## Docker
```sh
$ make docker
$ docker run -it lox
```## Better REPL experience
`lox repl` works out of the box with the [GNU Readline library](https://tiswww.cwru.edu/php/chet/readline/rltop.html) if you have it installed:
`rlwrap lox repl` will provide command history for free.
## Major differences with the official implementation
- Variable resolution does not distinguish between local/global variables. In practices it means that mutally recursive functions in the global scope are not allowed
- Stricter static analysis, e.g referring to undefined variables (will fail at compile time in some cases instead of at runtime)