rpiet 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/Gemfile +12 -0
  4. data/bin/color_wheel +84 -0
  5. data/bin/image_gen +39 -0
  6. data/bin/rpiet +68 -11
  7. data/images/counter.txt +7 -0
  8. data/lib/rpiet/asg/graph_interpreter.rb +39 -0
  9. data/lib/rpiet/asg/parser.rb +156 -0
  10. data/lib/rpiet/asg/visitor.rb +66 -0
  11. data/lib/rpiet/asg.rb +336 -0
  12. data/lib/rpiet/codel_chooser.rb +32 -4
  13. data/lib/rpiet/color.rb +70 -25
  14. data/lib/rpiet/cycle.rb +18 -7
  15. data/lib/rpiet/debugger/debugger.rb +298 -0
  16. data/lib/rpiet/debugger/stylesheet.css +88 -0
  17. data/lib/rpiet/direction_pointer.rb +49 -18
  18. data/lib/rpiet/event_handler.rb +62 -7
  19. data/lib/rpiet/group.rb +25 -8
  20. data/lib/rpiet/image/ascii_image.rb +8 -20
  21. data/lib/rpiet/image/image.rb +8 -3
  22. data/lib/rpiet/image/url_image.rb +28 -14
  23. data/lib/rpiet/interpreter.rb +72 -72
  24. data/lib/rpiet/ir/assembler.rb +87 -0
  25. data/lib/rpiet/ir/builder.rb +255 -0
  26. data/lib/rpiet/ir/cfg.rb +494 -0
  27. data/lib/rpiet/ir/instructions.rb +536 -0
  28. data/lib/rpiet/ir/ir_cfg_interpreter.rb +23 -0
  29. data/lib/rpiet/ir/ir_interpreter.rb +101 -0
  30. data/lib/rpiet/ir/ir_native_interpreter.rb +77 -0
  31. data/lib/rpiet/ir/jruby_backend.rb +279 -0
  32. data/lib/rpiet/ir/operands.rb +28 -0
  33. data/lib/rpiet/ir/passes/data_flow_problem.rb +32 -0
  34. data/lib/rpiet/ir/passes/flow_graph_node.rb +76 -0
  35. data/lib/rpiet/ir/passes/peephole.rb +214 -0
  36. data/lib/rpiet/ir/passes/push_pop_elimination_pass.rb +112 -0
  37. data/lib/rpiet/live_machine_state.rb +15 -0
  38. data/lib/rpiet/machine.rb +62 -32
  39. data/lib/rpiet/source.rb +83 -0
  40. data/lib/rpiet/version.rb +1 -1
  41. data/lib/rpiet.rb +2 -2
  42. data/rpiet.gemspec +19 -0
  43. data/spec/asg/visitor_spec.rb +41 -0
  44. data/spec/cycle_spec.rb +34 -34
  45. data/spec/direction_pointer_spec.rb +33 -6
  46. data/spec/group_spec.rb +73 -48
  47. data/spec/interpreter_spec.rb +161 -12
  48. data/spec/ir/assembler_spec.rb +122 -0
  49. data/spec/ir/builder_spec.rb +20 -0
  50. data/spec/ir/cfg_spec.rb +151 -0
  51. data/spec/ir/ir_interpreter_spec.rb +102 -0
  52. data/spec/ir/passes/push_pop_elimination_pass_spec.rb +34 -0
  53. data/spec/machine_spec.rb +5 -3
  54. data/spec/source_spec.rb +69 -0
  55. data/spec/spec_helper.rb +78 -0
  56. metadata +54 -16
  57. data/images/nfib.png +0 -0
