This includes a few separate changes:
- pass visibility information of declarations (depending on wether the
declaration was in a ```catala-metadata block or not)
- add reasonable hash computation functions to discriminate the interfaces. In
particular:
* Uids have a `hash` function that depends on their string, but not on their
actual uid (which is not stable between runs of the compiler) ; the existing
`hash` function and its uses have been renamed to `id`.
* The `Hash` module provides the tools to properly combine hashes, etc. While
we rely on `Hashtbl.hash` for the atoms, we take care not to use it on any
recursive structure (it relies on a bounded traversal).
- insert the hashes in the artefacts, and properly check and report those (for
OCaml)
**Remains to do**:
- Record and check the hashes in the other backends
- Provide a way to get stable inline-test outputs in the presence of module
hashes
- Provide a way to write external modules that don't break at every Catala
update.
mostly reverting to the ones the interpreter was printing ; for the case of
divisions, we choose to point to the denominator instead of the operator as it's
where the only possible error (division by zero) comes from.
- Clearly distinguish Exceptions from Errors. The only catchable exception
available in our AST is `EmptyError`, so the corresponding nodes are made less
generic, and a node `FatalError` is added
- Runtime errors are defined as a specific type in the OCaml runtime, with a
carrier exception and printing functions. These are used throughout, and
consistently by the interpreter. They always carry a position, that can be
converted to be printed with the fancy compiler location printer, or in a
simpler way from the backends.
- All operators that might be subject to an error take a position as argument,
in order to print an informative message without relying on backtraces from
the backend
This was a pending TODO: now the Catala program compiled into OCaml should
return better messages and a little more information about uncaught exceptions.
Note that this also concerns, at the moment, compiled modules called from the
Catala interpreter: in this case, it's already better than nothing, but what we
need is proper interoperation between the runtime exceptions and the interpreter
handling (`EmptyError` should already be handled properly since it is critical
to the computation flow, but "error" exceptions are left uncaught and will kill
the interpreter).
This may be part of a bigger task on unifying the output of the runtime and
toplevel, which also concerns computation traces.
Note 2: All runtime exceptions don't have a position available, which is quite
unfortunate when your program hits an error. With `OCAMLRUNPARAM=b` and if
compiled with `-g` (which should normally be the case), you can get an OCaml
backtrace but that's not very friendly. Ideas for improvement:
- The runtime could force-enable backtrace recording (`Printexc.record_backtrace
true`) to supersede the need for `OCAMLRUNPARAM`. We can also record our own
handler to print the file position and/or backtrace in the way we see fit
- The printer of OCaml code in Catala could insert line directives so that the
positions in the backtrace actually trace automatically back to the Catala
code
- If we don't want to leverage any OCaml machinery in this way, the compiler
should add position information to any operator that might fail (e.g.
divisions, date comparisons, etc.).
Note that running in trace mode might already help pinpoint the location of the
error ?
- This adds a `catala depends` command that recursively tracks module dependency.
It can then be used by Clerk for linking.
- Generation of cmo object files are added for OCaml (we only built native
objects, but jsoo requires bytecode).
- Some fixes to the generation of value embed/deembed shims (related to types
coming from different modules ; add support for options ; etc.)
Print to json directly rather than depend on yojson and a ppx.
Note: this should be tested with the website in order to validate that the Json
output is 1-to-1.
(a second step could be to simplify this output, now that it's manual)
The primary use-case for this was to be able to run computations on a list of
structures, then return an updated list with some fields in the structures
modified : that is what we need for distribution of tax amounts among household
members, for example.
This patch has a few components:
- Addition of a test as an example for tax distributions
- Added a transformation, performed during desugaring, that -- where lists are
syntactically expected, i.e. after the `among` keyword -- turns a (syntactic)
tuple of lists into a list of tuples ("zipping" the lists)
- Arg-extremum transformation was also fixed to use an intermediate list instead
of computing the predicate twice
- For convenience, allow to bind multiple variables in most* list
operations (previously only `let in` and functions allowed it)
- Fixed the printer for tuples to differentiate them from lists
*Note: tuples are not yet allowed on the left-hand side of filters and
arg-extremums for annoying syntax conflict reasons.
Runtimes for the various backends are expected to be made available from their
own ecosystem. However, for convenience and to help with development
settings (where the runtime might change), as part of installing catala they are
put, in source form, into `<prefix>/lib/catala/runtime_LANG`.
When using a dev version of Catala, and using Python, one would then just have
to do `pip install <prefix>/lib/catala/runtime_python` within their venv to be
able to run their python programs.