spitewaste 0.1.003 → 0.1.008
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/Rakefile +30 -12
- data/bin/spw +1 -0
- data/lib/spitewaste.rb +1 -1
- data/lib/spitewaste/assembler.rb +4 -4
- data/lib/spitewaste/cli.rb +21 -19
- data/lib/spitewaste/cli/asm.rb +2 -0
- data/lib/spitewaste/cli/compile.rb +2 -0
- data/lib/spitewaste/cli/convert.rb +2 -0
- data/lib/spitewaste/cli/docs.rb +51 -0
- data/lib/spitewaste/cli/exec.rb +12 -13
- data/lib/spitewaste/cli/image.rb +2 -0
- data/lib/spitewaste/libspw/array.spw +75 -20
- data/lib/spitewaste/libspw/bits.spw +70 -68
- data/lib/spitewaste/libspw/case.spw +34 -26
- data/lib/spitewaste/libspw/docs.json +1 -0
- data/lib/spitewaste/libspw/fun.spw +40 -24
- data/lib/spitewaste/libspw/io.spw +2 -0
- data/lib/spitewaste/libspw/math.spw +85 -45
- data/lib/spitewaste/libspw/prime.spw +36 -35
- data/lib/spitewaste/libspw/random.spw +2 -0
- data/lib/spitewaste/libspw/rational.spw +176 -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 +104 -42
- data/lib/spitewaste/parsers/spitewaste.rb +22 -16
- data/lib/spitewaste/version.rb +1 -1
- metadata +5 -2
@@ -1,24 +1,46 @@
|
|
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
|
+
; ["0" 10] => [0] ["-0" 10] => [0]
|
38
|
+
; ["-10001" 2] => [-17]
|
39
|
+
; ["-123" 10] => [-123]
|
40
|
+
; ["-ff" 16] => [-255]
|
41
|
+
stoi: swap dup :_stoi_sign swap copy 1 :eq
|
42
|
+
push 2 mul $-- push -2 swap store push 0
|
43
|
+
_stoi_loop: ; [b s a]
|
22
44
|
swap dup jz _stoi_done
|
23
45
|
swap copy 2 copy 2
|
24
46
|
:strlen push 1 sub :pow
|
@@ -27,24 +49,25 @@ _stoi_loop: ; [b s t]
|
|
27
49
|
dup jn _stoi_invalid ; found something non-alphanumeric
|
28
50
|
mul add swap push 128 div swap
|
29
51
|
jump _stoi_loop
|
52
|
+
_stoi_sign: dup push 0 :charat push '-' :eq copy 1 :strlen :strslice ret
|
53
|
+
_stoi_invalid: pop pop slide 1 swap div push -2 load mul ret
|
54
|
+
_stoi_done: swap slide 2 push -2 load mul ret
|
30
55
|
|
31
|
-
|
32
|
-
|
33
|
-
_stoi_done: swap slide 2 ret
|
34
|
-
|
35
|
-
;;;
|
36
|
-
|
56
|
+
; creature comforts
|
37
57
|
bin: push 2 :stoi ret
|
38
58
|
oct: push 8 :stoi ret
|
39
59
|
to_i: push 10 :stoi ret
|
40
60
|
hex: push 16 :stoi ret
|
41
61
|
|
42
|
-
|
43
|
-
|
44
|
-
;
|
45
|
-
|
46
|
-
|
47
|
-
|
62
|
+
; converts the integer N to a string in base B
|
63
|
+
; [N B]
|
64
|
+
;
|
65
|
+
; [42 2] => ["101010"]
|
66
|
+
; [511 8] => ["777"]
|
67
|
+
; [12345 10] => ["12345"]
|
68
|
+
; [57005 16] => ["dead"]
|
69
|
+
; [81699 17] => ["gabe"]
|
70
|
+
itos: swap push 0 ; accumulator
|
48
71
|
_itos_loop:
|
49
72
|
swap dup jz _itos_done
|
50
73
|
swap copy 1 copy 3 mod
|
@@ -52,47 +75,86 @@ _itos_loop:
|
|
52
75
|
swap :strcat
|
53
76
|
swap copy 2 div
|
54
77
|
swap jump _itos_loop
|
55
|
-
|
56
78
|
_itos_done: swap slide 2 ret
|
57
79
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
80
|
+
; creature comforts
|
81
|
+
to_bin: push 2 :itos ret
|
82
|
+
to_oct: push 8 :itos ret
|
83
|
+
to_s: push 10 :itos ret
|
84
|
+
to_hex: push 16 :itos ret
|
85
|
+
|
86
|
+
; puts the digits of N in base B on the stack as a pseudo-array
|
87
|
+
; [N B] => [Dn ...D0 n]
|
88
|
+
;
|
89
|
+
; [42 2] => [1 0 1 0 1 0 6]
|
90
|
+
; [12345 10] => [1 2 3 4 5 5]
|
91
|
+
; [255 16] => [15 15 2]
|
92
|
+
; [256 16] => [1 0 0 3]
|
93
|
+
digits:
|
63
94
|
copy 1 jz _digits_zero ; special case
|
64
95
|
push -1 swap store
|
65
96
|
push -1 swap ; sentinel value
|
66
|
-
|
67
97
|
_digits_loop:
|
68
98
|
dup jz _digits_done
|
69
99
|
push -1 load :divmod
|
70
100
|
swap jump _digits_loop
|
71
|
-
|
72
101
|
_digits_zero: dup div ret
|
73
|
-
|
74
102
|
_digits_done: push 1 sub :to_a ret
|
75
103
|
|
76
|
-
;
|
104
|
+
; increments the value at heap address N TODO: make heap effects test-able ?
|
105
|
+
; [N]
|
77
106
|
inc: dup load $++ store ret
|
78
107
|
|
79
|
-
;
|
108
|
+
; decrements the value at heap address N
|
109
|
+
; [N]
|
80
110
|
dec: dup load $-- store ret
|
81
111
|
|
82
|
-
|
83
|
-
|
112
|
+
; pops A and B and pushes 1 if they're equal, 0 otherwise
|
113
|
+
; [A B] => [A == B]
|
114
|
+
;
|
115
|
+
; [1 2] => [0]
|
116
|
+
; [3 3] => [1]
|
117
|
+
; [-4 4] => [0]
|
118
|
+
; ['A' 65] => [1]
|
119
|
+
; ['B' 65] => [0]
|
84
120
|
eq: sub jz _eq_yes push 0 ret
|
85
121
|
_eq_yes: push 1 ret
|
86
122
|
|
123
|
+
; pops A and B and pushes 1 if they're not equal, 0 otherwise
|
124
|
+
; [A B] => [A != B]
|
125
|
+
;
|
126
|
+
; [1 2] => [1]
|
127
|
+
; [3 3] => [0]
|
128
|
+
; [-4 4] => [1]
|
129
|
+
; ['A' 65] => [0]
|
130
|
+
; ['B' 65] => [1]
|
87
131
|
neq: sub jz _neq_no push 1 ret
|
88
132
|
_neq_no: push 0 ret
|
89
133
|
|
90
|
-
|
134
|
+
; pops A and B and pushes 1 if A is greater than B, 0 otherwise
|
135
|
+
; [A B] => [A > B]
|
136
|
+
;
|
137
|
+
; [4 3] => [1]
|
138
|
+
; [3 4] => [0]
|
139
|
+
; [2 2] => [0]
|
140
|
+
; [2 1] => [1]
|
141
|
+
gt: swap ; intentionally flow into lt
|
142
|
+
|
143
|
+
; pops A and B and pushes 1 if A is less than than B, 0 otherwise
|
144
|
+
; [A B] => [A < B]
|
145
|
+
;
|
146
|
+
; [3 4] => [1]
|
147
|
+
; [4 3] => [0]
|
148
|
+
; [2 2] => [0]
|
149
|
+
; [1 2] => [1]
|
91
150
|
lt: sub jn _lt_yes push 0 ret
|
92
151
|
_lt_yes: push 1 ret
|
93
152
|
|
94
|
-
|
95
|
-
|
96
|
-
|
153
|
+
; Though extremely rare, it's possible that we know a particular value is
|
154
|
+
; stored in the heap at some key, just not which one. This subroutine takes
|
155
|
+
; a value V to search for and a starting index I, and either returns the first
|
156
|
+
; key associated with that value or loops forever. Probably don't touch.
|
157
|
+
; [V I]
|
158
|
+
heap_seeking_missile:
|
97
159
|
$++ dup load copy 2 :eq jz heap_search
|
98
160
|
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,36 @@ 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
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
#
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
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
|
+
|
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
|
+
|
144
|
+
@src.gsub!(/(\$\S+)\s*=\s*(.+)/) { @macros[$1] ||= $2; '' }
|
145
|
+
@src.gsub!(/(\$\S+)/) { @macros[$1] || raise("no macro '#$1'") }
|
140
146
|
end
|
141
147
|
|
142
148
|
def eliminate_dead_code!
|
143
149
|
tokens = @src.split
|
144
150
|
|
145
|
-
# We need an entry point
|
151
|
+
# We need an entry point whence to begin determining which routines
|
146
152
|
# are never invoked, but Whitespace programs aren't required to start
|
147
153
|
# with a label. Here, we add an implcit "main" to the beginning of the
|
148
154
|
# 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.008
|
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
|
@@ -86,6 +86,7 @@ files:
|
|
86
86
|
- lib/spitewaste/cli/asm.rb
|
87
87
|
- lib/spitewaste/cli/compile.rb
|
88
88
|
- lib/spitewaste/cli/convert.rb
|
89
|
+
- lib/spitewaste/cli/docs.rb
|
89
90
|
- lib/spitewaste/cli/exec.rb
|
90
91
|
- lib/spitewaste/cli/image.rb
|
91
92
|
- lib/spitewaste/emitter.rb
|
@@ -99,11 +100,13 @@ files:
|
|
99
100
|
- lib/spitewaste/libspw/array.spw
|
100
101
|
- lib/spitewaste/libspw/bits.spw
|
101
102
|
- lib/spitewaste/libspw/case.spw
|
103
|
+
- lib/spitewaste/libspw/docs.json
|
102
104
|
- lib/spitewaste/libspw/fun.spw
|
103
105
|
- lib/spitewaste/libspw/io.spw
|
104
106
|
- lib/spitewaste/libspw/math.spw
|
105
107
|
- lib/spitewaste/libspw/prime.spw
|
106
108
|
- lib/spitewaste/libspw/random.spw
|
109
|
+
- lib/spitewaste/libspw/rational.spw
|
107
110
|
- lib/spitewaste/libspw/stack.spw
|
108
111
|
- lib/spitewaste/libspw/string.spw
|
109
112
|
- lib/spitewaste/libspw/syntax.spw
|