@@ -0,0 +1,298 @@
1
+ require 'jrubyfx'
2
+ require 'thread'
3
+
4
+ # FIXME : JRubyFX is not implementing add correctly.
5
+ class Java::JavafxSceneControl::ScrollPane
6
+ def add(child)
7
+ set_content(child)
8
+ end
9
+ end
10
+
11
+ module RPiet
12
+
13
+ class Debugger < JRubyFX::Application
14
+ include JRubyFX
15
+
16
+ attr_reader :stage
17
+
18
+ DEFAULT_DELAY = 0.25 # seconds
19
+ SIZE = 30
20
+ NORMAL = Java::javafx.scene.paint.Color.web("0x222222")
21
+ CANDIDATE = Java::javafx.scene.paint.Color::YELLOW
22
+ BREAKPOINT = Java::javafx.scene.paint.Color::RED
23
+ CURRENT = Java::javafx.scene.paint.Color::CADETBLUE
24
+ WHITE = Java::javafx.scene.paint.Color::WHITE
25
+
26
+ ARROW = [2, 9, 11, 9, 10, 4, 18, 10, 10, 16, 11, 11, 2, 11].to_java(:double)
27
+
28
+ def self.instance
29
+ @@instance
30
+ end
31
+
32
+ def break_point?(x,y)
33
+ @break_points["#{x}x#{y}"]
34
+ end
35
+
36
+ def update_directions(start_x, start_y, end_x, end_y)
37
+ stage["#connector"].tap do |connector|
38
+ connector.start_x = SIZE/2 + codel2pixels(start_x)
39
+ connector.start_y = SIZE/2 + codel2pixels(start_y)
40
+ connector.end_x = SIZE/2 + codel2pixels(end_x)
41
+ connector.end_y = SIZE/2 + codel2pixels(end_y)
42
+ end
43
+ end
44
+
45
+ def codel2pixels(codel_offset)
46
+ (codel_offset + 1) * SIZE
47
+ end
48
+
49
+ def begin_session
50
+ update_directions(-1, 0, 0, 0)
51
+ end
52
+
53
+ def highlight_candidate(runtime, edge_x, edge_y, next_x, next_y, valid)
54
+ update_directions(edge_x, edge_y, next_x, next_y)
55
+ # Replace with black edge in debugger later
56
+ if next_x < 0 || next_y < 0 || next_x >= runtime.source.cols || next_y >= runtime.source.rows
57
+ puts "OUT OF BOUNDS #{next_x} #{next_y} #{runtime.source.rows} #{runtime.source.cols}"
58
+ return
59
+ end
60
+ run_later do
61
+ stage["\##{next_x}x#{next_y}"].stroke = CANDIDATE
62
+ if @lastc_x
63
+ color = break_point?(@lastc_x, @lastc_y) ? BREAKPOINT : NORMAL
64
+ if color == NORMAL && stage["\##{@lastc_x}x#{@lastc_y}"].stroke != CURRENT
65
+ stage["\##{@lastc_x}x#{@lastc_y}"].stroke = color
66
+ end
67
+ end
68
+ @lastc_x, @lastc_y = next_x, next_y
69
+ end
70
+ end
71
+
72
+ def highlight(runtime, x, y)
73
+ run_later do
74
+ stage["\##{x}x#{y}"].stroke = CURRENT
75
+ if @last_x
76
+ color = break_point?(@last_x, @last_y) ? BREAKPOINT : NORMAL
77
+ stage["\##{@last_x}x#{@last_y}"].stroke = color
78
+ end
79
+ @last_x, @last_y = x, y
80
+
81
+ #@stage["#connector"].visible = false
82
+ stage["#dp-arrow"].rotate = @rpiet.pvm.dp.degrees
83
+ stage["#cc-arrow"].rotate = @rpiet.pvm.cc.degrees(@rpiet.pvm.dp)
84
+ stage["#cc-text"].text = @rpiet.pvm.cc.to_s
85
+
86
+ percent_y = y.to_f / (@rpiet.source.rows + 2)
87
+ percent_x = x.to_f / (@rpiet.source.cols + 2)
88
+ virtual_w = (@rpiet.source.cols + 2) * SIZE
89
+ virtual_h = (@rpiet.source.rows + 2) * SIZE
90
+ sb = stage['#scrollbar']
91
+ real_x, real_y = x * 43, y * 43 # I lay out 30x30 but they end up 43x43 on screen?
92
+ real_w, real_h = sb.width, sb.height
93
+ s_x, s_y = sb.hvalue * virtual_w, sb.vvalue * virtual_h
94
+
95
+ # FIXME: Add x,y offset guides on out of bound blocks so scrolling is less confusing
96
+ # FIXME: Clean this up and use a clamp so we do not exceed scroll bounds
97
+ a_x = real_x - s_x
98
+ if a_x > real_w
99
+ sb.hvalue += 0.1
100
+ elsif a_x < 0
101
+ sb.hvalue -= 0.1
102
+ end
103
+
104
+ a_y = real_y - s_y
105
+ if a_y > real_h
106
+ sb.vvalue += 0.1
107
+ elsif a_y < 0
108
+ sb.vvalue -= 0.1
109
+ end
110
+
111
+
112
+ # puts "VirtW: #{virtual_w}, REAL_W: #{real_w}"
113
+ # puts "S_X: #{(sb.hvalue * virtual_w).to_i} #{x * 43}"
114
+ # puts "V: #{percent_y} #{sb.vmax} #{sb.vvalue} H: #{percent_x} #{sb.hmax} #{sb.hvalue}"
115
+ runtime.pause if break_point?(x, y)
116
+ end
117
+ end
118
+
119
+ def operation(runtime, oper)
120
+ run_later do
121
+ puts "operation"
122
+ stage['#oper'].text = "oper: " + oper.to_s
123
+ stage['#stack'].text = "stack: " + runtime.pvm.stack.inspect
124
+ stage['#bv'].text = "value: " + runtime.pvm.block_value.inspect
125
+ stage['#state-values'].visible = true
126
+ end
127
+ end
128
+
129
+ # JavaFX has some caching so we cheat the cache by using file: uri and varying the uri by adding a time param.
130
+ def reload_stylesheet(scene)
131
+ run_later do
132
+ scene.stylesheets.clear
133
+ scene.stylesheets.add(File.join('file:' + File.dirname(__FILE__), (@odd_load_css ? '/./' : '') + "stylesheet.css"))
134
+ @odd_load_css = !@odd_load_css
135
+ end
136
+ end
137
+
138
+ def watch_stylesheet(scene)
139
+ file = File.join(File.dirname(__FILE__), "stylesheet.css")
140
+ last_time = File.mtime(file)
141
+ Thread.new do
142
+ loop do
143
+ mtime = File.mtime(file)
144
+
145
+ if mtime != last_time
146
+ reload_stylesheet(scene)
147
+ last_time = mtime
148
+ else
149
+ sleep 1
150
+ end
151
+ end
152
+ end.run
153
+ end
154
+
155
+ def start(stage)
156
+ @rpiet = $rpiet # how does jrubyfx pass params before start is called?
157
+ @break_points = break_points = {}
158
+ @stage = stage
159
+ debugger = self
160
+ @rpiet.delay = DEFAULT_DELAY
161
+
162
+ # FIXME: Move into convenience module near top of JRubyFX hier. Maybe make a feature for these
163
+ ::Kernel.instance_eval {
164
+ define_method(:codel) { |i=1| SIZE * i}
165
+ define_method(:half_codel) { SIZE/2 }
166
+ }
167
+ rows, cols, pixels = @rpiet.source.rows, @rpiet.source.cols, @rpiet.source.pixels
168
+ rpiet = @rpiet
169
+ stroke_width = SIZE / 10
170
+ with(stage, title: "RPiet", width: 800, height: 600) do
171
+ layout_scene do
172
+ vbox(id: 'main') do
173
+ border_pane do
174
+ top(menu_bar! do
175
+ menu("File") do
176
+ menu_item("Quit") do
177
+ set_on_action do |event|
178
+ rpiet.abort
179
+ Platform.exit
180
+ end
181
+ end
182
+ end
183
+ menu("View") do
184
+ menu_item("Reload Stylesheet") { set_on_action { |_| debugger.reload_stylesheet(stage.scene) } }
185
+ menu_item("Pause (0.025s)") { set_on_action { |_| rpiet.delay = 0.025 } }
186
+ menu_item("Pause (0.1s)") { set_on_action { |_| rpiet.delay = 0.1 } }
187
+ menu_item("Pause (#{DEFAULT_DELAY}s)") { set_on_action { |_| rpiet.delay = DEFAULT_DELAY } }
188
+ end
189
+ end)
190
+ left(hbox(id: 'state') do
191
+ label("DP", id: 'dp-label')
192
+ polygon(ARROW, id: 'dp-arrow')
193
+ label("CC:", id: 'cc-label')
194
+ polygon(ARROW, id: 'cc-arrow')
195
+ label(rpiet.pvm.cc.to_s, id: 'cc-text')
196
+ hbox(id: 'state-values') do
197
+ label("oper:", id: 'oper')
198
+ label("value: ", id: 'bv')
199
+ label("stack:", id: 'stack')
200
+ end
201
+ end)
202
+ right(hbox do
203
+ get_style_class.add "controls"
204
+ button("restart") do
205
+ get_style_class.add "control"
206
+ set_on_action { |_| rpiet.restart }
207
+ end
208
+ button("pause") do
209
+ get_style_class.add "control"
210
+ set_on_action { |_| rpiet.pause }
211
+ end
212
+ button("resume") do
213
+ get_style_class.add "control"
214
+ set_on_action { |_| rpiet.resume }
215
+ end
216
+ button("step") do
217
+ get_style_class.add "control"
218
+ set_on_action { |_| rpiet.advance }
219
+ end
220
+ end)
221
+ end
222
+ scroll_pane(id: 'scrollbar') do |sp|
223
+ sp.set_content(group() do
224
+ Java::javafx.scene.layout.VBox.setVgrow(sp, Java::javafx.scene.layout.Priority::ALWAYS)
225
+
226
+ # Horizontal top and bottom border
227
+ (rpiet.source.cols + 2).times do |i|
228
+ rectangle(codel(i), 0, codel-1, codel-1, stroke_type: :inside, stroke: NORMAL) do
229
+ get_style_class.add "out-of-bounds"
230
+ end
231
+ text(codel(i) + half_codel, half_codel, (i-1).to_s) if i != 0 && i != cols + 1
232
+
233
+ rectangle(codel(i), codel(rpiet.source.rows + 1), codel-1, codel-1,
234
+ stroke_type: :inside, stroke: NORMAL) do
235
+ get_style_class.add "out-of-bounds"
236
+ end
237
+ text(codel(i) + half_codel, codel(rows + 1) + half_codel, (i-1).to_s) if i != 0 && i != cols + 1
238
+
239
+ end
240
+
241
+ # Left and right vertical border
242
+ group do
243
+ rpiet.source.rows.times do |j|
244
+ rectangle(0, codel(j + 1), codel-1, codel-1, stroke_type: :inside, stroke: NORMAL) do
245
+ get_style_class.add "out-of-bounds"
246
+ end
247
+ text(half_codel, codel(j + 1) + half_codel, j.to_s)
248
+
249
+ rectangle(codel(cols + 1), codel(j + 1), codel-1, codel-1, stroke_type: :inside, stroke: NORMAL) do
250
+ get_style_class.add "out-of-bounds"
251
+ end
252
+ text(codel(cols + 1) + half_codel, codel(j + 1) + half_codel, j.to_s)
253
+ end
254
+ end
255
+
256
+ # Main codels
257
+ pixels.each_with_index do |row, i|
258
+ row.each_with_index do |piet_pixel, j|
259
+ color = Java::javafx.scene.paint.Color.web(piet_pixel.rgb)
260
+ ident = "#{i}x#{j}"
261
+ rectangle(codel(i+1), codel(j+1), codel-1, codel-1, fill: color,
262
+ stroke_type: :inside, stroke_width: stroke_width,
263
+ stroke: NORMAL, stroke_line_join: :round, id: ident) do
264
+ get_style_class.add "codel"
265
+ set_on_mouse_clicked do |event|
266
+ new_color = if event.source.stroke == BREAKPOINT
267
+ break_points[ident] = nil
268
+ NORMAL
269
+ else
270
+ break_points[ident] = event.source
271
+ BREAKPOINT
272
+ end
273
+ event.source.stroke = new_color
274
+ end
275
+ end
276
+ end
277
+ end
278
+ # FIXME: stroke_width must be derived but I feel I need to add scrolling and a minimum
279
+ # codel display SIZE before I can do this.
280
+ line(start_x: half_codel, start_y: codel + half_codel,
281
+ end_x: codel + half_codel, end_y: codel + half_codel, stroke_width: 10, id: 'connector')
282
+ end)
283
+ end
284
+ end
285
+ end
286
+ end.show
287
+
288
+ stage.set_on_close_request {
289
+ rpiet.abort
290
+ Platform.exit
291
+ }
292
+ $event_handler.debugger_started self
293
+ begin_session
294
+ reload_stylesheet(stage.scene)
295
+ watch_stylesheet(stage.scene)
296
+ end
297
+ end
298
+ end
@@ -0,0 +1,88 @@
1
+ #bv {
2
+ -fx-text-fill: #ffffff;
3
+ -fx-padding: 3;
4
+ }
5
+
6
+ #cc-arrow {
7
+ -fx-fill: #ffffff;
8
+ -fx-padding: 3;
9
+ -fx-stroke_width: 6;
10
+ }
11
+
12
+ #cc-label {
13
+ -fx-text-fill: #ffffff;
14
+ -fx-padding: 3;
15
+ -fx-font-size: 28;
16
+ }
17
+
18
+ #cc-text {
19
+ -fx-text-fill: #ffffff;
20
+ -fx-font-size: 28;
21
+ }
22
+
23
+ .codel {
24
+ -fx-arc-width: 1;
25
+ -fx-arc-width: 1;
26
+ -fx-stroke-width: 2;
27
+ -fx-background-color: #444455;
28
+ }
29
+
30
+ #connector {
31
+ -fx-fill: #999999;
32
+ -fx-stroke-width: 4;
33
+ }
34
+
35
+ .controls {
36
+ -fx-padding: 10;
37
+ -fx-text-fill: #000000;
38
+ }
39
+
40
+ .control {
41
+ -fx-text-fill: #000000;
42
+ }
43
+
44
+ #dp {
45
+ -fx-spacing: 20;
46
+ }
47
+
48
+ #dp-arrow {
49
+ -fx-fill: #ffffff;
50
+ }
51
+
52
+ #dp-label {
53
+ -fx-text-fill: #ffffff;
54
+ -fx-font-size: 28;
55
+ }
56
+
57
+ #main {
58
+ -fx-background-color: #444455;
59
+ }
60
+
61
+ #oper {
62
+ -fx-text-fill: #ffffff;
63
+ -fx-padding: 3;
64
+ }
65
+
66
+ .out-of-bounds {
67
+ -fx-arc-width: 1;
68
+ -fx-arc-width: 1;
69
+ -fx-stroke-width: 0;
70
+ -fx-fill: #999999;
71
+ }
72
+
73
+ #stack {
74
+ -fx-text-fill: #ffffff;
75
+ -fx-padding: 3;
76
+ }
77
+
78
+ #state {
79
+ -fx-padding: 40;
80
+ }
81
+
82
+ #state-values {
83
+ }
84
+
85
+ #value {
86
+ -fx-text-fill: #ffffff;
87
+ -fx-padding: 3;
88
+ }
@@ -1,39 +1,70 @@
1
- require 'rpiet/cycle'
2
- require 'rpiet/codel_chooser'
1
+ require_relative 'cycle'
2
+ require_relative 'codel_chooser'
3
3
 
