1
1
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:
Timothy Clem 2018-03-02 16:08:54 -08:00
parent d57c1e2d33
commit 7b4b35cb5e
6 changed files with 45 additions and 99 deletions

View File

@ -19,31 +19,6 @@ import qualified Data.ByteString.Char8 as BC
import qualified Data.Map as Map import qualified Data.Map as Map
import System.FilePath.Posix import System.FilePath.Posix
-- -- | Require/import another term/file and return an Effect.
-- --
-- -- Looks up the term's name in the cache of evaluated modules first, returns a value if found, otherwise loads/evaluates the module.
-- require :: forall v es.
-- ( Members (Evaluating v) es
-- , AbstractEnvironmentFor v
-- )
-- => ModuleName -> Eff es (EnvironmentFor v)
-- require name = get @(Linker (EnvironmentFor v)) >>= maybe (load name) pure . linkerLookup name
--
-- -- | Load another term/file and return an Effect.
-- --
-- -- Always loads/evaluates.
-- load :: forall v es.
-- ( Members (Evaluating v) es
-- , AbstractEnvironmentFor v
-- )
-- => ModuleName -> Eff es (EnvironmentFor v)
-- load name = ask @(Linker (Evaluator v)) >>= maybe notFound evalAndCache . linkerLookup name
-- where notFound = fail ("cannot find " <> show name)
-- evalAndCache e = do
-- v <- raiseEmbedded (runEvaluator e)
-- let env = environment v
-- modify @(Linker (EnvironmentFor v)) (linkerInsert name env)
-- pure env
-- | The effects necessary for concrete interpretation. -- | The effects necessary for concrete interpretation.
type EvaluationEffects t v type EvaluationEffects t v

View File

@ -37,6 +37,11 @@ class (MonadEvaluator t v m) => MonadValue t v m where
-- | 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
-- | Extract the environment from an interface value.
environment :: v -> m (EnvironmentFor v)
interface :: v -> m v
-- | Construct a 'Value' wrapping the value arguments (if any). -- | 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
@ -51,6 +56,7 @@ instance ( FreeVariables t
integer = pure . inj . Integer integer = pure . inj . Integer
boolean = pure . inj . Boolean boolean = pure . inj . Boolean
string = pure . inj . Value.String string = pure . inj . Value.String
interface v = inj . Value.Interface v <$> getGlobalEnv
ifthenelse cond if' else' ifthenelse cond if' else'
| Just (Boolean b) <- prj cond = if b then if' else else' | Just (Boolean b) <- prj cond = if b then if' else else'
@ -67,6 +73,10 @@ 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)
environment v
| Just (Interface _ env) <- prj v = pure env
| otherwise = pure mempty
-- | Discard the value arguments (if any), constructing a 'Type.Type' instead. -- | 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 instance (Alternative m, MonadEvaluator t Type m, MonadFresh m) => MonadValue t Type m where
abstract names (Subterm _ body) = do abstract names (Subterm _ body) = do
@ -83,6 +93,8 @@ instance (Alternative m, MonadEvaluator t Type m, MonadFresh m) => MonadValue t
integer _ = pure Int integer _ = pure Int
boolean _ = pure Bool boolean _ = pure Bool
string _ = pure Type.String string _ = pure Type.String
-- TODO
interface = undefined
ifthenelse cond if' else' = unify cond Bool *> (if' <|> else') ifthenelse cond if' else' = unify cond Bool *> (if' <|> else')
@ -91,3 +103,6 @@ instance (Alternative m, MonadEvaluator t Type m, MonadFresh m) => MonadValue t
paramTypes <- traverse subtermValue params paramTypes <- traverse subtermValue params
_ :-> ret <- op `unify` (Product paramTypes :-> Var tvar) _ :-> ret <- op `unify` (Product paramTypes :-> Var tvar)
pure ret pure ret
-- TODO
environment = undefined

View File

