Module: Idl::PruneHelpers

Extended by:
T::Sig
Defined in:
lib/idlc/passes/prune.rb

Class Method Summary collapse

Class Method Details

.coerce_ary_element_widths(symtab, elements, max_element_width) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/idlc/passes/prune.rb', line 55

def self.coerce_ary_element_widths(symtab, elements, max_element_width)
  if elements.is_a?(Array) && elements.empty?
    Idl::ArrayLiteralAst.new("pruned_literal_ary", 0..18, [])
  elsif elements.fetch(0).is_a?(Idl::ArrayLiteralAst)
    # Recursively coerce nested arrays - pass e.entries, not e
    Idl::ArrayLiteralAst.new("pruned_literal_ary", 0..18,
      elements.map { |e| coerce_ary_element_widths(symtab, e.entries, max_element_width) })
  else
    # Base case: elements is an array of leaf nodes, coerce each to max_element_width
    coerced = elements.map { |node| create_int_literal(node.value(symtab), forced_type: Idl::Type.new(:bits, width: max_element_width)) }
    Idl::ArrayLiteralAst.new("pruned_literal_ary", 0..18, coerced)
  end
end

.create_bool_literal(value) ⇒ Object



28
29
30
31
32
33
34
# File 'lib/idlc/passes/prune.rb', line 28

def self.create_bool_literal(value)
  if value
    Idl::TrueExpressionAst.new("true", 0..4)
  else
    Idl::FalseExpressionAst.new("false", 0..5)
  end
end

.create_int_literal(value, forced_type: nil) ⇒ Object



19
20
21
22
23
24
25
26
# File 'lib/idlc/passes/prune.rb', line 19

def self.create_int_literal(value, forced_type: nil)
  width = forced_type ? forced_type.width : value.bit_length
  raise "pruning error: attempting to prune an integer with unknown width" unless width.is_a?(Integer)
  width = 1 if width == 0
  v = value <= 512 ? value.to_s : "h#{value.to_s(16)}"
  str = "#{width}'#{v}"
  Idl::IntLiteralAst.new(str, 0...str.size, str)
end

.create_literal(symtab, value, type, forced_type: nil) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/idlc/passes/prune.rb', line 69

def self.create_literal(symtab, value, type, forced_type: nil)
  case type.kind
  when :enum_ref
    member_name = type.enum_class.element_names[type.enum_class.element_values.index(value)]
    str = "#{type.enum_class.name}::#{member_name}"
    Idl::EnumRefAst.new(str, 0...str.size, type.enum_class.name, member_name)
  when :bits
    create_int_literal(value, forced_type:)
  when :boolean
    create_bool_literal(value)
  when :array
    elements = value.map { |e| create_literal(symtab, e, type.sub_type) }
    # array elements MUST have the same type, so we need to coerce them
    # find the leaf level, and get the bit widths if needed
    ary = Idl::ArrayLiteralAst.new("pruned_literal_ary", 0..18, elements)
    max_element_width = find_max_element_width(symtab, ary)
    if max_element_width.nil?
      ary
    else
      coerce_ary_element_widths(symtab, elements, max_element_width)
    end
  else
    raise "TODO: #{type}"
  end
end

.find_max_element_width(symtab, node, max = nil) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/idlc/passes/prune.rb', line 39

def self.find_max_element_width(symtab, node, max = nil)
  if node.is_a?(Idl::ArrayLiteralAst)
    node.entries.map do |e|
      e_max = find_max_element_width(symtab, e)
      max.nil? ? e_max : [max, e_max].max
    end.max
  else
    if node.is_a?(Idl::TrueExpressionAst) || node.is_a?(Idl::FalseExpressionAst)
      nil
    else
      node_width = node.type(symtab).width
      max.nil? ? node_width : [max, node_width].max
    end
  end
end