Class: Idl::BuiltinTypeNameAst

Inherits:
AstNode
  • Object
show all
Defined in:
lib/idlc/ast.rb,
lib/idlc/passes/gen_adoc.rb

Overview

represents a type name of one of the builtin types:

* Bits<N>
* Boolean
* String

And their aliases:

* XReg (Bits<XLEN>)
* U32 (Bits<32>)
* U64 (Bits<64>)

Defined Under Namespace

Classes: Memo

Constant Summary

Constants inherited from AstNode

AstNode::Bits1Type, AstNode::Bits32Type, AstNode::Bits64Type, AstNode::BoolType, AstNode::ConstBoolType, AstNode::PossiblyUnknownBits1Type, AstNode::PossiblyUnknownBits32Type, AstNode::PossiblyUnknownBits64Type, AstNode::ReachableFunctionCacheType, AstNode::StringType, AstNode::VoidType

Instance Attribute Summary

Attributes inherited from AstNode

#children, #input, #interval, #parent

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from AstNode

#always_terminates?, #declaration?, #executable?, extract_base_var_name, #find_ancestor, #find_dst_registers, #find_referenced_csrs, #find_src_registers, #freeze_tree, #gen_option_adoc, #input_file, input_from_source_yaml, #inspect, #internal_error, interval_from_source_yaml, #lineno, #lines_around, #nullify_assignments, #pass_find_return_values, #path, #print_ast, #prune, #reachable_exceptions, #reachable_functions, #set_input_file, #set_input_file_unless_already_set, #source_line_file_offsets, #source_starting_offset, #source_yaml, #starting_line, #text_value, #truncation_warn, #type_error, #unindent, value_else, #value_else, value_error, #value_error, value_try, #value_try, write_back_nested

Constructor Details

#initialize(input, interval, type_name, bits_expression) ⇒ BuiltinTypeNameAst

Returns a new instance of BuiltinTypeNameAst.



7193
7194
7195
7196
7197
7198
7199
7200
7201
# File 'lib/idlc/ast.rb', line 7193

def initialize(input, interval, type_name, bits_expression)
  if bits_expression.nil?
    super(input, interval, EMPTY_ARRAY)
  else
    super(input, interval, [bits_expression])
  end
  @type_name = type_name
  @memo = Memo.new
end

Class Method Details

.from_h(yaml, source_mapper) ⇒ Object



7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
# File 'lib/idlc/ast.rb', line 7291

def self.from_h(yaml, source_mapper)
  raise "Bad YAML" unless yaml.key?("kind") && (yaml.fetch("kind") == "builtin_type" || yaml.fetch("kind") == "bits_type")

  input = input_from_source_yaml(yaml.fetch("source"), source_mapper)
  interval = interval_from_source_yaml(yaml.fetch("source"))
  if yaml.fetch("kind") == "bits_type"
    BuiltinTypeNameAst.new(
      input, interval, "Bits", AstNode.from_h(yaml.fetch("width_expr"), source_mapper)
    )
  else
    BuiltinTypeNameAst.new(
      input, interval, yaml.fetch("type"), nil
    )
  end
end

Instance Method Details

#bits_expressionObject



7191
# File 'lib/idlc/ast.rb', line 7191

def bits_expression = @children[0]

#bits_type(symtab) ⇒ Object



7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
# File 'lib/idlc/ast.rb', line 7222

def bits_type(symtab)
  @memo.bits_type[symtab] ||=
    begin
      t = T.let(nil, T.nilable(Type))
      value_result = value_try do
        t = Type.new(:bits, width: bits_expression.value(symtab))
      end
      value_else(value_result) do
        t = Type.new(:bits, width: :unknown, width_ast: bits_expression)
      end
      T.must(t)
    end
end

#const_eval?(symtab) ⇒ Boolean

Returns:

  • (Boolean)


7189
# File 'lib/idlc/ast.rb', line 7189

def const_eval?(symtab) = (@type_name == "bits") ? bits_expression.const_eval?(symtab) : true

#gen_adoc(indent = 0, indent_spaces: 2) ⇒ Object



197
198
199
200
201
202
203
# File 'lib/idlc/passes/gen_adoc.rb', line 197

def gen_adoc(indent = 0, indent_spaces: 2)
  if @type_name == "Bits"
    "#{' ' * indent}Bits<#{bits_expression.gen_adoc(0, indent_spaces:)}>"
  else
    to_idl
  end
end

#to_hObject



7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
# File 'lib/idlc/ast.rb', line 7274

def to_h
  if @type_name == "Bits"
    {
      "kind" => "bits_type",
      "width_expr" => bits_expression.to_h,
      "source" => source_yaml
    }
  else
    {
      "kind" => "builtin_type",
      "type" => @type_name,
      "source" => source_yaml
    }
  end
end

#to_idlObject



7265
7266
7267
7268
7269
7270
7271
# File 'lib/idlc/ast.rb', line 7265

def to_idl
  if @type_name == "Bits"
    "Bits<#{bits_expression.to_idl}>"
  else
    @type_name
  end
end

#type(symtab) ⇒ Object



7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
# File 'lib/idlc/ast.rb', line 7238

def type(symtab)
  case @type_name
  when "XReg"
    if symtab.mxlen == 32
      PossiblyUnknownBits32Type
    elsif symtab.mxlen == 64
      PossiblyUnknownBits64Type
    else
      Type.new(:bits, width: :unknown, max_width: 64)
    end
  when "Boolean"
    BoolType
  when "U32"
    PossiblyUnknownBits32Type
  when "U64"
    PossiblyUnknownBits64Type
  when "String"
    StringType
  when "Bits"
    bits_type(symtab)
  else
    internal_error "TODO: #{text_value}"
  end
end

#type_check(symtab, strict:) ⇒ void

This method returns an undefined value.

type check this node and all children

Calls to #type and/or #value may depend on type_check being called first with the same symtab. If not, those functions may raise an AstNode::InternalError

Parameters:

Raises:



7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
# File 'lib/idlc/ast.rb', line 7204

def type_check(symtab, strict:)
  if @type_name == "Bits"
    bits_expression.type_check(symtab, strict:)
    value_result = value_try do
      unless bits_expression.value(symtab).positive?
        type_error "Bits width (#{bits_expression.value(symtab)}) must be positive"
      end
    end
    unless bits_expression.type(symtab).const?
      type_error "Bits width (#{bits_expression.text_value}) must be const"
    end
  end
  unless ["Bits", "String", "XReg", "Boolean", "U32", "U64"].include?(@type_name)
    type_error "Unimplemented builtin type #{text_value}"
  end
end