@ -21,7 +21,6 @@ import Data.Abstract.FreeVariables as FreeVariables
import Data.Abstract.Linker import Data.Abstract.Linker
import Data.Abstract.Value import Data.Abstract.Value
import Data.Algebra import Data.Algebra
import qualified Data.ByteString.Char8 as BC
import Data.Functor.Classes import Data.Functor.Classes
import Data.Proxy import Data.Proxy
import Data.Semigroup import Data.Semigroup
@ -80,7 +79,7 @@ instance Evaluatable [] where
-- Looks up the term's name in the cache of evaluated modules first, returns a value if found, otherwise loads/evaluates the module. -- Looks up the term's name in the cache of evaluated modules first, returns a value if found, otherwise loads/evaluates the module.
require :: ( MonadAnalysis term v m require :: ( MonadAnalysis term v m
, MonadEvaluator term v m , MonadEvaluator term v m
, AbstractEnvironmentFor v , MonadValue term v m
) )
=> ModuleName => ModuleName
-> m (EnvironmentFor v) -> m (EnvironmentFor v)
@ -91,7 +90,7 @@ require name = getModuleTable >>= maybe (load name) pure . linkerLookup name
-- Always loads/evaluates. -- Always loads/evaluates.
load :: ( MonadAnalysis term v m load :: ( MonadAnalysis term v m
, MonadEvaluator term v m , MonadEvaluator term v m
, AbstractEnvironmentFor v , MonadValue term v m
) )
=> ModuleName => ModuleName
-> m (EnvironmentFor v) -> m (EnvironmentFor v)
@ -99,10 +98,6 @@ load name = askModuleTable >>= maybe notFound evalAndCache . linkerLookup name
where notFound = fail ("cannot find " <> show name) where notFound = fail ("cannot find " <> show name)
evalAndCache e = do evalAndCache e = do
v <- evaluateTerm e v <- evaluateTerm e
let env = environment v env <- environment v
modifyModuleTable (linkerInsert name env) modifyModuleTable (linkerInsert name env)
pure env pure env
-- | Get a module name from a term (expects single free variables).
moduleName :: FreeVariables term => term -> Prelude.String
moduleName term = let [n] = toList (freeVariables term) in BC.unpack n

View File

@ -86,16 +86,6 @@ type family LocationFor value :: * where
LocationFor (Value location term) = location LocationFor (Value location term) = location
LocationFor Type.Type = Monovariant LocationFor Type.Type = Monovariant
type AbstractEnvironmentFor v = AbstractEnvironment (LocationFor v) v
class AbstractEnvironment l v | v -> l where
environment :: v -> EnvironmentFor v
instance AbstractEnvironment l (Value l t) where
environment v
| Just (Interface _ env) <- prj v = env
| otherwise = mempty
-- | Value types, e.g. closures, which can root a set of addresses. -- | Value types, e.g. closures, which can root a set of addresses.
class ValueRoots l v | v -> l where 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.

View File

