Class: Idl::IfBodyAst
- Includes:
- Executable, 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
- #always_terminates? ⇒ Boolean
- #const_eval?(symtab) ⇒ Boolean
-
#execute(symtab) ⇒ void
“execute” the statement by updating the variables in the symbol table.
- #gen_adoc(indent = 0, indent_spaces: 2) ⇒ Object
- #gen_option_adoc ⇒ Object
-
#initialize(input, interval, body_stmts) ⇒ IfBodyAst
constructor
A new instance of IfBodyAst.
- #prune(symtab, restore: true, forced_type: nil) ⇒ Object
- #return_type(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_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.
- #stmts ⇒ Object
- #to_h ⇒ Object
- #to_idl ⇒ Object
-
#type_check(symtab, strict:) ⇒ void
type check this node and all children.
Methods included from Returns
Methods included from Executable
Methods inherited from AstNode
#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, body_stmts) ⇒ IfBodyAst
Returns a new instance of IfBodyAst.
8809 8810 8811 8812 8813 8814 8815 |
# File 'lib/idlc/ast.rb', line 8809 def initialize(input, interval, body_stmts) if body_stmts.empty? super("", 0...0, EMPTY_ARRAY) else super(input, interval, body_stmts) end end |
Class Method Details
.from_h(yaml, source_mapper) ⇒ Object
8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 |
# File 'lib/idlc/ast.rb', line 8925 def self.from_h(yaml, source_mapper) raise "Bad YAML" unless yaml.key?("kind") && yaml.fetch("kind") == "if_body" input = input_from_source_yaml(yaml.fetch("source"), source_mapper) interval = interval_from_source_yaml(yaml.fetch("source")) IfBodyAst.new( input, interval, yaml.fetch("stmts").map { |s| AstNode.from_h(s, source_mapper) } ) end |
Instance Method Details
#always_terminates? ⇒ Boolean
492 493 494 |
# File 'lib/idlc/passes/prune.rb', line 492 def always_terminates? !stmts.empty? && stmts.last.always_terminates? end |
#const_eval?(symtab) ⇒ Boolean
8801 8802 8803 |
# File 'lib/idlc/ast.rb', line 8801 def const_eval?(symtab) stmts.all? { |stmt| stmt.const_eval?(symtab) } end |
#execute(symtab) ⇒ void
This method returns an undefined value.
“execute” the statement by updating the variables in the symbol table
8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 |
# File 'lib/idlc/ast.rb', line 8886 def execute(symtab) err = T.let(nil, T.nilable(Symbol)) stmts.each do |s| value_result = value_try do if s.is_a?(Returns) value_result2 = value_try do v = s.return_value(symtab) break unless v.nil? # nil means this is a conditional return and the condition is false end value_else(value_result2) do # not known, keep going err = :value_error end else s.execute(symtab) end end value_else(value_result) do # keep going so that we invalidate everything err = :value_error end end throw err unless err.nil? end |
#gen_adoc(indent = 0, indent_spaces: 2) ⇒ Object
40 41 42 43 44 45 46 |
# File 'lib/idlc/passes/gen_adoc.rb', line 40 def gen_adoc(indent = 0, indent_spaces: 2) adoc = [] children.each do |e| adoc << e.gen_adoc(indent, indent_spaces:) end adoc.join("\n") end |
#gen_option_adoc ⇒ Object
71 72 73 |
# File 'lib/idlc/passes/gen_option_adoc.rb', line 71 def gen_option_adoc stmts.map(&:gen_option_adoc).join("\n") end |
#prune(symtab, restore: true, forced_type: nil) ⇒ Object
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
# File 'lib/idlc/passes/prune.rb', line 496 def prune(symtab, restore: true, forced_type: nil) pruned_stmts = [] symtab.push(nil) snapshot = symtab.snapshot_values if restore stmts.each do |s| pruned_stmts << s.prune(symtab) break if pruned_stmts.last.always_terminates? end if restore symtab.restore_values(snapshot) end symtab.pop IfBodyAst.new(input, interval, pruned_stmts) end |
#return_type(symtab) ⇒ Object
8831 8832 8833 8834 |
# File 'lib/idlc/ast.rb', line 8831 def return_type(symtab) # the return type is determined by the function t = expected_return_type(symtab) 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
8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 |
# File 'lib/idlc/ast.rb', line 8837 def return_value(symtab) symtab.push(self) begin stmts.each do |s| if s.is_a?(Returns) v = s.return_value(symtab) unless v.nil? return v end else s.execute(symtab) end end ensure symtab.pop end nil end |
#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
8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 |
# File 'lib/idlc/ast.rb', line 8858 def return_values(symtab) values = T.let([], T::Array[ValueRbType]) symtab.push(self) begin value_try do stmts.each do |s| if s.is_a?(Returns) value_result = value_try do v = s.return_value(symtab) return values.push(v).uniq unless v.nil? end value_else(value_result) do values += s.return_values(symtab) end else s.execute(symtab) end end end ensure symtab.pop end values.uniq end |
#stmts ⇒ Object
8806 |
# File 'lib/idlc/ast.rb', line 8806 def stmts = T.cast(@children, T::Array[StatementAst]) |
#to_h ⇒ Object
8918 8919 8920 8921 8922 |
# File 'lib/idlc/ast.rb', line 8918 def to_h = { "kind" => "if_body", "stmts" => stmts.map(&:to_h), "source" => source_yaml } |
#to_idl ⇒ Object
8913 8914 8915 |
# File 'lib/idlc/ast.rb', line 8913 def to_idl stmts.map(&:to_idl).join("") end |
#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
8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 |
# File 'lib/idlc/ast.rb', line 8818 def type_check(symtab, strict:) symtab.push(self) begin stmts.each do |s| s.type_check(symtab, strict:) end ensure symtab.pop end end |