packages feed

funcons-values (empty) → 0.1.0.0

raw patch · 25 files changed

+2456/−0 lines, 25 filesdep +basedep +bvdep +containerssetup-changed

Dependencies added: base, bv, containers, multiset, random-strings, text, vector

Files

+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2016 L. Thomas van Binsbergen and Neil Sculthorpe++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ funcons-values.cabal view
@@ -0,0 +1,54 @@+-- Initial funcons-values.cabal generated by cabal init.  For further+-- documentation, see http://haskell.org/cabal/users-guide/++name:                funcons-values+version:             0.1.0.0+synopsis:            Library providing values and operations on values.+-- description:+homepage:            http://plancomps.org+license:             MIT+license-file:        LICENSE+author:              L. Thomas van Binsbergen and Neil Sculthorpe+maintainer:          L. Thomas van Binsbergen <ltvanbinsbergen@acm.org>+-- copyright:+category:            Compilers/Interpreters+build-type:          Simple+-- extra-source-files:+cabal-version:       >=1.10++library+  exposed-modules:     Funcons.Operations+  other-modules:       Funcons.Operations.Eval+                      ,Funcons.Operations.Libraries+                      ,Funcons.Operations.Expr+                      ,Funcons.Operations.Values+                      ,Funcons.Operations.Types+                      ,Funcons.Operations.Atoms+                      ,Funcons.Operations.ADTs+                      ,Funcons.Operations.Booleans+                      ,Funcons.Operations.Optionals+--                      ,Funcons.Operations.Rationals+                      ,Funcons.Operations.Integers+                      ,Funcons.Operations.Floats+                      ,Funcons.Operations.Strings+                      ,Funcons.Operations.Lists+                      ,Funcons.Operations.Tuples+                      ,Funcons.Operations.NonGroundValues+                      ,Funcons.Operations.Multisets +                      ,Funcons.Operations.Sets +                      ,Funcons.Operations.Bits +                      ,Funcons.Operations.Characters+                      ,Funcons.Operations.Maps+                      ,Funcons.Operations.Internal+  other-extensions:    InstanceSigs, OverloadedStrings+  build-depends:       base >=4.8 && <5+                      ,containers >=0.5 && <0.6+                      ,vector >=0.12+                      ,bv >=0.5+                      ,multiset >=0.3 && <0.4+                      ,text >=1.2 && <1.3+                      ,random-strings+  hs-source-dirs:      src+  default-language:    Haskell2010+  ghc-options:         -fwarn-incomplete-patterns -fwarn-monomorphism-restriction -fwarn-unused-imports+
+ src/Funcons/Operations.hs view
@@ -0,0 +1,93 @@++module Funcons.Operations (+  module Funcons.Operations.Atoms,+  module Funcons.Operations.ADTs,+  module Funcons.Operations.Expr,+  module Funcons.Operations.Values,+  module Funcons.Operations.Eval,+  module Funcons.Operations.Lists,+  module Funcons.Operations.Tuples,+  module Funcons.Operations.Booleans,+  module Funcons.Operations.Optionals,+  module Funcons.Operations.Types,+  module Funcons.Operations.NonGroundValues,+  module Funcons.Operations.Integers,+  module Funcons.Operations.Floats,+  module Funcons.Operations.Strings,+--  module Funcons.Operations.Rationals,+  module Funcons.Operations.Sets,+  module Funcons.Operations.Multisets,+  module Funcons.Operations.Bits,+  module Funcons.Operations.Characters,+  module Funcons.Operations.Maps,+  libApp, Funcons.Operations.library, Library+  ) where++import Funcons.Operations.Expr +import Funcons.Operations.Libraries +import Funcons.Operations.Values hiding (showArgs, isGround, set_)+import Funcons.Operations.Eval hiding (showArgs)+import Funcons.Operations.Atoms hiding (library)+import qualified Funcons.Operations.Atoms (library)+import Funcons.Operations.Booleans hiding (library)+import qualified Funcons.Operations.Booleans (library)+import Funcons.Operations.Optionals hiding (library)+import qualified Funcons.Operations.Optionals (library)+import Funcons.Operations.Lists hiding (library)+import qualified Funcons.Operations.Lists (library)+import Funcons.Operations.Tuples hiding (library)+import qualified Funcons.Operations.Tuples (library)+import Funcons.Operations.Types hiding (library)+import qualified Funcons.Operations.Types (library)+import Funcons.Operations.NonGroundValues hiding (library, isGround)+import qualified Funcons.Operations.NonGroundValues (library)+import Funcons.Operations.Integers hiding (isInt, unInt, library)+import qualified Funcons.Operations.Integers (library)+import Funcons.Operations.Floats hiding (isInt, unInt, library)+import qualified Funcons.Operations.Floats (library)+import Funcons.Operations.Strings hiding (library)+import qualified Funcons.Operations.Strings (library)+--import Funcons.Operations.Rationals hiding (library)+--import qualified Funcons.Operations.Rationals (library)+import Funcons.Operations.Sets hiding (library)+import qualified Funcons.Operations.Sets (library)+import qualified Funcons.Operations.Multisets (library)+import qualified Funcons.Operations.Bits (library)+import Funcons.Operations.Characters hiding (library)+import qualified Funcons.Operations.Characters (library)+import Funcons.Operations.Maps hiding (library)+import qualified Funcons.Operations.Maps (library)+import Funcons.Operations.ADTs hiding (library)+import qualified Funcons.Operations.ADTs++library :: (HasValues t, Ord t) => Library t+library = libUnite [+    Funcons.Operations.Atoms.library+  , Funcons.Operations.ADTs.library+  , Funcons.Operations.Booleans.library+  , Funcons.Operations.Optionals.library+  , Funcons.Operations.Lists.library+  , Funcons.Operations.Tuples.library+  , Funcons.Operations.Types.library+  , Funcons.Operations.NonGroundValues.library+  , Funcons.Operations.Integers.library+  , Funcons.Operations.Floats.library+  , Funcons.Operations.Strings.library+--  , Funcons.Operations.Rationals.library+  , Funcons.Operations.Sets.library+  , Funcons.Operations.Multisets.library+  , Funcons.Operations.Bits.library+  , Funcons.Operations.Characters.library+  , Funcons.Operations.Maps.library+  ]++libApp :: (HasValues t, Ord t) => OP -> [OpExpr t] -> Maybe (OpExpr t)+libApp op args = do +  valop <- libLookup op Funcons.Operations.library+  case (args, valop) of+    ([], NullaryExpr op)      -> Just op+    ([x], UnaryExpr op)       -> Just (op x)+    ([x,y], BinaryExpr op)    -> Just (op x y)+    ([x,y,z], TernaryExpr op) -> Just (op x y z)+    (_, NaryExpr op)          -> Just (op args)+    _                         -> Nothing
+ src/Funcons/Operations/ADTs.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE OverloadedStrings #-}++module Funcons.Operations.ADTs where++import Funcons.Operations.Internal++import Data.Maybe (fromJust, isJust)+import Data.Text (pack, unpack)+import Data.String(fromString)++library :: HasValues t => Ord t => Library t+library = libFromList [+    ("adts", NullaryExpr adts)+  , ("adt-construct", NaryExpr adt_construct_)+  , ("adt-type", NaryExpr adt_type_construct_)+  , ("adt-type-construct", NaryExpr adt_type_construct_)+  , ("adt-constructor", UnaryExpr adt_constructor)+  , ("adt-fields", UnaryExpr adt_fields)+  ]++adts_ :: HasValues t => [OpExpr t] -> OpExpr t+adts_ = nullaryOp adts+adts :: HasValues t => OpExpr t+adts = NullaryOp "adts" (Normal $ injectT ADTs)++adt_construct_ :: HasValues t => [OpExpr t] -> OpExpr t+adt_construct_ = NaryOp "adt-construct" op+  where op :: HasValues t => [t] -> Result t+        op (x : vs) = case project x of+          Just v -> +            if isString_ v +              then Normal $ inject $ ADTVal (pack (unString v)) vs+              else SortErr "adt-construct: first argument not a string"+          _      -> ProjErr "adt-construct"+        op _  = SortErr "adt-construct: insufficient arguments"++adt_type_construct_ :: HasValues t => [OpExpr t] -> OpExpr t+adt_type_construct_ = vNaryOp "adt-type-construct" op+  where op (s : vs) +          | isString_ s =   +              if all isType vs +                then Normal $ injectT $ ADT (pack (unString s))+                              (map (injectT . fromJust . castType) vs)  +                else SortErr "adt-type-construct: last arguments not types" +        op _  = SortErr "adt-construct: first argument not a string"++adt_constructor_ :: HasValues t => [OpExpr t] -> OpExpr t+adt_constructor_ = unaryOp adt_constructor+adt_constructor :: HasValues t => OpExpr t -> OpExpr t+adt_constructor = vUnaryOp "adt-constructor" op+  where op (ADTVal cons _) = Normal $ inject $ fromString (unpack cons)+        op _ = SortErr "adt-constructor: argument not an adt value"++adt_fields_ :: HasValues t => [OpExpr t] -> OpExpr t+adt_fields_ = unaryOp adt_fields+adt_fields :: HasValues t => OpExpr t -> OpExpr t+adt_fields = vUnaryOp "adt-fields" op+  where op (ADTVal _ fs) = Normal $ inject $ ADTVal "list" fs +        op _ = SortErr "adt-fields: argument not an adt value"
+ src/Funcons/Operations/Atoms.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE OverloadedStrings #-}++module Funcons.Operations.Atoms where++import Funcons.Operations.Internal++library :: (HasValues t, Eq t) => Library t+library = libFromList [+    ("atoms", NullaryExpr atoms)+  , ("next-atom", UnaryExpr next_atom)+  , ("atom-seed", NullaryExpr atom_seed)+  , ("atom", UnaryExpr atom)+  ]++atom_seed_ :: HasValues t => [OpExpr t] -> OpExpr t+atom_seed_ = nullaryOp atom_seed +atom_seed :: HasValues t => OpExpr t+atom_seed = vNullaryOp "atom-seed" (Normal $ inject $ Atom "0")++next_atom_ :: HasValues t => [OpExpr t] -> OpExpr t+next_atom_ = unaryOp next_atom+next_atom :: HasValues t => OpExpr t -> OpExpr t+next_atom = vUnaryOp "next-atom" op+  where op (Atom a) = Normal $ inject $ Atom (show (i+1))+          where i::Int+                i = read a+        op _ = SortErr "next-atom not applied to an atom"++atoms_ :: HasValues t => [OpExpr t] -> OpExpr t+atoms_ = nullaryOp atoms+atoms :: HasValues t => OpExpr t+atoms = vNullaryOp "atoms" (Normal $ injectT Atoms)++atom_ :: HasValues t => [OpExpr t] -> OpExpr t+atom_ = unaryOp atom++atom :: HasValues t => OpExpr t -> OpExpr t+atom = vUnaryOp "atom" op+  where op v | isString_ v = Normal $ inject $ Atom (unString v)+             | otherwise   = SortErr "atom not applied to a string"  
+ src/Funcons/Operations/Bits.hs view
@@ -0,0 +1,9 @@++module Funcons.Operations.Bits where++import Funcons.Operations.Booleans (tobool)+import Funcons.Operations.Internal++library :: (HasValues t, Ord t) => Library t+library = libFromList []+ 
+ src/Funcons/Operations/Booleans.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE OverloadedStrings #-}++module Funcons.Operations.Booleans where++import Funcons.Operations.Internal++library :: (HasValues t, Eq t) => Library t+library = libFromList [+    ("is-equal", BinaryExpr is_equal)+--  , ("booleans", NullaryExpr booleans_)+--  , ("and", BinaryExpr stepAnd)+  ]++tobool :: Bool -> Values t +tobool True   = ADTVal "true" []+tobool False  = ADTVal "false" [] ++frombool :: (Values t) -> Maybe Bool+frombool (ADTVal "true" []) = Just True+frombool (ADTVal "false" []) = Just False+frombool _ = Nothing+++{-+and_ :: HasValues t => [OpExpr t] -> OpExpr t +and_ = binaryOp stepAnd+stepAnd :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+stepAnd = vBinaryOp "and" op+  where op x y = case (frombool x, frombool y) of +          (Just b1, Just b2) -> Normal $ inject $ tobool (b1 && b2)+          _ -> SortErr "and not applied to two booleans"+-}+booleans_ :: HasValues t => OpExpr t+booleans_ = vNullaryOp "booleans" (Normal $ injectT $ ADT "booleans" [])++true_ :: HasValues t => Values t +true_ = tobool True++false_ :: HasValues t => Values t +false_ = tobool False +++is_equal_ :: (HasValues t, Eq t) => [OpExpr t] -> OpExpr t+is_equal_ = binaryOp is_equal+is_equal :: (HasValues t, Eq t) => OpExpr t -> OpExpr t -> OpExpr t+is_equal = BinaryOp "is-equal" op +  where op :: (Eq t, HasValues t) => t -> t -> Result t+        op x y = Normal $ inject $ tobool (x == y)++
+ src/Funcons/Operations/Characters.hs view
@@ -0,0 +1,53 @@++module Funcons.Operations.Characters where++import Funcons.Operations.Booleans (tobool)+import Funcons.Operations.Internal++import Data.Char (ord,chr)++library :: (HasValues t, Ord t) => Library t+library = libFromList [+    ("ascii-characters", NullaryExpr ascii_characters)+  , ("ascii-character", UnaryExpr ascii_character)+  , ("unicode", UnaryExpr unicode)+  , ("unicode-character-code", UnaryExpr unicode_character_code)+  , ("characters", NullaryExpr characters)+  ]++characters_ :: HasValues t => [OpExpr t] -> OpExpr t+characters_ = nullaryOp characters+characters :: HasValues t => OpExpr t+characters = vNullaryOp "characters" (Normal $ injectT $ Characters)++ascii_characters_ :: HasValues t => [OpExpr t] -> OpExpr t+ascii_characters_ = nullaryOp ascii_characters+ascii_characters :: HasValues t => OpExpr t+ascii_characters = vNullaryOp "ascii-characters" (Normal $ injectT $ AsciiCharacters)++ascii_character_ :: HasValues t => [OpExpr t] -> OpExpr t+ascii_character_ = unaryOp ascii_character +ascii_character :: HasValues t => OpExpr t -> OpExpr t+ascii_character = vUnaryOp "ascii-character" op+  where op v | isString_ v, s <- unString v, length s == 1 +                = Normal $ inject $ Ascii $ head s+             | otherwise = SortErr "ascii-character not applied to a string (of 1 ascii character long)"++unicode_ :: HasValues t => [OpExpr t] -> OpExpr t+unicode_ = unaryOp unicode+unicode :: HasValues t => OpExpr t -> OpExpr t+unicode = vUnaryOp "unicode" op+  where op v | Int i <- upcastIntegers v, i < numUnicodeCodes = +                Normal $ inject $ mk_unicode_characters (chr $ fromInteger i)+             | otherwise = SortErr "unicode not applied to an integer in the range 0..(2^32)-1"++numUnicodeCodes :: Integer+numUnicodeCodes = (2^32)-1++unicode_character_code_ :: HasValues t => [OpExpr t] -> OpExpr t+unicode_character_code_ = unaryOp unicode_character_code +unicode_character_code :: HasValues t => OpExpr t -> OpExpr t+unicode_character_code = vUnaryOp "unicode-character-code" op+  where op v | Char c <- upcastUnicode v = +                  Normal $ inject $ mk_integers (toInteger $ ord c)+             | otherwise = SortErr "unicode-character-code not applied to a unicode-character"
+ src/Funcons/Operations/Eval.hs view
@@ -0,0 +1,33 @@++module Funcons.Operations.Eval where++import Funcons.Operations.Expr+import Funcons.Operations.Values hiding (showArgs)++import Control.Monad+import Data.List (intercalate)++data EvalResult t = Error         (OpExpr t) (Result t)+                  | Success       t+                  deriving (Show)++eval :: HasValues t => OpExpr t -> EvalResult t+eval expr = applyEval expr (applyExpr expr) ++applyEval :: OpExpr t -> Result t -> EvalResult t+applyEval expr (Normal v) = Success v+applyEval expr res = Error expr res + +instance (HasValues t, Show t) => Show (OpExpr t) where+  show (ValExpr v)            = ppValues show v+  show (TermExpr t)           = show t+  show (NullaryOp nm _)       = nm+  show (UnaryOp nm _ x)       = nm ++ showArgs [x]+  show (BinaryOp nm _ x y)    = nm ++ showArgs [x,y]+  show (TernaryOp nm _ x y z) = nm ++ showArgs [x,y,z]+  show (NaryOp nm _ xs)       = nm ++ showArgs xs+  show (InvalidOp nm _ xs)    = nm ++ showArgs xs+  show (RewritesTo nm _ xs)   = nm ++ showArgs xs++showArgs :: (HasValues t, Show t) => [OpExpr t] -> String+showArgs args = "(" ++ intercalate "," (map show args) ++ ")"
+ src/Funcons/Operations/Expr.hs view
@@ -0,0 +1,165 @@+{-# LANGUAGE InstanceSigs #-}++module Funcons.Operations.Expr where++import Funcons.Operations.Values+import Control.Monad (ap)++type OP = String++data Result t = SortErr     String -- sort mismatch+              | DomErr      String -- domain mismatch (in case of partial op)+              | ArityErr    String+              | ProjErr     String -- cannot project to a value+              | Normal      t +              deriving Show+ +type NullaryOp t  = Result t+type UnaryOp t    = t -> Result t+type BinaryOp t   = t -> t -> Result t+type TernaryOp t  = t -> t -> t -> Result t+type NaryOp t     = [t] -> Result t++type NullaryVOp t  = Result t+type UnaryVOp t    = Values t -> Result t+type BinaryVOp t   = Values t -> Values t -> Result t+type TernaryVOp t  = Values t -> Values t -> Values t -> Result t+type NaryVOp t     = [Values t] -> Result t++data OpExpr t  +      = ValExpr         (Values t)+      | TermExpr        t  +      | NullaryOp   OP  (NullaryOp t)                                    +      | UnaryOp     OP  (UnaryOp t)     (OpExpr t)                       +      | BinaryOp    OP  (BinaryOp t)    (OpExpr t) (OpExpr t)            +      | TernaryOp   OP  (TernaryOp t)   (OpExpr t) (OpExpr t) (OpExpr t) +      | NaryOp      OP  (NaryOp t)      [OpExpr t]  +      | InvalidOp   OP  String          [OpExpr t]+      | RewritesTo  OP  (OpExpr t)      [OpExpr t]++vNullaryOp :: OP -> NullaryVOp t -> OpExpr t+vNullaryOp nm op = NullaryOp nm op++vUnaryOp :: HasValues t => OP -> UnaryVOp t -> OpExpr t -> OpExpr t+vUnaryOp nm op = UnaryOp nm op'+  where op' t = case project t of+                  Nothing -> ProjErr nm+                  Just v  -> op v++vBinaryOp :: HasValues t => OP -> BinaryVOp t -> OpExpr t -> OpExpr t -> OpExpr t+vBinaryOp nm op = BinaryOp nm op'+  where op' x y = case (project x, project y) of+                  (Just v1,Just v2) -> op v1 v2 +                  _                 -> ProjErr nm++vTernaryOp :: HasValues t => OP -> TernaryVOp t -> OpExpr t -> OpExpr t -> OpExpr t -> OpExpr t+vTernaryOp nm op = TernaryOp nm op'+  where op' x y z = case (project x, project y, project z) of+                  (Just v1,Just v2, Just v3)  -> op v1 v2 v3+                  _                           -> ProjErr nm++vNaryOp :: HasValues t => OP -> NaryVOp t -> [OpExpr t] -> OpExpr t+vNaryOp nm op = NaryOp nm op'+  where op' ts = case mapM project ts of+                  Just vs -> op vs+                  Nothing -> ProjErr nm++opName :: OpExpr t -> OP+opName (ValExpr _) = error "opName val"+opName (TermExpr _) = error "opName term"+opName (NullaryOp op _) = op+opName (UnaryOp op _ _) = op+opName (BinaryOp op _ _ _) = op+opName (TernaryOp op _ _ _ _) = op+opName (NaryOp op _ _) = op+opName (InvalidOp op _ _) = op+opName (RewritesTo op _ _) = op++data ValueOp t      = NullaryExpr (NullaryExpr t)+                    | UnaryExpr (UnaryExpr t)+                    | BinaryExpr (BinaryExpr t)+                    | TernaryExpr (TernaryExpr t)+                    | NaryExpr (NaryExpr t)++type NullaryExpr t  = OpExpr  t+type UnaryExpr t    = OpExpr t -> OpExpr  t+type BinaryExpr t   = OpExpr t -> OpExpr t -> OpExpr  t+type TernaryExpr t  = OpExpr t -> OpExpr t -> OpExpr t -> OpExpr  t+type NaryExpr t     = [OpExpr t] -> OpExpr t++nullaryOp :: NullaryExpr t ->  [OpExpr t] -> OpExpr t+nullaryOp f [] = f+nullaryOp f xs = arityErr 0 (opName f) xs++unaryOp :: UnaryExpr t ->  [OpExpr t] -> OpExpr t+unaryOp f [x] = f x+unaryOp f xs = arityErr 1 (opName (f undefined)) xs++binaryOp :: BinaryExpr t ->  [OpExpr t] -> OpExpr t+binaryOp f [x,y] = f x y+binaryOp f xs = arityErr 2 (opName (f undefined undefined)) xs++ternaryOp :: TernaryExpr t -> [OpExpr t] -> OpExpr t+ternaryOp f [x,y,z] = f x y z +ternaryOp f xs = arityErr 3 (opName (f undefined undefined undefined)) xs++arityErr :: Int -> OP -> [OpExpr t] -> OpExpr t+arityErr i op = InvalidOp op ("not applied to " ++ show i ++ " arguments")++applyExpr :: HasValues t => OpExpr t -> Result t+applyExpr expr = case expr of+  ValExpr v                     -> Normal (inject v)+  TermExpr t                    -> Normal t+  InvalidOp _ err _             -> ArityErr err+  NullaryOp _ f                 -> f+  UnaryOp _ f x                 -> f =<< applyExpr x+  BinaryOp _ f x y              -> do   xv <- applyExpr x +                                        yv <- applyExpr y+                                        f xv yv+  TernaryOp _ f x y z           -> do   xv <- applyExpr x+                                        yv <- applyExpr y+                                        zv <- applyExpr z+                                        f xv yv zv+  NaryOp _ f xs                 -> f =<< mapM applyExpr xs+  RewritesTo _ e1 _             -> applyExpr e1++instance Functor Result where+  fmap f (SortErr err)  = SortErr err+  fmap f (ProjErr err)  = ProjErr err+  fmap f (DomErr err)   = DomErr err+  fmap f (ArityErr err) = ArityErr err+  fmap f (Normal v)     = Normal (f v)++instance Applicative Result where+  pure = Normal+  (<*>) = ap++instance Monad Result where+  return = Normal+  p >>= q = case p of+    SortErr err   -> SortErr err+    ProjErr err   -> ProjErr err+    DomErr err    -> DomErr err+    ArityErr err  -> ArityErr err+    Normal f      -> q f ++-- helper / smart constructors+{-+nullaryOp :: OP -> Result t -> OpExpr t+nullaryOp = NullaryOp++unaryOp :: IsOperand o => OP -> o t -> UnaryOp t -> OpExpr t+unaryOp nm o res = UnaryOp nm (toOp o) res++binaryOp :: (IsOperand o1, IsOperand o2) => OP -> o1 t -> o2 t -> BinaryOp t -> OpExpr t+binaryOp nm x y res = BinaryOp nm (toOp x) (toOp y) res++ternaryOp :: IsOperand o => OP -> o t -> o t -> o t -> TernaryOp t -> OpExpr t+ternaryOp nm x y z op = TernaryOp nm (toOp x) (toOp y) (toOp z) op++naryOp :: IsOperand o => OP -> [o t] -> NaryOp t -> OpExpr t+naryOp nm xs op = NaryOp nm (map toOp xs) op++rewritesTo :: (IsOperand o1, IsOperand o2) => OP -> [o1 t] -> o2 t -> OpExpr t +rewritesTo nm xs op = RewritesTo nm (map toOp xs) (toOp op)+-}
+ src/Funcons/Operations/Floats.hs view
@@ -0,0 +1,238 @@+{-# LANGUAGE OverloadedStrings #-}++module Funcons.Operations.Floats where++import Funcons.Operations.Internal hiding (isInt)+import Funcons.Operations.Types+import Funcons.Operations.Booleans (tobool)++library :: HasValues t => Library t+library = libFromList [+  ]++ieee_float_truncate_ :: HasValues t => [OpExpr t] -> OpExpr t+ieee_float_truncate_ = binaryOp ieee_float_truncate +ieee_float_truncate :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+ieee_float_truncate = vBinaryOp "ieee-float-truncate" op+  where op (IEEE_Float_64 f) (ADTVal "binary64" _) = Normal $ inject $ Int (truncate f)+        op _ _ = SortErr "ieee-float-truncate not applied to a float of the right format"++ieee_float_add_ :: HasValues t => [OpExpr t] -> OpExpr t+ieee_float_add_ = vNaryOp "ieee-float-add" op+  where op (format:vs) = ieee_float_op "ieee-float-add" (+) 0 format vs+        op [] = SortErr "ieee-float-add not applied to a format and a list of floats"++{-+ieee_float_multiply_ = ieee_float_multiply +ieee_float_multiply = applyFuncon "ieee-float-multiply"+ieee_float_multiply_op (format:vs) = ieee_float_op "ieee_float-multiply" ieee_float_multiply (*) 1 format vs+ieee_float_multiply_op [] = sortErr (ieee_float_multiply [listval []]) "ieee-float-multiply not applied to a format and a list of floats"++ieee_float_divide = applyFuncon "ieee-float-divide"+ieee_float_divide_op format vx vy+    | isIEEEFormat format vx && isIEEEFormat format vy =+        let f1 = doubleFromIEEEFormat format vx+            f2 = doubleFromIEEEFormat format vy+        in rewriteTo $ FValue $ IEEE_Float_64 $ (f1 / f2)+ieee_float_divide_op ft vx vy = sortErr (ieee_float_divide [FValue ft,FValue vx, FValue vy])+                         "ieee-float-divide not applied to a format and ieee-floats"++ieee_float_remainder = applyFuncon "ieee-float-remainder"+ieee_float_remainder_op format vx vy+    | isIEEEFormat format vx =+        let f1 = doubleFromIEEEFormat format vx+            f2 = doubleFromIEEEFormat format vy+        in rewriteTo $ FValue $ IEEE_Float_64 $ (f1 `mod'` f2)+ieee_float_remainder_op ft vx vy = sortErr (ieee_float_remainder [FValue ft,FValue vx, FValue vy])+                         "ieee-float-remainder not applied to a format and ieee-floats"++ieee_float_negate = applyFuncon "ieee-float-negate"+ieee_float_negate_op format vx+    | isIEEEFormat format vx = let f1 = doubleFromIEEEFormat format vx+                               in rewriteTo $ FValue $ IEEE_Float_64 (-f1)+    | otherwise = sortErr (ieee_float_negate [FValue format,FValue vx]) "ieee-float-negate not applied to ieee-float"++ieee_float_subtract = applyFuncon "ieee-float-subtract"+ieee_float_subtract_op format vx vy+    | isIEEEFormat format vx && isIEEEFormat format vy =+        let f1 = doubleFromIEEEFormat format vx+            f2 = doubleFromIEEEFormat format vy+        in rewriteTo $ FValue $ IEEE_Float_64 $ (f1 - f2)+ieee_float_subtract_op ft vx vy = sortErr (ieee_float_subtract [FValue ft, FValue vx, FValue vy])+                         "ieee-float-subtract not applied to a format and ieee-floats"++ieee_float_float_power = applyFuncon "ieee-float-float-power"+ieee_float_power_op format vx vy+    | isIEEEFormat format vx && isIEEEFormat format vy =+        let f1 = doubleFromIEEEFormat format vx+            f2 = doubleFromIEEEFormat format vy+        in rewriteTo $ FValue $ IEEE_Float_64 $ (f1 ** f2)+ieee_float_power_op ft vx vy = sortErr (ieee_float_float_power [FValue ft, FValue vx, FValue vy])+                         "ieee-float-power not applied to a format and ieee-floats"++ieee_float_is_less = applyFuncon "ieee-float-is-less"+ieee_float_is_less_op format vx vy+    | isIEEEFormat format vx && isIEEEFormat format vy =+        let f1 = doubleFromIEEEFormat format vx+            f2 = doubleFromIEEEFormat format vy+        in rewriteTo $ FValue $ tobool (f1 < f2)+ieee_float_is_less_op ft vx vy = sortErr (ieee_float_is_less [FValue ft, FValue vx, FValue vy])+                         "ieee-float-is-less not applied to a format and ieee-floats"++ieee_float_is_greater = applyFuncon "ieee-float-is-greater"+ieee_float_is_greater_op format vx vy+    | isIEEEFormat format vx && isIEEEFormat format vy =+        let f1 = doubleFromIEEEFormat format vx+            f2 = doubleFromIEEEFormat format vy+        in rewriteTo $ FValue $ tobool (f1 > f2)+ieee_float_is_greater_op ft vx vy = sortErr (ieee_float_is_greater [FValue ft, FValue vx, FValue vy])+                         "ieee-float-is-greater not applied to a format and ieee-floats"++ieee_float_is_less_or_equal = applyFuncon "ieee-float-is-less-or-equal"+ieee_float_is_less_or_equal_op format vx vy+    | isIEEEFormat format vx && isIEEEFormat format vy =+        let f1 = doubleFromIEEEFormat format vx+            f2 = doubleFromIEEEFormat format vy+        in rewriteTo $ FValue $ tobool (f1 <= f2)+ieee_float_is_less_or_equal_op ft vx vy = sortErr (ieee_float_is_less_or_equal [FValue ft,FValue vx, FValue vy])+                         "ieee-float-is-less-or-equal not applied to a format and ieee-floats"++ieee_float_is_greater_or_equal = applyFuncon "ieee-float-is-greater-or-equal"+ieee_float_is_greater_or_equal_op format vx vy+    | isIEEEFormat format vx && isIEEEFormat format vy =+        let f1 = doubleFromIEEEFormat format vx+            f2 = doubleFromIEEEFormat format vy+        in rewriteTo $ FValue $ tobool (f1 >= f2)+ieee_float_is_greater_or_equal_op ft vx vy = sortErr (ieee_float_is_greater_or_equal [FValue ft,FValue vx, FValue vy])+                         "ieee-float-is-greater-or-equal not applied to a format and ieee-floats"+++signed_bits_maximum = applyFuncon "signed-bits-maximum"+stepSigned_Bits_Maximum [vn] | Nat n <- upcastNaturals vn+        = rewriteTo $ integer_subtract_ [integer_power_ [int_ 2, integer_subtract_ [int_ $ fromInteger n, int_ 1]],int_ 1]+stepSigned_Bits_Maximum vs = sortErr (signed_bits_maximum (fvalues vs)) "sort check"++signed_bits_minimum = applyFuncon "signed-bits-minimum"+stepSigned_Bits_Minimum [vn] | Nat n <- upcastNaturals vn+        = rewriteTo $ applyFuncon "integer-negate" [signed_bits_maximum [FValue vn]]+stepSigned_Bits_Minimum vs = sortErr (signed_bits_maximum (fvalues vs)) "sort check"++    -- TODO binary64 assumption (perhaps use config files)+ieee_float_acos = applyFuncon "ieee-float-acos"+stepIEEE_Float_Acos [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (acos f1)+stepIEEE_Float_Acos vn = sortErr (ieee_float_acos (fvalues vn)) "sort check"++ieee_float_asin = applyFuncon "ieee-float-asin"+stepIEEE_Float_Asin [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (asin f1)+stepIEEE_Float_Asin vn = sortErr (ieee_float_asin (fvalues vn)) "sort check"++ieee_float_atan = applyFuncon "ieee-float-atan"+stepIEEE_Float_Atan [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (atan f1)+stepIEEE_Float_Atan vn = sortErr (ieee_float_atan (fvalues vn)) "sort check"++ieee_float_atan2 = applyFuncon "ieee-float-atan2"+stepIEEE_Float_Atan2 [f,vx,vy] = let f1 = doubleFromIEEEFormat f vx+                                     f2 = doubleFromIEEEFormat f vy+                                 in rewriteTo $ FValue $ IEEE_Float_64 (atan2 f1 f2)+stepIEEE_Float_Atan2 vn = sortErr (ieee_float_atan2 (fvalues vn)) "sort check"++ieee_float_cos = applyFuncon "ieee-float-cos"+stepIEEE_Float_Cos [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (cos f1)+stepIEEE_Float_Cos vn = sortErr (ieee_float_cos (fvalues vn)) "sort check"++ieee_float_cosh = applyFuncon "ieee-float-cosh"+stepIEEE_Float_Cosh [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (cosh f1)+stepIEEE_Float_Cosh vn = sortErr (ieee_float_cosh (fvalues vn)) "sort check"++ieee_float_exp = applyFuncon "ieee-float-exp"+stepIEEE_Float_Exp [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (exp f1)+stepIEEE_Float_Exp vn = sortErr (ieee_float_exp (fvalues vn)) "sort check"++ieee_float_log = applyFuncon "ieee-float-log"+stepIEEE_Float_Log [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (log f1)+stepIEEE_Float_Log vn = sortErr (ieee_float_log (fvalues vn)) "sort check"++ieee_float_log10 = applyFuncon "ieee-float-log10"+stepIEEE_Float_Log10 [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (logBase 10 f1)+stepIEEE_Float_Log10 vn = sortErr (ieee_float_log10 (fvalues vn)) "sort check"++ieee_float_sin = applyFuncon "ieee-float-sin"+stepIEEE_Float_Sin [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (sin f1)+stepIEEE_Float_Sin vn = sortErr (ieee_float_sin (fvalues vn)) "sort check"++ieee_float_sinh = applyFuncon "ieee-float-sinh"+stepIEEE_Float_Sinh [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (sinh f1)+stepIEEE_Float_Sinh vn = sortErr (ieee_float_sinh (fvalues vn)) "sort check"++ieee_float_sqrt = applyFuncon "ieee-float-sqrt"+stepIEEE_Float_Sqrt [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (sqrt f1)+stepIEEE_Float_Sqrt vn = sortErr (ieee_float_sqrt (fvalues vn)) "sort check"++ieee_float_tan = applyFuncon "ieee-float-tan"+stepIEEE_Float_Tan [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (tan f1)+stepIEEE_Float_Tan vn = sortErr (ieee_float_tan (fvalues vn)) "sort check"++ieee_float_tanh = applyFuncon "ieee-float-tanh"+stepIEEE_Float_Tanh [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (tanh f1)+stepIEEE_Float_Tanh vn = sortErr (ieee_float_tanh (fvalues vn)) "sort check"++ieee_float_ceiling = applyFuncon "ieee-float-ceiling"+stepIEEE_Float_Ceiling [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ int_ (ceiling f1)+stepIEEE_Float_Ceiling vn = sortErr (ieee_float_ceiling (fvalues vn)) "sort check"++ieee_float_floor = applyFuncon "ieee-float-floor"+stepIEEE_Float_Floor [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ int_ (floor f1)+stepIEEE_Float_Floor vn = sortErr (ieee_float_floor (fvalues vn)) "sort check"++ieee_float_absolute_value = applyFuncon "ieee-float-absolute-value"+stepIEEE_Float_Absolute_Value [f,vx] = let f1 = doubleFromIEEEFormat f vx+                                     in rewriteTo $ FValue $ IEEE_Float_64 (Prelude.abs f1)+stepIEEE_Float_Absolute_Value vn = sortErr (ieee_float_absolute_value (fvalues vn)) "sort check"++stepIEEE_Float_Remainder [f,f1,f2] = ieee_float_remainder_op f f1 f2+stepIEEE_Float_Remainder vn = sortErr (ieee_float_remainder (fvalues vn)) "sort check"++stepIEEE_Float_Is_Less [f,f1,f2] = ieee_float_is_less_op f f1 f2+stepIEEE_Float_Is_Less vn = sortErr (ieee_float_is_less (fvalues vn)) "sort check"+stepIEEE_Float_Is_Greater [f,f1,f2] = ieee_float_is_greater_op f f1 f2+stepIEEE_Float_Is_Greater vn = sortErr (ieee_float_is_greater (fvalues vn)) "sort check"+stepIEEE_Float_Is_Less_Or_Equal [f,f1,f2] = ieee_float_is_less_or_equal_op f f1 f2+stepIEEE_Float_Is_Less_Or_Equal vn = sortErr (ieee_float_is_less_or_equal (fvalues vn)) "sort check"+stepIEEE_Float_Is_Greater_Or_Equal [f,f1,f2] = ieee_float_is_greater_or_equal_op f f1 f2+stepIEEE_Float_Is_Greater_Or_Equal vn = sortErr (ieee_float_is_greater_or_equal (fvalues vn)) "sort check"+-}++ieee_float_op :: HasValues t => String -> (Double -> Double -> Double) +                -> Double -> Values t -> [Values t] -> Result t +ieee_float_op str f b format vs+    | all (isIEEEFormat format) vs = Normal $ inject $ IEEE_Float_64+        $ foldr f b $ map (doubleFromIEEEFormat format) vs+    | otherwise = SortErr err+    where   err     = str ++ " not applied to ieee_floats"+++isIEEEFormat :: Values t -> Values t -> Bool+isIEEEFormat (ADTVal "binary32" _) (IEEE_Float_32 _) = True+isIEEEFormat (ADTVal "binary64" _) (IEEE_Float_64 _) = True+isIEEEFormat _ _ = False++doubleFromIEEEFormat :: Values t -> Values t -> Double+doubleFromIEEEFormat (ADTVal "binary64" _) (IEEE_Float_64 d) = d+doubleFromIEEEFormat _ _ = error "fromIEEEFormat"++
+ src/Funcons/Operations/Integers.hs view
@@ -0,0 +1,185 @@+{-# LANGUAGE OverloadedStrings #-}++module Funcons.Operations.Integers where++import Funcons.Operations.Internal hiding (isInt)+import Funcons.Operations.Types+import Funcons.Operations.Booleans (tobool)++library :: HasValues t => Library t+library = libFromList [+    ("integers", NullaryExpr integers)+  , ("is-integer", UnaryExpr is_integer)+  , ("is-int", UnaryExpr is_integer)+  , ("integer-add", NaryExpr integer_add_)+  , ("integer-subtract", BinaryExpr integer_subtract)+  , ("integer-sub", BinaryExpr integer_subtract)+  , ("integer-modulo", BinaryExpr stepMod)+  , ("integer-mod", BinaryExpr stepMod)+  , ("integer-multiply", NaryExpr integer_multiply_)+  , ("int-mul", NaryExpr integer_multiply_)+  , ("integer-divide", BinaryExpr integer_divide)+  , ("int-div", BinaryExpr integer_divide)+  , ("integer-power", BinaryExpr integer_power)+  , ("int-pow", BinaryExpr integer_power)+-- integer-negate is now generated+--  ,   ("integer-negate", ValueOp stepInteger_Negate)+--  ,   ("int-neg", ValueOp stepInteger_Negate)+  , ("integer-list", BinaryExpr integer_list)+  , ("integer-absolute-value", UnaryExpr integer_absolute_value)+  , ("decimal-natural", UnaryExpr decimal_natural)+  , ("natural-predecessor", UnaryExpr natural_predecessor)+  , ("nat-pred", UnaryExpr natural_predecessor)+  , ("nat-successor", UnaryExpr natural_successor)+  , ("nat-succ", UnaryExpr natural_successor)+  , ("integer-is-less", BinaryExpr is_less)+  , ("is-less", BinaryExpr is_less)+  , ("is-less-or-equal", BinaryExpr is_less_or_equal)+  , ("integer-is-less-or-equal", BinaryExpr is_less_or_equal)+  , ("is-greater", BinaryExpr is_greater)+  , ("integer-is-greater", BinaryExpr is_greater)+  , ("is-greater-or-equal", BinaryExpr is_greater_or_equal)+  , ("integer-is-greater-or-equal", BinaryExpr is_greater_or_equal)+  ]++integer_modulo_, integer_mod_ :: HasValues t => [OpExpr t] -> OpExpr t+integer_mod_ = binaryOp stepMod+integer_modulo_ = binaryOp stepMod++stepMod :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+stepMod = vBinaryOp "mod" op+  where op vx vy | (Int x, Int y)<- (upcastIntegers vx, upcastIntegers vy)+                 = Normal $ inject $ mk_integers $ x `mod` y+        op _ _ = SortErr "mod not applied to integers"++integers_ :: HasValues t => [OpExpr t] -> OpExpr t+integers_ = nullaryOp integers+integers :: HasValues t => OpExpr t+integers = vNullaryOp "integers" (Normal $ injectT Integers)++is_integer_ :: HasValues t => [OpExpr t] -> OpExpr t+is_integer_ = unaryOp is_integer+is_integer :: HasValues t => OpExpr t -> OpExpr t+is_integer x = RewritesTo "is-integer" (type_member x (ValExpr (ComputationType (Type Integers)))) [x]++isInt :: Values t -> Bool+isInt x | Int i <- upcastIntegers x = True +        | otherwise = False++unInt x | Int i <- upcastIntegers x = i+        | otherwise = error "unInt"++integer_add_ :: HasValues t => [OpExpr t] -> OpExpr t+integer_add_ = vNaryOp "integer-add" op+  where op  xs | all isInt xs = Normal $ inject $ mk_integers $ sum (map unInt xs)+               | otherwise = SortErr "integer-add not applied to integers"++integer_multiply_ :: HasValues t => [OpExpr t] -> OpExpr t+integer_multiply_ = vNaryOp "integer-multiply" op+  where op  xs | all isInt xs = Normal $ inject $ mk_integers $ product (map unInt xs)+               | otherwise = SortErr "integer-multiply not applied to integers"+++integer_subtract_ :: HasValues t => [OpExpr t] -> OpExpr t+integer_subtract_ = binaryOp integer_subtract+integer_subtract :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+integer_subtract = vBinaryOp "integer-subtract" op+  where op vx vy | Int x <- upcastIntegers vx+                 , Int y <- upcastIntegers vy = Normal $ inject $ mk_integers $ (x - y)+        op _ _ = SortErr "integer-subtract not applied to integers"++integer_divide_ :: HasValues t => [OpExpr t] -> OpExpr t+integer_divide_ = binaryOp integer_divide+integer_divide :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+integer_divide = vBinaryOp "integer-divide" op+  where op vx vy+          | (Int x,Int y) <- (upcastIntegers vx, upcastIntegers vy) = +              Normal $ inject $ mk_integers $ fromInteger (x `div` y)+          | otherwise = SortErr "integer-divide not applied to ints" ++integer_power_ :: HasValues t => [OpExpr t] -> OpExpr t+integer_power_ = binaryOp integer_power  +integer_power :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+integer_power = vBinaryOp "integer-power" op+  where op vx vy+          | (Int x, Int y) <- (upcastIntegers vx, upcastIntegers vy) = +              Normal $ inject $ mk_integers $ fromInteger $(x ^ y)+          | otherwise = SortErr "integer-power not applied to two integers"++natural_predecessor_, nat_pred_ :: HasValues t => [OpExpr t] -> OpExpr t+natural_predecessor_ = unaryOp natural_predecessor +nat_pred_ = unaryOp natural_predecessor +natural_predecessor :: HasValues t => OpExpr t -> OpExpr t+natural_predecessor = vUnaryOp "natural-predecessor" op+  where op x | Nat n <- upcastNaturals x =+          if n == 0 then DomErr "no predecessor of 0"+                    else Normal $ inject $ Nat (n - 1) +             | otherwise = SortErr "natural-pred not applied to a natural number"++natural_successor_, nat_succ_ :: HasValues t => [OpExpr t] -> OpExpr t+natural_successor_ = nat_succ_+nat_succ_ = unaryOp natural_successor+natural_successor :: HasValues t => OpExpr t -> OpExpr t+natural_successor = vUnaryOp "natural-successor" op+  where op x | Nat n <- upcastNaturals x = Normal $ inject $ Nat (n + 1) +             | otherwise = SortErr "natural-succ not applied to a natural number"++integer_list_ :: HasValues t => [OpExpr t] -> OpExpr t+integer_list_ = binaryOp integer_list+integer_list :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+integer_list = vBinaryOp "integer-list" op+ where op vi1 vi2+        | (Int i1, Int i2) <- (upcastIntegers vi1, upcastIntegers vi2)+                = Normal $ inject $ ADTVal "list" (map (inject . Int) [i1.. i2])+        | otherwise = SortErr "integer-list not applied to two integers"++integer_absolute_value_ :: HasValues t => [OpExpr t] -> OpExpr t+integer_absolute_value_ = unaryOp integer_absolute_value +integer_absolute_value :: HasValues t => OpExpr t -> OpExpr t+integer_absolute_value = vUnaryOp "integer-absolute-value" op+  where op v | Int  i <- upcastIntegers v = +                Normal $ inject $ Int (Prelude.abs i)+             | otherwise = SortErr "sort check: integer-absolute-value(I1)"++decimal_natural_ :: HasValues t => [OpExpr t] -> OpExpr t+decimal_natural_ = unaryOp decimal_natural +decimal_natural :: HasValues t => OpExpr t -> OpExpr t+decimal_natural = vUnaryOp "decimal-natural" op+  where op :: HasValues t => Values t -> Result t +        op s | isString_ s = Normal $ inject $ Nat (read (unString s))+             | otherwise = SortErr "decimal-natural not applied to a string"++is_less_ :: HasValues t => [OpExpr t] -> OpExpr t+is_less_ = binaryOp is_less+is_less :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+is_less = vBinaryOp "is-less" op+  where op vx vy+          | (Int x, Int y) <- (upcastIntegers vx, upcastIntegers vy)+              = Normal $ inject $ tobool (x < y)+          | otherwise = SortErr "is-less not applied to rationals"++is_less_or_equal_ :: HasValues t => [OpExpr t] -> OpExpr t+is_less_or_equal_ = binaryOp is_less_or_equal+is_less_or_equal ::  HasValues t => OpExpr t -> OpExpr t -> OpExpr t+is_less_or_equal = vBinaryOp "is-less-or-equal" op+ where op vx vy+         | (Int x, Int y) <- (upcastIntegers vx, upcastIntegers vy)+            = Normal $ inject $ tobool (x <= y) +         | otherwise = SortErr "is_less_or_equal not applied to two arguments"++is_greater_ :: HasValues t => [OpExpr t] -> OpExpr t+is_greater_ = binaryOp is_greater+is_greater :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+is_greater = vBinaryOp "is-greater" op+ where op vx vy+        | (Int x, Int y) <- (upcastIntegers vx, upcastIntegers vy)+            = Normal $ inject $ tobool (x > y) +        | otherwise = SortErr "is-greater not applied to two arguments"++is_greater_or_equal_ :: HasValues t => [OpExpr t] -> OpExpr t+is_greater_or_equal_ = binaryOp is_greater_or_equal +is_greater_or_equal :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+is_greater_or_equal = vBinaryOp "is-greater-or-equal" op+ where op vx vy | (Int x, Int y) <- (upcastIntegers vx, upcastIntegers vy)+                    = Normal $ inject $ tobool (x >= y) +                | otherwise = SortErr "is-greater-or-equal not applied to rationals"
+ src/Funcons/Operations/Internal.hs view
@@ -0,0 +1,10 @@++module Funcons.Operations.Internal (+  module Funcons.Operations.Expr,+  module Funcons.Operations.Values,+  module Funcons.Operations.Libraries,+  ) where++import Funcons.Operations.Expr+import Funcons.Operations.Values+import Funcons.Operations.Libraries
+ src/Funcons/Operations/Libraries.hs view
@@ -0,0 +1,18 @@++module Funcons.Operations.Libraries where++import qualified Data.Map as M++import Funcons.Operations.Expr++type Library t = M.Map OP (ValueOp t)++libFromList :: [(OP, ValueOp t)] -> Library t+libFromList = M.fromList++libLookup :: OP -> Library t -> Maybe (ValueOp t)+libLookup = M.lookup++libUnite :: [Library t] -> Library t+libUnite = M.unions+
+ src/Funcons/Operations/Lists.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE OverloadedStrings #-}++module Funcons.Operations.Lists where++import Funcons.Operations.Internal+import Funcons.Operations.Booleans++import Data.Maybe (isJust, fromJust)++library :: HasValues t => Library t+library = libFromList [+    ("lists", UnaryExpr lists)+  , ("list-singleton", UnaryExpr list_singleton)+  , ("list", NaryExpr list_)+  , ("list-append", BinaryExpr list_append)+  , ("list-concat", NaryExpr list_concat)+  , ("nil", NullaryExpr nil)+  , ("cons", BinaryExpr cons)+  , ("is-nil", UnaryExpr is_nil)+  , ("head", UnaryExpr headOp)+  , ("tail", UnaryExpr tailOp)+  ]++lists_ :: HasValues t => [OpExpr t] -> OpExpr t+lists_ = unaryOp lists+lists :: HasValues t => OpExpr t -> OpExpr t+lists = UnaryOp "lists" (Normal . injectT . ADT "lists" . (:[]))++list_singleton_ :: HasValues t => [OpExpr t] -> OpExpr t +list_singleton_ = unaryOp list_singleton+list_singleton :: HasValues t => OpExpr t -> OpExpr t+list_singleton = vUnaryOp "list-singleton" (Normal . inject . list . (:[]))++nil_ :: HasValues t => [OpExpr t] -> OpExpr t+nil_ = nullaryOp nil+nil :: HasValues t => OpExpr t+nil = NullaryOp "nil" (Normal $ inject $ list [])++is_nil_ :: HasValues t => [OpExpr t] -> OpExpr t+is_nil_ = unaryOp is_nil+is_nil :: HasValues t => OpExpr t -> OpExpr t+is_nil = UnaryOp "is-nil" op+  where op xs | Just lv <- project xs = case lv of +                  ADTVal "list" [] -> Normal $ inject $ true_ +                  _                -> Normal $ inject $ false_+              | otherwise = ProjErr "is-nil"++cons_ ::  HasValues t =>[OpExpr t] -> OpExpr t+cons_ = binaryOp cons+cons :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t +cons = vBinaryOp "cons" op+  where op v lv = case lv of+                    ADTVal "list" xs -> Normal $ inject $ ADTVal "list" (inject v:xs)+                    _ -> SortErr"cons should be given a value and a list"++list_ :: HasValues t => [OpExpr t] -> OpExpr t+list_ = vNaryOp "list" (Normal . inject . list)++list_append_ :: HasValues t => [OpExpr t] -> OpExpr t+list_append_ = binaryOp list_append+list_append :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+list_append = vBinaryOp "list-append" op+   where op (ADTVal "list" l1) (ADTVal "list" l2) = +            Normal $ inject $ ADTVal "list" (l1 ++ l2)+         op _ _ = SortErr "list-append not applied to two lists"+isList (ADTVal "list" l) = all (isJust) $ map project l +isList _                 = False+toList (ADTVal "list" l) = map (fromJust . project) l+toList _                 = error "list-append 1"+     +list_concat_ :: HasValues t => [OpExpr t] -> OpExpr t+list_concat_ = list_concat+list_concat :: HasValues t => [OpExpr t] -> OpExpr t+list_concat = vNaryOp "list-concat" op+   where op args | all isList args = Normal $ inject $ list $ concatMap toList args+                 | otherwise       = SortErr "list-concat not applied to lists"++head_, tail_ :: HasValues t => [OpExpr t] -> OpExpr t+head_ = unaryOp headOp+tail_ = unaryOp tailOp+headOp,tailOp :: HasValues t => OpExpr t -> OpExpr t+headOp = vUnaryOp "head" op+  where op (ADTVal "list" [])      = DomErr "head of empty list"+        op (ADTVal "list" (x:xs))  = Normal x+        op _                       = SortErr "head not applied to a list"+tailOp = vUnaryOp "tail" op+  where op (ADTVal "list" [])      = DomErr "tail of empty list"+        op (ADTVal "list" (x:xs))  = Normal $ inject (ADTVal "list" xs)+        op _                       = SortErr "tail not applied to a list"
+ src/Funcons/Operations/Maps.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE OverloadedStrings #-}++module Funcons.Operations.Maps where++import Funcons.Operations.Booleans+import Funcons.Operations.Internal+import Funcons.Operations.Sets+import qualified Data.Map as M+import qualified Data.Set as S ++library :: (HasValues t, Ord t) => Library t+library = libFromList [+    ("map-empty", NullaryExpr map_empty)+  , ("map-singleton", BinaryExpr map_singleton)+  , ("is-map-empty", UnaryExpr is_map_empty)+  , ("map-insert", TernaryExpr map_insert)+  , ("map-lookup", BinaryExpr map_lookup)+  , ("lookup", BinaryExpr map_lookup)+  , ("map-domain", UnaryExpr domain)+  , ("domain", UnaryExpr domain)+  , ("map-delete", BinaryExpr map_delete)+  , ("is-in-domain", BinaryExpr is_in_domain)+  , ("map-unite", NaryExpr map_unite)+  , ("map-override", BinaryExpr map_override)+  , ("maps", BinaryExpr maps)+  , ("map", NaryExpr map_)+  , ("map-elements", UnaryExpr map_elements)+  , ("map-points", UnaryExpr map_points)+  ]++map_ :: (Ord t, HasValues t) => [OpExpr t] -> OpExpr t+map_ = vNaryOp "map" (Normal . inject . Map . M.fromList . mkPairs)++mkPairs :: [a] -> [(a,a)]+mkPairs []        = []+mkPairs [x]       = []+mkPairs (x:y:ys)  = (x,y) : mkPairs ys++maps_ :: HasValues t => [OpExpr t] -> OpExpr t+maps_ = binaryOp maps+maps :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+maps = vBinaryOp "maps" op+  where op (ComputationType (Type t1)) (ComputationType (Type t2)) = Normal $ injectT (Maps t1 t2)+        op _ _ = SortErr "maps not applied to two types"++map_empty_ :: HasValues t => [OpExpr t] -> OpExpr t +map_empty_ = nullaryOp map_empty+map_empty :: HasValues t => OpExpr t +map_empty = NullaryOp "map-empty" (Normal $ inject (Map M.empty))++map_singleton_ :: (HasValues t,Ord t) => [OpExpr t] -> OpExpr t+map_singleton_ = binaryOp map_singleton+map_singleton :: (HasValues t, Ord t) => OpExpr t -> OpExpr t -> OpExpr t +map_singleton k v = RewritesTo "map-insert" (map_insert map_empty k v) [k,v]++is_map_empty_ :: HasValues t => [OpExpr t] -> OpExpr t+is_map_empty_ = unaryOp is_map_empty+is_map_empty :: HasValues t => OpExpr t -> OpExpr t +is_map_empty = vUnaryOp "is-map-empty" op +  where op (Map m)  = Normal $ inject $ tobool (null m)+        op _        = SortErr "is-map-empty(M) not applied to a map"++map_insert_ :: (HasValues t, Ord t) => [OpExpr t] -> OpExpr t+map_insert_ = ternaryOp map_insert +map_insert :: (HasValues t, Ord t) => OpExpr t -> OpExpr t -> OpExpr t -> OpExpr t+map_insert = vTernaryOp "map-insert" op+  where op xv k v = case xv of +              Map m -> Normal $ inject $ Map (M.insert k v m)+              _     -> SortErr "map-insert(M,K,V) not applied to a map (first argument)"++map_lookup_ :: (HasValues t, Ord t) => [OpExpr t] -> OpExpr t+map_lookup_ = binaryOp map_lookup+map_lookup :: (HasValues t, Ord t) => OpExpr t -> OpExpr t -> OpExpr t+map_lookup = vBinaryOp "map-lookup" op+  where op xv k = case xv of +                    Map m -> case M.lookup k m of +                        Nothing -> DomErr "key not in domain"+                        Just v  -> Normal $ inject v+                    _ -> SortErr "map-lookup(M,V) not applied to a map and a value"++map_delete_ :: (HasValues t, Ord t) => [OpExpr t] -> OpExpr t+map_delete_ = binaryOp map_delete+map_delete :: (HasValues t, Ord t) => OpExpr t -> OpExpr t -> OpExpr t+map_delete = vBinaryOp "map-delete" op+  where op (Map m) (Set s) = Normal $ inject $ Map (foldr M.delete m s)+        op _ _ = SortErr "map-delete(M,S) not applied to a map and a set"++is_in_domain_ :: (Ord t, HasValues t) => [OpExpr t] -> OpExpr t +is_in_domain_ = binaryOp is_in_domain+is_in_domain :: (Ord t, HasValues t) => OpExpr t -> OpExpr t -> OpExpr t +is_in_domain x y = RewritesTo "is-in-domain" (is_in_set x (domain y)) [x,y] ++domain_ :: (HasValues t, Ord t) => [OpExpr t] -> OpExpr t+domain_ = unaryOp domain+domain :: (HasValues t, Ord t) => OpExpr t -> OpExpr t+domain = vUnaryOp "domain" op+  where op (Map m)  = Normal $ inject $ Set $ S.fromList $ M.keys m+        op _        = SortErr "domain(M) not applied to a map"++map_override_ :: (HasValues t, Ord t) => [OpExpr t] -> OpExpr t+map_override_ = binaryOp map_override+map_override :: (HasValues t, Ord t) => OpExpr t -> OpExpr t -> OpExpr t+map_override = vBinaryOp "map-override" op+  where op (Map m1) (Map m2) = Normal $ inject $ Map (M.union m1 m2)+        op _ _ = SortErr "map-override(M,M) not applied tOpExpr two maps"++map_unite_ :: (HasValues t, Ord t) => [OpExpr t] -> OpExpr t+map_unite_ = map_unite +map_unite :: (HasValues t, Ord t) => [OpExpr t] -> OpExpr t+map_unite = vNaryOp "map-unite" op+  where op args +          | all isMap args =+              let maps = map toMap args+                  domains = map (M.keysSet) maps+              in if all (null . uncurry S.intersection) (allDomainPairs domains)+                  then Normal $ inject $ Map $ M.unions maps+                  else DomErr "union with domain intersection"+          | otherwise     = SortErr "map-unite(M1,...,Mn) not applied to maps"+          where isMap (Map _) = True+                isMap _       = False+                toMap (Map m) = m+                toMap _       = error "map_unite"++allDomainPairs :: [a] -> [(a,a)] +allDomainPairs (x:xs) = [ (x,y)  | y <- xs ] ++ allDomainPairs xs+allDomainPairs [] = []++map_elements_ :: (Ord t, HasValues t) => [OpExpr t] -> OpExpr t+map_elements_ = unaryOp map_elements+map_elements :: (Ord t, HasValues t) => OpExpr t -> OpExpr t+map_elements = vUnaryOp "map-elements" op+  where op (Map m) = Normal $ inject $ ADTVal "list" (map inject $ M.foldrWithKey combine [] m)+          where combine k v ls = k:v:ls+        op _ = SortErr "map-elements not applied to a map"++map_points_ :: (Ord t, HasValues t) => [OpExpr t] -> OpExpr t+map_points_ = unaryOp map_points+map_points :: (Ord t, HasValues t) => OpExpr t -> OpExpr t+map_points = vUnaryOp "map-points" op+  where op (Map m) = Normal $ inject $ ADTVal "list" (map inject $ M.foldrWithKey combine [] m)+          where combine k v ls = ADTVal "tuple" [inject k, inject v]:ls+        op _ = SortErr "map-points not applied to a map"
+ src/Funcons/Operations/Multisets.hs view
@@ -0,0 +1,11 @@++module Funcons.Operations.Multisets where++import Funcons.Operations.Booleans+import Funcons.Operations.Internal++import qualified Data.MultiSet as MS++library :: (HasValues t, Ord t) => Library t+library = libFromList [+  ]
+ src/Funcons/Operations/NonGroundValues.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE OverloadedStrings #-}++module Funcons.Operations.NonGroundValues where++import Prelude hiding (non_grounded)+import Funcons.Operations.Internal++library :: (HasValues t, Eq t) => Library t+library = libFromList [+    ("non-grounded", UnaryExpr non_grounded)+  , ("non-grounded-values", NullaryExpr non_grounded_values)+  ]++non_grounded_ :: HasValues t => [OpExpr t] -> OpExpr t+non_grounded_ = unaryOp non_grounded +non_grounded :: HasValues t => OpExpr t -> OpExpr t+non_grounded = vUnaryOp "non-grounded" (Normal . inject . ADTVal "non-grounded" . (:[]) . inject) ++non_grounded_values_ :: HasValues t => [OpExpr t] -> OpExpr t+non_grounded_values_ = nullaryOp non_grounded_values +non_grounded_values :: HasValues t => OpExpr t+non_grounded_values = vNullaryOp "non-grounded-values" +  (Normal $ injectT $ ADT "non-grounded-values" [])++{-+-- This function differs from Funcons.Operations.Values.isGround+-- and assumes that non_grounded<> is the only non-ground value constructor+isGround :: Values t -> Bool+isGround (ADTVal "non-grounded" _) = False+isGround v = True+-}
+ src/Funcons/Operations/Optionals.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE OverloadedStrings #-}++module Funcons.Operations.Optionals where++import Funcons.Operations.Internal++library :: (HasValues t, Eq t) => Library t+library = libFromList [+    ("optionals", UnaryExpr optionals)+  , ("none", NullaryExpr none)+  , ("some", UnaryExpr some)+  ]++toOpt :: HasValues t => Maybe t -> Values t +toOpt (Just t)  = ADTVal "some" [t]+toOpt Nothing   = none__ ++optionals_ :: HasValues t => [OpExpr t] -> OpExpr t+optionals_ = unaryOp optionals+optionals :: HasValues t => OpExpr t -> OpExpr t+optionals = vUnaryOp "optionals" op+  where op (ComputationType t) = (Normal $ injectT $ ADT "optionals" [injectCT t])+        op _        = SortErr "optionals not applied to a type"++some__ :: HasValues t => t -> Values t +some__ = toOpt . Just+some_ :: HasValues t => [OpExpr t] -> OpExpr t+some_ = unaryOp some+some :: HasValues t => OpExpr t -> OpExpr t+some = vUnaryOp "some" (Normal . inject . some__ . inject)++none_ :: HasValues t => [OpExpr t] -> OpExpr t+none_ = nullaryOp none+none :: HasValues t => OpExpr t+none = vNullaryOp "none" (Normal $ inject $ none__)++
+ src/Funcons/Operations/Sets.hs view
@@ -0,0 +1,129 @@+{-# LANGUAGE OverloadedStrings #-}++module Funcons.Operations.Sets where++import Funcons.Operations.Booleans+import Funcons.Operations.Internal hiding (set_)++import qualified Data.Set as S++import Test.RandomStrings (randomString', randomASCII)+import System.IO.Unsafe (unsafePerformIO)++library :: (HasValues t, Ord t) => Library t+library = libFromList [+    ("set-empty", NullaryExpr set_empty)+  , ("sets", UnaryExpr sets) +  , ("is-in-set", BinaryExpr is_in_set) +  , ("set", NaryExpr set_)+  , ("set-elements", UnaryExpr set_elements)+  , ("is-subset", BinaryExpr is_subset)+  , ("set-insert", BinaryExpr set_insert)+  , ("set-unite", NaryExpr set_unite_)+  , ("set-intersect", NaryExpr set_intersect_)+  , ("set-difference", NaryExpr set_difference_)+  , ("set-size", UnaryExpr set_size)+  , ("some-element", UnaryExpr some_element)+  , ("element-not-in", BinaryExpr element_not_in)+--  , ("is-set-empty", UnaryExpr is_set_empty)+  ]++sets_ :: HasValues t => [OpExpr t] -> OpExpr t+sets_ = unaryOp sets+sets :: HasValues t => OpExpr t -> OpExpr t+sets = vUnaryOp "sets" op+  where op (ComputationType (Type t)) = Normal $ injectT $ Sets t+        op _ = SortErr "sets not applied to a type" ++set_empty_ :: HasValues t => [OpExpr t] -> OpExpr t+set_empty_ = nullaryOp set_empty+set_empty :: HasValues t => OpExpr t+set_empty = NullaryOp "set-empty" (Normal $ inject (Set S.empty))++is_in_set_ :: (HasValues t, Ord t) => [OpExpr t] -> OpExpr t+is_in_set_ = binaryOp is_in_set+is_in_set :: (HasValues t, Ord t) => OpExpr t -> OpExpr t -> OpExpr t +is_in_set = BinaryOp "is-in-set" op +  where op e' s' +          | Just s <- project s', Just e <- project e' = case s of +            Set set -> Normal $ inject $ tobool (e `S.member` set)+            _       -> SortErr "is-in-set(V,S) not applied to a value and a set"+          | otherwise = ProjErr "is-in-set"++set_elements_ :: HasValues t => [OpExpr t] -> OpExpr t+set_elements_ = unaryOp set_elements+set_elements :: HasValues t => OpExpr t -> OpExpr t+set_elements = vUnaryOp "set-elements" op+ where op (Set s) = Normal $ inject $ ADTVal "list" (map inject $ S.toList s)+       op _ = SortErr "set-elements not applied to a set"++set_size_ :: (Ord t, HasValues t) => [OpExpr t] -> OpExpr t+set_size_ = unaryOp set_size+set_size :: (Ord t, HasValues t) => OpExpr t -> OpExpr t+set_size = vUnaryOp "set-size" op+ where op (Set s) = Normal $ inject $ Nat (toInteger $ S.size s) +       op _ = SortErr "set-size not applied to a set"++set_intersect_ :: (Ord t, HasValues t) => [OpExpr t] -> OpExpr t+set_intersect_ = vNaryOp "set-intersect" op+  where op [] = SortErr "set-intersect applied to an empty sequence of sets"+        op vs | all isSet_ vs = Normal $ inject $ +                                  Set (foldr1 S.intersection (map toSet vs))+              | otherwise = SortErr "set-intersect not applied to sets"+          where isSet_ (Set _) = True+                isSet_ _       = False+                toSet (Set s)  = s+                toSet _        = error "set-intersect toSet"++set_difference_ :: (Ord t, HasValues t) => [OpExpr t] -> OpExpr t+set_difference_ = binaryOp set_difference+set_difference :: (Ord t, HasValues t) => OpExpr t -> OpExpr t -> OpExpr t+set_difference = vBinaryOp "set-difference" op+  where op (Set s1) (Set s2) = Normal $ inject $ Set (s1 `S.difference` s2)+        op _ _ = SortErr "set-difference not applied to two sets"++some_element_ :: (Ord t, HasValues t) => [OpExpr t] -> OpExpr t+some_element_ = unaryOp some_element+some_element :: (HasValues t, Ord t) => OpExpr t -> OpExpr t+some_element = vUnaryOp "some-element" op+  where op (Set s) | not (S.null s) = Normal $ inject $ S.findMax s+        op _ = SortErr "some-element not applied to a non-empty set"++is_subset_ :: (Ord t, HasValues t) => [OpExpr t] -> OpExpr t+is_subset_ = binaryOp is_subset+is_subset :: (Ord t, HasValues t) => OpExpr t -> OpExpr t -> OpExpr t+is_subset = vBinaryOp "is-subset" op+  where op (Set s1) (Set s2) = Normal $ inject $ tobool (s1 `S.isSubsetOf` s2)+        op _ _ = SortErr "is-subset not applied to two sets"++set_ :: (Ord t, HasValues t) => [OpExpr t] -> OpExpr t+set_ = vNaryOp "set" op+  where op vs = Normal $ inject $ Set (S.fromList vs)++set_unite_ :: (Ord t, HasValues t) => [OpExpr t] -> OpExpr t+set_unite_ = vNaryOp "set-unite" op+  where op vs | all isSet_ vs = Normal $ inject $ Set $ S.unions $ map unSet vs+              | otherwise = SortErr "set-unite not applied to sets"+          where isSet_ (Set s) = True+                isSet_ _       = False+                unSet (Set s) = s+                unSet _       = error "set-unite not applied to sets only"++set_insert_ :: (Ord t, HasValues t) => [OpExpr t] -> OpExpr t+set_insert_ = binaryOp set_insert+set_insert :: (HasValues t, Ord t) => OpExpr t -> OpExpr t -> OpExpr t+set_insert = vBinaryOp "set-insert" op+  where op e (Set s) = Normal $ inject $ Set (e `S.insert` s)+        op _ _ = SortErr "second argument of set-insert is not a set"++element_not_in_ :: (HasValues t, Ord t) => [OpExpr t] -> OpExpr t +element_not_in_ = binaryOp element_not_in+element_not_in :: (Ord t, HasValues t) => OpExpr t -> OpExpr t -> OpExpr t+element_not_in = vBinaryOp "element-not-in" op+  where op (ComputationType (Type ty)) (Set set) = case ty of +          Atoms -> Normal $ inject $ Atom (unsafePerformIO (getRnd >>= nextAtom))+          _     -> error "missing case for `element-not-in`"+          where nextAtom s | Atom s `S.member` set = getRnd >>= nextAtom+                           | otherwise             = return s  +                getRnd   = randomString' randomASCII 1 1 5+        op _ _ = SortErr "element-not-in not applied to a type and a set"
+ src/Funcons/Operations/Strings.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE OverloadedStrings #-}++module Funcons.Operations.Strings where++import Funcons.Operations.Libraries+import Funcons.Operations.Internal+import Funcons.Operations.Types++library :: HasValues t => Library t+library = libFromList [+    ("is-string", UnaryExpr is_string)+  , ("strings", NullaryExpr (vNullaryOp "strings" (Normal $ injectT $ ADT "strings" [])))+  , ("to-string", UnaryExpr to_string)+  ]++is_string_ :: HasValues t => [OpExpr t] -> OpExpr t+is_string_ = unaryOp is_string+is_string x = RewritesTo "is-string" (type_member x (ValExpr (ComputationType (Type Strings)))) [x]++to_string_ :: HasValues t => [OpExpr t] -> OpExpr t+to_string_ = unaryOp to_string+to_string :: HasValues t => OpExpr t -> OpExpr t +to_string = vUnaryOp "to-string" stepTo_String++stepTo_String s | isString_ s = Normal $ inject $ s+stepTo_String (Rational r)      = mk_string (show (fromRational r))+stepTo_String (Ascii c)         = mk_string ([c])+stepTo_String (Atom s)          = mk_string  s+stepTo_String (Int i)           = mk_string  (show i)+stepTo_String (Nat n)           = mk_string  (show n)+stepTo_String (Float f)         = mk_string  (show f)+stepTo_String (IEEE_Float_32 f) = mk_string  (show f)+stepTo_String (IEEE_Float_64 d) = mk_string  (show d)+stepTo_String v                 = DomErr ("to-string undefined on this type")++mk_string :: HasValues t => String -> Result t+mk_string = Normal . inject . ADTVal "list" . map (inject . Ascii)
+ src/Funcons/Operations/Tuples.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE OverloadedStrings #-}++module Funcons.Operations.Tuples where++import Funcons.Operations.Internal++library :: HasValues t => Library t+library = libFromList [+    ("tuples", NaryExpr tuples_)+  , ("tuple", NaryExpr tuple_)+  , ("tuple-index", BinaryExpr tuple_index)+  , ("empty-tuple", NullaryExpr  empty_tuple)+  , ("tuple-prepend", BinaryExpr tuple_prepend)+  ]++tuples_ :: HasValues t => [OpExpr t] -> OpExpr t+tuples_ = NaryOp "tuples" (Normal . injectT . ADT "tuples")++empty_tuple_, tuple_prepend_ :: HasValues t => [OpExpr t] -> OpExpr t+empty_tuple_ = nullaryOp empty_tuple+tuple_prepend_ = binaryOp tuple_prepend++empty_tuple :: HasValues t => OpExpr t+empty_tuple = vNullaryOp "empty-tuple" (Normal $ inject (tuple []))++tuple_prepend :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+tuple_prepend = vBinaryOp "tuple-prepend" op+  where op v (ADTVal "tuple" vs) = Normal $ inject (ADTVal "tuple" (inject v : vs))+        op _ _ = SortErr "tuple-prepend not applied to a value and a tuple"++tuple_ :: HasValues t => [OpExpr t] -> OpExpr t+tuple_ = vNaryOp "tuple" op+  where op ys = Normal $ inject (tuple ys)++tuple_index_ :: HasValues t => [OpExpr t] -> OpExpr t+tuple_index_ = binaryOp tuple_index+tuple_index :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+tuple_index = vBinaryOp "tuple-index" op+  where op (ADTVal "tuple" ts) v +          | Nat n' <- upcastNaturals v, let n :: Int; n = fromInteger n'+            = case () of +               () | n >= 1 && n <= length ts -> Normal $ ts !! (n - 1)+               _ -> SortErr "tuple-index not in range"+          | otherwise = SortErr ("tuple-index not applied to a natural number: " ++ ppValues (const "_") v)+        op _ _ = SortErr "tuple-index not applied to a tuple"
+ src/Funcons/Operations/Types.hs view
@@ -0,0 +1,171 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE LambdaCase #-}++module Funcons.Operations.Types where++import Funcons.Operations.Booleans+import Funcons.Operations.Internal+import Data.Foldable (toList) +import qualified Data.BitVector as BV+import qualified Data.Map as M+import qualified Data.Char as C+import qualified Data.Set as S+import qualified Data.MultiSet as MS+import qualified Data.Vector as V++library :: (HasValues t, Ord t) => Library t+library = libFromList [+    ("types", NullaryExpr types)+  , ("value-types", NullaryExpr value_types)+  , ("defined-values", NullaryExpr defined_values)+  , ("nothing", NullaryExpr nothing)+  , ("values", NullaryExpr values)+  , ("type-member", BinaryExpr type_member)+--  , ("is-value", UnaryExpr is_value)+--  , ("is-val", UnaryExpr is_value)+  , ("value-type", UnaryExpr value_type)+  , ("datatype-values", NullaryExpr datatype_values)+  , ("ground-values", NullaryExpr ground_values)+  ]++datatype_values_ :: HasValues t => [OpExpr t] -> OpExpr t+datatype_values_ = nullaryOp datatype_values+datatype_values :: HasValues t => OpExpr t+datatype_values = vNullaryOp "datatype-values" (Normal $ injectT ADTs)++ground_values_ :: HasValues t => [OpExpr t] -> OpExpr t+ground_values_ = nullaryOp ground_values+ground_values :: HasValues t => OpExpr t+ground_values = vNullaryOp "ground-values" (Normal $ injectT GroundValues)++types_ :: HasValues t => [OpExpr t] -> OpExpr t+types_ = nullaryOp types+types :: HasValues t => OpExpr t+types = NullaryOp "types" (Normal $ injectT Types)++value_types_ :: HasValues t => [OpExpr t] -> OpExpr t+value_types_ = nullaryOp types+value_types :: HasValues t => OpExpr t+value_types = NullaryOp "value-types" (Normal $ injectT Types)++defined_values_ :: HasValues t => [OpExpr t] -> OpExpr t+defined_values_ = nullaryOp defined_values+defined_values :: HasValues t => OpExpr t+defined_values = NullaryOp "defined-values" (Normal $ injectT DefinedValues)++nothing_ :: HasValues t => [OpExpr t] -> OpExpr t+nothing_ = nullaryOp nothing +nothing :: HasValues t => OpExpr t+nothing = NullaryOp "nothing" (Normal $ injectT Nothings)++values_ :: HasValues t => [OpExpr t] -> OpExpr t+values_ = nullaryOp values+values :: HasValues t => OpExpr t+values = NullaryOp "values" (Normal $ injectT Values)+++is_value_ :: HasValues t => [OpExpr t] -> OpExpr t+is_value_ = unaryOp is_value+is_value :: HasValues t => OpExpr t -> OpExpr t+is_value = UnaryOp "is-value" op+  where op _ = Normal $ inject (tobool True) ++value_type_ :: HasValues t => [OpExpr t] -> OpExpr t+value_type_ = unaryOp value_type+value_type :: HasValues t => OpExpr t -> OpExpr t+value_type = vUnaryOp "value-type" (Normal . injectT . tyOf)+ +tyOf :: HasValues t => Values t -> Types t+tyOf (ADTVal "true" [])         = ADT "booleans" []+tyOf (ADTVal "false" [])        = ADT "booleans" []+tyOf (Int _)                    = Integers+tyOf (Nat _)                    = Naturals+tyOf (ADTVal _ _)               = ADTs+tyOf (Ascii _)                  = AsciiCharacters+tyOf (Atom _)                   = Atoms+tyOf (Bit v)                    = Bits (BV.size v)+tyOf (Char _)                   = UnicodeCharacters +tyOf (ComputationType (Type _)) = Types+tyOf (ComputationType _)        = ComputationTypes+tyOf (Float f)                  = IEEEFloats Binary32 +--tyOf (Type _)                   = Types +tyOf (IEEE_Float_32 _)          = IEEEFloats Binary32 +tyOf (IEEE_Float_64 _)          = IEEEFloats Binary64 +tyOf (Rational _)               = Rationals+tyOf (Map m)                    = Maps Values Values -- TODO find "strongest common type"+tyOf (Set s)                    | null s = Sets Values+                                | otherwise = Sets (tyOf (S.findMax s))+tyOf (Multiset s)               | null s = Multisets Values+                                | otherwise = Multisets (tyOf (MS.findMax s)) +tyOf (Vector v)                 | V.null v = Vectors Values+                                | otherwise = Vectors (tyOf (v V.! 0))+tyOf VAny                       = Values+tyOf (VMeta t)                  = ASTs++type_member_ :: HasValues t => [OpExpr t] -> OpExpr t+type_member_ = binaryOp type_member+-- | Type membership check for primitive types and+-- predefined composite types (non-ADTs).+type_member :: HasValues t => OpExpr t -> OpExpr t -> OpExpr t+type_member = vBinaryOp "type-member" op+  where op v mty = case mty of+         ComputationType (Type t) -> proceed v t+         ComputationType (ComputesType t) -> proceed v t+         ComputationType (ComputesFromType _ t) -> proceed v t+         _ -> SortErr "type-member(V,Ty) not applied to a value and a type"+ +        proceed v ty = case isInType v ty of+          Nothing -> DomErr "type-member applied to an ADT or a non-type"+          Just b  -> Normal $ inject (tobool b)++isInType :: HasValues t => Values t -> Types t -> Maybe Bool+isInType _ EmptyType = return False+isInType v Values = return True +isInType n Nothings = return (isNoValue n) +isInType v DefinedValues = return (isDefinedVal v)+isInType v GroundValues = return (isGround v)+isInType v (ADT "strings" []) = return (isString_ v)+isInType (ADTVal "list" vs') (ADT "lists" [ty']) +  | Just ty <- projectT ty', Just vs <- sequence (map project vs') = +  and <$> mapM (flip isInType ty) vs+isInType (ADTVal "true" []) (ADT "booleans" []) = return True+isInType (ADTVal "false" []) (ADT "booleans" []) = return True+isInType v (ADT "tuples" ttparams') +  | Just ttparams <- sequence (map projectT ttparams') = case v of+    ADTVal "tuple" vs' | Just vs <- sequence (map project vs')+                            -> isInTupleType vs ttparams+    _                       -> isInTupleType [v] ttparams +isInType v (ADT nm tys) = Nothing+isInType (ADTVal _ _) ADTs = return True+isInType (Atom _) Atoms = return True+isInType (Ascii _) Characters = return True+isInType (Char _) Characters = return True+isInType (Ascii _) AsciiCharacters = return True+isInType (Bit bv) (Bits n) = return (BV.size bv == n)+isInType v (IntegersFrom n) +    | Int i <- upcastIntegers v = return (i >= n)+isInType v (IntegersUpTo n) +    | Int i <- upcastIntegers v = return (i <= n)+isInType (ComputationType _) Types = return True+isInType (ComputationType (ComputesFromType _ _)) ComputationTypes = return True+isInType (ComputationType (ComputesType _)) ComputationTypes = return True+isInType (ComputationType (Type _)) ComputationTypes = return True+isInType (IEEE_Float_32 _) (IEEEFloats Binary32) = return True+isInType (IEEE_Float_64 _) (IEEEFloats Binary64) = return True+isInType v Integers | Int _ <- upcastIntegers v = return True+isInType (Map m) (Maps kt vt) = and <$> sequence [and <$> mapM (flip isInType kt) (M.keys m)+                                                 ,and <$> mapM (flip isInType vt) (M.elems m)]+isInType (Multiset ls) (Multisets ty) = and <$> mapM (flip isInType ty) (toList ls)+isInType v Naturals | Nat _ <- upcastNaturals v = return True+isInType v Rationals | Rational _ <- upcastRationals v = return True +isInType (Set ls) (Sets ty) = and <$> mapM (flip isInType ty) (toList ls)+isInType v UnicodeCharacters | Char _ <- upcastUnicode v = return True+isInType v (Union ty1 ty2) = (||) <$> isInType v ty1 <*> isInType v ty2+isInType v (Complement ty) = not <$> isInType v ty+isInType v (Intersection ty1 ty2) = (&&) <$> isInType v ty1 <*> isInType v ty2+isInType (Vector ls) (Vectors ty) = and <$> mapM (flip isInType ty) (toList ls)+--isInType (VMeta _) ASTs = return True -- for meta-programming (see Funcons.MetaProgramming)+isInType _ _ = return False++isInTupleType :: HasValues t => [Values t] -> [Types t] -> Maybe Bool+isInTupleType vs ttparams = and <$> sequence (zipWith isInType vs ttparams)
+ src/Funcons/Operations/Values.hs view
@@ -0,0 +1,735 @@+{-# LANGUAGE UndecidableInstances, OverloadedStrings, TupleSections, RankNTypes, FlexibleInstances, LambdaCase #-}++module Funcons.Operations.Values where++import qualified Data.Map as M+import qualified Data.Vector as V+import qualified Data.Set as S+import qualified Data.BitVector as BV+import qualified Data.MultiSet as MS++import qualified Data.Char as C+import Data.Text (Text, pack, unpack)+import Data.List (intercalate)+import Data.Maybe (fromJust)+import Data.String++import Control.Monad (liftM2)+import Control.Arrow ((***))++type Name = Text+type MVar = String++-- | +-- This datatype provides a number of builtin value types.+-- The type `t` is expected to be a super-type of `Values t`,+-- such that there is a projection and injection between `t` and `Values t`,+-- (see 'HasValues')+-- Values forms a functor over the type `t` and provides a generic way of+-- comparing values (see `zipWithT`) for example to realise pattern matching +data Values t   = ADTVal Name [t]+                | Ascii Char +                | Atom String+                | Bit BV.BitVector+                | Char Char+                | ComputationType (ComputationTypes t)+                | Float Double +                | IEEE_Float_32 Float+                | IEEE_Float_64 Double+                | Int Integer+                | Map (ValueMaps (Values t))+                | Multiset (MS.MultiSet (Values t))+                | Nat Integer+                | Rational Rational+                | Set (ValueSets (Values t))+                | Vector (ValueVectors (Values t))+                | VMeta (TaggedSyntax t)+                | VAny -- used whenever funcon terms may have holes in them+                       -- currently only the case in "downwards" flowing signals+        deriving (Eq,Ord,Show,Read)++tuple :: HasValues t => [Values t] -> Values t+tuple = ADTVal "tuple" . map inject++list :: HasValues t => [Values t] -> Values t+list = ADTVal "list" . map inject++instance HasValues t => IsString (Values t) where+  fromString = ADTVal "list" . map (inject . Ascii)++data TaggedSyntax t = TagName Name [Values t]+                    | TagType (Types t) (Values t)+                  deriving (Eq, Ord, Show, Read)++type ValueMaps t      = M.Map t t +type ValueSets t      = S.Set t+type ValueVectors t   = V.Vector t++-- | Postfix operators for specifying sequences.+data SeqSortOp = StarOp | PlusOp | QuestionMarkOp+                deriving (Show, Eq, Ord, Read)+++-- | Computation type /S=>T/ reflects a type of term+-- whose given value is of type /S/ and result is of type /T/.+data ComputationTypes t = Type (Types t) -- | /=>T/+                        | ComputesType (Types t) -- | /S=>T/+                        | ComputesFromType (Types t) (Types t)+                        deriving (Ord,Eq,Show, Read)++-- | Representation of builtin types.+data Types t= ADTs+            | ADT Name [t]+            | AnnotatedType (Types t) SeqSortOp+            | AsciiCharacters+            | Atoms+            | Bits Int+            | IntegersFrom Integer -- value-dependent type+            | IntegersUpTo Integer+            | Characters+            | Complement (Types t)+            | ComputationTypes+            | EmptyType+            | GroundValues+            | IEEEFloats IEEEFormats+            | Integers+            | Intersection (Types t) (Types t)+            | Maps (Types t) (Types t)+            | Multisets (Types t)+            | Naturals+            | Nothings+            | Rationals+            | Sets (Types t)+            | Strings+            | Types+            | UnicodeCharacters+            | Union (Types t) (Types t)+            | DefinedValues +            | Values+            | Vectors (Types t)+            -- extension for meta-programming (see Funcons.MetaProgramming)+            | ASTs+              deriving (Ord,Eq,Show,Read)+++class HasValues t where+  project :: t -> Maybe (Values t)+  inject  :: Values t -> t+class HasComputationTypes t where+  projectCT :: t -> Maybe (ComputationTypes t)+  injectCT  :: ComputationTypes t -> t+class HasTypes t where+  projectT  :: t -> Maybe (Types t)+  injectT   :: Types t -> t+instance HasValues t => HasComputationTypes t where+  projectCT v = project v >>= \case+                ComputationType t -> Just t+                _      -> Nothing+                +  injectCT  = inject . ComputationType+instance HasComputationTypes t => HasTypes t where+  projectT ct = projectCT ct >>= \case +                  Type t -> Just t +                  _      -> Nothing+  injectT = injectCT . Type++data IEEEFormats = Binary32 | Binary64+        deriving (Enum,Show,Eq,Ord,Read)++-- Specialised version of 'fmap'+vmap :: (Ord b) => (a -> b) -> Values a -> Values b+vmap f v = case v of+    ADTVal nm ts      -> ADTVal nm (map f ts)+    Ascii a           -> Ascii a+    Atom a            -> Atom a+    Bit b             -> Bit b+    Char c            -> Char c+    ComputationType t -> ComputationType (fmap f t)+    Float f           -> Float f+    IEEE_Float_32 f   -> IEEE_Float_32 f+    IEEE_Float_64 f   -> IEEE_Float_64 f+    Int i             -> Int i+    Map m             -> Map $ M.fromList $ map (vmap f *** vmap f) $ M.assocs m+    Set s             -> Set $ S.map (vmap f) s+    Multiset ms       -> Multiset $ MS.map (vmap f) ms+    Nat n             -> Nat n+    Rational r        -> Rational r+    Vector v          -> Vector $ V.map (vmap f) v+    VMeta ts          -> VMeta $ vmapTS f ts+    VAny              -> VAny++vmapTS :: (Ord b) => (a -> b) -> TaggedSyntax a -> TaggedSyntax b+vmapTS f ts = case ts of+    TagName nm vs -> TagName nm (map (vmap f) vs)+    TagType t v   -> TagType (fmap f t) (vmap f v) +  +traverseV :: (Ord b, Monad m, HasValues a, HasValues b) => +  (a -> m b) -> Values a -> m (Values b)+traverseV f = traverseVM f (mapM f)++traverseVM :: (Ord b, Monad m, HasValues a, HasValues b) => +  (a -> m b) -> ([a] -> m [b]) -> Values a -> m (Values b)+traverseVM f fs v = case v of+    ADTVal nm vs      -> return . ADTVal nm =<< fs vs+    Ascii a           -> return $ Ascii a+    Atom a            -> return $ Atom a+    Bit b             -> return $ Bit b+    Char c            -> return $ Char c+    ComputationType t -> return . ComputationType   =<< traverseCTM f fs t+    Float f           -> return $ Float f+    IEEE_Float_32 f   -> return $ IEEE_Float_32 f+    IEEE_Float_64 f   -> return $ IEEE_Float_64 f+    Int i             -> return $ Int i+    Map m             -> do +        let (keys, vals) = unzip (M.assocs m)+        keys' <- map (fromJust . project) <$> fs (map inject keys)+        vals' <- map (fromJust . project) <$> fs (map inject vals)+        return (Map $ M.fromList $ zip keys' vals')+    Set s             -> return . Set . S.fromList . map (fromJust . project) =<< fs (map inject $ S.toList s)+    Multiset ms       -> return . Multiset . MS.fromList . map (fromJust . project) =<< fs (map inject $ MS.toList ms)+    Nat n             -> return $ Nat n+    Rational r        -> return $ Rational r+    Vector v          -> return . Vector . V.fromList . map (fromJust . project) =<< fs (map inject $ V.toList v)+    VMeta ts -> VMeta <$> traverseTSM f fs ts+    VAny -> return VAny++traverseT :: (Ord b, Monad m, HasValues a, HasValues b) => +  (a -> m b) -> Types a -> m (Types b)+traverseT f = traverseTM f (mapM f)+traverseTM :: (Ord b, Monad m, HasValues a, HasValues b) => +  (a -> m b) -> ([a] -> m [b]) -> Types a -> m (Types b)+traverseTM f fs t = case t of+  ADTs -> return ADTs+  ADT nm ts -> return . ADT nm =<< fs ts+  AsciiCharacters -> return AsciiCharacters+  Atoms ->  return Atoms+  AnnotatedType ty op -> AnnotatedType <$> traverseTM f fs ty <*> return op+  ASTs -> return ASTs+  Bits i -> return (Bits i)+  Characters -> return Characters+  ComputationTypes -> return ComputationTypes+  Complement t -> Complement <$> traverseTM f fs t  +  DefinedValues -> return DefinedValues+  GroundValues -> return GroundValues+  IntegersFrom f -> return (IntegersFrom f)+  IntegersUpTo f -> return (IntegersUpTo f)+  Intersection t1 t2 -> Intersection <$> traverseTM f fs t1 <*> traverseTM f fs t2+  Nothings -> return Nothings+  EmptyType -> return EmptyType+  IEEEFloats i -> return (IEEEFloats i)+  Integers -> return Integers+  Maps t1 t2 -> Maps <$> traverseTM f fs t1 <*> traverseTM f fs t2+  Multisets t -> Multisets <$> traverseTM f fs t+  Naturals -> return Naturals+  Rationals -> return Rationals+  Sets t -> Sets <$> traverseTM f fs t+  Strings -> return Strings+  Types -> return Types +  UnicodeCharacters -> return UnicodeCharacters+  Union t1 t2 -> Union <$> traverseTM f fs t1 <*> traverseTM f fs t2+  Values -> return Values+  Vectors t -> Vectors <$> traverseTM f fs t ++traverseTSM f fs t = case t of+  TagName nm vs -> TagName nm <$> traverse (traverseVM f fs) vs+  TagType ty v  -> TagType <$> traverseTM f fs ty <*> traverseVM f fs v++traverseCTM f fs t = case t of+  Type t -> Type <$> traverseTM f fs t+  ComputesType t -> ComputesType <$> traverseTM f fs t+  ComputesFromType ty ty2 -> ComputesFromType <$> traverseTM f fs ty+                                              <*> traverseTM f fs ty2++structVcompare :: (Monoid m, HasValues a, HasValues b) => +  (a -> b -> Maybe m) -> Values a -> Values b -> Maybe (Maybe m)+structVcompare comp = structVMcompare comp comps+  where comps xs ys | length xs == length ys = fmap mconcat $ sequence $ zipWith comp xs ys+                    | otherwise = Nothing++structCTMcompare :: (Monoid m, HasValues a, HasValues b) => +  (a -> b -> Maybe m) -> ([a] -> [b] -> Maybe m) ->+    ComputationTypes a -> ComputationTypes b -> (Maybe (Maybe m))+structCTMcompare comp comps va vb = case (va,vb) of+  (Type x, Type y)  -> structTMcompare comp comps x y +  (Type _,_)        -> Nothing+  (_, Type _)       -> Nothing+  (ComputesType x, ComputesType y)  -> structTMcompare comp comps x y +  (ComputesType _, _)               -> Nothing +  (_, ComputesType _)               -> Nothing+  (ComputesFromType x y, ComputesFromType x' y') -> +    liftM2 mappend (structTMcompare comp comps x x') (structTMcompare comp comps y y')++structVMcompare :: (Monoid m, HasValues b, HasValues a) => +  (a -> b -> Maybe m) -> ([a] -> [b] -> Maybe m) -> +    Values a -> Values b -> Maybe (Maybe m)+structVMcompare comp comps va vb = case (va, vb) of+  (ADTVal nm1 vs1, ADTVal nm2 vs2) +    | nm1 == nm2 -> Just $ comps vs1 vs2+  (ADTVal _ _, _) -> Nothing+  (_, ADTVal _ _) -> Nothing+  (Ascii x, Ascii u) | x == u -> Just (Just mempty)+  (Ascii _, _)                -> Nothing+  (_, Ascii _)                -> Nothing+  (Atom x, Atom y) | x == y   -> Just (Just mempty)+  (Atom _, _)                 -> Nothing+  (_, Atom _)                 -> Nothing+  (Bit x, Bit y)  | x == y    -> Just (Just mempty)+  (_, Bit _)                  -> Nothing+  (Bit _, _)                  -> Nothing+  (Char x, Char y) | x == y   -> Just (Just mempty)+  (Char _, _)                 -> Nothing+  (_, Char _)                 -> Nothing+  (ComputationType x+    ,ComputationType y)       -> structCTMcompare comp comps x y +  (_, ComputationType x)      -> Nothing+  (ComputationType _, _)      -> Nothing+  (Float x, Float y) | x == y -> Just (Just mempty)+  (Float _, _)                -> Nothing+  (_, Float _)                -> Nothing+  (IEEE_Float_32 x, IEEE_Float_32 y) | x == y -> Nothing+  (IEEE_Float_32 _, _)                        -> Nothing+  (_, IEEE_Float_32 _)                        -> Nothing+  (IEEE_Float_64 x, IEEE_Float_64 y) | x == y -> Nothing+  (IEEE_Float_64 _, _)                        -> Nothing+  (_, IEEE_Float_64 _)                        -> Nothing+  (Int x, Int y) | x == y                     -> Just (Just mempty)+  (Int _, _)                                  -> Nothing+  (_, Int _)                                  -> Nothing+  (Map m1, Map m2) -> Just $ liftM2 mappend (comps (map inject (M.keys m1)) +                                                   (map inject (M.keys m2)))+                                            (comps (map inject (M.elems m1)) +                                                   (map inject (M.elems m2)))+  (Map _, _)      -> Nothing+  (_, Map _)      -> Nothing+  (Set x, Set y) -> Just $ comps (map inject $ S.toList x) (map inject $ S.toList y)  +  (Set _, _)      -> Nothing+  (_, Set _)      -> Nothing+  (Multiset x, Multiset y) -> Just $ comps (map inject $ MS.toList x) +                                           (map inject $ MS.toList y)+  (Multiset _, _)           -> Nothing+  (_, Multiset _)           -> Nothing+  (Nat x, Nat y)  | x == y  -> Just (Just mempty)+  (Nat _, _)                -> Nothing+  (_, Nat _)                -> Nothing+  (Rational x, Rational y) | x == y -> Just (Just mempty)+  (Rational _, _)                   -> Nothing+  (_, Rational _)                   -> Nothing+  (Vector x, Vector y) -> Just $ comps (map inject $ V.toList x) (map inject $ V.toList y)+  (VAny, VAny)  -> Just (Just mempty)+  (_, VAny)     -> Nothing+  (VAny, _)     -> Nothing+  (VMeta ts, VMeta ts') -> structTSMcompare comp comps ts ts' +  (VMeta _, _)  -> Nothing+  (_, VMeta _)  -> Nothing++structTSMcompare comp comps ts ts' = case (ts,ts') of+  (TagName nm vs, TagName nm' vs') | nm == nm' -> +    Just $ comps (map inject vs) (map inject vs')  +  (TagName _ _, _) -> Nothing+  (_, TagName _ _) -> Nothing+  (TagType ty v, TagType ty' v') -> +    liftM2 (liftM2 mappend) (structTMcompare comp comps ty ty')+                            (structVMcompare comp comps v v')++structTMcompare :: (Monoid m, HasValues a, HasValues b) => +  (a -> b -> Maybe m) -> ([a] -> [b] -> Maybe m) -> +    Types a -> Types b -> Maybe (Maybe m)+structTMcompare comp comps ta tb = case (ta, tb) of+  (ADTs, ADTs)                        -> Just (Just mempty)+  (ADTs, _)                           -> Nothing+  (_, ADTs)                           -> Nothing+  (ADT nm1 ts, ADT nm2 ts') | nm1 == nm2 -> Just $ comps ts ts'+  (ADT _ _, _)                        -> Nothing+  (_, ADT _ _)                        -> Nothing+  (Atoms, Atoms)                      -> Just (Just mempty)+  (Atoms, _)                          -> Nothing+  (_, Atoms)                          -> Nothing+  (AsciiCharacters, AsciiCharacters)  -> Just (Just mempty) +  (AsciiCharacters, _)                -> Nothing+  (_, AsciiCharacters)                -> Nothing+  (ASTs, ASTs)                        -> Just (Just mempty)+  (_, ASTs)                           -> Nothing+  (ASTs, _)                           -> Nothing+  (AnnotatedType t1 op1, AnnotatedType t2 op2) | op1 == op2 -> structTMcompare comp comps t1 t2+  (AnnotatedType _ _, _)              -> Nothing+  (_, AnnotatedType _ _)              -> Nothing+  (Bits x, Bits y)  | x == y          -> Just (Just mempty)+  (Bits _, _)                         -> Nothing+  (_, Bits _)                         -> Nothing+  (Characters, Characters)            -> Just (Just mempty)+  (Characters, _)                     -> Nothing+  (_, Characters)                     -> Nothing+  (Complement x, Complement y)        -> structTMcompare comp comps x y+  (_, Complement _)                   -> Nothing+  (Complement _, _)                   -> Nothing+  (ComputationTypes, ComputationTypes)-> Just (Just mempty)+  (_, ComputationTypes)               -> Nothing+  (ComputationTypes, _)               -> Nothing+  (DefinedValues, DefinedValues)      -> Just (Just mempty)+  (_, DefinedValues)                  -> Nothing+  (DefinedValues, _)                  -> Nothing+  (GroundValues, GroundValues)        -> Just (Just mempty)+  (GroundValues, _)                   -> Nothing+  (_, GroundValues)                   -> Nothing+  (IntegersFrom mx, IntegersFrom mx') | mx == mx' -> Just (Just mempty)+  (IntegersFrom _, _)                 -> Nothing+  (_, IntegersFrom _)                 -> Nothing+  (IntegersUpTo mx, IntegersUpTo mx') | mx == mx' -> Just (Just mempty)+  (IntegersUpTo _, _)                   -> Nothing+  (_, IntegersUpTo _)                   -> Nothing+  (EmptyType, EmptyType)              -> Just (Just mempty)+  (_, EmptyType)                      -> Nothing+  (EmptyType, _)                      -> Nothing+  (IEEEFloats x, IEEEFloats y) | x ==y-> Just (Just mempty)+  (IEEEFloats _, _)                   -> Nothing+  (_, IEEEFloats _)                   -> Nothing+  (Maps k v, Maps k' v')              -> liftM2 mappend (structTMcompare comp comps k k') (structTMcompare comp comps v v')+  (Maps _ _, _)                       -> Nothing+  (_, Maps _ _)                       -> Nothing+  (Integers, Integers)                -> Just (Just mempty)+  (Integers, _)                       -> Nothing+  (_, Integers)                       -> Nothing+  (Intersection x y, Intersection x' y') -> liftM2 mappend (structTMcompare comp comps x x') (structTMcompare comp comps y y')+  (Intersection _ _, _)               -> Nothing+  (_, Intersection _ _)               -> Nothing+  (Multisets x, Multisets y)          -> structTMcompare comp comps x y+  (Multisets _, _)                    -> Nothing+  (_, Multisets _)                    -> Nothing+  (Naturals, Naturals)                -> Just (Just mempty)+  (_, Naturals)                       -> Nothing+  (Naturals, _)                       -> Nothing+  (Nothings, Nothings)                -> Just (Just mempty)+  (_, Nothings)                       -> Nothing+  (Nothings,_)                        -> Nothing+  (Rationals, Rationals)              -> Just (Just mempty)+  (Rationals, _)                      -> Nothing+  (_, Rationals)                      -> Nothing+  (Strings, Strings)                  -> Just (Just mempty) +  (_, Strings)                        -> Nothing+  (Strings, _)                        -> Nothing+  (Sets x, Sets y)                    -> structTMcompare comp comps x y+  (Sets _, _)                         -> Nothing+  (_, Sets _)                         -> Nothing+  (Types, Types)                      -> Just (Just mempty)+  (_, Types)                          -> Nothing+  (Types, _)                          -> Nothing+  (UnicodeCharacters, UnicodeCharacters)  -> Just (Just mempty)+  (UnicodeCharacters, _)                  -> Nothing+  (_, UnicodeCharacters)                  -> Nothing+  (Union u v, Union x y)                  -> liftM2 mappend (structTMcompare comp comps u x) (structTMcompare comp comps v y)+  (Union _ _, _)                          -> Nothing+  (_, Union _ _)                          -> Nothing+  (Values, Values)                        -> Just (Just mempty)+  (_, Values)                             -> Nothing+  (Values, _)                             -> Nothing+  (Vectors x, Vectors y)                  -> structTMcompare comp comps x y++instance Functor Types where+  fmap f t = case t of +    ADT nm ts           -> ADT nm (map f ts) +    ADTs                -> ADTs+    AsciiCharacters     -> AsciiCharacters+    Atoms               -> Atoms+    AnnotatedType ty op -> AnnotatedType (fmap f ty) op+    ASTs                -> ASTs+    Bits n              -> Bits n+    Complement t1       -> Complement (fmap f t1)+    ComputationTypes    -> ComputationTypes+    DefinedValues       -> DefinedValues  +    GroundValues        -> GroundValues+    IntegersFrom p      -> IntegersFrom p+    IntegersUpTo p      -> IntegersUpTo p+    Characters          -> Characters   +    EmptyType           -> EmptyType+    IEEEFloats b        -> IEEEFloats b+    Integers            -> Integers+    Intersection t1 t2  -> Intersection (fmap f t1) (fmap f t2)+    Maps k v            -> Maps (fmap f k) (fmap f v) +    Multisets t         -> Multisets (fmap f t)+    Naturals            -> Naturals+    Nothings            -> Nothings+    Rationals           -> Rationals+    Sets t              -> Sets (fmap f t)+    Strings             -> Strings+    Types               -> Types+    UnicodeCharacters   -> UnicodeCharacters+    Union t1 t2         -> Union (fmap f t1) (fmap f t2)+    Values              -> Values +    Vectors t           -> Vectors (fmap f t)++instance Functor ComputationTypes where+  fmap f t = case t of+    Type t -> Type $ fmap f t+    ComputesType t -> ComputesType $ fmap f t+    ComputesFromType t1 t2 -> ComputesFromType (fmap f t1) (fmap f t2)++instance Foldable Types where+  foldMap f fa = case fa of +    ADT _ ts            -> foldMap f ts+    ADTs                -> mempty+    AsciiCharacters     -> mempty+    Atoms               -> mempty+    ASTs                -> mempty+    AnnotatedType ty op -> foldMap f ty+    Bits _              -> mempty+    Characters          -> mempty+    Complement t1       -> foldMap f t1+    ComputationTypes    -> mempty+    DefinedValues       -> mempty+    GroundValues        -> mempty+    IntegersUpTo q      -> mempty+    IntegersFrom q      -> mempty+    Intersection t1 t2  -> foldMap f t1 `mappend` foldMap f t2+    EmptyType           -> mempty+    IEEEFloats b        -> mempty +    Integers            -> mempty+    Maps k v            -> foldMap f k `mappend` foldMap f v+    Multisets t         -> foldMap f t+    Naturals            -> mempty +    Nothings            -> mempty+    Rationals           -> mempty+    Sets t              -> foldMap f t+    Strings             -> mempty+    Types               -> mempty +    UnicodeCharacters   -> mempty +    Union t1 t2         -> foldMap f t1 `mappend` foldMap f t2+    Values              -> mempty +    Vectors t           -> foldMap f t++instance Traversable Types where+  traverse f ta = case ta of +    ADTs                -> pure ADTs+    ADT nm ts           -> ADT nm <$> traverse f ts+    AsciiCharacters     -> pure AsciiCharacters+    AnnotatedType ty op -> AnnotatedType <$> traverse f ty <*> pure op+    Atoms               -> pure Atoms+    ASTs                -> pure ASTs+    Bits n              -> pure $ Bits n+    Characters          -> pure Characters+    Complement t        -> Complement <$> traverse f t+    ComputationTypes    -> pure ComputationTypes+    DefinedValues       -> pure DefinedValues+    GroundValues        -> pure GroundValues +    IntegersFrom n      -> pure $ IntegersFrom n+    IntegersUpTo n        -> pure $ IntegersUpTo n+    EmptyType           -> pure EmptyType+    IEEEFloats b        -> pure $ IEEEFloats b+    Integers            -> pure Integers+    Intersection t1 t2  -> Intersection <$> traverse f t1 <*> traverse f t2+    Maps k v            -> Maps <$> traverse f k <*> traverse f v+    Multisets t         -> Multisets <$> traverse f t+    Naturals            -> pure Naturals+    Nothings            -> pure Nothings+    Rationals           -> pure Rationals+    Sets t              -> Sets <$> traverse f t+    Strings             -> pure Strings+    Types               -> pure Types+    UnicodeCharacters   -> pure UnicodeCharacters+    Union t1 t2         -> Union <$> traverse f t1 <*> traverse f t2+    Values              -> pure Values +    Vectors t           -> Vectors <$> traverse f t++downcastValueType :: Values t -> Types t+downcastValueType (ComputationType (Type t)) = t+downcastValueType (ComputationType (ComputesType t)) = t+downcastValueType (ComputationType (ComputesFromType _ t)) = t+downcastValueType _ = error "valueType: not a type"++-- | Returns the /rational/ representation of a value if it is a subtype.+-- Otherwise it returns the original value.+upcastRationals :: Values t -> Values t+upcastRationals (Nat n) = Rational (toRational n)+upcastRationals (Int i) = Rational (toRational i)+upcastRationals v       = v++-- | Returns the /integer/ representation of a value if it is a subtype.+-- Otherwise it returns the original value.+upcastIntegers :: Values t -> Values t+upcastIntegers (Nat n)  = Int n+upcastIntegers v        = v++-- | Returns the /natural/ representation of a value if it is a subtype.+-- Otherwise it returns the original value.+upcastNaturals :: Values t -> Values t+upcastNaturals (Int i) | i >= 0 = Nat i+upcastNaturals v = v++-- | Returns the /unicode/ representation of an assci value.+-- Otherwise it returns the original value.+upcastUnicode :: Values t -> Values t+upcastUnicode (Ascii c) = Char c+upcastUnicode v = v++castType :: HasValues t => Values t -> Maybe (Types t)+castType (ComputationType (Type ty)) = Just ty+castType (ComputationType (ComputesType ty)) = Just ty+castType (ComputationType (ComputesFromType _ ty)) = Just ty+castType _            = Nothing++-- numbers+mk_integers :: Integer -> Values t+mk_integers i   | i >= 0    = mk_naturals i+                | otherwise = Int i++mk_naturals :: Integer -> Values t+mk_naturals = Nat++mk_unicode_characters :: Char -> Values t+mk_unicode_characters c  | C.isAscii c = mk_ascii_characters c+                         | otherwise   = Char c++-- TODO: haven't included `basic-characters` in the subtyping heirarchy yet.++mk_ascii_characters :: Char -> Values t+mk_ascii_characters = Ascii++--- Value specific++(===) :: (HasValues t, Eq t {- UNNECESSARY CONSTRAINT -}) => Values t -> Values t -> Bool+v1 === v2 = isGround v1 && isGround v2 && (v1 == v2)++(=/=) :: (HasValues t, Eq t {- UNNECESSARY CONSTRAINT -}) => Values t -> Values t -> Bool+v1 =/= v2 = isGround v1 && isGround v2 && (v1 /= v2)++isGround :: HasValues t => Values t -> Bool+isGround (ADTVal _ mv)            = all (maybe False isGround . project) mv+isGround (Ascii _)                = True+isGround (Atom _)                 = True+isGround (Bit _)                  = True+isGround (Char _)                 = True+isGround (Float _)                = True+isGround (IEEE_Float_32 _)        = True+isGround (IEEE_Float_64 _)        = True+isGround (Int _)                  = True+isGround (Map m)                  = all isGround (M.elems m)+isGround (Multiset ms)            = all isGround (MS.elems ms)+isGround (Nat _)                  = True+isGround (ComputationType _)      = True+isGround (Rational _)             = True+isGround (Set s)                  = all isGround (S.toList s)+isGround (Vector v)               = all isGround (V.toList v)+isGround (VMeta _)                = True+isGround VAny                     = False++-- functions that check simple properties of funcons+-- TODO: Some of these are used, and all are exported by Funcons.EDSL+--       But are all of them still needed.  E.g isId doesn't seem very useful now that ids are just strings.+isAscii ((Ascii _))                 = True+isAscii _                           = False+isChar ((Char _))                   = True+isChar _                            = False+isNat ((Int _))                     = True+isNat _                             = False+isInt ((Int _))                     = True+isInt _                             = False+isEnv f                             = isMap f+isMap ((Map _))                     = True+isMap _                             = False+isSet ((Set _))                     = True+isSet _                             = False+isString_ :: HasValues t => Values t -> Bool+isString_ (ADTVal "list" vs)        = not (null vs) && all (maybe False isAscii) (map project vs)+isString_ _                         = False+isType (ComputationType _)          = True+isType _                            = False+isVec ((Vector _))                  = True+isVec _                             = False++unString :: HasValues t => Values t -> String+unString (ADTVal "list" vs) +  | Just vs' <- sequence (map project vs), all isAscii vs' = map (\(Ascii c) -> c) vs'+unString _ = error "unString"++none__ :: Values t+none__ = ADTVal "none" []++isNoValue :: Values t -> Bool+isNoValue (ADTVal "none" _) = True+isNoValue _ = False++isDefinedVal :: Values t -> Bool+isDefinedVal f = not (isNoValue f)++set_ :: Ord t => [Values t] -> Values t+set_ = Set . S.fromList ++ppValues :: HasValues t => (t -> String) -> Values t -> String+ppValues showT v@(ADTVal "list" vs)+  | isString_ v = show (unString v)+  | otherwise   = "[" ++ showArgs_ (map showT vs) ++ "]"+ppValues showT (ADTVal c []) = unpack c+ppValues showT (ADTVal c vs) = unpack c ++ showArgs (map showT vs)+ppValues showT (Atom c)       = "atom("++ c ++")"+ppValues showT (Ascii c)      = "`" ++ [c] ++ "`"+ppValues showT (Bit i)        = "bits(" ++ show (BV.size i)+                                            ++ ", " ++ show (BV.int i) ++ ")"+ppValues showT (Char c)       = show c+ppValues showT (Float f)      = show f+-- rationals+ppValues showT (IEEE_Float_32 f) = show f+ppValues showT (IEEE_Float_64 d) = show d+ppValues showT (Rational r)   = show r+ppValues showT (Int f)        = show f+ppValues showT (Nat f)        = show f+ppValues showT (Map m)        = if M.null m then "map-empty"+                               else "{" ++ key_values ++ "}"+ where key_values = intercalate ", " (map (\(k,v) -> ppValues showT k++" |-> "++ +                                                     ppValues showT v)$ M.toList m)+ppValues showT (Multiset s) = "{" ++ showArgs (map (ppValues showT) (MS.toList s)) ++ "}"+ppValues showT (Set s) =  "{" ++ showArgs (map (ppValues showT) (S.toList s)) ++ "}"+ppValues showT (Vector v) =  "vector" ++ showArgs (map (ppValues showT) (V.toList v))+ppValues showT (ComputationType ty) = ppComputationTypes showT ty+ppValues showT VAny = "_"+ppValues showT (VMeta ts) = ppTaggedSyntax showT ts++ppTaggedSyntax :: HasValues t => (t -> String) -> TaggedSyntax t -> String+ppTaggedSyntax showT (TagName nm vs) = "astv" ++ showArgs (unpack nm : map (ppValues showT) vs)+ppTaggedSyntax showT (TagType ty val) = "astv" ++ showArgs [ppTypes showT ty, ppValues showT val]++ppComputationTypes :: HasValues t => (t -> String) -> ComputationTypes t -> String+ppComputationTypes showT (Type t) = ppTypes showT t+ppComputationTypes showT (ComputesType ty) = "=>" ++ ppTypes showT ty+ppComputationTypes showT (ComputesFromType s t) = ppTypes showT s ++ "=>" ++ ppTypes showT t++ppTypes :: HasValues t => (t -> String) -> Types t -> String+ppTypes showT (AnnotatedType ty op)  = ppTypes showT ty ++ ppOp op+ppTypes showT (Complement ty)        = "~(" ++ ppTypes showT ty ++ ")"+ppTypes showT ComputationTypes       = "computation-types"+ppTypes showT GroundValues           = "ground-values"+ppTypes showT Nothings               = "nothing"+ppTypes showT DefinedValues          = "defined-values"+ppTypes showT ASTs                   = "asts"+ppTypes showT Atoms                  = "atoms"+ppTypes showT AsciiCharacters        = "ascii-characters"+ppTypes showT Characters             = "characters"+ppTypes showT (Intersection t1 t2)   = "(" ++ ppTypes showT t1 ++ "^" ++ ppTypes showT t2 ++")"+ppTypes showT (IntegersFrom n)       = "integers-from(" ++ show n ++ ")"+ppTypes showT (IntegersUpTo n)       = "integers-to(" ++ show n ++ ")"+ppTypes showT EmptyType              = "empty-type"+ppTypes showT (UnicodeCharacters)    = "unicode-characters"+ppTypes showT (Integers)             = "integers"+ppTypes showT (Strings)              = "strings"+ppTypes showT (Values)               = "values"+ppTypes showT (Maps x y)             = "maps" ++ showArgs [ppTypes showT x, ppTypes showT y]+ppTypes showT Types                  = "types"+ppTypes showT ADTs                   = "algebraic-datatypes"+ppTypes showT (ADT nm ts)            = unpack nm ++ showArgs (map showT ts)+ppTypes showT (Bits n)               = "bits(" ++ show n ++ ")"+ppTypes showT (IEEEFloats format)    = "ieee-floats(" ++ show format ++ ")"+ppTypes showT (Multisets ty)         = "multisets" ++ showArgs [ppTypes showT ty]+ppTypes showT Naturals               = "naturals"+ppTypes showT Rationals              = "rationals"+ppTypes showT (Sets ty)              = "sets(" ++ ppTypes showT ty ++ ")"+ppTypes showT (Vectors ty)           = "vectors(" ++ ppTypes showT ty ++ ")"+ppTypes showT (Union ty1 ty2)        = "(" ++ ppTypes showT ty1 ++ "|" ++ ppTypes showT ty2 ++")"++ppOp :: SeqSortOp -> String+ppOp StarOp = "*"+ppOp PlusOp = "+"+ppOp QuestionMarkOp = "?"++showArgs :: [String] -> String+showArgs args = "(" ++ showArgs_ args ++ ")"+showArgs_ :: [String] -> String+showArgs_ args = intercalate "," args +