4
4
  module RPiet
5
5
  extend RPiet::CycleMethod
6
6
  cycle :Direction, :RIGHT, :DOWN, :LEFT, :UP
7
7
 
8
- class << Direction::RIGHT; def deltas; [1, 0]; end; end
9
- class << Direction::DOWN; def deltas; [0, 1]; end; end
10
- class << Direction::LEFT; def deltas; [-1, 0]; end; end
11
- class << Direction::UP; def deltas; [0, -1]; end; end
8
+ module DirectionExtras
9
+ def next_point(x, y)
10
+ dx, dy = deltas
11
+ [x + dx, y + dy]
12
+ end
13
+ end
14
+
15
+ class << Direction::RIGHT
16
+ include DirectionExtras
17
+ def deltas = [1, 0]
18
+ end
19
+
20
+ class << Direction::DOWN
21
+ include DirectionExtras
22
+ def deltas = [0, 1]
23
+ end
24
+
25
+ class << Direction::LEFT
26
+ include DirectionExtras
27
+ def deltas = [-1, 0]
28
+ end
29
+
30
+ class << Direction::UP
31
+ include DirectionExtras
32
+ def deltas = [0, -1]
33
+ end
12
34
 
13
35
  class DirectionPointer
14
- attr_reader :direction
36
+ attr_accessor :direction
37
+
38
+ def initialize(value=nil)
39
+ @direction = value ? RPiet::Direction::RIGHT.abs(value) : RPiet::Direction::RIGHT
40
+ end
15
41
 
