bitescript 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,14 @@
1
+ === 0.0.8 / 2011-03-05
2
+
3
+ * Support parsing of generic signatures
4
+ * Update ASM reference to work with JRuby >=1.6.0.RC3 name mangling
5
+
6
+ === 0.0.7 / 2010-11-10
7
+
8
+ * Fix some likely label collisions
9
+ * Class mirror and annotation fixes
10
+ * Post-generate verification
11
+
1
12
  === 0.0.6 / 2010-06-09
2
13
 
3
14
  * Move to a class mirror API rather than loading and walking real classes
data/README.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  = bitescript
2
2
 
3
- http://kenai.com/projects/jvmscript
3
+ http://github.com/headius/bitescript
4
4
 
5
5
  == DESCRIPTION:
6
6
 
@@ -16,7 +16,7 @@ include BiteScript
16
16
 
17
17
  fb = FileBuilder.build(__FILE__) do
18
18
  public_class "SimpleLoop" do
19
- public_static_method "main", void, string[] do
19
+ public_static_method "main", [], void, string[] do
20
20
  aload 0
21
21
  push_int 0
22
22
  aaload
@@ -45,7 +45,7 @@ gem install bitescript
45
45
 
46
46
  == LICENSE:
47
47
 
48
- Copyright (c) 2009, Charles Oliver Nutter
48
+ Copyright (c) 2009-2011, Charles Oliver Nutter
49
49
  All rights reserved.
50
50
 
51
51
  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
data/bitescript.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{bitescript}
5
- s.version = "0.0.7"
5
+ s.version = "0.0.8"
6
6
  s.authors = ["Charles Oliver Nutter", "Ryan Brown"]
7
7
  s.date = Time.now.strftime('YYYY-MM-DD')
8
8
  s.description = %q{BiteScript is a Ruby DSL for generating Java bytecode and classes.}
@@ -0,0 +1,13 @@
1
+ main do
2
+ ldc 'hello'
3
+ instanceof java.lang.CharSequence
4
+ ifeq :not
5
+ ldc 'is instance of!'
6
+ aprintln
7
+ goto :end
8
+ label :not
9
+ ldc 'not instance of!'
10
+ aprintln
11
+ label :end
12
+ returnvoid
13
+ end
@@ -3,16 +3,25 @@ require 'java'
3
3
  module BiteScript
4
4
  module ASM
5
5
  begin
6
- # try mangled names for the version included with JRuby
6
+ # try mangled names for the version included with JRuby <=1.6.0.RC2
7
7
  java.lang.Class.for_name 'jruby.objectweb.asm.Opcodes'
8
8
 
9
9
  # no error, proceed with mangled name
10
10
  asm_package = Java::jruby.objectweb.asm
11
11
  java_import asm_package.Opcodes
12
12
  rescue Exception
13
- # fall back on standard names
14
- asm_package = org.objectweb.asm
15
- java_import asm_package.Opcodes
13
+ begin
14
+ # try mangled names for the version included with JRuby >=1.6.0.RC3
15
+ java.lang.Class.for_name 'org.jruby.org.objectweb.asm.Opcodes'
16
+
17
+ # no error, proceed with mangled name
18
+ asm_package = Java::org.jruby.org.objectweb.asm
19
+ java_import asm_package.Opcodes
20
+ rescue
21
+ # fall back on standard names
22
+ asm_package = org.objectweb.asm
23
+ java_import asm_package.Opcodes
24
+ end
16
25
  end
17
26
  java_import asm_package.Label
18
27
  java_import asm_package.Type
@@ -23,5 +32,8 @@ module BiteScript
23
32
  java_import asm_package.ClassReader
24
33
  java_import asm_package.ClassWriter
25
34
  java_import asm_package.util.CheckClassAdapter
35
+ java_import asm_package.signature.SignatureReader
36
+ java_import asm_package.signature.SignatureVisitor
37
+ java_import asm_package.signature.SignatureWriter
26
38
  end
27
39
  end
@@ -168,7 +168,7 @@ module BiteScript::ASM
168
168
  include Modifiers
