mirror of
https://github.com/unisonweb/unison.git
synced 2024-11-12 04:34:38 +03:00
Merge branch 'master' into topic/universals
This commit is contained in:
commit
37f25fd12c
@ -14,7 +14,7 @@ module Unison.Codebase.Editor where
|
||||
|
||||
import Data.Char ( toLower )
|
||||
import Data.List (sortOn, isSuffixOf, isPrefixOf)
|
||||
import Control.Monad ( forM_, forM, foldM, filterM)
|
||||
import Control.Monad ( forM_, forM, foldM, filterM, void)
|
||||
import Control.Monad.Extra ( ifM )
|
||||
import Data.Foldable (toList)
|
||||
import Data.Bifunctor ( bimap, second )
|
||||
@ -147,7 +147,7 @@ data Input
|
||||
| ChooseUpdateForTermI Referent Referent
|
||||
| ChooseUpdateForTypeI Reference Reference
|
||||
-- execute an IO object with arguments
|
||||
-- | ExecuteI Name [String]
|
||||
| ExecuteI String
|
||||
-- other
|
||||
| SlurpFileI AllowUpdates
|
||||
| ListBranchesI
|
||||
@ -280,7 +280,8 @@ data Command i v a where
|
||||
-> UF.TypecheckedUnisonFile v Ann
|
||||
-> Command i v (SlurpResult v)
|
||||
|
||||
Typecheck :: Branch
|
||||
Typecheck :: [Type.AnnotatedType v Ann]
|
||||
-> Branch
|
||||
-> SourceName
|
||||
-> Source
|
||||
-> Command i v (TypecheckingResult v)
|
||||
@ -356,7 +357,7 @@ data Command i v a where
|
||||
|
||||
Propagate :: Branch -> Command i v Branch
|
||||
|
||||
-- Execute :: Reference.Id -> Command i v (IO ())
|
||||
Execute :: Branch -> UF.UnisonFile v Ann -> Command i v ()
|
||||
|
||||
data Outcome
|
||||
-- New definition that was added to the branch
|
||||
@ -599,13 +600,14 @@ fileToBranch handleCollisions codebase branch uf = do
|
||||
|
||||
typecheck
|
||||
:: (Monad m, Var v)
|
||||
=> Codebase m v Ann
|
||||
=> [Type.AnnotatedType v Ann]
|
||||
-> Codebase m v Ann
|
||||
-> Names
|
||||
-> SourceName
|
||||
-> Text
|
||||
-> m (TypecheckingResult v)
|
||||
typecheck codebase names sourceName src =
|
||||
Result.getResult $ parseAndSynthesizeFile
|
||||
typecheck ambient codebase names sourceName src =
|
||||
Result.getResult $ parseAndSynthesizeFile ambient
|
||||
(((<> B.typeLookup) <$>) . Codebase.typeLookupForDependencies codebase)
|
||||
names
|
||||
(unpack sourceName)
|
||||
@ -661,16 +663,9 @@ commandLine awaitInput rt notifyUser codebase command = do
|
||||
Notify output -> notifyUser output
|
||||
SlurpFile handler branch unisonFile ->
|
||||
fileToBranch handler codebase branch unisonFile
|
||||
Typecheck branch sourceName source ->
|
||||
typecheck codebase (Branch.toNames branch) sourceName source
|
||||
Evaluate branch unisonFile -> do
|
||||
let codeLookup = Codebase.toCodeLookup codebase
|
||||
selfContained <- Codebase.makeSelfContained'
|
||||
codeLookup
|
||||
(Branch.head branch)
|
||||
unisonFile
|
||||
let noCache = const (pure Nothing)
|
||||
Runtime.evaluateWatches codeLookup noCache rt selfContained
|
||||
Typecheck ambient branch sourceName source ->
|
||||
typecheck ambient codebase (Branch.toNames branch) sourceName source
|
||||
Evaluate branch unisonFile -> evalUnisonFile branch unisonFile
|
||||
ListBranches -> Codebase.branches codebase
|
||||
LoadBranch branchName -> Codebase.getBranch codebase branchName
|
||||
NewBranch branchName -> newBranch codebase branchName
|
||||
@ -693,6 +688,14 @@ commandLine awaitInput rt notifyUser codebase command = do
|
||||
Propagate b -> do
|
||||
b0 <- Codebase.propagate codebase (Branch.head b)
|
||||
pure $ Branch.append b0 b
|
||||
Execute branch uf -> void $ evalUnisonFile branch uf
|
||||
evalUnisonFile branch unisonFile = do
|
||||
let codeLookup = Codebase.toCodeLookup codebase
|
||||
selfContained <- Codebase.makeSelfContained' codeLookup
|
||||
(Branch.head branch)
|
||||
unisonFile
|
||||
let noCache = const (pure Nothing)
|
||||
Runtime.evaluateWatches codeLookup noCache rt selfContained
|
||||
|
||||
doTodo :: Monad m => Codebase m v a -> Branch0 -> m (TodoOutput v a)
|
||||
doTodo code b = do
|
||||
|
@ -1,3 +1,4 @@
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE DoAndIfThenElse #-}
|
||||
{-# LANGUAGE GADTs #-}
|
||||
{-# LANGUAGE PatternSynonyms #-}
|
||||
@ -42,18 +43,20 @@ import Unison.Codebase.Editor ( Command(..)
|
||||
( NameChangeResult)
|
||||
, collateReferences
|
||||
)
|
||||
import qualified Unison.Codebase.Editor as Editor
|
||||
import qualified Unison.HashQualified as HQ
|
||||
import qualified Unison.Codebase.Editor as Editor
|
||||
import qualified Unison.DataDeclaration as DD
|
||||
import qualified Unison.HashQualified as HQ
|
||||
import Unison.Name ( Name )
|
||||
import Unison.Names ( NameTarget )
|
||||
import qualified Unison.Names as Names
|
||||
import Unison.Parser ( Ann )
|
||||
import Unison.Parser ( Ann(..) )
|
||||
import qualified Unison.PrettyPrintEnv as PPE
|
||||
import Unison.Reference ( Reference )
|
||||
import qualified Unison.Reference as Reference
|
||||
import qualified Unison.Referent as Referent
|
||||
import Unison.Result (pattern Result)
|
||||
import qualified Unison.Term as Term
|
||||
import qualified Unison.Term as Term
|
||||
import qualified Unison.Type as Type
|
||||
import qualified Unison.Result as Result
|
||||
import qualified Unison.UnisonFile as UF
|
||||
import Unison.Util.Free ( Free )
|
||||
@ -88,6 +91,21 @@ loop = do
|
||||
latestFile' <- use latestFile
|
||||
currentBranch' <- use currentBranch
|
||||
e <- eval Input
|
||||
let withFile ambient sourceName text k = do
|
||||
Result notes r <- eval $
|
||||
Typecheck ambient (view currentBranch s) sourceName text
|
||||
case r of
|
||||
-- Parsing failed
|
||||
Nothing ->
|
||||
respond $ ParseErrors
|
||||
text
|
||||
[ err | Result.Parsing err <- toList notes ]
|
||||
Just (errorEnv, r) ->
|
||||
let h = respond $ TypeErrors
|
||||
text
|
||||
errorEnv
|
||||
[ err | Result.TypeError err <- toList notes ]
|
||||
in maybe h (k errorEnv) r
|
||||
case e of
|
||||
Left (UnisonBranchChanged names) ->
|
||||
when (Set.member currentBranchName' names)
|
||||
@ -98,40 +116,21 @@ loop = do
|
||||
then modifying latestFile $ (fmap (const False) <$>)
|
||||
else do
|
||||
eval (Notify $ FileChangeEvent sourceName text)
|
||||
Result notes r <- eval
|
||||
(Typecheck (view currentBranch s) sourceName text)
|
||||
case r of
|
||||
-- Parsing failed
|
||||
Nothing ->
|
||||
respond $ ParseErrors
|
||||
text
|
||||
[ err | Result.Parsing err <- toList notes ]
|
||||
Just (errorEnv, r) -> case r of
|
||||
-- Typing failed
|
||||
Nothing ->
|
||||
respond $ TypeErrors
|
||||
text
|
||||
errorEnv
|
||||
[ err | Result.TypeError err <- toList notes ]
|
||||
-- A unison file has changed
|
||||
Just unisonFile -> do
|
||||
eval (Notify $ Typechecked sourceName errorEnv unisonFile)
|
||||
(bindings, e) <-
|
||||
eval
|
||||
( Evaluate (view currentBranch s)
|
||||
$ UF.discardTypes unisonFile
|
||||
)
|
||||
let e' = Map.map go e
|
||||
go (ann, _hash, _uneval, eval, isHit) = (ann, eval, isHit)
|
||||
-- todo: this would be a good spot to update the cache
|
||||
-- with all the (hash, eval) pairs, even if it's just an
|
||||
-- in-memory cache
|
||||
eval . Notify $ Evaluated text
|
||||
(errorEnv <> Branch.prettyPrintEnv (Branch.head currentBranch'))
|
||||
bindings
|
||||
e'
|
||||
latestFile .= Just (Text.unpack sourceName, False)
|
||||
latestTypecheckedFile .= Just unisonFile
|
||||
withFile [] sourceName text $ \errorEnv unisonFile -> do
|
||||
eval (Notify $ Typechecked sourceName errorEnv unisonFile)
|
||||
(bindings, e) <-
|
||||
eval . Evaluate (view currentBranch s) $ UF.discardTypes unisonFile
|
||||
let e' = Map.map go e
|
||||
go (ann, _hash, _uneval, eval, isHit) = (ann, eval, isHit)
|
||||
-- todo: this would be a good spot to update the cache
|
||||
-- with all the (hash, eval) pairs, even if it's just an
|
||||
-- in-memory cache
|
||||
eval . Notify $ Evaluated text
|
||||
(errorEnv <> Branch.prettyPrintEnv (Branch.head currentBranch'))
|
||||
bindings
|
||||
e'
|
||||
latestFile .= Just (Text.unpack sourceName, False)
|
||||
latestTypecheckedFile .= Just unisonFile
|
||||
Right input -> case input of
|
||||
-- ls with no arguments
|
||||
SearchByNameI [] ->
|
||||
@ -248,8 +247,13 @@ loop = do
|
||||
_ <- eval $ SyncBranch currentBranchName' b
|
||||
_ <- success
|
||||
currentBranch .= b
|
||||
-- ExecuteI name args ->
|
||||
|
||||
ExecuteI input ->
|
||||
withFile [Type.ref External $ Reference.DerivedId DD.ioHash]
|
||||
"execute command"
|
||||
("main_ = " <> Text.pack input) $
|
||||
\_ unisonFile ->
|
||||
eval . Execute (view currentBranch s) $
|
||||
UF.discardTypes unisonFile
|
||||
QuitI -> quit
|
||||
where
|
||||
success = respond $ Success input
|
||||
|
@ -132,6 +132,11 @@ validInputs =
|
||||
(\ws -> if not $ null ws
|
||||
then Left $ warn "`todo` doesn't take any arguments."
|
||||
else pure $ TodoI)
|
||||
, InputPattern "execute" [] [(True, noCompletions)]
|
||||
"`execute foo` evaluates the Unison expression `foo` of type `()` with access to the `IO` ability."
|
||||
(\ws -> if null ws
|
||||
then Left $ warn "`execute` needs a Unison language expression."
|
||||
else pure . ExecuteI $ intercalate " " ws)
|
||||
, InputPattern "quit" ["exit"] []
|
||||
"Exits the Unison command line interface."
|
||||
(\case
|
||||
|
@ -9,36 +9,40 @@
|
||||
|
||||
module Unison.DataDeclaration where
|
||||
|
||||
import Safe (atMay)
|
||||
import Data.List (sortOn)
|
||||
import Unison.Hash (Hash)
|
||||
import Safe ( atMay )
|
||||
import Data.List ( sortOn )
|
||||
import Unison.Hash ( Hash )
|
||||
import Data.Functor
|
||||
import Data.Map (Map)
|
||||
import qualified Data.Map as Map
|
||||
import Data.Set (Set)
|
||||
import qualified Data.Set as Set
|
||||
import Prelude hiding (cycle)
|
||||
import Prelude.Extras (Show1)
|
||||
import qualified Unison.ABT as ABT
|
||||
import Unison.Hashable (Accumulate, Hashable1)
|
||||
import qualified Unison.Hashable as Hashable
|
||||
import qualified Unison.Name as Name
|
||||
import Unison.Reference (Reference)
|
||||
import qualified Unison.Reference as Reference
|
||||
import Unison.Referent (Referent)
|
||||
import qualified Unison.Referent as Referent
|
||||
import qualified Unison.Term as Term
|
||||
import Unison.Term (AnnotatedTerm, AnnotatedTerm2)
|
||||
import Unison.Type (AnnotatedType)
|
||||
import qualified Unison.Type as Type
|
||||
import Unison.Var (Var)
|
||||
import Data.Text (Text)
|
||||
import qualified Unison.Var as Var
|
||||
import Unison.Names (Names)
|
||||
import Unison.Names as Names
|
||||
import Unison.Symbol (Symbol)
|
||||
import qualified Unison.Pattern as Pattern
|
||||
-- import Debug.Trace
|
||||
import Data.Map ( Map )
|
||||
import qualified Data.Map as Map
|
||||
import Data.Set ( Set )
|
||||
import qualified Data.Set as Set
|
||||
import Prelude hiding ( cycle )
|
||||
import Prelude.Extras ( Show1 )
|
||||
import qualified Unison.ABT as ABT
|
||||
import Unison.Hash as Hash
|
||||
import Unison.Hashable ( Accumulate
|
||||
, Hashable1
|
||||
)
|
||||
import qualified Unison.Hashable as Hashable
|
||||
import qualified Unison.Name as Name
|
||||
import Unison.Reference ( Reference )
|
||||
import qualified Unison.Reference as Reference
|
||||
import Unison.Referent ( Referent )
|
||||
import qualified Unison.Referent as Referent
|
||||
import qualified Unison.Term as Term
|
||||
import Unison.Term ( AnnotatedTerm
|
||||
, AnnotatedTerm2
|
||||
)
|
||||
import Unison.Type ( AnnotatedType )
|
||||
import qualified Unison.Type as Type
|
||||
import Unison.Var ( Var )
|
||||
import Data.Text ( Text )
|
||||
import qualified Unison.Var as Var
|
||||
import Unison.Names ( Names )
|
||||
import Unison.Names as Names
|
||||
import Unison.Symbol ( Symbol )
|
||||
import qualified Unison.Pattern as Pattern
|
||||
|
||||
type DataDeclaration v = DataDeclaration' v ()
|
||||
|
||||
@ -287,6 +291,14 @@ builtinDataDecls = hashDecls $
|
||||
(var "a" `arr` Type.app' (var "Optional") (var "a")))
|
||||
]
|
||||
|
||||
ioHash :: Reference.Id
|
||||
ioHash = Reference.Id
|
||||
(Hash.unsafeFromBase58
|
||||
"525sNixZKpeYWYAr8UFEUkYmATSbfuYkEWgnCa6xFr33JrZxra8jJtShxhtytDisdBSoCE6gtqDRkw67nRnSQXDx"
|
||||
)
|
||||
0
|
||||
1
|
||||
|
||||
pattern UnitRef <- (unUnitRef -> True)
|
||||
pattern PairRef <- (unPairRef -> True)
|
||||
pattern OptionalRef <- (unOptionalRef -> True)
|
||||
|
@ -79,7 +79,8 @@ convertNotes (Typechecker.Notes es is) =
|
||||
|
||||
parseAndSynthesizeFile
|
||||
:: (Var v, Monad m)
|
||||
=> (Set Reference -> m (TL.TypeLookup v Ann))
|
||||
=> [Type v]
|
||||
-> (Set Reference -> m (TL.TypeLookup v Ann))
|
||||
-> Names
|
||||
-> FilePath
|
||||
-> Text
|
||||
@ -87,22 +88,24 @@ parseAndSynthesizeFile
|
||||
(Seq (Note v Ann))
|
||||
m
|
||||
(PPE.PrettyPrintEnv, Maybe (UF.TypecheckedUnisonFile v Ann))
|
||||
parseAndSynthesizeFile typeLookupf names filePath src = do
|
||||
parseAndSynthesizeFile ambient typeLookupf names filePath src = do
|
||||
(errorEnv, parsedUnisonFile) <- Result.fromParsing
|
||||
$ Parsers.parseFile filePath (unpack src) names
|
||||
let refs = UF.dependencies parsedUnisonFile names
|
||||
typeLookup <- lift . lift $ typeLookupf refs
|
||||
let (Result notes' r) = synthesizeFile typeLookup names parsedUnisonFile
|
||||
let (Result notes' r) =
|
||||
synthesizeFile ambient typeLookup names parsedUnisonFile
|
||||
tell notes' *> pure (errorEnv, r)
|
||||
|
||||
synthesizeFile
|
||||
:: forall v
|
||||
. Var v
|
||||
=> TL.TypeLookup v Ann
|
||||
=> [Type v]
|
||||
-> TL.TypeLookup v Ann
|
||||
-> Names
|
||||
-> UnisonFile v
|
||||
-> Result (Seq (Note v Ann)) (UF.TypecheckedUnisonFile v Ann)
|
||||
synthesizeFile preexistingTypes preexistingNames unisonFile = do
|
||||
synthesizeFile ambient preexistingTypes preexistingNames unisonFile = do
|
||||
let
|
||||
-- substitute builtins into the datas/effects/body of unisonFile
|
||||
uf@(UnisonFile dds0 eds0 _terms _watches) = unisonFile
|
||||
@ -119,7 +122,7 @@ synthesizeFile preexistingTypes preexistingNames unisonFile = do
|
||||
-- substitute Blanks for any remaining free vars in UF body
|
||||
tdnrTerm = Term.prepareTDNR $ term
|
||||
lookupTypes = localTypes <> preexistingTypes
|
||||
env0 = (Typechecker.Env Intrinsic [] lookupTypes fqnsByShortName)
|
||||
env0 = (Typechecker.Env Intrinsic ambient lookupTypes fqnsByShortName)
|
||||
where
|
||||
fqnsByShortName :: Map Name [Typechecker.NamedReference v Ann]
|
||||
fqnsByShortName = Map.fromListWith mappend
|
||||
|
@ -641,14 +641,14 @@ run ioHandler env ir = do
|
||||
m <- MV.clone m2
|
||||
m <- MV.grow m 256
|
||||
pure (size2, m)
|
||||
loop (RRequest (Req ref cid vs k)) = do
|
||||
ioResult <- ioHandler ref cid vs
|
||||
x <- callContinuation 0 m0 k ioResult
|
||||
loop x
|
||||
loop a = pure a
|
||||
|
||||
r <- go 0 m0 ir
|
||||
case r of
|
||||
RRequest (Req ref cid vs k) -> do
|
||||
ioResult <- ioHandler ref cid vs
|
||||
callContinuation 0 m0 k ioResult
|
||||
a -> pure a
|
||||
|
||||
loop r
|
||||
|
||||
instance Show ExternalFunction where
|
||||
show _ = "ExternalFunction"
|
||||
|
@ -26,6 +26,10 @@ import System.IO ( Handle
|
||||
, IOMode(..)
|
||||
, openFile
|
||||
, hClose
|
||||
, hPutStr
|
||||
, stdin
|
||||
, stdout
|
||||
, stderr
|
||||
)
|
||||
import Unison.Symbol
|
||||
import qualified Unison.Reference as R
|
||||
@ -102,15 +106,6 @@ constructorName' cl hash cid = do
|
||||
go (DataDeclaration _ _ ctors) =
|
||||
pure . Var.name $ view _2 $ genericIndex ctors cid
|
||||
|
||||
-- TODO: Put the actual hashes of these types in here
|
||||
ioHash :: R.Id
|
||||
ioHash = R.Id
|
||||
(Hash.unsafeFromBase58
|
||||
"3aEd7hZ5DUwcKcTij4Ba8fUzs6B85euZ9Zcs2iNHxyG9UyDYUzXqgENLo9HNzqRKgXBg7B1eA2nNB1sxMcbqCa15"
|
||||
)
|
||||
0
|
||||
1
|
||||
|
||||
ioModeHash :: R.Id
|
||||
ioModeHash = R.Id (Hash.unsafeFromBase58 "abracadabra1") 0 1
|
||||
|
||||
@ -131,10 +126,20 @@ handleIO cid = (constructorName ioHash cid >>=) . flip go
|
||||
liftIO $ maybe (pure ()) hClose hh
|
||||
deleteUnisonHandle handle
|
||||
pure IR.unit
|
||||
go "IO.printLine" [IR.T string] = do
|
||||
liftIO . putStrLn $ Text.unpack string
|
||||
go "IO.putText" [IR.Data _ _ [IR.T handle], IR.T string] = do
|
||||
hh <- getHaskellHandle handle
|
||||
case hh of
|
||||
Just h -> liftIO . hPutStr h $ Text.unpack string
|
||||
Nothing -> pure ()
|
||||
pure IR.unit
|
||||
go _ _ = undefined
|
||||
go a b =
|
||||
error
|
||||
$ "IO handler called with cid "
|
||||
<> show cid
|
||||
<> " and "
|
||||
<> show a
|
||||
<> " args "
|
||||
<> show b
|
||||
|
||||
runtime :: Runtime Symbol
|
||||
runtime = Runtime terminate eval
|
||||
@ -148,8 +153,9 @@ runtime = Runtime terminate eval
|
||||
-> IO (Term.Term Symbol)
|
||||
eval cl term = do
|
||||
-- traceM $ Pretty.render 80 (prettyTop mempty term)
|
||||
cenv <- RT.compilationEnv cl term -- in `m`
|
||||
mmap <- newMVar mempty
|
||||
cenv <- RT.compilationEnv cl term -- in `m`
|
||||
mmap <- newMVar
|
||||
$ Map.fromList [("stdin", stdin), ("stdout", stdout), ("stderr", stderr)]
|
||||
RT.RDone result <- RT.run (handleIO' $ S mmap cl)
|
||||
cenv
|
||||
(IR.compile cenv $ Term.amap (const ()) term)
|
||||
|
@ -205,9 +205,11 @@ placeholder :: Var v => TermP v
|
||||
placeholder = (\t -> Term.placeholder (ann t) (L.payload t)) <$> blank
|
||||
|
||||
vector :: Var v => TermP v -> TermP v
|
||||
vector p = f <$> reserved "[" <*> elements <*> reserved "]"
|
||||
vector p = f <$> reserved "[" <*> elements <*> trailing
|
||||
where
|
||||
elements = sepBy (reserved ",") p
|
||||
trailing = optional semi *> reserved "]"
|
||||
sep = P.try $ optional semi *> reserved "," <* optional semi
|
||||
elements = sepBy sep p
|
||||
f open elems close = Term.vector (ann open <> ann close) elems
|
||||
|
||||
termLeaf :: forall v. Var v => TermP v
|
||||
|
@ -30,7 +30,7 @@ file
|
||||
-> Result
|
||||
(Seq (Note Symbol Ann))
|
||||
(PPE.PrettyPrintEnv, Maybe (TypecheckedUnisonFile Symbol Ann))
|
||||
file = parseAndSynthesizeAsFile ""
|
||||
file = parseAndSynthesizeAsFile [] ""
|
||||
|
||||
t :: String -> Type Symbol
|
||||
t = B.t
|
||||
@ -43,13 +43,15 @@ env = Typechecker.Env Intrinsic [] B.typeLookup mempty
|
||||
|
||||
parseAndSynthesizeAsFile
|
||||
:: Var v
|
||||
=> FilePath
|
||||
=> [Type v]
|
||||
-> FilePath
|
||||
-> String
|
||||
-> Result (Seq (Note v Ann))
|
||||
(PPE.PrettyPrintEnv, Maybe (TypecheckedUnisonFile v Ann))
|
||||
parseAndSynthesizeAsFile filename s =
|
||||
FP.parseAndSynthesizeFile
|
||||
(\_deps -> pure B.typeLookup)
|
||||
B.names
|
||||
filename
|
||||
(Text.pack s)
|
||||
-> Result
|
||||
(Seq (Note v Ann))
|
||||
(PPE.PrettyPrintEnv, Maybe (TypecheckedUnisonFile v Ann))
|
||||
parseAndSynthesizeAsFile ambient filename s = FP.parseAndSynthesizeFile
|
||||
ambient
|
||||
(\_deps -> pure B.typeLookup)
|
||||
B.names
|
||||
filename
|
||||
(Text.pack s)
|
||||
|
@ -104,7 +104,7 @@ makePassingTest
|
||||
makePassingTest rt how filepath = scope shortName $ do
|
||||
let valueFile = replaceExtension filepath "ur"
|
||||
source <- io $ unpack <$> Data.Text.IO.readFile filepath
|
||||
let r = decodeResult source $ parseAndSynthesizeAsFile shortName source
|
||||
let r = decodeResult source $ parseAndSynthesizeAsFile [] shortName source
|
||||
rFileExists <- io $ doesFileExist valueFile
|
||||
case (rFileExists, r) of
|
||||
(True, Right file) -> do
|
||||
|
@ -52,7 +52,7 @@ noYieldsError s ex = not $ yieldsError s ex
|
||||
|
||||
yieldsError :: forall v a. Var v => String -> ErrorExtractor v Ann a -> Bool
|
||||
yieldsError s ex = let
|
||||
Result notes (Just _) = Common.parseAndSynthesizeAsFile "> test" s
|
||||
Result notes (Just _) = Common.parseAndSynthesizeAsFile [] "> test" s
|
||||
notes' :: [C.ErrorNote v Ann]
|
||||
notes' = [ n | Result.TypeError n <- toList notes ]
|
||||
in any (isJust . Ex.extract ex) notes'
|
||||
|
165
unison-src/IO.u
Normal file
165
unison-src/IO.u
Normal file
@ -0,0 +1,165 @@
|
||||
-- Handles are unique identifiers.
|
||||
-- The implementation of IO in the runtime will supply Haskell
|
||||
-- file handles and map those to Unison handles.
|
||||
-- A pure implementation of I/O might use some kind of pure supply
|
||||
-- of unique IDs instead.
|
||||
type Handle = Handle Text
|
||||
|
||||
-- Ditto for sockets
|
||||
type Socket = Socket Text
|
||||
|
||||
-- Builtin handles: standard in, out, error
|
||||
|
||||
namespace IO where
|
||||
stdin: Handle
|
||||
stdin = Handle "stdin"
|
||||
|
||||
stdout: Handle
|
||||
stdout = Handle "stdout"
|
||||
|
||||
stderr: Handle
|
||||
stderr = Handle "stderr"
|
||||
|
||||
printLine : Text -> {IO} ()
|
||||
printLine t =
|
||||
IO.putText stdout t
|
||||
IO.putText stdout "\n"
|
||||
|
||||
-- IO Modes from the Haskell API
|
||||
type IOMode = Read | Write | Append | ReadWrite
|
||||
|
||||
-- IO error types from the Haskell API
|
||||
type IOErrorType
|
||||
= AlreadyExists
|
||||
| NoSuchThing
|
||||
| ResourceBusy
|
||||
| ResourceExhausted
|
||||
| EOF
|
||||
| IllegalOperation
|
||||
| PermissionDenied
|
||||
| UserError
|
||||
|
||||
type ErrorLocation = ErrorLocation Text
|
||||
type ErrorDescription = ErrorDescription Text
|
||||
type FilePath = FilePath Text
|
||||
|
||||
type IOError =
|
||||
IOError
|
||||
(Optional Handle)
|
||||
IOErrorType
|
||||
ErrorLocation
|
||||
ErrorDescription
|
||||
(Optional FilePath)
|
||||
|
||||
type SeekMode = Absolute | Relative | FromEnd
|
||||
|
||||
-- If the buffer size is not specified,
|
||||
-- use an implementation-specific size.
|
||||
type BufferMode = Line | Block (Optional Nat)
|
||||
|
||||
type EpochTime = EpochTime Nat
|
||||
|
||||
-- Either a host name e.g., "unisonweb.org" or a numeric host address
|
||||
-- string consisting of a dotted decimal IPv4 address or an IPv6 address
|
||||
-- e.g., "192.168.0.1".
|
||||
type HostName = HostName Text
|
||||
|
||||
type PortNumber = Nat
|
||||
|
||||
-- Represents a 32-bit host address
|
||||
type HostAddress = HostAddress Int
|
||||
|
||||
-- Internet protocol v4 socket address
|
||||
type SocketAddress = SocketAddress HostAddress PortNumber
|
||||
|
||||
|
||||
|
||||
ability IO where
|
||||
|
||||
-- Basic file IO
|
||||
openFile : FilePath -> IOMode ->{IO} Handle
|
||||
closeFile : Handle ->{IO} ()
|
||||
isEOF : Handle ->{IO} Boolean
|
||||
isFileOpen : Handle ->{IO} Boolean
|
||||
|
||||
-- Text input and output
|
||||
|
||||
--getChar : Handle ->{IO} Char
|
||||
getLine : Handle ->{IO} Text
|
||||
-- Get the entire contents of the file as text
|
||||
getText : Handle ->{IO} Text
|
||||
-- putChar : Handle -> Char ->{IO} ()
|
||||
putText : Handle -> Text ->{IO} ()
|
||||
|
||||
-- Handling I/O errors.
|
||||
-- Question: can we do better?
|
||||
throw : IOError ->{IO} a
|
||||
catch : '{IO} a -> (IOError ->{IO} a) ->{IO} a
|
||||
|
||||
-- File positioning
|
||||
isSeekable : Handle ->{IO} Boolean
|
||||
seek : Handle -> SeekMode -> Int ->{IO} ()
|
||||
position : Handle ->{IO} Int
|
||||
|
||||
-- File buffering
|
||||
getBuffering : Handle ->{IO} (Optional BufferMode)
|
||||
setBuffering : Handle -> Optional BufferMode ->{IO} ()
|
||||
|
||||
-- Should we expose mutable arrays for byte buffering?
|
||||
-- Inclined to say no, although that sounds a lot like
|
||||
-- a decision to just be slow.
|
||||
-- We'll need a byte buffer manipulation library in that case.
|
||||
|
||||
-- getBytes : Handle -> Nat ->{IO} Bytes
|
||||
-- putBytes : Handle -> Bytes ->{IO} ()
|
||||
|
||||
-- getBytes : Handle -> Nat -> ByteArray ->{IO} Nat
|
||||
-- putBytes : Handle -> Nat -> ByteArray ->{IO} ()
|
||||
|
||||
systemTime : {IO} EpochTime
|
||||
|
||||
|
||||
-- File system operations
|
||||
getCurrentDirectory : {IO} FilePath
|
||||
setCurrentDirectory : FilePath ->{IO} ()
|
||||
directoryContents : FilePath ->{IO} [FilePath]
|
||||
fileExists : FilePath -> {IO} Boolean
|
||||
isDirectory : FilePath ->{IO} Boolean
|
||||
createDirectory : FilePath ->{IO} ()
|
||||
removeDirectory : FilePath ->{IO} ()
|
||||
renameDirectory : FilePath -> FilePath -> {IO} ()
|
||||
removeFile : FilePath ->{IO} ()
|
||||
renameFile : FilePath -> FilePath ->{IO} ()
|
||||
getFileTimestamp : FilePath ->{IO} EpochTime
|
||||
getFileSize : FilePath ->{IO} Nat
|
||||
|
||||
|
||||
-- Network I/O
|
||||
|
||||
-- Glossing over address families (ipv4, ipv6),
|
||||
-- and socket types (stream, raw, etc)
|
||||
|
||||
-- Creates a socket and binds it to a the given local port
|
||||
serverSocket : SocketAddress -> {IO} Socket
|
||||
|
||||
-- Creates a socket connected to the given remote address
|
||||
clientSocket : SocketAddress -> {IO} Socket
|
||||
|
||||
socketToHandle : Socket ->{IO} Handle
|
||||
handleToSocket : Handle ->{IO} Socket
|
||||
closeSocket : Socket ->{IO} ()
|
||||
|
||||
-- Accept a connection on a socket.
|
||||
-- Returns a socket that can send and receive data on a new connection,
|
||||
-- together with the remote host information.
|
||||
accept : Socket ->{IO} (Socket, SocketAddress)
|
||||
|
||||
-- Returns the number of bytes actually sent
|
||||
-- send : Socket -> Bytes ->{IO} Int
|
||||
|
||||
-- scatter/gather mode network I/O
|
||||
-- sendMany : Socket -> [Bytes] ->{IO} Int
|
||||
|
||||
-- Read the spefified number of bytes from the socket.
|
||||
-- receive : Socket -> Int ->{IO} Bytes
|
||||
|
19
unison-src/tests/sequence-literal.u
Normal file
19
unison-src/tests/sequence-literal.u
Normal file
@ -0,0 +1,19 @@
|
||||
a = [1,2,3]
|
||||
b = [1 ,2 ,3
|
||||
]
|
||||
c = [ 1 , 2 , 3 ]
|
||||
d = [ 1
|
||||
, 2
|
||||
, 3 ]
|
||||
e = [ 1
|
||||
, 2
|
||||
, 3
|
||||
]
|
||||
f =
|
||||
[ 1
|
||||
, 2
|
||||
, 3
|
||||
]
|
||||
g = [ 1
|
||||
, 2,
|
||||
3 ]
|
Loading…
Reference in New Issue
Block a user