16
- def initialize
17
- @direction = RPiet::Direction::RIGHT
42
+ def ==(other)
43
+ @direction == other.direction
18
44
  end
19
45
 
20
46
  def rotate!(amount = 1)
21
47
  @direction = @direction.incr amount
48
+ self
22
49
  end
23
50
 
24
- def next_possible(x, y)
25
- dx, dy = @direction.deltas
26
- [x + dx, y + dy]
51
+ def degrees = @direction.value * 90
52
+
53
+ def from_ordinal!(ordinal)
54
+ @direction = @direction.abs(ordinal)
55
+ self
27
56
  end
28
57
 
58
+ def as_constant = %w[RIGHT DOWN LEFT UP][ordinal]
59
+
60
+ def next_possible(x, y) = @direction.next_point(x, y)
61
+
62
+ def ordinal = @direction.value
63
+
29
64
  ASCII_ARROWS = ['>', 'v', '<', '^']
30
- def ascii
31
- ASCII_ARROWS[@direction.value]
32
- end
65
+ def ascii = ASCII_ARROWS[@direction.value]
33
66
 
34
- def inspect
35
- @direction.inspect
36
- end
67
+ def inspect = ordinal.to_s
37
68
  alias :to_s :inspect
38
69
  end
39
70
  end
@@ -7,7 +7,10 @@ module RPiet
7
7
  def initialized(runtime)
