mirror of
https://github.com/github/semantic.git
synced 2024-12-22 06:11:49 +03:00
Merge remote-tracking branch 'origin/if-evaluation' into environment-scoping
This commit is contained in:
commit
d57c1e2d33
@ -33,7 +33,7 @@ library
|
|||||||
, Control.Abstract.Addressable
|
, Control.Abstract.Addressable
|
||||||
, Control.Abstract.Analysis
|
, Control.Abstract.Analysis
|
||||||
, Control.Abstract.Evaluator
|
, Control.Abstract.Evaluator
|
||||||
, Control.Abstract.Function
|
, Control.Abstract.Value
|
||||||
-- Control flow
|
-- Control flow
|
||||||
, Control.Effect
|
, Control.Effect
|
||||||
-- Effects used for program analysis
|
-- Effects used for program analysis
|
||||||
|
@ -29,13 +29,12 @@ type DeadCodeEffects t v
|
|||||||
|
|
||||||
-- | Run a dead code analysis of the given program.
|
-- | Run a dead code analysis of the given program.
|
||||||
evaluateDead :: forall term value
|
evaluateDead :: forall term value
|
||||||
. ( AbstractValue value
|
. ( Corecursive term
|
||||||
, Corecursive term
|
|
||||||
, Evaluatable (Base term)
|
, Evaluatable (Base term)
|
||||||
, Foldable (Base term)
|
, Foldable (Base term)
|
||||||
, FreeVariables term
|
, FreeVariables term
|
||||||
, MonadAddressable (LocationFor value) value (DeadCodeAnalysis term value)
|
, MonadAddressable (LocationFor value) value (DeadCodeAnalysis term value)
|
||||||
, MonadFunction term value (DeadCodeAnalysis term value)
|
, MonadValue term value (DeadCodeAnalysis term value)
|
||||||
, Ord (LocationFor value)
|
, Ord (LocationFor value)
|
||||||
, Ord term
|
, Ord term
|
||||||
, Recursive term
|
, Recursive term
|
||||||
@ -70,12 +69,11 @@ revive :: Ord t => t -> DeadCodeAnalysis t v ()
|
|||||||
revive t = DeadCodeAnalysis (Evaluator (modify (Dead . delete t . unDead)))
|
revive t = DeadCodeAnalysis (Evaluator (modify (Dead . delete t . unDead)))
|
||||||
|
|
||||||
|
|
||||||
instance ( AbstractValue v
|
instance ( Corecursive t
|
||||||
, Corecursive t
|
|
||||||
, Evaluatable (Base t)
|
, Evaluatable (Base t)
|
||||||
, FreeVariables t
|
, FreeVariables t
|
||||||
, MonadAddressable (LocationFor v) v (DeadCodeAnalysis t v)
|
, MonadAddressable (LocationFor v) v (DeadCodeAnalysis t v)
|
||||||
, MonadFunction t v (DeadCodeAnalysis t v)
|
, MonadValue t v (DeadCodeAnalysis t v)
|
||||||
, Ord t
|
, Ord t
|
||||||
, Recursive t
|
, Recursive t
|
||||||
, Semigroup (Cell (LocationFor v) v)
|
, Semigroup (Cell (LocationFor v) v)
|
||||||
|
@ -57,11 +57,10 @@ type EvaluationEffects t v
|
|||||||
|
|
||||||
-- | Evaluate a term to a value.
|
-- | Evaluate a term to a value.
|
||||||
evaluate :: forall v term
|
evaluate :: forall v term
|
||||||
. ( AbstractValue v
|
. ( Evaluatable (Base term)
|
||||||
, Evaluatable (Base term)
|
|
||||||
, FreeVariables term
|
, FreeVariables term
|
||||||
, MonadAddressable (LocationFor v) v (Evaluation term v)
|
, MonadAddressable (LocationFor v) v (Evaluation term v)
|
||||||
, MonadFunction term v (Evaluation term v)
|
, MonadValue term v (Evaluation term v)
|
||||||
, Ord (LocationFor v)
|
, Ord (LocationFor v)
|
||||||
, Recursive term
|
, Recursive term
|
||||||
, Semigroup (Cell (LocationFor v) v)
|
, Semigroup (Cell (LocationFor v) v)
|
||||||
@ -72,11 +71,10 @@ evaluate = run @(EvaluationEffects term v) . runEvaluator . runEvaluation . eval
|
|||||||
|
|
||||||
-- | Evaluate terms and an entry point to a value.
|
-- | Evaluate terms and an entry point to a value.
|
||||||
evaluates :: forall v term
|
evaluates :: forall v term
|
||||||
. ( AbstractValue v
|
. ( Evaluatable (Base term)
|
||||||
, Evaluatable (Base term)
|
|
||||||
, FreeVariables term
|
, FreeVariables term
|
||||||
, MonadAddressable (LocationFor v) v (Evaluation term v)
|
, MonadAddressable (LocationFor v) v (Evaluation term v)
|
||||||
, MonadFunction term v (Evaluation term v)
|
, MonadValue term v (Evaluation term v)
|
||||||
, Ord (LocationFor v)
|
, Ord (LocationFor v)
|
||||||
, Recursive term
|
, Recursive term
|
||||||
, Semigroup (Cell (LocationFor v) v)
|
, Semigroup (Cell (LocationFor v) v)
|
||||||
@ -101,11 +99,10 @@ newtype Evaluation term value a = Evaluation { runEvaluation :: Evaluator (Evalu
|
|||||||
|
|
||||||
deriving instance MonadEvaluator term value (Evaluation term value)
|
deriving instance MonadEvaluator term value (Evaluation term value)
|
||||||
|
|
||||||
instance ( AbstractValue v
|
instance ( Evaluatable (Base t)
|
||||||
, Evaluatable (Base t)
|
|
||||||
, FreeVariables t
|
, FreeVariables t
|
||||||
, MonadAddressable (LocationFor v) v (Evaluation t v)
|
, MonadAddressable (LocationFor v) v (Evaluation t v)
|
||||||
, MonadFunction t v (Evaluation t v)
|
, MonadValue t v (Evaluation t v)
|
||||||
, Recursive t
|
, Recursive t
|
||||||
, Semigroup (Cell (LocationFor v) v)
|
, Semigroup (Cell (LocationFor v) v)
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{-# LANGUAGE MultiParamTypeClasses, UndecidableInstances #-}
|
{-# LANGUAGE MultiParamTypeClasses, UndecidableInstances #-}
|
||||||
module Control.Abstract.Function where
|
module Control.Abstract.Value where
|
||||||
|
|
||||||
import Control.Abstract.Addressable
|
import Control.Abstract.Addressable
|
||||||
import Control.Abstract.Analysis
|
import Control.Abstract.Analysis
|
||||||
@ -8,20 +8,36 @@ import Control.Monad.Effect.Fresh
|
|||||||
import Data.Abstract.Address
|
import Data.Abstract.Address
|
||||||
import Data.Abstract.Environment
|
import Data.Abstract.Environment
|
||||||
import Data.Abstract.FreeVariables
|
import Data.Abstract.FreeVariables
|
||||||
import Data.Abstract.Value
|
import Data.Abstract.Value as Value
|
||||||
import Data.Abstract.Type
|
import Data.Abstract.Type as Type
|
||||||
import Prologue
|
import Prologue
|
||||||
import Prelude hiding (fail)
|
import Prelude hiding (fail)
|
||||||
|
|
||||||
-- | A 'Monad' abstracting the evaluation of (and under) binding constructs (functions, methods, etc).
|
-- | A 'Monad' abstracting the evaluation of (and under) binding constructs (functions, methods, etc).
|
||||||
--
|
--
|
||||||
-- This allows us to abstract the choice of whether to evaluate under binders for different value types.
|
-- This allows us to abstract the choice of whether to evaluate under binders for different value types.
|
||||||
class MonadEvaluator t v m => MonadFunction t v m where
|
class (MonadEvaluator t v m) => MonadValue t v m where
|
||||||
|
-- | Construct an abstract unit value.
|
||||||
|
unit :: m v
|
||||||
|
|
||||||
|
-- | Construct an abstract integral value.
|
||||||
|
integer :: Prelude.Integer -> m v
|
||||||
|
|
||||||
|
-- | Construct an abstract boolean value.
|
||||||
|
boolean :: Bool -> m v
|
||||||
|
|
||||||
|
-- | Construct an abstract string value.
|
||||||
|
string :: ByteString -> m v
|
||||||
|
|
||||||
|
-- | Eliminate boolean values. TODO: s/boolean/truthy
|
||||||
|
ifthenelse :: v -> m v -> m v -> m v
|
||||||
|
|
||||||
-- | Evaluate an abstraction (a binder like a lambda or method definition).
|
-- | Evaluate an abstraction (a binder like a lambda or method definition).
|
||||||
abstract :: [Name] -> Subterm t (m v) -> m v
|
abstract :: [Name] -> Subterm t (m v) -> m v
|
||||||
-- | Evaluate an application (like a function call).
|
-- | Evaluate an application (like a function call).
|
||||||
apply :: v -> [Subterm t (m v)] -> m v
|
apply :: v -> [Subterm t (m v)] -> m v
|
||||||
|
|
||||||
|
-- | Construct a 'Value' wrapping the value arguments (if any).
|
||||||
instance ( FreeVariables t
|
instance ( FreeVariables t
|
||||||
, MonadAddressable location (Value location t) m
|
, MonadAddressable location (Value location t) m
|
||||||
, MonadAnalysis t (Value location t) m
|
, MonadAnalysis t (Value location t) m
|
||||||
@ -29,7 +45,17 @@ instance ( FreeVariables t
|
|||||||
, Recursive t
|
, Recursive t
|
||||||
, Semigroup (Cell location (Value location t))
|
, Semigroup (Cell location (Value location t))
|
||||||
)
|
)
|
||||||
=> MonadFunction t (Value location t) m where
|
=> MonadValue t (Value location t) m where
|
||||||
|
|
||||||
|
unit = pure $ inj Value.Unit
|
||||||
|
integer = pure . inj . Integer
|
||||||
|
boolean = pure . inj . Boolean
|
||||||
|
string = pure . inj . Value.String
|
||||||
|
|
||||||
|
ifthenelse cond if' else'
|
||||||
|
| Just (Boolean b) <- prj cond = if b then if' else else'
|
||||||
|
| otherwise = fail "not defined for non-boolean conditions"
|
||||||
|
|
||||||
abstract names (Subterm body _) = inj . Closure names body <$> askLocalEnv
|
abstract names (Subterm body _) = inj . Closure names body <$> askLocalEnv
|
||||||
|
|
||||||
apply op params = do
|
apply op params = do
|
||||||
@ -41,7 +67,8 @@ instance ( FreeVariables t
|
|||||||
envInsert name a <$> rest) (pure env) (zip names params)
|
envInsert name a <$> rest) (pure env) (zip names params)
|
||||||
localEnv (mappend bindings) (evaluateTerm body)
|
localEnv (mappend bindings) (evaluateTerm body)
|
||||||
|
|
||||||
instance (Alternative m, MonadEvaluator t Type m, MonadFresh m) => MonadFunction t Type m where
|
-- | Discard the value arguments (if any), constructing a 'Type.Type' instead.
|
||||||
|
instance (Alternative m, MonadEvaluator t Type m, MonadFresh m) => MonadValue t Type m where
|
||||||
abstract names (Subterm _ body) = do
|
abstract names (Subterm _ body) = do
|
||||||
(env, tvars) <- foldr (\ name rest -> do
|
(env, tvars) <- foldr (\ name rest -> do
|
||||||
a <- alloc name
|
a <- alloc name
|
||||||
@ -52,6 +79,13 @@ instance (Alternative m, MonadEvaluator t Type m, MonadFresh m) => MonadFunction
|
|||||||
ret <- localEnv (mappend env) body
|
ret <- localEnv (mappend env) body
|
||||||
pure (Product tvars :-> ret)
|
pure (Product tvars :-> ret)
|
||||||
|
|
||||||
|
unit = pure Type.Unit
|
||||||
|
integer _ = pure Int
|
||||||
|
boolean _ = pure Bool
|
||||||
|
string _ = pure Type.String
|
||||||
|
|
||||||
|
ifthenelse cond if' else' = unify cond Bool *> (if' <|> else')
|
||||||
|
|
||||||
apply op params = do
|
apply op params = do
|
||||||
tvar <- fresh
|
tvar <- fresh
|
||||||
paramTypes <- traverse subtermValue params
|
paramTypes <- traverse subtermValue params
|
@ -1,11 +1,10 @@
|
|||||||
{-# LANGUAGE DefaultSignatures, FunctionalDependencies, UndecidableInstances #-}
|
{-# LANGUAGE DefaultSignatures, FunctionalDependencies, UndecidableInstances #-}
|
||||||
module Data.Abstract.Evaluatable
|
module Data.Abstract.Evaluatable
|
||||||
( Evaluatable(..)
|
( Evaluatable(..)
|
||||||
, AbstractValue(..)
|
|
||||||
, module Addressable
|
, module Addressable
|
||||||
, module Analysis
|
, module Analysis
|
||||||
, module FreeVariables
|
, module FreeVariables
|
||||||
, module Function
|
, module Value
|
||||||
, MonadEvaluator(..)
|
, MonadEvaluator(..)
|
||||||
, require
|
, require
|
||||||
, load
|
, load
|
||||||
@ -14,7 +13,7 @@ module Data.Abstract.Evaluatable
|
|||||||
import Control.Abstract.Addressable as Addressable
|
import Control.Abstract.Addressable as Addressable
|
||||||
import Control.Abstract.Analysis as Analysis
|
import Control.Abstract.Analysis as Analysis
|
||||||
import Control.Abstract.Evaluator
|
import Control.Abstract.Evaluator
|
||||||
import Control.Abstract.Function as Function
|
import Control.Abstract.Value as Value
|
||||||
import Control.Monad.Effect.Fail
|
import Control.Monad.Effect.Fail
|
||||||
import Data.Abstract.Address
|
import Data.Abstract.Address
|
||||||
import Data.Abstract.Environment
|
import Data.Abstract.Environment
|
||||||
@ -33,12 +32,11 @@ import Prologue
|
|||||||
|
|
||||||
-- | The 'Evaluatable' class defines the necessary interface for a term to be evaluated. While a default definition of 'eval' is given, instances with computational content must implement 'eval' to perform their small-step operational semantics.
|
-- | The 'Evaluatable' class defines the necessary interface for a term to be evaluated. While a default definition of 'eval' is given, instances with computational content must implement 'eval' to perform their small-step operational semantics.
|
||||||
class Evaluatable constr where
|
class Evaluatable constr where
|
||||||
eval :: ( AbstractValue value
|
eval :: ( FreeVariables term
|
||||||
, FreeVariables term
|
|
||||||
, MonadAddressable (LocationFor value) value m
|
, MonadAddressable (LocationFor value) value m
|
||||||
, MonadAnalysis term value m
|
, MonadAnalysis term value m
|
||||||
, MonadEvaluator term value m
|
, MonadEvaluator term value m
|
||||||
, MonadFunction term value m
|
, MonadValue term value m
|
||||||
, Ord (LocationFor value)
|
, Ord (LocationFor value)
|
||||||
, Semigroup (Cell (LocationFor value) value)
|
, Semigroup (Cell (LocationFor value) value)
|
||||||
)
|
)
|
||||||
@ -63,7 +61,7 @@ instance Evaluatable s => Evaluatable (TermF s a) where
|
|||||||
-- 2. Each statement can affect the environment of later statements (e.g. by 'modify'-ing the environment); and
|
-- 2. Each statement can affect the environment of later statements (e.g. by 'modify'-ing the environment); and
|
||||||
-- 3. Only the last statement’s return value is returned.
|
-- 3. Only the last statement’s return value is returned.
|
||||||
instance Evaluatable [] where
|
instance Evaluatable [] where
|
||||||
eval [] = pure unit -- Return unit value if this is an empty list of terms
|
eval [] = unit -- Return unit value if this is an empty list of terms
|
||||||
eval [x] = subtermValue x -- Return the value for the last term
|
eval [x] = subtermValue x -- Return the value for the last term
|
||||||
eval (x:xs) = do
|
eval (x:xs) = do
|
||||||
_ <- subtermValue x -- Evaluate the head term
|
_ <- subtermValue x -- Evaluate the head term
|
||||||
|
@ -9,7 +9,7 @@ import Data.Abstract.Live
|
|||||||
import qualified Data.Abstract.Type as Type
|
import qualified Data.Abstract.Type as Type
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
import Prologue
|
import Prologue
|
||||||
import Prelude hiding (Integer, String)
|
import Prelude hiding (Integer, String, fail)
|
||||||
import qualified Prelude
|
import qualified Prelude
|
||||||
|
|
||||||
type ValueConstructors location
|
type ValueConstructors location
|
||||||
@ -101,42 +101,11 @@ class ValueRoots l v | v -> l where
|
|||||||
-- | Compute the set of addresses rooted by a given value.
|
-- | Compute the set of addresses rooted by a given value.
|
||||||
valueRoots :: v -> Live l v
|
valueRoots :: v -> Live l v
|
||||||
|
|
||||||
-- | An interface for constructing abstract values.
|
|
||||||
class AbstractValue v where
|
|
||||||
-- | Construct an abstract unit value.
|
|
||||||
unit :: v
|
|
||||||
|
|
||||||
-- | Construct an abstract integral value.
|
|
||||||
integer :: Prelude.Integer -> v
|
|
||||||
|
|
||||||
-- | Construct an abstract boolean value.
|
|
||||||
boolean :: Bool -> v
|
|
||||||
|
|
||||||
-- | Construct an abstract string value.
|
|
||||||
string :: ByteString -> v
|
|
||||||
|
|
||||||
|
|
||||||
-- Instances
|
|
||||||
|
|
||||||
instance (FreeVariables term, Ord location) => ValueRoots location (Value location term) where
|
instance (FreeVariables term, Ord location) => ValueRoots location (Value location term) where
|
||||||
valueRoots v
|
valueRoots v
|
||||||
| Just (Closure names body env) <- prj v = envRoots env (foldr Set.delete (freeVariables body) names)
|
| Just (Closure names body env) <- prj v = envRoots env (foldr Set.delete (freeVariables body) names)
|
||||||
| Just (Interface _ env) <- prj v = envAll env
|
| Just (Interface _ env) <- prj v = envAll env
|
||||||
| otherwise = mempty
|
| otherwise = mempty
|
||||||
|
|
||||||
-- | Construct a 'Value' wrapping the value arguments (if any).
|
|
||||||
instance AbstractValue (Value location term) where
|
|
||||||
unit = inj Unit
|
|
||||||
integer = inj . Integer
|
|
||||||
boolean = inj . Boolean
|
|
||||||
string = inj . String
|
|
||||||
|
|
||||||
instance ValueRoots Monovariant Type.Type where
|
instance ValueRoots Monovariant Type.Type where
|
||||||
valueRoots _ = mempty
|
valueRoots _ = mempty
|
||||||
|
|
||||||
-- | Discard the value arguments (if any), constructing a 'Type.Type' instead.
|
|
||||||
instance AbstractValue Type.Type where
|
|
||||||
unit = Type.Unit
|
|
||||||
integer _ = Type.Int
|
|
||||||
boolean _ = Type.Bool
|
|
||||||
string _ = Type.String
|
|
||||||
|
@ -142,7 +142,7 @@ instance Evaluatable Program where
|
|||||||
-- interface val = inj . Value.Interface val <$> get @(EnvironmentFor (Value l t))
|
-- interface val = inj . Value.Interface val <$> get @(EnvironmentFor (Value l t))
|
||||||
interface val = pure val -- inj . Value.Interface val <$> askLocalEnv
|
interface val = pure val -- inj . Value.Interface val <$> askLocalEnv
|
||||||
|
|
||||||
eval' [] = interface unit
|
eval' [] = unit >>= interface
|
||||||
eval' [x] = subtermValue x >>= interface
|
eval' [x] = subtermValue x >>= interface
|
||||||
eval' (x:xs) = do
|
eval' (x:xs) = do
|
||||||
_ <- subtermValue x
|
_ <- subtermValue x
|
||||||
@ -171,7 +171,7 @@ instance Ord1 Empty where liftCompare _ _ _ = EQ
|
|||||||
instance Show1 Empty where liftShowsPrec _ _ _ _ = showString "Empty"
|
instance Show1 Empty where liftShowsPrec _ _ _ _ = showString "Empty"
|
||||||
|
|
||||||
instance Evaluatable Empty where
|
instance Evaluatable Empty where
|
||||||
eval _ = pure unit
|
eval _ = unit
|
||||||
|
|
||||||
|
|
||||||
-- | Syntax representing a parsing or assignment error.
|
-- | Syntax representing a parsing or assignment error.
|
||||||
|
@ -14,7 +14,7 @@ instance Ord1 Comment where liftCompare = genericLiftCompare
|
|||||||
instance Show1 Comment where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 Comment where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
|
||||||
instance Evaluatable Comment where
|
instance Evaluatable Comment where
|
||||||
eval _ = pure unit
|
eval _ = unit
|
||||||
|
|
||||||
-- TODO: nested comment types
|
-- TODO: nested comment types
|
||||||
-- TODO: documentation comment types
|
-- TODO: documentation comment types
|
||||||
|
@ -215,6 +215,7 @@ instance Ord1 Import where liftCompare = genericLiftCompare
|
|||||||
instance Show1 Import where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 Import where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
|
||||||
instance Evaluatable Import where
|
instance Evaluatable Import where
|
||||||
|
eval (Import from _ _) = undefined -- let n = qualifiedName (subterm from) in require n *> unit
|
||||||
|
|
||||||
|
|
||||||
data Import2 a = Import2 { import2From :: !a, import2Alias :: !a, import2Symbols :: ![(Name, Name)] }
|
data Import2 a = Import2 { import2From :: !a, import2Alias :: !a, import2Symbols :: ![(Name, Name)] }
|
||||||
|
@ -22,7 +22,7 @@ instance Ord1 Boolean where liftCompare = genericLiftCompare
|
|||||||
instance Show1 Boolean where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 Boolean where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
|
||||||
instance Evaluatable Boolean where
|
instance Evaluatable Boolean where
|
||||||
eval (Boolean x) = pure (boolean x)
|
eval (Boolean x) = boolean x
|
||||||
|
|
||||||
|
|
||||||
-- Numeric
|
-- Numeric
|
||||||
@ -37,7 +37,7 @@ instance Show1 Data.Syntax.Literal.Integer where liftShowsPrec = genericLiftShow
|
|||||||
|
|
||||||
instance Evaluatable Data.Syntax.Literal.Integer where
|
instance Evaluatable Data.Syntax.Literal.Integer where
|
||||||
-- TODO: This instance probably shouldn't have readInteger?
|
-- TODO: This instance probably shouldn't have readInteger?
|
||||||
eval (Data.Syntax.Literal.Integer x) = pure (integer (maybe 0 fst (readInteger x)))
|
eval (Data.Syntax.Literal.Integer x) = integer (maybe 0 fst (readInteger x))
|
||||||
|
|
||||||
|
|
||||||
-- TODO: Should IntegerLiteral hold an Integer instead of a ByteString?
|
-- TODO: Should IntegerLiteral hold an Integer instead of a ByteString?
|
||||||
@ -115,7 +115,7 @@ instance Ord1 TextElement where liftCompare = genericLiftCompare
|
|||||||
instance Show1 TextElement where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 TextElement where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
|
||||||
instance Evaluatable TextElement where
|
instance Evaluatable TextElement where
|
||||||
eval (TextElement x) = pure (string x)
|
eval (TextElement x) = string x
|
||||||
|
|
||||||
data Null a = Null
|
data Null a = Null
|
||||||
deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Mergeable, Ord, Show, Traversable, FreeVariables1)
|
deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Mergeable, Ord, Show, Traversable, FreeVariables1)
|
||||||
|
@ -15,8 +15,10 @@ instance Ord1 If where liftCompare = genericLiftCompare
|
|||||||
instance Show1 If where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 If where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
|
||||||
-- TODO: Implement Eval instance for If
|
-- TODO: Implement Eval instance for If
|
||||||
instance Evaluatable If
|
instance Evaluatable If where
|
||||||
|
eval (If cond if' else') = do
|
||||||
|
bool <- subtermValue cond
|
||||||
|
ifthenelse bool (subtermValue if') (subtermValue else')
|
||||||
|
|
||||||
-- | Else statement. The else condition is any term, that upon successful completion, continues evaluation to the elseBody, e.g. `for ... else` in Python.
|
-- | Else statement. The else condition is any term, that upon successful completion, continues evaluation to the elseBody, e.g. `for ... else` in Python.
|
||||||
data Else a = Else { elseCondition :: !a, elseBody :: !a }
|
data Else a = Else { elseCondition :: !a, elseBody :: !a }
|
||||||
@ -185,8 +187,8 @@ instance Ord1 NoOp where liftCompare = genericLiftCompare
|
|||||||
instance Show1 NoOp where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 NoOp where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
|
||||||
-- TODO: Implement Eval instance for NoOp
|
-- TODO: Implement Eval instance for NoOp
|
||||||
instance Evaluatable NoOp
|
instance Evaluatable NoOp where
|
||||||
|
eval _ = unit
|
||||||
|
|
||||||
-- Loops
|
-- Loops
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user