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.
8794 8795 8796 8797 8798 8799 8800 |
# File 'lib/idlc/ast.rb', line 8794 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
8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 |
# File 'lib/idlc/ast.rb', line 8910 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
8786 8787 8788 |
# File 'lib/idlc/ast.rb', line 8786 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
8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894 |
# File 'lib/idlc/ast.rb', line 8871 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
8816 8817 8818 8819 |
# File 'lib/idlc/ast.rb', line 8816 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
8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 |
# File 'lib/idlc/ast.rb', line 8822 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
8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 |
# File 'lib/idlc/ast.rb', line 8843 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
8791 |
# File 'lib/idlc/ast.rb', line 8791 def stmts = T.cast(@children, T::Array[StatementAst]) |
#to_h ⇒ Object
8903 8904 8905 8906 8907 |
# File 'lib/idlc/ast.rb', line 8903 def to_h = { "kind" => "if_body", "stmts" => stmts.map(&:to_h), "source" => source_yaml } |
#to_idl ⇒ Object
8898 8899 8900 |
# File 'lib/idlc/ast.rb', line 8898 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
8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 |
# File 'lib/idlc/ast.rb', line 8803 def type_check(symtab, strict:) symtab.push(self) begin stmts.each do |s| s.type_check(symtab, strict:) end ensure symtab.pop end end |