smalruby-editor 0.1.6-x86-mingw32 → 0.1.7-x86-mingw32
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.
Potentially problematic release.
This version of smalruby-editor might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/app/assets/javascripts/blocks/hardware.js.coffee.erb +40 -3
- data/app/assets/stylesheets/toolbox.css.scss.erb +1 -6
- data/app/controllers/source_codes_controller.rb +5 -1
- data/app/models/concerns/ruby_to_block/block/base.rb +251 -0
- data/app/models/concerns/ruby_to_block/block/character.rb +42 -0
- data/app/models/concerns/ruby_to_block/block/character_event.rb +27 -0
- data/app/models/concerns/ruby_to_block/block/character_method_call.rb +29 -0
- data/app/models/concerns/ruby_to_block/block/character_new.rb +7 -0
- data/app/models/concerns/ruby_to_block/block/character_operation.rb +80 -0
- data/app/models/concerns/ruby_to_block/block/control_if.rb +45 -0
- data/app/models/concerns/ruby_to_block/block/control_loop.rb +19 -0
- data/app/models/concerns/ruby_to_block/block/control_sleep.rb +18 -0
- data/app/models/concerns/ruby_to_block/block/do.rb +24 -0
- data/app/models/concerns/ruby_to_block/block/else.rb +12 -0
- data/app/models/concerns/ruby_to_block/block/end.rb +26 -0
- data/app/models/concerns/ruby_to_block/block/events_on_click.rb +14 -0
- data/app/models/concerns/ruby_to_block/block/events_on_key_push_or_down.rb +17 -0
- data/app/models/concerns/ruby_to_block/block/events_on_start.rb +14 -0
- data/app/models/concerns/ruby_to_block/block/hardware_init_hardware.rb +14 -0
- data/app/models/concerns/ruby_to_block/block/hardware_led_off.rb +16 -0
- data/app/models/concerns/ruby_to_block/block/hardware_led_on.rb +16 -0
- data/app/models/concerns/ruby_to_block/block/hardware_on_sensor_change.rb +17 -0
- data/app/models/concerns/ruby_to_block/block/hardware_rgb_led_off.rb +18 -0
- data/app/models/concerns/ruby_to_block/block/hardware_rgb_led_on.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/hardware_sensor_value.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/hardware_two_wheel_drive_car.rb +26 -0
- data/app/models/concerns/ruby_to_block/block/looks_hide.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/looks_say.rb +20 -0
- data/app/models/concerns/ruby_to_block/block/looks_show.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/looks_vanish.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/math_number.rb +14 -0
- data/app/models/concerns/ruby_to_block/block/motion_change_x_by.rb +20 -0
- data/app/models/concerns/ruby_to_block/block/motion_change_y_by.rb +20 -0
- data/app/models/concerns/ruby_to_block/block/motion_move.rb +15 -0
- data/app/models/concerns/ruby_to_block/block/motion_point_towards_character.rb +24 -0
- data/app/models/concerns/ruby_to_block/block/motion_point_towards_mouse.rb +9 -0
- data/app/models/concerns/ruby_to_block/block/motion_reach_wall.rb +24 -0
- data/app/models/concerns/ruby_to_block/block/motion_rotate_left.rb +20 -0
- data/app/models/concerns/ruby_to_block/block/motion_rotate_right.rb +20 -0
- data/app/models/concerns/ruby_to_block/block/motion_self_angle.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/motion_self_x.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/motion_self_y.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/motion_set_angle.rb +15 -0
- data/app/models/concerns/ruby_to_block/block/motion_set_x.rb +38 -0
- data/app/models/concerns/ruby_to_block/block/motion_set_y.rb +15 -0
- data/app/models/concerns/ruby_to_block/block/motion_turn.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/motion_turn_if_reach_wall.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/null.rb +17 -0
- data/app/models/concerns/ruby_to_block/block/operators_compare.rb +36 -0
- data/app/models/concerns/ruby_to_block/block/operators_false.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/operators_true.rb +8 -0
- data/app/models/concerns/ruby_to_block/block/require_smalruby.rb +7 -0
- data/app/models/concerns/ruby_to_block/block/ruby_comment.rb +16 -0
- data/app/models/concerns/ruby_to_block/block/ruby_expression.rb +14 -0
- data/app/models/concerns/ruby_to_block/block/ruby_statement.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/sensing_hit.rb +23 -0
- data/app/models/concerns/ruby_to_block/block/sound_play.rb +15 -0
- data/app/models/concerns/ruby_to_block/block/sound_preset_sounds.rb +31 -0
- data/app/models/concerns/ruby_to_block/block/text.rb +15 -0
- data/app/models/concerns/ruby_to_block/block/value.rb +12 -0
- data/app/models/concerns/ruby_to_block/block.rb +97 -0
- data/app/models/concerns/ruby_to_block/context.rb +97 -0
- data/app/models/concerns/ruby_to_block/formatter.rb +26 -0
- data/app/models/concerns/ruby_to_block.rb +17 -360
- data/app/models/source_code.rb +3 -1
- data/app/views/editor/_toolbox.html.haml +16 -0
- data/lib/smalruby_editor/version.rb +3 -3
- data/public/assets/{application-64a390efe879c386a5950515064f062d.css → application-28b7bed56c5389dfa372e972c75b6676.css} +17 -10
- data/public/assets/application-28b7bed56c5389dfa372e972c75b6676.css.gz +0 -0
- data/public/assets/{application-8bfffad1222d4e198f3c7ccc1cbd774f.js → application-4f747690ebc8ec4815ae36021fdb2c44.js} +135 -0
- data/public/assets/{application-8bfffad1222d4e198f3c7ccc1cbd774f.js.gz → application-4f747690ebc8ec4815ae36021fdb2c44.js.gz} +0 -0
- data/public/assets/manifest-332a5a1668194028b55103e0ea45c054.json +1 -1
- data/smalruby-editor.gemspec +1 -1
- data/spec/acceptance/block_mode/blocks/hardware/two_wheel_drive_car.feature +69 -0
- data/spec/acceptance/ruby_mode/translate.feature +1 -1
- data/spec/controllers/source_codes_controller_spec.rb +14 -11
- data/spec/models/concerns/ruby_to_block/block/character_method_call_spec.rb +175 -0
- data/spec/models/concerns/ruby_to_block/block/control_if_spec.rb +75 -0
- data/spec/models/concerns/ruby_to_block/block/control_loop_spec.rb +68 -0
- data/spec/models/concerns/ruby_to_block/block/events_on_start_spec.rb +120 -0
- data/spec/models/concerns/ruby_to_block/block/hardware_spec.rb +120 -0
- data/spec/models/concerns/ruby_to_block/block/looks_say_spec.rb +79 -0
- data/spec/models/concerns/ruby_to_block/block/looks_spec.rb +74 -0
- data/spec/models/concerns/ruby_to_block/block/motion_move_spec.rb +63 -0
- data/spec/models/concerns/ruby_to_block/block/motion_reach_wall_spec.rb +67 -0
- data/spec/models/concerns/ruby_to_block/block/motion_spec.rb +392 -0
- data/spec/models/concerns/ruby_to_block/block/motion_turn_spec.rb +54 -0
- data/spec/models/concerns/ruby_to_block/block/require_smalruby_spec.rb +39 -0
- data/spec/models/concerns/ruby_to_block/block/ruby_comment_spec.rb +55 -0
- data/spec/models/concerns/ruby_to_block/block/ruby_statement_spec.rb +113 -0
- data/spec/models/concerns/ruby_to_block/block/shared/block_examples.rb +44 -0
- data/spec/models/concerns/ruby_to_block/block/sound_spec.rb +46 -0
- data/spec/models/concerns/ruby_to_block/block_spec.rb +49 -0
- data/spec/models/concerns/ruby_to_block_spec.rb +421 -217
- data/spec/support/ruby_to_block.rb +10 -0
- metadata +108 -10
- data/public/assets/application-64a390efe879c386a5950515064f062d.css.gz +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0bd06fb1b52286227744f48188c8f7da643f328e
|
4
|
+
data.tar.gz: 9f26a444410952686966a504032f23732dfc80f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 147b02a2fa9819acd85149a19b8346d1e420eafe80ed8a6b846cdfe6dd0b54ccaa3b04e852fdc1de9f6e191bc7ae3a929dfdf2fefc9ce57e9ec541910d21934d
|
7
|
+
data.tar.gz: 3e6f91f3cfd1837d861cf488f757097d9afaec3d6eb0b9c0ebd07b1e96c9512d84147e3eae9764d5b45996fb8ead1252cc38ed743c27b86cb991caba2fc489f7
|
@@ -235,13 +235,50 @@ Blockly.Blocks['<%= n %>'] =
|
|
235
235
|
@setTooltip('')
|
236
236
|
|
237
237
|
Blockly.Ruby['<%= n %>'] = (block) ->
|
238
|
-
pin = @getFieldValue('PIN')
|
239
|
-
#p sensor("A0").value.class
|
240
|
-
#p(sensor("A0").value / 6)
|
238
|
+
pin = @getFieldValue('PIN')
|
241
239
|
|
242
240
|
pos = Blockly.Ruby.valueToCode(@, 'POS', Blockly.Ruby.ORDER_FUNCTION_CALL) || '5'
|
243
241
|
Blockly.Ruby.characterMethodCall_("servo(#{Blockly.Ruby.quote_(pin)}).position = #{pos}")
|
244
242
|
|
243
|
+
# 「車」サブジャンル
|
244
|
+
|
245
|
+
# 「2WD車[▼ピン]を進める」ブロック
|
246
|
+
# 「2WD車[▼ピン]をバックさせる」ブロック
|
247
|
+
# 「2WD車[▼ピン]を左に曲げる」ブロック
|
248
|
+
# 「2WD車[▼ピン]を右に曲げる」ブロック
|
249
|
+
# 「2WD車[▼ピン]を止める」ブロック
|
250
|
+
<%
|
251
|
+
[
|
252
|
+
['forward', '進める'],
|
253
|
+
['backward', 'バックさせる'],
|
254
|
+
['turn_left', '左に曲げる'],
|
255
|
+
['turn_right', '右に曲げる'],
|
256
|
+
['stop', '止める'],
|
257
|
+
].each do |method, label|
|
258
|
+
n = "#{category}_two_wheel_drive_car_#{method}"
|
259
|
+
%>
|
260
|
+
|
261
|
+
Blockly.Blocks['<%= n %>'] =
|
262
|
+
init: ()->
|
263
|
+
dropdown = (["D#{n}", "D#{n}"] for n in [2..10])
|
264
|
+
|
265
|
+
@setHelpUrl('')
|
266
|
+
@setColour(<%= color %>)
|
267
|
+
@appendDummyInput()
|
268
|
+
.appendField('2WD車')
|
269
|
+
.appendField(new Blockly.FieldDropdown(dropdown), 'PIN')
|
270
|
+
.appendField('を<%= label %>')
|
271
|
+
@setInputsInline(true)
|
272
|
+
@setPreviousStatement(true)
|
273
|
+
@setNextStatement(true)
|
274
|
+
@setTooltip('')
|
275
|
+
|
276
|
+
Blockly.Ruby['<%= n %>'] = (block) ->
|
277
|
+
pin = @getFieldValue('PIN')
|
278
|
+
|
279
|
+
Blockly.Ruby.characterMethodCall_("two_wheel_drive_car(#{Blockly.Ruby.quote_(pin)}).<%= method %>")
|
280
|
+
<% end %>
|
281
|
+
|
245
282
|
# 「ボタン」サブジャンル
|
246
283
|
|
247
284
|
# 条件:ボタン[▼]を押している
|
@@ -42,10 +42,9 @@
|
|
42
42
|
208
|
43
43
|
208
|
44
44
|
208
|
45
|
+
208
|
45
46
|
).map(&:to_i)
|
46
47
|
|
47
|
-
ruby_genre_index = hues.index(340) + 1
|
48
|
-
|
49
48
|
colors = hues.map { |h|
|
50
49
|
[hsv_to_rgb(h, 100, 80), hsv_to_rgb(h, 100, 100)]
|
51
50
|
}
|
@@ -55,10 +54,6 @@
|
|
55
54
|
%>
|
56
55
|
|
57
56
|
#\:<%= ids[index] %> {
|
58
|
-
<% if index == ruby_genre_index %>
|
59
|
-
display: none;
|
60
|
-
|
61
|
-
<% end %>
|
62
57
|
.blocklyTreeRow {
|
63
58
|
padding-top: 0.25em;
|
64
59
|
padding-bottom: 0.25em;
|
@@ -61,7 +61,11 @@ class SourceCodesController < ApplicationController
|
|
61
61
|
source_code = SourceCode.new(source_code_params)
|
62
62
|
render text: source_code.to_blocks
|
63
63
|
rescue
|
64
|
-
|
64
|
+
if Rails.env == 'development'
|
65
|
+
raise
|
66
|
+
else
|
67
|
+
head :bad_request
|
68
|
+
end
|
65
69
|
end
|
66
70
|
|
67
71
|
private
|
@@ -0,0 +1,251 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module RubyToBlock
|
4
|
+
module Block
|
5
|
+
# すべてのブロックのベースクラス
|
6
|
+
class Base
|
7
|
+
attr_accessor :parent
|
8
|
+
attr_accessor :prev_sibling
|
9
|
+
attr_accessor :sibling
|
10
|
+
attr_accessor :fields
|
11
|
+
attr_accessor :values
|
12
|
+
attr_accessor :statements
|
13
|
+
|
14
|
+
def self.inherited(child)
|
15
|
+
Block.register(child)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.blocknize(regexp, options = {})
|
19
|
+
klass = (class << self; self; end)
|
20
|
+
klass.instance_eval do
|
21
|
+
define_method(:regexp_string) do
|
22
|
+
regexp
|
23
|
+
end
|
24
|
+
|
25
|
+
%w(
|
26
|
+
statement
|
27
|
+
value
|
28
|
+
indent
|
29
|
+
inline
|
30
|
+
priority
|
31
|
+
).each do |name|
|
32
|
+
sym = name.to_sym
|
33
|
+
if options.key?(sym)
|
34
|
+
v = options[sym]
|
35
|
+
if v.is_a?(TrueClass) || v.is_a?(FalseClass)
|
36
|
+
sym = "#{name}?".to_sym
|
37
|
+
end
|
38
|
+
define_method(sym) do
|
39
|
+
v
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.type
|
47
|
+
name.sub('RubyToBlock::Block::', '').underscore
|
48
|
+
end
|
49
|
+
|
50
|
+
# 正規表現を返す
|
51
|
+
def self.regexp
|
52
|
+
@regexp ||= Regexp.new(regexp_string)
|
53
|
+
end
|
54
|
+
|
55
|
+
# ステートメントかどうかを返す
|
56
|
+
#
|
57
|
+
# trueの場合、Block.statement_regexpに追加される
|
58
|
+
def self.statement?
|
59
|
+
false
|
60
|
+
end
|
61
|
+
|
62
|
+
# 値かどうかを返す
|
63
|
+
#
|
64
|
+
# trueの場合、Block.value_regexpに追加される
|
65
|
+
def self.value?
|
66
|
+
false
|
67
|
+
end
|
68
|
+
|
69
|
+
# 正規表現の優先度を返す
|
70
|
+
def self.priority
|
71
|
+
0
|
72
|
+
end
|
73
|
+
|
74
|
+
# インデントする必要があるかどうかを返す
|
75
|
+
def self.indent?
|
76
|
+
false
|
77
|
+
end
|
78
|
+
|
79
|
+
# インラインのブロックかどうかを返す
|
80
|
+
def self.inline?
|
81
|
+
false
|
82
|
+
end
|
83
|
+
|
84
|
+
# 正規表現にマッチしたデータを解析する
|
85
|
+
#
|
86
|
+
# @return [true] これ以上解析する必要がない
|
87
|
+
# @return [false] 解析できなかったのでさらなる解析が必要
|
88
|
+
def self.process_match_data(md, context)
|
89
|
+
true
|
90
|
+
end
|
91
|
+
|
92
|
+
# 値を格納した文字列を解析する
|
93
|
+
#
|
94
|
+
# @return [true] これ以上解析する必要がない
|
95
|
+
# @return [false] 解析できなかったのでさらなる解析が必要
|
96
|
+
def self.process_value_string(context, block, string, name)
|
97
|
+
# HACK: 最初と最後の括弧を取り除く
|
98
|
+
string = string[1..-2] while string[0] == '(' && string[-1] == ')'
|
99
|
+
|
100
|
+
value_md = Block.value_regexp.match(string)
|
101
|
+
return false unless value_md
|
102
|
+
|
103
|
+
_current_block = context.current_block
|
104
|
+
context.current_block = block
|
105
|
+
context.value_name_stack.push(name)
|
106
|
+
|
107
|
+
unless Block.process_match_data(value_md, context)
|
108
|
+
Block.process_match_data(value_md, context, 'ruby_expression')
|
109
|
+
end
|
110
|
+
|
111
|
+
context.value_name_stack.pop
|
112
|
+
context.current_block = _current_block
|
113
|
+
|
114
|
+
true
|
115
|
+
end
|
116
|
+
|
117
|
+
# elseを発見した時の処理
|
118
|
+
#
|
119
|
+
# @return [true] これ以上処理する必要がない
|
120
|
+
# @return [false] 処理できなかった
|
121
|
+
def self.process_else(context)
|
122
|
+
false
|
123
|
+
end
|
124
|
+
|
125
|
+
# endを発見した時の処理
|
126
|
+
#
|
127
|
+
# @return [true] これ以上処理する必要がない
|
128
|
+
# @return [false] 処理できなかった
|
129
|
+
def self.process_end(context)
|
130
|
+
context.current_block = context.statement[1]
|
131
|
+
context.statement_stack.pop
|
132
|
+
|
133
|
+
true
|
134
|
+
end
|
135
|
+
|
136
|
+
def initialize(options = {})
|
137
|
+
@fields = options[:fields] || {}
|
138
|
+
@values = options[:values] || {}
|
139
|
+
@statements = options[:statements] || {}
|
140
|
+
|
141
|
+
if @statements.length > 0
|
142
|
+
@statements.values.each do |s|
|
143
|
+
s.parent = self
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def to_xml(parent)
|
149
|
+
e = parent.add_element('block', 'type' => type)
|
150
|
+
e.add_attribute('inline', 'true') if inline?
|
151
|
+
fields_to_xml(e)
|
152
|
+
values_to_xml(e)
|
153
|
+
statements_to_xml(e)
|
154
|
+
sibling_to_xml(e)
|
155
|
+
e
|
156
|
+
end
|
157
|
+
|
158
|
+
def type
|
159
|
+
@type ||= self.class.type
|
160
|
+
end
|
161
|
+
|
162
|
+
def inline?
|
163
|
+
@inline ||= self.class.inline?
|
164
|
+
end
|
165
|
+
|
166
|
+
def null?
|
167
|
+
false
|
168
|
+
end
|
169
|
+
|
170
|
+
def [](name)
|
171
|
+
@fields[name]
|
172
|
+
end
|
173
|
+
|
174
|
+
def add_statement(name, block)
|
175
|
+
b = @statements[name]
|
176
|
+
if b
|
177
|
+
b = b.sibling while b.sibling
|
178
|
+
b.sibling = block
|
179
|
+
else
|
180
|
+
block.parent = self
|
181
|
+
@statements[name] = block
|
182
|
+
end
|
183
|
+
self
|
184
|
+
end
|
185
|
+
|
186
|
+
def add_value(name, block)
|
187
|
+
b = @values[name]
|
188
|
+
if b
|
189
|
+
b = b.sibling while b.sibling
|
190
|
+
b.sibling = block
|
191
|
+
else
|
192
|
+
block.parent = self
|
193
|
+
@values[name] = block
|
194
|
+
end
|
195
|
+
self
|
196
|
+
end
|
197
|
+
|
198
|
+
def sibling=(block)
|
199
|
+
block.parent = parent
|
200
|
+
@sibling = block
|
201
|
+
block.prev_sibling = self
|
202
|
+
end
|
203
|
+
|
204
|
+
def indent_level
|
205
|
+
b = self
|
206
|
+
level = 0
|
207
|
+
while b.parent
|
208
|
+
b = b.parent
|
209
|
+
level += 1 if b.class.indent?
|
210
|
+
end
|
211
|
+
level
|
212
|
+
end
|
213
|
+
|
214
|
+
private
|
215
|
+
|
216
|
+
def fields_to_xml(parent)
|
217
|
+
@fields.each do |k, v|
|
218
|
+
e = parent.add_element('field', 'name' => k.to_s)
|
219
|
+
if v.is_a?(String)
|
220
|
+
e.text = v
|
221
|
+
else
|
222
|
+
# TODO
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def values_to_xml(parent)
|
228
|
+
@values.each do |k, v|
|
229
|
+
next if v.null?
|
230
|
+
e = parent.add_element('value', 'name' => k.to_s)
|
231
|
+
v.to_xml(e)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def statements_to_xml(parent)
|
236
|
+
@statements.each do |k, v|
|
237
|
+
next if v.null?
|
238
|
+
e = parent.add_element('statement', 'name' => k.to_s)
|
239
|
+
v.to_xml(e)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def sibling_to_xml(parent)
|
244
|
+
return nil unless @sibling
|
245
|
+
|
246
|
+
e = parent.add_element('next')
|
247
|
+
@sibling.to_xml(e)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module RubyToBlock
|
3
|
+
module Block
|
4
|
+
# ソースコードに含まれるキャラクターを表現するクラス
|
5
|
+
class Character < Base
|
6
|
+
# rubocop:disable LineLength
|
7
|
+
blocknize '^\s*(\S+)\s*=\s*Character\.new\(costume:\s*"(\s*[^"]+\s*)"\s*,\s*x:\s*(\s*\d+\s*)\s*,\s*y:\s*(\s*\d+\s*)\s*,\s*angle:\s*(\s*\d+\s*)\)\s*$',
|
8
|
+
statement: true
|
9
|
+
# rubocop:enable LineLength
|
10
|
+
|
11
|
+
attr_accessor :name
|
12
|
+
attr_accessor :costumes
|
13
|
+
attr_accessor :x
|
14
|
+
attr_accessor :y
|
15
|
+
attr_accessor :angle
|
16
|
+
|
17
|
+
def self.process_match_data(md, context)
|
18
|
+
md2 = regexp.match(md[type])
|
19
|
+
name = md2[1]
|
20
|
+
context[:characters][name] = new(name: name, costumes: [md2[2]],
|
21
|
+
x: md2[3], y: md2[4], angle: md2[5])
|
22
|
+
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(options)
|
27
|
+
@name = options[:name]
|
28
|
+
@costumes = options[:costumes]
|
29
|
+
@x = options[:x]
|
30
|
+
@y = options[:y]
|
31
|
+
@angle = options[:angle]
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_xml(parent)
|
35
|
+
parent.add_element('character',
|
36
|
+
'name' => @name,
|
37
|
+
'x' => @x, 'y' => @y, 'angle' => @angle,
|
38
|
+
'costumes' => @costumes.join(','))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module RubyToBlock
|
2
|
+
module Block
|
3
|
+
class CharacterEvent < CharacterMethodCall
|
4
|
+
def self.process_end(context)
|
5
|
+
context.receiver_stack.pop
|
6
|
+
context.character_stack.pop
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.add_character_event_blocks(context, name, block)
|
11
|
+
do_block = Block.new('null')
|
12
|
+
block.add_statement(:DO, do_block)
|
13
|
+
|
14
|
+
character = get_character(context, name)
|
15
|
+
context.character_stack.push(character)
|
16
|
+
|
17
|
+
character_new_block, _ =
|
18
|
+
add_child_or_create_character_new_block(context, name, block)
|
19
|
+
|
20
|
+
context.receiver_stack.push(character)
|
21
|
+
|
22
|
+
context.statement_stack.push([type, character_new_block])
|
23
|
+
context.current_block = do_block
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RubyToBlock
|
2
|
+
module Block
|
3
|
+
class CharacterMethodCall < Base
|
4
|
+
include CharacterOperation
|
5
|
+
|
6
|
+
def self.process_match_data(md, context)
|
7
|
+
md2 = regexp.match(md[type])
|
8
|
+
|
9
|
+
block = new
|
10
|
+
_, context.current_block =
|
11
|
+
*add_child_or_create_character_new_block(context, md2[1], block)
|
12
|
+
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.add_character_method_call_block(context, name, block,
|
17
|
+
values = {})
|
18
|
+
_, context.current_block =
|
19
|
+
*add_child_or_create_character_new_block(context, name, block)
|
20
|
+
|
21
|
+
values.each do |k, v|
|
22
|
+
process_value_string(context, block, v, k)
|
23
|
+
end
|
24
|
+
|
25
|
+
block
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module RubyToBlock
|
3
|
+
module Block
|
4
|
+
# キャラクターのメソッドや属性に共通するメソッドや定数を定義するモジュール
|
5
|
+
module CharacterOperation
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
CHAR_RE = '(?:(\S+)\.)?'
|
9
|
+
|
10
|
+
attr_accessor :character
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
# コンテキストからキャラクターを取得する
|
14
|
+
#
|
15
|
+
# キャラクターの名前がnil、または'self'の場合はコンテキストのレシー
|
16
|
+
# バの名前を利用する。
|
17
|
+
#
|
18
|
+
# コンテキストからキャラクターが取得できない場合は例外が発生する。
|
19
|
+
#
|
20
|
+
# @param [RubyToBlock::Context] context コンテキスト
|
21
|
+
# @param [String] name キャラクターの名前
|
22
|
+
# @return [Character] キャラクター
|
23
|
+
def get_character(context, name)
|
24
|
+
name = context.receiver.try(:name) if !name || name == 'self'
|
25
|
+
fail unless context.characters.key?(name)
|
26
|
+
context.characters[name]
|
27
|
+
end
|
28
|
+
|
29
|
+
# 必要であればcharacter_newブロックを作成してから指定したブロッ
|
30
|
+
# クをcharacter_newブロックの子供として追加する
|
31
|
+
#
|
32
|
+
# @param [RubyToBlock::Context] context コンテキスト
|
33
|
+
# @param [String] name キャラクターの名前
|
34
|
+
# @param [ブロック] block ブロックのインスタンス
|
35
|
+
# @return [Array<ブロック, ブロック>]
|
36
|
+
# 最初の要素がcharacter_newブロック、次の要素がカレントブロックの配列
|
37
|
+
def add_child_or_create_character_new_block(context, name, block)
|
38
|
+
character = get_character(context, name)
|
39
|
+
|
40
|
+
block.character = character
|
41
|
+
|
42
|
+
cb = context.current_block
|
43
|
+
if cb && cb.type == 'character_new' && cb.character == character
|
44
|
+
cb.add_statement(:DO, block)
|
45
|
+
[cb, cb]
|
46
|
+
elsif character == context.receiver
|
47
|
+
cb.sibling = block
|
48
|
+
[cb.parent, block]
|
49
|
+
else
|
50
|
+
character_new =
|
51
|
+
create_character_new_block(context, character, block)
|
52
|
+
[character_new, character_new]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# character_newブロックを生成する
|
57
|
+
#
|
58
|
+
# @param [RubyToBlock::Context] context コンテキスト
|
59
|
+
# @param [RubyToBlock::Block::Character] character キャラクター
|
60
|
+
# @param [RubyToBlock::Block::Baseのサブクラス] block ブロック
|
61
|
+
# @return [RubyToBlock::Block::CharacterNew] character_newブロック
|
62
|
+
def create_character_new_block(context, character, block)
|
63
|
+
character_new_block = Block.new('character_new',
|
64
|
+
fields: { NAME: character.name },
|
65
|
+
statements: { DO: block })
|
66
|
+
character_new_block.character = character
|
67
|
+
|
68
|
+
cb = context.current_block
|
69
|
+
if cb && cb.type != 'character_new'
|
70
|
+
cb.sibling = character_new_block
|
71
|
+
else
|
72
|
+
context.blocks.push(character_new_block)
|
73
|
+
end
|
74
|
+
|
75
|
+
character_new_block
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module RubyToBlock
|
2
|
+
module Block
|
3
|
+
class ControlIf < Base
|
4
|
+
blocknize '^\s*if\s+(.*?)\s*$',
|
5
|
+
statement: true, indent: true, inline: true
|
6
|
+
|
7
|
+
def self.process_match_data(md, context)
|
8
|
+
then_block = Block.new('null')
|
9
|
+
block = new(statements: { THEN: then_block })
|
10
|
+
|
11
|
+
if context.current_block
|
12
|
+
context.current_block.sibling = block
|
13
|
+
else
|
14
|
+
context.blocks.push(block)
|
15
|
+
end
|
16
|
+
|
17
|
+
md2 = regexp.match(md[type])
|
18
|
+
process_value_string(context, block, md2[1], :COND)
|
19
|
+
|
20
|
+
context.current_block = then_block
|
21
|
+
|
22
|
+
context.statement_stack.push([type, block])
|
23
|
+
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.process_else(context)
|
28
|
+
block = context.statement_block
|
29
|
+
else_block = Block.new('null')
|
30
|
+
block.add_statement(:ELSE, else_block)
|
31
|
+
context.current_block = else_block
|
32
|
+
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def type
|
37
|
+
if @statements.key?(:ELSE)
|
38
|
+
'control_if_else'
|
39
|
+
else
|
40
|
+
super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RubyToBlock
|
2
|
+
module Block
|
3
|
+
class ControlLoop < Base
|
4
|
+
blocknize '^\s*loop\s+do\s*$', statement: true, indent: true
|
5
|
+
|
6
|
+
def self.process_match_data(md, context)
|
7
|
+
return false unless context.receiver
|
8
|
+
|
9
|
+
do_block = Block.new('null')
|
10
|
+
block = new(statements: { DO: do_block })
|
11
|
+
context.statement_stack.push([type, block])
|
12
|
+
context.current_block.sibling = block
|
13
|
+
context.current_block = do_block
|
14
|
+
|
15
|
+
true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module RubyToBlock
|
3
|
+
module Block
|
4
|
+
class ControlSleep < Base
|
5
|
+
blocknize '^\s*sleep\((.+)\)\s*$', statement: true, inline: true
|
6
|
+
|
7
|
+
def self.process_match_data(md, context)
|
8
|
+
block = new
|
9
|
+
context.add_block(block)
|
10
|
+
|
11
|
+
md2 = regexp.match(md[type])
|
12
|
+
process_value_string(context, block, md2[1], :SEC)
|
13
|
+
|
14
|
+
true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module RubyToBlock
|
2
|
+
module Block
|
3
|
+
class Do < RubyStatement
|
4
|
+
blocknize '^.*?\s*do\s*$',
|
5
|
+
statement: true, priority: -1
|
6
|
+
|
7
|
+
def self.process_match_data(md, context)
|
8
|
+
block = new(fields: { STATEMENT: md.string })
|
9
|
+
context.add_block(block)
|
10
|
+
context.statement_stack.push([type, block])
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.process_end(context)
|
15
|
+
context.add_block(new(fields: { STATEMENT: 'end' }))
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def type
|
20
|
+
'ruby_statement'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module RubyToBlock
|
3
|
+
module Block
|
4
|
+
class End < Base
|
5
|
+
blocknize '^\s*end$', statement: true
|
6
|
+
|
7
|
+
def self.process_match_data(md, context)
|
8
|
+
ends_num = 1
|
9
|
+
context.lines.each do |l|
|
10
|
+
md2 = Block.statement_regexp.match(l)
|
11
|
+
type = md2.names.find { |n| md2[n.to_sym] }
|
12
|
+
if type == 'end'
|
13
|
+
ends_num += 1
|
14
|
+
elsif Block[type].indent?
|
15
|
+
ends_num -= 1
|
16
|
+
end
|
17
|
+
end
|
18
|
+
if context.statement && ends_num <= context.statement_stack.length
|
19
|
+
Block.process_end(context)
|
20
|
+
else
|
21
|
+
false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|