duby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,72 @@
|
|
1
|
+
require 'compiler/builder'
|
2
|
+
require 'jruby'
|
3
|
+
|
4
|
+
module Compiler
|
5
|
+
module PrimitiveRuby
|
6
|
+
# reload
|
7
|
+
module Java::OrgJrubyAst
|
8
|
+
class CallNode
|
9
|
+
def declared_type(builder)
|
10
|
+
if name == "[]"
|
11
|
+
# array type, top should be a constant; find the rest
|
12
|
+
array = true
|
13
|
+
elements = []
|
14
|
+
else
|
15
|
+
elements = [name]
|
16
|
+
end
|
17
|
+
|
18
|
+
receiver = receiver_node
|
19
|
+
|
20
|
+
loop do
|
21
|
+
case receiver
|
22
|
+
when ConstNode
|
23
|
+
elements << receiver_node.name
|
24
|
+
break
|
25
|
+
when CallNode
|
26
|
+
elements.unshift(receiver.name)
|
27
|
+
receiver = receiver.receiver_node
|
28
|
+
when SymbolNode
|
29
|
+
elements.unshift(receiver.name)
|
30
|
+
break
|
31
|
+
when VCallNode
|
32
|
+
elements.unshift(receiver.name)
|
33
|
+
break
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# join and load
|
38
|
+
class_name = elements.join(".")
|
39
|
+
type = builder.type(class_name)
|
40
|
+
|
41
|
+
if array
|
42
|
+
type.array_class
|
43
|
+
else
|
44
|
+
type
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Colon2Node
|
50
|
+
def declared_type(builder)
|
51
|
+
left_node.declared_type(builder).declared_field(name).static_value
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class HashNode
|
56
|
+
def declare_types(builder)
|
57
|
+
@declared = true
|
58
|
+
list = list_node.child_nodes.to_a
|
59
|
+
list.each_index do |index|
|
60
|
+
builder.local(list[index].name, list[index + 1].declared_type(builder)) if index % 2 == 0
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class SymbolNode
|
66
|
+
def declared_type(builder)
|
67
|
+
@type ||= builder.type(name.intern)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'compiler/builder'
|
2
|
+
require 'jruby'
|
3
|
+
|
4
|
+
module Compiler
|
5
|
+
module PrimitiveRuby
|
6
|
+
# reload
|
7
|
+
module Java::OrgJrubyAst
|
8
|
+
class CallNode
|
9
|
+
def mapped_name(builder)
|
10
|
+
# TODO move to a utility somewhere for smart name mappings
|
11
|
+
# TODO or at least make it a table...
|
12
|
+
mapped_name = name
|
13
|
+
case receiver_node.type(builder)
|
14
|
+
when JString
|
15
|
+
case name
|
16
|
+
when "+"
|
17
|
+
mapped_name = "concat"
|
18
|
+
# This doesn't work yet, because format is a static method on String
|
19
|
+
# when "%"
|
20
|
+
# mapped_name = "format"
|
21
|
+
end
|
22
|
+
else
|
23
|
+
case name
|
24
|
+
when "new"
|
25
|
+
mapped_name = "<init>"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
mapped_name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class DefnNode
|
34
|
+
def mapped_name(builder)
|
35
|
+
case name
|
36
|
+
when "initialize"
|
37
|
+
"<init>"
|
38
|
+
else
|
39
|
+
name
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class FCallNode
|
45
|
+
def mapped_name(builder)
|
46
|
+
if name == "puts"
|
47
|
+
"println"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class InstVarNode
|
53
|
+
def mapped_name(builder)
|
54
|
+
name[1..-1]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class InstAsgnNode
|
59
|
+
def mapped_name(builder)
|
60
|
+
name[1..-1]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class VCallNode
|
65
|
+
def mapped_name(builder)
|
66
|
+
# TODO map names for the local type?
|
67
|
+
name
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'compiler/builder'
|
2
|
+
require 'jruby'
|
3
|
+
|
4
|
+
module Compiler
|
5
|
+
module PrimitiveRuby
|
6
|
+
# reload
|
7
|
+
module Java::OrgJrubyAst
|
8
|
+
class CallNode
|
9
|
+
def signature(builder)
|
10
|
+
arg_types = []
|
11
|
+
args_node.child_nodes.each do |node|
|
12
|
+
arg_types << node.type(builder)
|
13
|
+
end if args_node
|
14
|
+
|
15
|
+
recv_java_class = receiver_node.type(builder)
|
16
|
+
declared_method = recv_java_class.declared_method_smart(mapped_name(builder), *arg_types)
|
17
|
+
return_type = declared_method.return_type
|
18
|
+
|
19
|
+
if (return_type)
|
20
|
+
return_class = builder.type(return_type.to_s)
|
21
|
+
else
|
22
|
+
return_type = Void
|
23
|
+
end
|
24
|
+
|
25
|
+
return [
|
26
|
+
return_class,
|
27
|
+
*declared_method.parameter_types.map {|type| builder.type(type.to_s)}
|
28
|
+
]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class HashNode
|
33
|
+
def signature(builder)
|
34
|
+
@declared = true
|
35
|
+
arg_types = []
|
36
|
+
return_type = Void
|
37
|
+
list = list_node.child_nodes.to_a
|
38
|
+
list.each_index do |index|
|
39
|
+
if index % 2 == 0
|
40
|
+
if SymbolNode === list[index] && list[index].name == 'return'
|
41
|
+
return_type = list[index + 1].declared_type(builder)
|
42
|
+
else
|
43
|
+
arg_types << list[index + 1].declared_type(builder)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
return [return_type, *arg_types]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'compiler/builder'
|
2
|
+
require 'jruby'
|
3
|
+
|
4
|
+
module Compiler
|
5
|
+
module PrimitiveRuby
|
6
|
+
# reload
|
7
|
+
module Java::OrgJrubyAst
|
8
|
+
class BeginNode
|
9
|
+
def type(builder)
|
10
|
+
body_node.type(builder)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class BlockNode
|
15
|
+
# Type of a block is the type of its final element
|
16
|
+
def type(builder)
|
17
|
+
if child_nodes.size == 0
|
18
|
+
JObject
|
19
|
+
else
|
20
|
+
@type ||= child_nodes.get(child_nodes.size - 1).type(builder)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class CallNode
|
26
|
+
def type(builder)
|
27
|
+
@return_type ||= begin
|
28
|
+
recv_type = receiver_node.type(builder)
|
29
|
+
|
30
|
+
# if we already have an exact class, use it
|
31
|
+
if recv_type.array?
|
32
|
+
if name == "length"
|
33
|
+
Jint
|
34
|
+
else
|
35
|
+
recv_type = recv_type.component_type
|
36
|
+
end
|
37
|
+
elsif JavaClass === recv_type
|
38
|
+
recv_type
|
39
|
+
else
|
40
|
+
# otherwise, find the target method and get its return type
|
41
|
+
recv_java_class = recv_type
|
42
|
+
arg_types = []
|
43
|
+
args_node.child_nodes.each do |node|
|
44
|
+
arg_types << node.type(builder)
|
45
|
+
end if args_node
|
46
|
+
declared_method = recv_java_class.declared_method_smart(mapped_name(builder), *arg_types)
|
47
|
+
return_type = declared_method.return_type
|
48
|
+
|
49
|
+
builder.type(return_type.to_s)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class ConstNode
|
56
|
+
def type(builder)
|
57
|
+
@type ||= builder.type(name)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class FCallNode
|
62
|
+
def special_signature(recv_type, builder)
|
63
|
+
arg_types = []
|
64
|
+
args_node.child_nodes.each do |node|
|
65
|
+
arg_types << node.type(builder)
|
66
|
+
end if args_node
|
67
|
+
recv_java_class = recv_type
|
68
|
+
declared_method = recv_java_class.declared_method_smart(mapped_name(builder), *arg_types)
|
69
|
+
return_type = declared_method.return_type
|
70
|
+
if (return_type)
|
71
|
+
return_class = return_type
|
72
|
+
else
|
73
|
+
return_class = Void
|
74
|
+
end
|
75
|
+
|
76
|
+
return [
|
77
|
+
return_class,
|
78
|
+
*declared_method.parameter_types
|
79
|
+
]
|
80
|
+
end
|
81
|
+
|
82
|
+
def type(builder)
|
83
|
+
@type ||= begin
|
84
|
+
arg_types = []
|
85
|
+
args_node.child_nodes.each do |node|
|
86
|
+
arg_types << node.type(builder)
|
87
|
+
end if args_node
|
88
|
+
if builder.static
|
89
|
+
signature = builder.static_signature(name, arg_types)
|
90
|
+
else
|
91
|
+
signature = builder.instance_signature(name, arg_types)
|
92
|
+
end
|
93
|
+
raise CompileError.new(position, "Signature not found for call #{name}") unless signature
|
94
|
+
|
95
|
+
signature[0]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class FixnumNode
|
101
|
+
def type(builder)
|
102
|
+
Jint
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class FloatNode
|
107
|
+
def type(builder)
|
108
|
+
Jfloat
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class InstVarNode
|
113
|
+
def type(builder)
|
114
|
+
@type ||= builder.field_type(mapped_name(builder))
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class InstAsgnNode
|
119
|
+
def type(builder)
|
120
|
+
builder.field(mapped_name(builder), value_node.type(builder))
|
121
|
+
@type ||= builder.field_type(mapped_name(builder))
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class LocalAsgnNode
|
126
|
+
def type(builder)
|
127
|
+
@type ||= builder.local_type(name)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
class LocalVarNode
|
132
|
+
def type(builder)
|
133
|
+
@type ||= builder.local_type(name)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class ModuleNode
|
138
|
+
end
|
139
|
+
|
140
|
+
class NewlineNode
|
141
|
+
def type(builder)
|
142
|
+
@type ||= next_node.type(builder)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
class StrNode
|
147
|
+
def type(builder)
|
148
|
+
JString
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
class VCallNode
|
153
|
+
def type(builder)
|
154
|
+
@type ||= if builder.static
|
155
|
+
builder.static_signature(name, [])[0]
|
156
|
+
else
|
157
|
+
builder.instance_signature(name, [])[0]
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
Duby::AST.defmacro('def_edb') do |transformer, fcall, parent|
|
4
|
+
name = fcall.args_node.get(0).name
|
5
|
+
path = fcall.args_node.get(1).value
|
6
|
+
compiler = ERB::Compiler.new(nil)
|
7
|
+
compiler.put_cmd = "_edbout.append"
|
8
|
+
compiler.insert_cmd = "__edb_insert__ _edbout.append"
|
9
|
+
compiler.pre_cmd = ["def #{name}", "_edbout = StringBuilder.new"]
|
10
|
+
compiler.post_cmd = ["_edbout.toString", "end"]
|
11
|
+
src = compiler.compile(IO.read(path))
|
12
|
+
ast = Duby::AST.parse_ruby(src, "(edb)")
|
13
|
+
transformer.transform(ast.body_node, parent)
|
14
|
+
end
|
15
|
+
|
16
|
+
Duby::AST.defmacro('__edb_insert__') do |transformer, fcall, parent|
|
17
|
+
# ERB sticks in a .to_s that we don't want.
|
18
|
+
# the ast is __edb_insert__(_edbout.append(content.to_s))
|
19
|
+
append = fcall.args_node.get(0)
|
20
|
+
content = append.args_node.get(0).receiver_node
|
21
|
+
new_args = org.jrubyparser.ast.ListNode.new(content.position, content)
|
22
|
+
append.setArgsNode(new_args)
|
23
|
+
transformer.transform(append, parent)
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'duby/typer'
|
2
|
+
require 'duby/jvm/method_lookup'
|
3
|
+
require 'duby/jvm/types'
|
4
|
+
require 'java'
|
5
|
+
|
6
|
+
module Duby
|
7
|
+
module Typer
|
8
|
+
class JavaTyper < BaseTyper
|
9
|
+
include Duby::JVM::MethodLookup
|
10
|
+
include Duby::JVM::Types
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
end
|
14
|
+
|
15
|
+
def name
|
16
|
+
"Java"
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_type(typer, target_type, name, parameter_types)
|
20
|
+
return if target_type.nil? or parameter_types.any? {|t| t.nil?}
|
21
|
+
if target_type.respond_to? :get_method
|
22
|
+
method = target_type.get_method(name, parameter_types)
|
23
|
+
unless method || target_type.basic_type.kind_of?(TypeDefinition)
|
24
|
+
raise NoMethodError, "Method %s(%s) on %s not found" %
|
25
|
+
[name, parameter_types.join(', '), target_type]
|
26
|
+
end
|
27
|
+
result = method.return_type if method
|
28
|
+
end
|
29
|
+
|
30
|
+
if result
|
31
|
+
log "Method type for \"#{name}\" #{parameter_types} on #{target_type} = #{result}"
|
32
|
+
else
|
33
|
+
log "Method type for \"#{name}\" #{parameter_types} on #{target_type} not found"
|
34
|
+
end
|
35
|
+
|
36
|
+
result
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
typer_plugins << Typer::JavaTyper.new
|
42
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'duby/typer'
|
2
|
+
|
3
|
+
module Duby
|
4
|
+
module Typer
|
5
|
+
class MathTyper < BaseTyper
|
6
|
+
def name
|
7
|
+
"Math"
|
8
|
+
end
|
9
|
+
|
10
|
+
def method_type(typer, target_type, name, parameter_types)
|
11
|
+
return nil unless parameter_types.size == 1
|
12
|
+
|
13
|
+
result = case name
|
14
|
+
when '-', '+', '*', '/', '%'
|
15
|
+
case target_type
|
16
|
+
when typer.fixnum_type
|
17
|
+
case parameter_types[0]
|
18
|
+
when typer.fixnum_type
|
19
|
+
typer.fixnum_type
|
20
|
+
when typer.float_type
|
21
|
+
typer.float_type
|
22
|
+
else
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
when typer.float_type
|
26
|
+
case parameter_types[0]
|
27
|
+
when typer.float_type
|
28
|
+
typer.float_type
|
29
|
+
when typer.fixnum_type
|
30
|
+
typer.float_type
|
31
|
+
else
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
else
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
when '<<', '>>', '>>>', '&', '|', '^'
|
38
|
+
case target_type
|
39
|
+
when typer.fixnum_type
|
40
|
+
case parameter_types[0]
|
41
|
+
when typer.fixnum_type
|
42
|
+
typer.fixnum_type
|
43
|
+
else
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
else
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
when '<', '>', '<=', '>=', '=='
|
50
|
+
case target_type
|
51
|
+
when typer.fixnum_type
|
52
|
+
case parameter_types[0]
|
53
|
+
when typer.fixnum_type
|
54
|
+
typer.boolean_type
|
55
|
+
else
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
when typer.float_type
|
59
|
+
case parameter_types[0]
|
60
|
+
when typer.float_type
|
61
|
+
typer.boolean_type
|
62
|
+
else
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
else
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
else
|
69
|
+
nil
|
70
|
+
end
|
71
|
+
|
72
|
+
if result
|
73
|
+
log "Method type for \"#{name}\" #{parameter_types} on #{target_type} = #{result}"
|
74
|
+
else
|
75
|
+
log "Method type for \"#{name}\" #{parameter_types} on #{target_type} not found"
|
76
|
+
end
|
77
|
+
|
78
|
+
result
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
typer_plugins << Typer::MathTyper.new
|
84
|
+
end
|