mirah 0.0.5-java → 0.0.6-java

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 (63) hide show
  1. data/History.txt +33 -0
  2. data/README.txt +2 -3
  3. data/Rakefile +5 -0
  4. data/bin/duby +0 -0
  5. data/bin/dubyc +0 -0
  6. data/bin/dubyp +0 -0
  7. data/bin/jrubyp +0 -0
  8. data/bin/mirah +0 -0
  9. data/bin/mirah.cmd +14 -14
  10. data/bin/mirahc +0 -0
  11. data/bin/mirahc.cmd +14 -14
  12. data/bin/mirahp +0 -0
  13. data/bin/mirahp.cmd +14 -14
  14. data/examples/Dynamic.class +0 -0
  15. data/examples/SizeThing.class +0 -0
  16. data/examples/plugins/appengine/Rakefile +3 -1
  17. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/MetaModel.mirah +385 -0
  18. data/examples/plugins/appengine/src/com/google/appengine/ext/duby/db/Model.duby +58 -15
  19. data/examples/wiki/war/public/javascripts/prettify.js +0 -0
  20. data/examples/wiki/war/public/stylesheets/prettify.css +0 -0
  21. data/javalib/dynalink-0.1.jar +0 -0
  22. data/javalib/jsr292-mock.jar +0 -0
  23. data/javalib/mirah-bootstrap.jar +0 -0
  24. data/javalib/mirah-parser.jar +0 -0
  25. data/lib/mirah.rb +45 -25
  26. data/lib/mirah/ast.rb +81 -27
  27. data/lib/mirah/ast/call.rb +62 -71
  28. data/lib/mirah/ast/class.rb +23 -26
  29. data/lib/mirah/ast/flow.rb +38 -62
  30. data/lib/mirah/ast/intrinsics.rb +59 -37
  31. data/lib/mirah/ast/literal.rb +16 -14
  32. data/lib/mirah/ast/local.rb +8 -8
  33. data/lib/mirah/ast/method.rb +33 -19
  34. data/lib/mirah/ast/structure.rb +54 -13
  35. data/lib/mirah/ast/type.rb +8 -11
  36. data/lib/mirah/compiler.rb +86 -0
  37. data/lib/mirah/errors.rb +60 -0
  38. data/lib/mirah/jvm/base.rb +5 -11
  39. data/lib/mirah/jvm/compiler.rb +12 -1
  40. data/lib/mirah/jvm/source_compiler.rb +10 -2
  41. data/lib/mirah/jvm/source_generator/builder.rb +3 -1
  42. data/lib/mirah/jvm/source_generator/precompile.rb +6 -0
  43. data/lib/mirah/jvm/typer.rb +6 -1
  44. data/lib/mirah/jvm/types.rb +8 -0
  45. data/lib/mirah/jvm/types/factory.rb +34 -10
  46. data/lib/mirah/jvm/types/intrinsics.rb +12 -5
  47. data/lib/mirah/jvm/types/methods.rb +5 -9
  48. data/lib/mirah/plugin/gwt.rb +3 -2
  49. data/lib/mirah/transform.rb +68 -10
  50. data/lib/mirah/transform2.rb +10 -1
  51. data/lib/mirah/typer.rb +5 -10
  52. data/lib/mirah/version.rb +1 -1
  53. data/test/test_compilation.rb +1 -1
  54. data/test/test_java_typer.rb +10 -0
  55. data/test/test_javac_compiler.rb +4 -2
  56. data/test/test_jvm_compiler.rb +132 -9
  57. data/test/test_macros.rb +51 -0
  58. data/test/test_typer.rb +29 -25
  59. metadata +13 -21
  60. data/examples/plugins/appengine/lib/com/google/appengine/ext/duby/db/datastore.rb +0 -390
  61. data/javalib/JRubyParser.jar +0 -0
  62. data/javalib/dynalang-invoke-0.1.jar +0 -0
  63. data/lib/mirah/nbcompiler.rb +0 -44
