1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429(******************************************************************************)(* ASLRef *)(******************************************************************************)(*
* SPDX-FileCopyrightText: Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
* SPDX-License-Identifier: BSD-3-Clause
*)(******************************************************************************)(* Disclaimer: *)(* This material covers both ASLv0 (viz, the existing ASL pseudocode language *)(* which appears in the Arm Architecture Reference Manual) and ASLv1, a new, *)(* experimental, and as yet unreleased version of ASL. *)(* This material is work in progress, more precisely at pre-Alpha quality as *)(* per Arm’s quality standards. *)(* In particular, this means that it would be premature to base any *)(* production tool development on this material. *)(* However, any feedback, question, query and feature request would be most *)(* welcome; those can be sent to Arm’s Architecture Formal Team Lead *)(* Jade Alglave <jade.alglave@arm.com>, or by raising issues or PRs to the *)(* herdtools7 github repository. *)(******************************************************************************)openASTopenASTUtilsletfatal_frompos=Error.fatal_frompos(* A bit more informative than assert false *)letfailamsg=failwith(Printf.sprintf"%s: %s"(PP.pp_pos_stra)msg)letfail_initialiseaid=faila(Printf.sprintf"Cannot initialise variable %s"id)let_warn=falselet_dbg=falsemoduletypeS=sigmoduleB:Backend.Svalrun_env:(AST.identifier*B.value)list->AST.t->B.valueB.mvalrun:AST.t->B.valueB.mvalrun_typed:AST.t->StaticEnv.env->B.valueB.mendmoduletypeConfig=sigmoduleInstr:Instrumentation.SEMINSTRvaltype_checking_strictness:Typing.strictnessvalunroll:intendmoduleMake(B:Backend.S)(C:Config)=structmoduleB=BmoduleSemanticsRule=Instrumentation.SemanticsRuletype'am='aB.mmoduleEnvConf=structtypev=B.valueletunroll=C.unrollendmoduleIEnv=Env.RunTime(EnvConf)typeenv=IEnv.envtypevalue_read_from=B.value*identifier*scopetype'amaybe_exception=|Normalof'a|Throwingof(value_read_from*ty)option*env(** An intermediate result of a statement. *)typecontrol_flow_state=|ReturningofB.valuelist*IEnv.global(** Control flow interruption: skip to the end of the function. *)|Continuingofenv(** Normal behaviour: pass to next statement. *)typeexpr_eval_type=(B.value*env)maybe_exceptionmtypestmt_eval_type=control_flow_statemaybe_exceptionmtypefunc_eval_type=(value_read_fromlist*IEnv.global)maybe_exceptionm(*****************************************************************************)(* *)(* Monadic operators *)(* *)(*****************************************************************************)letone=B.v_of_int1lettrue'=E_Literal(L_Booltrue)|>add_dummy_posletfalse'=E_Literal(L_Boolfalse)|>add_dummy_pos(* Return *)(* ------ *)letreturn=B.returnletreturn_normalv=Normalv|>returnletreturn_continueenv:stmt_eval_type=Continuingenv|>return_normalletreturn_returnenvvs:stmt_eval_type=Returning(vs,env.IEnv.global)|>return_normal(* Bind *)(* ---- *)(* Sequential bind *)let(let*|)=B.bind_seq(* Data bind *)let(let*)=B.bind_datalet(>>=)=B.bind_data(* Control bind *)let(let*=)=B.bind_ctrllet(>>*=)=B.bind_ctrl(* Choice *)letchoicemv1v2=B.choicem(returnv1)(returnv2)(*
* Choice with inserted branching (commit) effect/
* [choice_with_branching_effect_msg m_cond msg v1 v2 kont]:
* [m_cond], evaluates to boolean condition,
* [msg], message to decorate the branching event,
* [v1 v2] alternative for choice.
* [kont] contitinuation, takes choosed [v1] or [v2] as
* input .
*)letchoice_with_branch_effect_msgm_condmsgv1v2kont=choicem_condv1v2>>=funv->B.commit(Somemsg)>>*=fun()->kontvletchoice_with_branch_effectm_conde_condv1v2kont=letpp_cond=Format.asprintf"%a@?"PP.pp_expre_condinchoice_with_branch_effect_msgm_condpp_condv1v2kont(* Exceptions *)letbind_exceptionbindermf=binderm(functionNormalv->fv|Throwing_asres->returnres)letbind_exception_seqmf=bind_exceptionB.bind_seqmflet(let**|)=bind_exception_seqletbind_exception_datamf=bind_exceptionB.bind_datamflet(let**)=bind_exception_data(* Continue *)(* [bind_continue m f] executes [f] on [m] only if [m] is [Normal (Continuing _)] *)letbind_continue(m:stmt_eval_type)f:stmt_eval_type=bind_exception_seqm@@function|Continuingenv->fenv|Returning_asres->return_normalreslet(let*>)=bind_continue(* Unroll *)(* [bind_unroll "while" m f] executes [f] on [m] after having ticked the
unrolling stack of [m] only if [m] is [Normal (Continuing _)] *)letbind_unrollloop_name(m:stmt_eval_type)f:stmt_eval_type=bind_continuem@@funenv->letstop,env'=IEnv.tick_decrenvinifstopthenB.warnT(loop_name^" unrolling reached limit")env>>=return_continueelsefenv'letbind_maybe_unrollloop_nameundet=ifundetthenbind_unrollloop_nameelsebind_continue(* To give name to rules *)let(|:)=C.Instr.use_with(* Product parallel *)(* ---------------- *)let(and*)=B.prod_par(* Application *)(* ----------- *)let(>=>)mf=B.appl_datamf(*****************************************************************************)(* *)(* Environments *)(* *)(*****************************************************************************)(* Functions *)(* --------- *)(** [build_funcs] initialize the unique calling reference for each function
and builds the subprogram sub-env. *)letbuild_funcsast(funcs:IEnv.funcIMap.t)=List.to_seqast|>Seq.filter_map(fund->matchd.descwith|D_Funcfunc->Some(func.name,(ref0,func))|_->None)|>Fun.flipIMap.add_seqfuncs(* Global env *)(* ---------- *)letbuild_global_storageenv0eval_exprbase_value=letnames=List.fold_left(funk(name,_)->ISet.addnamek)ISet.emptyenv0inletprocess_one_decld=matchd.descwith|D_GlobalStorage{initial_value;name;ty;_}->letscope=Scope_Globaltrueinfunenv_m->ifISet.memnamenamesthenenv_melselet*|env=env_minlet*v=match(initial_value,ty)with|Somee,_->eval_exprenve|None,None->fail_initialisedname|None,Somet->base_valueenvtinlet*()=B.on_write_identifiernamescopevinIEnv.declare_globalnamevenv|>return|_->Fun.idinletfold=function|TopoSort.ASTFold.Singled->process_one_decld|TopoSort.ASTFold.Recursiveds->List.fold_rightprocess_one_decldsinfunast->TopoSort.ASTFold.foldfoldast(* Begin BuildGlobalEnv *)(** [build_genv static_env ast primitives] is the global environment before
the start of the evaluation of [ast]. *)letbuild_genvenv0eval_exprbase_value(static_env:StaticEnv.env)(ast:AST.t)=letfuncs=IMap.empty|>build_funcsastinlet()=if_dbgthenFormat.eprintf"@[<v 2>Executing in env:@ %a@.]"StaticEnv.pp_globalstatic_env.globalinletenv=letopenIEnvinletglobal={static=static_env.StaticEnv.global;storage=Storage.empty;funcs}in{global;local=empty_scoped(Scope_Globaltrue)}inletenv=List.fold_left(funenv(name,v)->IEnv.declare_globalnamevenv)envenv0inlet*|env=build_global_storageenv0eval_exprbase_valueast(returnenv)inreturnenv.global|:SemanticsRule.BuildGlobalEnv(* End *)(* Bind Environment *)(* ---------------- *)letdiscard_exceptionm=B.bind_datam@@function|Normalv->returnv|Throwing_->assertfalseletbind_envmf=B.delaym(function|Normal(_v,env)->funm->f(discard_exceptionm>=>fst,env)|Throwing(v,g)->Throwing(v,g)|>return|>Fun.const)let(let*^)=bind_env(* Primitives handling *)(* ------------------- *)letprimitive_runtimes=List.to_seqB.primitives|>Seq.mapAST.(fun({name;subprogram_type=_;_},f)->(name,f))|>Hashtbl.of_seqletprimitive_decls=List.map(fun(f,_)->D_Funcf|>add_dummy_pos)B.primitiveslet()=iffalsethenFormat.eprintf"@[<v 2>Primitives:@ %a@]@."PP.pp_tprimitive_decls(*****************************************************************************)(* *)(* Evaluation functions *)(* *)(*****************************************************************************)(* Utils *)(* ----- *)letv_true=L_Booltrue|>B.v_of_literalletm_true=returnv_trueletv_false=L_Boolfalse|>B.v_of_literalletm_false=returnv_falseletv_zero=L_IntZ.zero|>B.v_of_literalletm_zero=returnv_zeroletsync_listms=letfoldermvsm=let*v=mand*vs=vsminreturn(v::vs)inList.fold_rightfolderms(return[])letfold_par2fold1fold2acce1e2=let*^m1,acc=fold1acce1inlet*^m2,acc=fold2acce2inlet*v1=m1and*v2=m2inreturn_normal((v1,v2),acc)letrecfold_par_listfoldacces=matcheswith|[]->return_normal([],acc)|e::es->let**(v,vs),acc=fold_par2fold(fold_par_listfold)acceesinreturn_normal(v::vs,acc)letrecfold_parm_listfoldacces=matcheswith|[]->return_normal([],acc)|e::es->let*^m,acc=foldacceinlet**ms,acc=fold_parm_listfoldaccesinreturn_normal(m::ms,acc)letlexpr_is_varle=matchle.descwithLE_Var_|LE_Discard->true|_->falseletdeclare_local_identifierenvnamev=let*()=B.on_write_identifiername(IEnv.get_scopeenv)vinIEnv.declare_localnamevenv|>returnletdeclare_local_identifier_menvxm=m>>=declare_local_identifierenvxletdeclare_local_identifier_mmenvmxm=let*|env=envmindeclare_local_identifier_menvxmletassign_local_identifierenvxv=let*()=B.on_write_identifierx(IEnv.get_scopeenv)vinIEnv.assign_localxvenv|>returnletreturn_identifieri="return-"^string_of_intiletthrow_identifier()=fresh_var"thrown"(* Begin ReadValueFrom *)letread_value_from((v,name,scope):value_read_from)=let*()=B.on_read_identifiernamescopevinreturnv|:SemanticsRule.ReadValueFrom(* End *)letbig_opdefaultop=letfolderm_accm=let*acc=m_accand*v=minopaccvinfunction[]->default|x::li->List.fold_leftfolderxli(* Evaluation of Expressions *)(* ------------------------- *)(** [eval_expr] specifies how to evaluate an expression [e] in an environment
[env]. More precisely, [eval_expr env e] is the monadic evaluation of
[e] in [env]. *)letreceval_expr(env:env)(e:expr):expr_eval_type=iffalsethenFormat.eprintf"@[<3>Eval@ @[%a@]@]@."PP.pp_expre;matche.descwith(* Begin Lit *)|E_Literalv->return_normal(B.v_of_literalv,env)|:SemanticsRule.Lit(* End *)(* Begin CTC *)|E_CTC(e1,t)->let**v,new_env=eval_exprenve1inlet*b=is_val_of_typee1envvtin(ifbthenreturn_normal(v,new_env)elsefatal_frome1(Error.MismatchType(B.debug_valuev,[t.desc])))|:SemanticsRule.CTC(* End *)|E_Varx->(matchIEnv.findxenvwith(* Begin ELocalVar *)|Localv->let*()=B.on_read_identifierx(IEnv.get_scopeenv)vinreturn_normal(v,env)|:SemanticsRule.ELocalVar(* End *)(* Begin EGlobalVar *)|Globalv->let*()=B.on_read_identifierx(Scope_Globalfalse)vinreturn_normal(v,env)|:SemanticsRule.EGlobalVar(* End *)(* Begin EUndefIdent *)|NotFound->fatal_frome@@Error.UndefinedIdentifierx|:SemanticsRule.EUndefIdent)(* End *)(* Begin BinopAnd *)|E_Binop(BAND,e1,e2)->(* if e1 then e2 else false *)E_Cond(e1,e2,false')|>add_pos_frome|>eval_exprenv|:SemanticsRule.BinopAnd(* End *)(* Begin BinopOr *)|E_Binop(BOR,e1,e2)->(* if e1 then true else e2 *)E_Cond(e1,true',e2)|>add_pos_frome|>eval_exprenv|:SemanticsRule.BinopOr(* End *)(* Begin BinopImpl *)|E_Binop(IMPL,e1,e2)->(* if e1 then e2 else true *)E_Cond(e1,e2,true')|>add_pos_frome|>eval_exprenv|:SemanticsRule.BinopImpl(* End *)(* Begin Binop *)|E_Binop(op,e1,e2)->let*^m1,env1=eval_exprenve1inlet*^m2,new_env=eval_exprenv1e2inlet*v1=m1and*v2=m2inlet*v=B.binopopv1v2inreturn_normal(v,new_env)|:SemanticsRule.Binop(* End *)(* Begin Unop *)|E_Unop(op,e1)->let**v1,env1=eval_exprenve1inlet*v=B.unopopv1inreturn_normal(v,env1)|:SemanticsRule.Unop(* End *)(* Begin ECond *)|E_Cond(e_cond,e1,e2)->let*^m_cond,env1=eval_exprenve_condinifis_simple_expre1&&is_simple_expre2thenlet*=v_cond=m_condinlet*v=B.ternaryv_cond(fun()->eval_expr_sefenv1e1)(fun()->eval_expr_sefenv1e2)inreturn_normal(v,env)|:SemanticsRule.ECondSimpleelsechoice_with_branch_effectm_conde_conde1e2(eval_exprenv1)|:SemanticsRule.ECond(* End *)(* Begin ESlice *)|E_Slice(e_bv,slices)->let*^m_bv,env1=eval_exprenve_bvinlet*^m_positions,new_env=eval_slicesenv1slicesinlet*v_bv=m_bvand*positions=m_positionsinlet*v=B.read_from_bitvectorpositionsv_bvinreturn_normal(v,new_env)|:SemanticsRule.ESlice(* End *)(* Begin ECall *)|E_Call(name,actual_args,params)->let**|ms,new_env=eval_call(to_pose)nameenvactual_argsparamsinlet*v=matchmswith|[m]->m|_->let*vs=sync_listmsinB.create_vectorvsinreturn_normal(v,new_env)|:SemanticsRule.ECall(* End *)(* Begin EGetArray *)|E_GetArray(e_array,e_index)->(let*^m_array,env1=eval_exprenve_arrayinlet*^m_index,new_env=eval_exprenv1e_indexinlet*v_array=m_arrayand*v_index=m_indexinmatchB.v_to_intv_indexwith|None->(* TODO: create a proper runtime error for this.
It should be caught at type-checking, but still. *)fatal_frome(Error.UnsupportedExpre_index)|Somei->let*v=B.get_indexiv_arrayinreturn_normal(v,new_env)|:SemanticsRule.EGetArray)(* End *)(* Begin ERecord *)|E_Record(_,e_fields)->letnames,fields=List.splite_fieldsinlet**v_fields,new_env=eval_expr_listenvfieldsinlet*v=B.create_record(List.combinenamesv_fields)inreturn_normal(v,new_env)|:SemanticsRule.ERecord(* End *)(* Begin EGetField *)|E_GetField(e_record,field_name)->let**v_record,new_env=eval_exprenve_recordinlet*v=B.get_fieldfield_namev_recordinreturn_normal(v,new_env)|:SemanticsRule.EGetBitField(* End *)(* Begin EGetFields *)|E_GetFields_->fatal_fromeError.TypeInferenceNeeded|:SemanticsRule.EGetBitFields(* End *)(* Begin EConcat *)|E_Concate_list->let**v_list,new_env=eval_expr_listenve_listinlet*v=B.concat_bitvectorsv_listinreturn_normal(v,new_env)|:SemanticsRule.EConcat(* End *)(* Begin ETuple *)|E_Tuplee_list->let**v_list,new_env=eval_expr_listenve_listinlet*v=B.create_vectorv_listinreturn_normal(v,new_env)|:SemanticsRule.ETuple(* End *)(* Begin EUnknown *)|E_Unknownt->let*v=B.v_unknown_of_type~eval_expr_sef:(eval_expr_sefenv)tinreturn_normal(v,env)|:SemanticsRule.EUnknown(* End *)(* Begin EPattern *)|E_Pattern(e,p)->let**v1,new_env=eval_exprenveinlet*v=eval_patternenvev1pinreturn_normal(v,new_env)|:SemanticsRule.EPattern(* End *)(* Evaluation of Side-Effect-Free Expressions *)(* ------------------------------------------ *)(** [eval_expr_sef] specifies how to evaluate a side-effect-free expression
[e] in an environment [env]. More precisely, [eval_expr_sef env e] is the
[eval_expr env e], if e is side-effect-free. *)(* Begin ESideEffectFreeExpr *)andeval_expr_sefenve:B.valuem=eval_exprenve>>=function|Normal(v,_env)->returnv|Throwing(None,_)->letmsg=Format.asprintf"@[<hov 2>An exception was@ thrown@ when@ evaluating@ %a@]@."PP.pp_expreinfatal_frome(Error.UnexpectedSideEffectmsg)|Throwing(Some(_,ty),_)->letmsg=Format.asprintf"@[<hov 2>An exception of type @[<hv>%a@]@ was@ thrown@ when@ \
evaluating@ %a@]@."PP.pp_tytyPP.pp_expreinfatal_frome(Error.UnexpectedSideEffectmsg)(* End *)(* Runtime checks *)(* -------------- *)(* Begin ValOfType *)andis_val_of_typelocenvvty:boolB.m=letand'prevhere=prev>>=B.binopBANDhereinletor'prevhere=prev>>=B.binopBORhereinletrecin_valuesvty=match(Types.get_structure(IEnv.to_staticenv)ty).descwith|T_Real|T_Bool|T_Enum_|T_String|T_IntUnConstrained->m_true|T_Int(UnderConstrained_)->(* This cannot happen, because:
1. Forgetting now about named types, or any kind of compound type,
you cannot ask: [expr as ty] if ty is the unconstrained integer
because there is no syntax for it.
2. You cannot construct a type that is an alias for the
underconstrained integer type.
3. You cannot put the underconstrained integer type in a compound
type.
*)failwith"Cannot perform a CTC on the under-constrained type."|T_Bits(e,_)->let*v'=eval_expr_sefenveand*v_length=B.bitvector_lengthvinB.binopEQ_OPv_lengthv'|T_Int(WellConstrainedconstraints)->letfoldprev=function|Constraint_Exacte->let*v'=eval_expr_sefenveinlet*here=B.binopEQ_OPvv'inor'prevhere|Constraint_Range(e1,e2)->let*v1=eval_expr_sefenve1and*v2=eval_expr_sefenve2inlet*here=let*c1=B.binopLEQv1vand*c2=B.binopLEQvv2inB.binopBANDc1c2inor'prevhereinList.fold_leftfoldm_falseconstraints|T_Recordfields|T_Exceptionfields->letfoldprev(field_name,field_type)=let*v'=B.get_fieldfield_namevinlet*here=in_valuesv'field_typeinand'prevhereinList.fold_leftfoldm_truefields|T_Tupletys->letfold(i,prev)ty'=letm=let*v'=B.get_indexivinlet*here=in_valuesv'ty'inand'prevherein(i+1,m)inList.fold_leftfold(0,m_true)tys|>snd|T_Array(index,ty')->let*length=matchindexwith|ArrayLength_Enum(_,i)->returni|ArrayLength_Expre->(let*v_length=eval_expr_sefenveinmatchB.v_to_intv_lengthwith|Somei->returni|None->fatal_fromloc@@Error.UnsupportedExpre)inletrecloopiprev=ifi>=lengththenprevelselet*v'=B.get_indexivinlet*here=in_valuesv'ty'inloop(i+1)(and'prevhere)inloop0m_true|T_Named_->assertfalseinchoice(in_valuesvty)truefalse(* End *)(* Evaluation of Left-Hand-Side Expressions *)(* ---------------------------------------- *)(** [eval_lexpr version env le m] is [env[le --> m]]. *)andeval_lexprverleenvm:envmaybe_exceptionB.m=matchle.descwith(* Begin LEDiscard *)|LE_Discard->return_normalenv|:SemanticsRule.LEDiscard(* End *)|LE_Varx->(let*v=minmatchIEnv.assignxvenvwith(* Begin LELocalVar *)|Localenv->let*()=B.on_write_identifierx(IEnv.get_scopeenv)vinreturn_normalenv|:SemanticsRule.LELocalVar(* End *)(* Begin LEGlobalVar *)|Globalenv->let*()=B.on_write_identifierx(Scope_Globalfalse)vinreturn_normalenv|:SemanticsRule.LEGlobalVar(* End *)|NotFound->(matchverwith(* Begin LEUndefIdentOne *)|V1->fatal_fromle@@Error.UndefinedIdentifierx|:SemanticsRule.LEUndefIdentV1(* End *)(* Begin LEUndefIdentZero *)|V0->(* V0 first assignments promoted to local declarations *)declare_local_identifierenvxv>>=return_normal|:SemanticsRule.LEUndefIdentV0))(* End *)(* Begin LESlice *)|LE_Slice(e_bv,slices)->let*^m_bv,env1=expr_of_lexpre_bv|>eval_exprenvinlet*^m_positions,env2=eval_slicesenv1slicesinletnew_m_bv=let*v=mand*positions=m_positionsand*v_bv=m_bvinB.write_to_bitvectorpositionsvv_bvineval_lexprvere_bvenv2new_m_bv|:SemanticsRule.LESlice(* End *)(* Begin LESetArray *)|LE_SetArray(re_array,e_index)->let*^rm_array,env1=expr_of_lexprre_array|>eval_exprenvinlet*^m_index,env2=eval_exprenv1e_indexinletm1=let*v=mand*v_index=m_indexand*rv_array=rm_arrayinmatchB.v_to_intv_indexwith|None->fatal_fromle(Error.UnsupportedExpre_index)|Somei->B.set_indexivrv_arrayineval_lexprverre_arrayenv2m1|:SemanticsRule.LESetArray(* End *)(* Begin LESetField *)|LE_SetField(re_record,field_name)->let*^rm_record,env1=expr_of_lexprre_record|>eval_exprenvinletm1=let*v=mand*rv_record=rm_recordinB.set_fieldfield_namevrv_recordineval_lexprverre_recordenv1m1|:SemanticsRule.LESetField(* End *)(* Begin LEDestructuring *)|LE_Destructuringle_list->(* The index-out-of-bound on the vector are done either in typing,
either in [B.get_index]. *)letn=List.lengthle_listinletnmonads=List.initn(funi->m>>=B.get_indexi)inmulti_assignverenvle_listnmonads|:SemanticsRule.LEDestructuring(* End *)(* Begin LEConcat *)|LE_Concat(les,Somewidths)->letextract_onewidth(ms,start)=letend_=start+widthinletv_width=B.v_of_intwidthandv_start=B.v_of_intstartinletm'=m>>=B.read_from_bitvector[(v_start,v_width)]in(m'::ms,end_)inletms,_=List.fold_rightextract_onewidths([],0)inmulti_assignV1envlesms(* End *)|LE_Concat(_,None)|LE_SetFields_->let*()=let*v=minFormat.eprintf"@[<2>Failing on @[%a@]@ <-@ %s@]@."PP.pp_lexprle(B.debug_valuev);B.return()infatal_fromleError.TypeInferenceNeeded(* Evaluation of Expression Lists *)(* ------------------------------ *)(* Begin EExprListM *)andeval_expr_list_menves=fold_parm_listeval_exprenves|:SemanticsRule.EExprListM(* End *)(* Begin EExprList *)andeval_expr_listenves=fold_par_listeval_exprenves|:SemanticsRule.EExprList(* End *)(* Evaluation of Slices *)(* -------------------- *)(** [eval_slices env slices] is the list of pair [(i_n, l_n)] that
corresponds to the start (included) and the length of each slice in
[slices]. *)andeval_slicesenv:slicelist->((B.value*B.value)list*env)maybe_exceptionm=leteval_oneenv=function(* Begin SliceSingle *)|Slice_Singlee->let**v_start,new_env=eval_exprenveinreturn_normal((v_start,one),new_env)|:SemanticsRule.SliceSingle(* End *)(* Begin SliceLength *)|Slice_Length(e_start,e_length)->let*^m_start,env1=eval_exprenve_startinlet*^m_length,new_env=eval_exprenv1e_lengthinlet*v_start=m_startand*v_length=m_lengthinreturn_normal((v_start,v_length),new_env)|:SemanticsRule.SliceLength(* End *)(* Begin SliceRange *)|Slice_Range(e_top,e_start)->let*^m_top,env1=eval_exprenve_topinlet*^m_start,new_env=eval_exprenv1e_startinlet*v_top=m_topand*v_start=m_startinlet*v_length=B.binopMINUSv_topv_start>>=B.binopPLUSoneinreturn_normal((v_start,v_length),new_env)|:SemanticsRule.SliceRange(* End *)(* Begin SliceStar *)|Slice_Star(e_factor,e_length)->let*^m_factor,env1=eval_exprenve_factorinlet*^m_length,new_env=eval_exprenv1e_lengthinlet*v_factor=m_factorand*v_length=m_lengthinlet*v_start=B.binopMULv_factorv_lengthinreturn_normal((v_start,v_length),new_env)|:SemanticsRule.SliceStar(* End *)in(* Begin Slices *)fold_par_listeval_oneenv|:SemanticsRule.Slices(* End *)(* Evaluation of Patterns *)(* ---------------------- *)(** [eval_pattern env pos v p] determines if [v] matches the pattern [p]. *)andeval_patternenvposv:pattern->B.valuem=lettrue_=B.v_of_literal(L_Booltrue)|>returninletfalse_=B.v_of_literal(L_Boolfalse)|>returninletdisjunction=big_opfalse_(B.binopBOR)andconjunction=big_optrue_(B.binopBAND)infunction(* Begin PAll *)|Pattern_All->true_|:SemanticsRule.PAll(* End *)(* Begin PAny *)|Pattern_Anyps->letbs=List.map(eval_patternenvposv)psindisjunctionbs|:SemanticsRule.PAny(* End *)(* Begin PGeq *)|Pattern_Geqe->let*v1=eval_expr_sefenveinB.binopGEQvv1|:SemanticsRule.PGeq(* End *)(* Begin PLeq *)|Pattern_Leqe->let*v1=eval_expr_sefenveinB.binopLEQvv1|:SemanticsRule.PLeq(* End *)(* Begin PNot *)|Pattern_Notp1->let*b1=eval_patternenvposvp1inB.unopBNOTb1|:SemanticsRule.PNot(* End *)(* Begin PRange *)|Pattern_Range(e1,e2)->let*b1=let*v1=eval_expr_sefenve1inB.binopGEQvv1and*b2=let*v2=eval_expr_sefenve2inB.binopLEQvv2inB.binopBANDb1b2|:SemanticsRule.PRange(* End *)(* Begin PSingle *)|Pattern_Singlee->let*v1=eval_expr_sefenveinB.binopEQ_OPvv1|:SemanticsRule.PSingle(* End *)(* Begin PMask *)|Pattern_Maskm->letbvbv=L_BitVectorbv|>B.v_of_literalinletm_set=Bitvector.mask_setmandm_unset=Bitvector.mask_unsetminletm_specified=Bitvector.logorm_setm_unsetinlet*nv=B.unopNOTvinlet*v_set=B.binopAND(bvm_set)vand*v_unset=B.binopAND(bvm_unset)nvinlet*v_set_or_unset=B.binopORv_setv_unsetinB.binopEQ_OPv_set_or_unset(bvm_specified)|:SemanticsRule.PMask(* End *)(* Begin PTuple *)|Pattern_Tupleps->letn=List.lengthpsinlet*vs=List.initn(funi->B.get_indexiv)|>sync_listinletbs=List.map2(eval_patternenvpos)vspsinconjunctionbs|:SemanticsRule.PTuple(* End *)(* Evaluation of Local Declarations *)(* -------------------------------- *)andeval_local_declsldienvm_init_opt:envmaybe_exceptionm=let()=iffalsethenFormat.eprintf"Evaluating %a.@."PP.pp_local_decl_itemldiinmatch(ldi,m_init_opt)with(* Begin LDDiscard *)|LDI_Discard,_->return_normalenv|:SemanticsRule.LDDiscard(* End *)(* Begin LDVar *)|LDI_Varx,Somem->m>>=declare_local_identifierenvx>>=return_normal|:SemanticsRule.LDVar(* End *)(* Begin LDTyped *)|LDI_Typed(ldi1,_t),Somem->eval_local_declsldi1env(Somem)|:SemanticsRule.LDTyped(* End *)(* Begin LDUninitialisedTyped *)|LDI_Typed(ldi1,t),None->letm=base_valueenvtineval_local_declsldi1env(Somem)|:SemanticsRule.LDUninitialisedTyped(* End *)(* Begin LDTuple *)|LDI_Tupleldis,Somem->letn=List.lengthldisinletliv=List.initn(funi->m>>=B.get_indexi)inletfolderenvmldi1vm=let**|env=envmineval_local_declsldi1env(Somevm)inList.fold_left2folder(return_normalenv)ldisliv|:SemanticsRule.LDTuple(* End *)|LDI_Var_,None|LDI_Tuple_,None->(* Should not happen in V1 because of TypingRule.LDUninitialisedTuple *)fatal_fromsError.TypeInferenceNeeded(* Evaluation of Statements *)(* ------------------------ *)(** [eval_stmt env s] evaluates [s] in [env]. This is either an interruption
[Returning vs] or a continuation [env], see [eval_res]. *)andeval_stmt(env:env)s:stmt_eval_type=(iffalsethenmatchs.descwith|S_Seq_->()|_->Format.eprintf"@[<3>Eval@ @[%a@]@]@."PP.pp_stmts);matchs.descwith(* Begin SPass *)|S_Pass->return_continueenv|:SemanticsRule.SPass(* End *)(* Begin SAssignCall *)|S_Assign({desc=LE_Destructuringles;_},{desc=E_Call(name,args,named_args);_},ver)whenList.for_alllexpr_is_varles->let**|vs,env1=eval_call(to_poss)nameenvargsnamed_argsinlet**|new_env=protected_multi_assignverenv1slesvsinreturn_continuenew_env|:SemanticsRule.SAssignCall(* End *)(* Begin SAssignTuple *)|S_Assign({desc=LE_Destructuringles;_},{desc=E_Tupleexprs;_},ver)whenList.for_alllexpr_is_varles->let**|ms,env1=eval_expr_list_menvexprsinlet**|new_env=protected_multi_assignverenv1slesmsinreturn_continuenew_env|:SemanticsRule.SAssignTuple(* End *)(* Begin SAssign *)|S_Assign(le,re,ver)->let*^m,env1=eval_exprenvreinlet**|new_env=eval_lexprverleenv1minreturn_continuenew_env|:SemanticsRule.SAssign(* End *)(* Begin SReturnSome *)|S_Return(Some{desc=E_Tuplees;_})->let**|ms,new_env=eval_expr_list_menvesinletscope=IEnv.get_scopenew_envinletfolderaccm=let*|i,vs=accinlet*v=minlet*()=B.on_write_identifier(return_identifieri)scopevinreturn(i+1,v::vs)inlet*|_i,vs=List.fold_leftfolder(return(0,[]))msinreturn_returnnew_env(List.revvs)|:SemanticsRule.SReturnSome(* End *)(* Begin SReturnOne *)|S_Return(Somee)->let**v,env1=eval_exprenveinlet*()=B.on_write_identifier(return_identifier0)(IEnv.get_scopeenv1)vinreturn_returnenv1[v]|:SemanticsRule.SReturnOne(* Begin SReturnNone *)|S_ReturnNone->return_returnenv[]|:SemanticsRule.SReturnNone(* End *)(* Begin SSeq *)|S_Seq(s1,s2)->let*>env1=eval_stmtenvs1ineval_stmtenv1s2|:SemanticsRule.SSeq(* End *)(* Begin SCall *)|S_Call(name,args,named_args)->let**|returned,env'=eval_call(to_poss)nameenvargsnamed_argsinlet()=assert(returned=[])inreturn_continueenv'|:SemanticsRule.SCall(* End *)(* Begin SCond *)|S_Cond(e,s1,s2)->let*^v,env'=eval_exprenveinchoice_with_branch_effectves1s2(eval_blockenv')|:SemanticsRule.SCond(* Begin SCase *)|S_Case_->case_to_condss|>eval_stmtenv|:SemanticsRule.SCase(* End *)(* Begin SAssert *)|S_Asserte->let*^v,env1=eval_exprenveinlet*=b=choicevtruefalseinifbthenreturn_continueenv1elsefatal_frome@@Error.AssertionFailede|:SemanticsRule.SAssert(* End *)(* Begin SWhile *)|S_While(e,body)->letenv=IEnv.tick_pushenvineval_looptrueenvebody|:SemanticsRule.SWhile(* End *)(* Begin SRepeat *)|S_Repeat(body,e)->let*>env1=eval_blockenvbodyinletenv2=IEnv.tick_push_bisenv1ineval_loopfalseenv2ebody|:SemanticsRule.SRepeat(* End *)(* Begin SFor *)|S_For(id,e1,dir,e2,s)->let*v1=eval_expr_sefenve1and*v2=eval_expr_sefenve2in(* By typing *)letundet=B.is_undeterminedv1||B.is_undeterminedv2inlet*|env1=declare_local_identifierenvidv1inletenv2=ifundetthenIEnv.tick_push_bisenv1elseenv1inletloop_msg=ifundetthenPrintf.sprintf"for %s"idelsePrintf.sprintf"for %s = %s %s %s"id(B.debug_valuev1)(PP.pp_for_directiondir)(B.debug_valuev2)inlet*>env3=eval_forloop_msgundetenv2idv1dirv2sinletenv4=ifundetthenIEnv.tick_popenv3elseenv3inIEnv.remove_localidenv4|>return_continue|:SemanticsRule.SFor(* End *)(* Begin SThrowNone *)|S_ThrowNone->return(Throwing(None,env))|:SemanticsRule.SThrowNone(* End *)(* Begin SThrowSomeTyped *)|S_Throw(Some(e,Somet))->let**v,new_env=eval_exprenveinletname=throw_identifier()andscope=Scope_Globalfalseinlet*()=B.on_write_identifiernamescopevinreturn(Throwing(Some((v,name,scope),t),new_env))|:SemanticsRule.SThrowSomeTyped(* End *)(* Begin SThrowSome *)|S_Throw(Some(_e,None))->fatal_fromsError.TypeInferenceNeeded|:SemanticsRule.SThrowSome(* End *)(* Begin STry *)|S_Try(s1,catchers,otherwise_opt)->lets_m=eval_blockenvs1ineval_catchersenvcatchersotherwise_opts_m|:SemanticsRule.STry(* End *)(* Begin SDeclSome *)|S_Decl(_ldk,ldi,Somee)->let*^m,env1=eval_exprenveinlet**|new_env=eval_local_declsldienv1(Somem)inreturn_continuenew_env|:SemanticsRule.SDeclSome(* End *)(* Begin SDeclNone *)|S_Decl(_dlk,ldi,None)->let**|new_env=eval_local_declsldienvNoneinreturn_continuenew_env|:SemanticsRule.SDeclNone(* End *)|S_Print{args;debug}->let*vs=List.map(eval_expr_sefenv)args|>sync_listinlet()=ifdebugthenletopenFormatinletpp_valuefmtv=B.debug_valuev|>pp_print_stringfmtineprintf"@[@<2>%a:@ @[%a@]@ ->@ %a@]@."PP.pp_poss(pp_print_list~pp_sep:pp_print_spacePP.pp_expr)args(pp_print_list~pp_sep:pp_print_spacepp_value)vselse(List.mapB.debug_valuevs|>String.concat" "|>print_string;print_newline())inreturn_continueenv|:SemanticsRule.SDebug(* Evaluation of Blocks *)(* -------------------- *)(* Begin Block *)andeval_blockenvstm=letblock_env=IEnv.push_scopeenvinlet*>block_env1=eval_stmtblock_envstminIEnv.pop_scopeenvblock_env1|>return_continue|:SemanticsRule.Block(* End *)(* Evaluation of while and repeat loops *)(* ------------------------------------ *)(* Begin Loop *)andeval_loopis_whileenve_condbody:stmt_eval_type=(* Name for warn messages. *)letloop_name=ifis_whilethen"While loop"else"Repeat loop"in(* Continuation in the positive case. *)letloopenv=let*>env1=eval_blockenvbodyineval_loopis_whileenv1e_condbodyin(* First we evaluate the condition *)let*^cond_m,env=eval_exprenve_condin(* Depending if we are in a while or a repeat,
we invert that condition. *)letcond_m=ifis_whilethencond_melsecond_m>>=B.unopBNOTin(* If needs be, we tick the unrolling stack before looping. *)B.delaycond_m@@funcondcond_m->letbinder=bind_maybe_unrollloop_name(B.is_undeterminedcond)in(* Real logic: if condition is validated, we loop,
otherwise we continue to the next statement. *)choice_with_branch_effectcond_me_condloopreturn_continue(binder(return_continueenv))|:SemanticsRule.Loop(* End *)(* Evaluation of for loops *)(* ----------------------- *)(* Begin For *)andeval_forloop_msgundet(env:env)index_namev_startdirv_endbody:stmt_eval_type=(* Evaluate the condition: "Is the for loop terminated?" *)letcond_m=letcomp_for_dir=matchdirwithUp->LT|Down->GTinlet*()=B.on_read_identifierindex_name(IEnv.get_scopeenv)v_startinB.binopcomp_for_dirv_endv_startin(* Increase the loop counter *)letstepenvindex_namev_startdir=letop_for_dir=matchdirwithUp->PLUS|Down->MINUSinlet*()=B.on_read_identifierindex_name(IEnv.get_scopeenv)v_startinlet*v_step=B.binopop_for_dirv_startoneinlet*new_env=assign_local_identifierenvindex_namev_stepinreturn(v_step,new_env)in(* Continuation in the positive case. *)letloopenv=bind_maybe_unroll"For loop"undet(eval_blockenvbody)@@funenv1->let*|v_step,env2=stepenv1index_namev_startdirineval_forloop_msgundetenv2index_namev_stepdirv_endbodyin(* Real logic: if condition is validated, we continue to the next
statement, otherwise we loop. *)choice_with_branch_effect_msgcond_mloop_msgreturn_continueloop(funkont->kontenv)|:SemanticsRule.For(* End *)(* Evaluation of Catchers *)(* ---------------------- *)andeval_catchersenvcatchersotherwise_opts_m:stmt_eval_type=(* rethrow_implicit handles the implicit throwing logic, that is for
statement like:
try throw_my_exception ()
catch
when MyException => throw;
end
It edits the thrown value only in the case of an implicit throw and
we have a explicitely thrown exception in the context. More formally:
[rethrow_implicit to_throw m] is:
- [m] if [m] is [Normal _]
- [m] if [m] is [Throwing (Some _, _)]
- [Throwing (Some to_throw, g)] if [m] is [Throwing (None, g)] *)(* Begin RethrowImplicit *)letrethrow_implicit(v,v_ty)res=B.bind_seqres@@function|Throwing(None,env_throw1)->Throwing(Some(v,v_ty),env_throw1)|>return|_->res|:SemanticsRule.RethrowImplicit(* End *)in(* [catcher_matches t c] returns true if the catcher [c] match the raised
exception type [t]. *)(* Begin FindCatcher *)letcatcher_matches=letstatic_env={StaticEnv.emptywithglobal=env.global.static}infunv_ty(_e_name,e_ty,_stmt)->Types.type_satisfiesstatic_envv_tye_ty|:SemanticsRule.FindCatcher(* End *)in(* Main logic: *)(* If an explicit throw has been made in the [try] block: *)B.bind_seqs_m@@function(* Begin CatchNoThrow *)|Normal_|Throwing(None,_)->s_m|:SemanticsRule.CatchNoThrow(* End *)|Throwing(Some(v,v_ty),env_throw)->((* We compute the environment in which to compute the catch statements. *)letenv1=ifIEnv.same_scopeenvenv_throwthenenv_throwelse{local=env.local;global=env_throw.global}inmatchList.find_opt(catcher_matchesv_ty)catcherswith(* If any catcher matches the exception type: *)|Somecatcher->((* Begin Catch *)matchcatcherwith|None,_e_ty,s->eval_blockenv1s|>rethrow_implicit(v,v_ty)|:SemanticsRule.Catch(* Begin CatchNamed *)|Somename,_e_ty,s->(* If the exception is declared to be used in the
catcher, we update the environment before executing [s]. *)let*|env2=read_value_fromv|>declare_local_identifier_menv1namein(let*>env3=eval_blockenv2sinIEnv.remove_localnameenv3|>return_continue)|>rethrow_implicit(v,v_ty)|:SemanticsRule.CatchNamed(* End *))|None->((* Otherwise we try to execute the otherwise statement, or we
return the exception. *)matchotherwise_optwith(* Begin CatchOtherwise *)|Somes->eval_blockenv1s|>rethrow_implicit(v,v_ty)|:SemanticsRule.CatchOtherwise(* Begin CatchNone *)|None->s_m|:SemanticsRule.CatchNone))(* End *)(* Evaluation of Function Calls *)(* ---------------------------- *)(** [eval_call pos name env args named_args] evaluate the call to function
[name] with arguments [args] and parameters [named_args] *)(* Begin Call *)andeval_callposnameenvargsnamed_args=letnames,nargs1=List.splitnamed_argsinlet*^vargs,env1=eval_expr_list_menvargsinlet*^nargs2,env2=eval_expr_list_menv1nargs1inlet*vargs=vargsand*nargs2=nargs2inletnargs3=List.combinenamesnargs2inlet**|ms,global=eval_subprogramenv2.globalnameposvargsnargs3inletms2=List.mapread_value_frommsandnew_env={env2withglobal}inreturn_normal(ms2,new_env)|:SemanticsRule.Call(* End *)(* Evaluation of Subprograms *)(* ----------------------- *)(** [eval_subprogram genv name pos actual_args params] evaluate the function named [name]
in the global environment [genv], with [actual_args] the actual arguments, and
[params] the parameters deduced by type equality. *)andeval_subprogram(genv:IEnv.global)namepos(actual_args:B.valuemlist)params:func_eval_type=matchIMap.find_optnamegenv.funcswith(* Begin FUndefIdent *)|None->fatal_frompos@@Error.UndefinedIdentifiername|:SemanticsRule.FUndefIdent(* End *)(* Begin FPrimitive *)|Some(r,{body=SB_Primitive;_})->letscope=Scope_Local(name,!r)inlet()=incrrinletbody=Hashtbl.findprimitive_runtimesnameinlet*ms=bodyactual_argsinlet_,vsm=List.fold_right(funm(i,acc)->letx=return_identifieriinletm'=let*|v=let*v=minlet*()=B.on_write_identifierxscopevinreturn(v,x,scope)and*vs=accinreturn(v::vs)in(i+1,m'))ms(0,return[])inlet*|vs=vsminreturn_normal(vs,genv)|:SemanticsRule.FPrimitive(* End *)(* Begin FBadArity *)|Some(_,{args=arg_decls;_})whenList.compare_lengthsactual_argsarg_decls<>0->fatal_frompos@@Error.BadArity(name,List.lengtharg_decls,List.lengthactual_args)|:SemanticsRule.FBadArity(* End *)(* Begin FCall *)|Some(r,{body=SB_ASLbody;args=arg_decls;_})->(let()=iffalsethenFormat.eprintf"Evaluating %s.@."nameinletscope=Scope_Local(name,!r)inlet()=incrrinletenv1=IEnv.{global=genv;local=empty_scopedscope}inletone_argenvm(x,_)m=declare_local_identifier_mmenvmxminletenv2=List.fold_left2one_arg(returnenv1)arg_declsactual_argsinletone_nargenvm(x,m)=let*|env=envminifIEnv.memxenvthenreturnenvelsedeclare_local_identifier_menvxminlet*|env3=List.fold_leftone_nargenv2paramsinlet**|res=eval_stmtenv3bodyinlet()=iffalsethenFormat.eprintf"Finished evaluating %s.@."nameinmatchreswith|Continuingenv4->return_normal([],env4.global)|Returning(xs,ret_genv)->letvs=List.mapi(funiv->(v,return_identifieri,scope))xsinreturn_normal(vs,ret_genv))|:SemanticsRule.FCall(* End *)(** [multi_assign env [le_1; ... ; le_n] [m_1; ... ; m_n]] is
[env[le_1 --> m_1] ... [le_n --> m_n]]. *)(* Begin LEMultiAssign *)andmulti_assignverenvlesmonads:envmaybe_exceptionm=letfolderenvmlevm=let**|env=envmineval_lexprverleenvvminList.fold_left2folder(return_normalenv)lesmonads|:SemanticsRule.LEMultiAssign(* End *)(** As [multi_assign], but checks that [les] and [monads] have the same
length. *)andprotected_multi_assignverenvposlesmonads:envmaybe_exceptionm=ifList.compare_lengthslesmonads!=0thenfatal_frompos@@Error.BadArity("tuple construction",List.lengthles,List.lengthmonads)elsemulti_assignverenvlesmonads(* Base Value *)(* ---------- *)andbase_valueenvt=lett_struct=Types.get_structure(IEnv.to_staticenv)tinletlitv=B.v_of_literalv|>returninmatcht_struct.descwith|T_Bool->L_Boolfalse|>lit|T_Bits(e,_)->let*v=eval_expr_sefenveinletlength=matchB.v_to_intvwith|None->fatal_fromt(Error.UnsupportedExpre)|Somei->iinL_BitVector(Bitvector.zeroslength)|>lit|T_Enumli->(tryIMap.find(List.hdli)env.global.static.constant_values|>litwithNot_found->fatal_fromtError.TypeInferenceNeeded)|T_IntUnConstrained->m_zero|T_Int(UnderConstrained_)->failwith"Cannot request the base value of a under-constrained integer."|T_Int(WellConstrained[])->failwith"A well constrained integer cannot have an empty list of constraints."|T_Int(WellConstrainedcs)->(letleqxy=choice(B.binopLEQxy)truefalseinletis_negv=leqvv_zeroinletabsv=let*b=is_negvinifbthenB.unopNEGvelsereturnvinletm_none=returnNoneinletabs_minv1v2=match(v1,v2)with|None,v|v,None->returnv|Somev1,Somev2->let*abs_v1=absv1and*abs_v2=absv2inlet*v=choice(B.binopLEQabs_v1abs_v2)v1v2inreturn(Somev)inletbig_abs_min=big_opm_noneabs_mininletone_c=function|Constraint_Exacte->let*v=eval_expr_sefenveinreturn(Somev)|Constraint_Range(e1,e2)->(let*v1=eval_expr_sefenve1and*v2=eval_expr_sefenve2inlet*b=leqv1v2inifnotbthenm_noneelselet*b1=is_negv1and*b2=is_negv2inmatch(b1,b2)with|true,false->return(Somev_zero)|false,true->assertfalse(* caught by the [if not b] earlier *)|true,true->return(Somev2)|false,false->return(Somev1))inlet*v=List.mapone_ccs|>big_abs_mininmatchvwith|None->fatal_fromt(Error.BaseValueEmptyTypet)|Somev->returnv)|T_Named_->assertfalse|T_Real->L_RealQ.zero|>lit|T_Exceptionfields|T_Recordfields->List.map(fun(name,t_field)->let*v=base_valueenvt_fieldinreturn(name,v))fields|>sync_list>>=B.create_record|T_String->L_String""|>lit|T_Tupleli->List.map(base_valueenv)li|>sync_list>>=B.create_vector|T_Array(length,ty)->let*v=base_valueenvtyinlet*i_length=matchlengthwith|ArrayLength_Enum(_,i)->returni|ArrayLength_Expre->(let*length=eval_expr_sefenveinmatchB.v_to_intlengthwith|None->Error.fatal_fromt(Error.UnsupportedExpre)|Somei->returni)inList.initi_length(Fun.constv)|>B.create_vector(* Begin TopLevel *)letrun_typed_envenv(ast:AST.t)(static_env:StaticEnv.env):B.valuem=let*|env=build_genvenveval_expr_sefbase_valuestatic_envastinlet*|res=eval_subprogramenv"main"dummy_annotated[][]inmatchreswith|Normal([v],_genv)->read_value_fromv|Normal_->Error.(fatal_unknown_pos(MismatchedReturnValue"main"))|Throwing(v_opt,_genv)->letmsg=matchv_optwith|None->"implicitely thrown out of a try-catch."|Some((v,_,_scope),ty)->Format.asprintf"%a %s"PP.pp_tyty(B.debug_valuev)inError.fatal_unknown_pos(Error.UncaughtExceptionmsg)letrun_typedastenv=run_typed_env[]astenvletrun_env(env:(AST.identifier*B.value)list)(ast:AST.t):B.valuem=letast=List.rev_appendprimitive_declsastinletast=Builder.with_stdlibastinletast,static_env=Typing.type_check_astC.type_checking_strictnessastStaticEnv.emptyinlet()=iffalsethenFormat.eprintf"@[<v 2>Typed AST:@ %a@]@."PP.pp_tastinrun_typed_envenvaststatic_envletrunast=run_env[]ast|:SemanticsRule.TopLevel(* End TopLevel *)end