packages feed

futhark 0.21.7 → 0.21.8

raw patch · 42 files changed

+1104/−700 lines, 42 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Futhark.Compiler: readProgram :: (MonadError CompilerError m, MonadIO m) => [Name] -> FilePath -> m (Warnings, Imports, VNameSource)
- Futhark.Construct: letSubExps :: MonadBuilder m => String -> [Exp (Rep m)] -> m [SubExp]
- Futhark.IR.Aliases: addAliasesToPat :: (ASTRep rep, CanBeAliased (Op rep), Typed dec) => Pat dec -> Exp (Aliases rep) -> Pat (VarAliases, dec)
- Futhark.IR.Aliases: mkAliasedLetStm :: (ASTRep rep, CanBeAliased (Op rep)) => Pat (LetDec rep) -> StmAux (ExpDec rep) -> Exp (Aliases rep) -> Stm (Aliases rep)
- Futhark.IR.Aliases: mkBodyAliases :: Aliased rep => Stms rep -> Result -> BodyAliasing
- Futhark.IR.Aliases: mkPatAliases :: (Aliased rep, Typed dec) => Pat dec -> Exp rep -> [PatElem (VarAliases, dec)]
- Language.Futhark.Parser: data ParseError
- Language.Futhark.Parser.Monad: ParseError :: String -> ParseError
- Language.Futhark.Parser.Monad: instance GHC.Show.Show Language.Futhark.Parser.Monad.ParseError
- Language.Futhark.Parser.Monad: newtype ParseError
- Language.Futhark.TypeChecker.Terms.Pat: checkPat :: [SizeBinder VName] -> UncheckedPat -> InferredType -> (Pat -> TermTypeM a) -> TermTypeM a
+ Futhark.CLI.Literate: instance GHC.Show.Show Futhark.CLI.Literate.ImgParams
+ Futhark.Compiler: pprProgramErrors :: NonEmpty ProgramError -> Doc
+ Futhark.Compiler: readProgramFile :: (MonadError CompilerError m, MonadIO m) => [Name] -> FilePath -> m (Warnings, Imports, VNameSource)
+ Futhark.Compiler: readProgramFiles :: (MonadError CompilerError m, MonadIO m) => [Name] -> [FilePath] -> m (Warnings, Imports, VNameSource)
+ Futhark.Compiler.Program: ProgramError :: Loc -> Doc -> ProgramError
+ Futhark.Compiler.Program: data ProgramError
+ Futhark.IR.Aliases: mkAliasedPat :: (Aliased rep, Typed dec) => Pat dec -> Exp rep -> Pat (VarAliases, dec)
+ Futhark.IR.Aliases: mkBodyAliasing :: Aliased rep => Stms rep -> Result -> BodyAliasing
+ Language.Futhark.Parser: SyntaxError :: Loc -> String -> SyntaxError
+ Language.Futhark.Parser: [syntaxErrorLoc] :: SyntaxError -> Loc
+ Language.Futhark.Parser: [syntaxErrorMsg] :: SyntaxError -> String
+ Language.Futhark.Parser: data SyntaxError
+ Language.Futhark.Parser.Lexer.Tokens: APOSTROPHE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: APOSTROPHE_THEN_HAT :: Token
+ Language.Futhark.Parser.Lexer.Tokens: APOSTROPHE_THEN_TILDE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: ASSERT :: Token
+ Language.Futhark.Parser.Lexer.Tokens: ASTERISK :: Token
+ Language.Futhark.Parser.Lexer.Tokens: BACKSLASH :: Token
+ Language.Futhark.Parser.Lexer.Tokens: BACKTICK :: Token
+ Language.Futhark.Parser.Lexer.Tokens: BANG :: Token
+ Language.Futhark.Parser.Lexer.Tokens: CASE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: CHARLIT :: Char -> Token
+ Language.Futhark.Parser.Lexer.Tokens: COLON :: Token
+ Language.Futhark.Parser.Lexer.Tokens: COLON_GT :: Token
+ Language.Futhark.Parser.Lexer.Tokens: COMMA :: Token
+ Language.Futhark.Parser.Lexer.Tokens: CONSTRUCTOR :: Name -> Token
+ Language.Futhark.Parser.Lexer.Tokens: DEF :: Token
+ Language.Futhark.Parser.Lexer.Tokens: DO :: Token
+ Language.Futhark.Parser.Lexer.Tokens: DOC :: String -> Token
+ Language.Futhark.Parser.Lexer.Tokens: DOLLAR :: Token
+ Language.Futhark.Parser.Lexer.Tokens: DOT :: Token
+ Language.Futhark.Parser.Lexer.Tokens: ELSE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: ENTRY :: Token
+ Language.Futhark.Parser.Lexer.Tokens: EOF :: Token
+ Language.Futhark.Parser.Lexer.Tokens: EQU :: Token
+ Language.Futhark.Parser.Lexer.Tokens: F16LIT :: Half -> Token
+ Language.Futhark.Parser.Lexer.Tokens: F32LIT :: Float -> Token
+ Language.Futhark.Parser.Lexer.Tokens: F64LIT :: Double -> Token
+ Language.Futhark.Parser.Lexer.Tokens: FALSE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: FLOATLIT :: Double -> Token
+ Language.Futhark.Parser.Lexer.Tokens: FOR :: Token
+ Language.Futhark.Parser.Lexer.Tokens: HASH_LBRACKET :: Token
+ Language.Futhark.Parser.Lexer.Tokens: HAT :: Token
+ Language.Futhark.Parser.Lexer.Tokens: I16LIT :: Int16 -> Token
+ Language.Futhark.Parser.Lexer.Tokens: I32LIT :: Int32 -> Token
+ Language.Futhark.Parser.Lexer.Tokens: I64LIT :: Int64 -> Token
+ Language.Futhark.Parser.Lexer.Tokens: I8LIT :: Int8 -> Token
+ Language.Futhark.Parser.Lexer.Tokens: ID :: Name -> Token
+ Language.Futhark.Parser.Lexer.Tokens: IF :: Token
+ Language.Futhark.Parser.Lexer.Tokens: IMPORT :: Token
+ Language.Futhark.Parser.Lexer.Tokens: IN :: Token
+ Language.Futhark.Parser.Lexer.Tokens: INCLUDE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: INDEXING :: Name -> Token
+ Language.Futhark.Parser.Lexer.Tokens: INTLIT :: Integer -> Token
+ Language.Futhark.Parser.Lexer.Tokens: LBRACKET :: Token
+ Language.Futhark.Parser.Lexer.Tokens: LCURLY :: Token
+ Language.Futhark.Parser.Lexer.Tokens: LET :: Token
+ Language.Futhark.Parser.Lexer.Tokens: LOCAL :: Token
+ Language.Futhark.Parser.Lexer.Tokens: LOOP :: Token
+ Language.Futhark.Parser.Lexer.Tokens: LPAR :: Token
+ Language.Futhark.Parser.Lexer.Tokens: LTH :: Token
+ Language.Futhark.Parser.Lexer.Tokens: MATCH :: Token
+ Language.Futhark.Parser.Lexer.Tokens: MODULE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: NEGATE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: OPEN :: Token
+ Language.Futhark.Parser.Lexer.Tokens: PIPE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: PROJ_INTFIELD :: Name -> Token
+ Language.Futhark.Parser.Lexer.Tokens: QUALINDEXING :: [Name] -> Name -> Token
+ Language.Futhark.Parser.Lexer.Tokens: QUALPAREN :: [Name] -> Name -> Token
+ Language.Futhark.Parser.Lexer.Tokens: QUESTION_MARK :: Token
+ Language.Futhark.Parser.Lexer.Tokens: RBRACKET :: Token
+ Language.Futhark.Parser.Lexer.Tokens: RCURLY :: Token
+ Language.Futhark.Parser.Lexer.Tokens: RIGHT_ARROW :: Token
+ Language.Futhark.Parser.Lexer.Tokens: RPAR :: Token
+ Language.Futhark.Parser.Lexer.Tokens: RPAR_THEN_LBRACKET :: Token
+ Language.Futhark.Parser.Lexer.Tokens: STRINGLIT :: Text -> Token
+ Language.Futhark.Parser.Lexer.Tokens: SYMBOL :: BinOp -> [Name] -> Name -> Token
+ Language.Futhark.Parser.Lexer.Tokens: THEN :: Token
+ Language.Futhark.Parser.Lexer.Tokens: THREE_DOTS :: Token
+ Language.Futhark.Parser.Lexer.Tokens: TILDE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: TRUE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: TWO_DOTS :: Token
+ Language.Futhark.Parser.Lexer.Tokens: TWO_DOTS_GT :: Token
+ Language.Futhark.Parser.Lexer.Tokens: TWO_DOTS_LT :: Token
+ Language.Futhark.Parser.Lexer.Tokens: TYPE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: U16LIT :: Word16 -> Token
+ Language.Futhark.Parser.Lexer.Tokens: U32LIT :: Word32 -> Token
+ Language.Futhark.Parser.Lexer.Tokens: U64LIT :: Word64 -> Token
+ Language.Futhark.Parser.Lexer.Tokens: U8LIT :: Word8 -> Token
+ Language.Futhark.Parser.Lexer.Tokens: UNDERSCORE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: VAL :: Token
+ Language.Futhark.Parser.Lexer.Tokens: WHILE :: Token
+ Language.Futhark.Parser.Lexer.Tokens: WITH :: Token
+ Language.Futhark.Parser.Lexer.Tokens: data Token
+ Language.Futhark.Parser.Lexer.Tokens: fromRoman :: Integral a => Text -> a
+ Language.Futhark.Parser.Lexer.Tokens: indexing :: (Loc, Text) -> Alex Name
+ Language.Futhark.Parser.Lexer.Tokens: instance GHC.Classes.Eq Language.Futhark.Parser.Lexer.Tokens.Token
+ Language.Futhark.Parser.Lexer.Tokens: instance GHC.Classes.Ord Language.Futhark.Parser.Lexer.Tokens.Token
+ Language.Futhark.Parser.Lexer.Tokens: instance GHC.Show.Show Language.Futhark.Parser.Lexer.Tokens.Token
+ Language.Futhark.Parser.Lexer.Tokens: keyword :: Text -> Token
+ Language.Futhark.Parser.Lexer.Tokens: mkQualId :: Text -> Alex ([Name], Name)
+ Language.Futhark.Parser.Lexer.Tokens: readHexRealLit :: RealFloat a => Text -> Alex a
+ Language.Futhark.Parser.Lexer.Tokens: readIntegral :: Integral a => Text -> a
+ Language.Futhark.Parser.Lexer.Tokens: suffZero :: Text -> Text
+ Language.Futhark.Parser.Lexer.Tokens: symbol :: [Name] -> Name -> Token
+ Language.Futhark.Parser.Lexer.Tokens: tokenC :: a -> (Pos, Char, ByteString, Int64) -> Int64 -> Alex (Lexeme a)
+ Language.Futhark.Parser.Lexer.Tokens: tokenM :: (Text -> Alex a) -> (Pos, Char, ByteString, Int64) -> Int64 -> Alex (Lexeme a)
+ Language.Futhark.Parser.Lexer.Tokens: tokenPosM :: ((Loc, Text) -> Alex a) -> (Pos, Char, ByteString, Int64) -> Int64 -> Alex (Lexeme a)
+ Language.Futhark.Parser.Lexer.Tokens: tokenS :: (Text -> a) -> (Pos, Char, ByteString, Int64) -> Int64 -> Alex (Lexeme a)
+ Language.Futhark.Parser.Lexer.Tokens: tryRead :: Read a => String -> Text -> Alex a
+ Language.Futhark.Parser.Lexer.Tokens: type Lexeme a = (Pos, Pos, a)
+ Language.Futhark.Parser.Lexer.Wrapper: LexerError :: Loc -> String -> LexerError
+ Language.Futhark.Parser.Lexer.Wrapper: alexError :: Loc -> String -> Alex a
+ Language.Futhark.Parser.Lexer.Wrapper: alexGetByte :: AlexInput -> Maybe (Byte, AlexInput)
+ Language.Futhark.Parser.Lexer.Wrapper: alexGetInput :: Alex AlexInput
+ Language.Futhark.Parser.Lexer.Wrapper: alexGetPos :: Alex Pos
+ Language.Futhark.Parser.Lexer.Wrapper: alexGetStartCode :: Alex Int
+ Language.Futhark.Parser.Lexer.Wrapper: alexMove :: Pos -> Char -> Pos
+ Language.Futhark.Parser.Lexer.Wrapper: alexSetInput :: AlexInput -> Alex ()
+ Language.Futhark.Parser.Lexer.Wrapper: data Alex a
+ Language.Futhark.Parser.Lexer.Wrapper: data LexerError
+ Language.Futhark.Parser.Lexer.Wrapper: instance GHC.Base.Applicative Language.Futhark.Parser.Lexer.Wrapper.Alex
+ Language.Futhark.Parser.Lexer.Wrapper: instance GHC.Base.Functor Language.Futhark.Parser.Lexer.Wrapper.Alex
+ Language.Futhark.Parser.Lexer.Wrapper: instance GHC.Base.Monad Language.Futhark.Parser.Lexer.Wrapper.Alex
+ Language.Futhark.Parser.Lexer.Wrapper: instance GHC.Show.Show Language.Futhark.Parser.Lexer.Wrapper.LexerError
+ Language.Futhark.Parser.Lexer.Wrapper: runAlex' :: Pos -> ByteString -> Alex a -> Either LexerError a
+ Language.Futhark.Parser.Lexer.Wrapper: type AlexInput = (Pos, Char, ByteString, Int64)
+ Language.Futhark.Parser.Lexer.Wrapper: type Byte = Word8
+ Language.Futhark.Parser.Monad: SyntaxError :: Loc -> String -> SyntaxError
+ Language.Futhark.Parser.Monad: [syntaxErrorLoc] :: SyntaxError -> Loc
+ Language.Futhark.Parser.Monad: [syntaxErrorMsg] :: SyntaxError -> String
+ Language.Futhark.Parser.Monad: data SyntaxError
+ Language.Futhark.Syntax: prettyText :: Pretty a => a -> Text
+ Language.Futhark.TypeChecker: TypeError :: Loc -> Notes -> Doc -> TypeError
+ Language.Futhark.Warnings: listWarnings :: Warnings -> [(SrcLoc, Doc)]
- Futhark.Compiler.Program: extendProg :: (MonadError CompilerError m, MonadIO m) => LoadedProg -> [FilePath] -> m (Warnings, LoadedProg)
+ Futhark.Compiler.Program: extendProg :: LoadedProg -> [FilePath] -> IO (Either (NonEmpty ProgramError) (Warnings, LoadedProg))
- Futhark.Compiler.Program: readLibrary :: (MonadError CompilerError m, MonadIO m) => [Name] -> [FilePath] -> m (Warnings, Imports, VNameSource)
+ Futhark.Compiler.Program: readLibrary :: [Name] -> [FilePath] -> IO (Either (NonEmpty ProgramError) (Warnings, Imports, VNameSource))
- Futhark.Compiler.Program: readUntypedLibrary :: (MonadIO m, MonadError CompilerError m) => [FilePath] -> m [(ImportName, UncheckedProg)]
+ Futhark.Compiler.Program: readUntypedLibrary :: [FilePath] -> IO (Either (NonEmpty ProgramError) [(ImportName, UncheckedProg)])
- Futhark.Compiler.Program: reloadProg :: (MonadError CompilerError m, MonadIO m) => LoadedProg -> [FilePath] -> m (Warnings, LoadedProg)
+ Futhark.Compiler.Program: reloadProg :: LoadedProg -> [FilePath] -> IO (Either (NonEmpty ProgramError) (Warnings, LoadedProg))
- Language.Futhark.Parser: parseDecOrExpIncrM :: Monad m => m Text -> FilePath -> Text -> m (Either ParseError (Either UncheckedDec UncheckedExp))
+ Language.Futhark.Parser: parseDecOrExpIncrM :: Monad m => m Text -> FilePath -> Text -> m (Either SyntaxError (Either UncheckedDec UncheckedExp))
- Language.Futhark.Parser: parseExp :: FilePath -> Text -> Either ParseError UncheckedExp
+ Language.Futhark.Parser: parseExp :: FilePath -> Text -> Either SyntaxError UncheckedExp
- Language.Futhark.Parser: parseFuthark :: FilePath -> Text -> Either ParseError UncheckedProg
+ Language.Futhark.Parser: parseFuthark :: FilePath -> Text -> Either SyntaxError UncheckedProg
- Language.Futhark.Parser: parseModExp :: FilePath -> Text -> Either ParseError (ModExpBase NoInfo Name)
+ Language.Futhark.Parser: parseModExp :: FilePath -> Text -> Either SyntaxError (ModExpBase NoInfo Name)
- Language.Futhark.Parser: parseType :: FilePath -> Text -> Either ParseError UncheckedTypeExp
+ Language.Futhark.Parser: parseType :: FilePath -> Text -> Either SyntaxError UncheckedTypeExp
- Language.Futhark.Parser: parseValue :: FilePath -> Text -> Either ParseError Value
+ Language.Futhark.Parser: parseValue :: FilePath -> Text -> Either SyntaxError Value
- Language.Futhark.Parser: parseValues :: FilePath -> Text -> Either ParseError [Value]
+ Language.Futhark.Parser: parseValues :: FilePath -> Text -> Either SyntaxError [Value]
- Language.Futhark.Parser.Monad: binOpName :: L Token -> (QualName Name, SrcLoc)
+ Language.Futhark.Parser.Monad: binOpName :: L Token -> (QualName Name, Loc)
- Language.Futhark.Parser.Monad: combArrayElements :: Value -> [Value] -> Either String Value
+ Language.Futhark.Parser.Monad: combArrayElements :: Value -> [Value] -> Either SyntaxError Value
- Language.Futhark.Parser.Monad: emptyArrayError :: SrcLoc -> ParserMonad a
+ Language.Futhark.Parser.Monad: emptyArrayError :: Loc -> ParserMonad a
- Language.Futhark.Parser.Monad: mustBeEmpty :: SrcLoc -> ValueType -> ParserMonad ()
+ Language.Futhark.Parser.Monad: mustBeEmpty :: Located loc => loc -> ValueType -> ParserMonad ()
- Language.Futhark.Parser.Monad: parse :: ParserMonad a -> FilePath -> Text -> Either ParseError a
+ Language.Futhark.Parser.Monad: parse :: ParserMonad a -> FilePath -> Text -> Either SyntaxError a
- Language.Futhark.Parser.Monad: parseErrorAt :: SrcLoc -> Maybe String -> ParserMonad a
+ Language.Futhark.Parser.Monad: parseErrorAt :: Located loc => loc -> Maybe String -> ParserMonad a
- Language.Futhark.Parser.Monad: parseInMonad :: ParserMonad a -> FilePath -> Text -> ReadLineMonad (Either ParseError a)
+ Language.Futhark.Parser.Monad: parseInMonad :: ParserMonad a -> FilePath -> Text -> ReadLineMonad (Either SyntaxError a)
- Language.Futhark.Parser.Monad: primTypeFromName :: SrcLoc -> Name -> ParserMonad PrimType
+ Language.Futhark.Parser.Monad: primTypeFromName :: Loc -> Name -> ParserMonad PrimType
- Language.Futhark.Parser.Monad: twoDotsRange :: SrcLoc -> ParserMonad a
+ Language.Futhark.Parser.Monad: twoDotsRange :: Loc -> ParserMonad a
- Language.Futhark.Parser.Monad: type ParserMonad = ExceptT String (StateT ParserEnv (StateT ([L Token], Pos) ReadLineMonad))
+ Language.Futhark.Parser.Monad: type ParserMonad = ExceptT SyntaxError (StateT ParserEnv ReadLineMonad)
- Language.Futhark.TypeChecker.Modules: applyFunctor :: SrcLoc -> FunSig -> MTy -> TypeM (MTy, Map VName VName, Map VName VName)
+ Language.Futhark.TypeChecker.Modules: applyFunctor :: Loc -> FunSig -> MTy -> TypeM (MTy, Map VName VName, Map VName VName)
- Language.Futhark.TypeChecker.Modules: matchMTys :: MTy -> MTy -> SrcLoc -> Either TypeError (Map VName VName)
+ Language.Futhark.TypeChecker.Modules: matchMTys :: MTy -> MTy -> Loc -> Either TypeError (Map VName VName)
- Language.Futhark.TypeChecker.Monad: TypeError :: SrcLoc -> Notes -> Doc -> TypeError
+ Language.Futhark.TypeChecker.Monad: TypeError :: Loc -> Notes -> Doc -> TypeError
- Language.Futhark.TypeChecker.Unify: doUnification :: SrcLoc -> [TypeParam] -> StructType -> StructType -> Either TypeError StructType
+ Language.Futhark.TypeChecker.Unify: doUnification :: Loc -> [TypeParam] -> StructType -> StructType -> Either TypeError StructType

