duby 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +68 -0
  3. data/README.txt +31 -0
  4. data/Rakefile +37 -0
  5. data/bin/duby +9 -0
  6. data/bin/dubyc +9 -0
  7. data/bin/dubyp +9 -0
  8. data/examples/appengine/src/com/google/appengine/ext/duby/db/Model.duby +132 -0
  9. data/examples/appengine/src/com/ribrdb/DubyApp.duby +28 -0
  10. data/examples/bench_fractal.duby +57 -0
  11. data/examples/construction.duby +8 -0
  12. data/examples/edb.duby +3 -0
  13. data/examples/fib.duby +24 -0
  14. data/examples/fields.duby +22 -0
  15. data/examples/java_thing.duby +13 -0
  16. data/examples/simple_class.duby +12 -0
  17. data/examples/swing.duby +20 -0
  18. data/examples/tak.duby +15 -0
  19. data/javalib/JRubyParser.jar +0 -0
  20. data/lib/duby.rb +170 -0
  21. data/lib/duby/ast.rb +340 -0
  22. data/lib/duby/ast/call.rb +73 -0
  23. data/lib/duby/ast/class.rb +145 -0
  24. data/lib/duby/ast/flow.rb +328 -0
  25. data/lib/duby/ast/intrinsics.rb +46 -0
  26. data/lib/duby/ast/literal.rb +93 -0
  27. data/lib/duby/ast/local.rb +77 -0
  28. data/lib/duby/ast/method.rb +187 -0
  29. data/lib/duby/ast/structure.rb +44 -0
  30. data/lib/duby/ast/type.rb +93 -0
  31. data/lib/duby/c/compiler.rb +134 -0
  32. data/lib/duby/compiler.rb +261 -0
  33. data/lib/duby/jvm/compiler.rb +684 -0
  34. data/lib/duby/jvm/method_lookup.rb +185 -0
  35. data/lib/duby/jvm/source_compiler.rb +516 -0
  36. data/lib/duby/jvm/source_generator/builder.rb +368 -0
  37. data/lib/duby/jvm/source_generator/loops.rb +132 -0
  38. data/lib/duby/jvm/source_generator/precompile.rb +154 -0
  39. data/lib/duby/jvm/source_generator/typer.rb +11 -0
  40. data/lib/duby/jvm/typer.rb +118 -0
  41. data/lib/duby/jvm/types.rb +326 -0
  42. data/lib/duby/jvm/types/basic_types.rb +18 -0
  43. data/lib/duby/jvm/types/boolean.rb +11 -0
  44. data/lib/duby/jvm/types/factory.rb +151 -0
  45. data/lib/duby/jvm/types/floats.rb +70 -0
  46. data/lib/duby/jvm/types/integers.rb +110 -0
  47. data/lib/duby/jvm/types/intrinsics.rb +157 -0
  48. data/lib/duby/jvm/types/literals.rb +82 -0
  49. data/lib/duby/jvm/types/methods.rb +344 -0
  50. data/lib/duby/jvm/types/number.rb +92 -0
  51. data/lib/duby/nbcompiler.rb +29 -0
  52. data/lib/duby/old/compiler_old.rb +845 -0
  53. data/lib/duby/old/declaration.rb +72 -0
  54. data/lib/duby/old/mapper.rb +72 -0
  55. data/lib/duby/old/signature.rb +52 -0
  56. data/lib/duby/old/typer_old.rb +163 -0
  57. data/lib/duby/plugin/edb.rb +25 -0
  58. data/lib/duby/plugin/java.rb +42 -0
  59. data/lib/duby/plugin/math.rb +84 -0
  60. data/lib/duby/transform.rb +908 -0
  61. data/lib/duby/typer.rb +359 -0
  62. data/test/test_ast.rb +391 -0
  63. data/test/test_compilation.rb +98 -0
  64. data/test/test_java_typer.rb +199 -0
  65. data/test/test_javac_compiler.rb +57 -0
  66. data/test/test_jvm_compiler.rb +1459 -0
  67. data/test/test_math_plugin.rb +87 -0
  68. data/test/test_typer.rb +246 -0
  69. metadata +155 -0
