fix: dispatch
Paul Fournier authored
8ef10bf4

Petit Julia Compiler

Synopsis

  • As of now, this project is a syntax /type analyser for Petit-Julia. It takes a .jl file as input, then processes it to check if everything is valid. It is capable of producing an abstract syntax tree decorated with types, but as this is not used anywhere now, it is just thrown away.
  • If the input code is incorrect, it should raise an error, of the corresponding type (lexical, syntax, typing).

Table of contents

Usage

Before getting into the code, a brief mention on how to use it.

Here is provided the source code for the compiler, written in OCaml. It is compiled using the tool make, which uses internally dune.

  • Creating the compiler :

    When in the folder, simply run make pjuliac.exe. It should compile without any hurdle. Congratulations, you now have your own compiled version of the unofficial compiler from frustrated developers for Petit-Julia.

    Note : it requires OCaml version 4.10.0 or more. It was internally tested with OCaml version 4.11.1.

  • Testing the compiler :

    In case the user wants to check how poorly well this compiler works, they can download the tests folder designed by Jean-Christophe Filliatre, put it in the pjuliac folder, and run make test. Only one test should fail when it should run smoothly : tests/exec/int64.jl, for reasons detailed in the Limitations section.

  • Getting rid of the compiler :

    In case you wanted to remove our compiler, in addition to making our team sad, you can simply run a make clean to get rid of all the compiled files. For further annihilation, remove the folder altogether.

  • Using manually the compiler :

    When the make command is done, a link pjuliac.exe is created in the current folder. You can then use ./pjuliac.exe to run the compiler. The syntax is the following : ./pjuliac.exe [options] file.jl. It will run the compiler on the file file.jl with the options furnished. The options are the following :

    • --parse-only : stops after the parsing
    • --typing-only : stops after the typing
    • --help or -help : displays this list of options.

Code

lexer.mll

  • This file is the description of a lexer that will be read by ocamllex to create an automaton capable of transforming a stream of characters into a stream of tokens (elementary units of sense in the code), while also rejecting syntax errors.
  • It is also responsible for keeping a track of the position of the tokens in the file, so the errors can point to the right place in the program, at all stages of the compilation.
  • It also has a function for printing the tokens in stdout.
  • Overall, this is pretty much just translation of the syntax of Petit-Julia, nothing particularly clever here.

ast.ml

  • The abstract syntax tree of Petit-Julia. It provides the rest of the project with the types required to navigate and interact with the syntax of Petit-Julia. These types are such that every node of the AST are decorated with its location in the file.
  • It used to have a function that simplified the AST as well : whenever a computation arose where the result could easily be computed in advance, it would simplify it. For example 3 == 2 would be simplified to false. It simplified all the comparisons and unary operations. This no longer works since it relied on an older type of AST where the positions of the rules were not indicated. It would not be too hard to make it work again, but, time being a major constraint, we have decided not to maintain it for now.

parser.mly

  • The descriptor for menhir of the grammar of Petit-Julia. It converts a stream of tokens into an AST. It is significantly beefier than the grammar provided by the subject for two main reasons :
    • Remove ambiguity and conflicts for menhir. The provided grammar, while understandable by the fellow humans designing this project, was not detailed enough for menhir. That's why there are several variants of expr (including start_expr, final_expr...), and overall more distinctions in the cases.
    • Have an easier time giving the result decorated with the position. To avoid repetitive writing, in order both to keep our sanity, and to have a code that is easier to debug, we have put, as much as possible, the decoration of the AST in a separate grammar rule (expr and _expr for instance).
  • This was a difficult part, because the debugging was tedious : trying to understand the documentation of menhir, trying to understand why menhir was complaining, and trying to find a way to fix it while not breaking everything else around it.

typing.ml

  • Perhaps the longest part of the project so far. What this part does is getting the AST, and twists it in order to squeeze every tiny type/scope/definition error it can, while also producing a typed AST in the end.
  • It can detect a whole lotta love errors : a function that is not defined when used, a function called but no defined function matches the arguments, the call of a field on a structure that is not existent, scope errors, and so on.
  • Caution is advised : the typer tends to be in a bad mood (which may or may not reflect the dev's feeling about Julia typing).
  • If everything went well, it produces, without complaining, an AST with all the types inferred statically.
  • We tried to implement a way to notice when the dispatch would fail (when there's an ambiguity that is critical), but it was way too violent, so we commented it out. It relied on computing the type distance between the argument of a function and the input types for all the variants of the callee.
  • We also envisioned to make all the binary operators into function calls, as it would be the case in OCaml for instance. We have not yet decided to keep it, this is a decision we will take during the code production phase. It is semi-implemented and commented out for now.
  • What's more, the file should be relatively well organised despite its lengths. You will find, in this order :
    • SDAA
    • Type definitions
    • Error management functions
    • Helper functions
    • Type compatibility checking functions
    • Context editing utilities
    • Type conversion
    • Scope update
    • Expression enrichment
    • Global scope creation and reading of the file

printer.ml

  • The Not-So-Pretty Printer^TM^ (NSPP for short) is contained in printer.ml. While not really pretty, either in its source code or production, it is useful to print debugging information, such as dumping the content of the AST in a format decipherable for a human.

pjuliac.ml

  • The conductor. Its conception is rather minimal, as all it does it chit-chat with the user.
  • It reads the arguments given in the command line, gives all the menial jobs to the aforementioned modules, and then tells the user whether or not something went horribly wrong.

Limitations

  • The integers close to Int.max_int and Int.min_int can be a little buggy (namely -2^{63} is not accepted while it should be). This is something we plan on fixing in the future, either by adding a specific rule for it, or by changing the way integers are represented in memory during compilation.

Extra features

  • Super Dope ASCII Art (SDAA for short), progressively becoming more hellish as time and our own dissatisfaction regarding Julia go on.