jtor 0.1.0-java → 0.1.1-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.rb +6 -1
- data/lib/jtor/expressions.rb +182 -0
- data/lib/jtor/java_parser.rb +75 -21
- data/lib/jtor/translator.rb +9 -0
- data/lib/jtor/version.rb +4 -0
- data/lib/jtor_jars.rb +4 -0
- metadata +5 -3
- data/lib/jtor/load.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb6efd191fb3dab0c19ebe356c3a24e5cc1f8534
|
4
|
+
data.tar.gz: c33f0bc1150ace2e5db228e055e6f04593439888
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9629eefddac483afd218996e24ed53bf0b44d3198e4d37af1b802544dd579a9192ea15478dca39f477eb8e1019185796bc11d9cc57cebfa8e30090b11dff94e4
|
7
|
+
data.tar.gz: 295d55812f342355919eef6691d957164d868feabbed06e376de4011de1e61de3318c922488e4a2ee4e9a6496fe9d2e22def698d31c1ec08ab0f67824eba9c48
|
data/lib/jtor.rb
CHANGED
@@ -0,0 +1,182 @@
|
|
1
|
+
module Jtor
|
2
|
+
module Expressions
|
3
|
+
include_package 'com.github.javaparser.ast.expr'
|
4
|
+
include_package 'com.github.javaparser.ast.type'
|
5
|
+
|
6
|
+
ASSINGMENT_OPERATORS = {
|
7
|
+
assign: '=',
|
8
|
+
plus: '+=',
|
9
|
+
minus: '-=',
|
10
|
+
star: '*=',
|
11
|
+
slash: '/=',
|
12
|
+
and: '&=',
|
13
|
+
or: '|=',
|
14
|
+
xor: '^=',
|
15
|
+
rem: '%=',
|
16
|
+
lShift: '<<=',
|
17
|
+
rSignedShift: '>>=',
|
18
|
+
rUnsignedShift: '>>>='
|
19
|
+
}
|
20
|
+
|
21
|
+
UNARY_OPERATORS = {
|
22
|
+
positive: '+',
|
23
|
+
negative: '-',
|
24
|
+
preIncrement: '++',
|
25
|
+
preDecrement: '--',
|
26
|
+
not: '!',
|
27
|
+
inverse: '~',
|
28
|
+
posIncrement: '++',
|
29
|
+
posDecrement: '--'
|
30
|
+
}
|
31
|
+
|
32
|
+
BINARY_OPERATORS = {
|
33
|
+
or: '||',
|
34
|
+
and: '&&',
|
35
|
+
binOr: '|',
|
36
|
+
binAnd: '&',
|
37
|
+
xor: '^',
|
38
|
+
equals: '==',
|
39
|
+
notEquals: '!=',
|
40
|
+
less: '<',
|
41
|
+
greater: '>',
|
42
|
+
lessEquals: '<=',
|
43
|
+
greaterEquals: '>=',
|
44
|
+
lShift: '<<',
|
45
|
+
rSignedShift: '>>',
|
46
|
+
rUnsignedShift: '>>>',
|
47
|
+
plus: '+',
|
48
|
+
minus: '-',
|
49
|
+
times: '*',
|
50
|
+
divide: '/',
|
51
|
+
remainder: '%'
|
52
|
+
}
|
53
|
+
|
54
|
+
def translate_expression(expr)
|
55
|
+
case expr
|
56
|
+
when MethodCallExpr
|
57
|
+
scoped_expression(expr) do
|
58
|
+
"#{expr.name}#{translate_arguments(expr.args)}"
|
59
|
+
end
|
60
|
+
when AssignExpr
|
61
|
+
target = translate_expression(expr.target)
|
62
|
+
operator = ASSINGMENT_OPERATORS[expr.operator.to_s.to_sym]
|
63
|
+
value = translate_expression(expr.value)
|
64
|
+
"#{target} #{operator} #{value}"
|
65
|
+
when FieldAccessExpr
|
66
|
+
scoped_expression(expr) { expr.field }
|
67
|
+
when VariableDeclarationExpr
|
68
|
+
# I think we don't need to do anything, but I might be missing some scoping
|
69
|
+
# particularity. We'll see
|
70
|
+
when QualifiedNameExpr
|
71
|
+
"#{translate_expression(expr.qualifier)}.#{expr.name}"
|
72
|
+
when NameExpr
|
73
|
+
expr.name
|
74
|
+
when ArrayAccessExpr
|
75
|
+
"#{translate_expression(expr.name)}[#{translate_expression(expr.index)}]"
|
76
|
+
when ArrayCreationExpr
|
77
|
+
if expr.initializer
|
78
|
+
values = expr.initializer.values.map { |value| translate_expression(value) }
|
79
|
+
"[#{values.join(', ')}]"
|
80
|
+
else
|
81
|
+
"Array.new(#{expr.array_count})"
|
82
|
+
end
|
83
|
+
when UnaryExpr
|
84
|
+
op = expr.operator.to_s.to_sym
|
85
|
+
operator = UNARY_OPERATORS[op]
|
86
|
+
value = translate_expression(expr.expr)
|
87
|
+
if [:posIncrement, :posDecrement].include?(op)
|
88
|
+
"#{value}#{operator}"
|
89
|
+
else
|
90
|
+
"#{operator}#{value}"
|
91
|
+
end
|
92
|
+
when BinaryExpr
|
93
|
+
left = translate_expression(expr.left)
|
94
|
+
operator = BINARY_OPERATORS[expr.operator.to_s.to_sym]
|
95
|
+
right = translate_expression(expr.right)
|
96
|
+
"#{left} #{operator} #{right}"
|
97
|
+
when IntegerLiteralExpr
|
98
|
+
# NOTE: `IntegerLiteralExpr` is a subclass of `StringLiteralExpr`, so
|
99
|
+
# this case must be before the latter
|
100
|
+
expr.value
|
101
|
+
when StringLiteralExpr
|
102
|
+
expr.value.inspect
|
103
|
+
when BooleanLiteralExpr
|
104
|
+
expr.value
|
105
|
+
when ObjectCreationExpr
|
106
|
+
# TODO: Handle object creations with anonymous classes
|
107
|
+
scoped_expression(expr) do
|
108
|
+
type = translate_type(expr.type)
|
109
|
+
"#{type}.new#{translate_arguments(expr.args)}"
|
110
|
+
end
|
111
|
+
when InstanceOfExpr
|
112
|
+
# No `instanceof` operator in ruby, but every expression is an object
|
113
|
+
# with the `is_a?` method, which serves the same purpose. We wrap the
|
114
|
+
# expression in parenthesis just in case it's not atomic.
|
115
|
+
"(#{translate_expression(expr.expr)}).is_a?(#{translate_type(expr.type)})"
|
116
|
+
when NullLiteralExpr
|
117
|
+
'nil'
|
118
|
+
when CastExpr
|
119
|
+
# No need to cast anything :P
|
120
|
+
translate_expression(expr.expr)
|
121
|
+
when ThisExpr
|
122
|
+
# TODO: Handle class expressions on `this`
|
123
|
+
'self'
|
124
|
+
when ClassExpr
|
125
|
+
"#{translate_type(expr.type)}.class"
|
126
|
+
when EnclosedExpr
|
127
|
+
"(#{translate_expression(expr.inner)})"
|
128
|
+
when ConditionalExpr
|
129
|
+
condition = translate_expression(expr.condition)
|
130
|
+
then_expr = translate_expression(expr.then_expr)
|
131
|
+
else_expr = translate_expression(expr.else_expr)
|
132
|
+
"#{condition} ? #{then_expr} : #{else_expr}"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def translate_expressions(expressions)
|
137
|
+
expressions.map { |expr| translate_expression(expr) }.join('; ')
|
138
|
+
end
|
139
|
+
|
140
|
+
private
|
141
|
+
|
142
|
+
def translate_arguments(args)
|
143
|
+
return '' unless args
|
144
|
+
"(#{args.map { |arg| translate_expression(arg) }.join(', ')})"
|
145
|
+
end
|
146
|
+
|
147
|
+
def translate_type(type)
|
148
|
+
case type
|
149
|
+
when ClassOrInterfaceType
|
150
|
+
if type.scope
|
151
|
+
scope = type
|
152
|
+
while (scope = scope.scope)
|
153
|
+
module_string = "#{scope.name.to_constant_name}#{module_string}"
|
154
|
+
end
|
155
|
+
module_string = "Java::#{module_string}::"
|
156
|
+
end
|
157
|
+
"#{module_string}#{type.name}"
|
158
|
+
when PrimitiveType
|
159
|
+
# Mapping from
|
160
|
+
# https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby#java-to-ruby
|
161
|
+
case type.type
|
162
|
+
when PrimitiveType::Primitive::Boolean
|
163
|
+
'Java::JavaLang::Boolean'
|
164
|
+
when PrimitiveType::Primitive::Byte, PrimitiveType::Primitive::Short,
|
165
|
+
PrimitiveType::Primitive::Char, PrimitiveType::Primitive::Int,
|
166
|
+
PrimitiveType::Primitive::Long
|
167
|
+
'Fixnum'
|
168
|
+
when PrimitiveType::Primitive::Float, PrimitiveType::Primitive::Double
|
169
|
+
'Float'
|
170
|
+
end
|
171
|
+
when ReferenceType
|
172
|
+
# Integer[], String[], Float[][] all translates to Array in ruby
|
173
|
+
type.array_count == 0 ? translate_type(type.type) : 'Array'
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def scoped_expression(expr)
|
178
|
+
scope = "#{translate_expression(expr.scope)}." if expr.scope
|
179
|
+
"#{scope}#{yield}"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
data/lib/jtor/java_parser.rb
CHANGED
@@ -1,53 +1,107 @@
|
|
1
|
-
|
2
|
-
require 'jbundler'
|
1
|
+
require_relative 'expressions'
|
3
2
|
|
4
3
|
java_import java.io.FileInputStream
|
5
4
|
java_import com.github.javaparser.JavaParser
|
6
5
|
|
7
6
|
module Jtor
|
8
7
|
class JavaParser
|
8
|
+
include Jtor::Expressions
|
9
|
+
|
9
10
|
attr_accessor :indentator
|
10
11
|
|
11
12
|
def initialize(f)
|
12
13
|
@indentator = ' '
|
14
|
+
@level = 0
|
13
15
|
@f = f
|
14
16
|
end
|
15
17
|
|
16
18
|
def translate(file)
|
17
19
|
parser = ::JavaParser.parse(FileInputStream.new(file))
|
18
|
-
parser.
|
20
|
+
parser.imports.each do |import|
|
21
|
+
fputs("jtor_import '#{translate_expression(import.name)}'")
|
22
|
+
end
|
23
|
+
fputs('module Java')
|
24
|
+
indented do
|
25
|
+
fputs("module #{module_name(parser.package.name)}")
|
26
|
+
indented do
|
27
|
+
parser.types.each { |type| translate_class_or_interface(type) }
|
28
|
+
end
|
29
|
+
fputs('end')
|
30
|
+
end
|
31
|
+
fputs('end')
|
19
32
|
end
|
20
33
|
|
21
34
|
private
|
22
35
|
|
23
|
-
def
|
24
|
-
@
|
36
|
+
def indent
|
37
|
+
@level += 1
|
25
38
|
end
|
26
39
|
|
27
|
-
def
|
28
|
-
|
29
|
-
type.members.each { |member| translate_member(i_level + 1, member) }
|
30
|
-
write(i_level, 'end')
|
40
|
+
def outdent
|
41
|
+
@level -= 1
|
31
42
|
end
|
32
43
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
#
|
41
|
-
|
44
|
+
def indented
|
45
|
+
indent
|
46
|
+
yield
|
47
|
+
outdent
|
48
|
+
end
|
49
|
+
|
50
|
+
def fwrite(s)
|
51
|
+
@f.write "#{@indentator * @level}#{s}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def fputs(s)
|
55
|
+
@f.puts "#{@indentator * @level}#{s}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def translate_statement(stmt)
|
59
|
+
# TODO: Translate statement
|
60
|
+
end
|
61
|
+
|
62
|
+
def translate_block_statement(block_stmt)
|
63
|
+
block_stmt.stmts.each { |stmt| translate_statement(stmt) }
|
42
64
|
end
|
43
65
|
|
44
|
-
def
|
66
|
+
def translate_param_types(params)
|
67
|
+
"[#{params.map { |p| translate_type(p.type) }.join(', ')}]"
|
68
|
+
end
|
69
|
+
|
70
|
+
def translate_param_list(params)
|
71
|
+
params.any? ? " |#{params.map { |p| p.id.name }.join(', ')}|" : ''
|
72
|
+
end
|
73
|
+
|
74
|
+
def write_method(name, params, body)
|
75
|
+
types = translate_param_types(params)
|
76
|
+
param_list = translate_param_list(params)
|
77
|
+
fputs("add_java_method(:#{name}, #{types}) do#{param_list}")
|
78
|
+
indented { translate_block_statement(body) } if body
|
79
|
+
fputs('end')
|
80
|
+
end
|
81
|
+
|
82
|
+
def translate_member(member)
|
45
83
|
case member
|
46
84
|
when Java::ComGithubJavaparserAstBody::MethodDeclaration
|
47
|
-
|
85
|
+
write_method(member.name, member.parameters, member.body)
|
48
86
|
when Java::ComGithubJavaparserAstBody::ConstructorDeclaration
|
49
|
-
|
87
|
+
write_method(:initialize, member.parameters, member.block)
|
50
88
|
end
|
51
89
|
end
|
90
|
+
|
91
|
+
def translate_class_or_interface(type)
|
92
|
+
if type.extends.any?
|
93
|
+
extends = " < #{type.extends.map { |e| translate_type(e) }.join(', ')}"
|
94
|
+
end
|
95
|
+
fputs("class #{type.name.to_constant_name}#{extends}")
|
96
|
+
indented do
|
97
|
+
fputs('extend Jtor::StdLib::Base')
|
98
|
+
type.members.each { |member| translate_member(member) }
|
99
|
+
end
|
100
|
+
fputs('end')
|
101
|
+
end
|
102
|
+
|
103
|
+
def module_name(name_expr)
|
104
|
+
name_expr.name.split('.').map(&:to_constant_name).join
|
105
|
+
end
|
52
106
|
end
|
53
107
|
end
|
data/lib/jtor/translator.rb
CHANGED
@@ -1,13 +1,22 @@
|
|
1
1
|
require 'fileutils'
|
2
|
+
require 'erb'
|
2
3
|
|
3
4
|
module Jtor
|
4
5
|
class Translator
|
5
6
|
def self.run(src, dest)
|
7
|
+
gemfile_template = ERB.new(File.read('templates/Gemfile.erb'))
|
6
8
|
Dir.chdir(src)
|
9
|
+
# Write Gemfile
|
10
|
+
File.open(File.join(dest, 'Gemfile'), 'w') do |f|
|
11
|
+
f.puts(gemfile_template.result(binding))
|
12
|
+
end
|
13
|
+
|
14
|
+
# Translate files
|
7
15
|
Dir.glob('**/*.java').each do |file|
|
8
16
|
dest_file = File.join(dest, file.gsub(/java$/, 'rb'))
|
9
17
|
FileUtils.mkdir_p(File.dirname(dest_file))
|
10
18
|
File.open(dest_file, 'w') do |f|
|
19
|
+
f.puts("require 'jtor-stdlib'")
|
11
20
|
JavaParser.new(f).translate(File.join(src, file))
|
12
21
|
end
|
13
22
|
end
|
data/lib/jtor/version.rb
ADDED
data/lib/jtor_jars.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jtor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Alejandro Rodríguez
|
@@ -34,9 +34,11 @@ files:
|
|
34
34
|
- bin/jtor
|
35
35
|
- lib/ext/string.rb
|
36
36
|
- lib/jtor.rb
|
37
|
+
- lib/jtor/expressions.rb
|
37
38
|
- lib/jtor/java_parser.rb
|
38
|
-
- lib/jtor/load.rb
|
39
39
|
- lib/jtor/translator.rb
|
40
|
+
- lib/jtor/version.rb
|
41
|
+
- lib/jtor_jars.rb
|
40
42
|
homepage: https://gitlab.com/eReGeBe/jtor
|
41
43
|
licenses:
|
42
44
|
- MIT
|
@@ -56,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
58
|
- !ruby/object:Gem::Version
|
57
59
|
version: '0'
|
58
60
|
requirements:
|
59
|
-
- jar com.github.javaparser:javaparser-core, 2.
|
61
|
+
- jar com.github.javaparser:javaparser-core, 2.3.0
|
60
62
|
rubyforge_project:
|
61
63
|
rubygems_version: 2.5.0
|
62
64
|
signing_key:
|
data/lib/jtor/load.rb
DELETED