1
1
mirror of https://github.com/github/semantic.git synced 2024-12-22 14:21:31 +03:00

Express Evaluatable as an R-algebra.

Co-Authored-By: Josh Vera <vera@github.com>
This commit is contained in:
Rob Rix 2018-02-26 17:07:24 -05:00
parent ca21d42399
commit a99f97854d
6 changed files with 37 additions and 43 deletions

View File

@ -14,7 +14,6 @@ import Data.Abstract.Value
import Data.Abstract.FreeVariables
import Data.Blob
import Data.Traversable
import Data.Function (fix)
import Data.Functor.Foldable (Base, Recursive(..))
import Data.Foldable (toList)
import Data.Semigroup
@ -53,7 +52,7 @@ require term = do
where
evalModule linker name = case linkerLookupTerm name linker of
Just m -> do
v <- step @v m
v <- para eval m
modify @(Linker term v) (linkerInsert name v)
trace ("require[eval]:" <> name) (pure v)
_ -> fail ("cannot find " <> show name)
@ -67,7 +66,7 @@ evaluate :: forall v term.
)
=> term
-> Final (Evaluating term v) v
evaluate = run @(Evaluating term v) . fix (const step)
evaluate = run @(Evaluating term v) . para eval
-- | Evaluate terms and an entry point to a value.
evaluates :: forall v term.
@ -79,11 +78,10 @@ evaluates :: forall v term.
=> [(Blob, term)] -- List of (blob, term) pairs that make up the program to be evaluated
-> (Blob, term) -- Entrypoint
-> Final (Evaluating term v) v
evaluates pairs = run @(Evaluating term v) . fix go
where
go _ (Blob{..}, t) = do
evaluates pairs (Blob{..}, t) = run @(Evaluating term v) $ do
put (Linker @term @v Map.empty (Map.fromList (fmap toPathActionPair pairs)))
trace ("step[entryPoint]: " <> show blobPath) (step @v t)
trace ("step[entryPoint]: " <> show blobPath) (para eval t)
where
toPathActionPair (Blob{..}, t) = (dropExtensions blobPath, t)
@ -120,7 +118,7 @@ evaluate' :: forall v term.
)
=> term
-> Final (Evaluating' v) v
evaluate' = run @(Evaluating' v) . fix (const step)
evaluate' = run @(Evaluating' v) . para eval
-- | Evaluate terms and an entry point to a value.
evaluates' :: forall v term.
@ -132,14 +130,11 @@ evaluates' :: forall v term.
=> [(Blob, term)] -- List of (blob, term) pairs that make up the program to be evaluated
-> (Blob, term) -- Entrypoint
-> Final (Evaluating' v) v
evaluates' pairs = run @(Evaluating' v) . fix go
where
go _ (Blob{..}, t) = do
evaluates' pairs (Blob{..}, t) = run @(Evaluating' v) $ do
modules <- for pairs $ \(Blob{..}, t) -> do
v <- trace ("step: " <> show blobPath) $ step @v t
pure (dropExtensions blobPath, v)
local (const (Linker' (Map.fromList modules))) (trace ("step: " <> show blobPath) (step @v t))
v <- trace ("step: " <> show blobPath) $ para eval t
pure (dropExtensions blobPath, v :: v)
local (const (Linker' (Map.fromList modules))) (trace ("step: " <> show blobPath) (para eval t))
-- | The effects necessary for concrete interpretation.
--
@ -175,7 +170,7 @@ evaluate'' :: forall v term.
)
=> term
-> Final (Evaluating'' v) v
evaluate'' = run @(Evaluating'' v) . fix (const step)
evaluate'' = run @(Evaluating'' v) . para eval
-- | Evaluate terms and an entry point to a value.
evaluates'' :: forall v term.
@ -187,10 +182,9 @@ evaluates'' :: forall v term.
=> [(Blob, term)] -- List of (blob, term) pairs that make up the program to be evaluated
-> (Blob, term) -- Entrypoint
-> Final (Evaluating'' v) v
evaluates'' pairs = run @(Evaluating'' v) . fix go
evaluates'' pairs (Blob{..}, t) = run @(Evaluating'' v) $ local @(Linker' (Evaluator v)) (const (Linker' (Map.fromList (map toPathActionPair pairs)))) (trace ("step: " <> show blobPath) (para eval t))
where
go _ (Blob{..}, t) = local (const (Linker' (Map.fromList (map toPathActionPair pairs)))) (trace ("step: " <> show blobPath) (step @v t))
toPathActionPair (Blob{..}, t) = (dropExtensions blobPath, Evaluator (step @v t))
toPathActionPair (Blob{..}, t) = (dropExtensions blobPath, Evaluator (para eval t))
-- | The effects necessary for concrete interpretation.

View File

@ -25,8 +25,8 @@ import qualified Data.Union as U
-- | 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 es term v constr where
eval :: constr term -> Eff es v
default eval :: (Fail :< es, Show1 constr) => (constr term -> Eff es v)
eval :: constr (term, Eff es v) -> Eff es v
default eval :: (Fail :< es, Show1 constr) => (constr (term, Eff es v) -> Eff es v)
eval expr = fail $ "Eval unspecialized for " ++ liftShowsPrec (const (const id)) (const id) 0 expr ""
-- | If we can evaluate any syntax which can occur in a 'Union', we can evaluate the 'Union'.
@ -38,9 +38,9 @@ instance (Evaluatable es t v s) => Evaluatable es t v (TermF s a) where
eval In{..} = eval termFOut
-- | Evaluate by first projecting a term to recurse one level.
step :: forall v term es. (Evaluatable es term v (Base term), Recursive term)
=> term -> Eff es v
step = eval . project
step :: Recursive term
=> (term, Eff es v) -> Eff es v
step = snd
-- Instances
@ -61,9 +61,9 @@ instance ( Ord (LocationFor v)
)
=> Evaluatable es t v [] where
eval [] = pure unit -- Return unit value if this is an empty list of terms
eval [x] = step x -- Return the value for the last term
eval (x:xs) = do
_ <- step @v x -- Evaluate the head term
eval [(_, x)] = x -- Return the value for the last term
eval ((_, x):xs) = do
_ <- x -- Evaluate the head term
env <- get @(EnvironmentFor v) -- Get the global environment after evaluation
-- since it might have been modified by the
-- 'step' evaluation above ^.
@ -71,4 +71,4 @@ instance ( Ord (LocationFor v)
-- Finally, evaluate the rest of the terms, but do so by calculating a new
-- environment each time where the free variables in those terms are bound
-- to the global environment.
local (const (bindEnv (freeVariables1 xs) env)) (eval xs)
local (const (bindEnv (liftFreeVariables (freeVariables . fst) xs) env)) (eval xs)

View File

@ -163,9 +163,9 @@ instance ( Ord (LocationFor (Value l t))
interface val = inj . Value.Interface val <$> ask @(EnvironmentFor (Value l t))
eval' [] = interface unit
eval' [x] = step x >>= interface
eval' (x:xs) = do
_ <- step @(Value l t) x
eval' [(_, x)] = x >>= interface
eval' ((_, x):xs) = do
_ <- x
env <- get @(EnvironmentFor (Value l t))
local (envUnion env) (eval' xs)

View File

@ -48,10 +48,10 @@ instance ( FreeVariables t
) => Evaluatable es t (Value l t) Function where
eval Function{..} = do
env <- ask
let params = toList (freeVariables1 functionParameters)
let v = inj (Closure params functionBody env) :: Value l t
let params = toList (liftFreeVariables (freeVariables . fst) functionParameters)
let v = inj (Closure params (fst functionBody) env) :: Value l t
(name, addr) <- lookupOrAlloc functionName v env
(name, addr) <- lookupOrAlloc (fst functionName) v env
modify (envInsert name addr)
pure v
@ -104,10 +104,10 @@ instance ( FreeVariables t -- To get free variables from the func
) => Evaluatable es t (Value l t) Method where
eval Method{..} = do
env <- ask
let params = toList (freeVariables1 methodParameters)
let v = inj (Closure params methodBody env) :: Value l t
let params = toList (liftFreeVariables (freeVariables . fst) methodParameters)
let v = inj (Closure params (fst methodBody) env) :: Value l t
(name, addr) <- lookupOrAlloc methodName v env
(name, addr) <- lookupOrAlloc (fst methodName) v env
modify (envInsert name addr)
pure v
@ -286,7 +286,7 @@ instance ( Show l
, FreeVariables t
)
=> Evaluatable es t (Value l t) Import where
eval (Import from _ _) = do
eval (Import (from, _) _ _) = do
interface <- require @(Value l t) @t from
-- TODO: Consider returning the value instead of the interface.
Interface _ env <- maybe

View File

@ -43,7 +43,7 @@ instance ( Ord l
, Recursive t
) => Evaluatable es t (Value l t) Call where
eval Call{..} = do
closure <- step @(Value l t) callFunction
closure <- step callFunction
Closure names body env <- maybe (fail "expected a closure") pure (prj closure :: Maybe (Closure l t))
bindings <- for (zip names callParams) $ \(name, param) -> do
v <- step param
@ -51,7 +51,7 @@ instance ( Ord l
assign a v
pure (name, a)
local (const (foldr (uncurry envInsert) env bindings)) (step body)
local (const (foldr (uncurry envInsert) env bindings)) (para eval body)
-- TODO: Implement type checking for Call
instance Member Fail es => Evaluatable es t Type.Type Call

View File

@ -114,7 +114,7 @@ instance ( Semigroup (Cell (LocationFor v) v)
=> Evaluatable es t v Assignment where
eval Assignment{..} = do
v <- step assignmentValue
(var, a) <- ask >>= lookupOrAlloc assignmentTarget v
(var, a) <- ask >>= lookupOrAlloc (fst assignmentTarget) v
modify (envInsert var a)
pure v