@@ -0,0 +1,60 @@
1
+ module Mirah
2
+ class MirahError < StandardError
3
+ attr_accessor :position
4
+ attr_accessor :cause
5
+
6
+ def initialize(message, position=nil)
7
+ super(message)
8
+ @position = position
9
+ end
10
+ end
11
+
12
+ class NodeError < MirahError
13
+ attr_reader :node
14
+
15
+ def initialize(message, node=nil)
16
+ position = node.position if node
17
+ super(message, position)
18
+ @node = node
19
+ end
20
+
21
+ def node=(node)
22
+ @position = node ? node.position : nil
23
+ @node = node
24
+ end
25
+
26
+ def self.wrap(ex, node)
27
+ if ex.kind_of?(NodeError)
28
+ ex.node ||= node
29
+ return ex
30
+ elsif ex.kind_of?(MirahError)
31
+ ex.position ||= node.position
32
+ return ex
33
+ else
34
+ new_ex = new(ex.message, node)
35
+ new_ex.cause = ex
36
+ new_ex.position ||= ex.position if ex.respond_to?(:position)
37
+ new_ex.set_backtrace(ex.backtrace)
38
+ return new_ex
39
+ end
40
+ end
41
+
42
+ def position
43
+ if node && node.position
44
+ node.position
45
+ else
46
+ super
47
+ end
48
+ end
49
+ end
50
+
51
+ class SyntaxError < NodeError
52
+ end
53
+
54
+
55
+ class InferenceError < NodeError
56
+ end
57
+
58
+ class InternalCompilerError < NodeError
59
+ end
60
+ end
@@ -18,12 +18,7 @@ module Mirah
18
18
  class JVMCompilerBase
19
19
  attr_accessor :filename, :method, :static, :class
20
20
 
21
- class CompilationError < Exception
22
- attr_accessor :node
23
- def initialize(msg, node = nil)
24
- super(msg)
25
- @node = node
26
- end
21
+ class CompilationError < Mirah::NodeError
27
22
  end
28
23
 
29
24
  def initialize
@@ -41,8 +36,7 @@ module Mirah
41
36
  begin
42
37
  ast.compile(self, expression)
43
38
  rescue => ex
44
- Mirah.print_error(ex.message, ast.position)
45
- raise ex
39
+ raise Mirah::InternalCompilerError.wrap(ex, ast)
46
40
  end
47
41
  log "Compilation successful!"
48
42
  end
@@ -196,8 +190,7 @@ module Mirah
196
190
  scope = body.static_scope
197
191
  declare_locals(scope)
198
192
  if scope != @self_scope
199
- @self_scope = scope
200
- if scope.self_node
193
+ if scope.self_node && scope.self_node != :self
201
194
  # FIXME This is a horrible hack!
202
195
  # Instead we should eliminate unused self's.
203
196
  unless scope.self_type.name == 'mirah.impl.Builtin'
@@ -205,6 +198,7 @@ module Mirah
205
198
  scope, 'self', scope.self_type, false, scope.self_node)
206
199
  end
207
200
  end
201
+ @self_scope = scope
208
202
  end
209
203
  end
210
204
  # all except the last element in a body of code is treated as a statement
@@ -238,7 +232,7 @@ module Mirah
238
232
  alias float fixnum
239
233
 
240
234
  def compile_self
241
- if @self_scope && @self_scope.self_node
235
+ if @self_scope && @self_scope.self_node && @self_scope.self_node != :self
242
236
  local(@self_scope, 'self', @self_scope.self_type)
243
237
  else
244
238
  real_self
@@ -120,6 +120,17 @@ module Mirah
120
120
  @method.new type
121
121
  @method.dup
122
122
  @method.invokespecial type, "<init>", [@method.void]
123
+ if scope.respond_to? :arguments
124
+ scope.arguments.args.each do |param|
125
+ name = param.name
126
+ param_type = param.inferred_type
127
+ if scope.static_scope.captured?(param.name)
128
+ @method.dup
129
+ type.load(@method, @method.local(name, param_type))
130
+ @method.putfield(type, name, param_type)
131
+ end
132
+ end
133
+ end
123
134
  type.store(@method, @method.local('$binding', type))
124
135
  end
125
136
  begin
@@ -716,7 +727,7 @@ module Mirah
716
727
  @method.dup
717
728
  n.compile(self, true)
718
729
  # TODO this feels like it should be in the node.compile itself
719
- if n.inferred_type.primitive?
730
+ if n.inferred_type!.primitive?
720
731
  n.inferred_type.box(@method)
721
732
  end
722
733
  @method.invokeinterface java::util::List, "add", [@method.boolean, @method.object]
@@ -128,6 +128,14 @@ module Mirah
128
128
  type = scope.binding_type
129
129
  @binding = @bindings[type]
130
130
  @method.puts "#{type.to_source} $binding = new #{type.to_source}();"
