jtor 0.1.1-java → 0.1.2-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/jtor/expressions.rb +43 -9
- data/lib/jtor/java_parser.rb +142 -17
- data/lib/jtor/version.rb +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb0a35641aa58e399585b02e4bd5f0107ade213b
|
4
|
+
data.tar.gz: a513aa40d6a8f46a72d6131a2f19c6398feb52e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83bbc5dd9b936d8e3d0635c650179b57e82ad54e70ea49230fe51bf3ab64c2e42e67d3b590df51c8dabd2486e549cfc441984217f6db72678eee93ff2b4f0436
|
7
|
+
data.tar.gz: 8e3eddf4b2b7f05974b3741cc8c301dc62c23cbcaef62b373163f75c19369d4d1669579dbd5321e836b4637455e7350194c85a9d9c6c02efc08750f81a7e91be
|
data/lib/jtor/expressions.rb
CHANGED
@@ -65,8 +65,12 @@ module Jtor
|
|
65
65
|
when FieldAccessExpr
|
66
66
|
scoped_expression(expr) { expr.field }
|
67
67
|
when VariableDeclarationExpr
|
68
|
-
|
69
|
-
|
68
|
+
expr.vars.map do |var|
|
69
|
+
# If only declaring and not assigning, we don't need to translate it
|
70
|
+
# (I think)
|
71
|
+
next unless var.init
|
72
|
+
"#{var.id} = #{translate_expression(var.init)}"
|
73
|
+
end.compact.join('; ')
|
70
74
|
when QualifiedNameExpr
|
71
75
|
"#{translate_expression(expr.qualifier)}.#{expr.name}"
|
72
76
|
when NameExpr
|
@@ -84,8 +88,18 @@ module Jtor
|
|
84
88
|
op = expr.operator.to_s.to_sym
|
85
89
|
operator = UNARY_OPERATORS[op]
|
86
90
|
value = translate_expression(expr.expr)
|
87
|
-
|
88
|
-
|
91
|
+
case op
|
92
|
+
when :posIncrement
|
93
|
+
# For preIncrement and preDecrement we record the old value first,
|
94
|
+
# then execute the operation and then return the old value
|
95
|
+
"(__old = #{value}; #{value} += 1; __old)"
|
96
|
+
when :posDecrement
|
97
|
+
"(__old = #{value}; #{value} -= 1; __old)"
|
98
|
+
when :preIncrement
|
99
|
+
# No ++/-- in ruby
|
100
|
+
"(#{value} += 1)"
|
101
|
+
when :preDecrement
|
102
|
+
"(#{value} -= 1)"
|
89
103
|
else
|
90
104
|
"#{operator}#{value}"
|
91
105
|
end
|
@@ -121,6 +135,10 @@ module Jtor
|
|
121
135
|
when ThisExpr
|
122
136
|
# TODO: Handle class expressions on `this`
|
123
137
|
'self'
|
138
|
+
when SuperExpr
|
139
|
+
# Return our trusty `sup` helper object which encapsulates super methods
|
140
|
+
# TODO: Handle class expressions on `super`
|
141
|
+
'sup'
|
124
142
|
when ClassExpr
|
125
143
|
"#{translate_type(expr.type)}.class"
|
126
144
|
when EnclosedExpr
|
@@ -137,13 +155,27 @@ module Jtor
|
|
137
155
|
expressions.map { |expr| translate_expression(expr) }.join('; ')
|
138
156
|
end
|
139
157
|
|
140
|
-
private
|
141
|
-
|
142
158
|
def translate_arguments(args)
|
143
|
-
return '' unless args
|
159
|
+
return '' unless args && args.any?
|
144
160
|
"(#{args.map { |arg| translate_expression(arg) }.join(', ')})"
|
145
161
|
end
|
146
162
|
|
163
|
+
def translate_constructor_call_args(params, args)
|
164
|
+
# These arguments will be `eval`ed in Jtor::StdLib::Base. There the
|
165
|
+
# arguments are in an array called `args`. We'll translate any reference
|
166
|
+
# to a name defined in `params` to `args[i]`, where `i` is the index of
|
167
|
+
# that parameter in `params`
|
168
|
+
arguments = translate_arguments(args)
|
169
|
+
params.each_with_index do |param, index|
|
170
|
+
replacement = "\\1args[#{index}]\\2"
|
171
|
+
# Only replace unscoped names matching the param name
|
172
|
+
arguments.gsub!(/([ \(])#{param.id.name}([., \)])/, replacement)
|
173
|
+
end
|
174
|
+
arguments
|
175
|
+
end
|
176
|
+
|
177
|
+
private
|
178
|
+
|
147
179
|
def translate_type(type)
|
148
180
|
case type
|
149
181
|
when ClassOrInterfaceType
|
@@ -152,7 +184,9 @@ module Jtor
|
|
152
184
|
while (scope = scope.scope)
|
153
185
|
module_string = "#{scope.name.to_constant_name}#{module_string}"
|
154
186
|
end
|
155
|
-
module_string
|
187
|
+
module_string += '::'
|
188
|
+
elsif %w(Exception String Math Class Object).include?(type.name)
|
189
|
+
module_string = 'JavaLang::'
|
156
190
|
end
|
157
191
|
"#{module_string}#{type.name}"
|
158
192
|
when PrimitiveType
|
@@ -160,7 +194,7 @@ module Jtor
|
|
160
194
|
# https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby#java-to-ruby
|
161
195
|
case type.type
|
162
196
|
when PrimitiveType::Primitive::Boolean
|
163
|
-
'
|
197
|
+
'JavaLang::Boolean'
|
164
198
|
when PrimitiveType::Primitive::Byte, PrimitiveType::Primitive::Short,
|
165
199
|
PrimitiveType::Primitive::Char, PrimitiveType::Primitive::Int,
|
166
200
|
PrimitiveType::Primitive::Long
|
data/lib/jtor/java_parser.rb
CHANGED
@@ -5,6 +5,9 @@ java_import com.github.javaparser.JavaParser
|
|
5
5
|
|
6
6
|
module Jtor
|
7
7
|
class JavaParser
|
8
|
+
include_package 'com.github.javaparser.ast.stmt'
|
9
|
+
include_package 'com.github.javaparser.ast.body'
|
10
|
+
|
8
11
|
include Jtor::Expressions
|
9
12
|
|
10
13
|
attr_accessor :indentator
|
@@ -17,13 +20,16 @@ module Jtor
|
|
17
20
|
|
18
21
|
def translate(file)
|
19
22
|
parser = ::JavaParser.parse(FileInputStream.new(file))
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
+
# In Java, other classes on the same package are automatically accessible,
|
24
|
+
# we do that manually here.
|
25
|
+
fputs("jtor_import '#{parser.package.name}.*'")
|
23
26
|
fputs('module Java')
|
24
27
|
indented do
|
25
28
|
fputs("module #{module_name(parser.package.name)}")
|
26
29
|
indented do
|
30
|
+
parser.imports.each do |import|
|
31
|
+
fputs("jtor_import '#{translate_expression(import.name)}'")
|
32
|
+
end
|
27
33
|
parser.types.each { |type| translate_class_or_interface(type) }
|
28
34
|
end
|
29
35
|
fputs('end')
|
@@ -47,16 +53,99 @@ module Jtor
|
|
47
53
|
outdent
|
48
54
|
end
|
49
55
|
|
56
|
+
def indented_string(s)
|
57
|
+
# If we last used a `write` or if the string passed is empty, we don't
|
58
|
+
# want indentation
|
59
|
+
if @prev_write || !s
|
60
|
+
s
|
61
|
+
else
|
62
|
+
"#{@indentator * @level}#{s}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
50
66
|
def fwrite(s)
|
51
|
-
@f.write
|
67
|
+
@f.write(indented_string(s))
|
68
|
+
@prev_write = true
|
52
69
|
end
|
53
70
|
|
54
|
-
def fputs(s)
|
55
|
-
@f.puts
|
71
|
+
def fputs(s = nil)
|
72
|
+
@f.puts(indented_string(s))
|
73
|
+
@prev_write = false
|
56
74
|
end
|
57
75
|
|
58
76
|
def translate_statement(stmt)
|
59
|
-
|
77
|
+
case stmt
|
78
|
+
when BlockStmt
|
79
|
+
translate_block_statement(stmt)
|
80
|
+
when ExpressionStmt
|
81
|
+
translated_expression = translate_expression(stmt.expression)
|
82
|
+
fputs(translated_expression) if translated_expression
|
83
|
+
when IfStmt
|
84
|
+
fputs("if #{translate_expression(stmt.condition)}")
|
85
|
+
indented { translate_statement(stmt.then_stmt) }
|
86
|
+
if stmt.else_stmt
|
87
|
+
if stmt.else_stmt.is_a?(IfStmt)
|
88
|
+
fwrite('els')
|
89
|
+
translate_statement(stmt.else_stmt)
|
90
|
+
else
|
91
|
+
fputs('else')
|
92
|
+
indented { translate_statement(stmt.then_stmt) }
|
93
|
+
fputs('end')
|
94
|
+
end
|
95
|
+
else
|
96
|
+
fputs('end')
|
97
|
+
end
|
98
|
+
when TryStmt
|
99
|
+
fputs('begin')
|
100
|
+
indented { translate_block_statement(stmt.try_block) }
|
101
|
+
stmt.catchs.each do |catch_clause|
|
102
|
+
except = catch_clause.except
|
103
|
+
fputs("rescue #{except.types[0].type.name} => #{except.id.name}")
|
104
|
+
indented { translate_block_statement(catch_clause.catch_block) }
|
105
|
+
end
|
106
|
+
if stmt.finally_block
|
107
|
+
fputs('ensure')
|
108
|
+
indented { translate_block_statement(stmt.finally_block) }
|
109
|
+
end
|
110
|
+
fputs('end')
|
111
|
+
when ForStmt
|
112
|
+
fputs(translate_expressions(stmt.init)) if stmt.init.any?
|
113
|
+
fputs("while #{translate_expression(stmt.compare)} do")
|
114
|
+
indented do
|
115
|
+
translate_statement(stmt.body)
|
116
|
+
fputs(translate_expressions(stmt.update)) if stmt.update.any?
|
117
|
+
end
|
118
|
+
fputs('end')
|
119
|
+
when ForeachStmt
|
120
|
+
iterable = translate_expression(stmt.iterable)
|
121
|
+
var = stmt.variable.vars.first.id.to_s
|
122
|
+
fputs("#{iterable}.each do |#{var}|")
|
123
|
+
indented { translate_statement(stmt.body) }
|
124
|
+
fputs('end')
|
125
|
+
when ReturnStmt
|
126
|
+
"return #{translate_expression(stmt.expr)}"
|
127
|
+
when ThrowStmt
|
128
|
+
"fail #{translate_expression(stmt.expr)}"
|
129
|
+
when BreakStmt
|
130
|
+
# TODO: Handle labeled `break`s
|
131
|
+
'break'
|
132
|
+
when ContinueStmt
|
133
|
+
# TODO: Handle labeled `continue`s
|
134
|
+
'next'
|
135
|
+
when DoStmt
|
136
|
+
fputs('begin')
|
137
|
+
indented { translate_statement(stmt.body) }
|
138
|
+
fputs("end while #{translate_expression(stmt.condition)}")
|
139
|
+
when SwitchStmt
|
140
|
+
fputs("case #{translate_expression(stmt.selector)}")
|
141
|
+
stmt.entries.each do |entry|
|
142
|
+
fputs(entry.label ? "when #{entry.label}" : 'else')
|
143
|
+
indented do
|
144
|
+
entry.stmts.each { |stmt| translate_statement(stmt) }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
fputs('end')
|
148
|
+
end
|
60
149
|
end
|
61
150
|
|
62
151
|
def translate_block_statement(block_stmt)
|
@@ -71,20 +160,56 @@ module Jtor
|
|
71
160
|
params.any? ? " |#{params.map { |p| p.id.name }.join(', ')}|" : ''
|
72
161
|
end
|
73
162
|
|
74
|
-
def write_method(
|
75
|
-
types = translate_param_types(
|
76
|
-
param_list = translate_param_list(
|
77
|
-
|
78
|
-
|
163
|
+
def write_method(method)
|
164
|
+
types = translate_param_types(method.parameters)
|
165
|
+
param_list = translate_param_list(method.parameters)
|
166
|
+
declarer_method = if ModifierSet.static?(method.modifiers)
|
167
|
+
'add_static_java_method'
|
168
|
+
else
|
169
|
+
'add_java_method'
|
170
|
+
end
|
171
|
+
fputs("#{declarer_method}(:#{method.name}, #{types}) do#{param_list}")
|
172
|
+
indented { translate_block_statement(method.body) } if method.body
|
173
|
+
fputs('end')
|
174
|
+
end
|
175
|
+
|
176
|
+
def write_constructor(constructor)
|
177
|
+
types = translate_param_types(constructor.parameters)
|
178
|
+
param_list = translate_param_list(constructor.parameters)
|
179
|
+
stmts = constructor.block && constructor.block.stmts
|
180
|
+
if stmts && stmts.any? && stmts.first.is_a?(ExplicitConstructorInvocationStmt)
|
181
|
+
constructor_stmt = stmts.first
|
182
|
+
stmts = stmts.size > 1 ? stmts.sub_list(1, stmts.size - 1) : []
|
183
|
+
super_call = constructor_stmt.this? ? 'initialize' : 'super'
|
184
|
+
super_call += translate_constructor_call_args(constructor.parameters,
|
185
|
+
constructor_stmt.args)
|
186
|
+
end
|
187
|
+
# Using `#` as the delimiter, as it can't appear on Java expressions
|
188
|
+
fputs("add_java_constructor(#{types}, %q##{super_call}#) do#{param_list}")
|
189
|
+
indented do
|
190
|
+
stmts.each { |stmt| translate_statement(stmt) }
|
191
|
+
end if stmts
|
79
192
|
fputs('end')
|
80
193
|
end
|
81
194
|
|
195
|
+
def write_field(field)
|
196
|
+
field.variables.each do |var|
|
197
|
+
fputs "attr_accessor :#{var.id}"
|
198
|
+
next unless var.init
|
199
|
+
fputs "add_java_initializer do"
|
200
|
+
indented { fputs "self.#{var.id} ||= #{translate_expression(var.init)}" }
|
201
|
+
fputs "end"
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
82
205
|
def translate_member(member)
|
83
206
|
case member
|
84
|
-
when
|
85
|
-
write_method(member
|
86
|
-
when
|
87
|
-
|
207
|
+
when MethodDeclaration
|
208
|
+
write_method(member)
|
209
|
+
when ConstructorDeclaration
|
210
|
+
write_constructor(member)
|
211
|
+
when FieldDeclaration
|
212
|
+
write_field(member)
|
88
213
|
end
|
89
214
|
end
|
90
215
|
|
@@ -94,7 +219,7 @@ module Jtor
|
|
94
219
|
end
|
95
220
|
fputs("class #{type.name.to_constant_name}#{extends}")
|
96
221
|
indented do
|
97
|
-
fputs('
|
222
|
+
fputs('include Jtor::StdLib::Base')
|
98
223
|
type.members.each { |member| translate_member(member) }
|
99
224
|
end
|
100
225
|
fputs('end')
|
data/lib/jtor/version.rb
CHANGED