Add a --no-typing option

it is useful e.g. to be able to print intermediate ASTs when they don't type, to
debug the typing errors. This is better than commenting the typing line each
time.

Note that the option is not available on all targets (esp. not for ocaml and
python outputs ; it's allowed on the interpreters for debugging purposes but I'm
not sure if that's a good idea)
This commit is contained in:
Louis Gesbert 2023-11-02 14:36:55 +01:00
parent 9425753eca
commit b98bad8c33
6 changed files with 100 additions and 41 deletions

View File

@ -346,6 +346,10 @@ module Flags = struct
& flag & flag
& info ["check_invariants"] ~doc:"Check structural invariants on the AST." & info ["check_invariants"] ~doc:"Check structural invariants on the AST."
let no_typing =
value & flag & info ["no-typing"] ~doc:
"Don't check the consistency of types"
let wrap_weaved_output = let wrap_weaved_output =
value value
& flag & flag

View File

@ -113,6 +113,7 @@ module Flags : sig
(** Parsers for all flags and options that commands can use *) (** Parsers for all flags and options that commands can use *)
val check_invariants : bool Term.t val check_invariants : bool Term.t
val no_typing : bool Term.t
val wrap_weaved_output : bool Term.t val wrap_weaved_output : bool Term.t
val print_only_law : bool Term.t val print_only_law : bool Term.t
val ex_scope : string Term.t val ex_scope : string Term.t

View File

@ -141,20 +141,32 @@ module Passes = struct
in in
prg, ctx, exceptions_graphs prg, ctx, exceptions_graphs
let dcalc options ~includes ~optimize ~check_invariants : let dcalc:
typed Dcalc.Ast.program type ty.
* Desugared.Name_resolution.context Cli.options -> includes:Cli.raw_file list -> optimize:bool -> check_invariants:bool ->
* Scopelang.Dependency.TVertex.t list = typed: ty mark ->
ty Dcalc.Ast.program
* Desugared.Name_resolution.context
* Scopelang.Dependency.TVertex.t list =
fun options ~includes ~optimize ~check_invariants ~typed ->
let prg, ctx, _ = scopelang options ~includes in let prg, ctx, _ = scopelang options ~includes in
debug_pass_name "dcalc"; debug_pass_name "dcalc";
let type_ordering = let type_ordering =
Scopelang.Dependency.check_type_cycles prg.program_ctx.ctx_structs Scopelang.Dependency.check_type_cycles prg.program_ctx.ctx_structs
prg.program_ctx.ctx_enums prg.program_ctx.ctx_enums
in in
Message.emit_debug "Typechecking..."; let (prg: ty Scopelang.Ast.program) =
let prg = Scopelang.Ast.type_program prg in match typed with
| Typed _ ->
Message.emit_debug "Typechecking...";
Scopelang.Ast.type_program prg
| Untyped _ -> prg
| Custom _ -> invalid_arg "Driver.Passes.dcalc"
in
Message.emit_debug "Translating to default calculus..."; Message.emit_debug "Translating to default calculus...";
let prg = Dcalc.From_scopelang.translate_program prg in let prg =
Dcalc.From_scopelang.translate_program prg
in
let prg = let prg =
if optimize then begin if optimize then begin
Message.emit_debug "Optimizing default calculus..."; Message.emit_debug "Optimizing default calculus...";
@ -162,47 +174,64 @@ module Passes = struct
end end
else prg else prg
in in
Message.emit_debug "Typechecking again..."; let (prg: ty Dcalc.Ast.program) =
let prg = match typed with
try Typing.program ~leave_unresolved:false prg | Typed _ ->
with Message.CompilerError error_content -> Message.emit_debug "Typechecking again...";
let bt = Printexc.get_raw_backtrace () in (try Typing.program ~leave_unresolved:false prg
Printexc.raise_with_backtrace with Message.CompilerError error_content ->
(Message.CompilerError let bt = Printexc.get_raw_backtrace () in
(Message.Content.to_internal_error error_content)) Printexc.raise_with_backtrace
bt (Message.CompilerError
(Message.Content.to_internal_error error_content))
bt)
| Untyped _ -> prg
| Custom _ -> assert false
in in
if check_invariants then ( if check_invariants then (
Message.emit_debug "Checking invariants..."; Message.emit_debug "Checking invariants...";
let result = Dcalc.Invariants.check_all_invariants prg in match typed with
if not result then | Typed _ ->
raise (Message.raise_internal_error "Some Dcalc invariants are invalid")); let result = Dcalc.Invariants.check_all_invariants prg in
if not result then
raise (Message.raise_internal_error "Some Dcalc invariants are invalid")
| _ ->
Message.raise_error "--check_invariants cannot be used with --no-typing");
prg, ctx, type_ordering prg, ctx, type_ordering
let lcalc let lcalc (type ty)
options options
~includes ~includes
~optimize ~optimize
~check_invariants ~check_invariants
~(typed: ty mark)
~avoid_exceptions ~avoid_exceptions
~closure_conversion : ~closure_conversion :
untyped Lcalc.Ast.program untyped Lcalc.Ast.program
* Desugared.Name_resolution.context * Desugared.Name_resolution.context
* Scopelang.Dependency.TVertex.t list = * Scopelang.Dependency.TVertex.t list =
let prg, ctx, type_ordering = let prg, ctx, type_ordering =
dcalc options ~includes ~optimize ~check_invariants dcalc options ~includes ~optimize ~check_invariants ~typed
in in
debug_pass_name "lcalc"; debug_pass_name "lcalc";
let avoid_exceptions = avoid_exceptions || closure_conversion in let avoid_exceptions = avoid_exceptions || closure_conversion in
let optimize = optimize || closure_conversion in let optimize = optimize || closure_conversion in
(* --closure_conversion implies --avoid_exceptions and --optimize *) (* --closure_conversion implies --avoid_exceptions and --optimize *)
let prg = let prg =
if avoid_exceptions then ( match avoid_exceptions, options.trace, typed with
if options.trace then | true, true, _ ->
Message.raise_error Message.raise_error
"Option --avoid_exceptions is not compatible with option --trace"; "Option --avoid_exceptions is not compatible with option --trace"
Lcalc.Compile_without_exceptions.translate_program prg) | true, _, Untyped _ ->
else Program.untype (Lcalc.Compile_with_exceptions.translate_program prg) Message.raise_error
"Option --avoid_exceptions is not compatible with option --no-typing"
| true, _, Typed _ ->
Lcalc.Compile_without_exceptions.translate_program prg
| false, _, Typed _ ->
Program.untype (Lcalc.Compile_with_exceptions.translate_program prg)
| false, _, Untyped _ ->
Lcalc.Compile_with_exceptions.translate_program prg
| _, _, Custom _ -> invalid_arg "Driver.Passes.lcalc"
in in
let prg = let prg =
if optimize then begin if optimize then begin
@ -240,7 +269,7 @@ module Passes = struct
* Desugared.Name_resolution.context * Desugared.Name_resolution.context
* Scopelang.Dependency.TVertex.t list = * Scopelang.Dependency.TVertex.t list =
let prg, ctx, type_ordering = let prg, ctx, type_ordering =
lcalc options ~includes ~optimize ~check_invariants ~avoid_exceptions lcalc options ~includes ~optimize ~check_invariants ~typed:Expr.typed ~avoid_exceptions
~closure_conversion ~closure_conversion
in in
debug_pass_name "scalc"; debug_pass_name "scalc";
@ -507,9 +536,10 @@ module Commands = struct
~doc:"Parses and typechecks a Catala program, without interpreting it.") ~doc:"Parses and typechecks a Catala program, without interpreting it.")
Term.(const typecheck $ Cli.Flags.Global.options $ Cli.Flags.include_dirs) Term.(const typecheck $ Cli.Flags.Global.options $ Cli.Flags.include_dirs)
let dcalc options includes output optimize ex_scope_opt check_invariants = let dcalc typed options includes output optimize ex_scope_opt check_invariants
=
let prg, ctx, _ = let prg, ctx, _ =
Passes.dcalc options ~includes ~optimize ~check_invariants Passes.dcalc options ~includes ~optimize ~check_invariants ~typed
in in
let _output_file, with_output = get_output_format options output in let _output_file, with_output = get_output_format options output in
with_output with_output
@ -537,6 +567,9 @@ module Commands = struct
prg_dcalc_expr prg_dcalc_expr
let dcalc_cmd = let dcalc_cmd =
let f no_typing =
if no_typing then dcalc Expr.untyped else dcalc Expr.typed
in
Cmd.v Cmd.v
(Cmd.info "dcalc" (Cmd.info "dcalc"
~doc: ~doc:
@ -544,7 +577,8 @@ module Commands = struct
representation of the Catala program. Use the $(b,-s) option to \ representation of the Catala program. Use the $(b,-s) option to \
restrict the output to a particular scope.") restrict the output to a particular scope.")
Term.( Term.(
const dcalc const f
$ Cli.Flags.no_typing
$ Cli.Flags.Global.options $ Cli.Flags.Global.options
$ Cli.Flags.include_dirs $ Cli.Flags.include_dirs
$ Cli.Flags.output $ Cli.Flags.output
@ -560,7 +594,7 @@ module Commands = struct
check_invariants check_invariants
disable_counterexamples = disable_counterexamples =
let prg, ctx, _ = let prg, ctx, _ =
Passes.dcalc options ~includes ~optimize ~check_invariants Passes.dcalc options ~includes ~optimize ~check_invariants ~typed:Expr.typed
in in
Verification.Globals.setup ~optimize ~disable_counterexamples; Verification.Globals.setup ~optimize ~disable_counterexamples;
let vcs = let vcs =
@ -608,15 +642,16 @@ module Commands = struct
result) result)
results results
let interpret_dcalc options includes optimize check_invariants ex_scope = let interpret_dcalc typed options includes optimize check_invariants ex_scope =
let prg, ctx, _ = let prg, ctx, _ =
Passes.dcalc options ~includes ~optimize ~check_invariants Passes.dcalc options ~includes ~optimize ~check_invariants ~typed
in in
Interpreter.load_runtime_modules prg; Interpreter.load_runtime_modules prg;
print_interpretation_results options Interpreter.interpret_program_dcalc prg print_interpretation_results options Interpreter.interpret_program_dcalc prg
(get_scope_uid ctx ex_scope) (get_scope_uid ctx ex_scope)
let interpret_cmd = let interpret_cmd =
let f no_typing = if no_typing then interpret_dcalc Expr.untyped else interpret_dcalc Expr.typed in
Cmd.v Cmd.v
(Cmd.info "interpret" (Cmd.info "interpret"
~doc: ~doc:
@ -624,7 +659,8 @@ module Commands = struct
specified by the $(b,-s) option assuming no additional external \ specified by the $(b,-s) option assuming no additional external \
inputs.") inputs.")
Term.( Term.(
const interpret_dcalc const f
$ Cli.Flags.no_typing
$ Cli.Flags.Global.options $ Cli.Flags.Global.options
$ Cli.Flags.include_dirs $ Cli.Flags.include_dirs
$ Cli.Flags.optimize $ Cli.Flags.optimize
@ -632,6 +668,7 @@ module Commands = struct
$ Cli.Flags.ex_scope) $ Cli.Flags.ex_scope)
let lcalc let lcalc
typed
options options
includes includes
output output
@ -642,7 +679,7 @@ module Commands = struct
ex_scope_opt = ex_scope_opt =
let prg, ctx, _ = let prg, ctx, _ =
Passes.lcalc options ~includes ~optimize ~check_invariants Passes.lcalc options ~includes ~optimize ~check_invariants
~avoid_exceptions ~closure_conversion ~avoid_exceptions ~closure_conversion ~typed
in in
let _output_file, with_output = get_output_format options output in let _output_file, with_output = get_output_format options output in
with_output with_output
@ -658,6 +695,9 @@ module Commands = struct
Format.pp_print_newline fmt () Format.pp_print_newline fmt ()
let lcalc_cmd = let lcalc_cmd =
let f no_typing =
if no_typing then lcalc Expr.untyped else lcalc Expr.typed
in
Cmd.v Cmd.v
(Cmd.info "lcalc" (Cmd.info "lcalc"
~doc: ~doc:
@ -665,7 +705,8 @@ module Commands = struct
representation of the Catala program. Use the $(b,-s) option to \ representation of the Catala program. Use the $(b,-s) option to \
restrict the output to a particular scope.") restrict the output to a particular scope.")
Term.( Term.(
const lcalc const f
$ Cli.Flags.no_typing
$ Cli.Flags.Global.options $ Cli.Flags.Global.options
$ Cli.Flags.include_dirs $ Cli.Flags.include_dirs
$ Cli.Flags.output $ Cli.Flags.output
@ -676,6 +717,7 @@ module Commands = struct
$ Cli.Flags.ex_scope_opt) $ Cli.Flags.ex_scope_opt)
let interpret_lcalc let interpret_lcalc
typed
options options
includes includes
optimize optimize
@ -685,13 +727,16 @@ module Commands = struct
ex_scope = ex_scope =
let prg, ctx, _ = let prg, ctx, _ =
Passes.lcalc options ~includes ~optimize ~check_invariants Passes.lcalc options ~includes ~optimize ~check_invariants
~avoid_exceptions ~closure_conversion ~avoid_exceptions ~closure_conversion ~typed
in in
Interpreter.load_runtime_modules prg; Interpreter.load_runtime_modules prg;
print_interpretation_results options Interpreter.interpret_program_lcalc prg print_interpretation_results options Interpreter.interpret_program_lcalc prg
(get_scope_uid ctx ex_scope) (get_scope_uid ctx ex_scope)
let interpret_lcalc_cmd = let interpret_lcalc_cmd =
let f no_typing =
if no_typing then interpret_lcalc Expr.untyped else interpret_lcalc Expr.typed
in
Cmd.v Cmd.v
(Cmd.info "interpret_lcalc" (Cmd.info "interpret_lcalc"
~doc: ~doc:
@ -699,7 +744,8 @@ module Commands = struct
executing the scope specified by the $(b,-s) option assuming no \ executing the scope specified by the $(b,-s) option assuming no \
additional external inputs.") additional external inputs.")
Term.( Term.(
const interpret_lcalc const f
$ Cli.Flags.no_typing
$ Cli.Flags.Global.options $ Cli.Flags.Global.options
$ Cli.Flags.include_dirs $ Cli.Flags.include_dirs
$ Cli.Flags.optimize $ Cli.Flags.optimize
@ -718,7 +764,7 @@ module Commands = struct
closure_conversion = closure_conversion =
let prg, _, type_ordering = let prg, _, type_ordering =
Passes.lcalc options ~includes ~optimize ~check_invariants Passes.lcalc options ~includes ~optimize ~check_invariants
~avoid_exceptions ~closure_conversion ~avoid_exceptions ~closure_conversion ~typed:Expr.typed
in in
let output_file, with_output = let output_file, with_output =
get_output_format options ~ext:".ml" output get_output_format options ~ext:".ml" output

View File

@ -44,7 +44,8 @@ module Passes : sig
includes:Cli.raw_file list -> includes:Cli.raw_file list ->
optimize:bool -> optimize:bool ->
check_invariants:bool -> check_invariants:bool ->
Shared_ast.typed Dcalc.Ast.program typed:'m Shared_ast.mark ->
'm Dcalc.Ast.program
* Desugared.Name_resolution.context * Desugared.Name_resolution.context
* Scopelang.Dependency.TVertex.t list * Scopelang.Dependency.TVertex.t list
@ -53,6 +54,7 @@ module Passes : sig
includes:Cli.raw_file list -> includes:Cli.raw_file list ->
optimize:bool -> optimize:bool ->
check_invariants:bool -> check_invariants:bool ->
typed:'m Shared_ast.mark ->
avoid_exceptions:bool -> avoid_exceptions:bool ->
closure_conversion:bool -> closure_conversion:bool ->
Shared_ast.untyped Lcalc.Ast.program Shared_ast.untyped Lcalc.Ast.program

View File

@ -248,6 +248,9 @@ let maybe_ty (type m) ?(typ = TAny) (m : m mark) : typ =
| Untyped { pos } | Custom { pos; _ } -> Mark.add pos typ | Untyped { pos } | Custom { pos; _ } -> Mark.add pos typ
| Typed { ty; _ } -> ty | Typed { ty; _ } -> ty
let untyped = Untyped { pos = Pos.no_pos }
let typed = Typed { pos = Pos.no_pos; ty = TLit TUnit, Pos.no_pos }
(* - Predefined types (option) - *) (* - Predefined types (option) - *)
let option_enum = EnumName.fresh [] ("eoption", Pos.no_pos) let option_enum = EnumName.fresh [] ("eoption", Pos.no_pos)

View File

@ -193,6 +193,9 @@ val maybe_ty : ?typ:naked_typ -> 'm mark -> typ
(** Returns the corresponding type on a typed expr, or [typ] (defaulting to (** Returns the corresponding type on a typed expr, or [typ] (defaulting to
[TAny]) at the current position on an untyped one *) [TAny]) at the current position on an untyped one *)
val untyped : untyped mark (** Type witness for untyped marks *)
val typed : typed mark (** Type witness for untyped marks *)
(** {2 Predefined types} *) (** {2 Predefined types} *)
val option_enum : EnumName.t val option_enum : EnumName.t