mirror of
https://github.com/CatalaLang/catala.git
synced 2024-11-08 07:51:43 +03:00
Preliminary support for modules/externals + CLI subcommands (#478)
This commit is contained in:
commit
f31a78593e
41
Dockerfile
41
Dockerfile
@ -1,15 +1,9 @@
|
|||||||
# Stage 1: setup an opam switch with all dependencies installed
|
#
|
||||||
|
# STAGE 1: setup an opam switch with all dependencies installed
|
||||||
|
#
|
||||||
# (only depends on the opam files)
|
# (only depends on the opam files)
|
||||||
FROM ocamlpro/ocaml:4.14-2023-04-02 AS dev-build-context
|
FROM ocamlpro/ocaml:4.14-2023-06-18 AS dev-build-context
|
||||||
|
# Image from https://hub.docker.com/r/ocamlpro/ocaml
|
||||||
# pandoc and ninja are not in alpine stable yet, install it manually with an explicit repository
|
|
||||||
RUN sudo apk add pandoc --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community/
|
|
||||||
# In order to compiler rescript for `npm install` in french_law/js we need
|
|
||||||
# the following dependencies (according to https://github.com/GlancingMind/rescript-alpine-docker)
|
|
||||||
RUN sudo apk add python3
|
|
||||||
RUN sudo ln -s /usr/bin/python3 /usr/bin/python
|
|
||||||
RUN sudo apk add g++
|
|
||||||
RUN sudo apk add make
|
|
||||||
|
|
||||||
RUN mkdir catala
|
RUN mkdir catala
|
||||||
WORKDIR catala
|
WORKDIR catala
|
||||||
@ -22,16 +16,31 @@ ENV OPAMVAR_cataladevmode=1
|
|||||||
ENV OPAMVAR_catalaz3mode=1
|
ENV OPAMVAR_catalaz3mode=1
|
||||||
|
|
||||||
# Get a switch with all the dependencies installed
|
# Get a switch with all the dependencies installed
|
||||||
RUN opam --cli=2.1 update && \
|
# DON'T run 'opam update' here. Instead use a newer parent Docker image
|
||||||
opam --cli=2.1 switch create catala ocaml-system && \
|
# (update the 'FROM' line above)
|
||||||
opam --cli=2.1 pin . --no-action && \
|
RUN opam --cli=2.1 switch create catala ocaml-system && \
|
||||||
opam --cli=2.1 install . --with-test --with-doc --depext-only && \
|
opam --cli=2.1 install . --with-test --with-doc --depext-only && \
|
||||||
opam --cli=2.1 install . --with-test --with-doc --deps-only && \
|
opam --cli=2.1 install . --with-test --with-doc --deps-only && \
|
||||||
opam clean
|
opam clean
|
||||||
# Note: just one `opam switch create .` command should be enough once opam 2.1.3 is released (opam#5047 ; opam#5185)
|
# Note: just `opam switch create . --deps-only --with-test --with-doc && opam clean`
|
||||||
|
# should be enough once opam 2.2 is released (see opam#5185)
|
||||||
|
|
||||||
|
# Install extra dependencies not handled yet by the opam depexts
|
||||||
|
#
|
||||||
|
# python3, ninja (samurai in this case), etc. already got installed through opam's
|
||||||
|
# depext mechanism at this point -- see clerk.opam and catala.opam
|
||||||
|
#
|
||||||
|
# pandoc is not in alpine stable yet though, so install it manually with an explicit repository
|
||||||
|
RUN sudo apk add pandoc --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community/
|
||||||
|
|
||||||
|
# Workaround broken rescript build that recompiles its own version of
|
||||||
|
# ninja with a badly written script :[]
|
||||||
|
RUN sudo apk add pythonispython3
|
||||||
|
|
||||||
|
|
||||||
# Stage 2: get the whole repo, run checks and builds
|
#
|
||||||
|
# STAGE 2: get the whole repo, run checks and builds
|
||||||
|
#
|
||||||
FROM dev-build-context
|
FROM dev-build-context
|
||||||
|
|
||||||
# Get the full repo
|
# Get the full repo
|
||||||
|
@ -53,6 +53,7 @@ depends: [
|
|||||||
depopts: ["z3"]
|
depopts: ["z3"]
|
||||||
conflicts: [
|
conflicts: [
|
||||||
"z3" {< "4.8.11"}
|
"z3" {< "4.8.11"}
|
||||||
|
"base" {>= "v0.16.0"}
|
||||||
]
|
]
|
||||||
build: [
|
build: [
|
||||||
["dune" "subst"] {dev}
|
["dune" "subst"] {dev}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
type backend_lang = En | Fr | Pl
|
type backend_lang = En | Fr | Pl
|
||||||
|
|
||||||
type backend_option_builtin =
|
type backend_option =
|
||||||
[ `Latex
|
[ `Latex
|
||||||
| `Makefile
|
| `Makefile
|
||||||
| `Html
|
| `Html
|
||||||
@ -33,8 +33,6 @@ type backend_option_builtin =
|
|||||||
| `Exceptions
|
| `Exceptions
|
||||||
| `Proof ]
|
| `Proof ]
|
||||||
|
|
||||||
type 'a backend_option = [ backend_option_builtin | `Plugin of 'a ]
|
|
||||||
|
|
||||||
(** Associates a {!type: Cli.backend_lang} with its string represtation. *)
|
(** Associates a {!type: Cli.backend_lang} with its string represtation. *)
|
||||||
let languages = ["en", En; "fr", Fr; "pl", Pl]
|
let languages = ["en", En; "fr", Fr; "pl", Pl]
|
||||||
|
|
||||||
@ -42,41 +40,6 @@ let language_code =
|
|||||||
let rl = List.map (fun (a, b) -> b, a) languages in
|
let rl = List.map (fun (a, b) -> b, a) languages in
|
||||||
fun l -> List.assoc l rl
|
fun l -> List.assoc l rl
|
||||||
|
|
||||||
let backend_option_to_string = function
|
|
||||||
| `Interpret -> "Interpret"
|
|
||||||
| `Interpret_Lcalc -> "Interpret_Lcalc"
|
|
||||||
| `Makefile -> "Makefile"
|
|
||||||
| `OCaml -> "Ocaml"
|
|
||||||
| `Scopelang -> "Scopelang"
|
|
||||||
| `Dcalc -> "Dcalc"
|
|
||||||
| `Latex -> "Latex"
|
|
||||||
| `Proof -> "Proof"
|
|
||||||
| `Html -> "Html"
|
|
||||||
| `Python -> "Python"
|
|
||||||
| `Typecheck -> "Typecheck"
|
|
||||||
| `Scalc -> "Scalc"
|
|
||||||
| `Lcalc -> "Lcalc"
|
|
||||||
| `Exceptions -> "Exceptions"
|
|
||||||
| `Plugin s -> s
|
|
||||||
|
|
||||||
let backend_option_of_string backend =
|
|
||||||
match String.lowercase_ascii backend with
|
|
||||||
| "interpret" -> `Interpret
|
|
||||||
| "interpret_lcalc" -> `Interpret_Lcalc
|
|
||||||
| "makefile" -> `Makefile
|
|
||||||
| "ocaml" -> `OCaml
|
|
||||||
| "scopelang" -> `Scopelang
|
|
||||||
| "dcalc" -> `Dcalc
|
|
||||||
| "latex" -> `Latex
|
|
||||||
| "proof" -> `Proof
|
|
||||||
| "html" -> `Html
|
|
||||||
| "python" -> `Python
|
|
||||||
| "typecheck" -> `Typecheck
|
|
||||||
| "scalc" -> `Scalc
|
|
||||||
| "lcalc" -> `Lcalc
|
|
||||||
| "exceptions" -> `Exceptions
|
|
||||||
| s -> `Plugin s
|
|
||||||
|
|
||||||
(** Source files to be compiled *)
|
(** Source files to be compiled *)
|
||||||
let source_files : string list ref = ref []
|
let source_files : string list ref = ref []
|
||||||
|
|
||||||
@ -109,7 +72,7 @@ open Cmdliner
|
|||||||
let file =
|
let file =
|
||||||
Arg.(
|
Arg.(
|
||||||
required
|
required
|
||||||
& pos 1 (some file) None
|
& pos 0 (some file) None
|
||||||
& info [] ~docv:"FILE" ~doc:"Catala master file to be compiled.")
|
& info [] ~docv:"FILE" ~doc:"Catala master file to be compiled.")
|
||||||
|
|
||||||
let debug =
|
let debug =
|
||||||
@ -143,7 +106,7 @@ let unstyled =
|
|||||||
Arg.(
|
Arg.(
|
||||||
value
|
value
|
||||||
& flag
|
& flag
|
||||||
& info ["unstyled"; "u"]
|
& info ["unstyled"]
|
||||||
~doc:
|
~doc:
|
||||||
"Removes styling (colors, etc.) from terminal output. Equivalent to \
|
"Removes styling (colors, etc.) from terminal output. Equivalent to \
|
||||||
$(b,--color=never)")
|
$(b,--color=never)")
|
||||||
@ -203,14 +166,6 @@ let print_only_law =
|
|||||||
"In literate programming output, skip all code and metadata sections \
|
"In literate programming output, skip all code and metadata sections \
|
||||||
and print only the text of the law.")
|
and print only the text of the law.")
|
||||||
|
|
||||||
let backend =
|
|
||||||
Arg.(
|
|
||||||
required
|
|
||||||
& pos 0 (some string) None
|
|
||||||
& info [] ~docv:"COMMAND"
|
|
||||||
~doc:
|
|
||||||
"Backend selection (see the list of commands for available options).")
|
|
||||||
|
|
||||||
let plugins_dirs =
|
let plugins_dirs =
|
||||||
let doc = "Set the given directory to be searched for backend plugins." in
|
let doc = "Set the given directory to be searched for backend plugins." in
|
||||||
let env = Cmd.Env.info "CATALA_PLUGINS" ~doc in
|
let env = Cmd.Env.info "CATALA_PLUGINS" ~doc in
|
||||||
@ -277,13 +232,24 @@ let output =
|
|||||||
compiler. Defaults to $(i,FILE).$(i,EXT) where $(i,EXT) depends on \
|
compiler. Defaults to $(i,FILE).$(i,EXT) where $(i,EXT) depends on \
|
||||||
the chosen backend. Use $(b,-o -) for stdout.")
|
the chosen backend. Use $(b,-o -) for stdout.")
|
||||||
|
|
||||||
type options = {
|
let link_modules =
|
||||||
|
Arg.(
|
||||||
|
value
|
||||||
|
& opt_all file []
|
||||||
|
& info ["use"; "u"] ~docv:"FILE"
|
||||||
|
~doc:
|
||||||
|
"Specifies an additional module to be linked to the Catala program. \
|
||||||
|
$(i,FILE) must be a catala file with a metadata section expressing \
|
||||||
|
what is exported ; for interpretation, a compiled OCaml shared \
|
||||||
|
module by the same basename (either .cmo or .cmxs) will be \
|
||||||
|
expected.")
|
||||||
|
|
||||||
|
type global_options = {
|
||||||
debug : bool;
|
debug : bool;
|
||||||
color : when_enum;
|
color : when_enum;
|
||||||
message_format : message_format_enum;
|
message_format : message_format_enum;
|
||||||
wrap_weaved_output : bool;
|
wrap_weaved_output : bool;
|
||||||
avoid_exceptions : bool;
|
avoid_exceptions : bool;
|
||||||
backend : string;
|
|
||||||
plugins_dirs : string list;
|
plugins_dirs : string list;
|
||||||
language : string option;
|
language : string option;
|
||||||
max_prec_digits : int option;
|
max_prec_digits : int option;
|
||||||
@ -297,9 +263,10 @@ type options = {
|
|||||||
output_file : string option;
|
output_file : string option;
|
||||||
closure_conversion : bool;
|
closure_conversion : bool;
|
||||||
print_only_law : bool;
|
print_only_law : bool;
|
||||||
|
link_modules : string list;
|
||||||
}
|
}
|
||||||
|
|
||||||
let options =
|
let global_options =
|
||||||
let make
|
let make
|
||||||
debug
|
debug
|
||||||
color
|
color
|
||||||
@ -308,7 +275,6 @@ let options =
|
|||||||
wrap_weaved_output
|
wrap_weaved_output
|
||||||
avoid_exceptions
|
avoid_exceptions
|
||||||
closure_conversion
|
closure_conversion
|
||||||
backend
|
|
||||||
plugins_dirs
|
plugins_dirs
|
||||||
language
|
language
|
||||||
max_prec_digits
|
max_prec_digits
|
||||||
@ -320,14 +286,14 @@ let options =
|
|||||||
ex_scope
|
ex_scope
|
||||||
ex_variable
|
ex_variable
|
||||||
output_file
|
output_file
|
||||||
print_only_law : options =
|
print_only_law
|
||||||
|
link_modules : global_options =
|
||||||
{
|
{
|
||||||
debug;
|
debug;
|
||||||
color = (if unstyled then Never else color);
|
color = (if unstyled then Never else color);
|
||||||
message_format;
|
message_format;
|
||||||
wrap_weaved_output;
|
wrap_weaved_output;
|
||||||
avoid_exceptions;
|
avoid_exceptions;
|
||||||
backend;
|
|
||||||
plugins_dirs;
|
plugins_dirs;
|
||||||
language;
|
language;
|
||||||
max_prec_digits;
|
max_prec_digits;
|
||||||
@ -341,6 +307,7 @@ let options =
|
|||||||
output_file;
|
output_file;
|
||||||
closure_conversion;
|
closure_conversion;
|
||||||
print_only_law;
|
print_only_law;
|
||||||
|
link_modules;
|
||||||
}
|
}
|
||||||
in
|
in
|
||||||
Term.(
|
Term.(
|
||||||
@ -352,7 +319,6 @@ let options =
|
|||||||
$ wrap_weaved_output
|
$ wrap_weaved_output
|
||||||
$ avoid_exceptions
|
$ avoid_exceptions
|
||||||
$ closure_conversion
|
$ closure_conversion
|
||||||
$ backend
|
|
||||||
$ plugins_dirs
|
$ plugins_dirs
|
||||||
$ language
|
$ language
|
||||||
$ max_prec_digits_opt
|
$ max_prec_digits_opt
|
||||||
@ -364,9 +330,8 @@ let options =
|
|||||||
$ ex_scope
|
$ ex_scope
|
||||||
$ ex_variable
|
$ ex_variable
|
||||||
$ output
|
$ output
|
||||||
$ print_only_law)
|
$ print_only_law
|
||||||
|
$ link_modules)
|
||||||
let catala_t f = Term.(const f $ file $ options)
|
|
||||||
|
|
||||||
let set_option_globals options : unit =
|
let set_option_globals options : unit =
|
||||||
debug_flag := options.debug;
|
debug_flag := options.debug;
|
||||||
@ -382,6 +347,101 @@ let set_option_globals options : unit =
|
|||||||
avoid_exceptions_flag := options.avoid_exceptions;
|
avoid_exceptions_flag := options.avoid_exceptions;
|
||||||
message_format_flag := options.message_format
|
message_format_flag := options.message_format
|
||||||
|
|
||||||
|
let subcommands handler =
|
||||||
|
[
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "interpret"
|
||||||
|
~doc:
|
||||||
|
"Runs the interpreter on the Catala program, executing the scope \
|
||||||
|
specified by the $(b,-s) option assuming no additional external \
|
||||||
|
inputs.")
|
||||||
|
Term.(const (handler `Interpret) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "interpret_lcalc"
|
||||||
|
~doc:
|
||||||
|
"Runs the interpreter on the lcalc pass on the Catala program, \
|
||||||
|
executing the scope specified by the $(b,-s) option assuming no \
|
||||||
|
additional external inputs.")
|
||||||
|
Term.(const (handler `Interpret_Lcalc) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "typecheck"
|
||||||
|
~doc:"Parses and typechecks a Catala program, without interpreting it.")
|
||||||
|
Term.(const (handler `Typecheck) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "proof"
|
||||||
|
~doc:
|
||||||
|
"Generates and proves verification conditions about the \
|
||||||
|
well-behaved execution of the Catala program.")
|
||||||
|
Term.(const (handler `Proof) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "ocaml"
|
||||||
|
~doc:"Generates an OCaml translation of the Catala program.")
|
||||||
|
Term.(const (handler `OCaml) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "python"
|
||||||
|
~doc:"Generates a Python translation of the Catala program.")
|
||||||
|
Term.(const (handler `Python) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "latex"
|
||||||
|
~doc:
|
||||||
|
"Weaves a LaTeX literate programming output of the Catala program.")
|
||||||
|
Term.(const (handler `Latex) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "html"
|
||||||
|
~doc:
|
||||||
|
"Weaves an HTML literate programming output of the Catala program.")
|
||||||
|
Term.(const (handler `Html) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "makefile"
|
||||||
|
~doc:
|
||||||
|
"Generates a Makefile-compatible list of the file dependencies of a \
|
||||||
|
Catala program.")
|
||||||
|
Term.(const (handler `Makefile) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "scopelang"
|
||||||
|
~doc:
|
||||||
|
"Prints a debugging verbatim of the scope language intermediate \
|
||||||
|
representation of the Catala program. Use the $(b,-s) option to \
|
||||||
|
restrict the output to a particular scope.")
|
||||||
|
Term.(const (handler `Scopelang) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "dcalc"
|
||||||
|
~doc:
|
||||||
|
"Prints a debugging verbatim of the default calculus intermediate \
|
||||||
|
representation of the Catala program. Use the $(b,-s) option to \
|
||||||
|
restrict the output to a particular scope.")
|
||||||
|
Term.(const (handler `Dcalc) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "lcalc"
|
||||||
|
~doc:
|
||||||
|
"Prints a debugging verbatim of the lambda calculus intermediate \
|
||||||
|
representation of the Catala program. Use the $(b,-s) option to \
|
||||||
|
restrict the output to a particular scope.")
|
||||||
|
Term.(const (handler `Lcalc) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "scalc"
|
||||||
|
~doc:
|
||||||
|
"Prints a debugging verbatim of the statement calculus intermediate \
|
||||||
|
representation of the Catala program. Use the $(b,-s) option to \
|
||||||
|
restrict the output to a particular scope.")
|
||||||
|
Term.(const (handler `Scalc) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "exceptions"
|
||||||
|
~doc:
|
||||||
|
"Prints the exception tree for the definitions of a particular \
|
||||||
|
variable, for debugging purposes. Use the $(b,-s) option to select \
|
||||||
|
the scope and the $(b,-v) option to select the variable. Use \
|
||||||
|
foo.bar to access state bar of variable foo or variable bar of \
|
||||||
|
subscope foo.")
|
||||||
|
Term.(const (handler `Exceptions) $ file $ global_options);
|
||||||
|
Cmd.v
|
||||||
|
(Cmd.info "pygmentize"
|
||||||
|
~doc:
|
||||||
|
"This special command is a wrapper around the $(b,pygmentize) \
|
||||||
|
command that enables support for colorising Catala code.")
|
||||||
|
Term.(const (fun _ -> assert false) $ file);
|
||||||
|
]
|
||||||
|
|
||||||
let version = "0.8.0"
|
let version = "0.8.0"
|
||||||
|
|
||||||
let info =
|
let info =
|
||||||
@ -395,67 +455,6 @@ let info =
|
|||||||
`P
|
`P
|
||||||
"Catala is a domain-specific language for deriving \
|
"Catala is a domain-specific language for deriving \
|
||||||
faithful-by-construction algorithms from legislative texts.";
|
faithful-by-construction algorithms from legislative texts.";
|
||||||
`S Manpage.s_commands;
|
|
||||||
`I
|
|
||||||
( "$(b,Intepret)",
|
|
||||||
"Runs the interpreter on the Catala program, executing the scope \
|
|
||||||
specified by the $(b,-s) option assuming no additional external \
|
|
||||||
inputs." );
|
|
||||||
`I
|
|
||||||
( "$(b,Intepret_Lcalc)",
|
|
||||||
"Runs the interpreter on the lcalc pass on the Catala program, \
|
|
||||||
executing the scope specified by the $(b,-s) option assuming no \
|
|
||||||
additional external inputs." );
|
|
||||||
`I
|
|
||||||
( "$(b,Typecheck)",
|
|
||||||
"Parses and typechecks a Catala program, without interpreting it." );
|
|
||||||
`I
|
|
||||||
( "$(b,Proof)",
|
|
||||||
"Generates and proves verification conditions about the well-behaved \
|
|
||||||
execution of the Catala program." );
|
|
||||||
`I ("$(b,OCaml)", "Generates an OCaml translation of the Catala program.");
|
|
||||||
`I ("$(b,Python)", "Generates a Python translation of the Catala program.");
|
|
||||||
`I
|
|
||||||
( "$(b,LaTeX)",
|
|
||||||
"Weaves a LaTeX literate programming output of the Catala program." );
|
|
||||||
`I
|
|
||||||
( "$(b,HTML)",
|
|
||||||
"Weaves an HTML literate programming output of the Catala program." );
|
|
||||||
`I
|
|
||||||
( "$(b,Makefile)",
|
|
||||||
"Generates a Makefile-compatible list of the file dependencies of a \
|
|
||||||
Catala program." );
|
|
||||||
`I
|
|
||||||
( "$(b,Scopelang)",
|
|
||||||
"Prints a debugging verbatim of the scope language intermediate \
|
|
||||||
representation of the Catala program. Use the $(b,-s) option to \
|
|
||||||
restrict the output to a particular scope." );
|
|
||||||
`I
|
|
||||||
( "$(b,Dcalc)",
|
|
||||||
"Prints a debugging verbatim of the default calculus intermediate \
|
|
||||||
representation of the Catala program. Use the $(b,-s) option to \
|
|
||||||
restrict the output to a particular scope." );
|
|
||||||
`I
|
|
||||||
( "$(b,Lcalc)",
|
|
||||||
"Prints a debugging verbatim of the lambda calculus intermediate \
|
|
||||||
representation of the Catala program. Use the $(b,-s) option to \
|
|
||||||
restrict the output to a particular scope." );
|
|
||||||
`I
|
|
||||||
( "$(b,Scalc)",
|
|
||||||
"Prints a debugging verbatim of the statement calculus intermediate \
|
|
||||||
representation of the Catala program. Use the $(b,-s) option to \
|
|
||||||
restrict the output to a particular scope." );
|
|
||||||
`I
|
|
||||||
( "$(b,Exceptions)",
|
|
||||||
"Prints the exception tree for the definitions of a particular \
|
|
||||||
variable, for debugging purposes. Use the $(b,-s) option to select \
|
|
||||||
the scope and the $(b,-v) option to select the variable. Use \
|
|
||||||
foo.bar to access state bar of variable foo or variable bar of \
|
|
||||||
subscope foo." );
|
|
||||||
`I
|
|
||||||
( "$(b,pygmentize)",
|
|
||||||
"This special command is a wrapper around the $(b,pygmentize) \
|
|
||||||
command that enables support for colorising Catala code." );
|
|
||||||
`S Manpage.s_authors;
|
`S Manpage.s_authors;
|
||||||
`P "The authors are listed by alphabetical order.";
|
`P "The authors are listed by alphabetical order.";
|
||||||
`P "Nicolas Chataing <nicolas.chataing@ens.fr>";
|
`P "Nicolas Chataing <nicolas.chataing@ens.fr>";
|
||||||
@ -474,3 +473,5 @@ let info =
|
|||||||
in
|
in
|
||||||
let exits = Cmd.Exit.defaults @ [Cmd.Exit.info ~doc:"on error." 1] in
|
let exits = Cmd.Exit.defaults @ [Cmd.Exit.info ~doc:"on error." 1] in
|
||||||
Cmd.info "catala" ~version ~doc ~exits ~man
|
Cmd.info "catala" ~version ~doc ~exits ~man
|
||||||
|
|
||||||
|
let catala_t ?(extra = []) handler = Cmd.group info (subcommands handler @ extra)
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
type backend_lang = En | Fr | Pl
|
type backend_lang = En | Fr | Pl
|
||||||
|
|
||||||
type backend_option_builtin =
|
type backend_option =
|
||||||
[ `Latex
|
[ `Latex
|
||||||
| `Makefile
|
| `Makefile
|
||||||
| `Html
|
| `Html
|
||||||
@ -33,8 +33,6 @@ type backend_option_builtin =
|
|||||||
| `Exceptions
|
| `Exceptions
|
||||||
| `Proof ]
|
| `Proof ]
|
||||||
|
|
||||||
type 'a backend_option = [ backend_option_builtin | `Plugin of 'a ]
|
|
||||||
|
|
||||||
(** The usual auto/always/never option argument *)
|
(** The usual auto/always/never option argument *)
|
||||||
type when_enum = Auto | Always | Never
|
type when_enum = Auto | Always | Never
|
||||||
|
|
||||||
@ -43,14 +41,6 @@ val languages : (string * backend_lang) list
|
|||||||
val language_code : backend_lang -> string
|
val language_code : backend_lang -> string
|
||||||
(** Returns the lowercase two-letter language code *)
|
(** Returns the lowercase two-letter language code *)
|
||||||
|
|
||||||
val backend_option_to_string : string backend_option -> string
|
|
||||||
(** [backend_option_to_string backend] returns the string representation of the
|
|
||||||
given [backend].*)
|
|
||||||
|
|
||||||
val backend_option_of_string : string -> string backend_option
|
|
||||||
(** [backend_option_of_string backend] returns the {!type:backend_option}
|
|
||||||
corresponding to the [backend] string. *)
|
|
||||||
|
|
||||||
(** {2 Configuration globals} *)
|
(** {2 Configuration globals} *)
|
||||||
|
|
||||||
val source_files : string list ref
|
val source_files : string list ref
|
||||||
@ -95,20 +85,18 @@ val trace_opt : bool Cmdliner.Term.t
|
|||||||
val check_invariants_opt : bool Cmdliner.Term.t
|
val check_invariants_opt : bool Cmdliner.Term.t
|
||||||
val wrap_weaved_output : bool Cmdliner.Term.t
|
val wrap_weaved_output : bool Cmdliner.Term.t
|
||||||
val print_only_law : bool Cmdliner.Term.t
|
val print_only_law : bool Cmdliner.Term.t
|
||||||
val backend : string Cmdliner.Term.t
|
|
||||||
val plugins_dirs : string list Cmdliner.Term.t
|
val plugins_dirs : string list Cmdliner.Term.t
|
||||||
val language : string option Cmdliner.Term.t
|
val language : string option Cmdliner.Term.t
|
||||||
val max_prec_digits_opt : int option Cmdliner.Term.t
|
val max_prec_digits_opt : int option Cmdliner.Term.t
|
||||||
val ex_scope : string option Cmdliner.Term.t
|
val ex_scope : string option Cmdliner.Term.t
|
||||||
val output : string option Cmdliner.Term.t
|
val output : string option Cmdliner.Term.t
|
||||||
|
|
||||||
type options = {
|
type global_options = {
|
||||||
debug : bool;
|
debug : bool;
|
||||||
color : when_enum;
|
color : when_enum;
|
||||||
message_format : message_format_enum;
|
message_format : message_format_enum;
|
||||||
wrap_weaved_output : bool;
|
wrap_weaved_output : bool;
|
||||||
avoid_exceptions : bool;
|
avoid_exceptions : bool;
|
||||||
backend : string;
|
|
||||||
plugins_dirs : string list;
|
plugins_dirs : string list;
|
||||||
language : string option;
|
language : string option;
|
||||||
max_prec_digits : int option;
|
max_prec_digits : int option;
|
||||||
@ -122,14 +110,18 @@ type options = {
|
|||||||
output_file : string option;
|
output_file : string option;
|
||||||
closure_conversion : bool;
|
closure_conversion : bool;
|
||||||
print_only_law : bool;
|
print_only_law : bool;
|
||||||
|
link_modules : string list;
|
||||||
}
|
}
|
||||||
(** {2 Command-line application} *)
|
(** {2 Command-line application} *)
|
||||||
|
|
||||||
val options : options Cmdliner.Term.t
|
val global_options : global_options Cmdliner.Term.t
|
||||||
|
|
||||||
val catala_t : (string -> options -> 'a) -> 'a Cmdliner.Term.t
|
val catala_t :
|
||||||
|
?extra:int Cmdliner.Cmd.t list ->
|
||||||
|
(backend_option -> string -> global_options -> int) ->
|
||||||
|
int Cmdliner.Cmd.t
|
||||||
(** Main entry point: [catala_t file options] *)
|
(** Main entry point: [catala_t file options] *)
|
||||||
|
|
||||||
val set_option_globals : options -> unit
|
val set_option_globals : global_options -> unit
|
||||||
val version : string
|
val version : string
|
||||||
val info : Cmdliner.Cmd.info
|
val info : Cmdliner.Cmd.info
|
||||||
|
@ -10,14 +10,13 @@ let _ =
|
|||||||
(scope : Js.js_string Js.t)
|
(scope : Js.js_string Js.t)
|
||||||
(language : Js.js_string Js.t)
|
(language : Js.js_string Js.t)
|
||||||
(trace : bool) =
|
(trace : bool) =
|
||||||
driver
|
driver `Interpret
|
||||||
(Contents (Js.to_string contents))
|
(Contents (Js.to_string contents))
|
||||||
{
|
{
|
||||||
Cli.debug = false;
|
Cli.debug = false;
|
||||||
color = Never;
|
color = Never;
|
||||||
wrap_weaved_output = false;
|
wrap_weaved_output = false;
|
||||||
avoid_exceptions = false;
|
avoid_exceptions = false;
|
||||||
backend = "Interpret";
|
|
||||||
plugins_dirs = [];
|
plugins_dirs = [];
|
||||||
language = Some (Js.to_string language);
|
language = Some (Js.to_string language);
|
||||||
max_prec_digits = None;
|
max_prec_digits = None;
|
||||||
@ -32,5 +31,6 @@ let _ =
|
|||||||
ex_variable = None;
|
ex_variable = None;
|
||||||
output_file = None;
|
output_file = None;
|
||||||
print_only_law = false;
|
print_only_law = false;
|
||||||
|
link_modules = [];
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
@ -57,7 +57,6 @@ type 'm ctx = {
|
|||||||
subscope_vars :
|
subscope_vars :
|
||||||
('m Ast.expr Var.t * naked_typ * Desugared.Ast.io) ScopeVar.Map.t
|
('m Ast.expr Var.t * naked_typ * Desugared.Ast.io) ScopeVar.Map.t
|
||||||
SubScopeName.Map.t;
|
SubScopeName.Map.t;
|
||||||
local_vars : ('m Scopelang.Ast.expr, 'm Ast.expr Var.t) Var.Map.t;
|
|
||||||
date_rounding : date_rounding;
|
date_rounding : date_rounding;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,22 +201,6 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
|
|||||||
'm Ast.expr boxed =
|
'm Ast.expr boxed =
|
||||||
let m = Mark.get e in
|
let m = Mark.get e in
|
||||||
match Mark.remove e with
|
match Mark.remove e with
|
||||||
| EVar v -> Expr.evar (Var.Map.find v ctx.local_vars) m
|
|
||||||
| ELit
|
|
||||||
((LBool _ | LInt _ | LRat _ | LMoney _ | LUnit | LDate _ | LDuration _) as
|
|
||||||
l) ->
|
|
||||||
Expr.elit l m
|
|
||||||
| EStruct { name; fields } ->
|
|
||||||
let fields = StructField.Map.map (translate_expr ctx) fields in
|
|
||||||
Expr.estruct name fields m
|
|
||||||
| EStructAccess { e; field; name } ->
|
|
||||||
Expr.estructaccess (translate_expr ctx e) field name m
|
|
||||||
| ETuple es -> Expr.etuple (List.map (translate_expr ctx) es) m
|
|
||||||
| ETupleAccess { e; index; size } ->
|
|
||||||
Expr.etupleaccess (translate_expr ctx e) index size m
|
|
||||||
| EInj { e; cons; name } ->
|
|
||||||
let e' = translate_expr ctx e in
|
|
||||||
Expr.einj e' cons name m
|
|
||||||
| EMatch { e = e1; name; cases = e_cases } ->
|
| EMatch { e = e1; name; cases = e_cases } ->
|
||||||
let enum_sig = EnumName.Map.find name ctx.enums in
|
let enum_sig = EnumName.Map.find name ctx.enums in
|
||||||
let d_cases, remaining_e_cases =
|
let d_cases, remaining_e_cases =
|
||||||
@ -534,23 +517,6 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
|
|||||||
EndCall m
|
EndCall m
|
||||||
in
|
in
|
||||||
new_e
|
new_e
|
||||||
| EAbs { binder; tys } ->
|
|
||||||
let xs, body = Bindlib.unmbind binder in
|
|
||||||
let new_xs = Array.map (fun x -> Var.make (Bindlib.name_of x)) xs in
|
|
||||||
let both_xs = Array.map2 (fun x new_x -> x, new_x) xs new_xs in
|
|
||||||
let body =
|
|
||||||
translate_expr
|
|
||||||
{
|
|
||||||
ctx with
|
|
||||||
local_vars =
|
|
||||||
Array.fold_left
|
|
||||||
(fun local_vars (x, new_x) -> Var.Map.add x new_x local_vars)
|
|
||||||
ctx.local_vars both_xs;
|
|
||||||
}
|
|
||||||
body
|
|
||||||
in
|
|
||||||
let binder = Expr.bind new_xs body in
|
|
||||||
Expr.eabs binder tys m
|
|
||||||
| EDefault { excepts; just; cons } ->
|
| EDefault { excepts; just; cons } ->
|
||||||
let excepts = collapse_similar_outcomes excepts in
|
let excepts = collapse_similar_outcomes excepts in
|
||||||
Expr.edefault
|
Expr.edefault
|
||||||
@ -582,16 +548,13 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
|
|||||||
| ELocation (ToplevelVar v) ->
|
| ELocation (ToplevelVar v) ->
|
||||||
let v, _ = TopdefName.Map.find (Mark.remove v) ctx.toplevel_vars in
|
let v, _ = TopdefName.Map.find (Mark.remove v) ctx.toplevel_vars in
|
||||||
Expr.evar v m
|
Expr.evar v m
|
||||||
| EIfThenElse { cond; etrue; efalse } ->
|
|
||||||
Expr.eifthenelse (translate_expr ctx cond) (translate_expr ctx etrue)
|
|
||||||
(translate_expr ctx efalse)
|
|
||||||
m
|
|
||||||
| EOp { op = Add_dat_dur _; tys } ->
|
| EOp { op = Add_dat_dur _; tys } ->
|
||||||
Expr.eop (Add_dat_dur ctx.date_rounding) tys m
|
Expr.eop (Add_dat_dur ctx.date_rounding) tys m
|
||||||
| EOp { op; tys } -> Expr.eop (Operator.translate op) tys m
|
| EOp { op; tys } -> Expr.eop (Operator.translate op) tys m
|
||||||
| EEmptyError -> Expr.eemptyerror m
|
| ( EVar _ | EAbs _ | ELit _ | EExternal _ | EStruct _ | EStructAccess _
|
||||||
| EErrorOnEmpty e' -> Expr.eerroronempty (translate_expr ctx e') m
|
| ETuple _ | ETupleAccess _ | EInj _ | EEmptyError | EErrorOnEmpty _
|
||||||
| EArray es -> Expr.earray (List.map (translate_expr ctx) es) m
|
| EArray _ | EIfThenElse _ ) as e ->
|
||||||
|
Expr.map ~f:(translate_expr ctx) (e, m)
|
||||||
|
|
||||||
(** The result of a rule translation is a list of assignment, with variables and
|
(** The result of a rule translation is a list of assignment, with variables and
|
||||||
expressions. We also return the new translation context available after the
|
expressions. We also return the new translation context available after the
|
||||||
@ -1123,7 +1086,6 @@ let translate_program (prgm : 'm Scopelang.Ast.program) : 'm Ast.program =
|
|||||||
scopes_parameters = sctx;
|
scopes_parameters = sctx;
|
||||||
scope_vars = ScopeVar.Map.empty;
|
scope_vars = ScopeVar.Map.empty;
|
||||||
subscope_vars = SubScopeName.Map.empty;
|
subscope_vars = SubScopeName.Map.empty;
|
||||||
local_vars = Var.Map.empty;
|
|
||||||
toplevel_vars;
|
toplevel_vars;
|
||||||
date_rounding = AbortOnRound;
|
date_rounding = AbortOnRound;
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@ type scope = {
|
|||||||
|
|
||||||
type program = {
|
type program = {
|
||||||
program_scopes : scope ScopeName.Map.t;
|
program_scopes : scope ScopeName.Map.t;
|
||||||
program_topdefs : (expr * typ) TopdefName.Map.t;
|
program_topdefs : (expr option * typ) TopdefName.Map.t;
|
||||||
program_ctx : decl_ctx;
|
program_ctx : decl_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,4 +291,6 @@ let fold_exprs ~(f : 'a -> expr -> 'a) ~(init : 'a) (p : program) : 'a =
|
|||||||
acc)
|
acc)
|
||||||
p.program_scopes init
|
p.program_scopes init
|
||||||
in
|
in
|
||||||
TopdefName.Map.fold (fun _ (e, _) acc -> f acc e) p.program_topdefs acc
|
TopdefName.Map.fold
|
||||||
|
(fun _ (e, _) acc -> Option.fold ~none:acc ~some:(f acc) e)
|
||||||
|
p.program_topdefs acc
|
||||||
|
@ -114,7 +114,7 @@ type scope = {
|
|||||||
|
|
||||||
type program = {
|
type program = {
|
||||||
program_scopes : scope ScopeName.Map.t;
|
program_scopes : scope ScopeName.Map.t;
|
||||||
program_topdefs : (expr * typ) TopdefName.Map.t;
|
program_topdefs : (expr option * typ) TopdefName.Map.t;
|
||||||
program_ctx : decl_ctx;
|
program_ctx : decl_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,10 @@ let program prg =
|
|||||||
in
|
in
|
||||||
let program_topdefs =
|
let program_topdefs =
|
||||||
TopdefName.Map.map
|
TopdefName.Map.map
|
||||||
(fun (e, ty) -> Expr.unbox (expr prg.program_ctx env (Expr.box e)), ty)
|
(function
|
||||||
|
| Some e, ty ->
|
||||||
|
Some (Expr.unbox (expr prg.program_ctx env (Expr.box e))), ty
|
||||||
|
| None, ty -> None, ty)
|
||||||
prg.program_topdefs
|
prg.program_topdefs
|
||||||
in
|
in
|
||||||
let env =
|
let env =
|
||||||
|
@ -132,7 +132,7 @@ let disambiguate_constructor
|
|||||||
"The deep pattern matching syntactic sugar is not yet supported"
|
"The deep pattern matching syntactic sugar is not yet supported"
|
||||||
in
|
in
|
||||||
let possible_c_uids =
|
let possible_c_uids =
|
||||||
try IdentName.Map.find (Mark.remove constructor) ctxt.constructor_idmap
|
try Ident.Map.find (Mark.remove constructor) ctxt.constructor_idmap
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
Message.raise_spanned_error (Mark.get constructor)
|
Message.raise_spanned_error (Mark.get constructor)
|
||||||
"The name of this constructor has not been defined before, maybe it is \
|
"The name of this constructor has not been defined before, maybe it is \
|
||||||
@ -198,7 +198,7 @@ let rec translate_expr
|
|||||||
(expr : Surface.Ast.expression) : Ast.expr boxed =
|
(expr : Surface.Ast.expression) : Ast.expr boxed =
|
||||||
let scope_vars =
|
let scope_vars =
|
||||||
match scope with
|
match scope with
|
||||||
| None -> IdentName.Map.empty
|
| None -> Ident.Map.empty
|
||||||
| Some s -> (ScopeName.Map.find s ctxt.scopes).var_idmap
|
| Some s -> (ScopeName.Map.find s ctxt.scopes).var_idmap
|
||||||
in
|
in
|
||||||
let rec_helper = translate_expr scope inside_definition_of ctxt in
|
let rec_helper = translate_expr scope inside_definition_of ctxt in
|
||||||
@ -302,12 +302,12 @@ let rec translate_expr
|
|||||||
| Ident ([], (x, pos)) -> (
|
| Ident ([], (x, pos)) -> (
|
||||||
(* first we check whether this is a local var, then we resort to scope-wide
|
(* first we check whether this is a local var, then we resort to scope-wide
|
||||||
variables, then global variables *)
|
variables, then global variables *)
|
||||||
match IdentName.Map.find_opt x ctxt.local_var_idmap with
|
match Ident.Map.find_opt x ctxt.local_var_idmap with
|
||||||
| Some uid ->
|
| Some uid ->
|
||||||
Expr.make_var uid emark
|
Expr.make_var uid emark
|
||||||
(* the whole box thing is to accomodate for this case *)
|
(* the whole box thing is to accomodate for this case *)
|
||||||
| None -> (
|
| None -> (
|
||||||
match IdentName.Map.find_opt x scope_vars with
|
match Ident.Map.find_opt x scope_vars with
|
||||||
| Some (ScopeVar uid) ->
|
| Some (ScopeVar uid) ->
|
||||||
(* If the referenced variable has states, then here are the rules to
|
(* If the referenced variable has states, then here are the rules to
|
||||||
desambiguate. In general, only the last state can be referenced.
|
desambiguate. In general, only the last state can be referenced.
|
||||||
@ -352,7 +352,7 @@ let rec translate_expr
|
|||||||
(* Note: allowing access to a global variable with the same name as a
|
(* Note: allowing access to a global variable with the same name as a
|
||||||
subscope is disputable, but I see no good reason to forbid it either *)
|
subscope is disputable, but I see no good reason to forbid it either *)
|
||||||
| None -> (
|
| None -> (
|
||||||
match IdentName.Map.find_opt x ctxt.topdefs with
|
match Ident.Map.find_opt x ctxt.topdefs with
|
||||||
| Some v ->
|
| Some v ->
|
||||||
Expr.elocation
|
Expr.elocation
|
||||||
(ToplevelVar (v, Mark.get (TopdefName.get_info v)))
|
(ToplevelVar (v, Mark.get (TopdefName.get_info v)))
|
||||||
@ -360,8 +360,9 @@ let rec translate_expr
|
|||||||
| None ->
|
| None ->
|
||||||
Name_resolution.raise_unknown_identifier
|
Name_resolution.raise_unknown_identifier
|
||||||
"for a local, scope-wide or global variable" (x, pos))))
|
"for a local, scope-wide or global variable" (x, pos))))
|
||||||
| Ident (_path, _x) ->
|
| Surface.Ast.Ident (path, x) ->
|
||||||
Message.raise_spanned_error pos "Qualified paths are not supported yet"
|
let path = List.map Mark.remove path in
|
||||||
|
Expr.eexternal (path, Mark.remove x) emark
|
||||||
| Dotted (e, ((path, x), _ppos)) -> (
|
| Dotted (e, ((path, x), _ppos)) -> (
|
||||||
match path, Mark.remove e with
|
match path, Mark.remove e with
|
||||||
| [], Ident ([], (y, _))
|
| [], Ident ([], (y, _))
|
||||||
@ -369,7 +370,7 @@ let rec translate_expr
|
|||||||
Name_resolution.is_subscope_uid s ctxt y) ->
|
Name_resolution.is_subscope_uid s ctxt y) ->
|
||||||
(* In this case, y.x is a subscope variable *)
|
(* In this case, y.x is a subscope variable *)
|
||||||
let subscope_uid, subscope_real_uid =
|
let subscope_uid, subscope_real_uid =
|
||||||
match IdentName.Map.find y scope_vars with
|
match Ident.Map.find y scope_vars with
|
||||||
| SubScope (sub, sc) -> sub, sc
|
| SubScope (sub, sc) -> sub, sc
|
||||||
| ScopeVar _ -> assert false
|
| ScopeVar _ -> assert false
|
||||||
in
|
in
|
||||||
@ -409,7 +410,7 @@ let rec translate_expr
|
|||||||
(fun acc (fld_id, e) ->
|
(fun acc (fld_id, e) ->
|
||||||
let var =
|
let var =
|
||||||
match
|
match
|
||||||
IdentName.Map.find_opt (Mark.remove fld_id) scope_def.var_idmap
|
Ident.Map.find_opt (Mark.remove fld_id) scope_def.var_idmap
|
||||||
with
|
with
|
||||||
| Some (ScopeVar v) -> v
|
| Some (ScopeVar v) -> v
|
||||||
| Some (SubScope _) | None ->
|
| Some (SubScope _) | None ->
|
||||||
@ -449,7 +450,7 @@ let rec translate_expr
|
|||||||
Expr.eapp fn [rec_helper e1] emark
|
Expr.eapp fn [rec_helper e1] emark
|
||||||
| StructLit ((([], s_name), _), fields) ->
|
| StructLit ((([], s_name), _), fields) ->
|
||||||
let s_uid =
|
let s_uid =
|
||||||
match IdentName.Map.find_opt (Mark.remove s_name) ctxt.typedefs with
|
match Ident.Map.find_opt (Mark.remove s_name) ctxt.typedefs with
|
||||||
| Some (Name_resolution.TStruct s_uid) -> s_uid
|
| Some (Name_resolution.TStruct s_uid) -> s_uid
|
||||||
| _ ->
|
| _ ->
|
||||||
Message.raise_spanned_error (Mark.get s_name)
|
Message.raise_spanned_error (Mark.get s_name)
|
||||||
@ -462,7 +463,7 @@ let rec translate_expr
|
|||||||
let f_uid =
|
let f_uid =
|
||||||
try
|
try
|
||||||
StructName.Map.find s_uid
|
StructName.Map.find s_uid
|
||||||
(IdentName.Map.find (Mark.remove f_name) ctxt.field_idmap)
|
(Ident.Map.find (Mark.remove f_name) ctxt.field_idmap)
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
Message.raise_spanned_error (Mark.get f_name)
|
Message.raise_spanned_error (Mark.get f_name)
|
||||||
"This identifier should refer to a field of struct %s"
|
"This identifier should refer to a field of struct %s"
|
||||||
@ -492,7 +493,7 @@ let rec translate_expr
|
|||||||
Message.raise_spanned_error pos "Qualified paths are not supported yet"
|
Message.raise_spanned_error pos "Qualified paths are not supported yet"
|
||||||
| EnumInject (((path, (constructor, pos_constructor)), _), payload) -> (
|
| EnumInject (((path, (constructor, pos_constructor)), _), payload) -> (
|
||||||
let possible_c_uids =
|
let possible_c_uids =
|
||||||
try IdentName.Map.find constructor ctxt.constructor_idmap
|
try Ident.Map.find constructor ctxt.constructor_idmap
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
Message.raise_spanned_error pos_constructor
|
Message.raise_spanned_error pos_constructor
|
||||||
"The name of this constructor has not been defined before, maybe it \
|
"The name of this constructor has not been defined before, maybe it \
|
||||||
@ -1028,7 +1029,7 @@ let process_def
|
|||||||
match def.definition_label with
|
match def.definition_label with
|
||||||
| Some (label_str, label_pos) ->
|
| Some (label_str, label_pos) ->
|
||||||
Ast.ExplicitlyLabeled
|
Ast.ExplicitlyLabeled
|
||||||
(IdentName.Map.find label_str scope_def_ctxt.label_idmap, label_pos)
|
(Ident.Map.find label_str scope_def_ctxt.label_idmap, label_pos)
|
||||||
| None -> Ast.Unlabeled
|
| None -> Ast.Unlabeled
|
||||||
in
|
in
|
||||||
let exception_situation =
|
let exception_situation =
|
||||||
@ -1045,8 +1046,7 @@ let process_def
|
|||||||
| ExceptionToLabel label_str -> (
|
| ExceptionToLabel label_str -> (
|
||||||
try
|
try
|
||||||
let label_id =
|
let label_id =
|
||||||
IdentName.Map.find (Mark.remove label_str)
|
Ident.Map.find (Mark.remove label_str) scope_def_ctxt.label_idmap
|
||||||
scope_def_ctxt.label_idmap
|
|
||||||
in
|
in
|
||||||
ExceptionToLabel (label_id, Mark.get label_str)
|
ExceptionToLabel (label_id, Mark.get label_str)
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
@ -1248,17 +1248,16 @@ let process_topdef
|
|||||||
(prgm : Ast.program)
|
(prgm : Ast.program)
|
||||||
(def : S.top_def) : Ast.program =
|
(def : S.top_def) : Ast.program =
|
||||||
let id =
|
let id =
|
||||||
IdentName.Map.find
|
Ident.Map.find (Mark.remove def.S.topdef_name) ctxt.Name_resolution.topdefs
|
||||||
(Mark.remove def.S.topdef_name)
|
|
||||||
ctxt.Name_resolution.topdefs
|
|
||||||
in
|
in
|
||||||
let translate_typ t = Name_resolution.process_type ctxt t in
|
let translate_typ t = Name_resolution.process_type ctxt t in
|
||||||
let translate_tbase (tbase, m) = translate_typ (Base tbase, m) in
|
let translate_tbase (tbase, m) = translate_typ (Base tbase, m) in
|
||||||
let typ = translate_typ def.S.topdef_type in
|
let typ = translate_typ def.S.topdef_type in
|
||||||
let expr =
|
let expr_opt =
|
||||||
match def.S.topdef_args with
|
match def.S.topdef_expr, def.S.topdef_args with
|
||||||
| None -> translate_expr None None ctxt def.S.topdef_expr
|
| None, _ -> None
|
||||||
| Some (args, _) ->
|
| Some e, None -> Some (Expr.unbox_closed (translate_expr None None ctxt e))
|
||||||
|
| Some e, Some (args, _) ->
|
||||||
let ctxt, args_tys =
|
let ctxt, args_tys =
|
||||||
List.fold_left_map
|
List.fold_left_map
|
||||||
(fun ctxt ((lbl, pos), ty) ->
|
(fun ctxt ((lbl, pos), ty) ->
|
||||||
@ -1266,19 +1265,38 @@ let process_topdef
|
|||||||
ctxt, ((v, pos), ty))
|
ctxt, ((v, pos), ty))
|
||||||
ctxt args
|
ctxt args
|
||||||
in
|
in
|
||||||
let body = translate_expr None None ctxt def.S.topdef_expr in
|
let body = translate_expr None None ctxt e in
|
||||||
let args, tys = List.split args_tys in
|
let args, tys = List.split args_tys in
|
||||||
Expr.make_abs
|
let e =
|
||||||
(Array.of_list (List.map Mark.remove args))
|
Expr.make_abs
|
||||||
body
|
(Array.of_list (List.map Mark.remove args))
|
||||||
(List.map translate_tbase tys)
|
body
|
||||||
(Mark.get def.S.topdef_name)
|
(List.map translate_tbase tys)
|
||||||
|
(Mark.get def.S.topdef_name)
|
||||||
|
in
|
||||||
|
Some (Expr.unbox_closed e)
|
||||||
in
|
in
|
||||||
{
|
let program_topdefs =
|
||||||
prgm with
|
TopdefName.Map.update id
|
||||||
Ast.program_topdefs =
|
(fun def0 ->
|
||||||
TopdefName.Map.add id (Expr.unbox expr, typ) prgm.Ast.program_topdefs;
|
match def0, expr_opt with
|
||||||
}
|
| None, eopt -> Some (eopt, typ)
|
||||||
|
| Some (eopt0, ty0), eopt -> (
|
||||||
|
let err msg =
|
||||||
|
Message.raise_multispanned_error
|
||||||
|
[None, Mark.get ty0; None, Mark.get typ]
|
||||||
|
(msg ^^ " for %a") TopdefName.format_t id
|
||||||
|
in
|
||||||
|
if not (Type.equal ty0 typ) then err "Conflicting type definitions"
|
||||||
|
else
|
||||||
|
match eopt0, eopt with
|
||||||
|
| None, None -> err "Multiple declarations"
|
||||||
|
| Some _, Some _ -> err "Multiple definitions"
|
||||||
|
| Some e, None -> Some (Some e, typ)
|
||||||
|
| None, Some e -> Some (Some e, ty0)))
|
||||||
|
prgm.Ast.program_topdefs
|
||||||
|
in
|
||||||
|
{ prgm with Ast.program_topdefs }
|
||||||
|
|
||||||
let attribute_to_io (attr : Surface.Ast.scope_decl_context_io) : Ast.io =
|
let attribute_to_io (attr : Surface.Ast.scope_decl_context_io) : Ast.io =
|
||||||
{
|
{
|
||||||
@ -1295,7 +1313,7 @@ let attribute_to_io (attr : Surface.Ast.scope_decl_context_io) : Ast.io =
|
|||||||
|
|
||||||
let init_scope_defs
|
let init_scope_defs
|
||||||
(ctxt : Name_resolution.context)
|
(ctxt : Name_resolution.context)
|
||||||
(scope_idmap : Name_resolution.scope_var_or_subscope IdentName.Map.t) :
|
(scope_idmap : Name_resolution.scope_var_or_subscope Ident.Map.t) :
|
||||||
Ast.scope_def Ast.ScopeDef.Map.t =
|
Ast.scope_def Ast.ScopeDef.Map.t =
|
||||||
(* Initializing the definitions of all scopes and subscope vars, with no rules
|
(* Initializing the definitions of all scopes and subscope vars, with no rules
|
||||||
yet inside *)
|
yet inside *)
|
||||||
@ -1351,7 +1369,7 @@ let init_scope_defs
|
|||||||
let sub_scope_def =
|
let sub_scope_def =
|
||||||
ScopeName.Map.find subscope_uid ctxt.Name_resolution.scopes
|
ScopeName.Map.find subscope_uid ctxt.Name_resolution.scopes
|
||||||
in
|
in
|
||||||
IdentName.Map.fold
|
Ident.Map.fold
|
||||||
(fun _ v scope_def_map ->
|
(fun _ v scope_def_map ->
|
||||||
match v with
|
match v with
|
||||||
| Name_resolution.SubScope _ -> scope_def_map
|
| Name_resolution.SubScope _ -> scope_def_map
|
||||||
@ -1373,7 +1391,7 @@ let init_scope_defs
|
|||||||
scope_def_map)
|
scope_def_map)
|
||||||
sub_scope_def.Name_resolution.var_idmap scope_def_map
|
sub_scope_def.Name_resolution.var_idmap scope_def_map
|
||||||
in
|
in
|
||||||
IdentName.Map.fold add_def scope_idmap Ast.ScopeDef.Map.empty
|
Ident.Map.fold add_def scope_idmap Ast.ScopeDef.Map.empty
|
||||||
|
|
||||||
(** Main function of this module *)
|
(** Main function of this module *)
|
||||||
let translate_program
|
let translate_program
|
||||||
@ -1384,7 +1402,7 @@ let translate_program
|
|||||||
ScopeName.Map.mapi
|
ScopeName.Map.mapi
|
||||||
(fun s_uid s_context ->
|
(fun s_uid s_context ->
|
||||||
let scope_vars =
|
let scope_vars =
|
||||||
IdentName.Map.fold
|
Ident.Map.fold
|
||||||
(fun _ v acc ->
|
(fun _ v acc ->
|
||||||
match v with
|
match v with
|
||||||
| Name_resolution.SubScope _ -> acc
|
| Name_resolution.SubScope _ -> acc
|
||||||
@ -1396,7 +1414,7 @@ let translate_program
|
|||||||
s_context.Name_resolution.var_idmap ScopeVar.Map.empty
|
s_context.Name_resolution.var_idmap ScopeVar.Map.empty
|
||||||
in
|
in
|
||||||
let scope_sub_scopes =
|
let scope_sub_scopes =
|
||||||
IdentName.Map.fold
|
Ident.Map.fold
|
||||||
(fun _ v acc ->
|
(fun _ v acc ->
|
||||||
match v with
|
match v with
|
||||||
| Name_resolution.ScopeVar _ -> acc
|
| Name_resolution.ScopeVar _ -> acc
|
||||||
@ -1415,13 +1433,14 @@ let translate_program
|
|||||||
})
|
})
|
||||||
ctxt.Name_resolution.scopes
|
ctxt.Name_resolution.scopes
|
||||||
in
|
in
|
||||||
|
let translate_type t = Name_resolution.process_type ctxt t in
|
||||||
{
|
{
|
||||||
Ast.program_ctx =
|
Ast.program_ctx =
|
||||||
{
|
{
|
||||||
ctx_structs = ctxt.Name_resolution.structs;
|
ctx_structs = ctxt.Name_resolution.structs;
|
||||||
ctx_enums = ctxt.Name_resolution.enums;
|
ctx_enums = ctxt.Name_resolution.enums;
|
||||||
ctx_scopes =
|
ctx_scopes =
|
||||||
IdentName.Map.fold
|
Ident.Map.fold
|
||||||
(fun _ def acc ->
|
(fun _ def acc ->
|
||||||
match def with
|
match def with
|
||||||
| Name_resolution.TScope (scope, scope_out_struct) ->
|
| Name_resolution.TScope (scope, scope_out_struct) ->
|
||||||
@ -1429,6 +1448,19 @@ let translate_program
|
|||||||
| _ -> acc)
|
| _ -> acc)
|
||||||
ctxt.Name_resolution.typedefs ScopeName.Map.empty;
|
ctxt.Name_resolution.typedefs ScopeName.Map.empty;
|
||||||
ctx_struct_fields = ctxt.Name_resolution.field_idmap;
|
ctx_struct_fields = ctxt.Name_resolution.field_idmap;
|
||||||
|
ctx_modules =
|
||||||
|
List.fold_left
|
||||||
|
(fun map (path, def) ->
|
||||||
|
match def with
|
||||||
|
| Surface.Ast.Topdef { topdef_name; topdef_type; _ }, _pos ->
|
||||||
|
Qident.Map.add
|
||||||
|
(path, Mark.remove topdef_name)
|
||||||
|
(translate_type topdef_type)
|
||||||
|
map
|
||||||
|
| (ScopeDecl _ | StructDecl _ | EnumDecl _), _ (* as e *) ->
|
||||||
|
map (* assert false (\* TODO *\) *)
|
||||||
|
| ScopeUse _, _ -> assert false)
|
||||||
|
Qident.Map.empty prgm.Surface.Ast.program_interfaces;
|
||||||
};
|
};
|
||||||
Ast.program_topdefs = TopdefName.Map.empty;
|
Ast.program_topdefs = TopdefName.Map.empty;
|
||||||
Ast.program_scopes;
|
Ast.program_scopes;
|
||||||
|
@ -109,7 +109,7 @@ let detect_unused_struct_fields (p : program) : unit =
|
|||||||
| EDStructAccess { name_opt = Some name; e = e_struct; field } ->
|
| EDStructAccess { name_opt = Some name; e = e_struct; field } ->
|
||||||
let field =
|
let field =
|
||||||
StructName.Map.find name
|
StructName.Map.find name
|
||||||
(IdentName.Map.find field p.program_ctx.ctx_struct_fields)
|
(Ident.Map.find field p.program_ctx.ctx_struct_fields)
|
||||||
in
|
in
|
||||||
StructField.Set.add field
|
StructField.Set.add field
|
||||||
(structs_fields_used_expr e_struct struct_fields_used)
|
(structs_fields_used_expr e_struct struct_fields_used)
|
||||||
|
@ -27,7 +27,7 @@ type unique_rulename = Ambiguous of Pos.t list | Unique of RuleName.t Mark.pos
|
|||||||
|
|
||||||
type scope_def_context = {
|
type scope_def_context = {
|
||||||
default_exception_rulename : unique_rulename option;
|
default_exception_rulename : unique_rulename option;
|
||||||
label_idmap : LabelName.t IdentName.Map.t;
|
label_idmap : LabelName.t Ident.Map.t;
|
||||||
}
|
}
|
||||||
|
|
||||||
type scope_var_or_subscope =
|
type scope_var_or_subscope =
|
||||||
@ -35,7 +35,7 @@ type scope_var_or_subscope =
|
|||||||
| SubScope of SubScopeName.t * ScopeName.t
|
| SubScope of SubScopeName.t * ScopeName.t
|
||||||
|
|
||||||
type scope_context = {
|
type scope_context = {
|
||||||
var_idmap : scope_var_or_subscope IdentName.Map.t;
|
var_idmap : scope_var_or_subscope Ident.Map.t;
|
||||||
(** All variables, including scope variables and subscopes *)
|
(** All variables, including scope variables and subscopes *)
|
||||||
scope_defs_contexts : scope_def_context Ast.ScopeDef.Map.t;
|
scope_defs_contexts : scope_def_context Ast.ScopeDef.Map.t;
|
||||||
(** What is the default rule to refer to for unnamed exceptions, if any *)
|
(** What is the default rule to refer to for unnamed exceptions, if any *)
|
||||||
@ -56,7 +56,7 @@ type var_sig = {
|
|||||||
var_sig_parameters :
|
var_sig_parameters :
|
||||||
(Uid.MarkedString.info * Shared_ast.typ) list Mark.pos option;
|
(Uid.MarkedString.info * Shared_ast.typ) list Mark.pos option;
|
||||||
var_sig_io : Surface.Ast.scope_decl_context_io;
|
var_sig_io : Surface.Ast.scope_decl_context_io;
|
||||||
var_sig_states_idmap : StateName.t IdentName.Map.t;
|
var_sig_states_idmap : StateName.t Ident.Map.t;
|
||||||
var_sig_states_list : StateName.t list;
|
var_sig_states_list : StateName.t list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,19 +69,19 @@ type typedef =
|
|||||||
(** Implicitly defined output struct *)
|
(** Implicitly defined output struct *)
|
||||||
|
|
||||||
type context = {
|
type context = {
|
||||||
local_var_idmap : Ast.expr Var.t IdentName.Map.t;
|
local_var_idmap : Ast.expr Var.t Ident.Map.t;
|
||||||
(** Inside a definition, local variables can be introduced by functions
|
(** Inside a definition, local variables can be introduced by functions
|
||||||
arguments or pattern matching *)
|
arguments or pattern matching *)
|
||||||
typedefs : typedef IdentName.Map.t;
|
typedefs : typedef Ident.Map.t;
|
||||||
(** Gathers the names of the scopes, structs and enums *)
|
(** Gathers the names of the scopes, structs and enums *)
|
||||||
field_idmap : StructField.t StructName.Map.t IdentName.Map.t;
|
field_idmap : StructField.t StructName.Map.t Ident.Map.t;
|
||||||
(** The names of the struct fields. Names of fields can be shared between
|
(** The names of the struct fields. Names of fields can be shared between
|
||||||
different structs *)
|
different structs *)
|
||||||
constructor_idmap : EnumConstructor.t EnumName.Map.t IdentName.Map.t;
|
constructor_idmap : EnumConstructor.t EnumName.Map.t Ident.Map.t;
|
||||||
(** The names of the enum constructors. Constructor names can be shared
|
(** The names of the enum constructors. Constructor names can be shared
|
||||||
between different enums *)
|
between different enums *)
|
||||||
scopes : scope_context ScopeName.Map.t; (** For each scope, its context *)
|
scopes : scope_context ScopeName.Map.t; (** For each scope, its context *)
|
||||||
topdefs : TopdefName.t IdentName.Map.t; (** Global definitions *)
|
topdefs : TopdefName.t Ident.Map.t; (** Global definitions *)
|
||||||
structs : struct_context StructName.Map.t;
|
structs : struct_context StructName.Map.t;
|
||||||
(** For each struct, its context *)
|
(** For each struct, its context *)
|
||||||
enums : enum_context EnumName.Map.t; (** For each enum, its context *)
|
enums : enum_context EnumName.Map.t; (** For each enum, its context *)
|
||||||
@ -99,7 +99,7 @@ let raise_unsupported_feature (msg : string) (pos : Pos.t) =
|
|||||||
|
|
||||||
(** Function to call whenever an identifier used somewhere has not been declared
|
(** Function to call whenever an identifier used somewhere has not been declared
|
||||||
in the program previously *)
|
in the program previously *)
|
||||||
let raise_unknown_identifier (msg : string) (ident : IdentName.t Mark.pos) =
|
let raise_unknown_identifier (msg : string) (ident : Ident.t Mark.pos) =
|
||||||
Message.raise_spanned_error (Mark.get ident)
|
Message.raise_spanned_error (Mark.get ident)
|
||||||
"@{<yellow>\"%s\"@}: unknown identifier %s" (Mark.remove ident) msg
|
"@{<yellow>\"%s\"@}: unknown identifier %s" (Mark.remove ident) msg
|
||||||
|
|
||||||
@ -118,9 +118,9 @@ let get_var_io (ctxt : context) (uid : ScopeVar.t) :
|
|||||||
let get_var_uid
|
let get_var_uid
|
||||||
(scope_uid : ScopeName.t)
|
(scope_uid : ScopeName.t)
|
||||||
(ctxt : context)
|
(ctxt : context)
|
||||||
((x, pos) : IdentName.t Mark.pos) : ScopeVar.t =
|
((x, pos) : Ident.t Mark.pos) : ScopeVar.t =
|
||||||
let scope = ScopeName.Map.find scope_uid ctxt.scopes in
|
let scope = ScopeName.Map.find scope_uid ctxt.scopes in
|
||||||
match IdentName.Map.find_opt x scope.var_idmap with
|
match Ident.Map.find_opt x scope.var_idmap with
|
||||||
| Some (ScopeVar uid) -> uid
|
| Some (ScopeVar uid) -> uid
|
||||||
| _ ->
|
| _ ->
|
||||||
raise_unknown_identifier
|
raise_unknown_identifier
|
||||||
@ -131,18 +131,18 @@ let get_var_uid
|
|||||||
let get_subscope_uid
|
let get_subscope_uid
|
||||||
(scope_uid : ScopeName.t)
|
(scope_uid : ScopeName.t)
|
||||||
(ctxt : context)
|
(ctxt : context)
|
||||||
((y, pos) : IdentName.t Mark.pos) : SubScopeName.t =
|
((y, pos) : Ident.t Mark.pos) : SubScopeName.t =
|
||||||
let scope = ScopeName.Map.find scope_uid ctxt.scopes in
|
let scope = ScopeName.Map.find scope_uid ctxt.scopes in
|
||||||
match IdentName.Map.find_opt y scope.var_idmap with
|
match Ident.Map.find_opt y scope.var_idmap with
|
||||||
| Some (SubScope (sub_uid, _sub_id)) -> sub_uid
|
| Some (SubScope (sub_uid, _sub_id)) -> sub_uid
|
||||||
| _ -> raise_unknown_identifier "for a subscope of this scope" (y, pos)
|
| _ -> raise_unknown_identifier "for a subscope of this scope" (y, pos)
|
||||||
|
|
||||||
(** [is_subscope_uid scope_uid ctxt y] returns true if [y] belongs to the
|
(** [is_subscope_uid scope_uid ctxt y] returns true if [y] belongs to the
|
||||||
subscopes of [scope_uid]. *)
|
subscopes of [scope_uid]. *)
|
||||||
let is_subscope_uid (scope_uid : ScopeName.t) (ctxt : context) (y : IdentName.t)
|
let is_subscope_uid (scope_uid : ScopeName.t) (ctxt : context) (y : Ident.t) :
|
||||||
: bool =
|
bool =
|
||||||
let scope = ScopeName.Map.find scope_uid ctxt.scopes in
|
let scope = ScopeName.Map.find scope_uid ctxt.scopes in
|
||||||
match IdentName.Map.find_opt y scope.var_idmap with
|
match Ident.Map.find_opt y scope.var_idmap with
|
||||||
| Some (SubScope _) -> true
|
| Some (SubScope _) -> true
|
||||||
| _ -> false
|
| _ -> false
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ let is_subscope_uid (scope_uid : ScopeName.t) (ctxt : context) (y : IdentName.t)
|
|||||||
let belongs_to (ctxt : context) (uid : ScopeVar.t) (scope_uid : ScopeName.t) :
|
let belongs_to (ctxt : context) (uid : ScopeVar.t) (scope_uid : ScopeName.t) :
|
||||||
bool =
|
bool =
|
||||||
let scope = ScopeName.Map.find scope_uid ctxt.scopes in
|
let scope = ScopeName.Map.find scope_uid ctxt.scopes in
|
||||||
IdentName.Map.exists
|
Ident.Map.exists
|
||||||
(fun _ -> function
|
(fun _ -> function
|
||||||
| ScopeVar var_uid -> ScopeVar.equal uid var_uid
|
| ScopeVar var_uid -> ScopeVar.equal uid var_uid
|
||||||
| _ -> false)
|
| _ -> false)
|
||||||
@ -184,7 +184,7 @@ let is_def_cond (ctxt : context) (def : Ast.ScopeDef.t) : bool =
|
|||||||
is_var_cond ctxt x
|
is_var_cond ctxt x
|
||||||
|
|
||||||
let get_enum ctxt id =
|
let get_enum ctxt id =
|
||||||
match IdentName.Map.find (Mark.remove id) ctxt.typedefs with
|
match Ident.Map.find (Mark.remove id) ctxt.typedefs with
|
||||||
| TEnum id -> id
|
| TEnum id -> id
|
||||||
| TStruct sid ->
|
| TStruct sid ->
|
||||||
Message.raise_multispanned_error
|
Message.raise_multispanned_error
|
||||||
@ -205,7 +205,7 @@ let get_enum ctxt id =
|
|||||||
(Mark.remove id)
|
(Mark.remove id)
|
||||||
|
|
||||||
let get_struct ctxt id =
|
let get_struct ctxt id =
|
||||||
match IdentName.Map.find (Mark.remove id) ctxt.typedefs with
|
match Ident.Map.find (Mark.remove id) ctxt.typedefs with
|
||||||
| TStruct id | TScope (_, { out_struct_name = id; _ }) -> id
|
| TStruct id | TScope (_, { out_struct_name = id; _ }) -> id
|
||||||
| TEnum eid ->
|
| TEnum eid ->
|
||||||
Message.raise_multispanned_error
|
Message.raise_multispanned_error
|
||||||
@ -219,7 +219,7 @@ let get_struct ctxt id =
|
|||||||
(Mark.remove id)
|
(Mark.remove id)
|
||||||
|
|
||||||
let get_scope ctxt id =
|
let get_scope ctxt id =
|
||||||
match IdentName.Map.find (Mark.remove id) ctxt.typedefs with
|
match Ident.Map.find (Mark.remove id) ctxt.typedefs with
|
||||||
| TScope (id, _) -> id
|
| TScope (id, _) -> id
|
||||||
| TEnum eid ->
|
| TEnum eid ->
|
||||||
Message.raise_multispanned_error
|
Message.raise_multispanned_error
|
||||||
@ -249,7 +249,7 @@ let process_subscope_decl
|
|||||||
let name, name_pos = decl.scope_decl_context_scope_name in
|
let name, name_pos = decl.scope_decl_context_scope_name in
|
||||||
let subscope, s_pos = decl.scope_decl_context_scope_sub_scope in
|
let subscope, s_pos = decl.scope_decl_context_scope_sub_scope in
|
||||||
let scope_ctxt = ScopeName.Map.find scope ctxt.scopes in
|
let scope_ctxt = ScopeName.Map.find scope ctxt.scopes in
|
||||||
match IdentName.Map.find_opt subscope scope_ctxt.var_idmap with
|
match Ident.Map.find_opt subscope scope_ctxt.var_idmap with
|
||||||
| Some use ->
|
| Some use ->
|
||||||
let info =
|
let info =
|
||||||
match use with
|
match use with
|
||||||
@ -268,7 +268,7 @@ let process_subscope_decl
|
|||||||
{
|
{
|
||||||
scope_ctxt with
|
scope_ctxt with
|
||||||
var_idmap =
|
var_idmap =
|
||||||
IdentName.Map.add name
|
Ident.Map.add name
|
||||||
(SubScope (sub_scope_uid, original_subscope_uid))
|
(SubScope (sub_scope_uid, original_subscope_uid))
|
||||||
scope_ctxt.var_idmap;
|
scope_ctxt.var_idmap;
|
||||||
sub_scopes =
|
sub_scopes =
|
||||||
@ -304,7 +304,7 @@ let rec process_base_typ
|
|||||||
| Surface.Ast.Boolean -> TLit TBool, typ_pos
|
| Surface.Ast.Boolean -> TLit TBool, typ_pos
|
||||||
| Surface.Ast.Text -> raise_unsupported_feature "text type" typ_pos
|
| Surface.Ast.Text -> raise_unsupported_feature "text type" typ_pos
|
||||||
| Surface.Ast.Named ([], (ident, _pos)) -> (
|
| Surface.Ast.Named ([], (ident, _pos)) -> (
|
||||||
match IdentName.Map.find_opt ident ctxt.typedefs with
|
match Ident.Map.find_opt ident ctxt.typedefs with
|
||||||
| Some (TStruct s_uid) -> TStruct s_uid, typ_pos
|
| Some (TStruct s_uid) -> TStruct s_uid, typ_pos
|
||||||
| Some (TEnum e_uid) -> TEnum e_uid, typ_pos
|
| Some (TEnum e_uid) -> TEnum e_uid, typ_pos
|
||||||
| Some (TScope (_, scope_str)) ->
|
| Some (TScope (_, scope_str)) ->
|
||||||
@ -337,7 +337,7 @@ let process_data_decl
|
|||||||
let is_cond = is_type_cond decl.scope_decl_context_item_typ in
|
let is_cond = is_type_cond decl.scope_decl_context_item_typ in
|
||||||
let name, pos = decl.scope_decl_context_item_name in
|
let name, pos = decl.scope_decl_context_item_name in
|
||||||
let scope_ctxt = ScopeName.Map.find scope ctxt.scopes in
|
let scope_ctxt = ScopeName.Map.find scope ctxt.scopes in
|
||||||
match IdentName.Map.find_opt name scope_ctxt.var_idmap with
|
match Ident.Map.find_opt name scope_ctxt.var_idmap with
|
||||||
| Some use ->
|
| Some use ->
|
||||||
let info =
|
let info =
|
||||||
match use with
|
match use with
|
||||||
@ -352,15 +352,14 @@ let process_data_decl
|
|||||||
let scope_ctxt =
|
let scope_ctxt =
|
||||||
{
|
{
|
||||||
scope_ctxt with
|
scope_ctxt with
|
||||||
var_idmap = IdentName.Map.add name (ScopeVar uid) scope_ctxt.var_idmap;
|
var_idmap = Ident.Map.add name (ScopeVar uid) scope_ctxt.var_idmap;
|
||||||
}
|
}
|
||||||
in
|
in
|
||||||
let states_idmap, states_list =
|
let states_idmap, states_list =
|
||||||
List.fold_right
|
List.fold_right
|
||||||
(fun state_id
|
(fun state_id ((states_idmap : StateName.t Ident.Map.t), states_list) ->
|
||||||
((states_idmap : StateName.t IdentName.Map.t), states_list) ->
|
|
||||||
let state_id_name = Mark.remove state_id in
|
let state_id_name = Mark.remove state_id in
|
||||||
if IdentName.Map.mem state_id_name states_idmap then
|
if Ident.Map.mem state_id_name states_idmap then
|
||||||
Message.raise_multispanned_error_full
|
Message.raise_multispanned_error_full
|
||||||
[
|
[
|
||||||
( Some
|
( Some
|
||||||
@ -375,15 +374,15 @@ let process_data_decl
|
|||||||
"Second instance of state @{<yellow>\"%s\"@}:"
|
"Second instance of state @{<yellow>\"%s\"@}:"
|
||||||
state_id_name),
|
state_id_name),
|
||||||
Mark.get
|
Mark.get
|
||||||
(IdentName.Map.find state_id_name states_idmap
|
(Ident.Map.find state_id_name states_idmap
|
||||||
|> StateName.get_info) );
|
|> StateName.get_info) );
|
||||||
]
|
]
|
||||||
"There are two states with the same name for the same variable: \
|
"There are two states with the same name for the same variable: \
|
||||||
this is ambiguous. Please change the name of either states.";
|
this is ambiguous. Please change the name of either states.";
|
||||||
let state_uid = StateName.fresh state_id in
|
let state_uid = StateName.fresh state_id in
|
||||||
( IdentName.Map.add state_id_name state_uid states_idmap,
|
( Ident.Map.add state_id_name state_uid states_idmap,
|
||||||
state_uid :: states_list ))
|
state_uid :: states_list ))
|
||||||
decl.scope_decl_context_item_states (IdentName.Map.empty, [])
|
decl.scope_decl_context_item_states (Ident.Map.empty, [])
|
||||||
in
|
in
|
||||||
let var_sig_parameters =
|
let var_sig_parameters =
|
||||||
Option.map
|
Option.map
|
||||||
@ -407,14 +406,13 @@ let process_data_decl
|
|||||||
}
|
}
|
||||||
|
|
||||||
(** Adds a binding to the context *)
|
(** Adds a binding to the context *)
|
||||||
let add_def_local_var (ctxt : context) (name : IdentName.t) :
|
let add_def_local_var (ctxt : context) (name : Ident.t) :
|
||||||
context * Ast.expr Var.t =
|
context * Ast.expr Var.t =
|
||||||
let local_var_uid = Var.make name in
|
let local_var_uid = Var.make name in
|
||||||
let ctxt =
|
let ctxt =
|
||||||
{
|
{
|
||||||
ctxt with
|
ctxt with
|
||||||
local_var_idmap =
|
local_var_idmap = Ident.Map.add name local_var_uid ctxt.local_var_idmap;
|
||||||
IdentName.Map.add name local_var_uid ctxt.local_var_idmap;
|
|
||||||
}
|
}
|
||||||
in
|
in
|
||||||
ctxt, local_var_uid
|
ctxt, local_var_uid
|
||||||
@ -436,7 +434,7 @@ let process_struct_decl (ctxt : context) (sdecl : Surface.Ast.struct_decl) :
|
|||||||
{
|
{
|
||||||
ctxt with
|
ctxt with
|
||||||
field_idmap =
|
field_idmap =
|
||||||
IdentName.Map.update
|
Ident.Map.update
|
||||||
(Mark.remove fdecl.Surface.Ast.struct_decl_field_name)
|
(Mark.remove fdecl.Surface.Ast.struct_decl_field_name)
|
||||||
(fun uids ->
|
(fun uids ->
|
||||||
match uids with
|
match uids with
|
||||||
@ -481,7 +479,7 @@ let process_enum_decl (ctxt : context) (edecl : Surface.Ast.enum_decl) : context
|
|||||||
{
|
{
|
||||||
ctxt with
|
ctxt with
|
||||||
constructor_idmap =
|
constructor_idmap =
|
||||||
IdentName.Map.update
|
Ident.Map.update
|
||||||
(Mark.remove cdecl.Surface.Ast.enum_decl_case_name)
|
(Mark.remove cdecl.Surface.Ast.enum_decl_case_name)
|
||||||
(fun uids ->
|
(fun uids ->
|
||||||
match uids with
|
match uids with
|
||||||
@ -569,21 +567,21 @@ let process_scope_decl (ctxt : context) (decl : Surface.Ast.scope_decl) :
|
|||||||
let out_struct_fields =
|
let out_struct_fields =
|
||||||
let sco = ScopeName.Map.find scope_uid ctxt.scopes in
|
let sco = ScopeName.Map.find scope_uid ctxt.scopes in
|
||||||
let str = get_struct ctxt decl.scope_decl_name in
|
let str = get_struct ctxt decl.scope_decl_name in
|
||||||
IdentName.Map.fold
|
Ident.Map.fold
|
||||||
(fun id var svmap ->
|
(fun id var svmap ->
|
||||||
match var with
|
match var with
|
||||||
| SubScope _ -> svmap
|
| SubScope _ -> svmap
|
||||||
| ScopeVar v -> (
|
| ScopeVar v -> (
|
||||||
try
|
try
|
||||||
let field =
|
let field =
|
||||||
StructName.Map.find str (IdentName.Map.find id ctxt.field_idmap)
|
StructName.Map.find str (Ident.Map.find id ctxt.field_idmap)
|
||||||
in
|
in
|
||||||
ScopeVar.Map.add v field svmap
|
ScopeVar.Map.add v field svmap
|
||||||
with Not_found -> svmap))
|
with Not_found -> svmap))
|
||||||
sco.var_idmap ScopeVar.Map.empty
|
sco.var_idmap ScopeVar.Map.empty
|
||||||
in
|
in
|
||||||
let typedefs =
|
let typedefs =
|
||||||
IdentName.Map.update
|
Ident.Map.update
|
||||||
(Mark.remove decl.scope_decl_name)
|
(Mark.remove decl.scope_decl_name)
|
||||||
(function
|
(function
|
||||||
| Some (TScope (scope, { out_struct_name; _ })) ->
|
| Some (TScope (scope, { out_struct_name; _ })) ->
|
||||||
@ -617,13 +615,13 @@ let process_name_item (ctxt : context) (item : Surface.Ast.code_item Mark.pos) :
|
|||||||
Option.iter
|
Option.iter
|
||||||
(fun use ->
|
(fun use ->
|
||||||
raise_already_defined_error (typedef_info use) name pos "scope")
|
raise_already_defined_error (typedef_info use) name pos "scope")
|
||||||
(IdentName.Map.find_opt name ctxt.typedefs);
|
(Ident.Map.find_opt name ctxt.typedefs);
|
||||||
let scope_uid = ScopeName.fresh (name, pos) in
|
let scope_uid = ScopeName.fresh (name, pos) in
|
||||||
let out_struct_uid = StructName.fresh (name, pos) in
|
let out_struct_uid = StructName.fresh (name, pos) in
|
||||||
{
|
{
|
||||||
ctxt with
|
ctxt with
|
||||||
typedefs =
|
typedefs =
|
||||||
IdentName.Map.add name
|
Ident.Map.add name
|
||||||
(TScope
|
(TScope
|
||||||
( scope_uid,
|
( scope_uid,
|
||||||
{
|
{
|
||||||
@ -634,7 +632,7 @@ let process_name_item (ctxt : context) (item : Surface.Ast.code_item Mark.pos) :
|
|||||||
scopes =
|
scopes =
|
||||||
ScopeName.Map.add scope_uid
|
ScopeName.Map.add scope_uid
|
||||||
{
|
{
|
||||||
var_idmap = IdentName.Map.empty;
|
var_idmap = Ident.Map.empty;
|
||||||
scope_defs_contexts = Ast.ScopeDef.Map.empty;
|
scope_defs_contexts = Ast.ScopeDef.Map.empty;
|
||||||
sub_scopes = ScopeName.Set.empty;
|
sub_scopes = ScopeName.Set.empty;
|
||||||
}
|
}
|
||||||
@ -645,12 +643,12 @@ let process_name_item (ctxt : context) (item : Surface.Ast.code_item Mark.pos) :
|
|||||||
Option.iter
|
Option.iter
|
||||||
(fun use ->
|
(fun use ->
|
||||||
raise_already_defined_error (typedef_info use) name pos "struct")
|
raise_already_defined_error (typedef_info use) name pos "struct")
|
||||||
(IdentName.Map.find_opt name ctxt.typedefs);
|
(Ident.Map.find_opt name ctxt.typedefs);
|
||||||
let s_uid = StructName.fresh sdecl.struct_decl_name in
|
let s_uid = StructName.fresh sdecl.struct_decl_name in
|
||||||
{
|
{
|
||||||
ctxt with
|
ctxt with
|
||||||
typedefs =
|
typedefs =
|
||||||
IdentName.Map.add
|
Ident.Map.add
|
||||||
(Mark.remove sdecl.struct_decl_name)
|
(Mark.remove sdecl.struct_decl_name)
|
||||||
(TStruct s_uid) ctxt.typedefs;
|
(TStruct s_uid) ctxt.typedefs;
|
||||||
}
|
}
|
||||||
@ -659,12 +657,12 @@ let process_name_item (ctxt : context) (item : Surface.Ast.code_item Mark.pos) :
|
|||||||
Option.iter
|
Option.iter
|
||||||
(fun use ->
|
(fun use ->
|
||||||
raise_already_defined_error (typedef_info use) name pos "enum")
|
raise_already_defined_error (typedef_info use) name pos "enum")
|
||||||
(IdentName.Map.find_opt name ctxt.typedefs);
|
(Ident.Map.find_opt name ctxt.typedefs);
|
||||||
let e_uid = EnumName.fresh edecl.enum_decl_name in
|
let e_uid = EnumName.fresh edecl.enum_decl_name in
|
||||||
{
|
{
|
||||||
ctxt with
|
ctxt with
|
||||||
typedefs =
|
typedefs =
|
||||||
IdentName.Map.add
|
Ident.Map.add
|
||||||
(Mark.remove edecl.enum_decl_name)
|
(Mark.remove edecl.enum_decl_name)
|
||||||
(TEnum e_uid) ctxt.typedefs;
|
(TEnum e_uid) ctxt.typedefs;
|
||||||
}
|
}
|
||||||
@ -675,9 +673,9 @@ let process_name_item (ctxt : context) (item : Surface.Ast.code_item Mark.pos) :
|
|||||||
(fun use ->
|
(fun use ->
|
||||||
raise_already_defined_error (TopdefName.get_info use) name pos
|
raise_already_defined_error (TopdefName.get_info use) name pos
|
||||||
"toplevel definition")
|
"toplevel definition")
|
||||||
(IdentName.Map.find_opt name ctxt.topdefs);
|
(Ident.Map.find_opt name ctxt.topdefs);
|
||||||
let uid = TopdefName.fresh def.topdef_name in
|
let uid = TopdefName.fresh def.topdef_name in
|
||||||
{ ctxt with topdefs = IdentName.Map.add name uid ctxt.topdefs }
|
{ ctxt with topdefs = Ident.Map.add name uid ctxt.topdefs }
|
||||||
|
|
||||||
(** Process a code item that is a declaration *)
|
(** Process a code item that is a declaration *)
|
||||||
let process_decl_item (ctxt : context) (item : Surface.Ast.code_item Mark.pos) :
|
let process_decl_item (ctxt : context) (item : Surface.Ast.code_item Mark.pos) :
|
||||||
@ -731,8 +729,7 @@ let get_def_key
|
|||||||
| Some state -> (
|
| Some state -> (
|
||||||
try
|
try
|
||||||
Some
|
Some
|
||||||
(IdentName.Map.find (Mark.remove state)
|
(Ident.Map.find (Mark.remove state) var_sig.var_sig_states_idmap)
|
||||||
var_sig.var_sig_states_idmap)
|
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
Message.raise_multispanned_error
|
Message.raise_multispanned_error
|
||||||
[
|
[
|
||||||
@ -742,7 +739,7 @@ let get_def_key
|
|||||||
"This identifier is not a state declared for variable %a."
|
"This identifier is not a state declared for variable %a."
|
||||||
ScopeVar.format_t x_uid)
|
ScopeVar.format_t x_uid)
|
||||||
| None ->
|
| None ->
|
||||||
if not (IdentName.Map.is_empty var_sig.var_sig_states_idmap) then
|
if not (Ident.Map.is_empty var_sig.var_sig_states_idmap) then
|
||||||
Message.raise_multispanned_error
|
Message.raise_multispanned_error
|
||||||
[
|
[
|
||||||
None, Mark.get x;
|
None, Mark.get x;
|
||||||
@ -754,7 +751,7 @@ let get_def_key
|
|||||||
else None )
|
else None )
|
||||||
| [y; x] ->
|
| [y; x] ->
|
||||||
let (subscope_uid, subscope_real_uid) : SubScopeName.t * ScopeName.t =
|
let (subscope_uid, subscope_real_uid) : SubScopeName.t * ScopeName.t =
|
||||||
match IdentName.Map.find_opt (Mark.remove y) scope_ctxt.var_idmap with
|
match Ident.Map.find_opt (Mark.remove y) scope_ctxt.var_idmap with
|
||||||
| Some (SubScope (v, u)) -> v, u
|
| Some (SubScope (v, u)) -> v, u
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
Message.raise_spanned_error pos
|
Message.raise_spanned_error pos
|
||||||
@ -782,7 +779,7 @@ let update_def_key_ctx
|
|||||||
| None -> def_key_ctx
|
| None -> def_key_ctx
|
||||||
| Some label ->
|
| Some label ->
|
||||||
let new_label_idmap =
|
let new_label_idmap =
|
||||||
IdentName.Map.update (Mark.remove label)
|
Ident.Map.update (Mark.remove label)
|
||||||
(fun existing_label ->
|
(fun existing_label ->
|
||||||
match existing_label with
|
match existing_label with
|
||||||
| Some existing_label -> Some existing_label
|
| Some existing_label -> Some existing_label
|
||||||
@ -836,7 +833,7 @@ let empty_def_key_ctx =
|
|||||||
(* Here, this is the first time we encounter a definition for this
|
(* Here, this is the first time we encounter a definition for this
|
||||||
definition key *)
|
definition key *)
|
||||||
default_exception_rulename = None;
|
default_exception_rulename = None;
|
||||||
label_idmap = IdentName.Map.empty;
|
label_idmap = Ident.Map.empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
let process_definition
|
let process_definition
|
||||||
@ -885,7 +882,7 @@ let process_scope_use (ctxt : context) (suse : Surface.Ast.scope_use) : context
|
|||||||
=
|
=
|
||||||
let s_name =
|
let s_name =
|
||||||
match
|
match
|
||||||
IdentName.Map.find_opt
|
Ident.Map.find_opt
|
||||||
(Mark.remove suse.Surface.Ast.scope_use_name)
|
(Mark.remove suse.Surface.Ast.scope_use_name)
|
||||||
ctxt.typedefs
|
ctxt.typedefs
|
||||||
with
|
with
|
||||||
@ -913,15 +910,15 @@ let process_use_item (ctxt : context) (item : Surface.Ast.code_item Mark.pos) :
|
|||||||
let form_context (prgm : Surface.Ast.program) : context =
|
let form_context (prgm : Surface.Ast.program) : context =
|
||||||
let empty_ctxt =
|
let empty_ctxt =
|
||||||
{
|
{
|
||||||
local_var_idmap = IdentName.Map.empty;
|
local_var_idmap = Ident.Map.empty;
|
||||||
typedefs = IdentName.Map.empty;
|
typedefs = Ident.Map.empty;
|
||||||
scopes = ScopeName.Map.empty;
|
scopes = ScopeName.Map.empty;
|
||||||
topdefs = IdentName.Map.empty;
|
topdefs = Ident.Map.empty;
|
||||||
var_typs = ScopeVar.Map.empty;
|
var_typs = ScopeVar.Map.empty;
|
||||||
structs = StructName.Map.empty;
|
structs = StructName.Map.empty;
|
||||||
field_idmap = IdentName.Map.empty;
|
field_idmap = Ident.Map.empty;
|
||||||
enums = EnumName.Map.empty;
|
enums = EnumName.Map.empty;
|
||||||
constructor_idmap = IdentName.Map.empty;
|
constructor_idmap = Ident.Map.empty;
|
||||||
}
|
}
|
||||||
in
|
in
|
||||||
let ctxt =
|
let ctxt =
|
||||||
|
@ -27,7 +27,7 @@ type unique_rulename = Ambiguous of Pos.t list | Unique of RuleName.t Mark.pos
|
|||||||
|
|
||||||
type scope_def_context = {
|
type scope_def_context = {
|
||||||
default_exception_rulename : unique_rulename option;
|
default_exception_rulename : unique_rulename option;
|
||||||
label_idmap : LabelName.t IdentName.Map.t;
|
label_idmap : LabelName.t Ident.Map.t;
|
||||||
}
|
}
|
||||||
|
|
||||||
type scope_var_or_subscope =
|
type scope_var_or_subscope =
|
||||||
@ -35,7 +35,7 @@ type scope_var_or_subscope =
|
|||||||
| SubScope of SubScopeName.t * ScopeName.t
|
| SubScope of SubScopeName.t * ScopeName.t
|
||||||
|
|
||||||
type scope_context = {
|
type scope_context = {
|
||||||
var_idmap : scope_var_or_subscope IdentName.Map.t;
|
var_idmap : scope_var_or_subscope Ident.Map.t;
|
||||||
(** All variables, including scope variables and subscopes *)
|
(** All variables, including scope variables and subscopes *)
|
||||||
scope_defs_contexts : scope_def_context Ast.ScopeDef.Map.t;
|
scope_defs_contexts : scope_def_context Ast.ScopeDef.Map.t;
|
||||||
(** What is the default rule to refer to for unnamed exceptions, if any *)
|
(** What is the default rule to refer to for unnamed exceptions, if any *)
|
||||||
@ -56,7 +56,7 @@ type var_sig = {
|
|||||||
var_sig_parameters :
|
var_sig_parameters :
|
||||||
(Uid.MarkedString.info * Shared_ast.typ) list Mark.pos option;
|
(Uid.MarkedString.info * Shared_ast.typ) list Mark.pos option;
|
||||||
var_sig_io : Surface.Ast.scope_decl_context_io;
|
var_sig_io : Surface.Ast.scope_decl_context_io;
|
||||||
var_sig_states_idmap : StateName.t IdentName.Map.t;
|
var_sig_states_idmap : StateName.t Ident.Map.t;
|
||||||
var_sig_states_list : StateName.t list;
|
var_sig_states_list : StateName.t list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,19 +69,19 @@ type typedef =
|
|||||||
(** Implicitly defined output struct *)
|
(** Implicitly defined output struct *)
|
||||||
|
|
||||||
type context = {
|
type context = {
|
||||||
local_var_idmap : Ast.expr Var.t IdentName.Map.t;
|
local_var_idmap : Ast.expr Var.t Ident.Map.t;
|
||||||
(** Inside a definition, local variables can be introduced by functions
|
(** Inside a definition, local variables can be introduced by functions
|
||||||
arguments or pattern matching *)
|
arguments or pattern matching *)
|
||||||
typedefs : typedef IdentName.Map.t;
|
typedefs : typedef Ident.Map.t;
|
||||||
(** Gathers the names of the scopes, structs and enums *)
|
(** Gathers the names of the scopes, structs and enums *)
|
||||||
field_idmap : StructField.t StructName.Map.t IdentName.Map.t;
|
field_idmap : StructField.t StructName.Map.t Ident.Map.t;
|
||||||
(** The names of the struct fields. Names of fields can be shared between
|
(** The names of the struct fields. Names of fields can be shared between
|
||||||
different structs *)
|
different structs *)
|
||||||
constructor_idmap : EnumConstructor.t EnumName.Map.t IdentName.Map.t;
|
constructor_idmap : EnumConstructor.t EnumName.Map.t Ident.Map.t;
|
||||||
(** The names of the enum constructors. Constructor names can be shared
|
(** The names of the enum constructors. Constructor names can be shared
|
||||||
between different enums *)
|
between different enums *)
|
||||||
scopes : scope_context ScopeName.Map.t; (** For each scope, its context *)
|
scopes : scope_context ScopeName.Map.t; (** For each scope, its context *)
|
||||||
topdefs : TopdefName.t IdentName.Map.t; (** Global definitions *)
|
topdefs : TopdefName.t Ident.Map.t; (** Global definitions *)
|
||||||
structs : struct_context StructName.Map.t;
|
structs : struct_context StructName.Map.t;
|
||||||
(** For each struct, its context *)
|
(** For each struct, its context *)
|
||||||
enums : enum_context EnumName.Map.t; (** For each enum, its context *)
|
enums : enum_context EnumName.Map.t; (** For each enum, its context *)
|
||||||
@ -96,7 +96,7 @@ val raise_unsupported_feature : string -> Pos.t -> 'a
|
|||||||
(** Temporary function raising an error message saying that a feature is not
|
(** Temporary function raising an error message saying that a feature is not
|
||||||
supported yet *)
|
supported yet *)
|
||||||
|
|
||||||
val raise_unknown_identifier : string -> IdentName.t Mark.pos -> 'a
|
val raise_unknown_identifier : string -> Ident.t Mark.pos -> 'a
|
||||||
(** Function to call whenever an identifier used somewhere has not been declared
|
(** Function to call whenever an identifier used somewhere has not been declared
|
||||||
in the program previously *)
|
in the program previously *)
|
||||||
|
|
||||||
@ -106,14 +106,14 @@ val get_var_typ : context -> ScopeVar.t -> typ
|
|||||||
val is_var_cond : context -> ScopeVar.t -> bool
|
val is_var_cond : context -> ScopeVar.t -> bool
|
||||||
val get_var_io : context -> ScopeVar.t -> Surface.Ast.scope_decl_context_io
|
val get_var_io : context -> ScopeVar.t -> Surface.Ast.scope_decl_context_io
|
||||||
|
|
||||||
val get_var_uid : ScopeName.t -> context -> IdentName.t Mark.pos -> ScopeVar.t
|
val get_var_uid : ScopeName.t -> context -> Ident.t Mark.pos -> ScopeVar.t
|
||||||
(** Get the variable uid inside the scope given in argument *)
|
(** Get the variable uid inside the scope given in argument *)
|
||||||
|
|
||||||
val get_subscope_uid :
|
val get_subscope_uid :
|
||||||
ScopeName.t -> context -> IdentName.t Mark.pos -> SubScopeName.t
|
ScopeName.t -> context -> Ident.t Mark.pos -> SubScopeName.t
|
||||||
(** Get the subscope uid inside the scope given in argument *)
|
(** Get the subscope uid inside the scope given in argument *)
|
||||||
|
|
||||||
val is_subscope_uid : ScopeName.t -> context -> IdentName.t -> bool
|
val is_subscope_uid : ScopeName.t -> context -> Ident.t -> bool
|
||||||
(** [is_subscope_uid scope_uid ctxt y] returns true if [y] belongs to the
|
(** [is_subscope_uid scope_uid ctxt y] returns true if [y] belongs to the
|
||||||
subscopes of [scope_uid]. *)
|
subscopes of [scope_uid]. *)
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ val get_params :
|
|||||||
val is_def_cond : context -> Ast.ScopeDef.t -> bool
|
val is_def_cond : context -> Ast.ScopeDef.t -> bool
|
||||||
val is_type_cond : Surface.Ast.typ -> bool
|
val is_type_cond : Surface.Ast.typ -> bool
|
||||||
|
|
||||||
val add_def_local_var : context -> IdentName.t -> context * Ast.expr Var.t
|
val add_def_local_var : context -> Ident.t -> context * Ast.expr Var.t
|
||||||
(** Adds a binding to the context *)
|
(** Adds a binding to the context *)
|
||||||
|
|
||||||
val get_def_key :
|
val get_def_key :
|
||||||
@ -143,21 +143,20 @@ val get_def_key :
|
|||||||
Ast.ScopeDef.t
|
Ast.ScopeDef.t
|
||||||
(** Usage: [get_def_key var_name var_state scope_uid ctxt pos]*)
|
(** Usage: [get_def_key var_name var_state scope_uid ctxt pos]*)
|
||||||
|
|
||||||
val get_enum : context -> IdentName.t Mark.pos -> EnumName.t
|
val get_enum : context -> Ident.t Mark.pos -> EnumName.t
|
||||||
(** Find an enum definition from the typedefs, failing if there is none or it
|
(** Find an enum definition from the typedefs, failing if there is none or it
|
||||||
has a different kind *)
|
has a different kind *)
|
||||||
|
|
||||||
val get_struct : context -> IdentName.t Mark.pos -> StructName.t
|
val get_struct : context -> Ident.t Mark.pos -> StructName.t
|
||||||
(** Find a struct definition from the typedefs (possibly an implicit output
|
(** Find a struct definition from the typedefs (possibly an implicit output
|
||||||
struct from a scope), failing if there is none or it has a different kind *)
|
struct from a scope), failing if there is none or it has a different kind *)
|
||||||
|
|
||||||
val get_scope : context -> IdentName.t Mark.pos -> ScopeName.t
|
val get_scope : context -> Ident.t Mark.pos -> ScopeName.t
|
||||||
(** Find a scope definition from the typedefs, failing if there is none or it
|
(** Find a scope definition from the typedefs, failing if there is none or it
|
||||||
has a different kind *)
|
has a different kind *)
|
||||||
|
|
||||||
val process_type : context -> Surface.Ast.typ -> typ
|
val process_type : context -> Surface.Ast.typ -> typ
|
||||||
(** Convert a surface base type to an AST type *)
|
(** Convert a surface base type to an AST type *)
|
||||||
(* Note: should probably be moved to a different module *)
|
|
||||||
|
|
||||||
(** {1 API} *)
|
(** {1 API} *)
|
||||||
|
|
||||||
|
@ -21,9 +21,11 @@ open Catala_utils
|
|||||||
string representation. *)
|
string representation. *)
|
||||||
let extensions = [".catala_fr", "fr"; ".catala_en", "en"; ".catala_pl", "pl"]
|
let extensions = [".catala_fr", "fr"; ".catala_en", "en"; ".catala_pl", "pl"]
|
||||||
|
|
||||||
|
type backend = [ Cli.backend_option | `Plugin of Plugin.handler ]
|
||||||
|
|
||||||
let get_scope_uid
|
let get_scope_uid
|
||||||
(options : Cli.options)
|
(options : Cli.global_options)
|
||||||
(backend : Plugin.t Cli.backend_option)
|
(backend : backend)
|
||||||
(ctxt : Desugared.Name_resolution.context) =
|
(ctxt : Desugared.Name_resolution.context) =
|
||||||
match options.ex_scope, backend with
|
match options.ex_scope, backend with
|
||||||
| None, `Interpret ->
|
| None, `Interpret ->
|
||||||
@ -31,26 +33,26 @@ let get_scope_uid
|
|||||||
| None, _ ->
|
| None, _ ->
|
||||||
let _, scope =
|
let _, scope =
|
||||||
try
|
try
|
||||||
Shared_ast.IdentName.Map.filter_map
|
Shared_ast.Ident.Map.filter_map
|
||||||
(fun _ -> function
|
(fun _ -> function
|
||||||
| Desugared.Name_resolution.TScope (uid, _) -> Some uid
|
| Desugared.Name_resolution.TScope (uid, _) -> Some uid
|
||||||
| _ -> None)
|
| _ -> None)
|
||||||
ctxt.typedefs
|
ctxt.typedefs
|
||||||
|> Shared_ast.IdentName.Map.choose
|
|> Shared_ast.Ident.Map.choose
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
Message.raise_error "There isn't any scope inside the program."
|
Message.raise_error "There isn't any scope inside the program."
|
||||||
in
|
in
|
||||||
scope
|
scope
|
||||||
| Some name, _ -> (
|
| Some name, _ -> (
|
||||||
match Shared_ast.IdentName.Map.find_opt name ctxt.typedefs with
|
match Shared_ast.Ident.Map.find_opt name ctxt.typedefs with
|
||||||
| Some (Desugared.Name_resolution.TScope (uid, _)) -> uid
|
| Some (Desugared.Name_resolution.TScope (uid, _)) -> uid
|
||||||
| _ ->
|
| _ ->
|
||||||
Message.raise_error
|
Message.raise_error
|
||||||
"There is no scope @{<yellow>\"%s\"@} inside the program." name)
|
"There is no scope @{<yellow>\"%s\"@} inside the program." name)
|
||||||
|
|
||||||
let get_variable_uid
|
let get_variable_uid
|
||||||
(options : Cli.options)
|
(options : Cli.global_options)
|
||||||
(backend : Plugin.t Cli.backend_option)
|
(backend : backend)
|
||||||
(ctxt : Desugared.Name_resolution.context)
|
(ctxt : Desugared.Name_resolution.context)
|
||||||
(scope_uid : Shared_ast.ScopeName.t) =
|
(scope_uid : Shared_ast.ScopeName.t) =
|
||||||
match options.ex_variable, backend with
|
match options.ex_variable, backend with
|
||||||
@ -75,7 +77,7 @@ let get_variable_uid
|
|||||||
| Some groups -> Re.Group.get groups 1, Some (Re.Group.get groups 2)
|
| Some groups -> Re.Group.get groups 1, Some (Re.Group.get groups 2)
|
||||||
in
|
in
|
||||||
match
|
match
|
||||||
Shared_ast.IdentName.Map.find_opt first_part
|
Shared_ast.Ident.Map.find_opt first_part
|
||||||
(Shared_ast.ScopeName.Map.find scope_uid ctxt.scopes).var_idmap
|
(Shared_ast.ScopeName.Map.find scope_uid ctxt.scopes).var_idmap
|
||||||
with
|
with
|
||||||
| None ->
|
| None ->
|
||||||
@ -95,7 +97,7 @@ let get_variable_uid
|
|||||||
Shared_ast.ScopeName.format_t scope_uid
|
Shared_ast.ScopeName.format_t scope_uid
|
||||||
| Some second_part -> (
|
| Some second_part -> (
|
||||||
match
|
match
|
||||||
Shared_ast.IdentName.Map.find_opt second_part
|
Shared_ast.Ident.Map.find_opt second_part
|
||||||
(Shared_ast.ScopeName.Map.find subscope_name ctxt.scopes).var_idmap
|
(Shared_ast.ScopeName.Map.find subscope_name ctxt.scopes).var_idmap
|
||||||
with
|
with
|
||||||
| Some (Desugared.Name_resolution.ScopeVar v) ->
|
| Some (Desugared.Name_resolution.ScopeVar v) ->
|
||||||
@ -117,7 +119,7 @@ let get_variable_uid
|
|||||||
(fun second_part ->
|
(fun second_part ->
|
||||||
let var_sig = Shared_ast.ScopeVar.Map.find v ctxt.var_typs in
|
let var_sig = Shared_ast.ScopeVar.Map.find v ctxt.var_typs in
|
||||||
match
|
match
|
||||||
Shared_ast.IdentName.Map.find_opt second_part
|
Shared_ast.Ident.Map.find_opt second_part
|
||||||
var_sig.var_sig_states_idmap
|
var_sig.var_sig_states_idmap
|
||||||
with
|
with
|
||||||
| Some state -> state
|
| Some state -> state
|
||||||
@ -129,17 +131,14 @@ let get_variable_uid
|
|||||||
scope_uid)
|
scope_uid)
|
||||||
second_part )))
|
second_part )))
|
||||||
|
|
||||||
|
let modname_of_file f =
|
||||||
|
(* Fixme: make this more robust *)
|
||||||
|
String.capitalize_ascii Filename.(basename (remove_extension f))
|
||||||
|
|
||||||
(** Entry function for the executable. Returns a negative number in case of
|
(** Entry function for the executable. Returns a negative number in case of
|
||||||
error. Usage: [driver source_file options]*)
|
error. Usage: [driver source_file options]*)
|
||||||
let driver source_file (options : Cli.options) : int =
|
let driver backend source_file (options : Cli.global_options) : int =
|
||||||
try
|
try
|
||||||
List.iter
|
|
||||||
(fun d ->
|
|
||||||
match Sys.is_directory d with
|
|
||||||
| true -> Plugin.load_dir d
|
|
||||||
| false -> ()
|
|
||||||
| exception Sys_error _ -> ())
|
|
||||||
options.plugins_dirs;
|
|
||||||
Cli.set_option_globals options;
|
Cli.set_option_globals options;
|
||||||
if options.debug then Printexc.record_backtrace true;
|
if options.debug then Printexc.record_backtrace true;
|
||||||
Message.emit_debug "Reading files...";
|
Message.emit_debug "Reading files...";
|
||||||
@ -167,28 +166,23 @@ let driver source_file (options : Cli.options) : int =
|
|||||||
"The selected language (%s) is not supported by Catala" l
|
"The selected language (%s) is not supported by Catala" l
|
||||||
in
|
in
|
||||||
Cli.locale_lang := language;
|
Cli.locale_lang := language;
|
||||||
let backend = options.backend in
|
|
||||||
let backend =
|
|
||||||
match Cli.backend_option_of_string backend with
|
|
||||||
| #Cli.backend_option_builtin as backend -> backend
|
|
||||||
| `Plugin s -> (
|
|
||||||
try `Plugin (Plugin.find s)
|
|
||||||
with Not_found ->
|
|
||||||
Message.raise_error
|
|
||||||
"The selected backend (%s) is not supported by Catala, nor was a \
|
|
||||||
plugin by this name found under %a"
|
|
||||||
backend
|
|
||||||
(Format.pp_print_list
|
|
||||||
~pp_sep:(fun ppf () -> Format.fprintf ppf "@ or @ ")
|
|
||||||
(fun ppf dir ->
|
|
||||||
Format.pp_print_string ppf
|
|
||||||
(try Unix.readlink dir with _ -> dir)))
|
|
||||||
options.plugins_dirs)
|
|
||||||
in
|
|
||||||
let prgm =
|
let prgm =
|
||||||
Surface.Parser_driver.parse_top_level_file source_file language
|
Surface.Parser_driver.parse_top_level_file source_file language
|
||||||
in
|
in
|
||||||
let prgm = Surface.Fill_positions.fill_pos_with_legislative_info prgm in
|
let prgm = Surface.Fill_positions.fill_pos_with_legislative_info prgm in
|
||||||
|
let prgm =
|
||||||
|
List.fold_left
|
||||||
|
(fun prgm f ->
|
||||||
|
let lang =
|
||||||
|
Option.value ~default:language
|
||||||
|
@@ Option.bind
|
||||||
|
(List.assoc_opt (Filename.extension f) extensions)
|
||||||
|
(fun l -> List.assoc_opt l Cli.languages)
|
||||||
|
in
|
||||||
|
let modname = modname_of_file f in
|
||||||
|
Surface.Parser_driver.add_interface (FileName f) lang [modname] prgm)
|
||||||
|
prgm options.link_modules
|
||||||
|
in
|
||||||
let get_output ?ext =
|
let get_output ?ext =
|
||||||
File.get_out_channel ~source_file ~output_file:options.output_file ?ext
|
File.get_out_channel ~source_file ~output_file:options.output_file ?ext
|
||||||
in
|
in
|
||||||
@ -373,6 +367,14 @@ let driver source_file (options : Cli.options) : int =
|
|||||||
|
|
||||||
Verification.Solver.solve_vc prgm.decl_ctx vcs
|
Verification.Solver.solve_vc prgm.decl_ctx vcs
|
||||||
| `Interpret ->
|
| `Interpret ->
|
||||||
|
if options.link_modules <> [] then (
|
||||||
|
Message.emit_debug "Loading shared modules...";
|
||||||
|
List.iter
|
||||||
|
Dynlink.(
|
||||||
|
fun m ->
|
||||||
|
loadfile
|
||||||
|
(adapt_filename (Filename.remove_extension m ^ ".cmo")))
|
||||||
|
options.link_modules);
|
||||||
Message.emit_debug "Starting interpretation (dcalc)...";
|
Message.emit_debug "Starting interpretation (dcalc)...";
|
||||||
let results =
|
let results =
|
||||||
Shared_ast.Interpreter.interpret_program_dcalc prgm scope_uid
|
Shared_ast.Interpreter.interpret_program_dcalc prgm scope_uid
|
||||||
@ -490,7 +492,13 @@ let driver source_file (options : Cli.options) : int =
|
|||||||
Message.emit_debug "Compiling program into OCaml...";
|
Message.emit_debug "Compiling program into OCaml...";
|
||||||
Message.emit_debug "Writing to %s..."
|
Message.emit_debug "Writing to %s..."
|
||||||
(Option.value ~default:"stdout" output_file);
|
(Option.value ~default:"stdout" output_file);
|
||||||
Lcalc.To_ocaml.format_program fmt prgm type_ordering
|
let modname =
|
||||||
|
match source_file with
|
||||||
|
(* FIXME: WIP placeholder *)
|
||||||
|
| FileName n -> Some (modname_of_file n)
|
||||||
|
| _ -> None
|
||||||
|
in
|
||||||
|
Lcalc.To_ocaml.format_program fmt ?modname prgm type_ordering
|
||||||
| `Plugin (Plugin.Dcalc _) -> assert false
|
| `Plugin (Plugin.Dcalc _) -> assert false
|
||||||
| `Plugin (Plugin.Lcalc p) ->
|
| `Plugin (Plugin.Lcalc p) ->
|
||||||
let output_file, _ =
|
let output_file, _ =
|
||||||
@ -561,15 +569,65 @@ let driver source_file (options : Cli.options) : int =
|
|||||||
-1
|
-1
|
||||||
|
|
||||||
let main () =
|
let main () =
|
||||||
if
|
let argv = Array.copy Sys.argv in
|
||||||
Array.length Sys.argv >= 2
|
(* Our command names (first argument) are case-insensitive *)
|
||||||
&& String.lowercase_ascii Sys.argv.(1) = "pygmentize"
|
if Array.length argv >= 2 then argv.(1) <- String.lowercase_ascii argv.(1);
|
||||||
then Literate.Pygmentize.exec ();
|
(* Pygmentize is a specific exec subcommand that doesn't go through
|
||||||
|
cmdliner *)
|
||||||
|
if Array.length Sys.argv >= 2 && argv.(1) = "pygmentize" then
|
||||||
|
Literate.Pygmentize.exec ();
|
||||||
|
(* Peek to load plugins before the command-line is parsed proper *)
|
||||||
|
let plugins =
|
||||||
|
let plugins_dirs =
|
||||||
|
match
|
||||||
|
Cmdliner.Cmd.eval_peek_opts ~argv Cli.global_options ~version_opt:true
|
||||||
|
with
|
||||||
|
| Some opts, _ ->
|
||||||
|
Cli.set_option_globals opts;
|
||||||
|
(* Do this asap, for debug options, etc. *)
|
||||||
|
opts.Cli.plugins_dirs
|
||||||
|
| None, _ -> []
|
||||||
|
in
|
||||||
|
List.iter
|
||||||
|
(fun d ->
|
||||||
|
match Sys.is_directory d with
|
||||||
|
| true -> Plugin.load_dir d
|
||||||
|
| false -> ()
|
||||||
|
| exception Sys_error _ -> ())
|
||||||
|
plugins_dirs;
|
||||||
|
Plugin.list ()
|
||||||
|
in
|
||||||
let return_code =
|
let return_code =
|
||||||
Cmdliner.Cmd.eval'
|
Cmdliner.Cmd.eval' ~argv
|
||||||
(Cmdliner.Cmd.v Cli.info (Cli.catala_t (fun f -> driver (FileName f))))
|
(Cli.catala_t
|
||||||
|
(fun backend f -> driver backend (FileName f))
|
||||||
|
~extra:plugins)
|
||||||
in
|
in
|
||||||
exit return_code
|
exit return_code
|
||||||
|
|
||||||
(* Export module PluginAPI, hide parent module Plugin *)
|
(* Export module PluginAPI, hide parent module Plugin *)
|
||||||
module Plugin = Plugin.PluginAPI
|
module Plugin = struct
|
||||||
|
open Plugin
|
||||||
|
include PluginAPI
|
||||||
|
open Cmdliner
|
||||||
|
|
||||||
|
let register_cmd info plugin =
|
||||||
|
let term =
|
||||||
|
Term.(
|
||||||
|
const (fun file opts -> driver (`Plugin plugin) (FileName file) opts)
|
||||||
|
$ Cli.file
|
||||||
|
$ Cli.global_options)
|
||||||
|
in
|
||||||
|
register_generic info term
|
||||||
|
|
||||||
|
let info_name info = Cmd.name (Cmd.v info (Term.const ()))
|
||||||
|
|
||||||
|
let register_dcalc info ~extension apply =
|
||||||
|
register_cmd info (Dcalc { name = info_name info; extension; apply })
|
||||||
|
|
||||||
|
let register_lcalc info ~extension apply =
|
||||||
|
register_cmd info (Lcalc { name = info_name info; extension; apply })
|
||||||
|
|
||||||
|
let register_scalc info ~extension apply =
|
||||||
|
register_cmd info (Scalc { name = info_name info; extension; apply })
|
||||||
|
end
|
||||||
|
@ -16,11 +16,39 @@
|
|||||||
the License. *)
|
the License. *)
|
||||||
|
|
||||||
open Catala_utils
|
open Catala_utils
|
||||||
module Plugin = Plugin.PluginAPI
|
|
||||||
|
|
||||||
val driver : Pos.input_file -> Cli.options -> int
|
val driver :
|
||||||
|
[< Cli.backend_option | `Plugin of Plugin.handler ] ->
|
||||||
|
Pos.input_file ->
|
||||||
|
Cli.global_options ->
|
||||||
|
int
|
||||||
(** Entry function for the executable. Returns a negative number in case of
|
(** Entry function for the executable. Returns a negative number in case of
|
||||||
error. *)
|
error. *)
|
||||||
|
|
||||||
val main : unit -> unit
|
val main : unit -> unit
|
||||||
(** Main program entry point, including command-line parsing and return code *)
|
(** Main program entry point, including command-line parsing and return code *)
|
||||||
|
|
||||||
|
module Plugin : sig
|
||||||
|
include module type of Plugin.PluginAPI
|
||||||
|
open Cmdliner
|
||||||
|
|
||||||
|
val register_generic : Cmd.info -> Cmd.Exit.code Term.t -> unit
|
||||||
|
|
||||||
|
val register_dcalc :
|
||||||
|
Cmd.info ->
|
||||||
|
extension:string ->
|
||||||
|
Shared_ast.untyped Dcalc.Ast.program plugin_apply_fun_typ ->
|
||||||
|
unit
|
||||||
|
|
||||||
|
val register_lcalc :
|
||||||
|
Cmd.info ->
|
||||||
|
extension:string ->
|
||||||
|
Shared_ast.untyped Lcalc.Ast.program plugin_apply_fun_typ ->
|
||||||
|
unit
|
||||||
|
|
||||||
|
val register_scalc :
|
||||||
|
Cmd.info ->
|
||||||
|
extension:string ->
|
||||||
|
Scalc.Ast.program plugin_apply_fun_typ ->
|
||||||
|
unit
|
||||||
|
end
|
||||||
|
@ -38,7 +38,8 @@ let rec hoist_context_free_closures :
|
|||||||
let m = Mark.get e in
|
let m = Mark.get e in
|
||||||
match Mark.remove e with
|
match Mark.remove e with
|
||||||
| EStruct _ | EStructAccess _ | ETuple _ | ETupleAccess _ | EInj _ | EArray _
|
| EStruct _ | EStructAccess _ | ETuple _ | ETupleAccess _ | EInj _ | EArray _
|
||||||
| ELit _ | EAssert _ | EOp _ | EIfThenElse _ | ERaise _ | ECatch _ | EVar _ ->
|
| ELit _ | EAssert _ | EOp _ | EIfThenElse _ | ERaise _ | ECatch _ | EVar _
|
||||||
|
| EExternal _ ->
|
||||||
Expr.map_gather ~acc:[] ~join:( @ ) ~f:(hoist_context_free_closures ctx) e
|
Expr.map_gather ~acc:[] ~join:( @ ) ~f:(hoist_context_free_closures ctx) e
|
||||||
| EMatch { e; cases; name } ->
|
| EMatch { e; cases; name } ->
|
||||||
let collected_closures, new_e = (hoist_context_free_closures ctx) e in
|
let collected_closures, new_e = (hoist_context_free_closures ctx) e in
|
||||||
@ -98,7 +99,8 @@ let rec transform_closures_expr :
|
|||||||
let m = Mark.get e in
|
let m = Mark.get e in
|
||||||
match Mark.remove e with
|
match Mark.remove e with
|
||||||
| EStruct _ | EStructAccess _ | ETuple _ | ETupleAccess _ | EInj _ | EArray _
|
| EStruct _ | EStructAccess _ | ETuple _ | ETupleAccess _ | EInj _ | EArray _
|
||||||
| ELit _ | EAssert _ | EOp _ | EIfThenElse _ | ERaise _ | ECatch _ ->
|
| ELit _ | EExternal _ | EAssert _ | EOp _ | EIfThenElse _ | ERaise _
|
||||||
|
| ECatch _ ->
|
||||||
Expr.map_gather ~acc:Var.Set.empty ~join:Var.Set.union
|
Expr.map_gather ~acc:Var.Set.empty ~join:Var.Set.union
|
||||||
~f:(transform_closures_expr ctx)
|
~f:(transform_closures_expr ctx)
|
||||||
e
|
e
|
||||||
|
@ -74,9 +74,9 @@ and translate_expr (ctx : 'm ctx) (e : 'm D.expr) : 'm A.expr boxed =
|
|||||||
| EDefault { excepts; just; cons } ->
|
| EDefault { excepts; just; cons } ->
|
||||||
translate_default ctx excepts just cons (Mark.get e)
|
translate_default ctx excepts just cons (Mark.get e)
|
||||||
| EOp { op; tys } -> Expr.eop (Operator.translate op) tys m
|
| EOp { op; tys } -> Expr.eop (Operator.translate op) tys m
|
||||||
| ( ELit _ | EApp _ | EArray _ | EVar _ | EAbs _ | EIfThenElse _ | ETuple _
|
| ( ELit _ | EApp _ | EArray _ | EVar _ | EExternal _ | EAbs _ | EIfThenElse _
|
||||||
| ETupleAccess _ | EInj _ | EAssert _ | EStruct _ | EStructAccess _
|
| ETuple _ | ETupleAccess _ | EInj _ | EAssert _ | EStruct _
|
||||||
| EMatch _ ) as e ->
|
| EStructAccess _ | EMatch _ ) as e ->
|
||||||
Expr.map ~f:(translate_expr ctx) (Mark.add m e)
|
Expr.map ~f:(translate_expr ctx) (Mark.add m e)
|
||||||
| _ -> .
|
| _ -> .
|
||||||
|
|
||||||
|
@ -107,6 +107,7 @@ let rec trans (ctx : typed ctx) (e : typed D.expr) : (lcalc, typed) boxed_gexpr
|
|||||||
if (Var.Map.find x ctx.ctx_vars).info_pure then
|
if (Var.Map.find x ctx.ctx_vars).info_pure then
|
||||||
Ast.OptionMonad.return (Expr.evar (trans_var ctx x) m) ~mark
|
Ast.OptionMonad.return (Expr.evar (trans_var ctx x) m) ~mark
|
||||||
else Expr.evar (trans_var ctx x) m
|
else Expr.evar (trans_var ctx x) m
|
||||||
|
| EExternal eref -> Expr.eexternal eref mark
|
||||||
| EApp { f = EVar v, _; args = [(ELit LUnit, _)] } ->
|
| EApp { f = EVar v, _; args = [(ELit LUnit, _)] } ->
|
||||||
(* Invariant: as users cannot write thunks, it can only come from prior
|
(* Invariant: as users cannot write thunks, it can only come from prior
|
||||||
compilation passes. Hence we can safely remove those. *)
|
compilation passes. Hence we can safely remove those. *)
|
||||||
|
@ -87,6 +87,8 @@ let avoid_keywords (s : string) : string =
|
|||||||
| "while" | "with" | "Stdlib" | "Runtime" | "Oper" ->
|
| "while" | "with" | "Stdlib" | "Runtime" | "Oper" ->
|
||||||
s ^ "_user"
|
s ^ "_user"
|
||||||
| _ -> s
|
| _ -> s
|
||||||
|
(* Fixme: this could cause clashes if the user program contains both e.g. [new]
|
||||||
|
and [new_user] *)
|
||||||
|
|
||||||
let format_struct_name (fmt : Format.formatter) (v : StructName.t) : unit =
|
let format_struct_name (fmt : Format.formatter) (v : StructName.t) : unit =
|
||||||
Format.asprintf "%a" StructName.format_t v
|
Format.asprintf "%a" StructName.format_t v
|
||||||
@ -230,6 +232,7 @@ let rec format_expr (ctx : decl_ctx) (fmt : Format.formatter) (e : 'm expr) :
|
|||||||
in
|
in
|
||||||
match Mark.remove e with
|
match Mark.remove e with
|
||||||
| EVar v -> Format.fprintf fmt "%a" format_var v
|
| EVar v -> Format.fprintf fmt "%a" format_var v
|
||||||
|
| EExternal qid -> Qident.format fmt qid
|
||||||
| ETuple es ->
|
| ETuple es ->
|
||||||
Format.fprintf fmt "@[<hov 2>(%a)@]"
|
Format.fprintf fmt "@[<hov 2>(%a)@]"
|
||||||
(Format.pp_print_list
|
(Format.pp_print_list
|
||||||
@ -520,14 +523,15 @@ let rec format_scope_body_expr
|
|||||||
let format_code_items
|
let format_code_items
|
||||||
(ctx : decl_ctx)
|
(ctx : decl_ctx)
|
||||||
(fmt : Format.formatter)
|
(fmt : Format.formatter)
|
||||||
(code_items : 'm Ast.expr code_item_list) : unit =
|
(code_items : 'm Ast.expr code_item_list) : 'm Ast.expr Var.t String.Map.t =
|
||||||
Scope.fold_left
|
Scope.fold_left
|
||||||
~f:(fun () item var ->
|
~f:(fun bnd item var ->
|
||||||
match item with
|
match item with
|
||||||
| Topdef (_, typ, e) ->
|
| Topdef (name, typ, e) ->
|
||||||
Format.fprintf fmt "@\n@\n@[<hov 2>let %a : %a =@\n%a@]" format_var var
|
Format.fprintf fmt "@\n@\n@[<hov 2>let %a : %a =@\n%a@]" format_var var
|
||||||
format_typ typ (format_expr ctx) e
|
format_typ typ (format_expr ctx) e;
|
||||||
| ScopeDef (_, body) ->
|
String.Map.add (Mark.remove (TopdefName.get_info name)) var bnd
|
||||||
|
| ScopeDef (name, body) ->
|
||||||
let scope_input_var, scope_body_expr =
|
let scope_input_var, scope_body_expr =
|
||||||
Bindlib.unbind body.scope_body_expr
|
Bindlib.unbind body.scope_body_expr
|
||||||
in
|
in
|
||||||
@ -536,22 +540,54 @@ let format_code_items
|
|||||||
(`Sname body.scope_body_input_struct) format_to_module_name
|
(`Sname body.scope_body_input_struct) format_to_module_name
|
||||||
(`Sname body.scope_body_output_struct)
|
(`Sname body.scope_body_output_struct)
|
||||||
(format_scope_body_expr ctx)
|
(format_scope_body_expr ctx)
|
||||||
scope_body_expr)
|
scope_body_expr;
|
||||||
~init:() code_items
|
String.Map.add (Mark.remove (ScopeName.get_info name)) var bnd)
|
||||||
|
~init:String.Map.empty code_items
|
||||||
|
|
||||||
|
let format_module_registration
|
||||||
|
fmt
|
||||||
|
(bnd : 'm Ast.expr Var.t String.Map.t)
|
||||||
|
modname =
|
||||||
|
Format.pp_open_vbox fmt 2;
|
||||||
|
Format.pp_print_string fmt "let () =";
|
||||||
|
Format.pp_print_space fmt ();
|
||||||
|
Format.pp_open_hvbox fmt 2;
|
||||||
|
Format.fprintf fmt "Runtime_ocaml.Runtime.register_module %S" modname;
|
||||||
|
Format.pp_print_space fmt ();
|
||||||
|
Format.pp_open_vbox fmt 2;
|
||||||
|
Format.pp_print_string fmt "[ ";
|
||||||
|
Format.pp_print_seq
|
||||||
|
~pp_sep:(fun fmt () ->
|
||||||
|
Format.pp_print_char fmt ';';
|
||||||
|
Format.pp_print_cut fmt ())
|
||||||
|
(fun fmt (id, var) ->
|
||||||
|
Format.fprintf fmt "@[<hov 2>%S,@ Obj.repr %a@]" id format_var var)
|
||||||
|
fmt (String.Map.to_seq bnd);
|
||||||
|
Format.pp_close_box fmt ();
|
||||||
|
Format.pp_print_char fmt ' ';
|
||||||
|
Format.pp_print_string fmt "]";
|
||||||
|
Format.pp_print_space fmt ();
|
||||||
|
Format.pp_print_string fmt "\"todo-module-hash\"";
|
||||||
|
Format.pp_close_box fmt ();
|
||||||
|
Format.pp_close_box fmt ()
|
||||||
|
|
||||||
|
let header =
|
||||||
|
{ocaml|
|
||||||
|
(** This file has been generated by the Catala compiler, do not edit! *)
|
||||||
|
|
||||||
|
open Runtime_ocaml.Runtime
|
||||||
|
|
||||||
|
[@@@ocaml.warning "-4-26-27-32-41-42"]
|
||||||
|
|
||||||
|
|ocaml}
|
||||||
|
|
||||||
let format_program
|
let format_program
|
||||||
(fmt : Format.formatter)
|
(fmt : Format.formatter)
|
||||||
|
?modname
|
||||||
(p : 'm Ast.program)
|
(p : 'm Ast.program)
|
||||||
(type_ordering : Scopelang.Dependency.TVertex.t list) : unit =
|
(type_ordering : Scopelang.Dependency.TVertex.t list) : unit =
|
||||||
Format.fprintf fmt
|
Format.pp_print_string fmt header;
|
||||||
"(** This file has been generated by the Catala compiler, do not edit! *)@\n\
|
format_ctx type_ordering fmt p.decl_ctx;
|
||||||
@\n\
|
let bnd = format_code_items p.decl_ctx fmt p.code_items in
|
||||||
open Runtime_ocaml.Runtime@\n\
|
Format.pp_print_newline fmt ();
|
||||||
@\n\
|
Option.iter (format_module_registration fmt bnd) modname
|
||||||
[@@@@@@ocaml.warning \"-4-26-27-32-41-42\"]@\n\
|
|
||||||
@\n\
|
|
||||||
%a%a@\n\
|
|
||||||
@?"
|
|
||||||
(format_ctx type_ordering) p.decl_ctx
|
|
||||||
(format_code_items p.decl_ctx)
|
|
||||||
p.code_items
|
|
||||||
|
@ -40,7 +40,9 @@ val format_var : Format.formatter -> 'm Var.t -> unit
|
|||||||
|
|
||||||
val format_program :
|
val format_program :
|
||||||
Format.formatter ->
|
Format.formatter ->
|
||||||
|
?modname:string ->
|
||||||
'm Ast.program ->
|
'm Ast.program ->
|
||||||
Scopelang.Dependency.TVertex.t list ->
|
Scopelang.Dependency.TVertex.t list ->
|
||||||
unit
|
unit
|
||||||
(** Usage [format_program fmt p type_dependencies_ordering] *)
|
(** Usage [format_program fmt p type_dependencies_ordering]. If [modname] is
|
||||||
|
set, registers the module for dynamic loading *)
|
||||||
|
@ -16,45 +16,43 @@
|
|||||||
|
|
||||||
open Catala_utils
|
open Catala_utils
|
||||||
|
|
||||||
type 'ast plugin_apply_fun_typ =
|
type t = Cmdliner.Cmd.Exit.code Cmdliner.Cmd.t
|
||||||
source_file:Pos.input_file ->
|
|
||||||
output_file:string option ->
|
|
||||||
scope:Shared_ast.ScopeName.t option ->
|
|
||||||
'ast ->
|
|
||||||
Scopelang.Dependency.TVertex.t list ->
|
|
||||||
unit
|
|
||||||
|
|
||||||
type 'ast gen = {
|
|
||||||
name : string;
|
|
||||||
extension : string;
|
|
||||||
apply : 'ast plugin_apply_fun_typ;
|
|
||||||
}
|
|
||||||
|
|
||||||
type t =
|
|
||||||
| Dcalc of Shared_ast.untyped Dcalc.Ast.program gen
|
|
||||||
| Lcalc of Shared_ast.untyped Lcalc.Ast.program gen
|
|
||||||
| Scalc of Scalc.Ast.program gen
|
|
||||||
|
|
||||||
let name = function
|
|
||||||
| Dcalc { name; _ } | Lcalc { name; _ } | Scalc { name; _ } -> name
|
|
||||||
|
|
||||||
let backend_plugins : (string, t) Hashtbl.t = Hashtbl.create 17
|
let backend_plugins : (string, t) Hashtbl.t = Hashtbl.create 17
|
||||||
|
|
||||||
let register t =
|
let register t =
|
||||||
Hashtbl.replace backend_plugins (String.lowercase_ascii (name t)) t
|
Hashtbl.replace backend_plugins
|
||||||
|
(String.lowercase_ascii (Cmdliner.Cmd.name t))
|
||||||
|
t
|
||||||
|
|
||||||
|
let list () = Hashtbl.to_seq_values backend_plugins |> List.of_seq
|
||||||
|
|
||||||
module PluginAPI = struct
|
module PluginAPI = struct
|
||||||
let register_dcalc ~name ~extension apply =
|
open Cmdliner
|
||||||
register (Dcalc { name; extension; apply })
|
|
||||||
|
|
||||||
let register_lcalc ~name ~extension apply =
|
let register_generic info term = register (Cmd.v info term)
|
||||||
register (Lcalc { name; extension; apply })
|
|
||||||
|
|
||||||
let register_scalc ~name ~extension apply =
|
(* For plugins relying on the standard [Driver] *)
|
||||||
register (Scalc { name; extension; apply })
|
|
||||||
|
type 'ast plugin_apply_fun_typ =
|
||||||
|
source_file:Pos.input_file ->
|
||||||
|
output_file:string option ->
|
||||||
|
scope:Shared_ast.ScopeName.t option ->
|
||||||
|
'ast ->
|
||||||
|
Scopelang.Dependency.TVertex.t list ->
|
||||||
|
unit
|
||||||
end
|
end
|
||||||
|
|
||||||
let find name = Hashtbl.find backend_plugins (String.lowercase_ascii name)
|
type 'ast gen = {
|
||||||
|
name : string;
|
||||||
|
extension : string;
|
||||||
|
apply : 'ast PluginAPI.plugin_apply_fun_typ;
|
||||||
|
}
|
||||||
|
|
||||||
|
type handler =
|
||||||
|
| Dcalc of Shared_ast.untyped Dcalc.Ast.program gen
|
||||||
|
| Lcalc of Shared_ast.untyped Lcalc.Ast.program gen
|
||||||
|
| Scalc of Scalc.Ast.program gen
|
||||||
|
|
||||||
let load_file f =
|
let load_file f =
|
||||||
try
|
try
|
||||||
|
@ -14,31 +14,37 @@
|
|||||||
License for the specific language governing permissions and limitations under
|
License for the specific language governing permissions and limitations under
|
||||||
the License. *)
|
the License. *)
|
||||||
|
|
||||||
(** {2 catala-facing API} *)
|
|
||||||
|
|
||||||
open Catala_utils
|
open Catala_utils
|
||||||
|
|
||||||
type 'ast plugin_apply_fun_typ =
|
type t = Cmdliner.Cmd.Exit.code Cmdliner.Cmd.t
|
||||||
source_file:Pos.input_file ->
|
(** Plugins just provide an additional top-level command *)
|
||||||
output_file:string option ->
|
|
||||||
scope:Shared_ast.ScopeName.t option ->
|
|
||||||
'ast ->
|
|
||||||
Scopelang.Dependency.TVertex.t list ->
|
|
||||||
unit
|
|
||||||
|
|
||||||
type 'ast gen = {
|
(** {2 plugin-facing API} *)
|
||||||
name : string;
|
|
||||||
extension : string;
|
|
||||||
apply : 'ast plugin_apply_fun_typ;
|
|
||||||
}
|
|
||||||
|
|
||||||
type t =
|
module PluginAPI : sig
|
||||||
| Dcalc of Shared_ast.untyped Dcalc.Ast.program gen
|
open Cmdliner
|
||||||
| Lcalc of Shared_ast.untyped Lcalc.Ast.program gen
|
|
||||||
| Scalc of Scalc.Ast.program gen
|
|
||||||
|
|
||||||
val find : string -> t
|
val register_generic : Cmd.info -> Cmd.Exit.code Term.t -> unit
|
||||||
(** Find a registered plugin *)
|
(** Entry point for the registration of a generic catala subcommand *)
|
||||||
|
|
||||||
|
(** The following are used by [Driver.Plugin] to provide a higher-level
|
||||||
|
interface, registering plugins that rely on the [Driver.driver] function. *)
|
||||||
|
|
||||||
|
type 'ast plugin_apply_fun_typ =
|
||||||
|
source_file:Pos.input_file ->
|
||||||
|
output_file:string option ->
|
||||||
|
scope:Shared_ast.ScopeName.t option ->
|
||||||
|
'ast ->
|
||||||
|
Scopelang.Dependency.TVertex.t list ->
|
||||||
|
unit
|
||||||
|
end
|
||||||
|
|
||||||
|
val register : t -> unit
|
||||||
|
|
||||||
|
(** {2 catala-facing API} *)
|
||||||
|
|
||||||
|
val list : unit -> t list
|
||||||
|
(** List registered plugins *)
|
||||||
|
|
||||||
val load_file : string -> unit
|
val load_file : string -> unit
|
||||||
(** Load the given plugin (cmo/cma or cmxs file) *)
|
(** Load the given plugin (cmo/cma or cmxs file) *)
|
||||||
@ -46,26 +52,15 @@ val load_file : string -> unit
|
|||||||
val load_dir : string -> unit
|
val load_dir : string -> unit
|
||||||
(** Load all plugins found in the given directory *)
|
(** Load all plugins found in the given directory *)
|
||||||
|
|
||||||
(** {2 plugin-facing API} *)
|
(** {3 Facilities for plugins using the standard driver} *)
|
||||||
|
|
||||||
module PluginAPI : sig
|
type 'ast gen = {
|
||||||
val register_dcalc :
|
name : string;
|
||||||
name:string ->
|
extension : string;
|
||||||
extension:string ->
|
apply : 'ast PluginAPI.plugin_apply_fun_typ;
|
||||||
Shared_ast.untyped Dcalc.Ast.program plugin_apply_fun_typ ->
|
}
|
||||||
unit
|
|
||||||
|
|
||||||
val register_lcalc :
|
type handler =
|
||||||
name:string ->
|
| Dcalc of Shared_ast.untyped Dcalc.Ast.program gen
|
||||||
extension:string ->
|
| Lcalc of Shared_ast.untyped Lcalc.Ast.program gen
|
||||||
Shared_ast.untyped Lcalc.Ast.program plugin_apply_fun_typ ->
|
| Scalc of Scalc.Ast.program gen
|
||||||
unit
|
|
||||||
|
|
||||||
val register_scalc :
|
|
||||||
name:string ->
|
|
||||||
extension:string ->
|
|
||||||
Scalc.Ast.program plugin_apply_fun_typ ->
|
|
||||||
unit
|
|
||||||
end
|
|
||||||
|
|
||||||
val register : t -> unit
|
|
||||||
|
@ -15,9 +15,6 @@
|
|||||||
License for the specific language governing permissions and limitations under
|
License for the specific language governing permissions and limitations under
|
||||||
the License. *)
|
the License. *)
|
||||||
|
|
||||||
(** Catala plugin for generating web APIs. It generates OCaml code before the
|
|
||||||
the associated [js_of_ocaml] wrapper. *)
|
|
||||||
|
|
||||||
open Catala_utils
|
open Catala_utils
|
||||||
open Shared_ast
|
open Shared_ast
|
||||||
open Lcalc
|
open Lcalc
|
||||||
@ -28,6 +25,12 @@ module D = Dcalc.Ast
|
|||||||
let name = "api_web"
|
let name = "api_web"
|
||||||
let extension = ".ml"
|
let extension = ".ml"
|
||||||
|
|
||||||
|
let info =
|
||||||
|
Cmdliner.Cmd.info name
|
||||||
|
~doc:
|
||||||
|
"Catala plugin for generating web APIs. It generates OCaml code before \
|
||||||
|
the associated [js_of_ocaml] wrapper."
|
||||||
|
|
||||||
(** Contains all format functions used to generating the [js_of_ocaml] wrapper
|
(** Contains all format functions used to generating the [js_of_ocaml] wrapper
|
||||||
of the corresponding Catala program. *)
|
of the corresponding Catala program. *)
|
||||||
module To_jsoo = struct
|
module To_jsoo = struct
|
||||||
@ -468,4 +471,4 @@ let apply
|
|||||||
(Option.value ~default:"stdout" jsoo_output_file);
|
(Option.value ~default:"stdout" jsoo_output_file);
|
||||||
To_jsoo.format_program fmt module_name prgm type_ordering)
|
To_jsoo.format_program fmt module_name prgm type_ordering)
|
||||||
|
|
||||||
let () = Driver.Plugin.register_lcalc ~name ~extension apply
|
let () = Driver.Plugin.register_lcalc info ~extension apply
|
||||||
|
@ -14,12 +14,15 @@
|
|||||||
License for the specific language governing permissions and limitations under
|
License for the specific language governing permissions and limitations under
|
||||||
the License. *)
|
the License. *)
|
||||||
|
|
||||||
(** Catala plugin for generating {{:https://json-schema.org} JSON schemas} used
|
|
||||||
to build forms for the Catala website. *)
|
|
||||||
|
|
||||||
let name = "json_schema"
|
let name = "json_schema"
|
||||||
let extension = "_schema.json"
|
let extension = "_schema.json"
|
||||||
|
|
||||||
|
let info =
|
||||||
|
Cmdliner.Cmd.info name
|
||||||
|
~doc:
|
||||||
|
"Catala plugin for generating {{:https://json-schema.org} JSON schemas} \
|
||||||
|
used to build forms for the Catala website."
|
||||||
|
|
||||||
open Catala_utils
|
open Catala_utils
|
||||||
open Shared_ast
|
open Shared_ast
|
||||||
open Lcalc.To_ocaml
|
open Lcalc.To_ocaml
|
||||||
@ -232,4 +235,4 @@ let apply
|
|||||||
| None ->
|
| None ->
|
||||||
Message.raise_error "A scope must be specified for the plugin: %s" name
|
Message.raise_error "A scope must be specified for the plugin: %s" name
|
||||||
|
|
||||||
let () = Driver.Plugin.register_lcalc ~name ~extension apply
|
let () = Driver.Plugin.register_lcalc info ~extension apply
|
||||||
|
@ -17,6 +17,10 @@
|
|||||||
open Catala_utils
|
open Catala_utils
|
||||||
open Shared_ast
|
open Shared_ast
|
||||||
|
|
||||||
|
let name = "lazy"
|
||||||
|
let extension = ".out" (* unused *)
|
||||||
|
let info = Cmdliner.Cmd.info name ~doc:"Experimental lazy evaluation (plugin)"
|
||||||
|
|
||||||
(* -- Definition of the lazy interpreter -- *)
|
(* -- Definition of the lazy interpreter -- *)
|
||||||
|
|
||||||
let log fmt = Format.ifprintf Format.err_formatter (fmt ^^ "@\n")
|
let log fmt = Format.ifprintf Format.err_formatter (fmt ^^ "@\n")
|
||||||
@ -209,6 +213,7 @@ let rec lazy_eval :
|
|||||||
| (ELit (LBool false), _), _ ->
|
| (ELit (LBool false), _), _ ->
|
||||||
error e "Assert failure (%a)" Expr.format e
|
error e "Assert failure (%a)" Expr.format e
|
||||||
| _ -> error e "Invalid assertion condition %a" Expr.format e)
|
| _ -> error e "Invalid assertion condition %a" Expr.format e)
|
||||||
|
| EExternal _, _ -> assert false (* todo *)
|
||||||
| _ -> .
|
| _ -> .
|
||||||
|
|
||||||
let interpret_program (prg : ('dcalc, 'm) gexpr program) (scope : ScopeName.t) :
|
let interpret_program (prg : ('dcalc, 'm) gexpr program) (scope : ScopeName.t) :
|
||||||
@ -251,9 +256,6 @@ let interpret_program (prg : ('dcalc, 'm) gexpr program) (scope : ScopeName.t) :
|
|||||||
|
|
||||||
(* -- Plugin registration -- *)
|
(* -- Plugin registration -- *)
|
||||||
|
|
||||||
let name = "lazy"
|
|
||||||
let extension = ".out" (* unused *)
|
|
||||||
|
|
||||||
let apply ~source_file ~output_file ~scope prg _type_ordering =
|
let apply ~source_file ~output_file ~scope prg _type_ordering =
|
||||||
let scope =
|
let scope =
|
||||||
match scope with
|
match scope with
|
||||||
@ -268,4 +270,4 @@ let apply ~source_file ~output_file ~scope prg _type_ordering =
|
|||||||
let result_expr, _env = interpret_program prg scope in
|
let result_expr, _env = interpret_program prg scope in
|
||||||
Expr.format fmt result_expr
|
Expr.format fmt result_expr
|
||||||
|
|
||||||
let () = Driver.Plugin.register_dcalc ~name ~extension apply
|
let () = Driver.Plugin.register_dcalc info ~extension apply
|
||||||
|
@ -25,10 +25,16 @@ open Catala_utils
|
|||||||
let name = "python-plugin"
|
let name = "python-plugin"
|
||||||
let extension = ".py"
|
let extension = ".py"
|
||||||
|
|
||||||
|
let info =
|
||||||
|
Cmdliner.Cmd.info name
|
||||||
|
~doc:
|
||||||
|
"This plugin is for demonstration purposes and should be equivalent to \
|
||||||
|
using the built-in Python backend"
|
||||||
|
|
||||||
let apply ~source_file ~output_file ~scope prgm type_ordering =
|
let apply ~source_file ~output_file ~scope prgm type_ordering =
|
||||||
ignore source_file;
|
ignore source_file;
|
||||||
ignore scope;
|
ignore scope;
|
||||||
File.with_formatter_of_opt_file output_file
|
File.with_formatter_of_opt_file output_file
|
||||||
@@ fun fmt -> Scalc.To_python.format_program fmt prgm type_ordering
|
@@ fun fmt -> Scalc.To_python.format_program fmt prgm type_ordering
|
||||||
|
|
||||||
let () = Driver.Plugin.register_scalc ~name ~extension apply
|
let () = Driver.Plugin.register_scalc info ~extension apply
|
||||||
|
@ -46,6 +46,17 @@ let rec translate_expr (ctx : ctx) (e : Desugared.Ast.expr) :
|
|||||||
untyped Ast.expr boxed =
|
untyped Ast.expr boxed =
|
||||||
let m = Mark.get e in
|
let m = Mark.get e in
|
||||||
match Mark.remove e with
|
match Mark.remove e with
|
||||||
|
| EVar v -> Expr.evar (Var.Map.find v ctx.var_mapping) m
|
||||||
|
| EAbs { binder; tys } ->
|
||||||
|
let vars, body = Bindlib.unmbind binder in
|
||||||
|
let new_vars = Array.map (fun var -> Var.make (Bindlib.name_of var)) vars in
|
||||||
|
let ctx =
|
||||||
|
List.fold_left2
|
||||||
|
(fun ctx var new_var ->
|
||||||
|
{ ctx with var_mapping = Var.Map.add var new_var ctx.var_mapping })
|
||||||
|
ctx (Array.to_list vars) (Array.to_list new_vars)
|
||||||
|
in
|
||||||
|
Expr.eabs (Expr.bind new_vars (translate_expr ctx body)) tys m
|
||||||
| ELocation (SubScopeVar (s_name, ss_name, s_var)) ->
|
| ELocation (SubScopeVar (s_name, ss_name, s_var)) ->
|
||||||
(* When referring to a subscope variable in an expression, we are referring
|
(* When referring to a subscope variable in an expression, we are referring
|
||||||
to the output, hence we take the last state. *)
|
to the output, hence we take the last state. *)
|
||||||
@ -70,9 +81,6 @@ let rec translate_expr (ctx : ctx) (e : Desugared.Ast.expr) :
|
|||||||
| States states -> Mark.copy s_var (List.assoc state states)))
|
| States states -> Mark.copy s_var (List.assoc state states)))
|
||||||
m
|
m
|
||||||
| ELocation (ToplevelVar v) -> Expr.elocation (ToplevelVar v) m
|
| ELocation (ToplevelVar v) -> Expr.elocation (ToplevelVar v) m
|
||||||
| EVar v -> Expr.evar (Var.Map.find v ctx.var_mapping) m
|
|
||||||
| EStruct { name; fields } ->
|
|
||||||
Expr.estruct name (StructField.Map.map (translate_expr ctx) fields) m
|
|
||||||
| EDStructAccess { name_opt = None; _ } ->
|
| EDStructAccess { name_opt = None; _ } ->
|
||||||
(* Note: this could only happen if disambiguation was disabled. If we want
|
(* Note: this could only happen if disambiguation was disabled. If we want
|
||||||
to support it, we should still allow this case when the field has only
|
to support it, we should still allow this case when the field has only
|
||||||
@ -84,7 +92,7 @@ let rec translate_expr (ctx : ctx) (e : Desugared.Ast.expr) :
|
|||||||
let field =
|
let field =
|
||||||
try
|
try
|
||||||
StructName.Map.find name
|
StructName.Map.find name
|
||||||
(IdentName.Map.find field ctx.decl_ctx.ctx_struct_fields)
|
(Ident.Map.find field ctx.decl_ctx.ctx_struct_fields)
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
(* Should not happen after disambiguation *)
|
(* Should not happen after disambiguation *)
|
||||||
Message.raise_spanned_error (Expr.mark_pos m)
|
Message.raise_spanned_error (Expr.mark_pos m)
|
||||||
@ -93,14 +101,6 @@ let rec translate_expr (ctx : ctx) (e : Desugared.Ast.expr) :
|
|||||||
field StructName.format_t name
|
field StructName.format_t name
|
||||||
in
|
in
|
||||||
Expr.estructaccess e' field name m
|
Expr.estructaccess e' field name m
|
||||||
| ETuple es -> Expr.etuple (List.map (translate_expr ctx) es) m
|
|
||||||
| ETupleAccess { e; index; size } ->
|
|
||||||
Expr.etupleaccess (translate_expr ctx e) index size m
|
|
||||||
| EInj { e; cons; name } -> Expr.einj (translate_expr ctx e) cons name m
|
|
||||||
| EMatch { e; name; cases } ->
|
|
||||||
Expr.ematch (translate_expr ctx e) name
|
|
||||||
(EnumConstructor.Map.map (translate_expr ctx) cases)
|
|
||||||
m
|
|
||||||
| EScopeCall { scope; args } ->
|
| EScopeCall { scope; args } ->
|
||||||
Expr.escopecall scope
|
Expr.escopecall scope
|
||||||
(ScopeVar.Map.fold
|
(ScopeVar.Map.fold
|
||||||
@ -117,20 +117,6 @@ let rec translate_expr (ctx : ctx) (e : Desugared.Ast.expr) :
|
|||||||
ScopeVar.Map.add v' (translate_expr ctx e) args')
|
ScopeVar.Map.add v' (translate_expr ctx e) args')
|
||||||
args ScopeVar.Map.empty)
|
args ScopeVar.Map.empty)
|
||||||
m
|
m
|
||||||
| ELit
|
|
||||||
((LBool _ | LInt _ | LRat _ | LMoney _ | LUnit | LDate _ | LDuration _) as
|
|
||||||
l) ->
|
|
||||||
Expr.elit l m
|
|
||||||
| EAbs { binder; tys } ->
|
|
||||||
let vars, body = Bindlib.unmbind binder in
|
|
||||||
let new_vars = Array.map (fun var -> Var.make (Bindlib.name_of var)) vars in
|
|
||||||
let ctx =
|
|
||||||
List.fold_left2
|
|
||||||
(fun ctx var new_var ->
|
|
||||||
{ ctx with var_mapping = Var.Map.add var new_var ctx.var_mapping })
|
|
||||||
ctx (Array.to_list vars) (Array.to_list new_vars)
|
|
||||||
in
|
|
||||||
Expr.eabs (Expr.bind new_vars (translate_expr ctx body)) tys m
|
|
||||||
| EApp { f = EOp { op; tys }, m1; args } ->
|
| EApp { f = EOp { op; tys }, m1; args } ->
|
||||||
let args = List.map (translate_expr ctx) args in
|
let args = List.map (translate_expr ctx) args in
|
||||||
Operator.kind_dispatch op
|
Operator.kind_dispatch op
|
||||||
@ -144,19 +130,10 @@ let rec translate_expr (ctx : ctx) (e : Desugared.Ast.expr) :
|
|||||||
| op, `Reversed ->
|
| op, `Reversed ->
|
||||||
Expr.eapp (Expr.eop op (List.rev tys) m1) (List.rev args) m)
|
Expr.eapp (Expr.eop op (List.rev tys) m1) (List.rev args) m)
|
||||||
| EOp _ -> assert false (* Only allowed within [EApp] *)
|
| EOp _ -> assert false (* Only allowed within [EApp] *)
|
||||||
| EApp { f; args } ->
|
| ( EStruct _ | ETuple _ | ETupleAccess _ | EInj _ | EMatch _ | ELit _
|
||||||
Expr.eapp (translate_expr ctx f) (List.map (translate_expr ctx) args) m
|
| EApp _ | EDefault _ | EIfThenElse _ | EArray _ | EEmptyError
|
||||||
| EDefault { excepts; just; cons } ->
|
| EErrorOnEmpty _ | EExternal _ ) as e ->
|
||||||
Expr.edefault
|
Expr.map ~f:(translate_expr ctx) (e, m)
|
||||||
(List.map (translate_expr ctx) excepts)
|
|
||||||
(translate_expr ctx just) (translate_expr ctx cons) m
|
|
||||||
| EIfThenElse { cond; etrue; efalse } ->
|
|
||||||
Expr.eifthenelse (translate_expr ctx cond) (translate_expr ctx etrue)
|
|
||||||
(translate_expr ctx efalse)
|
|
||||||
m
|
|
||||||
| EArray args -> Expr.earray (List.map (translate_expr ctx) args) m
|
|
||||||
| EEmptyError -> Expr.eemptyerror m
|
|
||||||
| EErrorOnEmpty e1 -> Expr.eerroronempty (translate_expr ctx e1) m
|
|
||||||
|
|
||||||
(** {1 Rule tree construction} *)
|
(** {1 Rule tree construction} *)
|
||||||
|
|
||||||
@ -825,18 +802,24 @@ let translate_program
|
|||||||
{ out_str with out_struct_fields })
|
{ out_str with out_struct_fields })
|
||||||
pgrm.Desugared.Ast.program_ctx.ctx_scopes
|
pgrm.Desugared.Ast.program_ctx.ctx_scopes
|
||||||
in
|
in
|
||||||
let new_program_scopes =
|
let program_scopes =
|
||||||
ScopeName.Map.fold
|
ScopeName.Map.fold
|
||||||
(fun scope_name scope new_program_scopes ->
|
(fun scope_name scope new_program_scopes ->
|
||||||
let new_program_scope = translate_scope ctx scope exc_graphs in
|
let new_program_scope = translate_scope ctx scope exc_graphs in
|
||||||
ScopeName.Map.add scope_name new_program_scope new_program_scopes)
|
ScopeName.Map.add scope_name new_program_scope new_program_scopes)
|
||||||
pgrm.program_scopes ScopeName.Map.empty
|
pgrm.program_scopes ScopeName.Map.empty
|
||||||
in
|
in
|
||||||
|
let program_topdefs =
|
||||||
|
TopdefName.Map.mapi
|
||||||
|
(fun id -> function
|
||||||
|
| Some e, ty -> Expr.unbox (translate_expr ctx e), ty
|
||||||
|
| None, (_, pos) ->
|
||||||
|
Message.raise_spanned_error pos "No definition found for %a"
|
||||||
|
TopdefName.format_t id)
|
||||||
|
pgrm.program_topdefs
|
||||||
|
in
|
||||||
{
|
{
|
||||||
Ast.program_topdefs =
|
Ast.program_topdefs;
|
||||||
TopdefName.Map.map
|
program_scopes;
|
||||||
(fun (e, ty) -> Expr.unbox (translate_expr ctx e), ty)
|
|
||||||
pgrm.program_topdefs;
|
|
||||||
Ast.program_scopes = new_program_scopes;
|
|
||||||
program_ctx = { pgrm.program_ctx with ctx_scopes };
|
program_ctx = { pgrm.program_ctx with ctx_scopes };
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ module LabelName = Uid.Gen ()
|
|||||||
|
|
||||||
(** Used for unresolved structs/maps in desugared *)
|
(** Used for unresolved structs/maps in desugared *)
|
||||||
|
|
||||||
module IdentName = String
|
module Ident = String
|
||||||
|
|
||||||
(** Only used by desugared/scopelang *)
|
(** Only used by desugared/scopelang *)
|
||||||
|
|
||||||
@ -56,8 +56,13 @@ module StateName = Uid.Gen ()
|
|||||||
(** These types allow to select the features present in any given expression
|
(** These types allow to select the features present in any given expression
|
||||||
type *)
|
type *)
|
||||||
|
|
||||||
type yes = private Yes
|
type yes = Yes
|
||||||
type no = |
|
|
||||||
|
type no =
|
||||||
|
| No
|
||||||
|
(** Phantom types used in the definitions below. We don't make them
|
||||||
|
abstract, because the typer needs to know that their intersection is
|
||||||
|
empty. *)
|
||||||
|
|
||||||
type desugared =
|
type desugared =
|
||||||
< monomorphic : yes
|
< monomorphic : yes
|
||||||
@ -71,7 +76,8 @@ type desugared =
|
|||||||
; explicitScopes : yes
|
; explicitScopes : yes
|
||||||
; assertions : no
|
; assertions : no
|
||||||
; defaultTerms : yes
|
; defaultTerms : yes
|
||||||
; exceptions : no >
|
; exceptions : no
|
||||||
|
; custom : no >
|
||||||
|
|
||||||
type scopelang =
|
type scopelang =
|
||||||
< monomorphic : yes
|
< monomorphic : yes
|
||||||
@ -85,7 +91,8 @@ type scopelang =
|
|||||||
; explicitScopes : yes
|
; explicitScopes : yes
|
||||||
; assertions : no
|
; assertions : no
|
||||||
; defaultTerms : yes
|
; defaultTerms : yes
|
||||||
; exceptions : no >
|
; exceptions : no
|
||||||
|
; custom : no >
|
||||||
|
|
||||||
type dcalc =
|
type dcalc =
|
||||||
< monomorphic : yes
|
< monomorphic : yes
|
||||||
@ -99,7 +106,8 @@ type dcalc =
|
|||||||
; explicitScopes : no
|
; explicitScopes : no
|
||||||
; assertions : yes
|
; assertions : yes
|
||||||
; defaultTerms : yes
|
; defaultTerms : yes
|
||||||
; exceptions : no >
|
; exceptions : no
|
||||||
|
; custom : no >
|
||||||
|
|
||||||
type lcalc =
|
type lcalc =
|
||||||
< monomorphic : yes
|
< monomorphic : yes
|
||||||
@ -113,7 +121,8 @@ type lcalc =
|
|||||||
; explicitScopes : no
|
; explicitScopes : no
|
||||||
; assertions : yes
|
; assertions : yes
|
||||||
; defaultTerms : no
|
; defaultTerms : no
|
||||||
; exceptions : yes >
|
; exceptions : yes
|
||||||
|
; custom : no >
|
||||||
|
|
||||||
type 'a any = < .. > as 'a
|
type 'a any = < .. > as 'a
|
||||||
(** ['a any] is 'a, but adds the constraint that it should be restricted to
|
(** ['a any] is 'a, but adds the constraint that it should be restricted to
|
||||||
@ -131,7 +140,8 @@ type ('a, 'b) dcalc_lcalc =
|
|||||||
; explicitScopes : no
|
; explicitScopes : no
|
||||||
; assertions : yes
|
; assertions : yes
|
||||||
; defaultTerms : 'a
|
; defaultTerms : 'a
|
||||||
; exceptions : 'b >
|
; exceptions : 'b
|
||||||
|
; custom : no >
|
||||||
(** This type regroups Dcalc and Lcalc ASTs. *)
|
(** This type regroups Dcalc and Lcalc ASTs. *)
|
||||||
|
|
||||||
(** {2 Types} *)
|
(** {2 Types} *)
|
||||||
@ -379,6 +389,7 @@ and ('a, 'b, 'm) base_gexpr =
|
|||||||
-> ('a, (< .. > as 'b), 'm) base_gexpr
|
-> ('a, (< .. > as 'b), 'm) base_gexpr
|
||||||
| EArray : ('a, 'm) gexpr list -> ('a, < .. >, 'm) base_gexpr
|
| EArray : ('a, 'm) gexpr list -> ('a, < .. >, 'm) base_gexpr
|
||||||
| EVar : ('a, 'm) naked_gexpr Bindlib.var -> ('a, _, 'm) base_gexpr
|
| EVar : ('a, 'm) naked_gexpr Bindlib.var -> ('a, _, 'm) base_gexpr
|
||||||
|
| EExternal : Qident.t -> ('a, < .. >, 't) base_gexpr
|
||||||
| EAbs : {
|
| EAbs : {
|
||||||
binder : (('a, 'a, 'm) base_gexpr, ('a, 'm) gexpr) Bindlib.mbinder;
|
binder : (('a, 'a, 'm) base_gexpr, ('a, 'm) gexpr) Bindlib.mbinder;
|
||||||
tys : typ list;
|
tys : typ list;
|
||||||
@ -424,7 +435,7 @@ and ('a, 'b, 'm) base_gexpr =
|
|||||||
| EDStructAccess : {
|
| EDStructAccess : {
|
||||||
name_opt : StructName.t option;
|
name_opt : StructName.t option;
|
||||||
e : ('a, 'm) gexpr;
|
e : ('a, 'm) gexpr;
|
||||||
field : IdentName.t;
|
field : Ident.t;
|
||||||
}
|
}
|
||||||
-> ('a, < syntacticNames : yes ; .. >, 'm) base_gexpr
|
-> ('a, < syntacticNames : yes ; .. >, 'm) base_gexpr
|
||||||
(** [desugared] has ambiguous struct fields *)
|
(** [desugared] has ambiguous struct fields *)
|
||||||
@ -456,6 +467,16 @@ and ('a, 'b, 'm) base_gexpr =
|
|||||||
handler : ('a, 'm) gexpr;
|
handler : ('a, 'm) gexpr;
|
||||||
}
|
}
|
||||||
-> ('a, < exceptions : yes ; .. >, 'm) base_gexpr
|
-> ('a, < exceptions : yes ; .. >, 'm) base_gexpr
|
||||||
|
(* Only used during evaluation *)
|
||||||
|
| ECustom : {
|
||||||
|
obj : Obj.t;
|
||||||
|
targs : typ list;
|
||||||
|
tret : typ;
|
||||||
|
}
|
||||||
|
-> ('a, < custom : yes ; .. >, 't) base_gexpr
|
||||||
|
(** A function of the given type, as a runtime OCaml object. The specified
|
||||||
|
types for arguments and result must be the Catala types corresponding
|
||||||
|
to the runtime types of the function. *)
|
||||||
|
|
||||||
(** Useful for errors and printing, for example *)
|
(** Useful for errors and printing, for example *)
|
||||||
type any_expr = AnyExpr : ('a, _) gexpr -> any_expr
|
type any_expr = AnyExpr : ('a, _) gexpr -> any_expr
|
||||||
@ -549,9 +570,10 @@ type scope_out_struct = {
|
|||||||
type decl_ctx = {
|
type decl_ctx = {
|
||||||
ctx_enums : enum_ctx;
|
ctx_enums : enum_ctx;
|
||||||
ctx_structs : struct_ctx;
|
ctx_structs : struct_ctx;
|
||||||
ctx_struct_fields : StructField.t StructName.Map.t IdentName.Map.t;
|
ctx_struct_fields : StructField.t StructName.Map.t Ident.Map.t;
|
||||||
(** needed for disambiguation (desugared -> scope) *)
|
(** needed for disambiguation (desugared -> scope) *)
|
||||||
ctx_scopes : scope_out_struct ScopeName.Map.t;
|
ctx_scopes : scope_out_struct ScopeName.Map.t;
|
||||||
|
ctx_modules : typ Qident.Map.t;
|
||||||
}
|
}
|
||||||
|
|
||||||
type 'e program = { decl_ctx : decl_ctx; code_items : 'e code_item_list }
|
type 'e program = { decl_ctx : decl_ctx; code_items : 'e code_item_list }
|
||||||
|
@ -109,6 +109,7 @@ let subst binder vars =
|
|||||||
Bindlib.msubst binder (Array.of_list (List.map Mark.remove vars))
|
Bindlib.msubst binder (Array.of_list (List.map Mark.remove vars))
|
||||||
|
|
||||||
let evar v mark = Mark.add mark (Bindlib.box_var v)
|
let evar v mark = Mark.add mark (Bindlib.box_var v)
|
||||||
|
let eexternal eref mark = Mark.add mark (Bindlib.box (EExternal eref))
|
||||||
let etuple args = Box.appn args @@ fun args -> ETuple args
|
let etuple args = Box.appn args @@ fun args -> ETuple args
|
||||||
|
|
||||||
let etupleaccess e index size =
|
let etupleaccess e index size =
|
||||||
@ -140,6 +141,9 @@ let eraise e1 = Box.app0 @@ ERaise e1
|
|||||||
let ecatch body exn handler =
|
let ecatch body exn handler =
|
||||||
Box.app2 body handler @@ fun body handler -> ECatch { body; exn; handler }
|
Box.app2 body handler @@ fun body handler -> ECatch { body; exn; handler }
|
||||||
|
|
||||||
|
let ecustom obj targs tret mark =
|
||||||
|
Mark.add mark (Bindlib.box (ECustom { obj; targs; tret }))
|
||||||
|
|
||||||
let elocation loc = Box.app0 @@ ELocation loc
|
let elocation loc = Box.app0 @@ ELocation loc
|
||||||
|
|
||||||
let estruct name (fields : ('a, 't) boxed_gexpr StructField.Map.t) mark =
|
let estruct name (fields : ('a, 't) boxed_gexpr StructField.Map.t) mark =
|
||||||
@ -268,6 +272,7 @@ let map
|
|||||||
| EOp { op; tys } -> eop op tys m
|
| EOp { op; tys } -> eop op tys m
|
||||||
| EArray args -> earray (List.map f args) m
|
| EArray args -> earray (List.map f args) m
|
||||||
| EVar v -> evar (Var.translate v) m
|
| EVar v -> evar (Var.translate v) m
|
||||||
|
| EExternal eref -> eexternal eref m
|
||||||
| EAbs { binder; tys } ->
|
| EAbs { binder; tys } ->
|
||||||
let vars, body = Bindlib.unmbind binder in
|
let vars, body = Bindlib.unmbind binder in
|
||||||
let body = f body in
|
let body = f body in
|
||||||
@ -298,6 +303,7 @@ let map
|
|||||||
| EScopeCall { scope; args } ->
|
| EScopeCall { scope; args } ->
|
||||||
let fields = ScopeVar.Map.map f args in
|
let fields = ScopeVar.Map.map f args in
|
||||||
escopecall scope fields m
|
escopecall scope fields m
|
||||||
|
| ECustom { obj; targs; tret } -> ecustom obj targs tret m
|
||||||
|
|
||||||
let rec map_top_down ~f e = map ~f:(map_top_down ~f) (f e)
|
let rec map_top_down ~f e = map ~f:(map_top_down ~f) (f e)
|
||||||
let map_marks ~f e = map_top_down ~f:(Mark.map_mark f) e
|
let map_marks ~f e = map_top_down ~f:(Mark.map_mark f) e
|
||||||
@ -310,7 +316,9 @@ let shallow_fold
|
|||||||
(acc : 'acc) : 'acc =
|
(acc : 'acc) : 'acc =
|
||||||
let lfold x acc = List.fold_left (fun acc x -> f x acc) acc x in
|
let lfold x acc = List.fold_left (fun acc x -> f x acc) acc x in
|
||||||
match Mark.remove e with
|
match Mark.remove e with
|
||||||
| ELit _ | EOp _ | EVar _ | ERaise _ | ELocation _ | EEmptyError -> acc
|
| ELit _ | EOp _ | EVar _ | EExternal _ | ERaise _ | ELocation _ | EEmptyError
|
||||||
|
->
|
||||||
|
acc
|
||||||
| EApp { f = e; args } -> acc |> f e |> lfold args
|
| EApp { f = e; args } -> acc |> f e |> lfold args
|
||||||
| EArray args -> acc |> lfold args
|
| EArray args -> acc |> lfold args
|
||||||
| EAbs { binder; tys = _ } ->
|
| EAbs { binder; tys = _ } ->
|
||||||
@ -330,6 +338,7 @@ let shallow_fold
|
|||||||
| EMatch { e; cases; _ } ->
|
| EMatch { e; cases; _ } ->
|
||||||
acc |> f e |> EnumConstructor.Map.fold (fun _ -> f) cases
|
acc |> f e |> EnumConstructor.Map.fold (fun _ -> f) cases
|
||||||
| EScopeCall { args; _ } -> acc |> ScopeVar.Map.fold (fun _ -> f) args
|
| EScopeCall { args; _ } -> acc |> ScopeVar.Map.fold (fun _ -> f) args
|
||||||
|
| ECustom _ -> acc
|
||||||
|
|
||||||
(* Like [map], but also allows to gather a result bottom-up. *)
|
(* Like [map], but also allows to gather a result bottom-up. *)
|
||||||
let map_gather
|
let map_gather
|
||||||
@ -360,6 +369,7 @@ let map_gather
|
|||||||
let acc, args = lfoldmap args in
|
let acc, args = lfoldmap args in
|
||||||
acc, earray args m
|
acc, earray args m
|
||||||
| EVar v -> acc, evar (Var.translate v) m
|
| EVar v -> acc, evar (Var.translate v) m
|
||||||
|
| EExternal eref -> acc, eexternal eref m
|
||||||
| EAbs { binder; tys } ->
|
| EAbs { binder; tys } ->
|
||||||
let vars, body = Bindlib.unmbind binder in
|
let vars, body = Bindlib.unmbind binder in
|
||||||
let acc, body = f body in
|
let acc, body = f body in
|
||||||
@ -433,6 +443,7 @@ let map_gather
|
|||||||
args (acc, ScopeVar.Map.empty)
|
args (acc, ScopeVar.Map.empty)
|
||||||
in
|
in
|
||||||
acc, escopecall scope args m
|
acc, escopecall scope args m
|
||||||
|
| ECustom { obj; targs; tret } -> acc, ecustom obj targs tret m
|
||||||
|
|
||||||
(* - *)
|
(* - *)
|
||||||
|
|
||||||
@ -441,6 +452,11 @@ let rec rebox (e : ('a any, 't) gexpr) = map ~f:rebox e
|
|||||||
|
|
||||||
let box e = Mark.map Bindlib.box e
|
let box e = Mark.map Bindlib.box e
|
||||||
let unbox (e, m) = Bindlib.unbox e, m
|
let unbox (e, m) = Bindlib.unbox e, m
|
||||||
|
|
||||||
|
let unbox_closed e =
|
||||||
|
Box.assert_closed (fst e);
|
||||||
|
unbox e
|
||||||
|
|
||||||
let untype e = map_marks ~f:(fun m -> Untyped { pos = mark_pos m }) e
|
let untype e = map_marks ~f:(fun m -> Untyped { pos = mark_pos m }) e
|
||||||
|
|
||||||
(* Tests *)
|
(* Tests *)
|
||||||
@ -541,6 +557,7 @@ and equal : type a. (a, 't) gexpr -> (a, 't) gexpr -> bool =
|
|||||||
fun e1 e2 ->
|
fun e1 e2 ->
|
||||||
match Mark.remove e1, Mark.remove e2 with
|
match Mark.remove e1, Mark.remove e2 with
|
||||||
| EVar v1, EVar v2 -> Bindlib.eq_vars v1 v2
|
| EVar v1, EVar v2 -> Bindlib.eq_vars v1 v2
|
||||||
|
| EExternal eref1, EExternal eref2 -> Qident.equal eref1 eref2
|
||||||
| ETuple es1, ETuple es2 -> equal_list es1 es2
|
| ETuple es1, ETuple es2 -> equal_list es1 es2
|
||||||
| ( ETupleAccess { e = e1; index = id1; size = s1 },
|
| ( ETupleAccess { e = e1; index = id1; size = s1 },
|
||||||
ETupleAccess { e = e2; index = id2; size = s2 } ) ->
|
ETupleAccess { e = e2; index = id2; size = s2 } ) ->
|
||||||
@ -573,7 +590,7 @@ and equal : type a. (a, 't) gexpr -> (a, 't) gexpr -> bool =
|
|||||||
StructName.equal s1 s2 && StructField.Map.equal equal fields1 fields2
|
StructName.equal s1 s2 && StructField.Map.equal equal fields1 fields2
|
||||||
| ( EDStructAccess { e = e1; field = f1; name_opt = s1 },
|
| ( EDStructAccess { e = e1; field = f1; name_opt = s1 },
|
||||||
EDStructAccess { e = e2; field = f2; name_opt = s2 } ) ->
|
EDStructAccess { e = e2; field = f2; name_opt = s2 } ) ->
|
||||||
Option.equal StructName.equal s1 s2 && IdentName.equal f1 f2 && equal e1 e2
|
Option.equal StructName.equal s1 s2 && Ident.equal f1 f2 && equal e1 e2
|
||||||
| ( EStructAccess { e = e1; field = f1; name = s1 },
|
| ( EStructAccess { e = e1; field = f1; name = s1 },
|
||||||
EStructAccess { e = e2; field = f2; name = s2 } ) ->
|
EStructAccess { e = e2; field = f2; name = s2 } ) ->
|
||||||
StructName.equal s1 s2 && StructField.equal f1 f2 && equal e1 e2
|
StructName.equal s1 s2 && StructField.equal f1 f2 && equal e1 e2
|
||||||
@ -588,10 +605,14 @@ and equal : type a. (a, 't) gexpr -> (a, 't) gexpr -> bool =
|
|||||||
| ( EScopeCall { scope = s1; args = fields1 },
|
| ( EScopeCall { scope = s1; args = fields1 },
|
||||||
EScopeCall { scope = s2; args = fields2 } ) ->
|
EScopeCall { scope = s2; args = fields2 } ) ->
|
||||||
ScopeName.equal s1 s2 && ScopeVar.Map.equal equal fields1 fields2
|
ScopeName.equal s1 s2 && ScopeVar.Map.equal equal fields1 fields2
|
||||||
| ( ( EVar _ | ETuple _ | ETupleAccess _ | EArray _ | ELit _ | EAbs _ | EApp _
|
| ( ECustom { obj = obj1; targs = targs1; tret = tret1 },
|
||||||
| EAssert _ | EOp _ | EDefault _ | EIfThenElse _ | EEmptyError
|
ECustom { obj = obj2; targs = targs2; tret = tret2 } ) ->
|
||||||
| EErrorOnEmpty _ | ERaise _ | ECatch _ | ELocation _ | EStruct _
|
Type.equal_list targs1 targs2 && Type.equal tret1 tret2 && obj1 == obj2
|
||||||
| EDStructAccess _ | EStructAccess _ | EInj _ | EMatch _ | EScopeCall _ ),
|
| ( ( EVar _ | EExternal _ | ETuple _ | ETupleAccess _ | EArray _ | ELit _
|
||||||
|
| EAbs _ | EApp _ | EAssert _ | EOp _ | EDefault _ | EIfThenElse _
|
||||||
|
| EEmptyError | EErrorOnEmpty _ | ERaise _ | ECatch _ | ELocation _
|
||||||
|
| EStruct _ | EDStructAccess _ | EStructAccess _ | EInj _ | EMatch _
|
||||||
|
| EScopeCall _ | ECustom _ ),
|
||||||
_ ) ->
|
_ ) ->
|
||||||
false
|
false
|
||||||
|
|
||||||
@ -614,6 +635,8 @@ let rec compare : type a. (a, _) gexpr -> (a, _) gexpr -> int =
|
|||||||
List.compare compare a1 a2
|
List.compare compare a1 a2
|
||||||
| EVar v1, EVar v2 ->
|
| EVar v1, EVar v2 ->
|
||||||
Bindlib.compare_vars v1 v2
|
Bindlib.compare_vars v1 v2
|
||||||
|
| EExternal eref1, EExternal eref2 ->
|
||||||
|
Qident.compare eref1 eref2
|
||||||
| EAbs {binder=binder1; tys=typs1},
|
| EAbs {binder=binder1; tys=typs1},
|
||||||
EAbs {binder=binder2; tys=typs2} ->
|
EAbs {binder=binder2; tys=typs2} ->
|
||||||
List.compare Type.compare typs1 typs2 @@< fun () ->
|
List.compare Type.compare typs1 typs2 @@< fun () ->
|
||||||
@ -633,7 +656,7 @@ let rec compare : type a. (a, _) gexpr -> (a, _) gexpr -> int =
|
|||||||
| EDStructAccess {e=e1; field=field_name1; name_opt=struct_name1},
|
| EDStructAccess {e=e1; field=field_name1; name_opt=struct_name1},
|
||||||
EDStructAccess {e=e2; field=field_name2; name_opt=struct_name2} ->
|
EDStructAccess {e=e2; field=field_name2; name_opt=struct_name2} ->
|
||||||
compare e1 e2 @@< fun () ->
|
compare e1 e2 @@< fun () ->
|
||||||
IdentName.compare field_name1 field_name2 @@< fun () ->
|
Ident.compare field_name1 field_name2 @@< fun () ->
|
||||||
Option.compare StructName.compare struct_name1 struct_name2
|
Option.compare StructName.compare struct_name1 struct_name2
|
||||||
| EStructAccess {e=e1; field=field_name1; name=struct_name1},
|
| EStructAccess {e=e1; field=field_name1; name=struct_name1},
|
||||||
EStructAccess {e=e2; field=field_name2; name=struct_name2} ->
|
EStructAccess {e=e2; field=field_name2; name=struct_name2} ->
|
||||||
@ -678,11 +701,15 @@ let rec compare : type a. (a, _) gexpr -> (a, _) gexpr -> int =
|
|||||||
compare_except ex1 ex2 @@< fun () ->
|
compare_except ex1 ex2 @@< fun () ->
|
||||||
compare etry1 etry2 @@< fun () ->
|
compare etry1 etry2 @@< fun () ->
|
||||||
compare ewith1 ewith2
|
compare ewith1 ewith2
|
||||||
|
| ECustom _, _ | _, ECustom _ ->
|
||||||
|
(* fixme: ideally this would be forbidden by typing *)
|
||||||
|
invalid_arg "Custom block comparison"
|
||||||
| ELit _, _ -> -1 | _, ELit _ -> 1
|
| ELit _, _ -> -1 | _, ELit _ -> 1
|
||||||
| EApp _, _ -> -1 | _, EApp _ -> 1
|
| EApp _, _ -> -1 | _, EApp _ -> 1
|
||||||
| EOp _, _ -> -1 | _, EOp _ -> 1
|
| EOp _, _ -> -1 | _, EOp _ -> 1
|
||||||
| EArray _, _ -> -1 | _, EArray _ -> 1
|
| EArray _, _ -> -1 | _, EArray _ -> 1
|
||||||
| EVar _, _ -> -1 | _, EVar _ -> 1
|
| EVar _, _ -> -1 | _, EVar _ -> 1
|
||||||
|
| EExternal _, _ -> -1 | _, EExternal _ -> 1
|
||||||
| EAbs _, _ -> -1 | _, EAbs _ -> 1
|
| EAbs _, _ -> -1 | _, EAbs _ -> 1
|
||||||
| EIfThenElse _, _ -> -1 | _, EIfThenElse _ -> 1
|
| EIfThenElse _, _ -> -1 | _, EIfThenElse _ -> 1
|
||||||
| ELocation _, _ -> -1 | _, ELocation _ -> 1
|
| ELocation _, _ -> -1 | _, ELocation _ -> 1
|
||||||
@ -735,7 +762,7 @@ let format ppf e = Print.expr ~debug:false () ppf e
|
|||||||
let rec size : type a. (a, 't) gexpr -> int =
|
let rec size : type a. (a, 't) gexpr -> int =
|
||||||
fun e ->
|
fun e ->
|
||||||
match Mark.remove e with
|
match Mark.remove e with
|
||||||
| EVar _ | ELit _ | EOp _ | EEmptyError -> 1
|
| EVar _ | EExternal _ | ELit _ | EOp _ | EEmptyError | ECustom _ -> 1
|
||||||
| ETuple args -> List.fold_left (fun acc arg -> acc + size arg) 1 args
|
| ETuple args -> List.fold_left (fun acc arg -> acc + size arg) 1 args
|
||||||
| EArray args -> List.fold_left (fun acc arg -> acc + size arg) 1 args
|
| EArray args -> List.fold_left (fun acc arg -> acc + size arg) 1 args
|
||||||
| ETupleAccess { e; _ } -> size e + 1
|
| ETupleAccess { e; _ } -> size e + 1
|
||||||
|
@ -28,10 +28,15 @@ val box : ('a, 'm) gexpr -> ('a, 'm) boxed_gexpr
|
|||||||
val unbox : ('a, 'm) boxed_gexpr -> ('a, 'm) gexpr
|
val unbox : ('a, 'm) boxed_gexpr -> ('a, 'm) gexpr
|
||||||
(** For closed expressions, similar to [Bindlib.unbox] *)
|
(** For closed expressions, similar to [Bindlib.unbox] *)
|
||||||
|
|
||||||
|
val unbox_closed : ('a, 'm) boxed_gexpr -> ('a, 'm) gexpr
|
||||||
|
(** Similar to [unbox], but with an added assertion check on the expression
|
||||||
|
being closed *)
|
||||||
|
|
||||||
val rebox : ('a any, 'm) gexpr -> ('a, 'm) boxed_gexpr
|
val rebox : ('a any, 'm) gexpr -> ('a, 'm) boxed_gexpr
|
||||||
(** Rebuild the whole term, re-binding all variables and exposing free variables *)
|
(** Rebuild the whole term, re-binding all variables and exposing free variables *)
|
||||||
|
|
||||||
val evar : ('a, 'm) gexpr Var.t -> 'm mark -> ('a, 'm) boxed_gexpr
|
val evar : ('a, 'm) gexpr Var.t -> 'm mark -> ('a, 'm) boxed_gexpr
|
||||||
|
val eexternal : Qident.t -> 'm mark -> ('a any, 'm) boxed_gexpr
|
||||||
|
|
||||||
val bind :
|
val bind :
|
||||||
('a, 'm) gexpr Var.t array ->
|
('a, 'm) gexpr Var.t array ->
|
||||||
@ -110,7 +115,7 @@ val estruct :
|
|||||||
|
|
||||||
val edstructaccess :
|
val edstructaccess :
|
||||||
('a, 'm) boxed_gexpr ->
|
('a, 'm) boxed_gexpr ->
|
||||||
IdentName.t ->
|
Ident.t ->
|
||||||
StructName.t option ->
|
StructName.t option ->
|
||||||
'm mark ->
|
'm mark ->
|
||||||
((< syntacticNames : yes ; .. > as 'a), 'm) boxed_gexpr
|
((< syntacticNames : yes ; .. > as 'a), 'm) boxed_gexpr
|
||||||
@ -142,6 +147,13 @@ val escopecall :
|
|||||||
'm mark ->
|
'm mark ->
|
||||||
((< explicitScopes : yes ; .. > as 'a), 'm) boxed_gexpr
|
((< explicitScopes : yes ; .. > as 'a), 'm) boxed_gexpr
|
||||||
|
|
||||||
|
val ecustom :
|
||||||
|
Obj.t ->
|
||||||
|
Type.t list ->
|
||||||
|
Type.t ->
|
||||||
|
'm mark ->
|
||||||
|
(< custom : Definitions.yes ; .. >, 'm) boxed_gexpr
|
||||||
|
|
||||||
val fun_id : 'm mark -> ('a any, 'm) boxed_gexpr
|
val fun_id : 'm mark -> ('a any, 'm) boxed_gexpr
|
||||||
|
|
||||||
(** {2 Manipulation of marks} *)
|
(** {2 Manipulation of marks} *)
|
||||||
|
@ -23,6 +23,21 @@ open Definitions
|
|||||||
open Op
|
open Op
|
||||||
module Runtime = Runtime_ocaml.Runtime
|
module Runtime = Runtime_ocaml.Runtime
|
||||||
|
|
||||||
|
type features =
|
||||||
|
< monomorphic : yes
|
||||||
|
; polymorphic : yes
|
||||||
|
; overloaded : no
|
||||||
|
; resolved : yes
|
||||||
|
; syntacticNames : no
|
||||||
|
; resolvedNames : yes
|
||||||
|
; scopeVarStates : no
|
||||||
|
; scopeVarSimpl : no
|
||||||
|
; explicitScopes : no
|
||||||
|
; assertions : yes >
|
||||||
|
|
||||||
|
type ('d, 'e, 'c) astk =
|
||||||
|
< features ; defaultTerms : 'd ; exceptions : 'e ; custom : 'c >
|
||||||
|
|
||||||
(** {1 Helpers} *)
|
(** {1 Helpers} *)
|
||||||
|
|
||||||
let is_empty_error : type a. (a, 'm) gexpr -> bool =
|
let is_empty_error : type a. (a, 'm) gexpr -> bool =
|
||||||
@ -375,10 +390,123 @@ let rec evaluate_operator
|
|||||||
_ ) ->
|
_ ) ->
|
||||||
err ()
|
err ()
|
||||||
|
|
||||||
|
(* /S\ dark magic here. This relies both on internals of [Lcalc.to_ocaml] *and*
|
||||||
|
of the OCaml runtime *)
|
||||||
|
let rec runtime_to_val :
|
||||||
|
(decl_ctx -> ('a, 'm) gexpr -> ('a, 'm) gexpr) ->
|
||||||
|
decl_ctx ->
|
||||||
|
'm mark ->
|
||||||
|
typ ->
|
||||||
|
Obj.t ->
|
||||||
|
(((_, _, yes) astk as 'a), 'm) gexpr =
|
||||||
|
fun eval_expr ctx m ty o ->
|
||||||
|
let m = Expr.map_ty (fun _ -> ty) m in
|
||||||
|
match Mark.remove ty with
|
||||||
|
| TLit TBool -> ELit (LBool (Obj.obj o)), m
|
||||||
|
| TLit TUnit -> ELit LUnit, m
|
||||||
|
| TLit TInt -> ELit (LInt (Obj.obj o)), m
|
||||||
|
| TLit TRat -> ELit (LRat (Obj.obj o)), m
|
||||||
|
| TLit TMoney -> ELit (LMoney (Obj.obj o)), m
|
||||||
|
| TLit TDate -> ELit (LDate (Obj.obj o)), m
|
||||||
|
| TLit TDuration -> ELit (LDuration (Obj.obj o)), m
|
||||||
|
| TTuple ts ->
|
||||||
|
( ETuple
|
||||||
|
(List.map2
|
||||||
|
(runtime_to_val eval_expr ctx m)
|
||||||
|
ts
|
||||||
|
(Array.to_list (Obj.obj o))),
|
||||||
|
m )
|
||||||
|
| TStruct name ->
|
||||||
|
StructName.Map.find name ctx.ctx_structs
|
||||||
|
|> StructField.Map.to_seq
|
||||||
|
|> Seq.map2
|
||||||
|
(fun o (fld, ty) -> fld, runtime_to_val eval_expr ctx m ty o)
|
||||||
|
(Array.to_seq (Obj.obj o))
|
||||||
|
|> StructField.Map.of_seq
|
||||||
|
|> fun fields -> EStruct { name; fields }, m
|
||||||
|
| TEnum name ->
|
||||||
|
(* we only use non-constant constructors of arity 1, which allows us to
|
||||||
|
always use the tag directly (ordered as declared in the constr map), and
|
||||||
|
the field 0 *)
|
||||||
|
let cons, ty =
|
||||||
|
List.nth
|
||||||
|
(EnumConstructor.Map.bindings (EnumName.Map.find name ctx.ctx_enums))
|
||||||
|
(Obj.tag o - Obj.first_non_constant_constructor_tag)
|
||||||
|
in
|
||||||
|
let e = runtime_to_val eval_expr ctx m ty (Obj.field o 0) in
|
||||||
|
EInj { name; cons; e }, m
|
||||||
|
| TOption _ty -> assert false
|
||||||
|
| TArray ty ->
|
||||||
|
( EArray
|
||||||
|
(List.map
|
||||||
|
(runtime_to_val eval_expr ctx m ty)
|
||||||
|
(Array.to_list (Obj.obj o))),
|
||||||
|
m )
|
||||||
|
| TArrow (targs, tret) -> ECustom { obj = o; targs; tret }, m
|
||||||
|
| TAny -> assert false
|
||||||
|
|
||||||
|
and val_to_runtime :
|
||||||
|
(decl_ctx -> ('a, 'm) gexpr -> ('a, 'm) gexpr) ->
|
||||||
|
decl_ctx ->
|
||||||
|
typ ->
|
||||||
|
('b, 'm) gexpr ->
|
||||||
|
Obj.t =
|
||||||
|
fun eval_expr ctx ty v ->
|
||||||
|
match Mark.remove ty, Mark.remove v with
|
||||||
|
| TLit TBool, ELit (LBool b) -> Obj.repr b
|
||||||
|
| TLit TUnit, ELit LUnit -> Obj.repr ()
|
||||||
|
| TLit TInt, ELit (LInt i) -> Obj.repr i
|
||||||
|
| TLit TRat, ELit (LRat r) -> Obj.repr r
|
||||||
|
| TLit TMoney, ELit (LMoney m) -> Obj.repr m
|
||||||
|
| TLit TDate, ELit (LDate t) -> Obj.repr t
|
||||||
|
| TLit TDuration, ELit (LDuration d) -> Obj.repr d
|
||||||
|
| TTuple ts, ETuple es ->
|
||||||
|
List.map2 (val_to_runtime eval_expr ctx) ts es |> Array.of_list |> Obj.repr
|
||||||
|
| TStruct name1, EStruct { name; fields } ->
|
||||||
|
assert (StructName.equal name name1);
|
||||||
|
let fld_tys = StructName.Map.find name ctx.ctx_structs in
|
||||||
|
Seq.map2
|
||||||
|
(fun (_, ty) (_, v) -> val_to_runtime eval_expr ctx ty v)
|
||||||
|
(StructField.Map.to_seq fld_tys)
|
||||||
|
(StructField.Map.to_seq fields)
|
||||||
|
|> Array.of_seq
|
||||||
|
|> Obj.repr
|
||||||
|
| TEnum name1, EInj { name; cons; e } ->
|
||||||
|
assert (EnumName.equal name name1);
|
||||||
|
let rec find_tag n = function
|
||||||
|
| [] -> assert false
|
||||||
|
| (c, ty) :: _ when EnumConstructor.equal c cons -> n, ty
|
||||||
|
| _ :: r -> find_tag (n + 1) r
|
||||||
|
in
|
||||||
|
let tag, ty =
|
||||||
|
find_tag Obj.first_non_constant_constructor_tag
|
||||||
|
(EnumConstructor.Map.bindings (EnumName.Map.find name ctx.ctx_enums))
|
||||||
|
in
|
||||||
|
let o = Obj.with_tag tag (Obj.repr (Some ())) in
|
||||||
|
Obj.set_field o 0 (val_to_runtime eval_expr ctx ty e);
|
||||||
|
o
|
||||||
|
| TOption _ty, _ -> assert false
|
||||||
|
| TArray ty, EArray es ->
|
||||||
|
Array.of_list (List.map (val_to_runtime eval_expr ctx ty) es) |> Obj.repr
|
||||||
|
| TArrow (targs, tret), _ ->
|
||||||
|
let m = Mark.get v in
|
||||||
|
(* we want stg like [fun args -> val_to_runtime (eval_expr ctx (EApp (v,
|
||||||
|
args)))] but in curried form *)
|
||||||
|
let rec curry acc = function
|
||||||
|
| [] ->
|
||||||
|
let args = List.rev acc in
|
||||||
|
val_to_runtime eval_expr ctx tret
|
||||||
|
(eval_expr ctx (EApp { f = v; args }, m))
|
||||||
|
| targ :: targs ->
|
||||||
|
Obj.repr (fun x ->
|
||||||
|
curry (runtime_to_val eval_expr ctx m targ x :: acc) targs)
|
||||||
|
in
|
||||||
|
curry [] targs
|
||||||
|
| _ -> assert false
|
||||||
|
|
||||||
let rec evaluate_expr :
|
let rec evaluate_expr :
|
||||||
type a b.
|
type d e.
|
||||||
decl_ctx -> ((a, b) dcalc_lcalc, 'm) gexpr -> ((a, b) dcalc_lcalc, 'm) gexpr
|
decl_ctx -> ((d, e, yes) astk, 't) gexpr -> ((d, e, yes) astk, 't) gexpr =
|
||||||
=
|
|
||||||
fun ctx e ->
|
fun ctx e ->
|
||||||
let m = Mark.get e in
|
let m = Mark.get e in
|
||||||
let pos = Expr.mark_pos m in
|
let pos = Expr.mark_pos m in
|
||||||
@ -387,6 +515,14 @@ let rec evaluate_expr :
|
|||||||
Message.raise_spanned_error pos
|
Message.raise_spanned_error pos
|
||||||
"free variable found at evaluation (should not happen if term was \
|
"free variable found at evaluation (should not happen if term was \
|
||||||
well-typed)"
|
well-typed)"
|
||||||
|
| EExternal qid -> (
|
||||||
|
match Qident.Map.find_opt qid ctx.ctx_modules with
|
||||||
|
| None ->
|
||||||
|
Message.raise_spanned_error pos "Reference to %a could not be resolved"
|
||||||
|
Qident.format qid
|
||||||
|
| Some ty ->
|
||||||
|
let o = Runtime.lookup_value qid in
|
||||||
|
runtime_to_val evaluate_expr ctx m ty o)
|
||||||
| EApp { f = e1; args } -> (
|
| EApp { f = e1; args } -> (
|
||||||
let e1 = evaluate_expr ctx e1 in
|
let e1 = evaluate_expr ctx e1 in
|
||||||
let args = List.map (evaluate_expr ctx) args in
|
let args = List.map (evaluate_expr ctx) args in
|
||||||
@ -403,11 +539,23 @@ let rec evaluate_expr :
|
|||||||
(Bindlib.mbinder_arity binder)
|
(Bindlib.mbinder_arity binder)
|
||||||
(List.length args)
|
(List.length args)
|
||||||
| EOp { op; _ } -> evaluate_operator (evaluate_expr ctx) op m args
|
| EOp { op; _ } -> evaluate_operator (evaluate_expr ctx) op m args
|
||||||
|
| ECustom { obj; targs; tret } ->
|
||||||
|
(* Applies the arguments one by one to the curried form *)
|
||||||
|
List.fold_left2
|
||||||
|
(fun fobj targ arg ->
|
||||||
|
(Obj.obj fobj : Obj.t -> Obj.t)
|
||||||
|
(val_to_runtime evaluate_expr ctx targ arg))
|
||||||
|
obj targs args
|
||||||
|
|> Obj.obj
|
||||||
|
|> fun o -> runtime_to_val evaluate_expr ctx m tret o
|
||||||
| _ ->
|
| _ ->
|
||||||
Message.raise_spanned_error pos
|
Message.raise_spanned_error pos
|
||||||
"function has not been reduced to a lambda at evaluation (should not \
|
"function has not been reduced to a lambda at evaluation (should not \
|
||||||
happen if the term was well-typed")
|
happen if the term was well-typed")
|
||||||
| (EAbs _ | ELit _ | EOp _) as e -> Mark.add m e (* these are values *)
|
| EAbs { binder; tys } -> Expr.unbox (Expr.eabs (Bindlib.box binder) tys m)
|
||||||
|
| ELit _ as e -> Mark.add m e
|
||||||
|
| EOp { op; tys } -> Expr.unbox (Expr.eop (Operator.translate op) tys m)
|
||||||
|
(* | EAbs _ as e -> Marked.mark m e (* these are values *) *)
|
||||||
| EStruct { fields = es; name } ->
|
| EStruct { fields = es; name } ->
|
||||||
let fields, es = List.split (StructField.Map.bindings es) in
|
let fields, es = List.split (StructField.Map.bindings es) in
|
||||||
let es = List.map (evaluate_expr ctx) es in
|
let es = List.map (evaluate_expr ctx) es in
|
||||||
@ -514,6 +662,7 @@ let rec evaluate_expr :
|
|||||||
Message.raise_spanned_error (Expr.pos e')
|
Message.raise_spanned_error (Expr.pos e')
|
||||||
"Expected a boolean literal for the result of this assertion \
|
"Expected a boolean literal for the result of this assertion \
|
||||||
(should not happen if the term was well-typed)")
|
(should not happen if the term was well-typed)")
|
||||||
|
| ECustom _ -> e
|
||||||
| EEmptyError -> Mark.copy e EEmptyError
|
| EEmptyError -> Mark.copy e EEmptyError
|
||||||
| EErrorOnEmpty e' -> (
|
| EErrorOnEmpty e' -> (
|
||||||
match evaluate_expr ctx e' with
|
match evaluate_expr ctx e' with
|
||||||
@ -552,6 +701,55 @@ let rec evaluate_expr :
|
|||||||
evaluate_expr ctx handler)
|
evaluate_expr ctx handler)
|
||||||
| _ -> .
|
| _ -> .
|
||||||
|
|
||||||
|
(* Typing shenanigan to add custom terms to the AST type. This is an identity
|
||||||
|
and could be optimised into [Obj.magic]. *)
|
||||||
|
let addcustom e =
|
||||||
|
let rec f :
|
||||||
|
type c d e.
|
||||||
|
((d, e, c) astk, 't) gexpr -> ((d, e, yes) astk, 't) gexpr boxed =
|
||||||
|
function
|
||||||
|
| (ECustom _, _) as e -> Expr.map ~f e
|
||||||
|
| EOp { op; tys }, m -> Expr.eop (Operator.translate op) tys m
|
||||||
|
| (EDefault _, _) as e -> Expr.map ~f e
|
||||||
|
| (EEmptyError, _) as e -> Expr.map ~f e
|
||||||
|
| (EErrorOnEmpty _, _) as e -> Expr.map ~f e
|
||||||
|
| (ECatch _, _) as e -> Expr.map ~f e
|
||||||
|
| (ERaise _, _) as e -> Expr.map ~f e
|
||||||
|
| ( ( EAssert _ | ELit _ | EApp _ | EArray _ | EVar _ | EExternal _ | EAbs _
|
||||||
|
| EIfThenElse _ | ETuple _ | ETupleAccess _ | EInj _ | EStruct _
|
||||||
|
| EStructAccess _ | EMatch _ ),
|
||||||
|
_ ) as e ->
|
||||||
|
Expr.map ~f e
|
||||||
|
| _ -> .
|
||||||
|
in
|
||||||
|
Expr.unbox (f e)
|
||||||
|
|
||||||
|
let delcustom e =
|
||||||
|
let rec f :
|
||||||
|
type c d e.
|
||||||
|
((d, e, c) astk, 't) gexpr -> ((d, e, no) astk, 't) gexpr boxed = function
|
||||||
|
| ECustom _, _ -> invalid_arg "Custom term remaining in evaluated term"
|
||||||
|
| EOp { op; tys }, m -> Expr.eop (Operator.translate op) tys m
|
||||||
|
| (EDefault _, _) as e -> Expr.map ~f e
|
||||||
|
| (EEmptyError, _) as e -> Expr.map ~f e
|
||||||
|
| (EErrorOnEmpty _, _) as e -> Expr.map ~f e
|
||||||
|
| (ECatch _, _) as e -> Expr.map ~f e
|
||||||
|
| (ERaise _, _) as e -> Expr.map ~f e
|
||||||
|
| ( ( EAssert _ | ELit _ | EApp _ | EArray _ | EVar _ | EExternal _ | EAbs _
|
||||||
|
| EIfThenElse _ | ETuple _ | ETupleAccess _ | EInj _ | EStruct _
|
||||||
|
| EStructAccess _ | EMatch _ ),
|
||||||
|
_ ) as e ->
|
||||||
|
Expr.map ~f e
|
||||||
|
| _ -> .
|
||||||
|
in
|
||||||
|
Expr.unbox (f e)
|
||||||
|
|
||||||
|
(* Evaluation may introduce intermediate custom terms ([ECustom], pointers to
|
||||||
|
external functions), straying away from the DCalc and LCalc ASTS. [addcustom]
|
||||||
|
and [delcustom] are needed to expand and shrink the type of the terms to
|
||||||
|
reflect that. *)
|
||||||
|
let evaluate_expr ctx e = delcustom (evaluate_expr ctx (addcustom e))
|
||||||
|
|
||||||
let interpret_program_lcalc p s : (Uid.MarkedString.info * ('a, 'm) gexpr) list
|
let interpret_program_lcalc p s : (Uid.MarkedString.info * ('a, 'm) gexpr) list
|
||||||
=
|
=
|
||||||
let e = Expr.unbox @@ Program.to_expr p s in
|
let e = Expr.unbox @@ Program.to_expr p s in
|
||||||
|
@ -20,8 +20,21 @@
|
|||||||
open Catala_utils
|
open Catala_utils
|
||||||
open Definitions
|
open Definitions
|
||||||
|
|
||||||
|
type features =
|
||||||
|
< monomorphic : yes
|
||||||
|
; polymorphic : yes
|
||||||
|
; overloaded : no
|
||||||
|
; resolved : yes
|
||||||
|
; syntacticNames : no
|
||||||
|
; resolvedNames : yes
|
||||||
|
; scopeVarStates : no
|
||||||
|
; scopeVarSimpl : no
|
||||||
|
; explicitScopes : no
|
||||||
|
; assertions : yes >
|
||||||
|
(** The interpreter only works on dcalc and lcalc, which share these features *)
|
||||||
|
|
||||||
val evaluate_operator :
|
val evaluate_operator :
|
||||||
((((_, _) dcalc_lcalc as 'a), 'm) gexpr -> ('a, 'm) gexpr) ->
|
(((< features ; .. > as 'a), 'm) gexpr -> ('a, 'm) gexpr) ->
|
||||||
'a operator ->
|
'a operator ->
|
||||||
'm mark ->
|
'm mark ->
|
||||||
('a, 'm) gexpr list ->
|
('a, 'm) gexpr list ->
|
||||||
@ -32,9 +45,7 @@ val evaluate_operator :
|
|||||||
operator. *)
|
operator. *)
|
||||||
|
|
||||||
val evaluate_expr :
|
val evaluate_expr :
|
||||||
decl_ctx ->
|
decl_ctx -> (((_, _) dcalc_lcalc as 'a), 'm) gexpr -> ('a, 'm) gexpr
|
||||||
(('a, 'b) dcalc_lcalc, 'm) gexpr ->
|
|
||||||
(('a, 'b) dcalc_lcalc, 'm) gexpr
|
|
||||||
(** Evaluates an expression according to the semantics of the default calculus. *)
|
(** Evaluates an expression according to the semantics of the default calculus. *)
|
||||||
|
|
||||||
val interpret_program_dcalc :
|
val interpret_program_dcalc :
|
||||||
|
@ -184,7 +184,7 @@ let rec optimize_expr :
|
|||||||
when name = name1 ->
|
when name = name1 ->
|
||||||
Mark.remove (StructField.Map.find field fields)
|
Mark.remove (StructField.Map.find field fields)
|
||||||
| EDefault { excepts; just; cons } -> (
|
| EDefault { excepts; just; cons } -> (
|
||||||
(* TODO: mechanically prove each of these optimizations correct :) *)
|
(* TODO: mechanically prove each of these optimizations correct *)
|
||||||
let excepts =
|
let excepts =
|
||||||
List.filter (fun except -> Mark.remove except <> EEmptyError) excepts
|
List.filter (fun except -> Mark.remove except <> EEmptyError) excepts
|
||||||
(* we can discard the exceptions that are always empty error *)
|
(* we can discard the exceptions that are always empty error *)
|
||||||
@ -198,7 +198,8 @@ let rec optimize_expr :
|
|||||||
(* at this point we know a conflict error will be triggered so we just
|
(* at this point we know a conflict error will be triggered so we just
|
||||||
feed the expression to the interpreter that will print the beautiful
|
feed the expression to the interpreter that will print the beautiful
|
||||||
right error message *)
|
right error message *)
|
||||||
Mark.remove (Interpreter.evaluate_expr ctx.decl_ctx e)
|
let _ = Interpreter.evaluate_expr ctx.decl_ctx e in
|
||||||
|
assert false
|
||||||
else
|
else
|
||||||
match excepts, just with
|
match excepts, just with
|
||||||
| [except], _ when Expr.is_value except ->
|
| [except], _ when Expr.is_value except ->
|
||||||
@ -302,7 +303,12 @@ let rec optimize_expr :
|
|||||||
in
|
in
|
||||||
Expr.Box.app1 e reduce mark
|
Expr.Box.app1 e reduce mark
|
||||||
|
|
||||||
let optimize_expr (decl_ctx : decl_ctx) (e : (('a, 'b) dcalc_lcalc, 'm) gexpr) =
|
let optimize_expr :
|
||||||
|
'm.
|
||||||
|
decl_ctx ->
|
||||||
|
(('a, 'b) dcalc_lcalc, 'm) gexpr ->
|
||||||
|
(('a, 'b) dcalc_lcalc, 'm) boxed_gexpr =
|
||||||
|
fun (decl_ctx : decl_ctx) (e : (('a, 'b) dcalc_lcalc, 'm) gexpr) ->
|
||||||
optimize_expr { var_values = Var.Map.empty; decl_ctx } e
|
optimize_expr { var_values = Var.Map.empty; decl_ctx } e
|
||||||
|
|
||||||
let optimize_program (p : 'm program) : 'm program =
|
let optimize_program (p : 'm program) : 'm program =
|
||||||
@ -339,15 +345,7 @@ let test_iota_reduction_1 () =
|
|||||||
x"
|
x"
|
||||||
(Format.asprintf "before=%a\nafter=%a" Expr.format (Expr.unbox matchA)
|
(Format.asprintf "before=%a\nafter=%a" Expr.format (Expr.unbox matchA)
|
||||||
Expr.format
|
Expr.format
|
||||||
(Expr.unbox
|
(Expr.unbox (optimize_expr Program.empty_ctx (Expr.unbox matchA))))
|
||||||
(optimize_expr
|
|
||||||
{
|
|
||||||
ctx_enums = EnumName.Map.empty;
|
|
||||||
ctx_structs = StructName.Map.empty;
|
|
||||||
ctx_struct_fields = IdentName.Map.empty;
|
|
||||||
ctx_scopes = ScopeName.Map.empty;
|
|
||||||
}
|
|
||||||
(Expr.unbox matchA))))
|
|
||||||
|
|
||||||
let cases_of_list l : ('a, 't) boxed_gexpr EnumConstructor.Map.t =
|
let cases_of_list l : ('a, 't) boxed_gexpr EnumConstructor.Map.t =
|
||||||
EnumConstructor.Map.of_seq
|
EnumConstructor.Map.of_seq
|
||||||
@ -409,12 +407,4 @@ let test_iota_reduction_2 () =
|
|||||||
\ | B → (λ (x: any) → D B x)\n"
|
\ | B → (λ (x: any) → D B x)\n"
|
||||||
(Format.asprintf "before=@[%a@]@.after=%a@." Expr.format (Expr.unbox matchA)
|
(Format.asprintf "before=@[%a@]@.after=%a@." Expr.format (Expr.unbox matchA)
|
||||||
Expr.format
|
Expr.format
|
||||||
(Expr.unbox
|
(Expr.unbox (optimize_expr Program.empty_ctx (Expr.unbox matchA))))
|
||||||
(optimize_expr
|
|
||||||
{
|
|
||||||
ctx_enums = EnumName.Map.empty;
|
|
||||||
ctx_structs = StructName.Map.empty;
|
|
||||||
ctx_struct_fields = IdentName.Map.empty;
|
|
||||||
ctx_scopes = ScopeName.Map.empty;
|
|
||||||
}
|
|
||||||
(Expr.unbox matchA))))
|
|
||||||
|
@ -379,6 +379,7 @@ module Precedence = struct
|
|||||||
| EOp _ -> Contained
|
| EOp _ -> Contained
|
||||||
| EArray _ -> Contained
|
| EArray _ -> Contained
|
||||||
| EVar _ -> Contained
|
| EVar _ -> Contained
|
||||||
|
| EExternal _ -> Contained
|
||||||
| EAbs _ -> Abs
|
| EAbs _ -> Abs
|
||||||
| EIfThenElse _ -> Contained
|
| EIfThenElse _ -> Contained
|
||||||
| EStruct _ -> Contained
|
| EStruct _ -> Contained
|
||||||
@ -395,6 +396,7 @@ module Precedence = struct
|
|||||||
| EErrorOnEmpty _ -> App
|
| EErrorOnEmpty _ -> App
|
||||||
| ERaise _ -> App
|
| ERaise _ -> App
|
||||||
| ECatch _ -> App
|
| ECatch _ -> App
|
||||||
|
| ECustom _ -> Contained
|
||||||
|
|
||||||
let needs_parens ~context ?(rhs = false) e =
|
let needs_parens ~context ?(rhs = false) e =
|
||||||
match expr context, expr e with
|
match expr context, expr e with
|
||||||
@ -461,6 +463,7 @@ let rec expr_aux :
|
|||||||
let rhs ex = paren ~rhs:true ex in
|
let rhs ex = paren ~rhs:true ex in
|
||||||
match Mark.remove e with
|
match Mark.remove e with
|
||||||
| EVar v -> var fmt v
|
| EVar v -> var fmt v
|
||||||
|
| EExternal eref -> Qident.format fmt eref
|
||||||
| ETuple es ->
|
| ETuple es ->
|
||||||
Format.fprintf fmt "@[<hov 2>%a%a%a@]" punctuation "("
|
Format.fprintf fmt "@[<hov 2>%a%a%a@]" punctuation "("
|
||||||
(Format.pp_print_list
|
(Format.pp_print_list
|
||||||
@ -608,7 +611,7 @@ let rec expr_aux :
|
|||||||
| ELocation loc -> location fmt loc
|
| ELocation loc -> location fmt loc
|
||||||
| EDStructAccess { e; field; _ } ->
|
| EDStructAccess { e; field; _ } ->
|
||||||
Format.fprintf fmt "@[<hv 2>%a%a@,%a%a%a@]" (lhs exprc) e punctuation "."
|
Format.fprintf fmt "@[<hv 2>%a%a@,%a%a%a@]" (lhs exprc) e punctuation "."
|
||||||
punctuation "\"" IdentName.format_t field punctuation "\""
|
punctuation "\"" Ident.format_t field punctuation "\""
|
||||||
| EStruct { name; fields } ->
|
| EStruct { name; fields } ->
|
||||||
if StructField.Map.is_empty fields then (
|
if StructField.Map.is_empty fields then (
|
||||||
punctuation fmt "{";
|
punctuation fmt "{";
|
||||||
@ -665,6 +668,7 @@ let rec expr_aux :
|
|||||||
Format.pp_close_box fmt ();
|
Format.pp_close_box fmt ();
|
||||||
punctuation fmt "}";
|
punctuation fmt "}";
|
||||||
Format.pp_close_box fmt ()
|
Format.pp_close_box fmt ()
|
||||||
|
| ECustom _ -> Format.pp_print_string fmt "<obj>"
|
||||||
|
|
||||||
let rec colors =
|
let rec colors =
|
||||||
let open Ocolor_types in
|
let open Ocolor_types in
|
||||||
|
@ -28,6 +28,15 @@ let fold_left_exprs ~f ~init { code_items; decl_ctx = _ } =
|
|||||||
let fold_right_exprs ~f ~init { code_items; decl_ctx = _ } =
|
let fold_right_exprs ~f ~init { code_items; decl_ctx = _ } =
|
||||||
Scope.fold_right ~f:(fun e _ acc -> f e acc) ~init code_items
|
Scope.fold_right ~f:(fun e _ acc -> f e acc) ~init code_items
|
||||||
|
|
||||||
|
let empty_ctx =
|
||||||
|
{
|
||||||
|
ctx_enums = EnumName.Map.empty;
|
||||||
|
ctx_structs = StructName.Map.empty;
|
||||||
|
ctx_struct_fields = Ident.Map.empty;
|
||||||
|
ctx_scopes = ScopeName.Map.empty;
|
||||||
|
ctx_modules = Qident.Map.empty;
|
||||||
|
}
|
||||||
|
|
||||||
let get_scope_body { code_items; _ } scope =
|
let get_scope_body { code_items; _ } scope =
|
||||||
match
|
match
|
||||||
Scope.fold_left ~init:None
|
Scope.fold_left ~init:None
|
||||||
|
@ -17,6 +17,10 @@
|
|||||||
|
|
||||||
open Definitions
|
open Definitions
|
||||||
|
|
||||||
|
(** {2 Program declaration context helpers} *)
|
||||||
|
|
||||||
|
val empty_ctx : decl_ctx
|
||||||
|
|
||||||
(** {2 Transformations} *)
|
(** {2 Transformations} *)
|
||||||
|
|
||||||
val map_exprs :
|
val map_exprs :
|
||||||
|
53
compiler/shared_ast/qident.ml
Normal file
53
compiler/shared_ast/qident.ml
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
(* This file is part of the Catala compiler, a specification language for tax
|
||||||
|
and social benefits computation rules. Copyright (C) 2023 Inria, contributor:
|
||||||
|
Louis Gesbert <louis.gesbert@inria.fr>
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
License for the specific language governing permissions and limitations under
|
||||||
|
the License. *)
|
||||||
|
|
||||||
|
(** This module defines module names and path accesses, used to refer to
|
||||||
|
separate compilation units *)
|
||||||
|
|
||||||
|
open Catala_utils
|
||||||
|
|
||||||
|
type modname = string
|
||||||
|
type ident = string
|
||||||
|
type path = modname list
|
||||||
|
type t = path * ident
|
||||||
|
|
||||||
|
let compare_path = List.compare String.compare
|
||||||
|
let equal_path = List.equal String.equal
|
||||||
|
|
||||||
|
let compare (p1, i1) (p2, i2) =
|
||||||
|
match compare_path p1 p2 with 0 -> String.compare i1 i2 | n -> n
|
||||||
|
|
||||||
|
let equal (p1, i1) (p2, i2) = equal_path p1 p2 && String.equal i1 i2
|
||||||
|
|
||||||
|
module Ord = struct
|
||||||
|
type nonrec t = t
|
||||||
|
|
||||||
|
let compare = compare
|
||||||
|
end
|
||||||
|
|
||||||
|
module Set = Set.Make (Ord)
|
||||||
|
module Map = Map.Make (Ord)
|
||||||
|
|
||||||
|
let format_modname ppf m = Format.fprintf ppf "@{<blue>%s@}" m
|
||||||
|
|
||||||
|
let format_path ppf p =
|
||||||
|
let pp_sep ppf () = Format.fprintf ppf "@{<cyan>.@}" in
|
||||||
|
Format.pp_print_list ~pp_sep format_modname ppf p;
|
||||||
|
pp_sep ppf ()
|
||||||
|
|
||||||
|
let format ppf (p, i) =
|
||||||
|
format_path ppf p;
|
||||||
|
Format.pp_print_string ppf i
|
36
compiler/shared_ast/qident.mli
Normal file
36
compiler/shared_ast/qident.mli
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
(* This file is part of the Catala compiler, a specification language for tax
|
||||||
|
and social benefits computation rules. Copyright (C) 2023 Inria, contributor:
|
||||||
|
Louis Gesbert <louis.gesbert@inria.fr>
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
License for the specific language governing permissions and limitations under
|
||||||
|
the License. *)
|
||||||
|
|
||||||
|
(** This module defines module names and path accesses, used to refer to
|
||||||
|
separate compilation units. *)
|
||||||
|
|
||||||
|
type modname = string
|
||||||
|
(** Expected to be a uident (i.e. start with an uppercase letter) *)
|
||||||
|
|
||||||
|
type ident = string
|
||||||
|
(** Expected to be a lident (i.e. start with a lowercase letter) *)
|
||||||
|
|
||||||
|
type path = modname list
|
||||||
|
type t = path * ident
|
||||||
|
|
||||||
|
val compare_path : path -> path -> int
|
||||||
|
val equal_path : path -> path -> bool
|
||||||
|
val compare : t -> t -> int
|
||||||
|
val equal : t -> t -> bool
|
||||||
|
val format : Format.formatter -> t -> unit
|
||||||
|
|
||||||
|
module Set : Set.S with type elt = t
|
||||||
|
module Map : Map.S with type key = t
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
include Definitions
|
include Definitions
|
||||||
module Var = Var
|
module Var = Var
|
||||||
|
module Qident = Qident
|
||||||
module Type = Type
|
module Type = Type
|
||||||
module Operator = Operator
|
module Operator = Operator
|
||||||
module Expr = Expr
|
module Expr = Expr
|
||||||
|
@ -458,7 +458,7 @@ and typecheck_expr_top_down :
|
|||||||
in
|
in
|
||||||
let field =
|
let field =
|
||||||
let candidate_structs =
|
let candidate_structs =
|
||||||
try A.IdentName.Map.find field ctx.ctx_struct_fields
|
try A.Ident.Map.find field ctx.ctx_struct_fields
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
Message.raise_spanned_error
|
Message.raise_spanned_error
|
||||||
(Expr.mark_pos context_mark)
|
(Expr.mark_pos context_mark)
|
||||||
@ -610,6 +610,16 @@ and typecheck_expr_top_down :
|
|||||||
"Variable %s not found in the current context" (Bindlib.name_of v)
|
"Variable %s not found in the current context" (Bindlib.name_of v)
|
||||||
in
|
in
|
||||||
Expr.evar (Var.translate v) (mark_with_tau_and_unify tau')
|
Expr.evar (Var.translate v) (mark_with_tau_and_unify tau')
|
||||||
|
| A.EExternal eref ->
|
||||||
|
let ty =
|
||||||
|
try Qident.Map.find eref ctx.ctx_modules
|
||||||
|
with Not_found ->
|
||||||
|
Message.raise_spanned_error pos_e
|
||||||
|
"Could not resolve the reference to %a.@ Make sure the corresponding \
|
||||||
|
module was properly loaded?"
|
||||||
|
Qident.format eref
|
||||||
|
in
|
||||||
|
Expr.eexternal eref (mark_with_tau_and_unify (ast_to_typ ty))
|
||||||
| A.ELit lit -> Expr.elit lit (ty_mark (lit_type lit))
|
| A.ELit lit -> Expr.elit lit (ty_mark (lit_type lit))
|
||||||
| A.ETuple es ->
|
| A.ETuple es ->
|
||||||
let tys = List.map (fun _ -> unionfind (TAny (Any.fresh ()))) es in
|
let tys = List.map (fun _ -> unionfind (TAny (Any.fresh ()))) es in
|
||||||
@ -787,6 +797,11 @@ and typecheck_expr_top_down :
|
|||||||
List.map (typecheck_expr_top_down ~leave_unresolved ctx env cell_type) es
|
List.map (typecheck_expr_top_down ~leave_unresolved ctx env cell_type) es
|
||||||
in
|
in
|
||||||
Expr.earray es' mark
|
Expr.earray es' mark
|
||||||
|
| A.ECustom { obj; targs; tret } ->
|
||||||
|
let mark =
|
||||||
|
mark_with_tau_and_unify (ast_to_typ (A.TArrow (targs, tret), Expr.pos e))
|
||||||
|
in
|
||||||
|
Expr.ecustom obj targs tret mark
|
||||||
|
|
||||||
let wrap ctx f e =
|
let wrap ctx f e =
|
||||||
try f e
|
try f e
|
||||||
|
@ -735,7 +735,7 @@ type top_def = {
|
|||||||
topdef_args : (lident Mark.pos * base_typ Mark.pos) list Mark.pos option;
|
topdef_args : (lident Mark.pos * base_typ Mark.pos) list Mark.pos option;
|
||||||
(** Empty list if this is not a function *)
|
(** Empty list if this is not a function *)
|
||||||
topdef_type : typ;
|
topdef_type : typ;
|
||||||
topdef_expr : expression;
|
topdef_expr : expression option;
|
||||||
}
|
}
|
||||||
[@@deriving
|
[@@deriving
|
||||||
visitors
|
visitors
|
||||||
@ -869,6 +869,8 @@ type law_structure =
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
type program = {
|
type program = {
|
||||||
|
program_interfaces :
|
||||||
|
((Shared_ast.Qident.path[@opaque]) * code_item Mark.pos) list;
|
||||||
program_items : law_structure list;
|
program_items : law_structure list;
|
||||||
program_source_files : (string[@opaque]) list;
|
program_source_files : (string[@opaque]) list;
|
||||||
}
|
}
|
||||||
|
@ -238,9 +238,9 @@ source_file: BEGIN_CODE DECLARATION YEAR
|
|||||||
## code_item -> DECLARATION . STRUCT UIDENT COLON list(addpos(struct_scope)) [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION . STRUCT UIDENT COLON list(addpos(struct_scope)) [ SCOPE END_CODE DECLARATION ]
|
||||||
## code_item -> DECLARATION . SCOPE UIDENT COLON nonempty_list(addpos(scope_decl_item)) [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION . SCOPE UIDENT COLON nonempty_list(addpos(scope_decl_item)) [ SCOPE END_CODE DECLARATION ]
|
||||||
## code_item -> DECLARATION . ENUM UIDENT COLON list(addpos(enum_decl_line)) [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION . ENUM UIDENT COLON list(addpos(enum_decl_line)) [ SCOPE END_CODE DECLARATION ]
|
||||||
## code_item -> DECLARATION . lident CONTENT typ_data DEPENDS separated_nonempty_list(COMMA,var_content) DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION . lident CONTENT typ_data DEPENDS separated_nonempty_list(COMMA,var_content) option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
## code_item -> DECLARATION . lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION . lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
## code_item -> DECLARATION . lident CONTENT typ_data DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION . lident CONTENT typ_data option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
##
|
##
|
||||||
## The known suffix of the stack is as follows:
|
## The known suffix of the stack is as follows:
|
||||||
## DECLARATION
|
## DECLARATION
|
||||||
@ -944,7 +944,7 @@ expected the name of the scope being used
|
|||||||
|
|
||||||
source_file: BEGIN_CODE YEAR
|
source_file: BEGIN_CODE YEAR
|
||||||
##
|
##
|
||||||
## Ends in an error in state: 394.
|
## Ends in an error in state: 393.
|
||||||
##
|
##
|
||||||
## source_file_item -> BEGIN_CODE . code END_CODE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
|
## source_file_item -> BEGIN_CODE . code END_CODE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
|
||||||
##
|
##
|
||||||
@ -1005,8 +1005,8 @@ source_file: BEGIN_METADATA LAW_TEXT LAW_HEADING
|
|||||||
## accurate view of the past (what has been recognized so far), they
|
## accurate view of the past (what has been recognized so far), they
|
||||||
## may provide an INCOMPLETE view of the future (what was expected next).
|
## may provide an INCOMPLETE view of the future (what was expected next).
|
||||||
## In state 1, spurious reduction of production nonempty_list(LAW_TEXT) -> LAW_TEXT
|
## In state 1, spurious reduction of production nonempty_list(LAW_TEXT) -> LAW_TEXT
|
||||||
## In state 383, spurious reduction of production law_text -> nonempty_list(LAW_TEXT)
|
## In state 382, spurious reduction of production law_text -> nonempty_list(LAW_TEXT)
|
||||||
## In state 384, spurious reduction of production option(law_text) -> law_text
|
## In state 383, spurious reduction of production option(law_text) -> law_text
|
||||||
##
|
##
|
||||||
|
|
||||||
expected some law text or code block
|
expected some law text or code block
|
||||||
@ -4019,9 +4019,9 @@ source_file: BEGIN_CODE DECLARATION LIDENT YEAR
|
|||||||
##
|
##
|
||||||
## Ends in an error in state: 364.
|
## Ends in an error in state: 364.
|
||||||
##
|
##
|
||||||
## code_item -> DECLARATION lident . CONTENT typ_data DEPENDS separated_nonempty_list(COMMA,var_content) DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident . CONTENT typ_data DEPENDS separated_nonempty_list(COMMA,var_content) option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
## code_item -> DECLARATION lident . CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident . CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
## code_item -> DECLARATION lident . CONTENT typ_data DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident . CONTENT typ_data option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
##
|
##
|
||||||
## The known suffix of the stack is as follows:
|
## The known suffix of the stack is as follows:
|
||||||
## DECLARATION lident
|
## DECLARATION lident
|
||||||
@ -4033,9 +4033,9 @@ source_file: BEGIN_CODE DECLARATION LIDENT CONTENT YEAR
|
|||||||
##
|
##
|
||||||
## Ends in an error in state: 365.
|
## Ends in an error in state: 365.
|
||||||
##
|
##
|
||||||
## code_item -> DECLARATION lident CONTENT . typ_data DEPENDS separated_nonempty_list(COMMA,var_content) DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident CONTENT . typ_data DEPENDS separated_nonempty_list(COMMA,var_content) option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
## code_item -> DECLARATION lident CONTENT . typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident CONTENT . typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
## code_item -> DECLARATION lident CONTENT . typ_data DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident CONTENT . typ_data option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
##
|
##
|
||||||
## The known suffix of the stack is as follows:
|
## The known suffix of the stack is as follows:
|
||||||
## DECLARATION lident CONTENT
|
## DECLARATION lident CONTENT
|
||||||
@ -4047,9 +4047,9 @@ source_file: BEGIN_CODE DECLARATION LIDENT CONTENT BOOLEAN YEAR
|
|||||||
##
|
##
|
||||||
## Ends in an error in state: 366.
|
## Ends in an error in state: 366.
|
||||||
##
|
##
|
||||||
## code_item -> DECLARATION lident CONTENT typ_data . DEPENDS separated_nonempty_list(COMMA,var_content) DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident CONTENT typ_data . DEPENDS separated_nonempty_list(COMMA,var_content) option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
## code_item -> DECLARATION lident CONTENT typ_data . DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident CONTENT typ_data . DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
## code_item -> DECLARATION lident CONTENT typ_data . DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident CONTENT typ_data . option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
##
|
##
|
||||||
## The known suffix of the stack is as follows:
|
## The known suffix of the stack is as follows:
|
||||||
## DECLARATION lident CONTENT typ_data
|
## DECLARATION lident CONTENT typ_data
|
||||||
@ -4062,8 +4062,8 @@ source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS YEAR
|
|||||||
##
|
##
|
||||||
## Ends in an error in state: 367.
|
## Ends in an error in state: 367.
|
||||||
##
|
##
|
||||||
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS . separated_nonempty_list(COMMA,var_content) DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS . separated_nonempty_list(COMMA,var_content) option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS . LPAREN separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS . LPAREN separated_nonempty_list(COMMA,var_content) RPAREN option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
##
|
##
|
||||||
## The known suffix of the stack is as follows:
|
## The known suffix of the stack is as follows:
|
||||||
## DECLARATION lident CONTENT typ_data DEPENDS
|
## DECLARATION lident CONTENT typ_data DEPENDS
|
||||||
@ -4075,7 +4075,7 @@ source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS LPAREN YEAR
|
|||||||
##
|
##
|
||||||
## Ends in an error in state: 368.
|
## Ends in an error in state: 368.
|
||||||
##
|
##
|
||||||
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS LPAREN . separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS LPAREN . separated_nonempty_list(COMMA,var_content) RPAREN option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
##
|
##
|
||||||
## The known suffix of the stack is as follows:
|
## The known suffix of the stack is as follows:
|
||||||
## DECLARATION lident CONTENT typ_data DEPENDS LPAREN
|
## DECLARATION lident CONTENT typ_data DEPENDS LPAREN
|
||||||
@ -4087,7 +4087,7 @@ source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS LPAREN LIDENT
|
|||||||
##
|
##
|
||||||
## Ends in an error in state: 369.
|
## Ends in an error in state: 369.
|
||||||
##
|
##
|
||||||
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) . RPAREN DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) . RPAREN option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
##
|
##
|
||||||
## The known suffix of the stack is as follows:
|
## The known suffix of the stack is as follows:
|
||||||
## DECLARATION lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content)
|
## DECLARATION lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content)
|
||||||
@ -4109,7 +4109,7 @@ source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS LPAREN LIDENT
|
|||||||
##
|
##
|
||||||
## Ends in an error in state: 370.
|
## Ends in an error in state: 370.
|
||||||
##
|
##
|
||||||
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN . DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN . option(opt_def) [ SCOPE END_CODE DECLARATION ]
|
||||||
##
|
##
|
||||||
## The known suffix of the stack is as follows:
|
## The known suffix of the stack is as follows:
|
||||||
## DECLARATION lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN
|
## DECLARATION lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN
|
||||||
@ -4121,46 +4121,14 @@ source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS LPAREN LIDENT
|
|||||||
##
|
##
|
||||||
## Ends in an error in state: 371.
|
## Ends in an error in state: 371.
|
||||||
##
|
##
|
||||||
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS . expression [ SCOPE END_CODE DECLARATION ]
|
## option(opt_def) -> DEFINED_AS . expression [ SCOPE END_CODE DECLARATION ]
|
||||||
##
|
##
|
||||||
## The known suffix of the stack is as follows:
|
## The known suffix of the stack is as follows:
|
||||||
## DECLARATION lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS
|
## DEFINED_AS
|
||||||
##
|
##
|
||||||
|
|
||||||
expected an expression
|
expected an expression
|
||||||
|
|
||||||
source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS LPAREN LIDENT CONTENT UIDENT RPAREN DEFINED_AS FALSE YEAR
|
|
||||||
##
|
|
||||||
## Ends in an error in state: 372.
|
|
||||||
##
|
|
||||||
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS expression . [ SCOPE END_CODE DECLARATION ]
|
|
||||||
## expression -> expression . DOT qlident [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . OF funcall_args [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . WITH constructor_binding [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . CONTAINS expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . FOR lident AMONG expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . MULT expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . DIV expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . PLUS expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . MINUS expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . PLUSPLUS expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . LESSER expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . LESSER_EQUAL expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . GREATER expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . GREATER_EQUAL expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . EQUAL expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . NOT_EQUAL expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . AND expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . OR expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . XOR expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
## expression -> expression . FOR lident AMONG expression SUCH THAT expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
|
||||||
##
|
|
||||||
## The known suffix of the stack is as follows:
|
|
||||||
## DECLARATION lident CONTENT typ_data DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS expression
|
|
||||||
##
|
|
||||||
|
|
||||||
expected a binary operator continuing the expression, or a keyword ending the expression and starting the next item
|
|
||||||
|
|
||||||
source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS LIDENT YEAR
|
source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS LIDENT YEAR
|
||||||
##
|
##
|
||||||
## Ends in an error in state: 305.
|
## Ends in an error in state: 305.
|
||||||
@ -4212,44 +4180,10 @@ source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS LIDENT CONTENT
|
|||||||
|
|
||||||
expected the definition of another argument in the form '<var> content <type>'
|
expected the definition of another argument in the form '<var> content <type>'
|
||||||
|
|
||||||
source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS LIDENT CONTENT UIDENT RPAREN
|
|
||||||
##
|
|
||||||
## Ends in an error in state: 373.
|
|
||||||
##
|
|
||||||
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS separated_nonempty_list(COMMA,var_content) . DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
|
|
||||||
##
|
|
||||||
## The known suffix of the stack is as follows:
|
|
||||||
## DECLARATION lident CONTENT typ_data DEPENDS separated_nonempty_list(COMMA,var_content)
|
|
||||||
##
|
|
||||||
## WARNING: This example involves spurious reductions.
|
|
||||||
## This implies that, although the LR(1) items shown above provide an
|
|
||||||
## accurate view of the past (what has been recognized so far), they
|
|
||||||
## may provide an INCOMPLETE view of the future (what was expected next).
|
|
||||||
## In state 21, spurious reduction of production quident -> UIDENT
|
|
||||||
## In state 30, spurious reduction of production primitive_typ -> quident
|
|
||||||
## In state 296, spurious reduction of production typ_data -> primitive_typ
|
|
||||||
## In state 307, spurious reduction of production separated_nonempty_list(COMMA,var_content) -> lident CONTENT typ_data
|
|
||||||
##
|
|
||||||
|
|
||||||
expected 'equals <expression>'
|
|
||||||
|
|
||||||
source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS LIDENT CONTENT UIDENT DEFINED_AS YEAR
|
|
||||||
##
|
|
||||||
## Ends in an error in state: 374.
|
|
||||||
##
|
|
||||||
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS separated_nonempty_list(COMMA,var_content) DEFINED_AS . expression [ SCOPE END_CODE DECLARATION ]
|
|
||||||
##
|
|
||||||
## The known suffix of the stack is as follows:
|
|
||||||
## DECLARATION lident CONTENT typ_data DEPENDS separated_nonempty_list(COMMA,var_content) DEFINED_AS
|
|
||||||
##
|
|
||||||
|
|
||||||
expected an expression
|
|
||||||
|
|
||||||
source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS LIDENT CONTENT UIDENT DEFINED_AS FALSE YEAR
|
source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS LIDENT CONTENT UIDENT DEFINED_AS FALSE YEAR
|
||||||
##
|
##
|
||||||
## Ends in an error in state: 375.
|
## Ends in an error in state: 372.
|
||||||
##
|
##
|
||||||
## code_item -> DECLARATION lident CONTENT typ_data DEPENDS separated_nonempty_list(COMMA,var_content) DEFINED_AS expression . [ SCOPE END_CODE DECLARATION ]
|
|
||||||
## expression -> expression . DOT qlident [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
## expression -> expression . DOT qlident [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
||||||
## expression -> expression . OF funcall_args [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
## expression -> expression . OF funcall_args [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
||||||
## expression -> expression . WITH constructor_binding [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
## expression -> expression . WITH constructor_binding [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
||||||
@ -4270,16 +4204,17 @@ source_file: BEGIN_CODE DECLARATION LIDENT CONTENT UIDENT DEPENDS LIDENT CONTENT
|
|||||||
## expression -> expression . OR expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
## expression -> expression . OR expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
||||||
## expression -> expression . XOR expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
## expression -> expression . XOR expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
||||||
## expression -> expression . FOR lident AMONG expression SUCH THAT expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
## expression -> expression . FOR lident AMONG expression SUCH THAT expression [ XOR WITH SCOPE PLUSPLUS PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER FOR EQUAL END_CODE DOT DIV DECLARATION CONTAINS AND ]
|
||||||
|
## option(opt_def) -> DEFINED_AS expression . [ SCOPE END_CODE DECLARATION ]
|
||||||
##
|
##
|
||||||
## The known suffix of the stack is as follows:
|
## The known suffix of the stack is as follows:
|
||||||
## DECLARATION lident CONTENT typ_data DEPENDS separated_nonempty_list(COMMA,var_content) DEFINED_AS expression
|
## DEFINED_AS expression
|
||||||
##
|
##
|
||||||
|
|
||||||
expected a binary operator continuing the expression, or a keyword ending the expression and starting the next item
|
expected a binary operator continuing the expression, or a keyword ending the expression and starting the next item
|
||||||
|
|
||||||
source_file: BEGIN_DIRECTIVE YEAR
|
source_file: BEGIN_DIRECTIVE YEAR
|
||||||
##
|
##
|
||||||
## Ends in an error in state: 385.
|
## Ends in an error in state: 384.
|
||||||
##
|
##
|
||||||
## source_file_item -> BEGIN_DIRECTIVE . LAW_INCLUDE COLON nonempty_list(DIRECTIVE_ARG) option(AT_PAGE) END_DIRECTIVE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
|
## source_file_item -> BEGIN_DIRECTIVE . LAW_INCLUDE COLON nonempty_list(DIRECTIVE_ARG) option(AT_PAGE) END_DIRECTIVE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
|
||||||
##
|
##
|
||||||
@ -4291,7 +4226,7 @@ expected a directive, e.g. 'Include: <filename>'
|
|||||||
|
|
||||||
source_file: BEGIN_DIRECTIVE LAW_INCLUDE YEAR
|
source_file: BEGIN_DIRECTIVE LAW_INCLUDE YEAR
|
||||||
##
|
##
|
||||||
## Ends in an error in state: 386.
|
## Ends in an error in state: 385.
|
||||||
##
|
##
|
||||||
## source_file_item -> BEGIN_DIRECTIVE LAW_INCLUDE . COLON nonempty_list(DIRECTIVE_ARG) option(AT_PAGE) END_DIRECTIVE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
|
## source_file_item -> BEGIN_DIRECTIVE LAW_INCLUDE . COLON nonempty_list(DIRECTIVE_ARG) option(AT_PAGE) END_DIRECTIVE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
|
||||||
##
|
##
|
||||||
@ -4303,7 +4238,7 @@ expected ':', then a file name or 'JORFTEXTNNNNNNNNNNNN'
|
|||||||
|
|
||||||
source_file: BEGIN_DIRECTIVE LAW_INCLUDE COLON YEAR
|
source_file: BEGIN_DIRECTIVE LAW_INCLUDE COLON YEAR
|
||||||
##
|
##
|
||||||
## Ends in an error in state: 387.
|
## Ends in an error in state: 386.
|
||||||
##
|
##
|
||||||
## source_file_item -> BEGIN_DIRECTIVE LAW_INCLUDE COLON . nonempty_list(DIRECTIVE_ARG) option(AT_PAGE) END_DIRECTIVE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
|
## source_file_item -> BEGIN_DIRECTIVE LAW_INCLUDE COLON . nonempty_list(DIRECTIVE_ARG) option(AT_PAGE) END_DIRECTIVE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
|
||||||
##
|
##
|
||||||
@ -4315,7 +4250,7 @@ expected a file name or 'JORFTEXTNNNNNNNNNNNN'
|
|||||||
|
|
||||||
source_file: BEGIN_DIRECTIVE LAW_INCLUDE COLON DIRECTIVE_ARG YEAR
|
source_file: BEGIN_DIRECTIVE LAW_INCLUDE COLON DIRECTIVE_ARG YEAR
|
||||||
##
|
##
|
||||||
## Ends in an error in state: 388.
|
## Ends in an error in state: 387.
|
||||||
##
|
##
|
||||||
## nonempty_list(DIRECTIVE_ARG) -> DIRECTIVE_ARG . [ END_DIRECTIVE AT_PAGE ]
|
## nonempty_list(DIRECTIVE_ARG) -> DIRECTIVE_ARG . [ END_DIRECTIVE AT_PAGE ]
|
||||||
## nonempty_list(DIRECTIVE_ARG) -> DIRECTIVE_ARG . nonempty_list(DIRECTIVE_ARG) [ END_DIRECTIVE AT_PAGE ]
|
## nonempty_list(DIRECTIVE_ARG) -> DIRECTIVE_ARG . nonempty_list(DIRECTIVE_ARG) [ END_DIRECTIVE AT_PAGE ]
|
||||||
@ -4328,7 +4263,7 @@ expected a page specification in the form '@p.<number>', or a newline
|
|||||||
|
|
||||||
source_file: BEGIN_DIRECTIVE LAW_INCLUDE COLON DIRECTIVE_ARG AT_PAGE YEAR
|
source_file: BEGIN_DIRECTIVE LAW_INCLUDE COLON DIRECTIVE_ARG AT_PAGE YEAR
|
||||||
##
|
##
|
||||||
## Ends in an error in state: 392.
|
## Ends in an error in state: 391.
|
||||||
##
|
##
|
||||||
## source_file_item -> BEGIN_DIRECTIVE LAW_INCLUDE COLON nonempty_list(DIRECTIVE_ARG) option(AT_PAGE) . END_DIRECTIVE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
|
## source_file_item -> BEGIN_DIRECTIVE LAW_INCLUDE COLON nonempty_list(DIRECTIVE_ARG) option(AT_PAGE) . END_DIRECTIVE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
|
||||||
##
|
##
|
||||||
@ -4340,7 +4275,7 @@ expected a newline
|
|||||||
|
|
||||||
source_file: LAW_HEADING YEAR
|
source_file: LAW_HEADING YEAR
|
||||||
##
|
##
|
||||||
## Ends in an error in state: 397.
|
## Ends in an error in state: 396.
|
||||||
##
|
##
|
||||||
## source_file -> source_file_item . source_file [ # ]
|
## source_file -> source_file_item . source_file [ # ]
|
||||||
##
|
##
|
||||||
|
@ -658,15 +658,18 @@ let code_item :=
|
|||||||
| DECLARATION ; name = lident ;
|
| DECLARATION ; name = lident ;
|
||||||
CONTENT ; ty = addpos(typ) ;
|
CONTENT ; ty = addpos(typ) ;
|
||||||
args = depends_stance ;
|
args = depends_stance ;
|
||||||
DEFINED_AS ; e = expression ; {
|
topdef_expr = option(opt_def) ; {
|
||||||
Topdef {
|
Topdef {
|
||||||
topdef_name = name;
|
topdef_name = name;
|
||||||
topdef_args = args;
|
topdef_args = args;
|
||||||
topdef_type = type_from_args args ty;
|
topdef_type = type_from_args args ty;
|
||||||
topdef_expr = e;
|
topdef_expr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let opt_def ==
|
||||||
|
| DEFINED_AS; e = expression; <>
|
||||||
|
|
||||||
let code :=
|
let code :=
|
||||||
| code = list(addpos(code_item)) ; <>
|
| code = list(addpos(code_item)) ; <>
|
||||||
|
|
||||||
|
@ -291,6 +291,7 @@ let rec parse_source_file
|
|||||||
(match input with Some input -> close_in input | None -> ());
|
(match input with Some input -> close_in input | None -> ());
|
||||||
let program = expand_includes source_file_name commands language in
|
let program = expand_includes source_file_name commands language in
|
||||||
{
|
{
|
||||||
|
program_interfaces = [];
|
||||||
program_items = program.Ast.program_items;
|
program_items = program.Ast.program_items;
|
||||||
program_source_files = source_file_name :: program.Ast.program_source_files;
|
program_source_files = source_file_name :: program.Ast.program_source_files;
|
||||||
}
|
}
|
||||||
@ -309,6 +310,7 @@ and expand_includes
|
|||||||
let sub_source = Filename.concat source_dir (Mark.remove sub_source) in
|
let sub_source = Filename.concat source_dir (Mark.remove sub_source) in
|
||||||
let includ_program = parse_source_file (FileName sub_source) language in
|
let includ_program = parse_source_file (FileName sub_source) language in
|
||||||
{
|
{
|
||||||
|
program_interfaces = [];
|
||||||
Ast.program_source_files =
|
Ast.program_source_files =
|
||||||
acc.Ast.program_source_files @ includ_program.program_source_files;
|
acc.Ast.program_source_files @ includ_program.program_source_files;
|
||||||
Ast.program_items =
|
Ast.program_items =
|
||||||
@ -316,27 +318,71 @@ and expand_includes
|
|||||||
}
|
}
|
||||||
| Ast.LawHeading (heading, commands') ->
|
| Ast.LawHeading (heading, commands') ->
|
||||||
let {
|
let {
|
||||||
|
Ast.program_interfaces = _;
|
||||||
Ast.program_items = commands';
|
Ast.program_items = commands';
|
||||||
Ast.program_source_files = new_sources;
|
Ast.program_source_files = new_sources;
|
||||||
} =
|
} =
|
||||||
expand_includes source_file commands' language
|
expand_includes source_file commands' language
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
Ast.program_interfaces = [];
|
||||||
Ast.program_source_files = acc.Ast.program_source_files @ new_sources;
|
Ast.program_source_files = acc.Ast.program_source_files @ new_sources;
|
||||||
Ast.program_items =
|
Ast.program_items =
|
||||||
acc.Ast.program_items @ [Ast.LawHeading (heading, commands')];
|
acc.Ast.program_items @ [Ast.LawHeading (heading, commands')];
|
||||||
}
|
}
|
||||||
| i -> { acc with Ast.program_items = acc.Ast.program_items @ [i] })
|
| i -> { acc with Ast.program_items = acc.Ast.program_items @ [i] })
|
||||||
{ Ast.program_source_files = []; Ast.program_items = [] }
|
{
|
||||||
|
Ast.program_interfaces = [];
|
||||||
|
Ast.program_source_files = [];
|
||||||
|
Ast.program_items = [];
|
||||||
|
}
|
||||||
commands
|
commands
|
||||||
|
|
||||||
|
(** {2 Handling interfaces} *)
|
||||||
|
|
||||||
|
let get_interface program =
|
||||||
|
let rec filter acc = function
|
||||||
|
| Ast.LawInclude _ -> acc
|
||||||
|
| Ast.LawHeading (_, str) -> List.fold_left filter acc str
|
||||||
|
| Ast.LawText _ -> acc
|
||||||
|
| Ast.CodeBlock (code, _, true) ->
|
||||||
|
List.fold_left
|
||||||
|
(fun acc -> function
|
||||||
|
| Ast.ScopeUse _, _ -> acc
|
||||||
|
| ((Ast.ScopeDecl _ | StructDecl _ | EnumDecl _), _) as e -> e :: acc
|
||||||
|
| Ast.Topdef def, m ->
|
||||||
|
(Ast.Topdef { def with topdef_expr = None }, m) :: acc)
|
||||||
|
acc code
|
||||||
|
| Ast.CodeBlock (_, _, false) ->
|
||||||
|
(* Non-metadata blocks are ignored *)
|
||||||
|
acc
|
||||||
|
in
|
||||||
|
List.fold_left filter [] program.Ast.program_items
|
||||||
|
|
||||||
|
let qualify_interface path code_items =
|
||||||
|
List.map (fun item -> path, item) code_items
|
||||||
|
|
||||||
(** {1 API} *)
|
(** {1 API} *)
|
||||||
|
|
||||||
|
let add_interface source_file language path program =
|
||||||
|
let interface =
|
||||||
|
parse_source_file source_file language
|
||||||
|
|> get_interface
|
||||||
|
|> qualify_interface path
|
||||||
|
in
|
||||||
|
{
|
||||||
|
program with
|
||||||
|
Ast.program_interfaces =
|
||||||
|
List.append interface program.Ast.program_interfaces;
|
||||||
|
}
|
||||||
|
|
||||||
let parse_top_level_file
|
let parse_top_level_file
|
||||||
(source_file : Pos.input_file)
|
(source_file : Pos.input_file)
|
||||||
(language : Cli.backend_lang) : Ast.program =
|
(language : Cli.backend_lang) : Ast.program =
|
||||||
let program = parse_source_file source_file language in
|
let program = parse_source_file source_file language in
|
||||||
|
let interface = get_interface program in
|
||||||
{
|
{
|
||||||
program with
|
program with
|
||||||
Ast.program_items = law_struct_list_to_tree program.Ast.program_items;
|
Ast.program_items = law_struct_list_to_tree program.Ast.program_items;
|
||||||
|
Ast.program_interfaces = qualify_interface [] interface;
|
||||||
}
|
}
|
||||||
|
@ -19,4 +19,13 @@
|
|||||||
|
|
||||||
open Catala_utils
|
open Catala_utils
|
||||||
|
|
||||||
|
val add_interface :
|
||||||
|
Pos.input_file ->
|
||||||
|
Cli.backend_lang ->
|
||||||
|
Shared_ast.Qident.path ->
|
||||||
|
Ast.program ->
|
||||||
|
Ast.program
|
||||||
|
(** Reads only declarations in metadata in the supplied input file, and add them
|
||||||
|
to the given program *)
|
||||||
|
|
||||||
val parse_top_level_file : Pos.input_file -> Cli.backend_lang -> Ast.program
|
val parse_top_level_file : Pos.input_file -> Cli.backend_lang -> Ast.program
|
||||||
|
@ -656,6 +656,7 @@ and translate_expr (ctx : context) (vc : typed expr) : context * Expr.expr =
|
|||||||
of a match. It actually corresponds to applying an accessor to an enum,
|
of a match. It actually corresponds to applying an accessor to an enum,
|
||||||
the corresponding Z3 expression was previously stored in the context *)
|
the corresponding Z3 expression was previously stored in the context *)
|
||||||
ctx, e)
|
ctx, e)
|
||||||
|
| EExternal _ -> failwith "[Z3 encoding] EExternal unsupported"
|
||||||
| EStruct _ -> failwith "[Z3 encoding] EStruct unsupported"
|
| EStruct _ -> failwith "[Z3 encoding] EStruct unsupported"
|
||||||
| EStructAccess { e; field; name } ->
|
| EStructAccess { e; field; name } ->
|
||||||
let ctx, z3_struct = find_or_create_struct ctx name in
|
let ctx, z3_struct = find_or_create_struct ctx name in
|
||||||
|
@ -6,8 +6,8 @@ LATEXMK?=latexmk
|
|||||||
|
|
||||||
CURR_DIR=examples/$(shell basename $(shell pwd))/
|
CURR_DIR=examples/$(shell basename $(shell pwd))/
|
||||||
|
|
||||||
CATALA=cd ../../; _build/default/compiler/catala.exe \
|
CATALA=cd ../../; _build/default/compiler/catala.exe
|
||||||
$(CATALA_OPTS) --language=$(CATALA_LANG)
|
CATALA_OPTS := $(CATALA_OPTS) --language=$(CATALA_LANG)
|
||||||
|
|
||||||
PLUGIN_DIR=_build/default/compiler/plugins
|
PLUGIN_DIR=_build/default/compiler/plugins
|
||||||
|
|
||||||
@ -20,49 +20,43 @@ help : ../Makefile.common.mk
|
|||||||
|
|
||||||
#> SCOPE=<ScopeName> <target_file>.run : Runs the interpeter for the scope of the file
|
#> SCOPE=<ScopeName> <target_file>.run : Runs the interpeter for the scope of the file
|
||||||
%.run: %.catala_$(CATALA_LANG)
|
%.run: %.catala_$(CATALA_LANG)
|
||||||
@$(CATALA) Makefile $(CURR_DIR)$<
|
@$(CATALA) Makefile $(CATALA_OPTS) $(CURR_DIR)$<
|
||||||
$(CATALA) \
|
$(CATALA) Interpret $(CATALA_OPTS) \
|
||||||
Interpret \
|
|
||||||
-s $(SCOPE) \
|
-s $(SCOPE) \
|
||||||
$(CURR_DIR)$<
|
$(CURR_DIR)$<
|
||||||
|
|
||||||
#> <target_file>.ml : Compiles the file to OCaml
|
#> <target_file>.ml : Compiles the file to OCaml
|
||||||
%.ml: %.catala_$(CATALA_LANG)
|
%.ml: %.catala_$(CATALA_LANG)
|
||||||
@$(CATALA) Makefile $(CURR_DIR)$<
|
@$(CATALA) Makefile $(CATALA_OPTS) $(CURR_DIR)$<
|
||||||
$(CATALA) \
|
$(CATALA) OCaml $(CATALA_OPTS) \
|
||||||
OCaml \
|
|
||||||
$(CURR_DIR)$<
|
$(CURR_DIR)$<
|
||||||
|
|
||||||
#> <target_file>_api_web.ml : Compiles the file to OCaml + generates the API web
|
#> <target_file>_api_web.ml : Compiles the file to OCaml + generates the API web
|
||||||
%_api_web.ml: %.catala_$(CATALA_LANG)
|
%_api_web.ml: %.catala_$(CATALA_LANG)
|
||||||
@$(CATALA) Makefile $(CURR_DIR)$<
|
@$(CATALA) Makefile $(CATALA_OPTS) $(CURR_DIR)$<
|
||||||
$(CATALA) \
|
$(CATALA) api_web $(CATALA_OPTS) \
|
||||||
api_web \
|
|
||||||
--plugin-dir=$(PLUGIN_DIR) \
|
--plugin-dir=$(PLUGIN_DIR) \
|
||||||
$(CURR_DIR)$<
|
$(CURR_DIR)$<
|
||||||
|
|
||||||
#> SCOPE=<ScopeName> <target_file>_api_web.ml : Generates the JSON schema
|
#> SCOPE=<ScopeName> <target_file>_api_web.ml : Generates the JSON schema
|
||||||
%_schema.json: %.catala_$(CATALA_LANG)
|
%_schema.json: %.catala_$(CATALA_LANG)
|
||||||
@$(CATALA) Makefile $(CURR_DIR)$<
|
@$(CATALA) Makefile $(CATALA_OPTS) $(CURR_DIR)$<
|
||||||
$(CATALA) \
|
$(CATALA) json_schema $(CATALA_OPTS) \
|
||||||
json_schema \
|
|
||||||
--plugin-dir=$(PLUGIN_DIR) \
|
--plugin-dir=$(PLUGIN_DIR) \
|
||||||
-s $(SCOPE) \
|
-s $(SCOPE) \
|
||||||
$(CURR_DIR)$<
|
$(CURR_DIR)$<
|
||||||
|
|
||||||
#> <target_file>.py : Compiles the file to Python
|
#> <target_file>.py : Compiles the file to Python
|
||||||
%.py: %.catala_$(CATALA_LANG)
|
%.py: %.catala_$(CATALA_LANG)
|
||||||
@$(CATALA) Makefile $(CURR_DIR)$<
|
@$(CATALA) Makefile $(CATALA_OPTS) $(CURR_DIR)$<
|
||||||
$(CATALA) \
|
$(CATALA) Python $(CATALA_OPTS) \
|
||||||
Python \
|
|
||||||
$(CURR_DIR)$<
|
$(CURR_DIR)$<
|
||||||
|
|
||||||
#> <target_file>.tex : Weaves the file to LaTeX
|
#> <target_file>.tex : Weaves the file to LaTeX
|
||||||
%.tex: %.catala_$(CATALA_LANG)
|
%.tex: %.catala_$(CATALA_LANG)
|
||||||
@$(CATALA) Makefile $(CURR_DIR)$<
|
@$(CATALA) Makefile $(CATALA_OPTS) $(CURR_DIR)$<
|
||||||
$(CATALA) \
|
$(CATALA) LaTeX $(CATALA_OPTS) \
|
||||||
--wrap \
|
--wrap \
|
||||||
LaTeX \
|
|
||||||
$(CURR_DIR)$<
|
$(CURR_DIR)$<
|
||||||
|
|
||||||
#> <target_file>.pdf : Weaves the file to PDF (via XeLaTeX)
|
#> <target_file>.pdf : Weaves the file to PDF (via XeLaTeX)
|
||||||
@ -71,10 +65,9 @@ help : ../Makefile.common.mk
|
|||||||
|
|
||||||
#> <target_file>.html : Weaves the file to HTML
|
#> <target_file>.html : Weaves the file to HTML
|
||||||
%.html: %.catala_$(CATALA_LANG)
|
%.html: %.catala_$(CATALA_LANG)
|
||||||
@$(CATALA) Makefile $(CURR_DIR)$<
|
@$(CATALA) Makefile $(CATALA_OPTS) $(CURR_DIR)$<
|
||||||
$(CATALA) \
|
$(CATALA) HTML $(CATALA_OPTS) \
|
||||||
--wrap \
|
--wrap \
|
||||||
HTML \
|
|
||||||
$(CURR_DIR)$<
|
$(CURR_DIR)$<
|
||||||
|
|
||||||
%.spellok: %.catala_$(CATALA_LANG) ../whitelist.$(CATALA_LANG)
|
%.spellok: %.catala_$(CATALA_LANG) ../whitelist.$(CATALA_LANG)
|
||||||
|
@ -737,3 +737,23 @@ module Oper = struct
|
|||||||
end
|
end
|
||||||
|
|
||||||
include Oper
|
include Oper
|
||||||
|
|
||||||
|
type hash = string
|
||||||
|
|
||||||
|
let modules_table : (string, hash) Hashtbl.t = Hashtbl.create 13
|
||||||
|
let values_table : (string list * string, Obj.t) Hashtbl.t = Hashtbl.create 13
|
||||||
|
|
||||||
|
let register_module modname values hash =
|
||||||
|
Hashtbl.add modules_table modname hash;
|
||||||
|
List.iter (fun (id, v) -> Hashtbl.add values_table ([modname], id) v) values
|
||||||
|
|
||||||
|
let check_module m h = String.equal (Hashtbl.find modules_table m) h
|
||||||
|
|
||||||
|
let lookup_value qid =
|
||||||
|
try Hashtbl.find values_table qid
|
||||||
|
with Not_found ->
|
||||||
|
failwith
|
||||||
|
("Could not resolve reference to "
|
||||||
|
^ String.concat "." (fst qid)
|
||||||
|
^ "."
|
||||||
|
^ snd qid)
|
||||||
|
@ -385,3 +385,21 @@ module Oper : sig
|
|||||||
end
|
end
|
||||||
|
|
||||||
include module type of Oper
|
include module type of Oper
|
||||||
|
|
||||||
|
(** Modules API *)
|
||||||
|
|
||||||
|
type hash = string
|
||||||
|
|
||||||
|
val register_module : string -> (string * Obj.t) list -> hash -> unit
|
||||||
|
(** Registers a module by the given name defining the given bindings. Required
|
||||||
|
for evaluation to be able to access the given values. The last argument is
|
||||||
|
expected to be a hash of the source file and the Catala version, and will in
|
||||||
|
time be used to ensure that the module and the interface are in sync *)
|
||||||
|
|
||||||
|
val check_module : string -> hash -> bool
|
||||||
|
(** Returns [true] if it has been registered with the correct hash, [false] if
|
||||||
|
there is a hash mismatch.
|
||||||
|
|
||||||
|
@raise Not_found if the module does not exist at all *)
|
||||||
|
|
||||||
|
val lookup_value : string list * string -> Obj.t
|
||||||
|
@ -17,12 +17,14 @@ scope ScopeB:
|
|||||||
|
|
||||||
```catala-test-inline
|
```catala-test-inline
|
||||||
$ catala OCaml -O
|
$ catala OCaml -O
|
||||||
|
|
||||||
(** This file has been generated by the Catala compiler, do not edit! *)
|
(** This file has been generated by the Catala compiler, do not edit! *)
|
||||||
|
|
||||||
open Runtime_ocaml.Runtime
|
open Runtime_ocaml.Runtime
|
||||||
|
|
||||||
[@@@ocaml.warning "-4-26-27-32-41-42"]
|
[@@@ocaml.warning "-4-26-27-32-41-42"]
|
||||||
|
|
||||||
|
|
||||||
module ScopeA = struct
|
module ScopeA = struct
|
||||||
type t = {a: bool}
|
type t = {a: bool}
|
||||||
end
|
end
|
||||||
@ -58,4 +60,9 @@ let scope_b (scope_b_in: ScopeBIn.t) : ScopeB.t =
|
|||||||
start_line=8; start_column=10; end_line=8; end_column=11;
|
start_line=8; start_column=10; end_line=8; end_column=11;
|
||||||
law_headings=["Article"]})) in
|
law_headings=["Article"]})) in
|
||||||
{ScopeB.a = a_}
|
{ScopeB.a = a_}
|
||||||
|
let () =
|
||||||
|
Runtime_ocaml.Runtime.register_module "191_fix_record_name_confusion"
|
||||||
|
[ "ScopeA", Obj.repr scope_a;
|
||||||
|
"ScopeB", Obj.repr scope_b ]
|
||||||
|
"todo-module-hash"
|
||||||
```
|
```
|
||||||
|
Loading…
Reference in New Issue
Block a user