169
169
 
170
170
  attr_reader :type, :interfaces
171
- attr_accessor :superclass
171
+ attr_accessor :superclass, :signature
172
172
 
173
173
  def initialize(type, flags)
174
174
  super()
@@ -248,6 +248,18 @@ module BiteScript::ASM
248
248
  @fields[field.name] = field
249
249
  end
250
250
 
251
+ def type_parameters
252
+ signature.type_parameters is signature
253
+ end
254
+
255
+ def generic_superclass
256
+ signature.superclass if signature
257
+ end
258
+
259
+ def generic_interfaces
260
+ signature.interfaces if signature
261
+ end
262
+
251
263
  def inspect
252
264
  if annotation?
253
265
  kind = "@interface"
@@ -285,6 +297,7 @@ module BiteScript::ASM
285
297
  def visit(version, access, name, signature, super_name, interfaces)
286
298
  @current = @class = ClassMirror.new(Type.getObjectType(name), access)
287
299
  @class.superclass = Type.getObjectType(super_name) if super_name
300
+ @class.signature = SignatureMirror.new(signature) if signature
288
301
  if interfaces
289
302
  interfaces.each do |i|
290
303
  @class.interfaces << Type.getObjectType(i)
@@ -309,7 +322,8 @@ module BiteScript::ASM
309
322
  end
310
323
 
311
324
  def visitField(flags, name, desc, signature, value)
312
- @current = FieldMirror.new(@class.type, flags, name, Type.getType(desc), value)
325
+ signature = GenericTypeBuilder.read(signature)
326
+ @current = FieldMirror.new(@class.type, flags, name, Type.getType(desc), signature, value)
313
327
  @class.addField(@current)
314
328
  self
315
329
  end
@@ -318,8 +332,9 @@ module BiteScript::ASM
318
332
  return_type = Type.getReturnType(desc)
319
333
  parameters = Type.getArgumentTypes(desc).to_a
320
334
  exceptions = (exceptions || []).map {|e| Type.getObjectType(e)}
335
+ signature = SignatureMirror.new(signature) if signature
321
336
  @current = MethodMirror.new(
322
- @class.type, flags, return_type, name, parameters, exceptions)
337
+ @class.type, flags, return_type, name, parameters, exceptions, signature)
323
338
  @class.addMethod(@current)
324
339
  # TODO parameter annotations, default value, etc.
325
340
  self # This isn't legal is it?
@@ -337,13 +352,18 @@ module BiteScript::ASM
337
352
  include Modifiers
338
353
  include Annotated
339
354
 
340
- attr_reader :declaring_class, :name, :type, :value
341
- def initialize(klass, flags, name, type, value)
355
+ attr_reader :declaring_class, :name, :type, :value, :signature
356
+ def initialize(klass, flags, name, type, signature, value)
342
357
  @declaring_class = klass
343
358
  @flags = flags
344
359
  @name = name
345
360
  @type = type
346
361
  @value = value
362
+ @signature = signature
363
+ end
364
+
365
+ def generic_type
366
+ signature
347
367
  end
348
368
 
349
369
  def inspect
@@ -356,8 +376,9 @@ module BiteScript::ASM
356
376
  include Annotated
357
377
 
358
378
  attr_reader :declaring_class, :name, :return_type
359
- attr_reader :argument_types, :exception_types
360
- def initialize(klass, flags, return_type, name, parameters, exceptions)
379
+ attr_reader :argument_types, :exception_types, :signature
380
+
381
+ def initialize(klass, flags, return_type, name, parameters, exceptions, signature)
361
382
  @flags = flags
362
383
  @declaring_class = klass
363
384
  @name = name
@@ -366,6 +387,22 @@ module BiteScript::ASM
366
387
  @exception_types = exceptions
367
388
  end
368
389
 
390
+ def generic_parameter_types
391
+ signature.parameter_types if signature
392
+ end
393
+
394
+ def generic_return_type
395
+ signature.return_type if signature
396
+ end
397
+
398
+ def generic_exception_types
399
+ signature.exception_types if signature
400
+ end
401
+
402
+ def type_parameters
403
+ signature.type_parameters is signature
404
+ end
405
+
369
406
  def inspect
