Class: Idl::ReturnExpressionAst
Instance Method Summary collapse
- #enclosing_function ⇒ Object
-
#expected_return_type(symtab) ⇒ Type
The expected return type (as defined by the encolsing function).
-
#initialize(input, interval, return_nodes) ⇒ ReturnExpressionAst
constructor
A new instance of ReturnExpressionAst.
-
#return_type(symtab) ⇒ Type
The actual return type.
-
#return_types(symtab) ⇒ Array<Type>
List of actual return types.
-
#return_value(symtab) ⇒ Integer, ...
Evaluate the compile-time return value of this node, or, if the node does not return (e.g., because it is an IfAst but there is no return on the taken path), execute the node and update the symtab.
- #return_value_nodes ⇒ Object
-
#return_values(symtab) ⇒ Array<Integer>, Array<Boolean>
Evaluate all possible compile-time return values of this node, or, if the node does not return (e.g., because it is an IfAst but there is no return on a possible path), execute the node and update the symtab.
- #to_idl ⇒ Object
-
#type_check(symtab) ⇒ void
type check this node and all children.
Constructor Details
#initialize(input, interval, return_nodes) ⇒ ReturnExpressionAst
Returns a new instance of ReturnExpressionAst.
3983 3984 3985 3986 |
# File 'lib/idl/ast.rb', line 3983 def initialize(input, interval, return_nodes) super(input, interval, return_nodes) @func_type_cache = {} end |
Instance Method Details
#enclosing_function ⇒ Object
4059 4060 4061 |
# File 'lib/idl/ast.rb', line 4059 def enclosing_function find_ancestor(FunctionDefAst) end |
#expected_return_type(symtab) ⇒ Type
Returns The expected return type (as defined by the encolsing function).
4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 |
# File 'lib/idl/ast.rb', line 4008 def expected_return_type(symtab) func_def = find_ancestor(FunctionDefAst) if func_def.nil? if symtab.get("__expected_return_type").nil? internal_error "Forgot to set __expected_return_type in the symbol table" end symtab.get("__expected_return_type") else # need to find the type to get the right symbol table func_type = @func_type_cache[symtab.cfg_arch] return func_type.return_type(EMPTY_ARRAY, self) unless func_type.nil? func_type = symtab.get_global(func_def.name) internal_error "Couldn't find function type for '#{func_def.name}' #{symtab.keys} " if func_type.nil? # to get the return type, we need to find the template values in case this is # a templated function definition # # that information should be up the stack in the symbol table if func_type.templated? template_values = symtab.find_all(single_scope: true) do |o| o.is_a?(Var) && o.template_value_for?(func_def.name) end unless template_values.size == func_type.template_names.size internal_error "Did not find correct number of template arguments (found #{template_values.size}, need #{func_type.template_names.size}) #{symtab.keys_pretty}" end func_type.return_type(template_values.sort { |a, b| a.template_index <=> b.template_index }.map(&:value), self) else @func_type_cache[symtab.cfg_arch]= func_type func_type.return_type(EMPTY_ARRAY, self) end end end |
#return_type(symtab) ⇒ Type
Returns The actual return type.
3998 3999 4000 4001 4002 4003 4004 4005 |
# File 'lib/idl/ast.rb', line 3998 def return_type(symtab) types = return_types(symtab) if types.size > 1 Type.new(:tuple, tuple_types: types) else types[0] end end |
#return_types(symtab) ⇒ Array<Type>
Returns List of actual return types.
3989 3990 3991 3992 3993 3994 3995 |
# File 'lib/idl/ast.rb', line 3989 def return_types(symtab) if return_value_nodes[0].type(symtab).kind == :tuple return_value_nodes[0].type(symtab).tuple_types else return_value_nodes.map{ |v| v.type(symtab) } end end |
#return_value(symtab) ⇒ Integer, ...
Evaluate the compile-time return value of this node, or, if the node does not return (e.g., because it is an IfAst but there is no return on the taken path), execute the node and update the symtab
4064 4065 4066 4067 4068 4069 4070 |
# File 'lib/idl/ast.rb', line 4064 def return_value(symtab) if return_value_nodes.size == 1 return_value_nodes[0].value(symtab) else return_value_nodes.map { |v| v.value(symtab) } end end |
#return_value_nodes ⇒ Object
3981 |
# File 'lib/idl/ast.rb', line 3981 def return_value_nodes = @children |
#return_values(symtab) ⇒ Array<Integer>, Array<Boolean>
Evaluate all possible compile-time return values of this node, or, if the node does not return (e.g., because it is an IfAst but there is no return on a possible path), execute the node and update the symtab
4073 4074 4075 4076 4077 4078 4079 |
# File 'lib/idl/ast.rb', line 4073 def return_values(symtab) if return_value_nodes.size == 1 return_value_nodes[0].values(symtab) else return_value_nodes.map { |v| v.values(symtab) } end end |
#to_idl ⇒ Object
4081 |
# File 'lib/idl/ast.rb', line 4081 def to_idl = "return #{return_value_nodes.map(&:to_idl).join(',')}" |
#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
4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 |
# File 'lib/idl/ast.rb', line 4044 def type_check(symtab) return_value_nodes.each do |v| v.type_check(symtab) type_error "Unknown type for #{v.text_value}" if v.type(symtab).nil? end if return_value_nodes[0].type(symtab).kind == :tuple type_error("Can't combine tuple types in return") unless return_value_nodes.size == 1 end unless return_type(symtab).convertable_to?(expected_return_type(symtab)) type_error "Return type (#{return_type(symtab)}) not convertable to expected return type (#{expected_return_type(symtab)})" end end |