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.
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