131
+ if scope.respond_to? :arguments
132
+ scope.arguments.args.each do |param|
133
+ if scope.static_scope.captured?(param.name)
134
+ captured_local_declare(scope, param.name, param.inferred_type)
135
+ @method.puts "$binding.#{param.name} = #{param.name};"
136
+ end
137
+ end
138
+ end
131
139
  end
132
140
  begin
133
141
  yield
@@ -218,7 +226,7 @@ module Mirah
218
226
  def this(method=nil)
219
227
  if method && method.static?
220
228
  method.declaring_class.name
221
- elsif @self_scope && @self_scope.self_node
229
+ elsif @self_scope && @self_scope.self_node && @self_scope.self_node != :self
222
230
  scoped_local_name('self', @self_scope)
223
231
  else
224
232
  @static ? @class.class_name : 'this'
@@ -472,7 +480,7 @@ module Mirah
472
480
 
473
481
  def call(call, expression)
474
482
  return cast(call, expression) if call.cast?
475
- if Mirah::AST::Constant === call.target
483
+ if Mirah::AST::Constant === call.target || Mirah::AST::Colon2 === call.target
476
484
  target = call.target.inferred_type.to_source
477
485
  else
478
486
  target = call.precompile_target(self)
@@ -231,7 +231,9 @@ module Mirah
231
231
  end
232
232
 
233
233
  def finish_declaration
234
+ raise if @stopped
234
235
  return if @declaration_finished
236
+
235
237
  @declaration_finished = true
236
238
  modifiers = "public#{' static' if @static}#{' abstract' if @abstract}"
237
239
  print "#{modifiers} class #{class_name} extends #{superclass.name}"
@@ -247,8 +249,8 @@ module Mirah
247
249
  end
248
250
 
249
251
  def stop
250
- finish_declaration
251
252
  return if @stopped
253
+ finish_declaration
252
254
  @methods.each do |method|
253
255
  @out << method.out
254
256
  end
@@ -200,4 +200,10 @@ module Mirah::AST
200
200
  false
201
201
  end
202
202
  end
203
+
204
+ class Colon2
205
+ def expr?(compiler)
206
+ true
207
+ end
208
+ end
203
209
  end
@@ -42,7 +42,12 @@ module Mirah
42
42
  end
43
43
 
44
44
  def type_reference(scope, name, array=false, meta=false)
45
- @factory.type(scope, name, array, meta)
45
+ begin
46
+ @factory.type(scope, name, array, meta)
47
+ rescue NameError => ex
48
+ known_types[name] = Mirah::AST.error_type
49
+ raise Mirah::InferenceError.wrap(ex, nil)
50
+ end
46
51
  end
47
52
 
48
53
  def name
@@ -146,6 +146,14 @@ module Mirah
146
146
  method.anewarray(self)
147
147
  end
148
148
 
149
+ def pop(method)
150
+ if wide?
151
+ method.pop2
152
+ else
153
+ method.pop
154
+ end
155
+ end
156
+
149
157
  def superclass
150
158
  raise "Incomplete type #{self}" unless jvm_type
151
159
  AST.type(nil, jvm_type.superclass) if jvm_type.superclass
@@ -106,22 +106,26 @@ module Mirah::JVM::Types
106
106
  end
107
107
 
108
108
  def find_type(scope, name)
109
+ saved_ex = nil
109
110
  begin
110
111
  return get_type(name)
111
112
  rescue NameError => ex
112
- raise ex if scope.nil?
113
+ saved_ex = ex
113
114
  end
114
115
 
115
- imports = scope.static_scope.imports
116
- if imports.include?(name)
117
- name = imports[name] while imports.include?(name)
118
- return get_type(name)
119
- end
116
+ if scope
117
+ imports = scope.static_scope.imports
118
+ if imports.include?(name)
119
+ name = imports[name] while imports.include?(name)
120
+ return get_type(name)
121
+ end
120
122
 
121
- # TODO support inner class names
122
- if name !~ /\./
123
- return package_search(name, scope)
123
+ # TODO support inner class names
124
+ if name !~ /\./
125
+ return package_search(name, scope)
126
+ end
124
127
  end
128
+ raise saved_ex
125
129
  end
126
130
 
127
131
  def package_search(name, scope)
@@ -141,7 +145,27 @@ module Mirah::JVM::Types
141
145
  def get_type(full_name)
142
146
  type = @known_types[full_name]
143
147
  return type.basic_type if type
