Class: Idl::ReturnExpressionAst
- Inherits:
-
AstNode
- Object
- AstNode
- Idl::ReturnExpressionAst
show all
- Includes:
- Returns
- Defined in:
- lib/idlc/ast.rb,
lib/idlc/passes/prune.rb,
lib/idlc/passes/gen_adoc.rb,
lib/idlc/passes/gen_option_adoc.rb
Constant Summary
Constants inherited
from AstNode
AstNode::Bits1Type, AstNode::Bits32Type, AstNode::Bits64Type, AstNode::BoolType, AstNode::ConstBoolType, AstNode::PossiblyUnknownBits1Type, AstNode::PossiblyUnknownBits32Type, AstNode::PossiblyUnknownBits64Type, AstNode::ReachableFunctionCacheType, AstNode::StringType, AstNode::VoidType
Instance Attribute Summary
Attributes inherited from AstNode
#children, #input, #interval, #parent
Class Method Summary
collapse
Instance Method Summary
collapse
-
#const_eval?(symtab) ⇒ Boolean
-
#enclosing_function ⇒ Object
-
#gen_adoc(indent = 0, indent_spaces: 2) ⇒ Object
-
#gen_option_adoc ⇒ Object
-
#initialize(input, interval, return_nodes) ⇒ ReturnExpressionAst
constructor
A new instance of ReturnExpressionAst.
-
#prune(symtab, forced_type: nil) ⇒ Object
-
#return_type(symtab) ⇒ Object
-
#return_types(symtab) ⇒ Object
-
#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_h ⇒ Object
-
#to_idl ⇒ Object
-
#type_check(symtab, strict:) ⇒ void
type check this node and all children.
Methods included from Returns
#expected_return_type
Methods inherited from AstNode
#always_terminates?, #declaration?, #executable?, extract_base_var_name, #find_ancestor, #find_dst_registers, #find_referenced_csrs, #find_src_registers, #freeze_tree, #input_file, input_from_source_yaml, #inspect, #internal_error, interval_from_source_yaml, #lineno, #lines_around, #nullify_assignments, #pass_find_return_values, #path, #print_ast, #reachable_exceptions, #reachable_functions, #set_input_file, #set_input_file_unless_already_set, #source_line_file_offsets, #source_starting_offset, #source_yaml, #starting_line, #text_value, #truncation_warn, #type_error, #unindent, value_else, #value_else, value_error, #value_error, value_try, #value_try, write_back_nested
Constructor Details
#initialize(input, interval, return_nodes) ⇒ ReturnExpressionAst
Returns a new instance of ReturnExpressionAst.
6929
6930
6931
6932
|
# File 'lib/idlc/ast.rb', line 6929
def initialize(input, interval, return_nodes)
super(input, interval, return_nodes)
@func_type_cache = {}
end
|
Class Method Details
.from_h(yaml, source_mapper) ⇒ Object
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
|
# File 'lib/idlc/ast.rb', line 7012
def self.from_h(yaml, source_mapper)
raise "Bad YAML" unless yaml.key?("kind") && yaml.fetch("kind") == "return_expr"
input = input_from_source_yaml(yaml.fetch("source"), source_mapper)
interval = interval_from_source_yaml(yaml.fetch("source"))
ReturnExpressionAst.new(
input, interval,
yaml.fetch("exprs").map { |r| AstNode.from_h(r, source_mapper) }
)
end
|
Instance Method Details
#const_eval?(symtab) ⇒ Boolean
6925
|
# File 'lib/idlc/ast.rb', line 6925
def const_eval?(symtab) = return_value_nodes.all? { |node| node.const_eval?(symtab) }
|
#enclosing_function ⇒ Object
6975
6976
6977
|
# File 'lib/idlc/ast.rb', line 6975
def enclosing_function
find_ancestor(FunctionDefAst)
end
|
#gen_adoc(indent = 0, indent_spaces: 2) ⇒ Object
35
36
37
|
# File 'lib/idlc/passes/gen_adoc.rb', line 35
def gen_adoc(indent = 0, indent_spaces: 2)
"#{' ' * indent}return #{return_value_nodes.map { |r| r.gen_adoc(0, indent_spaces:) }.join(', ')}"
end
|
#gen_option_adoc ⇒ Object
115
116
117
118
119
|
# File 'lib/idlc/passes/gen_option_adoc.rb', line 115
def gen_option_adoc
raise "unexpected" if return_value_nodes.size != 1
return_value_nodes[0].gen_option_adoc
end
|
#prune(symtab, forced_type: nil) ⇒ Object
877
878
879
|
# File 'lib/idlc/passes/prune.rb', line 877
def prune(symtab, forced_type: nil)
ReturnExpressionAst.new(input, interval, return_value_nodes.map { |n| n.prune(symtab) })
end
|
#return_type(symtab) ⇒ Object
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
|
# File 'lib/idlc/ast.rb', line 6948
def return_type(symtab)
types = return_types(symtab)
if types.empty?
return Type.new(:void)
elsif types.size > 1
Type.new(:tuple, tuple_types: types)
else
types.fetch(0)
end
end
|
#return_types(symtab) ⇒ Object
6936
6937
6938
6939
6940
6941
6942
6943
6944
|
# File 'lib/idlc/ast.rb', line 6936
def return_types(symtab)
if return_value_nodes.empty?
[Type.new(:void)]
elsif 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
6980
6981
6982
6983
6984
6985
6986
6987
6988
|
# File 'lib/idlc/ast.rb', line 6980
def return_value(symtab)
if return_value_nodes.empty?
:void
elsif 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
6927
|
# File 'lib/idlc/ast.rb', line 6927
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
6991
6992
6993
6994
6995
6996
6997
6998
6999
|
# File 'lib/idlc/ast.rb', line 6991
def return_values(symtab)
if return_value_nodes.empty?
[:void]
elsif return_value_nodes.size == 1
return_value_nodes[0].values(symtab)
else
return_value_nodes.map { |v| v.values(symtab) }
end
end
|
#to_h ⇒ Object
7005
7006
7007
7008
7009
|
# File 'lib/idlc/ast.rb', line 7005
def to_h = {
"kind" => "return_expr",
"exprs" => return_value_nodes.map(&:to_h),
"source" => source_yaml
}
|
#to_idl ⇒ Object
7002
|
# File 'lib/idlc/ast.rb', line 7002
def to_idl = "return #{return_value_nodes.map(&:to_idl).join(',')}"
|
#type_check(symtab, strict:) ⇒ 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
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
|
# File 'lib/idlc/ast.rb', line 6960
def type_check(symtab, strict:)
return_value_nodes.each do |v|
v.type_check(symtab, strict:)
type_error "Unknown type for #{v.text_value}" if v.type(symtab).nil?
end
if !return_value_nodes.empty? && 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 convertible to expected return type (#{expected_return_type(symtab)})"
end
end
|