dtr_to_rust 0.2.10 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/aggregator/scope_block_aggregator.rb +72 -0
- data/lib/common/input_interpreter.rb +12 -1
- data/lib/common/reference_appender.rb +59 -0
- data/lib/common/type_translator.rb +22 -0
- data/lib/dtr_to_rust.rb +34 -4
- data/lib/generator.rb +105 -32
- data/lib/instruction/add.rb +12 -0
- data/lib/instruction/and.rb +19 -0
- data/lib/instruction/assign.rb +16 -0
- data/lib/instruction/divide.rb +12 -0
- data/lib/instruction/end_of_iteration_check.rb +11 -0
- data/lib/instruction/evaluate.rb +92 -17
- data/lib/instruction/exit_with_message.rb +18 -0
- data/lib/instruction/field.rb +3 -3
- data/lib/instruction/goto.rb +12 -0
- data/lib/instruction/handler.rb +11 -7
- data/lib/instruction/increment.rb +11 -0
- data/lib/instruction/instantiate_object.rb +78 -0
- data/lib/instruction/jump.rb +28 -0
- data/lib/instruction/label.rb +12 -0
- data/lib/instruction/multiply.rb +12 -0
- data/lib/instruction/or.rb +19 -0
- data/lib/instruction/{log_string.rb → print.rb} +2 -2
- data/lib/instruction/return.rb +1 -1
- data/lib/instruction/subtract.rb +13 -0
- data/lib/instruction_handler.rb +34 -18
- data/lib/optimization/binary_x_to_self_assignment_reduction.rb +93 -0
- data/lib/optimization/chained_invocation_assignment_reduction.rb +123 -0
- data/lib/optimization/field_to_assignment_conversion.rb +37 -0
- data/lib/user_defined_types/handler.rb +78 -0
- metadata +25 -7
- data/lib/instruction/add_and_assign.rb +0 -12
- data/lib/instruction/create_list.rb +0 -31
- data/lib/instruction/initialize_udt.rb +0 -22
data/lib/instruction/field.rb
CHANGED
@@ -5,17 +5,17 @@ module DTRToRust
|
|
5
5
|
# This class is responsible for generating Rust code for the Field instruction.
|
6
6
|
class Field < Handler
|
7
7
|
def handle
|
8
|
-
form_rust_string("#{handle_field_assign}#{handle_field_call}"
|
8
|
+
form_rust_string("#{handle_field_assign}#{handle_field_call}")
|
9
9
|
end
|
10
10
|
|
11
11
|
private
|
12
12
|
|
13
13
|
def handle_field_call
|
14
|
-
"#{@instruction
|
14
|
+
"#{@instruction.inputs[0]}.#{@instruction.inputs[1]};"
|
15
15
|
end
|
16
16
|
|
17
17
|
def handle_field_assign
|
18
|
-
"let mut #{@instruction
|
18
|
+
"let mut #{@instruction.assign} = " if @instruction.assign
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
data/lib/instruction/handler.rb
CHANGED
@@ -4,20 +4,24 @@ module DTRToRust
|
|
4
4
|
module Instruction
|
5
5
|
# This class is responsible for generating Rust code for the AddAndAssign instruction.
|
6
6
|
class Handler
|
7
|
-
def initialize(instruction)
|
7
|
+
def initialize(instruction, spacing_scope, function_names, user_defined_types, is_helper)
|
8
8
|
@instruction = instruction
|
9
|
+
@spacing_scope = spacing_scope
|
10
|
+
@function_names = function_names
|
11
|
+
@user_defined_types = user_defined_types
|
12
|
+
@is_helper = is_helper
|
9
13
|
end
|
10
14
|
|
11
|
-
def self.handle(instruction)
|
12
|
-
new(instruction).handle
|
15
|
+
def self.handle(instruction, spacing_scope, function_names, user_defined_types, is_helper)
|
16
|
+
new(instruction, spacing_scope, function_names, user_defined_types, is_helper).handle
|
13
17
|
end
|
14
18
|
|
15
|
-
def spacing
|
16
|
-
'
|
19
|
+
def spacing
|
20
|
+
' ' * (@is_helper ? 1 : @spacing_scope + 2)
|
17
21
|
end
|
18
22
|
|
19
|
-
def form_rust_string(instruction_string
|
20
|
-
"#{spacing
|
23
|
+
def form_rust_string(instruction_string)
|
24
|
+
"#{spacing}#{instruction_string}"
|
21
25
|
end
|
22
26
|
end
|
23
27
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module Instruction
|
5
|
+
# This class is responsible for generating Rust code for the LogString instruction.
|
6
|
+
class InstantiateObject < Handler
|
7
|
+
def handle
|
8
|
+
case @instruction.inputs[0]
|
9
|
+
when 'List'
|
10
|
+
handle_list
|
11
|
+
when 'UDT'
|
12
|
+
handle_udt
|
13
|
+
when 'Tuple'
|
14
|
+
form_rust_string("let mut #{@instruction.assign} = (#{normalish_inputs});")
|
15
|
+
else
|
16
|
+
raise "Unknown object type: #{@instruction.inputs[0]}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def handle_list
|
23
|
+
form_rust_string("let mut #{@instruction.assign} = vec![#{normalish_inputs}];")
|
24
|
+
end
|
25
|
+
|
26
|
+
def normalish_inputs
|
27
|
+
@instruction.inputs[1..].map do |x|
|
28
|
+
foobar(x)
|
29
|
+
end.join(', ')
|
30
|
+
end
|
31
|
+
|
32
|
+
def udt_name_fix(udt)
|
33
|
+
if udt.name.end_with?('_STRUCT') || udt.name.end_with?('_ENUM')
|
34
|
+
udt.name.split('_')[0..-2].join('_')
|
35
|
+
else
|
36
|
+
udt.name
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def handle_udt
|
41
|
+
udt_found = @user_defined_types.filter { |udt| udt_name_fix(udt) == @instruction.inputs[1] }
|
42
|
+
|
43
|
+
assignment = "let mut #{@instruction.assign} = "
|
44
|
+
udt = "#{@instruction.inputs[1]}{"
|
45
|
+
inputs = inputs_to_rust_string(@instruction.inputs[2..], udt_found[0].attributes.map { |x| x[:name] })
|
46
|
+
end_ = '};'
|
47
|
+
form_rust_string("#{assignment}#{udt}#{inputs}#{end_}")
|
48
|
+
end
|
49
|
+
|
50
|
+
def inputs_to_rust_string(inputs, udt_type_names)
|
51
|
+
inputs_to_return = []
|
52
|
+
inputs.each_with_index do |input, index|
|
53
|
+
inputs_to_return << handle_input(input, udt_type_names[index])
|
54
|
+
end
|
55
|
+
|
56
|
+
inputs_to_return.join(', ')
|
57
|
+
end
|
58
|
+
|
59
|
+
def foobar(input)
|
60
|
+
decorated_input = Common::InputInterpreter.interpret(input)
|
61
|
+
|
62
|
+
if decorated_input[:type] == 'string'
|
63
|
+
"symbol_short!(#{input})"
|
64
|
+
elsif decorated_input[:needs_reference] && input == 'env'
|
65
|
+
"&#{input}"
|
66
|
+
else
|
67
|
+
input
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def handle_input(input, udt_type_name)
|
72
|
+
value = foobar(input)
|
73
|
+
|
74
|
+
"#{udt_type_name}: #{value}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module Instruction
|
5
|
+
# This class handles the jump instruction.
|
6
|
+
class Jump < Handler
|
7
|
+
def handle
|
8
|
+
if @instruction.inputs.size == 1
|
9
|
+
handle_unconditional_jump
|
10
|
+
elsif @instruction.inputs.size == 2
|
11
|
+
handle_conditional_jump
|
12
|
+
else
|
13
|
+
raise 'Invalid jump instruction'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def handle_conditional_jump
|
20
|
+
form_rust_string("if #{@instruction.inputs[0]} {")
|
21
|
+
end
|
22
|
+
|
23
|
+
def handle_unconditional_jump
|
24
|
+
form_rust_string('else {')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module Instruction
|
5
|
+
# This class handles the add instruction.
|
6
|
+
class Multiply < Handler
|
7
|
+
def handle
|
8
|
+
form_rust_string("#{@instruction.assign} = #{@instruction.inputs[0]} * #{@instruction.inputs[1]};")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module Instruction
|
5
|
+
# This class handles the or instruction.
|
6
|
+
class Or < Handler
|
7
|
+
def handle
|
8
|
+
inputs = @instruction.inputs
|
9
|
+
assignment = @instruction.assign
|
10
|
+
|
11
|
+
assignment_rust = "let #{assignment} = "
|
12
|
+
body_rust = "#{inputs[0]} || #{inputs[1]};"
|
13
|
+
rust_string = "#{assignment.nil? ? '' : assignment_rust}#{body_rust}"
|
14
|
+
|
15
|
+
form_rust_string(rust_string)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -3,9 +3,9 @@
|
|
3
3
|
module DTRToRust
|
4
4
|
module Instruction
|
5
5
|
# This class is responsible for generating Rust code for the LogString instruction.
|
6
|
-
class
|
6
|
+
class Print < Handler
|
7
7
|
def handle
|
8
|
-
form_rust_string("log!(#{inputs_to_rust_string(@instruction
|
8
|
+
form_rust_string("log!(#{inputs_to_rust_string(@instruction.inputs)});")
|
9
9
|
end
|
10
10
|
|
11
11
|
private
|
data/lib/instruction/return.rb
CHANGED
@@ -5,7 +5,7 @@ module DTRToRust
|
|
5
5
|
# This class is responsible for generating Rust code for the Return instruction.
|
6
6
|
class Return < Handler
|
7
7
|
def handle
|
8
|
-
form_rust_string(@instruction
|
8
|
+
form_rust_string(@instruction.inputs[0])
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module Instruction
|
5
|
+
# This class handles the add instruction.
|
6
|
+
class Subtract < Handler
|
7
|
+
def handle
|
8
|
+
# TODO: fix this, depends if this is init or not
|
9
|
+
form_rust_string("#{@instruction.assign} = #{@instruction.inputs[0]} - #{@instruction.inputs[1]};")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/instruction_handler.rb
CHANGED
@@ -3,33 +3,49 @@
|
|
3
3
|
module DTRToRust
|
4
4
|
# This class is responsible for generating Rust code for a single instruction.
|
5
5
|
class InstructionHandler
|
6
|
-
def initialize(instruction)
|
6
|
+
def initialize(instruction, spacing_scope, function_names, user_defined_types, is_helper)
|
7
7
|
@instruction = instruction
|
8
|
+
@spacing_scope = spacing_scope
|
9
|
+
@function_names = function_names
|
10
|
+
@user_defined_types = user_defined_types
|
11
|
+
@is_helper = is_helper
|
8
12
|
end
|
9
13
|
|
10
14
|
def generate_rust
|
11
|
-
|
12
|
-
|
13
|
-
Instruction::Return.handle(@instruction)
|
14
|
-
when 'log_string'
|
15
|
-
Instruction::LogString.handle(@instruction)
|
16
|
-
when 'add_and_assign'
|
17
|
-
Instruction::AddAndAssign.handle(@instruction)
|
18
|
-
when 'evaluate'
|
19
|
-
Instruction::Evaluate.handle(@instruction)
|
20
|
-
when 'create_list'
|
21
|
-
Instruction::CreateList.handle(@instruction)
|
22
|
-
when 'field'
|
23
|
-
Instruction::Field.handle(@instruction)
|
24
|
-
when 'initialize_udt'
|
25
|
-
Instruction::InitializeUDT.handle(@instruction)
|
26
|
-
else
|
27
|
-
raise "Unknown instruction type: #{@instruction[:instruction]}"
|
15
|
+
unless EXPRESSION_FOOBAR.key?(@instruction.instruction.strip)
|
16
|
+
raise "Unknown instruction type: #{@instruction.instruction}"
|
28
17
|
end
|
18
|
+
|
19
|
+
EXPRESSION_FOOBAR[@instruction.instruction.strip].send(:handle, @instruction, @spacing_scope, @function_names,
|
20
|
+
@user_defined_types, @is_helper)
|
29
21
|
end
|
30
22
|
|
31
23
|
private
|
32
24
|
|
25
|
+
EXPRESSION_FOOBAR = {
|
26
|
+
'assign' => Instruction::Assign,
|
27
|
+
'jump' => Instruction::Jump,
|
28
|
+
'goto' => Instruction::Goto,
|
29
|
+
'exit_with_message' => Instruction::ExitWithMessage,
|
30
|
+
'and' => Instruction::And,
|
31
|
+
'or' => Instruction::Or,
|
32
|
+
'label' => Instruction::Label,
|
33
|
+
'add' => Instruction::Add,
|
34
|
+
'subtract' => Instruction::Subtract,
|
35
|
+
'multiply' => Instruction::Multiply,
|
36
|
+
'divide' => Instruction::Divide,
|
37
|
+
'instantiate_object' => Instruction::InstantiateObject,
|
38
|
+
'print' => Instruction::Print,
|
39
|
+
'return' => Instruction::Return,
|
40
|
+
'evaluate' => Instruction::Evaluate,
|
41
|
+
'field' => Instruction::Field,
|
42
|
+
'end_of_iteration_check' => Instruction::EndOfIterationCheck,
|
43
|
+
'increment' => Instruction::Increment
|
44
|
+
}.freeze
|
45
|
+
|
46
|
+
def handle_empty_instruction
|
47
|
+
''
|
48
|
+
end
|
33
49
|
attr_reader :instruction
|
34
50
|
end
|
35
51
|
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module Optimization
|
5
|
+
# This class is responsible for reducing binary operations that assign the result to the same variable
|
6
|
+
class BinaryXToSelfAssignmentReduction
|
7
|
+
def initialize(instructions)
|
8
|
+
@instructions = instructions
|
9
|
+
@cur_instruction = nil
|
10
|
+
@optimized_instructions = []
|
11
|
+
@memoize_assigns = {}
|
12
|
+
@to_remove = {}
|
13
|
+
@last_was_eavluate = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.apply(instructions)
|
17
|
+
new(instructions).apply
|
18
|
+
end
|
19
|
+
|
20
|
+
def apply
|
21
|
+
@instructions.each_with_index do |instruction, index|
|
22
|
+
@cur_instruction = instruction
|
23
|
+
|
24
|
+
if skip_instruction?
|
25
|
+
@optimized_instructions << @cur_instruction
|
26
|
+
next unless @cur_instruction.assign && @cur_instruction.assign == @cur_instruction.assign.upcase
|
27
|
+
|
28
|
+
@memoize_assigns[@cur_instruction.assign] = {
|
29
|
+
inputs: @cur_instruction.inputs,
|
30
|
+
index:
|
31
|
+
}
|
32
|
+
next
|
33
|
+
end
|
34
|
+
|
35
|
+
apply_to_instruction(index)
|
36
|
+
end
|
37
|
+
actually_optimized_instructions = []
|
38
|
+
@optimized_instructions.each_with_index do |instruction, index|
|
39
|
+
actually_optimized_instructions << instruction unless @to_remove[index]
|
40
|
+
end
|
41
|
+
|
42
|
+
actually_optimized_instructions
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def skip_instruction?
|
48
|
+
!%w[add subtract divide multiply].include?(@cur_instruction.instruction)
|
49
|
+
end
|
50
|
+
|
51
|
+
def apply_to_instruction(index)
|
52
|
+
match_on0 = @cur_instruction.inputs[0] == @cur_instruction.assign
|
53
|
+
match_on1 = @cur_instruction.inputs[1] == @cur_instruction.assign
|
54
|
+
|
55
|
+
unless @cur_instruction.inputs.length == 2 &&
|
56
|
+
(match_on1 || match_on0)
|
57
|
+
|
58
|
+
@optimized_instructions << @cur_instruction
|
59
|
+
return
|
60
|
+
end
|
61
|
+
|
62
|
+
optimized_inputs = []
|
63
|
+
|
64
|
+
if @memoize_assigns[@cur_instruction.inputs[0]]
|
65
|
+
optimized_inputs << @memoize_assigns[@cur_instruction.inputs[0]][:inputs]
|
66
|
+
@to_remove[@memoize_assigns[@cur_instruction.inputs[0]][:index]] = true
|
67
|
+
else
|
68
|
+
optimized_inputs << @cur_instruction.inputs[0]
|
69
|
+
end
|
70
|
+
|
71
|
+
if @memoize_assigns[@cur_instruction.inputs[1]]
|
72
|
+
optimized_inputs << @memoize_assigns[@cur_instruction.inputs[1]][:inputs]
|
73
|
+
@to_remove[@memoize_assigns[@cur_instruction.inputs[1]][:index]] = true
|
74
|
+
else
|
75
|
+
optimized_inputs << @cur_instruction.inputs[1]
|
76
|
+
end
|
77
|
+
|
78
|
+
optimized_inputs.flatten!
|
79
|
+
assignment = match_on0 ? optimized_inputs[0] : optimized_inputsinputs[1]
|
80
|
+
|
81
|
+
@optimized_instructions << DTRCore::Instruction.new(@cur_instruction.instruction, optimized_inputs, assignment,
|
82
|
+
@cur_instruction.scope)
|
83
|
+
|
84
|
+
return unless @cur_instruction.assign && @cur_instruction.assign == @cur_instruction.assign.upcase
|
85
|
+
|
86
|
+
@memoize_assigns[@cur_instruction.assign] = {
|
87
|
+
inputs: optimized_inputs,
|
88
|
+
index:
|
89
|
+
}
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module Optimization
|
5
|
+
# Optimizes the instructions by reducing chained invocation assignments
|
6
|
+
class ChainedInvocationAssignmentReduction
|
7
|
+
def initialize(instructions)
|
8
|
+
@instructions = instructions
|
9
|
+
@cur_instruction = nil
|
10
|
+
@optimized_instructions = []
|
11
|
+
@memoize_assigns = {}
|
12
|
+
@to_remove = {}
|
13
|
+
@last_was_eavluate = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def apply
|
17
|
+
@instructions.each_with_index do |instruction, index|
|
18
|
+
@cur_instruction = instruction
|
19
|
+
|
20
|
+
if skip_instruction?
|
21
|
+
@optimized_instructions << @cur_instruction
|
22
|
+
next
|
23
|
+
end
|
24
|
+
|
25
|
+
apply_to_instruction(index)
|
26
|
+
end
|
27
|
+
actually_optimized_instructions = []
|
28
|
+
@optimized_instructions.each_with_index do |instruction, index|
|
29
|
+
actually_optimized_instructions << instruction unless @to_remove[index]
|
30
|
+
end
|
31
|
+
|
32
|
+
actually_optimized_instructions
|
33
|
+
end
|
34
|
+
|
35
|
+
def skip_instruction?
|
36
|
+
@cur_instruction.instruction == 'instantiate_object'
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.apply(instructions)
|
40
|
+
new(instructions).apply
|
41
|
+
end
|
42
|
+
|
43
|
+
def apply_to_instruction(index)
|
44
|
+
@optimized_inputs = []
|
45
|
+
|
46
|
+
@cur_instruction&.inputs&.each do |input|
|
47
|
+
apply_to_instruction_input(@cur_instruction, input)
|
48
|
+
end
|
49
|
+
@optimized_instructions << DTRCore::Instruction.new(@cur_instruction.instruction, @optimized_inputs,
|
50
|
+
@cur_instruction&.assign, @cur_instruction.scope)
|
51
|
+
|
52
|
+
@memoize_assigns = {} unless clear_memoize?
|
53
|
+
return unless @cur_instruction.assign && @cur_instruction.assign == @cur_instruction.assign.upcase && !%w[
|
54
|
+
add subtract multiply divide
|
55
|
+
].include?(@cur_instruction.instruction)
|
56
|
+
|
57
|
+
@memoize_assigns[@cur_instruction.assign] = {
|
58
|
+
inputs: @optimized_inputs,
|
59
|
+
index:
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
def clear_memoize?
|
64
|
+
if @last_was_eavluate.nil?
|
65
|
+
@last_was_eavluate = @cur_instruction.instruction == 'evaluate'
|
66
|
+
return false
|
67
|
+
end
|
68
|
+
|
69
|
+
if @cur_instruction.instruction == 'evaluate'
|
70
|
+
if @last_was_eavluate
|
71
|
+
false
|
72
|
+
else
|
73
|
+
@last_was_eavluate = true
|
74
|
+
true
|
75
|
+
end
|
76
|
+
elsif @last_was_eavluate
|
77
|
+
@last_was_eavluate = false
|
78
|
+
true
|
79
|
+
else
|
80
|
+
false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def apply_to_instruction_input(_instruction, input)
|
85
|
+
done_a_thing = false
|
86
|
+
memoize_assigns_to_clear = []
|
87
|
+
@memoize_assigns.each do |key, value|
|
88
|
+
next unless do_a_thing?(input, key, input.split('.')[0])
|
89
|
+
|
90
|
+
# input = input.gsub(key, "#{value[:inputs][0]}(#{value[:inputs][1..].join(', ')})")
|
91
|
+
|
92
|
+
input = input.gsub(key, evaluate_input(key, value).to_s)
|
93
|
+
@optimized_inputs << input # evaluate_input(key, value)
|
94
|
+
done_a_thing = true
|
95
|
+
@to_remove[value[:index]] = true
|
96
|
+
memoize_assigns_to_clear << key
|
97
|
+
next
|
98
|
+
end
|
99
|
+
|
100
|
+
@optimized_inputs << input unless done_a_thing
|
101
|
+
|
102
|
+
memoize_assigns_to_clear.each do |key|
|
103
|
+
@memoize_assigns.delete(key)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def evaluate_input(_key, input)
|
108
|
+
InstructionHandler.new(DTRCore::Instruction.new('evaluate', input[:inputs], nil, 0), 0, [], [],
|
109
|
+
false).generate_rust.strip.gsub(';', '')
|
110
|
+
end
|
111
|
+
|
112
|
+
def do_a_thing?(input, key, input_beginning)
|
113
|
+
input &&
|
114
|
+
key &&
|
115
|
+
input_beginning == key &&
|
116
|
+
!(input.start_with?('"') &&
|
117
|
+
input.end_with?('"')) &&
|
118
|
+
@cur_instruction.instruction == 'evaluate' &&
|
119
|
+
!['equal_to', '!'].include?(@cur_instruction)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module Optimization
|
5
|
+
# This class is responsible for converting field instructions to assignment instructions
|
6
|
+
class FieldToAssignmentConversion
|
7
|
+
def initialize(instructions)
|
8
|
+
@instructions = instructions
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.apply(instructions)
|
12
|
+
new(instructions).apply
|
13
|
+
end
|
14
|
+
|
15
|
+
def apply
|
16
|
+
@instructions.map do |instruction|
|
17
|
+
next instruction if skip_instruction?(instruction)
|
18
|
+
|
19
|
+
apply_to_instruction(instruction)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def skip_instruction?(instruction)
|
26
|
+
instruction.instruction != 'field'
|
27
|
+
end
|
28
|
+
|
29
|
+
def apply_to_instruction(instruction)
|
30
|
+
return instruction unless instruction.inputs.length == 2
|
31
|
+
|
32
|
+
DTRCore::Instruction.new('assign', ["#{instruction.inputs[0]}.#{instruction.inputs[1]}"], instruction.assign,
|
33
|
+
instruction.scope)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module UserDefinedTypes
|
5
|
+
class Handler
|
6
|
+
def initialize(user_defined_type)
|
7
|
+
@user_defined_type = user_defined_type
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.generate(user_defined_type)
|
11
|
+
new(user_defined_type).generate
|
12
|
+
end
|
13
|
+
|
14
|
+
def generate
|
15
|
+
if struct?
|
16
|
+
generate_struct
|
17
|
+
elsif enum?
|
18
|
+
generate_enum
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def generate_struct
|
23
|
+
"#{derives}pub struct #{@user_defined_type.name.gsub('_STRUCT', '')} {\n#{generate_struct_attributes}\n}\n\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
def generate_struct_attributes
|
27
|
+
@user_defined_type.attributes.map do |x|
|
28
|
+
" pub #{x[:name]}: #{Common::TypeTranslator.translate_type(x[:type])},"
|
29
|
+
end.join("\n")
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate_enum
|
33
|
+
"#{derives}pub enum #{@user_defined_type.name.gsub('_ENUM', '')} {\n#{generate_enum_attributes}\n}\n\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate_enum_attributes
|
37
|
+
@user_defined_type.attributes.map do |x|
|
38
|
+
if x[:value]
|
39
|
+
" #{x[:name]} = #{x[:value]},"
|
40
|
+
elsif x[:type] && x[:type] != '()'
|
41
|
+
" #{x[:name]}(#{Common::TypeTranslator.translate_type(x[:type])}),"
|
42
|
+
else
|
43
|
+
" #{x[:name]},"
|
44
|
+
end
|
45
|
+
end.join("\n")
|
46
|
+
end
|
47
|
+
|
48
|
+
def derives
|
49
|
+
base = if error? && enum?
|
50
|
+
"#[contracterror]\n#[derive(Clone, Debug, Eq, PartialEq)]\n"
|
51
|
+
else
|
52
|
+
"#[contracttype]\n#[derive(Clone, Debug, Eq, PartialEq)]\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
base += "#[repr(u32)]\n" if numbered_enum?
|
56
|
+
|
57
|
+
base
|
58
|
+
end
|
59
|
+
|
60
|
+
# TODO: fix this terrible hack
|
61
|
+
def error?
|
62
|
+
@user_defined_type.name.start_with? 'Error'
|
63
|
+
end
|
64
|
+
|
65
|
+
def struct?
|
66
|
+
@user_defined_type.name.end_with? '_STRUCT'
|
67
|
+
end
|
68
|
+
|
69
|
+
def enum?
|
70
|
+
@user_defined_type.name.end_with? '_ENUM'
|
71
|
+
end
|
72
|
+
|
73
|
+
def numbered_enum?
|
74
|
+
enum? && @user_defined_type.attributes.all? { |x| x[:value] }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|