123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210openPrintfopenAg_errortypeloc=Atd_ast.locletannot_errorloc=Ag_error.errorloc"Invalid annotation"typeloc_id=string(*
Generic mapping, based on the core ATD types
*)type('a,'b)mapping=[`Unitof(loc*'a*'b)|`Boolof(loc*'a*'b)|`Intof(loc*'a*'b)|`Floatof(loc*'a*'b)|`Stringof(loc*'a*'b)|`Sumof(loc*('a,'b)variant_mappingarray*'a*'b)|`Recordof(loc*('a,'b)field_mappingarray*'a*'b)|`Tupleof(loc*('a,'b)cell_mappingarray*'a*'b)|`Listof(loc*('a,'b)mapping*'a*'b)|`Optionof(loc*('a,'b)mapping*'a*'b)|`Nullableof(loc*('a,'b)mapping*'a*'b)|`Wrapof(loc*('a,'b)mapping*'a*'b)|`Nameof(loc*string*('a,'b)mappinglist*'aoption*'boption)|`Externalof(loc*string*('a,'b)mappinglist*'a*'b)|`Tvarof(loc*string)]and('a,'b)cell_mapping={cel_loc:loc;cel_value:('a,'b)mapping;cel_arepr:'a;cel_brepr:'b}and('a,'b)field_mapping={f_loc:loc;f_name:string;f_kind:Atd_ast.field_kind;f_value:('a,'b)mapping;f_arepr:'a;f_brepr:'b}and('a,'b)variant_mapping={var_loc:loc;var_cons:string;var_arg:('a,'b)mappingoption;var_arepr:'a;var_brepr:'b}type('a,'b)def={def_loc:loc;def_name:string;def_param:stringlist;def_value:('a,'b)mappingoption;def_arepr:'a;def_brepr:'b;}letas_abstract=function`Name(_,(loc,"abstract",l),a)->ifl<>[]thenerrorloc"\"abstract\" takes no type parameters";Some(loc,a)|_->Noneletis_abstractx=as_abstractx<>Noneletloc_of_mappingx=match(x:(_,_)mapping)with`Unit(loc,_,_)|`Bool(loc,_,_)|`Int(loc,_,_)|`Float(loc,_,_)|`String(loc,_,_)|`Sum(loc,_,_,_)|`Record(loc,_,_,_)|`Tuple(loc,_,_,_)|`List(loc,_,_,_)|`Option(loc,_,_,_)|`Nullable(loc,_,_,_)|`Wrap(loc,_,_,_)|`Name(loc,_,_,_,_)|`External(loc,_,_,_,_)|`Tvar(loc,_)->locmoduleEnv=Map.Make(String)letrecsubstenv(x:(_,_)mapping)=matchxwith`Unit(loc,_,_)|`Bool(loc,_,_)|`Int(loc,_,_)|`Float(loc,_,_)|`String(loc,_,_)->x|`Sum(loc,ar,a,b)->`Sum(loc,Array.map(subst_variantenv)ar,a,b)|`Record(loc,ar,a,b)->`Record(loc,Array.map(subst_fieldenv)ar,a,b)|`Tuple(loc,ar,a,b)->`Tuple(loc,Array.map(subst_cellenv)ar,a,b)|`List(loc,x,a,b)->`List(loc,substenvx,a,b)|`Option(loc,x,a,b)->`Option(loc,substenvx,a,b)|`Nullable(loc,x,a,b)->`Nullable(loc,substenvx,a,b)|`Wrap(loc,x,a,b)->`Wrap(loc,substenvx,a,b)|`Name(loc,name,args,a,b)->`Name(loc,name,List.map(substenv)args,a,b)|`External(loc,name,args,a,b)->`External(loc,name,List.map(substenv)args,a,b)|`Tvar(loc,s)->tryEnv.findsenvwithNot_found->invalid_arg(sprintf"Ag_mapping.subst_var: '%s"s)andsubst_variantenvx=matchx.var_argwithNone->x|Somev->{xwithvar_arg=Some(substenvv)}andsubst_fieldenvx={xwithf_value=substenvx.f_value}andsubst_cellenvx={xwithcel_value=substenvx.cel_value}(*
Substitute type variables param in x by args
*)letapplyparamxargs=ifList.lengthparam<>List.lengthargstheninvalid_arg"Ag_mapping.apply";letenv=List.fold_left2(funenvvarvalue->Env.addvarvalueenv)Env.emptyparamargsinsubstenvxletrecfind_namelocenvvisitedname=ifList.memnamevisitedthenerrorloc"Cyclic type definition"elseletparam,x=Env.findnameenvin(param,deref_exprenv(name::visited)x)andderef_exprenvvisitedx=matchxwith`Name(loc,name,args,_,_)->(tryletparam,x=find_namelocenvvisitednameinapplyparamxargswithNot_found->x)|_->xletflattenl=List.flatten(List.mapsndl)letmake_deref(l:(bool*('a,'b)deflist)list):(('a,'b)mapping->('a,'b)mapping)=letdefs=List.fold_left(funenvd->matchd.def_valuewithNone->env|Somev->Env.addd.def_name(d.def_param,v)env)Env.empty(flattenl)infunx->deref_exprdefs[]x(*
Resolve names and unwrap `wrap` constructs
(discarding annotations along the way)
*)letrecunwrap(deref:('a,'b)mapping->('a,'b)mapping)x=matchderefxwith|`Wrap(loc,x,a,b)->unwrapderefx|x->x(* This is for debugging *)letconstructor:('a,'b)mapping->string=function|`Unit_->"Unit"|`Bool_->"Bool"|`Int_->"Int"|`Float_->"Float"|`String_->"String"|`Sum_->"Sum"|`Record_->"Record"|`Tuple_->"Tuple"|`List_->"List"|`Option_->"Option"|`Nullable_->"Nullable"|`Wrap_->"Wrap"|`Name(loc,name,_,_,_)->"Name "^name|`External_->"External"|`Tvar_->"Tvar"