Class: Duby::Compiler::JVMCompilerBase

Inherits:
Object
  • Object
show all
Defined in:
lib/duby/jvm/base.rb

Direct Known Subclasses

JVM, JavaSource

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename) ⇒ JVMCompilerBase

Returns a new instance of JVMCompilerBase.



6
7
8
9
10
11
12
13
14
# File 'lib/duby/jvm/base.rb', line 6

def initialize(filename)
  @filename = File.basename(filename)
  @static = true
  classname = JVM.classname_from_filename(filename)
  @type = AST::type(classname)
  @jump_scope = []
  @bindings = Hash.new {|h, type| h[type] = type.define(@file)}
  @captured_locals = Hash.new {|h, binding| h[binding] = {}}
end

Instance Attribute Details

#classObject

Returns the value of attribute class.



4
5
6
# File 'lib/duby/jvm/base.rb', line 4

def class
  @class
end

#filenameObject

Returns the value of attribute filename.



4
5
6
# File 'lib/duby/jvm/base.rb', line 4

def filename
  @filename
end

#methodObject

Returns the value of attribute method.



4
5
6
# File 'lib/duby/jvm/base.rb', line 4

def method
  @method
end

#staticObject

Returns the value of attribute static.



4
5
6
# File 'lib/duby/jvm/base.rb', line 4

def static
  @static
end

Instance Method Details

#begin_mainObject



67
# File 'lib/duby/jvm/base.rb', line 67

def begin_main; end

#body(body, expression) {|| ... } ⇒ Object

Yields:

  • ()


160
161
162
163
164
165
166
167
168
# File 'lib/duby/jvm/base.rb', line 160

def body(body, expression)
  # all except the last element in a body of code is treated as a statement
  i, last = 0, body.children.size - 1
  while i < last
    body.children[i].compile(self, false)
    i += 1
  end
  yield body.children[last] if last >= 0
end

#compile(ast, expression = false) ⇒ Object



16
17
18
19
# File 'lib/duby/jvm/base.rb', line 16

def compile(ast, expression = false)
  ast.compile(self, expression)
  log "Compilation successful!"
end

#constructor(node, args_are_types) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/duby/jvm/base.rb', line 131

def constructor(node, args_are_types)
  args = node.arguments.args || []
  arg_types = if args_are_types
    args.map { |arg| arg.inferred_type }
  else
    args
  end
  exceptions = node.signature[:throws]
  method = @class.public_constructor(exceptions, *arg_types)
  annotate(method, node.annotations)
  with :current_scope => node.static_scope do
    yield(method, args)
  end
end

#declare_argument(name, type) ⇒ Object



156
157
158
# File 'lib/duby/jvm/base.rb', line 156

def declare_argument(name, type)
  # declare local vars for arguments here
end

#declared_captures(binding = nil) ⇒ Object



189
190
191
# File 'lib/duby/jvm/base.rb', line 189

def declared_captures(binding=nil)
  @captured_locals[binding || @binding]
end

#define_class(class_def, expression) ⇒ Object



146
147
148
149
150
151
152
153
154
# File 'lib/duby/jvm/base.rb', line 146

def define_class(class_def, expression)
  with(:type => class_def.inferred_type,
       :class => class_def.inferred_type.define(@file),
       :static => false) do
    annotate(@class, class_def.annotations)
    class_def.body.compile(self, false) if class_def.body
    @class.stop
  end
end

#define_main(script) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/duby/jvm/base.rb', line 40

def define_main(script)
  body = script.body
  body = body[0] if body.children.size == 1
  if body.class != AST::ClassDefinition
    @class = @type.define(@file)
    with :method => @class.main do
      log "Starting main method"

      @method.start
      @current_scope = script.static_scope
      begin_main

      prepare_binding(script) do
        body.compile(self, false)
      end

      finish_main
      @method.stop
    end
    @class.stop
  else
    body.compile(self, false)
  end

  log "Main method complete!"
end

#define_method(node, args_are_types) ⇒ Object



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
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/duby/jvm/base.rb', line 70

def define_method(node, args_are_types)
  name, signature, args = node.name, node.signature, node.arguments.args
  if name == "initialize" && node.static?
    name = "<clinit>"
  end
  if args_are_types
    arg_types = args.map { |arg| arg.inferred_type } if args
  else
    arg_types = args
  end
  arg_types ||= []
  return_type = signature[:return]
  exceptions = signature[:throws]
  puts "exceptions: #{exceptions.inspect}" if exceptions && exceptions.size > 0

  with :static => @static || node.static?, :current_scope => node.static_scope do
    if @static
      method = @class.public_static_method(name.to_s, exceptions, return_type, *arg_types)
    else
      method = @class.public_method(name.to_s, exceptions, return_type, *arg_types)
    end
    annotate(method, node.annotations)
    yield method, arg_types
  end

  arg_types_for_opt = []
  args_for_opt = []
  if args
    args.each do |arg|
      if AST::OptionalArgument === arg
        new_args = if args_are_types
          arg_types_for_opt
        else
          args_for_opt
        end
        if @static
          method = @class.public_static_method(name.to_s, exceptions, return_type, *new_args)
        else
          method = @class.public_method(name.to_s, exceptions, return_type, *new_args)
        end

        with :method => method do
          log "Starting new method #{name}(#{arg_types_for_opt})"

          annotate(method, node.annotations)
          @method.start

          define_optarg_chain(name, arg,
                              return_type,
                              args_for_opt,
                              arg_types_for_opt)

          @method.stop
        end
      end
      arg_types_for_opt << arg.inferred_type
      args_for_opt << arg
    end
  end
end

#finish_mainObject



68
# File 'lib/duby/jvm/base.rb', line 68

def finish_main; end

#generateObject



27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/duby/jvm/base.rb', line 27

def generate
  log "Generating #{output_type}..."
  @file.generate do |filename, builder|
    log "  #{builder.class_name}"
    if block_given?
      yield filename, builder
    else
      File.open(filename, 'w') {|f| f.write(builder.generate)}
    end
  end
  log "...done!"
end

#get_binding(type) ⇒ Object



185
186
187
# File 'lib/duby/jvm/base.rb', line 185

def get_binding(type)
  @bindings[type]
end

#import(short, long) ⇒ Object



182
183
# File 'lib/duby/jvm/base.rb', line 182

def import(short, long)
end

#log(message) ⇒ Object



21
# File 'lib/duby/jvm/base.rb', line 21

def log(message); JVM.log(message); end

#scoped_body(scope, expression) ⇒ Object



170
171
172
# File 'lib/duby/jvm/base.rb', line 170

def scoped_body(scope, expression)
  body(scope, expression)
end

#scoped_local_name(name, scope = nil) ⇒ Object



174
175
176
177
178
179
180
# File 'lib/duby/jvm/base.rb', line 174

def scoped_local_name(name, scope=nil)
  if scope.nil? || scope == @current_scope
    name
  else
    "#{name}$#{scope.object_id}"
  end
end

#toplevel_classObject



23
24
25
# File 'lib/duby/jvm/base.rb', line 23

def toplevel_class
  @class = @type.define(@file)
end

#with(vars) ⇒ Object



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/duby/jvm/base.rb', line 193

def with(vars)
  orig_values = {}
  begin
    vars.each do |name, new_value|
      name = "@#{name}"
      orig_values[name] = instance_variable_get name
      instance_variable_set name, new_value
    end
    yield
  ensure
    orig_values.each do |name, value|
      instance_variable_set name, value
    end
  end
end