144
- type = Type.new(get_mirror(full_name)).load_extensions
148
+ begin
149
+ mirror = get_mirror(full_name)
150
+ rescue NameError => ex
151
+ if full_name =~ /^(.+)\.([^.]+)/
152
+ outer_name = $1
153
+ inner_name = $2
154
+ begin
155
+ outer_type = get_type(outer_name)
156
+ full_name = "#{outer_type.name}$#{inner_name}"
157
+ rescue NameError
158
+ raise ex
159
+ end
160
+ mirror = get_mirror(full_name)
161
+ else
162
+ raise ex
163
+ end
164
+ end
165
+ type = Type.new(mirror).load_extensions
166
+ if full_name.include? '$'
167
+ @known_types[full_name.gsub('$', '.')] = type
168
+ end
145
169
  @known_types[full_name] = type
146
170
  end
147
171
 
@@ -74,18 +74,25 @@ module Mirah::JVM::Types
74
74
 
75
75
  def add_compiled_macro(klass, name, arg_types)
76
76
  add_macro(name, *arg_types) do |duby, call|
77
+ # Ick. We need to preserve the scope of the arguments to the macro.
78
+ # However the only way to do that is to wrap them in a ScopedBody.
79
+ # It'd be better if we didn't have to expose this wrapper node to
80
+ # the user code.
81
+ call.parameters = call.parameters.map do |arg|
82
+ wrapper = Mirah::AST::ScopedBody.new(call.parent, call.position)
83
+ wrapper.static_scope = call.scope.static_scope
84
+ wrapper << arg
85
+ end
77
86
  expander = klass.constructors[0].newInstance(duby, call)
78
87
  ast = expander.expand
79
88
  if ast
89
+ body = Mirah::AST::ScopedBody.new(call.parent, call.position)
90
+ body << ast
80
91
  if call.target
81
- body = Mirah::AST::ScopedBody.new(call.parent, call.position)
82
92
  body.static_scope.self_type = call.target.inferred_type!
83
93
  body.static_scope.self_node = call.target
84
- body << ast
85
- body
86
- else
87
- ast
88
94
  end
95
+ body
89
96
  else
90
97
  Mirah::AST::Noop.new(call.parent, call.position)
91
98
  end
@@ -207,11 +207,7 @@ module Mirah::JVM::Types
207
207
  end
208
208
 
209
209
  unless expression || void?
210
- if return_type.wide?
211
- compiler.method.pop2
212
- else
213
- compiler.method.pop
214
- end
210
+ return_type.pop(compiler.method)
215
211
  end
216
212
  end
217
213
 
@@ -238,7 +234,7 @@ module Mirah::JVM::Types
238
234
  end
239
235
 
240
236
  unless expression || void?
241
- compiler.method.pop
237
+ return_type.pop(compiler.method)
242
238
  end
243
239
  end
244
240
  end
@@ -255,7 +251,7 @@ module Mirah::JVM::Types
255
251
  # TODO: inference phase needs to track that signature is void
256
252
  # but actual type is null object
257
253
  compiler.method.aconst_null if expression && void?
258
- compiler.method.pop unless expression || void?
254
+ return_type.pop(compiler.method) unless expression || void?
259
255
  end
260
256
  end
261
257
 
@@ -290,7 +286,7 @@ module Mirah::JVM::Types
290
286
  [return_type, target, *@types])
291
287
 
292
288
  unless expression
293
- compiler.method.pop
289
+ return_type.pop(compiler.method)
294
290
  end
295
291
 
296
292
  compiler.bootstrap_dynamic
@@ -422,7 +418,7 @@ module Mirah::JVM::Types
422
418
 
423
419
  begin
424
420
  descriptors = types.map {|type| BiteScript::Signature.class_id(type)}
425
- method = jvm_type.getDeclaredMethod(name, *descriptors)
421
+ method = jvm_type.getDeclaredMethod(name, *descriptors) if jvm_type
426
422
 
427
423
  if method.nil? && superclass
428
424
  method = superclass.java_method(name, *types) rescue nil
@@ -107,9 +107,10 @@ module Mirah::AST
107
107
  compiler.define_jsni_method(self)
108
108
  end
109
109
 
110
- def infer(typer)
110
+ def infer(typer, expression)
111
111
  @static ||= scope.static_scope.self_type.meta? unless scope.nil?
112
112
  @defining_class ||= begin
113
+ static_scope.self_node = :self
113
114
  static_scope.self_type = if static?
