diff --git a/Pinafore/pinafore-app/app/main/Main.hs b/Pinafore/pinafore-app/app/main/Main.hs index a4121d5e9..8927838ad 100644 --- a/Pinafore/pinafore-app/app/main/Main.hs +++ b/Pinafore/pinafore-app/app/main/Main.hs @@ -18,7 +18,7 @@ main = sqliteQDumpTable pinaforedir RunFileOption ropts fNoRun fscript -> do copts <- getModuleOptions ropts - runFiles copts fNoRun [fscript] + runFiles (roSloppy ropts) copts fNoRun [fscript] RunInteractiveOption ropts -> do copts <- getModuleOptions ropts - runInteractive copts + runInteractive (roSloppy ropts) copts diff --git a/Pinafore/pinafore-app/app/main/Options.hs b/Pinafore/pinafore-app/app/main/Options.hs index 5c87ff92e..13c23c564 100644 --- a/Pinafore/pinafore-app/app/main/Options.hs +++ b/Pinafore/pinafore-app/app/main/Options.hs @@ -49,7 +49,7 @@ optNoRun :: Parser Bool optNoRun = switch $ long "no-run" <> short 'n' optRunOptions :: Parser RunOptions -optRunOptions = MkRunOptions <$> optIncludes <*> optDataPath +optRunOptions = MkRunOptions <$> optIncludes <*> optDataPath <*> switch (long "sloppy") assignReader :: ReadM (Text, Text) assignReader = diff --git a/Pinafore/pinafore-app/app/main/Run.hs b/Pinafore/pinafore-app/app/main/Run.hs index c9157fddb..1fea67506 100644 --- a/Pinafore/pinafore-app/app/main/Run.hs +++ b/Pinafore/pinafore-app/app/main/Run.hs @@ -7,22 +7,24 @@ import Changes.Core import Pinafore.Main import Shapes -runFiles :: Foldable t => ModuleOptions -> Bool -> t (FilePath, [String], [(Text, Text)]) -> IO () -runFiles modopts fNoRun scripts = +runFiles :: Foldable t => Bool -> ModuleOptions -> Bool -> t (FilePath, [String], [(Text, Text)]) -> IO () +runFiles ibSloppy modopts fNoRun scripts = runWithOptions defaultExecutionOptions $ runLifecycle $ runView $ for_ scripts $ \(fpath, args, implArgs) -> do - let ?library = standardLibraryContext modopts + let ibLoadModule = standardLoadModule modopts + let ?behaviour = MkInterpretBehaviour {..} action <- qInterpretScriptFile fpath args implArgs if fNoRun then return () else action -runInteractive :: ModuleOptions -> IO () -runInteractive modopts = +runInteractive :: Bool -> ModuleOptions -> IO () +runInteractive ibSloppy modopts = runWithOptions defaultExecutionOptions $ runLifecycle $ runView $ do - let ?library = standardLibraryContext modopts + let ibLoadModule = standardLoadModule modopts + let ?behaviour = MkInterpretBehaviour {..} qInteract diff --git a/Pinafore/pinafore-app/app/main/Test.hs b/Pinafore/pinafore-app/app/main/Test.hs index d372476f0..9e53aa2d8 100644 --- a/Pinafore/pinafore-app/app/main/Test.hs +++ b/Pinafore/pinafore-app/app/main/Test.hs @@ -27,66 +27,80 @@ testOptionParsing = , testTree "script" [ testOptions ["scriptname"] $ - SuccessResult $ RunFileOption (MkRunOptions [] Nothing) False ("scriptname", [], []) + SuccessResult $ RunFileOption (MkRunOptions [] Nothing False) False ("scriptname", [], []) , testOptions ["scriptname", "a"] $ - SuccessResult $ RunFileOption (MkRunOptions [] Nothing) False ("scriptname", ["a"], []) + SuccessResult $ RunFileOption (MkRunOptions [] Nothing False) False ("scriptname", ["a"], []) , testOptions ["scriptname", "-x"] $ - SuccessResult $ RunFileOption (MkRunOptions [] Nothing) False ("scriptname", ["-x"], []) + SuccessResult $ RunFileOption (MkRunOptions [] Nothing False) False ("scriptname", ["-x"], []) , testOptions ["scriptname", "--opt"] $ - SuccessResult $ RunFileOption (MkRunOptions [] Nothing) False ("scriptname", ["--opt"], []) + SuccessResult $ RunFileOption (MkRunOptions [] Nothing False) False ("scriptname", ["--opt"], []) , testOptions ["scriptname", "-n"] $ - SuccessResult $ RunFileOption (MkRunOptions [] Nothing) False ("scriptname", ["-n"], []) + SuccessResult $ RunFileOption (MkRunOptions [] Nothing False) False ("scriptname", ["-n"], []) , testOptions ["scriptname", "-v"] $ - SuccessResult $ RunFileOption (MkRunOptions [] Nothing) False ("scriptname", ["-v"], []) + SuccessResult $ RunFileOption (MkRunOptions [] Nothing False) False ("scriptname", ["-v"], []) , testOptions ["scriptname", "--data", "dpath"] $ - SuccessResult $ RunFileOption (MkRunOptions [] Nothing) False ("scriptname", ["--data", "dpath"], []) + SuccessResult $ + RunFileOption (MkRunOptions [] Nothing False) False ("scriptname", ["--data", "dpath"], []) , testOptions ["-n", "scriptname"] $ - SuccessResult $ RunFileOption (MkRunOptions [] Nothing) True ("scriptname", [], []) + SuccessResult $ RunFileOption (MkRunOptions [] Nothing False) True ("scriptname", [], []) + , testOptions ["--sloppy", "scriptname"] $ + SuccessResult $ RunFileOption (MkRunOptions [] Nothing True) False ("scriptname", [], []) , testOptions ["--imply", "pqr=vv", "scriptname"] $ - SuccessResult $ RunFileOption (MkRunOptions [] Nothing) False ("scriptname", [], [("pqr", "vv")]) + SuccessResult $ RunFileOption (MkRunOptions [] Nothing False) False ("scriptname", [], [("pqr", "vv")]) , testOptions ["--imply", "a=1", "--imply", "b=2", "--imply", "c=3", "scriptname"] $ SuccessResult $ - RunFileOption (MkRunOptions [] Nothing) False ("scriptname", [], [("a", "1"), ("b", "2"), ("c", "3")]) + RunFileOption + (MkRunOptions [] Nothing False) + False + ("scriptname", [], [("a", "1"), ("b", "2"), ("c", "3")]) , testOptions ["-n", "scriptname", "-n"] $ - SuccessResult $ RunFileOption (MkRunOptions [] Nothing) True ("scriptname", ["-n"], []) + SuccessResult $ RunFileOption (MkRunOptions [] Nothing False) True ("scriptname", ["-n"], []) , testOptions ["-I", "incpath", "scriptname"] $ - SuccessResult $ RunFileOption (MkRunOptions ["incpath"] Nothing) False ("scriptname", [], []) + SuccessResult $ RunFileOption (MkRunOptions ["incpath"] Nothing False) False ("scriptname", [], []) , testOptions ["-I", "path1", "-I", "path2", "scriptname"] $ - SuccessResult $ RunFileOption (MkRunOptions ["path1", "path2"] Nothing) False ("scriptname", [], []) + SuccessResult $ + RunFileOption (MkRunOptions ["path1", "path2"] Nothing False) False ("scriptname", [], []) , testOptions ["--include", "incpath", "scriptname"] $ - SuccessResult $ RunFileOption (MkRunOptions ["incpath"] Nothing) False ("scriptname", [], []) + SuccessResult $ RunFileOption (MkRunOptions ["incpath"] Nothing False) False ("scriptname", [], []) , testOptions ["--include", "path1", "--include", "path2", "scriptname"] $ - SuccessResult $ RunFileOption (MkRunOptions ["path1", "path2"] Nothing) False ("scriptname", [], []) + SuccessResult $ + RunFileOption (MkRunOptions ["path1", "path2"] Nothing False) False ("scriptname", [], []) , testOptions ["--data", "dpath", "scriptname"] $ - SuccessResult $ RunFileOption (MkRunOptions [] (Just "dpath")) False ("scriptname", [], []) + SuccessResult $ RunFileOption (MkRunOptions [] (Just "dpath") False) False ("scriptname", [], []) , testOptions ["--data", "dpath", "scriptname", "arg1"] $ - SuccessResult $ RunFileOption (MkRunOptions [] (Just "dpath")) False ("scriptname", ["arg1"], []) + SuccessResult $ RunFileOption (MkRunOptions [] (Just "dpath") False) False ("scriptname", ["arg1"], []) , testOptions ["--data", "dpath", "scriptname", "arg1", "arg2"] $ SuccessResult $ - RunFileOption (MkRunOptions [] (Just "dpath")) False ("scriptname", ["arg1", "arg2"], []) + RunFileOption (MkRunOptions [] (Just "dpath") False) False ("scriptname", ["arg1", "arg2"], []) , testOptions ["-n", "--data", "dpath", "scriptname", "arg1", "arg2"] $ - SuccessResult $ RunFileOption (MkRunOptions [] (Just "dpath")) True ("scriptname", ["arg1", "arg2"], []) + SuccessResult $ + RunFileOption (MkRunOptions [] (Just "dpath") False) True ("scriptname", ["arg1", "arg2"], []) + , testOptions ["-n", "--sloppy", "--data", "dpath", "scriptname", "arg1", "arg2"] $ + SuccessResult $ + RunFileOption (MkRunOptions [] (Just "dpath") True) True ("scriptname", ["arg1", "arg2"], []) ] , testTree "interactive" - [ testOptions ["-i"] $ SuccessResult $ RunInteractiveOption $ MkRunOptions [] Nothing + [ testOptions ["-i"] $ SuccessResult $ RunInteractiveOption $ MkRunOptions [] Nothing False , testOptions ["-i", "--data", "dpath"] $ - SuccessResult $ RunInteractiveOption $ MkRunOptions [] $ Just "dpath" - , testOptions ["--interactive"] $ SuccessResult $ RunInteractiveOption $ MkRunOptions [] Nothing + SuccessResult $ RunInteractiveOption $ MkRunOptions [] (Just "dpath") False + , testOptions ["--interactive"] $ SuccessResult $ RunInteractiveOption $ MkRunOptions [] Nothing False , testOptions ["-I", "incpath", "--interactive"] $ - SuccessResult $ RunInteractiveOption $ MkRunOptions ["incpath"] Nothing + SuccessResult $ RunInteractiveOption $ MkRunOptions ["incpath"] Nothing False , testOptions ["--include", "incpath", "--interactive"] $ - SuccessResult $ RunInteractiveOption $ MkRunOptions ["incpath"] Nothing + SuccessResult $ RunInteractiveOption $ MkRunOptions ["incpath"] Nothing False , testOptions ["--interactive", "-I", "incpath"] $ - SuccessResult $ RunInteractiveOption $ MkRunOptions ["incpath"] Nothing + SuccessResult $ RunInteractiveOption $ MkRunOptions ["incpath"] Nothing False , testOptions ["-I", "path1", "-I", "path2", "--interactive"] $ - SuccessResult $ RunInteractiveOption $ MkRunOptions ["path1", "path2"] Nothing + SuccessResult $ RunInteractiveOption $ MkRunOptions ["path1", "path2"] Nothing False , testOptions ["--include", "path1", "--include", "path2", "--interactive"] $ - SuccessResult $ RunInteractiveOption $ MkRunOptions ["path1", "path2"] Nothing + SuccessResult $ RunInteractiveOption $ MkRunOptions ["path1", "path2"] Nothing False , testOptions ["--interactive", "-I", "path1", "-I", "path2"] $ - SuccessResult $ RunInteractiveOption $ MkRunOptions ["path1", "path2"] Nothing + SuccessResult $ RunInteractiveOption $ MkRunOptions ["path1", "path2"] Nothing False , testOptions ["--interactive", "--data", "dpath"] $ - SuccessResult $ RunInteractiveOption $ MkRunOptions [] $ Just "dpath" + SuccessResult $ RunInteractiveOption $ MkRunOptions [] (Just "dpath") False + , testOptions ["--interactive", "--sloppy", "--data", "dpath"] $ + SuccessResult $ RunInteractiveOption $ MkRunOptions [] (Just "dpath") True ] ] diff --git a/Pinafore/pinafore-app/app/main/test/option-help.ref b/Pinafore/pinafore-app/app/main/test/option-help.ref index d74335bd1..b659f3e38 100644 --- a/Pinafore/pinafore-app/app/main/test/option-help.ref +++ b/Pinafore/pinafore-app/app/main/test/option-help.ref @@ -2,5 +2,5 @@ Invalid option `--help' Usage: pinafore ((-v|--version) | ((-i|--interactive) | [-n|--no-run] [--imply name=value] PATH) - [-I|--include PATH] [--data PATH] | + [-I|--include PATH] [--data PATH] [--sloppy] | --dump-table [--data PATH]) diff --git a/Pinafore/pinafore-app/benchmark/Main.hs b/Pinafore/pinafore-app/benchmark/Main.hs index ccb3d0337..2f5466223 100644 --- a/Pinafore/pinafore-app/benchmark/Main.hs +++ b/Pinafore/pinafore-app/benchmark/Main.hs @@ -27,17 +27,18 @@ benchHashes = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" ] -getBenchEnv :: IO (() -> LibraryContext) +getBenchEnv :: IO (() -> InterpretBehaviour) getBenchEnv = let - library = mkLibraryContext $ libraryLoadModule appLibrary - in return $ \() -> library + ibLoadModule = libraryLoadModule appLibrary + ibSloppy = False + in return $ \() -> MkInterpretBehaviour {..} benchScript :: Text -> Benchmark benchScript text = env getBenchEnv $ \tpc -> let - library = tpc () + behaviour = tpc () in let - ?library = library + ?behaviour = behaviour in bgroup (show $ unpack text) [ bench "check" $ diff --git a/Pinafore/pinafore-app/lib/Pinafore/Options.hs b/Pinafore/pinafore-app/lib/Pinafore/Options.hs index 1eb7dd15d..037758a7b 100644 --- a/Pinafore/pinafore-app/lib/Pinafore/Options.hs +++ b/Pinafore/pinafore-app/lib/Pinafore/Options.hs @@ -13,6 +13,7 @@ import System.FilePath data RunOptions = MkRunOptions { roIncludeDirs :: [FilePath] , roDataDir :: Maybe FilePath + , roSloppy :: Bool } deriving (Eq, Show) getModuleOptions :: RunOptions -> IO ModuleOptions diff --git a/Pinafore/pinafore-app/test/Test/Library.hs b/Pinafore/pinafore-app/test/Test/Library.hs index 4bae777b0..948bd5b86 100644 --- a/Pinafore/pinafore-app/test/Test/Library.hs +++ b/Pinafore/pinafore-app/test/Test/Library.hs @@ -19,11 +19,12 @@ testLibrary = moduleNames :: [ModuleName] moduleNames = fmap lmName appLibrary in let - ?library = standardLibraryContext MkModuleOptions {..} + ?behaviour = MkInterpretBehaviour + {ibSloppy = False, ibLoadModule = standardLoadModule MkModuleOptions {..}} in for_ moduleNames $ \modname -> do mmod <- fromInterpretResult $ - runPinaforeScoped (show modname) $ runLoadModule (lcLoadModule ?library) modname + runPinaforeScoped (show modname) $ runLoadModule (ibLoadModule ?behaviour) modname pmodule <- maybeToM (show modname <> ": not found") mmod for_ (moduleScopeEntries pmodule) $ \(_, binfo) -> do let oname = biOriginalName binfo diff --git a/Pinafore/pinafore-docgen/app/Options.hs b/Pinafore/pinafore-docgen/app/Options.hs index 7716b796e..6d75a5329 100644 --- a/Pinafore/pinafore-docgen/app/Options.hs +++ b/Pinafore/pinafore-docgen/app/Options.hs @@ -22,7 +22,7 @@ optDataPath :: Parser (Maybe FilePath) optDataPath = optional $ strOption $ long "data" <> metavar "PATH" optRunOptions :: Parser RunOptions -optRunOptions = MkRunOptions <$> optIncludes <*> optDataPath +optRunOptions = MkRunOptions <$> optIncludes <*> optDataPath <*> switch (long "sloppy") optParser :: Parser Options optParser = diff --git a/Pinafore/pinafore-docgen/lib/Pinafore/DocGen.hs b/Pinafore/pinafore-docgen/lib/Pinafore/DocGen.hs index f8603d224..f86d9ed37 100644 --- a/Pinafore/pinafore-docgen/lib/Pinafore/DocGen.hs +++ b/Pinafore/pinafore-docgen/lib/Pinafore/DocGen.hs @@ -24,7 +24,7 @@ trimDoc (MkTree n children) = MkTree n $ trimDocChildren children generateCommonMarkDoc :: Handle -> ModuleOptions -> ModuleName -> IO () generateCommonMarkDoc outh modopts modname = do - let ?library = standardLibraryContext modopts + let ?behaviour = MkInterpretBehaviour {ibLoadModule = standardLoadModule modopts, ibSloppy = False} docs <- getModuleDocs modname let runDocTree :: Int -> Int -> Tree DefDoc -> IO () diff --git a/Pinafore/pinafore-docgen/test/Main.hs b/Pinafore/pinafore-docgen/test/Main.hs index f718b46ab..5e83b8338 100644 --- a/Pinafore/pinafore-docgen/test/Main.hs +++ b/Pinafore/pinafore-docgen/test/Main.hs @@ -29,6 +29,7 @@ main = do let roIncludeDirs = ["test" "golden"] roDataDir = Nothing + roSloppy = False mo <- getModuleOptions MkRunOptions {..} let testGolden :: TestTree diff --git a/Pinafore/pinafore-language/lib/Pinafore/Documentation.hs b/Pinafore/pinafore-language/lib/Pinafore/Documentation.hs index 5b12082c7..3e1514d31 100644 --- a/Pinafore/pinafore-language/lib/Pinafore/Documentation.hs +++ b/Pinafore/pinafore-language/lib/Pinafore/Documentation.hs @@ -48,7 +48,7 @@ libraryTypeNames lm = toList (lmContents lm) >>= bindDocTypeName allTypeNames :: [Name] allTypeNames = filter (not . nameIsInfix) $ sort $ nub $ pinaforeLibrary >>= libraryTypeNames -getModuleDocs :: (?library :: LibraryContext) => ModuleName -> IO Docs +getModuleDocs :: (?behaviour :: InterpretBehaviour) => ModuleName -> IO Docs getModuleDocs modname = do qmodule <- fromInterpretResult $ runPinaforeScoped "" $ getModule modname return $ moduleDoc qmodule diff --git a/Pinafore/pinafore-language/lib/Pinafore/Language.hs b/Pinafore/pinafore-language/lib/Pinafore/Language.hs index 0390f98b6..3660f70dc 100644 --- a/Pinafore/pinafore-language/lib/Pinafore/Language.hs +++ b/Pinafore/pinafore-language/lib/Pinafore/Language.hs @@ -7,8 +7,7 @@ module Pinafore.Language , libraryLoadModule , QModule(..) , getModule - , LibraryContext(..) - , mkLibraryContext + , InterpretBehaviour(..) , pinaforeLibrary , QError , fromParseResult @@ -42,7 +41,7 @@ import Pinafore.Language.Interpreter import Pinafore.Language.Library import Pinafore.Language.Var -interact :: (?library :: LibraryContext) => Handle -> Handle -> Bool -> View () +interact :: (?behaviour :: InterpretBehaviour) => Handle -> Handle -> Bool -> View () interact inh outh echo = do liftIO $ hSetBuffering outh NoBuffering runInteract inh outh echo $ fromInterpretResult . runPinaforeScoped "" diff --git a/Pinafore/pinafore-language/lib/Pinafore/Language/Error.hs b/Pinafore/pinafore-language/lib/Pinafore/Language/Error.hs index ad3c1b91f..c2d2ba8b7 100644 --- a/Pinafore/pinafore-language/lib/Pinafore/Language/Error.hs +++ b/Pinafore/pinafore-language/lib/Pinafore/Language/Error.hs @@ -2,9 +2,21 @@ module Pinafore.Language.Error where import Import +data QWarningType = + TestQWarningType + +instance ShowNamedText QWarningType where + showNamedText TestQWarningType = "test warning" + +type QWarning = SourceError QWarningType + +emitWarning :: QWarning -> IO () +emitWarning w = hPutStrLn stderr $ unpack $ "warning: " <> (toText $ showNamedText w) + data QErrorType = InternalError (Maybe Int) NamedText + | WarningError QWarningType | UnicodeDecodeError NamedText | ParserError ParseErrorType | PatternErrorError PatternError @@ -83,6 +95,7 @@ instance ShowNamedText QErrorType where (Just n, _) -> "INTERNAL ERROR: " <> toNamedText t <> " (issue #" <> showNamedText n <> ")" (Nothing, "") -> "INTERNAL ERROR" (Nothing, _) -> "INTERNAL ERROR: " <> toNamedText t + showNamedText (WarningError w) = showNamedText w <> " (use --sloppy to ignore)" showNamedText (UnicodeDecodeError t) = "Unicode decode error: " <> t showNamedText (ParserError err) = showNamedText err showNamedText (PatternErrorError e) = showNamedText e diff --git a/Pinafore/pinafore-language/lib/Pinafore/Language/Interpret.hs b/Pinafore/pinafore-language/lib/Pinafore/Language/Interpret.hs index 86a437e50..24d7b74ba 100644 --- a/Pinafore/pinafore-language/lib/Pinafore/Language/Interpret.hs +++ b/Pinafore/pinafore-language/lib/Pinafore/Language/Interpret.hs @@ -64,8 +64,8 @@ parseToValueSubsume t text = do val <- parseToValue text [] tsSubsumeValue @QTypeSystem t val -runPinaforeScoped :: (?library :: LibraryContext) => String -> QInterpreter a -> InterpretResult a +runPinaforeScoped :: (?behaviour :: InterpretBehaviour) => String -> QInterpreter a -> InterpretResult a runPinaforeScoped sourcename ma = - runInterpreter (initialPos sourcename) ?library $ do + runInterpreter (initialPos sourcename) ?behaviour $ do sd <- interpretImportDeclaration builtInModuleName withScopeDocs sd ma diff --git a/Pinafore/pinafore-language/lib/Pinafore/Language/Interpreter/Interpreter.hs b/Pinafore/pinafore-language/lib/Pinafore/Language/Interpreter/Interpreter.hs index e6715e67a..ca51b3d73 100644 --- a/Pinafore/pinafore-language/lib/Pinafore/Language/Interpreter/Interpreter.hs +++ b/Pinafore/pinafore-language/lib/Pinafore/Language/Interpreter/Interpreter.hs @@ -2,16 +2,17 @@ module Pinafore.Language.Interpreter.Interpreter ( QInterpreter + , warn , LoadModule(..) , nameWitnessErrorType , sourcePosParam , varIDStateParam , scopeParam - , loadModuleParam + , behaviourParam , currentNamespaceParam , appNotationVarRef , appNotationBindsProd - , LibraryContext(..) + , InterpretBehaviour(..) , runInterpreter , getRenderFullName , getBindingInfoLookup @@ -50,13 +51,18 @@ instance Semigroup LoadModule where instance Monoid LoadModule where mempty = MkLoadModule $ \_ -> return Nothing +data InterpretBehaviour = MkInterpretBehaviour + { ibLoadModule :: LoadModule + , ibSloppy :: Bool + } + data InterpretContext = MkInterpretContext { icSourcePos :: SourcePos , icVarIDState :: VarIDState , icScope :: QScope , icCurrentNamespace :: Namespace , icModulePath :: [ModuleName] - , icLoadModule :: LoadModule + , icBehvaiour :: InterpretBehaviour } data InterpretState = MkInterpretState @@ -104,12 +110,21 @@ instance MonadCoroutine QInterpreter where instance MonadThrow QErrorType QInterpreter where throw err = do - em <- mkErrorMessage - throw $ em err + mm <- mkErrorMessage + throw $ mm err instance MonadThrow PatternError QInterpreter where throw err = throw $ PatternErrorError err +warn :: QWarningType -> QInterpreter () +warn wt = do + sloppy <- paramAsks behaviourParam ibSloppy + if sloppy + then do + mm <- mkWarningMessage + liftIO $ emitWarning $ mm wt + else throw $ WarningError wt + -- Left if at least one a splitNonEmpty :: NonEmpty (Either a b) -> Either (NonEmpty a) (NonEmpty b) splitNonEmpty (Left a :| r) = Left $ a :| lefts r @@ -147,6 +162,10 @@ instance HasInterpreter where spos <- paramAsk sourcePosParam ntt <- getRenderFullName return $ MkSourceError spos ntt + mkWarningMessage = do + spos <- paramAsk sourcePosParam + ntt <- getRenderFullName + return $ MkSourceError spos ntt getSubtypeConversions = fmap (toList . scopeSubtypes) $ paramAsk scopeParam contextParam :: Param QInterpreter InterpretContext @@ -171,8 +190,11 @@ currentNamespaceParam = modulePathParam :: Param QInterpreter [ModuleName] modulePathParam = lensMapParam (\bfb a -> fmap (\b -> a {icModulePath = b}) $ bfb $ icModulePath a) contextParam +behaviourParam :: Param QInterpreter InterpretBehaviour +behaviourParam = lensMapParam (\bfb a -> fmap (\b -> a {icBehvaiour = b}) $ bfb $ icBehvaiour a) contextParam + loadModuleParam :: Param QInterpreter LoadModule -loadModuleParam = lensMapParam (\bfb a -> fmap (\b -> a {icLoadModule = b}) $ bfb $ icLoadModule a) contextParam +loadModuleParam = lensMapParam (\bfb a -> fmap (\b -> a {ibLoadModule = b}) $ bfb $ ibLoadModule a) behaviourParam interpretStateRef :: Ref QInterpreter InterpretState interpretStateRef = let @@ -194,17 +216,12 @@ appNotationVarRef :: Ref QInterpreter VarIDState appNotationVarRef = lensMapRef (\bfb a -> fmap (\b -> a {isAppNotationVar = b}) $ bfb $ isAppNotationVar a) interpretStateRef -data LibraryContext = MkLibraryContext - { lcLoadModule :: LoadModule - } - -runInterpreter :: SourcePos -> LibraryContext -> QInterpreter a -> InterpretResult a -runInterpreter icSourcePos MkLibraryContext {..} qa = let +runInterpreter :: SourcePos -> InterpretBehaviour -> QInterpreter a -> InterpretResult a +runInterpreter icSourcePos icBehvaiour qa = let icVarIDState = szero icScope = emptyScope icModulePath = [] icCurrentNamespace = RootNamespace - icLoadModule = lcLoadModule in evalStateT (evalWriterT $ runReaderT (unInterpreter qa) $ MkInterpretContext {..}) emptyInterpretState firstOf :: [a] -> (a -> Maybe b) -> Maybe b diff --git a/Pinafore/pinafore-language/lib/Pinafore/Language/Library.hs b/Pinafore/pinafore-language/lib/Pinafore/Language/Library.hs index 33cd1aff3..53c2da3b7 100644 --- a/Pinafore/pinafore-language/lib/Pinafore/Language/Library.hs +++ b/Pinafore/pinafore-language/lib/Pinafore/Language/Library.hs @@ -7,7 +7,6 @@ module Pinafore.Language.Library , directoryLoadModule , textLoadModule , libraryLoadModule - , mkLibraryContext , nameIsInfix ) where @@ -64,8 +63,3 @@ pinaforeLibrary = , pinaforeLibSection , debugLibSection ] - -mkLibraryContext :: LoadModule -> LibraryContext -mkLibraryContext lm = let - lcLoadModule = lm - in MkLibraryContext {..} diff --git a/Pinafore/pinafore-language/lib/Pinafore/Language/Library/Pinafore.hs b/Pinafore/pinafore-language/lib/Pinafore/Language/Library/Pinafore.hs index 3518727b7..633f0b22e 100644 --- a/Pinafore/pinafore-language/lib/Pinafore/Language/Library/Pinafore.hs +++ b/Pinafore/pinafore-language/lib/Pinafore/Language/Library/Pinafore.hs @@ -18,22 +18,22 @@ import Pinafore.Language.Var -- QContext newtype QContext = - MkQContext LibraryContext + MkQContext InterpretBehaviour instance HasQGroundType '[] QContext where qGroundType = stdSingleGroundType $(iowitness [t|'MkWitKind (SingletonFamily QContext)|]) "Context.Pinafore." thisContext :: QInterpreter LangExpression thisContext = do - lm <- paramAsk loadModuleParam + behaviour <- paramAsk behaviourParam let sval :: QContext - sval = MkQContext $ MkLibraryContext lm + sval = MkQContext behaviour return $ MkLangExpression $ constSealedExpression $ MkSomeOf qType sval langRunInterpreter :: QContext -> QInterpreter A -> Action (Result Text A) langRunInterpreter (MkQContext lc) ia = let - ?library = lc + ?behaviour = lc in do rea <- runInterpretResult $ runPinaforeScoped "" ia return $ mapResultFailure showText rea @@ -105,30 +105,35 @@ pinaforeLibSection = [ let defaultloadModule :: Text -> QInterpreter (Maybe QScopeDocs) defaultloadModule _ = return Nothing - rtype :: ListType QDocSignature '[ Text -> QInterpreter (Maybe QScopeDocs)] + rtype :: ListType QDocSignature '[ Bool, Text -> QInterpreter (Maybe QScopeDocs)] rtype = + ConsListType (ValueDocSignature @Bool "sloppy" "" qType $ Just $ pure False) $ ConsListType (ValueDocSignature @(Text -> QInterpreter (Maybe QScopeDocs)) "loadModule" "" qType $ Just $ pure defaultloadModule) NilListType - qContextLoadModule :: QContext -> Text -> QInterpreter (Maybe QScopeDocs) - qContextLoadModule (MkQContext lc) name = do - mqm <- runLoadModule (lcLoadModule lc) $ MkModuleName name + fromLoadModule :: LoadModule -> Text -> QInterpreter (Maybe QScopeDocs) + fromLoadModule lm name = do + mqm <- runLoadModule lm $ MkModuleName name return $ fmap moduleScopeDocs mqm toLoadModule :: (Text -> QInterpreter (Maybe QScopeDocs)) -> LoadModule toLoadModule lm = MkLoadModule $ \(MkModuleName name) -> do msdocs <- lm name for msdocs scopeDocsModule - fromQContext :: QContext -> Maybe (ListVProduct '[ Text -> QInterpreter (Maybe QScopeDocs)]) - fromQContext qc = - Just $ listProductToVProduct (listTypeToVType rtype) (qContextLoadModule qc, ()) - toQContext :: ListVProduct '[ Text -> QInterpreter (Maybe QScopeDocs)] -> QContext + fromQContext :: + QContext -> Maybe (ListVProduct '[ Bool, Text -> QInterpreter (Maybe QScopeDocs)]) + fromQContext (MkQContext (MkInterpretBehaviour {..})) = + Just $ + listProductToVProduct + (listTypeToVType rtype) + (ibSloppy, (fromLoadModule ibLoadModule, ())) + toQContext :: ListVProduct '[ Bool, Text -> QInterpreter (Maybe QScopeDocs)] -> QContext toQContext lvp = let - (lm, ()) = listVProductToProduct lvp - lcLoadModule = toLoadModule lm - in MkQContext $ MkLibraryContext {..} - codec :: Codec QContext (ListVProduct '[ Text -> QInterpreter (Maybe QScopeDocs)]) + (ibSloppy, (lm, ())) = listVProductToProduct lvp + ibLoadModule = toLoadModule lm + in MkQContext $ MkInterpretBehaviour {..} + codec :: Codec QContext (ListVProduct '[ Bool, Text -> QInterpreter (Maybe QScopeDocs)]) codec = MkCodec fromQContext toQContext in recordConsBDS "Mk" "" rtype codec ] diff --git a/Pinafore/pinafore-language/lib/Pinafore/Language/Type/Ground.hs b/Pinafore/pinafore-language/lib/Pinafore/Language/Type/Ground.hs index 02fffc390..641b857a4 100644 --- a/Pinafore/pinafore-language/lib/Pinafore/Language/Type/Ground.hs +++ b/Pinafore/pinafore-language/lib/Pinafore/Language/Type/Ground.hs @@ -72,6 +72,7 @@ class ( Monad Interpreter type Interpreter :: Type -> Type getSubtypeConversions :: Interpreter [QSubtypeConversionEntry] mkErrorMessage :: Interpreter (QErrorType -> QError) + mkWarningMessage :: Interpreter (QWarningType -> QWarning) instance HasInterpreter => ExprShow (QGroundType dv gt) where exprShowPrec = exprShowPrecGroundType diff --git a/Pinafore/pinafore-language/lib/Pinafore/Main.hs b/Pinafore/pinafore-language/lib/Pinafore/Main.hs index e2362da57..0fade97a5 100644 --- a/Pinafore/pinafore-language/lib/Pinafore/Main.hs +++ b/Pinafore/pinafore-language/lib/Pinafore/Main.hs @@ -6,7 +6,8 @@ module Pinafore.Main , RunWithOptions(..) , ModuleOptions(..) , module Pinafore.Context - , standardLibraryContext + , InterpretBehaviour(..) + , standardLoadModule , pinaforeLibrary , sqliteQDumpTable , qInterpretTextAtType @@ -76,9 +77,6 @@ standardLoadModule MkModuleOptions {..} = let dirLoadModule = mconcat $ fmap directoryLoadModule moModuleDirs in libLoadModule <> dirLoadModule -standardLibraryContext :: ModuleOptions -> LibraryContext -standardLibraryContext modopts = mkLibraryContext $ standardLoadModule modopts - sqliteQDumpTable :: FilePath -> IO () sqliteQDumpTable dirpath = do MkAllFor tables <- sqliteTableGetEntireDatabase emptyResourceContext $ dirpath "tables.sqlite3" @@ -96,7 +94,7 @@ sqliteQDumpTable dirpath = do in putStrLn $ show p ++ " " ++ show s ++ " = " ++ lv qInterpretTextAtType :: - forall t m. (?library :: LibraryContext, HasQType QPolyShim 'Negative t, MonadIO m, MonadThrow QError m) + forall t m. (?behaviour :: InterpretBehaviour, HasQType QPolyShim 'Negative t, MonadIO m, MonadThrow QError m) => FilePath -> Text -> [String] @@ -108,7 +106,7 @@ qInterpretTextAtType puipath puitext args impls = let runPinaforeScoped puipath $ parseToValueUnify puitext $ (MkImplicitName "arglist", arglist) : impls qInterpretScriptText :: - (?library :: LibraryContext, MonadIO m, MonadThrow QError m) + (?behaviour :: InterpretBehaviour, MonadIO m, MonadThrow QError m) => FilePath -> Text -> [String] @@ -118,14 +116,14 @@ qInterpretScriptText puipath puitext args impls = do action <- qInterpretTextAtType @(Action TopType) puipath puitext args impls return $ runAction $ fmap (\MkTopType -> ()) $ action -qInterpretScriptFile :: (?library :: LibraryContext) => FilePath -> [String] -> [(Text, Text)] -> View (View ()) +qInterpretScriptFile :: (?behaviour :: InterpretBehaviour) => FilePath -> [String] -> [(Text, Text)] -> View (View ()) qInterpretScriptFile fpath args implArgs = do ptext <- liftIO $ readFile fpath let impls = fmap (\(n, v) -> (MkImplicitName $ MkName n, qToValue v)) implArgs qInterpretScriptText fpath (decodeUtf8 $ toStrict ptext) args impls -qInteractHandles :: (?library :: LibraryContext) => Handle -> Handle -> Bool -> View () +qInteractHandles :: (?behaviour :: InterpretBehaviour) => Handle -> Handle -> Bool -> View () qInteractHandles inh outh echo = interact inh outh echo -qInteract :: (?library :: LibraryContext) => View () +qInteract :: (?behaviour :: InterpretBehaviour) => View () qInteract = qInteractHandles stdin stdout False diff --git a/Pinafore/pinafore-language/lib/Pinafore/Test.hs b/Pinafore/pinafore-language/lib/Pinafore/Test.hs index f362dcbe9..8f255d04c 100644 --- a/Pinafore/pinafore-language/lib/Pinafore/Test.hs +++ b/Pinafore/pinafore-language/lib/Pinafore/Test.hs @@ -20,7 +20,7 @@ module Pinafore.Test , testerGetTableState , libraryLoadModule , directoryLoadModule - , lcLoadModule + , ibLoadModule , qInterpretTextAtType ) where @@ -77,6 +77,7 @@ data TesterOptions = MkTesterOptions { tstExecutionOptions :: ExecutionOptions , tstOutput :: Handle , tstLibrary :: [LibraryModule] + , tstSloppy :: Bool } defaultTester :: TesterOptions @@ -84,11 +85,12 @@ defaultTester = let tstExecutionOptions = defaultExecutionOptions tstOutput = stdout tstLibrary = pinaforeLibrary + tstSloppy = False in MkTesterOptions {..} data TesterContext = MkTesterContext { tcStorageModel :: Model QStorageUpdate - , tcLibrary :: LibraryContext + , tcInterpretBehaviour :: InterpretBehaviour , tcGetTableState :: View QTableSubject } @@ -121,9 +123,12 @@ runTester MkTesterOptions {..} (MkTester ta) = namespaceBDS "Env" [valBDS "stdout" "OVERRIDDEN" $ MkLangSink outputSink, valBDS "outputLn" "OVERRIDDEN" testOutputLn] - tcLibrary = - mkLibraryContext $ + ibSloppy :: Bool + ibSloppy = tstSloppy + ibLoadModule :: LoadModule + ibLoadModule = libraryLoadModule $ overrideLibraryModule builtInModuleName (\lib -> lib <> myLibStuff) tstLibrary + tcInterpretBehaviour = MkInterpretBehaviour {..} runView $ runReaderT ta $ MkTesterContext {..} contextParam :: Param Tester TesterContext @@ -133,20 +138,20 @@ testerLoad :: LoadModule -> Tester --> Tester testerLoad lm = paramLocal contextParam $ \tc -> tc - { tcLibrary = + { tcInterpretBehaviour = let - tcl = tcLibrary tc - in tcl {lcLoadModule = lcLoadModule tcl <> lm} + tcl = tcInterpretBehaviour tc + in tcl {ibLoadModule = ibLoadModule tcl <> lm} } testerLoadLibrary :: [LibraryModule] -> Tester --> Tester testerLoadLibrary lms = testerLoad $ libraryLoadModule lms -testerLiftView :: forall a. ((?library :: LibraryContext) => View a) -> Tester a +testerLiftView :: forall a. ((?behaviour :: InterpretBehaviour) => View a) -> Tester a testerLiftView va = MkTester $ ReaderT $ \MkTesterContext {..} -> let - ?library = tcLibrary + ?behaviour = tcInterpretBehaviour in va testerRunAction :: Action () -> Tester () @@ -155,10 +160,10 @@ testerRunAction pa = testerLiftView $ runAction pa testerLiftAction :: Action --> Tester testerLiftAction pa = testerLiftView $ unliftActionOrFail pa -testerLiftInterpreterPath :: forall a. FilePath -> ((?library :: LibraryContext) => QInterpreter a) -> Tester a +testerLiftInterpreterPath :: forall a. FilePath -> ((?behaviour :: InterpretBehaviour) => QInterpreter a) -> Tester a testerLiftInterpreterPath fpath pia = testerLiftView $ fromInterpretResult $ runPinaforeScoped fpath pia -testerLiftInterpreter :: forall a. ((?library :: LibraryContext) => QInterpreter a) -> Tester a +testerLiftInterpreter :: forall a. ((?behaviour :: InterpretBehaviour) => QInterpreter a) -> Tester a testerLiftInterpreter = testerLiftInterpreterPath "" testerGetStore :: Tester QStore diff --git a/Pinafore/pinafore-lib-script/test/Main.hs b/Pinafore/pinafore-lib-script/test/Main.hs index 00c7c2aad..ef607c2d7 100644 --- a/Pinafore/pinafore-lib-script/test/Main.hs +++ b/Pinafore/pinafore-lib-script/test/Main.hs @@ -17,7 +17,7 @@ testCheckModule name = runTester defaultTester $ testerLoadLibrary (mediaLibrary <> gnomeLibrary) $ testerLoad (directoryLoadModule scriptLibDir) $ do - mm <- testerLiftInterpreter $ runLoadModule (lcLoadModule ?library) $ fromString name + mm <- testerLiftInterpreter $ runLoadModule (ibLoadModule ?behaviour) $ fromString name case mm of Just _ -> return () Nothing -> fail "module not found"