spitewaste 0.1.003 → 0.1.004
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 +27 -10
- data/lib/spitewaste.rb +1 -1
- data/lib/spitewaste/cli/exec.rb +10 -13
- data/lib/spitewaste/libspw/array.spw +5 -1
- data/lib/spitewaste/libspw/bits.spw +4 -2
- data/lib/spitewaste/libspw/case.spw +3 -1
- data/lib/spitewaste/libspw/fun.spw +5 -1
- data/lib/spitewaste/libspw/io.spw +2 -0
- data/lib/spitewaste/libspw/math.spw +83 -45
- data/lib/spitewaste/libspw/prime.spw +3 -2
- data/lib/spitewaste/libspw/random.spw +2 -0
- data/lib/spitewaste/libspw/rational.spw +153 -0
- data/lib/spitewaste/libspw/stack.spw +54 -30
- data/lib/spitewaste/libspw/string.spw +228 -92
- data/lib/spitewaste/libspw/test.spw +3 -0
- data/lib/spitewaste/libspw/util.spw +92 -39
- data/lib/spitewaste/parsers/spitewaste.rb +7 -15
- data/lib/spitewaste/version.rb +1 -1
- metadata +3 -2
@@ -1,24 +1,41 @@
|
|
1
|
-
import
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
import io ; println
|
2
|
+
import math ; divmod, pow
|
3
|
+
import stack ; to_a
|
4
|
+
import string ; charat, strcat, strindex, strlen
|
5
|
+
|
6
|
+
; inserts between the top two stack values the intervening consecutive elements
|
7
|
+
; ! TODO: Support step, and negative as well.
|
8
|
+
; [I J] => [I I+1 ... J]
|
9
|
+
;
|
10
|
+
; [2 5] => [2 3 4 5]
|
11
|
+
; [0 4] => [0 1 2 3 4]
|
12
|
+
; [-2 0] => [-2 -1 0]
|
13
|
+
; [-3 3] => [-3 -2 -1 0 1 2 3]
|
14
|
+
; [4 4] => [4 5] TODO: bug
|
5
15
|
range:
|
6
16
|
copy 1 push 1 add swap
|
7
17
|
copy 1 copy 1 sub jn range
|
8
18
|
pop ret
|
9
19
|
|
10
|
-
|
11
|
-
|
12
|
-
die: :println exit
|
13
|
-
;;;
|
20
|
+
; prints the string at the top of the stack and halts execution
|
21
|
+
die!: :println exit
|
14
22
|
|
23
|
+
; for stoi and itos
|
15
24
|
alpha: push "0123456789abcdefghijklmnopqrstuvwxyz" ret
|
16
25
|
|
17
|
-
; string to integer in base
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
26
|
+
; converts the string S to an integer in base B (2-36)
|
27
|
+
; ! TODO: support prefixes?
|
28
|
+
; [S B]
|
29
|
+
;
|
30
|
+
; ["101010" 2] => [42]
|
31
|
+
; ["0777" 8] => [511]
|
32
|
+
; ["12345" 10] => [12345]
|
33
|
+
; ["123_" 10] => [123]
|
34
|
+
; ["123____" 10] => [123000] ; TODO: bug
|
35
|
+
; ["dead" 16] => [57005]
|
36
|
+
; ["gabe" 17] => [81699]
|
37
|
+
stoi: swap push 0 ; accumulator
|
38
|
+
_stoi_loop: ; [b s a]
|
22
39
|
swap dup jz _stoi_done
|
23
40
|
swap copy 2 copy 2
|
24
41
|
:strlen push 1 sub :pow
|
@@ -27,24 +44,24 @@ _stoi_loop: ; [b s t]
|
|
27
44
|
dup jn _stoi_invalid ; found something non-alphanumeric
|
28
45
|
mul add swap push 128 div swap
|
29
46
|
jump _stoi_loop
|
30
|
-
|
31
|
-
_stoi_invalid: pop pop slide 1 swap div ret
|
32
|
-
|
47
|
+
_stoi_invalid: pop pop slide 1 swap div ret ; return what we were able to parse
|
33
48
|
_stoi_done: swap slide 2 ret
|
34
49
|
|
35
|
-
;;;
|
36
|
-
|
50
|
+
;;; creature comforts
|
37
51
|
bin: push 2 :stoi ret
|
38
52
|
oct: push 8 :stoi ret
|
39
53
|
to_i: push 10 :stoi ret
|
40
54
|
hex: push 16 :stoi ret
|
41
55
|
|
42
|
-
|
43
|
-
|
44
|
-
;
|
45
|
-
|
46
|
-
|
47
|
-
|
56
|
+
; converts the integer N to a string in base B
|
57
|
+
; [N B]
|
58
|
+
;
|
59
|
+
; [42 2] => ["101010"]
|
60
|
+
; [511 8] => ["777"]
|
61
|
+
; [12345 10] => ["12345"]
|
62
|
+
; [57005 16] => ["dead"]
|
63
|
+
; [81699 17] => ["gabe"]
|
64
|
+
itos: swap push 0 ; accumulator
|
48
65
|
_itos_loop:
|
49
66
|
swap dup jz _itos_done
|
50
67
|
swap copy 1 copy 3 mod
|
@@ -52,47 +69,83 @@ _itos_loop:
|
|
52
69
|
swap :strcat
|
53
70
|
swap copy 2 div
|
54
71
|
swap jump _itos_loop
|
55
|
-
|
56
72
|
_itos_done: swap slide 2 ret
|
57
73
|
|
74
|
+
; creature comfort
|
58
75
|
to_s: push 10 :itos ret
|
59
76
|
|
60
|
-
|
61
|
-
|
62
|
-
|
77
|
+
; puts the digits of N in base B on the stack as a pseudo-array
|
78
|
+
; [N B]
|
79
|
+
;
|
80
|
+
; [42 2] => [1 0 1 0 1 0 6]
|
81
|
+
; [12345 10] => [1 2 3 4 5 5]
|
82
|
+
; [255 16] => [15 15 2]
|
83
|
+
; [256 16] => [1 0 0 3]
|
84
|
+
digits:
|
63
85
|
copy 1 jz _digits_zero ; special case
|
64
86
|
push -1 swap store
|
65
87
|
push -1 swap ; sentinel value
|
66
|
-
|
67
88
|
_digits_loop:
|
68
89
|
dup jz _digits_done
|
69
90
|
push -1 load :divmod
|
70
91
|
swap jump _digits_loop
|
71
|
-
|
72
92
|
_digits_zero: dup div ret
|
73
|
-
|
74
93
|
_digits_done: push 1 sub :to_a ret
|
75
94
|
|
76
|
-
;
|
95
|
+
; increments the value at heap address N TODO: make heap effects test-able ?
|
96
|
+
; [N]
|
77
97
|
inc: dup load $++ store ret
|
78
98
|
|
79
|
-
;
|
99
|
+
; decrements the value at heap address N
|
100
|
+
; [N]
|
80
101
|
dec: dup load $-- store ret
|
81
102
|
|
82
|
-
|
83
|
-
|
103
|
+
; pops A and B and pushes 1 if they're equal, 0 otherwise
|
104
|
+
; [A B] => [A == B]
|
105
|
+
;
|
106
|
+
; [1 2] => [0]
|
107
|
+
; [3 3] => [1]
|
108
|
+
; [-4 4] => [0]
|
109
|
+
; ['A' 65] => [1]
|
110
|
+
; ['B' 65] => [0]
|
84
111
|
eq: sub jz _eq_yes push 0 ret
|
85
112
|
_eq_yes: push 1 ret
|
86
113
|
|
114
|
+
; pops A and B and pushes 1 if they're not equal, 0 otherwise
|
115
|
+
; [A B] => [A != B]
|
116
|
+
;
|
117
|
+
; [1 2] => [1]
|
118
|
+
; [3 3] => [0]
|
119
|
+
; [-4 4] => [1]
|
120
|
+
; ['A' 65] => [0]
|
121
|
+
; ['B' 65] => [1]
|
87
122
|
neq: sub jz _neq_no push 1 ret
|
88
123
|
_neq_no: push 0 ret
|
89
124
|
|
90
|
-
|
125
|
+
; pops A and B and pushes 1 if A is greater than B, 0 otherwise
|
126
|
+
; [A B] => [A > B]
|
127
|
+
;
|
128
|
+
; [4 3] => [1]
|
129
|
+
; [3 4] => [0]
|
130
|
+
; [2 2] => [0]
|
131
|
+
; [2 1] => [1]
|
132
|
+
gt: swap ; intentionally flow into lt
|
133
|
+
|
134
|
+
; pops A and B and pushes 1 if A is less than than B, 0 otherwise
|
135
|
+
; [A B] => [A < B]
|
136
|
+
;
|
137
|
+
; [3 4] => [1]
|
138
|
+
; [4 3] => [0]
|
139
|
+
; [2 2] => [0]
|
140
|
+
; [1 2] => [1]
|
91
141
|
lt: sub jn _lt_yes push 0 ret
|
92
142
|
_lt_yes: push 1 ret
|
93
143
|
|
94
|
-
|
95
|
-
|
96
|
-
|
144
|
+
; Though extremely rare, it's possible that we know a particular value is
|
145
|
+
; stored in the heap at some key, just not which one. This subroutine takes
|
146
|
+
; a value V to search for and a starting index I, and either returns the first
|
147
|
+
; key associated with that value or loops forever. Probably don't touch.
|
148
|
+
; [V I]
|
149
|
+
heap_seeking_missile:
|
97
150
|
$++ dup load copy 2 :eq jz heap_search
|
98
151
|
slide 1 ret
|
@@ -57,6 +57,7 @@ module Spitewaste
|
|
57
57
|
private
|
58
58
|
|
59
59
|
def preprocess!
|
60
|
+
@src.prepend "import syntax\n"
|
60
61
|
resolve_imports
|
61
62
|
seed_prng if @seen.include? 'random'
|
62
63
|
resolve_strings
|
@@ -94,7 +95,7 @@ module Spitewaste
|
|
94
95
|
end
|
95
96
|
|
96
97
|
def resolve_strings
|
97
|
-
@src.gsub!(/"([^"]
|
98
|
+
@src.gsub!(/"([^"]*)"/m) {
|
98
99
|
[0, *$1.reverse.bytes] * ' push ' + ' :strpack'
|
99
100
|
}
|
100
101
|
end
|
@@ -118,31 +119,22 @@ module Spitewaste
|
|
118
119
|
|
119
120
|
def fucktionalize
|
120
121
|
# Iteratively remove pseudo-fp calls until we can't to allow nesting.
|
121
|
-
1 while @src.gsub!(/(#{FUCKTIONAL.keys * ?|})\s*\((
|
122
|
+
1 while @src.gsub!(/(#{FUCKTIONAL.keys * ?|})\s*\((.+?)\)/m) do
|
122
123
|
FUCKTIONAL[$1] % [gensym, $2]
|
123
124
|
end
|
124
125
|
end
|
125
126
|
|
126
127
|
def propagate_macros
|
127
|
-
|
128
|
+
# Macros are write-once, allowing user code to customize the special
|
129
|
+
# values that get used to drive certain behavior in the standard library.
|
130
|
+
@src.gsub!(/(\$\S+)\s*=\s*(.+)/) { @macros[$1] ||= $2; '' }
|
128
131
|
@src.gsub!(/(\$\S+)/) { @macros[$1] || raise("no macro '#{$1}'") }
|
129
|
-
|
130
|
-
# @src.gsub!(/(\$[^(]+)\s*\((.+)\)\s*{(.+)}/m) { @macros[$1] = $2, $3; '' }
|
131
|
-
# @src.gsub!(/(\$[^(]+)\((.+?)\)/m) {
|
132
|
-
# unless (params, body = @macros[$1])
|
133
|
-
# raise "no macro function '#{$1}'"
|
134
|
-
# end
|
135
|
-
|
136
|
-
# params = params.split(?,).map &:strip
|
137
|
-
# args = $2.split ?,
|
138
|
-
# body.gsub /\b(#{params * ?|})\b/, params.zip(args).to_h
|
139
|
-
# }
|
140
132
|
end
|
141
133
|
|
142
134
|
def eliminate_dead_code!
|
143
135
|
tokens = @src.split
|
144
136
|
|
145
|
-
# We need an entry point
|
137
|
+
# We need an entry point whence to begin determining which routines
|
146
138
|
# are never invoked, but Whitespace programs aren't required to start
|
147
139
|
# with a label. Here, we add an implcit "main" to the beginning of the
|
148
140
|
# source unless it already contains an explicit entry point. TODO: better?
|
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.004
|
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-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- lib/spitewaste/libspw/math.spw
|
105
105
|
- lib/spitewaste/libspw/prime.spw
|
106
106
|
- lib/spitewaste/libspw/random.spw
|
107
|
+
- lib/spitewaste/libspw/rational.spw
|
107
108
|
- lib/spitewaste/libspw/stack.spw
|
108
109
|
- lib/spitewaste/libspw/string.spw
|
109
110
|
- lib/spitewaste/libspw/syntax.spw
|