rpiet 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +12 -0
- data/bin/color_wheel +84 -0
- data/bin/image_gen +39 -0
- data/bin/rpiet +68 -11
- data/images/counter.txt +7 -0
- data/lib/rpiet/asg/graph_interpreter.rb +39 -0
- data/lib/rpiet/asg/parser.rb +156 -0
- data/lib/rpiet/asg/visitor.rb +66 -0
- data/lib/rpiet/asg.rb +336 -0
- data/lib/rpiet/codel_chooser.rb +32 -4
- data/lib/rpiet/color.rb +70 -25
- data/lib/rpiet/cycle.rb +18 -7
- data/lib/rpiet/debugger/debugger.rb +298 -0
- data/lib/rpiet/debugger/stylesheet.css +88 -0
- data/lib/rpiet/direction_pointer.rb +49 -18
- data/lib/rpiet/event_handler.rb +62 -7
- data/lib/rpiet/group.rb +25 -8
- data/lib/rpiet/image/ascii_image.rb +8 -20
- data/lib/rpiet/image/image.rb +8 -3
- data/lib/rpiet/image/url_image.rb +28 -14
- data/lib/rpiet/interpreter.rb +72 -72
- data/lib/rpiet/ir/assembler.rb +87 -0
- data/lib/rpiet/ir/builder.rb +255 -0
- data/lib/rpiet/ir/cfg.rb +494 -0
- data/lib/rpiet/ir/instructions.rb +536 -0
- data/lib/rpiet/ir/ir_cfg_interpreter.rb +23 -0
- data/lib/rpiet/ir/ir_interpreter.rb +101 -0
- data/lib/rpiet/ir/ir_native_interpreter.rb +77 -0
- data/lib/rpiet/ir/jruby_backend.rb +279 -0
- data/lib/rpiet/ir/operands.rb +28 -0
- data/lib/rpiet/ir/passes/data_flow_problem.rb +32 -0
- data/lib/rpiet/ir/passes/flow_graph_node.rb +76 -0
- data/lib/rpiet/ir/passes/peephole.rb +214 -0
- data/lib/rpiet/ir/passes/push_pop_elimination_pass.rb +112 -0
- data/lib/rpiet/live_machine_state.rb +15 -0
- data/lib/rpiet/machine.rb +62 -32
- data/lib/rpiet/source.rb +83 -0
- data/lib/rpiet/version.rb +1 -1
- data/lib/rpiet.rb +2 -2
- data/rpiet.gemspec +19 -0
- data/spec/asg/visitor_spec.rb +41 -0
- data/spec/cycle_spec.rb +34 -34
- data/spec/direction_pointer_spec.rb +33 -6
- data/spec/group_spec.rb +73 -48
- data/spec/interpreter_spec.rb +161 -12
- data/spec/ir/assembler_spec.rb +122 -0
- data/spec/ir/builder_spec.rb +20 -0
- data/spec/ir/cfg_spec.rb +151 -0
- data/spec/ir/ir_interpreter_spec.rb +102 -0
- data/spec/ir/passes/push_pop_elimination_pass_spec.rb +34 -0
- data/spec/machine_spec.rb +5 -3
- data/spec/source_spec.rb +69 -0
- data/spec/spec_helper.rb +78 -0
- metadata +54 -16
- data/images/nfib.png +0 -0
data/lib/rpiet/asg.rb
ADDED
@@ -0,0 +1,336 @@
|
|
1
|
+
module RPiet
|
2
|
+
module ASG
|
3
|
+
##
|
4
|
+
# Base class of all nodes
|
5
|
+
class Node
|
6
|
+
attr_accessor :next_node
|
7
|
+
attr_reader :step, :x, :y
|
8
|
+
|
9
|
+
def initialize(step, x, y, *)
|
10
|
+
@step, @x, @y = step, x, y
|
11
|
+
end
|
12
|
+
|
13
|
+
def eql?(o)
|
14
|
+
x == o.x && y == o.y && operation == o.operation
|
15
|
+
end
|
16
|
+
|
17
|
+
def hash
|
18
|
+
[x, y, operation].hash
|
19
|
+
end
|
20
|
+
|
21
|
+
def visit(visitor) = visitor.visit self
|
22
|
+
|
23
|
+
# Does this node represent a branching operation?
|
24
|
+
def branch? = false
|
25
|
+
|
26
|
+
##
|
27
|
+
# Is this node hidden from the perspective of calling next_step?
|
28
|
+
# In simpler interpreter noop, cc, and dp will change during next_step
|
29
|
+
# while in graph and ir interpreters they are explicit actions.
|
30
|
+
def hidden? = false
|
31
|
+
|
32
|
+
# What possible paths can this node navigate to next
|
33
|
+
def paths = [@next_node]
|
34
|
+
|
35
|
+
def add_path(node, *)
|
36
|
+
@next_node = node
|
37
|
+
end
|
38
|
+
|
39
|
+
def operation = self.class.operation_name.to_sym
|
40
|
+
|
41
|
+
def self.operation_name = name.sub(/.*::/, '').sub('Node', '').downcase
|
42
|
+
|
43
|
+
def exec(machine)
|
44
|
+
value = execute(machine)
|
45
|
+
return value if branch?
|
46
|
+
next_node
|
47
|
+
end
|
48
|
+
|
49
|
+
def inspect
|
50
|
+
"p##{@step} [#{@x}, #{@y}](#{operation})"
|
51
|
+
end
|
52
|
+
alias :to_s :inspect
|
53
|
+
|
54
|
+
def self.create(step, x, y, operation, *extra_args)
|
55
|
+
Nodes[operation].new step, x, y, *extra_args
|
56
|
+
end
|
57
|
+
|
58
|
+
# Overhead of event handler is extreme so only reference it if there is one.
|
59
|
+
def self.handle_event_handler(event_handler)
|
60
|
+
prepend NodeEventHandler if event_handler
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
module NodeEventHandler
|
65
|
+
def exec(machine)
|
66
|
+
machine.event_handler.operation(machine, @step, operation)
|
67
|
+
super
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Perform common mathematical binary operation
|
73
|
+
class MathNode < Node
|
74
|
+
def initialize(step, x, y, operation, *)
|
75
|
+
super(step, x, y)
|
76
|
+
@operation = operation
|
77
|
+
end
|
78
|
+
|
79
|
+
def execute(machine)
|
80
|
+
stack = machine.stack
|
81
|
+
return nil unless stack.length >= 2
|
82
|
+
a, b = stack.pop(2)
|
83
|
+
stack << a.send(@operation, b)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Add two values from stack
|
89
|
+
class AddNode < MathNode
|
90
|
+
def initialize(step, x, y, *) = super(step, x, y, :+)
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# When dp changes due to natural navigation we update it
|
95
|
+
# to the new value
|
96
|
+
class CcNode < Node
|
97
|
+
attr_reader :value
|
98
|
+
|
99
|
+
def initialize(step, x, y, cc_ordinal, *)
|
100
|
+
super(step, x, y)
|
101
|
+
@value = cc_ordinal
|
102
|
+
end
|
103
|
+
|
104
|
+
def hidden? = true
|
105
|
+
|
106
|
+
def execute(machine) = machine.cc.from_ordinal!(@value)
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# Read in character from the console and push on the stack
|
111
|
+
class CinNode < Node
|
112
|
+
def execute(machine)
|
113
|
+
machine.output.write "> "
|
114
|
+
machine.stack << machine.input.read(1).ord
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
##
|
119
|
+
# Display top element of the stack to the console as a character.
|
120
|
+
class CoutNode < Node
|
121
|
+
def execute(machine) = print machine.stack.pop.chr
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Add two values from stack
|
126
|
+
class DivNode < MathNode
|
127
|
+
def initialize(step, x, y, *)= super(step, x, y, :/)
|
128
|
+
|
129
|
+
# Note: Following npiet's div by zero value.
|
130
|
+
def execute(machine)
|
131
|
+
stack = machine.stack
|
132
|
+
return nil unless stack.length >= 2
|
133
|
+
a, b = stack.pop(2)
|
134
|
+
stack << (b == 0 ? DIV_BY_ZERO_VALUE : a / b)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
##
|
139
|
+
# When dp changes due to natural navigation we update it
|
140
|
+
# to the new value
|
141
|
+
class DpNode < Node
|
142
|
+
attr_reader :value
|
143
|
+
|
144
|
+
def initialize(step, x, y, _, dp_ordinal)
|
145
|
+
super(step, x, y)
|
146
|
+
@value = dp_ordinal
|
147
|
+
end
|
148
|
+
|
149
|
+
def hidden? = true
|
150
|
+
|
151
|
+
def execute(machine) = machine.dp.from_ordinal!(@value)
|
152
|
+
end
|
153
|
+
|
154
|
+
##
|
155
|
+
# Duplicate top element of the stack.
|
156
|
+
class DupNode < Node
|
157
|
+
def execute(machine)
|
158
|
+
stack = machine.stack
|
159
|
+
stack << stack[-1] if stack[-1]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
class ExitNode < Node
|
164
|
+
def execute(machine)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
##
|
169
|
+
# Greater than operation on top two stack values
|
170
|
+
class GtrNode < Node
|
171
|
+
def execute(machine)
|
172
|
+
stack = machine.stack
|
173
|
+
return nil unless stack.length >= 2
|
174
|
+
a, b = stack.pop(2)
|
175
|
+
stack << (a > b ? 1 : 0)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
##
|
180
|
+
# Modulos two values from stack
|
181
|
+
class ModNode < MathNode
|
182
|
+
def initialize(step, x, y, *) = super(step, x, y, :%)
|
183
|
+
end
|
184
|
+
|
185
|
+
##
|
186
|
+
# Multiply two values from stack
|
187
|
+
class MultNode < MathNode
|
188
|
+
def initialize(step, x, y, *)= super(step, x, y, :*)
|
189
|
+
end
|
190
|
+
|
191
|
+
##
|
192
|
+
# Read in number from the console and push on the stack
|
193
|
+
class NinNode < Node
|
194
|
+
def execute(machine)
|
195
|
+
machine.output.puts "Enter an integer: "
|
196
|
+
machine.stack << machine.input.gets.to_i
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
##
|
201
|
+
# Entry point into the program. Not strictly necessary
|
202
|
+
# but we will kill this during analysis
|
203
|
+
class NoopNode < Node
|
204
|
+
def hidden? = true
|
205
|
+
|
206
|
+
def execute(_); end # No-op
|
207
|
+
end
|
208
|
+
|
209
|
+
##
|
210
|
+
# Greater than operation on top two stack values
|
211
|
+
class NotNode < Node
|
212
|
+
def execute(machine)
|
213
|
+
stack = machine.stack
|
214
|
+
top = stack.pop
|
215
|
+
stack << (!top || top == 0 ? 1 : 0)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
##
|
220
|
+
# Diplay top element of the stack to the console.
|
221
|
+
class NoutNode < Node
|
222
|
+
def execute(machine) = print machine.stack.pop
|
223
|
+
end
|
224
|
+
|
225
|
+
##
|
226
|
+
# Rotate the direction based on top stack value and
|
227
|
+
# change execution flow.
|
228
|
+
class PntrNode < Node
|
229
|
+
def branch? = true
|
230
|
+
|
231
|
+
def add_path(node, _, dp_value)
|
232
|
+
@values ||= []
|
233
|
+
@values[dp_value] = node
|
234
|
+
end
|
235
|
+
|
236
|
+
# What possible paths can this node navigate to next
|
237
|
+
def paths = @values
|
238
|
+
|
239
|
+
def execute(machine)
|
240
|
+
top = machine.stack.pop
|
241
|
+
@values[machine.dp.rotate!(top).ordinal]
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
##
|
246
|
+
# Pop a value from the stack
|
247
|
+
class PopNode < Node
|
248
|
+
def execute(machine) = machine.stack.pop
|
249
|
+
end
|
250
|
+
|
251
|
+
##
|
252
|
+
# Push a value onto the stack
|
253
|
+
class PushNode < Node
|
254
|
+
attr_reader :value
|
255
|
+
|
256
|
+
def initialize(step, x, y, value)
|
257
|
+
super(step, x, y)
|
258
|
+
@value = value
|
259
|
+
end
|
260
|
+
|
261
|
+
def execute(machine) = machine.stack << @value
|
262
|
+
end
|
263
|
+
|
264
|
+
##
|
265
|
+
# Roll the stack
|
266
|
+
class RollNode < Node
|
267
|
+
def execute(machine)
|
268
|
+
stack = machine.stack
|
269
|
+
depth, num = stack.pop(2)
|
270
|
+
num %= depth
|
271
|
+
return if depth <= 0 || num == 0
|
272
|
+
if num > 0
|
273
|
+
stack[-depth..-1] = stack[-num..-1] + stack[-depth...-num]
|
274
|
+
elsif num < 0
|
275
|
+
stack[-depth..-1] = stack[-depth...-num] + stack[-num..-1]
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
##
|
281
|
+
# Subtract two values from stack
|
282
|
+
class SubNode < MathNode
|
283
|
+
def initialize(step, x, y, *)= super(step, x, y, :-)
|
284
|
+
end
|
285
|
+
|
286
|
+
##
|
287
|
+
# Rotate the codel chooser based on top stack value and
|
288
|
+
# change execution flow.
|
289
|
+
class SwchNode < Node
|
290
|
+
def branch? = true
|
291
|
+
|
292
|
+
def add_path(node, cc, _)
|
293
|
+
if cc == RPiet::CodelChooser::LEFT
|
294
|
+
@left = node
|
295
|
+
else
|
296
|
+
@right = node
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# What possible paths can this node navigate to next
|
301
|
+
def paths = [@left, @right]
|
302
|
+
|
303
|
+
def execute(machine)
|
304
|
+
top = machine.stack.pop
|
305
|
+
if machine.cc.switch!(top) == RPiet::CodelChooser::LEFT
|
306
|
+
@left
|
307
|
+
else
|
308
|
+
@right
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
Nodes = {
|
314
|
+
noop: NoopNode,
|
315
|
+
push: PushNode,
|
316
|
+
pop: PopNode,
|
317
|
+
add: AddNode,
|
318
|
+
sub: SubNode,
|
319
|
+
mult: MultNode,
|
320
|
+
div: DivNode,
|
321
|
+
mod: ModNode,
|
322
|
+
not: NotNode,
|
323
|
+
gtr: GtrNode,
|
324
|
+
pntr: PntrNode,
|
325
|
+
swch: SwchNode,
|
326
|
+
dup: DupNode,
|
327
|
+
roll: RollNode,
|
328
|
+
nin: NinNode,
|
329
|
+
cin: CinNode,
|
330
|
+
nout: NoutNode,
|
331
|
+
cout: CoutNode,
|
332
|
+
dp: DpNode,
|
333
|
+
cc: CcNode
|
334
|
+
}
|
335
|
+
end
|
336
|
+
end
|
data/lib/rpiet/codel_chooser.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
|
1
|
+
require_relative 'direction_pointer'
|
2
2
|
|
3
3
|
module RPiet
|
4
4
|
class CodelChooser
|
5
5
|
LEFT, RIGHT = -1, 1
|
6
|
-
|
6
|
+
attr_accessor :direction
|
7
|
+
|
7
8
|
def initialize; @direction = LEFT; end
|
8
|
-
def switch!(amount = 1)
|
9
|
+
def switch!(amount = 1)
|
10
|
+
@direction *= -1.**(amount % 2)
|
11
|
+
self
|
12
|
+
end
|
9
13
|
|
10
14
|
def ascii(dp)
|
11
15
|
case dp.direction
|
@@ -20,8 +24,32 @@ module RPiet
|
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
27
|
+
def degrees(dp)
|
28
|
+
case dp.direction
|
29
|
+
when RPiet::Direction::RIGHT
|
30
|
+
@direction == LEFT ? 270 : 90
|
31
|
+
when RPiet::Direction::UP
|
32
|
+
@direction == LEFT ? 180 : 0
|
33
|
+
when RPiet::Direction::LEFT
|
34
|
+
@direction == LEFT ? 90 : 270
|
35
|
+
when RPiet::Direction::DOWN
|
36
|
+
@direction == LEFT ? 0 : 180
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def as_constant
|
41
|
+
@direction == LEFT ? "LEFT" : "RIGHT"
|
42
|
+
end
|
43
|
+
|
44
|
+
alias :ordinal :direction
|
45
|
+
|
46
|
+
def from_ordinal!(ordinal)
|
47
|
+
@direction = ordinal == LEFT ? LEFT : RIGHT
|
48
|
+
end
|
49
|
+
|
23
50
|
def inspect
|
24
|
-
|
51
|
+
@direction.to_s
|
52
|
+
#(@direction == LEFT ? "<-" : "->")
|
25
53
|
end
|
26
54
|
alias :to_s :inspect
|
27
55
|
end
|
data/lib/rpiet/color.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative 'cycle'
|
2
2
|
|
3
3
|
module RPiet
|
4
4
|
class Color
|
@@ -7,48 +7,93 @@ module RPiet
|
|
7
7
|
cycle :LIGHTNESS, :LIGHT, :NORMAL, :DARK
|
8
8
|
cycle :HUE, :RED, :YELLOW, :GREEN, :CYAN, :BLUE, :MAGENTA
|
9
9
|
|
10
|
-
attr_reader :hue, :lightness
|
10
|
+
attr_reader :hue, :lightness, :rgb
|
11
11
|
|
12
|
-
def initialize(lightness, hue)
|
13
|
-
@lightness, @hue = lightness, hue
|
12
|
+
def initialize(lightness, hue, rgb)
|
13
|
+
@lightness, @hue, @rgb = lightness, hue, rgb
|
14
14
|
end
|
15
15
|
|
16
|
+
def color_from(lightness_delta: 0, hue_delta: 0)
|
17
|
+
LIGHTNESS_HUE[lightness.incr(lightness_delta)][hue.incr(hue_delta)]
|
18
|
+
end
|
19
|
+
|
20
|
+
# Display color as initial of lightness followed by hue (normal blue == nb).
|
16
21
|
def to_initial
|
17
22
|
@lightness.to_initial + @hue.to_initial
|
18
23
|
end
|
19
24
|
|
20
25
|
def to_s
|
21
|
-
|
26
|
+
[@lightness == LIGHTNESS::NORMAL ? nil : @lightness.to_s,
|
27
|
+
@hue.to_s].compact.join('_')
|
22
28
|
end
|
23
29
|
alias :inspect :to_s
|
24
30
|
|
25
|
-
|
26
|
-
|
31
|
+
def self.color_for(rgb_hex)
|
32
|
+
RGB[rgb_hex]
|
33
|
+
end
|
34
|
+
|
35
|
+
RGB_WHITE, WHITE = '0xffffff', Color.new(LIGHTNESS::NORMAL, 'white', '0xffffff')
|
36
|
+
RGB_BLACK, BLACK = '0x000000', Color.new(LIGHTNESS::NORMAL, 'black', '0x000000')
|
27
37
|
|
28
38
|
class << WHITE; def to_initial; '..'; end; end
|
29
39
|
class << BLACK; def to_initial; '++'; end; end
|
30
40
|
|
41
|
+
LIGHT_RED = Color.new(LIGHTNESS::LIGHT, HUE::RED, '0xffc0c0')
|
42
|
+
LIGHT_YELLOW = Color.new(LIGHTNESS::LIGHT, HUE::YELLOW, '0xffffc0')
|
43
|
+
LIGHT_GREEN = Color.new(LIGHTNESS::LIGHT, HUE::GREEN, '0xc0ffc0')
|
44
|
+
LIGHT_CYAN = Color.new(LIGHTNESS::LIGHT, HUE::CYAN, '0xc0ffff')
|
45
|
+
LIGHT_BLUE = Color.new(LIGHTNESS::LIGHT, HUE::BLUE, '0xc0c0ff')
|
46
|
+
LIGHT_MAGENTA = Color.new(LIGHTNESS::LIGHT, HUE::MAGENTA, '0xffc0ff')
|
47
|
+
RED = Color.new(LIGHTNESS::NORMAL, HUE::RED, '0xff0000')
|
48
|
+
YELLOW = Color.new(LIGHTNESS::NORMAL, HUE::YELLOW, '0xffff00')
|
49
|
+
GREEN = Color.new(LIGHTNESS::NORMAL, HUE::GREEN, '0x00ff00')
|
50
|
+
CYAN = Color.new(LIGHTNESS::NORMAL, HUE::CYAN, '0x00ffff')
|
51
|
+
BLUE = Color.new(LIGHTNESS::NORMAL, HUE::BLUE, '0x0000ff')
|
52
|
+
MAGENTA = Color.new(LIGHTNESS::NORMAL, HUE::MAGENTA, '0xff00ff')
|
53
|
+
DARK_RED = Color.new(LIGHTNESS::DARK, HUE::RED, '0xc00000')
|
54
|
+
DARK_YELLOW = Color.new(LIGHTNESS::DARK, HUE::YELLOW, '0xc0c000')
|
55
|
+
DARK_GREEN = Color.new(LIGHTNESS::DARK, HUE::GREEN, '0x00c000')
|
56
|
+
DARK_CYAN = Color.new(LIGHTNESS::DARK, HUE::CYAN, '0x00c0c0')
|
57
|
+
DARK_BLUE = Color.new(LIGHTNESS::DARK, HUE::BLUE, '0x0000c0')
|
58
|
+
DARK_MAGENTA = Color.new(LIGHTNESS::DARK, HUE::MAGENTA, '0xc000c0')
|
59
|
+
|
31
60
|
RGB = {
|
32
|
-
'0xffc0c0' =>
|
33
|
-
'
|
34
|
-
'
|
35
|
-
'
|
36
|
-
'
|
37
|
-
'
|
38
|
-
'0xff0000' => Color.new(LIGHTNESS::NORMAL, HUE::RED),
|
39
|
-
'0xffff00' => Color.new(LIGHTNESS::NORMAL, HUE::YELLOW),
|
40
|
-
'0x00ff00' => Color.new(LIGHTNESS::NORMAL, HUE::GREEN),
|
41
|
-
'0x00ffff' => Color.new(LIGHTNESS::NORMAL, HUE::CYAN),
|
42
|
-
'0x0000ff' => Color.new(LIGHTNESS::NORMAL, HUE::BLUE),
|
43
|
-
'0xff00ff' => Color.new(LIGHTNESS::NORMAL, HUE::MAGENTA),
|
44
|
-
'0xc00000' => Color.new(LIGHTNESS::DARK, HUE::RED),
|
45
|
-
'0xc0c000' => Color.new(LIGHTNESS::DARK, HUE::YELLOW),
|
46
|
-
'0x00c000' => Color.new(LIGHTNESS::DARK, HUE::GREEN),
|
47
|
-
'0x00c0c0' => Color.new(LIGHTNESS::DARK, HUE::CYAN),
|
48
|
-
'0x0000c0' => Color.new(LIGHTNESS::DARK, HUE::BLUE),
|
49
|
-
'0xc000c0' => Color.new(LIGHTNESS::DARK, HUE::MAGENTA),
|
61
|
+
'0xffc0c0' => LIGHT_RED, '0xffffc0' => LIGHT_YELLOW, '0xc0ffc0' => LIGHT_GREEN,
|
62
|
+
'0xc0ffff' => LIGHT_CYAN, '0xc0c0ff' => LIGHT_BLUE, '0xffc0ff' => LIGHT_MAGENTA,
|
63
|
+
'0xff0000' => RED, '0xffff00' => YELLOW, '0x00ff00' => GREEN,
|
64
|
+
'0x00ffff' => CYAN, '0x0000ff' => BLUE, '0xff00ff' => MAGENTA,
|
65
|
+
'0xc00000' => DARK_RED, '0xc0c000' => DARK_YELLOW, '0x00c000' => DARK_GREEN,
|
66
|
+
'0x00c0c0' => DARK_CYAN, '0x0000c0' => DARK_BLUE, '0xc000c0' => DARK_MAGENTA,
|
50
67
|
RGB_WHITE => WHITE,
|
51
68
|
RGB_BLACK => BLACK
|
52
69
|
}
|
70
|
+
|
71
|
+
LIGHTNESS_HUE = {
|
72
|
+
LIGHTNESS::LIGHT => {
|
73
|
+
HUE::RED => LIGHT_RED,
|
74
|
+
HUE::YELLOW => LIGHT_YELLOW,
|
75
|
+
HUE::GREEN => LIGHT_GREEN,
|
76
|
+
HUE::CYAN => LIGHT_CYAN,
|
77
|
+
HUE::BLUE => LIGHT_BLUE,
|
78
|
+
HUE::MAGENTA => LIGHT_MAGENTA
|
79
|
+
},
|
80
|
+
LIGHTNESS::NORMAL => {
|
81
|
+
HUE::RED => RED,
|
82
|
+
HUE::YELLOW => YELLOW,
|
83
|
+
HUE::GREEN => GREEN,
|
84
|
+
HUE::CYAN => CYAN,
|
85
|
+
HUE::BLUE => BLUE,
|
86
|
+
HUE::MAGENTA => MAGENTA
|
87
|
+
},
|
88
|
+
LIGHTNESS::DARK => {
|
89
|
+
HUE::RED => DARK_RED,
|
90
|
+
HUE::YELLOW => DARK_YELLOW,
|
91
|
+
HUE::GREEN => DARK_GREEN,
|
92
|
+
HUE::CYAN => DARK_CYAN,
|
93
|
+
HUE::BLUE => DARK_BLUE,
|
94
|
+
HUE::MAGENTA => DARK_MAGENTA
|
95
|
+
}
|
96
|
+
|
97
|
+
}
|
53
98
|
end
|
54
99
|
end
|
data/lib/rpiet/cycle.rb
CHANGED
@@ -1,29 +1,34 @@
|
|
1
1
|
module RPiet
|
2
2
|
class Cycle
|
3
|
-
attr_reader :
|
3
|
+
attr_reader :type, :value
|
4
|
+
attr_accessor :length
|
4
5
|
|
5
6
|
def initialize(value, name, list)
|
6
7
|
@value, @name, @list = value, name.to_s.downcase, list
|
7
8
|
end
|
8
9
|
|
9
10
|
def delta(other)
|
10
|
-
(@value - other.value) % @
|
11
|
+
(@value - other.value) % @length
|
11
12
|
end
|
12
13
|
|
13
14
|
def -(other)
|
14
|
-
@list[(@value - other.value) % @
|
15
|
+
@list[(@value - other.value) % @length]
|
15
16
|
end
|
16
17
|
|
17
18
|
def +(other)
|
18
|
-
@list[(@value + other.value) % @
|
19
|
+
@list[(@value + other.value) % @length]
|
19
20
|
end
|
20
21
|
|
21
22
|
def incr(amount = 1)
|
22
|
-
@list[(@value + amount) % @
|
23
|
+
@list[(@value + amount) % @length]
|
23
24
|
end
|
24
25
|
|
25
26
|
def decr(amount = 1)
|
26
|
-
@list[(@value - amount) % @
|
27
|
+
@list[(@value - amount) % @length]
|
28
|
+
end
|
29
|
+
|
30
|
+
def abs(amount)
|
31
|
+
@list[amount % @length]
|
27
32
|
end
|
28
33
|
|
29
34
|
def to_initial
|
@@ -31,9 +36,12 @@ module RPiet
|
|
31
36
|
end
|
32
37
|
|
33
38
|
def to_s
|
39
|
+
"#{@name}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def inspect
|
34
43
|
"#{@name}(#{@value})"
|
35
44
|
end
|
36
|
-
alias :inspect :to_s
|
37
45
|
end
|
38
46
|
|
39
47
|
module CycleMethod
|
@@ -53,6 +61,9 @@ module RPiet
|
|
53
61
|
list[i] = Cycle.new(i, name, list)
|
54
62
|
holder_module.const_set name, list[i]
|
55
63
|
end
|
64
|
+
|
65
|
+
# Micro-opt...@list.length is slower than @length
|
66
|
+
list.each { |element| element.length = list.length}
|
56
67
|
end
|
57
68
|
module_function :cycle
|
58
69
|
end
|