370
407
  "%s%s%s %s(%s);" % [
371
408
  inspect_annotations,
@@ -376,4 +413,237 @@ module BiteScript::ASM
376
413
  ]
377
414
  end
378
415
  end
416
+
417
+ class SignatureMirror
418
+ include BiteScript::ASM::SignatureVisitor
419
+
420
+ attr_reader :type_parameters
421
+ attr_reader :parameter_types, :return_type, :exception_types
422
+ attr_reader :superclass, :interfaces
423
+
424
+ def method?
425
+ return_type != nil
426
+ end
427
+
428
+ def class?
429
+ superclass != nil
430
+ end
431
+
432
+ def initialize(signature=nil)
433
+ @type_parameters = []
434
+ @parameter_types = []
435
+ @exception_types = []
436
+ @interfaces = []
437
+ if (signature)
438
+ reader = BiteScript::ASM::SignatureReader.new(signature)
439
+ reader.accept(self)
440
+ end
441
+ end
442
+
443
+ def visitFormalTypeParameter(name)
444
+ type_parameters << TypeVariable.new(name)
445
+ end
446
+
447
+ def visitClassBound
448
+ GenericTypeBuilder.new {|bound| type_parameters[-1].bounds << bound}
449
+ end
450
+
451
+ def visitInterfaceBound
452
+ GenericTypeBuilder.new {|bound| type_parameters[-1].bounds << bound}
453
+ end
454
+
455
+ def visitParameterType
456
+ GenericTypeBuilder.new {|type| parameter_types << type}
457
+ end
458
+
459
+ def visitReturnType
460
+ GenericTypeBuilder.new {|type| @return_type = type}
461
+ end
462
+
463
+ def visitExceptionType
464
+ GenericTypeBuilder.new {|type| exception_types << type}
465
+ end
466
+
467
+ def visitSuperclass
468
+ GenericTypeBuilder.new {|type| @superclass = type}
469
+ end
470
+
471
+ def visitInterface
472
+ GenericTypeBuilder.new {|type| interfaces << type}
473
+ end
474
+ end
475
+
476
+ class GenericTypeMirror
477
+ def array?
478
+ false
479
+ end
480
+ def wildcard?
481
+ false
482
+ end
483
+ def generic_class?
484
+ false
485
+ end
486
+ def type_variable?
487
+ false
488
+ end
489
+ def inspect
490
+ "<#{self.class.name} #{to_s}>"
491
+ end
492
+ end
493
+
494
+ class TypeVariable < GenericTypeMirror
495
+ attr_reader :name, :bounds
496
+ def initialize(name)
497
+ @name = name
498
+ @bounds = []
499
+ end
500
+ def type_variable?
501
+ true
502
+ end
503
+
504
+ def to_s
505
+ result = "#{name}"
506
+ unless bounds.empty?
507
+ result << ' extends ' << bounds.map {|b| b.to_s}.join(' & ')
508
+ end
509
+ result
510
+ end
511
+ end
512
+
513
+ class GenericArray < GenericTypeMirror
514
+ attr_accessor :component_type
515
+ def array?
516
+ true
517
+ end
518
+ def to_s
519
+ "#{component_type}[]"
520
+ end
521
+ end
522
+
523
+ class Wildcard < GenericTypeMirror
524
+ attr_reader :lower_bound, :upper_bound
525
+ def initialize(upper_bound, lower_bound=nil)
526
+ @upper_bound = upper_bound
527
+ @lower_bound = lower_bound
528
+ end
529
+ def wildcard?
530
+ true
531
+ end
532
+ def to_s?
533
+ if lower_bound
534
+ "? super #{lower_bound}"
535
+ elsif upper_bound
536
+ "? extends #{upper_bound}"
537
+ else
538
+ "?"
539
+ end
540
+ end
541
+ end
542
+
543
+ class ParameterizedType < GenericTypeMirror
544
+ attr_reader :raw_type, :type_arguments, :outer_type
545
+
546
+ def initialize(raw_type, outer_type=nil)
547
+ @raw_type = raw_type
548
+ @type_arguments = []
549
+ @outer_type = outer_type
550
+ end
551
+
552
+ def descriptor
553
+ raw_type.descriptor
554
+ end
555
+
556
+ def generic_class?
557
+ true
558
+ end
559
+
560
+ def to_s
561
+ name = raw_type.internal_name.tr('/', '.')
562
+ unless type_arguments.empty?
563
+ name << "<#{type_arguments.map {|a| a.to_s}.join(', ')}>"
564
+ end
565
+ if outer_type
566
+ "#{outer_type}.#{name}"
567
+ else
568
+ name
569
+ end
570
+ end
571
+ end
572
+
573
+ class GenericTypeBuilder
574
+ include BiteScript::ASM::SignatureVisitor
575
+ attr_reader :result
576
+
577
+ def self.read(signature)
578
+ if signature
579
+ builder = GenericTypeBuilder.new
580
+ reader = BiteScript::ASM::SignatureReader.new(signature)
581
+ reader.accept(builder)
582
+ builder.result
583
+ end
584
+ end
585
+
586
+ def initialize(&block)
587
+ @block = block
588
+ end
589
+
590
+ def return_type(type)
591
+ @result = type
592
+ @block.call(type) if @block
593
+ end
594
+
595
+ def visitBaseType(desc)
596
+ return_type(Type.getType(desc.chr))
597
+ end
598
+
599
+ def visitArrayType
600
+ type = GenericArray.new
601
+ return_type(type)
602
+ GenericTypeBuilder.new {|component_type| type.component_type = component_type}
603
+ end
604
+
605
+ def visitTypeVariable(name)
606
+ return_type(TypeVariable.new(name))
607
+ end
608
+
609
+ def visitClassType(desc)
610
+ return_type(ParameterizedType.new(Type.getObjectType(desc)))
611
+ end
612
+
613
+ def visitTypeArgument(wildcard=nil)
614
+ if wildcard.nil?
615
+ @result.type_arguments <<
616
+ Wildcard.new(Type.getObjectType('java/lang/Object'))
617
+ return
618
+ end
619
+ GenericTypeBuilder.new do |type|
620
+ argument = case wildcard
621
+ when INSTANCEOF
622
+ type
623
+ when EXTENDS
624
+ Wildcard.new(type)
625
+ when SUPER
626
+ Wildcard.new(nil, type)
627
+ else
628
+ raise "Unknown wildcard #{wildcard.chr}"
629
+ end
630
+ @result.type_arguments << argument
631
+ end
632
+ end
633
+
634
+ def visitSuperclass
635
+ self
636
+ end
637
+
638
+ def visitInnerClassType(name)
639
+ desc = @result.descriptor.sub(/;$/, "$#{name};")
640
+ return_type(ParameterizedType.new(Type.getType(desc), @result))
641
+ end
642
+
643
+ def visitEnd
644
+ if @result.type_arguments.empty? && @result.outer_type.nil?
645
+ @result = @result.raw_type
646
+ end
647
+ end
648
+ end
379
649
  end
