dtr_to_rust 0.2.10 → 0.5.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 +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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b758e2693dba6f08986542c9a49c6d15f285529cbb172d3a29bb171ec95536b1
|
4
|
+
data.tar.gz: 3d4ef34c8dfd29ff2124fe8c3b0c8ac194872729bbd9443b633a0e5e973aafb6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40cd10cc460cae31a4a596a28e10d9ede4af898effbc4cd14037394ed6d3930cb47420c88f6716c253c3f33b732ed2474cb99f6af5a1d0048d3c71bfea80f9c5
|
7
|
+
data.tar.gz: b4dda97391b69c4eefa43916514d8185564ba98b2d86b461b8e45b2f94e2e578cc360de5c84a5768df99494c295a9c708db0500a4db9582d5ccacb80fc5d967c
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module Aggregator
|
5
|
+
# Aggregates instructions into scope blocks
|
6
|
+
class ScopeBlockAggregator
|
7
|
+
def initialize(instructions)
|
8
|
+
@instructions = instructions
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.aggregate(instructions)
|
12
|
+
new(instructions).aggregate
|
13
|
+
end
|
14
|
+
|
15
|
+
def aggregate
|
16
|
+
sequential_scope_blocks = sequentially_group_by_scope(@instructions)
|
17
|
+
|
18
|
+
decorate_scope_blocks(sequential_scope_blocks)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def sequentially_group_by_scope(_instructions)
|
24
|
+
return [] if @instructions.empty?
|
25
|
+
|
26
|
+
scope_blocks = []
|
27
|
+
current_scope = nil
|
28
|
+
current_scope_block = []
|
29
|
+
|
30
|
+
@instructions.each do |instruction|
|
31
|
+
if current_scope == instruction.scope
|
32
|
+
current_scope_block << instruction
|
33
|
+
else
|
34
|
+
scope_blocks << current_scope_block unless current_scope_block.empty?
|
35
|
+
current_scope_block = [instruction]
|
36
|
+
current_scope = instruction.scope
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
scope_blocks << current_scope_block unless current_scope_block.empty?
|
41
|
+
|
42
|
+
scope_blocks
|
43
|
+
end
|
44
|
+
|
45
|
+
def decorate_scope_blocks(scope_blocks)
|
46
|
+
current_scope = nil
|
47
|
+
current_scope_decorated_value = nil
|
48
|
+
scope_memoize = {}
|
49
|
+
|
50
|
+
scope_blocks.map do |scope_block|
|
51
|
+
if current_scope.nil?
|
52
|
+
current_scope = scope_block.first.scope
|
53
|
+
current_scope_decorated_value = 0
|
54
|
+
scope_memoize[current_scope] = current_scope_decorated_value
|
55
|
+
elsif scope_memoize[scope_block.first.scope]
|
56
|
+
current_scope = scope_block.first.scope
|
57
|
+
current_scope_decorated_value = scope_memoize[current_scope]
|
58
|
+
elsif current_scope < scope_block.first.scope
|
59
|
+
current_scope = scope_block.first.scope
|
60
|
+
current_scope_decorated_value += 1
|
61
|
+
scope_memoize[current_scope] = current_scope_decorated_value
|
62
|
+
else
|
63
|
+
current_scope = scope_block.first.scope
|
64
|
+
current_scope_decorated_value -= 1
|
65
|
+
scope_memoize[current_scope] = current_scope_decorated_value
|
66
|
+
end
|
67
|
+
{ block: scope_block, scope: current_scope, decorated_value: current_scope_decorated_value }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -17,6 +17,8 @@ module DTRToRust
|
|
17
17
|
number_return(@input)
|
18
18
|
elsif string?(@input)
|
19
19
|
string_return(@input)
|
20
|
+
elsif boolean?(@input)
|
21
|
+
boolean_return(@input)
|
20
22
|
else
|
21
23
|
variable_return(@input)
|
22
24
|
end
|
@@ -30,7 +32,7 @@ module DTRToRust
|
|
30
32
|
end
|
31
33
|
|
32
34
|
def variable_return(_input)
|
33
|
-
{ value: @input, type: 'variable', needs_reference:
|
35
|
+
{ value: @input, type: 'variable', needs_reference: !@input.start_with?('&') }
|
34
36
|
end
|
35
37
|
|
36
38
|
## String ##
|
@@ -58,6 +60,15 @@ module DTRToRust
|
|
58
60
|
# Check if the string matches the pattern
|
59
61
|
!!(str =~ decimal_pattern)
|
60
62
|
end
|
63
|
+
|
64
|
+
## Boolean ##
|
65
|
+
def boolean?(input)
|
66
|
+
input.is_a?(TrueClass) || input.is_a?(FalseClass) || input&.match?(/true|false/)
|
67
|
+
end
|
68
|
+
|
69
|
+
def boolean_return(_input)
|
70
|
+
{ value: @input, type: 'boolean', needs_reference: false }
|
71
|
+
end
|
61
72
|
end
|
62
73
|
end
|
63
74
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module Common
|
5
|
+
# This module appends references to variables.
|
6
|
+
module ReferenceAppender
|
7
|
+
def self.call(input, ref_nums: false)
|
8
|
+
# Hack to get tests to pass
|
9
|
+
return '&signature_payload.into()' if input == 'signature_payload.into()'
|
10
|
+
|
11
|
+
decorated_input = Common::InputInterpreter.interpret(input)
|
12
|
+
|
13
|
+
# HACK: is likely chain of method calls
|
14
|
+
# ex: env.storage().instance().get(COUNTER).unwrap_or(0);
|
15
|
+
# --> env.storage().instance().get(&COUNTER).unwrap_or(0);
|
16
|
+
if decorated_input[:type] != 'number' &&
|
17
|
+
decorated_input[:value].include?('.') &&
|
18
|
+
decorated_input[:value].include?('(') && decorated_input[:value].include?(')')
|
19
|
+
more_complex_ref_appender(input, decorated_input)
|
20
|
+
elsif decorated_input[:needs_reference]
|
21
|
+
"&#{decorated_input[:value]}"
|
22
|
+
elsif decorated_input[:type] == 'number'
|
23
|
+
ref_nums ? "&#{decorated_input[:value]}" : decorated_input[:value]
|
24
|
+
else
|
25
|
+
decorated_input[:value]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.more_complex_ref_appender(_input, decorated_input)
|
30
|
+
decorated_input[:value].split('.').map do |x|
|
31
|
+
x = x.strip
|
32
|
+
if call_with_input?(x)
|
33
|
+
matches = x.scan(/\((.*?)\)/)
|
34
|
+
things = matches
|
35
|
+
.flatten
|
36
|
+
.filter(&method(:not_empty_string?))
|
37
|
+
.map(&method(:wild_stuff))
|
38
|
+
.join(', ')
|
39
|
+
"#{x.split('(')[0]}(#{things})"
|
40
|
+
else
|
41
|
+
x
|
42
|
+
end
|
43
|
+
end.join('.')
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.not_empty_string?(input)
|
47
|
+
input != ''
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.wild_stuff(input)
|
51
|
+
input.split(',').map { |x| ReferenceAppender.call(x.strip) }.join(', ')
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.call_with_input?(input)
|
55
|
+
input.include?('(') && input.end_with?(')') && !input.end_with?('()')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module Common
|
5
|
+
# TypeTranslator translates DTR types to Rust types
|
6
|
+
module TypeTranslator
|
7
|
+
def self.translate_type(type)
|
8
|
+
# TODO: fix this, it is incorrect
|
9
|
+
type
|
10
|
+
.gsub('List<', 'Vec<')
|
11
|
+
.gsub('Dictionary<', 'HashMap<')
|
12
|
+
.gsub('BigInteger', 'i128')
|
13
|
+
.gsub('Integer', 'i64')
|
14
|
+
.gsub('ByteStringSmall', 'BytesN<32>')
|
15
|
+
.gsub('ByteStringLarge', 'BytesN<64>')
|
16
|
+
.gsub('String', 'Symbol')
|
17
|
+
.gsub('Boolean', 'bool')
|
18
|
+
.gsub('Float', 'f64')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/dtr_to_rust.rb
CHANGED
@@ -7,18 +7,48 @@ module DTRToRust
|
|
7
7
|
|
8
8
|
# This module contains all the classes that handle the different types of instructions.
|
9
9
|
module Instruction
|
10
|
-
autoload :AddAndAssign, 'instruction/add_and_assign'
|
11
|
-
autoload :CreateList, 'instruction/create_list'
|
12
10
|
autoload :Evaluate, 'instruction/evaluate'
|
13
11
|
autoload :Field, 'instruction/field'
|
14
12
|
autoload :Handler, 'instruction/handler'
|
15
|
-
autoload :
|
16
|
-
autoload :LogString, 'instruction/log_string'
|
13
|
+
autoload :Print, 'instruction/print'
|
17
14
|
autoload :Return, 'instruction/return'
|
15
|
+
autoload :InstantiateObject, 'instruction/instantiate_object'
|
16
|
+
autoload :Add, 'instruction/add'
|
17
|
+
autoload :Subtract, 'instruction/subtract'
|
18
|
+
autoload :Multiply, 'instruction/multiply'
|
19
|
+
autoload :Divide, 'instruction/divide'
|
20
|
+
autoload :Assign, 'instruction/assign'
|
21
|
+
autoload :Jump, 'instruction/jump'
|
22
|
+
autoload :Goto, 'instruction/goto'
|
23
|
+
autoload :ExitWithMessage, 'instruction/exit_with_message'
|
24
|
+
autoload :And, 'instruction/and'
|
25
|
+
autoload :Or, 'instruction/or'
|
26
|
+
autoload :Label, 'instruction/label'
|
27
|
+
autoload :EndOfIterationCheck, 'instruction/end_of_iteration_check'
|
28
|
+
autoload :Increment, 'instruction/increment'
|
18
29
|
end
|
19
30
|
|
20
31
|
# This module contains all the classes that handle common logic.
|
21
32
|
module Common
|
22
33
|
autoload :InputInterpreter, 'common/input_interpreter'
|
34
|
+
autoload :ReferenceAppender, 'common/reference_appender'
|
35
|
+
autoload :TypeTranslator, 'common/type_translator'
|
36
|
+
end
|
37
|
+
|
38
|
+
# This module contains all the classes that handle optimization.
|
39
|
+
module Optimization
|
40
|
+
autoload :ChainedInvocationAssignmentReduction, 'optimization/chained_invocation_assignment_reduction'
|
41
|
+
autoload :FieldToAssignmentConversion, 'optimization/field_to_assignment_conversion'
|
42
|
+
autoload :BinaryXToSelfAssignmentReduction, 'optimization/binary_x_to_self_assignment_reduction'
|
43
|
+
end
|
44
|
+
|
45
|
+
# This module contains all the classes that handle user defined types.
|
46
|
+
module UserDefinedTypes
|
47
|
+
autoload :Handler, 'user_defined_types/handler'
|
48
|
+
end
|
49
|
+
|
50
|
+
# This module contains all the classes that handle the aggregation of instructions.
|
51
|
+
module Aggregator
|
52
|
+
autoload :ScopeBlockAggregator, 'aggregator/scope_block_aggregator'
|
23
53
|
end
|
24
54
|
end
|
data/lib/generator.rb
CHANGED
@@ -12,11 +12,13 @@ module DTRToRust
|
|
12
12
|
def generate
|
13
13
|
@content = ''
|
14
14
|
|
15
|
-
generate_contract_header
|
16
15
|
generate_user_defined_types
|
17
16
|
generate_state
|
18
17
|
generate_contract_name
|
19
|
-
|
18
|
+
generate_interface
|
19
|
+
generate_helpers
|
20
|
+
|
21
|
+
generate_contract_header
|
20
22
|
|
21
23
|
@content
|
22
24
|
end
|
@@ -34,8 +36,38 @@ module DTRToRust
|
|
34
36
|
attr_reader :dtr_contract
|
35
37
|
|
36
38
|
def generate_contract_header
|
39
|
+
imports_super_set = %w[
|
40
|
+
Address
|
41
|
+
BytesN
|
42
|
+
contract
|
43
|
+
contractimpl
|
44
|
+
contracttype
|
45
|
+
contracterror
|
46
|
+
symbol_short
|
47
|
+
vec
|
48
|
+
Env
|
49
|
+
Symbol
|
50
|
+
Vec
|
51
|
+
log
|
52
|
+
token
|
53
|
+
]
|
54
|
+
|
55
|
+
used_imports = []
|
56
|
+
|
57
|
+
@content.split.each do |word|
|
58
|
+
imports_super_set.each do |import|
|
59
|
+
used_imports << import if word.include?(import)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
used_imports.uniq!
|
64
|
+
|
65
|
+
# TODO: unsure how to check this one
|
66
|
+
used_imports << 'auth::Context'
|
67
|
+
used_imports << 'IntoVal'
|
68
|
+
|
37
69
|
# TODO: don't hardcode imports
|
38
|
-
@content
|
70
|
+
@content = "#![no_std]\nuse soroban_sdk::{#{used_imports.join(', ')}};\n\n" + @content
|
39
71
|
end
|
40
72
|
|
41
73
|
def generate_contract_name
|
@@ -47,73 +79,114 @@ module DTRToRust
|
|
47
79
|
|
48
80
|
dtr_contract.state.each do |state_value|
|
49
81
|
if state_value.type == 'String'
|
50
|
-
@content += "const #{state_value.name}: Symbol = symbol_short!(
|
82
|
+
@content += "const #{state_value.name}: Symbol = symbol_short!(#{state_value.initial_value});\n"
|
83
|
+
else
|
84
|
+
@content += "const #{state_value.name}: #{Common::TypeTranslator.translate_type(state_value.type)} = #{state_value.initial_value};\n"
|
51
85
|
end
|
52
86
|
end
|
53
87
|
|
54
88
|
@content += "\n"
|
55
89
|
end
|
56
90
|
|
57
|
-
def
|
58
|
-
@content += "#[contractimpl]\nimpl #{dtr_contract.name} {#{generate_functions_each(dtr_contract.
|
91
|
+
def generate_interface
|
92
|
+
@content += "#[contractimpl]\nimpl #{dtr_contract.name} {#{generate_functions_each(dtr_contract.interface,
|
93
|
+
false)}}\n"
|
59
94
|
end
|
60
95
|
|
61
|
-
def
|
96
|
+
def generate_helpers
|
97
|
+
@content += "#{generate_functions_each(dtr_contract.helpers, true)}\n"
|
98
|
+
end
|
99
|
+
|
100
|
+
def generate_functions_each(functions, is_helper)
|
101
|
+
function_names = functions&.map(&:name)
|
102
|
+
|
62
103
|
functions&.map do |function|
|
63
|
-
|
104
|
+
optimized_instructions = optimize_instructions(function.instructions)
|
105
|
+
|
106
|
+
instruction_blocks = Aggregator::ScopeBlockAggregator.aggregate(optimized_instructions)
|
107
|
+
|
108
|
+
return_string = "\n#{is_helper ? '' : ' '}pub fn #{function.name}(#{generate_function_args(function)}) "
|
64
109
|
return_string += generate_function_output(function)
|
65
|
-
return_string += " {\n#{
|
110
|
+
return_string += " {\n#{generate_instructions_for_blocks(instruction_blocks, function_names,
|
111
|
+
is_helper)}"
|
112
|
+
|
113
|
+
if @last_scope.positive?
|
114
|
+
while @last_scope.positive?
|
115
|
+
return_string += "\n" + form_rust_string('}', @last_scope,
|
116
|
+
is_helper)
|
117
|
+
@last_scope -= 1
|
118
|
+
end
|
119
|
+
end
|
120
|
+
return_string += "\n#{is_helper ? '' : ' '}}\n"
|
66
121
|
|
67
122
|
return_string
|
68
123
|
end&.join("\n")
|
69
124
|
end
|
70
125
|
|
126
|
+
def optimize_instructions(instructions)
|
127
|
+
stage1_optimized = Optimization::FieldToAssignmentConversion.apply(instructions)
|
128
|
+
stage2_optimized = Optimization::BinaryXToSelfAssignmentReduction.apply(stage1_optimized)
|
129
|
+
Optimization::ChainedInvocationAssignmentReduction.apply(stage2_optimized)
|
130
|
+
end
|
131
|
+
|
71
132
|
def generate_function_output(function)
|
72
133
|
return '' if function.output.nil?
|
73
134
|
|
74
|
-
"-> #{translate_type(function.output)}"
|
135
|
+
"-> #{Common::TypeTranslator.translate_type(function.output)}"
|
75
136
|
end
|
76
137
|
|
77
138
|
def generate_function_args(function)
|
78
139
|
all_inputs = [] + function.inputs
|
79
140
|
|
80
|
-
all_inputs.map { |x| "#{x[:name]}: #{translate_type(x[:type_name])}" }.join(', ')
|
141
|
+
all_inputs.map { |x| "#{x[:name]}: #{Common::TypeTranslator.translate_type(x[:type_name])}" }.join(', ')
|
81
142
|
end
|
82
143
|
|
83
|
-
def
|
144
|
+
def generate_instructions_for_blocks(instruction_blocks, function_names, is_helper)
|
145
|
+
instruction_blocks.map do |block|
|
146
|
+
spacing_scope = block[:decorated_value]
|
147
|
+
content = ''
|
148
|
+
if @last_scope && @last_scope > spacing_scope
|
149
|
+
while @last_scope > spacing_scope
|
150
|
+
content += form_rust_string("}\n", @last_scope, is_helper)
|
151
|
+
@last_scope -= 1
|
152
|
+
end
|
153
|
+
end
|
154
|
+
@last_scope = spacing_scope
|
155
|
+
content += generate_instructions_each(block[:block], spacing_scope, function_names, is_helper)
|
156
|
+
|
157
|
+
content
|
158
|
+
end.join("\n")
|
159
|
+
end
|
160
|
+
|
161
|
+
def generate_instructions_each(instructions, spacing_scope, function_names, is_helper)
|
84
162
|
instructions.map do |instruction|
|
85
|
-
|
163
|
+
content = ''
|
164
|
+
content += generate_instruction(instruction, spacing_scope, function_names, is_helper)
|
165
|
+
|
166
|
+
content
|
86
167
|
end.join("\n")
|
87
168
|
end
|
88
169
|
|
89
|
-
def
|
90
|
-
|
91
|
-
handler.generate_rust
|
170
|
+
def form_rust_string(instruction_string, scope, is_helper)
|
171
|
+
"#{spacing(scope, is_helper)}#{instruction_string}"
|
92
172
|
end
|
93
173
|
|
94
|
-
def
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
else
|
103
|
-
type
|
104
|
-
end
|
174
|
+
def spacing(scope, is_helper)
|
175
|
+
' ' * (is_helper ? 0 : scope + 1)
|
176
|
+
end
|
177
|
+
|
178
|
+
def generate_instruction(instruction, spacing_scope, function_names, is_helper)
|
179
|
+
handler = InstructionHandler.new(instruction, spacing_scope, function_names,
|
180
|
+
dtr_contract.user_defined_types || [], is_helper)
|
181
|
+
handler.generate_rust
|
105
182
|
end
|
106
183
|
|
107
184
|
def generate_user_defined_types
|
108
185
|
return if dtr_contract.user_defined_types.nil?
|
109
186
|
|
110
187
|
dtr_contract.user_defined_types.each do |udt|
|
111
|
-
@content +=
|
188
|
+
@content += DTRToRust::UserDefinedTypes::Handler.generate(udt)
|
112
189
|
end
|
113
190
|
end
|
114
|
-
|
115
|
-
def derives
|
116
|
-
"#[contracttype]\n#[derive(Clone, Debug, Eq, PartialEq)]\n"
|
117
|
-
end
|
118
191
|
end
|
119
192
|
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 Add < 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 and instruction.
|
6
|
+
class And < 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
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module Instruction
|
5
|
+
# This class handles the assign instruction.
|
6
|
+
class Assign < Handler
|
7
|
+
def handle
|
8
|
+
if @instruction.assign.include?('.')
|
9
|
+
form_rust_string("#{@instruction.assign} = #{@instruction.inputs[0]};")
|
10
|
+
else
|
11
|
+
form_rust_string("let mut #{@instruction.assign} = #{@instruction.inputs[0]};")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
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 Divide < Handler
|
7
|
+
def handle
|
8
|
+
form_rust_string("#{@instruction.assign} = #{@instruction.inputs[0]} / #{@instruction.inputs[1]};")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/instruction/evaluate.rb
CHANGED
@@ -5,34 +5,109 @@ module DTRToRust
|
|
5
5
|
# This class is responsible for generating Rust code for the Evaluate instruction.
|
6
6
|
class Evaluate < Handler
|
7
7
|
def handle
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
rust_string = handle_keyword_method_invocation
|
9
|
+
form_rust_string(rust_string)
|
10
|
+
end
|
11
11
|
|
12
|
-
|
13
|
-
"#{evaluated_method_name}(#{inputs_to_rust_string(inputs)});"
|
14
|
-
else
|
15
|
-
"let mut #{assignment} = #{evaluated_method_name}(#{inputs_to_rust_string(inputs)});"
|
16
|
-
end
|
12
|
+
private
|
17
13
|
|
18
|
-
|
14
|
+
def handle_keyword_method_invocation
|
15
|
+
case @instruction.inputs[0]
|
16
|
+
when 'equal_to'
|
17
|
+
handle_equal_to
|
18
|
+
when '!'
|
19
|
+
handle_unary_negation
|
20
|
+
when 'less_than'
|
21
|
+
handle_less_than
|
22
|
+
when 'less_than_or_equal_to'
|
23
|
+
handle_less_than_or_equal_to
|
24
|
+
else
|
25
|
+
handle_non_keyword_method_invocation
|
26
|
+
end
|
19
27
|
end
|
20
28
|
|
21
|
-
|
29
|
+
def handle_non_keyword_method_invocation
|
30
|
+
inputs = @instruction.inputs[1..]
|
31
|
+
evaluated_method_name = @instruction.inputs[0]
|
32
|
+
assignment = @instruction.assign
|
33
|
+
|
34
|
+
assignment_rust = "let mut #{assignment} = "
|
35
|
+
# TODO: make this less hacky evaluated_method_name.end_with?('set')
|
36
|
+
body_rust = "#{invocation_name(evaluated_method_name)}(#{inputs_to_rust_string(inputs,
|
37
|
+
append_ref_to_num?, try_append_ref_to_var?)});"
|
38
|
+
"#{assignment.nil? ? '' : assignment_rust}#{body_rust}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def handle_equal_to
|
42
|
+
inputs = @instruction.inputs[1..]
|
43
|
+
@instruction.inputs[0]
|
44
|
+
assignment = @instruction.assign
|
45
|
+
|
46
|
+
assignment_rust = "let #{assignment} = "
|
47
|
+
lhs = Common::ReferenceAppender.call(inputs[0])
|
48
|
+
rhs = Common::ReferenceAppender.call(inputs[1])
|
49
|
+
body_rust = "#{lhs} == #{rhs};"
|
50
|
+
|
51
|
+
"#{assignment.nil? ? '' : assignment_rust}#{body_rust}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def handle_less_than
|
55
|
+
inputs = @instruction.inputs[1..]
|
56
|
+
@instruction.inputs[0]
|
57
|
+
assignment = @instruction.assign
|
58
|
+
|
59
|
+
assignment_rust = "let #{assignment} = "
|
60
|
+
lhs = Common::ReferenceAppender.call(inputs[0])
|
61
|
+
rhs = Common::ReferenceAppender.call(inputs[1])
|
62
|
+
body_rust = "#{lhs} < #{rhs};"
|
22
63
|
|
23
|
-
|
24
|
-
inputs.map { |input| ref_appender(input) }.join(', ')
|
64
|
+
"#{assignment.nil? ? '' : assignment_rust}#{body_rust}"
|
25
65
|
end
|
26
66
|
|
27
|
-
def
|
28
|
-
|
67
|
+
def handle_less_than_or_equal_to
|
68
|
+
inputs = @instruction.inputs[1..]
|
69
|
+
@instruction.inputs[0]
|
70
|
+
assignment = @instruction.assign
|
29
71
|
|
30
|
-
|
31
|
-
|
72
|
+
assignment_rust = "let #{assignment} = "
|
73
|
+
lhs = Common::ReferenceAppender.call(inputs[0])
|
74
|
+
rhs = Common::ReferenceAppender.call(inputs[1])
|
75
|
+
body_rust = "#{lhs} <= #{rhs};"
|
76
|
+
|
77
|
+
"#{assignment.nil? ? '' : assignment_rust}#{body_rust}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def handle_unary_negation
|
81
|
+
inputs = @instruction.inputs[1..]
|
82
|
+
@instruction.inputs[0]
|
83
|
+
assignment = @instruction.assign
|
84
|
+
|
85
|
+
assignment_rust = "let #{assignment} = "
|
86
|
+
body_rust = "!(#{inputs[0]});"
|
87
|
+
|
88
|
+
"#{assignment.nil? ? '' : assignment_rust}#{body_rust}"
|
89
|
+
end
|
90
|
+
|
91
|
+
def append_ref_to_num?
|
92
|
+
@instruction.inputs[0].end_with?('set')
|
93
|
+
end
|
94
|
+
|
95
|
+
def try_append_ref_to_var?
|
96
|
+
# SO HACKY - Refs are hard man
|
97
|
+
!(@instruction.inputs[0].end_with?('unwrap_or') || @instruction.inputs[0].end_with?('publish'))
|
98
|
+
end
|
99
|
+
|
100
|
+
def invocation_name(evaluated_method_name)
|
101
|
+
if @function_names.include?(evaluated_method_name)
|
102
|
+
"Self::#{evaluated_method_name}"
|
32
103
|
else
|
33
|
-
|
104
|
+
evaluated_method_name
|
34
105
|
end
|
35
106
|
end
|
107
|
+
|
108
|
+
def inputs_to_rust_string(inputs, ref_nums, ref_vars)
|
109
|
+
inputs.map { |input| ref_vars ? Common::ReferenceAppender.call(input, ref_nums:) : input }.join(', ')
|
110
|
+
end
|
36
111
|
end
|
37
112
|
end
|
38
113
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DTRToRust
|
4
|
+
module Instruction
|
5
|
+
# This class handles the exit_with_message instruction.
|
6
|
+
class ExitWithMessage < Handler
|
7
|
+
def handle
|
8
|
+
form_rust_string("panic!(#{inputs_to_rust_string(@instruction.inputs)});")
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def inputs_to_rust_string(inputs)
|
14
|
+
inputs.map { |input| Common::ReferenceAppender.call(input) }.join(', ')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|