-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathlang.xxl
706 lines (608 loc) · 18.6 KB
/
lang.xxl
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
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
// This is an XXL table that contains information about most of the predefined
// verbs.
'lists,'values,'logic,'math,'misc,'stdlib as 'categories;
// GENERAL LISTS & LIST MANIPULATION -----------------------------------
['t:'unary,
'name:"enlist",
'op:"",
'desc:"if x is not a list, returns [x]. otherwise x.
(This differs from the `list` verb, because `list` will split
up a scalar into a list, which is a very different use case,
though the name we use is similar.)
",
'ex:[ ["1 enlist", (enlist 1)] ],
'seealso:["list"],
'cat:'lists,
'classes:'] make 'table,
['t:'unary,
'name:"flat",
'op:"",
'cat:'lists,
'desc:"attempt to remove one level of nesting of x; may return general list if not possible to fuse general list into vector",
'ex:[
["[1,2,[3,4,5]] flat",(1,2,3,4,5)],
["[1,2,[3,4,'z]] flat",[[1, 2], [3, 4, 'z]]]
],
'seealso:[],
'cat:'lists],
['t:'unary,
'name:"list",
'desc:"Converts vector x into a general list",
'ex:[ ["(1,2,3)vec",[1,2,3]] ],
'seealso:["vec"],
'cat:'lists],
['t:'binary,
'name:"join",
'op:"|,",
'desc:"join list x into new list (or vector, if all types match) with pieces joined together by y",
'ex:[
["1,2,3 join 0",(1,0,2,0,3)],
["[\"m\",\"ss\",\"ss\",\"pp\",\"\"] join \"i\"",["mississippi"]]
],
'cat:'lists,
'classes:'x],
['t:'binary,
'name:"split",
'op:"||",
'desc:"splits x into a list of pieces delimited by y.",
'ex:[
["1,7,2,7,3 split 7",[1,2,3]],
["\"/sd/imgs/1.jpg\" split \"/\"", ["", "sd", "imgs", "1.jpg"]]
],
'cat:'lists,
'classes:'x],
['t:'unary,
'name:"vec",
'desc:"transforms general list x into a same-type vector. returns x unmolested if not possible.",
'ex:[
["1,2,3vec",(1,2,3)]
],
'cat:'lists],
// VECTORS & THEIR VALUES ----------------------------------------------
['t:'binary,
'name:"catenate",
'op:",",
'desc:"normally known simply as `,`, catenate joins x to y",
'ex:[
["(1,2),3",(1,2,3)]
],
'cat:'values,
'classes:'x],
['t:'binary,
'name:"amend",
'op:"!",
'desc:"update parts of x according to instructions in y.
y is a list like [indices, values].
y's first element is the indices to modify in x. This may be a callable (such
as a function), in which case the indices for which the function returns
something truthy will be used as the list to update.
y's second element is the value(s) to set the indices to.
If it is a callable, it will be applied with the value of x@(y@0@n).
If y@0 is plural and y@1 is singular, all of x@(y@0) will be updated with
the same value: y@1.
What's really powerful about this technique is that you can generate your
lists of indices to update or values to apply via other means.
",
'ex:[
["(4,5,6)![1,10]",(4,10,6)],
["(4,5,6)![(0,2),10]",(10,5,10)],
["(4,5,6)![(0,2),(10,20)]",(10,5,20)],
["(4,5,6)![{%2=0},{*3}]",(12,5,18)]
],
'cat:'values],
['t:'unary,
'name:"first",
'desc:"returns first item of x",
'ex:[
["1,2,3 first",1]
],
'seealso:["behead","curtail","last"],
'cat:'values,
'classes:'x],
['t:'unary,
'name:"last", 'desc:"returns last item of x",
'ex:[
["1,2,3 last",3]
],
'seealso:["behead","curtail","first"],
'cat:'values,
'classes:'x],
['t:'unary,
'name:"behead",
'op:"|_",
'desc:"return x without its first element",
'ex:[["2,3,4 behead",(3,4)]],
'seealso:["curtail","first","last"],
'cat:'values,
'classes:'x],
['t:'unary,
'name:"curtail",
'op:"_|",
'desc:"return x without its last element. cute name amirite?",
'ex:[["2,3,4 curtail",(2,3)]],
'seealso:["behead","first","last"],
'cat:'values,
'classes:'x],
['t:'binary,
'name:"take",
'op:"#|",
'desc:"takes the first y pieces of x (which can be a vector or a list). use a negative value in y to take from the end of the list",
'ex:[
["1,7,2,7,3 take 2",(1,7)],
["1,7,2,7,3 take (2neg)",(7,3)]
],
'cat:'values,
'classes:'x],
['t:'binary,
'name:"drop",
'op:"|#",
'desc:"removes the first y pieces of x (which can be a vector or a list). use a negative value in y to drop from the end of the list",
'ex:[
["1,7,2,7,3 drop 2",(2,7,3)],
["1,7,2,7,3 drop (2neg)",(1,7,2)]
],
'cat:'values,
'classes:'x],
['t:'binary,
'name:"except",
'op:"|?",
'desc:"remove items in x that are present in y",
'ex:[
["1,7,2,7,3 except 7",(1,2,3)],
["1,7,2,7,3 except (7,1,8)",(2,3)]
],
'cat:'values,
'classes:'x],
['t:'binary, 'name:"from", 'op:".:",
'desc:"
`x from y` is equivalent to `y@x`, or simply `x y` if y were a function.
It's easier to read in this \"reverse order\" for some expression constructs,
and helps the XXL parser from getting confused if y is a list, dict, or
table. :)
",
'ex:[],
'cat:'misc,
'classes:'y],
['t:'binary,
'name:"extract",
'op:"",
'desc:"extract items from x according to y; returns a list: [extracted_items_dict, rest_of_x]
Use this to unpack data structures into identified parts and \"everything else\".
y should be a vector of names (tags). These symbols will be used to create a dictionary of the
matching values of x.
You can use the special tag ' to ignore the corresponding item of x.
Extract returns a list. The dictionary formed by the items you extracted is the
first element. The rest of x, after the last extracted value, is returned as
the second item in the result.
",
'ex:[
[
"\"http://txpo.st/test/a/b\" split \"/\" extract ('method,','host)",
[['method:"http:", 'host:"txpo.st"], ["test","a","b"]]
]
],
'cat:'values],
['t:'binary,
'name:"extractas",
'op:"",
'desc:"extract items from x according to y; creates locals and returns the rest of x.
y should be a vector of names (tags). these symbols will be created in the local context and
set to the value of the corresponding item of x.
Use this to unpack data structures into friendly variables to manipulate.
You can use the special tag ' to ignore the corresponding item of x.
The rest of x, after the last extracted value, is returned as the result. This lets you
compose extract with other verbs to build out elaborate parsers.
",
'ex:[
["\"http://txpo.st/test/a/b\" split \"/\" extract ('method,','host)",["test","a","b"]]
],
'cat:'values
],
['t:'binary,
'name:"del",
'desc:"Similar to `except`, but modifies x in-place. Works with lists and dicts in x. For vectors, consider using except. Use with due care - not changing values this way is clearer.",
'op:".:",
'ex:[ ["[1,2,3]as 't; t del 0; t",[2,3]] ],
'cat:'values,
'classes:'x],
['t:'unary,
'name:"len",
'desc:"Returns length of list or vector x",
'ex:[],
'cat:'values,
'classes:'x],
['t:'binary,
'name:"make",
'desc:"transforms x into typed denoted by tag in y (such as float).
See `types` for full list of types. Common ones include 'tag, 'char,
'byte, 'int, 'long, 'float.
`make` casts values of similar types to one another. If you are working
with strings and want to convert them to other types, you may be looking
for:
If you have a string containing a number and you want to convert it
to a numeric value, you probably want to use `base`, like:
```
\"1234\"base10
1234```
If you have a numeric value and want to convert it to a string, you
probably want `str`:
```
1234 str
\"1234\"```
`make` can also be used with a list of values on the left and a string indicating
the types to cast them to on the right. This is useful for decoding rows
of data such as csv. This is called \"make many\".
Each character in the format string identifies a type to convert the matching
item from the x to.
Use `s` for string, `i` for integer, `t` for tags, and `_` to skip the element
from x entirely.
Make many returns a list of values.",
'op:"$",
'ex:[
["4.5$'int",4],
["[\"123\",\"abc\",\"def\",\"xyz\"]$\"is_t\"",[123,"abc",'xyz]]
],
'cat:'values,
'classes:'y
],
['t:'unary,
'name:"ranges",
'desc:"breaks apart a vector into a list of consecutive ranges. order can be either ascending or descending.",
'ex:[
[
"1,2 ranges",
"[(1,2)]"
],
[
"1,3 ranges",
"[1,3]"
],
[
"2,1 ranges",
"[(2,1)]"
],
[
"3,1 ranges",
"[3,1]"
],
[
"1,2,4 ranges",
"[(1,2),4]"
],
[
"1,2,4,5,7,10,11,100,101,102,2,3,103 ranges",
[(1,2), (4,5), 7, (10,11), (100,101,102), (2,3), 103]
]
],
'cat:'values,
'classes:'
],
['t:'unary,
'name:"rev",
'desc:"returns vector x in reverse order",
'ex:[["3,7,9rev",(9,7,3)]],
'cat:'values,
'classes:'x],
['t:'unary,
'name:"key",
'desc:"Returns the keys/columns of dictionary/table x",
'ex:[ ["['name:'Tom,'city:'Miami]key",['name,'city']] ],
'seealso:["val"],
'cat:'values],
['t:'unary,
'name:"val",
'desc:"when x is a dict or table, return the values of x. Exception otherwise",
'ex:[ ["['name:'Tom,'city:'Miami]val",['Tom,'Miami]] ],
'seealso:["key"],
'cat:'values]
show,
// LOGIC ---------------------------------------------------------------
['t:'binary,
'name:"case",
'op:"",
'desc:"tests x against pairs of conditions in y and returns them (or, if callable, executes and returns them) if they match.
y should be a list or vector of the form (test1, result1, test2, result2, else?).
the last item may be an else result. it will be invoked/returned if nothing else matches
if provided, but you may omit it, in which case the value of x is returned unchanged.
Returns after first match.",
'ex:[
["1 case [1,7,2,6,8]",1],
["2 case [1,7,2,6,8]",6],
["3 case [1,7,2,6,8]",8],
["3 case [1,7,2,6]",3]
],
'cat:'logic
],
['t:'binary,
'name:"iftrue",
'desc:"returns y if x is truthy. if y is callable, y will be invoked with x as an argument.",
'ex:[["0 iftrue 2",0],["1 iftrue 2",2]],
'cat:'logic],
['t:'binary,
'name:"orelse",
'desc:"returns y if x is falsy. if y is callable, y will be invoked with x as an argument.",
'ex:[["0 orelse 2",2],["1 orelse 2",1]],
'cat:'logic],
['t:'binary,
'name:"ifelse",
'desc:"returns y[0] if x is truthy or y[1] otherwise. if y is callable it will be invoked with x as an argument.",
'ex:[["0 ifelse (3,4)",4],["1 ifelse (3,4)",3]],
'cat:'logic],
['t:'unary,
'name:"condense",
'oper:"~>",
'desc:"
Repeats each item of x the number of times that the value contains.
This is useful for expanding boolean lists used in XXL logic functions (like
0,1,1,1,0,1) into indices to manipulate other vectors.
",
'ex:[ ["0,0,1,0,0,1,1,0,0 condense", (2,5,6)] ],
'cat:'logic],
['t:'binary,
'name:"and",
'op:"&",
'desc:"Returns x&y.
if x or y is empty, null, or an exception, returns the other (y or x).
for same-sized vectors: returns a vector composed of the higher element of each (x,y) pair. this can
be used as \"max\" of two vectors.
",
'ex:[
["() or 0",0],
["1,2,1,4,4 or (4,3,0,2,2)",(4,3,1,4,4)]
],
'cat:'logic,
'classes:'x],
['t:'binary,
'name:"or",
'op:"|",
'desc:"Returns x|y.
if x or y is empty, null, or an exception, returns the other (y or x).
if x and y are dictionaries: returns the union of those dictionaries.
for same-sized vectors: returns a vector composed of the higher element of each (x,y) pair. this can
be used as \"max\" of two vectors.
",
'ex:[
["() or 0",0],
["1,2,1,4,4 or (4,3,0,2,2)",(4,3,1,4,4)]
],
'cat:'logic,'classes:'x],
['t:'unary, 'name:"not",
'desc:"transforms non-zeroes to zeroes and vice versa",
'ex:[["1,0,2not",(0,1,0)]],
'cat:'misc,'classes:'x],
['t:'binary,
'name:"match",
'op:"~",
'desc:"finds y in x; returns a one-hot array like (0,1,1,0,1,0) indicating true/false for each index of x",
'ex:[["1,2,3,2~2",(0,1,0,1)]],
'seealso:["condense"],
'cat:'logic],
['t:'binary,
'name:"pick",
'desc:"returns items of x which correspond to indices of y containing 1.
This is useful to use with functions like match that returns vectors of
0s and 1s.",
'ex:[
["1,2,3 as 'z pick (z~2 not)",(1,3)],
["\"abcdefg\" pick (0,1,1,0,1)","bce"]
],
'cat:'logic],
// LOOPING -------------------------------------------------------------
['t:'binary,
'name:"each",
'op:"::",
'desc:"
perform y for every item in x and return result as same type as x (or a
general list if not possible)
",
'ex:[["1,7,2,7,3 each {*2}",(2,14,4,14,6)]],
'cat:'looping
],
['t:'binary,
'name:"exhaust",
'desc:"
apply y to x and then again to that result over and over again until it
returns x or the same thing twice. Returns the last result.
",
'ex:[
["\"abc\"exhaust{rot1}","cab"]
],
'cat:'misc
],
['t:'binary,
'name:"recurse",
'desc:"
call y on x, and then again on the result of that, collecting all intermediate
results in a list, until it returns x again or the same thing twice. Similar
to exhaust, but returns all results along the way, rather than the last one.
",
'ex:[
["\"abc\"recurse{rot1}",["bca","cab"]]
],
'cat:'misc
],
// MATH ----------------------------------------------------------------
['t:'binary,
'name:"deal",
'desc:"create y random integers from 0 to x. Can also be used with a list
as x, which will return y random items from that list.",
'ex:[], 'cat:'math],
['t:'binary, 'name:"plus",
'op:"+",
'desc:"x+y",
'ex:[["5 count+(5 count * 3)",(0,4,8,12,16)]],
'cat:'math,
'classes:'x],
['t:'binary, 'name:"minus",
'op:"-",
'desc:"x-y",
'ex:[["5 count *3-(5 count)",(0,2,4,6,8)]],
'cat:'math,
'classes:'x],
['t:'unary, 'name:"min",
'desc:"Returns the minimum value in vector x",
'ex:[["(100neg),0,100 min",(100 neg)]],
'cat:'math],
['t:'unary, 'name:"max",
'desc:"Returns the maximum value in vector x",
'ex:[["(100neg),0,100 max",100]],
'cat:'math],
['t:'unary, 'name:"neg",
'desc:"Reverse the sign of all elements in x",
'ex:[["(10neg),0,13neg",(10,0,-13)]],
'cat:'math,'classes:'x],
['t:'binary,
'name:"range",
'desc:"returns a vector comprised of x .. y inclusive",
'ex:[],
'cat:'math],
['t:'unary,
'name:"sum",
'desc:"return the sum of each item in vector x",
'ex:[ ["5,2,9,6 sum",22] ],
'cat:'math,'classes:'x],
['t:'unary,
'name:"sums",
'desc:"returns the running total for each item in vector x",
'ex:[ ["5,2,9,6 sums",(5,7,16,22)] ],
'cat:'math,'classes:'x],
// MISC ----------------------------------------------------------------
['t:'binary,
'name:"aside",'op:"",
'desc:"
A convenience function: evaluate y but return x. This is useful in situations
where you want to use some verb against the value of the expression you've
built up, but don't want that verb's result to interrupt the next stage of
that expression.
",
'ex:[["fname .file.get aside {len show} parse",['parsetree]]],
'cat:'misc],
['t:'unary,
'name:"count",
'desc:"
Returns a vector of the integers between 0 and x-1.
These can be used as indices into another value or perhaps as a loop counter of sorts.",
'ex:[["5 count",(0,1,2,3,4)]],
'cat:'misc],
['t:'unary, 'name:"info",
'desc:"Returns a dictionary of information about x",
'ex:[
["1,2,3 info",
['typenum:4,'type:"int",'len:3, 'capacity:4, 'itemsz:4, 'alloced:0, 'baseptr:13519424, 'memptr:13519488]
]
],
'cat:'misc,'classes:'x],
['t:'unary,
'name:"parse",
'desc:"return the XXL parse string for string x",
'ex:[
["\"[1,(2,3)]*z\" parse",
"['listexpr([[], 'raw(\",\"), 1i, 'raw(\",\"), 'expr([2i, 'raw(\",\"), 3i])]), 'raw(\"*\"), 'name(\"z\"), 'ws(\"\n\")]"
]
],
'cat:'misc],
['t:'binary,
'name:"rot",
'desc:"rotate the contents of the vector x right by y positions. y may be negative",
'ex:[], 'cat:'misc],
['t:'unary,
'name:"show",
'op:"",
'desc:"display the value of x on the user's screen (depending on how the XXL
program is being run) and return that value so it can be used in the rest of
the expression. The formatting used is the same as the repr verb.",
'ex:[ ["1,2,3 show","1,2,3"] ],
'seealso:["emit", "repr","str"],
'cat:'misc],
['t:'binary,
'name:"emit",
'op:"",
'desc:"Debug x tagged with identifier y. This performs `[y,x] show`, but also injects your
value into the Xray debugging system, which allows you to trace the flow of your program.
Use this to understand what your program is doing.
emit returns x, so you can safely use it in the middle of expressions, much like `show`.",
'ex:[ ["16,18,22 emit 'ages", (16,18,22) ] ],
'seealso:["show"],
'cat:'misc],
['t:'unary,
'name:"type",
'desc:"Returns the type of x as a symbol",
'ex:[["[1,2.1,\"x\"]::type",['int, 'float, 'char]]],
'seealso:[],
'cat:'misc
],
// STRINGS -------------------------------------------------------------
['t:'unary,
'name:"repr",
'desc:
"return a text representation of x. This is usually close to what you'd type in to XXL to create that value",
'ex:[], 'cat:'strings,'classes:'x],
['t:'unary,
'name:"str",
'desc:
"return string representation of x. Compared to the repr verb this is usually a simpler version of the value",
'ex:[], 'cat:'strings,'classes:'x],
['t:'binary,
'name:"base",
'desc:"
if x is a string, assume it's a number in base y, and return that number as an XXL value.
if x is a number type, format it as a string in base y, and return that string.
", 'ex:[], 'cat:'strings],
// SYSTEM
['t:'unary,
'name:"sys",
'op:"",
'desc:"retrieve information about the current XXL environment by passing [] as x",
'ex:[
["[]sys",('ver:"v0",'srcpath:"/tmp/xxl")]
],
'cat:'system
],
['t:'unary,
'name:"any",
'desc:"returns 1 if any of the elements of x are nonzero",
'ex:[["0,0any",0],["0,1any",1]],
'cat:'misc],
['t:'unary,
'name:"arity",
'desc:"returns 1 for unary functions and 2 for binary functions. Useful when applying user defined functions",
'ex:[],
'cat:'misc],
['t:'unary,
'name:"clone",
'desc:"Creates a copy of x",
'ex:[],
'cat:'misc],
['t:'binary,
'name:"wide",
'desc:"invoke y for each item in list x, and then again for each member of the result that's a list, and so on. This is similar to a breadth first search of a tree. ",
'ex:[],
'cat:'misc],
['t:'unary,
'name:"xray",
'desc:"
Xray controls XXL debugging output.
Use `1 xray` to turn on
`0 xray` to turn off
`(function;argument) xray` returns timing information when invoking `function @ argument`
",
'ex:[],
'cat:'misc],
// TODO
['t:'unary, 'name:"selftest", 'desc:"", 'ex:[], 'cat:'misc],
['t:'unary, 'name:"tag", 'desc:"", 'ex:[], 'cat:'misc],
['t:'binary, 'name:"bracketj", 'desc:"", 'ex:[], 'cat:'misc],
['t:'binary, 'name:"consecj", 'desc:"", 'ex:[], 'cat:'misc],
['t:'binary, 'name:"deep", 'desc:"invokes y for each nested list in x", 'ex:[], 'cat:'misc],
['t:'binary, 'name:"eachl", 'desc:"", 'ex:[], 'cat:'misc],
['t:'binary, 'name:"eachr", 'desc:"", 'ex:[], 'cat:'misc],
['t:'binary, 'name:"evalin", 'desc:"", 'ex:[], 'cat:'misc],
['t:'binary, 'name:"get", 'desc:"", 'ex:[], 'cat:'misc],
['t:'binary, 'name:"in", 'desc:"", 'ex:[], 'cat:'misc],
['t:'binary, 'name:"loadin", 'desc:"", 'ex:[], 'cat:'misc],
['t:'binary, 'name:"nest", 'desc:"", 'ex:[], 'cat:'misc],
['t:'binary, 'name:"over", 'desc:"", 'ex:[], 'cat:'misc],
['t:'binary, 'name:"scan", 'desc:"", 'ex:[], 'cat:'misc]
as 'verbs
// export:
[categories, verbs]