2022-02-14 20:22:26 +03:00
|
|
|
(* This file is part of the Catala compiler, a specification language for tax
|
|
|
|
and social benefits computation rules. Copyright (C) 2022 Inria, contributor:
|
|
|
|
Denis Merigoux <denis.merigoux@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. *)
|
|
|
|
|
|
|
|
open Utils
|
2022-08-12 23:42:39 +03:00
|
|
|
open Shared_ast
|
2022-02-14 20:22:26 +03:00
|
|
|
open Ast
|
|
|
|
|
2022-05-30 12:20:48 +03:00
|
|
|
let needs_parens (_e : expr Marked.pos) : bool = false
|
2022-02-14 20:22:26 +03:00
|
|
|
|
|
|
|
let format_local_name (fmt : Format.formatter) (v : LocalName.t) : unit =
|
|
|
|
Format.fprintf fmt "%a_%s" LocalName.format_t v
|
|
|
|
(string_of_int (LocalName.hash v))
|
|
|
|
|
|
|
|
let rec format_expr
|
2022-08-12 23:42:39 +03:00
|
|
|
(decl_ctx : decl_ctx)
|
2022-02-14 20:22:26 +03:00
|
|
|
?(debug : bool = false)
|
|
|
|
(fmt : Format.formatter)
|
2022-05-30 12:20:48 +03:00
|
|
|
(e : expr Marked.pos) : unit =
|
2022-02-14 20:22:26 +03:00
|
|
|
let format_expr = format_expr decl_ctx ~debug in
|
2022-05-30 12:20:48 +03:00
|
|
|
let format_with_parens (fmt : Format.formatter) (e : expr Marked.pos) =
|
2022-02-14 20:22:26 +03:00
|
|
|
if needs_parens e then
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "%a%a%a" Print.punctuation "(" format_expr e
|
|
|
|
Print.punctuation ")"
|
2022-02-14 20:22:26 +03:00
|
|
|
else Format.fprintf fmt "%a" format_expr e
|
|
|
|
in
|
2022-05-30 12:20:48 +03:00
|
|
|
match Marked.unmark e with
|
2022-02-14 20:22:26 +03:00
|
|
|
| EVar v -> Format.fprintf fmt "%a" format_local_name v
|
|
|
|
| EFunc v -> Format.fprintf fmt "%a" TopLevelName.format_t v
|
|
|
|
| EStruct (es, s) ->
|
2022-08-12 23:42:39 +03:00
|
|
|
Format.fprintf fmt "@[<hov 2>%a@ %a%a%a@]" StructName.format_t s
|
2022-08-17 17:14:14 +03:00
|
|
|
Print.punctuation "{"
|
2022-02-14 20:22:26 +03:00
|
|
|
(Format.pp_print_list
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
|
|
|
|
(fun fmt (e, struct_field) ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "%a%a%a%a %a" Print.punctuation "\""
|
|
|
|
StructFieldName.format_t struct_field Print.punctuation "\""
|
|
|
|
Print.punctuation ":" format_expr e))
|
2022-08-16 11:04:01 +03:00
|
|
|
(List.combine es (List.map fst (StructMap.find s decl_ctx.ctx_structs)))
|
2022-08-17 17:14:14 +03:00
|
|
|
Print.punctuation "}"
|
2022-02-14 20:22:26 +03:00
|
|
|
| EArray es ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "@[<hov 2>%a%a%a@]" Print.punctuation "["
|
2022-02-14 20:22:26 +03:00
|
|
|
(Format.pp_print_list
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt ";@ ")
|
|
|
|
(fun fmt e -> Format.fprintf fmt "%a" format_expr e))
|
2022-08-17 17:14:14 +03:00
|
|
|
es Print.punctuation "]"
|
2022-02-14 20:22:26 +03:00
|
|
|
| EStructFieldAccess (e1, field, s) ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "%a%a%a%a%a" format_expr e1 Print.punctuation "."
|
|
|
|
Print.punctuation "\"" StructFieldName.format_t
|
2022-02-14 20:22:26 +03:00
|
|
|
(fst
|
|
|
|
(List.find
|
2022-08-16 11:04:01 +03:00
|
|
|
(fun (field', _) -> StructFieldName.compare field' field = 0)
|
2022-08-12 23:42:39 +03:00
|
|
|
(StructMap.find s decl_ctx.ctx_structs)))
|
2022-08-17 17:14:14 +03:00
|
|
|
Print.punctuation "\""
|
2022-02-14 20:22:26 +03:00
|
|
|
| EInj (e, case, enum) ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "@[<hov 2>%a@ %a@]" Print.enum_constructor
|
2022-02-14 20:22:26 +03:00
|
|
|
(fst
|
|
|
|
(List.find
|
2022-08-12 23:42:39 +03:00
|
|
|
(fun (case', _) -> EnumConstructor.compare case' case = 0)
|
|
|
|
(EnumMap.find enum decl_ctx.ctx_enums)))
|
2022-02-14 20:22:26 +03:00
|
|
|
format_expr e
|
2022-08-17 17:14:14 +03:00
|
|
|
| ELit l -> Print.lit fmt l
|
2022-08-16 11:04:01 +03:00
|
|
|
| EApp ((EOp (Binop ((Map | Filter) as op)), _), [arg1; arg2]) ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "@[<hov 2>%a@ %a@ %a@]" Print.binop op format_with_parens
|
|
|
|
arg1 format_with_parens arg2
|
2022-02-14 20:22:26 +03:00
|
|
|
| EApp ((EOp (Binop op), _), [arg1; arg2]) ->
|
|
|
|
Format.fprintf fmt "@[<hov 2>%a@ %a@ %a@]" format_with_parens arg1
|
2022-08-17 17:14:14 +03:00
|
|
|
Print.binop op format_with_parens arg2
|
2022-02-14 20:22:26 +03:00
|
|
|
| EApp ((EOp (Unop (Log _)), _), [arg1]) when not debug ->
|
|
|
|
Format.fprintf fmt "%a" format_with_parens arg1
|
|
|
|
| EApp ((EOp (Unop op), _), [arg1]) ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "@[<hov 2>%a@ %a@]" Print.unop op format_with_parens arg1
|
2022-02-14 20:22:26 +03:00
|
|
|
| EApp (f, args) ->
|
|
|
|
Format.fprintf fmt "@[<hov 2>%a@ %a@]" format_expr f
|
|
|
|
(Format.pp_print_list
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ")
|
|
|
|
format_with_parens)
|
|
|
|
args
|
2022-08-17 17:14:14 +03:00
|
|
|
| EOp (Ternop op) -> Format.fprintf fmt "%a" Print.ternop op
|
|
|
|
| EOp (Binop op) -> Format.fprintf fmt "%a" Print.binop op
|
|
|
|
| EOp (Unop op) -> Format.fprintf fmt "%a" Print.unop op
|
2022-02-14 20:22:26 +03:00
|
|
|
|
|
|
|
let rec format_statement
|
2022-08-12 23:42:39 +03:00
|
|
|
(decl_ctx : decl_ctx)
|
2022-02-14 20:22:26 +03:00
|
|
|
?(debug : bool = false)
|
|
|
|
(fmt : Format.formatter)
|
2022-05-30 12:20:48 +03:00
|
|
|
(stmt : stmt Marked.pos) : unit =
|
2022-02-14 20:22:26 +03:00
|
|
|
if debug then () else ();
|
2022-05-30 12:20:48 +03:00
|
|
|
match Marked.unmark stmt with
|
2022-02-14 20:22:26 +03:00
|
|
|
| SInnerFuncDef (name, func) ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "@[<hov 2>%a@ %a@ %a@ %a@]@\n@[<v 2> %a@]" Print.keyword
|
|
|
|
"let" LocalName.format_t (Marked.unmark name)
|
2022-02-14 20:22:26 +03:00
|
|
|
(Format.pp_print_list
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ")
|
|
|
|
(fun fmt ((name, _), typ) ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "%a%a %a@ %a%a" Print.punctuation "("
|
|
|
|
LocalName.format_t name Print.punctuation ":" (Print.typ decl_ctx)
|
|
|
|
(Marked.unmark typ) Print.punctuation ")"))
|
|
|
|
func.func_params Print.punctuation "="
|
2022-02-14 20:22:26 +03:00
|
|
|
(format_block decl_ctx ~debug)
|
|
|
|
func.func_body
|
|
|
|
| SLocalDecl (name, typ) ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "@[<hov 2>%a %a %a@ %a@]" Print.keyword "decl"
|
|
|
|
LocalName.format_t (Marked.unmark name) Print.punctuation ":"
|
|
|
|
(Print.typ decl_ctx) (Marked.unmark typ)
|
2022-02-14 20:22:26 +03:00
|
|
|
| SLocalDef (name, expr) ->
|
|
|
|
Format.fprintf fmt "@[<hov 2>%a %a@ %a@]" LocalName.format_t
|
2022-08-17 17:14:14 +03:00
|
|
|
(Marked.unmark name) Print.punctuation "="
|
2022-02-14 20:22:26 +03:00
|
|
|
(format_expr decl_ctx ~debug)
|
|
|
|
expr
|
|
|
|
| STryExcept (b_try, except, b_with) ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "@[<v 2>%a%a@ %a@]@\n@[<v 2>%a %a%a@ %a@]" Print.keyword
|
|
|
|
"try" Print.punctuation ":"
|
2022-02-14 20:22:26 +03:00
|
|
|
(format_block decl_ctx ~debug)
|
2022-08-17 17:14:14 +03:00
|
|
|
b_try Print.keyword "with" Print.except except Print.punctuation ":"
|
2022-02-14 20:22:26 +03:00
|
|
|
(format_block decl_ctx ~debug)
|
|
|
|
b_with
|
|
|
|
| SRaise except ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "@[<hov 2>%a %a@]" Print.keyword "raise" Print.except
|
|
|
|
except
|
2022-02-14 20:22:26 +03:00
|
|
|
| SIfThenElse (e_if, b_true, b_false) ->
|
|
|
|
Format.fprintf fmt "@[<v 2>%a @[<hov 2>%a@]%a@ %a@ @]@[<v 2>%a%a@ %a@]"
|
2022-08-17 17:14:14 +03:00
|
|
|
Print.keyword "if"
|
2022-02-14 20:22:26 +03:00
|
|
|
(format_expr decl_ctx ~debug)
|
2022-08-17 17:14:14 +03:00
|
|
|
e_if Print.punctuation ":"
|
2022-02-14 20:22:26 +03:00
|
|
|
(format_block decl_ctx ~debug)
|
2022-08-17 17:14:14 +03:00
|
|
|
b_true Print.keyword "else" Print.punctuation ":"
|
2022-02-14 20:22:26 +03:00
|
|
|
(format_block decl_ctx ~debug)
|
|
|
|
b_false
|
|
|
|
| SReturn ret ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "@[<hov 2>%a %a@]" Print.keyword "return"
|
2022-02-14 20:22:26 +03:00
|
|
|
(format_expr decl_ctx ~debug)
|
2022-05-30 12:20:48 +03:00
|
|
|
(ret, Marked.get_mark stmt)
|
2022-02-14 20:22:26 +03:00
|
|
|
| SAssert expr ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "@[<hov 2>%a %a@]" Print.keyword "assert"
|
2022-02-14 20:22:26 +03:00
|
|
|
(format_expr decl_ctx ~debug)
|
2022-05-30 12:20:48 +03:00
|
|
|
(expr, Marked.get_mark stmt)
|
2022-02-14 20:22:26 +03:00
|
|
|
| SSwitch (e_switch, enum, arms) ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "@[<v 0>%a @[<hov 2>%a@]%a@]%a" Print.keyword "switch"
|
2022-02-14 20:22:26 +03:00
|
|
|
(format_expr decl_ctx ~debug)
|
2022-08-17 17:14:14 +03:00
|
|
|
e_switch Print.punctuation ":"
|
2022-02-14 20:22:26 +03:00
|
|
|
(Format.pp_print_list
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt "@\n")
|
|
|
|
(fun fmt ((case, _), (arm_block, payload_name)) ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "%a %a%a@ %a @[<v 2>%a@ %a@]" Print.punctuation
|
|
|
|
"|" Print.enum_constructor case Print.punctuation ":"
|
|
|
|
LocalName.format_t payload_name Print.punctuation "→"
|
2022-02-14 20:22:26 +03:00
|
|
|
(format_block decl_ctx ~debug)
|
|
|
|
arm_block))
|
2022-08-12 23:42:39 +03:00
|
|
|
(List.combine (EnumMap.find enum decl_ctx.ctx_enums) arms)
|
2022-02-14 20:22:26 +03:00
|
|
|
|
|
|
|
and format_block
|
2022-08-12 23:42:39 +03:00
|
|
|
(decl_ctx : decl_ctx)
|
2022-02-14 20:22:26 +03:00
|
|
|
?(debug : bool = false)
|
|
|
|
(fmt : Format.formatter)
|
|
|
|
(block : block) : unit =
|
|
|
|
Format.pp_print_list
|
2022-08-17 17:14:14 +03:00
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt "%a@ " Print.punctuation ";")
|
2022-02-14 20:22:26 +03:00
|
|
|
(format_statement decl_ctx ~debug)
|
|
|
|
fmt block
|
|
|
|
|
|
|
|
let format_scope
|
2022-08-12 23:42:39 +03:00
|
|
|
(decl_ctx : decl_ctx)
|
2022-02-14 20:22:26 +03:00
|
|
|
?(debug : bool = false)
|
|
|
|
(fmt : Format.formatter)
|
|
|
|
(body : scope_body) : unit =
|
|
|
|
if debug then () else ();
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "@[<hov 2>%a@ %a@ %a@ %a@]@\n@[<v 2> %a@]" Print.keyword
|
|
|
|
"let" TopLevelName.format_t body.scope_body_var
|
2022-02-14 20:22:26 +03:00
|
|
|
(Format.pp_print_list
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ")
|
|
|
|
(fun fmt ((name, _), typ) ->
|
2022-08-17 17:14:14 +03:00
|
|
|
Format.fprintf fmt "%a%a %a@ %a%a" Print.punctuation "("
|
|
|
|
LocalName.format_t name Print.punctuation ":" (Print.typ decl_ctx)
|
|
|
|
(Marked.unmark typ) Print.punctuation ")"))
|
|
|
|
body.scope_body_func.func_params Print.punctuation "="
|
2022-02-14 20:22:26 +03:00
|
|
|
(format_block decl_ctx ~debug)
|
|
|
|
body.scope_body_func.func_body
|