Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Module support: handle structs, enums and scope calls across modules #497

Merged
merged 20 commits into from
Sep 1, 2023

Conversation

AltGr
Copy link
Contributor

@AltGr AltGr commented Aug 15, 2023

Current state:

  • Works: modules compiled with catala module --build foo.catala_en then used
    through catala interpret --use foo.catala_en bar.catala_en
    (this is the use-case for running the interpreter on tests that will actually
    do a native-code computation)

  • Usage from native code doesn't work yet (but it's a matter of bugfixing) works as well (use catala module --link for now)

  • Desambiguation doesn't yet work cross-modules yet (but no technical
    difficulty, just needs handling ; can be left for a later PR)

  • Code needs cleanup (debugs remaining here and there...)

  • On second thought storing the paths as part of the program_ctx isn't the
    best approach: I'll revert that part and add the paths to an expanded version
    of Uid.t. The information will be closer to where it's needed, it will avoid
    limitation in printers, and this just needs the current path to be passed along
    during name resolution, when initialising the (Q)Uids.

    Done now, code is much simpler but one needs to remember to lookup the correct module context when querying scope or def info.

  • web_api and french_law friends are broken and temporarily disabled Now fixed, at least all tests and benches pass now

  • no support yet for other backends (but that will be left for later PRs)

@AltGr AltGr marked this pull request as draft August 15, 2023 22:13
@AltGr
Copy link
Contributor Author

AltGr commented Aug 15, 2023

(and obviously, the git history needs a rebase ;) )

Copy link
Contributor

@denismerigoux denismerigoux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @AltGr for another massive PR! It still needs some work though, but that'll be after your holidays :)