@@ -0,0 +1,18 @@
1
+ module Duby::JVM::Types
2
+ Boolean = BooleanType.new(Java::boolean, java.lang.Boolean)
3
+ Byte = IntegerType.new(Java::byte, java.lang.Byte)
4
+ Char = IntegerType.new(Java::char, java.lang.Character)
5
+ Short = IntegerType.new(Java::short, java.lang.Short)
6
+ Int = IntegerType.new(Java::int, java.lang.Integer)
7
+ Long = LongType.new(Java::long, java.lang.Long)
8
+ Float = FloatType.new(Java::float, java.lang.Float)
9
+ Double = DoubleType.new(Java::double, java.lang.Double)
10
+
11
+ Object = Type.new(Java::JavaLang.Object)
12
+ String = StringType.new(Java::JavaLang.String)
13
+
14
+ Void = VoidType.new
15
+ Null = NullType.new
16
+
17
+ TYPE_ORDERING = [Byte, Short, Int, Long, Float, Double]
18
+ end
@@ -0,0 +1,11 @@
1
+ module Duby::JVM::Types
2
+ class BooleanType < PrimitiveType
3
+ def init_value(builder)
4
+ builder.iconst_0
5
+ end
6
+
7
+ def prefix
8
+ 'i'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,151 @@
1
+ module Duby::JVM::Types
2
+ class TypeFactory
3
+ BASIC_TYPES = {
4
+ "boolean" => Boolean,
5
+ "byte" => Byte,
6
+ "char" => Char,
7
+ "short" => Short,
8
+ "int" => Int,
9
+ "long" => Long,
10
+ "float" => Float,
11
+ "double" => Double,
12
+ "fixnum" => Int,
13
+ "string" => String,
14
+ "java.lang.String" => String,
15
+ "java.lang.Object" => Object,
16
+ "void" => Void,
17
+ "notype" => Void,
18
+ "null" => Null
19
+ }.freeze
20
+
21
+ attr_accessor :package
22
+ attr_reader :known_types
23
+
24
+ class ParanoidHash < Hash
25
+ def []=(k, v)
26
+ raise ArgumentError, "Can't store nil for key #{k.inspect}" if v.nil?
27
+ super(k, v)
28
+ end
29
+ end
30
+
31
+ def initialize(filename='')
32
+ @known_types = ParanoidHash.new
33
+ @known_types.update(BASIC_TYPES)
34
+ @declarations = []
35
+ @package = File.dirname(filename).tr('/', '.')
36
+ @package.sub! /^\.+/, ''
37
+ @package = nil if @package.empty?
38
+ end
39
+
40
+ def define_types(builder)
41
+ @declarations.each do |declaration|
42
+ declaration.define(builder)
43
+ end
44
+ end
45
+
46
+ def type(name, array=false, meta=false)
47
+ type = basic_type(name)
48
+ type = type.meta if meta
49
+ type = type.array_type if array
50
+ return type
51
+ end
52
+
53
+ def basic_type(name)
54
+ if name.kind_of?(Type) || name.kind_of?(NarrowingType)
55
+ return name.basic_type
56
+ end
57
+ orig = name
58
+ if name.kind_of? Java::JavaClass
59
+ if name.array?
60
+ return type(name.component_type, true)
61
+ else
62
+ name = name.name
63
+ end
64
+ elsif name.respond_to? :java_class
65
+ name = name.java_class.name
66
+ end
67
+ name = name.to_s unless name.kind_of?(::String)
68
+ return @known_types[name].basic_type if @known_types[name]
69
+ raise ArgumentError, "Bad Type #{orig}" if name =~ /Java::/
70
+ raise ArgumentError, "Bad Type #{orig.inspect}" if name == '' || name.nil?
71
+ full_name = name
72
+ begin
73
+ @known_types[name] = Type.new(Java::JavaClass.for_name(full_name))
74
+ rescue NameError
75
+ unless full_name.include? '.'
76
+ full_name = "java.lang.#{full_name}"
77
+ retry
78
+ end
79
+ raise $!
80
+ end
81
+ end
82
+
83
+ def declare_type(node)
84
+ if node.kind_of? ::String
85
+ name = node
86
+ node = nil
87
+ else
88
+ name = node.name
89
+ end
90
+
91
+ if Duby::AST::InterfaceDeclaration === node
92
+ @known_types[name] = InterfaceDefinition.new(name, node)
93
+ elsif @known_types.include? name
94
+ existing = @known_types[name]
95
+ existing.node ||= node
96
+ existing
97
+ else
98
+ full_name = name
99
+ if !name.include?('.') && package
100
+ full_name = "#{package}.#{name}"
101
+ end
102
+ @known_types[full_name] = TypeDefinition.new(full_name, node)
103
+ @known_types[name] = @known_types[full_name]
104
+ end
105
+ end
106
+
107
+ def alias(from, to)
108
+ @known_types[from] = type(to)
109
+ end
110
+
111
+ def no_type
112
+ Void
113
+ end
114
+
115
+ def fixnum(parent, line_number, literal)
116
+ FixnumLiteralNode.new(parent, line_number, literal)
117
+ end
118
+
119
+ def float(parent, line_number, literal)
120
+ FloatLiteralNode.new(parent, line_number, literal)
121
+ end
122
+ end
123
+
124
+ class FixnumLiteralNode < AST::Fixnum
125
+ def infer(typer)
126
+ return @inferred_type if resolved?
127
+ resolved!
128
+ @inferred_type = FixnumLiteral.new(@literal)
129
+ end
130
+
131
+ def compile(compiler, expression)
132
+ if expression
133
+ inferred_type.literal(compiler.method, @literal)
134
+ end
135
+ end
136
+ end
137
+
138
+ class FloatLiteralNode < AST::Float
139
+ def infer(typer)
140
+ return @inferred_type if resolved?
141
+ resolved!
142
+ @inferred_type = FloatLiteral.new(@literal)
143
+ end
144
+
145
+ def compile(compiler, expression)
146
+ if expression
147
+ inferred_type.literal(compiler.method, @literal)
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,70 @@
1
+ module Duby::JVM::Types
2
+ class FloatType < Number
3
+ def prefix
4
+ 'f'
5
+ end
6
+
7
+ def suffix
8
+ 'g'
9
+ end
10
+
11
+ def init_value(builder)
12
+ builder.fconst_0
13
+ end
14
+
15
+ def literal(builder, value)
16
+ case value
17
+ when 0.0
18
+ builder.fconst_0
19
+ when 1.0
20
+ builder.fconst_1
21
+ when 2.0
22
+ builder.fconst_2
23
+ else
24
+ builder.ldc_float(value)
25
+ end
26
+ end
27
+
28
+ def widen(builder, type)
29
+ case type
30
+ when Float
31
+ # Do nothing
32
+ when Double
33
+ builder.f2d
34
+ else
35
+ raise ArgumentError, "Invalid widening conversion from Int to #{type}"
36
+ end
37
+ end
38
+ end
39
+
40
+ class DoubleType < FloatType
41
+ def prefix
42
+ 'd'
43
+ end
44
+
45
+ def wide?
46
+ true
47
+ end
48
+
49
+ def init_value(builder)
50
+ builder.dconst_0
51
+ end
52
+
53
+ def literal(builder, value)
54
+ case value
55
+ when 0.0
56
+ builder.dconst_0
57
+ when 1.0
58
+ builder.dconst_1
59
+ else
60
+ builder.ldc_double(value)
61
+ end
62
+ end
63
+
64
+ def widen(builder, type)
65
+ if type != Double
66
+ raise ArgumentError, "Invalid widening conversion from Int to #{type}"
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,110 @@
1
+ class BiteScript::MethodBuilder
2
+ def inot
3
+ iconst_m1
4
+ ixor
5
+ end
6
+
7
+ def lnot
8
+ # TODO would any of these be faster?
9
+ # iconst_m1; i2l
10
+ # lconst_1; lneg
11
+ ldc_long(-1)
12
+ ixor
13
+ end
14
+ end
15
+
16
+ module Duby::JVM::Types
17
+ class IntegerType < Number
18
+ def literal(builder, value)
19
+ builder.push_int(value)
20
+ end
21
+
22
+ def init_value(builder)
23
+ builder.iconst_0
24
+ end
25
+
26
+ def load(builder, index)
27
+ builder.iload(index)
28
+ end
29
+
30
+ def widen(builder, type)
31
+ case type
32
+ when Byte, Short, Int
33
+ # do nothing
34
+ when Long
35
+ builder.i2l
36
+ when Float
37
+ builder.i2f
38
+ when Double
39
+ builder.i2d
40
+ else
41
+ raise ArgumentError, "Invalid widening conversion from #{name} to #{type}"
42
+ end
43
+ end
44
+
45
+ def prefix
46
+ 'i'
47
+ end
48
+
49
+ def math_type
50
+ Int
51
+ end
52
+
53
+ def jump_if(builder, op, label)
54
+ builder.send "if_icmp#{op}", label
55
+ end
56
+
57
+ def add_intrinsics
58
+ super
59
+ math_operator('<<', 'shl')
60
+ math_operator('>>', 'shr')
61
+ math_operator('>>>', 'ushr')
62
+ math_operator('|', 'or')
63
+ math_operator('&', 'and')
64
+ math_operator('^', 'xor')
65
+ unary_operator('~', 'not')
66
+ end
67
+ end
68
+
69
+ class LongType < Number
70
+ def prefix
71
+ 'l'
72
+ end
73
+
74
+ def literal(builder, value)
75
+ builder.ldc_long(value)
76
+ end
77
+
78
+ def init_value(builder)
79
+ builder.lconst_0
80
+ end
81
+
82
+ def wide?
83
+ true
84
+ end
85
+
86
+ def widen(builder, type)
87
+ case type
88
+ when Long
89
+ # do nothing
90
+ when Float
91
+ builder.l2f
92
+ when Double
93
+ builder.l2d
94
+ else
95
+ raise ArgumentError, "Invalid widening conversion from Int to #{type}"
96
+ end
97
+ end
98
+
99
+ def add_intrinsics
100
+ super
101
+ math_operator('<<', 'shl')
102
+ math_operator('>>', 'shr')
103
+ math_operator('>>>', 'ushr')
104
+ math_operator('|', 'or')
105
+ math_operator('&', 'and')
106
+ math_operator('^', 'xor')
107
+ unary_operator('~', 'not')
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,157 @@
1
+ require 'bitescript'
2
+
3
+ class BiteScript::MethodBuilder
4
+ def op_to_bool
5
+ done_label = label
6
+ true_label = label
7
+
8
+ yield(true_label)
9
+ iconst_0
10
+ goto(done_label)
11
+ true_label.set!
12
+ iconst_1
13
+ done_label.set!
14
+ end
15
+ end
16
+
17
+ module Duby::JVM::Types
18
+ class Type
19
+ def load(builder, index)
20
+ builder.send "#{prefix}load", index
21
+ end
22
+
23
+ def store(builder, index)
24
+ builder.send "#{prefix}store", index
25
+ end
26
+
27
+ def return(builder)
28
+ builder.send "#{prefix}return"
29
+ end
30
+
31
+ def init_value(builder)
32
+ builder.aconst_null
33
+ end
34
+
35
+ def intrinsics
36
+ @intrinsics ||= begin
37
+ @intrinsics = Hash.new {|h, k| h[k] = {}}
38
+ add_intrinsics
39
+ @intrinsics
40
+ end
41
+ end
42
+
43
+ def add_method(name, args, method_or_type=nil, &block)
44
+ if block_given?
45
+ method_or_type = Intrinsic.new(self, name, args,
46
+ method_or_type, &block)
47
+ end
48
+ intrinsics[name][args] = method_or_type
49
+ end
50
+
51
+ def declared_intrinsics
52
+ methods = []
53
+ intrinsics.each do |name, group|
54
+ group.each do |args, method|
55
+ methods << method
56
+ end
57
+ end
58
+ methods
59
+ end
60
+
61
+ def add_intrinsics
62
+ add_method('nil?', [], Boolean) do |compiler, call, expression|
63
+ if expression
64
+ call.target.compile(compiler, true)
65
+ compiler.method.op_to_bool do |target|
66
+ compiler.method.ifnull(target)
67
+ end
68
+ end
69
+ end
70
+
71
+ add_method('==', [Object], Boolean) do |compiler, call, expression|
72
+ # Should this call Object.equals for consistency with Ruby?
73
+ if expression
74
+ call.target.compile(compiler, true)
75
+ call.parameters[0].compile(compiler, true)
76
+ compiler.method.op_to_bool do |target|
77
+ compiler.method.if_acmpeq(target)
78
+ end
79
+ end
80
+ end
81
+
82
+ add_method('!=', [Object], Boolean) do |compiler, call, expression|
83
+ # Should this call Object.equals for consistency with Ruby?
84
+ if expression
85
+ call.target.compile(compiler, true)
86
+ call.parameters[0].compile(compiler, true)
87
+ compiler.method.op_to_bool do |target|
88
+ compiler.method.if_acmpne(target)
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ class ArrayType
96
+ def add_intrinsics
97
+ super
98
+ add_method(
99
+ '[]', [Int], component_type) do |compiler, call, expression|
100
+ if expression
101
+ call.target.compile(compiler, true)
102
+ call.parameters[0].compile(compiler, true)
103
+ component_type.aload(compiler.method)
104
+ end
105
+ end
106
+
107
+ add_method('[]=',
108
+ [Int, component_type],
109
+ component_type) do |compiler, call, expression|
110
+ call.target.compile(compiler, true)
111
+ convert_args(compiler, call.parameters, [Int, component_type])
112
+ component_type.astore(compiler.method)
113
+ if expression
114
+ call.parameters[1].compile(compiler, true)
115
+ end
116
+ end
117
+
118
+ add_method('length', [], Int) do |compiler, call, expression|
119
+ call.target.compile(compiler, true)
120
+ compiler.method.arraylength
121
+ end
122
+ end
123
+ end
124
+
125
+ class StringType < Type
126
+ def add_intrinsics
127
+ super
128
+ add_method('+', [String], String) do |compiler, call, expression|
129
+ if expression
130
+ java_method('concat', String).call(compiler, call, expression)
131
+ end
132
+ end
133
+ add_method('+', [Int], String) do |compiler, call, expression|
134
+ if expression
135
+ call.target.compile(compiler, true)
136
+ call.parameters[0].compile(compiler, true)
137
+ compiler.method.invokestatic String, "valueOf", [String, Int]
138
+ compiler.method.invokevirtual String, "concat", [String, String]
139
+ end
140
+ end
141
+ add_method('+', [Float], String) do |compiler, call, expression|
142
+ if expression
143
+ call.target.compile(compiler, true)
144
+ call.parameters[0].compile(compiler, true)
145
+ compiler.method.invokestatic String, "valueOf", [String, Float]
146
+ compiler.method.invokevirtual String, "concat", [String, String]
147
+ end
148
+ end
149
+ end
150
+ end
151
+
152
+ class PrimitiveType
153
+ # Primitives define their own intrinsics instead of getting the Object ones.
154
+ def add_intrinsics
155
+ end
156
+ end
157
+ end