mirah 0.1.4-java → 0.2.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +0 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/History.txt +531 -0
- data/README.md +23 -10
- data/Rakefile +239 -156
- data/TODO.md +71 -10
- data/bin/mirah +1 -1
- data/bin/mirahc +1 -1
- data/dist/mirahc.jar +0 -0
- data/examples/bintrees.mirah +2 -2
- data/examples/construction.mirah +2 -2
- data/examples/fields.mirah +1 -1
- data/examples/fractal.mirah +1 -1
- data/examples/fractal.rb +70 -0
- data/examples/interfaces.mirah +1 -1
- data/examples/java_thing.mirah +1 -1
- data/examples/macros/square.mirah +3 -3
- data/examples/macros/square_int.mirah +3 -3
- data/examples/macros/string_each_char.mirah +6 -6
- data/examples/rosettacode/100-doors.mirah +0 -2
- data/examples/rosettacode/count-occurrences-of-a-substring.mirah +3 -3
- data/examples/rosettacode/empty-string.mirah +1 -1
- data/examples/rosettacode/fizz-buzz.mirah +4 -4
- data/examples/rosettacode/is-string-numeric.mirah +7 -7
- data/examples/rosettacode/palindrome.mirah +2 -2
- data/examples/rosettacode/reverse-a-string.mirah +1 -1
- data/examples/rosettacode/rot-13.mirah +1 -1
- data/examples/{edb.mirah → rosettacode/simple_character_math.mirah} +13 -4
- data/examples/rosettacode/string-case.mirah +2 -2
- data/examples/rosettacode/string-length.mirah +1 -1
- data/examples/swing.mirah +9 -14
- data/extensions_and_macros.md +117 -0
- data/lib/mirah.rb +1 -1
- data/lib/mirah/errors.rb +3 -1
- data/lib/mirah/transform/ast_ext.rb +3 -2
- data/lib/mirah/util/process_errors.rb +1 -2
- data/lib/mirah/version.rb +1 -1
- data/test/A.class +0 -0
- data/test/core/util/jvm_version_test.rb +10 -0
- data/test/core/util/mirah_arguments_test.rb +51 -4
- data/test/fixtures/cp1251_test.mirah +7 -0
- data/test/fixtures/org/foo/AbstractExecutorJava8.java +30 -0
- data/test/fixtures/org/foo/ClassWithSelfReferencingTypeParameter.java +24 -0
- data/test/fixtures/org/foo/InnerInterfaceClass.java +12 -0
- data/test/fixtures/org/foo/IntAnno.class +0 -0
- data/test/fixtures/org/foo/TypeFixtureJava8.java +10 -0
- data/test/fixtures/utf8_test.mirah +7 -0
- data/test/jvm/access_levels_test.rb +31 -0
- data/test/jvm/annotations_test.rb +3 -6
- data/test/jvm/blocks_test.rb +303 -120
- data/test/jvm/cast_test.rb +123 -50
- data/test/jvm/closure_test.rb +242 -0
- data/test/jvm/constructors_test.rb +1 -3
- data/test/jvm/example_test.rb +6 -2
- data/test/jvm/extensions/array_extensions_test.rb +181 -0
- data/test/jvm/extensions/collection_extensions_test.rb +195 -0
- data/test/jvm/{enumerable_test.rb → extensions/enumerable_test.rb} +81 -13
- data/test/jvm/extensions/hash_extensions_test.rb +56 -0
- data/test/jvm/extensions/list_extensions_test.rb +143 -0
- data/test/jvm/extensions/lock_extensions_test.rb +43 -0
- data/test/jvm/{numeric_extensions_test.rb → extensions/numeric_extensions_test.rb} +0 -0
- data/test/jvm/extensions/numeric_operators_test.rb +86 -0
- data/test/jvm/extensions/object_extensions_test.rb +122 -0
- data/test/jvm/{string_builder_extensions_test.rb → extensions/string_builder_extensions_test.rb} +0 -0
- data/test/jvm/{string_extensions_test.rb → extensions/string_extensions_test.rb} +57 -4
- data/test/jvm/generics_test.rb +14 -6
- data/test/jvm/import_test.rb +38 -1
- data/test/jvm/interface_test.rb +17 -0
- data/test/jvm/jvm_commands_test.rb +9 -0
- data/test/jvm/jvm_compiler_test.rb +568 -43
- data/test/jvm/macros_test.rb +343 -19
- data/test/jvm/main_method_test.rb +1 -3
- data/test/jvm/new_backend_test_helper.rb +54 -7
- data/test/jvm/rescue_test.rb +20 -5
- data/test/jvm/static_fields_test.rb +52 -10
- data/test/jvm/{mirror_compilation_test_helper.rb → string_test.rb} +10 -9
- data/test/jvm/varargs_test.rb +6 -16
- data/test/mirrors/base_type_test.rb +20 -7
- data/test/mirrors/bytecode_mirror_test.rb +8 -3
- data/test/mirrors/generics_test.rb +89 -10
- data/test/mirrors/member_test.rb +1 -1
- data/test/mirrors/method_lookup_test.rb +10 -3
- data/test/mirrors/mirrors_test.rb +20 -20
- data/test/mirrors/simple_async_mirror_loader_test.rb +1 -1
- data/test/mirrors/simple_mirror_loader_test.rb +1 -1
- data/test/newMirahClass$Closure2.class +0 -0
- data/test/newMirahClass.class +0 -0
- data/test/test_helper.rb +8 -1
- metadata +31 -16
- data/bin/bundler +0 -16
- data/bin/rake +0 -16
- data/examples/ant/example-build.xml~ +0 -7
- data/examples/test.edb +0 -9
- data/lib/mirah/compiler.rb +0 -67
- data/lib/mirah/parser.rb +0 -224
- data/lib/mirah/util/delegate.rb +0 -65
- data/test/jvm/list_extensions_test.rb +0 -23
data/TODO.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
- missing import should always show up in the summary of errors. eg
|
2
|
+
|
3
|
+
ERROR import X
|
4
|
+
ERROR fn X(1) doesn't exist
|
5
|
+
|
6
|
+
ERROR can't find type for import X
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
-- if a macro has a bug, the stacktrace is ugly
|
11
|
+
|
1
12
|
|
2
13
|
|
3
14
|
The TODO list of DOOM
|
@@ -31,6 +42,8 @@ Dist
|
|
31
42
|
|
32
43
|
Compiler Internals Improvements
|
33
44
|
======================
|
45
|
+
- add generic warnings / error message facility
|
46
|
+
-- right now we've got errors and they're ok. but it'd be better if we had something better.
|
34
47
|
- make Mirror type systems addDefaultImports more obvious
|
35
48
|
- faster mirah compiler build: src => class is tricky, I could make src => jar, jar => jar tho
|
36
49
|
- switch to minitest
|
@@ -51,6 +64,7 @@ Compiler Internals Improvements
|
|
51
64
|
- clean up javalib dir
|
52
65
|
- don't use 1.5 as java compile target
|
53
66
|
- make it obvious when ASTs have been dropped during macro expansion
|
67
|
+
- add timing to phases
|
54
68
|
|
55
69
|
- break compiler into phases
|
56
70
|
---------------
|
@@ -62,15 +76,19 @@ Compiler Internals Improvements
|
|
62
76
|
- load type systems
|
63
77
|
- load types for System, & predefs maybe?
|
64
78
|
- load scoped macros / extensions
|
79
|
+
|
65
80
|
# typer
|
66
81
|
- visit script body / class bodies, skipping method bodies
|
67
82
|
- compile macros
|
68
83
|
- visit method bodies
|
84
|
+
|
69
85
|
# finishs resolving typer wip
|
70
86
|
- resolve proxies
|
71
87
|
- change captured locals into binding fields
|
88
|
+
|
72
89
|
# clean up / compiler prep
|
73
90
|
- clean ast up
|
91
|
+
|
74
92
|
# compile
|
75
93
|
|
76
94
|
- maybe after parse, check built files to see if they need to be rebuilt, and ignore them otherwise
|
@@ -88,6 +106,10 @@ Warnings / Logging
|
|
88
106
|
|
89
107
|
- improve duplicate name/sig error when multiple method defs w/ same sig mirah#273
|
90
108
|
- code sources from macro expansion should know both the macro location and the invoke location and report both on errors so that users know where to look to debug
|
109
|
+
- -v should only show the version, it currently says no main method too. :/
|
110
|
+
- add -Werror where warnings become errors
|
111
|
+
- make block mirror type string a little nicer somehow
|
112
|
+
eg Can't find method java.util.concurrent.locks.ReentrantLock.synchronize(org.mirah.jvm.mirrors.BlockType)
|
91
113
|
|
92
114
|
Parser
|
93
115
|
======
|
@@ -97,25 +119,53 @@ Parser
|
|
97
119
|
|
98
120
|
Features
|
99
121
|
==========
|
122
|
+
- each macro for Maps
|
100
123
|
- Reflection Macros
|
101
124
|
- AST formatter that converts back to something the parser can parse
|
102
125
|
- default toString?
|
103
126
|
- default hashCode / equals
|
104
|
-
- change == to use equals
|
105
127
|
- default val/no type that defers to indy
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
128
|
+
eg
|
129
|
+
def foo(x: int, y=1)
|
130
|
+
end
|
131
|
+
should work
|
132
|
+
- allow defining equals using def ==(other)
|
112
133
|
- attr_reader/et al as varargs instead of just Hash. It would mean that the type info would have to come from somewhere else
|
113
134
|
- goto: headius wants it
|
114
135
|
- synchronize intrinsic ala java's
|
115
136
|
- file scoped macros / extensions
|
116
137
|
- extension syntax
|
117
|
-
- move macro / mirahc anno to separate class dir to improve javac interop
|
118
138
|
- public / private / protected / package scope helpers
|
139
|
+
|
140
|
+
|
141
|
+
# test cases
|
142
|
+
# - method w/ no modifier, modifier statement, method
|
143
|
+
# - modifier statement, method
|
144
|
+
# - modifier statement, method, same modifier statement, method
|
145
|
+
# - modifier statement, method, different modifier statement, method
|
146
|
+
# - modifier statement, method containing closure w/ mdefs
|
147
|
+
# - modifier fn w/ undefined method
|
148
|
+
# - mdef, modifier fn mname
|
149
|
+
# - modifier statement, modifiered method
|
150
|
+
# - modifier statement, differently modifiered method
|
151
|
+
# - modifier statement, modifiered method, unmodifiered method
|
152
|
+
# - modifier statement, differently modifiered method, unmodifiered method
|
153
|
+
|
154
|
+
# pub
|
155
|
+
# def a
|
156
|
+
# macro def self.public(mdef: MethodDefinition)
|
157
|
+
# set annotation on it directly
|
158
|
+
|
159
|
+
# macro def self.public(method_names: NodeList<Symbol> or something)
|
160
|
+
# find methods w/ those names, set anno on them directly
|
161
|
+
# if they don't exist, blow up
|
162
|
+
#macro def self.public()
|
163
|
+
# options
|
164
|
+
# 1) grab typer & set current scope's default access *** best most likely
|
165
|
+
# 2) don't expand here, instead throw into a queue, expand all at end
|
166
|
+
# 3) try to infer defs needed to do it
|
167
|
+
#end
|
168
|
+
|
119
169
|
- subclass access to super protected fields w/ @syntax
|
120
170
|
- (0) add a gets function like Ruby
|
121
171
|
- (2) a more "batteries included" set of imports
|
@@ -136,10 +186,16 @@ should work
|
|
136
186
|
- understand Java 8 default methods
|
137
187
|
- default args on non-last position params. eg when a method takes a block(read: functional interface), it should be allowed to have default args before the block arg.
|
138
188
|
- do jruby style method lookup
|
189
|
+
- add env var hash constant ala Ruby's ENV.
|
190
|
+
- Thread extensions:
|
191
|
+
Thread.start {}, which does t=Thread.new{};t.start;t
|
192
|
+
- macro for typecheck & cast. replace the x.kind_of? Y; Y(Object(x))
|
139
193
|
|
140
194
|
Bugs
|
141
195
|
==========
|
142
|
-
|
196
|
+
- a[-1] should work
|
197
|
+
- array ext size
|
198
|
+
- make sure that macro lookup looks at super classes
|
143
199
|
- "foo: #{x || y} acts weird", my guess is that interpolation doesn't generate the right code sometimes
|
144
200
|
- lambda's can't exist in methods! !! by which I mean that they can't close over things in methods. You can have them there, they just don't close. >:[]
|
145
201
|
- parser can't deal w/ unquotes in hash literals when key is unquote
|
@@ -169,6 +225,11 @@ class C
|
|
169
225
|
^^^^^^^^^
|
170
226
|
|
171
227
|
|
228
|
+
- constants are not referrable outside the defining scope :/ because they are private
|
229
|
+
- referring to classes as constants causes crashes
|
230
|
+
java -jar dist/mirahc.jar -cp test/fixtures/ -e 'puts org::foo::A' blows up w/ a asm error
|
231
|
+
java -jar dist/mirahc.jar -cp test/fixtures/ -e 'puts org::foo::A.class' doesn't
|
232
|
+
|
172
233
|
Libraries
|
173
234
|
===============
|
174
235
|
- delegation macro library
|
@@ -341,4 +402,4 @@ end
|
|
341
402
|
|
342
403
|
|
343
404
|
compile rake task doesn't fail, if it doesn't work for some things, it goes on anyway
|
344
|
-
in generics. hmm
|
405
|
+
in generics. hmm
|
data/bin/mirah
CHANGED
data/bin/mirahc
CHANGED
data/dist/mirahc.jar
CHANGED
Binary file
|
data/examples/bintrees.mirah
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
16
|
class BinaryTrees
|
17
|
-
def self.main(args:String[])
|
17
|
+
def self.main(args:String[]):void
|
18
18
|
n = 0
|
19
19
|
n = Integer.parseInt(args[0]) if args.length > 0
|
20
20
|
|
@@ -72,7 +72,7 @@ class TreeNode
|
|
72
72
|
|
73
73
|
def itemCheck
|
74
74
|
# if necessary deallocate here
|
75
|
-
if @left
|
75
|
+
if @left.nil?
|
76
76
|
@item
|
77
77
|
else
|
78
78
|
@item + @left.itemCheck - @right.itemCheck
|
data/examples/construction.mirah
CHANGED
@@ -13,8 +13,8 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
|
-
import
|
17
|
-
import
|
16
|
+
import java.lang.StringBuffer
|
17
|
+
import java.util.ArrayList
|
18
18
|
|
19
19
|
list = ArrayList.new
|
20
20
|
sb = StringBuffer.new("Hello")
|
data/examples/fields.mirah
CHANGED
data/examples/fractal.mirah
CHANGED
data/examples/fractal.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Copyright (c) 2010 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
|
+
def run
|
17
|
+
puts "Rendering"
|
18
|
+
y = -39.0
|
19
|
+
while y <= 39.0
|
20
|
+
puts
|
21
|
+
x = -39.0
|
22
|
+
while x <= 39.0
|
23
|
+
i = iterate(x/40.0,y/40.0)
|
24
|
+
if (i == 0)
|
25
|
+
print "*"
|
26
|
+
else
|
27
|
+
print " "
|
28
|
+
end
|
29
|
+
x += 1
|
30
|
+
end
|
31
|
+
y += 1
|
32
|
+
end
|
33
|
+
puts
|
34
|
+
end
|
35
|
+
|
36
|
+
def iterate(x:double,y:double)
|
37
|
+
cr = y-0.5
|
38
|
+
ci = x
|
39
|
+
zi = 0.0
|
40
|
+
zr = 0.0
|
41
|
+
i = 0
|
42
|
+
|
43
|
+
result = 0
|
44
|
+
while true
|
45
|
+
i += 1
|
46
|
+
temp = zr * zi
|
47
|
+
zr2 = zr * zr
|
48
|
+
zi2 = zi * zi
|
49
|
+
zr = zr2 - zi2 + cr
|
50
|
+
zi = temp + temp + ci
|
51
|
+
if (zi2 + zr2 > 16)
|
52
|
+
result = i
|
53
|
+
break
|
54
|
+
end
|
55
|
+
if (i > 1000)
|
56
|
+
result = 0
|
57
|
+
break
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
result
|
62
|
+
end
|
63
|
+
|
64
|
+
i = 0
|
65
|
+
while i < 10
|
66
|
+
start = System.currentTimeMillis
|
67
|
+
run()
|
68
|
+
puts "Time: #{(System.currentTimeMillis - start) / 1000.0}"
|
69
|
+
i += 1
|
70
|
+
end
|
data/examples/interfaces.mirah
CHANGED
data/examples/java_thing.mirah
CHANGED
@@ -15,14 +15,14 @@
|
|
15
15
|
|
16
16
|
|
17
17
|
macro def eachChar(value, block:Block)
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
quote do
|
19
|
+
`value`.toCharArray.each do |`block.arguments`|
|
20
|
+
`block.body`
|
21
|
+
end
|
22
|
+
end
|
23
23
|
end
|
24
24
|
|
25
25
|
eachChar('laat de leeeuw niet in zijn hempie staan') do | my_char |
|
26
|
-
|
26
|
+
puts my_char
|
27
27
|
end
|
28
28
|
|
@@ -18,7 +18,7 @@ import java.util.regex.Pattern
|
|
18
18
|
import java.util.regex.Matcher
|
19
19
|
|
20
20
|
#The "remove and count the difference" method
|
21
|
-
def count_substring(pattern:
|
21
|
+
def count_substring(pattern:String, source:String)
|
22
22
|
(source.length() - source.replace(pattern, "").length()) / pattern.length()
|
23
23
|
end
|
24
24
|
|
@@ -28,7 +28,7 @@ puts count_substring("a*b", "abaabba*bbaba*bbab") # ==> 2
|
|
28
28
|
|
29
29
|
|
30
30
|
# The "split and count" method
|
31
|
-
def count_substring2(pattern:
|
31
|
+
def count_substring2(pattern:String, source:String)
|
32
32
|
# the result of split() will contain one more element than the delimiter
|
33
33
|
# the "-1" second argument makes it not discard trailing empty strings
|
34
34
|
source.split(Pattern.quote(pattern), -1).length - 1
|
@@ -40,7 +40,7 @@ puts count_substring2("a*b", "abaabba*bbaba*bbab") # ==> 2
|
|
40
40
|
|
41
41
|
|
42
42
|
# This method does a match and counts how many times it matches
|
43
|
-
def count_substring3(pattern:
|
43
|
+
def count_substring3(pattern:String, source:String)
|
44
44
|
result = 0
|
45
45
|
Matcher m = Pattern.compile(Pattern.quote(pattern)).matcher(source);
|
46
46
|
while (m.find())
|
@@ -19,6 +19,6 @@ empty_string2 = String.new
|
|
19
19
|
|
20
20
|
puts "empty string is empty" if empty_string1.isEmpty()
|
21
21
|
puts "empty string has no length" if empty_string2.length() == 0
|
22
|
-
puts "empty string is not nil" unless empty_string1
|
22
|
+
puts "empty string is not nil" unless empty_string1.nil?
|
23
23
|
|
24
24
|
|
@@ -15,10 +15,10 @@
|
|
15
15
|
|
16
16
|
|
17
17
|
1.upto(100) do |n|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
print "Fizz" if a = ((n % 3) == 0)
|
19
|
+
print "Buzz" if b = ((n % 5) == 0)
|
20
|
+
print n unless (a || b)
|
21
|
+
print "\n"
|
22
22
|
end
|
23
23
|
|
24
24
|
# a little more straight forward
|
@@ -19,7 +19,7 @@ import java.util.Scanner
|
|
19
19
|
|
20
20
|
# this first example relies on catching an exception,
|
21
21
|
# which is bad style and poorly performing in Java
|
22
|
-
def is_numeric?(s:
|
22
|
+
def is_numeric?(s:String)
|
23
23
|
begin
|
24
24
|
Double.parseDouble(s)
|
25
25
|
return true
|
@@ -40,7 +40,7 @@ puts '1.2.3 is not numeric' unless is_numeric?('1.2.3')
|
|
40
40
|
|
41
41
|
|
42
42
|
# check every element of the string
|
43
|
-
def is_numeric2?(s:
|
43
|
+
def is_numeric2?(s: String)
|
44
44
|
if (s == nil || s.isEmpty())
|
45
45
|
return false
|
46
46
|
end
|
@@ -79,7 +79,7 @@ puts '1.2.3 is not numeric' unless is_numeric2?('1.2.3')
|
|
79
79
|
|
80
80
|
|
81
81
|
# use a regular expression
|
82
|
-
def is_numeric3?(s:
|
82
|
+
def is_numeric3?(s:String)
|
83
83
|
s == nil || s.matches("[-+]?\\d+(\\.\\d+)?")
|
84
84
|
end
|
85
85
|
|
@@ -98,8 +98,8 @@ puts '1.2.3 is not numeric' unless is_numeric3?('1.2.3')
|
|
98
98
|
# (a more robust solution). If, after parsing, the parse position is at
|
99
99
|
# the end of the string, we can deduce that the entire string was a
|
100
100
|
# valid number.
|
101
|
-
def is_numeric4?(s:
|
102
|
-
return false if s
|
101
|
+
def is_numeric4?(s:String)
|
102
|
+
return false if s.nil?
|
103
103
|
formatter = NumberFormat.getInstance()
|
104
104
|
pos = ParsePosition.new(0)
|
105
105
|
formatter.parse(s, pos)
|
@@ -123,8 +123,8 @@ puts '1.2.3 is not numeric' unless is_numeric4?('1.2.3')
|
|
123
123
|
# shorts, bytes, doubles, floats, BigIntegers, and BigDecimals as well
|
124
124
|
# as methods for integral types where you may input a base/radix other than
|
125
125
|
# 10 (10 is the default, which can be changed using the useRadix method).
|
126
|
-
def is_numeric5?(s:
|
127
|
-
return false if s
|
126
|
+
def is_numeric5?(s:String)
|
127
|
+
return false if s.nil?
|
128
128
|
Scanner sc = Scanner.new(s)
|
129
129
|
sc.hasNextDouble()
|
130
130
|
end
|