Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file types.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372(* The canonical index of a type. Abstract outside this module (its .mli exposes
neither [of_int] nor [to_int]), so an [Id.t] elsewhere can only originate from
the store — never be fabricated from, or mistaken for, a source-level or
wire-level integer. *)moduleId=structtypet=intletof_inti=iletto_inti=iletto_int_for_tests_only=to_intletequal=Int.equalletaddidn=id+nend(* The internal (resolved) type representation: type references carry the
abstract canonical [Id.t] rather than the wire format's plain [int]. The type
store and validation reason about this; the binary/text codec stays on
[Ast.Binary]. *)moduleInternal=structmoduleX=structtypeidx=Id.ttype'aannotated_array='aarraytype'aopt_annotated_array='aarrayendincludeAst.Make_types(X)typetabletype={limits:limits;reftype:reftype}endmoduleI=Internal(* A reference inside a *normalized* rec-type. An intra-group back-reference is
the constructor [Rec] carrying the referenced member's position in the group;
a reference to an already-defined type is [Def] carrying its canonical index.
Making these two distinct constructors — rather than a canonical index and a
negative sign-bit sharing one integer space — means they can no longer be
confused, and an [Id.t] is only ever a genuine store index. A caller resolving
a source rec group builds [Normalized.rectype] directly. *)typeref_index=Defof Id.t|RecofintmoduleNormalized=structmoduleX=structtypeidx=ref_indextype'aannotated_array='aarraytype 'aopt_annotated_array ='aarrayendincludeAst.Make_types(X)endmoduleN=Normalizedtypenormalized_rectype=N.rectype(* Deduplication keys on the normalized form directly: two structurally-equal rec
groups yield equal normalized values. The structural hash/equality below is
the tuned one carried over from the binary representation, now over [N]. *)moduleRecTypeTbl=Hashtbl.Make(structopenNtypet=N.rectypelethasht=(* We have large structs, that tend to hash to the same value *)Hashtbl.hash_param15100tletheaptype_eqt1t2=t1==t2||match(t1,t2)with|Typei1,Typei2|Exacti1,Exacti2->i1=i2|_->falseletreftype_eq{nullable=n1;typ=t1}{nullable=n2;typ=t2}=n1=n2&&heaptype_eqt1t2letvaltype_eqt1t2=t1==t2||match(t1,t2)withReft1,Reft2->reftype_eqt1t2|_->falseletstoragetype_eqt1t2=match(t1,t2)with|Valuev1,Valuev2->valtype_eqv1v2|Packedp1,Packedp2->p1==p2|_->falseletfieldtype_eq{mut=m1;typ=t1}{mut=m2;typ=t2}=m1=m2&&storagetype_eqt1t2(* Does not allocate and return false on length mismatch *)letarray_for_all2pa1a2=letn1=Array.lengtha1andn2=Array.lengtha2inn1=n2&&letreclooppa1a2n1i=i=n1||(pa1.(i)a2.(i)&&looppa1a2n1(succi))inlooppa1a2n10letcomptype_eq(t1:comptype)(t2:comptype)=match(t1,t2)with|Func{params=p1;results=r1},Func{params=p2;results=r2}->array_for_all2valtype_eqp1p2&&array_for_all2valtype_eqr1r2|Structl1,Structl2->array_for_all2fieldtype_eql1l2|Arrayf1,Arrayf2->fieldtype_eqf1f2|Conti1,Conti2->heaptype_eq(Typei1)(Typei2)|_->falseletsubtype_eq{final=f1;supertype=s1;typ=t1;_}{final=f2;supertype=s2;typ=t2;_}=f1=f2&&(match(s1,s2)with|Some_,None|None,Some_->false|None,None->true|Somei1,Somei2->i1=i2)&&comptype_eqt1t2letequalt1t2=match(t1,t2)with|[|t1|],[|t2|]->subtype_eqt1t2|_->array_for_all2subtype_eqt1t2end)typet={types:intRecTypeTbl.t;mutablelast_index:int;mutablerev_list:(int*normalized_rectype)list;}letcreate()={types=RecTypeTbl.create2000;last_index=0;rev_list=[]}letlast_indextypes=types.last_index(* Lower a normalized subtype to the internal (resolved) form, mapping every
reference with [f]. Both forms use plain arrays, so the array wrappers are a
straight [Array.map]; only the [idx] arms change. Shared by
[subtyping_info]/[get_all_rectypes] (resolving a back-reference to its
absolute canonical index) and the backstop (visiting every reference to
validate it). *)moduleN_to_I=Ast.Map_types(N)(I)(structtypectx=ref_index->Id.tletidxfi=filetparams_fa=Array.mapfaletfields_fa=Array.mapfaletmembers_fa=Array.mapfaend)letsubtype_to_internal(f:ref_index->Id.t)(s:N.subtype):I.subtype=N_to_I.subtypefs(* Backstop for the normalization contract (see [add_rectype] in the .mli). A
[Rec] back-reference must fall inside the group and a [Def] must denote an
already-defined type; [last_index] is the base index this group is about to
receive, so a well-formed [Def] is strictly below it. A violation is a
mis-normalized group (the source-vs-canonical index confusion class) and is
rejected here rather than silently corrupting the subtyping relation. *)letcheck_normalizedtypes(rt:normalized_rectype)=letn=Array.lengthrtinletcheck_ref=function|Recpos->ifpos<0||pos>=ntheninvalid_arg"Types.add_rectype: back-reference outside the rec group"|Defid->ifId.to_intid<0||Id.to_intid>=types.last_indextheninvalid_arg"Types.add_rectype: reference to an undefined or in-group type"inArray.iter(funs->ignore(subtype_to_internal(funr->check_refr;Id.of_int0)s))rtletadd_rectypetypes(typ:normalized_rectype)=check_normalizedtypestyp;Id.of_int(tryRecTypeTbl.findtypes.typestypwithNot_found->letindex=types.last_indexinRecTypeTbl.addtypes.typestypindex;types.last_index<-Array.lengthtyp+index;types.rev_list<-(index,typ)::types.rev_list;index)typesubtyping_info=I.subtypearray(* Resolve every reference to an absolute canonical index: a [Def] is already
one; a [Rec pos] is the [pos]-th member of a group based at [base]. *)letresolve_refbase=function|Defid->id|Recpos->Id.of_int(base+pos)letsubtyping_infot=letl=List.map(fun(base,a)->Array.map(subtype_to_internal(resolve_refbase))a)t.rev_listinArray.concat(List.revl)letget_subtypeai=a.(Id.to_inti)letget_all_rectypest=List.map(fun(base,a)->Array.map(subtype_to_internal(resolve_refbase))a)(List.revt.rev_list)letrecsubtypesubtyping_info(i:Id.t)i'=Id.equalii'||matchsubtyping_info.(Id.to_inti).I.supertypewith|None->false|Somes->subtypesubtyping_infosi'letheap_subtype(subtyping_info:I.subtypearray)(ty:I.heaptype)(ty':I.heaptype)=letopenIin(* Which top hierarchy a concrete type index [i] belongs to. Enumerating the
comptype constructors (no [_]) means a newly added comptype forces every
concrete-type arm below to be revisited. *)letis_structi=matchsubtyping_info.(Id.to_inti).typwith|Struct_->true|Func_|Array_|Cont_->falseinletis_arrayi=matchsubtyping_info.(Id.to_inti).typwith|Array_->true|Func_|Struct_|Cont_->falseinletis_funci=matchsubtyping_info.(Id.to_inti).typwith|Func_->true|Struct_|Array_|Cont_->falseinletis_conti=matchsubtyping_info.(Id.to_inti).typwith|Cont_->true|Func_|Struct_|Array_->falseinletis_aggregatei=is_structi||is_arrayiin(* Matched supertype-first, then subtype, both exhaustively and without a [_]
row, so a new heap type constructor forces every relevant arm to be
revisited. An [exact i] reference has the same proper supertypes as [i]
(via [exact i <: i]), so on the left it follows the [Type i] rules; the
bottom heap types are subtypes of the exact concrete types too. *)matchty'with|Func->(matchtywith|Func|NoFunc->true|Typei|Exacti->is_funci|Exn|NoExn|Cont|NoCont|Extern|NoExtern|Any|Eq|I31|Struct|Array|None_->false)|NoFunc->(matchtywith|NoFunc->true|Func|Exn|NoExn|Cont|NoCont|Extern|NoExtern|Any|Eq|I31|Struct|Array|None_|Type_|Exact_->false)|Exn->(matchtywith|Exn|NoExn->true|Func|NoFunc|Cont|NoCont|Extern|NoExtern|Any|Eq|I31|Struct|Array|None_|Type_|Exact_->false)|NoExn->(matchtywith|NoExn->true|Func|NoFunc|Exn|Cont|NoCont|Extern|NoExtern|Any|Eq|I31|Struct|Array|None_|Type_|Exact_->false)|Cont->(matchtywith|Cont|NoCont->true|Typei|Exacti->is_conti|Func|NoFunc|Exn|NoExn|Extern|NoExtern|Any|Eq|I31|Struct|Array|None_->false)|NoCont->(matchtywith|NoCont->true|Func|NoFunc|Exn|NoExn|Cont|Extern|NoExtern|Any|Eq|I31|Struct|Array|None_|Type_|Exact_->false)|Extern->(matchtywith|Extern|NoExtern->true|Func|NoFunc|Exn|NoExn|Cont|NoCont|Any|Eq|I31|Struct|Array|None_|Type_|Exact_->false)|NoExtern->(matchtywith|NoExtern->true|Func|NoFunc|Exn|NoExn|Cont|NoCont|Extern|Any|Eq|I31|Struct|Array|None_|Type_|Exact_->false)|Any->(matchtywith|Any|Eq|I31|Struct|Array|None_->true|Typei|Exacti->is_aggregatei|Func|NoFunc|Exn|NoExn|Cont|NoCont|Extern|NoExtern->false)|Eq->(matchtywith|Eq|I31|Struct|Array|None_->true|Typei|Exacti->is_aggregatei|Any|Func|NoFunc|Exn|NoExn|Cont|NoCont|Extern|NoExtern->false)|I31->(matchtywith|I31|None_->true|Any|Eq|Struct|Array|Func|NoFunc|Exn|NoExn|Cont|NoCont|Extern|NoExtern|Type_|Exact_->false)|Struct->(matchtywith|Struct|None_->true|Typei|Exacti->is_structi|Any|Eq|I31|Array|Func|NoFunc|Exn|NoExn|Cont|NoCont|Extern|NoExtern->false)|Array->(matchtywith|Array|None_->true|Typei|Exacti->is_arrayi|Any|Eq|I31|Struct|Func|NoFunc|Exn|NoExn|Cont|NoCont|Extern|NoExtern->false)|None_->(matchtywith|None_->true|Any|Eq|I31|Struct|Array|Func|NoFunc|Exn|NoExn|Cont|NoCont|Extern|NoExtern|Type_|Exact_->false)|Typei'->(matchtywith|Typei|Exacti->subtypesubtyping_infoii'|None_->is_aggregatei'|NoFunc->is_funci'|NoCont->is_conti'|Func|Exn|NoExn|Cont|Extern|NoExtern|Any|Eq|I31|Struct|Array->false)|Exacti'->(matchtywith(* [exact] is invariant among concrete types: only the same exact type. *)|Exacti->Id.equalii'|None_->is_aggregatei'|NoFunc->is_funci'|NoCont->is_conti'|Type_|Func|Exn|NoExn|Cont|Extern|NoExtern|Any|Eq|I31|Struct|Array->false)letref_subtypesubtyping_info{I.nullable;typ}{I.nullable=nullable';typ=typ'}=((notnullable)||nullable')&&heap_subtypesubtyping_infotyptyp'letval_subtypesubtyping_infotyty'=match(ty,ty')with|I.Reft,I.Reft'->ref_subtypesubtyping_infott'|_->ty==ty'