Class: Idl::FunctionCallExpressionAst
- Includes:
- Executable, Rvalue
- Defined in:
- lib/idl/ast.rb
Instance Method Summary collapse
-
#arg_nodes ⇒ Array<AstNode>
Function argument nodes.
- #args ⇒ Object
-
#execute_unknown(symtab) ⇒ Object
nothing to do for a function call.
- #func_type(symtab) ⇒ Object
-
#initialize(input, interval, function_name, targs, args) ⇒ FunctionCallExpressionAst
constructor
A new instance of FunctionCallExpressionAst.
- #name ⇒ Object
- #targs ⇒ Object
-
#template? ⇒ Boolean
Whether or not the function call has a template argument.
-
#template_arg_nodes ⇒ Array<AstNode>
Template argument nodes.
- #template_values(symtab, unknown_ok: false) ⇒ Object
-
#to_idl ⇒ String
Return valid IDL representation of the node (and its subtree).
-
#type(symtab) ⇒ Type
Given a specific symbol table, return the type of this node.
-
#type_check(symtab) ⇒ void
type check this node and all children.
-
#value(symtab) ⇒ Object
(also: #execute)
Return the compile-time-known value of the node.
-
#values(symtab) ⇒ Array<Integer>, ...
included
from Rvalue
Return a complete list of possible compile-time-known values of the node, or raise a ValueError if the full list cannot be determined.
Constructor Details
#initialize(input, interval, function_name, targs, args) ⇒ FunctionCallExpressionAst
Returns a new instance of FunctionCallExpressionAst.
4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 |
# File 'lib/idl/ast.rb', line 4504 def initialize(input, interval, function_name, targs, args) raise ArgumentError, "targs shoudl be an array" unless targs.is_a?(Array) raise ArgumentError, "args shoudl be an array" unless args.is_a?(Array) super(input, interval, targs + args) @num_targs = targs.size @name = function_name @reachable_exceptions_func_call_cache = {} @func_def_type_cache = {} end |
Instance Method Details
#arg_nodes ⇒ Array<AstNode>
Returns Function argument nodes.
4546 4547 4548 |
# File 'lib/idl/ast.rb', line 4546 def arg_nodes args end |
#args ⇒ Object
4502 |
# File 'lib/idl/ast.rb', line 4502 def args = children[@num_targs..] |
#execute_unknown(symtab) ⇒ Object
nothing to do for a function call
4668 |
# File 'lib/idl/ast.rb', line 4668 def execute_unknown(symtab); end |
#func_type(symtab) ⇒ Object
4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 |
# File 'lib/idl/ast.rb', line 4550 def func_type(symtab) func_def_type = @func_def_type_cache[symtab.archdef] return func_def_type unless func_def_type.nil? func_def_type = symtab.get(@name) type_error "No symbol #{@name}" if func_def_type.nil? unless func_def_type.is_a?(FunctionType) type_error "#{@name} is not a function (it's a #{func_def_type.class.name})" end @func_def_type_cache[symtab.archdef] = func_def_type end |
#name ⇒ Object
4662 4663 4664 |
# File 'lib/idl/ast.rb', line 4662 def name @name end |
#targs ⇒ Object
4501 |
# File 'lib/idl/ast.rb', line 4501 def targs = children[0...@num_targs] |
#template? ⇒ Boolean
Returns whether or not the function call has a template argument.
4517 4518 4519 |
# File 'lib/idl/ast.rb', line 4517 def template? !targs.empty? end |
#template_arg_nodes ⇒ Array<AstNode>
Returns Template argument nodes.
4522 4523 4524 |
# File 'lib/idl/ast.rb', line 4522 def template_arg_nodes targs end |
#template_values(symtab, unknown_ok: false) ⇒ Object
4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 |
# File 'lib/idl/ast.rb', line 4526 def template_values(symtab, unknown_ok: false) return EMPTY_ARRAY unless template? if unknown_ok template_arg_nodes.map do |e| val = nil value_result = value_try do val = e.value(symtab) end value_else(value_result) do val = :unknown end val end else template_arg_nodes.map { |e| e.value(symtab) } end end |
#to_idl ⇒ String
Return valid IDL representation of the node (and its subtree)
4671 4672 4673 4674 4675 4676 4677 |
# File 'lib/idl/ast.rb', line 4671 def to_idl if template? "#{name}<#{template_arg_nodes.map(&:to_idl).join(',')}>(#{arg_nodes.map(&:to_idl).join(',')})" else "#{name}(#{arg_nodes.map(&:to_idl).join(',')})" end end |
#type(symtab) ⇒ Type
Given a specific symbol table, return the type of this node.
Should not be called until #type_check is called with the same arguments
4617 4618 4619 4620 4621 |
# File 'lib/idl/ast.rb', line 4617 def type(symtab) return ConstBoolType if name == "implemented?" func_type(symtab).return_type(template_values(symtab, unknown_ok: symtab.archdef.partially_configured?), self) end |
#type_check(symtab) ⇒ void
4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 |
# File 'lib/idl/ast.rb', line 4565 def type_check(symtab) level = symtab.levels unknown_ok = symtab.archdef.partially_configured? tvals = template_values(symtab, unknown_ok:) func_def_type = func_type(symtab) type_error "Template arguments provided in call to non-template function #{@name}" if template? && func_def_type.template_names.empty? type_error "Missing template arguments in call to #{@name}" if !template? && !func_def_type.template_names.empty? if template? num_targs = template_arg_nodes.size if func_def_type.template_names.size != num_targs type_error "Wrong number of template arguments (expecting #{func_def_type.template_names.size}, got #{num_targs})" end template_arg_nodes.each_with_index do |t, idx| t.type_check(symtab) unless t.type(symtab).convertable_to?(func_def_type.template_types(symtab)[idx]) type_error "Template argument #{idx + 1} has wrong type" end end func_def_type.type_check_call(tvals, arg_nodes, symtab, self) else # no need to type check this function; it will be done on its own # func_def_type.type_check_call([], arg_nodes, symtab, self) end num_args = arg_nodes.size if func_def_type.num_args != num_args type_error "Wrong number of arguments to '#{name}' function call. Expecting #{func_def_type.num_args}, got #{num_args}" end arg_nodes.each do |a| a.type_check(symtab) end arg_nodes.each_with_index do |a, idx| unless a.type(symtab).convertable_to?(func_def_type.argument_type(idx, tvals, arg_nodes, symtab, self)) type_error "Wrong type for argument number #{idx + 1}. Expecting #{func_def_type.argument_type(idx, tvals, arg_nodes, symtab, self)}, got #{a.type(symtab)}" end end if func_def_type.return_type(tvals, self).nil? internal_error "No type determined for function" end internal_error "Function call symtab not at same level post type check (#{symtab.levels} #{level})" unless symtab.levels == level end |
#value(symtab) ⇒ Object Also known as: execute
Return the compile-time-known value of the node
4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 |
# File 'lib/idl/ast.rb', line 4624 def value(symtab) # sometimes we want to evaluate for a specific XLEN if name == "xlen" && !symtab.get("__effective_xlen").nil? return symtab.get("__effective_xlen").value end func_def_type = func_type(symtab) type_error "#{name} is not a function" unless func_def_type.is_a?(FunctionType) if func_def_type.builtin? if name == "implemented?" extname_ref = arg_nodes[0] type_error "First argument should be a ExtensionName" unless extname_ref.type(symtab).kind == :enum_ref && extname_ref.class_name == "ExtensionName" return symtab.archdef.ext?(arg_nodes[0].member_name) if symtab.archdef.fully_configured? if symtab.archdef.ext?(arg_nodes[0].member_name) # we can know if it is implemented, but not if it's not implemented for a partially configured return true end value_error "implemented? is only known when evaluating in the context of a fully-configured arch def" else value_error "value of builtin function cannot be known" end end template_values = if !template? EMPTY_ARRAY else template_arg_nodes.map do |targ| targ.value(symtab) end end func_def_type.return_value(template_values, arg_nodes, symtab, self) end |
#values(symtab) ⇒ Array<Integer>, ... Originally defined in module Rvalue
Return a complete list of possible compile-time-known values of the node, or raise a ValueError if the full list cannot be determined
For most AstNodes, this will just be a single-entry array