Skip to content

Commit

Permalink
add Struct, NotStruct and Equality shapes
Browse files Browse the repository at this point in the history
  • Loading branch information
eiriktsarpalis committed Sep 20, 2016
1 parent d79c612 commit 920cded
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
3 changes: 3 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
### 1.1
* Add Struct, NotStruct and Equality shapes.

### 1.0 - Initial Release
* Initial release
51 changes: 51 additions & 0 deletions src/TypeShape/TypeShape.fs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,42 @@ type private ShapeDefaultConstructor<'T when 'T : (new : unit -> 'T)>() =
interface IShapeDefaultConstructor with
member __.Accept v = v.Visit<'T>()

///////////// Equality Types

type IEqualityVisitor<'R> =
abstract Visit<'T when 'T : equality> : unit -> 'R

type IShapeEquality =
abstract Accept : IEqualityVisitor<'R> -> 'R

type private ShapeEquality<'T when 'T : equality>() =
interface IShapeEquality with
member __.Accept v = v.Visit<'T>()

///////////// Struct Types

type IStructVisitor<'R> =
abstract Visit<'T when 'T : struct> : unit -> 'R

type IShapeStruct =
abstract Accept : IStructVisitor<'R> -> 'R

type private ShapeStruct<'T when 'T : struct>() =
interface IShapeStruct with
member __.Accept v = v.Visit<'T>()

///////////// Reference Types

type INotStructVisitor<'R> =
abstract Visit<'T when 'T : not struct and 'T : null> : unit -> 'R

type IShapeNotStruct =
abstract Accept : INotStructVisitor<'R> -> 'R

type private ShapeNotStruct<'T when 'T : not struct and 'T : null>() =
interface IShapeNotStruct with
member __.Accept v = v.Visit<'T>()

///////////// Delegates

type IDelegateVisitor<'R> =
Expand Down Expand Up @@ -1280,6 +1316,21 @@ module Shape =
|> Some
| _ -> None

let (|Equality|_|) (s : TypeShape) =
try
Activator.CreateInstanceGeneric<ShapeEquality<_>> [|s.Type|]
:?> IShapeEquality
|> Some
with _ -> None

let (|Struct|NotStruct|) (s : TypeShape) =
if s.Type.IsValueType then
let instance = Activator.CreateInstanceGeneric<ShapeStruct<_>> [|s.Type|] :?> IShapeStruct
Struct instance
else
let instance = Activator.CreateInstanceGeneric<ShapeNotStruct<_>> [|s.Type|] :?> IShapeNotStruct
NotStruct instance

let (|DefaultConstructor|_|) (shape : TypeShape) =
match shape.Type.GetConstructor(BindingFlags.Public ||| BindingFlags.Instance, null, [||], [||]) with
| null -> None
Expand Down
12 changes: 12 additions & 0 deletions tests/TypeShape.Tests/Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ let ``Shape Type with default ctor`` () =

test <@ match shapeof<TypeWithDefaultCtor> with Shape.DefaultConstructor s -> s.Accept accepter | _ -> false @>

[<Fact>]
let ``Shape Struct`` () =
let accepter1 =
{ new IStructVisitor<bool> with
member __.Visit<'T when 'T : struct> () = true }
let accepter2 =
{ new INotStructVisitor<bool> with
member __.Visit<'T when 'T : not struct and 'T : null> () = false }

test <@ match shapeof<int> with Shape.Struct s -> s.Accept accepter1 | Shape.NotStruct s -> s.Accept accepter2 @>
test <@ not <| match shapeof<string> with Shape.Struct s -> s.Accept accepter1 | Shape.NotStruct s -> s.Accept accepter2 @>

[<Fact>]
let ``Shape Binding Flags`` () =
let accepter =
Expand Down

0 comments on commit 920cded

Please sign in to comment.