packages feed

futhark 0.25.17 → 0.25.18

raw patch · 47 files changed

+266/−144 lines, 47 filesdep ~futhark-manifestPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: futhark-manifest

API changes (from Hackage documentation)

- Futhark.Test: runProgram :: FutharkExe -> FilePath -> [String] -> String -> Text -> Values -> IO (ExitCode, ByteString, ByteString)
- Language.Futhark.Parser.Lexer.Tokens: advance :: Pos -> ByteString -> Pos
+ Futhark.IR.Syntax: ArrayVal :: [PrimValue] -> PrimType -> BasicOp
+ Language.Futhark.Parser.Monad: arrayLitExp :: [UncheckedExp] -> SrcLoc -> UncheckedExp
+ Language.Futhark.Semantic: [boundValTParams] :: BoundV -> [TypeParam]
+ Language.Futhark.Semantic: [boundValType] :: BoundV -> StructType
+ Language.Futhark.Syntax: ArrayVal :: [PrimValue] -> PrimType -> SrcLoc -> ExpBase f vn
+ Language.Futhark.TypeChecker.Monad: [boundValTParams] :: BoundV -> [TypeParam]
+ Language.Futhark.TypeChecker.Monad: [boundValType] :: BoundV -> StructType
- Futhark.Test: compileProgram :: (MonadIO m, MonadError [Text] m) => [String] -> FutharkExe -> String -> FilePath -> m (ByteString, ByteString)
+ Futhark.Test: compileProgram :: (MonadIO m, MonadError Text m) => [String] -> FutharkExe -> String -> FilePath -> m (ByteString, ByteString)
- Futhark.Test: ensureReferenceOutput :: (MonadIO m, MonadError [Text] m) => Maybe Int -> FutharkExe -> String -> FilePath -> [InputOutputs] -> m ()
+ Futhark.Test: ensureReferenceOutput :: (MonadIO m, MonadError Text m) => Maybe Int -> FutharkExe -> String -> FilePath -> [InputOutputs] -> m ()

Files