8
8
  end
9
9
 
10
- def step_begin(runtime)
10
+ def next_possible(runtime, edge_x, edge_y, next_x, next_y, valid)
11
+ end
12
+
13
+ def step_begin(runtime, ex, ey)
11
14
  end
12
15
 
13
16
  def trying_again(runtime, ex, ey)
@@ -19,7 +22,10 @@ module RPiet
19
22
  def execution_completed(runtime)
20
23
  end
21
24
 
22
- def operation(runtime, operation)
25
+ def operation(runtime, step, operation)
26
+ end
27
+
28
+ def instruction(runtime, instruction)
23
29
  end
24
30
  end
25
31
 
@@ -33,10 +39,11 @@ module RPiet
33
39
 
34
40
  def initialized(runtime)
35
41
  dmesg "codel_size: #{runtime.source.codel_size}"
42
+ dmesg "size: #{runtime.source.cols}x#{runtime.source.rows}"
36
43
  end
37
44
 
38
- def step_begin(runtime)
39
- dmesg "step \##{runtime.step} -- #{runtime.pvm}"
45
+ def step_begin(runtime, ex, ey)
46
+ dmesg "step \##{runtime.step} at #{ex} #{ey} -- #{runtime.pvm}"
40
47
  end
41
48
 
42
49
  def trying_again(runtime, ex, ey)
