Class: Idl::VariableDeclarationWithInitializationAst

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

Overview

represents a single variable declaration with initialization

for example:

Bits<64> doubleword = 64'hdeadbeef
Boolean has_property = true

Instance Method Summary collapse

Constructor Details

#initialize(input, interval, type_name_ast, var_write_ast, ary_size, rval_ast) ⇒ VariableDeclarationWithInitializationAst

Returns a new instance of VariableDeclarationWithInitializationAst.



2363
2364
2365
2366
2367
2368
2369
2370
# File 'lib/idl/ast.rb', line 2363

def initialize(input, interval, type_name_ast, var_write_ast, ary_size, rval_ast)
  if ary_size.nil?
    super(input, interval, [type_name_ast, var_write_ast, rval_ast])
  else
    super(input, interval, [type_name_ast, var_write_ast, rval_ast, ary_size])
  end
  @global = false
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



2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
# File 'lib/idl/ast.rb', line 2436

def add_symbol(symtab)
  if @global
    if lhs.text_value[0] == lhs.text_value[0].upcase
      # const, add the value if it's known
      value_result = value_try do
        symtab.add(lhs.text_value, Var.new(lhs.text_value, lhs_type(symtab), rhs.value(symtab)))
      end
      value_else(value_result) do
        symtab.add(lhs.text_value, Var.new(lhs.text_value, lhs_type(symtab)))
      end
    else
      # mutable globals never have a compile-time value
      symtab.add!(lhs.text_value, Var.new(lhs.text_value, lhs_type(symtab)))
    end
  else
    value_result = value_try do
      symtab.add(lhs.text_value, Var.new(lhs.text_value, lhs_type(symtab), rhs.value(symtab)))
    end
    value_else(value_result) do
      symtab.add(lhs.text_value, Var.new(lhs.text_value, lhs_type(symtab)))
    end
  end
end

#ary_sizeObject



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

def ary_size = @children[3]

#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



2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
# File 'lib/idl/ast.rb', line 2461

def execute(symtab)
  value_error "TODO: Array declaration" unless ary_size.nil?
  rhs_value = nil
  return if @global # never executed at compile time

  value_result = value_try do
    rhs_value = rhs.value(symtab)
  end
  value_else(value_result) do
    symtab.add(lhs.text_value, Var.new(lhs.text_value, lhs_type(symtab), nil))
    value_error "value of right-hand side of variable initialization is unknown"
  end
  symtab.add(lhs.text_value, Var.new(lhs.text_value, lhs_type(symtab), rhs_value))
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



2477
2478
2479
# File 'lib/idl/ast.rb', line 2477

def execute_unknown(symtab)
  symtab.add(lhs.text_value, Var.new(lhs.text_value, lhs_type(symtab), nil))
end

#lhsObject



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

def lhs = @children[1]

#lhs_type(symtab) ⇒ Object



2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
# File 'lib/idl/ast.rb', line 2376

def lhs_type(symtab)
  decl_type = type_name.type(symtab).clone
  type_error "No type '#{type_name.text_value}' on line #{lineno}" if decl_type.nil?

  qualifiers = []
  qualifiers << :const if lhs.text_value[0].upcase == lhs.text_value[0]
  qualifiers << :global if @global

  decl_type = Type.new(:enum_ref, enum_class: decl_type) if decl_type.kind == :enum

  qualifiers.each do |q|
    decl_type.qualify(q)
  end

  unless ary_size.nil?
    value_result = value_try do
      decl_type = Type.new(:array, sub_type: decl_type, width: ary_size.value(symtab), qualifiers:)
    end
    value_else(value_result) do
      type_error "Array size must be known at compile time"
    end
  end

  decl_type
end

#make_globalObject



2372
2373
2374
# File 'lib/idl/ast.rb', line 2372

def make_global
  @global = true
end

#rhsObject



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

def rhs = @children[2]

#to_idlString

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

Returns:

  • (String)

    IDL code for the node



2482
2483
2484
2485
2486
2487
2488
# File 'lib/idl/ast.rb', line 2482

def to_idl
  if ary_size.nil?
    "#{type_name.to_idl} #{lhs.to_idl} = #{rhs.to_idl}"
  else
    "#{type_name.to_idl} #{lhs.to_idl}[#{ary_size.to_idl}] = #{rhs.to_idl}"
  end
end

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



2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
# File 'lib/idl/ast.rb', line 2403

def type_check(symtab)
  rhs.type_check(symtab)

  type_name.type_check(symtab)

  ary_size&.type_check(symtab)

  decl_type = lhs_type(symtab)

  if decl_type.const?
    # this is a constant; ensure we are assigning a constant value
    value_result = value_try do
      symtab.add(lhs.text_value, Var.new(lhs.text_value, decl_type.clone, rhs.value(symtab)))
    end
    value_else(value_result) do
      unless rhs.type(symtab).const?
        type_error "Declaring constant with a non-constant value (#{rhs.text_value})"
      end
      symtab.add(lhs.text_value, Var.new(lhs.text_value, decl_type.clone))
    end
  else
    symtab.add(lhs.text_value, Var.new(lhs.text_value, decl_type.clone))
  end

  lhs.type_check(symtab)

  # now check that the assignment is compatible
  return if rhs.type(symtab).convertable_to?(decl_type)

  type_error "Incompatible type (#{decl_type}, #{rhs.type(symtab)}) in assignment"
end

#type_nameObject



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

def type_name = @children[0]