-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathalice.rb
93 lines (75 loc) · 2.31 KB
/
alice.rb
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
# coding: utf-8
Encoding.default_internal = Encoding::UTF_8
Encoding.default_external = Encoding::UTF_8
require_relative 'state'
# Add stable sorting methods to Enumerable
module Enumerable
def stable_sort
sort_by.with_index { |x, idx| [x, idx] }
end
def stable_sort_by
sort_by.with_index { |x, idx| [yield(x), idx] }
end
end
# Add convenience method for .chr(Encoding::UTF_8)
class Integer
def chr_utf_8
chr(Encoding::UTF_8)
end
end
class Alice
attr_accessor :state
class ProgramError < Exception; end
def self.run(src, in_str=$stdin, out_str=$stdout, args=ARGV, max_ticks=-1)
new(src, in_str, out_str, args, max_ticks).run
end
def initialize(src, in_str=$stdin, out_str=$stdout, args=ARGV, max_ticks=-1)
@state = State.new(src, in_str, out_str, args, max_ticks)
end
def run
ticks_exceeded = false
loop do
next while !@state.mode.move
cell = @state.cell
processed = false
if @state.string_mode
case cell
when "'".ord
@state.mode.raw_move
@state.current_string << @state.cell
@state.ip -= @state.dir.vec
processed = true
when '"'.ord
@state.string_mode = false
else
@state.current_string << cell
processed = true
end
elsif cell == '"'.ord
@state.string_mode = true
@state.current_string = []
processed = true
end
if !processed
iterator = @state.get_iterator
case iterator
when Integer
iterator.times { @state.mode.process cell.chr_utf_8 }
when String
iterator.each_char do |c|
@state.push c
@state.mode.process cell.chr_utf_8
end
end
end
@state.tick += 1
ticks_exceeded = @state.max_ticks > -1 && @state.tick >= @state.max_ticks
break if @state.done || ticks_exceeded
end
ticks_exceeded
end
private
def error msg
raise msg
end
end