2020-11-27 18:27:10 +03:00
|
|
|
(* This file is part of the Catala compiler, a specification language for tax and social benefits
|
|
|
|
computation rules. Copyright (C) 2020 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. *)
|
|
|
|
|
2021-01-21 23:33:04 +03:00
|
|
|
open Utils
|
2020-11-27 18:27:10 +03:00
|
|
|
open Ast
|
|
|
|
|
|
|
|
let needs_parens (e : expr Pos.marked) : bool =
|
|
|
|
match Pos.unmark e with EAbs _ -> true | _ -> false
|
|
|
|
|
|
|
|
let format_var (fmt : Format.formatter) (v : Var.t) : unit =
|
|
|
|
Format.fprintf fmt "%s_%d" (Bindlib.name_of v) (Bindlib.uid_of v)
|
|
|
|
|
|
|
|
let format_location (fmt : Format.formatter) (l : location) : unit =
|
|
|
|
match l with
|
|
|
|
| ScopeVar v -> Format.fprintf fmt "%a" ScopeVar.format_t (Pos.unmark v)
|
|
|
|
| SubScopeVar (_, subindex, subvar) ->
|
|
|
|
Format.fprintf fmt "%a.%a" SubScopeName.format_t (Pos.unmark subindex) ScopeVar.format_t
|
|
|
|
(Pos.unmark subvar)
|
|
|
|
|
2020-12-04 20:48:16 +03:00
|
|
|
let typ_needs_parens (e : typ Pos.marked) : bool =
|
|
|
|
match Pos.unmark e with TArrow _ -> true | _ -> false
|
|
|
|
|
|
|
|
let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit =
|
|
|
|
let format_typ_with_parens (fmt : Format.formatter) (t : typ Pos.marked) =
|
|
|
|
if typ_needs_parens t then Format.fprintf fmt "(%a)" format_typ t
|
|
|
|
else Format.fprintf fmt "%a" format_typ t
|
|
|
|
in
|
|
|
|
match Pos.unmark typ with
|
2020-12-10 13:35:56 +03:00
|
|
|
| TLit l -> Dcalc.Print.format_tlit fmt l
|
2020-12-04 20:48:16 +03:00
|
|
|
| TStruct s -> Format.fprintf fmt "%a" Ast.StructName.format_t s
|
|
|
|
| TEnum e -> Format.fprintf fmt "%a" Ast.EnumName.format_t e
|
|
|
|
| TArrow (t1, t2) ->
|
|
|
|
Format.fprintf fmt "@[<hov 2>%a →@ %a@]" format_typ_with_parens t1 format_typ t2
|
2020-12-30 00:26:10 +03:00
|
|
|
| TArray t1 -> Format.fprintf fmt "@[%a@ array@]" format_typ (Pos.same_pos_as t1 typ)
|
|
|
|
| TAny -> Format.fprintf fmt "any"
|
2020-12-04 20:48:16 +03:00
|
|
|
|
2020-11-27 18:27:10 +03:00
|
|
|
let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit =
|
|
|
|
let format_with_parens (fmt : Format.formatter) (e : expr Pos.marked) =
|
|
|
|
if needs_parens e then Format.fprintf fmt "(%a)" format_expr e
|
|
|
|
else Format.fprintf fmt "%a" format_expr e
|
|
|
|
in
|
|
|
|
match Pos.unmark e with
|
|
|
|
| ELocation l -> Format.fprintf fmt "%a" format_location l
|
2020-11-27 20:36:38 +03:00
|
|
|
| EVar v -> Format.fprintf fmt "%a" format_var (Pos.unmark v)
|
2020-11-27 18:27:10 +03:00
|
|
|
| ELit l -> Format.fprintf fmt "%a" Dcalc.Print.format_lit (Pos.same_pos_as l e)
|
2020-12-03 23:29:22 +03:00
|
|
|
| EStruct (name, fields) ->
|
|
|
|
Format.fprintf fmt "@[%a @[<hov 2>{@ %a@ }@]@]" Ast.StructName.format_t name
|
|
|
|
(Format.pp_print_list
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt ";@ ")
|
|
|
|
(fun fmt (field_name, field_expr) ->
|
|
|
|
Format.fprintf fmt "%a = %a" Ast.StructFieldName.format_t field_name format_expr
|
|
|
|
field_expr))
|
|
|
|
(Ast.StructFieldMap.bindings fields)
|
|
|
|
| EStructAccess (e1, field, _) ->
|
|
|
|
Format.fprintf fmt "%a.%a" format_expr e1 Ast.StructFieldName.format_t field
|
|
|
|
| EEnumInj (e1, cons, _) ->
|
|
|
|
Format.fprintf fmt "%a@ %a" Ast.EnumConstructor.format_t cons format_expr e1
|
|
|
|
| EMatch (e1, _, cases) ->
|
|
|
|
Format.fprintf fmt "@[<hov 2>@[match@ %a@ with@]@ %a@]" format_expr e1
|
|
|
|
(Format.pp_print_list
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt "@ |@ ")
|
|
|
|
(fun fmt (cons_name, case_expr) ->
|
|
|
|
Format.fprintf fmt "@[<hov 2>%a@ →@ %a@]" Ast.EnumConstructor.format_t cons_name
|
|
|
|
format_expr case_expr))
|
|
|
|
(Ast.EnumConstructorMap.bindings cases)
|
2021-04-03 12:49:13 +03:00
|
|
|
| EApp ((EAbs ((binder, _), taus), _), args) ->
|
2020-11-27 18:27:10 +03:00
|
|
|
let xs, body = Bindlib.unmbind binder in
|
|
|
|
let xs_tau = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in
|
|
|
|
let xs_tau_arg = List.map2 (fun (x, tau) arg -> (x, tau, arg)) xs_tau args in
|
|
|
|
Format.fprintf fmt "@[%a%a@]"
|
|
|
|
(Format.pp_print_list
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt " ")
|
|
|
|
(fun fmt (x, tau, arg) ->
|
|
|
|
Format.fprintf fmt "@[@[<hov 2>let@ %a@ :@ %a@ =@ %a@]@ in@\n@]" format_var x
|
2020-12-04 20:48:16 +03:00
|
|
|
format_typ tau format_expr arg))
|
2020-11-27 18:27:10 +03:00
|
|
|
xs_tau_arg format_expr body
|
2021-04-03 12:49:13 +03:00
|
|
|
| EAbs ((binder, _), taus) ->
|
2020-11-27 18:27:10 +03:00
|
|
|
let xs, body = Bindlib.unmbind binder in
|
|
|
|
let xs_tau = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in
|
|
|
|
Format.fprintf fmt "@[<hov 2>λ@ %a@ →@ %a@]"
|
|
|
|
(Format.pp_print_list
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt " ")
|
2020-12-04 20:48:16 +03:00
|
|
|
(fun fmt (x, tau) -> Format.fprintf fmt "@[(%a:@ %a)@]" format_var x format_typ tau))
|
2020-11-27 18:27:10 +03:00
|
|
|
xs_tau format_expr body
|
|
|
|
| EApp ((EOp (Binop op), _), [ arg1; arg2 ]) ->
|
|
|
|
Format.fprintf fmt "@[%a@ %a@ %a@]" format_with_parens arg1 Dcalc.Print.format_binop
|
|
|
|
(op, Pos.no_pos) format_with_parens arg2
|
|
|
|
| EApp ((EOp (Unop op), _), [ arg1 ]) ->
|
|
|
|
Format.fprintf fmt "@[%a@ %a@]" Dcalc.Print.format_unop (op, Pos.no_pos) format_with_parens
|
|
|
|
arg1
|
|
|
|
| EApp (f, args) ->
|
|
|
|
Format.fprintf fmt "@[%a@ %a@]" format_expr f
|
|
|
|
(Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ") format_with_parens)
|
|
|
|
args
|
|
|
|
| EIfThenElse (e1, e2, e3) ->
|
|
|
|
Format.fprintf fmt "if@ @[<hov 2>%a@]@ then@ @[<hov 2>%a@]@ else@ @[<hov 2>%a@]" format_expr
|
|
|
|
e1 format_expr e2 format_expr e3
|
2020-12-28 01:53:02 +03:00
|
|
|
| EOp (Ternop op) -> Format.fprintf fmt "%a" Dcalc.Print.format_ternop (op, Pos.no_pos)
|
2020-11-27 18:27:10 +03:00
|
|
|
| EOp (Binop op) -> Format.fprintf fmt "%a" Dcalc.Print.format_binop (op, Pos.no_pos)
|
|
|
|
| EOp (Unop op) -> Format.fprintf fmt "%a" Dcalc.Print.format_unop (op, Pos.no_pos)
|
2020-12-18 17:59:15 +03:00
|
|
|
| EDefault (excepts, just, cons) ->
|
|
|
|
if List.length excepts = 0 then
|
2020-11-27 18:27:10 +03:00
|
|
|
Format.fprintf fmt "@[⟨%a ⊢ %a⟩@]" format_expr just format_expr cons
|
|
|
|
else
|
2020-12-18 17:59:15 +03:00
|
|
|
Format.fprintf fmt "@[<hov 2>⟨%a@ |@ %a ⊢ %a⟩@]"
|
2020-11-27 18:27:10 +03:00
|
|
|
(Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") format_expr)
|
2020-12-18 17:59:15 +03:00
|
|
|
excepts format_expr just format_expr cons
|
2021-04-03 16:07:49 +03:00
|
|
|
| ErrorOnEmpty e' -> Format.fprintf fmt "error_empty@ %a" format_with_parens e'
|
2020-12-28 01:53:02 +03:00
|
|
|
| EArray es ->
|
|
|
|
Format.fprintf fmt "[%a]"
|
|
|
|
(Format.pp_print_list
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt ";")
|
|
|
|
(fun fmt e -> Format.fprintf fmt "@[%a@]" format_expr e))
|
|
|
|
es
|