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.
- data/History.txt +4 -0
- data/Manifest.txt +68 -0
- data/README.txt +31 -0
- data/Rakefile +37 -0
- data/bin/duby +9 -0
- data/bin/dubyc +9 -0
- data/bin/dubyp +9 -0
- data/examples/appengine/src/com/google/appengine/ext/duby/db/Model.duby +132 -0
- data/examples/appengine/src/com/ribrdb/DubyApp.duby +28 -0
- data/examples/bench_fractal.duby +57 -0
- data/examples/construction.duby +8 -0
- data/examples/edb.duby +3 -0
- data/examples/fib.duby +24 -0
- data/examples/fields.duby +22 -0
- data/examples/java_thing.duby +13 -0
- data/examples/simple_class.duby +12 -0
- data/examples/swing.duby +20 -0
- data/examples/tak.duby +15 -0
- data/javalib/JRubyParser.jar +0 -0
- data/lib/duby.rb +170 -0
- data/lib/duby/ast.rb +340 -0
- data/lib/duby/ast/call.rb +73 -0
- data/lib/duby/ast/class.rb +145 -0
- data/lib/duby/ast/flow.rb +328 -0
- data/lib/duby/ast/intrinsics.rb +46 -0
- data/lib/duby/ast/literal.rb +93 -0
- data/lib/duby/ast/local.rb +77 -0
- data/lib/duby/ast/method.rb +187 -0
- data/lib/duby/ast/structure.rb +44 -0
- data/lib/duby/ast/type.rb +93 -0
- data/lib/duby/c/compiler.rb +134 -0
- data/lib/duby/compiler.rb +261 -0
- data/lib/duby/jvm/compiler.rb +684 -0
- data/lib/duby/jvm/method_lookup.rb +185 -0
- data/lib/duby/jvm/source_compiler.rb +516 -0
- data/lib/duby/jvm/source_generator/builder.rb +368 -0
- data/lib/duby/jvm/source_generator/loops.rb +132 -0
- data/lib/duby/jvm/source_generator/precompile.rb +154 -0
- data/lib/duby/jvm/source_generator/typer.rb +11 -0
- data/lib/duby/jvm/typer.rb +118 -0
- data/lib/duby/jvm/types.rb +326 -0
- data/lib/duby/jvm/types/basic_types.rb +18 -0
- data/lib/duby/jvm/types/boolean.rb +11 -0
- data/lib/duby/jvm/types/factory.rb +151 -0
- data/lib/duby/jvm/types/floats.rb +70 -0
- data/lib/duby/jvm/types/integers.rb +110 -0
- data/lib/duby/jvm/types/intrinsics.rb +157 -0
- data/lib/duby/jvm/types/literals.rb +82 -0
- data/lib/duby/jvm/types/methods.rb +344 -0
- data/lib/duby/jvm/types/number.rb +92 -0
- data/lib/duby/nbcompiler.rb +29 -0
- data/lib/duby/old/compiler_old.rb +845 -0
- data/lib/duby/old/declaration.rb +72 -0
- data/lib/duby/old/mapper.rb +72 -0
- data/lib/duby/old/signature.rb +52 -0
- data/lib/duby/old/typer_old.rb +163 -0
- data/lib/duby/plugin/edb.rb +25 -0
- data/lib/duby/plugin/java.rb +42 -0
- data/lib/duby/plugin/math.rb +84 -0
- data/lib/duby/transform.rb +908 -0
- data/lib/duby/typer.rb +359 -0
- data/test/test_ast.rb +391 -0
- data/test/test_compilation.rb +98 -0
- data/test/test_java_typer.rb +199 -0
- data/test/test_javac_compiler.rb +57 -0
- data/test/test_jvm_compiler.rb +1459 -0
- data/test/test_math_plugin.rb +87 -0
- data/test/test_typer.rb +246 -0
- 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,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
|