Files

docs/man/futhark-literate.rst view
@@ -34,6 +34,10 @@ Image directives and builtin functions shell out to ``convert`` (from ImageMagick).  Video generation uses ``ffmpeg``. +For an input file ``foo.fut``, all generated files will be in a+directory named ``foo-img``.  A ``file`` parameter passed to a+directive may not contain a directory component or spaces.+ OPTIONS ======= @@ -118,6 +122,8 @@    * ``format: <webm|gif>`` +  * ``file: <name>``.  Make sure to provide a proper extension.+   ``e`` must be one of the following:    * A 3D array where the 2D elements is of a type acceptable to@@ -138,9 +144,14 @@   ``>``), but do not show the directive itself in the output, only its   result. -* ``> :img e``+* ``> :img e[; parameters...]`` -  Visualises ``e``. The following types are supported:+  Visualises ``e``.  The optional parameters are lines of+  the form *key: value*:++  * ``file: NAME``.  Make sure to use a proper extension.++  The expression ``e`` must have one of the following types:    * ``[][]i32`` and ``[][]u32`` 
futhark.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name:           futhark-version:        0.21.7+version:        0.21.8 synopsis:       An optimising compiler for a functional, array-oriented language.  description:    Futhark is a small programming language designed to be compiled to@@ -285,6 +285,8 @@       Language.Futhark.Interpreter       Language.Futhark.Parser       Language.Futhark.Parser.Monad+      Language.Futhark.Parser.Lexer.Tokens+      Language.Futhark.Parser.Lexer.Wrapper       Language.Futhark.Prelude       Language.Futhark.Pretty       Language.Futhark.Prop
src/Futhark/Analysis/Alias.hs view
@@ -32,6 +32,7 @@ aliasAnalysis (Prog consts funs) =   Prog (fst (analyseStms mempty consts)) (map analyseFun funs) +-- | Perform alias analysis on function. analyseFun ::   (ASTRep rep, CanBeAliased (Op rep)) =>   FunDef rep ->@@ -41,6 +42,7 @@   where     body' = analyseBody mempty body +-- | Perform alias analysis on Body. analyseBody ::   ( ASTRep rep,     CanBeAliased (Op rep)@@ -52,6 +54,7 @@   let (stms', _atable') = analyseStms atable stms    in mkAliasedBody rep stms' result +-- | Perform alias analysis on statements. analyseStms ::   (ASTRep rep, CanBeAliased (Op rep)) =>   AliasTable ->@@ -72,10 +75,11 @@   Stm (Aliases rep) analyseStm aliases (Let pat (StmAux cs attrs dec) e) =   let e' = analyseExp aliases e-      pat' = addAliasesToPat pat e'+      pat' = mkAliasedPat pat e'       rep' = (AliasDec $ consumedInExp e', dec)    in Let pat' (StmAux cs attrs rep') e' +-- | Perform alias analysis on expression. analyseExp ::   (ASTRep rep, CanBeAliased (Op rep)) =>   AliasTable ->@@ -114,6 +118,7 @@           mapOnOp = return . addOpAliases aliases         } +-- | Perform alias analysis on lambda. analyseLambda ::   (ASTRep rep, CanBeAliased (Op rep)) =>   AliasTable ->
src/Futhark/Analysis/Metrics.hs view
@@ -123,7 +123,7 @@ basicOpMetrics BinOp {} = seen "BinOp" basicOpMetrics UnOp {} = seen "UnOp" basicOpMetrics ConvOp {} = seen "ConvOp"-basicOpMetrics CmpOp {} = seen "ConvOp"+basicOpMetrics CmpOp {} = seen "CmpOp" basicOpMetrics Assert {} = seen "Assert" basicOpMetrics Index {} = seen "Index" basicOpMetrics Update {} = seen "Update"
src/Futhark/CLI/Bench.hs view
@@ -100,7 +100,7 @@       (sortBy (comparing fst) compiled_benchmarks)   let results = concat $ catMaybes maybe_results   case optJSON opts of-    Nothing -> return ()+    Nothing -> pure ()     Just file -> LBS.writeFile file $ encodeBenchResults results   when (any isNothing maybe_results || anyFailed results) exitFailure   where@@ -122,8 +122,8 @@  compileOptions :: BenchOptions -> IO CompileOptions compileOptions opts = do-  futhark <- maybe getExecutablePath return $ optFuthark opts-  return $+  futhark <- maybe getExecutablePath pure $ optFuthark opts+  pure $     CompileOptions       { compFuthark = futhark,         compBackend = optBackend opts,@@ -145,10 +145,10 @@           then do             exists <- doesFileExist $ binaryName program             if exists-              then return $ Right (program, cases)+              then pure $ Right (program, cases)               else do                 putStrLn $ binaryName program ++ " does not exist, but --skip-compilation passed."-                return $ Left FailedToCompile+                pure $ Left FailedToCompile           else do             putStr $ "Compiling " ++ program ++ "...\n" @@ -159,12 +159,12 @@             case res of               Left (err, errstr) -> do                 putStrLn $ inRed err-                maybe (return ()) SBS.putStrLn errstr-                return $ Left FailedToCompile+                maybe (pure ()) SBS.putStrLn errstr+                pure $ Left FailedToCompile               Right () ->-                return $ Right (program, cases)+                pure $ Right (program, cases)     _ ->-      return $ Left Skipped+      pure $ Left Skipped   where     hasRuns (InputOutputs _ runs) = not $ null runs @@ -251,7 +251,7 @@ mkProgressPrompt runs pad_to dataset_desc   | fancyTerminal = do     count <- newIORef (0, 0)-    return $ \us -> do+    pure $ \us -> do       putStr "\r" -- Go to start of line.       let p s =             putStr $@@ -269,7 +269,7 @@   | otherwise = do     putStr $ descString dataset_desc pad_to     hFlush stdout-    return $ const $ return ()+    pure $ const $ pure ()  reportResult :: [RunResult] -> IO () reportResult = putStrLn . reportString@@ -296,10 +296,10 @@   TestRun ->   IO (Maybe DataResult) runBenchmarkCase _ _ _ _ _ _ (TestRun _ _ RunTimeFailure {} _ _) =-  return Nothing -- Not our concern, we are not a testing tool.+  pure Nothing -- Not our concern, we are not a testing tool. runBenchmarkCase _ opts _ _ _ _ (TestRun tags _ _ _ _)   | any (`elem` tags) $ optExcludeCase opts =-    return Nothing+    pure Nothing runBenchmarkCase server opts futhark program entry pad_to tr@(TestRun _ input_spec (Succeeds expected_spec) _ dataset_desc) = do   prompt <- mkProgressPrompt (optRuns opts) pad_to dataset_desc @@ -321,23 +321,20 @@   when fancyTerminal $ do     clearLine     putStr "\r"+    putStr $ descString (atMostChars 40 dataset_desc) pad_to    case res of-    Left err -> do-      when fancyTerminal $-        liftIO $ putStrLn $ descString (atMostChars 40 dataset_desc) pad_to-      liftIO $ putStrLn $ inRed $ T.unpack err-      return $ Just $ DataResult dataset_desc $ Left err+    Left err -> liftIO $ do+      putStrLn ""+      putStrLn $ inRed $ T.unpack err+      pure $ Just $ DataResult dataset_desc $ Left err     Right (runtimes, errout) -> do-      when fancyTerminal $-        putStr $ descString (atMostChars 40 dataset_desc) pad_to-       reportResult runtimes       Result runtimes (getMemoryUsage errout) errout         & Right         & DataResult dataset_desc         & Just-        & return+        & pure  getMemoryUsage :: T.Text -> M.Map T.Text Int getMemoryUsage t =
src/Futhark/CLI/Dataset.hs view
@@ -177,7 +177,7 @@   | Just vs <- readValues $ BS.pack t =     return $ \_ fmt _ -> mapM_ (outValue fmt) vs   | otherwise = do-    t' <- toValueType =<< either (Left . show) Right (parseType name (T.pack t))+    t' <- toValueType =<< either (Left . syntaxErrorMsg) Right (parseType name (T.pack t))     return $ \conf fmt seed -> do       let v = randomValue conf t' seed       outValue fmt v
src/Futhark/CLI/Dev.hs view
@@ -52,8 +52,8 @@ import Futhark.Util.Log import Futhark.Util.Options import qualified Futhark.Util.Pretty as PP-import Language.Futhark.Core (nameFromString)-import Language.Futhark.Parser (parseFuthark)+import Language.Futhark.Core (locStr, nameFromString)+import Language.Futhark.Parser (SyntaxError (..), parseFuthark) import System.Exit import System.FilePath import System.IO@@ -642,13 +642,14 @@               . intersperse ""               . map (if futharkPrintAST config then show else pretty) -          readProgram' = readProgram (futharkEntryPoints (futharkConfig config)) file+          readProgram' = readProgramFile (futharkEntryPoints (futharkConfig config)) file        case futharkPipeline config of         PrettyPrint -> liftIO $ do           maybe_prog <- parseFuthark file <$> T.readFile file           case maybe_prog of-            Left err -> fail $ show err+            Left (SyntaxError loc err) ->+              fail $ "Syntax error at " <> locStr loc <> ":\n" <> err             Right prog               | futharkPrintAST config -> print prog               | otherwise -> putStrLn $ pretty prog
src/Futhark/CLI/Doc.hs view
@@ -11,7 +11,7 @@ import Data.List (nubBy) import qualified Data.Text.Lazy as T import qualified Data.Text.Lazy.IO as T-import Futhark.Compiler (Imports, dumpError, fileProg, newFutharkConfig, readLibrary)+import Futhark.Compiler (Imports, dumpError, fileProg, newFutharkConfig, readProgramFiles) import Futhark.Doc.Generator import Futhark.Pipeline (FutharkM, Verbosity (..), runFutharkM) import Futhark.Util (directoryContents, trim)@@ -49,7 +49,7 @@             liftIO $ do               mapM_ (hPutStrLn stderr . ("Found source file " <>)) files               hPutStrLn stderr "Reading files..."-          (_w, imports, _vns) <- readLibrary [] files+          (_w, imports, _vns) <- readProgramFiles [] files           liftIO $ printDecs config outdir files $ nubBy sameImport imports      sameImport (x, _) (y, _) = x == y
src/Futhark/CLI/Literate.hs view
@@ -57,11 +57,21 @@ import Text.Megaparsec.Char import Text.Printf +newtype ImgParams = ImgParams+  { imgFile :: Maybe FilePath+  }+  deriving (Show)++defaultImgParams :: ImgParams+defaultImgParams =+  ImgParams {imgFile = Nothing}+ data VideoParams = VideoParams   { videoFPS :: Maybe Int,     videoLoop :: Maybe Bool,     videoAutoplay :: Maybe Bool,-    videoFormat :: Maybe T.Text+    videoFormat :: Maybe T.Text,+    videoFile :: Maybe FilePath   }   deriving (Show) @@ -71,14 +81,15 @@     { videoFPS = Nothing,       videoLoop = Nothing,       videoAutoplay = Nothing,-      videoFormat = Nothing+      videoFormat = Nothing,+      videoFile = Nothing     }  data Directive   = DirectiveRes Exp   | DirectiveBrief Directive   | DirectiveCovert Directive-  | DirectiveImg Exp+  | DirectiveImg Exp ImgParams   | DirectivePlot Exp (Maybe (Int, Int))   | DirectiveGnuplot Exp T.Text   | DirectiveVideo Exp VideoParams@@ -88,7 +99,7 @@ varsInDirective (DirectiveRes e) = varsInExp e varsInDirective (DirectiveBrief d) = varsInDirective d varsInDirective (DirectiveCovert d) = varsInDirective d-varsInDirective (DirectiveImg e) = varsInExp e+varsInDirective (DirectiveImg e _) = varsInExp e varsInDirective (DirectivePlot e _) = varsInExp e varsInDirective (DirectiveGnuplot e _) = varsInExp e varsInDirective (DirectiveVideo e _) = varsInExp e@@ -100,8 +111,17 @@   pprDirective False f pprDirective _ (DirectiveCovert f) =   pprDirective False f-pprDirective _ (DirectiveImg e) =+pprDirective _ (DirectiveImg e params) =   "> :img " <> PP.align (PP.ppr e)+    <> if null params' then mempty else PP.stack $ ";" : params'+  where+    params' =+      catMaybes+        [ p "file" imgFile PP.ppr+        ]+    p s f ppr = do+      x <- f params+      Just $ s <> ": " <> ppr x pprDirective True (DirectivePlot e (Just (h, w))) =   PP.stack     [ "> :plot2d " <> PP.ppr e <> ";",@@ -126,7 +146,8 @@         [ p "fps" videoFPS PP.ppr,           p "loop" videoLoop ppBool,           p "autoplay" videoAutoplay ppBool,-          p "format" videoFormat PP.strictText+          p "format" videoFormat PP.strictText,+          p "file" videoFile PP.ppr         ]     ppBool b = if b then "true" else "false"     p s f ppr = do@@ -191,6 +212,35 @@       *> token "("       *> ((,) <$> parseInt <* token "," <*> parseInt) <* token ")" +withPredicate :: (a -> Bool) -> String -> Parser a -> Parser a+withPredicate f msg p = do+  r <- lookAhead p+  if f r then p else fail msg++parseFilePath :: Parser FilePath+parseFilePath =+  withPredicate ok "filename must not have directory component" p+  where+    p = T.unpack <$> lexeme (takeWhileP Nothing (not . isSpace))+    ok f = takeFileName f == f++parseImgParams :: Parser ImgParams+parseImgParams =+  fmap (fromMaybe defaultImgParams) $+    optional $ ";" *> hspace *> eol *> "-- " *> parseParams defaultImgParams+  where+    parseParams params =+      choice+        [ choice+            [pFile params]+            >>= parseParams,+          pure params+        ]+    pFile params = do+      token "file:"+      b <- parseFilePath+      pure params {imgFile = Just b}+ parseVideoParams :: Parser VideoParams parseVideoParams =   fmap (fromMaybe defaultVideoParams) $@@ -246,7 +296,8 @@           directiveName "brief" $> DirectiveBrief             <*> parseDirective,           directiveName "img" $> DirectiveImg-            <*> parseExp postlexeme <* eol,+            <*> parseExp postlexeme+            <*> parseImgParams <* eol,           directiveName "plot2d" $> DirectivePlot             <*> parseExp postlexeme             <*> parsePlotParams <* eol,@@ -533,9 +584,9 @@     envHash :: T.Text   } -newFileWorker :: Env -> FilePath -> (FilePath -> ScriptM ()) -> ScriptM (FilePath, FilePath)-newFileWorker env template m = do-  let fname_base = T.unpack (envHash env) <> "-" <> template+newFileWorker :: Env -> (Maybe FilePath, FilePath) -> (FilePath -> ScriptM ()) -> ScriptM (FilePath, FilePath)+newFileWorker env (fname_desired, template) m = do+  let fname_base = fromMaybe (T.unpack (envHash env) <> "-" <> template) fname_desired       fname = envImgDir env </> fname_base       fname_rel = envRelImgDir env </> fname_base   exists <- liftIO $ doesFileExist fname@@ -549,12 +600,12 @@   modify $ \s -> s {stateFiles = S.insert fname $ stateFiles s}   pure (fname, fname_rel) -newFile :: Env -> FilePath -> (FilePath -> ScriptM ()) -> ScriptM FilePath-newFile env template m = snd <$> newFileWorker env template m+newFile :: Env -> (Maybe FilePath, FilePath) -> (FilePath -> ScriptM ()) -> ScriptM FilePath+newFile env f m = snd <$> newFileWorker env f m -newFileContents :: Env -> FilePath -> (FilePath -> ScriptM ()) -> ScriptM T.Text-newFileContents env template m =-  liftIO . T.readFile . fst =<< newFileWorker env template m+newFileContents :: Env -> (Maybe FilePath, FilePath) -> (FilePath -> ScriptM ()) -> ScriptM T.Text+newFileContents env f m =+  liftIO . T.readFile . fst =<< newFileWorker env f m  processDirective :: Env -> Directive -> ScriptM T.Text processDirective env (DirectiveBrief d) =@@ -563,7 +614,7 @@   processDirective env d processDirective env (DirectiveRes e) = do   result <--    newFileContents env "eval.txt" $ \resultf -> do+    newFileContents env (Nothing, "eval.txt") $ \resultf -> do       v <- either nope pure =<< evalExpToGround literateBuiltin (envServer env) e       liftIO $ T.writeFile resultf $ prettyText v   pure $@@ -578,8 +629,8 @@     nope t =       throwError $ "Cannot show value of type " <> prettyText t ---processDirective env (DirectiveImg e) = do-  fmap imgBlock . newFile env "img.png" $ \pngfile -> do+processDirective env (DirectiveImg e params) = do+  fmap imgBlock . newFile env (imgFile params, "img.png") $ \pngfile -> do     maybe_v <- evalExpToGround literateBuiltin (envServer env) e     case maybe_v of       Right (ValueAtom v)@@ -598,7 +649,7 @@         "Cannot create image from value of type " <> prettyText t -- processDirective env (DirectivePlot e size) = do-  fmap imgBlock . newFile env "plot.png" $ \pngfile -> do+  fmap imgBlock . newFile env (Nothing, "plot.png") $ \pngfile -> do     maybe_v <- evalExpToGround literateBuiltin (envServer env) e     case maybe_v of       Right v@@ -642,7 +693,7 @@         void $ system "gnuplot" [] script -- processDirective env (DirectiveGnuplot e script) = do-  fmap imgBlock . newFile env "plot.png" $ \pngfile -> do+  fmap imgBlock . newFile env (Nothing, "plot.png") $ \pngfile -> do     maybe_v <- evalExpToGround literateBuiltin (envServer env) e     case maybe_v of       Right (ValueRecord m)@@ -667,7 +718,8 @@   when (format `notElem` ["webm", "gif"]) $     throwError $ "Unknown video format: " <> format -  fmap (videoBlock params) . newFile env ("video" <.> T.unpack format) $ \videofile -> do+  let file = (videoFile params, "video" <.> T.unpack format)+  fmap (videoBlock params) . newFile env file $ \videofile -> do     v <- evalExp literateBuiltin (envServer env) e     let nope =           throwError $
src/Futhark/CLI/REPL.hs view
@@ -153,7 +153,8 @@   (prog, tenv, ienv) <- case maybe_file of     Nothing -> do       -- Load the builtins through the type checker.-      (_, prog) <- badOnLeft show =<< runExceptT (reloadProg prev_prog [])+      (_, prog) <-+        badOnLeft prettyProgramErrors =<< liftIO (reloadProg prev_prog [])       -- Then into the interpreter.       ienv <-         foldM@@ -166,7 +167,7 @@        pure (prog, tenv, ienv')     Just file -> do-      (ws, prog) <- badOnLeft show =<< runExceptT (reloadProg prev_prog [file])+      (ws, prog) <- badOnLeft prettyProgramErrors =<< liftIO (reloadProg prev_prog [file])       liftIO $ putStrLn $ pretty ws        ienv <-@@ -195,6 +196,8 @@     badOnLeft _ (Right x) = pure x     badOnLeft p (Left err) = throwError $ p err +    prettyProgramErrors = pretty . pprProgramErrors+ getPrompt :: FutharkiM String getPrompt = do   i <- gets futharkiCount@@ -235,7 +238,7 @@       maybe_dec_or_e <- parseDecOrExpIncrM (inputLine "  ") prompt line        case maybe_dec_or_e of-        Left err -> liftIO $ print err+        Left (SyntaxError _ err) -> liftIO $ putStrLn err         Right (Left d) -> onDec d         Right (Right e) -> onExp e   modify $ \s -> s {futharkiCount = futharkiCount s + 1}@@ -260,12 +263,10 @@   let mkImport = uncurry $ T.mkImportFrom cur_import       files = map (T.includeToFilePath . mkImport) $ decImports d -  imp_r <- runExceptT $ do-    prog <- lift $ gets futharkiProg-    extendProg prog files-+  cur_prog <- gets futharkiProg+  imp_r <- liftIO $ extendProg cur_prog files   case imp_r of-    Left e -> liftIO $ print e+    Left e -> liftIO $ T.putStrLn $ prettyText $ pprProgramErrors e     Right (_ws, prog) -> do       env <- gets futharkiEnv       let (tenv, ienv) = extendEnvs prog env (map fst $ decImports d)@@ -392,15 +393,14 @@     (False, _) -> throwError $ Load $ T.unpack file  genTypeCommand ::-  Show err =>-  (String -> T.Text -> Either err a) ->+  (String -> T.Text -> Either SyntaxError a) ->   (Imports -> VNameSource -> T.Env -> a -> (Warnings, Either T.TypeError b)) ->   (b -> String) ->   Command genTypeCommand f g h e = do   prompt <- getPrompt   case f prompt e of-    Left err -> liftIO $ print err+    Left (SyntaxError _ err) -> liftIO $ putStrLn err     Right e' -> do       (imports, src, tenv, _) <- getIt       case snd $ g imports src tenv e' of
src/Futhark/CLI/Run.hs view
@@ -47,8 +47,8 @@    inps <-     case vr of-      Left err -> do-        hPutStrLn stderr $ "Error when reading input: " ++ show err+      Left (SyntaxError loc err) -> do+        hPutStrLn stderr $ "Input syntax error at " <> locStr loc <> ":\n" <> err         exitFailure       Right vs ->         return vs@@ -117,7 +117,7 @@   (ws, imports, src) <-     badOnLeft show       =<< liftIO-        ( runExceptT (readProgram [] file)+        ( runExceptT (readProgramFile [] file)             `catch` \(err :: IOException) ->               return (externalErrorS (show err))         )
src/Futhark/CodeGen/Backends/MulticoreC.hs view
@@ -47,6 +47,8 @@     )     <=< ImpGen.compileProg +-- | Generate the multicore context definitions.  This is exported+-- because the WASM backend needs it. generateContext :: GC.CompilerM op () () generateContext = do   mapM_ GC.earlyDecl [C.cunit|$esc:(T.unpack schedulerH)|]@@ -215,6 +217,7 @@                    }|]     ) +-- | Multicore-related command line options. cliOptions :: [Option] cliOptions =   [ Option@@ -233,6 +236,7 @@       }   ] +-- | Operations for generating multicore code. operations :: GC.Operations Multicore () operations =   GC.defaultOperations
src/Futhark/CodeGen/ImpGen/GPU/SegHist.hs view
@@ -414,8 +414,7 @@         num_threads = sExt64 $ kernelNumThreads constants     kernelLoop gtid num_threads total_w_64 $ \offset -> do       -- Construct segment indices.-      zipWithM_ dPrimV_ space_is $-        map sExt32 $ unflattenIndex space_sizes_64 offset+      dIndexSpace (zip space_is space_sizes_64) offset        -- We execute the bucket function once and update each histogram serially.       -- We apply the bucket function if j=offset+ltid is less than@@ -716,7 +715,7 @@         sOp $ Imp.Barrier Imp.FenceLocal          kernelLoop pgtid_in_segment threads_per_segment (sExt32 segment_size') $ \ie -> do-          dPrimV_ i_in_segment ie+          dPrimV_ i_in_segment $ sExt64 ie            -- We execute the bucket function once and update each histogram           -- serially.  This also involves writing to the mapout arrays if
src/Futhark/CodeGen/ImpGen/Multicore.hs view
@@ -40,6 +40,7 @@         (Or Int64, Imp.AtomicOr Int64)       ] +-- | Compile the program. compileProg ::   MonadFreshNames m =>   Prog MCMem ->
src/Futhark/Compiler.hs view
@@ -8,9 +8,11 @@     runCompilerOnProgram,     dumpError,     handleWarnings,+    pprProgramErrors,     module Futhark.Compiler.Program,     module Futhark.Compiler.Config,-    readProgram,+    readProgramFile,+    readProgramFiles,     readProgramOrDie,     readUntypedProgram,     readUntypedProgramOrDie,@@ -20,6 +22,8 @@ import Control.Monad import Control.Monad.Except import Data.Bifunctor (first)+import qualified Data.List.NonEmpty as NE+import Data.Loc (Loc (NoLoc)) import qualified Data.Text.IO as T import qualified Futhark.Analysis.Alias as Alias import Futhark.Compiler.Config@@ -30,8 +34,9 @@ import Futhark.Internalise import Futhark.MonadFreshNames import Futhark.Pipeline+import Futhark.Util.Console (inRed) import Futhark.Util.Log-import Futhark.Util.Pretty (ppr, prettyText)+import Futhark.Util.Pretty (Doc, line, ppr, prettyText, punctuate, stack, text, (</>)) import qualified Language.Futhark as E import Language.Futhark.Semantic (includeToString) import Language.Futhark.Warnings@@ -105,7 +110,7 @@   (prog_imports, namesrc) <-     handleWarnings config $       (\(a, b, c) -> (a, (b, c)))-        <$> readProgram (futharkEntryPoints config) file+        <$> readProgramFile (futharkEntryPoints config) file    putNameSource namesrc   int_prog <- internaliseProg config prog_imports@@ -128,14 +133,44 @@   where     prog' = Alias.aliasAnalysis prog --- | Read and type-check a Futhark program, including all imports.-readProgram ::+-- | Prettyprint program errors as suitable for showing on a text console.+pprProgramErrors :: NE.NonEmpty ProgramError -> Doc+pprProgramErrors = stack . punctuate line . map onError . NE.toList+  where+    onError (ProgramError NoLoc msg) =+      msg+    onError (ProgramError loc msg) =+      text (inRed $ "Error at " <> locStr (srclocOf loc) <> ":") </> msg++-- | Throw an exception formatted with 'pprProgramErrors' if there's+-- an error.+throwOnProgramError ::+  MonadError CompilerError m =>+  Either (NE.NonEmpty ProgramError) a ->+  m a+throwOnProgramError =+  either (externalError . pprProgramErrors) pure++-- | Read and type-check a Futhark program, comprising a single file,+-- including all imports.+readProgramFile ::   (MonadError CompilerError m, MonadIO m) =>   [I.Name] ->   FilePath ->   m (Warnings, Imports, VNameSource)-readProgram extra_eps = readLibrary extra_eps . pure+readProgramFile extra_eps =+  readProgramFiles extra_eps . pure +-- | Read and type-check a Futhark library, comprising multiple files,+-- including all imports.+readProgramFiles ::+  (MonadError CompilerError m, MonadIO m) =>+  [I.Name] ->+  [FilePath] ->+  m (Warnings, Imports, VNameSource)+readProgramFiles extra_eps =+  throwOnProgramError <=< liftIO . readLibrary extra_eps+ -- | Read and parse (but do not type-check) a Futhark program, -- including all imports. readUntypedProgram ::@@ -143,7 +178,8 @@   FilePath ->   m [(String, E.UncheckedProg)] readUntypedProgram =-  fmap (map (first includeToString)) . readUntypedLibrary . pure+  fmap (map (first includeToString)) . throwOnProgramError+    <=< liftIO . readUntypedLibrary . pure  orDie :: MonadIO m => FutharkM a -> m a orDie m = liftIO $ do@@ -156,7 +192,7 @@  -- | Not verbose, and terminates process on error. readProgramOrDie :: MonadIO m => FilePath -> m (Warnings, Imports, VNameSource)-readProgramOrDie file = orDie $ readProgram mempty file+readProgramOrDie file = orDie $ readProgramFile mempty file  -- | Not verbose, and terminates process on error. readUntypedProgramOrDie :: MonadIO m => FilePath -> m [(String, E.UncheckedProg)]
src/Futhark/Compiler/Program.hs view
@@ -10,6 +10,7 @@     Imports,     FileModule (..),     E.Warnings,+    ProgramError (..),     LoadedProg (lpNameSource),     noLoadedProg,     lpImports,@@ -32,17 +33,18 @@ import Control.Monad.State (execStateT, gets, modify) import Data.Bifunctor (first) import Data.List (intercalate, isPrefixOf, sort)+import qualified Data.List.NonEmpty as NE+import Data.Loc (Loc (..), locOf) import qualified Data.Map as M import Data.Maybe (mapMaybe) import qualified Data.Text as T import qualified Data.Text.IO as T import Data.Time.Clock (UTCTime)-import Futhark.Error import Futhark.FreshNames import Futhark.Util (interactWithFileSafely, nubOrd, startupTime)-import Futhark.Util.Pretty (line, ppr, text, (</>))+import Futhark.Util.Pretty (Doc, line, ppr, text, (</>)) import qualified Language.Futhark as E-import Language.Futhark.Parser+import Language.Futhark.Parser (SyntaxError (..), parseFuthark) import Language.Futhark.Prelude import Language.Futhark.Semantic import qualified Language.Futhark.TypeChecker as E@@ -60,9 +62,15 @@   }   deriving (Eq, Ord, Show) +-- | Note that the location may be 'NoLoc'.  This essentially only+-- happens when the problem is that a root file cannot be found.+data ProgramError = ProgramError Loc Doc++type WithErrors = Either (NE.NonEmpty ProgramError)+ newtype UncheckedImport = UncheckedImport   { unChecked ::-      Either CompilerError (LoadedFile E.UncheckedProg, [(ImportName, MVar UncheckedImport)])+      WithErrors (LoadedFile E.UncheckedProg, [(ImportName, MVar UncheckedImport)])   }  -- | If mapped to Nothing, treat it as present.  This is used when@@ -72,29 +80,46 @@ newState :: [ImportName] -> IO ReaderState newState known = newMVar $ M.fromList $ zip known $ repeat Nothing +-- Since we need to work with base 4.14 that does not have NE.singleton.+singleError :: ProgramError -> NE.NonEmpty ProgramError+singleError = (NE.:| [])+ orderedImports ::-  (MonadError CompilerError m, MonadIO m) =>   [(ImportName, MVar UncheckedImport)] ->-  m [(ImportName, LoadedFile E.UncheckedProg)]+  IO [(ImportName, WithErrors (LoadedFile E.UncheckedProg))] orderedImports = fmap reverse . flip execStateT [] . mapM_ (spelunk [])   where     spelunk steps (include, mvar)-      | include `elem` steps =-        externalErrorS $-          "Import cycle: "-            ++ intercalate-              " -> "-              (map includeToString $ reverse $ include : steps)+      | include `elem` steps = do+        let problem =+              ProgramError (locOf include) . text $+                "Import cycle: "+                  <> intercalate+                    " -> "+                    (map includeToString $ reverse $ include : steps)+        modify ((include, Left (singleError problem)) :)       | otherwise = do         prev <- gets $ lookup include         case prev of           Just _ -> pure ()           Nothing -> do-            (file, more_imports) <--              either throwError pure . unChecked =<< liftIO (readMVar mvar)-            mapM_ (spelunk (include : steps)) more_imports-            modify ((include, file) :)+            res <- unChecked <$> liftIO (readMVar mvar)+            case res of+              Left errors ->+                modify ((include, Left errors) :)+              Right (file, more_imports) -> do+                mapM_ (spelunk (include : steps)) more_imports+                modify ((include, Right file) :) +errorsToTop ::+  [(ImportName, WithErrors (LoadedFile E.UncheckedProg))] ->+  WithErrors [(ImportName, LoadedFile E.UncheckedProg)]+errorsToTop [] = Right []+errorsToTop ((_, Left x) : rest) =+  either (Left . (x <>)) (const (Left x)) (errorsToTop rest)+errorsToTop ((name, Right x) : rest) =+  fmap ((name, x) :) (errorsToTop rest)+ newImportMVar :: IO UncheckedImport -> IO (Maybe (MVar UncheckedImport)) newImportMVar m = do   mvar <- newEmptyMVar@@ -106,7 +131,7 @@   interactWithFileSafely $     (,) <$> T.readFile filepath <*> getModificationTime filepath -readImportFile :: ImportName -> IO (Either CompilerError (LoadedFile T.Text))+readImportFile :: ImportName -> IO (Either ProgramError (LoadedFile T.Text)) readImportFile include = do   -- First we try to find a file of the given name in the search path,   -- then we look at the builtin library if we have to.  For the@@ -116,10 +141,12 @@   case (r, lookup prelude_str prelude) of     (Just (Right (s, mod_time)), _) ->       pure $ Right $ loaded filepath s mod_time-    (Just (Left e), _) -> pure $ Left $ ExternalError $ text e+    (Just (Left e), _) ->+      pure $ Left $ ProgramError (locOf include) $ text e     (Nothing, Just s) ->       pure $ Right $ loaded prelude_str s startupTime-    (Nothing, Nothing) -> pure $ Left $ ExternalError $ text not_found+    (Nothing, Nothing) ->+      pure $ Left $ ProgramError (locOf include) $ text not_found   where     prelude_str = "/" Posix.</> includeToString include Posix.<.> "fut" @@ -132,16 +159,14 @@         }      not_found =-      "Error at " ++ E.locStr (E.srclocOf include)-        ++ ": could not find import '"-        ++ includeToString include-        ++ "'."+      "Could not find import " <> E.quote (includeToString include) <> "."  handleFile ::   ReaderState -> LoadedFile T.Text -> IO UncheckedImport handleFile state_mvar (LoadedFile file_name import_name file_contents mod_time) = do   case parseFuthark file_name file_contents of-    Left err -> pure $ UncheckedImport $ Left $ ExternalError $ text $ show err+    Left (SyntaxError loc err) ->+      pure . UncheckedImport . Left . singleError $ ProgramError loc $ text err     Right prog -> do       let imports = map (uncurry (mkImportFrom import_name)) $ E.progImports prog       mvars <-@@ -164,22 +189,21 @@       Nothing -> do         prog_mvar <- newImportMVar $ do           readImportFile include >>= \case-            Left e -> pure $ UncheckedImport $ Left e+            Left e -> pure $ UncheckedImport $ Left $ singleError e             Right file -> handleFile state_mvar file         pure (M.insert include prog_mvar state, prog_mvar)  readUntypedLibraryExceptKnown ::-  (MonadIO m, MonadError CompilerError m) =>   [ImportName] ->   [FilePath] ->-  m [LoadedFile E.UncheckedProg]+  IO (Either (NE.NonEmpty ProgramError) [LoadedFile E.UncheckedProg]) readUntypedLibraryExceptKnown known fps = do   state_mvar <- liftIO $ newState known   let prelude_import = mkInitialImport "/prelude/prelude"   prelude_mvar <- liftIO $ readImport state_mvar prelude_import   fps_mvars <- liftIO (mapM (onFile state_mvar) fps)   let unknown_mvars = onlyUnknown ((prelude_import, prelude_mvar) : fps_mvars)-  map snd <$> orderedImports unknown_mvars+  fmap (map snd) . errorsToTop <$> orderedImports unknown_mvars   where     onlyUnknown = mapMaybe sequenceA     onFile state_mvar fp =@@ -199,9 +223,11 @@                         lfPath = fp                       }                 Just (Left e) ->-                  pure $ UncheckedImport $ Left $ ExternalError $ text $ show e+                  pure . UncheckedImport . Left . singleError $+                    ProgramError NoLoc $ text $ show e                 Nothing ->-                  pure $ UncheckedImport $ Left $ ExternalError $ text $ fp <> ": file not found."+                  pure . UncheckedImport . Left . singleError $+                    ProgramError NoLoc $ text $ fp <> ": file not found."             pure (M.insert include prog_mvar state, (include, prog_mvar))       where         include = mkInitialImport fp_name@@ -213,11 +239,10 @@     f lf = (includeToString (lfImportName lf), snd $ lfMod lf)  typeCheckProg ::-  MonadError CompilerError m =>   [LoadedFile (VNameSource, FileModule)] ->   VNameSource ->   [LoadedFile E.UncheckedProg] ->-  m (E.Warnings, [LoadedFile (VNameSource, FileModule)], VNameSource)+  WithErrors (E.Warnings, [LoadedFile (VNameSource, FileModule)], VNameSource) typeCheckProg orig_imports orig_src =   foldM f (mempty, orig_imports, orig_src)   where@@ -228,14 +253,15 @@             | "/prelude" `isPrefixOf` includeToFilePath import_name = prog             | otherwise = prependRoots roots prog       case E.checkProg (asImports imports) src import_name prog' of-        (prog_ws, Left err) -> do+        (prog_ws, Left (E.TypeError loc notes msg)) -> do           let ws' = ws <> prog_ws-          externalError $+              err' = msg <> ppr notes+          Left . singleError . ProgramError (locOf loc) $             if anyWarnings ws'-              then ppr ws' </> line <> ppr err-              else ppr err+              then ppr ws' </> line <> ppr err'+              else ppr err'         (prog_ws, Right (m, src')) ->-          pure+          Right             ( ws <> prog_ws,               imports ++ [LoadedFile path import_name (src, m) mod_time],               src'@@ -330,53 +356,51 @@  -- | Extend a loaded program with (possibly new) files. extendProg ::-  (MonadError CompilerError m, MonadIO m) =>   LoadedProg ->   [FilePath] ->-  m (E.Warnings, LoadedProg)+  IO (Either (NE.NonEmpty ProgramError) (E.Warnings, LoadedProg)) extendProg lp new_roots = do   new_imports_untyped <-     readUntypedLibraryExceptKnown (map lfImportName $ lpFiles lp) new_roots-  (ws, imports, src') <--    typeCheckProg (lpFiles lp) (lpNameSource lp) new_imports_untyped-  pure (ws, LoadedProg (nubOrd (lpRoots lp ++ new_roots)) imports src')+  pure $ do+    (ws, imports, src') <-+      typeCheckProg (lpFiles lp) (lpNameSource lp) =<< new_imports_untyped+    Right (ws, LoadedProg (nubOrd (lpRoots lp ++ new_roots)) imports src')  -- | Load some new files, reusing as much of the previously loaded -- program as possible.  This does not *extend* the currently loaded -- program the way 'extendProg' does it, so it is always correct (if -- less efficient) to pass 'noLoadedProg'. reloadProg ::-  (MonadError CompilerError m, MonadIO m) =>   LoadedProg ->   [FilePath] ->-  m (E.Warnings, LoadedProg)+  IO (Either (NE.NonEmpty ProgramError) (E.Warnings, LoadedProg)) reloadProg lp new_roots = do   lp' <- usableLoadedProg lp new_roots   extendProg lp' new_roots  -- | Read and type-check some Futhark files. readLibrary ::-  (MonadError CompilerError m, MonadIO m) =>   -- | Extra functions that should be marked as entry points; only   -- applies to the immediate files, not any imports imported.   [E.Name] ->   -- | The files to read.   [FilePath] ->-  m (E.Warnings, Imports, VNameSource)+  IO (Either (NE.NonEmpty ProgramError) (E.Warnings, Imports, VNameSource)) readLibrary extra_eps fps =-  fmap frob-    . typeCheckProg mempty (lpNameSource noLoadedProg)-    . setEntryPoints (E.defaultEntryPoint : extra_eps) fps-    =<< readUntypedLibraryExceptKnown [] fps+  ( fmap frob+      . typeCheckProg mempty (lpNameSource noLoadedProg)+      <=< fmap (setEntryPoints (E.defaultEntryPoint : extra_eps) fps)+  )+    <$> readUntypedLibraryExceptKnown [] fps   where     frob (x, y, z) = (x, asImports y, z)  -- | Read (and parse) all source files (including the builtin prelude) -- corresponding to a set of root files. readUntypedLibrary ::-  (MonadIO m, MonadError CompilerError m) =>   [FilePath] ->-  m [(ImportName, E.UncheckedProg)]-readUntypedLibrary = fmap (map f) . readUntypedLibraryExceptKnown []+  IO (Either (NE.NonEmpty ProgramError) [(ImportName, E.UncheckedProg)])+readUntypedLibrary = fmap (fmap (map f)) . readUntypedLibraryExceptKnown []   where     f lf = (lfImportName lf, lfMod lf)
src/Futhark/Construct.hs view
@@ -47,18 +47,29 @@ -- z <- letExp "z" $ BasicOp $ BinOp (Add Int32) (Var x) (Var y) -- @ --+-- == Monadic expression builders+--+-- This module also contains "monadic expression" functions that let+-- us build nested expressions in a "direct" style, rather than using+-- 'letExp' and friends to bind every sub-part first.  See functions+-- such as 'eIf' and 'eBody' for example.  See also+-- "Futhark.Analysis.PrimExp" and the 'ToExp' type class.+-- -- == Examples -- -- The "Futhark.Transform.FirstOrderTransform" module is a -- (relatively) simple example of how to use these components.  As are -- some of the high-level building blocks in this very module. module Futhark.Construct-  ( letSubExp,-    letSubExps,+  ( -- * Basic building blocks+    module Futhark.Builder,+    letSubExp,     letExp,     letTupExp,     letTupExp',     letInPlace,++    -- * Monadic expression builders     eSubExp,     eParam,     eIf,@@ -75,6 +86,8 @@     eBlank,     eAll,     eOutOfBounds,++    -- * Other building blocks     asIntZ,     asIntS,     resultBody,@@ -93,7 +106,6 @@     isFullSlice,     sliceAt,     ifCommon,-    module Futhark.Builder,      -- * Result types     instantiateShapes,@@ -115,6 +127,10 @@ import Futhark.IR import Futhark.Util (maybeNth) +-- | @letSubExp desc e@ binds the expression @e@, which must produce a+-- single value.  Returns a t'SubExp' corresponding to the resulting+-- value.  For expressions that produce multiple values, see+-- 'letTupExp'. letSubExp ::   MonadBuilder m =>   String ->@@ -123,6 +139,7 @@ letSubExp _ (BasicOp (SubExp se)) = return se letSubExp desc e = Var <$> letExp desc e +-- | Like 'letSubExp', but returns a name rather than a t'SubExp'. letExp ::   MonadBuilder m =>   String ->@@ -138,6 +155,9 @@     [v] -> return v     _ -> error $ "letExp: tuple-typed expression given:\n" ++ pretty e +-- | Like 'letExp', but the 'VName' and 'Slice' denote an array that+-- is 'Update'd with the result of the expression.  The name of the+-- updated array is returned. letInPlace ::   MonadBuilder m =>   String ->@@ -149,13 +169,7 @@   tmp <- letSubExp (desc ++ "_tmp") e   letExp desc $ BasicOp $ Update Unsafe src slice tmp -letSubExps ::-  MonadBuilder m =>-  String ->-  [Exp (Rep m)] ->-  m [SubExp]-letSubExps desc = mapM $ letSubExp desc-+-- | Like 'letExp', but the expression may return multiple values. letTupExp ::   (MonadBuilder m) =>   String ->@@ -169,6 +183,7 @@   letBindNames names e   pure names +-- | Like 'letTupExp', but returns t'SubExp's instead of 'VName's. letTupExp' ::   (MonadBuilder m) =>   String ->@@ -177,18 +192,25 @@ letTupExp' _ (BasicOp (SubExp se)) = return [se] letTupExp' name ses = map Var <$> letTupExp name ses +-- | Turn a subexpression into a monad expression.  Does not actually+-- lead to any code generation.  This is supposed to be used alongside+-- the other monadic expression functions, such as 'eIf'. eSubExp ::   MonadBuilder m =>   SubExp ->   m (Exp (Rep m)) eSubExp = pure . BasicOp . SubExp +-- | Treat a parameter as a monadic expression. eParam ::   MonadBuilder m =>   Param t ->   m (Exp (Rep m)) eParam = eSubExp . Var . paramName +-- | Construct an 'If' expression from a monadic condition and monadic+-- branches.  'eBody' might be convenient for constructing the+-- branches. eIf ::   (MonadBuilder m, BranchType (Rep m) ~ ExtType) =>   m (Exp (Rep m)) ->@@ -233,6 +255,7 @@   where     stmsscope = scopeOf stms +-- | Construct a v'BinOp' expression with the given operator. eBinOp ::   MonadBuilder m =>   BinOp ->@@ -244,6 +267,7 @@   y' <- letSubExp "y" =<< y   return $ BasicOp $ BinOp op x' y' +-- | Construct a v'CmpOp' expression with the given comparison. eCmpOp ::   MonadBuilder m =>   CmpOp ->@@ -255,6 +279,7 @@   y' <- letSubExp "y" =<< y   return $ BasicOp $ CmpOp op x' y' +-- | Construct a v'ConvOp' expression with the given conversion. eConvOp ::   MonadBuilder m =>   ConvOp ->@@ -264,6 +289,8 @@   x' <- letSubExp "x" =<< x   return $ BasicOp $ ConvOp op x' +-- | Construct a 'SSignum' expression.  Fails if the provided+-- expression is not of integer type. eSignum ::   MonadBuilder m =>   m (Exp (Rep m)) ->@@ -278,12 +305,20 @@     _ ->       error $ "eSignum: operand " ++ pretty e ++ " has invalid type." +-- | Construct a 'Copy' expression. eCopy ::   MonadBuilder m =>   m (Exp (Rep m)) ->   m (Exp (Rep m)) eCopy e = BasicOp . Copy <$> (letExp "copy_arg" =<< e) +-- | Construct a body from expressions.  If multiple expressions are+-- provided, their results will be concatenated in order and returned+-- as the result.+--+-- /Beware/: this will not produce correct code if the type of the+-- body would be existential.  That is, the type of the results being+-- returned should be invariant to the body. eBody ::   (MonadBuilder m) =>   [m (Exp (Rep m))] ->@@ -293,6 +328,9 @@   xs <- mapM (letTupExp "x") es'   pure $ varsRes $ concat xs +-- | Bind each lambda parameter to the result of an expression, then+-- bind the body of the lambda.  The expressions must produce only a+-- single value each. eLambda ::   MonadBuilder m =>   Lambda (Rep m) ->@@ -304,6 +342,9 @@   where     bindParam param arg = letBindNames [paramName param] =<< arg +-- | @eRoundToMultipleOf t x d@ produces an expression that rounds the+-- integer expression @x@ upwards to be a multiple of @d@, with @t@+-- being the integer type of the expressions. eRoundToMultipleOf ::   MonadBuilder m =>   IntType ->@@ -492,6 +533,7 @@     allOfIt d (DimSlice _ n _) = d == n     allOfIt _ _ = False +-- | Produce the common case of an 'IfDec'. ifCommon :: [Type] -> IfDec ExtType ifCommon ts = IfDec (staticShapes ts) IfNormal @@ -568,6 +610,9 @@           return se     instantiate' (Free se) = return se +-- | Like 'instantiateShapes', but obtains names from the provided+-- list.  If an 'Ext' is out of bounds of this list, the function+-- fails with 'error'. instantiateShapes' :: [VName] -> [TypeBase ExtShape u] -> [TypeBase Shape u] instantiateShapes' names ts =   -- Carefully ensure that the order of idents we produce corresponds@@ -579,6 +624,8 @@         Nothing -> error $ "instantiateShapes': " ++ pretty names ++ ", " ++ show x         Just name -> pure $ Var name +-- | Remove existentials by imposing sizes from another type where+-- needed. removeExistentials :: ExtType -> Type -> Type removeExistentials t1 t2 =   t1
src/Futhark/IR/Aliases.hs view
@@ -5,8 +5,14 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} --- | A representation where all bindings are annotated with aliasing--- information.+-- | A representation where all patterns are annotated with aliasing+-- information.  It also records consumption of variables in bodies.+--+-- Note that this module is mostly not concerned with actually+-- /computing/ the aliasing information; only with shuffling it around+-- and providing some basic building blocks.  See modules such as+-- "Futhark.Analysis.Alias" for computing the aliases in the first+-- place. module Futhark.IR.Aliases   ( -- * The representation definition     Aliases,@@ -23,11 +29,9 @@     module Futhark.IR.Syntax,      -- * Adding aliases-    addAliasesToPat,-    mkAliasedLetStm,     mkAliasedBody,-    mkPatAliases,-    mkBodyAliases,+    mkAliasedPat,+    mkBodyAliasing,      -- * Removing aliases     removeProgAliases,@@ -185,6 +189,7 @@       rephraseOp = return . removeOpAliases     } +-- | Remove alias information from an aliased scope. removeScopeAliases :: Scope (Aliases rep) -> Scope rep removeScopeAliases = M.map unAlias   where@@ -193,49 +198,49 @@     unAlias (LParamName dec) = LParamName dec     unAlias (IndexName it) = IndexName it +-- | Remove alias information from a program. removeProgAliases ::   CanBeAliased (Op rep) =>   Prog (Aliases rep) ->   Prog rep removeProgAliases = runIdentity . rephraseProg removeAliases +-- | Remove alias information from a function. removeFunDefAliases ::   CanBeAliased (Op rep) =>   FunDef (Aliases rep) ->   FunDef rep removeFunDefAliases = runIdentity . rephraseFunDef removeAliases +-- | Remove alias information from an expression. removeExpAliases ::   CanBeAliased (Op rep) =>   Exp (Aliases rep) ->   Exp rep removeExpAliases = runIdentity . rephraseExp removeAliases +-- | Remove alias information from statements. removeStmAliases ::   CanBeAliased (Op rep) =>   Stm (Aliases rep) ->   Stm rep removeStmAliases = runIdentity . rephraseStm removeAliases +-- | Remove alias information from lambda. removeLambdaAliases ::   CanBeAliased (Op rep) =>   Lambda (Aliases rep) ->   Lambda rep removeLambdaAliases = runIdentity . rephraseLambda removeAliases +-- | Remove alias information from pattern. removePatAliases ::   Pat (AliasDec, a) ->   Pat a removePatAliases = runIdentity . rephrasePat (return . snd) -addAliasesToPat ::-  (ASTRep rep, CanBeAliased (Op rep), Typed dec) =>-  Pat dec ->-  Exp (Aliases rep) ->-  Pat (VarAliases, dec)-addAliasesToPat pat e =-  Pat $ mkPatAliases pat e-+-- | Augment a body decoration with aliasing information provided by+-- the statements and result of that body. mkAliasedBody ::   (ASTRep rep, CanBeAliased (Op rep)) =>   BodyDec rep ->@@ -243,20 +248,20 @@   Result ->   Body (Aliases rep) mkAliasedBody dec stms res =-  Body (mkBodyAliases stms res, dec) stms res+  Body (mkBodyAliasing stms res, dec) stms res -mkPatAliases ::+-- | Augment a pattern with aliasing information provided by the+-- expression the pattern is bound to.+mkAliasedPat ::   (Aliased rep, Typed dec) =>   Pat dec ->   Exp rep ->-  [PatElem (VarAliases, dec)]-mkPatAliases pat e =-  let als = expAliases e ++ repeat mempty-   in -- In case the pattern has-      -- more elements (this-      -- implies a type error).-      zipWith annotatePatElem (patElems pat) als+  Pat (VarAliases, dec)+mkAliasedPat pat e = Pat $ zipWith annotatePatElem (patElems pat) als   where+    -- Repeat mempty in case the pattern has more elements (this+    -- implies a type error).+    als = expAliases e ++ repeat mempty     annotatePatElem bindee names =       bindee `setPatElemDec` (AliasDec names', patElemDec bindee)       where@@ -266,12 +271,18 @@             Mem _ -> names             _ -> mempty -mkBodyAliases ::+-- | Given statements (with aliasing information) and a body result,+-- produce aliasing information for the corresponding body as a whole.+-- This is basically just looking up the aliasing of each element of+-- the result, and removing the names that are no longer in scope.+-- Note that this does *not* include aliases of results that are not+-- bound in the statements!+mkBodyAliasing ::   Aliased rep =>   Stms rep ->   Result ->   BodyAliasing-mkBodyAliases stms res =+mkBodyAliasing stms res =   -- We need to remove the names that are bound in stms from the alias   -- and consumption sets.  We do this by computing the transitive   -- closure of the alias map (within stms), then removing anything@@ -302,11 +313,19 @@       where         look k = M.findWithDefault mempty k aliasmap +-- | A tuple of a mapping from variable names to their aliases, and+-- the names of consumed variables. type AliasesAndConsumed =   ( M.Map VName Names,     Names   ) +-- | A helper function for computing the aliases of a sequence of+-- statements.  You'd use this while recursing down the statements+-- from first to last.  The 'AliasesAndConsumed' parameter is the+-- current "state" of aliasing, and the function then returns a new+-- state.  The main thing this function provides is proper handling of+-- transitivity and "reverse" aliases. trackAliases ::   Aliased rep =>   AliasesAndConsumed ->@@ -337,7 +356,7 @@   Stm (Aliases rep) mkAliasedLetStm pat (StmAux cs attrs dec) e =   Let-    (addAliasesToPat pat e)+    (mkAliasedPat pat e)     (StmAux cs attrs (AliasDec $ consumedInExp e, dec))     e @@ -347,7 +366,7 @@      in (AliasDec $ consumedInExp e, dec)    mkExpPat ids e =-    addAliasesToPat (mkExpPat ids $ removeExpAliases e) e+    mkAliasedPat (mkExpPat ids $ removeExpAliases e) e    mkLetNames names e = do     env <- asksScope removeScopeAliases
src/Futhark/IR/GPU/Simplify.hs view
@@ -15,7 +15,6 @@   ) where -import qualified Futhark.Analysis.SymbolTable as ST import Futhark.IR.GPU import qualified Futhark.IR.SOACS.Simplify as SOAC import Futhark.MonadFreshNames@@ -26,7 +25,6 @@ import Futhark.Optimise.Simplify.Rules import Futhark.Pass import Futhark.Tools-import qualified Futhark.Transform.FirstOrderTransform as FOT  simpleGPU :: Simplify.SimpleOps GPU simpleGPU = Simplify.bindableSimpleOps $ simplifyKernelOp SOAC.simplifySOAC@@ -95,23 +93,10 @@ kernelRules =   standardRules <> segOpRules     <> ruleBook-      [ RuleOp redomapIotaToLoop,-        RuleOp SOAC.simplifyKnownIterationSOAC,+      [ RuleOp SOAC.simplifyKnownIterationSOAC,         RuleOp SOAC.removeReplicateMapping,         RuleOp SOAC.liftIdentityMapping,         RuleOp SOAC.simplifyMapIota       ]       [ RuleBasicOp removeUnnecessaryCopy       ]---- We turn reductions over (solely) iotas into do-loops, because there--- is no useful structure here anyway.  This is mostly a hack to work--- around the fact that loop tiling would otherwise pointlessly tile--- them.-redomapIotaToLoop :: TopDownRuleOp (Wise GPU)-redomapIotaToLoop vtable pat aux (OtherOp soac@(Screma _ [arr] form))-  | Just _ <- isRedomapSOAC form,-    Just (Iota {}, _) <- ST.lookupBasicOp arr vtable =-    Simplify $ certifying (stmAuxCerts aux) $ FOT.transformSOAC pat soac-redomapIotaToLoop _ _ _ _ =-  Skip
src/Futhark/IR/SOACS/SOAC.hs view
@@ -80,7 +80,7 @@ -- | A second-order array combinator (SOAC). data SOAC rep   = Stream SubExp [VName] (StreamForm rep) [SubExp] (Lambda rep)-  | -- | @Scatter <length> <lambda> <inputs> <outputs>@+  | -- | @Scatter <length> <inputs> <lambda> <outputs>@     --     -- Scatter maps values from a set of input arrays to indices and values of a     -- set of output arrays. It is able to write multiple values to multiple@@ -116,13 +116,11 @@     -- arr2. Additionally, the results are grouped, so the first 6 index values     -- will correspond to the first two output values, and so on. For this     -- example, <lambda> should return a total of 11 values, 8 index values and-    -- 3 output values.+    -- 3 output values.  See also 'splitScatterResults'.     Scatter SubExp [VName] (Lambda rep) [(Shape, Int, VName)]-  | -- | @Hist <length> <dest-arrays-and-ops> <bucket fun> <input arrays>@+  | -- | @Hist <length> <input arrays> <dest-arrays-and-ops> <bucket fun>@     ---    -- The first SubExp is the length of the input arrays. The first-    -- list describes the operations to perform.  The t'Lambda' is the-    -- bucket function.  Finally comes the input images.+    -- The final lambda produces indexes and values for the 'HistOp's.     Hist SubExp [VName] [HistOp rep] (Lambda rep)   | -- | A combination of scan, reduction, and map.  The first     -- t'SubExp' is the size of the input arrays.
src/Futhark/IR/SOACS/Simplify.hs view
@@ -671,6 +671,7 @@   = ArrayIndexing Certs VName (Slice SubExp)   | ArrayRearrange Certs VName [Int]   | ArrayRotate Certs VName [SubExp]+  | ArrayReshape Certs VName (ShapeChange SubExp)   | ArrayCopy Certs VName   | -- | Never constructed.     ArrayVar Certs VName@@ -680,6 +681,7 @@ arrayOpArr (ArrayIndexing _ arr _) = arr arrayOpArr (ArrayRearrange _ arr _) = arr arrayOpArr (ArrayRotate _ arr _) = arr+arrayOpArr (ArrayReshape _ arr _) = arr arrayOpArr (ArrayCopy _ arr) = arr arrayOpArr (ArrayVar _ arr) = arr @@ -687,6 +689,7 @@ arrayOpCerts (ArrayIndexing cs _ _) = cs arrayOpCerts (ArrayRearrange cs _ _) = cs arrayOpCerts (ArrayRotate cs _ _) = cs+arrayOpCerts (ArrayReshape cs _ _) = cs arrayOpCerts (ArrayCopy cs _) = cs arrayOpCerts (ArrayVar cs _) = cs @@ -697,6 +700,8 @@   Just $ ArrayRearrange cs arr perm isArrayOp cs (BasicOp (Rotate rots arr)) =   Just $ ArrayRotate cs arr rots+isArrayOp cs (BasicOp (Reshape new_shape arr)) =+  Just $ ArrayReshape cs arr new_shape isArrayOp cs (BasicOp (Copy arr)) =   Just $ ArrayCopy cs arr isArrayOp _ _ =@@ -706,6 +711,7 @@ fromArrayOp (ArrayIndexing cs arr slice) = (cs, BasicOp $ Index arr slice) fromArrayOp (ArrayRearrange cs arr perm) = (cs, BasicOp $ Rearrange perm arr) fromArrayOp (ArrayRotate cs arr rots) = (cs, BasicOp $ Rotate rots arr)+fromArrayOp (ArrayReshape cs arr new_shape) = (cs, BasicOp $ Reshape new_shape arr) fromArrayOp (ArrayCopy cs arr) = (cs, BasicOp $ Copy arr) fromArrayOp (ArrayVar cs arr) = (cs, BasicOp $ SubExp $ Var arr) @@ -901,6 +907,9 @@     arrayIsMapParam (_, ArrayRotate cs arr rots) =       arr `elem` map_param_names         && all (`ST.elem` vtable) (namesToList $ freeIn cs <> freeIn rots)+    arrayIsMapParam (_, ArrayReshape cs arr new_shape) =+      arr `elem` map_param_names+        && all (`ST.elem` vtable) (namesToList $ freeIn cs <> freeIn new_shape)     arrayIsMapParam (_, ArrayCopy cs arr) =       arr `elem` map_param_names         && all (`ST.elem` vtable) (namesToList $ freeIn cs)@@ -921,6 +930,8 @@                 BasicOp $ Rearrange (0 : map (+ 1) perm) arr               ArrayRotate _ _ rots ->                 BasicOp $ Rotate (intConst Int64 0 : rots) arr+              ArrayReshape _ _ new_shape ->+                BasicOp $ Reshape (DimCoercion w : new_shape) arr               ArrayCopy {} ->                 BasicOp $ Copy arr               ArrayVar {} ->
src/Futhark/IR/Syntax/Core.hs view
@@ -413,6 +413,7 @@       DimSlice (j + (s0 * i)) n (s0 * s1) : sliceSlice' js' is'     sliceSlice' _ _ = [] +-- | A dimension in a 'FlatSlice'. data FlatDimIndex d   = FlatDimIndex       d@@ -430,6 +431,10 @@ instance Foldable FlatDimIndex where   foldMap = foldMapDefault +-- | A flat slice is a way of viewing a one-dimensional array as a+-- multi-dimensional array, using a more compressed mechanism than+-- reshaping and using 'Slice'.  The initial @d@ is an offset, and the+-- list then specifies the shape of the resulting array. data FlatSlice d = FlatSlice d [FlatDimIndex d]   deriving (Eq, Ord, Show) @@ -443,11 +448,13 @@ instance Foldable FlatSlice where   foldMap = foldMapDefault +-- | The dimensions (shape) of the view produced by a flat slice. flatSliceDims :: FlatSlice d -> [d] flatSliceDims (FlatSlice _ ds) = map dimSlice ds   where     dimSlice (FlatDimIndex n _) = n +-- | The strides of each dimension produced by a flat slice. flatSliceStrides :: FlatSlice d -> [d] flatSliceStrides (FlatSlice _ ds) = map dimStride ds   where
src/Futhark/Internalise/Exps.hs view
@@ -228,7 +228,7 @@   let index v = do         v_t <- lookupType v         return $ I.BasicOp $ I.Index v $ fullSlice v_t idxs'-  certifying cs $ letSubExps desc =<< mapM index vs+  certifying cs $ mapM (letSubExp desc <=< index) vs internaliseAppExp desc _ (E.Range start maybe_second end loc) = do   start' <- internaliseExp1 "range_start" start   end' <- internaliseExp1 "range_end" $ case end of@@ -676,7 +676,7 @@               ks           return $ I.BasicOp $ I.ArrayLit ks' rt -    letSubExps desc+    mapM (letSubExp desc)       =<< if null es'         then mapM (arraylit []) rowtypes         else zipWithM arraylit (transpose es') rowtypes@@ -1333,7 +1333,7 @@   InternaliseM [I.SubExp] internaliseOperation s e op = do   vs <- internaliseExpToVars s e-  letSubExps s =<< mapM (fmap I.BasicOp . op) vs+  mapM (letSubExp s . I.BasicOp <=< op) vs  certifyingNonzero ::   SrcLoc ->@@ -1788,7 +1788,7 @@        let conc xarr yarr =             I.BasicOp $ I.Concat 0 (xarr :| [yarr]) ressize-      letSubExps desc $ zipWith conc xs ys+      mapM (letSubExp desc) $ zipWith conc xs ys     handleRest [TupLit [offset, e] _] "rotate" = Just $ \desc -> do       offset' <- internaliseExp1 "rotation_offset" offset       internaliseOperation desc e $ \v -> do
src/Futhark/Optimise/Simplify/Engine.hs view
@@ -668,6 +668,13 @@       -- possible.       isNotHoistableBnd _ _ (Let _ _ (BasicOp ArrayLit {})) = False       isNotHoistableBnd _ _ (Let _ _ (BasicOp SubExp {})) = False+      -- Hoist things that are free.+      isNotHoistableBnd _ _ (Let _ _ (BasicOp Reshape {})) = False+      isNotHoistableBnd _ _ (Let _ _ (BasicOp Rearrange {})) = False+      isNotHoistableBnd _ _ (Let _ _ (BasicOp Rotate {})) = False+      isNotHoistableBnd _ _ (Let _ _ (BasicOp (Index _ slice))) =+        null $ sliceDims slice+      --       isNotHoistableBnd _ usage (Let pat _ _)         | any (`UT.isSize` usage) $ patNames pat =           False@@ -679,9 +686,10 @@        block =         branch_blocker-          `orIf` ((isNotSafe `orIf` isNotCheap) `andAlso` stmIs (not . desirableToHoist))+          `orIf` ( (isNotSafe `orIf` isNotCheap `orIf` isNotHoistableBnd)+                     `andAlso` stmIs (not . desirableToHoist)+                 )           `orIf` isConsuming-          `orIf` isNotHoistableBnd    (hoisted1, body1') <-     protectIfHoisted cond True $
src/Futhark/Optimise/Simplify/Rep.hs view
@@ -203,11 +203,9 @@   Exp (Wise rep) ->   Pat (LetDec (Wise rep)) addWisdomToPat pat e =-  Pat $ map f $ Aliases.mkPatAliases pat e+  f <$> Aliases.mkAliasedPat pat e   where-    f pe =-      let (als, dec) = patElemDec pe-       in pe `setPatElemDec` (VarWisdom als, dec)+    f (als, dec) = (VarWisdom als, dec)  mkWiseBody ::   (ASTRep rep, CanBeWise (Op rep)) =>@@ -223,7 +221,7 @@     stms     res   where-    (aliases, consumed) = Aliases.mkBodyAliases stms res+    (aliases, consumed) = Aliases.mkBodyAliasing stms res  mkWiseLetStm ::   (ASTRep rep, CanBeWise (Op rep)) =>
src/Futhark/Test.hs view
@@ -205,8 +205,8 @@   let types = map snd names_and_types       vs_types = map (V.valueTypeTextNoDims . V.valueType) vs   unless (types == vs_types) . throwError . T.unlines $-    [ "Expected input of types: " <> prettyTextOneLine types,-      "Provided input of types: " <> prettyTextOneLine vs_types+    [ "Expected input of types: " <> T.unwords (map prettyTextOneLine types),+      "Provided input of types: " <> T.unwords (map prettyTextOneLine vs_types)     ]   cmdMaybe . withSystemTempFile "futhark-input" $ \tmpf tmpf_h -> do     mapM_ (BS.hPutStr tmpf_h . Bin.encode) vs
src/Language/Futhark/Parser.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE OverloadedStrings #-}+ -- | Interface to the Futhark parser. module Language.Futhark.Parser   ( parseFuthark,@@ -7,7 +9,7 @@     parseValue,     parseValues,     parseDecOrExpIncrM,-    ParseError,+    SyntaxError (..),   ) where @@ -21,7 +23,7 @@ parseFuthark ::   FilePath ->   T.Text ->-  Either ParseError UncheckedProg+  Either SyntaxError UncheckedProg parseFuthark = parse prog  -- | Parse an Futhark expression from the given 'String', using the@@ -29,7 +31,7 @@ parseExp ::   FilePath ->   T.Text ->-  Either ParseError UncheckedExp+  Either SyntaxError UncheckedExp parseExp = parse expression  -- | Parse a Futhark module expression from the given 'String', using the@@ -37,7 +39,7 @@ parseModExp ::   FilePath ->   T.Text ->-  Either ParseError (ModExpBase NoInfo Name)+  Either SyntaxError (ModExpBase NoInfo Name) parseModExp = parse modExpression  -- | Parse an Futhark type from the given 'String', using the@@ -45,7 +47,7 @@ parseType ::   FilePath ->   T.Text ->-  Either ParseError UncheckedTypeExp+  Either SyntaxError UncheckedTypeExp parseType = parse futharkType  -- | Parse any Futhark value from the given 'String', using the 'FilePath'@@ -53,7 +55,7 @@ parseValue ::   FilePath ->   T.Text ->-  Either ParseError Value+  Either SyntaxError Value parseValue = parse anyValue  -- | Parse several Futhark values (separated by anything) from the given@@ -62,5 +64,32 @@ parseValues ::   FilePath ->   T.Text ->-  Either ParseError [Value]+  Either SyntaxError [Value] parseValues = parse anyValues++-- | Parse an Futhark expression incrementally from monadic actions, using the+-- 'FilePath' as the source name for error messages.+parseExpIncrM ::+  Monad m =>+  m T.Text ->+  FilePath ->+  T.Text ->+  m (Either SyntaxError UncheckedExp)+parseExpIncrM fetch file program =+  getLinesFromM fetch $ parseInMonad expression file program++-- | Parse either an expression or a declaration incrementally;+-- favouring declarations in case of ambiguity.+parseDecOrExpIncrM ::+  Monad m =>+  m T.Text ->+  FilePath ->+  T.Text ->+  m (Either SyntaxError (Either UncheckedDec UncheckedExp))+parseDecOrExpIncrM fetch file input =+  case parseInMonad declaration file input of+    Value Left {} -> fmap Right <$> parseExpIncrM fetch file input+    Value (Right d) -> pure $ Right $ Left d+    GetLine _ -> do+      l <- fetch+      parseDecOrExpIncrM fetch file $ input <> "\n" <> l
src/Language/Futhark/Parser/Lexer.x view
@@ -6,11 +6,11 @@ -- | The Futhark lexer.  Takes a string, produces a list of tokens with position information. module Language.Futhark.Parser.Lexer   ( Token(..)-  , L(..)   , scanTokens   , scanTokensText   ) where +import Data.Bifunctor (second) import qualified Data.ByteString.Lazy as BS import qualified Data.Text as T import qualified Data.Text.Encoding as T@@ -18,6 +18,7 @@ import Data.Char (ord, toLower, digitToInt) import Data.Int (Int8, Int16, Int32, Int64) import Data.Word (Word8)+import Data.Loc (Loc (..), L(..), Pos(..)) import Data.Bits import Data.Function (fix) import Data.List@@ -30,12 +31,13 @@                               Name, nameFromText, nameToText) import Language.Futhark.Prop (leadingOperator) import Language.Futhark.Syntax (BinOp(..))-import Futhark.Util.Loc hiding (L)+import Language.Futhark.Parser.Lexer.Wrapper+import Language.Futhark.Parser.Lexer.Tokens+import qualified Data.ByteString.Internal as ByteString (w2c)+import qualified Data.ByteString.Lazy as ByteString  } -%wrapper "monad-bytestring"- @charlit = ($printable#['\\]|\\($printable|[0-9]+)) @stringcharlit = ($printable#[\"\\]|\\($printable|[0-9]+)) @hexlit = 0[xX][0-9a-fA-F][0-9a-fA-F_]*@@ -117,9 +119,9 @@   \" @stringcharlit* \"    { tokenM $ fmap (STRINGLIT . T.pack) . tryRead "string"  }    @identifier              { tokenS keyword }-  @identifier "["          { tokenM $ fmap INDEXING . indexing . T.takeWhile (/='[') }+  @identifier "["          { tokenPosM $ fmap INDEXING . indexing . second (T.takeWhile (/='[')) }   @qualidentifier "["      { tokenM $ fmap (uncurry QUALINDEXING) . mkQualId . T.takeWhile (/='[') }-  @identifier "." "("      { tokenM $ fmap (QUALPAREN []) . indexing . T.init . T.takeWhile (/='(') }+  @identifier "." "("      { tokenPosM $ fmap (QUALPAREN []) . indexing . second (T.init . T.takeWhile (/='(')) }   @qualidentifier "." "("  { tokenM $ fmap (uncurry QUALPAREN) . mkQualId . T.init . T.takeWhile (/='(') }   "#" @identifier          { tokenS $ CONSTRUCTOR . nameFromText . T.drop 1 } @@ -129,291 +131,36 @@   "." [0-9]+               { tokenS $ PROJ_INTFIELD . nameFromText . T.drop 1 } { -keyword :: T.Text -> Token-keyword s =-  case s of-    "true"         -> TRUE-    "false"        -> FALSE-    "if"           -> IF-    "then"         -> THEN-    "else"         -> ELSE-    "def"          -> DEF-    "let"          -> LET-    "loop"         -> LOOP-    "in"           -> IN-    "val"          -> VAL-    "for"          -> FOR-    "do"           -> DO-    "with"         -> WITH-    "local"        -> LOCAL-    "open"         -> OPEN-    "include"      -> INCLUDE-    "import"       -> IMPORT-    "type"         -> TYPE-    "entry"        -> ENTRY-    "module"       -> MODULE-    "while"        -> WHILE-    "assert"       -> ASSERT-    "match"        -> MATCH-    "case"         -> CASE--    _              -> ID $ nameFromText s--indexing :: T.Text -> Alex Name-indexing s = case keyword s of-  ID v -> return v-  _    -> alexError $ "Cannot index keyword '" ++ T.unpack s ++ "'."--mkQualId :: T.Text -> Alex ([Name], Name)-mkQualId s = case reverse $ T.splitOn "." s of-  []   -> error "mkQualId: no components"-  k:qs -> return (map nameFromText (reverse qs), nameFromText k)---- | Suffix a zero if the last character is dot.-suffZero :: T.Text -> T.Text-suffZero s = if T.last s == '.' then s <> "0" else s--tryRead :: Read a => String -> T.Text -> Alex a-tryRead desc s = case reads s' of-  [(x, "")] -> return x-  _         -> error $ "Invalid " ++ desc ++ " literal: `" ++ T.unpack s ++ "'."-  where s' = T.unpack s--readIntegral :: Integral a => T.Text -> a-readIntegral s-  | "0x" `T.isPrefixOf` s || "0X" `T.isPrefixOf` s = parseBase 16 (T.drop 2 s)-  | "0b" `T.isPrefixOf` s || "0B" `T.isPrefixOf` s = parseBase 2 (T.drop 2 s)-  | "0r" `T.isPrefixOf` s || "0R" `T.isPrefixOf` s = fromRoman (T.drop 2 s)-  | otherwise = parseBase 10 s-      where parseBase base = T.foldl (\acc c -> acc * base + fromIntegral (digitToInt c)) 0--tokenC v  = tokenS $ const v--tokenS f = tokenM $ return . f--type Lexeme a = ((Int, Int, Int), (Int, Int, Int), a)--tokenM :: (T.Text -> Alex a)-       -> (AlexPosn, Char, ByteString.ByteString, Int64)-       -> Int64-       -> Alex (Lexeme a)-tokenM f (AlexPn addr line col, _, s, _) len = do-  x <- f $ T.decodeUtf8 $ BS.toStrict s'-  return (pos, advance pos s', x)-  where pos = (line, col, addr)-        s' = BS.take len s--advance :: (Int, Int, Int) -> ByteString.ByteString -> (Int, Int, Int)-advance orig_pos = foldl' advance' orig_pos . init . ByteString.unpack-  where advance' (!line, !col, !addr) c-          | c == nl   = (line + 1, 1, addr + 1)-          | otherwise = (line, col + 1, addr + 1)-        nl = fromIntegral $ ord '\n'--symbol :: [Name] -> Name -> Token-symbol [] q-  | nameToText q == "*" = ASTERISK-  | nameToText q == "-" = NEGATE-  | nameToText q == "<" = LTH-  | nameToText q == "^" = HAT-  | nameToText q == "|" = PIPE-  | otherwise = SYMBOL (leadingOperator q) [] q-symbol qs q = SYMBOL (leadingOperator q) qs q---romanNumerals :: Integral a => [(T.Text,a)]-romanNumerals = reverse-                [ ("I",     1)-                , ("IV",    4)-                , ("V",     5)-                , ("IX",    9)-                , ("X",    10)-                , ("XL",   40)-                , ("L",    50)-                , ("XC",   90)-                , ("C",   100)-                , ("CD",  400)-                , ("D",   500)-                , ("CM",  900)-                , ("M",  1000)-                ]--fromRoman :: Integral a => T.Text -> a-fromRoman s =-  case find ((`T.isPrefixOf` s) . fst) romanNumerals of-    Nothing -> 0-    Just (d,n) -> n+fromRoman (T.drop (T.length d) s)--readHexRealLit :: RealFloat a => T.Text -> Alex a-readHexRealLit s =-  let num =  (T.drop 2 s) in-  -- extract number into integer, fractional and (optional) exponent-  let comps = T.split (`elem` ['.','p','P']) num in-  case comps of-    [i, f, p] ->-        let runTextReader r = fromIntegral . fst . fromRight (error "internal error") . r-            intPart = runTextReader T.hexadecimal i-            fracPart = runTextReader T.hexadecimal f-            exponent = runTextReader (T.signed T.decimal) p--            fracLen = fromIntegral $ T.length f-            fracVal = fracPart / (16.0 ** fracLen)-            totalVal = (intPart + fracVal) * (2.0 ** exponent) in-        return totalVal-    _ -> error "bad hex real literal"--alexGetPosn :: Alex (Int, Int, Int)-alexGetPosn = Alex $ \s ->-  let (AlexPn off line col) = alex_pos s-  in Right (s, (line, col, off))--alexEOF = do-  posn <- alexGetPosn-  return (posn, posn, EOF)---- | A value tagged with a source location.-data L a = L SrcLoc a deriving (Show)--instance Eq a => Eq (L a) where-  L _ x == L _ y = x == y--instance Located (L a) where-  locOf (L (SrcLoc loc) _) = loc---- | A lexical token.  It does not itself contain position--- information, so in practice the parser will consume tokens tagged--- with a source position.-data Token = ID Name-           | INDEXING Name-           | QUALINDEXING [Name] Name-           | QUALPAREN [Name] Name-           | SYMBOL BinOp [Name] Name-           | CONSTRUCTOR Name-           | PROJ_INTFIELD Name--           | INTLIT Integer-           | STRINGLIT T.Text-           | I8LIT Int8-           | I16LIT Int16-           | I32LIT Int32-           | I64LIT Int64-           | U8LIT Word8-           | U16LIT Word16-           | U32LIT Word32-           | U64LIT Word64-           | FLOATLIT Double-           | F16LIT Half-           | F32LIT Float-           | F64LIT Double-           | CHARLIT Char--           | COLON-           | COLON_GT-           | BACKSLASH-           | APOSTROPHE-           | APOSTROPHE_THEN_HAT-           | APOSTROPHE_THEN_TILDE-           | BACKTICK-           | HASH_LBRACKET-           | DOT-           | TWO_DOTS-           | TWO_DOTS_LT-           | TWO_DOTS_GT-           | THREE_DOTS-           | LPAR-           | RPAR-           | RPAR_THEN_LBRACKET-           | LBRACKET-           | RBRACKET-           | LCURLY-           | RCURLY-           | COMMA-           | UNDERSCORE-           | RIGHT_ARROW-           | QUESTION_MARK--           | EQU-           | ASTERISK-           | NEGATE-           | BANG-           | DOLLAR-           | LTH-           | HAT-           | TILDE-           | PIPE--           | IF-           | THEN-           | ELSE-           | DEF-           | LET-           | LOOP-           | IN-           | FOR-           | DO-           | WITH-           | ASSERT-           | TRUE-           | FALSE-           | WHILE-           | INCLUDE-           | IMPORT-           | ENTRY-           | TYPE-           | MODULE-           | VAL-           | OPEN-           | LOCAL-           | MATCH-           | CASE--           | DOC String--           | EOF--             deriving (Show, Eq, Ord)--runAlex' :: AlexPosn -> ByteString.ByteString -> Alex a -> Either String a-runAlex' start_pos input__ (Alex f) =-  case f (AlexState { alex_pos = start_pos-                    , alex_bpos = 0-                    , alex_inp = input__-                    , alex_chr = '\n'-                    , alex_scd = 0}) of Left msg -> Left msg-                                        Right ( _, a ) -> Right a---getToken :: FilePath -> Alex (Lexeme Token)-getToken file = do-  inp__@(_,_,_,n) <- alexGetInput+getToken :: Alex (Lexeme Token)+getToken = do+  inp@(_,_,_,n) <- alexGetInput   sc <- alexGetStartCode-  case alexScan inp__ sc of-    AlexEOF -> alexEOF-    AlexError ((AlexPn _ line column),_,_,_) ->-      alexError $ "Error at " ++ file ++ ":" ++ show line ++ ":" ++ show column ++ ": lexical error."-    AlexSkip  inp__' _len -> do-      alexSetInput inp__'-      getToken file-    AlexToken inp__'@(_,_,_,n') _ action -> let len = n'-n in do-      alexSetInput inp__'-      action (ignorePendingBytes inp__) len---- | Given a starting position, produce tokens from the given text (or--- a lexer error).  Returns the final position.-scanTokensText :: Pos -> T.Text -> Either String ([L Token], Pos)-scanTokensText pos = scanTokens pos . BS.fromStrict . T.encodeUtf8+  case alexScan inp sc of+    AlexEOF -> do pos <- alexGetPos+                  pure (pos, pos, EOF)+    AlexError (pos,_,_,_) ->+      alexError (Loc pos pos) "Invalid lexical syntax."+    AlexSkip  inp' _len -> do+      alexSetInput inp'+      getToken+    AlexToken inp'@(_,_,_,n') _ action -> let len = n'-n in do+      alexSetInput inp'+      action inp len -scanTokens :: Pos -> BS.ByteString -> Either String ([L Token], Pos)-scanTokens (Pos file start_line start_col start_off) str =-  runAlex' (AlexPn start_off start_line start_col) str $ do+scanTokens :: Pos -> BS.ByteString -> Either LexerError ([L Token], Pos)+scanTokens pos str =+  runAlex' pos str $ do   fix $ \loop -> do-    tok <- getToken file+    tok <- getToken     case tok of       (start, end, EOF) ->-        return ([], posnToPos end)+        pure ([], end)       (start, end, t) -> do         (rest, endpos) <- loop-        return (L (pos start end) t : rest, endpos)-  where pos start end = SrcLoc $ Loc (posnToPos start) (posnToPos end)-        posnToPos (line, col, off) = Pos file line col off+        pure (L (Loc start end) t : rest, endpos)++-- | Given a starting position, produce tokens from the given text (or+-- a lexer error).  Returns the final position.+scanTokensText :: Pos -> T.Text -> Either LexerError ([L Token], Pos)+scanTokensText pos = scanTokens pos . BS.fromStrict . T.encodeUtf8 }
+ src/Language/Futhark/Parser/Lexer/Tokens.hs view
@@ -0,0 +1,283 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Strict #-}++-- | Definition of the tokens used in the lexer.+--+-- Also defines other useful building blocks for constructing tokens.+module Language.Futhark.Parser.Lexer.Tokens+  ( Token (..),+    Lexeme,+    fromRoman,+    symbol,+    mkQualId,+    tokenPosM,+    tokenM,+    tokenC,+    keyword,+    tokenS,+    indexing,+    suffZero,+    tryRead,+    readIntegral,+    readHexRealLit,+  )+where++import qualified Data.ByteString.Lazy as BS+import Data.Char (digitToInt, ord)+import Data.Either+import Data.List (find, foldl')+import Data.Loc (Loc (..), Pos (..))+import qualified Data.Text as T+import qualified Data.Text.Encoding as T+import qualified Data.Text.Read as T+import Language.Futhark.Core+  ( Int16,+    Int32,+    Int64,+    Int8,+    Name,+    Word16,+    Word32,+    Word64,+    Word8,+  )+import Language.Futhark.Parser.Lexer.Wrapper+import Language.Futhark.Prop (leadingOperator)+import Language.Futhark.Syntax (BinOp, nameFromText, nameToText)+import Numeric.Half+import Prelude hiding (exponent)++-- | A lexical token.  It does not itself contain position+-- information, so in practice the parser will consume tokens tagged+-- with a source position.+data Token+  = ID Name+  | INDEXING Name+  | QUALINDEXING [Name] Name+  | QUALPAREN [Name] Name+  | SYMBOL BinOp [Name] Name+  | CONSTRUCTOR Name+  | PROJ_INTFIELD Name+  | INTLIT Integer+  | STRINGLIT T.Text+  | I8LIT Int8+  | I16LIT Int16+  | I32LIT Int32+  | I64LIT Int64+  | U8LIT Word8+  | U16LIT Word16+  | U32LIT Word32+  | U64LIT Word64+  | FLOATLIT Double+  | F16LIT Half+  | F32LIT Float+  | F64LIT Double+  | CHARLIT Char+  | COLON+  | COLON_GT+  | BACKSLASH+  | APOSTROPHE+  | APOSTROPHE_THEN_HAT+  | APOSTROPHE_THEN_TILDE+  | BACKTICK+  | HASH_LBRACKET+  | DOT+  | TWO_DOTS+  | TWO_DOTS_LT+  | TWO_DOTS_GT+  | THREE_DOTS+  | LPAR+  | RPAR+  | RPAR_THEN_LBRACKET+  | LBRACKET+  | RBRACKET+  | LCURLY+  | RCURLY+  | COMMA+  | UNDERSCORE+  | RIGHT_ARROW+  | QUESTION_MARK+  | EQU+  | ASTERISK+  | NEGATE+  | BANG+  | DOLLAR+  | LTH+  | HAT+  | TILDE+  | PIPE+  | IF+  | THEN+  | ELSE+  | DEF+  | LET+  | LOOP+  | IN+  | FOR+  | DO+  | WITH+  | ASSERT+  | TRUE+  | FALSE+  | WHILE+  | INCLUDE+  | IMPORT+  | ENTRY+  | TYPE+  | MODULE+  | VAL+  | OPEN+  | LOCAL+  | MATCH+  | CASE+  | DOC String+  | EOF+  deriving (Show, Eq, Ord)++keyword :: T.Text -> Token+keyword s =+  case s of+    "true" -> TRUE+    "false" -> FALSE+    "if" -> IF+    "then" -> THEN+    "else" -> ELSE+    "def" -> DEF+    "let" -> LET+    "loop" -> LOOP+    "in" -> IN+    "val" -> VAL+    "for" -> FOR+    "do" -> DO+    "with" -> WITH+    "local" -> LOCAL+    "open" -> OPEN+    "include" -> INCLUDE+    "import" -> IMPORT+    "type" -> TYPE+    "entry" -> ENTRY+    "module" -> MODULE+    "while" -> WHILE+    "assert" -> ASSERT+    "match" -> MATCH+    "case" -> CASE+    _ -> ID $ nameFromText s++indexing :: (Loc, T.Text) -> Alex Name+indexing (loc, s) = case keyword s of+  ID v -> return v+  _ -> alexError loc $ "Cannot index keyword '" ++ T.unpack s ++ "'."++mkQualId :: T.Text -> Alex ([Name], Name)+mkQualId s = case reverse $ T.splitOn "." s of+  [] -> error "mkQualId: no components"+  k : qs -> return (map nameFromText (reverse qs), nameFromText k)++-- | Suffix a zero if the last character is dot.+suffZero :: T.Text -> T.Text+suffZero s = if T.last s == '.' then s <> "0" else s++tryRead :: Read a => String -> T.Text -> Alex a+tryRead desc s = case reads s' of+  [(x, "")] -> return x+  _ -> error $ "Invalid " ++ desc ++ " literal: `" ++ T.unpack s ++ "'."+  where+    s' = T.unpack s++readIntegral :: Integral a => T.Text -> a+readIntegral s+  | "0x" `T.isPrefixOf` s || "0X" `T.isPrefixOf` s = parseBase 16 (T.drop 2 s)+  | "0b" `T.isPrefixOf` s || "0B" `T.isPrefixOf` s = parseBase 2 (T.drop 2 s)+  | "0r" `T.isPrefixOf` s || "0R" `T.isPrefixOf` s = fromRoman (T.drop 2 s)+  | otherwise = parseBase 10 s+  where+    parseBase base = T.foldl (\acc c -> acc * base + fromIntegral (digitToInt c)) 0++tokenC :: a -> (Pos, Char, BS.ByteString, Int64) -> Int64 -> Alex (Lexeme a)+tokenC v = tokenS $ const v++tokenS :: (T.Text -> a) -> (Pos, Char, BS.ByteString, Int64) -> Int64 -> Alex (Lexeme a)+tokenS f = tokenM $ return . f++type Lexeme a = (Pos, Pos, a)++tokenM ::+  (T.Text -> Alex a) ->+  (Pos, Char, BS.ByteString, Int64) ->+  Int64 ->+  Alex (Lexeme a)+tokenM f = tokenPosM (f . snd)++tokenPosM ::+  ((Loc, T.Text) -> Alex a) ->+  (Pos, Char, BS.ByteString, Int64) ->+  Int64 ->+  Alex (Lexeme a)+tokenPosM f (pos, _, s, _) len = do+  x <- f (Loc pos pos', T.decodeUtf8 $ BS.toStrict s')+  return (pos, pos', x)+  where+    pos' = advance pos s'+    s' = BS.take len s++advance :: Pos -> BS.ByteString -> Pos+advance orig_pos = foldl' advance' orig_pos . init . BS.unpack+  where+    advance' (Pos f !line !col !addr) c+      | c == nl = Pos f (line + 1) 1 (addr + 1)+      | otherwise = Pos f line (col + 1) (addr + 1)+    nl = fromIntegral $ ord '\n'++symbol :: [Name] -> Name -> Token+symbol [] q+  | nameToText q == "*" = ASTERISK+  | nameToText q == "-" = NEGATE+  | nameToText q == "<" = LTH+  | nameToText q == "^" = HAT+  | nameToText q == "|" = PIPE+  | otherwise = SYMBOL (leadingOperator q) [] q+symbol qs q = SYMBOL (leadingOperator q) qs q++romanNumerals :: Integral a => [(T.Text, a)]+romanNumerals =+  reverse+    [ ("I", 1),+      ("IV", 4),+      ("V", 5),+      ("IX", 9),+      ("X", 10),+      ("XL", 40),+      ("L", 50),+      ("XC", 90),+      ("C", 100),+      ("CD", 400),+      ("D", 500),+      ("CM", 900),+      ("M", 1000)+    ]++fromRoman :: Integral a => T.Text -> a+fromRoman s =+  case find ((`T.isPrefixOf` s) . fst) romanNumerals of+    Nothing -> 0+    Just (d, n) -> n + fromRoman (T.drop (T.length d) s)++readHexRealLit :: RealFloat a => T.Text -> Alex a+readHexRealLit s =+  let num = T.drop 2 s+   in -- extract number into integer, fractional and (optional) exponent+      let comps = T.split (`elem` ['.', 'p', 'P']) num+       in case comps of+            [i, f, p] ->+              let runTextReader r = fromInteger . fst . fromRight (error "internal error") . r+                  intPart = runTextReader T.hexadecimal i+                  fracPart = runTextReader T.hexadecimal f+                  exponent = runTextReader (T.signed T.decimal) p++                  fracLen = fromIntegral $ T.length f+                  fracVal = fracPart / (16.0 ** fracLen)+                  totalVal = (intPart + fracVal) * (2.0 ** exponent)+               in return totalVal+            _ -> error "bad hex real literal"
+ src/Language/Futhark/Parser/Lexer/Wrapper.hs view
@@ -0,0 +1,137 @@+{-# LANGUAGE BangPatterns #-}+{-# OPTIONS_GHC -funbox-strict-fields #-}++-- | Utility definitions used by the lexer.  None of the default Alex+-- "wrappers" are precisely what we need.  The code here is based on+-- the "monad-bytestring" wrapper.  The code here is completely+-- Futhark-agnostic, and perhaps it can even serve as inspiration for+-- other Alex lexer wrappers.+module Language.Futhark.Parser.Lexer.Wrapper+  ( runAlex',+    Alex,+    AlexInput,+    Byte,+    LexerError (..),+    alexSetInput,+    alexGetInput,+    alexGetByte,+    alexGetStartCode,+    alexMove,+    alexError,+    alexGetPos,+  )+where++import Control.Applicative (liftA)+import qualified Data.ByteString.Internal as BS (w2c)+import qualified Data.ByteString.Lazy as BS+import Data.Int (Int64)+import Data.Loc (Loc, Pos (..))+import Data.Word (Word8)++type Byte = Word8++-- | The input type.  Contains:+--+-- 1. current position+--+-- 2. previous char+--+-- 3. current input string+--+-- 4. bytes consumed so far+type AlexInput =+  ( Pos, -- current position,+    Char, -- previous char+    BS.ByteString, -- current input string+    Int64 -- bytes consumed so far+  )++{-# INLINE alexGetByte #-}+alexGetByte :: AlexInput -> Maybe (Byte, AlexInput)+alexGetByte (p, _, cs, n) =+  case BS.uncons cs of+    Nothing -> Nothing+    Just (b, cs') ->+      let c = BS.w2c b+          p' = alexMove p c+          n' = n + 1+       in p' `seq` cs' `seq` n' `seq` Just (b, (p', c, cs', n'))++tabSize :: Int+tabSize = 8++{-# INLINE alexMove #-}+alexMove :: Pos -> Char -> Pos+alexMove (Pos !f !l !c !a) '\t' = Pos f l (c + tabSize - ((c - 1) `mod` tabSize)) (a + 1)+alexMove (Pos !f !l _ !a) '\n' = Pos f (l + 1) 1 (a + 1)+alexMove (Pos !f !l !c !a) _ = Pos f l (c + 1) (a + 1)++data AlexState = AlexState+  { alex_pos :: !Pos, -- position at current input location+    alex_bpos :: !Int64, -- bytes consumed so far+    alex_inp :: BS.ByteString, -- the current input+    alex_chr :: !Char, -- the character before the input+    alex_scd :: !Int -- the current startcode+  }++runAlex' :: Pos -> BS.ByteString -> Alex a -> Either LexerError a+runAlex' start_pos input__ (Alex f) =+  case f+    ( AlexState+        { alex_pos = start_pos,+          alex_bpos = 0,+          alex_inp = input__,+          alex_chr = '\n',+          alex_scd = 0+        }+    ) of+    Left msg -> Left msg+    Right (_, a) -> Right a++newtype Alex a = Alex {unAlex :: AlexState -> Either LexerError (AlexState, a)}++data LexerError = LexerError Loc String++instance Show LexerError where+  show (LexerError _ s) = s++instance Functor Alex where+  fmap = liftA++instance Applicative Alex where+  pure a = Alex $ \s -> Right (s, a)+  fa <*> a = Alex $ \s -> case unAlex fa s of+    Left msg -> Left msg+    Right (s', f) -> case unAlex a s' of+      Left msg -> Left msg+      Right (s'', b) -> Right (s'', f b)++instance Monad Alex where+  m >>= k = Alex $ \s -> case unAlex m s of+    Left msg -> Left msg+    Right (s', a) -> unAlex (k a) s'++alexGetInput :: Alex AlexInput+alexGetInput =+  Alex $ \s@AlexState {alex_pos = pos, alex_bpos = bpos, alex_chr = c, alex_inp = inp} ->+    Right (s, (pos, c, inp, bpos))++alexSetInput :: AlexInput -> Alex ()+alexSetInput (pos, c, inp, bpos) =+  Alex $ \s -> case s+    { alex_pos = pos,+      alex_bpos = bpos,+      alex_chr = c,+      alex_inp = inp+    } of+    state@AlexState {} -> Right (state, ())++alexError :: Loc -> String -> Alex a+alexError loc message = Alex $ const $ Left $ LexerError loc message++alexGetStartCode :: Alex Int+alexGetStartCode = Alex $ \s@AlexState {alex_scd = sc} -> Right (s, sc)++alexGetPos :: Alex Pos+alexGetPos = Alex $ \s -> Right (s, alex_pos s)
src/Language/Futhark/Parser/Monad.hs view
@@ -31,7 +31,7 @@     addDoc,     addAttr,     twoDotsRange,-    ParseError (..),+    SyntaxError (..),     emptyArrayError,     parseError,     parseErrorAt,@@ -50,9 +50,10 @@ import qualified Data.Map.Strict as M import Data.Monoid import qualified Data.Text as T-import Futhark.Util.Loc hiding (L) -- Lexer has replacements.+import Futhark.Util.Loc import Futhark.Util.Pretty hiding (line) import Language.Futhark.Parser.Lexer+import Language.Futhark.Parser.Lexer.Wrapper (LexerError (..)) import Language.Futhark.Pretty () import Language.Futhark.Prop import Language.Futhark.Syntax@@ -88,18 +89,19 @@   parseErrorAt loc . Just $     "Only the keyword '" <> expected <> "' may appear here." -mustBeEmpty :: SrcLoc -> ValueType -> ParserMonad ()+mustBeEmpty :: Located loc => loc -> ValueType -> ParserMonad () mustBeEmpty _ (Array _ _ _ (ShapeDecl dims))   | 0 `elem` dims = pure () mustBeEmpty loc t =   parseErrorAt loc $ Just $ pretty t ++ " is not an empty array." -newtype ParserEnv = ParserEnv-  { parserFile :: FilePath+data ParserEnv = ParserEnv+  { _parserFile :: FilePath,+    parserInput :: T.Text,+    parserLexical :: ([L Token], Pos)   } -type ParserMonad =-  ExceptT String (StateT ParserEnv (StateT ([L Token], Pos) ReadLineMonad))+type ParserMonad = ExceptT SyntaxError (StateT ParserEnv ReadLineMonad)  data ReadLineMonad a   = Value a@@ -126,23 +128,23 @@   s <- fetch   getLinesFromM fetch $ f $ Just s -getNoLines :: ReadLineMonad a -> Either String a+getNoLines :: ReadLineMonad a -> Either SyntaxError a getNoLines (Value x) = Right x getNoLines (GetLine f) = getNoLines $ f Nothing -combArrayElements :: Value -> [Value] -> Either String Value+combArrayElements :: Value -> [Value] -> Either SyntaxError Value combArrayElements = foldM comb   where     comb x y       | valueType x == valueType y = Right x       | otherwise =-        Left $+        Left . SyntaxError NoLoc $           "Elements " <> pretty x <> " and "             <> pretty y             <> " cannot exist in same array."  arrayFromList :: [a] -> Array Int a-arrayFromList l = listArray (0, length l -1) l+arrayFromList l = listArray (0, length l - 1) l  applyExp :: [UncheckedExp] -> ParserMonad UncheckedExp applyExp all_es@((Constr n [] _ loc1) : es) =@@ -173,24 +175,24 @@     field (name, pat) = RecordFieldExplicit name <$> patternExp pat <*> pure loc  eof :: Pos -> L Token-eof pos = L (SrcLoc $ Loc pos pos) EOF+eof pos = L (Loc pos pos) EOF -binOpName :: L Token -> (QualName Name, SrcLoc)+binOpName :: L Token -> (QualName Name, Loc) binOpName (L loc (SYMBOL _ qs op)) = (QualName qs op, loc) binOpName t = error $ "binOpName: unexpected " ++ show t  binOp :: UncheckedExp -> L Token -> UncheckedExp -> UncheckedExp binOp x (L loc (SYMBOL _ qs op)) y =-  AppExp (BinOp (QualName qs op, loc) NoInfo (x, NoInfo) (y, NoInfo) (srcspan x y)) NoInfo+  AppExp (BinOp (QualName qs op, srclocOf loc) NoInfo (x, NoInfo) (y, NoInfo) (srcspan x y)) NoInfo binOp _ t _ = error $ "binOp: unexpected " ++ show t  getTokens :: ParserMonad ([L Token], Pos)-getTokens = lift $ lift get+getTokens = lift $ gets parserLexical  putTokens :: ([L Token], Pos) -> ParserMonad ()-putTokens = lift . lift . put+putTokens l = lift $ modify $ \env -> env {parserLexical = l} -primTypeFromName :: SrcLoc -> Name -> ParserMonad PrimType+primTypeFromName :: Loc -> Name -> ParserMonad PrimType primTypeFromName loc s = maybe boom pure $ M.lookup s namesToPrimTypes   where     boom = parseErrorAt loc $ Just $ "No type named " ++ nameToString s@@ -213,7 +215,13 @@ primNegate (BoolValue v) = BoolValue $ not v  readLine :: ParserMonad (Maybe T.Text)-readLine = lift $ lift $ lift readLineFromMonad+readLine = do+  s <- lift $ lift readLineFromMonad+  case s of+    Just s' ->+      lift $ modify $ \env -> env {parserInput = parserInput env <> "\n" <> s'}+    Nothing -> pure ()+  pure s  lexer :: (L Token -> ParserMonad a) -> ParserMonad a lexer cont = do@@ -229,10 +237,7 @@             case line of               Nothing -> throwError parse_e               Just line' -> pure $ scanTokensText (advancePos pos '\n') line'-          (ts'', pos') <--            case ts' of-              Right x -> pure x-              Left lex_e -> throwError lex_e+          (ts'', pos') <- either (throwError . lexerErrToParseErr) pure ts'           case ts'' of             [] -> cont $ eof pos             xs -> do@@ -244,49 +249,51 @@  parseError :: (L Token, [String]) -> ParserMonad a parseError (L loc EOF, expected) =-  parseErrorAt (srclocOf loc) . Just . unlines $-    [ "unexpected end of file.",+  parseErrorAt (locOf loc) . Just . unlines $+    [ "Unexpected end of file.",       "Expected one of the following: " ++ unwords expected     ] parseError (L loc DOC {}, _) =-  parseErrorAt (srclocOf loc) $-    Just "documentation comments ('-- |') are only permitted when preceding declarations."-parseError (L loc tok, expected) =+  parseErrorAt (locOf loc) $+    Just "Documentation comments ('-- |') are only permitted when preceding declarations."+parseError (L loc _, expected) = do+  input <- lift $ gets parserInput+  let ~(Loc (Pos _ _ _ beg) (Pos _ _ _ end)) = locOf loc+      tok_src = T.take (end - beg + 1) $ T.drop beg input   parseErrorAt loc . Just . unlines $-    [ "unexpected " ++ show tok,-      "Expected one of the following: " ++ unwords expected+    [ "Unexpected token: '" <> T.unpack tok_src <> "'",+      "Expected one of the following: " <> unwords expected     ] -parseErrorAt :: SrcLoc -> Maybe String -> ParserMonad a-parseErrorAt loc Nothing = throwError $ "Error at " ++ locStr loc ++ ": Parse error."-parseErrorAt loc (Just s) = throwError $ "Error at " ++ locStr loc ++ ": " ++ s+parseErrorAt :: Located loc => loc -> Maybe String -> ParserMonad a+parseErrorAt loc Nothing = throwError $ SyntaxError (locOf loc) "Syntax error."+parseErrorAt loc (Just s) = throwError $ SyntaxError (locOf loc) s -emptyArrayError :: SrcLoc -> ParserMonad a+emptyArrayError :: Loc -> ParserMonad a emptyArrayError loc =   parseErrorAt loc $     Just "write empty arrays as 'empty(t)', for element type 't'.\n" -twoDotsRange :: SrcLoc -> ParserMonad a+twoDotsRange :: Loc -> ParserMonad a twoDotsRange loc = parseErrorAt loc $ Just "use '...' for ranges, not '..'.\n"  --- Now for the parser interface. --- | A parse error.  Use 'show' to get a human-readable description.-newtype ParseError = ParseError String+-- | A syntax error.+data SyntaxError = SyntaxError {syntaxErrorLoc :: Loc, syntaxErrorMsg :: String} -instance Show ParseError where-  show (ParseError s) = s+lexerErrToParseErr :: LexerError -> SyntaxError+lexerErrToParseErr (LexerError loc msg) = SyntaxError loc msg -parseInMonad :: ParserMonad a -> FilePath -> T.Text -> ReadLineMonad (Either ParseError a)+parseInMonad :: ParserMonad a -> FilePath -> T.Text -> ReadLineMonad (Either SyntaxError a) parseInMonad p file program =-  either (Left . ParseError) Right-    <$> either-      (pure . Left)-      (evalStateT (evalStateT (runExceptT p) env))-      (scanTokensText (Pos file 1 1 0) program)+  either+    (pure . Left . lexerErrToParseErr)+    (evalStateT (runExceptT p) . env)+    (scanTokensText (Pos file 1 1 0) program)   where-    env = ParserEnv {parserFile = file}+    env = ParserEnv file program -parse :: ParserMonad a -> FilePath -> T.Text -> Either ParseError a+parse :: ParserMonad a -> FilePath -> T.Text -> Either SyntaxError a parse p file program =-  either (Left . ParseError) id $ getNoLines $ parseInMonad p file program+  either Left id $ getNoLines $ parseInMonad p file program
src/Language/Futhark/Parser/Parser.y view
@@ -6,16 +6,20 @@ module Language.Futhark.Parser.Parser   ( prog   , expression+  , declaration   , modExpression   , futharkType   , anyValue   , anyValues   , parse-  , ParseError(..)-  , parseDecOrExpIncrM+  , ReadLineMonad (..)+  , getLinesFromM+  , parseInMonad+  , SyntaxError(..)   )   where +import Data.Bifunctor (second) import Control.Monad import Control.Monad.Trans import Control.Monad.Except@@ -37,7 +41,7 @@ import Language.Futhark.Pretty import Language.Futhark.Parser.Lexer import Futhark.Util.Pretty-import Futhark.Util.Loc hiding (L) -- Lexer has replacements.+import Futhark.Util.Loc import Language.Futhark.Parser.Monad  }@@ -195,7 +199,7 @@ -- The main parser.  Doc :: { DocComment }-     : doc { let L loc (DOC s) = $1 in DocComment s loc }+     : doc { let L loc (DOC s) = $1 in DocComment s (srclocOf loc) }  -- Four cases to avoid ambiguities. Prog :: { UncheckedProg }@@ -222,7 +226,7 @@     | TypeAbbr          { TypeDec $1 }     | SigBind           { SigDec $1 }     | ModBind           { ModDec $1 }-    | open ModExp       { OpenDec $2 $1 }+    | open ModExp       { OpenDec $2 (srclocOf $1) }     | import stringlit       { let L _ (STRINGLIT s) = $2 in ImportDec (T.unpack s) NoInfo (srcspan $1 $>) }     | local Dec         { LocalDec $2 (srcspan $1 $>) }@@ -232,7 +236,7 @@ ;  SigExp :: { UncheckedSigExp }-        : QualName            { let (v, loc) = $1 in SigVar v NoInfo loc }+        : QualName            { let (v, loc) = $1 in SigVar v NoInfo (srclocOf loc) }         | '{' Specs '}'  { SigSpecs $2 (srcspan $1 $>) }         | SigExp with TypeRef { SigWith $1 $3 (srcspan $1 $>) }         | '(' SigExp ')'      { SigParens $2 (srcspan $1 $>) }@@ -273,11 +277,11 @@             : '(' ModExp ')'               { ModParens $2 (srcspan $1 $>) }             | QualName-              { let (v, loc) = $1 in ModVar v loc }+              { let (v, loc) = $1 in ModVar v (srclocOf loc) }             | '{' Decs '}' { ModDecs $2 (srcspan $1 $>) }  SimpleSigExp :: { UncheckedSigExp }-             : QualName            { let (v, loc) = $1 in SigVar v NoInfo loc }+             : QualName            { let (v, loc) = $1 in SigVar v NoInfo (srclocOf loc) }              | '(' SigExp ')'      { $2 }  ModBind :: { ModBindBase NoInfo Name }@@ -312,7 +316,7 @@           in TypeSpec $2 name $4 Nothing (srcspan $1 $>) }       | type Liftedness 'id[' id ']' TypeParams         { let L _ (INDEXING name) = $3; L ploc (ID pname) = $4-          in TypeSpec $2 name (TypeParamDim pname ploc : $6) Nothing (srcspan $1 $>) }+          in TypeSpec $2 name (TypeParamDim pname (srclocOf ploc) : $6) Nothing (srcspan $1 $>) }        | module id ':' SigExp         { let L _ (ID name) = $2@@ -347,7 +351,7 @@  -- Note that this production does not include Minus, but does include -- operator sections.-BinOp :: { (QualName Name, SrcLoc) }+BinOp :: { (QualName Name, Loc) }       : '+...'     { binOpName $1 }       | '-...'     { binOpName $1 }       | '*...'     { binOpName $1 }@@ -384,7 +388,7 @@                    pure name }       | '-'   { nameFromString "-" } -BindingId :: { (Name, SrcLoc) }+BindingId :: { (Name, Loc) }      : id                   { let L loc (ID name) = $1 in (name, loc) }      | '(' BindingBinOp ')' { ($2, $1) } @@ -416,6 +420,19 @@             Nothing mempty (srcspan $1 $>)           } +        -- Some error cases+        | def '(' Pat ',' Pats1 ')' '=' Exp+          {% parseErrorAt (srcspan $2 $6) $ Just $+             unlines ["Cannot bind patterns at top level.",+                      "Bind a single name instead."]+          }++        | let '(' Pat ',' Pats1 ')' '=' Exp+          {% parseErrorAt (srcspan $2 $6) $ Just $+             unlines ["Cannot bind patterns at top level.",+                      "Bind a single name instead."]+          }+ TypeExpDecl :: { TypeDeclBase NoInfo Name }              : TypeExp %prec bottom { TypeDecl $1 NoInfo } @@ -425,7 +442,7 @@               in TypeBind name $2 $4 $6 NoInfo Nothing (srcspan $1 $>) }          | type Liftedness 'id[' id ']' TypeParams '=' TypeExp            { let L loc (INDEXING name) = $3; L ploc (ID pname) = $4-             in TypeBind name $2 (TypeParamDim pname ploc:$6) $8 NoInfo Nothing (srcspan $1 $>) }+             in TypeBind name $2 (TypeParamDim pname (srclocOf ploc):$6) $8 NoInfo Nothing (srcspan $1 $>) }  TypeExp :: { UncheckedTypeExp }          : '(' id ':' TypeExp ')' '->' TypeExp@@ -454,18 +471,18 @@            }  SumType :: { UncheckedTypeExp }-SumType  : SumClauses %prec sumprec { let (cs, loc) = $1 in TESum cs loc }+SumType  : SumClauses %prec sumprec { let (cs, loc) = $1 in TESum cs (srclocOf loc) } -SumClauses :: { ([(Name, [UncheckedTypeExp])], SrcLoc) }+SumClauses :: { ([(Name, [UncheckedTypeExp])], Loc) }             : SumClauses '|' SumClause %prec sumprec               { let (cs, loc1) = $1; (c, ts, loc2) = $3-                in (cs++[(c, ts)], srcspan loc1 loc2) }+                in (cs++[(c, ts)], locOf (srcspan loc1 loc2)) }             | SumClause  %prec sumprec               { let (n, ts, loc) = $1 in ([(n, ts)], loc) } -SumClause :: { (Name, [UncheckedTypeExp], SrcLoc) }+SumClause :: { (Name, [UncheckedTypeExp], Loc) }            : SumClause TypeExpAtom-             { let (n, ts, loc) = $1 in (n, ts ++ [$2], srcspan loc $>)}+             { let (n, ts, loc) = $1 in (n, ts ++ [$2], locOf (srcspan loc $>))}            | Constr             { (fst $1, [], snd $1) } @@ -474,10 +491,10 @@                 { TEApply $1 $2 (srcspan $1 $>) }               | 'id[' DimExp ']'                 { let L loc (INDEXING v) = $1-                  in TEApply (TEVar (qualName v) loc) (TypeArgExpDim $2 loc) (srcspan $1 $>) }+                  in TEApply (TEVar (qualName v) (srclocOf loc)) (TypeArgExpDim $2 (srclocOf loc)) (srcspan $1 $>) }               | 'qid[' DimExp ']'                 { let L loc (QUALINDEXING qs v) = $1-                  in TEApply (TEVar (QualName qs v) loc) (TypeArgExpDim $2 loc) (srcspan $1 $>) }+                  in TEApply (TEVar (QualName qs v) (srclocOf loc)) (TypeArgExpDim $2 (srclocOf loc)) (srcspan $1 $>) }               | TypeExpAtom                 { $1 } @@ -487,11 +504,11 @@              | '(' TypeExp ',' TupleTypes ')' { TETuple ($2:$4) (srcspan $1 $>) }              | '{' '}'                        { TERecord [] (srcspan $1 $>) }              | '{' FieldTypes1 '}'            { TERecord $2 (srcspan $1 $>) }-             | QualName                       { TEVar (fst $1) (snd $1) }+             | QualName                       { TEVar (fst $1) (srclocOf (snd $1)) }              | SumType                        { $1 } -Constr :: { (Name, SrcLoc) }-        : constructor { let L _ (CONSTRUCTOR c) = $1 in (c, srclocOf $1) }+Constr :: { (Name, Loc) }+        : constructor { let L _ (CONSTRUCTOR c) = $1 in (c, locOf $1) }  TypeArg :: { TypeArgExp Name }          : '[' DimExp ']' { TypeArgExpDim $2 (srcspan $1 $>) }@@ -510,10 +527,10 @@  DimExp :: { DimExp Name }         : QualName-          { DimExpNamed (fst $1) (snd $1) }+          { DimExpNamed (fst $1) (srclocOf (snd $1)) }         | intlit           { let L loc (INTLIT n) = $1-            in DimExpConst (fromIntegral n) loc }+            in DimExpConst (fromIntegral n) (srclocOf loc) }         |           { DimExpAny } @@ -528,12 +545,12 @@ FunParams :                     { [] }            | FunParam FunParams { $1 : $2 } -QualName :: { (QualName Name, SrcLoc) }+QualName :: { (QualName Name, Loc) }           : id FieldAccesses             { let L vloc (ID v) = $1 in               foldl (\(QualName qs v', loc) (y, yloc) ->-                      (QualName (qs ++ [v']) y, srcspan loc yloc))-                    (qualName v, vloc) $2 }+                      (QualName (qs ++ [v']) y, locOf (srcspan loc yloc)))+                    (qualName v, locOf vloc) $2 }  -- Expressions are divided into several layers.  The first distinction -- (between Exp and Exp2) is to factor out ascription, which we do not@@ -591,7 +608,7 @@      | Exp2 '<|...' Exp2   { binOp $1 $2 $3 }       | Exp2 '<' Exp2              { binOp $1 (L $2 (SYMBOL Less [] (nameFromString "<"))) $3 }-     | Exp2 '`' QualName '`' Exp2 { AppExp (BinOp $3 NoInfo ($1, NoInfo) ($5, NoInfo) (srcspan $1 $>)) NoInfo }+     | Exp2 '`' QualName '`' Exp2 { AppExp (BinOp (second srclocOf $3) NoInfo ($1, NoInfo) ($5, NoInfo) (srcspan $1 $>)) NoInfo }       | Exp2 '...' Exp2           { AppExp (Range $1 Nothing (ToInclusive $3) (srcspan $1 $>)) NoInfo }      | Exp2 '..<' Exp2           { AppExp (Range $1 Nothing (UpToExclusive $3) (srcspan $1 $>)) NoInfo }@@ -601,8 +618,8 @@      | Exp2 '..' Exp2 '..>' Exp2 { AppExp (Range $1 (Just $3) (DownToExclusive $5) (srcspan $1 $>)) NoInfo }      | Exp2 '..' Atom            {% twoDotsRange $2 }      | Atom '..' Exp2            {% twoDotsRange $2 }-     | '-' Exp2  %prec juxtprec  { Negate $2 $1 }-     | '!' Exp2 %prec juxtprec   { Not $2 $1 }+     | '-' Exp2  %prec juxtprec  { Negate $2 (srcspan $1 $>) }+     | '!' Exp2 %prec juxtprec   { Not $2 (srcspan $1 $>) }        | Exp2 with '[' DimIndices ']' '=' Exp2@@ -626,19 +643,19 @@             { [$1] }  Atom :: { UncheckedExp }-Atom : PrimLit        { Literal (fst $1) (snd $1) }-     | Constr         { Constr (fst $1) [] NoInfo (snd $1) }+Atom : PrimLit        { Literal (fst $1) (srclocOf (snd $1)) }+     | Constr         { Constr (fst $1) [] NoInfo (srclocOf (snd $1)) }      | charlit        { let L loc (CHARLIT x) = $1-                        in IntLit (toInteger (ord x)) NoInfo loc }-     | intlit         { let L loc (INTLIT x) = $1 in IntLit x NoInfo loc }-     | floatlit       { let L loc (FLOATLIT x) = $1 in FloatLit x NoInfo loc }+                        in IntLit (toInteger (ord x)) NoInfo (srclocOf loc) }+     | intlit         { let L loc (INTLIT x) = $1 in IntLit x NoInfo (srclocOf loc) }+     | floatlit       { let L loc (FLOATLIT x) = $1 in FloatLit x NoInfo (srclocOf loc) }      | stringlit      { let L loc (STRINGLIT s) = $1 in-                        StringLit (BS.unpack (T.encodeUtf8 s)) loc }+                        StringLit (BS.unpack (T.encodeUtf8 s)) (srclocOf loc) }      | '(' Exp ')' FieldAccesses        { foldl (\x (y, _) -> Project y x NoInfo (srclocOf x))                (Parens $2 (srcspan $1 ($3:map snd $>)))                $4 }-     | '(' Exp ')[' DimIndices ']'    { AppExp (Index (Parens $2 $1) $4 (srcspan $1 $>)) NoInfo }+     | '(' Exp ')[' DimIndices ']'    { AppExp (Index (Parens $2 (srclocOf $1)) $4 (srcspan $1 $>)) NoInfo }      | '(' Exp ',' Exps1 ')'          { TupLit ($2 : fst $4 : snd $4) (srcspan $1 $>) }      | '('      ')'                   { TupLit [] (srcspan $1 $>) }      | '[' Exps1 ']'                  { ArrayLit (fst $2:snd $2) NoInfo (srcspan $1 $>) }@@ -647,14 +664,14 @@      | QualVarSlice FieldAccesses        { let ((v, vloc),slice,loc) = $1          in foldl (\x (y, _) -> Project y x NoInfo (srcspan x (srclocOf x)))-                  (AppExp (Index (Var v NoInfo vloc) slice (srcspan vloc loc)) NoInfo)+                  (AppExp (Index (Var v NoInfo (srclocOf vloc)) slice (srcspan vloc loc)) NoInfo)                   $2 }      | QualName-       { Var (fst $1) NoInfo (snd $1) }+       { Var (fst $1) NoInfo (srclocOf (snd $1)) }      | '{' Fields '}' { RecordLit $2 (srcspan $1 $>) }      | 'qid.(' Exp ')'        { let L loc (QUALPAREN qs name) = $1 in-         QualParens (QualName qs name, loc) $2 (srcspan $1 $>) }+         QualParens (QualName qs name, srclocOf loc) $2 (srcspan $1 $>) }       -- Operator sections.      | '(' '-' ')'@@ -676,7 +693,7 @@        { IndexSection $4 NoInfo (srcspan $1 $>) }  -NumLit :: { (PrimValue, SrcLoc) }+NumLit :: { (PrimValue, Loc) }         : i8lit   { let L loc (I8LIT num)  = $1 in (SignedValue $ Int8Value num, loc) }         | i16lit  { let L loc (I16LIT num) = $1 in (SignedValue $ Int16Value num, loc) }         | i32lit  { let L loc (I32LIT num) = $1 in (SignedValue $ Int32Value num, loc) }@@ -692,7 +709,7 @@         | f64lit { let L loc (F64LIT num) = $1 in (FloatValue $ Float64Value num, loc) }  -PrimLit :: { (PrimValue, SrcLoc) }+PrimLit :: { (PrimValue, Loc) }         : true   { (BoolValue True, $1) }         | false  { (BoolValue False, $1) }         | NumLit { $1 }@@ -706,20 +723,20 @@         : Exps1_ ',' Exp { (snd $1 : fst $1, $3) }         | Exp            { ([], $1) } -FieldAccess :: { (Name, SrcLoc) }+FieldAccess :: { (Name, Loc) }              : '.' id { let L loc (ID f) = $2 in (f, loc) }              | '.int' { let L loc (PROJ_INTFIELD x) = $1 in (x, loc) } -FieldAccesses :: { [(Name, SrcLoc)] }+FieldAccesses :: { [(Name, Loc)] }                : FieldAccess FieldAccesses { $1 : $2 }                |                           { [] } -FieldAccesses_ :: { [(Name, SrcLoc)] }+FieldAccesses_ :: { [(Name, Loc)] }                : FieldId FieldAccesses { (fst $1, snd $1) : $2 }  Field :: { FieldBase NoInfo Name }        : FieldId '=' Exp { RecordFieldExplicit (fst $1) $3 (srcspan (snd $1) $>) }-       | id              { let L loc (ID s) = $1 in RecordFieldImplicit s NoInfo loc }+       | id              { let L loc (ID s) = $1 in RecordFieldImplicit s NoInfo (srclocOf loc) }  Fields :: { [FieldBase NoInfo Name] }         : Fields1 { $1 }@@ -742,7 +759,7 @@                    NoInfo}       | let VarSlice '=' Exp LetBody-       { let ((v,_),slice,loc) = $2; ident = Ident v NoInfo loc+       { let ((v,_),slice,loc) = $2; ident = Ident v NoInfo (srclocOf loc)          in AppExp (LetWith ident ident slice $4 $5 (srcspan $1 $>)) NoInfo }  LetBody :: { UncheckedExp }@@ -778,16 +795,16 @@            | CPat ',' CPats1 { $1 : $3 }  CInnerPat :: { PatBase NoInfo Name }-               : id                                 { let L loc (ID name) = $1 in Id name NoInfo loc }+               : id                                 { let L loc (ID name) = $1 in Id name NoInfo (srclocOf loc) }                | '(' BindingBinOp ')'               { Id $2 NoInfo (srcspan $1 $>) }-               | '_'                                { Wildcard NoInfo $1 }+               | '_'                                { Wildcard NoInfo (srclocOf $1) }                | '(' ')'                            { TuplePat [] (srcspan $1 $>) }                | '(' CPat ')'                       { PatParens $2 (srcspan $1 $>) }                | '(' CPat ',' CPats1 ')'            { TuplePat ($2:$4) (srcspan $1 $>) }                | '{' CFieldPats '}'                 { RecordPat $2 (srcspan $1 $>) }-               | CaseLiteral                        { PatLit (fst $1) NoInfo (snd $1) }+               | CaseLiteral                        { PatLit (fst $1) NoInfo (srclocOf (snd $1)) }                | Constr                             { let (n, loc) = $1-                                                      in PatConstr n NoInfo [] loc }+                                                      in PatConstr n NoInfo [] (srclocOf loc) }  ConstrFields :: { [PatBase NoInfo Name] }               : CInnerPat                { [$1] }@@ -797,9 +814,9 @@                : FieldId '=' CPat                { (fst $1, $3) }                | FieldId ':' TypeExpDecl-               { (fst $1, PatAscription (Id (fst $1) NoInfo (snd $1)) $3 (srcspan (snd $1) $>)) }+               { (fst $1, PatAscription (Id (fst $1) NoInfo (srclocOf (snd $1))) $3 (srcspan (snd $1) $>)) }                | FieldId-               { (fst $1, Id (fst $1) NoInfo (snd $1)) }+               { (fst $1, Id (fst $1) NoInfo (srclocOf (snd $1))) }  CFieldPats :: { [(Name, PatBase NoInfo Name)] }                 : CFieldPats1 { $1 }@@ -809,7 +826,7 @@                  : CFieldPat ',' CFieldPats1 { $1 : $3 }                  | CFieldPat                    { [$1] } -CaseLiteral :: { (PatLit, SrcLoc) }+CaseLiteral :: { (PatLit, Loc) }              : charlit  { let L loc (CHARLIT x) = $1                           in (PatLitInt (toInteger (ord x)), loc) }              | PrimLit  { (PatLitPrim (fst $1), snd $1) }@@ -827,17 +844,17 @@          | while Exp            { While $2 } -VarSlice :: { ((Name, SrcLoc), UncheckedSlice, SrcLoc) }+VarSlice :: { ((Name, Loc), UncheckedSlice, Loc) }           : 'id[' DimIndices ']'             { let L vloc (INDEXING v) = $1-              in ((v, vloc), $2, srcspan $1 $>) }+              in ((v, vloc), $2, locOf (srcspan $1 $>)) } -QualVarSlice :: { ((QualName Name, SrcLoc), UncheckedSlice, SrcLoc) }+QualVarSlice :: { ((QualName Name, Loc), UncheckedSlice, Loc) }               : VarSlice                 { let ((v, vloc), y, loc) = $1 in ((qualName v, vloc), y, loc) }               | 'qid[' DimIndices ']'                 { let L vloc (QUALINDEXING qs v) = $1-                  in ((QualName qs v, vloc), $2, srcspan $1 $>) }+                  in ((QualName qs v, vloc), $2, locOf (srcspan $1 $>)) }  DimIndex :: { UncheckedDimIndex }          : Exp2                   { DimFix $1 }@@ -859,9 +876,9 @@              | DimIndex ',' DimIndices1 { ($1, fst $3 : snd $3) }  VarId :: { IdentBase NoInfo Name }-VarId : id { let L loc (ID name) = $1 in Ident name NoInfo loc }+VarId : id { let L loc (ID name) = $1 in Ident name NoInfo (srclocOf loc) } -FieldId :: { (Name, SrcLoc) }+FieldId :: { (Name, Loc) }          : id     { let L loc (ID name) = $1 in (name, loc) }          | intlit { let L loc (INTLIT n) = $1 in (nameFromString (show n), loc) } @@ -875,9 +892,9 @@        | Pat ',' Pats1          { $1 : $3 }  InnerPat :: { PatBase NoInfo Name }-InnerPat : id                               { let L loc (ID name) = $1 in Id name NoInfo loc }+InnerPat : id                               { let L loc (ID name) = $1 in Id name NoInfo (srclocOf loc) }              | '(' BindingBinOp ')'         { Id $2 NoInfo (srcspan $1 $>) }-             | '_'                          { Wildcard NoInfo $1 }+             | '_'                          { Wildcard NoInfo (srclocOf $1) }              | '(' ')'                      { TuplePat [] (srcspan $1 $>) }              | '(' Pat ')'                  { PatParens $2 (srcspan $1 $>) }              | '(' Pat ',' Pats1 ')'        { TuplePat ($2:$4) (srcspan $1 $>) }@@ -887,9 +904,9 @@               : FieldId '=' Pat                 { (fst $1, $3) }               | FieldId ':' TypeExpDecl-                { (fst $1, PatAscription (Id (fst $1) NoInfo (snd $1)) $3 (srcspan (snd $1) $>)) }+                { (fst $1, PatAscription (Id (fst $1) NoInfo (srclocOf (snd $1))) $3 (srcspan (snd $1) $>)) }               | FieldId-                { (fst $1, Id (fst $1) NoInfo (snd $1)) }+                { (fst $1, Id (fst $1) NoInfo (srclocOf (snd $1))) }  FieldPats :: { [(Name, PatBase NoInfo Name)] }                : FieldPats1 { $1 }@@ -903,12 +920,12 @@ maybeAscription(p) : ':' p { Just $2 }                    |       { Nothing } -AttrAtom :: { (AttrAtom Name, SrcLoc) }+AttrAtom :: { (AttrAtom Name, Loc) }           : id     { let L loc (ID s) =     $1 in (AtomName s, loc) }           | intlit { let L loc (INTLIT x) = $1 in (AtomInt x, loc) }  AttrInfo :: { AttrInfo Name }-         : AttrAtom         { uncurry AttrAtom $1 }+         : AttrAtom         { let (x,y) = $1 in AttrAtom x (srclocOf y) }          | id '('       ')' { let L _ (ID s) = $1 in AttrComp s [] (srcspan $1 $>) }          | id '(' Attrs ')' { let L _ (ID s) = $1 in AttrComp s $3 (srcspan $1 $>) } @@ -947,7 +964,7 @@ BoolValue : true           { PrimValue $ BoolValue True }           | false          { PrimValue $ BoolValue False } -SignedLit :: { (IntValue, SrcLoc) }+SignedLit :: { (IntValue, Loc) }           : i8lit   { let L loc (I8LIT num)  = $1 in (Int8Value num, loc) }           | i16lit  { let L loc (I16LIT num) = $1 in (Int16Value num, loc) }           | i32lit  { let L loc (I32LIT num) = $1 in (Int32Value num, loc) }@@ -955,13 +972,13 @@           | intlit  { let L loc (INTLIT num) = $1 in (Int32Value $ fromInteger num, loc) }           | charlit { let L loc (CHARLIT char) = $1 in (Int32Value $ fromIntegral $ ord char, loc) } -UnsignedLit :: { (IntValue, SrcLoc) }+UnsignedLit :: { (IntValue, Loc) }             : u8lit  { let L pos (U8LIT num)  = $1 in (Int8Value $ fromIntegral num, pos) }             | u16lit { let L pos (U16LIT num) = $1 in (Int16Value $ fromIntegral num, pos) }             | u32lit { let L pos (U32LIT num) = $1 in (Int32Value $ fromIntegral num, pos) }             | u64lit { let L pos (U64LIT num) = $1 in (Int64Value $ fromIntegral num, pos) } -FloatLit :: { (FloatValue, SrcLoc) }+FloatLit :: { (FloatValue, Loc) }          : f16lit { let L loc (F16LIT num) = $1 in (Float16Value num, loc) }          | f32lit { let L loc (F32LIT num) = $1 in (Float32Value num, loc) }          | f64lit { let L loc (F64LIT num) = $1 in (Float64Value num, loc) }@@ -1006,32 +1023,3 @@ Values : Value ',' Values { $1 : $3 }        | Value            { [$1] }        |                  { [] }--{-  -- | Parse an Futhark expression incrementally from monadic actions, using the--- 'FilePath' as the source name for error messages.-parseExpIncrM ::-  Monad m =>-  m T.Text ->-  FilePath ->-  T.Text ->-  m (Either ParseError UncheckedExp)-parseExpIncrM fetch file program =-  getLinesFromM fetch $ parseInMonad expression file program---- | Parse either an expression or a declaration incrementally;--- favouring declarations in case of ambiguity.-parseDecOrExpIncrM ::-  Monad m =>-  m T.Text ->-  FilePath ->-  T.Text ->-  m (Either ParseError (Either UncheckedDec UncheckedExp))-parseDecOrExpIncrM fetch file input =-  case parseInMonad declaration file input of-    Value Left {} -> fmap Right <$> parseExpIncrM fetch file input-    Value (Right d) -> pure $ Right $ Left d-    GetLine c -> do-      l <- fetch-      parseDecOrExpIncrM fetch file $ input <> "\n" <> l-}
src/Language/Futhark/Syntax.hs view
@@ -13,6 +13,7 @@ module Language.Futhark.Syntax   ( module Language.Futhark.Core,     pretty,+    prettyText,      -- * Types     Uniqueness (..),
src/Language/Futhark/TypeChecker.hs view
@@ -11,7 +11,7 @@     checkExp,     checkDec,     checkModExp,-    TypeError,+    TypeError (..),     Warnings,     initialEnv,     envWithImports,@@ -403,7 +403,7 @@   case mtyMod f_mty of     ModFun functor -> do       (e_abs, e_mty, e') <- checkOneModExp e-      (mty, psubsts, rsubsts) <- applyFunctor loc functor e_mty+      (mty, psubsts, rsubsts) <- applyFunctor (locOf loc) functor e_mty       return         ( mtyAbs mty <> f_abs <> e_abs,           mty,@@ -414,7 +414,7 @@ checkOneModExp (ModAscript me se NoInfo loc) = do   (me_abs, me_mod, me') <- checkOneModExp me   (se_abs, se_mty, se') <- checkSigExp se-  match_subst <- badOnLeft $ matchMTys me_mod se_mty loc+  match_subst <- badOnLeft $ matchMTys me_mod se_mty (locOf loc)   return (se_abs <> me_abs, se_mty, ModAscript me' se' (Info match_subst) loc) checkOneModExp (ModLambda param maybe_fsig_e body_e loc) =   withModParam param $ \param' param_abs param_mod -> do@@ -476,7 +476,7 @@         )     Just fsig_e -> do       (fsig_abs, fsig_mty, fsig_e') <- checkSigExp fsig_e-      fsig_subst <- badOnLeft $ matchMTys body_mty fsig_mty loc+      fsig_subst <- badOnLeft $ matchMTys body_mty fsig_mty (locOf loc)       return         ( fsig_abs <> body_e_abs,           Just (fsig_e', Info fsig_subst),
src/Language/Futhark/TypeChecker/Modules.hs view
@@ -251,7 +251,7 @@   TySet ->   Mod ->   TySet ->-  SrcLoc ->+  Loc ->   Either TypeError (M.Map VName (QualName VName, TypeBinding)) resolveAbsTypes mod_abs mod sig_abs loc = do   let abs_mapping =@@ -282,7 +282,7 @@         missingType loc $ fmap baseName name   where     mismatchedLiftedness name_l abs name mod_t =-      Left . TypeError loc mempty $+      Left . TypeError (locOf loc) mempty $         "Module defines"           </> indent 2 (ppTypeAbbr abs name mod_t)           </> "but module type requires" <+> text what <> "."@@ -293,11 +293,10 @@           Lifted -> "a lifted type"      anonymousSizes abs name mod_t =-      Left $-        TypeError loc mempty $-          "Module defines"-            </> indent 2 (ppTypeAbbr abs name mod_t)-            </> "which contains anonymous sizes, but module type requires non-lifted type."+      Left . TypeError (locOf loc) mempty $+        "Module defines"+          </> indent 2 (ppTypeAbbr abs name mod_t)+          </> "which contains anonymous sizes, but module type requires non-lifted type."  resolveMTyNames ::   MTy ->@@ -338,38 +337,34 @@         resolve' name _ =           M.lookup (namespace, baseName name) $ envNameMap mod_env -missingType :: Pretty a => SrcLoc -> a -> Either TypeError b+missingType :: Pretty a => Loc -> a -> Either TypeError b missingType loc name =-  Left $-    TypeError loc mempty $-      "Module does not define a type named" <+> ppr name <> "."+  Left . TypeError loc mempty $+    "Module does not define a type named" <+> ppr name <> "." -missingVal :: Pretty a => SrcLoc -> a -> Either TypeError b+missingVal :: Pretty a => Loc -> a -> Either TypeError b missingVal loc name =-  Left $-    TypeError loc mempty $-      "Module does not define a value named" <+> ppr name <> "."+  Left . TypeError loc mempty $+    "Module does not define a value named" <+> ppr name <> "." -missingMod :: Pretty a => SrcLoc -> a -> Either TypeError b+missingMod :: Pretty a => Loc -> a -> Either TypeError b missingMod loc name =-  Left $-    TypeError loc mempty $-      "Module does not define a module named" <+> ppr name <> "."+  Left . TypeError loc mempty $+    "Module does not define a module named" <+> ppr name <> "."  mismatchedType ::-  SrcLoc ->+  Loc ->   [VName] ->   VName ->   (Liftedness, [TypeParam], StructRetType) ->   (Liftedness, [TypeParam], StructRetType) ->   Either TypeError b mismatchedType loc abs name spec_t env_t =-  Left $-    TypeError loc mempty $-      "Module defines"-        </> indent 2 (ppTypeAbbr abs name env_t)-        </> "but module type requires"-        </> indent 2 (ppTypeAbbr abs name spec_t)+  Left . TypeError loc mempty $+    "Module defines"+      </> indent 2 (ppTypeAbbr abs name env_t)+      </> "but module type requires"+      </> indent 2 (ppTypeAbbr abs name spec_t)  ppTypeAbbr :: [VName] -> VName -> (Liftedness, [TypeParam], StructRetType) -> Doc ppTypeAbbr abs name (l, ps, RetType [] (Scalar (TypeVar () _ tn args)))@@ -390,7 +385,7 @@ matchMTys ::   MTy ->   MTy ->-  SrcLoc ->+  Loc ->   Either TypeError (M.Map VName VName) matchMTys orig_mty orig_mty_sig =   matchMTys'@@ -402,7 +397,7 @@       M.Map VName (Subst StructRetType) ->       MTy ->       MTy ->-      SrcLoc ->+      Loc ->       Either TypeError (M.Map VName VName)      matchMTys' _ (MTy _ ModFun {}) (MTy _ ModEnv {}) loc =@@ -433,7 +428,7 @@       M.Map VName (Subst StructRetType) ->       Mod ->       Mod ->-      SrcLoc ->+      Loc ->       Either TypeError (M.Map VName VName)     matchMods _ ModEnv {} ModFun {} loc =       Left $@@ -466,7 +461,7 @@       M.Map VName (Subst StructRetType) ->       Env ->       Env ->-      SrcLoc ->+      Loc ->       Either TypeError (M.Map VName VName)     matchEnvs abs_subst_to_type env sig loc = do       -- XXX: we only want to create substitutions for visible names.@@ -505,7 +500,7 @@       return $ val_substs <> mod_substs <> abbr_name_substs      matchTypeAbbr ::-      SrcLoc ->+      Loc ->       M.Map VName (Subst StructRetType) ->       VName ->       Liftedness ->@@ -559,7 +554,7 @@       nomatch      matchVal ::-      SrcLoc ->+      Loc ->       VName ->       BoundV ->       VName ->@@ -577,7 +572,7 @@                 </> indent 2 (ppValBind spec_name v)                 </> fromMaybe mempty problem -    matchValBinding :: SrcLoc -> BoundV -> BoundV -> Maybe (Maybe Doc)+    matchValBinding :: Loc -> BoundV -> BoundV -> Maybe (Maybe Doc)     matchValBinding loc (BoundV _ orig_spec_t) (BoundV tps orig_t) =       case doUnification loc tps (toStruct orig_spec_t) (toStruct orig_t) of         Left (TypeError _ notes msg) ->@@ -596,7 +591,7 @@  -- | Apply a parametric module to an argument. applyFunctor ::-  SrcLoc ->+  Loc ->   FunSig ->   MTy ->   TypeM
src/Language/Futhark/TypeChecker/Monad.hs view
@@ -91,11 +91,11 @@ aNote = Notes . pure . Note . ppr  -- | Information about an error during type checking.-data TypeError = TypeError SrcLoc Notes Doc+data TypeError = TypeError Loc Notes Doc  instance Pretty TypeError where   ppr (TypeError loc notes msg) =-    text (inRed $ "Error at " <> locStr loc <> ":")+    text (inRed $ "Error at " <> locStr (srclocOf loc) <> ":")       </> msg <> ppr notes  errorIndexUrl :: Doc@@ -370,7 +370,7 @@                     qualifyTypeVars outer_env mempty qs t'                 ) -  typeError loc notes s = throwError $ TypeError (srclocOf loc) notes s+  typeError loc notes s = throwError $ TypeError (locOf loc) notes s  -- | Extract from a type a first-order type. getType :: TypeBase dim as -> Maybe (TypeBase dim as)
src/Language/Futhark/TypeChecker/Terms.hs view
@@ -1098,11 +1098,11 @@         | (d, dloc) : _ <-             mapMaybe (unknown constraints known) $               S.toList $ typeDimNames $ toStruct t =-          Just $ lift $ causality what loc d dloc t+          Just $ lift $ causality what (locOf loc) d dloc t         | otherwise = Nothing        checkParamCausality known p =-        checkCausality (ppr p) known (patternType p) (srclocOf p)+        checkCausality (ppr p) known (patternType p) (locOf p)        onExp ::         S.Set VName ->
src/Language/Futhark/TypeChecker/Terms/Monad.hs view
@@ -500,10 +500,10 @@     case checking of       Just checking' ->         throwError $-          TypeError (srclocOf loc) notes $+          TypeError (locOf loc) notes $             ppr checking' <> line </> doc <> ppr bcs       Nothing ->-        throwError $ TypeError (srclocOf loc) notes $ doc <> ppr bcs+        throwError $ TypeError (locOf loc) notes $ doc <> ppr bcs    matchError loc notes bcs t1 t2 = do     checking <- asks termChecking@@ -511,14 +511,14 @@       Just checking'         | hasNoBreadCrumbs bcs ->           throwError $-            TypeError (srclocOf loc) notes $+            TypeError (locOf loc) notes $               ppr checking'         | otherwise ->           throwError $-            TypeError (srclocOf loc) notes $+            TypeError (locOf loc) notes $               ppr checking' <> line </> doc <> ppr bcs       Nothing ->-        throwError $ TypeError (srclocOf loc) notes $ doc <> ppr bcs+        throwError $ TypeError (locOf loc) notes $ doc <> ppr bcs     where       doc =         "Types"@@ -686,9 +686,9 @@     checking <- asks termChecking     case checking of       Just checking' ->-        throwError $ TypeError (srclocOf loc) notes (ppr checking' <> line </> s)+        throwError $ TypeError (locOf loc) notes (ppr checking' <> line </> s)       Nothing ->-        throwError $ TypeError (srclocOf loc) notes s+        throwError $ TypeError (locOf loc) notes s  onFailure :: Checking -> TermTypeM a -> TermTypeM a onFailure c = local $ \env -> env {termChecking = Just c}
src/Language/Futhark/TypeChecker/Terms/Pat.hs view
@@ -2,10 +2,10 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TupleSections #-} +-- | Type checking of patterns. module Language.Futhark.TypeChecker.Terms.Pat   ( binding,     bindingParams,-    checkPat,     bindingPat,     bindingIdent,     bindingSizes,@@ -66,6 +66,9 @@   | otherwise =     return () +-- | Bind these identifiers locally while running the provided action.+-- Checks that the identifiers are used properly within the scope+-- (e.g. consumption). binding :: [Ident] -> TermTypeM a -> TermTypeM a binding stms = check . handleVars   where@@ -170,6 +173,7 @@   Just $ Ident v (Info $ Scalar $ Prim $ Signed Int64) loc typeParamIdent _ = Nothing +-- | Bind a single term-level identifier. bindingIdent ::   IdentBase NoInfo Name ->   PatType ->@@ -181,6 +185,8 @@     let ident = Ident v' (Info t) vloc     binding [ident] $ m ident +-- | Bind @let@-bound sizes.  This is usually followed by 'bindingPat'+-- immediately afterwards. bindingSizes :: [SizeBinder Name] -> ([SizeBinder VName] -> TermTypeM a) -> TermTypeM a bindingSizes [] m = m [] -- Minor optimisation. bindingSizes sizes m = do@@ -217,6 +223,7 @@     dimIdent _ NamedDim {} = Nothing patternDims _ = [] +-- | Check and bind a @let@-pattern. bindingPat ::   [SizeBinder VName] ->   PatBase NoInfo Name ->@@ -394,6 +401,7 @@     [] ->       bindNameMap (patNameMap p') $ m p' +-- | Check and bind type and value parameters. bindingParams ::   [UncheckedTypeParam] ->   [UncheckedPat] ->
src/Language/Futhark/TypeChecker/Unify.hs view
@@ -1152,10 +1152,10 @@   curLevel = pure 0    unifyError loc notes bcs doc =-    throwError $ TypeError (srclocOf loc) notes $ doc <> ppr bcs+    throwError $ TypeError (locOf loc) notes $ doc <> ppr bcs    matchError loc notes bcs t1 t2 =-    throwError $ TypeError (srclocOf loc) notes $ doc <> ppr bcs+    throwError $ TypeError (locOf loc) notes $ doc <> ppr bcs     where       doc =         "Types"@@ -1175,13 +1175,13 @@ -- The type parameters are allowed to be instantiated; all other types -- are considered rigid. doUnification ::-  SrcLoc ->+  Loc ->   [TypeParam] ->   StructType ->   StructType ->   Either TypeError StructType doUnification loc tparams t1 t2 = runUnifyM tparams $ do-  expect (Usage Nothing loc) t1 t2+  expect (Usage Nothing (srclocOf loc)) t1 t2   normTypeFully t2  -- Note [Linking variables to sum types]
src/Language/Futhark/Warnings.hs view
@@ -6,6 +6,7 @@     anyWarnings,     singleWarning,     singleWarning',+    listWarnings,   ) where @@ -59,3 +60,7 @@ -- trace (sort of) to the location. singleWarning' :: SrcLoc -> [SrcLoc] -> Doc -> Warnings singleWarning' loc locs problem = Warnings [(loc, locs, problem)]++-- | Exports Warnings into a list of (location, problem).+listWarnings :: Warnings -> [(SrcLoc, Doc)]+listWarnings (Warnings ws) = map (\(loc, _, doc) -> (loc, doc)) ws
unittests/Language/Futhark/SyntaxTests.hs view
@@ -14,7 +14,6 @@ import Data.Void import Futhark.IR.Primitive.Parse (constituent, keyword, lexeme) import Futhark.IR.PrimitiveTests ()-import Futhark.Util.Pretty (prettyText) import Language.Futhark import Language.Futhark.Parser import Test.QuickCheck@@ -62,7 +61,7 @@  instance IsString UncheckedTypeExp where   fromString =-    either (error . show) id . parseType "IsString UncheckedTypeExp" . fromString+    either (error . syntaxErrorMsg) id . parseType "IsString UncheckedTypeExp" . fromString  type Parser = Parsec Void T.Text