@ -1,13 +1,11 @@
{-# LANGUAGE DeriveAnyClass, GADTs, TypeOperators, MultiParamTypeClasses, UndecidableInstances, ScopedTypeVariables, TypeApplications #-} {-# LANGUAGE DeriveAnyClass, GADTs, TypeOperators, MultiParamTypeClasses, UndecidableInstances, ScopedTypeVariables #-}
module Data.Syntax where module Data.Syntax where
import qualified Assigning.Assignment as Assignment
import Control.Monad.Fail import Control.Monad.Fail
import Data.Abstract.Environment import Data.Abstract.Environment
import Data.Abstract.Evaluatable import Data.Abstract.Evaluatable
import Data.AST import Data.AST
import Data.ByteString.Char8 (unpack) import Data.ByteString.Char8 (unpack)
import qualified Data.Error as Error
import Data.Range import Data.Range
import Data.Record import Data.Record
import Data.Span import Data.Span
@ -15,6 +13,8 @@ import Data.Term
import Diffing.Algorithm hiding (Empty) import Diffing.Algorithm hiding (Empty)
import Prelude hiding (fail) import Prelude hiding (fail)
import Prologue import Prologue
import qualified Assigning.Assignment as Assignment
import qualified Data.Error as Error
-- Combinators -- Combinators
@ -139,15 +139,12 @@ instance Show1 Program where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable Program where instance Evaluatable Program where
eval (Program xs) = eval' xs eval (Program xs) = eval' xs
where where
-- interface val = inj . Value.Interface val <$> get @(EnvironmentFor (Value l t))
interface val = pure val -- inj . Value.Interface val <$> askLocalEnv
eval' [] = unit >>= interface 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
env <- getGlobalEnv env <- getGlobalEnv
localEnv (envUnion env) (eval' xs) localEnv (const env) (eval' xs)
-- | An accessibility modifier, e.g. private, public, protected, etc. -- | An accessibility modifier, e.g. private, public, protected, etc.
newtype AccessibilityModifier a = AccessibilityModifier ByteString newtype AccessibilityModifier a = AccessibilityModifier ByteString

View File

@ -5,6 +5,7 @@ import Prologue
import Data.Abstract.Environment import Data.Abstract.Environment
import Data.Abstract.Evaluatable import Data.Abstract.Evaluatable
import Diffing.Algorithm import Diffing.Algorithm
import qualified Data.Map as Map
data Function a = Function { functionContext :: ![a], functionName :: !a, functionParameters :: ![a], functionBody :: !a } data Function a = Function { functionContext :: ![a], functionName :: !a, functionParameters :: ![a], functionBody :: !a }
deriving (Eq, Foldable, Functor, GAlign, Generic1, Mergeable, Ord, Show, Traversable, FreeVariables1) deriving (Eq, Foldable, Functor, GAlign, Generic1, Mergeable, Ord, Show, Traversable, FreeVariables1)
@ -215,7 +216,8 @@ 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 eval (Import from _ _) = require name *> unit
where name = qualifiedName (subterm from)
data Import2 a = Import2 { import2From :: !a, import2Alias :: !a, import2Symbols :: ![(Name, Name)] } data Import2 a = Import2 { import2From :: !a, import2Alias :: !a, import2Symbols :: ![(Name, Name)] }
@ -226,41 +228,24 @@ instance Ord1 Import2 where liftCompare = genericLiftCompare
instance Show1 Import2 where liftShowsPrec = genericLiftShowsPrec instance Show1 Import2 where liftShowsPrec = genericLiftShowsPrec
instance Evaluatable Import2 where instance Evaluatable Import2 where
-- TODO: eval (Import2 from alias xs) = do
eval (Import2 from alias xs) = undefined-- require (qualifiedName (subterm from)) >> pure unit env <- getGlobalEnv
putGlobalEnv mempty
importedEnv <- require name
env' <- Map.foldrWithKey (\k v rest -> do
if Map.null symbols
-- Copy over all symbols in the environment under their qualified names.
then envInsert (prefix <> k) v <$> rest
-- Only copy over specified symbols, possibly aliasing them.
else maybe rest (\symAlias -> envInsert symAlias v <$> rest) (Map.lookup k symbols)
) (pure env) (unEnvironment importedEnv)
-- instance ( Members (Evaluating v) es modifyGlobalEnv (const env')
-- , Evaluatable es t v (Base t) unit
-- , Recursive t where
-- , FreeVariables t name = qualifiedName (subterm from)
-- , AbstractValue v symbols = Map.fromList xs
-- , AbstractEnvironmentFor v prefix = qualifiedName (subterm alias) <> "."
-- )
-- => Evaluatable es t v Import2 where
-- eval (Import2 from alias xs) = do
-- -- Capture current global environment
-- env <- get @(EnvironmentFor v)
--
-- -- TODO: We may or may not want to clear the globalEnv before requiring.
-- put @(EnvironmentFor v) mempty
--
-- -- Evaluate the import to get it's environment.
-- -- (requiring will have also have potentially updated the global environment)
-- importedEnv <- require @v (qualifiedName (subterm from))
--
-- -- Restore previous global environment, adding the imported env
-- let symbols = Map.fromList xs
-- let prefix = qualifiedName (subterm alias) <> "."
-- env' <- Map.foldrWithKey (\k v rest -> do
-- if Map.null symbols
-- -- Copy over all symbols in the environment under their qualified names.
-- then envInsert (prefix <> k) v <$> rest
-- -- Only copy over specified symbols, possibly aliasing them.
-- else maybe rest (\symAlias -> envInsert symAlias v <$> rest) (Map.lookup k symbols)
-- ) (pure env) (unEnvironment importedEnv)
--
-- modify (const env')
-- pure unit
-- | A wildcard import -- | A wildcard import
@ -271,21 +256,10 @@ instance Eq1 WildcardImport where liftEq = genericLiftEq
instance Ord1 WildcardImport where liftCompare = genericLiftCompare instance Ord1 WildcardImport where liftCompare = genericLiftCompare
instance Show1 WildcardImport where liftShowsPrec = genericLiftShowsPrec instance Show1 WildcardImport where liftShowsPrec = genericLiftShowsPrec
-- instance ( Members (Evaluating v) es
-- , FreeVariables t
-- , AbstractEnvironmentFor v
-- , AbstractValue v
-- )
-- => Evaluatable es t v WildcardImport where
-- eval (WildcardImport from _) = put @(EnvironmentFor v) mempty
-- >> require @v (qualifiedName (subterm from))
-- >> pure unit
instance Evaluatable WildcardImport where instance Evaluatable WildcardImport where
eval (WildcardImport from _) = undefined eval (WildcardImport from _) = putGlobalEnv mempty *> require name *> unit
-- putGlobalEnv mempty where name = qualifiedName (subterm from)
-- >> require (qualifiedName (subterm from))
-- >> pure unit
-- | An imported symbol -- | An imported symbol
data ImportSymbol a = ImportSymbol { importSymbolName :: !a, importSymbolAlias :: !a } data ImportSymbol a = ImportSymbol { importSymbolName :: !a, importSymbolAlias :: !a }