mirror of
https://github.com/unisonweb/unison.git
synced 2024-09-11 02:25:39 +03:00
commit
4ce7cdf5d4
@ -15,7 +15,7 @@ be listed here, please [file a ticket](https://github.com/unisonweb/unison/issue
|
||||
|
||||
This file was generated using [unisonweb/credits-generator](http://github.com/unisonweb/credits-generator).
|
||||
|
||||
### Listing
|
||||
### Listing
|
||||
These are listed in alphabetical order.
|
||||
|
||||
| Package name | License |
|
||||
@ -109,6 +109,7 @@ These are listed in alphabetical order.
|
||||
| [network-bsd-2.8.1.0](https://hackage.haskell.org/package/network-bsd-2.8.1.0) | [BSD3](https://hackage.haskell.org/package/network-bsd-2.8.1.0/src/LICENSE) |
|
||||
| [network-info-0.2.0.10](https://hackage.haskell.org/package/network-info-0.2.0.10) | [BSD3](https://hackage.haskell.org/package/network-info-0.2.0.10/src/LICENSE) |
|
||||
| [network-simple-0.4.5](https://hackage.haskell.org/package/network-simple-0.4.5) | [BSD3](https://hackage.haskell.org/package/network-simple-0.4.5/src/LICENSE) |
|
||||
| [network-udp-0.0.0](https://hackage.haskell.org/package/network-udp-0.0.0) | [BSD3](https://hackage.haskell.org/package/network-udp-0.0.0/src/LICENSE) |
|
||||
| [nonempty-containers-0.3.3.0](https://hackage.haskell.org/package/nonempty-containers-0.3.3.0) | [BSD3](https://hackage.haskell.org/package/nonempty-containers-0.3.3.0/src/LICENSE) |
|
||||
| [nonempty-vector-0.2.0.2](https://hackage.haskell.org/package/nonempty-vector-0.2.0.2) | [BSD3](https://hackage.haskell.org/package/nonempty-vector-0.2.0.2/src/LICENSE) |
|
||||
| [parallel-3.2.2.0](https://hackage.haskell.org/package/parallel-3.2.2.0) | [BSD3](https://hackage.haskell.org/package/parallel-3.2.2.0/src/LICENSE) |
|
||||
|
@ -60,6 +60,7 @@ dependencies:
|
||||
- http-media
|
||||
- http-types
|
||||
- IntervalMap
|
||||
- iproute
|
||||
- lens
|
||||
- lucid
|
||||
- megaparsec
|
||||
@ -73,6 +74,7 @@ dependencies:
|
||||
- natural-transformation
|
||||
- network
|
||||
- network-simple
|
||||
- network-udp
|
||||
- network-uri
|
||||
- nonempty-containers
|
||||
- open-browser
|
||||
|
@ -246,7 +246,10 @@ builtinTypesSrc =
|
||||
B' "MutableArray" CT.Data,
|
||||
B' "ImmutableByteArray" CT.Data,
|
||||
B' "MutableByteArray" CT.Data,
|
||||
B' "Char.Class" CT.Data
|
||||
B' "Char.Class" CT.Data,
|
||||
B' "UDPSocket" CT.Data,
|
||||
B' "ListenSocket" CT.Data,
|
||||
B' "ClientSockAddr" CT.Data
|
||||
]
|
||||
|
||||
-- rename these to "builtin" later, when builtin means intrinsic as opposed to
|
||||
@ -815,6 +818,17 @@ ioBuiltins =
|
||||
("IO.serverSocket.impl.v3", optionalt text --> text --> iof socket),
|
||||
("IO.listen.impl.v3", socket --> iof unit),
|
||||
("IO.clientSocket.impl.v3", text --> text --> iof socket),
|
||||
("IO.UDP.clientSocket.impl.v1", text --> text --> iof udpSocket),
|
||||
("IO.UDP.ClientSockAddr.toText.v1", udpClientSockAddr --> text),
|
||||
("IO.UDP.UDPSocket.toText.impl.v1", udpSocket --> text),
|
||||
("IO.UDP.UDPSocket.close.impl.v1", udpSocket --> iof unit),
|
||||
("IO.UDP.serverSocket.impl.v1", text --> text --> iof udpListenSocket),
|
||||
("IO.UDP.ListenSocket.recvFrom.impl.v1", udpListenSocket --> iof (tuple [bytes, udpClientSockAddr])),
|
||||
("IO.UDP.ListenSocket.sendTo.impl.v1", udpListenSocket --> bytes --> udpClientSockAddr --> iof unit),
|
||||
("IO.UDP.ListenSocket.toText.impl.v1", udpListenSocket --> text),
|
||||
("IO.UDP.ListenSocket.close.impl.v1", udpListenSocket --> iof unit),
|
||||
("IO.UDP.UDPSocket.recv.impl.v1", udpSocket --> iof bytes),
|
||||
("IO.UDP.UDPSocket.send.impl.v1", udpSocket --> bytes --> iof unit),
|
||||
("IO.closeSocket.impl.v3", socket --> iof unit),
|
||||
("IO.socketPort.impl.v3", socket --> iof nat),
|
||||
("IO.socketAccept.impl.v3", socket --> iof socket),
|
||||
@ -1055,6 +1069,12 @@ handle = Type.fileHandle ()
|
||||
phandle = Type.processHandle ()
|
||||
unit = DD.unitType ()
|
||||
|
||||
|
||||
udpSocket, udpListenSocket, udpClientSockAddr :: Type
|
||||
udpSocket = Type.udpSocket ()
|
||||
udpListenSocket = Type.udpListenSocket ()
|
||||
udpClientSockAddr = Type.udpClientSockAddr ()
|
||||
|
||||
tls, tlsClientConfig, tlsServerConfig, tlsSignedCert, tlsPrivateKey, tlsVersion, tlsCipher :: Type
|
||||
tls = Type.ref () Type.tlsRef
|
||||
tlsClientConfig = Type.ref () Type.tlsClientConfigRef
|
||||
|
@ -356,6 +356,9 @@ builtinConstraintTree =
|
||||
flip Type.ref Type.filePathRef,
|
||||
Type.threadId,
|
||||
Type.socket,
|
||||
Type.udpSocket,
|
||||
Type.udpListenSocket,
|
||||
Type.udpClientSockAddr,
|
||||
Type.processHandle,
|
||||
Type.ibytearrayType,
|
||||
flip Type.ref Type.charClassRef,
|
||||
|
@ -52,6 +52,7 @@ import Data.IORef as SYS
|
||||
readIORef,
|
||||
writeIORef,
|
||||
)
|
||||
import Data.IP (IP)
|
||||
import Data.Map qualified as Map
|
||||
import Data.PEM (PEM, pemContent, pemParseLBS)
|
||||
import Data.Set (insert)
|
||||
@ -81,9 +82,23 @@ import Network.Simple.TCP as SYS
|
||||
import Network.Socket as SYS
|
||||
( Socket,
|
||||
accept,
|
||||
socketPort,
|
||||
socketPort, PortNumber,
|
||||
)
|
||||
import Network.TLS as TLS
|
||||
import Network.UDP as UDP
|
||||
( UDPSocket (..),
|
||||
ClientSockAddr,
|
||||
ListenSocket,
|
||||
clientSocket,
|
||||
close,
|
||||
recv,
|
||||
recvFrom,
|
||||
send,
|
||||
sendTo,
|
||||
serverSocket,
|
||||
stop,
|
||||
)
|
||||
|
||||
import Network.TLS.Extra.Cipher as Cipher
|
||||
import System.Clock (Clock (..), getTime, nsec, sec)
|
||||
import System.Directory as SYS
|
||||
@ -1544,6 +1559,22 @@ outIoFailBool stack1 stack2 stack3 extra fail result =
|
||||
)
|
||||
]
|
||||
|
||||
outIoFailTup :: forall v . (Var v) => v -> v -> v -> v -> v -> v -> v -> v -> ANormal v
|
||||
outIoFailTup stack1 stack2 stack3 stack4 stack5 extra fail result =
|
||||
TMatch result . MatchSum $
|
||||
mapFromList
|
||||
[ failureCase stack1 stack2 stack3 extra fail,
|
||||
( 1,
|
||||
([BX, BX],
|
||||
TAbss [stack1, stack2]
|
||||
. TLetD stack3 BX (TCon Ty.unitRef 0 [])
|
||||
. TLetD stack4 BX (TCon Ty.pairRef 0 [stack2, stack3])
|
||||
. TLetD stack5 BX (TCon Ty.pairRef 0 [stack1, stack4])
|
||||
$ right stack5
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
outIoFailG ::
|
||||
(Var v) =>
|
||||
v ->
|
||||
@ -1767,6 +1798,14 @@ boxToEFBox =
|
||||
where
|
||||
(arg, result, stack1, stack2, stack3, any, fail) = fresh
|
||||
|
||||
-- a -> Either Failure (b, c)
|
||||
boxToEFTup :: ForeignOp
|
||||
boxToEFTup =
|
||||
inBx arg result $
|
||||
outIoFailTup stack1 stack2 stack3 stack4 stack5 extra fail result
|
||||
where
|
||||
(arg, result, stack1, stack2, stack3, stack4, stack5, extra, fail) = fresh
|
||||
|
||||
-- a -> Either Failure (Maybe b)
|
||||
boxToEFMBox :: ForeignOp
|
||||
boxToEFMBox =
|
||||
@ -1858,6 +1897,14 @@ boxBoxToEF0 =
|
||||
where
|
||||
(arg1, arg2, result, stack1, stack2, stack3, fail, unit) = fresh
|
||||
|
||||
-- a -> b -> c -> Either Failure ()
|
||||
boxBoxBoxToEF0 :: ForeignOp
|
||||
boxBoxBoxToEF0 =
|
||||
inBxBxBx arg1 arg2 arg3 result $
|
||||
outIoFailUnit stack1 stack2 stack3 fail unit result
|
||||
where
|
||||
(arg1, arg2, arg3, result, stack1, stack2, stack3, fail, unit) = fresh
|
||||
|
||||
-- a -> Either Failure Nat
|
||||
boxToEFNat :: ForeignOp
|
||||
boxToEFNat =
|
||||
@ -2290,8 +2337,64 @@ mkForeignTlsE f = mkForeign $ \a -> fmap flatten (tryIO2 (tryIO1 (f a)))
|
||||
flatten (Right (Right (Left e))) = Left e
|
||||
flatten (Right (Right (Right a))) = Right a
|
||||
|
||||
declareUdpForeigns :: FDecl Symbol ()
|
||||
declareUdpForeigns = do
|
||||
declareForeign Tracked "IO.UDP.clientSocket.impl.v1" boxBoxToEFBox
|
||||
. mkForeignIOF
|
||||
$ \(host :: Util.Text.Text, port :: Util.Text.Text) ->
|
||||
let hostStr = Util.Text.toString host
|
||||
portStr = Util.Text.toString port
|
||||
in UDP.clientSocket hostStr portStr True
|
||||
|
||||
declareForeign Tracked "IO.UDP.UDPSocket.recv.impl.v1" boxToEFBox
|
||||
. mkForeignIOF
|
||||
$ \(sock :: UDPSocket) -> Bytes.fromArray <$> UDP.recv sock
|
||||
|
||||
declareForeign Tracked "IO.UDP.UDPSocket.send.impl.v1" boxBoxToEF0
|
||||
. mkForeignIOF
|
||||
$ \(sock :: UDPSocket, bytes :: Bytes.Bytes) ->
|
||||
UDP.send sock (Bytes.toArray bytes)
|
||||
|
||||
declareForeign Tracked "IO.UDP.UDPSocket.close.impl.v1" boxToEF0
|
||||
. mkForeignIOF
|
||||
$ \(sock :: UDPSocket) -> UDP.close sock
|
||||
|
||||
declareForeign Tracked "IO.UDP.ListenSocket.close.impl.v1" boxToEF0
|
||||
. mkForeignIOF
|
||||
$ \(sock :: ListenSocket) -> UDP.stop sock
|
||||
|
||||
declareForeign Tracked "IO.UDP.UDPSocket.toText.impl.v1" boxDirect
|
||||
. mkForeign
|
||||
$ \(sock :: UDPSocket) -> pure $ show sock
|
||||
|
||||
declareForeign Tracked "IO.UDP.serverSocket.impl.v1" boxBoxToEFBox
|
||||
. mkForeignIOF
|
||||
$ \(ip :: Util.Text.Text, port :: Util.Text.Text) ->
|
||||
let maybeIp = readMaybe $ Util.Text.toString ip :: Maybe IP
|
||||
maybePort = readMaybe $ Util.Text.toString port :: Maybe PortNumber
|
||||
in case (maybeIp, maybePort) of
|
||||
(Nothing, _) -> fail "Invalid IP Address"
|
||||
(_, Nothing) -> fail "Invalid Port Number"
|
||||
(Just ip, Just pt) -> UDP.serverSocket (ip, pt)
|
||||
|
||||
declareForeign Tracked "IO.UDP.ListenSocket.toText.impl.v1" boxDirect
|
||||
. mkForeign
|
||||
$ \(sock :: ListenSocket) -> pure $ show sock
|
||||
|
||||
declareForeign Tracked "IO.UDP.ListenSocket.recvFrom.impl.v1" boxToEFTup .
|
||||
mkForeignIOF $ fmap (first Bytes.fromArray) <$> UDP.recvFrom
|
||||
|
||||
declareForeign Tracked "IO.UDP.ClientSockAddr.toText.v1" boxDirect
|
||||
. mkForeign
|
||||
$ \(sock :: ClientSockAddr) -> pure $ show sock
|
||||
|
||||
declareForeign Tracked "IO.UDP.ListenSocket.sendTo.impl.v1" boxBoxBoxToEF0 .
|
||||
mkForeignIOF $ \(socket :: ListenSocket, bytes :: Bytes.Bytes, addr :: ClientSockAddr) ->
|
||||
UDP.sendTo socket (Bytes.toArray bytes) addr
|
||||
|
||||
declareForeigns :: FDecl Symbol ()
|
||||
declareForeigns = do
|
||||
declareUdpForeigns
|
||||
declareForeign Tracked "IO.openFile.impl.v3" boxIomrToEFBox $
|
||||
mkForeignIOF $ \(fnameText :: Util.Text.Text, n :: Int) ->
|
||||
let fname = Util.Text.toString fnameText
|
||||
|
@ -27,6 +27,7 @@ import Data.Primitive (ByteArray, MutableArray, MutableByteArray)
|
||||
import Data.Tagged (Tagged (..))
|
||||
import Data.X509 qualified as X509
|
||||
import Network.Socket (Socket)
|
||||
import Network.UDP (ListenSocket, UDPSocket, ClientSockAddr)
|
||||
import Network.TLS qualified as TLS (ClientParams, Context, ServerParams)
|
||||
import System.Clock (TimeSpec)
|
||||
import System.IO (Handle)
|
||||
@ -81,6 +82,10 @@ socketEq :: Socket -> Socket -> Bool
|
||||
socketEq l r = l == r
|
||||
{-# NOINLINE socketEq #-}
|
||||
|
||||
udpSocketEq :: UDPSocket -> UDPSocket -> Bool
|
||||
udpSocketEq l r = l == r
|
||||
{-# NOINLINE udpSocketEq #-}
|
||||
|
||||
refEq :: IORef () -> IORef () -> Bool
|
||||
refEq l r = l == r
|
||||
{-# NOINLINE refEq #-}
|
||||
@ -157,6 +162,7 @@ ref2eq r
|
||||
-- Ditto
|
||||
| r == Ty.tvarRef = Just $ promote tvarEq
|
||||
| r == Ty.socketRef = Just $ promote socketEq
|
||||
| r == Ty.udpSocketRef = Just $ promote udpSocketEq
|
||||
| r == Ty.refRef = Just $ promote refEq
|
||||
| r == Ty.threadIdRef = Just $ promote tidEq
|
||||
| r == Ty.marrayRef = Just $ promote marrEq
|
||||
@ -230,6 +236,12 @@ instance BuiltinForeign Referent where foreignRef = Tagged Ty.termLinkRef
|
||||
|
||||
instance BuiltinForeign Socket where foreignRef = Tagged Ty.socketRef
|
||||
|
||||
instance BuiltinForeign ListenSocket where foreignRef = Tagged Ty.udpListenSocketRef
|
||||
|
||||
instance BuiltinForeign ClientSockAddr where foreignRef = Tagged Ty.udpClientSockAddrRef
|
||||
|
||||
instance BuiltinForeign UDPSocket where foreignRef = Tagged Ty.udpSocketRef
|
||||
|
||||
instance BuiltinForeign ThreadId where foreignRef = Tagged Ty.threadIdRef
|
||||
|
||||
instance BuiltinForeign TLS.ClientParams where foreignRef = Tagged Ty.tlsClientConfigRef
|
||||
|
@ -26,6 +26,7 @@ import Data.Time.Clock.POSIX (POSIXTime)
|
||||
import Data.Word (Word16, Word32, Word64, Word8)
|
||||
import GHC.IO.Exception (IOErrorType (..), IOException (..))
|
||||
import Network.Socket (Socket)
|
||||
import Network.UDP (UDPSocket)
|
||||
import System.IO (BufferMode (..), Handle, IOMode, SeekMode)
|
||||
import Unison.Builtin.Decls qualified as Ty
|
||||
import Unison.Reference (Reference)
|
||||
@ -139,6 +140,10 @@ instance ForeignConvention Socket where
|
||||
readForeign = readForeignBuiltin
|
||||
writeForeign = writeForeignBuiltin
|
||||
|
||||
instance ForeignConvention UDPSocket where
|
||||
readForeign = readForeignBuiltin
|
||||
writeForeign = writeForeignBuiltin
|
||||
|
||||
instance ForeignConvention ThreadId where
|
||||
readForeign = readForeignBuiltin
|
||||
writeForeign = writeForeignBuiltin
|
||||
|
@ -268,6 +268,7 @@ library
|
||||
, http-client
|
||||
, http-media
|
||||
, http-types
|
||||
, iproute
|
||||
, lens
|
||||
, lucid
|
||||
, megaparsec
|
||||
@ -281,6 +282,7 @@ library
|
||||
, natural-transformation
|
||||
, network
|
||||
, network-simple
|
||||
, network-udp
|
||||
, network-uri
|
||||
, nonempty-containers
|
||||
, open-browser
|
||||
@ -462,6 +464,7 @@ test-suite parser-typechecker-tests
|
||||
, http-client
|
||||
, http-media
|
||||
, http-types
|
||||
, iproute
|
||||
, lens
|
||||
, lucid
|
||||
, megaparsec
|
||||
@ -475,6 +478,7 @@ test-suite parser-typechecker-tests
|
||||
, natural-transformation
|
||||
, network
|
||||
, network-simple
|
||||
, network-udp
|
||||
, network-uri
|
||||
, nonempty-containers
|
||||
, open-browser
|
||||
|
@ -30,6 +30,7 @@
|
||||
unison/data-info
|
||||
unison/chunked-seq
|
||||
unison/primops
|
||||
unison/builtin
|
||||
unison/primops-generated
|
||||
unison/builtin-generated)
|
||||
|
||||
|
@ -47,6 +47,10 @@
|
||||
builtin-tls.signedcert:typelink
|
||||
builtin-tls.version:typelink
|
||||
|
||||
builtin-udpsocket:typelink
|
||||
builtin-listensocket:typelink
|
||||
builtin-clientsockaddr:typelink
|
||||
|
||||
bytevector
|
||||
bytes
|
||||
control
|
||||
|
4
scheme-libs/racket/unison/builtin.rkt
Normal file
4
scheme-libs/racket/unison/builtin.rkt
Normal file
@ -0,0 +1,4 @@
|
||||
#lang racket/base
|
||||
(require unison/udp)
|
||||
|
||||
(provide (all-from-out))
|
@ -80,6 +80,9 @@
|
||||
builtin-timespec:typelink
|
||||
builtin-threadid:typelink
|
||||
builtin-value:typelink
|
||||
builtin-udpsocket:typelink
|
||||
builtin-listensocket:typelink
|
||||
builtin-clientsockaddr:typelink
|
||||
|
||||
builtin-crypto.hashalgorithm:typelink
|
||||
builtin-char.class:typelink
|
||||
@ -440,6 +443,9 @@
|
||||
(define builtin-timespec:typelink (unison-typelink-builtin "TimeSpec"))
|
||||
(define builtin-threadid:typelink (unison-typelink-builtin "ThreadId"))
|
||||
(define builtin-value:typelink (unison-typelink-builtin "Value"))
|
||||
(define builtin-udpsocket:typelink (unison-typelink-builtin "UDPSocket"))
|
||||
(define builtin-listensocket:typelink (unison-typelink-builtin "ListenSocket"))
|
||||
(define builtin-clientsockaddr:typelink (unison-typelink-builtin "ClientSockAddr"))
|
||||
|
||||
(define builtin-crypto.hashalgorithm:typelink
|
||||
(unison-typelink-builtin "crypto.HashAlgorithm"))
|
||||
|
31
scheme-libs/racket/unison/network-utils.rkt
Normal file
31
scheme-libs/racket/unison/network-utils.rkt
Normal file
@ -0,0 +1,31 @@
|
||||
#lang racket/base
|
||||
(require racket/exn
|
||||
unison/data ; exception
|
||||
unison/data-info ; ref-*
|
||||
unison/chunked-seq
|
||||
unison/core) ; exception->string, chunked-string
|
||||
|
||||
(provide handle-errors)
|
||||
|
||||
(define (handle-errors fn)
|
||||
(with-handlers
|
||||
[[exn:fail:network?
|
||||
(lambda (e)
|
||||
(exception
|
||||
ref-iofailure:typelink
|
||||
(exception->string e)
|
||||
ref-unit-unit))]
|
||||
[exn:fail:contract?
|
||||
(lambda (e)
|
||||
(exception
|
||||
ref-miscfailure:typelink
|
||||
(exception->string e)
|
||||
ref-unit-unit))]
|
||||
[(lambda _ #t)
|
||||
(lambda (e)
|
||||
(exception
|
||||
ref-miscfailure:typelink
|
||||
(string->chunked-string
|
||||
(format "Unknown exception ~a" (exn->string e)))
|
||||
ref-unit-unit))]]
|
||||
(fn)))
|
@ -186,6 +186,29 @@
|
||||
builtin-TypeLink.toReference
|
||||
builtin-TypeLink.toReference:termlink
|
||||
|
||||
builtin-IO.UDP.clientSocket.impl.v1
|
||||
builtin-IO.UDP.clientSocket.impl.v1:termlink
|
||||
builtin-IO.UDP.UDPSocket.recv.impl.v1
|
||||
builtin-IO.UDP.UDPSocket.recv.impl.v1:termlink
|
||||
builtin-IO.UDP.UDPSocket.send.impl.v1
|
||||
builtin-IO.UDP.UDPSocket.send.impl.v1:termlink
|
||||
builtin-IO.UDP.UDPSocket.close.impl.v1
|
||||
builtin-IO.UDP.UDPSocket.close.impl.v1:termlink
|
||||
builtin-IO.UDP.ListenSocket.close.impl.v1
|
||||
builtin-IO.UDP.ListenSocket.close.impl.v1:termlink
|
||||
builtin-IO.UDP.UDPSocket.toText.impl.v1
|
||||
builtin-IO.UDP.UDPSocket.toText.impl.v1:termlink
|
||||
builtin-IO.UDP.serverSocket.impl.v1
|
||||
builtin-IO.UDP.serverSocket.impl.v1:termlink
|
||||
builtin-IO.UDP.ListenSocket.toText.impl.v1
|
||||
builtin-IO.UDP.ListenSocket.toText.impl.v1:termlink
|
||||
builtin-IO.UDP.ListenSocket.recvFrom.impl.v1
|
||||
builtin-IO.UDP.ListenSocket.recvFrom.impl.v1:termlink
|
||||
builtin-IO.UDP.ClientSockAddr.toText.v1
|
||||
builtin-IO.UDP.ClientSockAddr.toText.v1:termlink
|
||||
builtin-IO.UDP.ListenSocket.sendTo.impl.v1
|
||||
builtin-IO.UDP.ListenSocket.sendTo.impl.v1:termlink
|
||||
|
||||
unison-FOp-internal.dataTag
|
||||
unison-FOp-Char.toText
|
||||
; unison-FOp-Code.dependencies
|
||||
@ -645,6 +668,7 @@
|
||||
(unison murmurhash)
|
||||
(unison tls)
|
||||
(unison tcp)
|
||||
(unison udp)
|
||||
(unison gzip)
|
||||
(unison zlib)
|
||||
(unison concurrent)
|
||||
|
@ -103,6 +103,17 @@
|
||||
(sandbox-builtin "IO.getFileSize.impl.v3")
|
||||
(sandbox-builtin "IO.serverSocket.impl.v3")
|
||||
(sandbox-builtin "Socket.toText")
|
||||
(sandbox-builtin "UDP.clientSocket.impl.v1")
|
||||
(sandbox-builtin "UDP.serverSocket.impl.v1")
|
||||
(sandbox-builtin "UDP.UDPSocket.close.impl.v1")
|
||||
(sandbox-builtin "UDP.UDPSocket.recv.impl.v1")
|
||||
(sandbox-builtin "UDP.UDPSocket.send.impl.v1")
|
||||
(sandbox-builtin "UDP.ListenSocket.close.impl.v1")
|
||||
(sandbox-builtin "UDP.UDPSocket.toText.impl.v1")
|
||||
(sandbox-builtin "UDP.ListenSocket.toText.impl.v1")
|
||||
(sandbox-builtin "UDP.ListenSocket.recvFrom.impl.v1")
|
||||
(sandbox-builtin "UDP.ClientSockAddr.toText.v1")
|
||||
(sandbox-builtin "UDP.ListenSocket.sendTo.impl.v1")
|
||||
(sandbox-builtin "Handle.toText")
|
||||
(sandbox-builtin "ThreadId.toText")
|
||||
(sandbox-builtin "IO.socketPort.impl.v3")
|
||||
|
@ -6,6 +6,7 @@
|
||||
unison/data
|
||||
unison/data-info
|
||||
unison/chunked-seq
|
||||
unison/network-utils
|
||||
unison/core)
|
||||
|
||||
(provide
|
||||
@ -25,29 +26,6 @@
|
||||
|
||||
(struct socket-pair (input output))
|
||||
|
||||
(define (handle-errors fn)
|
||||
(with-handlers
|
||||
[[exn:fail:network?
|
||||
(lambda (e)
|
||||
(exception
|
||||
ref-iofailure:typelink
|
||||
(exception->string e)
|
||||
ref-unit-unit))]
|
||||
[exn:fail:contract?
|
||||
(lambda (e)
|
||||
(exception
|
||||
ref-miscfailure:typelink
|
||||
(exception->string e)
|
||||
ref-unit-unit))]
|
||||
[(lambda _ #t)
|
||||
(lambda (e)
|
||||
(exception
|
||||
ref-miscfailure:typelink
|
||||
(chunked-string->string
|
||||
(format "Unknown exception ~a" (exn->string e)))
|
||||
ref-unit-unit))]]
|
||||
(fn)))
|
||||
|
||||
(define (closeSocket.impl.v3 socket)
|
||||
(handle-errors
|
||||
(lambda ()
|
||||
|
179
scheme-libs/racket/unison/udp.rkt
Normal file
179
scheme-libs/racket/unison/udp.rkt
Normal file
@ -0,0 +1,179 @@
|
||||
; UDP primitives!
|
||||
#lang racket/base
|
||||
(require racket/udp
|
||||
racket/format
|
||||
(only-in unison/boot define-unison)
|
||||
unison/data
|
||||
unison/data-info
|
||||
unison/chunked-seq
|
||||
(only-in unison/boot sum-case)
|
||||
unison/network-utils
|
||||
unison/core)
|
||||
|
||||
(provide
|
||||
(prefix-out
|
||||
builtin-IO.UDP.
|
||||
(combine-out
|
||||
clientSocket.impl.v1
|
||||
clientSocket.impl.v1:termlink
|
||||
UDPSocket.recv.impl.v1
|
||||
UDPSocket.recv.impl.v1:termlink
|
||||
UDPSocket.send.impl.v1
|
||||
UDPSocket.send.impl.v1:termlink
|
||||
UDPSocket.close.impl.v1
|
||||
UDPSocket.close.impl.v1:termlink
|
||||
ListenSocket.close.impl.v1
|
||||
ListenSocket.close.impl.v1:termlink
|
||||
UDPSocket.toText.impl.v1
|
||||
UDPSocket.toText.impl.v1:termlink
|
||||
serverSocket.impl.v1
|
||||
serverSocket.impl.v1:termlink
|
||||
ListenSocket.toText.impl.v1
|
||||
ListenSocket.toText.impl.v1:termlink
|
||||
ListenSocket.recvFrom.impl.v1
|
||||
ListenSocket.recvFrom.impl.v1:termlink
|
||||
ClientSockAddr.toText.v1
|
||||
ClientSockAddr.toText.v1:termlink
|
||||
ListenSocket.sendTo.impl.v1
|
||||
ListenSocket.sendTo.impl.v1:termlink)))
|
||||
|
||||
|
||||
(struct client-sock-addr (host port))
|
||||
|
||||
; Haskell's Network.UDP choice of buffer size is 2048, so mirror that here
|
||||
(define buffer-size 2048)
|
||||
|
||||
(define ; a -> Either Failure a
|
||||
(wrap-in-either a)
|
||||
(sum-case a
|
||||
(0 (type msg meta)
|
||||
(ref-either-left (ref-failure-failure type msg (unison-any-any meta))))
|
||||
(1 (data)
|
||||
(ref-either-right data))))
|
||||
|
||||
(define
|
||||
(format-socket socket)
|
||||
(let*-values ([(local-hn local-port remote-hn remote-port) (udp-addresses socket #t)]
|
||||
[(rv) (~a "<socket local=" local-hn ":" local-port " remote=" remote-hn ":" remote-port ">")])
|
||||
(string->chunked-string rv)))
|
||||
|
||||
(define (close-socket socket)
|
||||
(let ([rv (handle-errors (lambda() (begin
|
||||
(udp-close socket)
|
||||
(right ref-unit-unit))))])
|
||||
(wrap-in-either rv)))
|
||||
|
||||
;; define termlink builtins
|
||||
(define clientSocket.impl.v1:termlink
|
||||
(unison-termlink-builtin "IO.UDP.clientSocket.impl.v1"))
|
||||
(define UDPSocket.recv.impl.v1:termlink
|
||||
(unison-termlink-builtin "IO.UDP.UDPSocket.recv.impl.v1"))
|
||||
(define UDPSocket.send.impl.v1:termlink
|
||||
(unison-termlink-builtin "IO.UDP.UDPSocket.send.impl.v1"))
|
||||
(define UDPSocket.close.impl.v1:termlink
|
||||
(unison-termlink-builtin "IO.UDP.UDPSocket.close.impl.v1"))
|
||||
(define ListenSocket.close.impl.v1:termlink
|
||||
(unison-termlink-builtin "IO.UDP.ListenSocket.close.impl.v1"))
|
||||
(define UDPSocket.toText.impl.v1:termlink
|
||||
(unison-termlink-builtin "IO.UDP.UDPSocket.toText.impl.v1"))
|
||||
(define serverSocket.impl.v1:termlink
|
||||
(unison-termlink-builtin "IO.UDP.serverSocket.impl.v1"))
|
||||
(define ListenSocket.toText.impl.v1:termlink
|
||||
(unison-termlink-builtin "IO.UDP.ListenSocket.toText.impl.v1"))
|
||||
(define ListenSocket.recvFrom.impl.v1:termlink
|
||||
(unison-termlink-builtin "IO.UDP.ListenSocket.recvFrom.impl.v1"))
|
||||
(define ClientSockAddr.toText.v1:termlink
|
||||
(unison-termlink-builtin "IO.UDP.ClientSockAddr.toText.v1"))
|
||||
(define ListenSocket.sendTo.impl.v1:termlink
|
||||
(unison-termlink-builtin "IO.UDP.ListenSocket.sendTo.impl.v1"))
|
||||
|
||||
;; define builtins
|
||||
|
||||
(define-unison
|
||||
(UDPSocket.recv.impl.v1 socket) ; socket -> Either Failure Bytes
|
||||
(let
|
||||
([rv (handle-errors (lambda()
|
||||
(let*-values
|
||||
([(buffer) (make-bytes buffer-size)]
|
||||
[(len a b) (udp-receive! socket buffer)])
|
||||
(right (bytes->chunked-bytes (subbytes buffer 0 len))))))])
|
||||
(wrap-in-either rv)))
|
||||
|
||||
(define-unison
|
||||
(ListenSocket.close.impl.v1 socket) ; socket -> Either Failure ()
|
||||
(close-socket socket))
|
||||
|
||||
(define-unison
|
||||
(serverSocket.impl.v1 ip port) ; string string -> Either Failure socket
|
||||
(let
|
||||
([result (handle-errors (lambda()
|
||||
(let* ([iip (chunked-string->string ip)]
|
||||
[pport (string->number (chunked-string->string port))]
|
||||
[sock (udp-open-socket iip pport)])
|
||||
(begin
|
||||
(udp-bind! sock iip pport)
|
||||
(right sock)))))])
|
||||
(wrap-in-either result)))
|
||||
|
||||
(define-unison
|
||||
(ListenSocket.recvFrom.impl.v1 socket) ; socket -> Either Failure (Bytes, ClientSockAddr)
|
||||
(let ([result (handle-errors (lambda()
|
||||
(if (not (udp? socket))
|
||||
(raise-argument-error 'socket "a UDP socket" socket)
|
||||
(let*-values
|
||||
([(buffer) (make-bytes buffer-size)]
|
||||
[(len host port) (udp-receive! socket buffer)]
|
||||
[(csa) (client-sock-addr host port)]
|
||||
[(bs) (subbytes buffer 0 len)]
|
||||
[(chunked) (bytes->chunked-bytes bs)])
|
||||
(right (ref-tuple-pair chunked (ref-tuple-pair csa ref-unit-unit)))))))])
|
||||
(wrap-in-either result)))
|
||||
|
||||
(define-unison
|
||||
(UDPSocket.send.impl.v1 socket data) ; socket -> Bytes -> Either Failure ()
|
||||
(let
|
||||
([result (handle-errors (lambda () (begin
|
||||
(udp-send socket (chunked-bytes->bytes data))
|
||||
(right ref-unit-unit))))])
|
||||
(wrap-in-either result)))
|
||||
|
||||
(define-unison
|
||||
(ListenSocket.sendTo.impl.v1 sock bytes addr) ; socket -> Bytes -> ClientSockAddr -> Either Failure ()
|
||||
(let
|
||||
([result (handle-errors (lambda()
|
||||
(let* ([host (client-sock-addr-host addr)]
|
||||
[port (client-sock-addr-port addr)]
|
||||
[bytes (chunked-bytes->bytes bytes)])
|
||||
(begin
|
||||
(udp-send-to sock host port bytes)
|
||||
(right ref-unit-unit)))))])
|
||||
(wrap-in-either result)))
|
||||
|
||||
(define-unison
|
||||
(UDPSocket.toText.impl.v1 socket) ; socket -> string
|
||||
(format-socket socket))
|
||||
|
||||
(define-unison
|
||||
(ClientSockAddr.toText.v1 addr) ; ClientSocketAddr -> string
|
||||
(string->chunked-string (format "<client-sock-addr ~a ~a>" (client-sock-addr-host addr) (client-sock-addr-port addr))))
|
||||
|
||||
(define-unison
|
||||
(ListenSocket.toText.impl.v1 socket) ; socket -> string
|
||||
(format-socket socket))
|
||||
|
||||
(define-unison
|
||||
(UDPSocket.close.impl.v1 socket) ; socket -> Either Failure ()
|
||||
(let
|
||||
([rv (handle-errors (lambda() (begin
|
||||
(udp-close socket)
|
||||
(right ref-unit-unit))))])
|
||||
(wrap-in-either rv)))
|
||||
|
||||
(define-unison
|
||||
(clientSocket.impl.v1 host port) ; string string -> Either Failure socket
|
||||
(let ([rv (handle-errors (lambda() (let* ([pport (string->number (chunked-string->string port))]
|
||||
[hhost (chunked-string->string host)]
|
||||
[sock (udp-open-socket hhost pport)]
|
||||
[_ (udp-bind! sock #f 0)]
|
||||
[res (udp-connect! sock hhost pport)]) (right sock))))])
|
||||
(wrap-in-either rv)))
|
@ -65,6 +65,7 @@ extra-deps:
|
||||
- lsp-2.2.0.0@sha256:82fbf4b69d94d8d22543be71f89986b3e90050032d671fb3de3f8253ea1e5b6f,3550
|
||||
- lsp-types-2.0.2.0@sha256:a9a51c3cea0726d91fe63fa0670935ee720f7b31bc3f3b33b2483fc538152677,29421
|
||||
- row-types-1.0.1.2@sha256:4d4c7cb95d06a32b28ba977852d52a26b4c1f695ef083a6fd874ab6d79933b64,3071
|
||||
- network-udp-0.0.0
|
||||
|
||||
ghc-options:
|
||||
# All packages
|
||||
|
@ -82,6 +82,13 @@ packages:
|
||||
size: 1060
|
||||
original:
|
||||
hackage: row-types-1.0.1.2@sha256:4d4c7cb95d06a32b28ba977852d52a26b4c1f695ef083a6fd874ab6d79933b64,3071
|
||||
- completed:
|
||||
hackage: network-udp-0.0.0@sha256:408d2d4fa1a25e49e95752ee124cca641993404bb133ae10fb81daef22d876ae,1075
|
||||
pantry-tree:
|
||||
sha256: ee19a66c9d420861c5cc1dfad3210e2a53cdc6088ff3dd90b44f7961f5caebee
|
||||
size: 284
|
||||
original:
|
||||
hackage: network-udp-0.0.0
|
||||
snapshots:
|
||||
- completed:
|
||||
sha256: 5a59b2a405b3aba3c00188453be172b85893cab8ebc352b1ef58b0eae5d248a2
|
||||
|
@ -50,6 +50,7 @@ dependencies:
|
||||
- mtl
|
||||
- network-uri
|
||||
- network-simple
|
||||
- network-udp
|
||||
- network
|
||||
- co-log-core
|
||||
- uri-encode
|
||||
|
@ -215,6 +215,7 @@ library
|
||||
, mtl
|
||||
, network
|
||||
, network-simple
|
||||
, network-udp
|
||||
, network-uri
|
||||
, nonempty-containers
|
||||
, open-browser
|
||||
@ -353,6 +354,7 @@ executable transcripts
|
||||
, mtl
|
||||
, network
|
||||
, network-simple
|
||||
, network-udp
|
||||
, network-uri
|
||||
, nonempty-containers
|
||||
, open-browser
|
||||
@ -499,6 +501,7 @@ test-suite cli-tests
|
||||
, mtl
|
||||
, network
|
||||
, network-simple
|
||||
, network-udp
|
||||
, network-uri
|
||||
, nonempty-containers
|
||||
, open-browser
|
||||
|
@ -15,6 +15,19 @@ import Unison.LabeledDependency qualified as LD
|
||||
import Unison.Name qualified as Name
|
||||
import Unison.Names.ResolutionResult qualified as Names
|
||||
import Unison.Prelude
|
||||
( Const (Const, getConst),
|
||||
Generic,
|
||||
Generic1,
|
||||
Identity (runIdentity),
|
||||
Map,
|
||||
Set,
|
||||
Text,
|
||||
foldl',
|
||||
join,
|
||||
sortOn,
|
||||
($>),
|
||||
(<&>),
|
||||
)
|
||||
import Unison.Reference (TypeReference)
|
||||
import Unison.Reference qualified as Reference
|
||||
import Unison.Settings qualified as Settings
|
||||
@ -269,6 +282,11 @@ filePathRef = Reference.Builtin "FilePath"
|
||||
threadIdRef = Reference.Builtin "ThreadId"
|
||||
socketRef = Reference.Builtin "Socket"
|
||||
|
||||
udpSocketRef, udpListenSocketRef, udpClientSockAddrRef :: TypeReference
|
||||
udpSocketRef = Reference.Builtin "UDPSocket"
|
||||
udpListenSocketRef = Reference.Builtin "ListenSocket"
|
||||
udpClientSockAddrRef = Reference.Builtin "ClientSockAddr"
|
||||
|
||||
processHandleRef :: TypeReference
|
||||
processHandleRef = Reference.Builtin "ProcessHandle"
|
||||
|
||||
@ -388,6 +406,15 @@ mbytearrayType a = ref a mbytearrayRef
|
||||
socket :: (Ord v) => a -> Type v a
|
||||
socket a = ref a socketRef
|
||||
|
||||
udpSocket :: (Ord v) => a -> Type v a
|
||||
udpSocket a = ref a udpSocketRef
|
||||
|
||||
udpListenSocket :: (Ord v) => a -> Type v a
|
||||
udpListenSocket a = ref a udpListenSocketRef
|
||||
|
||||
udpClientSockAddr :: (Ord v) => a -> Type v a
|
||||
udpClientSockAddr a = ref a udpClientSockAddrRef
|
||||
|
||||
list :: (Ord v) => a -> Type v a
|
||||
list a = ref a listRef
|
||||
|
||||
|
66
unison-src/builtin-tests/udp-tests.u
Normal file
66
unison-src/builtin-tests/udp-tests.u
Normal file
@ -0,0 +1,66 @@
|
||||
UDP.client' h p = Either.toException (##IO.UDP.clientSocket.impl.v1 h p)
|
||||
UDP.server' i p = Either.toException (##IO.UDP.serverSocket.impl.v1 i p)
|
||||
closeClient' = ##IO.UDP.UDPSocket.close.impl.v1 >> Either.toException
|
||||
send' s b = Either.toException (##IO.UDP.UDPSocket.send.impl.v1 s b)
|
||||
closeServer' = ##IO.UDP.ListenSocket.close.impl.v1 >> Either.toException
|
||||
sendTo' s b a = Either.toException (##IO.UDP.ListenSocket.sendTo.impl.v1 s b a)
|
||||
recvFrom' = ##IO.UDP.ListenSocket.recvFrom.impl.v1 >> Either.toException
|
||||
recv' = ##IO.UDP.UDPSocket.recv.impl.v1 >> Either.toException
|
||||
|
||||
badPort = "what"
|
||||
badIp = "what"
|
||||
goodPort = "8000"
|
||||
goodIp = "127.0.0.1"
|
||||
|
||||
shouldFail fn =
|
||||
result = catchAll fn
|
||||
isLeft result
|
||||
|
||||
udp.tests = do
|
||||
check "client rejects invalid port" do shouldFail do UDP.client' goodIp badPort
|
||||
check "server rejects invalid port" do shouldFail do UDP.server' goodIp badPort
|
||||
check "server rejects invalid IP address" do shouldFail do UDP.server' badIp goodPort
|
||||
check "client: no send after close" do shouldFail do
|
||||
socket = UDP.client' goodIp goodPort
|
||||
closeClient' socket
|
||||
send' socket (toUtf8 "hello") -- should fail here
|
||||
check "server no send after close" do shouldFail do
|
||||
ssocket = UDP.server' goodIp goodPort
|
||||
csocket = UDP.client' goodIp goodPort
|
||||
send' csocket (toUtf8 "hello")
|
||||
(_, clientSockAddr) = recvFrom' ssocket
|
||||
closeServer' ssocket
|
||||
sendTo' ssocket (toUtf8 "hello") clientSockAddr -- should fail here
|
||||
check "no receive after close" do shouldFail do
|
||||
socket = UDP.client' goodIp goodPort
|
||||
closeClient' socket
|
||||
recv' socket
|
||||
!testServerAndClient
|
||||
|
||||
testServerAndClient = do
|
||||
fromServerMsg = "from server"
|
||||
fromClientMsg = "from client"
|
||||
setup = catchAll do
|
||||
UDP.server' goodIp goodPort
|
||||
match setup with
|
||||
Left e ->
|
||||
Tests.fail "Unable to open a socket for UDP server" (Debug.evalToText e)
|
||||
Right ssocket ->
|
||||
serve = do
|
||||
(data, sockAddr) = recvFrom' ssocket
|
||||
sendTo' ssocket (toUtf8 fromServerMsg) sockAddr
|
||||
closeServer' ssocket
|
||||
fromUtf8 data
|
||||
|
||||
serveResult = !Promise.new
|
||||
_ = fork do Promise.write serveResult (catchAll serve)
|
||||
|
||||
data = catchAll do
|
||||
csocket = UDP.client' goodIp goodPort
|
||||
send' csocket (toUtf8 fromClientMsg)
|
||||
d = recv' csocket
|
||||
closeClient' csocket
|
||||
fromUtf8 d
|
||||
|
||||
checkEqual "Server received data" (Promise.read serveResult) (Right fromClientMsg)
|
||||
checkEqual "Client received data" data (Right fromServerMsg)
|
File diff suppressed because it is too large
Load Diff
@ -178,21 +178,21 @@ Stream.collect s =
|
||||
handle !s with Stream.collect.handler
|
||||
|
||||
|
||||
-- An ability that facilitates creating temoporary directories that can be
|
||||
-- An ability that facilitates creating temoporary directories that can be
|
||||
-- automatically cleaned up
|
||||
structural ability TempDirs where
|
||||
newTempDir: Text -> Text
|
||||
removeDir: Text -> ()
|
||||
|
||||
-- A handler for TempDirs which cleans up temporary directories
|
||||
-- This will be useful for IO tests which need to interact with
|
||||
-- This will be useful for IO tests which need to interact with
|
||||
-- the filesystem
|
||||
|
||||
autoCleaned.handler: '{io2.IO} (Request {TempDirs} r -> r)
|
||||
autoCleaned.handler _ =
|
||||
remover : [Text] -> {io2.IO} ()
|
||||
remover = cases
|
||||
a +: as -> match removeDirectory.impl a with
|
||||
a +: as -> match removeDirectory.impl a with
|
||||
Left (Failure _ e _) -> watch e ()
|
||||
_ -> ()
|
||||
remover as
|
||||
@ -277,12 +277,12 @@ putBytes = compose2 reraise putBytes.impl
|
||||
getLine = compose reraise getLine.impl
|
||||
systemTime = compose reraise systemTime.impl
|
||||
decodeCert = compose reraise decodeCert.impl
|
||||
serverSocket = compose2 reraise serverSocket.impl
|
||||
serverSocket = compose2 reraise IO.serverSocket.impl
|
||||
listen = compose reraise listen.impl
|
||||
handshake = compose reraise handshake.impl
|
||||
send = compose2 reraise send.impl
|
||||
handshake = compose reraise handshake.impl
|
||||
send = compose2 reraise Tls.send.impl
|
||||
closeSocket = compose reraise closeSocket.impl
|
||||
clientSocket = compose2 reraise clientSocket.impl
|
||||
clientSocket = compose2 reraise IO.clientSocket.impl
|
||||
receive = compose reraise receive.impl
|
||||
terminate = compose reraise terminate.impl
|
||||
newServer = compose2 reraise newServer.impl
|
||||
@ -451,4 +451,3 @@ saveTestCase name ver f i =
|
||||
saveSelfContained (f, i) sfile
|
||||
writeFile ofile (toUtf8 output)
|
||||
writeFile hfile (Bytes.toBase32 (crypto.hash Sha3_512 (f, i)))
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
```unison:hide
|
||||
serverSocket = compose2 reraise serverSocket.impl
|
||||
serverSocket = compose2 reraise IO.serverSocket.impl
|
||||
socketPort = compose reraise socketPort.impl
|
||||
listen = compose reraise listen.impl
|
||||
closeSocket = compose reraise closeSocket.impl
|
||||
clientSocket = compose2 reraise clientSocket.impl
|
||||
clientSocket = compose2 reraise IO.clientSocket.impl
|
||||
socketSend = compose2 reraise socketSend.impl
|
||||
socketReceive = compose2 reraise socketReceive.impl
|
||||
socketAccept = compose reraise socketAccept.impl
|
||||
@ -36,11 +36,11 @@ stored in `/etc/services` and queried with the `getent` tool:
|
||||
# map number to name
|
||||
$ getent services 22
|
||||
ssh 22/tcp
|
||||
|
||||
|
||||
# map name to number
|
||||
$ getent services finger
|
||||
finger 79/tcp
|
||||
|
||||
|
||||
# get a list of all known names
|
||||
$ getent services | head
|
||||
tcpmux 1/tcp
|
||||
@ -58,35 +58,35 @@ Below shows different examples of how we might specify the server coordinates.
|
||||
|
||||
``` unison
|
||||
testExplicitHost : '{io2.IO} [Result]
|
||||
testExplicitHost _ =
|
||||
testExplicitHost _ =
|
||||
test = 'let
|
||||
sock = serverSocket (Some "127.0.0.1") "1028"
|
||||
emit (Ok "successfully created socket")
|
||||
port = socketPort sock
|
||||
putBytes (stdHandle StdOut) (toUtf8 (toText port))
|
||||
expectU "should have bound to port 1028" 1028 port
|
||||
expectU "should have bound to port 1028" 1028 port
|
||||
|
||||
runTest test
|
||||
|
||||
testDefaultHost : '{io2.IO} [Result]
|
||||
testDefaultHost _ =
|
||||
testDefaultHost _ =
|
||||
test = 'let
|
||||
sock = serverSocket None "1028"
|
||||
emit (Ok "successfully created socket")
|
||||
port = socketPort sock
|
||||
putBytes (stdHandle StdOut) (toUtf8 (toText port))
|
||||
expectU "should have bound to port 1028" 1028 port
|
||||
expectU "should have bound to port 1028" 1028 port
|
||||
|
||||
runTest test
|
||||
|
||||
testDefaultPort : '{io2.IO} [Result]
|
||||
testDefaultPort _ =
|
||||
testDefaultPort _ =
|
||||
test = 'let
|
||||
sock = serverSocket None "0"
|
||||
emit (Ok "successfully created socket")
|
||||
port = socketPort sock
|
||||
putBytes (stdHandle StdOut) (toUtf8 (toText port))
|
||||
|
||||
|
||||
check "port should be > 1024" (1024 < port)
|
||||
check "port should be < 65536" (65536 > port)
|
||||
|
||||
@ -113,7 +113,7 @@ serverThread portVar toSend = 'let
|
||||
socketSend sock' (toUtf8 toSend)
|
||||
closeSocket sock'
|
||||
|
||||
match (toEither go) with
|
||||
match (toEither go) with
|
||||
Left (Failure _ t _) -> watch t ()
|
||||
_ -> ()
|
||||
|
||||
@ -130,24 +130,24 @@ clientThread portVar resultVar = 'let
|
||||
_ -> ()
|
||||
|
||||
testTcpConnect : '{io2.IO}[Result]
|
||||
testTcpConnect = 'let
|
||||
testTcpConnect = 'let
|
||||
test = 'let
|
||||
portVar = !MVar.newEmpty
|
||||
resultVar = !MVar.newEmpty
|
||||
|
||||
|
||||
toSend = "12345"
|
||||
|
||||
void (forkComp (serverThread portVar toSend))
|
||||
void (forkComp (clientThread portVar resultVar))
|
||||
|
||||
|
||||
received = take resultVar
|
||||
|
||||
expectU "should have reaped what we've sown" toSend received
|
||||
|
||||
|
||||
runTest test
|
||||
|
||||
|
||||
```
|
||||
```ucm
|
||||
```ucm
|
||||
|
||||
.> add
|
||||
.> io.test testTcpConnect
|
||||
|
@ -1,9 +1,9 @@
|
||||
```unison
|
||||
serverSocket = compose2 reraise serverSocket.impl
|
||||
serverSocket = compose2 reraise IO.serverSocket.impl
|
||||
socketPort = compose reraise socketPort.impl
|
||||
listen = compose reraise listen.impl
|
||||
closeSocket = compose reraise closeSocket.impl
|
||||
clientSocket = compose2 reraise clientSocket.impl
|
||||
clientSocket = compose2 reraise IO.clientSocket.impl
|
||||
socketSend = compose2 reraise socketSend.impl
|
||||
socketReceive = compose2 reraise socketReceive.impl
|
||||
socketAccept = compose reraise socketAccept.impl
|
||||
@ -34,11 +34,11 @@ stored in `/etc/services` and queried with the `getent` tool:
|
||||
# map number to name
|
||||
$ getent services 22
|
||||
ssh 22/tcp
|
||||
|
||||
|
||||
# map name to number
|
||||
$ getent services finger
|
||||
finger 79/tcp
|
||||
|
||||
|
||||
# get a list of all known names
|
||||
$ getent services | head
|
||||
tcpmux 1/tcp
|
||||
@ -56,35 +56,35 @@ Below shows different examples of how we might specify the server coordinates.
|
||||
|
||||
```unison
|
||||
testExplicitHost : '{io2.IO} [Result]
|
||||
testExplicitHost _ =
|
||||
testExplicitHost _ =
|
||||
test = 'let
|
||||
sock = serverSocket (Some "127.0.0.1") "1028"
|
||||
emit (Ok "successfully created socket")
|
||||
port = socketPort sock
|
||||
putBytes (stdHandle StdOut) (toUtf8 (toText port))
|
||||
expectU "should have bound to port 1028" 1028 port
|
||||
expectU "should have bound to port 1028" 1028 port
|
||||
|
||||
runTest test
|
||||
|
||||
testDefaultHost : '{io2.IO} [Result]
|
||||
testDefaultHost _ =
|
||||
testDefaultHost _ =
|
||||
test = 'let
|
||||
sock = serverSocket None "1028"
|
||||
emit (Ok "successfully created socket")
|
||||
port = socketPort sock
|
||||
putBytes (stdHandle StdOut) (toUtf8 (toText port))
|
||||
expectU "should have bound to port 1028" 1028 port
|
||||
expectU "should have bound to port 1028" 1028 port
|
||||
|
||||
runTest test
|
||||
|
||||
testDefaultPort : '{io2.IO} [Result]
|
||||
testDefaultPort _ =
|
||||
testDefaultPort _ =
|
||||
test = 'let
|
||||
sock = serverSocket None "0"
|
||||
emit (Ok "successfully created socket")
|
||||
port = socketPort sock
|
||||
putBytes (stdHandle StdOut) (toUtf8 (toText port))
|
||||
|
||||
|
||||
check "port should be > 1024" (1024 < port)
|
||||
check "port should be < 65536" (65536 > port)
|
||||
|
||||
@ -143,7 +143,7 @@ serverThread portVar toSend = 'let
|
||||
socketSend sock' (toUtf8 toSend)
|
||||
closeSocket sock'
|
||||
|
||||
match (toEither go) with
|
||||
match (toEither go) with
|
||||
Left (Failure _ t _) -> watch t ()
|
||||
_ -> ()
|
||||
|
||||
@ -160,22 +160,22 @@ clientThread portVar resultVar = 'let
|
||||
_ -> ()
|
||||
|
||||
testTcpConnect : '{io2.IO}[Result]
|
||||
testTcpConnect = 'let
|
||||
testTcpConnect = 'let
|
||||
test = 'let
|
||||
portVar = !MVar.newEmpty
|
||||
resultVar = !MVar.newEmpty
|
||||
|
||||
|
||||
toSend = "12345"
|
||||
|
||||
void (forkComp (serverThread portVar toSend))
|
||||
void (forkComp (clientThread portVar resultVar))
|
||||
|
||||
|
||||
received = take resultVar
|
||||
|
||||
expectU "should have reaped what we've sown" toSend received
|
||||
|
||||
|
||||
runTest test
|
||||
|
||||
|
||||
```
|
||||
|
||||
```ucm
|
||||
|
@ -17,74 +17,77 @@ The `builtins.merge` command adds the known builtins to a `builtin` subnamespace
|
||||
6. Bytes/ (34 terms)
|
||||
7. Char (builtin type)
|
||||
8. Char/ (22 terms, 1 type)
|
||||
9. Code (builtin type)
|
||||
10. Code/ (9 terms)
|
||||
11. Debug/ (3 terms)
|
||||
12. Doc (type)
|
||||
13. Doc/ (6 terms)
|
||||
14. Either (type)
|
||||
15. Either/ (2 terms)
|
||||
16. Exception (type)
|
||||
17. Exception/ (1 term)
|
||||
18. Float (builtin type)
|
||||
19. Float/ (38 terms)
|
||||
20. Handle/ (1 term)
|
||||
21. ImmutableArray (builtin type)
|
||||
22. ImmutableArray/ (3 terms)
|
||||
23. ImmutableByteArray (builtin type)
|
||||
24. ImmutableByteArray/ (8 terms)
|
||||
25. Int (builtin type)
|
||||
26. Int/ (31 terms)
|
||||
27. IsPropagated (type)
|
||||
28. IsPropagated/ (1 term)
|
||||
29. IsTest (type)
|
||||
30. IsTest/ (1 term)
|
||||
31. Link (type)
|
||||
32. Link/ (3 terms, 2 types)
|
||||
33. List (builtin type)
|
||||
34. List/ (10 terms)
|
||||
35. MutableArray (builtin type)
|
||||
36. MutableArray/ (6 terms)
|
||||
37. MutableByteArray (builtin type)
|
||||
38. MutableByteArray/ (14 terms)
|
||||
39. Nat (builtin type)
|
||||
40. Nat/ (28 terms)
|
||||
41. Optional (type)
|
||||
42. Optional/ (2 terms)
|
||||
43. Pattern (builtin type)
|
||||
44. Pattern/ (9 terms)
|
||||
45. Ref (builtin type)
|
||||
46. Ref/ (2 terms)
|
||||
47. Request (builtin type)
|
||||
48. RewriteCase (type)
|
||||
49. RewriteCase/ (1 term)
|
||||
50. RewriteSignature (type)
|
||||
51. RewriteSignature/ (1 term)
|
||||
52. RewriteTerm (type)
|
||||
53. RewriteTerm/ (1 term)
|
||||
54. Rewrites (type)
|
||||
55. Rewrites/ (1 term)
|
||||
56. Scope (builtin type)
|
||||
57. Scope/ (6 terms)
|
||||
58. SeqView (type)
|
||||
59. SeqView/ (2 terms)
|
||||
60. Socket/ (1 term)
|
||||
61. Test/ (2 terms, 1 type)
|
||||
62. Text (builtin type)
|
||||
63. Text/ (34 terms)
|
||||
64. ThreadId/ (1 term)
|
||||
65. Tuple (type)
|
||||
66. Tuple/ (1 term)
|
||||
67. Unit (type)
|
||||
68. Unit/ (1 term)
|
||||
69. Universal/ (7 terms)
|
||||
70. Value (builtin type)
|
||||
71. Value/ (5 terms)
|
||||
72. bug (a -> b)
|
||||
73. crypto/ (15 terms, 2 types)
|
||||
74. io2/ (135 terms, 32 types)
|
||||
75. metadata/ (2 terms)
|
||||
76. todo (a -> b)
|
||||
77. unsafe/ (1 term)
|
||||
9. ClientSockAddr (builtin type)
|
||||
10. Code (builtin type)
|
||||
11. Code/ (9 terms)
|
||||
12. Debug/ (3 terms)
|
||||
13. Doc (type)
|
||||
14. Doc/ (6 terms)
|
||||
15. Either (type)
|
||||
16. Either/ (2 terms)
|
||||
17. Exception (type)
|
||||
18. Exception/ (1 term)
|
||||
19. Float (builtin type)
|
||||
20. Float/ (38 terms)
|
||||
21. Handle/ (1 term)
|
||||
22. ImmutableArray (builtin type)
|
||||
23. ImmutableArray/ (3 terms)
|
||||
24. ImmutableByteArray (builtin type)
|
||||
25. ImmutableByteArray/ (8 terms)
|
||||
26. Int (builtin type)
|
||||
27. Int/ (31 terms)
|
||||
28. IsPropagated (type)
|
||||
29. IsPropagated/ (1 term)
|
||||
30. IsTest (type)
|
||||
31. IsTest/ (1 term)
|
||||
32. Link (type)
|
||||
33. Link/ (3 terms, 2 types)
|
||||
34. List (builtin type)
|
||||
35. List/ (10 terms)
|
||||
36. ListenSocket (builtin type)
|
||||
37. MutableArray (builtin type)
|
||||
38. MutableArray/ (6 terms)
|
||||
39. MutableByteArray (builtin type)
|
||||
40. MutableByteArray/ (14 terms)
|
||||
41. Nat (builtin type)
|
||||
42. Nat/ (28 terms)
|
||||
43. Optional (type)
|
||||
44. Optional/ (2 terms)
|
||||
45. Pattern (builtin type)
|
||||
46. Pattern/ (9 terms)
|
||||
47. Ref (builtin type)
|
||||
48. Ref/ (2 terms)
|
||||
49. Request (builtin type)
|
||||
50. RewriteCase (type)
|
||||
51. RewriteCase/ (1 term)
|
||||
52. RewriteSignature (type)
|
||||
53. RewriteSignature/ (1 term)
|
||||
54. RewriteTerm (type)
|
||||
55. RewriteTerm/ (1 term)
|
||||
56. Rewrites (type)
|
||||
57. Rewrites/ (1 term)
|
||||
58. Scope (builtin type)
|
||||
59. Scope/ (6 terms)
|
||||
60. SeqView (type)
|
||||
61. SeqView/ (2 terms)
|
||||
62. Socket/ (1 term)
|
||||
63. Test/ (2 terms, 1 type)
|
||||
64. Text (builtin type)
|
||||
65. Text/ (34 terms)
|
||||
66. ThreadId/ (1 term)
|
||||
67. Tuple (type)
|
||||
68. Tuple/ (1 term)
|
||||
69. UDPSocket (builtin type)
|
||||
70. Unit (type)
|
||||
71. Unit/ (1 term)
|
||||
72. Universal/ (7 terms)
|
||||
73. Value (builtin type)
|
||||
74. Value/ (5 terms)
|
||||
75. bug (a -> b)
|
||||
76. crypto/ (15 terms, 2 types)
|
||||
77. io2/ (146 terms, 32 types)
|
||||
78. metadata/ (2 terms)
|
||||
79. todo (a -> b)
|
||||
80. unsafe/ (1 term)
|
||||
|
||||
```
|
||||
|
@ -23,7 +23,7 @@ Technically, the definitions all exist, but they have no names. `builtins.merge`
|
||||
|
||||
.foo> ls
|
||||
|
||||
1. builtin/ (456 terms, 71 types)
|
||||
1. builtin/ (467 terms, 74 types)
|
||||
|
||||
```
|
||||
And for a limited time, you can get even more builtin goodies:
|
||||
@ -35,7 +35,7 @@ And for a limited time, you can get even more builtin goodies:
|
||||
|
||||
.foo> ls
|
||||
|
||||
1. builtin/ (630 terms, 89 types)
|
||||
1. builtin/ (641 terms, 92 types)
|
||||
|
||||
```
|
||||
More typically, you'd start out by pulling `base.
|
||||
|
@ -37,7 +37,7 @@ Exception.unsafeRun! e _ =
|
||||
|
||||
socketSend s bytes = reraise (socketSend.impl s bytes)
|
||||
closeSocket s = reraise (closeSocket.impl s)
|
||||
serverSocket host port = reraise (serverSocket.impl host port)
|
||||
serverSocket host port = reraise (IO.serverSocket.impl host port)
|
||||
|
||||
hello : Text -> Text -> {IO, Exception} ()
|
||||
hello host port =
|
||||
|
@ -33,7 +33,7 @@ Exception.unsafeRun! e _ =
|
||||
|
||||
socketSend s bytes = reraise (socketSend.impl s bytes)
|
||||
closeSocket s = reraise (closeSocket.impl s)
|
||||
serverSocket host port = reraise (serverSocket.impl host port)
|
||||
serverSocket host port = reraise (IO.serverSocket.impl host port)
|
||||
|
||||
hello : Text -> Text -> {IO, Exception} ()
|
||||
hello host port =
|
||||
|
@ -119,13 +119,13 @@ it's still in the `history` of the parent namespace and can be resurrected at an
|
||||
Note: The most recent namespace hash is immediately below this
|
||||
message.
|
||||
|
||||
⊙ 1. #mqis95ft23
|
||||
⊙ 1. #720815367g
|
||||
|
||||
- Deletes:
|
||||
|
||||
feature1.y
|
||||
|
||||
⊙ 2. #5ro9c9692q
|
||||
⊙ 2. #4hps00eboc
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
@ -136,26 +136,26 @@ it's still in the `history` of the parent namespace and can be resurrected at an
|
||||
Original name New name(s)
|
||||
feature1.y master.y
|
||||
|
||||
⊙ 3. #da33td9rni
|
||||
⊙ 3. #c15feh0lv3
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
feature1.y
|
||||
|
||||
⊙ 4. #ks6rftepdv
|
||||
⊙ 4. #5k00u4h52h
|
||||
|
||||
> Moves:
|
||||
|
||||
Original name New name
|
||||
x master.x
|
||||
|
||||
⊙ 5. #dgcqc7jftr
|
||||
⊙ 5. #b3s8tvonc0
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
x
|
||||
|
||||
□ 6. #ms344fdodl (start of history)
|
||||
□ 6. #fdbvr2f3s3 (start of history)
|
||||
|
||||
```
|
||||
To resurrect an old version of a namespace, you can learn its hash via the `history` command, then use `fork #namespacehash .newname`.
|
||||
|
@ -80,7 +80,7 @@ Should be able to move the term, type, and namespace, including its types, terms
|
||||
1. Bar (Nat)
|
||||
2. Bar (type)
|
||||
3. Bar/ (4 terms, 1 type)
|
||||
4. builtin/ (456 terms, 71 types)
|
||||
4. builtin/ (467 terms, 74 types)
|
||||
|
||||
.> ls Bar
|
||||
|
||||
@ -145,7 +145,7 @@ bonk = 5
|
||||
|
||||
.z> ls
|
||||
|
||||
1. builtin/ (456 terms, 71 types)
|
||||
1. builtin/ (467 terms, 74 types)
|
||||
2. zonk (Nat)
|
||||
|
||||
```
|
||||
@ -188,7 +188,7 @@ bonk.zonk = 5
|
||||
|
||||
.a> ls
|
||||
|
||||
1. builtin/ (456 terms, 71 types)
|
||||
1. builtin/ (467 terms, 74 types)
|
||||
2. zonk/ (1 term)
|
||||
|
||||
.a> view zonk.zonk
|
||||
|
@ -277,7 +277,7 @@ I should be able to move the root into a sub-namespace
|
||||
|
||||
.> ls
|
||||
|
||||
1. root/ (1373 terms, 214 types)
|
||||
1. root/ (1406 terms, 223 types)
|
||||
|
||||
.> history
|
||||
|
||||
@ -286,22 +286,22 @@ I should be able to move the root into a sub-namespace
|
||||
|
||||
|
||||
|
||||
□ 1. #vrn80pdffk (start of history)
|
||||
□ 1. #corns7qr1t (start of history)
|
||||
|
||||
```
|
||||
```ucm
|
||||
.> ls .root.at.path
|
||||
|
||||
1. existing/ (457 terms, 71 types)
|
||||
2. happy/ (459 terms, 72 types)
|
||||
3. history/ (457 terms, 71 types)
|
||||
1. existing/ (468 terms, 74 types)
|
||||
2. happy/ (470 terms, 75 types)
|
||||
3. history/ (468 terms, 74 types)
|
||||
|
||||
.> history .root.at.path
|
||||
|
||||
Note: The most recent namespace hash is immediately below this
|
||||
message.
|
||||
|
||||
⊙ 1. #g3ri07hi09
|
||||
⊙ 1. #vgp4hc72su
|
||||
|
||||
- Deletes:
|
||||
|
||||
@ -312,7 +312,7 @@ I should be able to move the root into a sub-namespace
|
||||
Original name New name
|
||||
existing.a.termInA existing.b.termInA
|
||||
|
||||
⊙ 2. #ifjg1bj57v
|
||||
⊙ 2. #hg5coa0n3k
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
@ -324,26 +324,26 @@ I should be able to move the root into a sub-namespace
|
||||
happy.b.termInA existing.a.termInA
|
||||
history.b.termInA existing.a.termInA
|
||||
|
||||
⊙ 3. #bdn8f7vhg1
|
||||
⊙ 3. #pgpp3mqenr
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
existing.a.termInA existing.b.termInB
|
||||
|
||||
⊙ 4. #5dqmgnr0lt
|
||||
⊙ 4. #gbun790pgn
|
||||
|
||||
> Moves:
|
||||
|
||||
Original name New name
|
||||
history.a.termInA history.b.termInA
|
||||
|
||||
⊙ 5. #vd3d37rn3c
|
||||
⊙ 5. #ljad7emlrb
|
||||
|
||||
- Deletes:
|
||||
|
||||
history.b.termInB
|
||||
|
||||
⊙ 6. #gi32sh566a
|
||||
⊙ 6. #3easopbtbb
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
@ -354,13 +354,13 @@ I should be able to move the root into a sub-namespace
|
||||
Original name New name(s)
|
||||
happy.b.termInA history.a.termInA
|
||||
|
||||
⊙ 7. #u2bs53f2hl
|
||||
⊙ 7. #bhmp53toom
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
history.a.termInA history.b.termInB
|
||||
|
||||
⊙ 8. #48hsm89mgl
|
||||
⊙ 8. #l5ncvimoh2
|
||||
|
||||
> Moves:
|
||||
|
||||
@ -370,7 +370,7 @@ I should be able to move the root into a sub-namespace
|
||||
happy.a.T.T2 happy.b.T.T2
|
||||
happy.a.termInA happy.b.termInA
|
||||
|
||||
⊙ 9. #pqd79g3q7l
|
||||
⊙ 9. #j0hfgeiitb
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
@ -380,7 +380,7 @@ I should be able to move the root into a sub-namespace
|
||||
|
||||
happy.a.T.T
|
||||
|
||||
⊙ 10. #allrjqq7ga
|
||||
⊙ 10. #7mnjol2gir
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
@ -392,7 +392,7 @@ I should be able to move the root into a sub-namespace
|
||||
|
||||
⠇
|
||||
|
||||
⊙ 11. #ohd0a9rim1
|
||||
⊙ 11. #plq3nk8j34
|
||||
|
||||
|
||||
```
|
||||
@ -414,26 +414,26 @@ I should be able to move a sub namespace _over_ the root.
|
||||
.> ls
|
||||
|
||||
1. b/ (3 terms, 1 type)
|
||||
2. builtin/ (456 terms, 71 types)
|
||||
2. builtin/ (467 terms, 74 types)
|
||||
|
||||
.> history
|
||||
|
||||
Note: The most recent namespace hash is immediately below this
|
||||
message.
|
||||
|
||||
⊙ 1. #lf3m1s2e7i
|
||||
⊙ 1. #li00cqteoe
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
b.T b.T.T1 b.T.T2 b.termInA
|
||||
|
||||
⊙ 2. #b1cg22v7s1
|
||||
⊙ 2. #ck551mk9b5
|
||||
|
||||
- Deletes:
|
||||
|
||||
a.T a.T.T1 a.T.T2 a.termInA
|
||||
|
||||
⊙ 3. #r83v608ifd
|
||||
⊙ 3. #gearhpa349
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
@ -443,13 +443,13 @@ I should be able to move a sub namespace _over_ the root.
|
||||
|
||||
a.T.T
|
||||
|
||||
⊙ 4. #pmm6a0f6fj
|
||||
⊙ 4. #f1f560n79b
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
a.T a.T.T a.termInA
|
||||
|
||||
□ 5. #nmcjvlnbk1 (start of history)
|
||||
□ 5. #9vjjqeod4l (start of history)
|
||||
|
||||
```
|
||||
```ucm
|
||||
|
@ -63,17 +63,17 @@ y = 2
|
||||
most recent, along with the command that got us there. Try:
|
||||
|
||||
`fork 2 .old`
|
||||
`fork #mq4oqhiuuq .old` to make an old namespace
|
||||
`fork #ce6qpkdjhn .old` to make an old namespace
|
||||
accessible again,
|
||||
|
||||
`reset-root #mq4oqhiuuq` to reset the root namespace and
|
||||
`reset-root #ce6qpkdjhn` to reset the root namespace and
|
||||
its history to that of the
|
||||
specified namespace.
|
||||
|
||||
When Root Hash Action
|
||||
1. now #1n5tjujeu7 add
|
||||
2. now #mq4oqhiuuq add
|
||||
3. now #nmcjvlnbk1 builtins.merge
|
||||
1. now #fmdokt2dim add
|
||||
2. now #ce6qpkdjhn add
|
||||
3. now #9vjjqeod4l builtins.merge
|
||||
4. #sg60bvjo91 history starts here
|
||||
|
||||
Tip: Use `diff.namespace 1 7` to compare namespaces between
|
||||
|
@ -28,13 +28,13 @@ a = 5
|
||||
Note: The most recent namespace hash is immediately below this
|
||||
message.
|
||||
|
||||
⊙ 1. #0nv4t3770d
|
||||
⊙ 1. #5qd3km7th4
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
a
|
||||
|
||||
□ 2. #nmcjvlnbk1 (start of history)
|
||||
□ 2. #9vjjqeod4l (start of history)
|
||||
|
||||
.> reset 2
|
||||
|
||||
@ -47,7 +47,7 @@ a = 5
|
||||
|
||||
|
||||
|
||||
□ 1. #nmcjvlnbk1 (start of history)
|
||||
□ 1. #9vjjqeod4l (start of history)
|
||||
|
||||
```
|
||||
```unison
|
||||
@ -83,13 +83,13 @@ foo.a = 5
|
||||
Note: The most recent namespace hash is immediately below this
|
||||
message.
|
||||
|
||||
⊙ 1. #3s91aop8k9
|
||||
⊙ 1. #1p2akhggkc
|
||||
|
||||
+ Adds / updates:
|
||||
|
||||
foo.a
|
||||
|
||||
□ 2. #nmcjvlnbk1 (start of history)
|
||||
□ 2. #9vjjqeod4l (start of history)
|
||||
|
||||
.> reset 1 foo
|
||||
|
||||
|
@ -13,7 +13,7 @@ Let's look at some examples. We'll start with a namespace with just the builtins
|
||||
|
||||
|
||||
|
||||
□ 1. #3pq2vvggng (start of history)
|
||||
□ 1. #o6oig4fk7p (start of history)
|
||||
|
||||
.> fork builtin builtin2
|
||||
|
||||
@ -42,21 +42,21 @@ Now suppose we `fork` a copy of builtin, then rename `Nat.+` to `frobnicate`, th
|
||||
Note: The most recent namespace hash is immediately below this
|
||||
message.
|
||||
|
||||
⊙ 1. #4g884gq7lc
|
||||
⊙ 1. #695699eqes
|
||||
|
||||
> Moves:
|
||||
|
||||
Original name New name
|
||||
Nat.frobnicate Nat.+
|
||||
|
||||
⊙ 2. #hnah4l7s0j
|
||||
⊙ 2. #5acatj352b
|
||||
|
||||
> Moves:
|
||||
|
||||
Original name New name
|
||||
Nat.+ Nat.frobnicate
|
||||
|
||||
□ 3. #3pq2vvggng (start of history)
|
||||
□ 3. #o6oig4fk7p (start of history)
|
||||
|
||||
```
|
||||
If we merge that back into `builtin`, we get that same chain of history:
|
||||
@ -73,21 +73,21 @@ If we merge that back into `builtin`, we get that same chain of history:
|
||||
Note: The most recent namespace hash is immediately below this
|
||||
message.
|
||||
|
||||
⊙ 1. #4g884gq7lc
|
||||
⊙ 1. #695699eqes
|
||||
|
||||
> Moves:
|
||||
|
||||
Original name New name
|
||||
Nat.frobnicate Nat.+
|
||||
|
||||
⊙ 2. #hnah4l7s0j
|
||||
⊙ 2. #5acatj352b
|
||||
|
||||
> Moves:
|
||||
|
||||
Original name New name
|
||||
Nat.+ Nat.frobnicate
|
||||
|
||||
□ 3. #3pq2vvggng (start of history)
|
||||
□ 3. #o6oig4fk7p (start of history)
|
||||
|
||||
```
|
||||
Let's try again, but using a `merge.squash` (or just `squash`) instead. The history will be unchanged:
|
||||
@ -108,7 +108,7 @@ Let's try again, but using a `merge.squash` (or just `squash`) instead. The hist
|
||||
|
||||
|
||||
|
||||
□ 1. #3pq2vvggng (start of history)
|
||||
□ 1. #o6oig4fk7p (start of history)
|
||||
|
||||
```
|
||||
The churn that happened in `mybuiltin` namespace ended up back in the same spot, so the squash merge of that namespace with our original namespace had no effect.
|
||||
@ -493,13 +493,13 @@ This checks to see that squashing correctly preserves deletions:
|
||||
Note: The most recent namespace hash is immediately below this
|
||||
message.
|
||||
|
||||
⊙ 1. #jdptkosbfp
|
||||
⊙ 1. #erp3nu5u70
|
||||
|
||||
- Deletes:
|
||||
|
||||
Nat.* Nat.+
|
||||
|
||||
□ 2. #3pq2vvggng (start of history)
|
||||
□ 2. #o6oig4fk7p (start of history)
|
||||
|
||||
```
|
||||
Notice that `Nat.+` and `Nat.*` are deleted by the squash, and we see them deleted in one atomic step in the history.
|
||||
|
@ -57,7 +57,7 @@ proj/main> upgrade old new
|
||||
|
||||
proj/main> ls lib
|
||||
|
||||
1. builtin/ (456 terms, 71 types)
|
||||
1. builtin/ (467 terms, 74 types)
|
||||
2. new/ (1 term)
|
||||
|
||||
proj/main> view thingy
|
||||
|
Loading…
Reference in New Issue
Block a user