Class: Idl::IdAst

Inherits:
AstNode show all
Includes:
Rvalue
Defined in:
lib/idlc/ast.rb,
lib/idlc/passes/prune.rb,
lib/idlc/passes/gen_adoc.rb,
lib/idlc/passes/gen_option_adoc.rb

Overview

an identifier

Used for variables

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 Rvalue

#truncate, #values

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, #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, #reachable_exceptions, #reachable_functions, #set_input_file, #set_input_file_unless_already_set, #source_line_file_offsets, #source_starting_offset, #source_yaml, #starting_line, #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, name) ⇒ IdAst

Returns a new instance of IdAst.



1090
1091
1092
1093
1094
# File 'lib/idlc/ast.rb', line 1090

def initialize(input, interval, name)
  super(input, interval, EMPTY_ARRAY)
  @name = name
  @const = T.let((text_value[0] == T.must(text_value[0]).upcase), T::Boolean)
end

Class Method Details

.from_h(yaml, source_mapper) ⇒ Object



1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
# File 'lib/idlc/ast.rb', line 1185

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

  input = input_from_source_yaml(yaml.fetch("source"), source_mapper)
  interval = interval_from_source_yaml(yaml.fetch("source"))
  if input.nil?
    IdAst.new(yaml.fetch("name"), 0...yaml.fetch("name").length, yaml.fetch("name"))
  else
    raise "name does match input: '#{yaml.fetch("name")}', '#{input[T.must(interval)]}'" unless yaml.fetch("name") == input[T.must(interval)]

    IdAst.new(input, T.must(interval), T.must(input[T.must(interval)]))
  end
end

Instance Method Details

#const?Boolean

Returns:

  • (Boolean)


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

def const? = @const

#const_eval?(symtab) ⇒ Boolean

Returns:

  • (Boolean)


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

def const_eval?(symtab) = const? || symtab.get(name).const_eval?

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



163
164
165
# File 'lib/idlc/passes/gen_adoc.rb', line 163

def gen_adoc(indent = 0, indent_spaces: 2)
  "#{' ' * indent}#{text_value}"
end

#gen_option_adocObject



97
98
99
# File 'lib/idlc/passes/gen_option_adoc.rb', line 97

def gen_option_adoc
  text_value
end

#max_value(symtab) ⇒ Object



1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
# File 'lib/idlc/ast.rb', line 1138

def max_value(symtab)
  max = T.let(:unknown, T.any(Integer, Symbol))
  value_result = value_try do
    max = value(symtab)
  end
  value_else(value_result) do
    var = symtab.get(name)
    if !var.nil? && var.param?
      param = T.must(symtab.param(text_value))
      if param.schema.max_val_known?
        max = param.schema.max_val
      end
    end
  end
  max
end

#min_value(symtab) ⇒ Object



1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
# File 'lib/idlc/ast.rb', line 1156

def min_value(symtab)
  min = T.let(:unknown, T.any(Integer, Symbol))
  value_result = value_try do
    min = value(symtab)
  end
  value_else(value_result) do
    var = symtab.get(name)
    if !var.nil? && var.param?
      param = T.must(symtab.param(text_value))
      if param.schema.min_val_known?
        min = param.schema.min_val
      end
    end
  end
  min
end

#nameObject



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

def name = @name

#prune(symtab, forced_type: nil) ⇒ Object



773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
# File 'lib/idlc/passes/prune.rb', line 773

def prune(symtab, forced_type: nil)
  value_result = value_try do
    value_error "Not pruning struct types" if type(symtab).kind == :struct
    v = value(symtab)
    if type(symtab).kind == :bits
      if type(symtab).width == :unknown
        value_error "Unknown width"
      end
    end
    return PruneHelpers.create_literal(symtab, v, type(symtab), forced_type: forced_type || type(symtab))
  end
  value_else(value_result) do
    dup
  end
end

#text_valueObject



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

def text_value = @name

#to_hObject



1178
1179
1180
1181
1182
# File 'lib/idlc/ast.rb', line 1178

def to_h = {
  "kind" => "id",
  "name" => name,
  "source" => source_yaml
}

#to_idlObject



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

def to_idl = name

#type(symtab) ⇒ Object



1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
# File 'lib/idlc/ast.rb', line 1104

def type(symtab)
  return @type unless @type.nil?

  type_error "Symbol '#{name}' not found" if symtab.get(name).nil?

  sym = symtab.get(name)
  # @type =
  if sym.is_a?(Type)
    sym
  elsif sym.is_a?(Var)
    sym.type
  else
    internal_error "Unexpected object on the symbol table"
  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:



1097
1098
1099
1100
# File 'lib/idlc/ast.rb', line 1097

def type_check(symtab, strict:)
  type_error "Cannot use reserved word '#{name}' as variable name" if ReservedWords::RESERVED.include?(name)
  type_error "no symbol named '#{name}'" if symtab.get(name).nil?
end

#value(symtab) ⇒ Object

Return the compile-time-known value of the node



1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
# File 'lib/idlc/ast.rb', line 1125

def value(symtab)
  var = symtab.get(name)

  type_error "Variable '#{name}' was not found" if var.nil?

  value_error "Value of '#{name}' not known" if var.value.nil?

  v = var.value
  value_error "Value of #{name} is unknown" if v == :unknown
  v
end