Class: Mirah::AST::FunctionalCall

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

Instance Attribute Summary collapse

Attributes included from Named

#name

Attributes inherited from Node

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

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Scoped

#containing_scope, #scope

Methods included from Named

#string_value, #to_s, #validate_name

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, name, &kids) ⇒ FunctionalCall

Returns a new instance of FunctionalCall.



32
33
34
35
36
# File 'lib/mirah/ast/call.rb', line 32

def initialize(parent, line_number, name, &kids)
  super(parent, line_number, &kids)
  self.name = name
  @cast = false
end

Instance Attribute Details

#castObject Also known as: cast?

Returns the value of attribute cast.



21
22
23
# File 'lib/mirah/ast/call.rb', line 21

def cast
  @cast
end

#inlinedObject

Returns the value of attribute inlined.



21
22
23
# File 'lib/mirah/ast/call.rb', line 21

def inlined
  @inlined
end

#proxyObject

Returns the value of attribute proxy.



21
22
23
# File 'lib/mirah/ast/call.rb', line 21

def proxy
  @proxy
end

#targetObject

Returns the value of attribute target.



46
47
48
# File 'lib/mirah/ast/call.rb', line 46

def target
  nil
end

Class Method Details

.new(*args, &block) ⇒ Object



27
28
29
30
# File 'lib/mirah/ast/call.rb', line 27

def self.new(*args, &block)
  real_node = super
  real_node.proxy = NodeProxy.new(real_node)
end

Instance Method Details

#argumentsObject



38
39
40
41
42
43
44
# File 'lib/mirah/ast/call.rb', line 38

def arguments
  args = java.util.ArrayList.new(parameters.size)
  parameters.each do |param|
    args.add(param)
  end
  args
end

#compile(compiler, expression) ⇒ Object



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

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

#expr?(compiler) ⇒ Boolean

Returns:



117
118
119
120
# File 'lib/mirah/jvm/source_generator/precompile.rb', line 117

def expr?(compiler)
  parameters.all? {|p| p.expr?(compiler)} &&
      (cast? || !method(compiler).return_type.void?)
end

#infer(typer, expression) ⇒ Object



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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/mirah/ast/call.rb', line 61

def infer(typer, expression)
  unless @inferred_type
    @self_type ||= scope.static_scope.self_type
    receiver_type = @self_type
    should_defer = false

    parameter_types = parameters.map do |param|
      typer.infer(param, true) || should_defer = true
    end

    parameter_types << Mirah::AST.block_type if block

    unless should_defer
      if parameters.size == 1 && typer.known_type(scope, name)
        # cast operation
        resolved!
        self.cast = true
        @inferred_type = typer.known_type(scope, name)
      elsif parameters.size == 0 && scope.static_scope.include?(name)
        @inlined = Local.new(parent, position, name)
        proxy.__inline__(@inlined)
        return proxy.infer(typer, expression)
      else
        @inferred_type = typer.method_type(receiver_type, name,
                                           parameter_types)
        if @inferred_type.kind_of? InlineCode
          @inlined = @inferred_type.inline(typer.transformer, self)
          proxy.__inline__(@inlined)
          return proxy.infer(typer, expression)
        end
      end
    end

    if @inferred_type && !@inferred_type.error?
      if block
        method = receiver_type.get_method(name, parameter_types)
        block.prepare(typer, method)
      end
      @inferred_type = receiver_type if @inferred_type.void?
      resolved!
    else
      if should_defer || receiver_type.nil?
        message = nil
      else
        parameter_names = parameter_types.map {|t| t.full_name}.join(', ')
        receiver = receiver_type.full_name
        desc = "#{name}(#{parameter_names})"
        kind = receiver_type.meta? ? "static" : "instance"
        message = "Cannot find #{kind} method #{desc} on #{receiver}"
      end
      typer.defer(proxy, message)
    end
  end

  @inferred_type
end

#method(compiler) ⇒ Object



110
111
112
113
114
115
# File 'lib/mirah/jvm/source_generator/precompile.rb', line 110

def method(compiler)
  @method ||= begin
    arg_types = parameters.map {|p| p.inferred_type}
    @self_type.get_method(name, arg_types)
  end
end

#type_reference(typer) ⇒ Object



118
119
120
# File 'lib/mirah/ast/call.rb', line 118

def type_reference(typer)
  typer.type_reference(scope, name)
end

#validate_parametersObject



50
51
52
53
54
55
56
57
58
59
# File 'lib/mirah/ast/call.rb', line 50

def validate_parameters
  parameters.each_with_index do |child, i|
    if UnquotedValue === child
      children = child.nodes
      children.each {|c| c.parent = self}
      parameters[i] = children
    end
  end
  parameters.flatten!
end