CHANGELOG.md view
@@ -5,6 +5,24 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.25.18]++### Added++* New prelude function: `rep`, an implicit form of `replicate`.++* Improved handling of large monomorphic single-dimensional array+  literals (#2160).++### Fixed++* `futhark repl` no longer asks for confirmation on EOF.++* Obscure oversight related to abstract size-lifted types (#2120).++* Accidential exponential-time algorithm in layout optimisation for+  multicore backends (#2151).+ ## [0.25.17]  * Faster device-to-device copies on CUDA.
docs/c-api.rst view
@@ -400,11 +400,13 @@ .. c:function:: int futhark_new_opaque_t(struct futhark_context *ctx, struct futhark_opaque_t **out, const struct futhark_opaque_t2 *bar, const struct futhark_opaque_t1 *foo);     Construct a record in ``*out`` which has the given values for the-   ``bar`` and ``foo`` fields.  The parameters are the-   fields in alphabetic order.  Tuple fields are named ``vX`` where-   ``X`` is an integer.  The resulting record *aliases* the values-   provided for ``bar`` and ``foo``, but has its own lifetime, and all-   values must be individually freed when they are no longer needed.+   ``bar`` and ``foo`` fields. The parameters are the fields in+   alphabetic order. As a special case, if the record is a tuple+   (i.e., has numeric fields), the parameters are ordered numerically.+   Tuple fields are named ``vX`` where ``X`` is an integer. The+   resulting record *aliases* the values provided for ``bar`` and+   ``foo``, but has its own lifetime, and all values must be+   individually freed when they are no longer needed.  .. c:function:: int futhark_project_opaque_t_bar(struct futhark_context *ctx, struct futhark_opaque_t2 **out, const struct futhark_opaque_t *obj); 
docs/language-reference.rst view
@@ -743,6 +743,14 @@ Create an array containing the indicated elements.  Each element must have the same type and shape. +**Large array optimisation**: as a special case, large one-dimensional+array literal consisting *entirely* of monomorphic constants (i.e.,+numbers must have a type suffix) are handled with specialised+fast-path code by the compiler. To keep compile times manageable, make+sure that all very large array literals (more than about ten thousand+elements) are of this form. This is likely relevant only for generated+code.+ .. _range:  ``x..y...z``@@ -1580,6 +1588,10 @@ then returns a module that exposes only the functionality described by the module type.  This is how internal details of a module can be hidden.++As a slightly ad-hoc limitation, ascription is forbidden when a type+substitution of size-lifted types occurs in a size appearing at the+top level.  ``\(p: mt1): mt2 -> e`` .......................
futhark.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name:           futhark-version:        0.25.17+version:        0.25.18 synopsis:       An optimising compiler for a functional, array-oriented language.  description:    Futhark is a small programming language designed to be compiled to
prelude/array.fut view
@@ -128,6 +128,16 @@ def replicate 't (n: i64) (x: t): *[n]t =   map (const x) (iota n) +-- | Construct an array of an inferred length containing the given+-- value.+--+-- **Work:** O(n).+--+-- **Span:** O(1).+#[inline]+def rep 't [n] (x: t): *[n]t =+  replicate n x+ -- | Copy a value.  The result will not alias anything. -- -- **Work:** O(n).
rts/c/copy.h view
@@ -122,6 +122,10 @@    *num_arrays_out = num_arrays; +  if (r==map_r) {+    return false;+  }+   if (memcmp(&rowmajor_strides[map_r],              &dst_strides[map_r],              sizeof(int64_t)*(r-map_r)) == 0) {@@ -193,11 +197,11 @@     fprintf(ctx->log, "Shape: ");     for (int i = 0; i < r; i++) { fprintf(ctx->log, "[%ld]", (long int)shape[i]); }     fprintf(ctx->log, "\n");-    fprintf(ctx->log, "Dst offset: %ld\n", dst_offset);+    fprintf(ctx->log, "Dst offset: %ld\n", (long int)dst_offset);     fprintf(ctx->log, "Dst strides:");     for (int i = 0; i < r; i++) { fprintf(ctx->log, " %ld", (long int)dst_strides[i]); }     fprintf(ctx->log, "\n");-    fprintf(ctx->log, "Src offset: %ld\n", src_offset);+    fprintf(ctx->log, "Src offset: %ld\n", (long int)src_offset);     fprintf(ctx->log, "Src strides:");     for (int i = 0; i < r; i++) { fprintf(ctx->log, " %ld", (long int)src_strides[i]); }     fprintf(ctx->log, "\n");
rts/c/server.h view
@@ -703,7 +703,7 @@    if (num_args != r->num_fields) {     failure();-    printf("%d fields expected byt %d values provided.\n", num_args, r->num_fields);+    printf("%d fields expected but %d values provided.\n", num_args, r->num_fields);     return;   } 
src/Futhark/AD/Rev.hs view
@@ -107,6 +107,9 @@     Assert {} ->       void $ commonBasicOp pat aux e m     --+    ArrayVal {} ->+      void $ commonBasicOp pat aux e m+    --     ArrayLit elems _ -> do       (_pat_v, pat_adj) <- commonBasicOp pat aux e m       t <- lookupType pat_adj
src/Futhark/Analysis/AccessPattern.hs view
@@ -465,6 +465,7 @@   let ctx_val = case expression of         SubExp se -> varInfoFromSubExp se         Opaque _ se -> varInfoFromSubExp se+        ArrayVal _ _ -> (varInfoFromNames ctx mempty) {variableType = ConstType}         ArrayLit ses _t -> concatVariableInfos mempty ses         UnOp _ se -> varInfoFromSubExp se         BinOp _ lsubexp rsubexp -> concatVariableInfos mempty [lsubexp, rsubexp]@@ -497,14 +498,7 @@     varInfoFromSubExp (Var v) =       case M.lookup v (assignments ctx) of         Just _ -> (varInfoFromNames ctx $ oneName v) {variableType = Variable}-        Nothing ->-          error $-            "Failed to lookup variable \""-              ++ prettyString v-              ++ "\npat: "-              ++ prettyString pats-              ++ "\n\nContext\n"-              ++ show ctx+        Nothing -> (varInfoFromNames ctx mempty) {variableType = Variable} -- Means a global.  analyseMatch :: (Analyse rep) => Context rep -> [VName] -> Body rep -> [Body rep] -> (Context rep, IndexTable rep) analyseMatch ctx pats body parents =@@ -628,8 +622,8 @@     | ParOp Nothing seq_segop <- mc_op = analyseSegOp seq_segop     | ParOp (Just segop) seq_segop <- mc_op = \ctx name -> do         let (ctx', res') = analyseSegOp segop ctx name-        let (ctx'', res'') = analyseSegOp seq_segop ctx name-        (ctx' <> ctx'', unionIndexTables res' res'')+        let (ctx'', res'') = analyseSegOp seq_segop ctx' name+        (ctx'', unionIndexTables res' res'')     | Futhark.IR.MC.OtherOp _ <- mc_op = analyseOtherOp  -- Unfortunately we need these instances, even though they may never appear.
src/Futhark/Analysis/Metrics.hs view
@@ -123,6 +123,7 @@ basicOpMetrics :: BasicOp -> MetricsM () basicOpMetrics (SubExp _) = seen "SubExp" basicOpMetrics (Opaque _ _) = seen "Opaque"+basicOpMetrics ArrayVal {} = seen "ArrayVal" basicOpMetrics ArrayLit {} = seen "ArrayLit" basicOpMetrics BinOp {} = seen "BinOp" basicOpMetrics UnOp {} = seen "UnOp"
src/Futhark/Bench.hs view
@@ -416,9 +416,9 @@       pure $         Left           ( "Reference output generation for "-              ++ program-              ++ " failed:\n"-              ++ unlines (map T.unpack err),+              <> program+              <> " failed:\n"+              <> T.unpack err,             Nothing           )     Right () -> do
src/Futhark/CLI/Literate.hs view
@@ -1161,7 +1161,7 @@           unwords compile_options      let onError err = do-          mapM_ (T.hPutStrLn stderr) err+          T.hPutStrLn stderr err           exitFailure      void $
src/Futhark/CLI/Misc.hs view
@@ -128,7 +128,7 @@         Just (Right (Left e)) -> do           hPrint stderr e           exitWith $ ExitFailure 2-        Just (Right (Right (tokens, _))) ->+        Just (Right (Right tokens)) ->           mapM_ printToken tokens     _ -> Nothing   where
src/Futhark/CLI/REPL.hs view
@@ -89,9 +89,7 @@                 toploop s'           Right _ -> pure () -      finish s = do-        quit <- if fancyTerminal then confirmQuit else pure True-        if quit then pure () else toploop s+      finish _s = pure ()    maybe_init_state <- liftIO $ newFutharkiState 0 noLoadedProg maybe_prog   s <- case maybe_init_state of@@ -108,15 +106,6 @@   Haskeline.runInputT Haskeline.defaultSettings $ toploop s    putStrLn "Leaving 'futhark repl'."--confirmQuit :: Haskeline.InputT IO Bool-confirmQuit = do-  c <- Haskeline.getInputChar "Quit REPL? (y/n) "-  case c of-    Nothing -> pure True -- EOF-    Just 'y' -> pure True-    Just 'n' -> pure False-    _ -> confirmQuit  -- | Representation of breaking at a breakpoint, to allow for -- navigating through the stack frames and such.
src/Futhark/CLI/Test.hs view
@@ -37,6 +37,10 @@  --- Test execution +-- The use of [T.Text] here is somewhat kludgy. We use it to track how+-- many errors have occurred during testing of a single program (which+-- may have multiple entry points). This should really not be done at+-- the monadic level - a test failing should be handled explicitly. type TestM = ExceptT [T.Text] IO  -- Taken from transformers-0.5.5.0.@@ -286,7 +290,8 @@         context "Generating reference outputs" $           -- We probably get the concurrency at the test program level,           -- so force just one data set at a time here.-          ensureReferenceOutput (Just 1) (FutharkExe futhark) "c" program ios+          withExceptT pure $+            ensureReferenceOutput (Just 1) (FutharkExe futhark) "c" program ios        when (mode == Structure) $         mapM_ (testMetrics progs program) structures@@ -393,7 +398,9 @@  compileTestProgram :: [String] -> FutharkExe -> String -> FilePath -> [WarningTest] -> TestM () compileTestProgram extra_options futhark backend program warnings = do-  (_, futerr) <- compileProgram ("--server" : extra_options) futhark backend program+  (_, futerr) <-+    withExceptT pure $+      compileProgram ("--server" : extra_options) futhark backend program   testWarnings warnings futerr  compareResult ::
src/Futhark/CodeGen/Backends/GenericC/Code.hs view
@@ -22,6 +22,7 @@ import Data.Maybe import Data.Text qualified as T import Futhark.CodeGen.Backends.GenericC.Monad+import Futhark.CodeGen.Backends.GenericC.Pretty (expText, idText, typeText) import Futhark.CodeGen.ImpCode import Futhark.IR.Prop (isBuiltInFunction) import Futhark.MonadFreshNames@@ -58,12 +59,6 @@ compilePrimExp f (UnOpExp Not {} x) = do   x' <- compilePrimExp f x   pure [C.cexp|!$exp:x'|]-compilePrimExp f (UnOpExp (FAbs Float32) x) = do-  x' <- compilePrimExp f x-  pure [C.cexp|(float)fabs($exp:x')|]-compilePrimExp f (UnOpExp (FAbs Float64) x) = do-  x' <- compilePrimExp f x-  pure [C.cexp|fabs($exp:x')|] compilePrimExp f (UnOpExp SSignum {} x) = do   x' <- compilePrimExp f x   pure [C.cexp|($exp:x' > 0 ? 1 : 0) - ($exp:x' < 0 ? 1 : 0)|]@@ -366,8 +361,19 @@   let ct = primTypeToCType t   case vs of     ArrayValues vs' -> do-      let vs'' = [[C.cinit|$exp:v|] | v <- vs']-      earlyDecl [C.cedecl|static $ty:ct $id:name_realtype[$int:(length vs')] = {$inits:vs''};|]+      -- To handle very large literal arrays (which are inefficient+      -- with language-c-quote, see #2160), we do our own formatting and inject it as a string.+      let array_decl =+            "static "+              <> typeText ct+              <> " "+              <> idText (C.toIdent name_realtype mempty)+              <> "["+              <> prettyText (length vs')+              <> "] = { "+              <> T.intercalate "," (map (expText . flip C.toExp mempty) vs')+              <> "};"+      earlyDecl [C.cedecl|$esc:(T.unpack array_decl)|]     ArrayZeros n ->       earlyDecl [C.cedecl|static $ty:ct $id:name_realtype[$int:n];|]   -- Fake a memory block.
src/Futhark/CodeGen/ImpGen.hs view
@@ -444,7 +444,7 @@      in ( ( stateWarnings s',             Imp.Definitions               types-              (stateConstants s' <> foldMap stateConstants ss)+              (foldMap stateConstants ss <> stateConstants s')               (stateFunctions s')           ),           stateNameSource s'@@ -954,17 +954,19 @@         destslice = skip_slices ++ [DimSlice (tvExp offs_glb) rows 1]     copyDWIM (patElemName pe) destslice (Var y) []     offs_glb <-- tvExp offs_glb + rows+defCompileBasicOp (Pat [pe]) (ArrayVal vs t) = do+  dest_mem <- entryArrayLoc <$> lookupArray (patElemName pe)+  static_array <- newVNameForFun "static_array"+  emit $ Imp.DeclareArray static_array t $ Imp.ArrayValues vs+  let static_src =+        MemLoc static_array [intConst Int64 $ fromIntegral $ length vs] $+          LMAD.iota 0 [fromIntegral $ length vs]+  addVar static_array $ MemVar Nothing $ MemEntry DefaultSpace+  copy t dest_mem static_src defCompileBasicOp (Pat [pe]) (ArrayLit es _)   | Just vs@(v : _) <- mapM isLiteral es = do-      dest_mem <- entryArrayLoc <$> lookupArray (patElemName pe)       let t = primValueType v-      static_array <- newVNameForFun "static_array"-      emit $ Imp.DeclareArray static_array t $ Imp.ArrayValues vs-      let static_src =-            MemLoc static_array [intConst Int64 $ fromIntegral $ length es] $-              LMAD.iota 0 [fromIntegral $ length es]-      addVar static_array $ MemVar Nothing $ MemEntry DefaultSpace-      copy t dest_mem static_src+      defCompileBasicOp (Pat [pe]) (ArrayVal vs t)   | otherwise =       forM_ (zip [0 ..] es) $ \(i, e) ->         copyDWIMFix (patElemName pe) [fromInteger i] e []
src/Futhark/IR/Parse.hs view
@@ -314,6 +314,10 @@           <*> pFlatSlice           <* lexeme "="           <*> pVName,+      try $+        ArrayVal+          <$> brackets (pPrimValue `sepBy` pComma)+          <*> (lexeme ":" *> "[]" *> pPrimType),       ArrayLit         <$> brackets (pSubExp `sepBy` pComma)         <*> (lexeme ":" *> "[]" *> pType),
src/Futhark/IR/Pretty.hs view
@@ -198,6 +198,11 @@       <+> colon       <+> "[]"       <> pretty rt+  pretty (ArrayVal vs t) =+    brackets (commasep $ map pretty vs)+      <+> colon+      <+> "[]"+      <> pretty t   pretty (BinOp bop x y) = pretty bop <> parens (pretty x <> comma <+> pretty y)   pretty (CmpOp op x y) = pretty op <> parens (pretty x <> comma <+> pretty y)   pretty (ConvOp conv x) =
src/Futhark/IR/Prop/Aliases.hs view
@@ -57,6 +57,7 @@ basicOpAliases :: BasicOp -> [Names] basicOpAliases (SubExp se) = [subExpAliases se] basicOpAliases (Opaque _ se) = [subExpAliases se]+basicOpAliases (ArrayVal _ _) = [mempty] basicOpAliases (ArrayLit _ _) = [mempty] basicOpAliases BinOp {} = [mempty] basicOpAliases ConvOp {} = [mempty]
src/Futhark/IR/Prop/TypeOf.hs view
@@ -63,6 +63,10 @@   pure <$> subExpType se basicOpType (Opaque _ se) =   pure <$> subExpType se+basicOpType (ArrayVal vs t) =+  pure [arrayOf (Prim t) (Shape [n]) NoUniqueness]+  where+    n = intConst Int64 $ toInteger $ length vs basicOpType (ArrayLit es rt) =   pure [arrayOf rt (Shape [n]) NoUniqueness]   where
src/Futhark/IR/Syntax.hs view
@@ -328,6 +328,13 @@   | -- | Array literals, e.g., @[ [1+x, 3], [2, 1+4] ]@.     -- Second arg is the element type of the rows of the array.     ArrayLit [SubExp] Type+  | -- | A one-dimensional array literal that contains only constants.+    -- This is a fast-path for representing very large array literals+    -- that show up in some programs. The key rule for processing this+    -- in compiler passes is that you should never need to look at the+    -- individual elements. Has exactly the same semantics as an+    -- 'ArrayLit'.+    ArrayVal [PrimValue] PrimType   | -- | Unary operation.     UnOp UnOp SubExp   | -- | Binary operation.
src/Futhark/IR/Traversals.hs view
@@ -89,6 +89,8 @@   m (Exp trep) mapExpM tv (BasicOp (SubExp se)) =   BasicOp <$> (SubExp <$> mapOnSubExp tv se)+mapExpM _ (BasicOp (ArrayVal vs t)) =+  pure $ BasicOp $ ArrayVal vs t mapExpM tv (BasicOp (ArrayLit els rowt)) =   BasicOp     <$> ( ArrayLit@@ -279,6 +281,8 @@ walkExpM :: (Monad m) => Walker rep m -> Exp rep -> m () walkExpM tv (BasicOp (SubExp se)) =   walkOnSubExp tv se+walkExpM _ (BasicOp ArrayVal {}) =+  pure () walkExpM tv (BasicOp (ArrayLit els rowt)) =   mapM_ (walkOnSubExp tv) els >> walkOnType tv rowt walkExpM tv (BasicOp (BinOp _ x y)) =
src/Futhark/IR/TypeCheck.hs view
@@ -837,6 +837,9 @@   void $ checkSubExp es checkBasicOp (Opaque _ es) =   void $ checkSubExp es+checkBasicOp ArrayVal {} =+  -- We assume this is never changed, so no need to check it.+  pure () checkBasicOp (ArrayLit [] _) =   pure () checkBasicOp (ArrayLit (e : es') t) = do
src/Futhark/Internalise/Defunctionalise.hs view
@@ -507,6 +507,8 @@         _ ->           let tp = Info $ structTypeFromSV sv            in pure (RecordFieldImplicit vn tp loc', (baseName vn, sv))+defuncExp e@(ArrayVal vs t loc) =+  pure (ArrayVal vs t loc, Dynamic $ toParam Observe $ typeOf e) defuncExp (ArrayLit es t@(Info t') loc) = do   es' <- mapM defuncExp' es   pure (ArrayLit es' t loc, Dynamic $ toParam Observe t')
src/Futhark/Internalise/Exps.hs view
@@ -628,6 +628,9 @@           (baseName name)           (E.Var (E.qualName name) t loc)           loc+internaliseExp desc (E.ArrayVal vs t _) =+  fmap pure . letSubExp desc . I.BasicOp $+    I.ArrayVal (map internalisePrimValue vs) (internalisePrimType t) internaliseExp desc (E.ArrayLit es (Info arr_t) loc)   -- If this is a multidimensional array literal of primitives, we   -- treat it specially by flattening it out followed by a reshape.
src/Futhark/Internalise/FullNormalise.hs view
@@ -172,9 +172,18 @@       pure $ RecordFieldExplicit n e' floc     f (RecordFieldImplicit v t _) =       f $ RecordFieldExplicit (baseName v) (Var (qualName v) t loc) loc-getOrdering _ (ArrayLit es ty loc) = do-  es' <- mapM (getOrdering False) es-  pure $ ArrayLit es' ty loc+getOrdering _ (ArrayVal vs t loc) =+  pure $ ArrayVal vs t loc+getOrdering _ (ArrayLit es ty loc)+  | Just vs <- mapM isLiteral es,+    Info (Array _ (Shape [_]) (Prim t)) <- ty =+      pure $ ArrayVal vs t loc+  | otherwise = do+      es' <- mapM (getOrdering False) es+      pure $ ArrayLit es' ty loc+  where+    isLiteral (Literal v _) = Just v+    isLiteral _ = Nothing getOrdering _ (Project n e ty loc) = do   e' <- getOrdering False e   pure $ Project n e' ty loc
src/Futhark/Internalise/Monomorphise.hs view
@@ -638,6 +638,8 @@           (baseName v)           (Var (qualName v) t' loc)           loc+transformExp (ArrayVal vs t loc) =+  pure $ ArrayVal vs t loc transformExp (ArrayLit es t loc) =   ArrayLit <$> mapM transformExp es <*> traverse transformType t <*> pure loc transformExp (AppExp e res) =
src/Futhark/Optimise/ArrayShortCircuiting/DataStructs.hs view
@@ -336,6 +336,7 @@ createsNewArrOK (BasicOp Manifest {}) = True createsNewArrOK (BasicOp Concat {}) = True createsNewArrOK (BasicOp ArrayLit {}) = True+createsNewArrOK (BasicOp ArrayVal {}) = True createsNewArrOK (BasicOp Scratch {}) = True createsNewArrOK _ = False 
src/Futhark/Optimise/ArrayShortCircuiting/MemRefAggreg.hs view
@@ -93,6 +93,9 @@     isFix _ = False getUseSumFromStm _ _ (Let Pat {} _ (BasicOp Index {})) = Just ([], []) -- incomplete slices getUseSumFromStm _ _ (Let Pat {} _ (BasicOp FlatIndex {})) = Just ([], []) -- incomplete slices+getUseSumFromStm td_env coal_tab (Let (Pat pes) _ (BasicOp ArrayVal {})) =+  let wrts = mapMaybe (getDirAliasedIxfn td_env coal_tab . patElemName) pes+   in Just (wrts, wrts) getUseSumFromStm td_env coal_tab (Let (Pat pes) _ (BasicOp (ArrayLit ses _))) =   let rds = mapMaybe (getDirAliasedIxfn td_env coal_tab) $ mapMaybe seName ses       wrts = mapMaybe (getDirAliasedIxfn td_env coal_tab . patElemName) pes
src/Futhark/Optimise/ReduceDeviceSyncs/MigrationTable.hs view
@@ -482,6 +482,9 @@       -- Whether the rows are primitive constants or arrays, without any scalar       -- variable operands such ArrayLit cannot directly prevent a scalar read.       graphHostOnly e+    BasicOp ArrayVal {} ->+      -- As above.+      graphHostOnly e     BasicOp Update {} ->       graphHostOnly e     BasicOp Concat {} ->
src/Futhark/Test.hs view
@@ -13,7 +13,6 @@     testRunReferenceOutput,     getExpectedResult,     compileProgram,-    runProgram,     readResults,     ensureReferenceOutput,     determineTuning,@@ -31,7 +30,7 @@ import Control.Exception (catch) import Control.Exception.Base qualified as E import Control.Monad-import Control.Monad.Except (MonadError (..))+import Control.Monad.Except (MonadError (..), runExceptT) import Control.Monad.IO.Class (MonadIO, liftIO) import Data.Binary qualified as Bin import Data.ByteString qualified as SBS@@ -344,7 +343,7 @@ -- returns stdout and stderr of the compiler.  Throws an IO exception -- containing stderr if compilation fails. compileProgram ::-  (MonadIO m, MonadError [T.Text] m) =>+  (MonadIO m, MonadError T.Text m) =>   [String] ->   FutharkExe ->   String ->@@ -353,8 +352,8 @@ compileProgram extra_options (FutharkExe futhark) backend program = do   (futcode, stdout, stderr) <- liftIO $ readProcessWithExitCode futhark (backend : options) ""   case futcode of-    ExitFailure 127 -> throwError [progNotFound $ T.pack futhark]-    ExitFailure _ -> throwError [T.decodeUtf8 stderr]+    ExitFailure 127 -> throwError $ progNotFound $ T.pack futhark+    ExitFailure _ -> throwError $ T.decodeUtf8 stderr     ExitSuccess -> pure ()   pure (stdout, stderr)   where@@ -362,35 +361,6 @@     options = [program, "-o", binOutputf] ++ extra_options     progNotFound s = s <> ": command not found" --- | @runProgram futhark runner extra_options prog entry input@ runs the--- Futhark program @prog@ (which must have the @.fut@ suffix),--- executing the @entry@ entry point and providing @input@ on stdin.--- The program must have been compiled in advance with--- 'compileProgram'.  If @runner@ is non-null, then it is used as--- "interpreter" for the compiled program (e.g. @python@ when using--- the Python backends).  The @extra_options@ are passed to the--- program.-runProgram ::-  FutharkExe ->-  FilePath ->-  [String] ->-  String ->-  T.Text ->-  Values ->-  IO (ExitCode, SBS.ByteString, SBS.ByteString)-runProgram futhark runner extra_options prog entry input = do-  let progbin = binaryName prog-      dir = takeDirectory prog-      binpath = "." </> progbin-      entry_options = ["-e", T.unpack entry]--      (to_run, to_run_args)-        | null runner = (binpath, entry_options ++ extra_options)-        | otherwise = (runner, binpath : entry_options ++ extra_options)--  input' <- getValuesBS futhark dir input-  liftIO $ readProcessWithExitCode to_run to_run_args $ BS.toStrict input'- -- | Read the given variables from a running server. readResults ::   (MonadIO m, MonadError T.Text m) =>@@ -400,11 +370,33 @@ readResults server =   mapM (either throwError pure <=< liftIO . getValue server) +-- | Call an entry point. Returns server variables storing the result.+callEntry ::+  (MonadIO m, MonadError T.Text m) =>+  FutharkExe ->+  Server ->+  FilePath ->+  EntryName ->+  Values ->+  m [VarName]+callEntry futhark server prog entry input = do+  output_types <- cmdEither $ cmdOutputs server entry+  input_types <- cmdEither $ cmdInputs server entry+  let outs = ["out" <> showText i | i <- [0 .. length output_types - 1]]+      ins = ["in" <> showText i | i <- [0 .. length input_types - 1]]+      ins_and_types = zip ins (map inputType input_types)+  valuesAsVars server ins_and_types futhark dir input+  _ <- cmdEither $ cmdCall server entry outs ins+  cmdMaybe $ cmdFree server ins+  pure outs+  where+    dir = takeDirectory prog+ -- | Ensure that any reference output files exist, or create them (by -- compiling the program with the reference compiler and running it on -- the input) if necessary. ensureReferenceOutput ::-  (MonadIO m, MonadError [T.Text] m) =>+  (MonadIO m, MonadError T.Text m) =>   Maybe Int ->   FutharkExe ->   String ->@@ -415,31 +407,20 @@   missing <- filterM isReferenceMissing $ concatMap entryAndRuns ios    unless (null missing) $ do-    void $ compileProgram [] futhark compiler prog--    res <- liftIO . flip (pmapIO concurrency) missing $ \(entry, tr) -> do-      (code, stdout, stderr) <- runProgram futhark "" ["-b"] prog entry $ runInput tr-      case code of-        ExitFailure e ->-          pure $-            Left-              [ T.pack $-                  "Reference dataset generation failed with exit code "-                    ++ show e-                    ++ " and stderr:\n"-                    ++ map (chr . fromIntegral) (SBS.unpack stderr)-              ]-        ExitSuccess -> do-          let f = file (entry, tr)-          liftIO $ createDirectoryIfMissing True $ takeDirectory f-          SBS.writeFile f stdout-          pure $ Right ()+    void $ compileProgram ["--server"] futhark compiler prog -    case sequence_ res of-      Left err -> throwError err-      Right () -> pure ()+    res <- liftIO . flip (pmapIO concurrency) missing $ \(entry, tr) ->+      withServer server_cfg $ \server -> runExceptT $ do+        outs <- callEntry futhark server prog entry $ runInput tr+        let f = file entry tr+        liftIO $ createDirectoryIfMissing True $ takeDirectory f+        cmdMaybe $ cmdStore server f outs+        cmdMaybe $ cmdFree server outs+    either throwError (const (pure ())) (sequence_ res)   where-    file (entry, tr) =+    server_cfg = futharkServerCfg (dropExtension prog) []++    file entry tr =       takeDirectory prog </> testRunReferenceOutput prog entry tr      entryAndRuns (InputOutputs entry rts) = map (entry,) rts@@ -447,7 +428,7 @@     isReferenceMissing (entry, tr)       | Succeeds (Just SuccessGenerateValues) <- runExpectedResult tr =           liftIO $-            ((<) <$> getModificationTime (file (entry, tr)) <*> getModificationTime prog)+            ((<) <$> getModificationTime (file entry tr) <*> getModificationTime prog)               `catch` (\e -> if isDoesNotExistError e then pure True else E.throw e)       | otherwise =           pure False
src/Language/Futhark/FreeVars.hs view
@@ -54,6 +54,7 @@     where       freeInExpField (RecordFieldExplicit _ e _) = freeInExp e       freeInExpField (RecordFieldImplicit vn t _) = ident $ Ident vn t mempty+  ArrayVal {} -> mempty   ArrayLit es t _ ->     foldMap freeInExp es <> freeInType (unInfo t)   AppExp (Range e me incl _) _ ->
src/Language/Futhark/Interpreter.hs view
@@ -966,6 +966,9 @@   v' <- eval env v   vs' <- mapM (eval env) vs   pure $ toArray' (valueShape v') (v' : vs')+eval _ (ArrayVal vs _ _) =+  -- Probably will not ever be used.+  pure $ toArray' ShapeLeaf $ map ValuePrim vs eval env (AppExp e (Info (AppRes t retext))) = do   let t' = expandType env $ toStruct t   v <- evalAppExp env e
src/Language/Futhark/Parser/Lexer.x view
@@ -196,20 +196,19 @@       let x = action (BS.take (n'-n) s)       x `seq` Right (state', (pos, pos', x)) -scanTokens :: Pos -> BS.ByteString -> Either LexerError ([L Token], Pos)-scanTokens pos str = loop $ initialLexerState pos str+scanTokens :: Pos -> BS.ByteString -> Either LexerError [L Token]+scanTokens pos str = fmap reverse $ loop [] $ initialLexerState pos str   where-   loop s = do+   loop toks s = do      (s', tok) <- getToken s      case tok of        (start, end, EOF) ->-         pure ([], end)-       (start, end, t) -> do-         (rest, endpos) <- loop s'-         pure (L (Loc start end) t : rest, endpos)+         pure toks+       (start, end, t) ->+         loop (L (Loc start end) t:toks) s'  -- | 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 -> T.Text -> Either LexerError [L Token] scanTokensText pos = scanTokens pos . BS.fromStrict . T.encodeUtf8 }
src/Language/Futhark/Parser/Lexer/Tokens.hs view
@@ -16,16 +16,13 @@     binToken,     hexToken,     romToken,-    advance,     readHexRealLit,   ) where  import Data.ByteString.Lazy qualified as BS-import Data.Char (ord) import Data.Either import Data.List (find)-import Data.Loc (Pos (..)) import Data.Text qualified as T import Data.Text.Encoding qualified as T import Data.Text.Read qualified as T@@ -191,14 +188,6 @@ {-# INLINE tokenS #-} tokenS :: (T.Text -> a) -> BS.ByteString -> a tokenS f = f . T.decodeUtf8 . BS.toStrict--advance :: Pos -> BS.ByteString -> Pos-advance orig_pos = BS.foldl' advance' orig_pos . BS.init-  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
src/Language/Futhark/Parser/Monad.hs view
@@ -17,6 +17,7 @@     mustBe,     primNegate,     applyExp,+    arrayLitExp,     patternExp,     addDocSpec,     addAttrSpec,@@ -110,6 +111,17 @@  arrayFromList :: [a] -> Array Int a arrayFromList l = listArray (0, length l - 1) l++arrayLitExp :: [UncheckedExp] -> SrcLoc -> UncheckedExp+arrayLitExp es loc+  | Just (v : vs) <- mapM isLiteral es,+    all ((primValueType v ==) . primValueType) vs =+      ArrayVal (v : vs) (primValueType v) loc+  | otherwise =+      ArrayLit es NoInfo loc+  where+    isLiteral (Literal v _) = Just v+    isLiteral _ = Nothing  applyExp :: NE.NonEmpty UncheckedExp -> ParserMonad UncheckedExp applyExp all_es@((Constr n [] _ loc1) NE.:| es) =
src/Language/Futhark/Parser/Parser.y view
@@ -605,8 +605,8 @@      | '(' Exp ')'            { Parens $2 (srcspan $1 $>) }      | '(' Exp ',' Exps1 ')'  { TupLit ($2 : $4) (srcspan $1 $>) }      | '('      ')'           { TupLit [] (srcspan $1 $>) }-     | '[' Exps1 ']'          { ArrayLit $2 NoInfo (srcspan $1 $>) }-     | '['       ']'          { ArrayLit [] NoInfo (srcspan $1 $>) }+     | '[' Exps1 ']'          { arrayLitExp $2 (srcspan $1 $>) }+     | '['       ']'          { arrayLitExp [] (srcspan $1 $>) }       | id { let L loc (ID v)  = $1 in Var (QualName [] v) NoInfo (srclocOf loc) } 
src/Language/Futhark/Pretty.hs view
@@ -353,6 +353,8 @@   where     fieldArray (RecordFieldExplicit _ e _) = hasArrayLit e     fieldArray RecordFieldImplicit {} = False+prettyExp _ (ArrayVal vs _ _) =+  brackets (commasep $ map pretty vs) prettyExp _ (ArrayLit es t _) =   brackets (commasep $ map pretty es) <> prettyInst t prettyExp _ (StringLit s _) =@@ -631,4 +633,5 @@     precedence Backtick = 9     rprecedence Minus = 10     rprecedence Divide = 10-    rprecedence op = precedence op+    rprecedence PipeLeft = -1+    rprecedence op = precedence op + 1
src/Language/Futhark/Prop.hs view
@@ -463,6 +463,8 @@     record (RecordFieldExplicit name e _) = (name, typeOf e)     record (RecordFieldImplicit name (Info t) _) = (baseName name, t) typeOf (ArrayLit _ (Info t) _) = t+typeOf (ArrayVal vs t loc) =+  Array mempty (Shape [sizeFromInteger (genericLength vs) loc]) (Prim t) typeOf (StringLit vs loc) =   Array     mempty
src/Language/Futhark/Semantic.hs view
@@ -125,7 +125,10 @@ -- return type.  The type parameters are in scope in both parameter -- types and the return type.  Non-functional values have only a -- return type.-data BoundV = BoundV [TypeParam] StructType+data BoundV = BoundV+  { boundValTParams :: [TypeParam],+    boundValType :: StructType+  }   deriving (Show)  -- | A mapping from names (which always exist in some namespace) to a
src/Language/Futhark/Syntax.hs view
@@ -806,6 +806,12 @@   | -- | Array literals, e.g., @[ [1+x, 3], [2, 1+4] ]@.     -- Second arg is the row type of the rows of the array.     ArrayLit [ExpBase f vn] (f StructType) SrcLoc+  | -- | Array value constants, where the elements are known to be+    -- constant primitives. This is a fast-path variant of 'ArrayLit'+    -- that will never be constructed by the parser, but may result+    -- from normalisation later on. Has exactly the same semantics as+    -- an 'ArrayLit'.+    ArrayVal [PrimValue] PrimType SrcLoc   | -- | An attribute applied to the following expression.     Attr (AttrInfo vn) (ExpBase f vn) SrcLoc   | Project Name (ExpBase f vn) (f StructType) SrcLoc@@ -877,6 +883,7 @@   locOf (RecordLit _ pos) = locOf pos   locOf (Project _ _ _ pos) = locOf pos   locOf (ArrayLit _ _ pos) = locOf pos+  locOf (ArrayVal _ _ loc) = locOf loc   locOf (StringLit _ loc) = locOf loc   locOf (Var _ _ loc) = locOf loc   locOf (Ascript _ _ loc) = locOf loc
src/Language/Futhark/Traversals.hs view
@@ -146,6 +146,8 @@     TupLit <$> mapM (mapOnExp tv) els <*> pure loc   astMap tv (RecordLit fields loc) =     RecordLit <$> astMap tv fields <*> pure loc+  astMap _ (ArrayVal vs t loc) =+    pure $ ArrayVal vs t loc   astMap tv (ArrayLit els t loc) =     ArrayLit <$> mapM (mapOnExp tv) els <*> traverse (mapOnStructType tv) t <*> pure loc   astMap tv (Ascript e tdecl loc) =@@ -456,6 +458,7 @@ bareExp (TupLit els loc) = TupLit (map bareExp els) loc bareExp (StringLit vs loc) = StringLit vs loc bareExp (RecordLit fields loc) = RecordLit (map bareField fields) loc+bareExp (ArrayVal vs t loc) = ArrayVal vs t loc bareExp (ArrayLit els _ loc) = ArrayLit (map bareExp els) NoInfo loc bareExp (Ascript e te loc) = Ascript (bareExp e) (bareTypeExp te) loc bareExp (Coerce e te _ loc) = Coerce (bareExp e) (bareTypeExp te) NoInfo loc
src/Language/Futhark/TypeChecker/Consumption.hs view
@@ -954,6 +954,7 @@ checkExp e@FloatLit {} = noAliases e checkExp e@Literal {} = noAliases e checkExp e@StringLit {} = noAliases e+checkExp e@ArrayVal {} = noAliases e checkExp e@ArrayLit {} = noAliases e checkExp e@Negate {} = noAliases e checkExp e@Not {} = noAliases e
src/Language/Futhark/TypeChecker/Modules.hs view
@@ -34,7 +34,7 @@ substituteTypesInEnv :: TypeSubs -> Env -> Env substituteTypesInEnv substs env =   env-    { envVtable = M.map (substituteTypesInBoundV substs) $ envVtable env,+    { envVtable = M.map (snd . substituteTypesInBoundV substs) $ envVtable env,       envTypeTable = M.mapWithKey subT $ envTypeTable env,       envModTable = M.map (substituteTypesInMod substs) $ envModTable env     }@@ -44,10 +44,14 @@     subT _ (TypeAbbr l ps (RetType dims t)) =       TypeAbbr l ps $ applySubst substs $ RetType dims t -substituteTypesInBoundV :: TypeSubs -> BoundV -> BoundV+-- Also returns names of new sizes arising from substituting a+-- size-lifted type at the outermost part of the type. This is a+-- somewhat rare case (see #2120). The right solution is to generally+-- fresh (or at least unique) names.+substituteTypesInBoundV :: TypeSubs -> BoundV -> ([VName], BoundV) substituteTypesInBoundV substs (BoundV tps t) =   let RetType dims t' = applySubst substs $ RetType [] t-   in BoundV (tps ++ map (`TypeParamDim` mempty) dims) t'+   in (dims, BoundV (tps <> map (`TypeParamDim` mempty) dims) t')  -- | All names defined anywhere in the 'Env'. allNamesInEnv :: Env -> S.Set VName@@ -346,6 +350,11 @@   Left . TypeError loc mempty $     "Module does not define a value named" <+> pretty name <> "." +topLevelSize :: Loc -> VName -> Either TypeError b+topLevelSize loc name =+  Left . TypeError loc mempty $+    "Type substitution in" <+> dquotes (prettyName name) <+> "results in a top-level size."+ missingMod :: (Pretty a) => Loc -> a -> Either TypeError b missingMod loc name =   Left . TypeError loc mempty $@@ -499,7 +508,11 @@       -- abstract types first.       val_substs <- fmap M.fromList $         forM (M.toList $ envVtable sig) $ \(name, spec_bv) -> do-          let spec_bv' = substituteTypesInBoundV (`M.lookup` abs_subst_to_type) spec_bv+          let (spec_dims, spec_bv') =+                substituteTypesInBoundV (`M.lookup` abs_subst_to_type) spec_bv+              (spec_witnesses, _) = determineSizeWitnesses $ boundValType spec_bv'+          -- The hacky check for #2120.+          when (any (`S.member` spec_witnesses) spec_dims) $ topLevelSize loc name           case findBinding envVtable Term (baseName name) env of             Just (name', bv) -> matchVal loc quals name spec_bv' name' bv             _ -> missingVal loc (baseName name)
src/Language/Futhark/TypeChecker/Names.hs view
@@ -245,6 +245,8 @@   Attr <$> resolveAttrInfo attr <*> resolveExp e <*> pure loc resolveExp (TupLit es loc) =   TupLit <$> mapM resolveExp es <*> pure loc+resolveExp (ArrayVal vs t loc) =+  pure $ ArrayVal vs t loc resolveExp (ArrayLit es NoInfo loc) =   ArrayLit <$> mapM resolveExp es <*> pure NoInfo <*> pure loc resolveExp (Negate e loc) =
src/Language/Futhark/TypeChecker/Terms.hs view
@@ -389,6 +389,10 @@               <+> pretty (locStrRel rloc sloc)               <> "."         Nothing -> pure ()+-- No need to type check this, as these are only produced by the+-- parser if the elements are monomorphic and all match.+checkExp (ArrayVal vs t loc) =+  pure $ ArrayVal vs t loc checkExp (ArrayLit all_es _ loc) =   -- Construct the result type and unify all elements with it.  We   -- only create a type variable for empty arrays; otherwise we use