-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexample.rpn
403 lines (321 loc) · 10.4 KB
/
example.rpn
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
5 value => 5
{ 3 } value => 3
{ 3 6 + } value => 9
{ { 3 6 + } } value => { 3 6 + }
{ { 3 6 + } } vvalue => 9
{ { { 3 6 + } } } vvalue => 9 # vvalue recursively calls value till the argument is fully evaluated
5 6 discard => 5 # discard removes the top value from the stack
5 6 puts => 5 # puts writes the top value on the stack out to the terminal (to_s handling?)
FalseValue TrueValue Conditional if
FalseValue else TrueValue Conditional if
# if (Conditional vvalue) is truthy => TrueValue
# if (Conditional vvalue) is not truthy => FalseValue
# in this case else is a no-op, it expands to nothing.
5 8 true if => 8
5 8 false if => 5
{ 3 5 + } 6 true if value => 6 # The block is not evaluated at all in this case
{ 3 5 + } 6 false if value => 8
[A]{ 3 } value => [A]{ 3 } # Only 0-arity blocks get evaluated
5 [A]{ 3 A + } call => 3 5 + => 8
{ 3 6 + } call => 3 6 + => 9 # call on 0-arity blocks is equivalent to value
3 5 [First Second]{ First First Second + * } call
=> 3 5 [Second]{ [First]{ First First Second + * } call } call # multi-arity blocks get converted to a sequence of 1-arity blocks
=> 3 [First]{ First First 5 + * } call # call substitutes
=> 3 3 5 + * # call substitutes
=> 3 8 * # expression is evaluated
=> 24 # expression is evaluated
{ 3 5 + } dup => { 3 5 + } { 3 5 + }
{ 3 } { 7 } + => 10 # built-in arithmetic and logical operators call vvalue on both arguments
{ 3 5 + } dup + => 16 # Block is only evaluated once, 0-arity + immutability means the return value cannot change so the result is cached after the first evaluation
{ 3 5 + } { 3 5 + } + => 16 # Both blocks are evaluated, multiple definitions of equivalent blocks still result in different blocks
[First Second]{ First Second First if } => [Second]{ [First]{ First Second First if } call }
[First Second]{ First Second First if } andand def
andand => [Second]{ [First]{ First Second First if } call } call
# def causes the preceding identifier to expand to the preceding block followed
# by call
false true andand
=> false true [Second]{ [First]{ First Second First if } call } call
=> true [First]{ First true First if } call
=> false true false if
=> false
true false andand
=> true false [Second]{ [First]{ First Second First if } call } call
=> true [First]{ First false First if } call
=> true false true if
=> false
true true andand => true
false true andand => false
true false andand => false
false false andand => false
{ false } { true } andand
=> { false } { true } [Second]{ [First]{ First Second First if } call } call
=> { true } [First]{ First { true } First if } call
=> { false } { true } { false } if
=> { false } { true } false if
=> { false }
[Value]{ Value 1 - } -- def
[Value]{ Value 1 + } ++ def
{ true } { true } andand => { true }
{ false } { true } andand => { false }
{ true } { false } andand => { false }
{ false } { false } andand => { false }
[First Second]{ Second First First if } oror def
{ true } { true } oror => { true }
{ false } { true } oror => { true }
{ true } { false } oror => { true }
{ false } { false } oror => { false }
error # when error is called it errors the entire tree, should there be some exception handling?
# wrap it in a block to allow conditional errors
[Value] { true { error } Value 1 == if value } error_if_one def
{
# new list
{ [Getter]{ true { error } { create } Getter call } } create def
# prepend a value onto a list
[Value List]{ [Getter] { false { List } { Value } Getter call } } unshift def
# the first value in a list
[List]{ [Empty Tail Head]{ Head value } List call } head def
# the rest of the values in a list
[List]{ [Empty Tail Head]{ Tail value } List call } tail def
# the first value in a list then the rest of the list
[List]{ [Empty Tail Head]{ Head value Tail value } List call } split def
# if a list is empty
[List]{ [Empty Tail Head]{ Empty } List call } empty? def
} list namespace
# sum of values in a list
[List]{
[Acc Head Tail]{
{ Acc Head + Tail list::split list_sum_inner }
{ Acc Head + }
Tail list::empty? if value
} list_sum_inner def
0 List list::split list_sum_inner
} list_sum def
# max value of a pair of values
[First Second]{ First Second First Second < if } max def
# max value in a list
[List]{
[Acc Head Tail]{
{ Acc Head max Tail list::split list_max_inner }
{ Acc Head max }
Tail list::empty? if value
} list_max_inner def
{ 0 List list::split list_max_inner }
{ error }
List list::empty? if value
} list_max def
# value of Pascal's triangle at specified row and col
[Col Row]{
{ Col Row 1 - pascal Col 1 - Row 1 - pascal + }
else
1
Row 0 == if else
0
Col Row > Col 0 < oror if value
} pascal def
# if parantheses balance
[Chars]{
[Char]{
0 -1 char ')' == if 1 char '(' == if
} charVal def
[Count Chars]{
{Count Chars list::head charVal + Chars list::tail inner_balance }
else
false
Count 0 < if else
count 0 ==
Chars list::empty? if value
} inner_balance def
0 Chars bal
} balance def
# how many ways to make `money` change from `coins`
[Money, Coins]{
{ Money Coins list::head - Coins countChange Money Coins list::tail countChange }
else
0
money 0 < Coins list::empty? || if else
1
money 0 == if value
} countChange def
# whether a function set contains an element
[Set, Elem]{
Elem Set call
} contains def
# create a singleton set
[Elem]{
[Value]{ Elem Value == }
} singletonSet def
# create the union set of two sets
[Set, OtherSet]{
[Value]{ { Set Value contains } { OtherSet Value contains } || value }
} union def
# create the intersection set of two sets
[Set, OtherSet]{
[Value]{ { Set Value contains } { OtherSet Value contains } && value }
} intersect def
# return the subset of a set for which a predicate holds
[Set, Predicate]{
[Value]{ { Set Value contains } { Value Predicate call } && value }
} filter def
# return a set containing elements in the first set that are not in the second
# set
[Set, OtherSet]{
[Value]{ { Set Value contains } { OtherSet Value contains not } && value }
} diff def
# Whether all elements between -1000 and 1000 contained in a set are satisfied
# by a predicate
[Set, Predicate]{
[Value]{
{ Value 1 + iter }
else
false
{ Set Value contains Value Predicate call not && } if
true
Value 1000 > if value
} iter def
-1000 iter
} forall def
# Whether there exists an element between -100 and 1000 that satisfies a
# predicate
[Set, Predicate]{
Set [Value]{ Value Predicate call not } forall not
} exists def
# return a set that contains all elements of an existing set transformed by a
# function
[Set, Transform]{
[Value]{ Set [Test]{ Test Transform call Value == } exists }
} map def
[User, Text, Retweets]{
{
{ User } user def
{ Text } text def
{ Retweets } retweets def
}
} tweet def
[TweetOne, TweetTwo]{
{
{ TweetOne } one def
{ TweetTwo } two def
}
} tweet_pair def
[Tweet]{
Tweet [Obj]{ { Obj [This]{ user } call } Obj bind call } call
} get_user def
[Tweet]{
Tweet.text
} get_text def
[TweetPair]{
TweetPair [Obj]{ Obj [This]{ one } call } Obj bind call } call
[Obj]{ Obj [This]{ user } call } Obj bind call } call
} get_first_user def
[TweetPair]{
TweetPair.one.text
} get_first_text def
# so A.b => A [O]{ O [This]{ b } call } O bind call } call
# so A.b.c => (A.b).c
# => A.b [O]{ O [This]{ c } call } O bind call } call
# => A [O]{ O [This]{ b } call } O bind call } call [O]{ O [This]{ c } call } O bind call } call
"user" "text" 5 tweet get_user
{
{
{ This.head This.tail.find_min_0 } find_min def
[Filter]{ Filter empty_tweet_set This.filter0 } filter def
}
} tweet_set def
{
{
[Tweet]{ false } contains? def
[Tweet]{ Tweet empty_tweet_set empty_tweet_set non_empty_tweet_set } include def
{ true } is_empty? def
{ error } head def
{ error } tail def
[Tweet]{ This } remove def
[CurrentMin]{ CurrentMin } find_min_0 def
[Function]{ } foreach def
} tweet_set bind
} empty_tweet_set def
[Elem, Left, Right]{
{
[Tweet]{
true
Tweet Right.contains?
Elem.text Tweet.text < if
Tweet Left.contains?
Tweet.text Elem.text < if
} contains? def
[Tweet]{
{ This }
{ Elem Left Tweet Right.include non_empty_tweet_set }
Elem.text Tweet.text < if
{ Elem Tweet Left.include Right non_empty_tweet_set }
Tweet.text Elem.text < if
} include def
{ false } is_empty? def
{ { Left.head } { Elem } Left.is_empty? if } head def
{ { Elem Left.tail Right non_empty_tweet_set } { Right } Left.is_empty? if } head def
[Tweet]{
{ Right Left.union }
{ Elem Left Tweet Right.remove non_empty_tweet_set }
{ Elem.text Tweet.text < } if
{ Elem Tweet Left.remove Right non_empty_tweet_set }
{ Tweet.text Elem.text < } if
value
} remove def
[CurrentMin]{
CurrentMin
This.head
This.head.retweets CurrentMin.retweets < if This.tail.find_min_0
} find_min_0 def
[Function]{
This.head Function call Function This.tail.foreach
} foreach def
} tweet_set bind
} non_empty_tweet_set def
# Reimplemented list
{
{
[Value]{ This Value non_empty_list } unshift def
{ This.head This.tail } split def
}
} list def
{
{
{ error } head def
{ error } tail def
{ true } empty? def
} list bind
} empty_list def
[Tail, Head]{
{
{ Head } head def
{ Tail } tail def
{ false } empty? def
} list bind
} non_empty_list def
[Elems Count]{
[Acc Count]{
{ Acc } { Acc.unshift Count -- inner } Count 0 > if value
} inner def
Elems call empty_list Count inner
} create_list def
# reimplemented sum of values in a list
[List]{
[Acc List]{
{ Acc List.head + List.tail inner }
{ Acc }
List.empty? if value
} inner def
0 List inner
} list_sum def
# reimplemented max value in a list
[List]{
[Acc Head Tail]{
{ Acc Head max Tail.split inner }
{ Acc Head max }
Tail.empty? if value
} inner def
{ 0 List.split inner }
{ error }
List.empty? if value
} list_max def
{ 6 2 7 6 1 } 5 create_list list_max #=> 7
{ 6 2 7 6 1 } 5 create_list list_sum #=> 22