blockly_interpreter 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +12 -0
- data/COPYING +8 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +91 -0
- data/Guardfile +22 -0
- data/README.md +72 -0
- data/Rakefile +10 -0
- data/app/assets/javascripts/blockly_interpreter/extension_blocks.js +1 -0
- data/app/assets/javascripts/blockly_interpreter/extension_blocks/dates.js +16 -0
- data/app/assets/javascripts/blockly_interpreter/extension_blocks/debugging.js +17 -0
- data/app/assets/javascripts/blockly_interpreter/extension_blocks/lists.js +45 -0
- data/app/assets/javascripts/blockly_interpreter/extension_blocks/logic.js +274 -0
- data/app/assets/javascripts/blockly_interpreter/extension_blocks/text.js.erb +21 -0
- data/bin/_guard-core +16 -0
- data/bin/console +14 -0
- data/bin/guard +16 -0
- data/bin/rake +16 -0
- data/bin/setup +7 -0
- data/blockly_interpreter.gemspec +33 -0
- data/exe/blocklyi +13 -0
- data/exe/rublocklyc +31 -0
- data/lib/blockly_interpreter.rb +25 -0
- data/lib/blockly_interpreter/block.rb +113 -0
- data/lib/blockly_interpreter/block_library.rb +14 -0
- data/lib/blockly_interpreter/console_interpreter.rb +15 -0
- data/lib/blockly_interpreter/core_blocks.rb +55 -0
- data/lib/blockly_interpreter/core_blocks/arithmetic_operator_block.rb +24 -0
- data/lib/blockly_interpreter/core_blocks/boolean_block.rb +23 -0
- data/lib/blockly_interpreter/core_blocks/comparison_operator_block.rb +50 -0
- data/lib/blockly_interpreter/core_blocks/for_block.rb +68 -0
- data/lib/blockly_interpreter/core_blocks/for_each_block.rb +42 -0
- data/lib/blockly_interpreter/core_blocks/get_variable_block.rb +19 -0
- data/lib/blockly_interpreter/core_blocks/if_block.rb +105 -0
- data/lib/blockly_interpreter/core_blocks/lists_create_empty_block.rb +17 -0
- data/lib/blockly_interpreter/core_blocks/lists_create_with_block.rb +48 -0
- data/lib/blockly_interpreter/core_blocks/lists_get_index_block.rb +95 -0
- data/lib/blockly_interpreter/core_blocks/logic_negate_block.rb +20 -0
- data/lib/blockly_interpreter/core_blocks/logical_operator_block.rb +22 -0
- data/lib/blockly_interpreter/core_blocks/number_block.rb +23 -0
- data/lib/blockly_interpreter/core_blocks/procedure_block.rb +49 -0
- data/lib/blockly_interpreter/core_blocks/procedures_call_no_return_block.rb +21 -0
- data/lib/blockly_interpreter/core_blocks/procedures_call_return_block.rb +21 -0
- data/lib/blockly_interpreter/core_blocks/procedures_def_no_return_block.rb +31 -0
- data/lib/blockly_interpreter/core_blocks/procedures_def_return_block.rb +64 -0
- data/lib/blockly_interpreter/core_blocks/procedures_if_return_block.rb +45 -0
- data/lib/blockly_interpreter/core_blocks/repeat_times_block.rb +33 -0
- data/lib/blockly_interpreter/core_blocks/set_variable_block.rb +24 -0
- data/lib/blockly_interpreter/core_blocks/text_block.rb +23 -0
- data/lib/blockly_interpreter/core_blocks/text_change_case_block.rb +32 -0
- data/lib/blockly_interpreter/core_blocks/text_join_block.rb +50 -0
- data/lib/blockly_interpreter/dsl.rb +291 -0
- data/lib/blockly_interpreter/dsl_generator.rb +147 -0
- data/lib/blockly_interpreter/engine.rb +8 -0
- data/lib/blockly_interpreter/execution_context.rb +72 -0
- data/lib/blockly_interpreter/extension_blocks.rb +25 -0
- data/lib/blockly_interpreter/extension_blocks/date_today_block.rb +17 -0
- data/lib/blockly_interpreter/extension_blocks/debug_message_block.rb +18 -0
- data/lib/blockly_interpreter/extension_blocks/lists_append_block.rb +34 -0
- data/lib/blockly_interpreter/extension_blocks/lists_concat_block.rb +37 -0
- data/lib/blockly_interpreter/extension_blocks/lists_include_operator_block.rb +52 -0
- data/lib/blockly_interpreter/extension_blocks/object_present_block.rb +21 -0
- data/lib/blockly_interpreter/extension_blocks/switch_block.rb +107 -0
- data/lib/blockly_interpreter/extension_blocks/text_inflect_block.rb +27 -0
- data/lib/blockly_interpreter/generic_block_dsl_generator.rb +64 -0
- data/lib/blockly_interpreter/interpreter.rb +25 -0
- data/lib/blockly_interpreter/parser.rb +117 -0
- data/lib/blockly_interpreter/program.rb +51 -0
- data/lib/blockly_interpreter/program_cache.rb +19 -0
- data/lib/blockly_interpreter/test_helper.rb +98 -0
- data/lib/blockly_interpreter/version.rb +3 -0
- metadata +272 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::LogicNegateBlock < BlocklyInterpreter::Block
|
2
|
+
include BlocklyInterpreter::DSLGenerator
|
3
|
+
self.block_type = :logic_negate
|
4
|
+
|
5
|
+
def value(execution_context)
|
6
|
+
!values['BOOL'].value(execution_context)
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_dsl
|
10
|
+
method_call_with_possible_block("logic_negate", "", values['BOOL'])
|
11
|
+
end
|
12
|
+
|
13
|
+
module DSLMethods
|
14
|
+
def logic_negate(&proc)
|
15
|
+
block :logic_negate do
|
16
|
+
value 'BOOL', &proc
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::LogicalOperatorBlock < BlocklyInterpreter::Block
|
2
|
+
self.block_type = :logic_operation
|
3
|
+
|
4
|
+
def value(execution_context)
|
5
|
+
case fields['OP']
|
6
|
+
when 'AND' then values['A'].value(execution_context) && values['B'].value(execution_context)
|
7
|
+
when 'OR' then values['A'].value(execution_context) || values['B'].value(execution_context)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_dsl
|
12
|
+
BlocklyInterpreter::DSL::BinaryOperationDSLGenerator.new(self, "logic_operation").dsl
|
13
|
+
end
|
14
|
+
|
15
|
+
module DSLMethods
|
16
|
+
def logic_operation(op, a = nil, b = nil, &proc)
|
17
|
+
@blocks << BlocklyInterpreter::DSL::BinaryOperationBlockBuilder.new("logic_operation", op, a, b).tap do |builder|
|
18
|
+
builder.instance_exec(&proc) if block_given?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::NumberBlock < BlocklyInterpreter::Block
|
2
|
+
self.block_type = :math_number
|
3
|
+
|
4
|
+
def num
|
5
|
+
fields['NUM'].to_i
|
6
|
+
end
|
7
|
+
|
8
|
+
def value(execution_context)
|
9
|
+
num
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_dsl
|
13
|
+
"math_number #{num.inspect}"
|
14
|
+
end
|
15
|
+
|
16
|
+
module DSLMethods
|
17
|
+
def math_number(n)
|
18
|
+
block :math_number do
|
19
|
+
field :NUM, n.to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::ProcedureBlock < BlocklyInterpreter::Block
|
2
|
+
include BlocklyInterpreter::DSLGenerator
|
3
|
+
|
4
|
+
def arg_hash(parameters)
|
5
|
+
Hash[arg_names.zip(parameters)]
|
6
|
+
end
|
7
|
+
|
8
|
+
def arg_names
|
9
|
+
@arg_names ||= (mutation && mutation.css('> arg').map { |arg| arg['name'] }) || []
|
10
|
+
end
|
11
|
+
|
12
|
+
def arg_values(execution_context)
|
13
|
+
(0...arg_names.size).map do |arg_num|
|
14
|
+
values["ARG#{arg_num}"].value(execution_context)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def args_dsl
|
19
|
+
arg_names.each_with_index.map do |arg_name, i|
|
20
|
+
method_call_with_possible_block("arg", arg_name.inspect, values["ARG#{i}"])
|
21
|
+
end.compact
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_dsl
|
25
|
+
method_call_with_possible_block "#{self.class.block_type}", procedure_name.inspect, args_dsl
|
26
|
+
end
|
27
|
+
|
28
|
+
module DSLMethods
|
29
|
+
class ProcedureCallBlockBuilder < BlocklyInterpreter::DSL::BlockBuilder
|
30
|
+
attr_reader :arg_number
|
31
|
+
|
32
|
+
def initialize(block_type, procedure_name)
|
33
|
+
super(block_type)
|
34
|
+
|
35
|
+
mutation_attr :name, procedure_name
|
36
|
+
@arg_number = 0
|
37
|
+
end
|
38
|
+
|
39
|
+
def arg(name, &proc)
|
40
|
+
mutation_child :arg do |child|
|
41
|
+
child['name'] = name
|
42
|
+
end
|
43
|
+
|
44
|
+
value "ARG#{arg_number}", &proc
|
45
|
+
@arg_number += 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::ProceduresCallNoReturnBlock < BlocklyInterpreter::CoreBlocks::ProcedureBlock
|
2
|
+
self.block_type = :procedures_callnoreturn
|
3
|
+
|
4
|
+
def procedure_name
|
5
|
+
@procedure_name ||= mutation.try!(:[], 'name')
|
6
|
+
end
|
7
|
+
|
8
|
+
def execute_statement(execution_context)
|
9
|
+
execution_context.execute_procedure(procedure_name, arg_values(execution_context))
|
10
|
+
end
|
11
|
+
|
12
|
+
module DSLMethods
|
13
|
+
def procedures_callnoreturn(name, &proc)
|
14
|
+
builder = BlocklyInterpreter::CoreBlocks::ProcedureBlock::DSLMethods::ProcedureCallBlockBuilder.new("procedures_callnoreturn", name)
|
15
|
+
|
16
|
+
@blocks << builder.tap do |builder|
|
17
|
+
builder.instance_exec(&proc) if proc
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::ProceduresCallReturnBlock < BlocklyInterpreter::CoreBlocks::ProcedureBlock
|
2
|
+
self.block_type = :procedures_callreturn
|
3
|
+
|
4
|
+
def procedure_name
|
5
|
+
@procedure_name ||= mutation.try!(:[], 'name')
|
6
|
+
end
|
7
|
+
|
8
|
+
def value(execution_context)
|
9
|
+
execution_context.value_for_procedure(procedure_name, arg_values(execution_context))
|
10
|
+
end
|
11
|
+
|
12
|
+
module DSLMethods
|
13
|
+
def procedures_callreturn(name, &proc)
|
14
|
+
builder = BlocklyInterpreter::CoreBlocks::ProcedureBlock::DSLMethods::ProcedureCallBlockBuilder.new("procedures_callreturn", name)
|
15
|
+
|
16
|
+
@blocks << builder.tap do |builder|
|
17
|
+
builder.instance_exec(&proc) if proc
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::ProceduresDefNoReturnBlock < BlocklyInterpreter::CoreBlocks::ProcedureBlock
|
2
|
+
self.block_type = :procedures_defnoreturn
|
3
|
+
|
4
|
+
def procedure_name
|
5
|
+
fields['NAME']
|
6
|
+
end
|
7
|
+
|
8
|
+
def execute_statement(execution_context)
|
9
|
+
execution_context.execute(statements['STACK'])
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_dsl
|
13
|
+
method_call_with_possible_block("procedures_defnoreturn", ([procedure_name] + arg_names).map(&:inspect).join(", "), statements['STACK'])
|
14
|
+
end
|
15
|
+
|
16
|
+
module DSLMethods
|
17
|
+
def procedures_defnoreturn(name, *arg_names, &proc)
|
18
|
+
block :procedures_defnoreturn do
|
19
|
+
field :NAME, name
|
20
|
+
|
21
|
+
arg_names.each do |arg_name|
|
22
|
+
mutation_child :arg do |child|
|
23
|
+
child['name'] = arg_name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
statement :STACK, &proc
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::ProceduresDefReturnBlock < BlocklyInterpreter::CoreBlocks::ProcedureBlock
|
2
|
+
self.block_type = :procedures_defreturn
|
3
|
+
|
4
|
+
def procedure_name
|
5
|
+
fields['NAME']
|
6
|
+
end
|
7
|
+
|
8
|
+
def value(execution_context)
|
9
|
+
execution_context.execute(statements['STACK'])
|
10
|
+
|
11
|
+
if execution_context.terminated
|
12
|
+
execution_context.early_return_value
|
13
|
+
else
|
14
|
+
values['RETURN'].value(execution_context)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_dsl
|
19
|
+
block_contents = [
|
20
|
+
method_call_with_block_or_nothing("body", "", statements['STACK']),
|
21
|
+
method_call_with_block_or_nothing("return_value", "", values['RETURN'])
|
22
|
+
]
|
23
|
+
|
24
|
+
method_call_with_possible_block "#{self.class.block_type}", ([procedure_name] + arg_names).map(&:inspect).join(", "), block_contents
|
25
|
+
end
|
26
|
+
|
27
|
+
module DSLMethods
|
28
|
+
class ProceduresDefReturnBlockBuilder < BlocklyInterpreter::DSL::BlockBuilder
|
29
|
+
attr_reader :stack
|
30
|
+
|
31
|
+
def initialize(block_type, procedure_name, arg_names)
|
32
|
+
super(block_type)
|
33
|
+
|
34
|
+
field :NAME, procedure_name
|
35
|
+
|
36
|
+
arg_names.each do |arg_name|
|
37
|
+
mutation_child :arg do |child|
|
38
|
+
child['name'] = arg_name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def body(&proc)
|
44
|
+
statement :STACK, &proc
|
45
|
+
end
|
46
|
+
|
47
|
+
def return_value(&proc)
|
48
|
+
value :RETURN, &proc
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def procedures_defreturn(name, *arg_names, &proc)
|
53
|
+
builder = BlocklyInterpreter::CoreBlocks::ProceduresDefReturnBlock::DSLMethods::ProceduresDefReturnBlockBuilder.new(
|
54
|
+
"procedures_defreturn",
|
55
|
+
name,
|
56
|
+
arg_names
|
57
|
+
)
|
58
|
+
|
59
|
+
@blocks << builder.tap do |builder|
|
60
|
+
builder.instance_exec(&proc) if proc
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::ProceduresIfReturnBlock < BlocklyInterpreter::Block
|
2
|
+
include BlocklyInterpreter::DSLGenerator
|
3
|
+
|
4
|
+
self.block_type = :procedures_ifreturn
|
5
|
+
|
6
|
+
def execute_statement(execution_context)
|
7
|
+
if values['CONDITION'].value(execution_context).present?
|
8
|
+
return_value = values['VALUE'].value(execution_context) if values['VALUE']
|
9
|
+
execution_context.early_return!(return_value)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_dsl
|
14
|
+
block_contents = [method_call_with_possible_block("condition", "", values['CONDITION'])]
|
15
|
+
block_contents << method_call_with_block_or_nothing("return_value", "", values['VALUE'])
|
16
|
+
|
17
|
+
method_call_with_possible_block("procedures_ifreturn", "", block_contents.compact)
|
18
|
+
end
|
19
|
+
|
20
|
+
module DSLMethods
|
21
|
+
class ProceduresIfReturnBlockBuilder < BlocklyInterpreter::DSL::BlockBuilder
|
22
|
+
def initialize(block_type)
|
23
|
+
super
|
24
|
+
mutation_attr :value, 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def condition(&proc)
|
28
|
+
value :CONDITION, &proc
|
29
|
+
end
|
30
|
+
|
31
|
+
def return_value(&proc)
|
32
|
+
mutation_attr :value, 1
|
33
|
+
value :VALUE, &proc
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def procedures_ifreturn(&proc)
|
38
|
+
builder = BlocklyInterpreter::CoreBlocks::ProceduresIfReturnBlock::DSLMethods::ProceduresIfReturnBlockBuilder.new("procedures_ifreturn")
|
39
|
+
|
40
|
+
@blocks << builder.tap do |builder|
|
41
|
+
builder.instance_exec(&proc) if proc
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::RepeatTimesBlock < BlocklyInterpreter::Block
|
2
|
+
self.block_type = :controls_repeat_ext
|
3
|
+
|
4
|
+
def execute_statement(execution_context)
|
5
|
+
n = values['TIMES'].value(execution_context).to_i
|
6
|
+
n.times { execution_context.execute(statements['DO']) }
|
7
|
+
end
|
8
|
+
|
9
|
+
module DSLMethods
|
10
|
+
class RepeatBlockBuilder < BlocklyInterpreter::DSL::BlockBuilder
|
11
|
+
def times(&proc)
|
12
|
+
value "TIMES", &proc
|
13
|
+
end
|
14
|
+
|
15
|
+
def action(&proc)
|
16
|
+
statement "DO", &proc
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def controls_repeat_ext(&proc)
|
21
|
+
@blocks << BlocklyInterpreter::CoreBlocks::RepeatTimesBlock::DSLMethods::RepeatBlockBuilder.new("controls_repeat_ext").tap do |builder|
|
22
|
+
builder.instance_exec(&proc)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def repeat_times(n, &proc)
|
27
|
+
controls_repeat_ext do
|
28
|
+
times { math_number n }
|
29
|
+
action &proc
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::SetVariableBlock < BlocklyInterpreter::Block
|
2
|
+
include BlocklyInterpreter::DSLGenerator
|
3
|
+
|
4
|
+
self.block_type = :variables_set
|
5
|
+
|
6
|
+
def execute_statement(execution_context)
|
7
|
+
execution_context.set_variable(fields['VAR'], values['VALUE'].value(execution_context))
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_dsl
|
11
|
+
method_call_with_possible_block("variables_set", fields['VAR'].inspect, values['VALUE'])
|
12
|
+
end
|
13
|
+
|
14
|
+
module DSLMethods
|
15
|
+
def variables_set(name, &proc)
|
16
|
+
block :variables_set do
|
17
|
+
field :VAR, name
|
18
|
+
value :VALUE do
|
19
|
+
instance_exec &proc
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::TextBlock < BlocklyInterpreter::Block
|
2
|
+
self.block_type = :text
|
3
|
+
|
4
|
+
def text
|
5
|
+
fields['TEXT']
|
6
|
+
end
|
7
|
+
|
8
|
+
def value(execution_context)
|
9
|
+
text
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_dsl
|
13
|
+
"text #{text.inspect}"
|
14
|
+
end
|
15
|
+
|
16
|
+
module DSLMethods
|
17
|
+
def text(content)
|
18
|
+
block :text do
|
19
|
+
field :TEXT, content
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::TextChangeCaseBlock < BlocklyInterpreter::Block
|
2
|
+
include BlocklyInterpreter::DSLGenerator
|
3
|
+
self.block_type = :text_changeCase
|
4
|
+
|
5
|
+
def destination_case
|
6
|
+
fields['CASE']
|
7
|
+
end
|
8
|
+
|
9
|
+
def value(execution_context)
|
10
|
+
text = values['TEXT'].value(execution_context).to_s
|
11
|
+
|
12
|
+
case destination_case
|
13
|
+
when 'UPPERCASE' then text.upcase
|
14
|
+
when 'LOWERCASE' then text.downcase
|
15
|
+
when 'TITLECASE' then text.titleize
|
16
|
+
else raise "Unknown case: #{destination_case.inspect}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_dsl
|
21
|
+
method_call_with_possible_block "text_change_case", destination_case.inspect, values['TEXT']
|
22
|
+
end
|
23
|
+
|
24
|
+
module DSLMethods
|
25
|
+
def text_change_case(destination_case, &proc)
|
26
|
+
block :text_changeCase do
|
27
|
+
field :CASE, destination_case
|
28
|
+
value :TEXT, &proc
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class BlocklyInterpreter::CoreBlocks::TextJoinBlock < BlocklyInterpreter::Block
|
2
|
+
include BlocklyInterpreter::DSLGenerator
|
3
|
+
self.block_type = :text_join
|
4
|
+
|
5
|
+
def item_count
|
6
|
+
@item_count ||= mutation.try(:[], 'items').try(:to_i) || 0
|
7
|
+
end
|
8
|
+
|
9
|
+
def value(execution_context)
|
10
|
+
(0...item_count).map { |i| values["ADD#{i}"].value(execution_context) }.join
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_dsl
|
14
|
+
item_dsls = (0...item_count).map do |i|
|
15
|
+
method_call_with_block_or_nothing("item", "", values["ADD#{i}"])
|
16
|
+
end.compact
|
17
|
+
|
18
|
+
method_call_with_possible_block("text_join", "", item_dsls)
|
19
|
+
end
|
20
|
+
|
21
|
+
module DSLMethods
|
22
|
+
class TextJoinBlockBuilder < BlocklyInterpreter::DSL::BlockBuilder
|
23
|
+
def initialize(block_type)
|
24
|
+
super
|
25
|
+
@item_number = 0
|
26
|
+
end
|
27
|
+
|
28
|
+
def item(string = nil, &proc)
|
29
|
+
proc ||= Proc.new { text string }
|
30
|
+
value("ADD#{@item_number}", &proc)
|
31
|
+
@item_number += 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_xml(node)
|
35
|
+
mutation_attr("items", @item_number)
|
36
|
+
super
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def text_join(*strings, &proc)
|
41
|
+
@blocks << BlocklyInterpreter::CoreBlocks::TextJoinBlock::DSLMethods::TextJoinBlockBuilder.new('text_join').tap do |builder|
|
42
|
+
strings.each do |string|
|
43
|
+
builder.item string
|
44
|
+
end
|
45
|
+
|
46
|
+
builder.instance_exec(&proc) if proc
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|