@@ -0,0 +1,127 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'test/unit'
4
+ require 'bitescript'
5
+
6
+ class TestGenerics < Test::Unit::TestCase
7
+ def test_type_signature
8
+ sig = BiteScript::GenericTypeBuilder.read('Ljava/util/List<TE;>;')
9
+ assert sig.generic_class?
10
+ assert_equal 'Ljava/util/List;', sig.raw_type.descriptor
11
+ assert_kind_of BiteScript::ASM::Type, sig.raw_type
12
+ assert_equal 1, sig.type_arguments.size
13
+ assert sig.type_arguments[0].type_variable?
14
+ assert_equal 'E', sig.type_arguments[0].name
15
+ end
16
+
17
+ def test_wildcard
18
+ sig = BiteScript::GenericTypeBuilder.read('Ljava/util/List<*>;')
19
+ assert sig.generic_class?
20
+ assert_equal 'Ljava/util/List;', sig.raw_type.descriptor
21
+ assert_kind_of BiteScript::ASM::Type, sig.raw_type
22
+ assert_equal 1, sig.type_arguments.size
23
+ assert sig.type_arguments[0].wildcard?
24
+
25
+ wildcard = sig.type_arguments[0]
26
+ assert_nil wildcard.lower_bound
27
+ assert_not_nil wildcard.upper_bound
28
+ assert_equal 'Ljava/lang/Object;', wildcard.upper_bound.descriptor
29
+
30
+ sig = BiteScript::GenericTypeBuilder.read('Ljava/util/List<+Ljava/lang/Number;>;')
31
+ wildcard = sig.type_arguments[0]
32
+ assert wildcard.wildcard?
33
+ assert_nil wildcard.lower_bound
34
+ assert_not_nil wildcard.upper_bound
35
+ assert_equal 'Ljava/lang/Number;', wildcard.upper_bound.descriptor
36
+
37
+ sig = BiteScript::GenericTypeBuilder.read('Ljava/util/List<-Ljava/lang/Integer;>;')
38
+ wildcard = sig.type_arguments[0]
39
+ assert wildcard.wildcard?
40
+ assert_not_nil wildcard.lower_bound
41
+ assert_nil wildcard.upper_bound
42
+ assert_equal 'Ljava/lang/Integer;', wildcard.lower_bound.descriptor
43
+ end
44
+
45
+ def test_array
46
+ sig = BiteScript::GenericTypeBuilder.read('[Ljava/util/List<Ljava/lang/String;>;')
47
+ assert sig.array?
48
+ list = sig.component_type
49
+ assert list.generic_class?
50
+ assert_equal 'Ljava/util/List;', list.raw_type.descriptor
51
+ assert_kind_of BiteScript::ASM::Type, list.raw_type
52
+ assert_equal 1, list.type_arguments.size
53
+ string = list.type_arguments[0]
54
+ assert_equal 'Ljava/lang/String;', string.descriptor
55
+ end
56
+
57
+ def test_inner_class
58
+ sig = BiteScript::GenericTypeBuilder.read('Ljava/util/HashMap<TK;TV;>.HashIterator<TK;>;')
59
+ assert sig.generic_class?
60
+ assert_kind_of BiteScript::ASM::Type, sig.raw_type
61
+ assert_equal 'Ljava/util/HashMap$HashIterator;', sig.raw_type.descriptor
62
+ assert sig.outer_type.generic_class?
63
+ assert_kind_of BiteScript::ASM::Type, sig.outer_type.raw_type
64
+ assert_equal 'Ljava/util/HashMap;', sig.outer_type.raw_type.descriptor
65
+ assert_equal ['K', 'V'], sig.outer_type.type_arguments.map {|x| x.name}
66
+ end
67
+
68
+ def test_method_signature
69
+ sig = BiteScript::SignatureMirror.new(
70
+ '<T:Ljava/lang/Object;>(I)Ljava/lang/Class<+TT;>;')
71
+ assert sig.method?
72
+ assert !sig.class?
73
+
74
+ type = sig.return_type
75
+ assert type.generic_class?
76
+ assert_equal 'Ljava/lang/Class;', type.raw_type.descriptor
77
+ assert_equal 1, type.type_arguments.size
78
+
79
+ arg = type.type_arguments[0]
80
+ assert arg.wildcard?
81
+ assert_nil arg.lower_bound
82
+ assert_not_nil arg.upper_bound
83
+ assert arg.upper_bound.type_variable?
84
+ assert_equal 'T', arg.upper_bound.name
85
+
86
+ assert_equal 1, sig.parameter_types.size
87
+ assert_kind_of BiteScript::ASM::Type, sig.parameter_types[0]
88
+ assert_equal 'I', sig.parameter_types[0].descriptor
89
+
90
+ assert_equal 1, sig.type_parameters.size
91
+ var = sig.type_parameters[0]
92
+ assert var.type_variable?
93
+ assert_equal 'T', var.name
94
+ assert_equal 1, var.bounds.size
95
+ assert_equal 'Ljava/lang/Object;', var.bounds[0].descriptor
96
+ end
97
+
98
+ def test_class_signature
99
+ sig = BiteScript::SignatureMirror.new(
100
+ '<E:Ljava/lang/Object;>Ljava/util/List<TE;>;')
101
+ assert sig.class?
102
+ assert !sig.method?
103
+
104
+ assert_equal 0, sig.interfaces.size
105
+
106
+ superclass = sig.superclass
107
+ assert superclass.generic_class?
108
+ assert_equal 'Ljava/util/List;', superclass.raw_type.descriptor
109
+ assert_equal 'E', superclass.type_arguments[0].name
110
+
111
+ assert_equal 1, sig.type_parameters.size
112
+ var = sig.type_parameters[0]
113
+ assert var.type_variable?
114
+ assert_equal 'E', var.name
115
+ assert_equal 1, var.bounds.size
116
+ assert_equal 'Ljava/lang/Object;', var.bounds[0].descriptor
117
+ end
118
+
119
+ def test_multiple_bounds
120
+ sig = BiteScript::SignatureMirror.new(
121
+ '<T::Ljava/lang/Comparable<TT;>;:Ljava/lang/Iterable<TT;>;>Ljava/lang/Object;')
122
+ t = sig.type_parameters[0]
123
+ assert_equal 2, t.bounds.size
124
+ assert_equal "java.lang.Comparable<T>", t.bounds[0].to_s
125
+ assert_equal "java.lang.Iterable<T>", t.bounds[1].to_s
126
+ end
127
+ end
metadata CHANGED
@@ -1,12 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitescript
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 7
9
- version: 0.0.7
4
+ prerelease:
5
+ version: 0.0.8
10
6
  platform: ruby
