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.
4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 |
# File 'lib/idl/ast.rb', line 4539 def initialize(input, interval, function_name, targs, args) raise ArgumentError, "targs should be an array" unless targs.is_a?(Array) raise ArgumentError, "args should 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.
4581 4582 4583 |
# File 'lib/idl/ast.rb', line 4581 def arg_nodes args end |
#args ⇒ Object
4537 |
# File 'lib/idl/ast.rb', line 4537 def args = children[@num_targs..] |
#execute_unknown(symtab) ⇒ Object
nothing to do for a function call
4703 |
# File 'lib/idl/ast.rb', line 4703 def execute_unknown(symtab); end |
#func_type(symtab) ⇒ Object
4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 |
# File 'lib/idl/ast.rb', line 4585 def func_type(symtab) func_def_type = @func_def_type_cache[symtab.cfg_arch] 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.cfg_arch] = func_def_type end |
#name ⇒ Object
4697 4698 4699 |
# File 'lib/idl/ast.rb', line 4697 def name @name end |
#targs ⇒ Object
4536 |
# File 'lib/idl/ast.rb', line 4536 def targs = children[0...@num_targs] |
#template? ⇒ Boolean
Returns whether or not the function call has a template argument.
4552 4553 4554 |
# File 'lib/idl/ast.rb', line 4552 def template? !targs.empty? end |
#template_arg_nodes ⇒ Array<AstNode>
Returns Template argument nodes.
4557 4558 4559 |
# File 'lib/idl/ast.rb', line 4557 def template_arg_nodes targs end |
#template_values(symtab, unknown_ok: false) ⇒ Object
4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 |
# File 'lib/idl/ast.rb', line 4561 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)
4706 4707 4708 4709 4710 4711 4712 |
# File 'lib/idl/ast.rb', line 4706 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
4652 4653 4654 4655 4656 |
# File 'lib/idl/ast.rb', line 4652 def type(symtab) return ConstBoolType if name == "implemented?" func_type(symtab).return_type(template_values(symtab, unknown_ok: symtab.cfg_arch.partially_configured?), self) end |
#type_check(symtab) ⇒ void
4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 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 |
# File 'lib/idl/ast.rb', line 4600 def type_check(symtab) level = symtab.levels unknown_ok = symtab.cfg_arch.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
4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 |
# File 'lib/idl/ast.rb', line 4659 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.cfg_arch.ext?(arg_nodes[0].member_name) if symtab.cfg_arch.fully_configured? if symtab.cfg_arch.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