Class: BiteScript::ClassBuilder

Inherits:
Object
  • Object
show all
Includes:
ASM, Annotatable, QuickTypes, Signature, Util
Defined in:
lib/bitescript/builder.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Signature

ci, class_id, classname, path, sig, signature

Methods included from Annotatable

#annotate

Methods included from QuickTypes

#boolean, #byte, #char, #double, #float, #int, #long, #null, #object, #short, #string, #void

Methods included from Util

#type_from_dotted

Constructor Details

#initialize(file_builder, class_name, file_name, opts) ⇒ ClassBuilder

Returns a new instance of ClassBuilder.



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/bitescript/builder.rb', line 214

def initialize(file_builder, class_name, file_name, opts) 
  @parent = file_builder
  @class_name = class_name
  @superclass = opts[:superclass] || Object
  @interfaces = opts[:interfaces] || []
  @interface = opts[:interface]
  flags = Opcodes::ACC_SUPER
  if @interface
    flags = Opcodes::ACC_INTERFACE | Opcodes::ACC_ABSTRACT
  end
  
  @class_writer = ClassWriter.new(ClassWriter::COMPUTE_MAXS)
  
  interface_paths = []
  (@interfaces).each {|interface| interface_paths << path(interface)}

  visibility = case (opts[:visibility] && opts[:visibility].to_sym)
    when nil
      Opcodes::ACC_PUBLIC  # NOTE Not specified means public -- must explicitly ask for default
    when :default
      0
    when :public
      Opcodes::ACC_PUBLIC
    when :private
      Opcodes::ACC_PRIVATE
    when :protected
      Opcodes::ACC_PROTECTED
    else
      raise "Unknown visibility: #{opts[:visibility]}"
  end

  @class_writer.visit(BiteScript.bytecode_version, visibility | flags, class_name, nil, path(superclass), interface_paths.to_java(:string))
  @class_writer.visit_source(file_name, nil)

  @constructor = nil
  @constructors = {}
  @methods = {}
  
  @imports = {}
  
  @fields = {}
end

Instance Attribute Details

#class_nameObject

Returns the value of attribute class_name.



206
207
208
# File 'lib/bitescript/builder.rb', line 206

def class_name
  @class_name
end

#constructorsObject

Returns the value of attribute constructors.



208
209
210
# File 'lib/bitescript/builder.rb', line 208

def constructors
  @constructors
end

#fieldsObject

Returns the value of attribute fields.



211
212
213
# File 'lib/bitescript/builder.rb', line 211

def fields
  @fields
end

#importsObject

Returns the value of attribute imports.



210
211
212
# File 'lib/bitescript/builder.rb', line 210

def imports
  @imports
end

#interfacesObject

Returns the value of attribute interfaces.



212
213
214
# File 'lib/bitescript/builder.rb', line 212

def interfaces
  @interfaces
end

#methodsObject

Returns the value of attribute methods.



209
210
211
# File 'lib/bitescript/builder.rb', line 209

def methods
  @methods
end

#superclassObject

Returns the value of attribute superclass.



207
208
209
# File 'lib/bitescript/builder.rb', line 207

def superclass
  @superclass
end

Instance Method Details

#array?Boolean

never generating an array

Returns:

  • (Boolean)


380
381
382
# File 'lib/bitescript/builder.rb', line 380

def array?
  false
end

#constructor(*params) ⇒ Object



360
361
362
# File 'lib/bitescript/builder.rb', line 360

def constructor(*params)
  constructors[params] or raise NameError.new("failed to find constructor #{sig(params)} on #{self}")
end

#field(flags, name, type) ⇒ Object



369
370
371
372
# File 'lib/bitescript/builder.rb', line 369

def field(flags, name, type)
  field = @class_writer.visit_field(flags, name, ci(type), nil, nil)
  field.extend Annotatable
end

#generateObject



272
273
274
# File 'lib/bitescript/builder.rb', line 272

def generate
  String.from_java_bytes(@class_writer.to_byte_array)
end

#interface?Boolean

Returns:

  • (Boolean)


364
365
366
367
# File 'lib/bitescript/builder.rb', line 364

def interface?
  # TODO: interface types
  @interface
end

#java_method(name, *params) ⇒ Object



346
347
348
349
350
351
352
# File 'lib/bitescript/builder.rb', line 346

def java_method(name, *params)
  if methods[name]
    method = methods[name][params]
  end

  method or raise NameError.new("failed to find method #{name}#{sig(params)} on #{self}")
end

#macro(name, &b) ⇒ Object



406
407
408
# File 'lib/bitescript/builder.rb', line 406

def macro(name, &b)
  MethodBuilder.send :define_method, name, &b
end

#main(&b) ⇒ Object



354
355
356
357
358
# File 'lib/bitescript/builder.rb', line 354

def main(&b)
  raise "already defined main" if methods[name]

  public_static_method "main", [], void, string[], &b
end

#method(flags, name, signature, exceptions, &block) ⇒ Object



319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/bitescript/builder.rb', line 319

def method(flags, name, signature, exceptions, &block)
  flags |= Opcodes::ACC_ABSTRACT if interface?
  mb = MethodBuilder.new(self, flags, name, exceptions, signature)

  if name == "<init>"
    constructors[signature[1..-1]] = mb
  else
    methods[name] ||= {}
    methods[name][signature[1..-1]] = mb
  end

  # non-static methods reserve index 0 for 'this'
  mb.local 'this', self if (flags & Opcodes::ACC_STATIC) == 0
  
  if block_given? && !interface?
    mb.start
    if block.arity == 1
      block.call(mb)
    else
      mb.instance_eval(&block)
    end
    mb.stop
  end

  mb
end

#nameObject

name for signature generation using the class being generated



375
376
377
# File 'lib/bitescript/builder.rb', line 375

def name
  @class_name
end

#new_method(modifiers, name, signature, exceptions) ⇒ Object



397
398
399
400
401
402
403
404
# File 'lib/bitescript/builder.rb', line 397

def new_method(modifiers, name, signature, exceptions)
  exceptions ||= []
  unless exceptions.kind_of?(Array)
    raise ArgumentError, "Expected array of exceptions, got #{exceptions.inspect}"
  end
  exceptions = exceptions.map {|e| path(e)}
  @class_writer.visit_method(modifiers, name, sig(*signature), nil, exceptions.to_java(:string))
end

#primitive?Boolean

never generating a primitive

Returns:

  • (Boolean)


385
386
387
# File 'lib/bitescript/builder.rb', line 385

def primitive?
  false
end

#startObject



257
258
# File 'lib/bitescript/builder.rb', line 257

def start
end

#static_init(&block) ⇒ Object



315
316
317
# File 'lib/bitescript/builder.rb', line 315

def static_init(&block)
  method(Opcodes::ACC_STATIC, "<clinit>", [void], [], &block)
end

#stopObject



260
261
262
263
264
265
266
267
268
269
270
# File 'lib/bitescript/builder.rb', line 260

def stop
  # if we haven't seen a constructor, generate a default one
  unless @constructor || @interface
    method = public_constructor([])
    method.start
    method.aload 0
    method.invokespecial @superclass, "<init>", [Void::TYPE]
    method.returnvoid
    method.stop
  end
end

#thisObject



389
390
391
# File 'lib/bitescript/builder.rb', line 389

def this
  self
end

#visit_annotation(*args) ⇒ Object



393
394
395
# File 'lib/bitescript/builder.rb', line 393

def visit_annotation(*args)
  @class_writer.visit_annotation(*args)
end