namespace WoofWare.PawPrint open System open System.Reflection open System.Reflection.Metadata type FakeUnit = private | FakeUnit [] module FakeUnit = let ofUnit () = FakeUnit.FakeUnit let toUnit (f : FakeUnit) = match f with | FakeUnit.FakeUnit -> () /// A type which has been concretised, runtime-representable, etc. [] [] type ConcreteType<'typeGeneric when 'typeGeneric : comparison and 'typeGeneric :> IComparable<'typeGeneric>> = private { _AssemblyName : AssemblyName _Definition : ComparableTypeDefinitionHandle _Name : string _Namespace : string _Generics : 'typeGeneric list } member this.Assembly : AssemblyName = this._AssemblyName member this.Definition : ComparableTypeDefinitionHandle = this._Definition member this.Generics : 'typeGeneric list = this._Generics member this.Name = this._Name member this.Namespace = this._Namespace override this.Equals (other : obj) : bool = match other with | :? ConcreteType<'typeGeneric> as other -> this._Generics = other._Generics && this._Definition = other._Definition && this._AssemblyName.FullName = other._AssemblyName.FullName | _ -> false override this.GetHashCode () : int = hash (this._AssemblyName.FullName, this._Definition, this._Generics) interface IComparable> with member this.CompareTo (other : ConcreteType<'typeGeneric>) : int = let comp = this._AssemblyName.FullName.CompareTo other._AssemblyName.FullName if comp = 0 then let comp = (this._Definition :> IComparable).CompareTo other._Definition if comp = 0 then let thisGen = (this._Generics : 'typeGeneric list) :> IComparable<'typeGeneric list> thisGen.CompareTo other._Generics else comp else comp interface IComparable with member this.CompareTo other = match other with | :? ConcreteType<'typeGeneric> as other -> (this :> IComparable>).CompareTo other | _ -> failwith "bad comparison" type RuntimeConcreteType = ConcreteType [] module ConcreteType = let make (assemblyName : AssemblyName) (ns : string) (name : string) (defn : TypeDefinitionHandle) (generics : TypeDefn list) : RuntimeConcreteType = { _AssemblyName = assemblyName _Definition = ComparableTypeDefinitionHandle.Make defn _Name = name _Namespace = ns _Generics = generics } let make' (assemblyName : AssemblyName) (defn : TypeDefinitionHandle) (ns : string) (name : string) (genericParamCount : int) : ConcreteType = { _AssemblyName = assemblyName _Definition = ComparableTypeDefinitionHandle.Make defn _Name = name _Namespace = ns _Generics = List.replicate genericParamCount FakeUnit.FakeUnit } let mapGeneric<'a, 'b when 'a : comparison and 'a :> IComparable<'a> and 'b : equality and 'b : comparison and 'b :> IComparable<'b>> (f : int -> 'a -> 'b) (x : ConcreteType<'a>) : ConcreteType<'b> = let generics = x._Generics |> List.mapi f { _AssemblyName = x._AssemblyName _Definition = x._Definition _Generics = generics _Name = x._Name _Namespace = x._Namespace }