1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|0 @System &pad $f &state $1
|10 @Console &vector $2 &read $1 &pad $4 &type $1 &write $1 &error $1
|0 @State &numType $1 &number $2 &err $1 &errChar $1
@flag $1
|0 @NumType &decimal $1 &binary $1 &octal $1 &hexcadecimal $1
|100
@on-reset ( -> )
.Console/type DEI ?{ prompt BRK }
;on-console .Console/vector DEO2
BRK
@on-console ( -> )
#63 .Console/write DEO
.Console/type DEI #04 NEQ ?{ prompt } BRK
@on-prefix ( -> ) ( FIXME: this could be simpler )
[ LITr 00 ]
.Console/read DEI
DUP #30 NEQ ?{ .NumType/octal .State/numType STZ BRK }
DUP LIT "b NEQ ?{ .NumType/binary !&matched }
DUP LIT "o NEQ ?{ .NumType/octal !&matched }
DUP LIT "d NEQ ?{ .NumType/decimal !&matched }
DUP LIT "x NEQ ?{ .NumType/hexcadecimal !&matched }
LIT "q NEQ ?{ #80 .System/state DEO } ( exit on 'q' )
.State/numType LDZ ( will fallthrough to decimal or octal )
[ LITr 01 ]
&matched
DUP .State/numType STZ #10 SFT2 #00 SWP
;&parsers ADD2 LDA2 DUP2 .Console/vector DEO2
STHr ?{ BRK } JMP2 ( jump to the handler if we matched a non-prefix )
&parsers [ =on-decimal =on-binary =on-octal =on-hexcadecimal ]
@peek2 ( val* -- val* )
LIT "x .Console/write DEO
DUP2 SWP printhex printhex
JMP2r
@on-binary ( -> )
.Console/read DEI
DUP #0a NEQ ?{ finish-number }
DUP #fe AND DUP #30 EQU ?{ err-encoding }
EOR #00 SWP
.State/number LDZ2 #10 SFT2 ORA2
.State/number STZ2
BRK
@on-octal ( -> )
.Console/read DEI
DUP #0a NEQ ?{ finish-number }
DUP #f8 AND DUP #30 EQU ?{ err-encoding }
EOR #00 SWP
.State/number LDZ2 #30 SFT2 ORA2
.State/number STZ2
BRK
@on-decimal ( -> )
.Console/read DEI
DUP #0a NEQ ?{ finish-number }
#30 SUB DUP #0a LTH ?{ err-encoding }
#00 SWP
.State/number LDZ2 #000a MUL2 ADD2
.State/number STZ2
BRK
@on-hexcadecimal ( -> )
.Console/read DEI
DUP #0a NEQ ?{ finish-number }
#30 SUB DUP #09 GTH ?{ !&incr } ( 0-9 )
#07 SUB DUP #0f GTH ?{ !&incr } ( A-F )
#20 SUB DUP #0f GTH ?{ !&incr } ( a-f )
err-encoding
&incr
#00 SWP
.State/number LDZ2 #40 SFT2 ORA2
.State/number STZ2
BRK
@on-error ( -> )
.Console/read DEI #0a EQU ?{ BRK }
;Errors/prefix puts
.State/errChar LDZ .Console/write DEO
;Errors/prefix2 puts
;Encodings/tab .State/numType LDZ indextab puts
;Errors/prefix3 puts
;Errors/tab .State/err LDZ indextab puts
#0a .Console/write DEO
prompt
BRK
@err-encoding ( char -- )
.Console/read DEI .State/errChar STZ
#01 .State/err STZ
;on-error .Console/vector DEO2
BRK
@finish-number ( -- )
.State/number LDZ2
LIT "0 .Console/write DEO
LIT "b .Console/write DEO
DUP2 OVR #00 EQU ?{ SWP DUP printbinary SWP } NIP printbinary
#09 .Console/write DEO
LIT "0 .Console/write DEO
DUP2 printoctal
#09 .Console/write DEO
DUP2 printdecimal
#09 .Console/write DEO
LIT "0 .Console/write DEO
LIT "x .Console/write DEO
OVR #00 EQU ?{ SWP DUP printhex SWP } NIP printhex
#0a .Console/write DEO
prompt
BRK
@prompt ( -- )
#0000 .State/number STZ2
#00 .State/numType STZ
;on-prefix .Console/vector DEO2
LIT "% .Console/write DEO
#20 .Console/write DEO
JMP2r
( HELPER ROUTINES )
@indextab ( list* idx -- ptr* )
#02 MUL #00 SWP ADD2
LDA2
JMP2r
@puts ( str* -- )
LDA2k SWP2 INC2 INC2 ( end* str+2* )
&loop EQU2k ?&break
LDAk .Console/write DEO
INC2 !&loop
&break POP2 POP2 JMP2r
@printhex ( num -- )
#10 DIVk DUP printhexdigit
MUL SUB printhexdigit
JMP2r
@printdecimal ( num* -- )
#01 .flag STZ
[ LITr 00 ]
#2710 DIV2k DUP2 NIP DUP #00 EQU ?{
DUP printbcddigit
#00 .flag STZ
} POP
MUL2 SUB2
&loop
#03e8 DIV2k DUP2 NIP ( get 1000s place )
DUP #00 EQU .flag LDZ AND ?{ ( if flag || s != 0 )
DUP printbcddigit
#00 .flag STZ
} POP
MUL2 SUB2 #000a MUL2 ( DUP2 SWP printhex printhex )
STHr #01 ADD DUP STH #04 NEQ
( end ) ?&loop
POPr POP2 JMP2r
@printoctal ( num* -- )
#01 .flag STZ
[ LITr 00 ]
DUP2 #0f SFT2 NIP #00 EQU ?{
#31 .Console/write DEO
#00 .flag STZ
}
#10 SFT2
&loop
DUP2 #0d SFT2 NIP ( get top 3 bits )
DUP #00 EQU .flag LDZ AND ?{ ( if flag || s != 0 )
DUP printbcddigit
#00 .flag STZ
} POP
#30 SFT2
STHr #01 ADD DUP STH #05 NEQ
( end ) ?&loop
POPr POP2 JMP2r
@printbinary ( num -- )
[ LITr 00 ]
&loop
DUP #07 SFT #30 ADD
.Console/write DEO
#10 SFT
STHr #01 ADD DUP STH #08 NEQ
( end ) ?&loop
POPr POP JMP2r
@printhexdigit ( digit -- )
#0f AND
DUP #0a LTH ?{ #27 ADD } ( take top part, if 10-15 move to a-f )
#30 ADD .Console/write DEO
JMP2r
@printbcddigit ( digit -- )
#0f AND
#30 ADD .Console/write DEO
JMP2r
( STRING DATA )
@Errors
&prefix ={ "bad 20 "char 20 "' }
&prefix2 ={ "' 20 "for 20 }
&prefix3 ={ 20 "encoding: 20 }
&unknown ={ "unknown 20 "error }
&encoding ={ "not 20 "in 20 "range. }
&tab =&unknown =&encoding
@Encodings
&binary ={ "binary }
&octal ={ "octal }
&decimal ={ "decimal }
&hexcadecimal ={ "hexcadecimal }
&tab =&decimal =&binary =&octal =&hexcadecimal