blockly_interpreter 0.2.0
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 +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
|