/Fing/FSharpTypes.fs

http://github.com/sandersn/fing · F# · 101 lines · 75 code · 4 blank · 22 comment · 12 complexity · 9a361bceb477c8856688cb8adde56af9 MD5 · raw file

  1. // Copyright (c) 2010, Nathan Sanders
  2. // Licence: New BSD. See accompanying documentation.
  3. /// code specific to types retrieved from FSharp.Powerpack.Metadata
  4. module FSharpTypes
  5. open Microsoft.FSharp.Metadata
  6. open Types
  7. let rec debinarize t =
  8. let rec debinarise = function
  9. | Arrow [t; Arrow ts] -> match debinarize (Arrow ts) with
  10. | Arrow ts -> Some (Arrow (debinarize t::ts))
  11. | _ -> failwith "oh no"
  12. | _ -> None
  13. Types.map debinarise id t
  14. let isArray (e:FSharpType) =
  15. let name = e.NamedEntity.DisplayName
  16. // it appears that DisplayName can either be array or []
  17. // I think this is inconsistency on the part of either the Powerpack or (more likely)
  18. // the F# runtime in allowing Set.ofArray : array<'t> -> Set<'t>
  19. // while all the Array functions are eg : ('a -> 'b) -> 'a[] -> 'b[]
  20. // OH WELL. Should work now
  21. name = "array" || name.StartsWith "[" && name.EndsWith "]"
  22. /// e must be the FSharpType of an array
  23. let dimensions (e:FSharpType) =
  24. match e.NamedEntity.DisplayName with
  25. | "array" -> 1
  26. | brackets -> brackets.Length - 1
  27. let tryFindConstraint (param:FSharpGenericParameter) (p,f) =
  28. match param.Constraints |> Seq.tryFind p with
  29. | Some(x) -> Some (f x)
  30. | None -> None
  31. let rec optionsum = function
  32. | [] -> None
  33. | Some(x)::xs -> Some(x)
  34. | None::xs -> optionsum xs
  35. (* FSharpType -> Typ, no longer a Ty<System.Type,string>
  36. TODO: cvtParam is not done, it really only does type defaulting as yet
  37. *)
  38. let rec cvt (e:FSharpType) =
  39. if e.IsTuple then
  40. Tuple (e.GenericArguments |> Seq.map cvt |> List.ofSeq)
  41. elif e.IsFunction then
  42. Arrow (e.GenericArguments |> Seq.map cvt |> List.ofSeq)
  43. elif e.IsGenericParameter then
  44. cvtParam e.GenericParameter // TODO: cvtParam is very much not done
  45. elif e |> isArray then // It only has in defaulting so far
  46. Array(dimensions e, e.GenericArguments |> Seq.map cvt |> Seq.head)
  47. else
  48. match e.NamedEntity |> canonicalType, e.GenericArguments |> Seq.map cvt |> List.ofSeq with
  49. | t,[] -> t
  50. | Generic(t,_),args -> Generic(t,args)
  51. | t,args -> Generic(t, args)
  52. and cvtParam (param:FSharpGenericParameter) =
  53. if Seq.isEmpty param.Constraints then
  54. Var (Normal param.Name)
  55. else
  56. match param.Constraints
  57. |> Seq.tryFind (fun c -> c.IsDefaultsToConstraint
  58. && c.DefaultsToTarget.IsNamed) with
  59. | Some def -> def.DefaultsToTarget.NamedEntity |> canonicalType
  60. | None -> Var (Normal param.Name)
  61. // param.Constraints |> Seq.map whenify |> Seq.fold SOMETHING param
  62. (* Gets something stable from an FSharpEntity so that we can see if two are identical *)
  63. and canonicalType (e:FSharpEntity) =
  64. if e.IsAbbreviation then
  65. cvt e.AbbreviatedType
  66. else
  67. // the dealias here is a hack because
  68. // unit-of-measure types do not have IsAbbreviation set.
  69. // TODO: I have no idea how to make this work once real alias detection
  70. // is implemented, because it will (probably) be based on IsAbbreviation.
  71. Id e.DisplayName |> ParsedTypes.dealias // e.ReflectionType |> string
  72. and whenify (param:FSharpGenericParameter) (con:FSharpGenericParameterConstraint) =
  73. // NOTE: This is missing several important (but non-syntactic) kinds of constraints
  74. // particuarly the defaults constraint
  75. // Also: I have no way to compose whenify's results in cvtParam. Most types with constraints
  76. // have multiple constraints, and these are also duplicated for each occurrence of the type
  77. if con.IsSupportsNullConstraint then
  78. Null (Normal param.Name)
  79. elif con.IsReferenceTypeConstraint then
  80. NotStruct (Normal param.Name)
  81. elif con.IsNonNullableValueTypeConstraint then
  82. Struct (Normal param.Name)
  83. elif con.IsRequiresDefaultConstructorConstraint then
  84. DefaultConstructor (Normal param.Name)
  85. elif con.IsEnumConstraint then
  86. Enum(Normal param.Name, cvt con.EnumConstraintTarget)
  87. elif con.IsDelegateConstraint then
  88. Delegate(Normal param.Name, cvt con.DelegateTupledArgumentType, cvt con.DelegateReturnType)
  89. elif con.IsCoercesToConstraint then
  90. Subtype(Normal param.Name, cvt con.CoercesToTarget)
  91. elif con.IsMemberConstraint then
  92. Sig(Structural param.Name,
  93. Id con.MemberName,
  94. Arrow (List.ofSeq (Seq.map cvt con.MemberArgumentTypes) @ [cvt con.MemberReturnType]),
  95. Function)
  96. else
  97. failwith "basically this style of data structure just sucks"