@@ -51,16 +58,64 @@ module RPiet
51
58
  dmesg "Execution trapped, program terminates"
52
59
  end
53
60
 
54
- def operation(runtime, operation)
55
- dmesg "exec: #{operation} -- #{runtime.pvm}"
61
+ def instruction(runtime, instruction)
62
+ dmesg " instr: #{instruction}"
63
+ end
64
+
65
+ def operation(runtime, step, operation)
66
+ dmesg "exec: step: \##{step} oper: #{operation}, #{runtime}"
56
67
  end
57
68
  end
58
69
 
59
70
  class ComplexAsciiOutput < SimpleAsciiOutput
60
- def step_begin(runtime)
71
+ def step_begin(runtime, ex, ey)
61
72
  super
62
73
  dmesg runtime.source.ascii(runtime.groups[runtime.x][runtime.y])
63
74
  end
64
75
  end
76
+
77
+ class Graphical < SimpleAsciiOutput
78
+ def initialized(runtime)
79
+ unless $event_handler
80
+ require 'rpiet/debugger/debugger'
81
+ $rpiet = runtime
82
+ $event_handler = self
83
+ Thread.new { RPiet::Debugger.launch }.run
84
+ else
85
+ @debugger.begin_session
86
+ end
87
+ runtime.pause
88
+ end
89
+
90
+ def debugger_started(debugger)
91
+ @debugger = debugger
92
+ end
93
+
94
+ def step_begin(runtime, ex, ey)
95
+ @debugger.highlight(runtime, ex, ey)
96
+ if @debugger.break_point?(ex, ey)
97
+ puts "Break point at #{ex}, #{ey}"
98
+ end
99
+ end
100
+ alias :trying_again :step_begin
101
+
102
+ # edge of current group to potential entry point of next group (valid is if next is a valid group).
103
+ def next_possible(runtime, edge_x, edge_y, next_x, next_y, valid)
104
+ @debugger.highlight_candidate(runtime, edge_x, edge_y, next_x, next_y, valid)
105
+ end
106
+
107
+ def operation(runtime, step, operation)
108
+ # FIXME: display step in debugger
109
+ @debugger.operation(runtime, operation)
110
+ end
111
+
112
+ def seen_white(runtime)
113
+ puts "SEEN WHITE"
114
+ end
115
+
116
+ def trying_again(runtime, ex, ey)
117
+ @debugger.highlight(runtime, ex, ey)
118
+ end
119
+ end
65
120
  end
