Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file type_immediacy.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445(* This module is very much dependent on the runtime representation of values. Should the
way the compiler represents various types change, it needs to be reflected in this
module, otherwise bad things could happen. Therefore the conversions and
representations are tested thoroughly in [../test/test_witness.ml] and
[../test/test_conversions.ml]
*)open!ImportmoduleList=Base.ListmoduleHash_set=Base.Hash_setletsprintf=Printf.sprintfmoduleKey=structtypet=int[@@derivingcompare,sexp_of](* The integers here are the values underlying the polymorphic variants, they already
are hashes of constructor names, and hence are expected to be uniformly
distributed. *)lethashx=xendmoduleAllowed_ints=structtypet=|None|All|Hash_setofHash_set.M(Key).t|From_zero_toofintlet_invariant=function|None|All|Hash_set_->()|From_zero_ton->assert(n>=0);;letint_is_valueti=matchtwith|None->false|All->true|Hash_sethash_set->Hash_set.memhash_seti|From_zero_ton->0<=i&&i<=n;;endmoduleImmediacy=structtypet=|Always|Sometimes|Never|Unknown[@@derivingcompare]letequal=[%compare.equal:t]letto_string=function|Always->"Always"|Sometimes->"Sometimes"|Never->"Never"|Unknown->"Unknown";;endopenImmediacymoduleT:sigtype'atvalcreate:'aTypename.t->Immediacy.t->Allowed_ints.t->'atvalcreate_with_name:string->Immediacy.t->Allowed_ints.t->_tvalimmediacy:_t->Immediacy.tvalallowed_ints:_t->Allowed_ints.tvaltypename:_t->stringmoduleNever_values:sigvalint32:int32tvalint64:int64tvalnativeint:nativeinttvalfloat:floattvalstring:stringtvalbytes:bytestvalarray:_arraytvalref_:_reftvaltuple2:(_*_)tvaltuple3:(_*_*_)tvaltuple4:(_*_*_*_)tvaltuple5:(_*_*_*_*_)tvalfunction_:(_->_)tendvalnever:'aTypename.t->'atvalunknown:'aTypename.t->'atvaloption:_tvallist:_tvalmagic:_t->_tend=structtypet_={immediacy:Immediacy.t;allowed_ints:Allowed_ints.t;typename:string}type'at=t_letcreate_with_nametypenameimmediacyallowed_ints={immediacy;allowed_ints;typename};;letcreatetypenameimmediacyallowed_ints=create_with_name(Typename.nametypename)immediacyallowed_ints;;letimmediacyt=t.immediacyletallowed_intst=t.allowed_intslettypenamet=t.typenameletmagict=tletnever_with_namename=create_with_namenameNeverNoneletnevertypename=createtypenameNeverNoneletunknowntypename=createtypenameUnknownNoneletoption=create_with_name"option"Sometimes(Allowed_ints.From_zero_to0)letlist=create_with_name"list"Sometimes(Allowed_ints.From_zero_to0)moduleNever_values=struct(* int32 is boxed even on 64b platform at the moment. *)letint32=nevertypename_of_int32letint64=nevertypename_of_int64letnativeint=nevertypename_of_nativeintletfloat=nevertypename_of_floatletstring=nevertypename_of_stringletbytes=nevertypename_of_bytesletarray=never_with_name"array"letref_=never_with_name"ref"lettuple2=never_with_name"tuple2"lettuple3=never_with_name"tuple3"lettuple4=never_with_name"tuple4"lettuple5=never_with_name"tuple5"letfunction_=never_with_name"function"endendincludeTletint=createtypename_of_intAlwaysAllowed_ints.Allletunit=createtypename_of_unitAlways(Allowed_ints.From_zero_to0)letbool=createtypename_of_boolAlways(Allowed_ints.From_zero_to1)letchar=createtypename_of_charAlways(Allowed_ints.From_zero_to255)moduleComputation_impl=structtypenonrec'at='atincludeType_generic.Variant_and_record_intf.M(structtypenonrec'at='atend)includeNever_valuesletref__=ref_letarray_=arraylettuple2__=tuple2lettuple3___=tuple3lettuple4____=tuple4lettuple5_____=tuple5letfunction___=function_letint=intletchar=charletbool=boolletunit=unitletoption_=optionletlist_=list(* An [a Lazy.t] might be a boxed closure, so must have immediacy either [Never] or
[Sometimes]. An [a Lazy.t] value could be immediate if [a] is immediate. But if [a]
is never immediate, then [a Lazy.t] cannot be. *)letlazy_tt=letimmediacy=matchimmediacytwith|Never->Never|Unknown->Unknown|Sometimes|Always->Sometimesincreate_with_name"lazy_t"immediacy(allowed_intst);;letpossibly_unboxedtypenamechild_type=matchimmediacychild_typewith|Never->nevertypename|Unknown|Always|Sometimes->unknowntypename;;letrecordr=ifRecord.lengthr>1thennever(Record.typename_of_tr)else(let(Fieldthe_only_field)=Record.fieldr0inpossibly_unboxed(Record.typename_of_tr)(Field.traversethe_only_field));;(* Variants with all constructors having no arguments are always immediate; variants
with all constructors having some arguments are never immediate; mixed variants are
sometimes immediate.
If a variant has a single constructor, and the constructor has an argument, the
variant can be unboxed. If unboxed, either explicitly or by default (depending on
compiler settings), the representation is simply the argument. Otherwise, the rules
above apply normally. *)letvariantvariant=letno_arg_list,one_arg_list,more_arg_list=Variant.foldvariant~init:([],[],[])~f:(fun(no,one,more)(Tagtastag)->matchTag.aritytwith|0->tag::no,one,more|1->no,tag::one,more|_->no,one,tag::more)inmatchno_arg_list,one_arg_list,more_arg_listwith|[],[Tagtag],[]whennot(Variant.is_polymorphicvariant)->possibly_unboxed(Variant.typename_of_tvariant)(Tag.traversetag)|[],[],[]->(* We don't have an explict way of saying a type is uninhabited. *)unknown(Variant.typename_of_tvariant)|[],_::_,_|[],_,_::_->never(Variant.typename_of_tvariant)|_::_,_,_->letno_arg_count=List.lengthno_arg_listinletallowed_ints=ifnot(Variant.is_polymorphicvariant)thenAllowed_ints.From_zero_to(no_arg_count-1)else(lethash_set=Hash_set.create(moduleKey)~size:(no_arg_count*2)inList.iterno_arg_list~f:(fun(Tagtag)->matchTag.createtagwith|Tag.Const_->Hash_set.addhash_set(Tag.ocaml_reprtag)|Tag.Args_->assertfalse);Allowed_ints.Hash_sethash_set)inletimmediacy=ifList.is_emptyone_arg_list&&List.is_emptymore_arg_listthenAlwayselseSometimesincreate(Variant.typename_of_tvariant)immediacyallowed_ints;;letname="is_immediate"letrequired=[]moduleNamed=structmoduleContext=structtypet=unitletcreate()=()endtypenonrec'at='atref(* The default witness - which is created by calling [init] and recovered at any later
point by calling [get_wip_computation] - can only be used in a recursive type.
Other types that don't use [get_wip_computation] will just evaluate to the actual
witness which will replace the initial dummy one. *)letinit_name=ref(createnameSometimesAllowed_ints.None)letget_wip_computationcomp=!completset_final_computationrt=r:=t;t;;letshare_=trueendendmoduleGeneric=Type_generic.Make(Computation_impl)letof_typereptyperep=let(`generict)=Generic.of_typereptyperepint;;moduleFor_all_parameters(M:sigvalimmediacy:Immediacy.tend)=structletwitnesstyperep1typerep2=lett1=of_typereptyperep1inlett2=of_typereptyperep2inleti1=immediacyt1inleti2=immediacyt2inifnot(Immediacy.equali1i2)thenfailwith(sprintf"type %s is not independent of its arguments"(Typename.name(Typerep.typename_of_ttyperep1)))elseifnot(Immediacy.equali1M.immediacy)thenfailwith(sprintf"type %s does not have desired immediacy: wanted %s but got %s"(Typename.name(Typerep.typename_of_ttyperep1))(Immediacy.to_stringM.immediacy)(Immediacy.to_stringi1))elset1;;(* always immediate *)letra=Typerep.Int(* never immediate *)letrn=Typerep.String(* Each of the [For_all_parameters_*] functors works by instantiating the n-ary type
with all [Always] types, and then with all [Never] types. If those produce the same
immediacy, then we conclude that the n-ary type is independent of its arguments. *)moduleFor_all_parameters_S1(X:Typerepable.S1)=structlett=witness(X.typerep_of_tra)(X.typerep_of_trn)letwitness()=magictendmoduleFor_all_parameters_S2(X:Typerepable.S2)=structlett=witness(X.typerep_of_trara)(X.typerep_of_trnrn)letwitness()=magictendmoduleFor_all_parameters_S3(X:Typerepable.S3)=structlett=witness(X.typerep_of_trarara)(X.typerep_of_trnrnrn)letwitness()=magictendmoduleFor_all_parameters_S4(X:Typerepable.S4)=structlett=witness(X.typerep_of_trararara)(X.typerep_of_trnrnrnrn)letwitness()=magictendmoduleFor_all_parameters_S5(X:Typerepable.S5)=structlett=witness(X.typerep_of_trarararara)(X.typerep_of_trnrnrnrnrn)letwitness()=magictendendletint_is_valuetint=Allowed_ints.int_is_value(allowed_intst)intletint_as_value(typea)(t:at)int=ifint_is_valuetintthenSome(Obj.magic(int:int):a)elseNone;;letint_as_value_exn(typea)(t:at)int=ifint_is_valuetintthen(Obj.magic(int:int):a)elsefailwith(sprintf"Immediate.int_as_value_exn: typename:%S int:%d"(T.typenamet)int);;letvalue_as_int_exn(typea)(t:at)a=ifObj.is_int(Obj.repra)then(Obj.magic(a:a):int)elsefailwith(sprintf"Immediate.value_as_int_exn: typename:%S"(T.typenamet));;letvalue_as_int(typea)(_:at)a=ifObj.is_int(Obj.repra)thenSome(Obj.magic(a:a):int)elseNone;;letvalue_is_int(typea)(_:at)a=Obj.is_int(Obj.repra)moduleAlways=structtypenonrec'at='atincludeFor_all_parameters(structletimmediacy=Alwaysend)letof_typereptyperep=lett=of_typereptyperepinmatchimmediacytwith|Always->Somet|Unknown|Never|Sometimes->None;;letof_typerep_exnheretyperep=Option.value_exn~here(of_typereptyperep)letint_as_value=int_as_valueletint_as_value_exn=int_as_value_exnletint_is_value=int_is_valuelet[@inlinealways]value_as_int(typea)_a=a|>(Obj.magic:a->int)letint=intletchar=charletbool=boolletunit=unitendmoduleSometimes=structtypenonrec'at='atincludeFor_all_parameters(structletimmediacy=Sometimesend)letof_typereptyperep=lett=of_typereptyperepinmatchimmediacytwith|Sometimes->Somet|Unknown|Always|Never->None;;letof_typerep_exnheretyperep=Option.value_exn~here(of_typereptyperep)letint_as_value=int_as_valueletint_as_value_exn=int_as_value_exnletint_is_value=int_is_valueletvalue_as_int=value_as_intletvalue_as_int_exn=value_as_int_exnletvalue_is_int=value_is_intletoption=optionletlist=listendmoduleNever=structtypenonrec'at='atincludeFor_all_parameters(structletimmediacy=Neverend)letof_typereptyperep=lett=of_typereptyperepinmatchimmediacytwith|Never->Somet|Unknown|Always|Sometimes->None;;letof_typerep_exnheretyperep=Option.value_exn~here(of_typereptyperep)includeNever_valuesendtype'adest=|Alwaysof'aAlways.t|Sometimesof'aSometimes.t|Neverof'aNever.t|Unknownletdestt=matchimmediacytwith|Always->Alwayst|Sometimes->Sometimest|Never->Nevert|Unknown->Unknown;;