123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126(* This file is part of the Catala compiler, a specification language for tax
and social benefits computation rules. Copyright (C) 2020 Inria, contributor:
Alain Delaët-Tixeuil <alain.delaet--tixeuil@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. *)openCatala_utilsopenShared_astmoduleD=Dcalc.AstmoduleA=Ast(** We make use of the strong invriants on the structure of programs:
Defaultable values can only appear in certin positions. This information is
given by the type structure of expressions. In particular this mean we don't
need to use the monadic bind while computing arithmetic opertions or
function calls. The resulting function is not more difficult than what we
had when translating without exceptions.
The typing translation is to simply trnsform default type into option types. *)letrectranslate_typ(tau:typ):typ=Mark.copytaubeginmatchMark.removetauwith|TDefaultt->TOption(translate_typt)|TLitl->TLitl|TTuplets->TTuple(List.maptranslate_typts)|TStructs->TStructs|TEnumen->TEnumen|TOption_->Message.error~internal:true"The types option should not appear before the dcalc -> lcalc \
translation step."|TClosureEnv->Message.error~internal:true"The types closure_env should not appear before the dcalc -> lcalc \
translation step."|TAny->TAny|TArrayts->TArray(translate_typts)|TArrow(t1,t2)->TArrow(List.maptranslate_typt1,translate_typt2)endlettranslate_markm=Expr.map_tytranslate_typmletrectranslate_default(exceptions:'mD.exprlist)(just:'mD.expr)(cons:'mD.expr)(mark_default:'mmark):'mA.exprboxed=(* Since the program is well typed, all exceptions have as type [option 't] *)letpos=Expr.mark_posmark_defaultinletexceptions=List.maptranslate_exprexceptionsinletexceptions_and_cons_ty=Expr.maybe_tymark_defaultinExpr.eappop~op:(Op.HandleDefaultOpt,Expr.poscons)~tys:[TArrayexceptions_and_cons_ty,pos;TArrow([TLitTUnit,pos],(TLitTBool,pos)),pos;TArrow([TLitTUnit,pos],exceptions_and_cons_ty),pos;]~args:[Expr.earrayexceptions(Expr.map_ty(funty->TArrayty,pos)mark_default);(* In call-by-value programming languages, as lcalc, arguments are
evalulated before calling the function. Since we don't want to
execute the justification and conclusion while before checking every
exceptions, we need to thunk them. *)Expr.thunk_term(translate_exprjust);Expr.thunk_term(translate_exprcons);]mark_defaultandtranslate_expr(e:'mD.expr):'mA.exprboxed=matchewith|EEmpty,m->letm=translate_markminletpos=Expr.mark_posminExpr.einj~e:(Expr.elitLUnit(Expr.with_tym(TLitTUnit,pos)))~cons:Expr.none_constr~name:Expr.option_enumm|EErrorOnEmptyarg,m->letm=translate_markminletpos=Expr.mark_posminletcases=EnumConstructor.Map.of_list[(Expr.none_constr,letx=Var.make"_"inExpr.make_abs[|x|](Expr.efatalerrorNoValuem)[TAny,pos]pos);(* | None x -> raise NoValueProvided *)Expr.some_constr,Expr.fun_id~var_name:"arg"m(* | Some x -> x *);]inExpr.ematch~e:(translate_exprarg)~name:Expr.option_enum~casesm|EDefault{excepts;just;cons},m->translate_defaultexceptsjustcons(translate_markm)|EPureDefaulte,m->Expr.einj~e:(translate_expre)~cons:Expr.some_constr~name:Expr.option_enum(translate_markm)|EAppOp{op;tys;args},m->Expr.eappop~op:(Operator.translateop)~tys:(List.maptranslate_typtys)~args:(List.maptranslate_exprargs)(translate_markm)|((ELit_|EArray_|EVar_|EApp_|EAbs_|EExternal_|EIfThenElse_|ETuple_|ETupleAccess_|EInj_|EAssert_|EFatalError_|EStruct_|EStructAccess_|EMatch_),_)ase->Expr.map~f:translate_expr~typ:translate_type|_->.lettranslate_program(prg:'mD.program):'mA.program=Program.map_exprsprg~typ:translate_typ~varf:Var.translate~f:translate_expr