spitewaste 0.1.005 → 0.1.006
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +2 -1
- data/lib/spitewaste/assembler.rb +4 -4
- data/lib/spitewaste/cli/docs.rb +1 -1
- data/lib/spitewaste/libspw/array.spw +69 -18
- data/lib/spitewaste/libspw/bits.spw +70 -70
- data/lib/spitewaste/libspw/case.spw +34 -28
- data/lib/spitewaste/libspw/docs.json +1 -1
- data/lib/spitewaste/libspw/fun.spw +34 -22
- data/lib/spitewaste/libspw/math.spw +1 -1
- data/lib/spitewaste/libspw/string.spw +18 -18
- data/lib/spitewaste/libspw/util.spw +7 -4
- data/lib/spitewaste/parsers/spitewaste.rb +15 -1
- data/lib/spitewaste/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17fcfab8a738ff0666343f1456c4608f0b721a7e8a1a1dc89887c18b258d538c
|
4
|
+
data.tar.gz: 7d923d804a932d6a055804a616ae6b518db37ca87006bf049ecd2a590477c10a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c2b108463c434fed7f09d5a6b922c0363cf979ed9ba89a3bd731dba0436e7ed39da71d9ffc76ad1f8f3c9b5ba3ad58405bf9777443e8d3f116a4eb7001d4ba44
|
7
|
+
data.tar.gz: 07e9108b800fa22b36cf033b57eb6d8fdc5df3a73e3d19e2385093ea9a5dc4fc91bfddb23620ab4df6cbe28dc17f24a3ce86d3bb5c88b156b5ffc223184376c9
|
data/Rakefile
CHANGED
@@ -14,7 +14,8 @@ task :docs do |t|
|
|
14
14
|
docs = {}
|
15
15
|
|
16
16
|
Dir.chdir('lib/spitewaste/libspw') do |d|
|
17
|
-
|
17
|
+
Dir['*.spw'].each do |path|
|
18
|
+
next if path['random']
|
18
19
|
lib = File.basename path, '.spw'
|
19
20
|
docs[lib] = extract_docs path
|
20
21
|
end
|
data/lib/spitewaste/assembler.rb
CHANGED
@@ -9,7 +9,7 @@ module Spitewaste
|
|
9
9
|
raise ArgumentError, "unknown format for parse: #{format}"
|
10
10
|
end
|
11
11
|
|
12
|
-
|
12
|
+
parser =
|
13
13
|
case format
|
14
14
|
when :whitespace
|
15
15
|
WhitespaceParser
|
@@ -19,9 +19,9 @@ module Spitewaste
|
|
19
19
|
SpitewasteParser
|
20
20
|
end
|
21
21
|
|
22
|
-
parser =
|
23
|
-
@instructions = parser.instructions
|
24
|
-
@src = parser.src if format == :spitewaste
|
22
|
+
@parser = parser.new(program, **options).tap &:parse
|
23
|
+
@instructions = @parser.instructions
|
24
|
+
@src = @parser.src if format == :spitewaste
|
25
25
|
end
|
26
26
|
|
27
27
|
def assemble! format:, io: STDOUT, **options
|
data/lib/spitewaste/cli/docs.rb
CHANGED
@@ -41,7 +41,7 @@ class SpitewasteCLI
|
|
41
41
|
|
42
42
|
IO.popen('less -R', 'w') do |io|
|
43
43
|
found.each do |lib, fn, full|
|
44
|
-
full.gsub! /#{terms * ?|}
|
44
|
+
full.gsub! /#{terms * ?|}/i, &method(:hi)
|
45
45
|
desc, specs = full.split "\n\n"
|
46
46
|
io.puts "#{?- * 10}\n#{lib}/#{bold under fn} #{desc}\n\n"
|
47
47
|
io.puts specs if options[:show_specs]
|
@@ -1,21 +1,57 @@
|
|
1
|
+
;;; Pseudo-arrays
|
2
|
+
|
3
|
+
; An "array" is really just a sequence of elements on the stack followed by
|
4
|
+
; the number of elements, so care must be taken to ensure one knows what kind
|
5
|
+
; of data is currently being operated on.
|
6
|
+
|
1
7
|
import math ; divmod, max, min, pos?
|
2
8
|
import stack ; bury, dig, ncopy, nslide, roll
|
3
9
|
import util ; dec, die!, eq
|
4
10
|
|
5
11
|
$amax = 1000
|
6
12
|
|
13
|
+
; returns the sum of the array A
|
14
|
+
; [A] => [sum]
|
15
|
+
;
|
16
|
+
; [3 1] => [3]
|
17
|
+
; [4 3 2 1 4] => [10]
|
18
|
+
; [-10 -5 7 5 10 5] => [7]
|
7
19
|
arysum: reduce (add) ret
|
8
20
|
|
21
|
+
; duplicates the array at the top of the stack
|
22
|
+
; [A] => [A A]
|
23
|
+
;
|
24
|
+
; [1 2 3 3] => [1 2 3 3 1 2 3 3]
|
25
|
+
; [7 50 10 2] => [7 50 10 2 50 10 2]
|
9
26
|
arydup:
|
10
27
|
dup $++ push -2 copy 1 store
|
11
28
|
times (push -2 load $-- :ncopy) ret
|
12
29
|
|
30
|
+
; removes the element at the end of the array A
|
31
|
+
; [A] => [A']
|
32
|
+
;
|
33
|
+
; [10 1] => [0]
|
34
|
+
; [1 2 3 4 4] => [1 2 3 3]
|
35
|
+
; [7 10 20 30 3] => [7 10 20 2]
|
13
36
|
arypop: slide 1 $-- ret
|
14
37
|
|
38
|
+
; removes the element at the beginning of the array A
|
39
|
+
; [A] => [A']
|
40
|
+
;
|
41
|
+
; [10 1] => [0]
|
42
|
+
; [1 2 3 4 4] => [2 3 4 3]
|
43
|
+
; [7 10 20 30 3] => [7 20 30 2]
|
15
44
|
aryshift: dup :dig $-- ret
|
16
45
|
|
46
|
+
; returns the concatenation of arrays A and B
|
47
|
+
; [A B] => [A+B]
|
48
|
+
;
|
49
|
+
; [1 2 3 3 4 5 6 3] => [1 2 3 4 5 6 6]
|
50
|
+
; [7 10 2 5 4 3 3] => [7 10 5 4 3 5]
|
17
51
|
arycat: dup $++ :roll add ret
|
18
52
|
|
53
|
+
;;;
|
54
|
+
|
19
55
|
arypack:
|
20
56
|
:arydup reduce (:max) $++ push -1 swap store
|
21
57
|
$-- times (push -1 load mul add)
|
@@ -30,36 +66,43 @@ aryunpack:
|
|
30
66
|
|
31
67
|
arylen: push $amax mod ret
|
32
68
|
|
33
|
-
|
34
|
-
|
69
|
+
; returns the index I of element E in array A (or -1 if not found)
|
70
|
+
; [A E] => [I]
|
71
|
+
;
|
72
|
+
; [1 2 3 4 4 2] => [1]
|
73
|
+
; [1 2 3 4 4 4] => [3]
|
74
|
+
; [1 2 3 4 4 5] => [-1]
|
35
75
|
aryindex: copy 1 ; two copies of length, one gets decremented, index is diff
|
36
|
-
_aryindex_loop:
|
37
|
-
dup jn _aryindex_notfound
|
76
|
+
_aryindex_loop: dup jn _aryindex_notfound
|
38
77
|
dup push 2 add :roll copy 2 :eq jz _aryindex_no
|
39
78
|
copy 2 copy 1 sub swap $++ :nslide ret
|
40
|
-
|
41
79
|
_aryindex_no: $-- jump _aryindex_loop
|
42
|
-
|
43
80
|
_aryindex_notfound: slide 1 ret
|
44
81
|
|
45
|
-
|
46
|
-
|
47
|
-
;
|
48
|
-
|
82
|
+
; returns the element E at index I in array A (or dies on out of bounds)
|
83
|
+
; [A I] => [E]
|
84
|
+
;
|
85
|
+
; [1 2 3 4 4 0] => [1]
|
86
|
+
; [1 2 3 4 4 2] => [3]
|
87
|
+
; [1 2 3 4 4 -1] => [4] negative index counts from the end
|
88
|
+
aryat:
|
49
89
|
dup jn _aryat_neg
|
50
90
|
copy 1 swap sub dup :pos? jz _aryat_oob
|
51
91
|
:roll swap $-- :nslide ret
|
52
|
-
|
53
92
|
_aryat_neg: copy 1 add dup jn _aryat_oob jump aryat
|
54
|
-
|
55
93
|
_aryat_oob: push "(aryat) index out of bounds!" :die!
|
56
94
|
|
95
|
+
; returns the minimum and maximum elements of array A
|
96
|
+
; [A] => [min max]
|
97
|
+
;
|
98
|
+
; [4 3 2 1 4] => [1 4]
|
99
|
+
; [6 8 -3 4 0 5] => [-3 8]
|
100
|
+
; [7 1] => [7 7]
|
57
101
|
minmax:
|
58
|
-
:arydup reduce (:max)
|
59
|
-
push -1 swap store
|
102
|
+
:arydup reduce (:max) push -1 swap store
|
60
103
|
reduce (:min) push -1 load ret
|
61
104
|
|
62
|
-
;;;
|
105
|
+
;;; TODO: make sort not atrociously inefficient
|
63
106
|
|
64
107
|
sort: push -3 copy 1 store ; preserve length
|
65
108
|
_sort_loop:
|
@@ -70,17 +113,25 @@ _sort_loop:
|
|
70
113
|
push 0 copy 1 sub jn _sort_loop
|
71
114
|
push 3 sub load ret
|
72
115
|
|
116
|
+
; reverses the array A
|
117
|
+
; [A] => [A']
|
118
|
+
;
|
119
|
+
; [1 2 3 3] => [3 2 1 3]
|
120
|
+
; [7 1] => [7 1]
|
121
|
+
; [5 4 3 2 1 5] => [1 2 3 4 5 5]
|
73
122
|
aryrev: push -3 copy 1 store
|
74
123
|
_aryrev_loop:
|
75
124
|
swap copy 1 :bury $--
|
76
125
|
push 0 copy 1 sub jn _aryrev_loop
|
77
126
|
push 3 sub load ret
|
78
127
|
|
79
|
-
|
80
|
-
|
128
|
+
; returns the array A replicated N times
|
129
|
+
; ! N must be greater than 1
|
130
|
+
; [A N] => [A']
|
131
|
+
;
|
132
|
+
; [3 2 1 3 4] => [3 2 1 3 2 1 3 2 1 3 2 1 12]
|
81
133
|
aryrep: push -1 swap push -3 copy 1 store store
|
82
134
|
_aryrep_loop:
|
83
135
|
push -1 dup :dec load jz _aryrep_done
|
84
136
|
:arydup jump _aryrep_loop
|
85
|
-
|
86
137
|
_aryrep_done: push -3 load $-- times (:arycat) ret
|
@@ -1,74 +1,74 @@
|
|
1
|
-
import math
|
2
|
-
import
|
3
|
-
|
4
|
-
|
5
|
-
;
|
6
|
-
|
7
|
-
;
|
8
|
-
;
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
copy
|
15
|
-
|
16
|
-
|
17
|
-
push
|
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
|
-
_bitwise_xor_update: :_bitwise_update jump _bitwise_xor_loop
|
58
|
-
|
59
|
-
; flip all bits in n ; [n]
|
60
|
-
bitwise_not:
|
1
|
+
import math ; ilog, pow
|
2
|
+
import util ; digits
|
3
|
+
|
4
|
+
; The bitwise operators all work very similarly, differing only in how they
|
5
|
+
; map pairs of bits to 0 or 1. For AND, we simply multiply them. For OR, we
|
6
|
+
; sum them, add 1, then divide by 2. For XOR, we only want 1 if they're neq.
|
7
|
+
; We repeatedly halve the inputs while consuming bits and stop when at least
|
8
|
+
; one of them becomes zero. For AND, the answer is in the accumulator and we
|
9
|
+
; are done. For OR and XOR, it's likely the nonzero input still has bits to
|
10
|
+
; contribute, so we also accumulate its product with the current power of 2.
|
11
|
+
$bitfun(op, bit, done) {
|
12
|
+
push -2,1,-1,0 store store
|
13
|
+
_`op`_loop: push -1
|
14
|
+
copy 2 push 2 mod copy 2 push 2 mod `bit`
|
15
|
+
push -1 load swap push -2 load dup push 2 mul
|
16
|
+
push -2 swap store mul add store
|
17
|
+
push 2 div swap push 2 div
|
18
|
+
dup copy 2 mul jz _`op`_done swap jump _`op`_loop
|
19
|
+
_`op`_done: `done` ret
|
20
|
+
}
|
21
|
+
|
22
|
+
; returns the bitwise AND of A and B
|
23
|
+
; [A B] => [A & B]
|
24
|
+
;
|
25
|
+
; [65 47] => [1] [83 25] => [17]
|
26
|
+
; [40 64] => [0] [74 59] => [10]
|
27
|
+
; [31 18] => [18] [86 32] => [0]
|
28
|
+
; [93 79] => [77] [11 79] => [11]
|
29
|
+
band: $bitfun(band, mul, mul $-- load)
|
30
|
+
|
31
|
+
; returns the bitwise OR of A and B
|
32
|
+
; [A B] => [A | B]
|
33
|
+
;
|
34
|
+
; [66 51] => [115] [64 4] => [68]
|
35
|
+
; [61 77] => [125] [93 65] => [93]
|
36
|
+
; [14 87] => [95] [71 37] => [103]
|
37
|
+
; [7 19] => [23] [38 92] => [126]
|
38
|
+
bor: $bitfun(bor, add $++ push 2 div, add push -2 load mul push -1 load add)
|
39
|
+
|
40
|
+
; returns the bitwise XOR of A and B
|
41
|
+
; [A B] => [A ^ B]
|
42
|
+
;
|
43
|
+
; [4 14] => [10] [0 80] => [80]
|
44
|
+
; [51 5] => [54] [97 77] => [44]
|
45
|
+
; [39 65] => [102] [12 26] => [22]
|
46
|
+
; [44 36] => [8] [6 21] => [19]
|
47
|
+
bxor: $bitfun(bxor, :neq, add push -2 load mul push -1 load add)
|
48
|
+
|
49
|
+
; returns the infinite-precision bitwise NOT of N by inverting all of its bits
|
50
|
+
; [N] => [~N]
|
51
|
+
;
|
52
|
+
; [58] => [5] [46] => [17]
|
53
|
+
; [48] => [15] [87] => [40]
|
54
|
+
; [98] => [29] [51] => [12]
|
55
|
+
; [3] => [0] [42] => [21]
|
56
|
+
bnot:
|
61
57
|
dup push 0 swap push 1 add sub
|
62
58
|
swap push 2 :ilog push 2 swap :pow mod ret
|
63
59
|
|
64
|
-
|
65
|
-
|
66
|
-
;
|
60
|
+
; returns the number of bits in the binary representation of N
|
61
|
+
; [N] => [# of bits]
|
62
|
+
;
|
63
|
+
; [0] => [0] [1] => [1]
|
64
|
+
; [7] => [3] [8] => [4]
|
65
|
+
; [255] => [8]
|
66
|
+
blength: dup jz _blength_zero push 2 :ilog $++ ret
|
67
|
+
_blength_zero: ret
|
68
|
+
|
69
|
+
; returns the number of set bits in N
|
70
|
+
; [N] => [popcount]
|
71
|
+
;
|
72
|
+
; [0] => [0] [1] => [1]
|
73
|
+
; [7] => [3] [8] => [1]
|
67
74
|
popcount: push 2 :digits reduce (add) ret
|
68
|
-
|
69
|
-
;;;
|
70
|
-
|
71
|
-
; most significant set bit in n, as a power of 2 ; [n]
|
72
|
-
msb: dup jz _msb_zero
|
73
|
-
push 2 :itos :strlen $-- push 2 swap :pow ret
|
74
|
-
_msb_zero: ret
|
@@ -1,34 +1,40 @@
|
|
1
|
-
import bits ; bitwise_and, bitwise_or, bitwise_xor
|
2
|
-
import string ; isalpha, strcat, strunpack
|
3
|
-
|
4
1
|
;;; Case conversion
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
swap dup jz _upcase_done
|
9
|
-
dup :isalpha jz _upcase_cat
|
10
|
-
push 95 :bitwise_and
|
11
|
-
_upcase_cat:
|
12
|
-
:strcat jump _upcase_loop
|
13
|
-
|
14
|
-
_upcase_done: pop ret
|
3
|
+
import bits ; band, bor, bxor
|
4
|
+
import string ; isalpha, strcat, strunpack
|
15
5
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
6
|
+
; The case conversion functions all behave very similarly, differing only in
|
7
|
+
; how they modify the ordinal value V of a character to be kept.
|
8
|
+
; upcase is V & 95, downcase is V | 32, and swapcase is V ^ 32.
|
9
|
+
$casefun(case, op) {
|
10
|
+
:strunpack push 0 ; get characters on stack and initialize accumulator
|
11
|
+
_`case`_loop: swap dup jz _`case`_done dup :isalpha jz _`case`_cat `op`
|
12
|
+
_`case`_cat: :strcat jump _`case`_loop
|
13
|
+
_`case`_done: pop ret
|
14
|
+
}
|
23
15
|
|
24
|
-
|
16
|
+
; returns string S with all alphabetical characters capitalized
|
17
|
+
; [S] => [S']
|
18
|
+
;
|
19
|
+
; [""] => [""]
|
20
|
+
; ["abc"] => ["ABC"]
|
21
|
+
; ["123"] => ["123"]
|
22
|
+
; ["Abc123Def"] => ["ABC123DEF"]
|
23
|
+
upcase: $casefun(upcase, push 0x5F :band)
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
; returns string S with all alphabetical characters lower-cased
|
26
|
+
; [S] => [S']
|
27
|
+
;
|
28
|
+
; [""] => [""]
|
29
|
+
; ["ABC"] => ["abc"]
|
30
|
+
; ["123"] => ["123"]
|
31
|
+
; ["aBC123dEF"] => ["abc123def"]
|
32
|
+
downcase: $casefun(downcase, push 0x20 :bor)
|
33
33
|
|
34
|
-
|
34
|
+
; returns string S with the case of all alphabetical characters swapped
|
35
|
+
; [S] => [S']
|
36
|
+
;
|
37
|
+
; [""] => [""]
|
38
|
+
; ["FooBar"] => ["fOObAR"]
|
39
|
+
; ["Abc123deF"] => ["aBC123DEf"]
|
40
|
+
swapcase: $casefun(swapcase, push 0x20 :bxor)
|
@@ -1 +1 @@
|
|
1
|
-
{"rational":{"to_r":{"full":"encodes a numerator N and a denominator D as a rational number R with the\nfollowing structure: ((N × $RAT + D) << 1) + sign (0 for negative, else 1).\nThis representation is nice because, with care, it makes it so that we never\nhave to involve the heap (besides divmod) just to do fairly basic arithmetic.\n[N D] => [R]\n\n[22 7] => [R(22,7)]\n[4 8] => [R(4,8)] ; no implicit simplification TODO: make it configurable?\n[5 1] => [R(5,1)] ; no conversion to integer (duh)\n[-3 4] => [R(-3,4)]\n[3 -4] => [R(-3,4)] ; sign always held in the numerator\n[-1 -3] => [R(1,3)]\n","desc":"encodes a numerator N and a denominator D as a rational number R with the\nfollowing structure: ((N × $RAT + D) << 1) + sign (0 for negative, else 1).\nThis representation is nice because, with care, it makes it so that we never\nhave to involve the heap (besides divmod) just to do fairly basic arithmetic.","effect":"[N D] => [R]","cases":[[[22,7],[94489280527]],[[4,8],[17179869201]],[[5,1],[21474836483]],[[-3,4],[12884901896]],[[3,-4],[12884901896]],[[-1,-3],[4294967303]]]},"ratnum":{"full":"returns the numerator N of the rational number R, which may be negative\n[R] => [N]\n\n[R(22,7)] => [22]\n[R(-3,4)] => [-3]\n[R(3,-4)] => [-3]\n","desc":"returns the numerator N of the rational number R, which may be negative","effect":"[R] => [N]","cases":[[[94489280527],[22]],[[12884901896],[-3]],[[12884901896],[-3]]]},"ratden":{"full":"returns the denominator D of the rational number R; always positive\n[R] => [D]\n\n[R(22,7)] => [7]\n[R(-3,4)] => [4]\n[R(3,-4)] => [4]\n","desc":"returns the denominator D of the rational number R; always positive","effect":"[R] => [D]","cases":[[[94489280527],[7]],[[12884901896],[4]],[[12884901896],[4]]]},"from_r":{"full":"decomposes the rational number R into its numerator N and denominator D\n[R] => [N D]\n\n[R(22,7)] => [22 7]\n[R(-3,4)] => [-3 4]\n[R(3,-4)] => [-3 4]\n[R(4,8)] => [4 8] ; no implicit simplification\n","desc":"decomposes the rational number R into its numerator N and denominator D","effect":"[R] => [N D]","cases":[[[94489280527],[22,7]],[[12884901896],[-3,4]],[[12884901896],[-3,4]],[[17179869201],[4,8]]]},"ratsimp":{"full":"fully simplifies the rational number R by dividing both of its components\nby their greatest common divisor\n[R] => [R, simplified]\n\n[R(4,8)] => [R(1,2)]\n[R(-3,12)] => [R(-1,4)]\n[R(17,-51)] => [R(-1,3)]\n","desc":"fully simplifies the rational number R by dividing both of its components\nby their greatest common divisor","effect":"[R] => [R, simplified]","cases":[[[17179869201],[4294967301]],[[12884901912],[4294967304]],[[73014444134],[4294967302]]]},"ratadd":{"full":"returns the simplified sum of the rational numbers Ra and Rb\n[Ra Rb] => [Ra + Rb]\n\n[R(-9,-14) R(-3,19)] => [R(129,266)]\n[R(17,30) R(18,10)] => [R(71,30)]\n[R(-27,14) R(15,-23)] => [R(-831,322)]\n[R(3,-9) R(8,3)] => [R(7,3)]\n[R(-5,27) R(-2,-27)] => [R(-1,9)]\n[R(-27,-8) R(-15,22)] => [R(237,88)]\n[R(-9,-29) R(-27,3)] => [R(-252,29)]\n[R(2,-21) R(4,6)] => [R(4,7)]\n","desc":"returns the simplified sum of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra + Rb]","cases":[[[38654705693,12884901926],[554050781717]],[[73014444093,77309411349],[304942678077]],[[115964117020,64424509486],[3569117823620]],[[12884901906,34359738375],[30064771079]],[[21474836534,8589934647],[4294967314]],[[115964117009,64424509484],[1017907249329]],[[38654705723,115964116998],[1082331758650]],[[8589934634,17179869197],[17179869199]]]},"ratsub":{"full":"returns the simplified difference of the rational numbers Ra and Rb\n[Ra Rb] => [Ra - Rb]\n\n[R(21,25) R(-28,27)] => [R(1267,675)]\n[R(14,7) R(13,6)] => [R(-1,6)]\n[R(-24,-9) R(-5,-21)] => [R(17,7)]\n[R(-27,-2) R(-2,26)] => [R(353,26)]\n[R(-27,3) R(2,-22)] => [R(-98,11)]\n[R(-4,23) R(-9,13)] => [R(155,299)]\n[R(-14,19) R(-18,-11)] => [R(-496,209)]\n[R(-29,21) R(-15,-16)] => [R(-779,336)]\n","desc":"returns the simplified difference of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra - Rb]","cases":[[[90194313267,120259084342],[5441723565383]],[[60129542159,55834574861],[4294967308]],[[103079215123,21474836523],[73014444047]],[[115964116997,8589934644],[1516123455541]],[[115964116998,8589934636],[420906795030]],[[17179869230,38654705690],[665719931479]],[[60129542182,77309411351],[2130303779234]],[[124554051626,64424509473],[3345779524256]]]},"ratmul":{"full":"returns the simplified product of the rational numbers Ra and Rb\n[Ra Rb] => [Ra × Rb]\n\n[R(-24,26) R(-1,-30)] => [R(-2,65)]\n[R(19,4) R(27,2)] => [R(513,8)]\n[R(25,27) R(4,-11)] => [R(-100,297)]\n[R(1,18) R(4,8)] => [R(1,36)]\n[R(1,27) R(-8,29)] => [R(-8,783)]\n[R(25,-13) R(-6,24)] => [R(25,52)]\n[R(6,-13) R(9,23)] => [R(-54,299)]\n[R(11,8) R(-19,-19)] => [R(11,8)]\n","desc":"returns the simplified product of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra × Rb]","cases":[[[103079215156,4294967357],[8589934722]],[[81604378633,115964116997],[2203318222865]],[[107374182455,17179869206],[429496730194]],[[4294967333,17179869201],[4294967369]],[[4294967351,34359738426],[34359739934]],[[107374182426,25769803824],[107374182505]],[[25769803802,38654705711],[231928234582]],[[47244640273,81604378663],[47244640273]]]},"ratdiv":{"full":"returns the simplified quotient of the rational numbers Ra and Rb\n[Ra Rb] => [Ra / Rb]\n\n[R(-30,-22) R(15,12)] => [R(12,11)]\n[R(13,28) R(-15,29)] => [R(-377,420)]\n[R(7,-30) R(-22,-12)] => [R(-7,55)]\n[R(15,4) R(8,-8)] => [R(-15,4)]\n[R(-23,28) R(-16,-15)] => [R(-345,448)]\n[R(-18,12) R(6,18)] => [R(-9,2)]\n[R(29,-2) R(11,-21)] => [R(609,22)]\n[R(-23,25) R(25,-3)] => [R(69,625)]\n","desc":"returns the simplified quotient of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra / Rb]","cases":[[[128849018925,64424509465],[51539607575]],[[55834574905,64424509498],[1619202671432]],[[30064771132,94489280537],[30064771182]],[[64424509449,34359738384],[64424509448]],[[98784247864,68719476767],[1481763718016]],[[77309411352,25769803813],[38654705668]],[[124554051588,47244640298],[2615635083309]],[[98784247858,107374182406],[296352744675]]]},"ratmod":{"full":"returns the simplified modulus of the rational numbers Ra and Rb\n[Ra Rb] => [Ra % Rb]\n\n[R(-15,-3) R(-16,-10)] => [R(1,5)]\n[R(4,2) R(21,21)] => [R(0,1)]\n[R(24,10) R(-18,-3)] => [R(12,5)]\n[R(3,-7) R(-2,16)] => [R(-3,56)]\n[R(4,28) R(-29,7)] => [R(-4,1)]\n[R(7,-27) R(10,23)] => [R(109,621)]\n[R(28,-3) R(30,-12)] => [R(-11,6)]\n[R(-29,21) R(19,-23)] => [R(-268,483)]\n","desc":"returns the simplified modulus of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra % Rb]","cases":[[[64424509447,68719476757],[4294967307]],[[17179869189,90194313259],[3]],[[103079215125,77309411335],[51539607563]],[[12884901902,8589934624],[12884902000]],[[17179869241,124554051598],[17179869186]],[[30064771126,42949673007],[468151436507]],[[120259084294,128849018904],[47244640268]],[[124554051626,81604378670],[1151051236294]]]},"ratsign":{"full":"returns the sign of the rational number R\n[R] => [-1 | 0 | 1]\n\n[R(4,3)] => [1]\n[R(4,-3)] => [-1]\n[R(0,10)] => [0]\n[R(-3,4)] => [-1]\n[R(-3,-4)] => [1]\n","desc":"returns the sign of the rational number R","effect":"[R] => [-1 | 0 | 1]","cases":[[[17179869191],[1]],[[17179869190],[-1]],[[21],[0]],[[12884901896],[-1]],[[12884901897],[1]]]}},"array":{"aryat":{"full":"element at index i\n","desc":"","effect":"element at index i","cases":[]}},"stack":{"roll":{"full":"rolls the Ith element (counting from 0) to the top of the stack,\nshifting the elements above it down by 1.\n[I]\n\n[1 2 3 2] => [2 3 1]\n[1 2 3 4 1] => [1 2 4 3]\n[1 2 3 4 5 3] => [1 3 4 5 2]\n","desc":"rolls the Ith element (counting from 0) to the top of the stack,\nshifting the elements above it down by 1.","effect":"[I]","cases":[[[1,2,3,2],[2,3,1]],[[1,2,3,4,1],[1,2,4,3]],[[1,2,3,4,5,3],[1,3,4,5,2]]]},"bury":{"full":"\"buries\" X in the stack at index I, counting from 0\n[X I]\n\n[1 2 3 4 2] => [1 4 2 3] ; 2nd element of stack now 4\n[1 2 3 4 5 8 5] => [8 1 2 3 4 5]\n","desc":"\"buries\" X in the stack at index I, counting from 0","effect":"[X I]","cases":[[[1,2,3,4,2],[1,4,2,3]],[[1,2,3,4,5,8,5],[8,1,2,3,4,5]]]},"dig":{"full":"\"digs\" out the Ith element of the stack and discards it\n[I]\n\n[1 2 3 4 5 2] => [1 2 4 5]\n[1 2 3 4 5 4] => [2 3 4 5]\n","desc":"\"digs\" out the Ith element of the stack and discards it","effect":"[I]","cases":[[[1,2,3,4,5,2],[1,2,4,5]],[[1,2,3,4,5,4],[2,3,4,5]]]},"to_a":{"full":"pops elements off the stack until it hits the specified sentinel value S,\npushing them to the resulting pseudo-array. It's often more convenient to\nbuild up a collection in reverse order, and we often don't know in advance\nhow many elements we'll meet, but we do know to stop at the sentinel.\n[S En ... E1 S] => [E1 ... En n]\n\n[-1 9 8 7 -1] => [7 8 9 3]\n[0 'c' 'b' 'a' 0] => ['a' 'b' 'c' 3]\n","desc":"pops elements off the stack until it hits the specified sentinel value S,\npushing them to the resulting pseudo-array. It's often more convenient to\nbuild up a collection in reverse order, and we often don't know in advance\nhow many elements we'll meet, but we do know to stop at the sentinel.","effect":"[S En ... E1 S] => [E1 ... En n]","cases":[[[-1,9,8,7,-1],[7,8,9,3]],[[0,99,98,97,0],[97,98,99,3]]]},"npop":{"full":"pops N elements off the top of the stack\n[N]\n\n[1 2 3 4 5 3] => [1 2]\n[1 2 3 4 0] => [1 2 3 4]\n","desc":"pops N elements off the top of the stack","effect":"[N]","cases":[[[1,2,3,4,5,3],[1,2]],[[1,2,3,4,0],[1,2,3,4]]]},"nslide":{"full":"slides N elements off the stack, as if the `slide` operator took an argument\n[N]\n\n[1 2 3 4 5 2] => [1 2 5]\n[1 2 3 4 1] => [1 2 4]\n","desc":"slides N elements off the stack, as if the `slide` operator took an argument","effect":"[N]","cases":[[[1,2,3,4,5,2],[1,2,5]],[[1,2,3,4,1],[1,2,4]]]},"ncopy":{"full":"copies the Nth element to the top of the stack; this does exactly what\na `copy N` instruction would do, but we don't always know N in advance\n[N]\n\n[1 2 3 4 0] => [1 2 3 4 4] ; `copy 0` is just dup\n[1 2 3 4 3] => [1 2 3 4 1]\n","desc":"copies the Nth element to the top of the stack; this does exactly what\na `copy N` instruction would do, but we don't always know N in advance","effect":"[N]","cases":[[[1,2,3,4,0],[1,2,3,4,4]],[[1,2,3,4,3],[1,2,3,4,1]]]}},"util":{"range":{"full":"inserts between the top two stack values the intervening consecutive elements\n[I J] => [I I+1 ... J]\n\n[2 5] => [2 3 4 5]\n[0 4] => [0 1 2 3 4]\n[-2 0] => [-2 -1 0]\n[-3 3] => [-3 -2 -1 0 1 2 3]\n[4 4] => [4 5] TODO: bug\n","desc":"inserts between the top two stack values the intervening consecutive elements","effect":"[I J] => [I I+1 ... J]","cases":[[[2,5],[2,3,4,5]],[[0,4],[0,1,2,3,4]],[[-2,0],[-2,-1,0]],[[-3,3],[-3,-2,-1,0,1,2,3]],[[4,4],[4,5]]]},"die!":{"full":"prints the string at the top of the stack and halts execution\n","desc":"","effect":"prints the string at the top of the stack and halts execution","cases":[]},"alpha":{"full":"for stoi and itos\n","desc":"","effect":"for stoi and itos","cases":[]},"stoi":{"full":"converts the string S to an integer in base B (2-36)\n[S B]\n\n[\"101010\" 2] => [42]\n[\"0777\" 8] => [511]\n[\"12345\" 10] => [12345]\n[\"123_\" 10] => [123]\n[\"123____\" 10] => [123000] ; TODO: bug\n[\"dead\" 16] => [57005]\n[\"gabe\" 17] => [81699]\n","desc":"converts the string S to an integer in base B (2-36)","effect":"[S B]","cases":[[[1662522251313,2],[42]],[[116251568,8],[511]],[[14336973105,10],[12345]],[[200071473,10],[123]],[[421104295139633,10],[123000]],[[211317476,16],[57005]],[[213430503,17],[81699]]]},"bin":{"full":";; creature comforts\n","desc":"","effect":";; creature comforts","cases":[]},"itos":{"full":"converts the integer N to a string in base B\n[N B]\n\n[42 2] => [\"101010\"]\n[511 8] => [\"777\"]\n[12345 10] => [\"12345\"]\n[57005 16] => [\"dead\"]\n[81699 17] => [\"gabe\"]\n","desc":"converts the integer N to a string in base B","effect":"[N B]","cases":[[[42,2],[1662522251313]],[[511,8],[908215]],[[12345,10],[14336973105]],[[57005,16],[211317476]],[[81699,17],[213430503]]]},"to_s":{"full":"creature comfort\n","desc":"","effect":"creature comfort","cases":[]},"digits":{"full":"puts the digits of N in base B on the stack as a pseudo-array\n[N B]\n\n[42 2] => [1 0 1 0 1 0 6]\n[12345 10] => [1 2 3 4 5 5]\n[255 16] => [15 15 2]\n[256 16] => [1 0 0 3]\n","desc":"puts the digits of N in base B on the stack as a pseudo-array","effect":"[N B]","cases":[[[42,2],[1,0,1,0,1,0,6]],[[12345,10],[1,2,3,4,5,5]],[[255,16],[15,15,2]],[[256,16],[1,0,0,3]]]},"inc":{"full":"increments the value at heap address N TODO: make heap effects test-able ?\n[N]\n","desc":"increments the value at heap address N TODO: make heap effects test-able ?","effect":"[N]","cases":[]},"dec":{"full":"decrements the value at heap address N\n[N]\n","desc":"decrements the value at heap address N","effect":"[N]","cases":[]},"eq":{"full":"pops A and B and pushes 1 if they're equal, 0 otherwise\n[A B] => [A == B]\n\n[1 2] => [0]\n[3 3] => [1]\n[-4 4] => [0]\n['A' 65] => [1]\n['B' 65] => [0]\n","desc":"pops A and B and pushes 1 if they're equal, 0 otherwise","effect":"[A B] => [A == B]","cases":[[[1,2],[0]],[[3,3],[1]],[[-4,4],[0]],[[65,65],[1]],[[66,65],[0]]]},"neq":{"full":"pops A and B and pushes 1 if they're not equal, 0 otherwise\n[A B] => [A != B]\n\n[1 2] => [1]\n[3 3] => [0]\n[-4 4] => [1]\n['A' 65] => [0]\n['B' 65] => [1]\n","desc":"pops A and B and pushes 1 if they're not equal, 0 otherwise","effect":"[A B] => [A != B]","cases":[[[1,2],[1]],[[3,3],[0]],[[-4,4],[1]],[[65,65],[0]],[[66,65],[1]]]},"gt":{"full":"pops A and B and pushes 1 if A is greater than B, 0 otherwise\n[A B] => [A > B]\n\n[4 3] => [1]\n[3 4] => [0]\n[2 2] => [0]\n[2 1] => [1]\n","desc":"pops A and B and pushes 1 if A is greater than B, 0 otherwise","effect":"[A B] => [A > B]","cases":[[[4,3],[1]],[[3,4],[0]],[[2,2],[0]],[[2,1],[1]]]},"lt":{"full":"pops A and B and pushes 1 if A is less than than B, 0 otherwise\n[A B] => [A < B]\n\n[3 4] => [1]\n[4 3] => [0]\n[2 2] => [0]\n[1 2] => [1]\n","desc":"pops A and B and pushes 1 if A is less than than B, 0 otherwise","effect":"[A B] => [A < B]","cases":[[[3,4],[1]],[[4,3],[0]],[[2,2],[0]],[[1,2],[1]]]},"heap_seeking_missile":{"full":"Though extremely rare, it's possible that we know a particular value is\nstored in the heap at some key, just not which one. This subroutine takes\na value V to search for and a starting index I, and either returns the first\nkey associated with that value or loops forever. Probably don't touch.\n[V I]\n","desc":"Though extremely rare, it's possible that we know a particular value is\nstored in the heap at some key, just not which one. This subroutine takes\na value V to search for and a starting index I, and either returns the first\nkey associated with that value or loops forever. Probably don't touch.","effect":"[V I]","cases":[]}},"string":{"strpack":{"full":"convert a 0-terminated string on the stack to a single base-128 integer\n[0 ... c b a] => [\"abc...\"]\n\n[0 99 98 97] => [\"abc\"]\n[0 99 98 97] => [1634657]\n[0] => [0]\n","desc":"convert a 0-terminated string on the stack to a single base-128 integer","effect":"[0 ... c b a] => [\"abc...\"]","cases":[[[0,99,98,97],[1634657]],[[0,99,98,97],[1634657]],[[0],[0]]]},"strunpack":{"full":"convert a single base-128 integer to a 0-terminated string on the stack\n[\"abc...\"] => [0 ... c b a]\n\n[\"abc\"] => [0 99 98 97]\n[1634657] => [0 99 98 97]\n[0] => [0]\n","desc":"convert a single base-128 integer to a 0-terminated string on the stack","effect":"[\"abc...\"] => [0 ... c b a]","cases":[[[1634657],[0,99,98,97]],[[1634657],[0,99,98,97]],[[0],[0]]]},"strlen":{"full":"returns the length of a packed string, which is just the\nvalue itself log-128, +1 if the integer logarithm isn't exact.\n[S] => [len(S)]\n\n[\"\"] => [0]\n[\"abc\"] => [3]\n[\"foobar\"] => [6]\n","desc":"returns the length of a packed string, which is just the\nvalue itself log-128, +1 if the integer logarithm isn't exact.","effect":"[S] => [len(S)]","cases":[[[0],[0]],[[1634657],[3]],[[3943255767014],[6]]]},"strcat":{"full":"takes two packed strings and returns their concatenation (as a packed string)\n[S T] => [S+T]\n\n[\"foo\" \"\"] => [\"foo\"]\n[\"\" \"foo\"] => [\"foo\"]\n[\"foo\" \"bar\"] => [\"foobar\"]\n","desc":"takes two packed strings and returns their concatenation (as a packed string)","effect":"[S T] => [S+T]","cases":[[[1832934,0],[1832934]],[[0,1832934],[1832934]],[[1832934,1880290],[3943255767014]]]},"strrev":{"full":"reverses a packed string \"in-place\"\n[S] => [reverse(S)]\n\n[\"foo\"] => [\"oof\"]\n[\"bark\"] => [\"krab\"]\n[\"ab\"] => [\"ba\"] ['a'] => ['a'] [\"\"] => [\"\"]\n","desc":"reverses a packed string \"in-place\"","effect":"[S] => [reverse(S)]","cases":[[[1832934],[1685487]],[[226275554],[207124843]],[[12641],[12514]],[[97],[97]],[[0],[0]]]},"strslice":{"full":"takes a packed string S, a start index I, and a length L and returns the\ncorresponding substring (simply by doing division with powers of 128; neat)\n[S I L] => [substring]\n\n[\"foobar\" 0 6] => [\"foobar\"]\n[\"foobar\" 1 4] => [\"ooba\"]\n[\"foobar\" 1 10] => [\"oobar\"]\n[\"foobar\" 5 1] => ['r']\n[\"foobar\" 6 0] => [\"\"]\n","desc":"takes a packed string S, a start index I, and a length L and returns the\ncorresponding substring (simply by doing division with powers of 128; neat)","effect":"[S I L] => [substring]","cases":[[[3943255767014,0,6],[3943255767014]],[[3943255767014,1,4],[205043695]],[[3943255767014,1,10],[30806685679]],[[3943255767014,5,1],[114]],[[3943255767014,6,0],[0]]]},"strindex":{"full":"returns the index of substring T in string S (or -1 if not found)\n[S T] => [index]\n\n[\"foobar\" 'o'] => [1]\n[\"foobar\" \"ob\"] => [2]\n[\"foobar\" \"\"] => [0]\n[\"foobar\" \"bar\"] => [3]\n[\"foobar\" \"bark\"] => [-1]\n","desc":"returns the index of substring T in string S (or -1 if not found)","effect":"[S T] => [index]","cases":[[[3943255767014,111],[1]],[[3943255767014,12655],[2]],[[3943255767014,0],[0]],[[3943255767014,1880290],[3]],[[3943255767014,226275554],[-1]]]},"charat":{"full":"returns the character at index I in string S\n[S I] => [char]\n\n[\"foobar\" 1] => ['o']\n[\"foobar\" 3] => ['b']\n[\"foobar\" 5] => ['r']\n[\"foobar\" 6] => [\"\"]\n","desc":"returns the character at index I in string S","effect":"[S I] => [char]","cases":[[[3943255767014,1],[111]],[[3943255767014,3],[98]],[[3943255767014,5],[114]],[[3943255767014,6],[0]]]},"isalpha":{"full":"returns 1 if the character at the top of the stack is\nalphabetical (ASCII 65-90 or 97-122), 0 otherwise\n[C] => [0/1]\n\n['@'] => [0] ['a'] => [1]\n['z'] => [1] ['['] => [0]\n['`'] => [0] ['A'] => [1]\n['Z'] => [1] ['{'] => [0]\n","desc":"returns 1 if the character at the top of the stack is\nalphabetical (ASCII 65-90 or 97-122), 0 otherwise","effect":"[C] => [0/1]","cases":[[[64],[0]],[[97],[1]],[[122],[1]],[[91],[0]],[[96],[0]],[[65],[1]],[[90],[1]],[[123],[0]]]},"strrep":{"full":"returns string S replicated N times\n[S N] => [S+S+...]\n\n[\"abc\" 1] => [\"abc\"]\n[\"abc\" 2] => [\"abcabc\"]\n[\"abc\" 0] => [\"\"]\n","desc":"returns string S replicated N times","effect":"[S N] => [S+S+...]","cases":[[[1634657,1],[1634657]],[[1634657,2],[3428125831521]],[[1634657,0],[0]]]},"ljustc":{"full":"left-justifies string S to width W with character C\n[S W C] => [S, left-justified]\n\n[\"foo\" 5 'x'] => [\"fooxx\"]\n[\"foobar\" 4 'x'] => [\"foobar\"]\n[\"\" 3 'x'] => [\"xxx\"]\n","desc":"left-justifies string S to width W with character C","effect":"[S W C] => [S, left-justified]","cases":[[[1832934,5,120],[32465745894]],[[3943255767014,4,120],[3943255767014]],[[0,3,120],[1981560]]]},"ljust":{"full":"left-justifies string S to width W with spaces\n[S W] => [S, left-justified]\n\n[\"foo\" 5] => [\"foo \"]\n[\"foobar\" 4] => [\"foobar\"]\n[\"\" 3] => [528416]\n","desc":"left-justifies string S to width W with spaces","effect":"[S W] => [S, left-justified]","cases":[[[1832934,5],[8658876390]],[[3943255767014,4],[3943255767014]],[[0,3],[528416]]]},"rjustc":{"full":"right-justifies string S to width W with character C\n[S W C] => [S, right-justified]\n\n[\"foo\" 5 'x'] => [\"xxfoo\"]\n[\"foobar\" 4 'x'] => [\"foobar\"]\n[\"\" 3 'x'] => [\"xxx\"]\n","desc":"right-justifies string S to width W with character C","effect":"[S W C] => [S, right-justified]","cases":[[[1832934,5,120],[30030806136]],[[3943255767014,4,120],[3943255767014]],[[0,3,120],[1981560]]]},"rjust":{"full":"right-justifies string S to width W with spaces\n[S W C] => [S, right-justified]\n\n[\"foo\" 5] => [\" foo\"]\n[\"foobar\" 4] => [\"foobar\"]\n[\"\" 3] => [528416]\n","desc":"right-justifies string S to width W with spaces","effect":"[S W C] => [S, right-justified]","cases":[[[1832934,5],[30030794784]],[[3943255767014,4],[3943255767014]],[[0,3],[528416]]]},"centerc":{"full":"centers string S to width W with character C, favoring left alignment when\nthere's a parity mismatch (even-length string to odd width or vice versa)\n[S W C] => [S, centered]\n\n[\"abc\" 7 'x'] => [\"xxabcxx\"]\n[\"abc\" 6 'x'] => [\"xabcxx\"]\n[\"abcd\" 6 'o'] => [\"oabcdo\"]\n[\"abcd\" 7 'o'] => [\"oabcdoo\"]\n[\"abcd\" 3 '!'] => [\"abcd\"]\n","desc":"centers string S to width W with character C, favoring left alignment when\nthere's a parity mismatch (even-length string to odd width or vice versa)","effect":"[S W C] => [S, centered]","cases":[[[1634657,7,120],[531915532172408]],[[1634657,6,120],[4155590095096]],[[211349857,6,111],[3840983740655]],[[211349857,7,111],[492024146473199]],[[211349857,3,33],[211349857]]]},"center":{"full":"centers string S to width W with spaces\n[S W] => [S, centered]\n\n[\"abc\" 7] => [\" abc \"]\n[\"abc\" 6] => [\" abc \"]\n[\"abcd\" 6] => [\" abcd \"]\n[\"abcd\" 7] => [\" abcd \"]\n[\"abcd\" 3] => [\"abcd\"]\n","desc":"centers string S to width W with spaces","effect":"[S W] => [S, centered]","cases":[[[1634657,7],[141863782207520]],[[1634657,6],[1108310798496]],[[211349857,6],[1126564409504]],[[211349857,7],[141864052764832]],[[211349857,3],[211349857]]]},"strchop":{"full":"removes the last character of a string\n[S] => [S.chop]\n\n[\"foobar\"] => [\"fooba\"]\n[\"abc\"] => [\"ab\"]\n[\"a\"] => [\"\"]\n","desc":"removes the last character of a string","effect":"[S] => [S.chop]","cases":[[[3943255767014],[26245593062]],[[1634657],[12641]],[[97],[0]]]},"strsplit":{"full":"splits string S on delimiting character C, leaving the resultant substrings\non the stack as a pseudo-array (length at top of stack)\n[S C] => [A]\n\n[\"fooxbar\" 'x'] => [\"foo\" \"bar\" 2]\n[\"foobar\" 'x'] => [\"foobar\" 1]\n[\"foo|bar|baz\" '|'] => [\"foo\" \"bar\" \"baz\" 3]\n[\"foo,,bar\" ','] => [\"foo\" \"\" \"bar\" 3]\n[\"/foo/bar/\" '/'] => [\"\" \"foo\" \"bar\" \"\" 4]\n","desc":"splits string S on delimiting character C, leaving the resultant substrings\non the stack as a pseudo-array (length at top of stack)","effect":"[S C] => [A]","cases":[[[504736757053414,120],[1832934,1880290,2]],[[3943255767014,120],[3943255767014,1]],[[144933976769845798893542,124],[1832934,1880290,2011362,3]],[[64606284361234406,44],[1832934,0,1880290,3]],[[3451313205089661743,47],[0,1832934,1880290,0,4]]]},"lines":{"full":"splits the string S on newlines\n","desc":"","effect":"splits the string S on newlines","cases":[]},"strjoinc":{"full":"joins the pseudo-array of strings A into string S with delimiter string D\n[A D] => [S]\n\n[\"foo\" \"bar\" 2 'x'] => [\"fooxbar\"]\n[\"foo\" \"bar\" \"baz\" 3 '--'] => [\"foo--bar--baz\"]\n[\"foo\" 1 \"?!\"] => [\"foo\"]\n","desc":"joins the pseudo-array of strings A into string S with delimiter string D","effect":"[A D] => [S]","cases":[[[1832934,1880290,2,120],[504736757053414]],[[1832934,1880290,2011362,3,5805],[2374597541788353508880938982]],[[1832934,1,4287],[1832934]]]},"strjoin":{"full":"concatenates the pseudo-array of strings A into string S\n[A] => [S]\n\n[\"foo\" 1] => [\"foo\"]\n[\"foo\" \"bar\" 2] => [\"foobar\"]\n[\"foo\" 'x' \"bar\" 'x' \"baz\" 5] => [\"fooxbarxbaz\"]\n","desc":"concatenates the pseudo-array of strings A into string S","effect":"[A] => [S]","cases":[[[1832934,1],[1832934]],[[1832934,1880290,2],[3943255767014]],[[1832934,120,1880290,120,2011362,5],[144933974518045976819686]]]},"strcountc":{"full":"returns the number of ocurrences of character C in string S\n[S C] => [N]\n\n[\"foobar\" 'a'] => [1]\n[\"foobar\" 'o'] => [2]\n[\"foobar\" 'c'] => [0]\n","desc":"returns the number of ocurrences of character C in string S","effect":"[S C] => [N]","cases":[[[3943255767014,97],[1]],[[3943255767014,111],[2]],[[3943255767014,99],[0]]]},"strcount":{"full":"returns the total number of ocurrences of all characters in string T in string S\n[S T] => [N]\n\n[\"foobar\" 'o'] => [2]\n[\"foobar\" \"ob\"] => [3]\n[\"foxboar\" \"box\"] => [4]\n[\"eunoia\" \"aeiou\"] => [5]\n[\"why\" \"aeiou\"] => [0]\n","desc":"returns the total number of ocurrences of all characters in string T in string S","effect":"[S T] => [N]","cases":[[[3943255767014,111],[2]],[[3943255767014,12655],[3]],[[504740200724454,1980386],[4]],[[3361314945765,31641465569],[5]],[[1995895,31641465569],[0]]]},"strtrans":{"full":"translates all characters in A to the corresponding characters in B\nin stirng S, ; similar to the `tr` utility in Unix. A and B must be\nof the same length. TODO: make this smarter (ranges, length mismatch)\n[S A B] => [S]\n\n[\"abcd\" \"abc\" \"xyz\"] => [\"xyzd\"]\n[\"foobar\" \"oba\" \"ele\"] => [\"feeler\"]\n[\"abcdcba\" \"abcd\" \"xyz|\"] => [\"xyz|zyx\"]\n","desc":"translates all characters in A to the corresponding characters in B\nin stirng S, ; similar to the `tr` utility in Unix. A and B must be\nof the same length. TODO: make this smarter (ranges, length mismatch)","effect":"[S A B] => [S]","cases":[[[211349857,1634657,2014456],[211729656]],[[3943255767014,1601903,1668709],[3944350315238]],[[430004552397153,211349857,262061304],[531956120861944]]]},"strexpand":{"full":"expands the length-2 string S to contain the intervening ASCII characters\n[S] => [S, expanded]\n\n[\"CJ\"] => [\"CDEFGHIJ\"]\n[\"DA\"] => [\"DE\"] TODO: bug\n[\"af\"] => [\"abcdef\"]\n[\"09\"] => [\"0123456789\"]\n[\"(1\"] => [\"()*+,-./01\"]\n","desc":"expands the length-2 string S to contain the intervening ASCII characters","effect":"[S] => [S, expanded]","cases":[[[9539],[41981847056507459]],[[8388],[8900]],[[13153],[3532016644449]],[[7344],[529798632943928514736]],[[6312],[455430656835745125544]]]},"strsqueeze":{"full":"\"squeezes\" runs of the same character in string S to just one occurrence\n[S] => [S, squeezed]\n\n[\"abc\"] => [\"abc\"]\n[\"foobar\"] => [\"fobar\"]\n[\"bookkeeper\"] => [\"bokeper\"]\n[\"xxxxxxx\"] => [\"x\"]\n","desc":"\"squeezes\" runs of the same character in string S to just one occurrence","effect":"[S] => [S, squeezed]","cases":[[[1634657],[1634657]],[[3943255767014],[30806685670]],[[1058805727296038369250],[504877914191842]],[[531921215831160],[120]]]},"strsum":{"full":"returns the sum of the ordinal values of the characters in string S\n[S] => [N]\n\n[\"ABC\"] => [198]\n[\"012\"] => [147]\n[\"a\"] => [97]\n[\"\"] => [] TODO: bug, should be 0\n","desc":"returns the sum of the ordinal values of the characters in string S","effect":"[S] => [N]","cases":[[[1106241],[198]],[[825520],[147]],[[97],[97]],[[0],[]]]},"strrotl":{"full":"rotates the string S to the left N times, wrapping\n[S N]\n\n[\"abc\" 0] => [\"abc\"]\n[\"abcd\" 1] => [\"bcda\"]\n[\"abcd\" 5] => [\"bcda\"]\n[\"foodbar\" 4] => [\"barfood\"]\n","desc":"rotates the string S to the left N times, wrapping","effect":"[S N]","cases":[[[1634657,0],[1634657]],[[211349857,1],[205074914]],[[211349857,5],[205074914]],[[504736715110374,4],[443648594194658]]]},"strrotr":{"full":"rotates the string S to the right N times, wrapping\n[S N]\n\n[\"abcd\" 1] => [\"dabc\"]\n[\"abcd\" 5] => [\"dabc\"]\n[\"foodbar\" 3] => [\"barfood\"]\n","desc":"rotates the string S to the right N times, wrapping","effect":"[S N]","cases":[[[211349857,1],[209236196]],[[211349857,5],[209236196]],[[504736715110374,3],[443648594194658]]]}},"math":{"pow":{"full":"returns B raised to the power E\n[B E] => [B**E]\n\n[0 0] => [1], [0 9] => [0], [9 0] => [1]\n[3 2] => [9], [2 3] => [8], [7 4] => [2401]\n","desc":"returns B raised to the power E","effect":"[B E] => [B**E]","cases":[[[0,0],[1]],[[0,9],[0]],[[9,0],[1]],[[3,2],[9]],[[2,3],[8]],[[7,4],[2401]]]},"factorial":{"full":"returns the product of the integers from 1 to N, with 0! defined to be 1\n[N] => [N!]\n\n[0] => [1], [1] => [1], [2] => [2]\n[3] => [6], [5] => [120], [10] => [3628800]\n","desc":"returns the product of the integers from 1 to N, with 0! defined to be 1","effect":"[N] => [N!]","cases":[[[0],[1]],[[1],[1]],[[2],[2]],[[3],[6]],[[5],[120]],[[10],[3628800]]]},"isqrt":{"full":"returns the integer square root of N\n[N] => [floor(sqrt(N))]\n\n[0] => [0], [1] => [1], [2] => [1], [3] => [1]\n[4] => [2], [8] => [2], [9] => [3], [99] => [9], [100] => [10]\n","desc":"returns the integer square root of N","effect":"[N] => [floor(sqrt(N))]","cases":[[[0],[0]],[[1],[1]],[[2],[1]],[[3],[1]],[[4],[2]],[[8],[2]],[[9],[3]],[[99],[9]],[[100],[10]]]},"ilog":{"full":"returns the intger logarithm of N in base B\n[N B] => [logB(N)]\n\n[15 4] => [1]\n[16 4] => [2]\n[100 10] => [2]\n[42 2] => [5]\n","desc":"returns the intger logarithm of N in base B","effect":"[N B] => [logB(N)]","cases":[[[15,4],[1]],[[16,4],[2]],[[100,10],[2]],[[42,2],[5]]]},"gcd":{"full":"returns the greatest common divisor of A and B\n[A B] => [gcd(A, B)]\n\n[6 9] => [3]\n[13 17] => [1]\n[24 36] => [12]\n","desc":"returns the greatest common divisor of A and B","effect":"[A B] => [gcd(A, B)]","cases":[[[6,9],[3]],[[13,17],[1]],[[24,36],[12]]]},"lcm":{"full":"returns the least common multiple of A and B\n[A B] => [lcm(A, B)]\n\n[6 9] => [18]\n[13 17] => [221]\n[24 36] => [72]\n","desc":"returns the least common multiple of A and B","effect":"[A B] => [lcm(A, B)]","cases":[[[6,9],[18]],[[13,17],[221]],[[24,36],[72]]]},"min":{"full":"keeps the minimum of the top two stack values\n[A B] => [A < B ? A : B]\n\n[3 1] => [1]\n[2 4] => [2]\n","desc":"keeps the minimum of the top two stack values","effect":"[A B] => [A < B ? A : B]","cases":[[[3,1],[1]],[[2,4],[2]]]},"max":{"full":"keeps the maximum of the top two stack values\n[A B] => [A > B ? A : B]\n\n[3 1] => [3]\n[2 4] => [4]\n","desc":"keeps the maximum of the top two stack values","effect":"[A B] => [A > B ? A : B]","cases":[[[3,1],[3]],[[2,4],[4]]]},"sign":{"full":"returns -1, 0, or 1 to indicate the sign of N\n[N] => [-1 | 0 | 1]\n\n[17] => [1]\n[-25] => [-1]\n[0] => [0]\n","desc":"returns -1, 0, or 1 to indicate the sign of N","effect":"[N] => [-1 | 0 | 1]","cases":[[[17],[1]],[[-25],[-1]],[[0],[0]]]},"abs":{"full":"returns the absolute value of N\n[N] => [N < 0 ? -N : N]\n\n[-5] => [5]\n[10] => [10]\n[0] => [0]\n","desc":"returns the absolute value of N","effect":"[N] => [N < 0 ? -N : N]","cases":[[[-5],[5]],[[10],[10]],[[0],[0]]]},"divmod":{"full":"pops A and B and pushes both their quotient and modulus\n[A B] => [A/B A%B]\n\n[17 5] => [3 2]\n[42 6] => [7 0]\n[ 1 5] => [0 1]\n","desc":"pops A and B and pushes both their quotient and modulus","effect":"[A B] => [A/B A%B]","cases":[[[17,5],[3,2]],[[42,6],[7,0]],[[1,5],[0,1]]]},"pos?":{"full":"returns whether N is greater than 0\n[N] => [N > 0]\n\n[5] => [1] [-3] => [0] [0] => [0]\n","desc":"returns whether N is greater than 0","effect":"[N] => [N > 0]","cases":[[[5],[1]],[[-3],[0]],[[0],[0]]]},"neg?":{"full":"returns whether N is less than 0\n[N] => [N < 0]\n\n[5] => [0] [-3] => [1] [0] => [0]\n","desc":"returns whether N is less than 0","effect":"[N] => [N < 0]","cases":[[[5],[0]],[[-3],[1]],[[0],[0]]]},"divisors":{"full":"returns a pseudo-array of the positive divisors of N; as an optimization,\nthey're not returned in ascending order, but rather in two \"halves\".\nThe alternative is unnecessarily invoking to_a and clobbering heap.\n[N]\n\n[10] => [1 2 10 5 4]\n[12] => [1 2 3 12 6 4 6]\n[25] => [1 5 25 3] ; no duplicate for perfect squares\n[60] => [1 2 3 4 5 6 60 30 20 15 12 10 12]\n","desc":"returns a pseudo-array of the positive divisors of N; as an optimization,\nthey're not returned in ascending order, but rather in two \"halves\".\nThe alternative is unnecessarily invoking to_a and clobbering heap.","effect":"[N]","cases":[[[10],[1,2,10,5,4]],[[12],[1,2,3,12,6,4,6]],[[25],[1,5,25,3]],[[60],[1,2,3,4,5,6,60,30,20,15,12,10,12]]]},"nCk":{"full":"returns the number of ways to choose K elements from a set of N\n[N K]\n\n[ 4 5] => [0]\n[ 7 7] => [1]\n[13 3] => [286]\n[16 4] => [1820]\n[50 3] => [19600]\n","desc":"returns the number of ways to choose K elements from a set of N","effect":"[N K]","cases":[[[4,5],[0]],[[7,7],[1]],[[13,3],[286]],[[16,4],[1820]],[[50,3],[19600]]]}}}
|
1
|
+
{"fun":{"palindrome?":{"full":"returns whether the string S is the same forwards and backwards\n[S] => [0 | 1]\n\n[\"racecar\"] => [1]\n[\"divider\"] => [0]\n[\"redivider\"] => [1]\n","desc":"returns whether the string S is the same forwards and backwards","effect":"[S] => [0 | 1]","cases":[[[504736985444594],[1]],[[504874701534436],[0]],[[8271867109940212466],[1]]]},"anagrams?":{"full":"returns whether the strings S and T are composed of the same characters\n[S T] => [0 | 1]\n\n[\"allergy\" \"gallery\"] => [1]\n[\"largely\" \"regally\"] => [1]\n[\"foo\" \"bar\"] => [0]\n","desc":"returns whether the strings S and T are composed of the same characters","effect":"[S T] => [0 | 1]","cases":[[[535733496133217,536107978272999],[1]],[[535901809455340,535903675740914],[1]],[[1832934,1880290],[0]]]},"isop":{"full":"returns the sum of the alphabetical characters in string S where A=1, B=2...\n[S] => [sum]\n\n[\"Math\"] => [42]\n[\"wizards\"] => [100]\n[\"AbCd\"] => [10]\n","desc":"returns the sum of the alphabetical characters in string S where A=1, B=2...","effect":"[S] => [sum]","cases":[[[220016845],[42]],[[509242129691895],[100]],[[210825537],[10]]]},"collatz":{"full":"returns the elements of the Collatz sequence for integer N as a pseudo-array\n[N] => [A]\n\n[1] => [1 1]\n[2] => [2 1 2]\n[3] => [3 10 5 16 8 4 2 1 8]\n[4] => [4 2 1 3]\n[5] => [5 16 8 4 2 1 6]\n","desc":"returns the elements of the Collatz sequence for integer N as a pseudo-array","effect":"[N] => [A]","cases":[[[1],[1,1]],[[2],[2,1,2]],[[3],[3,10,5,16,8,4,2,1,8]],[[4],[4,2,1,3]],[[5],[5,16,8,4,2,1,6]]]}},"math":{"pow":{"full":"returns B raised to the power E\n[B E] => [B**E]\n\n[0 0] => [1], [0 9] => [0], [9 0] => [1]\n[3 2] => [9], [2 3] => [8], [7 4] => [2401]\n","desc":"returns B raised to the power E","effect":"[B E] => [B**E]","cases":[[[0,0],[1]],[[0,9],[0]],[[9,0],[1]],[[3,2],[9]],[[2,3],[8]],[[7,4],[2401]]]},"factorial":{"full":"returns the product of the integers from 1 to N, with 0! defined to be 1\n[N] => [N!]\n\n[0] => [1], [1] => [1], [2] => [2]\n[3] => [6], [5] => [120], [10] => [3628800]\n","desc":"returns the product of the integers from 1 to N, with 0! defined to be 1","effect":"[N] => [N!]","cases":[[[0],[1]],[[1],[1]],[[2],[2]],[[3],[6]],[[5],[120]],[[10],[3628800]]]},"isqrt":{"full":"returns the integer square root of N\n[N] => [floor(sqrt(N))]\n\n[0] => [0], [1] => [1], [2] => [1], [3] => [1]\n[4] => [2], [8] => [2], [9] => [3], [99] => [9], [100] => [10]\n","desc":"returns the integer square root of N","effect":"[N] => [floor(sqrt(N))]","cases":[[[0],[0]],[[1],[1]],[[2],[1]],[[3],[1]],[[4],[2]],[[8],[2]],[[9],[3]],[[99],[9]],[[100],[10]]]},"ilog":{"full":"returns the intger logarithm of N in base B\n[N B] => [logB(N)]\n\n[15 4] => [1]\n[16 4] => [2]\n[100 10] => [2]\n[42 2] => [5]\n","desc":"returns the intger logarithm of N in base B","effect":"[N B] => [logB(N)]","cases":[[[15,4],[1]],[[16,4],[2]],[[100,10],[2]],[[42,2],[5]]]},"gcd":{"full":"returns the greatest common divisor of A and B\n[A B] => [gcd(A, B)]\n\n[6 9] => [3]\n[13 17] => [1]\n[24 36] => [12]\n","desc":"returns the greatest common divisor of A and B","effect":"[A B] => [gcd(A, B)]","cases":[[[6,9],[3]],[[13,17],[1]],[[24,36],[12]]]},"lcm":{"full":"returns the least common multiple of A and B\n[A B] => [lcm(A, B)]\n\n[6 9] => [18]\n[13 17] => [221]\n[24 36] => [72]\n","desc":"returns the least common multiple of A and B","effect":"[A B] => [lcm(A, B)]","cases":[[[6,9],[18]],[[13,17],[221]],[[24,36],[72]]]},"min":{"full":"keeps the minimum of the top two stack values\n[A B] => [A < B ? A : B]\n\n[3 1] => [1]\n[2 4] => [2]\n","desc":"keeps the minimum of the top two stack values","effect":"[A B] => [A < B ? A : B]","cases":[[[3,1],[1]],[[2,4],[2]]]},"max":{"full":"keeps the maximum of the top two stack values\n[A B] => [A > B ? A : B]\n\n[3 1] => [3]\n[2 4] => [4]\n","desc":"keeps the maximum of the top two stack values","effect":"[A B] => [A > B ? A : B]","cases":[[[3,1],[3]],[[2,4],[4]]]},"sign":{"full":"returns -1, 0, or 1 to indicate the sign of N\n[N] => [-1 | 0 | 1]\n\n[17] => [1]\n[-25] => [-1]\n[0] => [0]\n","desc":"returns -1, 0, or 1 to indicate the sign of N","effect":"[N] => [-1 | 0 | 1]","cases":[[[17],[1]],[[-25],[-1]],[[0],[0]]]},"abs":{"full":"returns the absolute value of N\n[N] => [N < 0 ? -N : N]\n\n[-5] => [5]\n[10] => [10]\n[0] => [0]\n","desc":"returns the absolute value of N","effect":"[N] => [N < 0 ? -N : N]","cases":[[[-5],[5]],[[10],[10]],[[0],[0]]]},"divmod":{"full":"pops A and B and pushes both their quotient and modulus\n[A B] => [A/B A%B]\n\n[17 5] => [3 2]\n[42 6] => [7 0]\n[ 1 5] => [0 1]\n","desc":"pops A and B and pushes both their quotient and modulus","effect":"[A B] => [A/B A%B]","cases":[[[17,5],[3,2]],[[42,6],[7,0]],[[1,5],[0,1]]]},"pos?":{"full":"returns whether N is greater than 0\n[N] => [N > 0]\n\n[5] => [1] [-3] => [0] [0] => [0]\n","desc":"returns whether N is greater than 0","effect":"[N] => [N > 0]","cases":[[[5],[1]],[[-3],[0]],[[0],[0]]]},"neg?":{"full":"returns whether N is less than 0\n[N] => [N < 0]\n\n[5] => [0] [-3] => [1] [0] => [0]\n","desc":"returns whether N is less than 0","effect":"[N] => [N < 0]","cases":[[[5],[0]],[[-3],[1]],[[0],[0]]]},"divisors":{"full":"returns a pseudo-array of the positive divisors of N; as an optimization,\nthey're not returned in ascending order, but rather in two \"halves\".\nThe alternative is unnecessarily invoking to_a and clobbering heap.\n[N] => [D1 ... Dn n]\n\n[10] => [1 2 10 5 4]\n[12] => [1 2 3 12 6 4 6]\n[25] => [1 5 25 3] ; no duplicate for perfect squares\n[60] => [1 2 3 4 5 6 60 30 20 15 12 10 12]\n","desc":"returns a pseudo-array of the positive divisors of N; as an optimization,\nthey're not returned in ascending order, but rather in two \"halves\".\nThe alternative is unnecessarily invoking to_a and clobbering heap.","effect":"[N] => [D1 ... Dn n]","cases":[[[10],[1,2,10,5,4]],[[12],[1,2,3,12,6,4,6]],[[25],[1,5,25,3]],[[60],[1,2,3,4,5,6,60,30,20,15,12,10,12]]]},"nCk":{"full":"returns the number of ways to choose K elements from a set of N\n[N K]\n\n[ 4 5] => [0]\n[ 7 7] => [1]\n[13 3] => [286]\n[16 4] => [1820]\n[50 3] => [19600]\n","desc":"returns the number of ways to choose K elements from a set of N","effect":"[N K]","cases":[[[4,5],[0]],[[7,7],[1]],[[13,3],[286]],[[16,4],[1820]],[[50,3],[19600]]]}},"stack":{"roll":{"full":"rolls the Ith element (counting from 0) to the top of the stack,\nshifting the elements above it down by 1.\n[I]\n\n[1 2 3 2] => [2 3 1]\n[1 2 3 4 1] => [1 2 4 3]\n[1 2 3 4 5 3] => [1 3 4 5 2]\n","desc":"rolls the Ith element (counting from 0) to the top of the stack,\nshifting the elements above it down by 1.","effect":"[I]","cases":[[[1,2,3,2],[2,3,1]],[[1,2,3,4,1],[1,2,4,3]],[[1,2,3,4,5,3],[1,3,4,5,2]]]},"bury":{"full":"\"buries\" X in the stack at index I, counting from 0\n[X I]\n\n[1 2 3 4 2] => [1 4 2 3] ; 2nd element of stack now 4\n[1 2 3 4 5 8 5] => [8 1 2 3 4 5]\n","desc":"\"buries\" X in the stack at index I, counting from 0","effect":"[X I]","cases":[[[1,2,3,4,2],[1,4,2,3]],[[1,2,3,4,5,8,5],[8,1,2,3,4,5]]]},"dig":{"full":"\"digs\" out the Ith element of the stack and discards it\n[I]\n\n[1 2 3 4 5 2] => [1 2 4 5]\n[1 2 3 4 5 4] => [2 3 4 5]\n","desc":"\"digs\" out the Ith element of the stack and discards it","effect":"[I]","cases":[[[1,2,3,4,5,2],[1,2,4,5]],[[1,2,3,4,5,4],[2,3,4,5]]]},"to_a":{"full":"pops elements off the stack until it hits the specified sentinel value S,\npushing them to the resulting pseudo-array. It's often more convenient to\nbuild up a collection in reverse order, and we often don't know in advance\nhow many elements we'll meet, but we do know to stop at the sentinel.\n[S En ... E1 S] => [E1 ... En n]\n\n[-1 9 8 7 -1] => [7 8 9 3]\n[0 'c' 'b' 'a' 0] => ['a' 'b' 'c' 3]\n","desc":"pops elements off the stack until it hits the specified sentinel value S,\npushing them to the resulting pseudo-array. It's often more convenient to\nbuild up a collection in reverse order, and we often don't know in advance\nhow many elements we'll meet, but we do know to stop at the sentinel.","effect":"[S En ... E1 S] => [E1 ... En n]","cases":[[[-1,9,8,7,-1],[7,8,9,3]],[[0,99,98,97,0],[97,98,99,3]]]},"npop":{"full":"pops N elements off the top of the stack\n[N]\n\n[1 2 3 4 5 3] => [1 2]\n[1 2 3 4 0] => [1 2 3 4]\n","desc":"pops N elements off the top of the stack","effect":"[N]","cases":[[[1,2,3,4,5,3],[1,2]],[[1,2,3,4,0],[1,2,3,4]]]},"nslide":{"full":"slides N elements off the stack, as if the `slide` operator took an argument\n[N]\n\n[1 2 3 4 5 2] => [1 2 5]\n[1 2 3 4 1] => [1 2 4]\n","desc":"slides N elements off the stack, as if the `slide` operator took an argument","effect":"[N]","cases":[[[1,2,3,4,5,2],[1,2,5]],[[1,2,3,4,1],[1,2,4]]]},"ncopy":{"full":"copies the Nth element to the top of the stack; this does exactly what\na `copy N` instruction would do, but we don't always know N in advance\n[N]\n\n[1 2 3 4 0] => [1 2 3 4 4] ; `copy 0` is just dup\n[1 2 3 4 3] => [1 2 3 4 1]\n","desc":"copies the Nth element to the top of the stack; this does exactly what\na `copy N` instruction would do, but we don't always know N in advance","effect":"[N]","cases":[[[1,2,3,4,0],[1,2,3,4,4]],[[1,2,3,4,3],[1,2,3,4,1]]]}},"rational":{"to_r":{"full":"encodes a numerator N and a denominator D as a rational number R with the\nfollowing structure: ((N × $RAT + D) << 1) + sign (0 for negative, else 1).\nThis representation is nice because, with care, it makes it so that we never\nhave to involve the heap (besides divmod) just to do fairly basic arithmetic.\n[N D] => [R]\n\n[22 7] => [R(22,7)]\n[4 8] => [R(4,8)] ; no implicit simplification TODO: make it configurable?\n[5 1] => [R(5,1)] ; no conversion to integer (duh)\n[-3 4] => [R(-3,4)]\n[3 -4] => [R(-3,4)] ; sign always held in the numerator\n[-1 -3] => [R(1,3)]\n","desc":"encodes a numerator N and a denominator D as a rational number R with the\nfollowing structure: ((N × $RAT + D) << 1) + sign (0 for negative, else 1).\nThis representation is nice because, with care, it makes it so that we never\nhave to involve the heap (besides divmod) just to do fairly basic arithmetic.","effect":"[N D] => [R]","cases":[[[22,7],[94489280527]],[[4,8],[17179869201]],[[5,1],[21474836483]],[[-3,4],[12884901896]],[[3,-4],[12884901896]],[[-1,-3],[4294967303]]]},"ratnum":{"full":"returns the numerator N of the rational number R, which may be negative\n[R] => [N]\n\n[R(22,7)] => [22]\n[R(-3,4)] => [-3]\n[R(3,-4)] => [-3]\n","desc":"returns the numerator N of the rational number R, which may be negative","effect":"[R] => [N]","cases":[[[94489280527],[22]],[[12884901896],[-3]],[[12884901896],[-3]]]},"ratden":{"full":"returns the denominator D of the rational number R; always positive\n[R] => [D]\n\n[R(22,7)] => [7]\n[R(-3,4)] => [4]\n[R(3,-4)] => [4]\n","desc":"returns the denominator D of the rational number R; always positive","effect":"[R] => [D]","cases":[[[94489280527],[7]],[[12884901896],[4]],[[12884901896],[4]]]},"from_r":{"full":"decomposes the rational number R into its numerator N and denominator D\n[R] => [N D]\n\n[R(22,7)] => [22 7]\n[R(-3,4)] => [-3 4]\n[R(3,-4)] => [-3 4]\n[R(4,8)] => [4 8] ; no implicit simplification\n","desc":"decomposes the rational number R into its numerator N and denominator D","effect":"[R] => [N D]","cases":[[[94489280527],[22,7]],[[12884901896],[-3,4]],[[12884901896],[-3,4]],[[17179869201],[4,8]]]},"ratsimp":{"full":"fully simplifies the rational number R by dividing both of its components\nby their greatest common divisor\n[R] => [R, simplified]\n\n[R(4,8)] => [R(1,2)]\n[R(-3,12)] => [R(-1,4)]\n[R(17,-51)] => [R(-1,3)]\n","desc":"fully simplifies the rational number R by dividing both of its components\nby their greatest common divisor","effect":"[R] => [R, simplified]","cases":[[[17179869201],[4294967301]],[[12884901912],[4294967304]],[[73014444134],[4294967302]]]},"ratadd":{"full":"returns the simplified sum of the rational numbers Ra and Rb\n[Ra Rb] => [Ra + Rb]\n\n[R(-9,-14) R(-3,19)] => [R(129,266)]\n[R(17,30) R(18,10)] => [R(71,30)]\n[R(-27,14) R(15,-23)] => [R(-831,322)]\n[R(3,-9) R(8,3)] => [R(7,3)]\n[R(-5,27) R(-2,-27)] => [R(-1,9)]\n[R(-27,-8) R(-15,22)] => [R(237,88)]\n[R(-9,-29) R(-27,3)] => [R(-252,29)]\n[R(2,-21) R(4,6)] => [R(4,7)]\n","desc":"returns the simplified sum of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra + Rb]","cases":[[[38654705693,12884901926],[554050781717]],[[73014444093,77309411349],[304942678077]],[[115964117020,64424509486],[3569117823620]],[[12884901906,34359738375],[30064771079]],[[21474836534,8589934647],[4294967314]],[[115964117009,64424509484],[1017907249329]],[[38654705723,115964116998],[1082331758650]],[[8589934634,17179869197],[17179869199]]]},"ratsub":{"full":"returns the simplified difference of the rational numbers Ra and Rb\n[Ra Rb] => [Ra - Rb]\n\n[R(21,25) R(-28,27)] => [R(1267,675)]\n[R(14,7) R(13,6)] => [R(-1,6)]\n[R(-24,-9) R(-5,-21)] => [R(17,7)]\n[R(-27,-2) R(-2,26)] => [R(353,26)]\n[R(-27,3) R(2,-22)] => [R(-98,11)]\n[R(-4,23) R(-9,13)] => [R(155,299)]\n[R(-14,19) R(-18,-11)] => [R(-496,209)]\n[R(-29,21) R(-15,-16)] => [R(-779,336)]\n","desc":"returns the simplified difference of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra - Rb]","cases":[[[90194313267,120259084342],[5441723565383]],[[60129542159,55834574861],[4294967308]],[[103079215123,21474836523],[73014444047]],[[115964116997,8589934644],[1516123455541]],[[115964116998,8589934636],[420906795030]],[[17179869230,38654705690],[665719931479]],[[60129542182,77309411351],[2130303779234]],[[124554051626,64424509473],[3345779524256]]]},"ratmul":{"full":"returns the simplified product of the rational numbers Ra and Rb\n[Ra Rb] => [Ra × Rb]\n\n[R(-24,26) R(-1,-30)] => [R(-2,65)]\n[R(19,4) R(27,2)] => [R(513,8)]\n[R(25,27) R(4,-11)] => [R(-100,297)]\n[R(1,18) R(4,8)] => [R(1,36)]\n[R(1,27) R(-8,29)] => [R(-8,783)]\n[R(25,-13) R(-6,24)] => [R(25,52)]\n[R(6,-13) R(9,23)] => [R(-54,299)]\n[R(11,8) R(-19,-19)] => [R(11,8)]\n","desc":"returns the simplified product of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra × Rb]","cases":[[[103079215156,4294967357],[8589934722]],[[81604378633,115964116997],[2203318222865]],[[107374182455,17179869206],[429496730194]],[[4294967333,17179869201],[4294967369]],[[4294967351,34359738426],[34359739934]],[[107374182426,25769803824],[107374182505]],[[25769803802,38654705711],[231928234582]],[[47244640273,81604378663],[47244640273]]]},"ratdiv":{"full":"returns the simplified quotient of the rational numbers Ra and Rb\n[Ra Rb] => [Ra / Rb]\n\n[R(-30,-22) R(15,12)] => [R(12,11)]\n[R(13,28) R(-15,29)] => [R(-377,420)]\n[R(7,-30) R(-22,-12)] => [R(-7,55)]\n[R(15,4) R(8,-8)] => [R(-15,4)]\n[R(-23,28) R(-16,-15)] => [R(-345,448)]\n[R(-18,12) R(6,18)] => [R(-9,2)]\n[R(29,-2) R(11,-21)] => [R(609,22)]\n[R(-23,25) R(25,-3)] => [R(69,625)]\n","desc":"returns the simplified quotient of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra / Rb]","cases":[[[128849018925,64424509465],[51539607575]],[[55834574905,64424509498],[1619202671432]],[[30064771132,94489280537],[30064771182]],[[64424509449,34359738384],[64424509448]],[[98784247864,68719476767],[1481763718016]],[[77309411352,25769803813],[38654705668]],[[124554051588,47244640298],[2615635083309]],[[98784247858,107374182406],[296352744675]]]},"ratmod":{"full":"returns the simplified modulus of the rational numbers Ra and Rb\n[Ra Rb] => [Ra % Rb]\n\n[R(-15,-3) R(-16,-10)] => [R(1,5)]\n[R(4,2) R(21,21)] => [R(0,1)]\n[R(24,10) R(-18,-3)] => [R(12,5)]\n[R(3,-7) R(-2,16)] => [R(-3,56)]\n[R(4,28) R(-29,7)] => [R(-4,1)]\n[R(7,-27) R(10,23)] => [R(109,621)]\n[R(28,-3) R(30,-12)] => [R(-11,6)]\n[R(-29,21) R(19,-23)] => [R(-268,483)]\n","desc":"returns the simplified modulus of the rational numbers Ra and Rb","effect":"[Ra Rb] => [Ra % Rb]","cases":[[[64424509447,68719476757],[4294967307]],[[17179869189,90194313259],[3]],[[103079215125,77309411335],[51539607563]],[[12884901902,8589934624],[12884902000]],[[17179869241,124554051598],[17179869186]],[[30064771126,42949673007],[468151436507]],[[120259084294,128849018904],[47244640268]],[[124554051626,81604378670],[1151051236294]]]},"ratsign":{"full":"returns the sign of the rational number R\n[R] => [-1 | 0 | 1]\n\n[R(4,3)] => [1]\n[R(4,-3)] => [-1]\n[R(0,10)] => [0]\n[R(-3,4)] => [-1]\n[R(-3,-4)] => [1]\n","desc":"returns the sign of the rational number R","effect":"[R] => [-1 | 0 | 1]","cases":[[[17179869191],[1]],[[17179869190],[-1]],[[21],[0]],[[12884901896],[-1]],[[12884901897],[1]]]}},"string":{"strpack":{"full":"convert a 0-terminated string on the stack to a single base-128 integer\n[0 ... c b a] => [\"abc...\"]\n\n[0 99 98 97] => [\"abc\"]\n[0 99 98 97] => [1634657]\n[0] => [0]\n","desc":"convert a 0-terminated string on the stack to a single base-128 integer","effect":"[0 ... c b a] => [\"abc...\"]","cases":[[[0,99,98,97],[1634657]],[[0,99,98,97],[1634657]],[[0],[0]]]},"strunpack":{"full":"convert a single base-128 integer to a 0-terminated string on the stack\n[\"abc...\"] => [0 ... c b a]\n\n[\"abc\"] => [0 99 98 97]\n[1634657] => [0 99 98 97]\n[0] => [0]\n","desc":"convert a single base-128 integer to a 0-terminated string on the stack","effect":"[\"abc...\"] => [0 ... c b a]","cases":[[[1634657],[0,99,98,97]],[[1634657],[0,99,98,97]],[[0],[0]]]},"strlen":{"full":"returns the length of a packed string, which is just the\nvalue itself log-128, +1 if the integer logarithm isn't exact.\n[S] => [len(S)]\n\n[\"\"] => [0]\n[\"abc\"] => [3]\n[\"foobar\"] => [6]\n","desc":"returns the length of a packed string, which is just the\nvalue itself log-128, +1 if the integer logarithm isn't exact.","effect":"[S] => [len(S)]","cases":[[[0],[0]],[[1634657],[3]],[[3943255767014],[6]]]},"strcat":{"full":"takes two packed strings and returns their concatenation (as a packed string)\n[S T] => [S+T]\n\n[\"foo\" \"\"] => [\"foo\"]\n[\"\" \"foo\"] => [\"foo\"]\n[\"foo\" \"bar\"] => [\"foobar\"]\n","desc":"takes two packed strings and returns their concatenation (as a packed string)","effect":"[S T] => [S+T]","cases":[[[1832934,0],[1832934]],[[0,1832934],[1832934]],[[1832934,1880290],[3943255767014]]]},"strrev":{"full":"reverses a packed string \"in-place\"\n[S] => [S']\n\n[\"foo\"] => [\"oof\"]\n[\"bark\"] => [\"krab\"]\n[\"ab\"] => [\"ba\"] ['a'] => ['a'] [\"\"] => [\"\"]\n","desc":"reverses a packed string \"in-place\"","effect":"[S] => [S']","cases":[[[1832934],[1685487]],[[226275554],[207124843]],[[12641],[12514]],[[97],[97]],[[0],[0]]]},"strslice":{"full":"takes a packed string S, a start index I, and a length L and returns the\ncorresponding substring (simply by doing division with powers of 128; neat)\n[S I L] => [S']\n\n[\"foobar\" 0 6] => [\"foobar\"]\n[\"foobar\" 1 4] => [\"ooba\"]\n[\"foobar\" 1 10] => [\"oobar\"]\n[\"foobar\" 5 1] => ['r']\n[\"foobar\" 6 0] => [\"\"]\n","desc":"takes a packed string S, a start index I, and a length L and returns the\ncorresponding substring (simply by doing division with powers of 128; neat)","effect":"[S I L] => [S']","cases":[[[3943255767014,0,6],[3943255767014]],[[3943255767014,1,4],[205043695]],[[3943255767014,1,10],[30806685679]],[[3943255767014,5,1],[114]],[[3943255767014,6,0],[0]]]},"strindex":{"full":"returns the index I of substring T in string S (or -1 if not found)\n[S T] => [I]\n\n[\"foobar\" 'o'] => [1]\n[\"foobar\" \"ob\"] => [2]\n[\"foobar\" \"\"] => [0]\n[\"foobar\" \"bar\"] => [3]\n[\"foobar\" \"bark\"] => [-1]\n","desc":"returns the index I of substring T in string S (or -1 if not found)","effect":"[S T] => [I]","cases":[[[3943255767014,111],[1]],[[3943255767014,12655],[2]],[[3943255767014,0],[0]],[[3943255767014,1880290],[3]],[[3943255767014,226275554],[-1]]]},"charat":{"full":"returns the character C at index I in string S\n[S I] => [C]\n\n[\"foobar\" 1] => ['o']\n[\"foobar\" 3] => ['b']\n[\"foobar\" 5] => ['r']\n[\"foobar\" 6] => [\"\"]\n","desc":"returns the character C at index I in string S","effect":"[S I] => [C]","cases":[[[3943255767014,1],[111]],[[3943255767014,3],[98]],[[3943255767014,5],[114]],[[3943255767014,6],[0]]]},"isalpha":{"full":"returns 1 if the character at the top of the stack is\nalphabetical (ASCII 65-90 or 97-122), 0 otherwise\n[C] => [0 | 1]\n\n['@'] => [0] ['a'] => [1]\n['z'] => [1] ['['] => [0]\n['`'] => [0] ['A'] => [1]\n['Z'] => [1] ['{'] => [0]\n","desc":"returns 1 if the character at the top of the stack is\nalphabetical (ASCII 65-90 or 97-122), 0 otherwise","effect":"[C] => [0 | 1]","cases":[[[64],[0]],[[97],[1]],[[122],[1]],[[91],[0]],[[96],[0]],[[65],[1]],[[90],[1]],[[123],[0]]]},"strrep":{"full":"returns string S replicated N times\n[S N] => [S']\n\n[\"abc\" 1] => [\"abc\"]\n[\"abc\" 2] => [\"abcabc\"]\n[\"abc\" 0] => [\"\"]\n","desc":"returns string S replicated N times","effect":"[S N] => [S']","cases":[[[1634657,1],[1634657]],[[1634657,2],[3428125831521]],[[1634657,0],[0]]]},"ljustc":{"full":"left-justifies string S to width W with character C\n[S W C] => [S']\n\n[\"foo\" 5 'x'] => [\"fooxx\"]\n[\"foobar\" 4 'x'] => [\"foobar\"]\n[\"\" 3 'x'] => [\"xxx\"]\n","desc":"left-justifies string S to width W with character C","effect":"[S W C] => [S']","cases":[[[1832934,5,120],[32465745894]],[[3943255767014,4,120],[3943255767014]],[[0,3,120],[1981560]]]},"ljust":{"full":"left-justifies string S to width W with spaces\n[S W] => [S']\n\n[\"foo\" 5] => [\"foo \"]\n[\"foobar\" 4] => [\"foobar\"]\n[\"\" 3] => [528416]\n","desc":"left-justifies string S to width W with spaces","effect":"[S W] => [S']","cases":[[[1832934,5],[8658876390]],[[3943255767014,4],[3943255767014]],[[0,3],[528416]]]},"rjustc":{"full":"right-justifies string S to width W with character C\n[S W C] => [S']\n\n[\"foo\" 5 'x'] => [\"xxfoo\"]\n[\"foobar\" 4 'x'] => [\"foobar\"]\n[\"\" 3 'x'] => [\"xxx\"]\n","desc":"right-justifies string S to width W with character C","effect":"[S W C] => [S']","cases":[[[1832934,5,120],[30030806136]],[[3943255767014,4,120],[3943255767014]],[[0,3,120],[1981560]]]},"rjust":{"full":"right-justifies string S to width W with spaces\n[S W C] => [S']\n\n[\"foo\" 5] => [\" foo\"]\n[\"foobar\" 4] => [\"foobar\"]\n[\"\" 3] => [528416]\n","desc":"right-justifies string S to width W with spaces","effect":"[S W C] => [S']","cases":[[[1832934,5],[30030794784]],[[3943255767014,4],[3943255767014]],[[0,3],[528416]]]},"centerc":{"full":"centers string S to width W with character C, favoring left alignment when\nthere's a parity mismatch (even-length string to odd width or vice versa)\n[S W C] => [S']\n\n[\"abc\" 7 'x'] => [\"xxabcxx\"]\n[\"abc\" 6 'x'] => [\"xabcxx\"]\n[\"abcd\" 6 'o'] => [\"oabcdo\"]\n[\"abcd\" 7 'o'] => [\"oabcdoo\"]\n[\"abcd\" 3 '!'] => [\"abcd\"]\n","desc":"centers string S to width W with character C, favoring left alignment when\nthere's a parity mismatch (even-length string to odd width or vice versa)","effect":"[S W C] => [S']","cases":[[[1634657,7,120],[531915532172408]],[[1634657,6,120],[4155590095096]],[[211349857,6,111],[3840983740655]],[[211349857,7,111],[492024146473199]],[[211349857,3,33],[211349857]]]},"center":{"full":"centers string S to width W with spaces\n[S W] => [S']\n\n[\"abc\" 7] => [\" abc \"]\n[\"abc\" 6] => [\" abc \"]\n[\"abcd\" 6] => [\" abcd \"]\n[\"abcd\" 7] => [\" abcd \"]\n[\"abcd\" 3] => [\"abcd\"]\n","desc":"centers string S to width W with spaces","effect":"[S W] => [S']","cases":[[[1634657,7],[141863782207520]],[[1634657,6],[1108310798496]],[[211349857,6],[1126564409504]],[[211349857,7],[141864052764832]],[[211349857,3],[211349857]]]},"strchop":{"full":"removes the last character of a string\n[S] => [S']\n\n[\"foobar\"] => [\"fooba\"]\n[\"abc\"] => [\"ab\"]\n[\"a\"] => [\"\"]\n","desc":"removes the last character of a string","effect":"[S] => [S']","cases":[[[3943255767014],[26245593062]],[[1634657],[12641]],[[97],[0]]]},"strsplit":{"full":"splits string S on delimiting character C, leaving the resultant substrings\non the stack as a pseudo-array (length at top of stack)\n[S C] => [A]\n\n[\"fooxbar\" 'x'] => [\"foo\" \"bar\" 2]\n[\"foobar\" 'x'] => [\"foobar\" 1]\n[\"foo|bar|baz\" '|'] => [\"foo\" \"bar\" \"baz\" 3]\n[\"foo,,bar\" ','] => [\"foo\" \"\" \"bar\" 3]\n[\"/foo/bar/\" '/'] => [\"\" \"foo\" \"bar\" \"\" 4]\n","desc":"splits string S on delimiting character C, leaving the resultant substrings\non the stack as a pseudo-array (length at top of stack)","effect":"[S C] => [A]","cases":[[[504736757053414,120],[1832934,1880290,2]],[[3943255767014,120],[3943255767014,1]],[[144933976769845798893542,124],[1832934,1880290,2011362,3]],[[64606284361234406,44],[1832934,0,1880290,3]],[[3451313205089661743,47],[0,1832934,1880290,0,4]]]},"lines":{"full":"splits the string S on newlines\n","desc":"","effect":"splits the string S on newlines","cases":[]},"strjoinc":{"full":"joins the pseudo-array of strings A into string S with delimiter string D\n[A D] => [S]\n\n[\"foo\" \"bar\" 2 'x'] => [\"fooxbar\"]\n[\"foo\" \"bar\" \"baz\" 3 '--'] => [\"foo--bar--baz\"]\n[\"foo\" 1 \"?!\"] => [\"foo\"]\n","desc":"joins the pseudo-array of strings A into string S with delimiter string D","effect":"[A D] => [S]","cases":[[[1832934,1880290,2,120],[504736757053414]],[[1832934,1880290,2011362,3,5805],[2374597541788353508880938982]],[[1832934,1,4287],[1832934]]]},"strjoin":{"full":"concatenates the pseudo-array of strings A into string S\n[A] => [S]\n\n[\"foo\" 1] => [\"foo\"]\n[\"foo\" \"bar\" 2] => [\"foobar\"]\n[\"foo\" 'x' \"bar\" 'x' \"baz\" 5] => [\"fooxbarxbaz\"]\n","desc":"concatenates the pseudo-array of strings A into string S","effect":"[A] => [S]","cases":[[[1832934,1],[1832934]],[[1832934,1880290,2],[3943255767014]],[[1832934,120,1880290,120,2011362,5],[144933974518045976819686]]]},"strcountc":{"full":"returns the number of ocurrences of character C in string S\n[S C] => [N]\n\n[\"foobar\" 'a'] => [1]\n[\"foobar\" 'o'] => [2]\n[\"foobar\" 'c'] => [0]\n","desc":"returns the number of ocurrences of character C in string S","effect":"[S C] => [N]","cases":[[[3943255767014,97],[1]],[[3943255767014,111],[2]],[[3943255767014,99],[0]]]},"strcount":{"full":"returns the total number of ocurrences of all characters in string T in string S\n[S T] => [N]\n\n[\"foobar\" 'o'] => [2]\n[\"foobar\" \"ob\"] => [3]\n[\"foxboar\" \"box\"] => [4]\n[\"eunoia\" \"aeiou\"] => [5]\n[\"why\" \"aeiou\"] => [0]\n","desc":"returns the total number of ocurrences of all characters in string T in string S","effect":"[S T] => [N]","cases":[[[3943255767014,111],[2]],[[3943255767014,12655],[3]],[[504740200724454,1980386],[4]],[[3361314945765,31641465569],[5]],[[1995895,31641465569],[0]]]},"strtrans":{"full":"translates all characters in A to the corresponding characters in B\nin stirng S, ; similar to the `tr` utility in Unix. A and B must be\nof the same length. TODO: make this smarter (ranges, length mismatch)\n[S A B] => [S']\n\n[\"abcd\" \"abc\" \"xyz\"] => [\"xyzd\"]\n[\"foobar\" \"oba\" \"ele\"] => [\"feeler\"]\n[\"abcdcba\" \"abcd\" \"xyz|\"] => [\"xyz|zyx\"]\n","desc":"translates all characters in A to the corresponding characters in B\nin stirng S, ; similar to the `tr` utility in Unix. A and B must be\nof the same length. TODO: make this smarter (ranges, length mismatch)","effect":"[S A B] => [S']","cases":[[[211349857,1634657,2014456],[211729656]],[[3943255767014,1601903,1668709],[3944350315238]],[[430004552397153,211349857,262061304],[531956120861944]]]},"strexpand":{"full":"expands the length-2 string S to contain the intervening ASCII characters\n[S] => [S']\n\n[\"CJ\"] => [\"CDEFGHIJ\"]\n[\"DA\"] => [\"DE\"] TODO: bug\n[\"af\"] => [\"abcdef\"]\n[\"09\"] => [\"0123456789\"]\n[\"(1\"] => [\"()*+,-./01\"]\n","desc":"expands the length-2 string S to contain the intervening ASCII characters","effect":"[S] => [S']","cases":[[[9539],[41981847056507459]],[[8388],[8900]],[[13153],[3532016644449]],[[7344],[529798632943928514736]],[[6312],[455430656835745125544]]]},"strsqueeze":{"full":"\"squeezes\" runs of the same character in string S to just one occurrence\n[S] => [S']\n\n[\"abc\"] => [\"abc\"]\n[\"foobar\"] => [\"fobar\"]\n[\"bookkeeper\"] => [\"bokeper\"]\n[\"xxxxxxx\"] => [\"x\"]\n","desc":"\"squeezes\" runs of the same character in string S to just one occurrence","effect":"[S] => [S']","cases":[[[1634657],[1634657]],[[3943255767014],[30806685670]],[[1058805727296038369250],[504877914191842]],[[531921215831160],[120]]]},"strsum":{"full":"returns the sum of the ordinal values of the characters in string S\n[S] => [N]\n\n[\"ABC\"] => [198]\n[\"012\"] => [147]\n[\"a\"] => [97]\n[\"\"] => [] TODO: bug, should be 0\n","desc":"returns the sum of the ordinal values of the characters in string S","effect":"[S] => [N]","cases":[[[1106241],[198]],[[825520],[147]],[[97],[97]],[[0],[]]]},"strrotl":{"full":"rotates the string S to the left N times, wrapping\n[S N]\n\n[\"abc\" 0] => [\"abc\"]\n[\"abcd\" 1] => [\"bcda\"]\n[\"abcd\" 5] => [\"bcda\"]\n[\"foodbar\" 4] => [\"barfood\"]\n","desc":"rotates the string S to the left N times, wrapping","effect":"[S N]","cases":[[[1634657,0],[1634657]],[[211349857,1],[205074914]],[[211349857,5],[205074914]],[[504736715110374,4],[443648594194658]]]},"strrotr":{"full":"rotates the string S to the right N times, wrapping\n[S N]\n\n[\"abcd\" 1] => [\"dabc\"]\n[\"abcd\" 5] => [\"dabc\"]\n[\"foodbar\" 3] => [\"barfood\"]\n","desc":"rotates the string S to the right N times, wrapping","effect":"[S N]","cases":[[[211349857,1],[209236196]],[[211349857,5],[209236196]],[[504736715110374,3],[443648594194658]]]}},"bits":{"band":{"full":"returns the bitwise AND of A and B\n[A B] => [A & B]\n\n[65 47] => [1] [83 25] => [17]\n[40 64] => [0] [74 59] => [10]\n[31 18] => [18] [86 32] => [0]\n[93 79] => [77] [11 79] => [11]\n","desc":"returns the bitwise AND of A and B","effect":"[A B] => [A & B]","cases":[[[65,47],[1]],[[83,25],[17]],[[40,64],[0]],[[74,59],[10]],[[31,18],[18]],[[86,32],[0]],[[93,79],[77]],[[11,79],[11]]]},"bor":{"full":"returns the bitwise OR of A and B\n[A B] => [A | B]\n\n[66 51] => [115] [64 4] => [68]\n[61 77] => [125] [93 65] => [93]\n[14 87] => [95] [71 37] => [103]\n[7 19] => [23] [38 92] => [126]\n","desc":"returns the bitwise OR of A and B","effect":"[A B] => [A | B]","cases":[[[66,51],[115]],[[64,4],[68]],[[61,77],[125]],[[93,65],[93]],[[14,87],[95]],[[71,37],[103]],[[7,19],[23]],[[38,92],[126]]]},"bxor":{"full":"returns the bitwise XOR of A and B\n[A B] => [A ^ B]\n\n[4 14] => [10] [0 80] => [80]\n[51 5] => [54] [97 77] => [44]\n[39 65] => [102] [12 26] => [22]\n[44 36] => [8] [6 21] => [19]\n","desc":"returns the bitwise XOR of A and B","effect":"[A B] => [A ^ B]","cases":[[[4,14],[10]],[[0,80],[80]],[[51,5],[54]],[[97,77],[44]],[[39,65],[102]],[[12,26],[22]],[[44,36],[8]],[[6,21],[19]]]},"bnot":{"full":"returns the infinite-precision bitwise NOT of N by inverting all of its bits\n[N] => [~N]\n\n[58] => [5] [46] => [17]\n[48] => [15] [87] => [40]\n[98] => [29] [51] => [12]\n[3] => [0] [42] => [21]\n","desc":"returns the infinite-precision bitwise NOT of N by inverting all of its bits","effect":"[N] => [~N]","cases":[[[58],[5]],[[46],[17]],[[48],[15]],[[87],[40]],[[98],[29]],[[51],[12]],[[3],[0]],[[42],[21]]]},"blength":{"full":"returns the number of bits in the binary representation of N\n[N] => [# of bits]\n\n[0] => [0] [1] => [1]\n[7] => [3] [8] => [4]\n[255] => [8]\n","desc":"returns the number of bits in the binary representation of N","effect":"[N] => [# of bits]","cases":[[[0],[0]],[[1],[1]],[[7],[3]],[[8],[4]],[[255],[8]]]},"popcount":{"full":"returns the number of set bits in N\n[N] => [popcount]\n\n[0] => [0] [1] => [1]\n[7] => [3] [8] => [1]\n","desc":"returns the number of set bits in N","effect":"[N] => [popcount]","cases":[[[0],[0]],[[1],[1]],[[7],[3]],[[8],[1]]]}},"io":{"print":{"full":"prints the character at the top of the stack until terminating zero\n","desc":"","effect":"prints the character at the top of the stack until terminating zero","cases":[]},"println":{"full":"print with newline\n","desc":"","effect":"print with newline","cases":[]},"getline":{"full":"reads a line of input onto the top of the stack as a packed string\n","desc":"","effect":"reads a line of input onto the top of the stack as a packed string","cases":[]},"readall":{"full":"consume stdin until EOF\n","desc":"","effect":"consume stdin until EOF","cases":[]}},"case":{"upcase":{"full":"returns string S with all alphabetical characters capitalized\n[S] => [S']\n\n[\"\"] => [\"\"]\n[\"abc\"] => [\"ABC\"]\n[\"123\"] => [\"123\"]\n[\"Abc123Def\"] => [\"ABC123DEF\"]\n","desc":"returns string S with all alphabetical characters capitalized","effect":"[S] => [S']","cases":[[[0],[0]],[[1634657],[1106241]],[[842033],[842033]],[[7407033370199781697],[5083175962476077377]]]},"downcase":{"full":"returns string S with all alphabetical characters lower-cased\n[S] => [S']\n\n[\"\"] => [\"\"]\n[\"ABC\"] => [\"abc\"]\n[\"123\"] => [\"123\"]\n[\"aBC123dEF\"] => [\"abc123def\"]\n","desc":"returns string S with all alphabetical characters lower-cased","effect":"[S] => [S']","cases":[[[0],[0]],[[1106241],[1634657]],[[842033],[842033]],[[5083316699964432737],[7407174107688137057]]]},"swapcase":{"full":"returns string S with the case of all alphabetical characters swapped\n[S] => [S']\n\n[\"\"] => [\"\"]\n[\"FooBar\"] => [\"fOObAR\"]\n[\"Abc123deF\"] => [\"aBC123DEf\"]\n","desc":"returns string S with the case of all alphabetical characters swapped","effect":"[S] => [S']","cases":[[[0],[0]],[[3943188658118],[2835153676262]],[[5101331098474443073],[7389018971689771361]]]}},"test":{},"array":{"arysum":{"full":"returns the sum of the array A\n[A] => [sum]\n\n[3 1] => [3]\n[4 3 2 1 4] => [10]\n[-10 -5 7 5 10 5] => [7]\n","desc":"returns the sum of the array A","effect":"[A] => [sum]","cases":[[[3,1],[3]],[[4,3,2,1,4],[10]],[[-10,-5,7,5,10,5],[7]]]},"arydup":{"full":"duplicates the array at the top of the stack\n[A] => [A A]\n\n[1 2 3 3] => [1 2 3 3 1 2 3 3]\n[7 50 10 2] => [7 50 10 2 50 10 2]\n","desc":"duplicates the array at the top of the stack","effect":"[A] => [A A]","cases":[[[1,2,3,3],[1,2,3,3,1,2,3,3]],[[7,50,10,2],[7,50,10,2,50,10,2]]]},"arypop":{"full":"removes the element at the end of the array A\n[A] => [A']\n\n[10 1] => [0]\n[1 2 3 4 4] => [1 2 3 3]\n[7 10 20 30 3] => [7 10 20 2]\n","desc":"removes the element at the end of the array A","effect":"[A] => [A']","cases":[[[10,1],[0]],[[1,2,3,4,4],[1,2,3,3]],[[7,10,20,30,3],[7,10,20,2]]]},"aryshift":{"full":"removes the element at the beginning of the array A\n[A] => [A']\n\n[10 1] => [0]\n[1 2 3 4 4] => [2 3 4 3]\n[7 10 20 30 3] => [7 20 30 2]\n","desc":"removes the element at the beginning of the array A","effect":"[A] => [A']","cases":[[[10,1],[0]],[[1,2,3,4,4],[2,3,4,3]],[[7,10,20,30,3],[7,20,30,2]]]},"arycat":{"full":"returns the concatenation of arrays A and B\n[A B] => [A+B]\n\n[1 2 3 3 4 5 6 3] => [1 2 3 4 5 6 6]\n[7 10 2 5 4 3 3] => [7 10 5 4 3 5]\n","desc":"returns the concatenation of arrays A and B","effect":"[A B] => [A+B]","cases":[[[1,2,3,3,4,5,6,3],[1,2,3,4,5,6,6]],[[7,10,2,5,4,3,3],[7,10,5,4,3,5]]]},"aryindex":{"full":"returns the index I of element E in array A (or -1 if not found)\n[A E] => [I]\n\n[1 2 3 4 4 2] => [1]\n[1 2 3 4 4 4] => [3]\n[1 2 3 4 4 5] => [-1]\n","desc":"returns the index I of element E in array A (or -1 if not found)","effect":"[A E] => [I]","cases":[[[1,2,3,4,4,2],[1]],[[1,2,3,4,4,4],[3]],[[1,2,3,4,4,5],[-1]]]},"aryat":{"full":"returns the element E at index I in array A (or dies on out of bounds)\n[A I] => [E]\n\n[1 2 3 4 4 0] => [1]\n[1 2 3 4 4 2] => [3]\n[1 2 3 4 4 -1] => [4] negative index counts from the end\n","desc":"returns the element E at index I in array A (or dies on out of bounds)","effect":"[A I] => [E]","cases":[[[1,2,3,4,4,0],[1]],[[1,2,3,4,4,2],[3]],[[1,2,3,4,4,-1],[4]]]},"minmax":{"full":"returns the minimum and maximum elements of array A\n[A] => [min max]\n\n[4 3 2 1 4] => [1 4]\n[6 8 -3 4 0 5] => [-3 8]\n[7 1] => [7 7]\n","desc":"returns the minimum and maximum elements of array A","effect":"[A] => [min max]","cases":[[[4,3,2,1,4],[1,4]],[[6,8,-3,4,0,5],[-3,8]],[[7,1],[7,7]]]},"aryrev":{"full":"reverses the array A\n[A] => [A']\n\n[1 2 3 3] => [3 2 1 3]\n[7 1] => [7 1]\n[5 4 3 2 1 5] => [1 2 3 4 5 5]\n","desc":"reverses the array A","effect":"[A] => [A']","cases":[[[1,2,3,3],[3,2,1,3]],[[7,1],[7,1]],[[5,4,3,2,1,5],[1,2,3,4,5,5]]]},"aryrep":{"full":"returns the array A replicated N times\n[A N] => [A']\n\n[3 2 1 3 4] => [3 2 1 3 2 1 3 2 1 3 2 1 12]\n","desc":"returns the array A replicated N times","effect":"[A N] => [A']","cases":[[[3,2,1,3,4],[3,2,1,3,2,1,3,2,1,3,2,1,12]]]}},"syntax":{},"util":{"range":{"full":"inserts between the top two stack values the intervening consecutive elements\n[I J] => [I I+1 ... J]\n\n[2 5] => [2 3 4 5]\n[0 4] => [0 1 2 3 4]\n[-2 0] => [-2 -1 0]\n[-3 3] => [-3 -2 -1 0 1 2 3]\n[4 4] => [4 5] TODO: bug\n","desc":"inserts between the top two stack values the intervening consecutive elements","effect":"[I J] => [I I+1 ... J]","cases":[[[2,5],[2,3,4,5]],[[0,4],[0,1,2,3,4]],[[-2,0],[-2,-1,0]],[[-3,3],[-3,-2,-1,0,1,2,3]],[[4,4],[4,5]]]},"die!":{"full":"prints the string at the top of the stack and halts execution\n","desc":"","effect":"prints the string at the top of the stack and halts execution","cases":[]},"alpha":{"full":"for stoi and itos\n","desc":"","effect":"for stoi and itos","cases":[]},"stoi":{"full":"converts the string S to an integer in base B (2-36)\n[S B]\n\n[\"101010\" 2] => [42]\n[\"0777\" 8] => [511]\n[\"12345\" 10] => [12345]\n[\"123_\" 10] => [123]\n[\"123____\" 10] => [123000] ; TODO: bug\n[\"dead\" 16] => [57005]\n[\"gabe\" 17] => [81699]\n","desc":"converts the string S to an integer in base B (2-36)","effect":"[S B]","cases":[[[1662522251313,2],[42]],[[116251568,8],[511]],[[14336973105,10],[12345]],[[200071473,10],[123]],[[421104295139633,10],[123000]],[[211317476,16],[57005]],[[213430503,17],[81699]]]},"bin":{"full":"creature comforts\n","desc":"","effect":"creature comforts","cases":[]},"itos":{"full":"converts the integer N to a string in base B\n[N B]\n\n[42 2] => [\"101010\"]\n[511 8] => [\"777\"]\n[12345 10] => [\"12345\"]\n[57005 16] => [\"dead\"]\n[81699 17] => [\"gabe\"]\n","desc":"converts the integer N to a string in base B","effect":"[N B]","cases":[[[42,2],[1662522251313]],[[511,8],[908215]],[[12345,10],[14336973105]],[[57005,16],[211317476]],[[81699,17],[213430503]]]},"to_bin":{"full":"creature comforts\n","desc":"","effect":"creature comforts","cases":[]},"digits":{"full":"puts the digits of N in base B on the stack as a pseudo-array\n[N B] => [Dn ...D0 n]\n\n[42 2] => [1 0 1 0 1 0 6]\n[12345 10] => [1 2 3 4 5 5]\n[255 16] => [15 15 2]\n[256 16] => [1 0 0 3]\n","desc":"puts the digits of N in base B on the stack as a pseudo-array","effect":"[N B] => [Dn ...D0 n]","cases":[[[42,2],[1,0,1,0,1,0,6]],[[12345,10],[1,2,3,4,5,5]],[[255,16],[15,15,2]],[[256,16],[1,0,0,3]]]},"inc":{"full":"increments the value at heap address N TODO: make heap effects test-able ?\n[N]\n","desc":"increments the value at heap address N TODO: make heap effects test-able ?","effect":"[N]","cases":[]},"dec":{"full":"decrements the value at heap address N\n[N]\n","desc":"decrements the value at heap address N","effect":"[N]","cases":[]},"eq":{"full":"pops A and B and pushes 1 if they're equal, 0 otherwise\n[A B] => [A == B]\n\n[1 2] => [0]\n[3 3] => [1]\n[-4 4] => [0]\n['A' 65] => [1]\n['B' 65] => [0]\n","desc":"pops A and B and pushes 1 if they're equal, 0 otherwise","effect":"[A B] => [A == B]","cases":[[[1,2],[0]],[[3,3],[1]],[[-4,4],[0]],[[65,65],[1]],[[66,65],[0]]]},"neq":{"full":"pops A and B and pushes 1 if they're not equal, 0 otherwise\n[A B] => [A != B]\n\n[1 2] => [1]\n[3 3] => [0]\n[-4 4] => [1]\n['A' 65] => [0]\n['B' 65] => [1]\n","desc":"pops A and B and pushes 1 if they're not equal, 0 otherwise","effect":"[A B] => [A != B]","cases":[[[1,2],[1]],[[3,3],[0]],[[-4,4],[1]],[[65,65],[0]],[[66,65],[1]]]},"gt":{"full":"pops A and B and pushes 1 if A is greater than B, 0 otherwise\n[A B] => [A > B]\n\n[4 3] => [1]\n[3 4] => [0]\n[2 2] => [0]\n[2 1] => [1]\n","desc":"pops A and B and pushes 1 if A is greater than B, 0 otherwise","effect":"[A B] => [A > B]","cases":[[[4,3],[1]],[[3,4],[0]],[[2,2],[0]],[[2,1],[1]]]},"lt":{"full":"pops A and B and pushes 1 if A is less than than B, 0 otherwise\n[A B] => [A < B]\n\n[3 4] => [1]\n[4 3] => [0]\n[2 2] => [0]\n[1 2] => [1]\n","desc":"pops A and B and pushes 1 if A is less than than B, 0 otherwise","effect":"[A B] => [A < B]","cases":[[[3,4],[1]],[[4,3],[0]],[[2,2],[0]],[[1,2],[1]]]},"heap_seeking_missile":{"full":"Though extremely rare, it's possible that we know a particular value is\nstored in the heap at some key, just not which one. This subroutine takes\na value V to search for and a starting index I, and either returns the first\nkey associated with that value or loops forever. Probably don't touch.\n[V I]\n","desc":"Though extremely rare, it's possible that we know a particular value is\nstored in the heap at some key, just not which one. This subroutine takes\na value V to search for and a starting index I, and either returns the first\nkey associated with that value or loops forever. Probably don't touch.","effect":"[V I]","cases":[]}},"prime":{"prime?":{"full":"[n] => [0|1]\n","desc":"","effect":"[n] => [0|1]","cases":[]},"factor":{"full":"prime factorization\n","desc":"","effect":"prime factorization","cases":[]}}}
|
@@ -4,43 +4,55 @@ import stack ; to_a
|
|
4
4
|
import string ; isalpha, strcat, strjoin, strrev, strunpack
|
5
5
|
import util ; eq
|
6
6
|
|
7
|
+
; returns whether the string S is the same forwards and backwards
|
8
|
+
; [S] => [0 | 1]
|
9
|
+
;
|
10
|
+
; ["racecar"] => [1]
|
11
|
+
; ["divider"] => [0]
|
12
|
+
; ["redivider"] => [1]
|
7
13
|
palindrome?: dup :strrev :eq ret
|
8
14
|
|
9
|
-
|
10
|
-
|
15
|
+
; returns whether the strings S and T are composed of the same characters
|
16
|
+
; [S T] => [0 | 1]
|
17
|
+
;
|
18
|
+
; ["allergy" "gallery"] => [1]
|
19
|
+
; ["largely" "regally"] => [1]
|
20
|
+
; ["foo" "bar"] => [0]
|
11
21
|
anagrams?:
|
12
22
|
:strunpack push 0 :to_a :sort :strjoin swap
|
13
23
|
:strunpack push 0 :to_a :sort :strjoin :eq ret
|
14
24
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
25
|
+
; returns the sum of the alphabetical characters in string S where A=1, B=2...
|
26
|
+
; [S] => [sum]
|
27
|
+
;
|
28
|
+
; ["Math"] => [42]
|
29
|
+
; ["wizards"] => [100]
|
30
|
+
; ["AbCd"] => [10]
|
31
|
+
isop: :upcase push 0 swap
|
32
|
+
_isop_loop: dup jz _isop_done
|
20
33
|
swap copy 1 push 128 mod
|
21
|
-
dup :isalpha jz _isop_no
|
22
|
-
|
23
|
-
_isop_resume:
|
24
|
-
sub add
|
25
|
-
swap push 128 div jump _isop_loop
|
26
|
-
|
34
|
+
dup :isalpha jz _isop_no push 64
|
35
|
+
_isop_resume: sub add swap push 128 div jump _isop_loop
|
27
36
|
_isop_no: dup jump _isop_resume
|
28
|
-
|
29
37
|
_isop_done: pop ret
|
30
38
|
|
31
|
-
|
32
|
-
|
39
|
+
; returns the elements of the Collatz sequence for integer N as a pseudo-array
|
40
|
+
; ! may run forever on some as-yet-unknown input
|
41
|
+
; [N] => [A]
|
42
|
+
;
|
43
|
+
; [1] => [1 1]
|
44
|
+
; [2] => [2 1 2]
|
45
|
+
; [3] => [3 10 5 16 8 4 2 1 8]
|
46
|
+
; [4] => [4 2 1 3]
|
47
|
+
; [5] => [5 16 8 4 2 1 6]
|
33
48
|
collatz: push 1 ; sequence length
|
34
49
|
_collatz_loop:
|
35
50
|
copy 1 dup push 1 sub jz _collatz_done
|
36
|
-
dup push 2 mod
|
51
|
+
dup push 2 mod
|
37
52
|
swap copy 1 push 2 mul $++ mul
|
38
53
|
push 2 copy 2 sub div add
|
39
54
|
swap $++ jump _collatz_loop
|
40
|
-
|
41
55
|
_collatz_done: pop ret
|
42
56
|
|
43
|
-
|
44
|
-
|
45
|
-
ruby:
|
46
|
-
push "'" :strcat push "ruby -e 'p " swap :strcat shell ret
|
57
|
+
; ruby:
|
58
|
+
; push "'" :strcat push "ruby -e 'p " swap :strcat shell ret
|
@@ -130,7 +130,7 @@ neg?: :sign push -1 :eq ret
|
|
130
130
|
; returns a pseudo-array of the positive divisors of N; as an optimization,
|
131
131
|
; they're not returned in ascending order, but rather in two "halves".
|
132
132
|
; The alternative is unnecessarily invoking to_a and clobbering heap.
|
133
|
-
; [N]
|
133
|
+
; [N] => [D1 ... Dn n]
|
134
134
|
;
|
135
135
|
; [10] => [1 2 10 5 4]
|
136
136
|
; [12] => [1 2 3 12 6 4 6]
|
@@ -49,7 +49,7 @@ strlen: dup push 128 :ilog swap push 128 mod push 0 :neq add ret
|
|
49
49
|
strcat: push 128 copy 2 :strlen :pow mul add ret
|
50
50
|
|
51
51
|
; reverses a packed string "in-place"
|
52
|
-
; [S] => [
|
52
|
+
; [S] => [S']
|
53
53
|
;
|
54
54
|
; ["foo"] => ["oof"]
|
55
55
|
; ["bark"] => ["krab"]
|
@@ -65,7 +65,7 @@ _strrev_done: pop ret
|
|
65
65
|
|
66
66
|
; takes a packed string S, a start index I, and a length L and returns the
|
67
67
|
; corresponding substring (simply by doing division with powers of 128; neat)
|
68
|
-
; [S I L] => [
|
68
|
+
; [S I L] => [S']
|
69
69
|
;
|
70
70
|
; ["foobar" 0 6] => ["foobar"]
|
71
71
|
; ["foobar" 1 4] => ["ooba"]
|
@@ -78,8 +78,8 @@ strslice:
|
|
78
78
|
swap push 128 swap :pow
|
79
79
|
mod slide 1 ret
|
80
80
|
|
81
|
-
; returns the index of substring T in string S (or -1 if not found)
|
82
|
-
; [S T] => [
|
81
|
+
; returns the index I of substring T in string S (or -1 if not found)
|
82
|
+
; [S T] => [I]
|
83
83
|
;
|
84
84
|
; ["foobar" 'o'] => [1]
|
85
85
|
; ["foobar" "ob"] => [2]
|
@@ -95,8 +95,8 @@ _strindex_loop: ; [t s i]
|
|
95
95
|
_strindex_no: push -1 slide 3 ret
|
96
96
|
_strindex_found: slide 2 ret
|
97
97
|
|
98
|
-
; returns the character at index I in string S
|
99
|
-
; [S I] => [
|
98
|
+
; returns the character C at index I in string S
|
99
|
+
; [S I] => [C]
|
100
100
|
;
|
101
101
|
; ["foobar" 1] => ['o']
|
102
102
|
; ["foobar" 3] => ['b']
|
@@ -106,7 +106,7 @@ charat: push 1 :strslice ret
|
|
106
106
|
|
107
107
|
; returns 1 if the character at the top of the stack is
|
108
108
|
; alphabetical (ASCII 65-90 or 97-122), 0 otherwise
|
109
|
-
; [C] => [0
|
109
|
+
; [C] => [0 | 1]
|
110
110
|
;
|
111
111
|
; ['@'] => [0] ['a'] => [1]
|
112
112
|
; ['z'] => [1] ['['] => [0]
|
@@ -119,7 +119,7 @@ isalpha:
|
|
119
119
|
_isalpha_no: dup sub ret
|
120
120
|
|
121
121
|
; returns string S replicated N times
|
122
|
-
; [S N] => [S
|
122
|
+
; [S N] => [S']
|
123
123
|
;
|
124
124
|
; ["abc" 1] => ["abc"]
|
125
125
|
; ["abc" 2] => ["abcabc"]
|
@@ -138,7 +138,7 @@ _strrep_done: swap slide 2 ret
|
|
138
138
|
_justc: swap copy 2 :strlen sub push 0 :max :strrep ret
|
139
139
|
|
140
140
|
; left-justifies string S to width W with character C
|
141
|
-
; [S W C] => [S
|
141
|
+
; [S W C] => [S']
|
142
142
|
;
|
143
143
|
; ["foo" 5 'x'] => ["fooxx"]
|
144
144
|
; ["foobar" 4 'x'] => ["foobar"]
|
@@ -146,7 +146,7 @@ _justc: swap copy 2 :strlen sub push 0 :max :strrep ret
|
|
146
146
|
ljustc: :_justc :strcat ret
|
147
147
|
|
148
148
|
; left-justifies string S to width W with spaces
|
149
|
-
; [S W] => [S
|
149
|
+
; [S W] => [S']
|
150
150
|
;
|
151
151
|
; ["foo" 5] => ["foo "]
|
152
152
|
; ["foobar" 4] => ["foobar"]
|
@@ -154,7 +154,7 @@ ljustc: :_justc :strcat ret
|
|
154
154
|
ljust: push ' ' :ljustc ret
|
155
155
|
|
156
156
|
; right-justifies string S to width W with character C
|
157
|
-
; [S W C] => [S
|
157
|
+
; [S W C] => [S']
|
158
158
|
;
|
159
159
|
; ["foo" 5 'x'] => ["xxfoo"]
|
160
160
|
; ["foobar" 4 'x'] => ["foobar"]
|
@@ -162,7 +162,7 @@ ljust: push ' ' :ljustc ret
|
|
162
162
|
rjustc: :_justc swap :strcat ret
|
163
163
|
|
164
164
|
; right-justifies string S to width W with spaces
|
165
|
-
; [S W C] => [S
|
165
|
+
; [S W C] => [S']
|
166
166
|
;
|
167
167
|
; ["foo" 5] => [" foo"]
|
168
168
|
; ["foobar" 4] => ["foobar"]
|
@@ -172,7 +172,7 @@ rjust: push ' ' :rjustc ret
|
|
172
172
|
; centers string S to width W with character C, favoring left alignment when
|
173
173
|
; there's a parity mismatch (even-length string to odd width or vice versa)
|
174
174
|
; ! TODO: This seems unnecessarily intricate, but perhaps just its nature.
|
175
|
-
; [S W C] => [S
|
175
|
+
; [S W C] => [S']
|
176
176
|
;
|
177
177
|
; ["abc" 7 'x'] => ["xxabcxx"]
|
178
178
|
; ["abc" 6 'x'] => ["xabcxx"]
|
@@ -190,7 +190,7 @@ centerc:
|
|
190
190
|
slide 2 ret
|
191
191
|
|
192
192
|
; centers string S to width W with spaces
|
193
|
-
; [S W] => [S
|
193
|
+
; [S W] => [S']
|
194
194
|
;
|
195
195
|
; ["abc" 7] => [" abc "]
|
196
196
|
; ["abc" 6] => [" abc "]
|
@@ -202,7 +202,7 @@ center: push ' ' :centerc ret
|
|
202
202
|
;;;
|
203
203
|
|
204
204
|
; removes the last character of a string
|
205
|
-
; [S] => [S
|
205
|
+
; [S] => [S']
|
206
206
|
;
|
207
207
|
; ["foobar"] => ["fooba"]
|
208
208
|
; ["abc"] => ["ab"]
|
@@ -296,7 +296,7 @@ strcount:
|
|
296
296
|
; in stirng S, ; similar to the `tr` utility in Unix. A and B must be
|
297
297
|
; of the same length. TODO: make this smarter (ranges, length mismatch)
|
298
298
|
; ! clobbers heap addresses -1, -2, and -3
|
299
|
-
; [S A B] => [S]
|
299
|
+
; [S A B] => [S']
|
300
300
|
;
|
301
301
|
; ["abcd" "abc" "xyz"] => ["xyzd"]
|
302
302
|
; ["foobar" "oba" "ele"] => ["feeler"]
|
@@ -316,7 +316,7 @@ _strtrans_no: pop ret
|
|
316
316
|
|
317
317
|
; expands the length-2 string S to contain the intervening ASCII characters
|
318
318
|
; ! TODO: make this smarter; multiple ranges in one string
|
319
|
-
; [S] => [S
|
319
|
+
; [S] => [S']
|
320
320
|
;
|
321
321
|
; ["CJ"] => ["CDEFGHIJ"]
|
322
322
|
; ["DA"] => ["DE"] TODO: bug
|
@@ -328,7 +328,7 @@ strexpand:
|
|
328
328
|
swap :range :strpack :strrev ret
|
329
329
|
|
330
330
|
; "squeezes" runs of the same character in string S to just one occurrence
|
331
|
-
; [S] => [S
|
331
|
+
; [S] => [S']
|
332
332
|
;
|
333
333
|
; ["abc"] => ["abc"]
|
334
334
|
; ["foobar"] => ["fobar"]
|
@@ -47,7 +47,7 @@ _stoi_loop: ; [b s a]
|
|
47
47
|
_stoi_invalid: pop pop slide 1 swap div ret ; return what we were able to parse
|
48
48
|
_stoi_done: swap slide 2 ret
|
49
49
|
|
50
|
-
|
50
|
+
; creature comforts
|
51
51
|
bin: push 2 :stoi ret
|
52
52
|
oct: push 8 :stoi ret
|
53
53
|
to_i: push 10 :stoi ret
|
@@ -71,11 +71,14 @@ _itos_loop:
|
|
71
71
|
swap jump _itos_loop
|
72
72
|
_itos_done: swap slide 2 ret
|
73
73
|
|
74
|
-
; creature
|
75
|
-
|
74
|
+
; creature comforts
|
75
|
+
to_bin: push 2 :itos ret
|
76
|
+
to_oct: push 8 :itos ret
|
77
|
+
to_s: push 10 :itos ret
|
78
|
+
to_hex: push 16 :itos ret
|
76
79
|
|
77
80
|
; puts the digits of N in base B on the stack as a pseudo-array
|
78
|
-
; [N B]
|
81
|
+
; [N B] => [Dn ...D0 n]
|
79
82
|
;
|
80
83
|
; [42 2] => [1 0 1 0 1 0 6]
|
81
84
|
; [12345 10] => [1 2 3 4 5 5]
|
@@ -127,8 +127,22 @@ module Spitewaste
|
|
127
127
|
def propagate_macros
|
128
128
|
# Macros are write-once, allowing user code to customize the special
|
129
129
|
# values that get used to drive certain behavior in the standard library.
|
130
|
+
|
131
|
+
parse = -> s { s.split(?,).map &:strip }
|
132
|
+
|
133
|
+
# Macro "functions" get handled first.
|
134
|
+
@src.gsub!(/(\$\S+?)\(([^)]+)\)\s*{(.+?)}/m) {
|
135
|
+
@macros[$1] ||= [$2, $3]; ''
|
136
|
+
}
|
137
|
+
@src.gsub!(/(\$\S+?)\(([^)]+)\)/) {
|
138
|
+
params, body = @macros[$1]
|
139
|
+
raise "no macro function '#$1'" unless body
|
140
|
+
map = parse[params].zip(parse[$2]).to_h
|
141
|
+
body.gsub(/`(.+?)`/) { map[$1] }
|
142
|
+
}
|
143
|
+
|
130
144
|
@src.gsub!(/(\$\S+)\s*=\s*(.+)/) { @macros[$1] ||= $2; '' }
|
131
|
-
@src.gsub!(/(\$\S+)/) { @macros[$1] || raise("no macro '
|
145
|
+
@src.gsub!(/(\$\S+)/) { @macros[$1] || raise("no macro '#$1'") }
|
132
146
|
end
|
133
147
|
|
134
148
|
def eliminate_dead_code!
|
data/lib/spitewaste/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spitewaste
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.006
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Collided Scope (collidedscope)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-12-
|
11
|
+
date: 2020-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|