mirah 0.1.1-java → 0.1.2-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.
@@ -16,18 +16,20 @@ require 'test_helper'
16
16
  require 'set'
17
17
 
18
18
  module JVMCompiler
19
- TEST_DEST = File.expand_path(File.dirname(__FILE__)+'/../../tmp_test/') + "/"
20
19
  $CLASSPATH << TEST_DEST
21
20
 
22
- import java.lang.System
23
- import java.io.PrintStream
21
+ java_import 'java.lang.System'
22
+ java_import 'java.io.PrintStream'
23
+ java_import 'java.net.URLClassLoader'
24
+ java_import 'org.jruby.javasupport.JavaClass'
25
+
24
26
  include Mirah
25
27
 
26
28
  def new_state
27
29
  state = Mirah::Util::CompilationState.new
28
30
  state.save_extensions = true
29
31
  state.destination = TEST_DEST
30
- state.classpath = TEST_DEST
32
+ state.classpath = Env.encode_paths [TEST_DEST, FIXTURE_TEST_DEST]
31
33
  state.type_system = type_system if type_system
32
34
  state
33
35
  end
@@ -71,7 +73,7 @@ module JVMCompiler
71
73
  ast
72
74
  end
73
75
 
74
- def generate_classes compiler_results
76
+ def generate_classes compiler_results, state
75
77
  classes = {}
76
78
 
77
79
  compiler_results.each do |result|
@@ -83,11 +85,15 @@ module JVMCompiler
83
85
  classes[result.filename[0..-7]] = Mirah::Util::ClassLoader.binary_string bytes
84
86
  end
85
87
 
86
- loader = Mirah::Util::ClassLoader.new(JRuby.runtime.jruby_class_loader, classes)
88
+ loader = Mirah::Util::ClassLoader.new(
89
+ URLClassLoader.new(
90
+ Mirah::Env.make_urls(state.classpath),
91
+ JRuby.runtime.jruby_class_loader),
92
+ classes)
87
93
 
88
94
  classes.keys.map do |name|
89
95
  cls = loader.load_class(name.tr('/', '.'))
90
- JavaUtilities.get_proxy_class(cls.name)
96
+ JavaUtilities.get_proxy_class(JavaClass.get(JRuby.runtime, cls))
91
97
  end
92
98
  end
93
99
 
@@ -107,9 +113,10 @@ module JVMCompiler
107
113
  ast = [AST.parse_ruby(nil, code, name)]
108
114
 
109
115
  scoper, typer = generator.infer_asts(ast, true)
116
+ generator.do_transforms ast
110
117
  compiler_results = generator.compiler.compile_asts(ast, scoper, typer)
111
118
 
112
- generate_classes compiler_results
119
+ generate_classes compiler_results, state
113
120
  end
114
121
 
115
122
  def tmp_script_name
@@ -119,8 +126,8 @@ end
119
126
 
120
127
 
121
128
  module CommonAssertions
122
- import java.lang.System
123
- import java.io.PrintStream
129
+ java_import 'java.lang.System'
130
+ java_import 'java.io.PrintStream'
124
131
 
125
132
  def assert_include(value, array, message=nil)
126
133
  message = build_message message, '<?> does not include <?>', array, value
@@ -21,4 +21,14 @@ class JVMCommandsTest < Test::Unit::TestCase
21
21
  Mirah::Commands::Run.new(['-e','puts 1']).execute
22
22
  end
23
23
  end