114
115
  scope.static_scope.self_type.meta
115
116
  else
@@ -117,7 +118,7 @@ module Mirah::AST
117
118
  end
118
119
  end
119
120
  resolve_if(typer) do
120
- argument_types = typer.infer(arguments)
121
+ argument_types = typer.infer(arguments, true)
121
122
  if argument_types.all?
122
123
  typer.learn_method_type(defining_class, name, argument_types,
123
124
  signature[:return], signature[:throws])
@@ -15,16 +15,16 @@
15
15
 
16
16
  require 'base64'
17
17
  require 'jruby'
18
+ require 'mirah/errors'
18
19
 
19
20
  module Mirah
20
21
  module Transform
21
- class Error < StandardError
22
- attr_reader :position, :cause
22
+ class Error < Mirah::MirahError
23
+ attr_reader :position
23
24
  def initialize(msg, position, cause=nil)
24
- super(msg)
25
- @position = position
26
- @position = position.position if position.respond_to? :position
27
- @cause = cause
25
+ position = position.position if position.respond_to? :position
26
+ super(msg, position)
27
+ self.cause = cause
28
28
  end
29
29
  end
30
30
 
@@ -145,14 +145,35 @@ module Mirah
145
145
  duby_node
146
146
  end
147
147
 
148
- def dump_ast(node)
148
+ def dump_ast(node, call=nil)
149
149
  encoded = nil
150
150
  values = Mirah::AST::Unquote.extract_values do
151
151
  encoded = Base64.encode64(Marshal.dump(node))
152
152
  end
153
+ scope = call.scope.static_scope if call
153
154
  result = Mirah::AST::Array.new(nil, node.position)
154
- result << Mirah::AST::String.new(result, node.position, encoded)
155
- values.each {|value| result << value}
155
+ if encoded.size < 65535
156
+ result << Mirah::AST::String.new(result, node.position, encoded)
157
+ else
158
+ strings = Mirah::AST::StringConcat.new(result, node.position)
159
+ result << strings
160
+ while encoded.size >= 65535
161
+ chunk = encoded[0, 65535]
162
+ encoded[0, 65535] = ""
163
+ strings << Mirah::AST::String.new(strings, node.position, chunk)
164
+ end
165
+ strings << Mirah::AST::String.new(strings, node.position, encoded)
166
+ end
167
+ values.each do |value|
168
+ if call
169
+ scoped_value = Mirah::AST::ScopedBody.new(result, value.position)
170
+ scoped_value << value
171
+ scoped_value.static_scope = scope
172
+ else
173
+ scoped_value = value
174
+ end
175
+ result << scoped_value
176
+ end
156
177
  return result
157
178
  end
158
179
 
@@ -179,9 +200,33 @@ module Mirah
179
200
  node
180
201
  end
181
202
 
182
- def constant(name)
203
+ def constant(name, array=false)
183
204
  node = eval("Foo")
184
205
  node.name = name
206
+ node.array = array
207
+ node
208
+ end
209
+
210
+ def cast(type, value)
211
+ if value.kind_of?(String)
212
+ value = Mirah::AST::Local.new(@extra_body, @extra_body.position, value)
213
+ end
214
+ fcall = eval("Foo()")
215
+ fcall.name = type
216
+ fcall.parameters = [value]
217
+ fcall
218
+ end
219
+
220
+ def string(value)
221
+ node = eval('"Foo"')
222
+ node.literal = value
223
+ node
224
+ end
225
+
226
+ def empty_array(type_node, size_node)
227
+ node = eval('int[0]')
228
+ node.type_node = type_node
229
+ node.size = size_node
185
230
  node
186
231
  end
187
232
 
@@ -206,6 +251,19 @@ module Mirah
206
251
  append_node Mirah::AST::ClassDefinition.new(@extra_body, position, name, &block)
207
252
  end
208
253
 
254
+ def defineClass(name, superclass=nil)
255
+ define_class(@extra_body.position, name) do |class_def|
256
+ superclass = constant(superclass)
257
+ superclass.parent = class_def
258
+ [superclass, body(class_def)]
259
+ end
260
+ end
261
+
262
+ def body(parent=nil)
263
+ parent ||= @extra_body
264
+ Mirah::AST::Body.new(parent, parent.position)
265
+ end
266
+
209
267
  def define_closure(position, name, enclosing_type)
210
268
  target = self
211
269
  parent = @extra_body