mirror of
https://github.com/github/semantic.git
synced 2024-12-19 12:51:52 +03:00
Merge branch 'master' into quiet-analysis
This commit is contained in:
commit
41f2cdd6a9
@ -1,23 +1,23 @@
|
|||||||
{-# LANGUAGE DataKinds, GeneralizedNewtypeDeriving, MultiParamTypeClasses, Rank2Types, StandaloneDeriving, TypeFamilies, UndecidableInstances #-}
|
{-# LANGUAGE DataKinds, GeneralizedNewtypeDeriving, MultiParamTypeClasses, Rank2Types, StandaloneDeriving, TypeFamilies, UndecidableInstances #-}
|
||||||
module Analysis.Abstract.Evaluating
|
module Analysis.Abstract.Evaluating
|
||||||
( type Evaluating
|
( Evaluating
|
||||||
, findValue
|
, findValue
|
||||||
, findEnv
|
, findEnv
|
||||||
, findHeap
|
, findHeap
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Abstract.Analysis
|
import Control.Abstract.Analysis
|
||||||
import Control.Monad.Effect
|
import Control.Monad.Effect
|
||||||
import Data.Abstract.Configuration
|
import Data.Abstract.Configuration
|
||||||
import qualified Data.Abstract.Environment as Env
|
import qualified Data.Abstract.Environment as Env
|
||||||
import Data.Abstract.Evaluatable
|
import Data.Abstract.Evaluatable
|
||||||
import Data.Abstract.Heap
|
import Data.Abstract.Heap
|
||||||
import Data.Abstract.Module
|
import Data.Abstract.Module
|
||||||
import Data.Abstract.ModuleTable
|
import Data.Abstract.ModuleTable
|
||||||
import qualified Data.IntMap as IntMap
|
import qualified Data.IntMap as IntMap
|
||||||
import qualified Data.Map.Monoidal as Monoidal
|
import qualified Data.Map.Monoidal as Monoidal
|
||||||
import Prelude hiding (fail)
|
import Prelude hiding (fail)
|
||||||
import Prologue
|
import Prologue
|
||||||
|
|
||||||
-- | An analysis evaluating @term@s to @value@s with a list of @effects@ using 'Evaluatable', and producing incremental results of type @a@.
|
-- | An analysis evaluating @term@s to @value@s with a list of @effects@ using 'Evaluatable', and producing incremental results of type @a@.
|
||||||
newtype Evaluating term value effects a = Evaluating (Eff effects a)
|
newtype Evaluating term value effects a = Evaluating (Eff effects a)
|
||||||
|
@ -1,29 +1,29 @@
|
|||||||
{-# LANGUAGE ConstrainedClassMethods, DataKinds, FunctionalDependencies, RankNTypes, ScopedTypeVariables, TypeFamilies, TypeOperators, UndecidableInstances #-}
|
{-# LANGUAGE ConstrainedClassMethods, DataKinds, FunctionalDependencies, RankNTypes, ScopedTypeVariables, TypeFamilies, TypeOperators, UndecidableInstances #-}
|
||||||
module Control.Abstract.Evaluator
|
module Control.Abstract.Evaluator
|
||||||
( MonadEvaluator(..)
|
( MonadEvaluator(..)
|
||||||
, MonadEnvironment(..)
|
, MonadEnvironment(..)
|
||||||
, modifyEnv
|
, modifyEnv
|
||||||
, modifyExports
|
, modifyExports
|
||||||
, addExport
|
, addExport
|
||||||
, fullEnvironment
|
, fullEnvironment
|
||||||
, MonadHeap(..)
|
, MonadHeap(..)
|
||||||
, modifyHeap
|
, modifyHeap
|
||||||
, localize
|
, localize
|
||||||
, lookupHeap
|
, lookupHeap
|
||||||
, assign
|
, assign
|
||||||
, MonadModuleTable(..)
|
, MonadModuleTable(..)
|
||||||
, modifyModuleTable
|
, modifyModuleTable
|
||||||
, MonadControl(..)
|
, MonadControl(..)
|
||||||
, MonadThrow(..)
|
, MonadThrow(..)
|
||||||
, resumeException
|
-- Type synonyms specialized for location types
|
||||||
, EnvironmentFor
|
, CellFor
|
||||||
, ExportsFor
|
, ConfigurationFor
|
||||||
, HeapFor
|
, EnvironmentFor
|
||||||
, CellFor
|
, ExportsFor
|
||||||
, LiveFor
|
, HeapFor
|
||||||
, LocationFor
|
, LiveFor
|
||||||
, ConfigurationFor
|
, LocationFor
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Effect
|
import Control.Effect
|
||||||
import Control.Monad.Effect.Resumable
|
import Control.Monad.Effect.Resumable
|
||||||
@ -170,7 +170,7 @@ modifyModuleTable f = do
|
|||||||
|
|
||||||
|
|
||||||
-- | A 'Monad' abstracting jumps in imperative control.
|
-- | A 'Monad' abstracting jumps in imperative control.
|
||||||
class Monad m => MonadControl term m | m -> term where
|
class Monad m => MonadControl term m where
|
||||||
-- | Allocate a 'Label' for the given @term@.
|
-- | Allocate a 'Label' for the given @term@.
|
||||||
--
|
--
|
||||||
-- Labels must be allocated before being jumped to with 'goto', but are suitable for nonlocal jumps; thus, they can be used to implement coroutines, exception handling, call with current continuation, and other esoteric control mechanisms.
|
-- Labels must be allocated before being jumped to with 'goto', but are suitable for nonlocal jumps; thus, they can be used to implement coroutines, exception handling, call with current continuation, and other esoteric control mechanisms.
|
||||||
@ -179,33 +179,31 @@ class Monad m => MonadControl term m | m -> term where
|
|||||||
goto :: Label -> m term
|
goto :: Label -> m term
|
||||||
|
|
||||||
|
|
||||||
|
-- | 'Monad's which can throw exceptions of type @exc v@ which can be resumed with a value of type @v@.
|
||||||
class Monad m => MonadThrow exc m where
|
class Monad m => MonadThrow exc m where
|
||||||
throwException :: exc v -> m v
|
throwException :: exc v -> m v
|
||||||
|
|
||||||
instance (Monad (m effects), Effectful m, Members '[Resumable exc] effects) => MonadThrow exc (m effects) where
|
instance (Effectful m, Members '[Resumable exc] effects, Monad (m effects)) => MonadThrow exc (m effects) where
|
||||||
throwException = raise . throwError
|
throwException = raise . throwError
|
||||||
|
|
||||||
resumeException :: forall exc m e a. (Effectful m, Resumable exc :< e) => m e a -> (forall v. (v -> m e a) -> exc v -> m e a) -> m e a
|
|
||||||
resumeException m handle = raise (resumeError (lower m) (\yield -> lower . handle (raise . yield)))
|
|
||||||
|
|
||||||
|
|
||||||
-- | The environment for an abstract value type.
|
|
||||||
type EnvironmentFor v = Env.Environment (LocationFor v) v
|
|
||||||
|
|
||||||
-- | The exports for an abstract value type.
|
|
||||||
type ExportsFor v = Export.Exports (LocationFor v) v
|
|
||||||
|
|
||||||
-- | The 'Heap' for an abstract value type.
|
|
||||||
type HeapFor value = Heap (LocationFor value) value
|
|
||||||
|
|
||||||
-- | The cell for an abstract value type.
|
-- | The cell for an abstract value type.
|
||||||
type CellFor value = Cell (LocationFor value) value
|
type CellFor value = Cell (LocationFor value) value
|
||||||
|
|
||||||
-- | The address set type for an abstract value type.
|
|
||||||
type LiveFor value = Live (LocationFor value) value
|
|
||||||
|
|
||||||
-- | The configuration for term and abstract value types.
|
-- | The configuration for term and abstract value types.
|
||||||
type ConfigurationFor term value = Configuration (LocationFor value) term value
|
type ConfigurationFor term value = Configuration (LocationFor value) term value
|
||||||
|
|
||||||
|
-- | The environment for an abstract value type.
|
||||||
|
type EnvironmentFor value = Env.Environment (LocationFor value) value
|
||||||
|
|
||||||
|
-- | The exports for an abstract value type.
|
||||||
|
type ExportsFor value = Export.Exports (LocationFor value) value
|
||||||
|
|
||||||
|
-- | The 'Heap' for an abstract value type.
|
||||||
|
type HeapFor value = Heap (LocationFor value) value
|
||||||
|
|
||||||
|
-- | The address set type for an abstract value type.
|
||||||
|
type LiveFor value = Live (LocationFor value) value
|
||||||
|
|
||||||
-- | The location type (the body of 'Address'es) which should be used for an abstract value type.
|
-- | The location type (the body of 'Address'es) which should be used for an abstract value type.
|
||||||
type family LocationFor value :: *
|
type family LocationFor value :: *
|
||||||
|
@ -105,6 +105,9 @@ class (Monad m, Show value) => MonadValue value m where
|
|||||||
-- | Eliminate boolean values. TODO: s/boolean/truthy
|
-- | Eliminate boolean values. TODO: s/boolean/truthy
|
||||||
ifthenelse :: value -> m a -> m a -> m a
|
ifthenelse :: value -> m a -> m a -> m a
|
||||||
|
|
||||||
|
-- | Construct the nil/null datatype.
|
||||||
|
null :: m value
|
||||||
|
|
||||||
-- | Build a class value from a name and environment.
|
-- | Build a class value from a name and environment.
|
||||||
klass :: Name -- ^ The new class's identifier
|
klass :: Name -- ^ The new class's identifier
|
||||||
-> [value] -- ^ A list of superclasses
|
-> [value] -- ^ A list of superclasses
|
||||||
@ -170,14 +173,15 @@ class ValueRoots value where
|
|||||||
valueRoots :: value -> LiveFor value
|
valueRoots :: value -> LiveFor value
|
||||||
|
|
||||||
|
|
||||||
|
-- The type of exceptions that can be thrown when constructing values in `MonadValue`.
|
||||||
data ValueExc value resume where
|
data ValueExc value resume where
|
||||||
ValueExc :: Prelude.String -> ValueExc value value
|
ValueExc :: Prelude.String -> ValueExc value value
|
||||||
StringExc :: Prelude.String -> ValueExc value ByteString
|
StringExc :: Prelude.String -> ValueExc value ByteString
|
||||||
|
|
||||||
instance Eq1 (ValueExc value) where
|
instance Eq1 (ValueExc value) where
|
||||||
liftEq _ (ValueExc a) (ValueExc b) = a == b
|
liftEq _ (ValueExc a) (ValueExc b) = a == b
|
||||||
liftEq _ (StringExc a) (StringExc b) = a == b
|
liftEq _ (StringExc a) (StringExc b) = a == b
|
||||||
liftEq _ _ _ = False
|
liftEq _ _ _ = False
|
||||||
|
|
||||||
deriving instance Show (ValueExc value resume)
|
deriving instance Show (ValueExc value resume)
|
||||||
instance Show1 (ValueExc value) where
|
instance Show1 (ValueExc value) where
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{-# LANGUAGE TypeFamilies, TypeOperators, UndecidableInstances, ScopedTypeVariables #-}
|
{-# LANGUAGE RankNTypes, TypeFamilies, TypeOperators, UndecidableInstances #-}
|
||||||
module Control.Effect where
|
module Control.Effect where
|
||||||
|
|
||||||
import Control.Monad.Effect as Effect
|
import Control.Monad.Effect as Effect
|
||||||
@ -68,6 +68,13 @@ instance RunEffect (Resumable exc) a where
|
|||||||
type Result (Resumable exc) a = Either (SomeExc exc) a
|
type Result (Resumable exc) a = Either (SomeExc exc) a
|
||||||
runEffect = runError
|
runEffect = runError
|
||||||
|
|
||||||
|
resumeException :: (Resumable exc :< e, Effectful m) => m e a -> (forall v . (v -> m e a) -> exc v -> m e a) -> m e a
|
||||||
|
resumeException m handle = raise (resumeError (lower m) (\yield -> lower . handle (raise . yield)))
|
||||||
|
|
||||||
|
-- | Reassociate 'Either's, combining errors into 'Left' values and successes in a single level of 'Right'.
|
||||||
|
mergeEither :: Either a (Either b c) -> Either (Either a b) c
|
||||||
|
mergeEither = either (Left . Left) (either (Left . Right) Right)
|
||||||
|
|
||||||
|
|
||||||
-- | Types wrapping 'Eff' actions.
|
-- | Types wrapping 'Eff' actions.
|
||||||
--
|
--
|
||||||
|
@ -25,7 +25,7 @@ moduleForBlob :: Maybe FilePath -- ^ The root directory relative to which the mo
|
|||||||
moduleForBlob rootDir blob = Module (moduleNameForPath (modulePathForBlob blob)) (blobPath blob)
|
moduleForBlob rootDir blob = Module (moduleNameForPath (modulePathForBlob blob)) (blobPath blob)
|
||||||
where modulePathForBlob Blob{..} | Just Go <- blobLanguage = takeDirectory (modulePath blobPath)
|
where modulePathForBlob Blob{..} | Just Go <- blobLanguage = takeDirectory (modulePath blobPath)
|
||||||
| otherwise = modulePath blobPath
|
| otherwise = modulePath blobPath
|
||||||
-- TODO: Need a better way to handle module registration and resolution
|
-- TODO: Need a better way to handle module registration and resolution
|
||||||
modulePath = dropExtensions . maybe takeFileName makeRelative rootDir
|
modulePath = dropExtensions . maybe takeFileName makeRelative rootDir
|
||||||
|
|
||||||
moduleNameForPath :: FilePath -> ModuleName
|
moduleNameForPath :: FilePath -> ModuleName
|
||||||
|
@ -23,6 +23,7 @@ data Type
|
|||||||
| Array [Type] -- ^ Arrays. Note that this is heterogenous.
|
| Array [Type] -- ^ Arrays. Note that this is heterogenous.
|
||||||
| Hash [(Type, Type)] -- ^ Heterogenous key-value maps.
|
| Hash [(Type, Type)] -- ^ Heterogenous key-value maps.
|
||||||
| Object -- ^ Objects. Once we have some notion of inheritance we'll need to store a superclass.
|
| Object -- ^ Objects. Once we have some notion of inheritance we'll need to store a superclass.
|
||||||
|
| Null -- ^ The null type. Unlike 'Unit', this unifies with any other type.
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
-- TODO: À la carte representation of types.
|
-- TODO: À la carte representation of types.
|
||||||
@ -31,6 +32,8 @@ data Type
|
|||||||
-- | Unify two 'Type's.
|
-- | Unify two 'Type's.
|
||||||
unify :: MonadFail m => Type -> Type -> m Type
|
unify :: MonadFail m => Type -> Type -> m Type
|
||||||
unify (a1 :-> b1) (a2 :-> b2) = (:->) <$> unify a1 a2 <*> unify b1 b2
|
unify (a1 :-> b1) (a2 :-> b2) = (:->) <$> unify a1 a2 <*> unify b1 b2
|
||||||
|
unify a Null = pure a
|
||||||
|
unify Null b = pure b
|
||||||
-- FIXME: this should be constructing a substitution.
|
-- FIXME: this should be constructing a substitution.
|
||||||
unify (Var _) b = pure b
|
unify (Var _) b = pure b
|
||||||
unify a (Var _) = pure a
|
unify a (Var _) = pure a
|
||||||
@ -70,6 +73,8 @@ instance (Alternative m, MonadEnvironment Type m, MonadFail m, MonadFresh m, Mon
|
|||||||
hash = pure . Hash
|
hash = pure . Hash
|
||||||
kvPair k v = pure (Product [k, v])
|
kvPair k v = pure (Product [k, v])
|
||||||
|
|
||||||
|
null = pure Null
|
||||||
|
|
||||||
klass _ _ _ = pure Object
|
klass _ _ _ = pure Object
|
||||||
namespace _ _ = pure Unit
|
namespace _ _ = pure Unit
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ type ValueConstructors
|
|||||||
, Integer
|
, Integer
|
||||||
, KVPair
|
, KVPair
|
||||||
, Namespace
|
, Namespace
|
||||||
|
, Null
|
||||||
, Rational
|
, Rational
|
||||||
, String
|
, String
|
||||||
, Symbol
|
, Symbol
|
||||||
@ -175,6 +176,13 @@ instance Eq1 Hash where liftEq = genericLiftEq
|
|||||||
instance Ord1 Hash where liftCompare = genericLiftCompare
|
instance Ord1 Hash where liftCompare = genericLiftCompare
|
||||||
instance Show1 Hash where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 Hash where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
|
||||||
|
data Null value = Null
|
||||||
|
deriving (Eq, Generic1, Ord, Show)
|
||||||
|
|
||||||
|
instance Eq1 Null where liftEq = genericLiftEq
|
||||||
|
instance Ord1 Null where liftCompare = genericLiftCompare
|
||||||
|
instance Show1 Null where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
|
||||||
|
|
||||||
type instance LocationFor Value = Precise
|
type instance LocationFor Value = Precise
|
||||||
|
|
||||||
@ -199,6 +207,8 @@ instance (Monad m, MonadEvaluatable term Value m) => MonadValue Value m where
|
|||||||
|
|
||||||
kvPair k = pure . injValue . KVPair k
|
kvPair k = pure . injValue . KVPair k
|
||||||
|
|
||||||
|
null = pure . injValue $ Null
|
||||||
|
|
||||||
asPair k
|
asPair k
|
||||||
| Just (KVPair k v) <- prjValue k = pure (k, v)
|
| Just (KVPair k v) <- prjValue k = pure (k, v)
|
||||||
| otherwise = fail ("expected key-value pair, got " <> show k)
|
| otherwise = fail ("expected key-value pair, got " <> show k)
|
||||||
@ -239,15 +249,15 @@ instance (Monad m, MonadEvaluatable term Value m) => MonadValue Value m where
|
|||||||
| otherwise = fail ("Invalid operand to liftNumeric: " <> show arg)
|
| otherwise = fail ("Invalid operand to liftNumeric: " <> show arg)
|
||||||
|
|
||||||
liftNumeric2 f left right
|
liftNumeric2 f left right
|
||||||
| Just (Integer i, Integer j) <- prjPair pair = f i j & specialize
|
| Just (Integer i, Integer j) <- prjPair pair = f i j & specialize
|
||||||
| Just (Integer i, Rational j) <- prjPair pair = f i j & specialize
|
| Just (Integer i, Rational j) <- prjPair pair = f i j & specialize
|
||||||
| Just (Integer i, Float j) <- prjPair pair = f i j & specialize
|
| Just (Integer i, Float j) <- prjPair pair = f i j & specialize
|
||||||
| Just (Rational i, Integer j) <- prjPair pair = f i j & specialize
|
| Just (Rational i, Integer j) <- prjPair pair = f i j & specialize
|
||||||
| Just (Rational i, Rational j) <- prjPair pair = f i j & specialize
|
| Just (Rational i, Rational j) <- prjPair pair = f i j & specialize
|
||||||
| Just (Rational i, Float j) <- prjPair pair = f i j & specialize
|
| Just (Rational i, Float j) <- prjPair pair = f i j & specialize
|
||||||
| Just (Float i, Integer j) <- prjPair pair = f i j & specialize
|
| Just (Float i, Integer j) <- prjPair pair = f i j & specialize
|
||||||
| Just (Float i, Rational j) <- prjPair pair = f i j & specialize
|
| Just (Float i, Rational j) <- prjPair pair = f i j & specialize
|
||||||
| Just (Float i, Float j) <- prjPair pair = f i j & specialize
|
| Just (Float i, Float j) <- prjPair pair = f i j & specialize
|
||||||
| otherwise = fail ("Invalid operands to liftNumeric2: " <> show pair)
|
| otherwise = fail ("Invalid operands to liftNumeric2: " <> show pair)
|
||||||
where
|
where
|
||||||
-- Dispatch whatever's contained inside a 'Number.SomeNumber' to its appropriate 'MonadValue' ctor
|
-- Dispatch whatever's contained inside a 'Number.SomeNumber' to its appropriate 'MonadValue' ctor
|
||||||
@ -259,12 +269,12 @@ instance (Monad m, MonadEvaluatable term Value m) => MonadValue Value m where
|
|||||||
|
|
||||||
liftComparison comparator left right
|
liftComparison comparator left right
|
||||||
| Just (Integer (Number.Integer i), Integer (Number.Integer j)) <- prjPair pair = go i j
|
| Just (Integer (Number.Integer i), Integer (Number.Integer j)) <- prjPair pair = go i j
|
||||||
| Just (Integer (Number.Integer i), Float (Number.Decimal j)) <- prjPair pair = go (fromIntegral i) j
|
| Just (Integer (Number.Integer i), Float (Number.Decimal j)) <- prjPair pair = go (fromIntegral i) j
|
||||||
| Just (Float (Number.Decimal i), Integer (Number.Integer j)) <- prjPair pair = go i (fromIntegral j)
|
| Just (Float (Number.Decimal i), Integer (Number.Integer j)) <- prjPair pair = go i (fromIntegral j)
|
||||||
| Just (Float (Number.Decimal i), Float (Number.Decimal j)) <- prjPair pair = go i j
|
| Just (Float (Number.Decimal i), Float (Number.Decimal j)) <- prjPair pair = go i j
|
||||||
| Just (String i, String j) <- prjPair pair = go i j
|
| Just (String i, String j) <- prjPair pair = go i j
|
||||||
| Just (Boolean i, Boolean j) <- prjPair pair = go i j
|
| Just (Boolean i, Boolean j) <- prjPair pair = go i j
|
||||||
| Just (Unit, Unit) <- prjPair pair = boolean True
|
| Just (Unit, Unit) <- prjPair pair = boolean True
|
||||||
| otherwise = fail ("Type error: invalid arguments to liftComparison: " <> show pair)
|
| otherwise = fail ("Type error: invalid arguments to liftComparison: " <> show pair)
|
||||||
where
|
where
|
||||||
-- Explicit type signature is necessary here because we're passing all sorts of things
|
-- Explicit type signature is necessary here because we're passing all sorts of things
|
||||||
|
@ -283,7 +283,7 @@ instance Evaluatable QualifiedImport where
|
|||||||
where
|
where
|
||||||
moduleName = freeVariable (subterm from)
|
moduleName = freeVariable (subterm from)
|
||||||
renames importedEnv
|
renames importedEnv
|
||||||
| null xs = fmap prepend (Env.names importedEnv)
|
| Prologue.null xs = fmap prepend (Env.names importedEnv)
|
||||||
| otherwise = xs
|
| otherwise = xs
|
||||||
prefix = freeVariable (subterm alias)
|
prefix = freeVariable (subterm alias)
|
||||||
prepend n = (n, prefix <> n)
|
prepend n = (n, prefix <> n)
|
||||||
@ -306,7 +306,7 @@ instance Evaluatable Import where
|
|||||||
where
|
where
|
||||||
moduleName = freeVariable (subterm from)
|
moduleName = freeVariable (subterm from)
|
||||||
renamed importedEnv
|
renamed importedEnv
|
||||||
| null xs = importedEnv
|
| Prologue.null xs = importedEnv
|
||||||
| otherwise = Env.overwrite xs importedEnv
|
| otherwise = Env.overwrite xs importedEnv
|
||||||
|
|
||||||
-- | Side effect only imports (no symbols made available to the calling environment).
|
-- | Side effect only imports (no symbols made available to the calling environment).
|
||||||
|
@ -8,8 +8,8 @@ import qualified Data.ByteString.Char8 as B
|
|||||||
import Data.Monoid (Endo (..), appEndo)
|
import Data.Monoid (Endo (..), appEndo)
|
||||||
import Data.Scientific (Scientific)
|
import Data.Scientific (Scientific)
|
||||||
import Diffing.Algorithm
|
import Diffing.Algorithm
|
||||||
import Prelude hiding (Float, fail)
|
import Prelude hiding (Float, fail, null)
|
||||||
import Prologue hiding (Set, hash)
|
import Prologue hiding (Set, hash, null)
|
||||||
import Text.Read (readMaybe)
|
import Text.Read (readMaybe)
|
||||||
|
|
||||||
-- Boolean
|
-- Boolean
|
||||||
@ -169,9 +169,7 @@ instance Eq1 Null where liftEq = genericLiftEq
|
|||||||
instance Ord1 Null where liftCompare = genericLiftCompare
|
instance Ord1 Null where liftCompare = genericLiftCompare
|
||||||
instance Show1 Null where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 Null where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
|
||||||
-- TODO: Implement Eval instance for Null
|
instance Evaluatable Null where eval = const null
|
||||||
instance Evaluatable Null
|
|
||||||
|
|
||||||
|
|
||||||
newtype Symbol a = Symbol { symbolContent :: ByteString }
|
newtype Symbol a = Symbol { symbolContent :: ByteString }
|
||||||
deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Mergeable, Ord, Show, Traversable, FreeVariables1)
|
deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Mergeable, Ord, Show, Traversable, FreeVariables1)
|
||||||
|
Loading…
Reference in New Issue
Block a user