24
+
25
+ def test_runtime_classpath_modifications
26
+ assert_output "1234\n" do
27
+ Mirah::Commands::Run.new(['-c', FIXTURE_TEST_DEST,
28
+ '-e',
29
+ 'import org.foo.LowerCaseInnerClass
30
+ puts LowerCaseInnerClass.inner.field']
31
+ ).execute
32
+ end
33
+ end
24
34
  end
@@ -0,0 +1,49 @@
1
+ # Copyright (c) 2013 The Mirah project authors. All Rights Reserved.
2
+ # All contributing project authors may be found in the NOTICE file.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ class StringBuilderExtensionsTest < Test::Unit::TestCase
17
+ def test_string_builder_greetings
18
+ result = '<p>Greetings are: hello hola ciao salut hallo</p>'
19
+ cls, = compile(<<-EOF)
20
+ def greetings
21
+ languages = ['hello ', 'hola ', 'ciao ', 'salut ', 'hallo']
22
+ greetings = StringBuilder.new
23
+ greetings << '<p>Greetings are: '
24
+ languages.each { |greet| greetings << greet }
25
+ greetings << '</p>'
26
+ greetings.toString
27
+ end
28
+ EOF
29
+ assert_equal result, cls.greetings
30
+ end
31
+
32
+ def test_string_builder_shovel_object
33
+ cls, = compile(<<-EOF)
34
+ class MyObject
35
+ def toString
36
+ "Hey, I am a shiny instance of \#{getClass.getName}"
37
+ end
38
+ end
39
+
40
+ def shovel_object
41
+ sb = StringBuilder.new
42
+ sb << MyObject.new
43
+ sb.toString
44
+ end
45
+ EOF
46
+ result = 'Hey, I am a shiny instance of MyObject'
47
+ assert_equal result, cls.shovel_object
48
+ end
49
+ end
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- class StringTest < Test::Unit::TestCase
16
+ class StringExtensionsTest < Test::Unit::TestCase
17
17
 
18
18
  def test_string_concat
19
19
  cls, = compile("
@@ -38,4 +38,35 @@ class StringTest < Test::Unit::TestCase
38
38
  assert_equal("a1", cls.str_long)
39
39
  end
40
40
 
41
+ def test_string_included
42
+ cls, = compile("def included; 'abcdef'.include? 'd'; end")
43
+ assert cls.included, 'failed to find the contained string'
44
+ end
45
+
46
+ def test_string_dont_include
47
+ cls, = compile("def dont_include; 'abcdef'.include? 'g'; end")
48
+ refute cls.dont_include, 'mistakenly found contained string'
49
+ end
50
+
51
+ def test_string_include_wrong_type
52
+ assert_raises Mirah::MirahError do
53
+ compile("def include_wrong_type; 'abcdef'.include? 1; end")
54
+ end
55
+ end
56
+
57
+ def test_string_match
58
+ cls, = compile("def match; 'abcdef' =~ /d/; end")
59
+ assert cls.match, 'failed to match string'
60
+ end
61
+
62
+ def test_string_dont_match
63
+ cls, = compile("def dont_match; 'abcdef' =~ /g/; end")
64
+ refute cls.dont_match, 'mistakenly matched string'
65
+ end
66
+
67
+ def test_string_match_wrong_type
68
+ assert_raises Mirah::MirahError do
69
+ compile("def match_wrong_type; 'abcdef' =~ 'd'; end")
70
+ end
71
+ end
41
72
  end
@@ -358,7 +358,7 @@ class CompareSpecificityTest < BaseMethodLookupTest
358
358
  end
359
359
 
360
360
  def assert_specificity(a, b, value)
361
- actual = MethodLookup.compareSpecificity(make_method(a), make_method(b))
361
+ actual = MethodLookup.compareSpecificity(make_method(a), make_method(b), [nil, nil])
362
362
  assert_block "Expected compareSpecificity(#{a.inspect}, #{b.inspect}) = #{value} but was #{actual}" do
363
363
  if value.nan?
364
364
  actual.nan?
@@ -423,7 +423,7 @@ class FindMaximallySpecificTest < BaseMethodLookupTest
423
423
  method = make_method(m)
424
424
  methods[method] = m
425
425
  end
426
- result = MethodLookup.findMaximallySpecific(methods.keys)
426
+ result = MethodLookup.findMaximallySpecific(methods.keys, [nil, nil])
427
427
  result.map {|m| methods[m] || m}
428
428
  end
429
429
 
@@ -21,6 +21,7 @@ class BaseMirrorsTest < Test::Unit::TestCase
21
21
  java_import 'org.mirah.jvm.mirrors.JVMScope'
22
22
  java_import 'org.mirah.jvm.types.JVMType'
23
23
  java_import 'org.mirah.jvm.types.JVMTypeUtils'
24
+ java_import 'org.mirah.typer.AssignableTypeFuture'
24
25
  java_import 'org.mirah.typer.BaseTypeFuture'
25
26
  java_import 'org.mirah.typer.CallFuture'
26
27
  java_import 'org.mirah.typer.TypeFuture'
@@ -45,7 +46,7 @@ class BaseMirrorsTest < Test::Unit::TestCase
45
46
  end
46
47
 
47
48
  def assert_descriptor(descriptor, type)
48
- assert(type.isResolved)
49
+ assert(type.isResolved, type.resolve.toString)
49
50
  assert_resolved_to(descriptor, type.resolve)
50
51
  assert_not_error(type)
51
52
  end
@@ -62,7 +63,7 @@ class BaseMirrorsTest < Test::Unit::TestCase
62
63
  end
63
64
 
64
65
  def assert_not_error(type)
65
- assert(!type.resolve.isError)
66
+ assert(!type.resolve.isError, type.resolve.toString)
66
67
  end
67
68
 
68
69
  def assert_subtype_of(supertype, subtype)
@@ -405,6 +406,26 @@ class MTS_MethodLookupTest < BaseMirrorsTest
405
406
  assert_resolved_to('I', type.resolve.returnType)
406
407
  end
407
408
 
409
+ def test_async_return_type_from_superclass
410
+ a = define_type('A')
411
+ b = define_type('B', a)
412
+ type = CallFuture.new(@types, @scope, b, true, 'foo', [], [], nil)
413
+ assert_error(type)
414
+ @types.getMethodDefType(a, 'foo', [], a, nil)
415
+ assert_not_error(type)
416
+ assert_descriptor('LA;', type)
417
+ end
418
+
419
+ def test_async_return_type_from_interface
420
+ a = define_type('A')
421
+ b = define_type('B', main_type, [a])
422
+ type = CallFuture.new(@types, @scope, b, true, 'foo', [], [], nil)
423
+ assert_error(type)
424
+ @types.getMethodDefType(a, 'foo', [], a, nil)
425
+ assert_not_error(type)
426
+ assert_descriptor('LA;', type)
427
+ end
428
+
408
429
  def test_infer_return_type_from_body
409
430
  future = @types.getMethodDefType(main_type, 'foo', [], nil, nil)
410
431
  type = @types.getMethodType(
@@ -420,9 +441,13 @@ class MTS_MethodLookupTest < BaseMirrorsTest
420
441
  @scope.selfType_set(type)
421
442
  int = @types.wrap(Type.getType("I"))
422
443
  short = @types.wrap(Type.getType("S"))
423
- @types.getMethodDefType(type, 'foo', [int], int, nil)
444
+ decl = AssignableTypeFuture.new(nil)
445
+ decl.declare(int, nil)
446
+ @types.getMethodDefType(type, 'foo', [decl], int, nil)
424
447
  argument_future = BaseTypeFuture.new
425
- @types.getMethodDefType(type, 'foo', [argument_future], short, nil)
448
+ decl = AssignableTypeFuture.new(nil)
449
+ decl.declare(argument_future, nil)
450
+ @types.getMethodDefType(type, 'foo', [decl], short, nil)
426
451
 
427
452
  call_future = CallFuture.new(@types, @scope, type, true, 'foo', [short], [], nil)
428
453
  assert_not_error(call_future)
@@ -436,9 +461,13 @@ class MTS_MethodLookupTest < BaseMirrorsTest
436
461
  def test_async_arguments_meta
437
462
  int = @types.wrap(Type.getType("I"))
438
463
  short = @types.wrap(Type.getType("S"))
439
- @types.getMethodDefType(main_type, 'foo', [int], int, nil)
464
+ decl = AssignableTypeFuture.new(nil)
465
+ decl.declare(int, nil)
466
+ @types.getMethodDefType(main_type, 'foo', [decl], int, nil)
440
467
  argument_future = BaseTypeFuture.new
441
- @types.getMethodDefType(main_type, 'foo', [argument_future], short, nil)
468
+ decl = AssignableTypeFuture.new(nil)
469
+ decl.declare(argument_future, nil)
470
+ @types.getMethodDefType(main_type, 'foo', [decl], short, nil)
442
471
 
443
472
  call_future = CallFuture.new(@types, @scope, main_type, true, 'foo', [short], [], nil)
444
473
  assert_not_error(call_future)
@@ -455,8 +484,10 @@ class MTS_MethodLookupTest < BaseMirrorsTest
455
484
  b = @types.defineType(@scope, ClassDefinition.new, "B", super_future, [])
456
485
  a = @types.defineType(@scope, ClassDefinition.new, "A", b, [])
457
486
  c = @types.defineType(@scope, ClassDefinition.new, "C", nil, [])
487
+ decl = AssignableTypeFuture.new(nil)
488
+ decl.declare(c, nil)
458
489
 
459
- @types.getMethodDefType(main_type, 'foobar', [c],
490
+ @types.getMethodDefType(main_type, 'foobar', [decl],
460
491
  @types.getFixnumType(0), nil)
461
492
  type1 = CallFuture.new(@types, @scope, main_type, true, 'foobar', [b], [], nil)
462
493
  assert_error(type1)
@@ -559,4 +590,10 @@ class MTS_MethodLookupTest < BaseMirrorsTest
559
590
  @types, @scope, collections, true, 'checkedSet', [set, klass], [], nil)
560
591
  assert_equal('java.util.Set<FooBar>', checked.resolve.toString)
561
592
  end
593
+
594
+ def test_nil_argument
595
+ sb = @types.get(@scope, typeref('java.lang.StringBuilder'))
596
+ result = CallFuture.new(@types, @scope, sb, true, 'append', [@types.getNullType], [], nil)
597
+ assert_descriptor('Ljava/lang/StringBuilder;', result)
598
+ end
562
599
  end
@@ -19,6 +19,12 @@ require 'jruby'
19
19
  require 'stringio'
20
20
  require 'fileutils'
21
21
 
22
+ test_tmp_dir = File.expand_path(File.dirname(__FILE__)+'/../tmp_test/')
23
+ TEST_DEST = "#{test_tmp_dir}/test_classes/"
24
+ FIXTURE_TEST_DEST = "#{test_tmp_dir}/fixtures/"
25
+
26
+
27
+
22
28
  module CommonAssertions
23
29
  import java.lang.System
24
30
  import java.io.PrintStream
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mirah
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.1.1
4
+ version: 0.1.2
6
5
  platform: java
7
6
  authors:
8
7
  - Charles Oliver Nutter
@@ -10,7 +9,7 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2013-08-05 00:00:00.000000000 Z
12
+ date: 2014-01-05 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: bitescript
@@ -19,13 +18,11 @@ dependencies:
19
18
  - - '>='
20
19
  - !ruby/object:Gem::Version
21
20
  version: 0.1.4
22
- none: false
23
21
  requirement: !ruby/object:Gem::Requirement
24
22
  requirements:
25
23
  - - '>='
26
24
  - !ruby/object:Gem::Version
27
25
  version: 0.1.4
28
- none: false
29
26
  prerelease: false
30
27
  type: :runtime
31
28
  description: |-
@@ -93,7 +90,6 @@ files:
93
90
  - lib/mirah/jvm/types/literals.rb
94
91
  - lib/mirah/jvm/types/meta_type.rb
95
92
  - lib/mirah/jvm/types/methods.rb
96
- - lib/mirah/jvm/types/methods.rb~
97
93
  - lib/mirah/jvm/types/null_type.rb
98
94
  - lib/mirah/jvm/types/number.rb
99
95
  - lib/mirah/jvm/types/primitive_type.rb
@@ -105,7 +101,6 @@ files:
105
101
  - lib/mirah/transform/ast_ext.rb
106
102
  - lib/mirah/transform/transformer.rb
107
103
  - lib/mirah/util/argument_processor.rb
108
- - lib/mirah/util/argument_processor.rb~
109
104
  - lib/mirah/util/class_loader.rb
110
105
  - lib/mirah/util/compilation_state.rb
111
106
  - lib/mirah/util/delegate.rb
@@ -116,6 +111,9 @@ files:
116
111
  - test/core/env_test.rb
117
112
  - test/core/generator_test.rb
118
113
  - test/core/typer_test.rb
114
+ - test/core/typer/assignable_type_future_test.rb
115
+ - test/core/typer/error_type_test.rb
116
+ - test/core/typer/simple_type_test.rb
119
117
  - test/core/util/argument_processor_test.rb
120
118
  - test/core/util/class_loader_test.rb
121
119
  - test/core/util/compilation_state_test.rb
@@ -146,7 +144,8 @@ files:
146
144
  - test/jvm/new_backend_test_helper.rb
147
145
  - test/jvm/numeric_extensions_test.rb
148
146
  - test/jvm/rescue_test.rb
149
- - test/jvm/string_test.rb
147
+ - test/jvm/string_builder_extensions_test.rb
148
+ - test/jvm/string_extensions_test.rb
150
149
  - test/jvm/varargs_test.rb
151
150
  - test/mirrors/base_type_test.rb
152
151
  - test/mirrors/bytecode_mirror_test.rb
@@ -221,6 +220,7 @@ files:
221
220
  - javalib/mirah-bootstrap.jar
222
221
  - javalib/mirah-builtins.jar
223
222
  - javalib/mirah-compiler.jar
223
+ - javalib/mirah-mirrors.jar
224
224
  - javalib/mirah-newast-transitional.jar
225
225
  - javalib/mirah-parser.jar
226
226
  - javalib/mirah-util.jar
@@ -228,7 +228,9 @@ files:
228
228
  - Rakefile
229
229
  - README.md
230
230
  homepage: http://www.mirah.org/
231
- licenses: []
231
+ licenses:
232
+ - Apache-2.0
233
+ metadata: {}
232
234
  post_install_message:
233
235
  rdoc_options:
234
236
  - --main
@@ -239,25 +241,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
239
241
  requirements:
240
242
  - - '>='
241
243
  - !ruby/object:Gem::Version
242
- segments:
243
- - 0
244
- hash: 2
245
244
  version: '0'
246
- none: false
247
245
  required_rubygems_version: !ruby/object:Gem::Requirement
248
246
  requirements:
249
247
  - - '>='
250
248
  - !ruby/object:Gem::Version
251
- segments:
252
- - 0
253
- hash: 2
254
249
  version: '0'
255
- none: false
256
250
  requirements: []
257
251
  rubyforge_project: mirah
258
- rubygems_version: 1.8.24
252
+ rubygems_version: 2.1.11
259
253
  signing_key:
260
- specification_version: 3
254
+ specification_version: 4
261
255
  summary: Mirah is a customizable programming language featuring static types, local type inference and a heavily Ruby-inspired syntax
262
256
  test_files:
263
257
  - test/test_helper.rb
@@ -1,973 +0,0 @@
1
- # Copyright (c) 2010-2013 The Mirah project authors. All Rights Reserved.
2
- # All contributing project authors may be found in the NOTICE file.
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- require 'mirah/jvm/types'
17
-
18
- class Java::JavaMethod
19
- def static?
20
- java.lang.reflect.Modifier.static?(modifiers)
21
- end
22
-
23
- def abstract?
24
- java.lang.reflect.Modifier.abstract?(modifiers)
25
- end
26
- end
27
-
28
- class BiteScript::ASM::FieldMirror
29
- def returnType
30
- self.type
31
- end
32
- end
33
-
34
- module Mirah::JVM::Types
35
- AST ||= Mirah::AST
36
-
37
- module ArgumentConversion
38
- def convert_args(compiler, values, types=nil)
39
- # TODO boxing/unboxing
40
- types ||= argument_types
41
- needs_to_build_varargs_array = false
42
-
43
- if respond_to?(:varargs?) && varargs?
44
- non_varargs_types = types[0..-2]
45
- non_varargs_values = values.first non_varargs_types.size
46
-
47
- varargs_values = values.to_a.last(values.size - non_varargs_values.size)
48
- varargs_type = types.last
49
-
50
- unless varargs_values.length == 1 &&
51
- varargs_type.compatible?(compiler.inferred_type(varargs_values.first))
52
- needs_to_build_varargs_array = true
53
- values = non_varargs_values
54
- end
55
- end
56
-
57
- values_and_types = values.zip(types)
58
-
59
- values_and_types.each do |value, type|
60
- compiler.visit(value, true)
61
- in_type = compiler.inferred_type(value)
62
- if in_type.primitive? && type != in_type
63
- in_type.compile_widen(compiler.method, type)
64
- end
65
- end
66
-
67
- if needs_to_build_varargs_array
68
- compiler.visitVarargsArray(varargs_type, varargs_values)
69
- end
70
- end
71
- end
72
-
73
- Type.send :include, ArgumentConversion
74
-
75
- class Intrinsic
76
- include ArgumentConversion
77
- attr_reader :name, :argument_types, :return_type
78
-
79
- def initialize(klass, name, args, type, kind=nil, &block)
80
- raise ArgumentError, "Block required" unless block_given?
81
- @class = klass
82
- @name = name
83
- @argument_types = args
84
- @return_type = type
85
- @block = block
86
- @kind = kind
87
- end
88
-
89
- def kind
90
- Java::OrgMirahJvmTypes::MemberKind.const_get(@kind)
91
- end
92
-
93
- def accept(visitor, expression)
94
- name = "visit_#{@kind.downcase}".sub(/_op$/,"")
95
- visitor.send(name, self, expression)
96
- end
97
-
98
- def call(builder, ast, expression, *args)
99
- @block.call(builder, ast, expression, *args)
100
- end
101
-
102
- def declaring_class
103
- @class
104
- end
105
-
106
- def constructor?
107
- false
108
- end
109
-
110
- def field?
111
- false
112
- end
113
-
114
- def abstract?
115
- false
116
- end
117
-
118
- def exceptions
119
- []
120
- end
121
-
122
- def varargs?
123
- false
124
- end
125
-
126
- def isVararg
127
- varargs?
128
- end
129
- end
130
-
131
- class Macro
132
- java_import 'org.mirah.typer.InlineCode'
133
- java_import 'org.mirah.typer.NodeBuilder'
134
- attr_reader :name, :argument_types, :return_type
135
-
136
- def initialize(klass, name, args, &block)
137
- raise ArgumentError, "Block required" unless block_given?
138
- @class = klass
139
- @name = name
140
- @argument_types = args
141
- raise ArgumentError unless args.all?
142
- @return_type = InlineCode.new(block.to_java(NodeBuilder))
143
- end
144
-
145
- def declaring_class
146
- @class
147
- end
148
- end
149
-
150
- class JavaCallable
151
- include ArgumentConversion
152
-
153
- attr_accessor :member
154
-
155
- def initialize(types, member)
156
- raise ArgumentError unless types.kind_of?(Mirah::Typer::TypeSystem)
157
- @types = types
158
- @member = member
159
- end
160
-
161
- def name
162
- @name ||= @member.name
163
- end
164
-
165
- def field?
166
- false
167
- end
168
-
169
- def parameter_types
170
- @member.parameter_types
171
- end
172
-
173
- def synthetic?
174
- @member.synthetic?
175
- end
176
- end
177
-
178
- class JavaConstructor < JavaCallable
179
- def argument_types
180
- @argument_types ||= @member.argument_types.map do |arg|
181
- if arg.kind_of?(Type) || arg.nil?
182
- arg
183
- else
184
- @types.type(nil, arg)
185
- end
186
- end
187
- end
188
-
189
- def return_type
190
- declaring_class
191
- end
192
-
193
- def exceptions
194
- @member.exception_types.map do |exception|
195
- if exception.kind_of?(Mirah::Typer::ResolvedType)
196
- exception
197
- else
198
- @types.type(nil, exception.class_name)
199
- end
200
- end
201
- end
202
-
203
- def declaring_class
204
- @types.type(nil, @member.declaring_class)
205
- end
206
-
207
- def type_parameters
208
- @declaring_class and @declaring_class.jvm_type.type_parameters
209
- end
210
-
211
- def call(compiler, ast, expression, parameters=nil, delegate=false)
212
- target = compiler.inferred_type(ast.target)
213
- unless delegate
214
- compiler.method.new target
215
- compiler.method.dup if expression
216
- end
217
- parameters ||= ast.parameters
218
- convert_args(compiler, parameters)
219
- compiler.method.invokespecial(
220
- target,
221
- "<init>",
222
- [nil, *@member.argument_types])
223
- end
224
-
225
- def constructor?
226
- true
227
- end
228
-
229
- def varargs?
230
- @member.varargs?
231
- end
232
-
233
- def isVararg
234
- varargs?
235
- end
236
-
237
- def accept(visitor, expression)
238
- visitor.visitConstructor(self, expression)
239
- end
240
-
241
- def kind
242
- Java::OrgMirahJvmTypes::MemberKind::CONSTRUCTOR
243
- end
244
- end
245
-
246
- class JavaMethod < JavaConstructor
247
- def return_type
248
- @return_type ||= begin
249
- if void?
250
- @types.type(nil, 'void')
251
- else
252
- @types.type(nil, @member.return_type)
253
- end
254
- end
255
- end
256
-
257
- def static?
258
- @member.static?
259
- end
260
-
261
- def abstract?
262
- @member.abstract?
263
- end
264
-
265
- def type_parameters
266
- @member.type_parameters
267
- end
268
-
269
- def void?
270
- return_type = @member.return_type
271
- return true if return_type.nil?
272
- if return_type.respond_to?(:descriptor) && return_type.descriptor == 'V'
273
- return true
274
- end
275
- false
276
- end
277
-
278
- def constructor?
279
- false
280
- end
281
-
282
- def accept(visitor, expression)
283
- if self.static?
284
- visitor.visitStaticMethodCall(self, expression)
285
- else
286
- visitor.visitMethodCall(self, expression)
287
- end
288
- end
289
-
290
- def kind
291
- if self.static?
292
- Java::OrgMirahJvmTypes::MemberKind::STATIC_METHOD
293
- else
294
- Java::OrgMirahJvmTypes::MemberKind::METHOD
295
- end
296
- end
297
-
298
- def call(compiler, ast, expression, parameters=nil)
299
- target = compiler.inferred_type(ast.target)
300
- compiler.visit(ast.target, true)
301
-
302
- # if expression, void methods return the called object,
303
- # for consistency and chaining
304
- # TODO: inference phase needs to track that signature is
305
- # void but actual type is callee
306
- if expression && void?
307
- compiler.method.dup
308
- end
309
-
310
- parameters ||= ast.parameters
311
- convert_args(compiler, parameters)
312
- if target.interface?
313
- compiler.method.invokeinterface(
314
- target,
315
- name,
316
- [@member.return_type, *@member.argument_types])
317
- else
318
- compiler.method.invokevirtual(
319
- target,
320
- name,
321
- [@member.return_type, *@member.argument_types])
322
- end
323
-
324
- if expression && !void?
325
- # Insert a cast if the inferred type and actual type differ. This is part of generics support.
326
- inferred_return_type = compiler.inferred_type(ast)
327
- if !inferred_return_type.assignableFrom(return_type)
328
- compiler.method.checkcast(inferred_return_type)
329
- end
330
- end
331
-
332
- unless expression || void?
333
- return_type.pop(compiler.method)
334
- end
335
- end
336
-
337
- def call_special(compiler, target, target_type, parameters, expression)
338
- target_type ||= compiler.inferred_type(target)
339
- compiler.visit(target, true)
340
-
341
- # if expression, void methods return the called object,
342
- # for consistency and chaining
343
- # TODO: inference phase needs to track that signature is
344
- # void but actual type is callee
345
- if expression && void?
346
- compiler.method.dup
347
- end
348
-
349
- convert_args(compiler, parameters)
350
- if target_type.interface?
351
- raise "interfaces should not receive call_special"
352
- else
353
- compiler.method.invokespecial(
354
- target_type,
355
- name,
356
- [@member.return_type, *@member.argument_types])
357
- end
358
-
359
- unless expression || void?
360
- return_type.pop(compiler.method)
361
- end
362
- end
363
- end
364
-
365
- class JavaStaticMethod < JavaMethod
366
- def call(compiler, ast, expression, parameters=nil)
367
- target = declaring_class
368
- parameters ||= ast.parameters
369
- convert_args(compiler, parameters)
370
- compiler.method.invokestatic(
371
- target,
372
- name,
373
- [@member.return_type, *@member.argument_types])
374
- # if expression, void static methods return null, for consistency
375
- # TODO: inference phase needs to track that signature is void
376
- # but actual type is null object
377
- compiler.method.aconst_null if expression && void?
378
- return_type.pop(compiler.method) unless expression || void?
379
- end
380
-
381
- def accept(visitor, expression)
382
- visitor.visitStaticMethodCall(self, expression)
383
- end
384
-
385
- def kind
386
- Java::OrgMirahJvmTypes::MemberKind::STATIC_METHOD
387
- end
388
- end
389
-
390
- class JavaDynamicMethod < JavaMethod
391
- def initialize(type_system, name, *argument_types)
392
- super(type_system, nil)
393
- @name = name
394
- @argument_types = argument_types
395
- end
396
-
397
- def return_type
398
- @types.type(nil, 'dynamic')
399
- end
400
-
401
- def declaring_class
402
- java.lang.Object
403
- end
404
-
405
- def argument_types
406
- @argument_types
407
- end
408
-
409
- def call(compiler, ast, expression, parameters=nil)
410
- unless compiler.respond_to?(:supports_invokedynamic?) && compiler.supports_invokedynamic?
411
- raise Mirah::MirahError, "Target JVM version: #{compiler.target_jvm_version} doesn't support invoke dynamic"
412
- end
413
- target = compiler.inferred_type(ast.target)
414
- compiler.visit(ast.target, true)
415
-
416
- parameters ||= ast.parameters
417
- parameters.each do |param|
418
- compiler.visit(param, true)
419
- end
420
- handle = compiler.method.h_invokestatic(
421
- org.dynalang.dynalink.DefaultBootstrapper,
422
- "bootstrap",
423
- java.lang.invoke.CallSite,
424
- java.lang.invoke.MethodHandles::Lookup,
425
- java.lang.String,
426
- java.lang.invoke.MethodType)
427
- compiler.method.invokedynamic(
428
- "dyn:callPropWithThis:#{name}",
429
- [return_type, target, *@argument_types],
430
- handle)
431
-
432
- unless expression
433
- return_type.pop(compiler.method)
434
- end
435
- end
436
- end
437
-
438
- class JavaFieldAccessor < JavaMethod
439
- def field?
440
- true
441
- end
442
-
443
- def return_type
444
- @types.type(nil, @member.type)
445
- end
446
-
447
- def public?
448
- @member.public?
449
- end
450
-
451
- def final?
452
- @member.final?
453
- end
454
- end
455
-
456
- class JavaFieldGetter < JavaFieldAccessor
457
- def argument_types
458
- []
459
- end
460
-
461
- def call(compiler, ast, expression, parameters=nil)
462
- target = compiler.inferred_type(ast.target)
463
-
464
- # TODO: assert that no args are being passed, though that should have failed lookup
465
-
466
- if expression
467
- if @member.static?
468
- compiler.method.getstatic(target, name, @member.type)
469
- else
470
- compiler.visit(ast.target, true)
471
- compiler.method.getfield(target, name, @member.type)
472
- end
473
- end
474
- end
475
-
476
- def accept(visitor, expression)
477
- if self.static?
478
- visitor.visitStaticFieldAccess(self, expression)
479
- else
480
- visitor.visitFieldAccess(self, expression)
481
- end
482
- end
483
-
484
- def kind
485
- if self.static?
486
- Java::OrgMirahJvmTypes::MemberKind::STATIC_FIELD_ACCESS
487
- else
488
- Java::OrgMirahJvmTypes::MemberKind::FIELD_ACCESS
489
- end
490
- end
491
- end
492
-
493
- class JavaFieldSetter < JavaFieldAccessor
494
- def return_type
495
- @types.type(nil, @member.type)
496
- end
497
-
498
- def argument_types
499
- [@types.type(nil, @member.type)]
500
- end
501
-
502
- def call(compiler, ast, expression, parameters=nil)
503
- target = compiler.inferred_type(ast.target)
504
-
505
- # TODO: assert that no args are being passed, though that should have failed lookup
506
-
507
- parameters ||= ast.parameters
508
- if @member.static?
509
- convert_args(compiler, parameters)
510
- compiler.method.dup if expression
511
- compiler.method.putstatic(target, name, @member.type)
512
- else
513
- compiler.visit(ast.target, true)
514
- convert_args(compiler, parameters)
515
- compiler.method.dup_x2 if expression
516
- compiler.method.putfield(target, name, @member.type)
517
- end
518
- end
519
-
520
- def accept(visitor, expression)
521
- if self.static?
522
- visitor.visitStaticFieldAssign(self, expression)
523
- else
524
- visitor.visitFieldAssign(self, expression)
525
- end
526
- end
527
-
528
- def kind
529
- if self.static?
530
- Java::OrgMirahJvmTypes::MemberKind::STATIC_FIELD_ASSIGN
531
- else
532
- Java::OrgMirahJvmTypes::MemberKind::FIELD_ASSIGN
533
- end
534
- end
535
- end
536
-
537
- class MirahMember
538
- attr_reader :name, :argument_types, :declaring_class, :return_type
539
- attr_reader :exception_types
540
-
541
- def initialize(klass, name, args, return_type, static, exceptions)
542
- if return_type.name == 'void' || return_type.name == ':unreachable'
543
- return_type = nil
544
- end
545
- @declaring_class = klass
546
- @name = name
547
- @argument_types = args
548
- @return_type = return_type
549
- @static = static
550
- @exception_types = exceptions || []
551
- end
552
-
553
- def static?
554
- @static
555
- end
556
-
557
- def abstract?
558
- @declaring_class.interface?
559
- end
560
-
561
- def varargs?
562
- false
563
- end
564
-
565
- def isVararg
566
- varargs?
567
- end
568
- end
569
-
570
- class Type
571
- java_import "org.mirah.jvm.types.JVMMethod" rescue nil
572
-
573
- def method_listeners
574
- if meta?
575
- unmeta.method_listeners
576
- else
577
- @method_listeners ||= {}
578
- end
579
- end
580
-
581
- def method_updated(name)
582
- listeners = method_listeners[name]
583
- listeners.values.each do |l|
584
- if l.kind_of?(Proc)
585
- l.call(name)
586
- else
587
- l.method_updated(name)
588
- end
589
- end if listeners
590
- end
591
-
592
- def add_method_listener(name, listener=nil, &block)
593
- listeners = method_listeners[name] ||= {}
594
- if listener
595
- unless listener.respond_to?(:method_updated) || listener.kind_of?(Proc)
596
- raise "Invalid listener"
597
- end
598
- listeners[listener] = listener
599
- else
600
- listeners[block] = block
601
- end
602
- if !self.meta? && jvm_type && super_class_valid?
603
- superclass.add_method_listener(name, self)
604
- end
605
- interfaces.each {|i| i.add_method_listener(name, self) unless i.isError}
606
- end
607
-
608
- # TODO take a scope and check visibility
609
- def find_callable_macros(name)
610
- macros = find_callable_macros2 name
611
- macros.concat collect_up_interface_tree {|interface| interface.declared_macros(name) }
612
- macros
613
- end
614
-
615
- def find_callable_macros2(name)
616
- collect_up_inheritance_tree {|type| type.declared_macros name }
617
- end
618
-
619
- def find_callable_static_methods(name)
620
- collect_up_inheritance_tree { |type| type.declared_class_methods(name) }
621
- end
622
-
623
- # TODO take a scope and check visibility
624
- def find_callable_methods(name, include_interfaces=false, &proc)
625
- if block_given?
626
- add_method_listener(name) {proc.call(find_callable_methods(name))}
627
- proc.call(find_callable_methods(name))
628
- return
629
- end
630
-
631
- methods = find_callable_methods2 name
632
-
633
- if self.interface? || include_interfaces # TODO || self.abstract?
634
- methods.concat collect_up_interface_tree { |interface| interface.declared_instance_methods(name) }
635
- end
636
- methods
637
- end
638
-
639
- def find_callable_methods2(name)
640
- collect_up_inheritance_tree { |type| type.declared_instance_methods(name) }
641
- end
642
-
643
- def get_method(name, args)
644
- method = find_method(self, name, args, nil, meta?)
645
- unless method
646
- # Allow constant narrowing for assignment methods
647
- if name =~ /=$/ && args[-1].respond_to?(:narrow!)
648
- if args[-1].narrow!
649
- method = find_method(self, name, args, meta?)
650
- end
651
- end
652
- end
653
- method
654
- end
655
-
656
- def constructor(*types)
657
- begin
658
- constructor = jvm_type.getConstructor(*bitescript_signatures(types))
659
- return JavaConstructor.new(@type_system, constructor) if constructor
660
- rescue => ex
661
- log("#{ex.message}\n#{ex.backtrace.join("\n")}")
662
- end
663
- raise NameError, "No constructor #{name}(#{types.join ', '})"
664
- end
665
-
666
- def java_method(name, *types)
667
- intrinsic = intrinsics[name][types]
668
- return intrinsic if intrinsic
669
- jvm_types = types.map {|type| type.jvm_type}
670
-
671
- return JavaDynamicMethod.new(@type_system, name, *jvm_types) if dynamic?
672
-
673
- begin
674
- method = jvm_type.getDeclaredMethod(name, *bitescript_signatures(types)) if jvm_type
675
-
676
- if method.nil? && superclass
677
- method = superclass.java_method(name, *types) rescue nil
678
- end
679
-
680
- if method.nil? && jvm_type && jvm_type.abstract?
681
- interfaces.each do |interface|
682
- method = interface.java_method(name, *types) rescue nil
683
- break if method
684
- end
685
- end
686
-
687
- return method if method.kind_of?(JavaCallable)
688
- if method && method.static? == meta?
689
- return wrap_jvm_method method
690
- end
691
- rescue => ex
692
- log("#{ex.message}\n#{ex.backtrace.join("\n")}")
693
- end
694
- raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
695
- end
696
-
697
- def declared_instance_methods(name=nil)
698
- all_declared_jvm_methods(name).reject{ |method| method.static? && !method.synthetic? } +
699
- (meta? ? unmeta : self).declared_intrinsics(name)
700
- end
701
-
702
- def declared_class_methods(name=nil)
703
- all_declared_jvm_methods(name).select{ |method| method.static? && !method.synthetic? } +
704
- meta.declared_intrinsics(name)
705
- end
706
-
707
- def declared_constructors
708
- jvm_type.getConstructors.map do |method|
709
- JavaConstructor.new(@type_system, method)
710
- end
711
- end
712
-
713
- def field_getter(name)
714
- field = jvm_field(name)
715
- return nil unless field
716
-
717
- JavaFieldGetter.new(@type_system, field)
718
- end
719
-
720
- def field_setter(name)
721
- field = jvm_field(name)
722
- return nil unless field
723
-
724
- JavaFieldSetter.new(@type_system, field)
725
- end
726
-
727
- def inner_class_getter(name)
728
- full_name = "#{self.name}$#{name}"
729
- inner_class = @type_system.type(nil, full_name) rescue nil
730
- return unless inner_class
731
-
732
- inner_class.inner_class = true
733
- macro = Macro.new(self, name, []) do |call, typer|
734
- Mirah::AST::Constant.new(call.position, Mirah::AST::SimpleString.new(call.position, full_name))
735
- end
736
- intrinsics[name][[]] = macro
737
- end
738
-
739
- def getDeclaredFields
740
- @member.getDeclaredFields.to_java(JVMMethod)
741
- end
742
-
743
- def getDeclaredField(name)
744
- @member.getDeclaredField(name)
745
- end
746
-
747
- def hasStaticField(name)
748
- f = getDeclaredField(name)
749
- f && f.static?
750
- end
751
-
752
- protected
753
-
754
- def find_interfaces
755
- collect_up_inheritance_tree {|type| type.interfaces }
756
- end
757
-
758
- def collect_up_interface_tree &block
759
- interfaces = find_interfaces
760
- things = []
761
- seen = {}
762
- until interfaces.empty?
763
- interface = interfaces.pop
764
- next if seen[interface]
765
- seen[interface] = true
766
- interfaces.concat(interface.interfaces)
767
- new_things = block.call interface
768
- things.concat new_things if new_things
769
- end
770
- things
771
- end
772
-
773
- def collect_up_inheritance_tree(&block)
774
- things = []
775
- new_things = block.call(self)
776
- things.concat new_things if new_things
777
- if super_class_valid?
778
- things.concat superclass.collect_up_inheritance_tree(&block)
779
- end
780
- things
781
- end
782
-
783
- private
784
-
785
- def super_class_valid?
786
- superclass && !superclass.error?
787
- end
788
-
789
- def all_declared_jvm_methods(name=nil)
790
- return [] if !jvm_type || (meta? ? unmeta : self).array?
791
-
792
- jvm_type.getDeclaredMethods(name).map { |method| wrap_jvm_method method }
793
- end
794
-
795
- def wrap_jvm_method method
796
- if (method.static? && !method.synthetic?)
797
- JavaStaticMethod.new(@type_system, method)
798
- else
799
- JavaMethod.new(@type_system, method)
800
- end
801
- end
802
-
803
- def jvm_field(name)
804
- return nil unless jvm_type
805
- jvm_type.getField(name)
806
- end
807
-
808
- def bitescript_signatures types
809
- types.map {|type| BiteScript::Signature.class_id(type)}
810
- end
811
- end
812
-
813
- class TypeDefinition
814
- java_import "org.mirah.jvm.types.JVMMethod" rescue nil
815
-
816
- def java_method(name, *types)
817
- method = first_matching instance_methods[name], types
818
- return method if method
819
- intrinsic = intrinsics[name][types]
820
- return intrinsic if intrinsic
821
- raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
822
- end
823
-
824
- def java_static_method(name, *types)
825
- method = first_matching static_methods[name], types
826
- return method if method
827
- intrinsic = meta.intrinsics[name][types]
828
- return intrinsic if intrinsic
829
- raise NameError, "No method #{self.name}.#{name}(#{types.join ', '})"
830
- end
831
-
832
- def constructor(*types)
833
- constructor = first_matching constructors, types
834
- return constructor if constructor
835
- raise NameError, "No constructor #{name}(#{types.join ', '})"
836
- end
837
-
838
- def declared_instance_methods(name=nil)
839
- declared_methods self, instance_methods, name
840
- end
841
-
842
- def declared_class_methods(name=nil)
843
- declared_methods meta, static_methods, name
844
- end
845
-
846
- def constructors
847
- if @constructors.nil?
848
- @constructors = []
849
- declare_method('initialize', [], self, [])
850
- @have_default_constructor = true
851
- end
852
- @constructors
853
- end
854
- alias :declared_constructors :constructors
855
-
856
- def instance_methods
857
- @instance_methods ||= Hash.new {|h, k| h[k] = []}
858
- end
859
-
860
- def static_methods
861
- @static_methods ||= Hash.new {|h, k| h[k] = []}
862
- end
863
-
864
- def getDeclaredFields
865
- @fields.values.to_java(JVMMethod)
866
- end
867
-
868
- def getDeclaredField(name)
869
- @fields[name]
870
- end
871
-
872
- def hasStaticField(name)
873
- f = getDeclaredField(name)
874
- f && f.static?
875
- end
876
-
877
- def declared_fields
878
- @fields ||= {}
879
- end
880
-
881
- def declare_field(name, type, static)
882
- declared_fields[name] ||= MirahMember.new(self, name, [], type, static, [])
883
- end
884
-
885
- def declare_method(name, arguments, type, exceptions)
886
- raise "Bad args" unless arguments.all?
887
- if type.isError
888
- instance_methods.delete(name)
889
- method_updated(name)
890
- return
891
- end
892
- member = MirahMember.new(self, name, arguments, type, false, exceptions)
893
- if name == 'initialize'
894
- # The ordering is important here:
895
- # The first call to constructors initializes @have_default_constructor.
896
- if constructors.size == 1 && @have_default_constructor
897
- constructors.clear
898
- @have_default_constructor = false
899
- elsif constructors.size > 1 && @have_default_constructor
900
- raise "Invalid state: default constructor but #{constructors.size} constructors"
901
- end
902
- constructors << JavaConstructor.new(@type_system, member)
903
- else
904
- instance_methods[name] << JavaMethod.new(@type_system, member)
905
- end
906
- method_updated(name)
907
- end
908
-
909
- def declare_static_method(name, arguments, type, exceptions)
910
- if type.isError
911
- static_methods.delete(name)
912
- else
913
- member = MirahMember.new(self, name, arguments, type, true, exceptions)
914
- static_methods[name] << JavaStaticMethod.new(@type_system, member)
915
- end
916
- method_updated(name)
917
- end
918
-
919
- def interface?
920
- false
921
- end
922
-
923
- def field_getter(name)
924
- nil
925
- end
926
-
927
- def field_setter(name)
928
- nil
929
- end
930
-
931
- private
932
-
933
- def declared_methods target, method_hash, name
934
- # should the declared intrinsics be first here? nh
935
- target.declared_intrinsics(name) +
936
- if name.nil?
937
- method_hash.values.flatten
938
- else
939
- method_hash[name]
940
- end
941
- end
942
-
943
- def first_matching method_list, types
944
- method_list.find {|m| m.argument_types == types}
945
- end
946
- end
947
-
948
- class TypeDefMeta
949
- def constructor(*args)
950
- unmeta.constructor(*args)
951
- end
952
-
953
- def java_method(*args)
954
- unmeta.java_static_method(*args)
955
- end
956
-
957
- def declared_class_methods(name=nil)
958
- unmeta.declared_class_methods(name)
959
- end
960
-
961
- def declared_instance_methods(name=nil)
962
- unmeta.declared_instance_methods(name)
963
- end
964
-
965
- def field_getter(name)
966
- nil
967
- end
968
-
969
- def field_setter(name)
970
- nil
971
- end
972
- end
973
- end