123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259(* Time-stamp: <modified the 01/07/2022 (at 11:04) by Erwan Jahier> *)openAstPredefopenLic(* open Lxm *)(* open Lv6errors *)typeconst_evaluator=Lic.constevaluatorexceptionEvalConst_errorofstringleteval_real_error()=raise(EvalConst_error("only expression involving ints are statically evaluated\n***"^" to avoid semantics issues, sorry."))(* exported *)let(type_error_const:Lic.constlist->string->'a)=fun_vexpect->raise(EvalConst_error("type mismatch "^(ifexpect=""then""else(expect^" expected"))))letsoi=string_of_intletios=int_of_stringlet(arity_error_const:Lic.constlist->string->'a)=funvexpect->raise(EvalConst_error(Printf.sprintf"\n*** arity error : %d argument%s, whereas %s were expected"(List.lengthv)(ifList.lengthv>1then"s"else"")expect))let(bbb_evaluator:(bool->bool->bool)->const_evaluator)=funop->funll->matchList.flattenllwith|[Bool_const_effv0;Bool_const_effv1]->[Bool_const_eff(opv0v1)]|_->assertfalse(* should not occur because eval_type is called before *)let(ooo_evaluator:(int->int->int)->(float->float->float)->const_evaluator)=funopi_opr->funll->matchList.flattenllwith|[Int_const_effv0;Int_const_effv1]->[Int_const_eff(soi(opi(iosv0)(iosv1)))]|[Real_const_eff_v0;Real_const_eff_v1]->eval_real_error()(* [Real_const_eff (opr v0 v1)] *)|_->assertfalse(* should not occur because eval_type is called before *)let(iii_evaluator:(int->int->int)->const_evaluator)=funop->funll->matchList.flattenllwith|[Int_const_effv0;Int_const_effv1]->[Int_const_eff(soi(op(iosv0)(iosv1)))]|_->assertfalse(* should not occur because eval_type is called before *)let(aab_evaluator:('a->'a->bool)->const_evaluator)=funop->funll->matchList.flattenllwith|[Int_const_effv0;Int_const_effv1]->[Bool_const_eff(op(int_of_stringv0)(int_of_stringv1))]|[_;_]->eval_real_error()|_->assertfalse(* should not occur because eval_type is called before *)let(fff_evaluator:(float->float->float)->const_evaluator)=fun_op->funll->matchList.flattenllwith|[Real_const_eff_v0;Real_const_eff_v1]->eval_real_error()(* [Real_const_eff (op v0 v1)] *)|_->assertfalse(* should not occur because eval_type is called before *)let(bb_evaluator:(bool->bool)->const_evaluator)=funop->funll->matchList.flattenllwith|[Bool_const_effv0]->[Bool_const_eff(opv0)]|_->assertfalse(* should not occur because eval_type is called before *)let(ii_evaluator:(int->int)->const_evaluator)=funop->funll->matchList.flattenllwith|[Int_const_effv0]->[Int_const_eff(soi(op(iosv0)))]|_->assertfalse(* should not occur because eval_type is called before *)let(_uminus_evaluator:const_evaluator)=funll->matchList.flattenllwith|[Real_const_effv0]->[Real_const_eff("-"^v0)](* touch it a less as possible *)|_->assertfalse(* should not occur because eval_type is called before *)let(uminus_evaluator:const_evaluator)=funll->matchList.flattenllwith|[Int_const_effv0]->[Int_const_eff("-"^v0)]|[Real_const_effv0]->[Real_const_eff("-"^v0)]|_->assertfalse(* should not occur because eval_type is called before *)let(sf_evaluator:Lv6Id.t->const_evaluator)=funid_ceff_ll->[Real_const_eff(Lv6Id.to_stringid)]let(si_evaluator:Lv6Id.t->const_evaluator)=funid_ceff_ll->tryletv=(Lv6Id.to_stringid)in[Int_const_effv]withFailure_->raise(EvalConst_error(Printf.sprintf"\n*** fail to convert the string \"%s\" into an int"(Lv6Id.to_stringid)))let(sb_evaluator:bool->const_evaluator)=funv_ceff_ll->[Bool_const_effv]let(fi_evaluator:(string->int)->const_evaluator)=funop->funll->matchList.flattenllwith|[Real_const_effv0]->[Int_const_eff(soi(opv0))]|_->assertfalse(* should not occur because [eval_type] is called before *)let(if_evaluator:(int->string)->const_evaluator)=funop->funll->matchList.flattenllwith|[Int_const_effv0]->[Real_const_eff(op(iosv0))]|_->assertfalse(* should not occur because [eval_type] is called before *)let(ite_evaluator:const_evaluator)=function|[[Bool_const_effc];t;e]->ifcthentelsee|_->assertfalse(* should not occur because [eval_type] is called before *)let(boolred_evaluator:int->int->const_evaluator)=funminmaxceff_ll->letnb=List.fold_left(funacc->function|(Bool_const_effb)->ifbthenacc+1elseacc|_->assertfalse)0(List.flattenceff_ll)in[Bool_const_eff(min<=nb&&nb<=max)](* exported *)letf(id_solver:IdSolver.t)(op:op)(lxm:Lxm.t)(_sargs:Lic.static_arglist):const_evaluator=funll->(* we first check the type so that we do not need to check it during the const
evaluation *)ignore(LicEvalType.fid_solveroplxm(List.map(List.mapLic.type_of_const)ll));matchopwith|TRUE_n->sb_evaluatortruell|FALSE_n->sb_evaluatorfalsell|ICONST_nid->si_evaluatoridll|RCONST_nid->sf_evaluatoridll|NOT_n->bb_evaluator(not)ll|REAL2INT_n->fi_evaluatorint_of_stringll|INT2REAL_n->if_evaluatorstring_of_intll|AND_n->bbb_evaluator(&&)ll|OR_n->bbb_evaluator(||)ll|IMPL_n->bbb_evaluator(funab->(nota)||b)ll|EQ_n->aab_evaluator(=)ll|NEQ_n->aab_evaluator(<>)ll|LT_n|ILT_n|RLT_n->aab_evaluator(<)ll|LTE_n|ILTE_n|RLTE_n->aab_evaluator(<=)ll|GT_n|IGT_n|RGT_n->aab_evaluator(>)ll|GTE_n|IGTE_n|RGTE_n->aab_evaluator(>=)ll|DIV_n->iii_evaluator(/)ll|MOD_n->iii_evaluator(mod)ll|IF_n->ite_evaluatorll|UMINUS_n->uminus_evaluatorll|MINUS_n->ooo_evaluator(-)(-.)ll|PLUS_n->ooo_evaluator(+)(+.)ll|SLASH_n->ooo_evaluator(/)(/.)ll|TIMES_n->ooo_evaluator(*)(*.)ll|IUMINUS_n->ii_evaluator(funx->-x)ll|IMINUS_n->iii_evaluator(-)ll|IPLUS_n->iii_evaluator(+)ll|ISLASH_n->iii_evaluator(/)ll|ITIMES_n->iii_evaluator(*)ll|RUMINUS_n->uminus_evaluatorll|RMINUS_n->fff_evaluator(-.)ll|RPLUS_n->fff_evaluator(+.)ll|RSLASH_n->fff_evaluator(/.)ll|RTIMES_n->fff_evaluator(*.)ll|NOR_n->boolred_evaluator00ll|DIESE_n->boolred_evaluator01ll|XOR_n->boolred_evaluator11ll(*
| CondAct -> assert false
| Map -> assert false
| Fill -> assert false
| Red -> assert false
| FillRed -> assert false
| BoolRed ->
match sargs with
| [ConstStaticArgLic(_,Int_const_eff i);
ConstStaticArgLic(_,Int_const_eff j);
ConstStaticArgLic(_,Int_const_eff n)
] ->
boolred_evaluator i j ll
*)(*********************************************************************************)(*********************************************************************************)(*
pour evaluer l'égalité, Pascal faisait comme ca (j'ai été plus (trop ?) brutal) :
(*----------------------------
Calcul de l'égalité
N.B. Sur les constantes abstraites
on est très méfiant
N.B. Sur les types structure,
on fait des appels récursifs
----------------------------*)
let rec compute_eq
(args : const_eff list)
= (
let rec fields_eq f0 f1 = (
match (f0, f1) with
| ([], []) ->
[Bool_const_eff true]
| ((f0,h0)::t0, (f1,h1)::t1) -> (
assert (f0 = f1);
match (compute_eq [h0;h1]) with
[Bool_const_eff false] -> [Bool_const_eff false]
| [Bool_const_eff true] -> (fields_eq t0 t1)
| _ -> assert false
)
| _ -> assert false
)
in
match args with
[Bool_const_eff v0; Bool_const_eff v1] -> [Bool_const_eff (v0 = v1)]
| [Int_const_eff v0; Int_const_eff v1] -> [Bool_const_eff (v0 = v1)]
| [Real_const_eff v0; Real_const_eff v1] -> (
let res = (v0 = v1) in
warning src
(sprintf "float in static exp: %f=%f evaluated as %b" v0 v1 res);
[Bool_const_eff res]
)
(*
2007-07 obsolete
| [Extern_const_eff (v0, t0); Extern_const_eff (v1, t1)] -> (
if (t0 <> t1) then (
type_error args "t*t for some type t"
) else if (v0 <> v1) then (
uneval_error args (
sprintf "%s=%s (external constants)"
(string_of_fullid v0)
(string_of_fullid v1)
)
) else (
[Bool_const_eff true]
)
)
*)
| [Enum_const_eff (v0, t0); Enum_const_eff (v1, t1)] -> (
if (t0 = t1) then [Bool_const_eff (v0 = v1)]
else type_error args "t*t for some type t"
)
| [Struct_const_eff (f0, t0); Struct_const_eff (f1, t1)] -> (
if (t0 = t1) then (fields_eq f0 f1)
else type_error args "t*t for some type t"
)
| [x;y] -> type_error args "t*t for some type t"
| x -> arity_error args "2"
)
in
*)