Class: Idl::VariableAssignmentAst

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

Overview

represents a scalar variable assignment statement

for example, these will result in a VariableAssignmentAst

# given: Bits<XLEN> zero;
zero = XLEN'b0

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 Executable

#executable?

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, #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, #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, lhs_ast, rhs_ast) ⇒ VariableAssignmentAst

Returns a new instance of VariableAssignmentAst.



2847
2848
2849
2850
# File 'lib/idlc/ast.rb', line 2847

def initialize(input, interval, lhs_ast, rhs_ast)
  super(input, interval, [lhs_ast, rhs_ast])
  @vars = {}
end

Class Method Details

.from_h(yaml, source_mapper) ⇒ Object



2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
# File 'lib/idlc/ast.rb', line 2911

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

  input = input_from_source_yaml(yaml.fetch("source"), source_mapper)
  interval = interval_from_source_yaml(yaml.fetch("source"))
  VariableAssignmentAst.new(
    input, interval,
    T.cast(AstNode.from_h(yaml.fetch("var"), source_mapper), RvalueAst),
    T.cast(AstNode.from_h(yaml.fetch("value"), source_mapper), RvalueAst)
  )
end

Instance Method Details

#const_eval?(symtab) ⇒ Boolean

Returns:

  • (Boolean)


2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
# File 'lib/idlc/ast.rb', line 2827

def const_eval?(symtab)
  return false if !lhs.const_eval?(symtab)

  if rhs.const_eval?(symtab)
    true
  else
    lhs_var = symtab.get(lhs.name)
    type_error "variable #{lhs.name} was not declared" if lhs_var.nil? || !lhs_var.is_a?(Var)

    lhs_var.const_incompatible!
    false
  end
end

#execute(symtab) ⇒ void

This method returns an undefined value.

“execute” the statement by updating the variables in the symbol table

Parameters:

  • symtab (SymbolTable)

    The symbol table for the context

Raises:

  • ValueError if some part of the statement cannot be executed at compile time



2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
# File 'lib/idlc/ast.rb', line 2878

def execute(symtab)
  if lhs.is_a?(CsrWriteAst)
    value_error "CSR writes are never compile-time-known"
  else
    variable = var(symtab)

    internal_error "No variable #{lhs.text_value}" if variable.nil?

    unless variable.type.global?
      value_result = value_try do
        variable.value = rhs.value(symtab)
      end
      value_else(value_result) do
        variable.value = nil
        value_error ""
      end
    end
  end
end

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



246
247
248
# File 'lib/idlc/passes/gen_adoc.rb', line 246

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

#lhsObject



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

def lhs = T.cast(@children.fetch(0), IdAst)

#nullify_assignments(symtab) ⇒ Object



137
138
139
140
141
142
# File 'lib/idlc/passes/prune.rb', line 137

def nullify_assignments(symtab)
  sym = symtab.get(lhs.text_value)
  unless sym.nil?
    sym.value = nil
  end
end

#prune(symtab, forced_type: nil) ⇒ Object



129
130
131
132
133
134
135
136
# File 'lib/idlc/passes/prune.rb', line 129

def prune(symtab, forced_type: nil)
  new_ast = VariableAssignmentAst.new(input, interval, lhs.dup, rhs.prune(symtab))
  value_try do
    new_ast.execute(symtab)
  end
  # value_else: execute already sets nil on failure, nothing more to do
  new_ast
end

#rhsObject



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

def rhs = T.cast(@children.fetch(1), RvalueAst)

#to_hObject



2903
2904
2905
2906
2907
2908
# File 'lib/idlc/ast.rb', line 2903

def to_h = {
  "kind" => "var_assignment",
  "var" => lhs.to_h,
  "value" => rhs.to_h,
  "source" => source_yaml
}

#to_idlObject



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

def to_idl = "#{lhs.to_idl} = #{rhs.to_idl}"

#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:



2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
# File 'lib/idlc/ast.rb', line 2853

def type_check(symtab, strict:)
  lhs.type_check(symtab, strict:)
  lhs_var = symtab.get(lhs.name)
  type_error "Cannot assign to a const" if lhs_var.type.const? && !lhs_var.for_loop_iter?

  rhs.type_check(symtab, strict:)
  if lhs_var.type.const? && lhs_var.for_loop_iter?
    # also check that the rhs is const_eval
    type_error "Assignment would make iteration variable non-const" unless rhs.type(symtab).const?
  end
  unless rhs.type(symtab).convertable_to?(lhs.type(symtab))
    type_error "Incompatible type in assignment (#{lhs.type(symtab)}, #{rhs.type(symtab)})"
  end
end

#var(symtab) ⇒ Object



2868
2869
2870
2871
2872
2873
2874
2875
# File 'lib/idlc/ast.rb', line 2868

def var(symtab)
  variable = @vars[symtab.name]
  if variable.nil?
    variable = symtab.get(lhs.text_value)
    @vars[symtab.name] = variable
  end
  variable
end