on master help sign in
15 files changed+305−347
since splitsnapshots
unifiedsplit
LICENSE+7 README.md+8−1 elm.json+11−2 example/src/Sink.elm+1−2 example/src/Vanilla.elm+10−9 src/BitWriter.elm+5−5 src/Ur.elm+2−2 src/Ur/Deconstructor.elm+206−226 src/Ur/NounDiff.elm+21−61 src/Ur/Requests.elm+1−1 src/Ur/Run.elm+10−12 src/Ur/Sub.elm+4−7 src/Ur/Sub/Internal.elm+1−1 src/Ur/Uw.elm+7−7 tests/Test/Urbit.elm+11−11
LICENSEnew file+7
@@ -0,0 +1,7 @@
1+Copyright 2023 Ilia Kostiuchenko
2+
3+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4+
5+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6+
7+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
README.md+8−1
@@ -6,10 +6,17 @@
66
77### Demo
88
9−[![Demo](https://img.youtube.com/vi/KV49E-D-SOY/default.jpg)](https://youtu.be/KV49E-D-SOY)
9+[![DEMO](https://img.youtube.com/vi/tynCzifvIzE/0.jpg)](https://www.youtube.com/watch?v=tynCzifvIzE)
10+
11+
12+## Getting started
13+
14+The easiest way of using this library is by using the [airlock template](https://github.com/ilyakooo0/airlock-template).
1015
1116### FFI
1217
18+This is for setting up this library from scratch.
19+
1320Urbit subscriptions require [server-side event (SSE)](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events).
1421Unfortunately, Elm does not provide a native implementation.
1522This means that we will need to use [JS FFI (aka ports)](https://guide.elm-lang.org/interop/ports.html).
elm.json+11−2
@@ -3,9 +3,18 @@
33 "name": "ilyakooo0/airlock",
44 "summary": "Urbit airlock",
55 "license": "MIT",
6− "version": "1.0.0",
6+ "version": "1.1.1",
77 "exposed-modules": [
8− "Ur", "Ur.Cmd", "Ur.Sub", "Ur.Constructor", "Ur.Deconstructor", "Ur.Phonemic", "Ur.Da", "Ur.Uw", "Ur.Run", "Ur.Types"
8+ "Ur",
9+ "Ur.Cmd",
10+ "Ur.Sub",
11+ "Ur.Constructor",
12+ "Ur.Deconstructor",
13+ "Ur.Phonemic",
14+ "Ur.Da",
15+ "Ur.Uw",
16+ "Ur.Run",
17+ "Ur.Types"
918 ],
1019 "elm-version": "0.19.0 <= v < 0.20.0",
1120 "dependencies": {
example/src/Sink.elm+1−2
@@ -14,7 +14,6 @@ import Ur.Constructor as C
1414import Ur.Deconstructor as D
1515import Ur.Run
1616import Ur.Sub
17−import Ur.Types exposing (Noun)
1817import Widget
1918import Widget.Icon as Icon
2019import Widget.Material as Material
@@ -56,7 +55,7 @@ main =
5655 , app = "journal"
5756 , path = [ "sync" ]
5857 , deconstructor =
59− D.list (D.cell D.bigint D.cord |> D.map (\a b -> ( a, b )))
58+ D.list (D.cell D.bigint D.cord)
6059 |> D.map GotListings
6160 }
6261 ]
example/src/Vanilla.elm+10−9
@@ -46,9 +46,9 @@ main =
4646 , success =
4747 D.cell D.ignore
4848 (D.cell (D.const D.cord "jrnl")
49− (D.list (D.cell D.bigint D.cord |> D.map (\a b -> ( a, b ))))
50− |> D.map GotListings
49+ (D.list (D.cell D.bigint D.cord))
5150 )
51+ |> D.map (\( (), ( (), listings ) ) -> GotListings listings)
5252 }
5353 ]
5454 |> Ur.Cmd.cmd
@@ -177,14 +177,15 @@ type JournalUpdate
177177 | Delete BigInt
178178
179179
180−decodeJournalUpdate : D.Deconstructor (JournalUpdate -> a) a
180+decodeJournalUpdate : D.Deconstructor JournalUpdate
181181decodeJournalUpdate =
182− D.cell D.ignore <|
183− D.oneOf
184− [ (D.cell (D.const D.cord "add") <| D.cell D.bigint D.cord) |> D.map Add
185− , (D.cell (D.const D.cord "edit") <| D.cell D.bigint D.cord) |> D.map Edit
186− , D.cell (D.const D.cord "del") D.bigint |> D.map Delete
187− ]
182+ D.oneOf
183+ [ (D.cell (D.const D.cord "add") <| D.cell D.bigint D.cord) |> D.map (\( (), ( id, txt ) ) -> Add id txt)
184+ , D.cell (D.const D.cord "edit") (D.cell D.bigint D.cord) |> D.map (\( (), ( id, txt ) ) -> Edit id txt)
185+ , D.cell (D.const D.cord "del") D.bigint |> D.map (\( (), id ) -> Delete id)
186+ ]
187+ |> D.cell D.ignore
188+ |> D.map (\( (), upd ) -> upd)
188189
189190
190191view : Model -> Document Msg
src/BitWriter.elm+5−5
@@ -14,17 +14,17 @@ import Bytes.Encode as BE
1414
1515empty : BitWriter
1616empty =
17− BitWriter { running = Nothing, collected = BE.sequence [], offset = 0 }
17+ BitWriter { running = Nothing, collected = [], offset = 0 }
1818
1919
2020run : BitWriter -> Bytes
2121run (BitWriter { running, collected }) =
2222 case running of
2323 Nothing ->
24− BE.encode collected
24+ BE.encode (collected |> List.reverse |> BE.sequence)
2525
2626 Just { value } ->
27− BE.sequence [ collected, BE.unsignedInt8 value ] |> BE.encode
27+ BE.sequence (BE.unsignedInt8 value :: collected |> List.reverse) |> BE.encode
2828
2929
3030type BitWriter
@@ -35,7 +35,7 @@ type BitWriter
3535 , length : Int
3636 }
3737 , offset : Int
38− , collected : BE.Encoder
38+ , collected : List BE.Encoder
3939 }
4040
4141
@@ -68,7 +68,7 @@ bit b (BitWriter { running, collected, offset }) =
6868 if length == 7 then
6969 BitWriter
7070 { running = Nothing
71− , collected = BE.sequence [ collected, BE.unsignedInt8 newValue ]
71+ , collected = BE.unsignedInt8 newValue :: collected
7272 , offset = newOffset
7373 }
7474
src/Ur.elm+2−2
@@ -77,7 +77,7 @@ scry :
7777 , agent : Agent
7878 , path : Path
7979 , error : msg
80− , success : D.Deconstructor (msg -> msg) msg
80+ , success : D.Deconstructor msg
8181 }
8282 -> Cmd msg
8383scry args =
@@ -91,7 +91,7 @@ scryTask :
9191 , agent : Agent
9292 , path : Path
9393 , error : msg
94− , success : D.Deconstructor (msg -> msg) msg
94+ , success : D.Deconstructor msg
9595 }
9696 -> Task a msg
9797scryTask { url, agent, path, error, success } =
src/Ur/Deconstructor.elm+206−226
@@ -6,24 +6,16 @@ module Ur.Deconstructor exposing
66 , int, signedInt, bigint
77 , float32, float64
88 , cord, tape
9− , bytes, sig, ignore, tar, lazy
9+ , bytes, sig, ignore, tar, lazy, debug
1010 )
1111
1212{-| This module provides an API to deconstruct `Noun`s into arbitrary Elm data structures.
1313
14−The principal (and types) are very similar to `Url.Parser` from `elm/url`.
15−
1614You would parse a `[%edit @ cord]` like this:
1715
1816 type alias Edit = {id: Int, text : String}
1917
20− (D.cell (D.const D.cord "edit") (D.cell D.int D.cord)) |> D.map Edit
21−
22−When you `map` a `Deconstructor` the function you pass to `map` will accept exactly the number of arguments
23−that "captured" values in exacly the order they occured in the `Deconstructor`.
24−
25−In our case we `map` the `Edit` type, which accepts exaclty two arguments because there are two `Deconstructor`s
26−that "capture" a value: `D.int` and `D.cord`.
18+ (D.cell (D.const D.cord "edit") (D.cell D.bigint D.cord)) |> D.map (\( (), ( id, txt ) ) -> Edit id txt)
2719
2820@docs Deconstructor
2921
@@ -63,7 +55,7 @@ that "capture" a value: `D.int` and `D.cord`.
6355
6456# Miscellaneous
6557
66−@docs bytes, sig, ignore, tar, lazy
58+@docs bytes, sig, ignore, tar, lazy, debug
6759
6860-}
6961
@@ -74,33 +66,31 @@ import Bytes exposing (Bytes, Endianness(..))
7466import Bytes.Decode as BD
7567import Bytes.Encode as BE
7668import Bytes.Extra
77−import Ur.Jam exposing (cue)
69+import Ur.Jam exposing (cue, isSig)
7870import Ur.Types exposing (..)
7971
8072
8173{-| A `Noun` deconstructor.
8274-}
83−type Deconstructor a b
84− = Deconstructor (Noun -> a -> Maybe b)
75+type alias Deconstructor a =
76+ Noun -> Maybe a
8577
8678
8779{-| Executes a `Deconstructor` on a `Noun`.
8880-}
89−run : Deconstructor (a -> a) a -> Noun -> Maybe a
90−run (Deconstructor f) noun =
91− f noun identity
81+run : Deconstructor a -> Noun -> Maybe a
82+run f noun =
83+ f noun
9284
9385
9486{-| Executes a deconstructor on a `jam`med `Noun`.
9587-}
96−runBytes : Deconstructor (a -> a) a -> Bytes -> Maybe a
97−runBytes (Deconstructor f) bs =
98− cue bs
99− |> Maybe.andThen
100− (\noun -> f noun identity)
88+runBytes : Deconstructor a -> Bytes -> Maybe a
89+runBytes f bs =
90+ cue bs |> Maybe.andThen f
10191
10292
103−{-| Asserts that the value at the current position should be exactly equal to the second argument.
93+{-| Asserts that the value should be exactly equal to the second argument.
10494
10595The first argument is a `Deconstructor` for the given type.
10696
@@ -109,104 +99,41 @@ The second argument is the value to compare with.
10999This is useful to match on `term`s when there are multiple possible cases in a head-tagged union.
110100
111101-}
112−const : Deconstructor (a -> a) a -> a -> Deconstructor c c
113−const (Deconstructor f) value =
114− Deconstructor
115− (\noun c ->
116− case f noun identity of
117− Just a ->
118− if a == value then
119− Just c
102+const : Deconstructor a -> a -> Deconstructor ()
103+const f value noun =
104+ case f noun of
105+ Just a ->
106+ if a == value then
107+ Just ()
120108
121− else
122− Nothing
109+ else
110+ Nothing
123111
124− Nothing ->
125− Nothing
126− )
112+ Nothing ->
113+ Nothing
127114
128115
129−{-| Extracts a `cord` at the current location.
116+{-| Extracts a `BigInt`.
130117-}
131−cord : Deconstructor (String -> a) a
132−cord =
133− Deconstructor
134− (\x f ->
135− case x of
136− Atom bs ->
137− BD.decode (BD.string (Bytes.width bs)) bs
138− |> Maybe.map f
139−
140− Cell _ ->
141− Nothing
142− )
118+bigint : Deconstructor BigInt
119+bigint x =
120+ case x of
121+ Atom bs ->
122+ BigInt.Bytes.decode bs |> Just
143123
144−
145−{-| Extracts a `tape` at the current location.
146−-}
147−tape : Deconstructor (String -> a) a
148−tape =
149− list cord |> fmap String.concat
124+ Cell _ ->
125+ Nothing
150126
151127
152−{-| Extracts a 32-bit unsigned `Int` at the given location.
128+{-| Extracts a 32-bit signed `Int`.
153129
154−If the `Atom` at the current location is larger than 32 bits the the behaviour is undefined.
130+If the `Atom` is larger than 32 bits the the behaviour is undefined.
155131
156132-}
157−int : Deconstructor (Int -> a) a
158−int =
159− Deconstructor
160− (\x f ->
161− case x of
162− Atom bs ->
163− (case Bytes.width bs of
164− 1 ->
165− BD.decode BD.unsignedInt8 bs
166−
167− 2 ->
168− BD.decode (BD.unsignedInt16 LE) bs
169−
170− 3 ->
171− BD.decode (BD.unsignedInt32 LE) (BE.encode (BE.sequence [ BE.bytes bs, BE.unsignedInt8 0 ]))
172−
173− 4 ->
174− BD.decode (BD.unsignedInt32 LE) bs
175−
176− _ ->
177− Nothing
178− )
179− |> Maybe.map f
180−
181− Cell _ ->
182− Nothing
183− )
184−
185−
186−{-| Extracts a `BigInt` at the current location.
187−-}
188−bigint : Deconstructor (BigInt -> a) a
189−bigint =
190− Deconstructor
191− (\x f ->
192− case x of
193− Atom bs ->
194− BigInt.Bytes.decode bs |> f |> Just
195−
196− Cell _ ->
197− Nothing
198− )
199−
200−
201−{-| Extracts a 32-bit signed `Int` at the given location.
202−
203−If the `Atom` at the current location is larger than 32 bits the the behaviour is undefined.
204−
205−-}
206−signedInt : Deconstructor (Int -> a) a
133+signedInt : Deconstructor Int
207134signedInt =
208135 int
209− |> fmap
136+ |> map
210137 (\i ->
211138 if Bitwise.and 1 i == 1 then
212139 -(Bitwise.shiftRightBy 1 (1 + i))
@@ -216,105 +143,85 @@ signedInt =
216143 )
217144
218145
219−{-| Extracts a 32-bit `Float` at the given location.
146+{-| Extracts a 32-bit `Float`.
220147-}
221−float32 : Deconstructor (Float -> a) a
222−float32 =
223− Deconstructor
224− (\x f ->
225− case x of
226− Atom bs ->
227− BD.decode (BD.float32 LE) bs
228− |> Maybe.map f
229−
230− Cell _ ->
231− Nothing
232− )
148+float32 : Deconstructor Float
149+float32 x =
150+ case x of
151+ Atom bs ->
152+ BD.decode (BD.float32 LE) bs
153+
154+ Cell _ ->
155+ Nothing
233156
234157
235−{-| Extracts a 64-bit `Float` at the given location.
158+{-| Extracts a 64-bit `Float`.
236159-}
237−float64 : Deconstructor (Float -> a) a
238−float64 =
239− Deconstructor
240− (\x f ->
241− case x of
242− Atom bs ->
243− BD.decode (BD.float64 LE) bs
244− |> Maybe.map f
245−
246− Cell _ ->
247− Nothing
248− )
160+float64 : Deconstructor Float
161+float64 x =
162+ case x of
163+ Atom bs ->
164+ BD.decode (BD.float64 LE) bs
165+
166+ Cell _ ->
167+ Nothing
249168
250169
251−{-| Extracts the raw `Byte`s of an `Atom` at the current location.
170+{-| Extracts the raw `Byte`s of an `Atom`.
252171-}
253−bytes : Deconstructor (Bytes -> a) a
254−bytes =
255− Deconstructor
256− (\n f ->
257− case n of
258− Atom bs ->
259− f bs |> Just
172+bytes : Deconstructor Bytes
173+bytes n =
174+ case n of
175+ Atom bs ->
176+ Just bs
260177
261− Cell _ ->
262− Nothing
263− )
178+ Cell _ ->
179+ Nothing
264180
265181
266−{-| Asserts the the `Atom` at the current position should be exactly `sig` (`~`).
182+{-| Asserts the the `Atom` should be exactly `sig` (`~`).
267183-}
268−sig : Deconstructor a a
269−sig =
270− Deconstructor
271− (\n a ->
272− case n of
273− Atom b ->
274− if (Bytes.Extra.toByteValues b |> List.filter (\x -> x /= 0)) == [] then
275− Just a
184+sig : Deconstructor ()
185+sig n =
186+ case n of
187+ Atom b ->
188+ if (Bytes.Extra.toByteValues b |> List.filter (\x -> x /= 0)) == [] then
189+ Just ()
276190
277− else
278− Nothing
191+ else
192+ Nothing
279193
280− Cell _ ->
281− Nothing
282− )
194+ Cell _ ->
195+ Nothing
283196
284197
285−{-| Extracts a sig-terminated list of arbitrary elements at the current position.
198+{-| Extracts a sig-terminated list of arbitrary elements.
286199
287200The first argument is a `Deconstructor` of the elements of the list.
288201
289202-}
290−list : Deconstructor (a -> a) a -> Deconstructor (List a -> b) b
291−list (Deconstructor f) =
292− Deconstructor
293− (\n g ->
294− let
295− go n_ =
296− case n_ of
297− Atom _ ->
298− Just []
203+list : Deconstructor a -> Deconstructor (List a)
204+list f n =
205+ let
206+ go n_ =
207+ case n_ of
208+ Atom _ ->
209+ Just []
299210
300− Cell ( el, tail ) ->
301− Maybe.map2 (\a b -> a :: b) (f el identity) (go tail)
302− in
303− go n |> Maybe.map g
304− )
211+ Cell ( el, tail ) ->
212+ Maybe.map2 (\a b -> a :: b) (f el) (go tail)
213+ in
214+ go n
305215
306216
307−alt : Deconstructor a b -> Deconstructor a b -> Deconstructor a b
308−alt (Deconstructor f) (Deconstructor g) =
309− Deconstructor
310− (\n a ->
311− case f n a of
312− Just x ->
313− Just x
217+alt : Deconstructor a -> Deconstructor a -> Deconstructor a
218+alt f g n =
219+ case f n of
220+ Just x ->
221+ Just x
314222
315− Nothing ->
316− g n a
317− )
223+ Nothing ->
224+ g n
318225
319226
320227{-| Try to execute all of the `Deconstructor`s in order until one succeeds.
@@ -322,77 +229,150 @@ alt (Deconstructor f) (Deconstructor g) =
322229This is especially useful for deconstructing head-tagged unions from Hoon.
323230
324231-}
325−oneOf : List (Deconstructor a b) -> Deconstructor a b
232+oneOf : List (Deconstructor a) -> Deconstructor a
326233oneOf l =
327234 case l of
328235 [] ->
329− Deconstructor (\_ _ -> Nothing)
236+ always Nothing
330237
331238 x :: xs ->
332239 alt x (oneOf xs)
333240
334241
335−{-| Extract the raw `Noun` at the current position.
242+{-| Ignore any value.
336243
337−Always succeeds.
244+This is useful when you have a value you don't care about. `ignore` allows you to just skip the value.
338245
339246-}
340−tar : Deconstructor (Noun -> a) a
341−tar =
342− Deconstructor (\noun f -> Just (f noun))
247+ignore : Deconstructor ()
248+ignore =
249+ always (Just ())
343250
344251
345−{-| Ignore any value at the current position.
252+{-| Extracts a [`Cell`](https://developers.urbit.org/reference/glossary/cell) (pair) of two arbitrary values.
346253
347−This is useful when you have a value you don't care about. `ignore` allows you to just skip the value.
254+Accepts two arbitrary `Deconstructor`s that form a Cell.
348255
349256-}
350−ignore : Deconstructor a a
351−ignore =
352− Deconstructor (\_ f -> Just f)
257+cell : Deconstructor a -> Deconstructor b -> Deconstructor ( a, b )
258+cell l r noun =
259+ case noun of
260+ Cell ( lhs, rhs ) ->
261+ l lhs |> Maybe.andThen (\a -> r rhs |> Maybe.map (\b -> ( a, b )))
353262
263+ Atom _ ->
264+ Nothing
354265
355−{-| Extracts a [`Cell`](https://developers.urbit.org/reference/glossary/cell) (pair) of two arbitrary values.
356266
357−Accepts two arbitrary `Deconstructor`s that form a Cell.
267+{-| Maps (applies) a function to all of the values deconstructed.
268+
269+This is useful when you want to create a data type with extracted values as fields.
358270
359271-}
360−cell : Deconstructor a b -> Deconstructor b c -> Deconstructor a c
361−cell (Deconstructor l) (Deconstructor r) =
362− Deconstructor
363− (\noun a ->
364− case noun of
365− Cell ( lhs, rhs ) ->
366− l lhs a |> Maybe.andThen (\b -> r rhs b)
272+lazy : (() -> Deconstructor a) -> Deconstructor a
273+lazy f noun =
274+ f () noun
367275
368− Atom _ ->
369− Nothing
370− )
276+
277+{-| Maps over the result of the deconstructor.
278+-}
279+map : (a -> b) -> Deconstructor a -> Deconstructor b
280+map g f noun =
281+ f noun |> Maybe.map g
371282
372283
373−{-| "Lazily" applies a deconstructor.
374−This is useful when you are defining a recursive `Deconstructor` which needs to call itself.
284+{-| Extracts a `cord`.
375285-}
376−lazy : (() -> Deconstructor a b) -> Deconstructor a b
377−lazy f =
378− Deconstructor
379− (\noun a ->
380− case f () of
381− Deconstructor g ->
382− g noun a
383− )
286+cord : Deconstructor String
287+cord x =
288+ case x of
289+ Atom bs ->
290+ BD.decode (BD.string (Bytes.width bs)) bs
384291
292+ Cell _ ->
293+ Nothing
385294
386−{-| Maps (applies) a function to all of the values deconstructed.
387295
388−This is useful when you want to create a data type with extracted values as fields.
296+{-| Extracts a `tape`.
297+-}
298+tape : Deconstructor String
299+tape =
300+ list cord |> map String.concat
301+
302+
303+{-| Extracts a 32-bit unsigned `Int`.
304+
305+If the `Atom` is larger than 32 bits the the behaviour is undefined.
389306
390307-}
391−map : a -> Deconstructor a b -> Deconstructor (b -> c) c
392−map a (Deconstructor f) =
393− Deconstructor (\noun g -> f noun a |> Maybe.map g)
308+int : Deconstructor Int
309+int x =
310+ case x of
311+ Atom bs ->
312+ case Bytes.width bs of
313+ 1 ->
314+ BD.decode BD.unsignedInt8 bs
315+
316+ 2 ->
317+ BD.decode (BD.unsignedInt16 LE) bs
318+
319+ 3 ->
320+ BD.decode (BD.unsignedInt32 LE) (BE.encode (BE.sequence [ BE.bytes bs, BE.unsignedInt8 0 ]))
321+
322+ 4 ->
323+ BD.decode (BD.unsignedInt32 LE) bs
324+
325+ _ ->
326+ Nothing
327+
328+ Cell _ ->
329+ Nothing
394330
395331
396−fmap : (a -> b) -> Deconstructor (a -> c) c -> Deconstructor (b -> c) c
397−fmap f (Deconstructor g) =
398− Deconstructor (\noun h -> g noun (f >> h))
332+{-| Extract the raw `Noun`.
333+
334+Always succeeds.
335+
336+-}
337+tar : Deconstructor Noun
338+tar =
339+ Just
340+
341+
342+{-| Debug a deconstructor.
343+If the deconstructor from the second argument fails then the failed nock will be printed to the console.
344+-}
345+debug : (String -> String) -> Deconstructor a -> Deconstructor a
346+debug log f noun =
347+ case f noun of
348+ Just x ->
349+ Just x
350+
351+ Nothing ->
352+ let
353+ _ =
354+ log (prettyNoun noun)
355+ in
356+ Nothing
357+
358+
359+prettyNoun : Noun -> String
360+prettyNoun noun =
361+ let
362+ go isRhs n =
363+ case n of
364+ Atom a ->
365+ if isSig a then
366+ "~"
367+
368+ else
369+ "@"
370+
371+ Cell ( lhs, rhs ) ->
372+ if isRhs then
373+ go False lhs ++ " " ++ go True rhs
374+
375+ else
376+ "[" ++ go False lhs ++ " " ++ go True rhs ++ "]"
377+ in
378+ go False noun
src/Ur/NounDiff.elm+21−61
@@ -11,29 +11,17 @@ type Patch
1111 | Diff DelDiff InsDiff
1212
1313
14−deconstructPatch : D.Deconstructor (Patch -> c) c
15−deconstructPatch =
14+deconstructPatch : () -> D.Deconstructor Patch
15+deconstructPatch () =
1616 D.oneOf
1717 [ D.cell (D.const D.cord "cell")
1818 (D.cell
19− (D.lazy (\() -> deconstructPatch_))
20− (D.lazy (\() -> deconstructPatch_))
19+ (D.lazy deconstructPatch)
20+ (D.lazy deconstructPatch)
2121 )
22− |> D.map PatchCell
23− , D.cell (D.const D.cord "diff") (D.cell deconstructDel deconstructIns) |> D.map Diff
24− ]
25−
26−
27−deconstructPatch_ : D.Deconstructor (Patch -> c) c
28−deconstructPatch_ =
29− D.oneOf
30− [ D.cell (D.const D.cord "cell")
31− (D.cell
32− deconstructPatch
33− deconstructPatch
34− )
35− |> D.map PatchCell
36− , D.cell (D.const D.cord "diff") (D.cell deconstructDel deconstructIns) |> D.map Diff
22+ |> D.map (\( (), ( a, b ) ) -> PatchCell a b)
23+ , D.cell (D.const D.cord "diff") (D.cell (D.lazy deconstructDel) (D.lazy deconstructIns))
24+ |> D.map (\( (), ( a, b ) ) -> Diff a b)
3725 ]
3826
3927
@@ -93,31 +81,17 @@ type DelDiff
9381 | DelCell DelDiff DelDiff
9482
9583
96−deconstructDel : D.Deconstructor (DelDiff -> c) c
97−deconstructDel =
84+deconstructDel : () -> D.Deconstructor DelDiff
85+deconstructDel () =
9886 D.oneOf
99− [ D.cell (D.const D.cord "ignore") D.ignore |> D.map Ignore
100− , D.cell (D.const D.cord "hole") D.int |> D.map DelHole
87+ [ D.cell (D.const D.cord "ignore") D.ignore |> D.map (\( (), () ) -> Ignore)
88+ , D.cell (D.const D.cord "hole") D.int |> D.map (\( (), x ) -> DelHole x)
10189 , D.cell (D.const D.cord "cell")
10290 (D.cell
103− deconstructDel_
104− deconstructDel_
91+ (D.lazy deconstructDel)
92+ (D.lazy deconstructDel)
10593 )
106− |> D.map DelCell
107− ]
108−
109−
110−deconstructDel_ : D.Deconstructor (DelDiff -> c) c
111−deconstructDel_ =
112− D.oneOf
113− [ D.const D.cord "ignore" |> D.map Ignore
114− , D.cell (D.const D.cord "hole") D.int |> D.map DelHole
115− , D.cell (D.const D.cord "cell")
116− (D.cell
117− (D.lazy (\() -> deconstructDel))
118− (D.lazy (\() -> deconstructDel))
119− )
120− |> D.map DelCell
94+ |> D.map (\( (), ( lhs, rhs ) ) -> DelCell lhs rhs)
12195 ]
12296
12397
@@ -127,29 +101,15 @@ type InsDiff
127101 | InsCell InsDiff InsDiff
128102
129103
130−deconstructIns : D.Deconstructor (InsDiff -> c) c
131−deconstructIns =
132− D.oneOf
133− [ D.cell (D.const D.cord "hole") D.int |> D.map InsHole
134− , D.cell (D.const D.cord "atom") D.bytes |> D.map InsAtom
135− , D.cell (D.const D.cord "cell")
136− (D.cell
137− deconstructIns_
138− deconstructIns_
139− )
140− |> D.map InsCell
141− ]
142−
143−
144−deconstructIns_ : D.Deconstructor (InsDiff -> c) c
145−deconstructIns_ =
104+deconstructIns : () -> D.Deconstructor InsDiff
105+deconstructIns () =
146106 D.oneOf
147− [ D.cell (D.const D.cord "hole") D.int |> D.map InsHole
148− , D.cell (D.const D.cord "atom") D.bytes |> D.map InsAtom
107+ [ D.cell (D.const D.cord "hole") D.int |> D.map (\( (), x ) -> InsHole x)
108+ , D.cell (D.const D.cord "atom") D.bytes |> D.map (\( (), bs ) -> InsAtom bs)
149109 , D.cell (D.const D.cord "cell")
150110 (D.cell
151− (D.lazy (\() -> deconstructIns))
152− (D.lazy (\() -> deconstructIns))
111+ (D.lazy deconstructIns)
112+ (D.lazy deconstructIns)
153113 )
154− |> D.map InsCell
114+ |> D.map (\( (), ( a, b ) ) -> InsCell a b)
155115 ]
src/Ur/Requests.elm+1−1
@@ -98,7 +98,7 @@ toNoun eventId req =
9898 C.cell (C.cord app) (C.listOf C.cord path)
9999
100100 Unsubscribe subId ->
101− C.cell (C.cord "usubscribe") <|
101+ C.cell (C.cord "unsubscribe") <|
102102 C.cell (C.int eventId) (C.int subId)
103103
104104 Poke { ship, agent, mark, noun } ->
src/Ur/Run.elm+10−12
@@ -31,7 +31,7 @@ type alias SubDict msg =
3131 Dict
3232 -- (ship, agent, path)
3333 ( String, String, List String )
34− { deconstructor : D.Deconstructor (msg -> msg) msg
34+ { deconstructor : D.Deconstructor msg
3535 , number : Int
3636 , sink : Bool
3737 }
@@ -178,7 +178,7 @@ update inp msg model =
178178 processUrSubs
179179 model.eventId
180180 model.subscriptions
181− (inp.urbitSubscriptions model.app |> (\(Ur.Sub.Internal.Sub x) -> x))
181+ (inp.urbitSubscriptions appModel |> (\(Ur.Sub.Internal.Sub x) -> x))
182182
183183 ( eventId_, cmds, urReqs ) =
184184 processCmd subsResult.eventId appCmds
@@ -211,12 +211,10 @@ update inp msg model =
211211 Ok string ->
212212 case
213213 D.runBytes
214− (D.cell D.int (D.cell D.cord D.tar)
215− |> D.map (\a b c -> ( a, b, c ))
216− )
214+ (D.cell D.int (D.cell D.cord D.tar))
217215 (Ur.Uw.decode string)
218216 of
219− Just ( messageId, messageType, rest ) ->
217+ Just ( messageId, ( messageType, rest ) ) ->
220218 let
221219 ( eventId, ackReqs ) =
222220 tag model.eventId [ Ack messageId ]
@@ -248,7 +246,7 @@ update inp msg model =
248246 of
249247 Just { deconstructor, sink } ->
250248 if sink then
251− case D.run (D.cell D.ignore (D.cell D.ignore deconstructSink)) rest of
249+ case D.run (D.cell D.ignore (D.cell D.ignore deconstructSink) |> D.map (\( (), ( (), s ) ) -> s)) rest of
252250 Just (Flush noun) ->
253251 ( { model | sinks = Dict.insert messageId noun model.sinks }
254252 , case D.run deconstructor noun of
@@ -284,7 +282,7 @@ update inp msg model =
284282 ( model, Cmd.none )
285283
286284 else
287− case D.run (D.cell D.ignore (D.cell D.ignore deconstructor)) rest of
285+ case D.run (D.cell D.ignore (D.cell D.ignore deconstructor) |> D.map (\( (), ( (), m ) ) -> m)) rest of
288286 Just subMsg ->
289287 ( model_, pureCmd (AppMsg subMsg) )
290288
@@ -315,7 +313,7 @@ update inp msg model =
315313 NeedsActivation ->
316314 let
317315 ( eventId, reqs ) =
318− [ Poke { ship = "~zod", agent = "hood", mark = "helm-hi", noun = C.cord "Opening airlock!" } ]
316+ [ Poke { ship = "", agent = "hood", mark = "helm-hi", noun = C.cord "Opening airlock!" } ]
319317 |> tag model.eventId
320318 in
321319 ( { model | eventId = eventId }
@@ -351,11 +349,11 @@ type Sink
351349 | Drain Patch
352350
353351
354−deconstructSink : D.Deconstructor (Sink -> c) c
352+deconstructSink : D.Deconstructor Sink
355353deconstructSink =
356354 D.oneOf
357− [ D.cell (D.const D.cord "flush") D.tar |> D.map Flush
358− , D.cell (D.const D.cord "drain") deconstructPatch |> D.map Drain
355+ [ D.cell (D.const D.cord "flush") D.tar |> D.map (\( (), n ) -> Flush n)
356+ , D.cell (D.const D.cord "drain") (D.lazy deconstructPatch) |> D.map (\( (), patch ) -> Drain patch)
359357 ]
360358
361359
src/Ur/Sub.elm+4−7
@@ -1,11 +1,8 @@
1−module Ur.Sub exposing
2− ( Sub, subscribe, none, batch
3− , sink
4− )
1+module Ur.Sub exposing (Sub, subscribe, none, batch, sink)
52
63{-| This module is conceptually similar to `Platform.Sub`, but allows you to subscribe to Urbit channels.
74
8−@docs Sub, subscribe, none, batch
5+@docs Sub, subscribe, none, batch, sink
96
107-}
118
@@ -30,7 +27,7 @@ type alias Sub msg =
3027 }
3128
3229-}
33−subscribe : { ship : String, app : String, path : List String, deconstructor : D.Deconstructor (msg -> msg) msg } -> Sub msg
30+subscribe : { ship : String, app : String, path : List String, deconstructor : D.Deconstructor msg } -> Sub msg
3431subscribe { ship, app, path, deconstructor } =
3532 Dict.singleton ( ship, app, path )
3633 { deconstructor = deconstructor
@@ -41,7 +38,7 @@ subscribe { ship, app, path, deconstructor } =
4138
4239{-| Creates a %sink subscription.
4340-}
44−sink : { ship : String, app : String, path : List String, deconstructor : D.Deconstructor (msg -> msg) msg } -> Sub msg
41+sink : { ship : String, app : String, path : List String, deconstructor : D.Deconstructor msg } -> Sub msg
4542sink { ship, app, path, deconstructor } =
4643 Dict.singleton ( ship, app, path )
4744 { deconstructor = deconstructor
src/Ur/Sub/Internal.elm+1−1
@@ -10,7 +10,7 @@ type Sub msg
1010 (Dict
1111 -- key is (ship, app, path)
1212 ( Ship, Agent, Path )
13− { deconstructor : D.Deconstructor (msg -> msg) msg
13+ { deconstructor : D.Deconstructor msg
1414 , sink : Bool
1515 }
1616 )
src/Ur/Uw.elm+7−7
@@ -29,24 +29,24 @@ decode string =
2929 -- 0w
3030 |> List.drop 2
3131
32− go : List Char -> BW.BitWriter -> BW.BitWriter
33− go cs writer =
32+ go : List Char -> List Int -> BW.BitWriter -> BW.BitWriter
33+ go cs append writer =
3434 case cs of
3535 [] ->
36− writer
36+ BW.bits append writer
3737
3838 '.' :: rest ->
39− go rest writer
39+ go rest append writer
4040
4141 c :: rest ->
4242 case Dict.get c charToBits of
4343 Just bits ->
44− go rest writer |> BW.bits bits
44+ go rest (bits ++ append) writer
4545
4646 Nothing ->
47− go rest writer
47+ go rest [] writer
4848 in
49− BW.run (go chars BW.empty)
49+ BW.run (go chars [] BW.empty)
5050
5151
5252{-| -}
tests/Test/Urbit.elm+11−11
@@ -77,7 +77,7 @@ tests =
7777 Expect.equal
7878 (Just ( 1, 2 ))
7979 (D.runBytes
80− (D.cell D.int D.int |> D.map Tuple.pair)
80+ (D.cell D.int D.int)
8181 (Bytes.fromByteValues [ 0x31, 0x12 ])
8282 )
8383 )
@@ -96,7 +96,7 @@ tests =
9696 Expect.equal
9797 (Just ( 4, [ 1, 2, 3 ] ))
9898 (D.runBytes
99− (D.cell D.int (D.list D.int) |> D.map Tuple.pair)
99+ (D.cell D.int (D.list D.int))
100100 (Bytes.fromByteValues [ 0x61, 0xC6, 0x21, 0x43, 0x0B ])
101101 )
102102 )
@@ -105,7 +105,7 @@ tests =
105105 Expect.equal
106106 (Just ( 8, 11 ))
107107 (D.runBytes
108− (D.cell D.float32 D.float32 |> D.map Tuple.pair)
108+ (D.cell D.float32 D.float32)
109109 (Bytes.fromByteValues [ 0x01, 0x1F, 0x00, 0x00, 0x20, 0x08, 0x7C, 0x00, 0x00, 0x98, 0x20 ])
110110 )
111111 )
@@ -114,7 +114,7 @@ tests =
114114 Expect.equal
115115 (Just ( 8, "hi" ))
116116 (D.runBytes
117− (D.cell D.int D.cord |> D.map Tuple.pair)
117+ (D.cell D.int D.cord)
118118 (Bytes.fromByteValues [ 0x41, 0x10, 0x3C, 0x5A, 0x1A ])
119119 )
120120 )
@@ -123,7 +123,7 @@ tests =
123123 Expect.equal
124124 (Just ( 8, "hi" ))
125125 (D.runBytes
126− (D.cell D.int D.tape |> D.map Tuple.pair)
126+ (D.cell D.int D.tape)
127127 (Bytes.fromByteValues [ 0x41, 0x30, 0x38, 0x3A, 0x78, 0x5A ])
128128 )
129129 )
@@ -134,8 +134,8 @@ tests =
134134 (Just "hi")
135135 (D.runBytes
136136 (D.oneOf
137− [ D.cell (D.const D.cord "tape") D.tape
138− , D.cell (D.const D.cord "cord") D.cord
137+ [ D.cell (D.const D.cord "tape") D.tape |> D.map (\((), t) -> t)
138+ , D.cell (D.const D.cord "cord") D.cord |> D.map (\((), c) -> c)
139139 ]
140140 )
141141 (Bytes.fromByteValues [ 0x01, 0x9F, 0x2E, 0x0C, 0xAE, 0x1C, 0x1C, 0x1D, 0x3C, 0x2D ])
@@ -147,8 +147,8 @@ tests =
147147 (Just "hi")
148148 (D.runBytes
149149 (D.oneOf
150− [ D.cell (D.const D.cord "tape") D.tape
151− , D.cell (D.const D.cord "cord") D.cord
150+ [ D.cell (D.const D.cord "tape") D.tape |> D.map (\((), t) -> t)
151+ , D.cell (D.const D.cord "cord") D.cord |> D.map (\((), c) -> c)
152152 ]
153153 )
154154 (Bytes.fromByteValues [ 0x01, 0x7F, 0xEC, 0x4D, 0x8E, 0x0C, 0x1E, 0x2D, 0x0D ])
@@ -160,7 +160,7 @@ tests =
160160 Expect.equal
161161 (Just ( 8, -8 ))
162162 (D.runBytes
163− (D.cell D.signedInt D.signedInt |> D.map Tuple.pair)
163+ (D.cell D.signedInt D.signedInt)
164164 (Bytes.fromByteValues [ 0xC1, 0x20, 0xE4, 0x01 ])
165165 )
166166 )
@@ -190,7 +190,7 @@ tests =
190190 (\( f, i, ui ) ->
191191 Expect.equal (Just ( f, i, ui ))
192192 (D.run
193− (D.cell D.float64 (D.cell D.signedInt D.int) |> D.map (\a b c -> ( a, b, c )))
193+ (D.cell D.float64 (D.cell D.signedInt D.int) |> D.map (\(a, (b, c)) -> ( a, b, c )))
194194 (C.cell (C.float64 f) (C.cell (C.signedInt i) (C.int ui)))
195195 )
196196 )