123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821(* Time-stamp: <modified the 29/08/2019 (at 15:19) by Erwan Jahier> *)(** Define the Data Structure representing Compiled programs. By
compiled we mean that constant are propagated, packages are
instanciated, recursive node are inlined, etc.
lic = lustre internal code
Basically it is Lustre with all the suggar removed.
*)(**
Définition des structures de données utilisée pour la compil,
plus des utilitaires pour les messages d'erreurs, de bug etc.
N.B. on utilise beaucoup l'adjectif "effectif", qui signifie
simplement "correct" (c'est bizzare mais c'est ainsi.
REMARQUE GENERALE :
D'une manière générale, la compil d'une entité syntaxique
"toto" est implémentée par une fonction check_toto, qui
prend en entrée (entr'autre) un toto et renvoie un
toto.
TYPES DE DONNEES :
- type_ :
dénotation de type effectif, implémente l'équivalence des types,
construit à partir d'une type_exp.
- const :
dénotation de constante effective,
construit à partir d'une val_exp => IL S'AGIT DE LA REPRESENTATION
INTERNE DES CONSTANTES STATIQUES
- var_info :
déclaration de variable,
construit à partir de var_info.
- val :
union entre const et var_info.
- slice_info :
dénotation de tranche de tableau,
construit à partir de slice_info.
- left :
version compilée de left_part
- eq_info :
version compilée de eq_info
- node_exp :
dénotation d'opération,
peut être predef ou utilisateur,
construit à partir de node_exp.
- static_arg :
déclaration d'un static arg
- pack_env :
la "grosse" structure de données qui gère la compilation
des packages => implémentée dans CheckGlobal pour la partie type/const/function
(initialisation) et dans CheckNode pour la partie node/template qui
est faite à la demande.
UTILITAIRES :
- type_of_const : renvoie le type d'une const
- string_of_type : pretty-print d'un type
- string_of_const : pretty-print d'une const
- string_of_node_key : pretty-print d'un node_key
_ string_of_slice :
----------------------------------------------------------------------*)openLv6errorsopenPrintfopenLxm(* open AstCore *)let_dbg=(Lv6Verbose.get_flag"lazyc")(*---------------------------------------------------------------------
Type : type
-----------------------------------------------------------------------
Dénotation de type immédiat : l'équivalence sémantique des types
EST l'équivalence structurelle des types.
Par rapport à une type_exp :
- pas d'alias
- taille des tableaux résolues
----------------------------------------------------------------------*)typetype_=|Bool_type_eff|Int_type_eff|Real_type_eff|External_type_effofLv6Id.long|Abstract_type_effofLv6Id.long*type_(* | Alias_type_eff of Lv6Id.long *)|Enum_type_effofLv6Id.long*(Lv6Id.longlist)|Array_type_effoftype_*int|Struct_type_effofLv6Id.long*(Lv6Id.t*(type_*constoption))list|TypeVaroftype_var(* [Overload] is like [Any], except that it can only be [int] or [real] *)andtype_var=|Any|AnyNum(* pascal : A VIRER A MOYEN TERME !
R1 : euh... a voir. Pour l'instant, ca ne sert plus car Pascal a
débranché la verif de type lors de l'instanciation de noeud. J'en
aurais peut-etre besoin le jour où j'y rebrancherai.
*)andnode_profile=(Lv6Id.t*type_)list*(Lv6Id.t*type_)listandprofile=type_list*type_listandslice_info={(* Dénotation de tranche de tableau correcte :
si A est le tableau d'entrée, alors S est le tableau
de sortie avec :
S[i] = A[first + i*step] pour i = 0 .. width
*)se_first:int;se_last:int;se_step:int;se_width:int;(* -> size? *)}andleft=(* Version checkée des left_part
(les idents, les index et les tranches sont résolus)
N.B. On conserve aussi le type effectif de chaque noeud
bien qu'il soit possible de le retrouver.
N.B. On garde aussi l'info source des idents au cas ou.*)|LeftVarLicof(var_info*Lxm.t)|LeftFieldLicof(left*Lv6Id.t*type_)|LeftArrayLicof(left*int*type_)(* XXX should be called LeftArrayIndexLic? *)|LeftSliceLicof(left*slice_info*type_)andeq_info=leftlist*val_expandval_exp={ve_core:val_exp_core;ve_typ:type_list;(* An empty list means that its type has not been computed (EvalType.f) yet.
a cleaner solution would be to define two versions of val_exp: one with
type info, and one without. But it is a big mutually recursive thing,
and doing that would be a little bit heavy...
XXX why not an option type? because of tuples?
*)ve_clk:clocklist;ve_src:Lxm.t(* ditto *)}(* CallByPosLic est (sans doute ?)
le BON endroit pour stocker l'information de 'matches',
i.e. est-ce qu'un 'type_matches' a été nécessaire
pour typer l'appel de l'opérateur ?
*)andval_exp_core=|CallByPosLicof(by_pos_opsrcflagged*val_explist)|CallByNameLicof(by_name_opsrcflagged*(Lv6Id.tsrcflagged*val_exp)list)|Mergeofval_exp*(constsrcflagged*val_exp)listandby_name_op=|STRUCTofLv6Id.long|STRUCT_withofLv6Id.long*Lv6Id.t(* XXX devrait etre une expression !!! *)|STRUCT_anonymousandby_pos_op=|PREDEF_CALLofnode_keysrcflagged|CALLofnode_keysrcflagged|CONST_REFofLv6Id.long|CONSTofconst|VAR_REFofLv6Id.t|PRE|ARROW|FBY|CURRENTofLv6Id.longoption(* hold the clock constructor; the clock var is
provided via the args (val_exp list) *)(* nb : we have an option type because we know the clock after
clock checking only *)|WHENofclock|TUPLE|CONCAT|HATofint|ARRAY|STRUCT_ACCESSofLv6Id.t(* those are different from [by_pos_op] *)|ARRAY_ACCESofint|ARRAY_SLICEofslice_info(*---------------------------------------------------------------------
Type : const
-----------------------------------------------------------------------
Dénotation de constante immédiate
N.B. les const "portent" leur type :
- il est implicite pour bool, int, real,
- explicite pour extern, enum et struct
- pour array c'est le TYPE DES ELEMENTS QU'ON TRIMBALE
VOIR => type_of_const
----------------------------------------------------------------------*)andconst=(* type predef *)Bool_const_effofbool|Int_const_effofstring|Real_const_effofstring(* type atomique non predef : on précise le type *)|Extern_const_effof(Lv6Id.long*type_)|Abstract_const_effof(Lv6Id.long*type_*const*bool)(* if the abstract const is extern (i.e., defined as an extern
in the provided part), then the bool flag is set to
true.
*)|Enum_const_effof(Lv6Id.long*type_)(* type_ tructure : liste (champ,valeur) + type_ structure *)|Struct_const_effof((Lv6Id.t*const)list*type_)(* type_ tableau : liste des valeurs + type_ des elts + taille
Is it really a good idea to live both with
- constant arrays (and struct), i.e., Array_const_eff
- array of constants, i.e., ARRAY(const)
?
*)|Array_const_effof(constlist*type_)(* type of the const element *)|Tuple_const_effofconstlist(*---------------------------------------------------------------------
Type: val
-----------------------------------------------------------------------
Une constante ou une variable
=> item de la table des symboles de valeurs
----------------------------------------------------------------------*)(*---------------------------------------------------------------------
Type: var_info
-----------------------------------------------------------------------
Info associée à un ident de variable
----------------------------------------------------------------------*)(* ICI à completer/modifier sans doute *)andvar_info={var_name_eff:Lv6Id.t;var_nature_eff:AstCore.var_nature;var_number_eff:int;var_type_eff:type_;var_clock_eff:id_clock;}andid_clock=Lv6Id.t*clock(*
A pair made of an ident and its clock.
The ident is used to relate arguments and parameters
when clocking node calls (in order to be able to transmit
the clocking constraints between the node I/O, in EvalClock.f).
*)andclock=|BaseLic|ClockVarofint(* to deal internally with polymorphic clocks (i.e., constants) *)|Onof(Lv6Id.long*Lv6Id.t*type_)*clock(* - The clock constructor (holding the clock value),
- the clock variable
- the type of the clock variable (enum or bool)
- the clock of the clock
e.g., in
On(clk_constructor, clk_var, clk_typ, sub_clk )
sub_clk is the clock of clock clk_var
*)(**********************************************************************************)(** [node_exp] correspond à une instance de template (ou, cas
limite, de noeud sans param statique).
La clé est un couple ident/liste d'arguments statiques effectifs
N.B. une horloge formelle est soit None (base) soit l'index d'une
entrée (0..nb entrées-1). Les formal-clocks sont créées au cours du
type-checking (et pas du clock-checking)
*)andnode_exp={node_key_eff:node_key;inlist_eff:var_infolist;outlist_eff:var_infolist;loclist_eff:var_infolistoption;(* None => extern or abstract *)def_eff:node_def;has_mem_eff:bool;is_safe_eff:bool;lxm:Lxm.t;(* is_polym_eff : bool *)}andtype_matches=(type_var*type_)listandnode_def=|ExternLic|MetaOpLic|AbstractLicofnode_expoption(* None if extern in the provide part *)|BodyLicofnode_bodyandnode_body={asserts_eff:(val_expsrcflagged)list;eqs_eff:(eq_infosrcflagged)list;}(* key used for type, constant, and clock tables *)anditem_key=Lv6Id.longandnode_key=item_key*static_arglistandstatic_arg=(* may be a tuple *)|ConstStaticArgLicof(Lv6Id.t*const)|TypeStaticArgLicof(Lv6Id.t*type_)(* | NodeStaticArgLic of (Lv6Id.t * sarg_node_eff * node_exp) *)|NodeStaticArgLicof(Lv6Id.t*node_key)andsarg_node_eff=node_key*var_infolist*var_infolist(****************************************************************************)(* Because of clocks and types, we cannot rely on compare; hence this
dedicated function *)let(compare_var_info:var_info->var_info->int)=funv1v2->if(v1.var_name_eff=v2.var_name_eff)&&(v1.var_nature_eff=v2.var_nature_eff)&&(v1.var_number_eff=v2.var_number_eff)then0elsecomparev1v2(****************************************************************************)(** Type check_flag
Au cours du check, on conserve le statut des idents :
- Checking => en cours de traitement, permet de lever les récursions
- Checked => traité et correct
- Incorrect => déjà marqué comme incorrect (pas besoin d'un nouveau
message d'erreur)
*)type'acheck_flag=Checking|Checkedof'a|Incorrectlet(profile_of_node_exp:node_exp->profile)=funne->List.map(funvi->vi.var_type_eff)ne.inlist_eff,List.map(funvi->vi.var_type_eff)ne.outlist_eff(****************************************************************************)(* currently not used *)(* type world_env = { *)(* wenv_src : AstV6.pack_or_model list; *)(* wenv_mod_srcs : (Lv6Id.t, AstV6.model_info srcflagged) Hashtbl.t ; *)(* wenv_pack_srcs : (Lv6Id.t, AstV6.pack_info srcflagged) Hashtbl.t ; *)(* wenv_pack_envs : (Lv6Id.t, pack_env) Hashtbl.t ; *)(* } *)(* and pack_env = { *)(* penv_world : world_env ; *)(* (* penv_src : AstV6.package ; *) *)(* penv_type_table : (Lv6Id.t, type check_flag) Hashtbl.t ; *)(* penv_const_table : (Lv6Id.t, const check_flag) Hashtbl.t ; *)(* penv_oper_table : (Lv6Id.t, node_half) Hashtbl.t ; *)(* penv_node_table : (node_key, node_exp check_flag) Hashtbl.t *)(* } *)(* the local tables are indexed by Lv6Id.t, because local idents (var,const, flow)
cannot have any package name.
and for nodes, the only possibility to have an entry in this table is via the
static parameters.
i.e.
min_4 = min_n<< 4, toto<<2>> >> ;
is not allowed (I think). One has to write something like :
toto_2 = toto<<2>>;
min_4 = min_n<< 4, toto_2 >> ;
It would not be difficult to handle that here though.
*)(****************************************************************************)(** [type_are_compatible t1 t2] checks that t1 is compatible with t2, i.e.,
if t1 = t2 or t1 is abstract and not t2.
*)let(type_are_compatible:type_->type_->bool)=funte1te2->matchte1,te2with|External_type_eff(id1),External_type_eff(id2)->id1=id2|External_type_eff_,_->true|Abstract_type_eff_,_->true|TypeVarAny,_->true|_,TypeVarAny->true|(TypeVarAnyNum),Real_type_eff|Real_type_eff,(TypeVarAnyNum)|(TypeVarAnyNum),Int_type_eff|Int_type_eff,(TypeVarAnyNum)->true|t1,t2->t1=t2let(is_extern_type:type_->bool)=funte->matchtewith|External_type_eff_->true|_->falselet(clock_are_equals:clock->clock->bool)=func1c2->matchc1,c2with|On(cid1,_),On(cid2,_)->cid1=cid2(* equivalent ? try both before commit !!! *)(* | On(_,c1), On(_,c2) -> clock_are_equals c1 c2 *)|c1,c2->c1=c2let(var_are_compatible:var_info->var_info->bool)=funv1v2->(type_are_compatiblev1.var_type_effv2.var_type_eff)&&(clock_are_equals(sndv1.var_clock_eff)(sndv2.var_clock_eff))letident_of_type=function|Bool_type_eff->Lv6Id.out_of_pack"bool"|Int_type_eff->Lv6Id.out_of_pack"int"|Real_type_eff->Lv6Id.out_of_pack"real"|External_type_effid|Abstract_type_eff(id,_)|Enum_type_eff(id,_)|Struct_type_eff(id,_)->id|TypeVarAny->Lv6Id.out_of_pack"any"|(TypeVarAnyNum)->Lv6Id.out_of_pack"anynum"|Array_type_eff(_,_)->assertfalse(****************************************************************************)(* Utilitaires liés aux node_key *)let(node_key_of_idref:Lv6Id.idref->node_key)=funnkey->(Lv6Id.long_of_idrefnkey,[])let(node_key_of_ident:string->node_key)=funid->(Lv6Id.long_of_stringid,[])(* OBSOLETE ET UN PEU FAUX !
R1: pas forcément obsolete ; cf commentaire plus haut.
*)letrec(subst_type:type_->type_->type_)=funtteff_ext->matchteff_extwith(* substitutes [t] in [teff_ext] *)|Bool_type_eff->Bool_type_eff|Int_type_eff->Int_type_eff|Real_type_eff->Real_type_eff|External_type_eff(l)->External_type_eff(l)|Abstract_type_eff(l,t)->Abstract_type_eff(l,t)|Enum_type_eff(l,el)->Enum_type_eff(l,el)|Array_type_eff(teff_ext,i)->Array_type_eff(subst_typetteff_ext,i)|Struct_type_eff(l,fl)->Struct_type_eff(l,List.map(fun(id,(teff,copt))->(id,(subst_typetteff,copt)))fl)|TypeVarAny|(TypeVarAnyNum)->t(* *)letrecsubst_matches(matches:type_matches)(t:type_):type_=matchtwith|Bool_type_eff|Int_type_eff|Real_type_eff|External_type_eff_|Enum_type_eff_->t(* normallement, seul cas récursif ? *)|Array_type_eff(telts,i)->Array_type_eff(subst_matchesmatchestelts,i)(* NE DEVRAIENT PAS ETRE RECURSIFS
on utilse paranoid au cas où ...
*)|Abstract_type_eff(l,td)->Lv6Verbose.exe~flag:Lv6MainArgs.paranoid(fun()->lett'=Abstract_type_eff(l,subst_matchesmatchestd)inift<>t'thenassertfalse);t|Struct_type_eff(l,fl)->Lv6Verbose.exe~flag:Lv6MainArgs.paranoid(fun()->lett'=Struct_type_eff(l,List.map(fun(id,(teff,copt))->(id,(subst_matchesmatchesteff,copt)))fl)inift<>t'thenassertfalse);t|TypeVartvar->try(List.assoctvarmatches)withNot_found->tletapply_type_matches(matches:type_matches)(tl:type_list):type_list=matchmatcheswith|[]->tl|_->List.map(subst_matchesmatches)tlletrec(type_is_poly:type_->bool)=funt->matchtwith|Bool_type_eff|Int_type_eff|Real_type_eff|External_type_eff_|Enum_type_eff(_)->false(* peut-être un alias ! *)|Abstract_type_eff(_id,te)->type_is_polyte|TypeVarAny|(TypeVarAnyNum)->true|Array_type_eff(teff_ext,_i)->type_is_polyteff_ext|Struct_type_eff(_l,fl)->List.exists(fun(_,(teff,_))->type_is_polyteff)flletnode_is_poly(ne:node_exp):bool=(* let it, ot = profile_of_node_exp ne in *)letvarispolyv=type_is_polyv.var_type_effinList.existsvarispolyne.inlist_eff||List.existsvarispolyne.outlist_effletnode_is_extern(ne:node_exp):bool=matchne.def_effwith|ExternLic->true|_->falselet(is_extern_const:const->bool)=funte->matchtewith|Extern_const_eff_|Abstract_const_eff(_,_,_,true)->true|_->falselet(val_exp_is_constant:val_exp->bool)=function|{ve_core=CallByPosLic({it=(CONST_REF_|CONST_);_},_);_}->true|_->falselettype_of_val_expve=ve.ve_typletreclxm_of_val_expve=matchve.ve_corewith|CallByPosLic(x,_)->x.src|CallByNameLic(x,_)->x.src|Merge(ve,_)->lxm_of_val_expve(********************************************************************************)(* for source level info : we want the smallest and the highest lxm of the expr *)letmin_lxmlxm1lxm2=if(linelxm1)=0thenlxm2elseif(linelxm1)=(linelxm2)thenif(cstartlxm1)<(cstartlxm2)thenlxm1elselxm2elseif(linelxm1)<(linelxm2)thenlxm1elselxm2letmax_lxmlxm1lxm2=if(linelxm1)=(linelxm2)thenif(cendlxm1)>(cendlxm2)thenlxm1elselxm2elseif(linelxm1)>(linelxm2)thenlxm1elselxm2(********************************************************************************)(* Ne doit être appelée que pour les constantes simples *)let(type_of_const:const->type_)=function|Bool_const_eff_->Bool_type_eff|Int_const_eff_->Int_type_eff|Real_const_eff_->Real_type_eff|Extern_const_eff(_s,teff)->teff|Abstract_const_eff(_s,teff,_v,_is_exported)->teff|Enum_const_eff(_s,teff)->teff|Struct_const_eff(_fl,teff)->teff(* | Array_const_eff (ct, teff) -> teff (* Array_type_eff (teff, List.length ct) *) *)|Array_const_eff(ct,teff)->Array_type_eff(teff,List.lengthct)|Tuple_const_eff_cl->(* Utiliser plutot types_of_const (ci dessous) qui traite les tuples *)print_internal_error"Lic.type_of_const""should not have been called for a tuple";assertfalse(* accepte un UNIQUE niveau de tuple *)let(types_of_const:const->type_list)=function|Tuple_const_effcl->List.maptype_of_constcl|c->[type_of_constc](* const list *)(* Ignore the abstraction layer (necessary when expanding struct) *)(* XXX not used anymore. This is very suspect... *)let(true_type_of_const:const->type_)=function|Abstract_const_eff(_s,teff,_v,_is_exported)->teff|teff->type_of_consttefflet(type_of_left:left->type_)=function|LeftVarLic(vi,_lxm)->vi.var_type_eff|LeftFieldLic(_,_,t)->t|LeftArrayLic(_,_,t)->t|LeftSliceLic(_,_,t)->tletrec(lxm_of_left:left->Lxm.t)=function|LeftVarLic(_,lxm)->lxm|LeftFieldLic(l,_,_)|LeftArrayLic(l,_,_)|LeftSliceLic(l,_,_)->lxm_of_leftlletrec(var_info_of_left:left->var_info)=function|LeftVarLic(v,_)->v|LeftFieldLic(left,_,_)->var_info_of_leftleft|LeftArrayLic(left,_,_)->var_info_of_leftleft|LeftSliceLic(left,_,_)->var_info_of_leftleftlet(clock_of_left:left->clock)=funleft->snd(var_info_of_leftleft).var_clock_effletstring_of_ident=Lv6Id.string_of_long_bisfalseletrecstring_of_type=function|Bool_type_eff->"bool"|Int_type_eff->"int"|Real_type_eff->"real"|External_type_eff(name)->(string_of_identname)|Abstract_type_eff(name,_t)->(string_of_identname)|Enum_type_eff(name,_)->(string_of_identname)|Array_type_eff(ty,sz)->Printf.sprintf"%s^%d"(string_of_typety)sz|Struct_type_eff(name,_)->(string_of_identname)|TypeVarAny->"any"|(TypeVarAnyNum)->"anynum"andstring_of_type_list=function|[]->""|[x]->string_of_typex|l->String.concat" * "(List.mapstring_of_typel)andstring_of_type_profile(i,o)=(string_of_type_listi)^" -> "^(string_of_type_listo)andstring_of_clock=function|BaseLic->" on base"|ClockVari->" on 'CV"^(string_of_inti)|On((cc,cv,_ct),ck)->" on "^(Lv6Id.string_of_longfalsecc)^"("^(Lv6Id.to_stringcv)^")"^(string_of_clockck)andenum_to_stringsll=matchLv6MainArgs.global_opt.Lv6MainArgs.expand_enumswith|Lv6MainArgs.AsInt->(string_of_int(Lv6util.pos_in_list0sll))|Lv6MainArgs.AsBool|Lv6MainArgs.AsConst|Lv6MainArgs.AsEnum->string_of_identsandstring_of_const=function|Bool_const_efftrue->"true"|Bool_const_efffalse->"false"|Int_const_effi->(sprintf"%s"i)|Real_const_effr->r|Extern_const_eff(s,_)->(string_of_idents)|Abstract_const_eff(s,_t,_v,_)->(string_of_idents)|Enum_const_eff(s,Enum_type_eff(_,ll))->enum_to_stringsll|Enum_const_eff_->assertfalse|Struct_const_eff(fl,t)->letstring_of_field(id,veff)=(Lv6Id.to_stringid)^" = "^(string_of_constveff)inPrintf.sprintf"%s{%s}"(string_of_typet)(String.concat"; "(List.mapstring_of_fieldfl))|Array_const_eff(ctab,_t)->Printf.sprintf"[%s]"(String.concat", "(List.mapstring_of_constctab))|Tuple_const_effcl->Printf.sprintf"(%s)"(String.concat", "(List.mapstring_of_constcl))andstring_of_var_infox=(AstCore.string_of_var_naturex.var_nature_eff)^" "^(Lv6Id.to_stringx.var_name_eff)^":"^(string_of_typex.var_type_eff)^(string_of_clock(sndx.var_clock_eff)^"("^(Lv6Id.to_string(fstx.var_clock_eff))^","^(string_of_intx.var_number_eff)^")")andstring_of_var_listvl=String.concat" ; "(List.mapstring_of_var_infovl)andstring_of_node_key=function|(ik,[])->(string_of_identik)|(ik,sargs)->Printf.sprintf"%s<<%s>>"(string_of_identik)(String.concat", "(List.mapstring_of_static_argsargs))andstring_of_static_arg=function|ConstStaticArgLic(id,ceff)->Printf.sprintf"const %s = %s"id(string_of_constceff)|TypeStaticArgLic(id,teff)->Printf.sprintf"type %s = %s"id(string_of_typeteff)(* | NodeStaticArgLic (id, ((long,sargs), _, _), _) -> *)|NodeStaticArgLic(id,nk)->Printf.sprintf"node %s = %s"id(string_of_node_keynk)andstring_of_type_vartv=string_of_type(TypeVartv)andstring_of_type_matchespm=letsotm(tv,t)=Printf.sprintf"%s <- %s"(string_of_type_vartv)(string_of_typet)inString.concat", "(List.mapsotmpm)letstring_of_node_expne=(Printf.sprintf" node_key_eff = %s\n"(string_of_node_keyne.node_key_eff))^(Printf.sprintf" inlist_eff = %s\n"(string_of_var_listne.inlist_eff))^(Printf.sprintf" outlist_eff = %s\n"(string_of_var_listne.outlist_eff))(* ne.loclist_eff : var_info list option; (* None => extern or abstract *) *)(* ne.def_eff : node_def; *)(* ne.has_mem_eff : bool; *)(* ne.is_safe_eff : bool; *)(* NodeStaticArgLic of (Lv6Id.t * sarg_node_eff * node_exp) *)(* sarg_node_eff = node_key * var_info list * var_info list *)(* utile : liste standard de var_info a partir de liste de type *)letcreate_var_listnattl=letpfx=matchnatwith|AstCore.VarInput->"i"|AstCore.VarOutput->"o"|AstCore.VarLocal->assertfalseinletcpt=ref1inletdovart=(leti=!cptinletid=Printf.sprintf"%s%d"pfxiinincrcpt;{var_name_eff=id;var_nature_eff=nat;var_number_eff=i;var_type_eff=t;(* ???? *)var_clock_eff=(id,BaseLic);})inList.mapdovartlletcreate_varnattname={var_name_eff=name;var_nature_eff=nat;var_number_eff=0;var_type_eff=t;(* ???? *)var_clock_eff=(name,BaseLic);}(*---------------------------------------------------------------------
Une erreur associée à un noeud + 1 lexeme dans le fichier source
----------------------------------------------------------------------*)exceptionCompile_node_errorofnode_key*Lxm.t*stringexceptionGlobal_node_errorofnode_key*string(******************************************************************************)(* topologically sort vars wrt their clock dependecency *)moduleTopoSortVarInfo=TopoSort.Make(structtypeelt=var_infotypestore=(var_info,var_infolist)Hashtbl.tletfind_deptblx=tryHashtbl.findtblxwithNot_found->[]lethave_deptblx=tryHashtbl.findtblx<>[]withNot_found->falseletremove_deptblx=Hashtbl.removetblx;tblend)(* Looks like the one in LicTab *)let(sort_var_info:var_infolist->var_infolist)=funvars->(* we sort vars according to their clock deps *)letvartable=Hashtbl.create(List.lengthvars)inletfind_direct_depv_vars=matchsndv.var_clock_effwith|BaseLic->None|ClockVar_->None|On((_cc,cv,_ct),_sclk)->(* Printf.printf "sort_var_info: %s depends on %s\n" v.var_name_eff cv; *)flushstdout;trySome(Hashtbl.findvartablecv)withNot_found->Noneinletdep_starvars=lettbl=Hashtbl.create(List.lengthvars)inletrecfind_depsv=ifHashtbl.memtblvthenHashtbl.findtblvelsematchfind_direct_depvvarswith|None->[]|Somev2->letv2_deps=find_depsv2inletv_deps=v2::v2_depsinHashtbl.replacetblvv_deps;v_depsinList.iter(funv->matchfind_depsvwith|[]->Hashtbl.removetblv(* cleaning *)|_::_->())vars;tblinList.iter(funv->Hashtbl.addvartablev.var_name_effv)vars;TopoSortVarInfo.f(dep_starvars)vars