rpiet 0.1 → 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|