66
121
  end
data/lib/rpiet/group.rb CHANGED
@@ -1,16 +1,22 @@
1
- require 'rpiet/direction_pointer'
2
- require 'rpiet/codel_chooser'
1
+ require 'set'
2
+ require_relative 'direction_pointer'
3
+ require_relative 'codel_chooser'
3
4
 
4
5
  module RPiet
5
6
  class Group
6
7
  include RPiet::Direction
7
- attr_reader :rgb, :points
8
+ attr_reader :color, :points
8
9
 
9
- def initialize(rgb, point)
10
- @rgb, @points = rgb, []
10
+ # represents significant corners in a group based on the dp and cc.
11
+ # First letter is the dp: {r-ight, l-eft, d-own, u-p}.
12
+ # The second letter is the codel chooser: {l-eft, r-ight}.
13
+ attr_reader :rl, :rr, :lr, :ll, :ul, :ur, :dr, :dl
14
+
15
+ def initialize(color, *points)
16
+ @color, @points = color, []
11
17
  @max = { RIGHT => [], LEFT => [], UP => [], DOWN => [] }
12
18
 
13
- self << point
19
+ points.each { |point| self << point}
14
20
  end
15
21
 
16
22
  def point_for(pvm)
@@ -35,11 +41,22 @@ module RPiet
35
41
  @points << point
