on master help sign in
Added noun construction (#3)
commit89f0999d9eed0d72ba1091bec949a1fc1665cf1d authoriko <mail@iko.soy> dateSat 3 Jun 2023, 16:00 (3 years ago) parent2bb7a1a
3 files changed+166−6
src/Urbit/Constructor.elm+93 src/Urbit/Deconstructor.elm+18−6 tests/Test/Urbit.elm+55
src/Urbit/Constructor.elmnew file+93
@@ -0,0 +1,93 @@
1+module Urbit.Constructor exposing
2+ ( Constructor
3+ , cell
4+ , cord
5+ , float32
6+ , float64
7+ , int
8+ , listOf
9+ , sig
10+ , signedInt
11+ , tape
12+ )
13+
14+import Bitwise
15+import Bytes exposing (Bytes, Endianness(..))
16+import Bytes.Encode as BE
17+import Urbit exposing (..)
18+
19+
20+type alias Constructor a =
21+ a -> Noun
22+
23+
24+cell : Noun -> Noun -> Noun
25+cell a b =
26+ Cell ( a, b )
27+
28+
29+int : Int -> Noun
30+int i =
31+ Atom
32+ (BE.encode
33+ (if i <= 255 then
34+ BE.unsignedInt8 i
35+
36+ else if i <= 65535 then
37+ BE.unsignedInt16 LE i
38+
39+ else
40+ BE.unsignedInt32 LE i
41+ )
42+ )
43+
44+
45+signedInt : Int -> Noun
46+signedInt i =
47+ int
48+ (if i < 0 then
49+ negate (Bitwise.shiftLeftBy 1 i) - 1
50+
51+ else
52+ Bitwise.shiftLeftBy 1 i
53+ )
54+
55+
56+bytes : Bytes -> Noun
57+bytes =
58+ Atom
59+
60+
61+cord : String -> Noun
62+cord s =
63+ Atom (BE.encode (BE.string s))
64+
65+
66+tape : String -> Noun
67+tape s =
68+ String.toList s |> List.map String.fromChar |> listOf cord
69+
70+
71+listOf : (a -> Noun) -> List a -> Noun
72+listOf encEl list =
73+ case list of
74+ [] ->
75+ sig
76+
77+ x :: xs ->
78+ cell (encEl x) (listOf encEl xs)
79+
80+
81+sig : Noun
82+sig =
83+ Atom (BE.encode (BE.sequence []))
84+
85+
86+float32 : Float -> Noun
87+float32 f =
88+ Atom (BE.encode (BE.float32 LE f))
89+
90+
91+float64 : Float -> Noun
92+float64 f =
93+ Atom (BE.encode (BE.float64 LE f))
src/Urbit/Deconstructor.elm+18−6
@@ -23,6 +23,7 @@ module Urbit.Deconstructor exposing
2323import Bitwise
2424import Bytes exposing (Bytes, Endianness(..))
2525import Bytes.Decode as BD
26+import Bytes.Encode as BE
2627import Bytes.Extra
2728import Urbit exposing (..)
2829
@@ -85,12 +86,23 @@ int =
8586 (\x f ->
8687 case x of
8788 Atom bs ->
88− Bytes.Extra.toByteValues bs
89− |> List.foldr
90− (\b acc -> Bitwise.shiftLeftBy 8 acc |> Bitwise.or b)
91− 0
92− |> f
93− |> Just
89+ (case Bytes.width bs of
90+ 1 ->
91+ BD.decode BD.unsignedInt8 bs
92+
93+ 2 ->
94+ BD.decode (BD.unsignedInt16 LE) bs
95+
96+ 3 ->
97+ BD.decode (BD.unsignedInt32 LE) (BE.encode (BE.sequence [ BE.bytes bs, BE.unsignedInt8 0 ]))
98+
99+ 4 ->
100+ BD.decode (BD.unsignedInt32 LE) bs
101+
102+ _ ->
103+ Nothing
104+ )
105+ |> Maybe.map f
94106
95107 Cell _ ->
96108 Nothing
tests/Test/Urbit.elm+55
@@ -10,6 +10,7 @@ import List.Extra as List
1010import Test exposing (..)
1111import Test.Utils exposing (..)
1212import Urbit exposing (..)
13+import Urbit.Constructor as C
1314import Urbit.Deconstructor as D
1415
1516
@@ -148,6 +149,60 @@ tests =
148149 (Bytes.fromByteValues [ 0xC1, 0x20, 0xE4, 0x01 ])
149150 )
150151 )
152+ , test "65.600"
153+ (\() ->
154+ Expect.equal
155+ (Just 65600)
156+ (D.runBytes
157+ D.int
158+ (Bytes.fromByteValues [ 0xC0, 0x00, 0x02, 0x08 ])
159+ )
160+ )
161+ ]
162+ , describe "Constructor <-> Deconstructor"
163+ [ Test.fuzz
164+ (Fuzz.triple Fuzz.niceFloat Fuzz.int (Fuzz.intAtLeast 0))
165+ "[@rd @s @u]"
166+ (\( f, i, ui ) ->
167+ Expect.equal (Just ( f, i, ui ))
168+ (D.run
169+ (D.cell D.float64 (D.cell D.signedInt D.int) |> D.map (\a b c -> ( a, b, c )))
170+ (C.cell (C.float64 f) (C.cell (C.signedInt i) (C.int ui)))
171+ )
172+ )
173+ , Test.fuzz
174+ (Fuzz.list Fuzz.int)
175+ "~[@s]"
176+ (\x ->
177+ Expect.equal
178+ (Just x)
179+ (D.run
180+ (D.list D.signedInt)
181+ (C.listOf C.signedInt x)
182+ )
183+ )
184+ , Test.fuzz
185+ Fuzz.string
186+ "cord"
187+ (\x ->
188+ Expect.equal
189+ (Just x)
190+ (D.run
191+ D.cord
192+ (C.cord x)
193+ )
194+ )
195+ , Test.fuzz
196+ Fuzz.string
197+ "tape"
198+ (\x ->
199+ Expect.equal
200+ (Just x)
201+ (D.run
202+ D.tape
203+ (C.tape x)
204+ )
205+ )
151206 ]
152207 ]
153208