anchor.diff:  open Prime
   open Nu
   
  +/// Allows a value to always pass as equal with another of its same type.
  +/// TODO: move this elsewhere?
  +type [<CustomEquality; NoComparison; Struct>] 'a AlwaysEqual =
  +    | AlwaysEqual of 'a
  +    member this.Value = match this with AlwaysEqual value -> value
  +    override this.GetHashCode () = 0
  +    override this.Equals (that : obj) = that :? AlwaysEqual<'a>
  +
   /// The base component type of an Ecs.
   type Component<'c when 'c : struct and 'c :> 'c Component> =
       interface
           abstract Active : bool with get, set
           end
  -
  -/// Allows a value to always pass as equal with another of its same type.
  -type [<CustomEquality; NoComparison; Struct>] 'a AlwaysEqual =
  -    | AlwaysEqual of 'a
  -    member this.Value = match this with AlwaysEqual value -> value
  -    override this.GetHashCode () = 0
  -    override this.Equals (that : obj) = that :? AlwaysEqual<'a>
   
   /// The component that holds an entity's id.
   type [<NoEquality; NoComparison; Struct>] EntityId =
  
positive.code:         | (Terms terms, Terms terms2) ->
              if terms.Length = terms2.Length then
                  let mutable errOpt = ValueNone
                  let result = List.forall2 (fun term term2 -> match Subquery.le term term2 with Bool b -> b | Err err -> (errOpt <- ValueSome err; false) | _ -> false) terms terms2
                  match errOpt with ValueSome err -> Err err | ValueNone -> Bool result
              else Bool false
          | ((Err _ as err), _) -> err
          | (_, (Err _ as err)) -> err
          | (_, _) -> Err "Comparing non-comparable terms."
  
      static member eval (terms : Map<string, Term>) (subquery : Subquery) : Term =
          match subquery with
          | V3Ctor (subquery, subquery2, subquery3) ->
              match (Subquery.eval terms subquery, Subquery.eval terms subquery2, Subquery.eval terms subquery3) with
              | (Single x, Single y, Single z) -> V3 (v3 x y z)
              | ((Err _ as err), _, _) -> err
              | (_, (Err _ as err), _) -> err
              | (_, _, (Err _ as err)) -> err
              | (_, _, _) -> Err "Invalid v3 call; 3 F's required."
          | Box3Ctor (subquery, subquery2) ->
              match (Subquery.eval terms subquery, Subquery.eval terms subquery2) with
              | (V3 p, V3 s) -> Box3 (box3 p s)
              | ((Err _ as err), _) -> err
              | (_, (Err _ as err)) -> err
              | (_, _) -> Err "Invalid box3 call; 2 V3's required."
          | PairCtor (subquery, subquery2) ->
              match (Subquery.eval terms subquery, Subquery.eval terms subquery2) with
              | ((Err _ as err), _) -> err
              | (_, (Err _ as err)) -> err
              | (f, s) -> Pair (f, s)
          | EntityIdCtor entityId ->
              EntityId entityId
          | Tagged subquery ->
              match subquery with
              | Val v -> match v with Err _ as err -> err | _ -> Bool true
              | Var v -> Bool (terms.ContainsKey v)
              | _ -> Bool true
          | Eq (subquery, subquery2) ->
              match (Subquery.eval terms subquery, Subquery.eval terms subquery2) with
              | ((Err _ as err), _) -> err
              | (_, (Err _ as err)) -> err
              | (term, term2) -> Subquery.eq term term2
          | Gt (subquery, subquery2) ->
              match (Subquery.eval terms subquery, Subquery.eval terms subquery2) with
              | ((Err _ as err), _) -> err
              | (_, (Err _ as err)) -> err
              | (term, term2) -> Subquery.gt term term2
          | Ge (subquery, subquery2) ->
              match (Subquery.eval terms subquery, Subquery.eval terms subquery2) with
              | ((Err _ as err), _) -> err
              | (_, (Err _ as err)) -> err
              | (term, term2) -> Subquery.ge term term2
          | Lt (subquery, subquery2) ->
              match (Subquery.eval terms subquery, Subquery.eval terms subquery2) with
              | ((Err _ as err), _) -> err
              | (_, (Err _ as err)) -> err
              | (term, term2) -> Subquery.lt term term2
          | Le (subquery, subquery2) ->
              match (Subquery.eval terms subquery, Subquery.eval terms subquery2) with
              | ((Err _ as err), _) -> err
              | (_, (Err _ as err)) -> err
              | (term, term2) -> Subquery.le term term2
          | If (predicate, consequent, alternate) ->
              match Subquery.eval terms predicate with
              | Bool b -> if b then Subquery.eval terms consequent else Subquery.eval terms alternate
              | Err _ as err -> err
              | _ -> Err "Invalid If predicate; B required."
          | GetX subquery ->
              match Subquery.eval terms subquery with V3 v -> Single v.X | Err _ as err -> err | _ -> Err "Invalid GetX argument; V3 required."
          | GetY subquery ->
              match Subquery.eval terms subquery with V3 v -> Single v.Y | Err _ as err -> err | _ -> Err "Invalid GetY argument; V3 required."
          | GetZ subquery ->
              match Subquery.eval terms subquery with V3 v -> Single v.Z | Err _ as err -> err | _ -> Err "Invalid GetZ argument; V3 required."
          | GetPosition subquery ->
              match Subquery.eval terms subquery with Box3 box -> V3 box.Position | Err _ as err -> err | _ -> Err "Invalid GetPosition argument; Box3 required."
          | GetSize subquery ->
              match Subquery.eval terms subquery with Box3 box -> V3 box.Size | Err _ as err -> err | _ -> Err "Invalid GetSize argument; Box3 required."
          | Intersects (subquery, subquery2) ->
              match (Subquery.eval terms subquery, Subquery.eval terms subquery2) with
              | (Box3 box, Box3 box2) -> Bool (box.Intersects box2)
              | (V3 v, Box3 box) | (Box3 box, V3 v)-> Bool (box.Intersects v)
              | ((Err _ as err), _) -> err
              | (_, (Err _ as err)) -> err
              | (_, _) -> Err "Invalid Intersect arguments."
          | Or (subquery, subquery2) ->
              match (Subquery.eval terms subquery, Subquery.eval terms subquery2) with
              | (Bool b, Bool b2) -> Bool (b || b2)
              | ((Err _ as err), _) -> err
              | (_, (Err _ as err)) -> err
              | (_, _) -> Err "Invalid Or arguments; two B's required."
          | And (subquery, subquery2) ->
              match (Subquery.eval terms subquery, Subquery.eval terms subquery2) with
              | (Bool b, Bool b2) -> Bool (b && b2)
              | ((Err _ as err), _) -> err
              | (_, (Err _ as err)) -> err
              | (_, _) -> Err "Invalid And arguments; two B's required."
          | Not subquery ->
              match Subquery.eval terms subquery with
              | Bool b -> Bool (not b)
              | Err _ as err -> err
              | _ -> Err "Invalid Not argument; B required."
          | Val term ->
              term
          | Var varName ->
              match terms.TryGetValue varName with
              | (true, term) -> term
              | (false, _) -> Err "Non-existent binding."
          | Let (bindingName, subquery, subquery2) ->
              let term = Subquery.eval terms subquery
              let terms = Map.add bindingName term terms
  
negative.code:         | (Terms terms, Terms terms2) ->
              if terms.Length = terms2.Length then
                  let mutable errOpt = ValueNone
                  let result = List.forall2 (fun term term2 -> match Subquery.ge term term2 with Bool b -> b | Error err -> (errOpt <- ValueSome err; false) | _ -> false) terms terms2
                  match errOpt with ValueSome err -> Error err | ValueNone -> Bool result
              else Bool false
          | ((Error _ as err), _) -> err
          | (_, (Error _ as err)) -> err
          | (_, _) -> Error "Comparing non-comparable terms."
  
      static member lt term term2 =
          match (term, term2) with
  