11
7
  authors:
12
8
  - Charles Oliver Nutter
@@ -15,7 +11,7 @@ autorequire:
15
11
  bindir: bin
16
12
  cert_chain: []
17
13
 
18
- date: 2010-11-10 08:48:06.220000 +01:00
14
+ date: 2011-03-07 10:38:26.957000 -06:00
19
15
  default_executable:
20
16
  dependencies: []
21
17
 
@@ -41,6 +37,7 @@ files:
41
37
  - examples/hello_world.class
42
38
  - examples/hello_world_macro.bs
43
39
  - examples/indy.bs
40
+ - examples/instanceof.bs
44
41
  - examples/mixed_bag.rb
45
42
  - examples/simple_loop.rb
46
43
  - examples/using_ruby.bs
@@ -57,6 +54,7 @@ files:
57
54
  - test/test_bitescript.rb
58
55
  - test/test_builder.rb
59
56
  - test/test_bytecode.rb
57
+ - test/test_generics.rb
60
58
  - test/test_java_class.rb
61
59
  - test/test_signature.rb
62
60
  - History.txt
@@ -79,21 +77,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
77
  requirements:
80
78
  - - ">="
81
79
  - !ruby/object:Gem::Version
82
- segments:
83
- - 0
84
80
  version: "0"
85
81
  required_rubygems_version: !ruby/object:Gem::Requirement
86
82
  none: false
87
83
  requirements:
88
84
  - - ">="
89
85
  - !ruby/object:Gem::Version
90
- segments:
91
- - 0
92
86
  version: "0"
93
87
  requirements: []
94
88
 
95
89
  rubyforge_project: jruby-extras
96
- rubygems_version: 1.3.7
90
+ rubygems_version: 1.5.1
97
91
  signing_key:
98
92
  specification_version: 3
99
93
  summary: BiteScript is a Ruby DSL for generating Java bytecode.
@@ -101,5 +95,6 @@ test_files:
101
95
  - test/test_bitescript.rb
102
96
  - test/test_builder.rb
103
97
  - test/test_bytecode.rb
98
+ - test/test_generics.rb
104
99
  - test/test_java_class.rb
105
100
  - test/test_signature.rb