@@ -53,7 +53,7 @@ def move
53
53
end
54
54
55
55
def push val
56
- @state . stack << val
56
+ @state . push val
57
57
end
58
58
59
59
def pop
@@ -65,24 +65,13 @@ def shift
65
65
end
66
66
67
67
def unshift val
68
- @state . stack . unshift val
68
+ @state . unshift val
69
69
end
70
70
71
71
def peek
72
72
raise NotImplementedError
73
73
end
74
74
75
- def read_byte
76
- result = nil
77
- if @next_byte
78
- result = @next_byte
79
- @next_byte = nil
80
- else
81
- result = @in_str . getc
82
- end
83
- result
84
- end
85
-
86
75
end
87
76
88
77
class Cardinal < Mode
@@ -116,6 +105,9 @@ class Cardinal < Mode
116
105
'"' => :string_mode ,
117
106
"'" => :escape ,
118
107
108
+ 'i' => :input ,
109
+ 'o' => :output ,
110
+
119
111
#'(' => ,
120
112
#')' => ,
121
113
@@ -146,6 +138,26 @@ def move
146
138
@state . wrap
147
139
end
148
140
141
+ def pop
142
+ loop do
143
+ val = @state . pop
144
+ if val . is_a? ( String )
145
+ found = false
146
+ val . scan ( /-?\d +/ ) { push $&. to_i ; found = true }
147
+ next if !found
148
+ val = @state . pop
149
+ end
150
+
151
+ break
152
+ end
153
+
154
+ val || 0
155
+ end
156
+
157
+ def process_string
158
+ @state . stack += @state . current_string
159
+ end
160
+
149
161
def process opcode , cmd
150
162
case opcode
151
163
when :terminate
@@ -155,6 +167,51 @@ def process opcode, cmd
155
167
@state . set_ordinal
156
168
when :wall
157
169
@state . dir = @state . dir . reflect cmd . chr
170
+ when :move_east
171
+ @state . dir = East . new
172
+ when :move_west
173
+ @state . dir = West . new
174
+ when :move_south
175
+ @state . dir = South . new
176
+ when :move_north
177
+ @state . dir = North . new
178
+ when :turn_left
179
+ @state . dir = @state . dir . left
180
+ when :turn_right
181
+ @state . dir = @state . dir . right
182
+
183
+ when :mp_left
184
+ @state . mp -= 1
185
+ when :mp_right
186
+ @state . mp += 1
187
+
188
+ when :string_mode
189
+ @state . string_mode = true
190
+ when :escape
191
+ move
192
+ push @state . cell
193
+
194
+ when :input
195
+ char = @state . in_str . getc
196
+ push ( char ? char . ord : -1 )
197
+ when :output
198
+ @state . out_str << pop . chr
199
+
200
+ when :digit
201
+ push cmd . chr . to_i
202
+ when :add
203
+ push ( pop + pop )
204
+ when :sub
205
+ y = pop
206
+ push ( pop - y )
207
+ when :mul
208
+ push ( pop * pop )
209
+ when :div
210
+ y = pop
211
+ push ( pop / y )
212
+ when :mod
213
+ y = pop
214
+ push ( pop % y )
158
215
end
159
216
end
160
217
end
@@ -175,17 +232,20 @@ class Ordinal < Mode
175
232
':' => :split ,
176
233
'%' => :mod ,
177
234
178
- '<' => :rotate_west ,
179
- '>' => :rotate_east ,
180
- '^' => :rotate_north ,
181
- 'v' => :rotate_south ,
235
+ '<' => :ensure_west ,
236
+ '>' => :ensure_east ,
237
+ '^' => :ensure_north ,
238
+ 'v' => :ensure_south ,
182
239
183
240
'{' => :strafe_left ,
184
241
'}' => :strafe_right ,
185
242
186
243
'"' => :string_mode ,
187
244
"'" => :escape ,
188
245
246
+ 'i' => :input ,
247
+ 'o' => :output ,
248
+
189
249
#'(' => ,
190
250
#')' => ,
191
251
@@ -226,6 +286,17 @@ def move
226
286
@state . ip += @state . dir . vec
227
287
end
228
288
289
+ def pop
290
+ val = @state . pop
291
+
292
+ val ? val . to_s : ''
293
+ end
294
+
295
+ def process_string
296
+ # Will throw an error when cell isn't a valid code point
297
+ push @state . current_string . map ( &:chr ) *''
298
+ end
299
+
229
300
def process opcode , cmd
230
301
case opcode
231
302
when :terminate
@@ -235,6 +306,31 @@ def process opcode, cmd
235
306
@state . set_cardinal
236
307
when :wall
237
308
@state . dir = @state . dir . reflect cmd . chr
309
+ when :ensure_west
310
+ @state . dir = @state . dir . reflect cmd . chr if @state . dir . x > 0
311
+ when :ensure_east
312
+ @state . dir = @state . dir . reflect cmd . chr if @state . dir . x < 0
313
+ when :ensure_north
314
+ @state . dir = @state . dir . reflect cmd . chr if @state . dir . y > 0
315
+ when :ensure_south
316
+ @state . dir = @state . dir . reflect cmd . chr if @state . dir . y < 0
317
+ when :strafe_left
318
+ @state . ip += ( @state . dir . reverse + @state . dir . left ) / 2
319
+ when :strafe_right
320
+ @state . ip += ( @state . dir . reverse + @state . dir . right ) / 2
321
+ when :string_mode
322
+ @state . string_mode = true
323
+ when :escape
324
+ move
325
+ push @state . cell . chr # Will throw an error when cell isn't a valid code point
326
+
327
+ when :digit
328
+ push ( pop + cmd . chr )
329
+ when :input
330
+ line = @state . in_str . gets
331
+ push ( line ? line . chomp : '' )
332
+ when :output
333
+ @state . out_str << pop
238
334
end
239
335
end
240
336
end
0 commit comments