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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/lib/aggregator/scope_block_aggregator.rb +72 -0
  3. data/lib/common/input_interpreter.rb +12 -1
  4. data/lib/common/reference_appender.rb +59 -0
  5. data/lib/common/type_translator.rb +22 -0
  6. data/lib/dtr_to_rust.rb +34 -4
  7. data/lib/generator.rb +105 -32
  8. data/lib/instruction/add.rb +12 -0
  9. data/lib/instruction/and.rb +19 -0
  10. data/lib/instruction/assign.rb +16 -0
  11. data/lib/instruction/divide.rb +12 -0
  12. data/lib/instruction/end_of_iteration_check.rb +11 -0
  13. data/lib/instruction/evaluate.rb +92 -17
  14. data/lib/instruction/exit_with_message.rb +18 -0
  15. data/lib/instruction/field.rb +3 -3
  16. data/lib/instruction/goto.rb +12 -0
  17. data/lib/instruction/handler.rb +11 -7
  18. data/lib/instruction/increment.rb +11 -0
  19. data/lib/instruction/instantiate_object.rb +78 -0
  20. data/lib/instruction/jump.rb +28 -0
  21. data/lib/instruction/label.rb +12 -0
  22. data/lib/instruction/multiply.rb +12 -0
  23. data/lib/instruction/or.rb +19 -0
  24. data/lib/instruction/{log_string.rb → print.rb} +2 -2
  25. data/lib/instruction/return.rb +1 -1
  26. data/lib/instruction/subtract.rb +13 -0
  27. data/lib/instruction_handler.rb +34 -18
  28. data/lib/optimization/binary_x_to_self_assignment_reduction.rb +93 -0
  29. data/lib/optimization/chained_invocation_assignment_reduction.rb +123 -0
  30. data/lib/optimization/field_to_assignment_conversion.rb +37 -0
  31. data/lib/user_defined_types/handler.rb +78 -0
  32. metadata +25 -7
  33. data/lib/instruction/add_and_assign.rb +0 -12
  34. data/lib/instruction/create_list.rb +0 -31
  35. data/lib/instruction/initialize_udt.rb +0 -22
@@ -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}", @instruction[:scope])
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[:inputs][0]}.#{@instruction[:inputs][1]};"
14
+ "#{@instruction.inputs[0]}.#{@instruction.inputs[1]};"
15
15
  end
16
16
 
17
17
  def handle_field_assign
18
- "let mut #{@instruction[:assign]} = " if @instruction[:assign]
18
+ "let mut #{@instruction.assign} = " if @instruction.assign
19
19
  end
20
20
  end
21
21
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DTRToRust
4
+ module Instruction
5
+ # This class handles the goto instruction.
6
+ class Goto < Handler
7
+ def handle
8
+ form_rust_string("goto: #{@instruction.inputs[0]}")
9
+ end
10
+ end
11
+ end
12
+ end
@@ -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(scope)
16
- ' ' * (scope + 1)
19
+ def spacing
20
+ ' ' * (@is_helper ? 1 : @spacing_scope + 2)
17
21
  end
18
22
 
19
- def form_rust_string(instruction_string, scope)
20
- "#{spacing(scope)}#{instruction_string}"
23
+ def form_rust_string(instruction_string)
24
+ "#{spacing}#{instruction_string}"
21
25
  end
22
26
  end
23
27
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DTRToRust
4
+ module Instruction
5
+ class Increment < Handler
6
+ def handle
7
+ form_rust_string("increment: #{@instruction.inputs[0]}")
8
+ end
9
+ end
10
+ end
11
+ 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 label instruction.
6
+ class Label < Handler
7
+ def handle
8
+ form_rust_string("label: #{@instruction.inputs[0]}")
9
+ end
10
+ end
11
+ end
12
+ 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 LogString < Handler
6
+ class Print < Handler
7
7
  def handle
8
- form_rust_string("log!(#{inputs_to_rust_string(@instruction[:inputs])});", @instruction[:scope])
8
+ form_rust_string("log!(#{inputs_to_rust_string(@instruction.inputs)});")
9
9
  end
10
10
 
11
11
  private
@@ -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[:inputs][0], @instruction[:scope])
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
@@ -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
- case @instruction[:instruction]
12
- when 'Return'
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