Class: Mirah::AST::If

Inherits:
Node
  • Object
show all
Defined in:
lib/mirah/ast/flow.rb,
lib/mirah/compiler/flow.rb,
lib/mirah/jvm/source_generator/precompile.rb

Instance Attribute Summary

Attributes inherited from Node

#children, #inferred_type, #newline, #parent, #position

Instance Method Summary collapse

Methods inherited from Node

#<<, ===, #[], #[]=, #_dump, _load, #_set_parent, child, child_name, #child_nodes, #each, #empty?, #inferred_type!, #initialize_copy, #insert, #inspect, #inspect_children, #line_number, #log, #precompile, #resolve_if, #resolved!, #resolved?, #simple_name, #string_value, #temp, #to_s, #top_level?, #validate_child, #validate_children

Constructor Details

#initialize(parent, line_number, &block) ⇒ If

Returns a new instance of If.



49
50
51
# File 'lib/mirah/ast/flow.rb', line 49

def initialize(parent, line_number, &block)
  super(parent, line_number, &block)
end

Instance Method Details

#compile(compiler, expression) ⇒ Object



19
20
21
22
23
24
# File 'lib/mirah/compiler/flow.rb', line 19

def compile(compiler, expression)
  compiler.line(line_number)
  compiler.branch(self, expression)
rescue Exception => ex
  raise Mirah::InternalCompilerError.wrap(ex, self)
end

#expr?(compiler) ⇒ Boolean

Returns:



65
66
67
68
69
70
# File 'lib/mirah/jvm/source_generator/precompile.rb', line 65

def expr?(compiler)
  return false unless condition.predicate.expr?(compiler)
  return false unless body.nil? || body.expr?(compiler)
  return false unless self.else.nil? || self.else.expr?(compiler)
  true
end

#infer(typer, expression) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/mirah/ast/flow.rb', line 53

def infer(typer, expression)
  unless resolved?
    condition_type = typer.infer(condition, true)
    unless condition_type
      typer.defer(condition)
    end

    # condition type is unrelated to body types, so we proceed with bodies
    then_type = typer.infer(body, expression) if body
    else_type = typer.infer(self.else, expression) if self.else

    if expression
      have_body_type = body.nil? || then_type
      have_else_type = self.else.nil? || else_type
      
      if have_body_type && have_else_type
        if then_type && else_type
          # both then and else inferred, ensure they're compatible
          if then_type.compatible?(else_type)
            # types are compatible...if condition is resolved, we're done
            @inferred_type = then_type.narrow(else_type)
            resolved! if condition_type
          else
            raise Mirah::Typer::InferenceError.new("if statement with incompatible result types #{then_type} and #{else_type}")
          end
        else
          @inferred_type = then_type || else_type
          resolved!
        end
      else
        typer.defer(self)
      end
    else
      @inferred_type = typer.no_type
      resolved!
    end
  end

  @inferred_type
end