36
42
  end
37
43
 
44
+ def edges
45
+ edges = Set.new
46
+ @points.each do |x, y|
47
+ edges.add [x, y, :up] unless @points.include?(UP.next_point(x, y))
48
+ edges.add [x, y, :down] unless @points.include? DOWN.next_point(x, y)
49
+ edges.add [x, y, :left] unless @points.include?(LEFT.next_point(x, y))
50
+ edges.add [x, y, :right] unless @points.include? RIGHT.next_point(x, y)
51
+ end
52
+ edges
53
+ end
54
+
38
55
  def include?(point)
39
56
  @points.include? point
40
57
  end
41
58
 
42
- def finish
59
+ def calculate_corners
43
60
  @rl, @rr = ends(@max[RIGHT].sort { |a, b| a[1] <=> b[1] })
44
61
  @lr, @ll = ends(@max[LEFT].sort { |a, b| a[1] <=> b[1] })
45
62
  @ul, @ur = ends(@max[UP].sort { |a, b| a[0] <=> b[0] })
@@ -99,7 +116,7 @@ module RPiet
99
116
  end
100
117
 
101
118
  def inspect
102
- "Group #{rgb}: Size: #{size} Points: #{@points.inspect}\n" +
119
+ "Group #{color}: Size: #{size} Points: #{@points.inspect}\n" +
103
120
  "rr #@rr rl #@rl lr #@lr ll #@ll ur #@ur ul #@ul dr #@dr dl #@dl"
104
121
  end
105
122
  alias :to_s :inspect
@@ -4,25 +4,15 @@ module RPiet
4
4
  module Image
5
5
  class AsciiImage < RPiet::Image::Image
6
6
  def initialize(string, codel_size=1)
7
- @codel_size = codel_size
8
- lines = string.split("\n")
9
- @data = []
10
- lines.each do |line|
11
- @data << line.split(/\s+/).map { |e| str_to_rgb(e) }
7
+ super codel_size
8
+ @data = string.each_line(chomp: true).map do |line|
9
+ line.split(/\s+/).map { |e| str_to_rgb(e) }
12
10
  end
13
11
  end
14
12
 
15
- def raw_pixel(x, y)
16
- @data[x][y]
17
- end
18
-
19
- def raw_height
20
- @data.length
21
- end
22
-
23
- def raw_width
24
- @data[0].length
25
- end
13
+ def raw_pixel(x, y) = @data[y][x]
14
+ def raw_height = @data.length
15
+ def raw_width = @data[0].length
26
16
 
27
17
  STR2RGB = {
28
18
  'lr' => [0xff, 0xc0, 0xc0],
@@ -33,7 +23,7 @@ module RPiet
33
23
  'lm' => [0xff, 0xc0, 0xff],
34
24
  'nr' => [0xff, 0x00, 0x00],
35
25
  'ny' => [0xff, 0xff, 0x00],
36
- 'ng' => [0xc0, 0xff, 0x00],
26
+ 'ng' => [0x00, 0xff, 0x00],
37
27
  'nc' => [0x00, 0xff, 0xff],
38
28
  'nb' => [0x00, 0x00, 0xff],
39
29
  'nm' => [0xff, 0x00, 0xff],
@@ -47,9 +37,7 @@ module RPiet
47
37
  '++' => [0x00, 0x00, 0x00]
48
38
  }
49
39
 
50
- def str_to_rgb(str)
51
- STR2RGB[str]
52
- end
40
+ def str_to_rgb(str) = STR2RGB[str]
53
41
  end
54
42
  end
55
43
  end