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.
6914
6915
6916
6917
|
# File 'lib/idlc/ast.rb', line 6914
def initialize(input, interval, return_nodes)
super(input, interval, return_nodes)
@func_type_cache = {}
end
|
Class Method Details
.from_h(yaml, source_mapper) ⇒ Object
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
|
# File 'lib/idlc/ast.rb', line 6997
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
6910
|
# File 'lib/idlc/ast.rb', line 6910
def const_eval?(symtab) = return_value_nodes.all? { |node| node.const_eval?(symtab) }
|
#enclosing_function ⇒ Object
6960
6961
6962
|
# File 'lib/idlc/ast.rb', line 6960
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
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
|
# File 'lib/idlc/ast.rb', line 6933
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
6921
6922
6923
6924
6925
6926
6927
6928
6929
|
# File 'lib/idlc/ast.rb', line 6921
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
6965
6966
6967
6968
6969
6970
6971
6972
6973
|
# File 'lib/idlc/ast.rb', line 6965
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
6912
|
# File 'lib/idlc/ast.rb', line 6912
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
6976
6977
6978
6979
6980
6981
6982
6983
6984
|
# File 'lib/idlc/ast.rb', line 6976
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
6990
6991
6992
6993
6994
|
# File 'lib/idlc/ast.rb', line 6990
def to_h = {
"kind" => "return_expr",
"exprs" => return_value_nodes.map(&:to_h),
"source" => source_yaml
}
|
#to_idl ⇒ Object
6987
|
# File 'lib/idlc/ast.rb', line 6987
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
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
|
# File 'lib/idlc/ast.rb', line 6945
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
|