Class: Idl::EnumDefinitionAst

Inherits:
AstNode
  • Object
show all
Includes:
Declaration
Defined in:
lib/idlc/ast.rb,
lib/idlc/type.rb

Overview

Node representing an IDL enum definition

# this will result in an EnumDefinitionAst
enum PrivilegeMode {
  M  0b011
  S  0b001
  HS 0b001 # alias for S when H extension is used
  U  0b000
  VS 0b101
  VU 0b100
}

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 included from Declaration

#declaration?

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_adoc, #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, user_type, element_names, element_values) ⇒ EnumDefinitionAst

Returns a new instance of EnumDefinitionAst.



1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
# File 'lib/idlc/ast.rb', line 1924

def initialize(input, interval, user_type, element_names, element_values)
  super(input, interval, ([user_type] + element_names + element_values).compact)
  @user_type = user_type
  @element_name_asts = element_names
  @element_value_asts = element_values

  next_auto_value = 0
  @element_values = T.let([], T::Array[Integer])

  @element_value_asts.each do |e|
    if e.nil?
      @element_values << next_auto_value
      next_auto_value += 1
    else
      @element_values << e.value(nil)
      next_auto_value = T.must(@element_values.last) + 1
    end
  end

  @type = EnumerationType.new(name, self.element_names, self.element_values)
end

Class Method Details

.from_h(yaml, source_mapper) ⇒ Object



2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
# File 'lib/idlc/ast.rb', line 2023

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

  input = input_from_source_yaml(yaml.fetch("source"), source_mapper)
  interval = interval_from_source_yaml(yaml.fetch("source"))
  EnumDefinitionAst.new(
    input, interval,
    T.cast(AstNode.from_h(yaml.fetch("enum_class_name"), source_mapper), UserTypeNameAst),
    yaml.fetch("members").map { |m| AstNode.from_h(m.fetch("name"), source_mapper) },
    yaml.fetch("members").map { |m| m["value"].nil? ? nil : AstNode.from_h(m.fetch("value"), source_mapper) }
  )
end

Instance Method Details

#add_symbol(symtab) ⇒ Object

Add symbol(s) at the outermost scope of the symbol table

Parameters:

  • symtab (SymbolTable)

    Symbol table at the scope that the symbol(s) will be inserted



1979
1980
1981
1982
1983
1984
1985
# File 'lib/idlc/ast.rb', line 1979

def add_symbol(symtab)
  internal_error "All enums should be declared in global scope" unless symtab.levels == 1
  type_error "Cannot use reserved word '#{name}' as user-defined type name" if ReservedWords::RESERVED.include?(name)

  internal_error "Type is nil?" if type(symtab).nil?
  symtab.add!(name, type(symtab))
end

#const_eval?(symtab) ⇒ Boolean

Returns:

  • (Boolean)


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

def const_eval?(symtab) = true

#element_namesObject



1948
1949
1950
1951
1952
# File 'lib/idlc/ast.rb', line 1948

def element_names
  return @element_names unless @element_names.nil?

  @element_names = @element_name_asts.map(&:text_value)
end

#element_valuesObject



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

def element_values = @element_values

#nameString

Returns enum name.

Returns:

  • (String)

    enum name



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

def name = @user_type.text_value

#to_hObject



2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
# File 'lib/idlc/ast.rb', line 2010

def to_h = {
  "kind" => "enum_decl",
  "enum_class_name" => @user_type.to_h,
  "members" => element_names.each_index.map do |idx|
    {
      "name" => @element_name_asts[idx].to_h,
      "value" => @element_value_asts[idx]&.to_h
    }
  end,
  "source" => source_yaml
}

#to_idlObject



2000
2001
2002
2003
2004
2005
2006
2007
# File 'lib/idlc/ast.rb', line 2000

def to_idl
  idl = "enum #{name} { "
  element_names.each_index do |idx|
    idl << "#{element_names[idx]} #{element_values[idx]} "
  end
  idl << "}"
  idl
end

#type(symtab) ⇒ Type

Return the type of this node

Parameters:

Returns:

  • (Type)

    The type of the node



1988
1989
1990
# File 'lib/idlc/ast.rb', line 1988

def type(symtab)
  @type
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:



1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
# File 'lib/idlc/ast.rb', line 1961

def type_check(symtab, strict:)
  type_error "Cannot use reserved word '#{name}' as user-defined type name" if ReservedWords::RESERVED.include?(name)

  @element_name_asts.each do |e|
    type_error "Cannot use reserved word '#{e.text_value}' as enum member" if ReservedWords::RESERVED.include?(e.text_value)
  end

  @element_value_asts.each do |e|
    unless e.nil?
      e.type_check(symtab, strict:)
    end
  end

  add_symbol(symtab)
  @user_type.type_check(symtab, strict:)
end

#value(_symtab) ⇒ Integer, Boolean

Return the compile-time-known value of the node

Parameters:

Returns:

  • (Integer)

    if the compile-time-known value is an integer

  • (Boolean)

    if the compile-time-known value is a boolean

Raises:



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

def value(_symtab) = raise InternalError, "Enum definitions have no value"