duby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,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