jtor 0.1.0-java → 0.1.1-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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ca5126acd5831041982af13ccfaa6d53a8725c6a
4
- data.tar.gz: 8e09af5305d4109c2708563b0be9c00d9ec130ab
3
+ metadata.gz: bb6efd191fb3dab0c19ebe356c3a24e5cc1f8534
4
+ data.tar.gz: c33f0bc1150ace2e5db228e055e6f04593439888
5
5
  SHA512:
6
- metadata.gz: c8fe1028b34ca30c698ee1732b6d97865ebac35b5e591dd60bfe93c60e8497d7397526099bd10a39009195bf0105329087c1e18067a7ec0a9d1a44921b89e064
7
- data.tar.gz: a44d00a8f8be8c383d3964c173256b094d4cd91f203131043b93fc96a106de9d8659cd934fa32525f6fe3dd093e448df5e34112e8583e6d1c7873fd92f7a2dbe
6
+ metadata.gz: 9629eefddac483afd218996e24ed53bf0b44d3198e4d37af1b802544dd579a9192ea15478dca39f477eb8e1019185796bc11d9cc57cebfa8e30090b11dff94e4
7
+ data.tar.gz: 295d55812f342355919eef6691d957164d868feabbed06e376de4011de1e61de3318c922488e4a2ee4e9a6496fe9d2e22def698d31c1ec08ab0f67824eba9c48
data/lib/jtor.rb CHANGED
@@ -1,6 +1,11 @@
1
+ warn 'Loading jtor in a non-JRuby interpreter' unless defined? JRUBY_VERSION
2
+
3
+ require 'java'
4
+
1
5
  require 'ext/string'
2
6
 
3
- require 'jtor/load'
7
+ require 'jtor_jars.rb'
4
8
 
9
+ require 'jtor/version'
5
10
  require 'jtor/java_parser'
6
11
  require 'jtor/translator'
@@ -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
@@ -1,53 +1,107 @@
1
- require 'java'
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.types.each { |type| translate_type(0, type) }
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 write(i_level, s)
24
- @f.puts "#{@indentator * i_level}#{s}"
36
+ def indent
37
+ @level += 1
25
38
  end
26
39
 
27
- def translate_type(i_level, type)
28
- write(i_level, "class #{type.name.to_constant_name}")
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 translate_method(i_level, name, parameters)
34
- params = if parameters.any?
35
- "(#{parameters.map { |p| p.id.name }.join(', ')})"
36
- else
37
- ''
38
- end
39
- write(i_level, "def #{name}#{params}")
40
- # TODO: Translate method body
41
- write(i_level, 'end')
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 translate_member(i_level, member)
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
- translate_method(i_level, member.name, member.parameters)
85
+ write_method(member.name, member.parameters, member.body)
48
86
  when Java::ComGithubJavaparserAstBody::ConstructorDeclaration
49
- translate_method(i_level, 'initialize', member.parameters)
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
@@ -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
@@ -0,0 +1,4 @@
1
+ module Jtor
2
+ VERSION = '0.1.1'
3
+ JTOR_STDLIB_VERSION = '0.1.1'
4
+ end
data/lib/jtor_jars.rb ADDED
@@ -0,0 +1,4 @@
1
+ # this is a generated file, to avoid over-writing it just delete this comment
2
+ require 'jar_dependencies'
3
+
4
+ require_jar( 'com.github.javaparser', 'javaparser-core', '2.3.0' )
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.0
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.1.0
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
@@ -1,4 +0,0 @@
1
- warn 'Loading jtor in a non-JRuby interpreter' unless defined? JRUBY_VERSION
2
-
3
- require 'jar-dependencies'
4
- require_jar('com.github.javaparser', 'javaparser-core', '2.1.0')