build_system/clerk_runtest.mli Outdated Show resolved Hide resolved
compiler/dcalc/from_scopelang.ml Show resolved Hide resolved
compiler/dcalc/from_scopelang.ml Show resolved Hide resolved
(* Find a witness of a mark in the definitions *)
match sigma.scope_decl_rules with
| [] ->
(* Todo: are we sure this can't happen in normal code ? E.g. is calling a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah ideally a scope with only input variables should compile, you can maybe return Pos.no_pos at this point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit more involved because of the GADT for annotations, we would need to take a type witness as parameter of the function. I'll see what I can do ^^

compiler/dcalc/from_scopelang.ml Outdated Show resolved Hide resolved
;; (rule
;; (targets aides_logement.ml aides_logement_api_web.ml)
;; (deps
;; (source_tree ..)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code?

examples/dune Outdated
@@ -0,0 +1 @@
(dirs :standard \ aides_logement)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah this is temporary and will be removed from the finalised PR, see 0a98f63

french_law/dune Outdated
@@ -0,0 +1,3 @@
(dirs catala_legifrance)

;; ocaml js python
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same as above, this disables most of french_law)

tests/test_scope/good/scope_call4.catala_en Outdated Show resolved Hide resolved
@AltGr
Copy link
Contributor Author

AltGr commented Aug 31, 2023

Should now be regression-free and ready for final review;
I should still do some cleanup on the branch git history, but without impact on the result.

@AltGr
Copy link
Contributor Author

AltGr commented Aug 31, 2023

cf. ocaml/opam-repository#24342 on CI failure

@AltGr AltGr changed the title [DRAFT] Module support: handle structs, enums and scope calls across modules Module support: handle structs, enums and scope calls across modules Aug 31, 2023
@AltGr AltGr marked this pull request as ready for review August 31, 2023 15:41
... and add a custom printer

Since this is a very common bug, this patch should gain us a lot of time when
debugging uncaught Not_found errors, because the element not found can now be
printed straight away without the need for further debugging.

The small cost is that one should remember to catch the correct specialised
`Foo.Map.Not_found _` exception rather than the standard `Not_found` (which
would type-check but not catch the exception). Using `find_opt` should be
preferred anyway.

Note that the other functions from the module `Map` that raise `Not_found` are
not affected ; these functions are `choose`, `min/max_binding`,
`find_first/last` which either take a predicate or fail on the empty map, so it
wouldn't make sense for them (and we probably don't use them much).
(they use UIDs so this doesn't jeopardize proper name resolution ; and it allows
resolution of subscope calls without further code modifications)
This makes sure `catala module` finds the local runtime when run from the catala
source tree; and fixes lookup of the catala exec on custom uses of `clerk runtest`.
@AltGr
Copy link
Contributor Author

AltGr commented Aug 31, 2023

Done cleaning up the git history a bit

Half-baked because clerk doesn't know to order the tests properly at the moment,
and we spit compiled files into the source test directory.
rather than scattered in structures

The context is still hierarchical for defs though, so one needs to retrieve the
path to lookup in the correct context for info. Exceptions are enums and struct
defs, which are re-exposed at toplevel.
Copy link
Contributor

@denismerigoux denismerigoux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK to merge! While I'm thinking about it : the invariants checking phase that @adelaett made is only triggered by the Invariants CLI target, but shouldn't they be checked more often and at least in the CI ?

@@ -136,7 +136,8 @@ let detect_unused_struct_fields (p : program) : unit =
in
StructName.Map.iter
(fun s_name fields ->
if
if StructName.path s_name <> [] then ()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah so you don't check structs from other modules during linting. I guess that makes sense but that would be better with a little comment no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In time we may also want to fine-tune the warnings when compiling modules: in some cases it makes sense that stuff is unused here.

let prg, _ = surface options in
let prg = load_module_interfaces prg options link_modules in
let prg, _ = surface options ~link_modules in
Message.emit_debug "- DESUGARED -";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks style with the other debug messages right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes: I see them as section titles, it makes it easy to see what stage you were in when there is a crash.
Example:

[DEBUG] - INIT -
[DEBUG] Could not read plugin directory /home/lg/inria/catala/_build/default/compiler/../lib/catala/plugins
[DEBUG] Loading plugins from _build/default/compiler/plugins
[DEBUG] Plugin "_build/default/compiler/plugins/api_web.cmxs" loaded
[DEBUG] Plugin "_build/default/compiler/plugins/python.cmxs" loaded
[DEBUG] Plugin "_build/default/compiler/plugins/modules.cmxs" loaded
[DEBUG] Plugin "_build/default/compiler/plugins/explain.cmxs" loaded
[DEBUG] Plugin "_build/default/compiler/plugins/lazy_interpreter.cmxs" loaded
[DEBUG] Plugin "_build/default/compiler/plugins/json_schema.cmxs" loaded
[DEBUG] - SURFACE -
[DEBUG] Parsing sources/impot_revenu.catala_fr
[DEBUG] Parsing sources/prologue.catala_fr
[DEBUG] Parsing sources/vérifications.catala_fr
[DEBUG] Parsing sources/cgi_revenus.catala_fr
[DEBUG] Parsing sources/lfr_2022.catala_fr
[DEBUG] Parsing sources/loi_2022-1158.catala_fr
[DEBUG] - DESUGARED -
[DEBUG] Name resolution...
[DEBUG] Desugaring...
[DEBUG] Disambiguating...
[DEBUG] Linting...
[DEBUG] - SCOPELANG -
[DEBUG] - DCALC -
[DEBUG] Typechecking...
[DEBUG] Translating to default calculus...
[DEBUG] Typechecking again...
[DEBUG] - LCALC -
[DEBUG] Catala runtime libraries found at /home/lg/.opam/latest/lib/catala/runtime.
[DEBUG] Compiling OCaml shared object file sources/impot_revenu.cmxs...

May add in some color as well 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, looks good to me. Yep color would be perfect :)

@@ -245,11 +223,15 @@ let format_var (fmt : Format.formatter) (v : 'm Var.t) : unit =
let lowercase_name = String.to_ascii lowercase_name in
if
List.mem lowercase_name ["handle_default"; "handle_default_opt"]
|| String.begins_with_uppercase (Bindlib.name_of v)
(* O_O *)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm I don't exactly remember the mood I was in when I wrote this 🤣
But certainly there should be a better way of special-casing without matching the final ident strings.

@@ -529,7 +530,7 @@ let format_ctx
format_to_module_name (`Ename enum_name)
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "@\n")
(fun _fmt (enum_cons, enum_cons_type) ->
(fun fmt (enum_cons, enum_cons_type) ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well caught!

let rec dump ppf env =
let pp_sep = Format.pp_print_space in
Format.pp_open_vbox ppf 0;
(* Format.fprintf ppf "structs: @[<hov>%a@]@,"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well technically this function is dead code, it shouldn't be used outside of debugging sessions — but pretty convenient nevertheless and we shouldn't need to rewrite it every time. The same applies to the commented code: while you generally wouldn't want all the typedecls listed here, I thought that having this available to be uncommented here could be helpful in debugging sessions where you might actually have use for it.

But well, since it's normally unused we may indeed prefer to uncomment to make sure the extended function continues to typecheck...

@AltGr
Copy link
Contributor Author

AltGr commented Sep 1, 2023

the invariants checking phase that @adelaett made is only triggered by the Invariants CLI target, but shouldn't they be checked more often and at least in the CI ?

It may even make sense to enable it in tests by default, when applicable 🤔

@AltGr AltGr merged commit dcb057b into CatalaLang:master Sep 1, 2023
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants