diff --git a/src/Analysis/Abstract/Evaluating.hs b/src/Analysis/Abstract/Evaluating.hs index a95ca73be..bf11c9d72 100644 --- a/src/Analysis/Abstract/Evaluating.hs +++ b/src/Analysis/Abstract/Evaluating.hs @@ -10,7 +10,7 @@ import Data.Semilattice.Lower -- | An analysis evaluating @term@s to @value@s with a list of @effects@ using 'Evaluatable', and producing incremental results of type @a@. data EvaluatingState address value = EvaluatingState { heap :: Heap address (Cell address) value - , modules :: ModuleTable (Maybe (address, Environment address)) + , modules :: ModuleTable (Maybe (Environment address, address)) } deriving instance (Eq (Cell address value), Eq address, Eq value) => Eq (EvaluatingState address value) @@ -18,14 +18,15 @@ deriving instance (Ord (Cell address value), Ord address, Ord value) => Ord deriving instance (Show (Cell address value), Show address, Show value) => Show (EvaluatingState address value) -evaluating :: Evaluator address value +evaluating :: Effects effects + => Evaluator address value ( Fresh ': State (Heap address (Cell address) value) - ': State (ModuleTable (Maybe (address, Environment address))) + ': State (ModuleTable (Maybe (Environment address, address))) ': effects) result -> Evaluator address value effects (result, EvaluatingState address value) evaluating - = fmap (\ ((result, heap), modules) -> (result, EvaluatingState heap modules)) - . runState lowerBound -- State (ModuleTable (Maybe (address, Environment address))) + = fmap (\ (modules, (heap, result)) -> (result, EvaluatingState heap modules)) + . runState lowerBound -- State (ModuleTable (Maybe (Environment address, address))) . runState lowerBound -- State (Heap address (Cell address) value) . runFresh 0 diff --git a/src/Control/Abstract/Modules.hs b/src/Control/Abstract/Modules.hs index 86ef546b4..d8affccc1 100644 --- a/src/Control/Abstract/Modules.hs +++ b/src/Control/Abstract/Modules.hs @@ -26,7 +26,7 @@ import Data.Language import Prologue -- | Retrieve an evaluated module, if any. The outer 'Maybe' indicates whether we’ve begun loading the module or not, while the inner 'Maybe' indicates whether we’ve completed loading it or not. Thus, @Nothing@ means we’ve never tried to load it, @Just Nothing@ means we’ve started but haven’t yet finished loading it, and @Just (Just (env, value))@ indicates the result of a completed load. -lookupModule :: Member (Modules address value) effects => ModulePath -> Evaluator address value effects (Maybe (Maybe (address, Environment address))) +lookupModule :: Member (Modules address value) effects => ModulePath -> Evaluator address value effects (Maybe (Maybe (Environment address, address))) lookupModule = sendModules . Lookup -- | Resolve a list of module paths to a possible module table entry. @@ -40,19 +40,19 @@ listModulesInDir = sendModules . List @address @value -- | Require/import another module by name and return its environment and value. -- -- Looks up the module's name in the cache of evaluated modules first, returns if found, otherwise loads/evaluates the module. -require :: Member (Modules address value) effects => ModulePath -> Evaluator address value effects (Maybe (address, Environment address)) +require :: Member (Modules address value) effects => ModulePath -> Evaluator address value effects (Maybe (Environment address, address)) require path = lookupModule path >>= maybeM (load path) -- | Load another module by name and return its environment and value. -- -- Always loads/evaluates. -load :: Member (Modules address value) effects => ModulePath -> Evaluator address value effects (Maybe (address, Environment address)) +load :: Member (Modules address value) effects => ModulePath -> Evaluator address value effects (Maybe (Environment address, address)) load path = sendModules (Load path) data Modules address value (m :: * -> *) return where - Load :: ModulePath -> Modules address value m (Maybe (address, Environment address)) - Lookup :: ModulePath -> Modules address value m (Maybe (Maybe (address, Environment address))) + Load :: ModulePath -> Modules address value m (Maybe (Environment address, address)) + Lookup :: ModulePath -> Modules address value m (Maybe (Maybe (Environment address, address))) Resolve :: [FilePath] -> Modules address value m (Maybe ModulePath) List :: FilePath -> Modules address value m [ModulePath] @@ -61,11 +61,11 @@ sendModules = send runModules :: forall term address value effects a . ( Member (Resumable (LoadError address value)) effects - , Member (State (ModuleTable (Maybe (address, Environment address)))) effects + , Member (State (ModuleTable (Maybe (Environment address, address)))) effects , Member Trace effects , Effects effects ) - => (Module term -> Evaluator address value (Modules address value ': effects) (address, Environment address)) + => (Module term -> Evaluator address value (Modules address value ': effects) (Environment address, address)) -> Evaluator address value (Modules address value ': effects) a -> Evaluator address value (Reader (ModuleTable (NonEmpty (Module term))) ': effects) a runModules evaluateModule = go @@ -90,22 +90,22 @@ runModules evaluateModule = go pure (find isMember names) List dir -> modulePathsInDir dir <$> askModuleTable @term) -getModuleTable :: Member (State (ModuleTable (Maybe (address, Environment address)))) effects => Evaluator address value effects (ModuleTable (Maybe (address, Environment address))) +getModuleTable :: Member (State (ModuleTable (Maybe (Environment address, address)))) effects => Evaluator address value effects (ModuleTable (Maybe (Environment address, address))) getModuleTable = get -cacheModule :: Member (State (ModuleTable (Maybe (address, Environment address)))) effects => ModulePath -> Maybe (address, Environment address) -> Evaluator address value effects (Maybe (address, Environment address)) +cacheModule :: Member (State (ModuleTable (Maybe (Environment address, address)))) effects => ModulePath -> Maybe (Environment address, address) -> Evaluator address value effects (Maybe (Environment address, address)) cacheModule path result = modify' (ModuleTable.insert path result) $> result askModuleTable :: Member (Reader (ModuleTable (NonEmpty (Module term)))) effects => Evaluator address value effects (ModuleTable (NonEmpty (Module term))) askModuleTable = ask -newtype Merging m address value = Merging { runMerging :: m (Maybe (address, Environment address)) } +newtype Merging m address value = Merging { runMerging :: m (Maybe (Environment address, address)) } instance Applicative m => Semigroup (Merging m address value) where Merging a <> Merging b = Merging (merge <$> a <*> b) where merge a b = mergeJusts <$> a <*> b <|> a <|> b - mergeJusts (_, env1) (v, env2) = (v, mergeEnvs env1 env2) + mergeJusts (env1, _) (env2, v) = (mergeEnvs env1 env2, v) instance Applicative m => Monoid (Merging m address value) where mappend = (<>) @@ -114,7 +114,7 @@ instance Applicative m => Monoid (Merging m address value) where -- | An error thrown when loading a module from the list of provided modules. Indicates we weren't able to find a module with the given name. data LoadError address value resume where - ModuleNotFound :: ModulePath -> LoadError address value (Maybe (address, Environment address)) + ModuleNotFound :: ModulePath -> LoadError address value (Maybe (Environment address, address)) deriving instance Eq (LoadError address value resume) deriving instance Show (LoadError address value resume) @@ -123,7 +123,7 @@ instance Show1 (LoadError address value) where instance Eq1 (LoadError address value) where liftEq _ (ModuleNotFound a) (ModuleNotFound b) = a == b -moduleNotFound :: forall address value effects . Member (Resumable (LoadError address value)) effects => ModulePath -> Evaluator address value effects (Maybe (address, Environment address)) +moduleNotFound :: forall address value effects . Member (Resumable (LoadError address value)) effects => ModulePath -> Evaluator address value effects (Maybe (Environment address, address)) moduleNotFound = throwResumable . ModuleNotFound @address @value resumeLoadError :: Member (Resumable (LoadError address value)) effects => Evaluator address value effects a -> (forall resume . LoadError address value resume -> Evaluator address value effects resume) -> Evaluator address value effects a diff --git a/src/Data/Abstract/Evaluatable.hs b/src/Data/Abstract/Evaluatable.hs index 25c06a105..26a2a9fd0 100644 --- a/src/Data/Abstract/Evaluatable.hs +++ b/src/Data/Abstract/Evaluatable.hs @@ -68,6 +68,7 @@ evaluatePackageWith :: forall address term value inner inner' inner'' outer -- FIXME: It’d be nice if we didn’t have to mention 'Addressable' here at all, but 'Located' locations require knowledge of 'currentModule' to run. Can we fix that? , Addressable address inner' , Declarations term + , Effects outer , Evaluatable (Base term) , Foldable (Cell address) , FreeVariables term @@ -79,7 +80,7 @@ evaluatePackageWith :: forall address term value inner inner' inner'' outer , Member (Resumable ResolutionError) outer , Member (Resumable (Unspecialized value)) outer , Member (State (Heap address (Cell address) value)) outer - , Member (State (ModuleTable (Maybe (address, Environment address)))) outer + , Member (State (ModuleTable (Maybe (Environment address, address)))) outer , Member Trace outer , Recursive term , Reducer value (Cell address value) @@ -91,7 +92,7 @@ evaluatePackageWith :: forall address term value inner inner' inner'' outer => (SubtermAlgebra Module term (TermEvaluator term address value inner address) -> SubtermAlgebra Module term (TermEvaluator term address value inner address)) -> (SubtermAlgebra (Base term) term (TermEvaluator term address value inner (ValueRef address)) -> SubtermAlgebra (Base term) term (TermEvaluator term address value inner (ValueRef address))) -> Package term - -> TermEvaluator term address value outer [(address, Environment address)] + -> TermEvaluator term address value outer [(Environment address, address)] evaluatePackageWith analyzeModule analyzeTerm package = runReader (packageInfo package) . runReader lowerBound @@ -115,20 +116,20 @@ evaluatePackageWith analyzeModule analyzeTerm package . raiseHandler runReturn . raiseHandler runLoopControl - evaluateEntryPoint :: Environment address -> ModulePath -> Maybe Name -> TermEvaluator term address value inner'' (address, Environment address) + evaluateEntryPoint :: Environment address -> ModulePath -> Maybe Name -> TermEvaluator term address value inner'' (Environment address, address) evaluateEntryPoint preludeEnv m sym = runInModule preludeEnv (ModuleInfo m) . TermEvaluator $ do addr <- box unit -- TODO don't *always* allocate - use maybeM instead - (ptr, env) <- fromMaybe (addr, emptyEnv) <$> require m + (env, ptr) <- fromMaybe (emptyEnv, addr) <$> require m bindAll env maybe (pure ptr) ((`call` []) <=< deref <=< variable) sym evalPrelude prelude = raiseHandler (runModules (runTermEvaluator . evalModule emptyEnv)) $ do - (_, builtinsEnv) <- runInModule emptyEnv moduleInfoFromCallStack (TermEvaluator (defineBuiltins *> box unit)) - second (mergeEnvs builtinsEnv) <$> evalModule builtinsEnv prelude + (builtinsEnv, _) <- runInModule emptyEnv moduleInfoFromCallStack (TermEvaluator (defineBuiltins *> box unit)) + first (mergeEnvs builtinsEnv) <$> evalModule builtinsEnv prelude withPrelude Nothing f = f emptyEnv withPrelude (Just prelude) f = do - (_, preludeEnv) <- evalPrelude prelude + (preludeEnv, _) <- evalPrelude prelude f preludeEnv @@ -166,10 +167,10 @@ instance Show1 EvalError where throwEvalError :: (Effectful m, Member (Resumable EvalError) effects) => EvalError resume -> m effects resume throwEvalError = throwResumable -runEvalError :: Effectful m => m (Resumable EvalError ': effects) a -> m effects (Either (SomeExc EvalError) a) +runEvalError :: (Effectful m, Effects effects) => m (Resumable EvalError ': effects) a -> m effects (Either (SomeExc EvalError) a) runEvalError = runResumable -runEvalErrorWith :: Effectful m => (forall resume . EvalError resume -> m effects resume) -> m (Resumable EvalError ': effects) a -> m effects a +runEvalErrorWith :: (Effectful m, Effects effects) => (forall resume . EvalError resume -> m effects resume) -> m (Resumable EvalError ': effects) a -> m effects a runEvalErrorWith = runResumableWith @@ -185,10 +186,10 @@ instance Eq1 (Unspecialized a) where instance Show1 (Unspecialized a) where liftShowsPrec _ _ = showsPrec -runUnspecialized :: Effectful (m value) => m value (Resumable (Unspecialized value) ': effects) a -> m value effects (Either (SomeExc (Unspecialized value)) a) +runUnspecialized :: (Effectful (m value), Effects effects) => m value (Resumable (Unspecialized value) ': effects) a -> m value effects (Either (SomeExc (Unspecialized value)) a) runUnspecialized = runResumable -runUnspecializedWith :: Effectful (m value) => (forall resume . Unspecialized value resume -> m value effects resume) -> m value (Resumable (Unspecialized value) ': effects) a -> m value effects a +runUnspecializedWith :: (Effectful (m value), Effects effects) => (forall resume . Unspecialized value resume -> m value effects resume) -> m value (Resumable (Unspecialized value) ': effects) a -> m value effects a runUnspecializedWith = runResumableWith