Class: Idl::MultiVariableAssignmentAst

Inherits:
AstNode
  • Object
show all
Includes:
Executable
Defined in:
lib/idl/ast.rb

Overview

represents assignement of multiple variable from a function call that returns multiple values

for example:

(match_result, cfg) = pmp_match<access_size>(paddr);

Instance Method Summary collapse

Constructor Details

#initialize(input, interval, variables, function_call) ⇒ MultiVariableAssignmentAst

Returns a new instance of MultiVariableAssignmentAst.



2079
2080
2081
# File 'lib/idl/ast.rb', line 2079

def initialize(input, interval, variables, function_call)
  super(input, interval, variables + [function_call])
end

Instance Method Details

#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



2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
# File 'lib/idl/ast.rb', line 2124

def execute(symtab)
  value_result = value_try do
    values = function_call.execute(symtab)

    i = 0
    variables.each do |v|
      next if v.type(symtab).global?

      var = symtab.get(v.text_value)
      internal_error "call type check" if var.nil?

      var.value = values[i]
      i += 1
    end
  end
  value_else(value_result) do
    variables.each do |v|
      symtab.get(v.text_value).value = nil
    end
    value_error "value of right-hand side of multi-variable assignment is unknown"
  end
end

#execute_unknown(symtab) ⇒ void

This method returns an undefined value.

“execute” the statement, forcing any variable assignments to an unknown state This is used down unknown conditional paths.

Parameters:

  • symtab (SymbolTable)

    The symbol table for the context

Raises:

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



2148
2149
2150
2151
2152
# File 'lib/idl/ast.rb', line 2148

def execute_unknown(symtab)
  variables.each do |v|
    symtab.get(v.text_value).value = nil
  end
end

#function_callObject



2077
# File 'lib/idl/ast.rb', line 2077

def function_call = @children.last

#rhsObject



2088
2089
2090
# File 'lib/idl/ast.rb', line 2088

def rhs
  function_call
end

#to_idlString

Return valid IDL representation of the node (and its subtree)

Returns:

  • (String)

    IDL code for the node



2155
# File 'lib/idl/ast.rb', line 2155

def to_idl = "(#{variables.map(&:to_idl).join(', ')}) = #{function_call.to_idl}"

#type_check(symtab) ⇒ 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:



2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
# File 'lib/idl/ast.rb', line 2093

def type_check(symtab)
  function_call.type_check(symtab)
  variables.each { |var| var.type_check(symtab) }

  type_error "Assigning value to a constant" if variables.any? { |v| v.type(symtab).const? }

  type_error "Function '#{function_call.name}' has no return type" if function_call.type(symtab).nil?
  unless function_call.type(symtab).kind == :tuple
    type_error "Function '#{function_call.name}' only returns 1 variable"
  end

  if function_call.type(symtab).tuple_types.size != vars.size
    type_error "function '#{function_call.name}' returns #{function_call.type(symtab).tuple_types.size} arguments, but  #{variables.size} were specified"
  end

  function_call.type(symtab).tuple_types.each_index do |i|
    next if variables[i].is_a?(DontCareLvalueAst)
    raise "Implementation error" if variables[i].is_a?(DontCareReturnAst)

    var = symtab.get(variables[i].text_value)
    type_error "No symbol named '#{variables[i].text_value}'" if var.nil?

    internal_error "Cannot determine type of #{variables[i].text_value}" unless var.respond_to?(:type)

    unless var.type.convertable_to?(function_call.type(symtab).tuple_types[i])
      type_error "'#{function_call.name}' expecting a #{function_call.type(symtab).tuple_types[i]} in argument #{i}, but was given #{var.type(symtab)}"
    end
  end
end

#variablesObject



2076
# File 'lib/idl/ast.rb', line 2076

def variables = @children[0..-2]

#varsArray<AstNode>

Returns The variables being assigned, in order.

Returns:

  • (Array<AstNode>)

    The variables being assigned, in order



2084
2085
2086
# File 'lib/idl/ast.rb', line 2084

def vars
  variables
end