to_source 0.1.3 → 0.2.0
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.
- data/.rspec +1 -0
- data/.travis.yml +12 -1
- data/Changelog.md +11 -0
- data/Gemfile +6 -3
- data/Gemfile.devtools +52 -0
- data/Guardfile +18 -0
- data/README.md +68 -0
- data/Rakefile +3 -8
- data/TODO +5 -0
- data/bin/to_source +16 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/roodi.yml +26 -0
- data/config/site.reek +93 -0
- data/config/yardstick.yml +2 -0
- data/lib/to_source.rb +13 -11
- data/lib/to_source/version.rb +1 -1
- data/lib/to_source/visitor.rb +1566 -196
- data/spec/spec_helper.rb +11 -0
- data/spec/unit/to_source/visitor/class_methods/run_spec.rb +999 -0
- data/to_source.gemspec +11 -7
- metadata +59 -12
- data/.rvmrc +0 -1
- data/Readme.md +0 -38
- data/lib/to_source/core_ext/node.rb +0 -22
- data/test/to_source/visitor_test.rb +0 -202
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
language: ruby
|
2
|
+
bundler_args: --without guard metrics
|
3
|
+
script: "bundle exec rake spec"
|
1
4
|
rvm:
|
2
|
-
|
5
|
+
#- 1.8.7
|
6
|
+
- 1.9.2
|
7
|
+
- 1.9.3
|
8
|
+
#- jruby-18mode # JRuby in 1.8 mode, no cextension support on travis
|
9
|
+
#- jruby-19mode # JRuby in 1.9 mode, no cextension support on travis
|
10
|
+
#- rbx-18mode
|
3
11
|
- rbx-19mode
|
12
|
+
notifications:
|
13
|
+
email:
|
14
|
+
- mbj@seonic.net
|
data/Changelog.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# v0.2.0 2012-12-07
|
2
|
+
|
3
|
+
* [BRAKING CHANGE] Remove core extension Rubinius::AST::Node#to_source (mbj)
|
4
|
+
* [feature] Add support for MRI via melbourne gem (mbj)
|
5
|
+
* [fixed] 100% Yard covered documentation (mbj)
|
6
|
+
* [fixed] Emit most binary operators without parantheses (mbj)
|
7
|
+
* [feature] Port tests to rspec2 and greatly improve coverage and layout of these.
|
8
|
+
* [feature] Introduce metric tools via devtools
|
9
|
+
* [fixed] Lots of transitvity edge cases
|
10
|
+
|
11
|
+
[Compare v0.1.3..v0.2.0](https://github.com/solnic/virtus/compare/v0.1.3...v0.2.0)
|
data/Gemfile
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
-
source
|
1
|
+
source :rubygems
|
2
2
|
|
3
|
-
# Specify your gem's dependencies in to_source.gemspec
|
4
3
|
gemspec
|
5
|
-
|
4
|
+
|
5
|
+
gem 'mutant-melbourne', :git => 'https://github.com/mbj/melbourne.git'
|
6
|
+
gem 'devtools', :git => 'https://github.com/mbj/devtools.git', :branch => 'rspec-2-mutant'
|
7
|
+
|
8
|
+
eval File.read('Gemfile.devtools')
|
data/Gemfile.devtools
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
group :development do
|
2
|
+
gem 'rake', '~> 0.9.2'
|
3
|
+
gem 'rspec', '~> 2.12.0'
|
4
|
+
gem 'yard', '~> 0.8.3'
|
5
|
+
end
|
6
|
+
|
7
|
+
group :guard do
|
8
|
+
gem 'guard', '~> 1.5.4'
|
9
|
+
gem 'guard-bundler', '~> 1.0.0'
|
10
|
+
gem 'guard-rspec', '~> 2.1.1'
|
11
|
+
gem 'rb-inotify', :git => 'https://github.com/mbj/rb-inotify'
|
12
|
+
end
|
13
|
+
|
14
|
+
group :benchmarks do
|
15
|
+
gem 'rbench', '~> 0.2.3'
|
16
|
+
end
|
17
|
+
|
18
|
+
platform :jruby do
|
19
|
+
group :jruby do
|
20
|
+
gem 'jruby-openssl', '~> 0.7.4'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
group :metrics do
|
25
|
+
gem 'flay', '~> 1.4.2'
|
26
|
+
gem 'flog', '~> 2.5.1'
|
27
|
+
gem 'reek', '~> 1.2.8', :git => 'https://github.com/dkubb/reek.git'
|
28
|
+
gem 'roodi', '~> 2.1.0'
|
29
|
+
gem 'yardstick', '~> 0.7.0'
|
30
|
+
gem 'simplecov'
|
31
|
+
|
32
|
+
platforms :ruby_18, :ruby_19 do
|
33
|
+
# this indirectly depends on ffi which does not build on ruby-head
|
34
|
+
gem 'yard-spellcheck', '~> 0.1.5'
|
35
|
+
end
|
36
|
+
|
37
|
+
platforms :mri_18 do
|
38
|
+
gem 'arrayfields', '~> 4.7.4' # for metric_fu
|
39
|
+
gem 'fattr', '~> 2.2.0' # for metric_fu
|
40
|
+
gem 'json', '~> 1.7.3' # for metric_fu rake task
|
41
|
+
gem 'map', '~> 6.0.1' # for metric_fu
|
42
|
+
gem 'metric_fu', '~> 2.1.1'
|
43
|
+
gem 'mspec', '~> 1.5.17'
|
44
|
+
gem 'rcov', '~> 1.0.0'
|
45
|
+
end
|
46
|
+
|
47
|
+
platforms :rbx do
|
48
|
+
gem 'pelusa', '~> 0.2.1'
|
49
|
+
gem 'anima', '~> 0.0.1', :git => 'https://github.com/mbj/anima.git'
|
50
|
+
gem 'mutant', '~> 0.0.1', :git => 'https://github.com/mbj/mutant.git'
|
51
|
+
end
|
52
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
guard :bundler do
|
4
|
+
watch('Gemfile')
|
5
|
+
end
|
6
|
+
|
7
|
+
guard :rspec do
|
8
|
+
# run all specs if the spec_helper or supporting files files are modified
|
9
|
+
watch('spec/spec_helper.rb') { 'spec' }
|
10
|
+
watch(%r{\Aspec/(?:lib|support|shared)/.+\.rb\z}) { 'spec' }
|
11
|
+
|
12
|
+
# run unit specs if associated lib code is modified
|
13
|
+
watch(%r{\Alib/(.+)\.rb\z}) { |m| Dir["spec/unit/#{m[1]}"] }
|
14
|
+
watch("lib/#{File.basename(File.expand_path('../', __FILE__))}.rb") { 'spec' }
|
15
|
+
|
16
|
+
# run a spec if it is modified
|
17
|
+
watch(%r{\Aspec/(?:unit|integration)/.+_spec\.rb\z})
|
18
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
to_source
|
2
|
+
=========
|
3
|
+
|
4
|
+
[](http://travis-ci.org/mbj/to_source)
|
5
|
+
[](https://gemnasium.com/mbj/to_source)
|
6
|
+
[](https://codeclimate.com/github/mbj/to_source)
|
7
|
+
|
8
|
+
Reverse parser to generate source code from the Rubinius AST. Also works well under MRI.
|
9
|
+
|
10
|
+
Installation
|
11
|
+
------------
|
12
|
+
|
13
|
+
Install the gem ```to_source``` via your preferred method.
|
14
|
+
|
15
|
+
Examples
|
16
|
+
--------
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
require 'to_source'
|
20
|
+
some_code = "a = 123"
|
21
|
+
ast = some_code.to_ast
|
22
|
+
# => #<Rubinius::AST::LocalVariableAssignment:0x21b8
|
23
|
+
# @value=#<Rubinius::AST::FixnumLiteral:0x21bc @value=123 @line=1>
|
24
|
+
# @variable=nil @line=1 @name=:a>
|
25
|
+
ast.to_source
|
26
|
+
# => "a = 123"
|
27
|
+
```
|
28
|
+
|
29
|
+
Credits
|
30
|
+
-------
|
31
|
+
|
32
|
+
* [Josep M. Bach (Txus)](http://txustice.me), [@txustice](http://twitter.com/txustice) on twitter
|
33
|
+
* [Markus Schirp (mbj)](https://github.com/mbj), [@_m_b_j_](http://twitter.com/_m_b_j_) on twitter
|
34
|
+
|
35
|
+
Contributing
|
36
|
+
-------------
|
37
|
+
|
38
|
+
* Fork the project.
|
39
|
+
* Make your feature addition or bug fix.
|
40
|
+
* Add tests for it. This is important so I don't break it in a
|
41
|
+
future version unintentionally.
|
42
|
+
* Commit, do not mess with Rakefile or version
|
43
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
44
|
+
* Send me a pull request. Bonus points for topic branches.
|
45
|
+
|
46
|
+
License
|
47
|
+
-------
|
48
|
+
|
49
|
+
Copyright (c) 2012 Josep M. Bach (Txus), Markus Schirp (mbj)
|
50
|
+
|
51
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
52
|
+
a copy of this software and associated documentation files (the
|
53
|
+
"Software"), to deal in the Software without restriction, including
|
54
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
55
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
56
|
+
permit persons to whom the Software is furnished to do so, subject to
|
57
|
+
the following conditions:
|
58
|
+
|
59
|
+
The above copyright notice and this permission notice shall be
|
60
|
+
included in all copies or substantial portions of the Software.
|
61
|
+
|
62
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
63
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
64
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
65
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
66
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
67
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
68
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -1,10 +1,5 @@
|
|
1
|
-
require
|
1
|
+
require 'rake'
|
2
2
|
|
3
|
-
require '
|
4
|
-
Rake::TestTask.new do |t|
|
5
|
-
t.libs << "test"
|
6
|
-
t.test_files = FileList['test/**/*_test.rb']
|
7
|
-
t.verbose = true
|
8
|
-
end
|
3
|
+
require 'devtools'
|
9
4
|
|
10
|
-
|
5
|
+
Devtools.init
|
data/TODO
ADDED
data/bin/to_source
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'to_source'
|
4
|
+
|
5
|
+
ARGV.each do |path|
|
6
|
+
source = File.read(path)
|
7
|
+
ast = source.to_ast
|
8
|
+
next if ast.nil? # When file only has comments
|
9
|
+
$stderr.puts(path)
|
10
|
+
begin
|
11
|
+
$stdout.puts(ToSource.to_source(ast))
|
12
|
+
rescue
|
13
|
+
ast.ascii_graph
|
14
|
+
raise
|
15
|
+
end
|
16
|
+
end
|
data/config/flay.yml
ADDED
data/config/flog.yml
ADDED
data/config/roodi.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
---
|
2
|
+
AbcMetricMethodCheck:
|
3
|
+
score: 12.2
|
4
|
+
AssignmentInConditionalCheck: {}
|
5
|
+
CaseMissingElseCheck: {}
|
6
|
+
ClassLineCountCheck:
|
7
|
+
line_count: 324
|
8
|
+
ClassNameCheck:
|
9
|
+
pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/
|
10
|
+
ClassVariableCheck: {}
|
11
|
+
CyclomaticComplexityBlockCheck:
|
12
|
+
complexity: 2
|
13
|
+
CyclomaticComplexityMethodCheck:
|
14
|
+
complexity: 4
|
15
|
+
EmptyRescueBodyCheck: {}
|
16
|
+
ForLoopCheck: {}
|
17
|
+
MethodLineCountCheck:
|
18
|
+
line_count: 9
|
19
|
+
MethodNameCheck:
|
20
|
+
pattern: !ruby/regexp /\A(?:[a-z\d](?:_?[a-z\d])+[?!=]?|\[\]=?|==|<=>|<<|[+*&|-])\z/
|
21
|
+
ModuleLineCountCheck:
|
22
|
+
line_count: 327
|
23
|
+
ModuleNameCheck:
|
24
|
+
pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/
|
25
|
+
ParameterNumberCheck:
|
26
|
+
parameter_count: 3
|
data/config/site.reek
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
---
|
2
|
+
UncommunicativeParameterName:
|
3
|
+
accept: []
|
4
|
+
exclude: []
|
5
|
+
enabled: true
|
6
|
+
reject:
|
7
|
+
- !ruby/regexp /^.$/
|
8
|
+
- !ruby/regexp /[0-9]$/
|
9
|
+
- !ruby/regexp /[A-Z]/
|
10
|
+
LargeClass:
|
11
|
+
max_methods: 10
|
12
|
+
exclude:
|
13
|
+
- "Mutant::Matcher::Method" # 13 methods
|
14
|
+
enabled: true
|
15
|
+
max_instance_variables: 3
|
16
|
+
UncommunicativeMethodName:
|
17
|
+
accept: []
|
18
|
+
exclude: []
|
19
|
+
enabled: true
|
20
|
+
reject:
|
21
|
+
- !ruby/regexp /^[a-z]$/
|
22
|
+
- !ruby/regexp /[0-9]$/
|
23
|
+
- !ruby/regexp /[A-Z]/
|
24
|
+
LongParameterList:
|
25
|
+
max_params: 2
|
26
|
+
exclude:
|
27
|
+
- "Mutant::Context::Constant#initialize" # 3 params
|
28
|
+
enabled: true
|
29
|
+
overrides: {}
|
30
|
+
FeatureEnvy:
|
31
|
+
exclude: []
|
32
|
+
enabled: true
|
33
|
+
ClassVariable:
|
34
|
+
exclude: []
|
35
|
+
enabled: true
|
36
|
+
BooleanParameter:
|
37
|
+
exclude: []
|
38
|
+
enabled: true
|
39
|
+
IrresponsibleModule:
|
40
|
+
exclude: []
|
41
|
+
enabled: true
|
42
|
+
UncommunicativeModuleName:
|
43
|
+
accept: []
|
44
|
+
exclude: []
|
45
|
+
enabled: true
|
46
|
+
reject:
|
47
|
+
- !ruby/regexp /^.$/
|
48
|
+
- !ruby/regexp /[0-9]$/
|
49
|
+
NestedIterators:
|
50
|
+
ignore_iterators: []
|
51
|
+
exclude: []
|
52
|
+
enabled: true
|
53
|
+
max_allowed_nesting: 1
|
54
|
+
LongMethod:
|
55
|
+
max_statements: 6
|
56
|
+
exclude: []
|
57
|
+
enabled: true
|
58
|
+
Duplication:
|
59
|
+
allow_calls: []
|
60
|
+
exclude: []
|
61
|
+
enabled: true
|
62
|
+
max_calls: 1
|
63
|
+
UtilityFunction:
|
64
|
+
max_helper_calls: 0
|
65
|
+
exclude: []
|
66
|
+
enabled: true
|
67
|
+
Attribute:
|
68
|
+
exclude: []
|
69
|
+
enabled: false
|
70
|
+
UncommunicativeVariableName:
|
71
|
+
accept: []
|
72
|
+
exclude: []
|
73
|
+
enabled: true
|
74
|
+
reject:
|
75
|
+
- !ruby/regexp /^.$/
|
76
|
+
- !ruby/regexp /[0-9]$/
|
77
|
+
- !ruby/regexp /[A-Z]/
|
78
|
+
SimulatedPolymorphism:
|
79
|
+
exclude: []
|
80
|
+
enabled: true
|
81
|
+
max_ifs: 1
|
82
|
+
DataClump:
|
83
|
+
exclude: []
|
84
|
+
enabled: true
|
85
|
+
max_copies: 2
|
86
|
+
min_clump_size: 2
|
87
|
+
ControlCouple:
|
88
|
+
exclude: []
|
89
|
+
enabled: true
|
90
|
+
LongYieldList:
|
91
|
+
max_params: 1
|
92
|
+
exclude: []
|
93
|
+
enabled: true
|
data/lib/to_source.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require 'melbourne'
|
2
|
+
require 'to_source/version'
|
3
|
+
require 'to_source/visitor'
|
4
4
|
|
5
|
+
# Namespace of library
|
5
6
|
module ToSource
|
6
|
-
#
|
7
|
+
# Convert node to string
|
7
8
|
#
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
# @param [Rubinius::AST::Node] node
|
10
|
+
#
|
11
|
+
# @return [String]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
#
|
15
|
+
def self.to_source(node)
|
16
|
+
Visitor.run(node)
|
13
17
|
end
|
14
18
|
end
|
15
|
-
|
16
|
-
Rubinius::AST::Node.send :include, ToSource
|
data/lib/to_source/version.rb
CHANGED
data/lib/to_source/visitor.rb
CHANGED
@@ -1,189 +1,1276 @@
|
|
1
1
|
module ToSource
|
2
|
+
# Converter from AST to source
|
2
3
|
class Visitor
|
3
|
-
|
4
|
+
|
5
|
+
# Create source code from AST node
|
6
|
+
#
|
7
|
+
# @param [Rubinius::AST::Node] node
|
8
|
+
# the node to convert to source code
|
9
|
+
#
|
10
|
+
# @return [String]
|
11
|
+
# returns the source code for ast node
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
#
|
15
|
+
def self.run(node)
|
16
|
+
new(node).output
|
17
|
+
end
|
18
|
+
|
19
|
+
# Return the source code of AST
|
20
|
+
#
|
21
|
+
# @return [String]
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
#
|
25
|
+
def output
|
26
|
+
@output.join
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Initialize visitor
|
32
|
+
#
|
33
|
+
# @param [Rubinius::AST::Node] node
|
34
|
+
#
|
35
|
+
# @return [undefined]
|
36
|
+
#
|
37
|
+
# @api private
|
38
|
+
#
|
39
|
+
def initialize(node)
|
4
40
|
@output = []
|
5
41
|
@indentation = 0
|
42
|
+
dispatch(node)
|
6
43
|
end
|
7
44
|
|
8
|
-
|
9
|
-
|
45
|
+
# Dispatch node
|
46
|
+
#
|
47
|
+
# @param [Rubinius::AST::Node] node
|
48
|
+
#
|
49
|
+
# @return [undefined]
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
#
|
53
|
+
def dispatch(node)
|
54
|
+
name = node.node_name
|
55
|
+
name = "#{name}_def" if %w[ class module ].include?(name)
|
56
|
+
__send__(name, node)
|
10
57
|
end
|
11
58
|
|
12
|
-
|
13
|
-
|
59
|
+
# Emit file
|
60
|
+
#
|
61
|
+
# @param [Rubinius::AST::Node] node
|
62
|
+
#
|
63
|
+
# @return [undefined]
|
64
|
+
#
|
65
|
+
# @api private
|
66
|
+
#
|
67
|
+
def file(node)
|
68
|
+
emit('__FILE__')
|
69
|
+
end
|
70
|
+
|
71
|
+
# Emit element assignment
|
72
|
+
#
|
73
|
+
# @param [Rubinius::AST::Node] node
|
74
|
+
#
|
75
|
+
# @return [undefined]
|
76
|
+
#
|
77
|
+
# @api private
|
78
|
+
#
|
79
|
+
def element_assignment(node)
|
80
|
+
index, value = node.arguments.array
|
81
|
+
dispatch(node.receiver)
|
82
|
+
emit('[')
|
83
|
+
dispatch(index)
|
84
|
+
emit('] = ')
|
85
|
+
dispatch(value)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Emit alias
|
89
|
+
#
|
90
|
+
# @param [Rubinius::AST::Node] node
|
91
|
+
#
|
92
|
+
# @return [undefined]
|
93
|
+
#
|
94
|
+
# @api private
|
95
|
+
#
|
96
|
+
def alias(node)
|
97
|
+
emit("alias #{node.to.value} #{node.from.value}")
|
14
98
|
end
|
15
99
|
|
100
|
+
# Emit match operator
|
101
|
+
#
|
102
|
+
# @param [Rubinius::AST::Node] node
|
103
|
+
#
|
104
|
+
# @return [undefined]
|
105
|
+
#
|
106
|
+
# @api private
|
107
|
+
#
|
108
|
+
def match3(node)
|
109
|
+
dispatch(node.value)
|
110
|
+
emit(' =~ ')
|
111
|
+
dispatch(node.pattern)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Emit break
|
115
|
+
#
|
116
|
+
# @param [Rubinius::AST::Node] node
|
117
|
+
#
|
118
|
+
# @return [undefined]
|
119
|
+
#
|
120
|
+
# @api private
|
121
|
+
#
|
122
|
+
def break(node)
|
123
|
+
emit('break')
|
124
|
+
end
|
125
|
+
|
126
|
+
# Emit next
|
127
|
+
#
|
128
|
+
# @param [Rubinius::AST::Node] node
|
129
|
+
#
|
130
|
+
# @return [undefined]
|
131
|
+
#
|
132
|
+
# @api private
|
133
|
+
#
|
134
|
+
def next(node)
|
135
|
+
emit('next')
|
136
|
+
end
|
137
|
+
|
138
|
+
# Emit conditional element assignment
|
139
|
+
#
|
140
|
+
# @param [Rubinius::AST::Node] node
|
141
|
+
#
|
142
|
+
# @return [undefined]
|
143
|
+
#
|
144
|
+
# @api private
|
145
|
+
#
|
146
|
+
def op_assign1(node)
|
147
|
+
receiver(node)
|
148
|
+
emit('[')
|
149
|
+
dispatch(node.arguments.array.first)
|
150
|
+
emit('] ||= ')
|
151
|
+
dispatch(node.value)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Emit attribute assignment after merge
|
155
|
+
#
|
156
|
+
# @param [Rubinius::AST::Node] node
|
157
|
+
#
|
158
|
+
# @return [undefined]
|
159
|
+
#
|
160
|
+
# @api private
|
161
|
+
#
|
162
|
+
def op_assign2(node)
|
163
|
+
dispatch(node.receiver)
|
164
|
+
emit('.')
|
165
|
+
emit(node.name)
|
166
|
+
emit(' |= ')
|
167
|
+
dispatch(node.value)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Emit rescue
|
171
|
+
#
|
172
|
+
# @param [Rubinius::AST::Node] node
|
173
|
+
#
|
174
|
+
# @return [undefined]
|
175
|
+
#
|
176
|
+
# @api private
|
177
|
+
#
|
178
|
+
def rescue(node)
|
179
|
+
body(node.body)
|
180
|
+
rescue_condition(node.rescue)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Emit rescue condition
|
184
|
+
#
|
185
|
+
# @param [Rubinius::AST::Node] node
|
186
|
+
#
|
187
|
+
# @return [undefined]
|
188
|
+
#
|
189
|
+
# @api private
|
190
|
+
#
|
191
|
+
def rescue_condition(node)
|
192
|
+
emit('rescue')
|
193
|
+
if node.conditions
|
194
|
+
body = node.conditions.body
|
195
|
+
first = body.first
|
196
|
+
unless body.one? and first.kind_of?(Rubinius::AST::ConstantAccess) and first.name == :StandardError
|
197
|
+
emit(' ')
|
198
|
+
array_body(body)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
if node.splat
|
203
|
+
emit(',') if node.conditions
|
204
|
+
emit(' ')
|
205
|
+
dispatch(node.splat)
|
206
|
+
end
|
207
|
+
|
208
|
+
if node.assignment
|
209
|
+
emit(' => ')
|
210
|
+
emit(node.assignment.name)
|
211
|
+
end
|
212
|
+
nl
|
213
|
+
body(node.body)
|
214
|
+
|
215
|
+
if node.next
|
216
|
+
dispatch(node.next)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# Emit rescue splat
|
221
|
+
#
|
222
|
+
# @param [Rubinius::AST::Node] node
|
223
|
+
#
|
224
|
+
# @return [undefined]
|
225
|
+
#
|
226
|
+
# @api private
|
227
|
+
#
|
228
|
+
def rescue_splat(node)
|
229
|
+
emit('*')
|
230
|
+
dispatch(node.value)
|
231
|
+
end
|
232
|
+
|
233
|
+
# Emit ensure
|
234
|
+
#
|
235
|
+
# @param [Rubinius::AST::Node] node
|
236
|
+
#
|
237
|
+
# @return [undefined]
|
238
|
+
#
|
239
|
+
# @api private
|
240
|
+
#
|
241
|
+
def ensure(node)
|
242
|
+
body(node.body)
|
243
|
+
emit('ensure')
|
244
|
+
nl
|
245
|
+
body(node.ensure)
|
246
|
+
end
|
247
|
+
|
248
|
+
# Emit attribute assignment
|
249
|
+
#
|
250
|
+
# @param [Rubinius::AST::Node] node
|
251
|
+
#
|
252
|
+
# @return [undefined]
|
253
|
+
#
|
254
|
+
# @api private
|
255
|
+
#
|
256
|
+
def attribute_assignment(node)
|
257
|
+
dispatch(node.receiver)
|
258
|
+
emit('.')
|
259
|
+
emit(node.name)
|
260
|
+
emit(' ')
|
261
|
+
actual_arguments(node.arguments)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Emit body with taking care on indentation
|
265
|
+
#
|
266
|
+
# @param [Rubinius::AST::Node] node
|
267
|
+
#
|
268
|
+
# @return [undefined]
|
269
|
+
#
|
270
|
+
# @api private
|
271
|
+
#
|
272
|
+
def body(node)
|
273
|
+
@indentation+=1
|
274
|
+
node =
|
275
|
+
case node
|
276
|
+
when Rubinius::AST::EmptyBody
|
277
|
+
node
|
278
|
+
when Rubinius::AST::Block
|
279
|
+
# Hack to correctly indent ensure or rescue
|
280
|
+
noindent = [Rubinius::AST::Ensure, Rubinius::AST::Rescue]
|
281
|
+
if node.array.one? && noindent.include?(node.array.first.class)
|
282
|
+
@indentation-=1
|
283
|
+
dispatch(node)
|
284
|
+
return
|
285
|
+
end
|
286
|
+
node
|
287
|
+
else
|
288
|
+
Rubinius::AST::Block.new(node.line, [node])
|
289
|
+
end
|
290
|
+
|
291
|
+
dispatch(node)
|
292
|
+
nl
|
293
|
+
@indentation-=1
|
294
|
+
end
|
295
|
+
|
296
|
+
# Emit end keyword
|
297
|
+
#
|
298
|
+
# @return [undefined]
|
299
|
+
#
|
300
|
+
# @api private
|
301
|
+
#
|
302
|
+
def kend
|
303
|
+
emit(current_indentation)
|
304
|
+
emit('end')
|
305
|
+
end
|
306
|
+
|
307
|
+
# Emit newline
|
308
|
+
#
|
309
|
+
# @return [undefined]
|
310
|
+
#
|
311
|
+
# @api private
|
312
|
+
#
|
313
|
+
def nl
|
314
|
+
emit("\n")
|
315
|
+
end
|
316
|
+
|
317
|
+
# Emit pice of code
|
318
|
+
#
|
319
|
+
# @param [String] code
|
320
|
+
#
|
321
|
+
# @return [undefined]
|
322
|
+
#
|
323
|
+
# @api private
|
324
|
+
#
|
325
|
+
def emit(code)
|
326
|
+
@output << code
|
327
|
+
end
|
328
|
+
|
329
|
+
# Return current indentation
|
330
|
+
#
|
331
|
+
# @return [String]
|
332
|
+
#
|
333
|
+
# @api private
|
334
|
+
#
|
16
335
|
def current_indentation
|
17
336
|
' ' * @indentation
|
18
337
|
end
|
19
338
|
|
20
|
-
|
21
|
-
|
339
|
+
# Emit dynamic regexp
|
340
|
+
#
|
341
|
+
# @param [Rubinius::AST::Node] node
|
342
|
+
#
|
343
|
+
# @return [undefined]
|
344
|
+
#
|
345
|
+
# @api private
|
346
|
+
#
|
347
|
+
def dynamic_regex(node)
|
348
|
+
emit('/')
|
349
|
+
emit(node.string)
|
350
|
+
node.array.each do |member|
|
351
|
+
case member
|
352
|
+
when Rubinius::AST::ToString
|
353
|
+
emit('#{')
|
354
|
+
dispatch(member.value)
|
355
|
+
emit('}')
|
356
|
+
when Rubinius::AST::StringLiteral
|
357
|
+
emit(member.string)
|
358
|
+
end
|
359
|
+
end
|
360
|
+
emit('/')
|
361
|
+
end
|
362
|
+
|
363
|
+
# Emit dynamic string body
|
364
|
+
#
|
365
|
+
# @param [Rubinius::AST::Node] node
|
366
|
+
#
|
367
|
+
# @return [undefined]
|
368
|
+
#
|
369
|
+
# @api private
|
370
|
+
#
|
371
|
+
def dynamic_string_body(node)
|
372
|
+
emit(node.string.inspect[1..-2])
|
373
|
+
node.array.each do |member|
|
374
|
+
case member
|
375
|
+
when Rubinius::AST::ToString
|
376
|
+
emit('#{')
|
377
|
+
dispatch(member.value)
|
378
|
+
emit('}')
|
379
|
+
when Rubinius::AST::StringLiteral
|
380
|
+
emit(member.string.inspect[1..-2])
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
# Emit dynamic execute string
|
386
|
+
#
|
387
|
+
# @param [Rubinius::AST::Node] node
|
388
|
+
#
|
389
|
+
# @return [undefined]
|
390
|
+
#
|
391
|
+
# @api private
|
392
|
+
#
|
393
|
+
def dynamic_execute_string(node)
|
394
|
+
emit('`')
|
395
|
+
dynamic_string_body(node)
|
396
|
+
emit('`')
|
397
|
+
end
|
398
|
+
|
399
|
+
# Emit dynamic string
|
400
|
+
#
|
401
|
+
# @param [Rubinius::AST::Node] node
|
402
|
+
#
|
403
|
+
# @return [undefined]
|
404
|
+
#
|
405
|
+
# @api private
|
406
|
+
#
|
407
|
+
def dynamic_string(node)
|
408
|
+
emit('"')
|
409
|
+
dynamic_string_body(node)
|
410
|
+
emit('"')
|
411
|
+
end
|
412
|
+
|
413
|
+
# Emit dynamic symbol
|
414
|
+
#
|
415
|
+
# @param [Rubinius::AST::Node] node
|
416
|
+
#
|
417
|
+
# @return [undefined]
|
418
|
+
#
|
419
|
+
# @api private
|
420
|
+
#
|
421
|
+
def dynamic_symbol(node)
|
422
|
+
emit(':')
|
423
|
+
dynamic_string(node)
|
424
|
+
end
|
425
|
+
|
426
|
+
# Emit singleton class inheritance
|
427
|
+
#
|
428
|
+
# @param [Rubinius::AST::Node] node
|
429
|
+
#
|
430
|
+
# @return [undefined]
|
431
|
+
#
|
432
|
+
# @api private
|
433
|
+
#
|
434
|
+
def s_class(node)
|
435
|
+
emit('class << ')
|
436
|
+
dispatch(node.receiver)
|
437
|
+
nl
|
438
|
+
# FIXME: attr_reader missing on Rubinius::AST::SClass
|
439
|
+
scope = node.instance_variable_get(:@body)
|
440
|
+
body = scope.body
|
441
|
+
if body
|
442
|
+
body(body)
|
443
|
+
end
|
444
|
+
kend
|
445
|
+
end
|
446
|
+
|
447
|
+
# Emit to array
|
448
|
+
#
|
449
|
+
# @param [Rubinius::AST::Node] node
|
450
|
+
#
|
451
|
+
# @return [undefined]
|
452
|
+
#
|
453
|
+
# @api private
|
454
|
+
#
|
455
|
+
def to_array(node)
|
456
|
+
dispatch(node.value)
|
457
|
+
end
|
458
|
+
|
459
|
+
# Emit multiple assignment
|
460
|
+
#
|
461
|
+
# @param [Rubinius::AST::Node] node
|
462
|
+
#
|
463
|
+
# @return [undefined]
|
464
|
+
#
|
465
|
+
# @api private
|
466
|
+
#
|
467
|
+
def multiple_assignment(node)
|
468
|
+
body = node.left.body
|
469
|
+
|
470
|
+
array_body(node.left.body)
|
471
|
+
|
472
|
+
emit(' = ')
|
473
|
+
|
474
|
+
right = node.right
|
475
|
+
|
476
|
+
if node.right.kind_of?(Rubinius::AST::ArrayLiteral)
|
477
|
+
array_body(right.body)
|
478
|
+
else
|
479
|
+
dispatch(right)
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
# Emit constant assignment
|
484
|
+
#
|
485
|
+
# @param [Rubinius::AST::Node] node
|
486
|
+
#
|
487
|
+
# @return [undefined]
|
488
|
+
#
|
489
|
+
# @api private
|
490
|
+
#
|
491
|
+
def constant_assignment(node)
|
492
|
+
dispatch(node.constant)
|
493
|
+
emit(' = ')
|
494
|
+
dispatch(node.value)
|
495
|
+
end
|
496
|
+
|
497
|
+
# Emit negation
|
498
|
+
#
|
499
|
+
# @param [Rubinius::AST::Node] node
|
500
|
+
#
|
501
|
+
# @return [undefined]
|
502
|
+
#
|
503
|
+
# @api private
|
504
|
+
#
|
505
|
+
def negate(node)
|
506
|
+
emit('-')
|
507
|
+
dispatch(node.value)
|
508
|
+
end
|
509
|
+
|
510
|
+
# Emit class definition
|
511
|
+
#
|
512
|
+
# @param [Rubinius::AST::Node] node
|
513
|
+
#
|
514
|
+
# @return [undefined]
|
515
|
+
#
|
516
|
+
# @api private
|
517
|
+
#
|
518
|
+
def class_def(node)
|
519
|
+
emit('class ')
|
520
|
+
|
521
|
+
dispatch(node.name)
|
22
522
|
|
23
523
|
superclass = node.superclass
|
24
524
|
unless superclass.is_a?(Rubinius::AST::NilLiteral)
|
25
|
-
emit
|
525
|
+
emit ' < '
|
526
|
+
dispatch(superclass)
|
26
527
|
end
|
528
|
+
nl
|
27
529
|
|
28
|
-
node.body
|
530
|
+
dispatch(node.body)
|
29
531
|
|
30
|
-
|
31
|
-
emit "end"
|
532
|
+
kend
|
32
533
|
end
|
33
534
|
|
34
|
-
|
35
|
-
|
535
|
+
# Emit class name
|
536
|
+
#
|
537
|
+
# @param [Rubinius::AST::Node] node
|
538
|
+
#
|
539
|
+
# @return [undefined]
|
540
|
+
#
|
541
|
+
# @api private
|
542
|
+
#
|
543
|
+
def class_name(node)
|
544
|
+
emit(node.name)
|
545
|
+
end
|
36
546
|
|
37
|
-
|
547
|
+
# Emit module name
|
548
|
+
#
|
549
|
+
# @param [Rubinius::AST::Node] node
|
550
|
+
#
|
551
|
+
# @return [undefined]
|
552
|
+
#
|
553
|
+
# @api private
|
554
|
+
#
|
555
|
+
def module_name(node)
|
556
|
+
emit(node.name)
|
557
|
+
end
|
38
558
|
|
39
|
-
|
40
|
-
|
559
|
+
# Emit module definition
|
560
|
+
#
|
561
|
+
# @param [Rubinius::AST::Node] node
|
562
|
+
#
|
563
|
+
# @return [undefined]
|
564
|
+
#
|
565
|
+
# @api private
|
566
|
+
#
|
567
|
+
def module_def(node)
|
568
|
+
emit "module "
|
569
|
+
dispatch(node.name)
|
570
|
+
nl
|
571
|
+
|
572
|
+
dispatch(node.body)
|
573
|
+
|
574
|
+
kend
|
41
575
|
end
|
42
576
|
|
43
|
-
|
577
|
+
# Emit empty body
|
578
|
+
#
|
579
|
+
# @param [Rubinius::AST::Node] node
|
580
|
+
#
|
581
|
+
# @return [undefined]
|
582
|
+
#
|
583
|
+
# @api private
|
584
|
+
#
|
585
|
+
def empty_body(node)
|
44
586
|
# do nothing
|
45
587
|
end
|
46
588
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
589
|
+
# Emit class scope
|
590
|
+
#
|
591
|
+
# @param [Rubinius::AST::Node] node
|
592
|
+
#
|
593
|
+
# @return [undefined]
|
594
|
+
#
|
595
|
+
# @api private
|
596
|
+
#
|
597
|
+
def class_scope(node)
|
598
|
+
body(node.body)
|
599
|
+
end
|
600
|
+
|
601
|
+
# Emit module scope
|
602
|
+
#
|
603
|
+
# @param [Rubinius::AST::Node] node
|
604
|
+
#
|
605
|
+
# @return [undefined]
|
606
|
+
#
|
607
|
+
# @api private
|
608
|
+
#
|
609
|
+
def module_scope(node)
|
610
|
+
body(node.body)
|
611
|
+
end
|
612
|
+
|
613
|
+
# Emit class variable assignment
|
614
|
+
#
|
615
|
+
# @param [Rubinius::AST::Node] node
|
616
|
+
#
|
617
|
+
# @return [undefined]
|
618
|
+
#
|
619
|
+
# @api private
|
620
|
+
#
|
621
|
+
def class_variable_assignment(node)
|
622
|
+
if node.value
|
623
|
+
emit("#{node.name} = ")
|
624
|
+
dispatch(node.value)
|
625
|
+
else
|
626
|
+
emit(node.name)
|
627
|
+
end
|
628
|
+
end
|
629
|
+
|
630
|
+
# Emit local variable assignment
|
631
|
+
#
|
632
|
+
# @param [Rubinius::AST::Node] node
|
633
|
+
#
|
634
|
+
# @return [undefined]
|
635
|
+
#
|
636
|
+
# @api private
|
637
|
+
#
|
638
|
+
def local_variable_assignment(node)
|
639
|
+
if node.value
|
640
|
+
emit("#{node.name} = ")
|
641
|
+
dispatch(node.value)
|
642
|
+
else
|
643
|
+
emit(node.name)
|
644
|
+
end
|
645
|
+
end
|
646
|
+
|
647
|
+
# Emit class variable
|
648
|
+
#
|
649
|
+
# @param [Rubinius::AST::Node] node
|
650
|
+
#
|
651
|
+
# @return [undefined]
|
652
|
+
#
|
653
|
+
# @api private
|
654
|
+
#
|
655
|
+
def class_variable_access(node)
|
656
|
+
emit(node.name)
|
657
|
+
end
|
658
|
+
|
659
|
+
# Emit local variable access
|
660
|
+
#
|
661
|
+
# @param [Rubinius::AST::Node] node
|
662
|
+
#
|
663
|
+
# @return [undefined]
|
664
|
+
#
|
665
|
+
# @api private
|
666
|
+
#
|
667
|
+
def local_variable_access(node)
|
668
|
+
emit(node.name)
|
53
669
|
end
|
54
|
-
alias module_scope class_scope
|
55
670
|
|
56
|
-
|
57
|
-
|
58
|
-
|
671
|
+
# Emit global variable access
|
672
|
+
#
|
673
|
+
# @param [Rubinius::AST::Node] node
|
674
|
+
#
|
675
|
+
# @return [undefined]
|
676
|
+
#
|
677
|
+
# @api private
|
678
|
+
#
|
679
|
+
def global_variable_access(node)
|
680
|
+
emit(node.name)
|
681
|
+
end
|
682
|
+
|
683
|
+
# Emit global variable assignment
|
684
|
+
#
|
685
|
+
# @param [Rubinius::AST::Node] node
|
686
|
+
#
|
687
|
+
# @return [undefined]
|
688
|
+
#
|
689
|
+
# @api private
|
690
|
+
#
|
691
|
+
def global_variable_assignment(node)
|
692
|
+
if(node.value)
|
693
|
+
emit("%s = " % node.name)
|
694
|
+
dispatch(node.value)
|
695
|
+
else
|
696
|
+
emit(node.name)
|
697
|
+
end
|
698
|
+
end
|
699
|
+
|
700
|
+
# Emit nref global variable access
|
701
|
+
#
|
702
|
+
# @param [Rubinius::AST::Node] node
|
703
|
+
#
|
704
|
+
# @return [undefined]
|
705
|
+
#
|
706
|
+
# @api private
|
707
|
+
#
|
708
|
+
def nth_ref(node)
|
709
|
+
emit("$#{node.which}")
|
710
|
+
end
|
711
|
+
|
712
|
+
# Emit instance variable assignment
|
713
|
+
#
|
714
|
+
# @param [Rubinius::AST::Node] node
|
715
|
+
#
|
716
|
+
# @return [undefined]
|
717
|
+
#
|
718
|
+
# @api private
|
719
|
+
#
|
720
|
+
def instance_variable_assignment(node)
|
721
|
+
if(node.value)
|
722
|
+
emit("%s = " % node.name)
|
723
|
+
dispatch(node.value)
|
724
|
+
else
|
725
|
+
emit(node.name)
|
726
|
+
end
|
59
727
|
end
|
60
728
|
|
61
|
-
|
62
|
-
|
729
|
+
# Emit instance variable access
|
730
|
+
#
|
731
|
+
# @param [Rubinius::AST::Node] node
|
732
|
+
#
|
733
|
+
# @return [undefined]
|
734
|
+
#
|
735
|
+
# @api private
|
736
|
+
#
|
737
|
+
def instance_variable_access(node)
|
738
|
+
emit(node.name)
|
63
739
|
end
|
64
740
|
|
65
|
-
|
66
|
-
|
67
|
-
|
741
|
+
# Emit defined check
|
742
|
+
#
|
743
|
+
# @param [Rubinius::AST::Node] node
|
744
|
+
#
|
745
|
+
# @return [undefined]
|
746
|
+
#
|
747
|
+
# @api private
|
748
|
+
#
|
749
|
+
def defined(node)
|
750
|
+
emit('defined?(')
|
751
|
+
dispatch(node.expression)
|
752
|
+
emit(')')
|
68
753
|
end
|
69
754
|
|
70
|
-
|
71
|
-
|
755
|
+
# Emit fixnum literal
|
756
|
+
#
|
757
|
+
# @param [Rubinius::AST::Node] node
|
758
|
+
#
|
759
|
+
# @return [undefined]
|
760
|
+
#
|
761
|
+
# @api private
|
762
|
+
#
|
763
|
+
def fixnum_literal(node)
|
764
|
+
emit(node.value.to_s)
|
72
765
|
end
|
73
766
|
|
74
|
-
|
75
|
-
|
767
|
+
# Emit float literal
|
768
|
+
#
|
769
|
+
# @param [Rubinius::AST::Node] node
|
770
|
+
#
|
771
|
+
# @return [undefined]
|
772
|
+
#
|
773
|
+
# @api private
|
774
|
+
#
|
775
|
+
def float_literal(node)
|
776
|
+
emit(node.value.to_s)
|
76
777
|
end
|
77
778
|
|
78
|
-
|
79
|
-
|
779
|
+
# Emit string literal
|
780
|
+
#
|
781
|
+
# @param [Rubinius::AST::Node] node
|
782
|
+
#
|
783
|
+
# @return [undefined]
|
784
|
+
#
|
785
|
+
# @api private
|
786
|
+
#
|
787
|
+
def string_literal(node)
|
788
|
+
emit(node.string.inspect)
|
80
789
|
end
|
81
790
|
|
82
|
-
|
83
|
-
|
791
|
+
# Emit execute string
|
792
|
+
#
|
793
|
+
# @param [Rubinius::AST::Node] node
|
794
|
+
#
|
795
|
+
# @return [undefined]
|
796
|
+
#
|
797
|
+
# @api private
|
798
|
+
#
|
799
|
+
def execute_string(node)
|
800
|
+
emit("`#{node.string.inspect[1..-2]}`")
|
84
801
|
end
|
85
802
|
|
86
|
-
|
87
|
-
|
803
|
+
# Emit symbol literal
|
804
|
+
#
|
805
|
+
# @param [Rubinius::AST::Node] node
|
806
|
+
#
|
807
|
+
# @return [undefined]
|
808
|
+
#
|
809
|
+
# @api private
|
810
|
+
#
|
811
|
+
def symbol_literal(node)
|
812
|
+
emit ":#{node.value.to_s}"
|
88
813
|
end
|
89
814
|
|
90
|
-
|
815
|
+
# Emit true literal
|
816
|
+
#
|
817
|
+
# @param [Rubinius::AST::Node] node
|
818
|
+
#
|
819
|
+
# @return [undefined]
|
820
|
+
#
|
821
|
+
# @api private
|
822
|
+
#
|
823
|
+
def true_literal(node)
|
91
824
|
emit 'true'
|
92
825
|
end
|
93
826
|
|
94
|
-
|
827
|
+
# Emit false literal
|
828
|
+
#
|
829
|
+
# @param [Rubinius::AST::Node] node
|
830
|
+
#
|
831
|
+
# @return [undefined]
|
832
|
+
#
|
833
|
+
# @api private
|
834
|
+
#
|
835
|
+
def false_literal(node)
|
95
836
|
emit 'false'
|
96
837
|
end
|
97
838
|
|
98
|
-
|
839
|
+
# Emit nil literal
|
840
|
+
#
|
841
|
+
# @param [Rubinius::AST::Node] node
|
842
|
+
#
|
843
|
+
# @return [undefined]
|
844
|
+
#
|
845
|
+
# @api private
|
846
|
+
#
|
847
|
+
def nil_literal(node)
|
99
848
|
emit 'nil'
|
100
849
|
end
|
101
850
|
|
102
|
-
|
103
|
-
|
851
|
+
# Emit argumentless super
|
852
|
+
#
|
853
|
+
# @param [Rubinius::AST::Node] node
|
854
|
+
#
|
855
|
+
# @return [undefined]
|
856
|
+
#
|
857
|
+
# @api private
|
858
|
+
#
|
859
|
+
def z_super(node)
|
860
|
+
emit('super')
|
861
|
+
end
|
862
|
+
|
863
|
+
# Emit super
|
864
|
+
#
|
865
|
+
# @param [Rubinius::AST::Node] node
|
866
|
+
#
|
867
|
+
# @return [undefined]
|
868
|
+
#
|
869
|
+
# @api private
|
870
|
+
#
|
871
|
+
def super(node)
|
872
|
+
z_super(node)
|
873
|
+
arguments(node)
|
874
|
+
end
|
104
875
|
|
105
|
-
|
876
|
+
# Emit concat args
|
877
|
+
#
|
878
|
+
# @param [Rubinius::AST::Node] node
|
879
|
+
#
|
880
|
+
# @return [undefined]
|
881
|
+
#
|
882
|
+
# @api private
|
883
|
+
#
|
884
|
+
def concat_args(node)
|
885
|
+
emit('[')
|
886
|
+
array_body(node.array.body)
|
887
|
+
emit(', ')
|
888
|
+
emit('*')
|
889
|
+
dispatch(node.rest)
|
890
|
+
emit(']')
|
891
|
+
end
|
892
|
+
|
893
|
+
# Emit array body
|
894
|
+
#
|
895
|
+
# @param [Array] body
|
896
|
+
#
|
897
|
+
# @return [undefined]
|
898
|
+
#
|
899
|
+
# @api private
|
900
|
+
#
|
901
|
+
def array_body(body)
|
106
902
|
body.each_with_index do |node, index|
|
107
|
-
node
|
903
|
+
dispatch(node)
|
108
904
|
emit ', ' unless body.length == index + 1 # last element
|
109
905
|
end
|
110
|
-
emit ']'
|
111
906
|
end
|
112
907
|
|
113
|
-
|
908
|
+
# Emit array literal
|
909
|
+
#
|
910
|
+
# @param [Rubinius::AST::Node] node
|
911
|
+
#
|
912
|
+
# @return [undefined]
|
913
|
+
#
|
914
|
+
# @api private
|
915
|
+
#
|
916
|
+
def array_literal(node)
|
917
|
+
emit('[')
|
918
|
+
array_body(node.body)
|
919
|
+
emit(']')
|
920
|
+
end
|
921
|
+
|
922
|
+
|
923
|
+
# Emit emtpy array literal
|
924
|
+
#
|
925
|
+
# @param [Rubinius::AST::Node] node
|
926
|
+
#
|
927
|
+
# @return [undefined]
|
928
|
+
#
|
929
|
+
# @api private
|
930
|
+
#
|
931
|
+
def empty_array(node)
|
932
|
+
emit('[]')
|
933
|
+
end
|
934
|
+
|
935
|
+
# Emit hash literal
|
936
|
+
#
|
937
|
+
# @param [Rubinius::AST::Node] node
|
938
|
+
#
|
939
|
+
# @return [undefined]
|
940
|
+
#
|
941
|
+
# @api private
|
942
|
+
#
|
943
|
+
def hash_literal(node)
|
114
944
|
body = node.array.each_slice(2)
|
115
945
|
|
116
946
|
emit '{'
|
117
947
|
body.each_with_index do |slice, index|
|
118
948
|
key, value = slice
|
119
949
|
|
120
|
-
key
|
950
|
+
dispatch(key)
|
121
951
|
emit " => "
|
122
|
-
value
|
952
|
+
dispatch(value)
|
123
953
|
|
124
954
|
emit ', ' unless body.to_a.length == index + 1 # last element
|
125
955
|
end
|
126
956
|
emit '}'
|
127
957
|
end
|
128
958
|
|
129
|
-
|
130
|
-
|
959
|
+
# Emit inclusive range literal
|
960
|
+
#
|
961
|
+
# @param [Rubinius::AST::Node] node
|
962
|
+
#
|
963
|
+
# @return [undefined]
|
964
|
+
#
|
965
|
+
# @api private
|
966
|
+
#
|
967
|
+
def range(node)
|
968
|
+
dispatch(node.start)
|
131
969
|
emit '..'
|
132
|
-
node.finish
|
970
|
+
dispatch(node.finish)
|
133
971
|
end
|
134
972
|
|
135
|
-
|
136
|
-
|
973
|
+
# Emit exlusive range literal
|
974
|
+
#
|
975
|
+
# @param [Rubinius::AST::Node] node
|
976
|
+
#
|
977
|
+
# @return [undefined]
|
978
|
+
#
|
979
|
+
# @api private
|
980
|
+
#
|
981
|
+
def range_exclude(node)
|
982
|
+
dispatch(node.start)
|
137
983
|
emit '...'
|
138
|
-
node.finish
|
984
|
+
dispatch(node.finish)
|
139
985
|
end
|
140
986
|
|
141
|
-
|
987
|
+
# Emit range literal
|
988
|
+
#
|
989
|
+
# @param [Rubinius::AST::Node] node
|
990
|
+
#
|
991
|
+
# @return [undefined]
|
992
|
+
#
|
993
|
+
# @api private
|
994
|
+
#
|
995
|
+
def regex_literal(node)
|
142
996
|
emit '/'
|
143
997
|
emit node.source
|
144
998
|
emit '/'
|
145
999
|
end
|
146
1000
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
1001
|
+
|
1002
|
+
# Emit receiver
|
1003
|
+
#
|
1004
|
+
# @param [Rubinius::AST::Node] node
|
1005
|
+
#
|
1006
|
+
# @return [true]
|
1007
|
+
# returns true if there is an explicit receiver
|
1008
|
+
#
|
1009
|
+
# @return [false]
|
1010
|
+
# returns false otherwise
|
1011
|
+
#
|
1012
|
+
# @api private
|
1013
|
+
#
|
1014
|
+
def receiver(node)
|
1015
|
+
unless node.receiver.is_a?(Rubinius::AST::Self) and node.privately
|
1016
|
+
dispatch(node.receiver)
|
1017
|
+
true
|
1018
|
+
else
|
1019
|
+
false
|
151
1020
|
end
|
152
|
-
|
1021
|
+
end
|
153
1022
|
|
154
|
-
|
155
|
-
|
156
|
-
|
1023
|
+
# Emit send literal
|
1024
|
+
#
|
1025
|
+
# @param [Rubinius::AST::Node] node
|
1026
|
+
#
|
1027
|
+
# @return [undefined]
|
1028
|
+
#
|
1029
|
+
# @api private
|
1030
|
+
#
|
1031
|
+
def send(node)
|
1032
|
+
if node.name == :'!'
|
1033
|
+
emit('!')
|
1034
|
+
dispatch(node.receiver)
|
1035
|
+
return
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
if receiver(node)
|
1039
|
+
emit('.')
|
1040
|
+
end
|
1041
|
+
|
1042
|
+
emit(node.name)
|
1043
|
+
|
1044
|
+
block = node.block
|
1045
|
+
|
1046
|
+
if(block)
|
1047
|
+
if block.kind_of?(Rubinius::AST::BlockPass)
|
1048
|
+
emit('(')
|
1049
|
+
block_pass(block)
|
1050
|
+
emit(')')
|
1051
|
+
else
|
1052
|
+
dispatch(block)
|
1053
|
+
end
|
157
1054
|
end
|
158
1055
|
end
|
159
1056
|
|
160
|
-
|
161
|
-
|
1057
|
+
# Emit arguments
|
1058
|
+
#
|
1059
|
+
# @param [Rubinius::AST::Node] node
|
1060
|
+
#
|
1061
|
+
# @return [undefined]
|
1062
|
+
#
|
1063
|
+
# @api private
|
1064
|
+
#
|
1065
|
+
def arguments(node, open='(', close=')')
|
1066
|
+
arguments = node.arguments
|
1067
|
+
array, block = arguments.array, node.block
|
162
1068
|
|
1069
|
+
return if array.empty? and block.nil? and arguments.splat.nil?
|
1070
|
+
|
1071
|
+
emit(open)
|
1072
|
+
|
1073
|
+
array_body(array)
|
1074
|
+
is_block_pass = block.kind_of?(Rubinius::AST::BlockPass)
|
1075
|
+
|
1076
|
+
if arguments.splat
|
1077
|
+
emit(', ') unless array.empty?
|
1078
|
+
dispatch(arguments.splat)
|
1079
|
+
end
|
1080
|
+
|
1081
|
+
if is_block_pass
|
1082
|
+
emit(', ') unless array.empty?
|
1083
|
+
block_pass(block)
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
emit(close)
|
1087
|
+
|
1088
|
+
if block and !is_block_pass
|
1089
|
+
dispatch(node.block)
|
1090
|
+
end
|
1091
|
+
end
|
1092
|
+
|
1093
|
+
# Emit self
|
1094
|
+
#
|
1095
|
+
# @param [Rubinius::AST::Node] node
|
1096
|
+
#
|
1097
|
+
# @return [undefined]
|
1098
|
+
#
|
1099
|
+
# @api private
|
1100
|
+
#
|
1101
|
+
def self(node)
|
1102
|
+
emit('self')
|
1103
|
+
end
|
1104
|
+
|
1105
|
+
# Emit element reference
|
1106
|
+
#
|
1107
|
+
# @param [Rubinius::AST::Node] node
|
1108
|
+
#
|
1109
|
+
# @return [undefined]
|
1110
|
+
#
|
1111
|
+
# @api private
|
1112
|
+
#
|
1113
|
+
def element_reference(node)
|
163
1114
|
unless node.receiver.is_a?(Rubinius::AST::Self)
|
164
|
-
node.receiver
|
165
|
-
|
1115
|
+
dispatch(node.receiver)
|
1116
|
+
end
|
1117
|
+
|
1118
|
+
arguments(node,'[',']')
|
1119
|
+
end
|
1120
|
+
|
1121
|
+
# Emit send with arguments
|
1122
|
+
#
|
1123
|
+
# @param [Rubinius::AST::Node] node
|
1124
|
+
#
|
1125
|
+
# @return [undefined]
|
1126
|
+
#
|
1127
|
+
# @api private
|
1128
|
+
#
|
1129
|
+
def send_with_arguments(node)
|
1130
|
+
if node.name == :[]
|
1131
|
+
return element_reference(node)
|
1132
|
+
end
|
1133
|
+
return if process_binary_operator(node)
|
1134
|
+
|
1135
|
+
if receiver(node)
|
1136
|
+
emit('.')
|
166
1137
|
end
|
167
1138
|
|
168
|
-
emit
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
1139
|
+
emit(node.name)
|
1140
|
+
|
1141
|
+
arguments(node)
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
# Emit yield
|
1145
|
+
#
|
1146
|
+
# @param [Rubinius::AST::Node] node
|
1147
|
+
#
|
1148
|
+
# @return [undefined]
|
1149
|
+
#
|
1150
|
+
# @api private
|
1151
|
+
#
|
1152
|
+
def yield(node)
|
1153
|
+
emit('yield')
|
1154
|
+
arguments(node)
|
1155
|
+
end
|
1156
|
+
|
1157
|
+
# Emit receiver case statment
|
1158
|
+
#
|
1159
|
+
# @param [Rubinius::AST::Node] node
|
1160
|
+
#
|
1161
|
+
# @return [undefined]
|
1162
|
+
#
|
1163
|
+
# @api private
|
1164
|
+
#
|
1165
|
+
def receiver_case(node)
|
1166
|
+
emit('case ')
|
1167
|
+
dispatch(node.receiver)
|
1168
|
+
nl
|
1169
|
+
node.whens.each do |branch|
|
1170
|
+
dispatch(branch)
|
1171
|
+
end
|
1172
|
+
else_body = node.else
|
1173
|
+
unless else_body.kind_of?(Rubinius::AST::NilLiteral)
|
1174
|
+
emit('else')
|
1175
|
+
nl
|
1176
|
+
body(else_body)
|
175
1177
|
end
|
1178
|
+
kend
|
176
1179
|
end
|
177
1180
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
1181
|
+
# Emit when
|
1182
|
+
#
|
1183
|
+
# @param [Rubinius::AST::Node] node
|
1184
|
+
#
|
1185
|
+
# @return [undefined]
|
1186
|
+
#
|
1187
|
+
# @api private
|
1188
|
+
#
|
1189
|
+
def when(node)
|
1190
|
+
emit('when ')
|
1191
|
+
if node.single
|
1192
|
+
dispatch(node.single)
|
1193
|
+
end
|
1194
|
+
if node.conditions
|
1195
|
+
array_body(node.conditions.body)
|
183
1196
|
end
|
1197
|
+
if node.splat
|
1198
|
+
dispatch(node.splat)
|
1199
|
+
end
|
1200
|
+
nl
|
1201
|
+
body(node.body)
|
1202
|
+
end
|
1203
|
+
|
1204
|
+
# Emit splat when
|
1205
|
+
#
|
1206
|
+
# @param [Rubinius::AST::Node] node
|
1207
|
+
#
|
1208
|
+
# @return [undefined]
|
1209
|
+
#
|
1210
|
+
# @api private
|
1211
|
+
#
|
1212
|
+
def splat_when(node)
|
1213
|
+
emit('*')
|
1214
|
+
dispatch(node.condition)
|
184
1215
|
end
|
185
1216
|
|
186
|
-
|
1217
|
+
# Emit splat value
|
1218
|
+
#
|
1219
|
+
# @param [Rubinius::AST::Node] node
|
1220
|
+
#
|
1221
|
+
# @return [undefined]
|
1222
|
+
#
|
1223
|
+
# @api private
|
1224
|
+
#
|
1225
|
+
def splat_value(node)
|
1226
|
+
emit('*')
|
1227
|
+
dispatch(node.value)
|
1228
|
+
end
|
1229
|
+
|
1230
|
+
# Emit acutal arguments
|
1231
|
+
#
|
1232
|
+
# @param [Rubinius::AST::Node] node
|
1233
|
+
#
|
1234
|
+
# @return [undefined]
|
1235
|
+
#
|
1236
|
+
# @api private
|
1237
|
+
#
|
1238
|
+
def actual_arguments(node)
|
1239
|
+
array_body(node.array)
|
1240
|
+
end
|
1241
|
+
|
1242
|
+
# Emit iteration
|
1243
|
+
#
|
1244
|
+
# @param [Rubinius::AST::Node] node
|
1245
|
+
#
|
1246
|
+
# @return [undefined]
|
1247
|
+
#
|
1248
|
+
# @api private
|
1249
|
+
#
|
1250
|
+
def iter(node)
|
1251
|
+
emit(' do')
|
1252
|
+
|
1253
|
+
arguments = node.arguments
|
1254
|
+
unless arguments.names.empty?
|
1255
|
+
emit(' ')
|
1256
|
+
iter_arguments(node.arguments)
|
1257
|
+
end
|
1258
|
+
|
1259
|
+
nl
|
1260
|
+
body(node.body)
|
1261
|
+
|
1262
|
+
kend
|
1263
|
+
end
|
1264
|
+
|
1265
|
+
# Emit iteration arguments for ruby18 mode
|
1266
|
+
#
|
1267
|
+
# @param [Rubinius::AST::Node] node
|
1268
|
+
#
|
1269
|
+
# @return [undefined]
|
1270
|
+
#
|
1271
|
+
# @api private
|
1272
|
+
#
|
1273
|
+
def iter_arguments(node)
|
187
1274
|
body = if node.prelude == :single
|
188
1275
|
Array(node.arguments.name)
|
189
1276
|
else
|
@@ -198,180 +1285,463 @@ module ToSource
|
|
198
1285
|
emit '|'
|
199
1286
|
end
|
200
1287
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
1288
|
+
# Emit iteration arguments for ruby19 mode
|
1289
|
+
#
|
1290
|
+
# @param [Rubinius::AST::Node] node
|
1291
|
+
#
|
1292
|
+
# @return [undefined]
|
1293
|
+
#
|
1294
|
+
# @api private
|
1295
|
+
#
|
1296
|
+
def iter19(node)
|
1297
|
+
emit(' do')
|
1298
|
+
|
1299
|
+
arguments = node.arguments
|
1300
|
+
unless arguments.names.empty?
|
1301
|
+
emit(' ')
|
1302
|
+
formal_arguments_generic(node.arguments,'|','|')
|
207
1303
|
end
|
208
1304
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
if node.body.is_a?(Rubinius::AST::Block)
|
213
|
-
node.body.lazy_visit self, parent, true
|
214
|
-
else
|
215
|
-
emit current_indentation
|
216
|
-
node.body.lazy_visit self, parent
|
217
|
-
end
|
1305
|
+
nl
|
1306
|
+
body(node.body)
|
218
1307
|
|
219
|
-
|
220
|
-
emit 'end'
|
1308
|
+
kend
|
221
1309
|
end
|
222
1310
|
|
223
|
-
|
1311
|
+
# Emit block
|
1312
|
+
#
|
1313
|
+
# @param [Rubinius::AST::Node] node
|
1314
|
+
#
|
1315
|
+
# @return [undefined]
|
1316
|
+
#
|
1317
|
+
# @api private
|
1318
|
+
#
|
1319
|
+
def block(node)
|
224
1320
|
body = node.array
|
225
|
-
body.each_with_index do |expression,
|
226
|
-
emit
|
227
|
-
expression
|
228
|
-
|
1321
|
+
body.each_with_index do |expression,index|
|
1322
|
+
emit(current_indentation)
|
1323
|
+
dispatch(expression)
|
1324
|
+
nl unless body.length == index+1
|
229
1325
|
end
|
230
1326
|
end
|
231
1327
|
|
232
|
-
|
233
|
-
|
234
|
-
|
1328
|
+
# Emit not
|
1329
|
+
#
|
1330
|
+
# @param [Rubinius::AST::Node] node
|
1331
|
+
#
|
1332
|
+
# @return [undefined]
|
1333
|
+
#
|
1334
|
+
# @api private
|
1335
|
+
#
|
1336
|
+
def not(node)
|
1337
|
+
emit('!')
|
1338
|
+
dispatch(node.value)
|
235
1339
|
end
|
236
1340
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
1341
|
+
# Emit and
|
1342
|
+
#
|
1343
|
+
# @param [Rubinius::AST::Node] node
|
1344
|
+
#
|
1345
|
+
# @return [undefined]
|
1346
|
+
#
|
1347
|
+
# @api private
|
1348
|
+
#
|
1349
|
+
def and(node)
|
1350
|
+
dispatch(node.left)
|
1351
|
+
emit(' && ')
|
1352
|
+
dispatch(node.right)
|
241
1353
|
end
|
242
1354
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
1355
|
+
# Emit or
|
1356
|
+
#
|
1357
|
+
# @param [Rubinius::AST::Node] node
|
1358
|
+
#
|
1359
|
+
# @return [undefined]
|
1360
|
+
#
|
1361
|
+
# @api private
|
1362
|
+
#
|
1363
|
+
def or(node)
|
1364
|
+
dispatch(node.left)
|
1365
|
+
emit(' || ')
|
1366
|
+
dispatch(node.right)
|
247
1367
|
end
|
248
1368
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
1369
|
+
# Emit and operation with assignment
|
1370
|
+
#
|
1371
|
+
# @param [Rubinius::AST::Node] node
|
1372
|
+
#
|
1373
|
+
# @return [undefined]
|
1374
|
+
#
|
1375
|
+
# @api private
|
1376
|
+
#
|
1377
|
+
def op_assign_and(node)
|
1378
|
+
dispatch(node.left)
|
1379
|
+
emit(' && ')
|
1380
|
+
dispatch(node.right)
|
253
1381
|
end
|
254
1382
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
1383
|
+
# Emit or operation with assignment
|
1384
|
+
#
|
1385
|
+
# @param [Rubinius::AST::Node] node
|
1386
|
+
#
|
1387
|
+
# @return [undefined]
|
1388
|
+
#
|
1389
|
+
# @api private
|
1390
|
+
#
|
1391
|
+
def op_assign_or(node)
|
1392
|
+
dispatch(node.left)
|
1393
|
+
emit(' || ')
|
1394
|
+
dispatch(node.right)
|
259
1395
|
end
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
1396
|
+
alias_method :op_assign_or19, :op_assign_or
|
1397
|
+
|
1398
|
+
# Emit toplevel constant
|
1399
|
+
#
|
1400
|
+
# @param [Rubinius::AST::Node] node
|
1401
|
+
#
|
1402
|
+
# @return [undefined]
|
1403
|
+
#
|
1404
|
+
# @api private
|
1405
|
+
#
|
1406
|
+
def toplevel_constant(node)
|
1407
|
+
emit('::')
|
1408
|
+
emit(node.name)
|
264
1409
|
end
|
265
1410
|
|
266
|
-
|
267
|
-
|
1411
|
+
# Emit constant accesws
|
1412
|
+
#
|
1413
|
+
# @param [Rubinius::AST::Node] node
|
1414
|
+
#
|
1415
|
+
# @return [undefined]
|
1416
|
+
#
|
1417
|
+
# @api private
|
1418
|
+
#
|
1419
|
+
def constant_access(node)
|
1420
|
+
emit(node.name)
|
268
1421
|
end
|
269
1422
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
1423
|
+
# Emit scoped constant
|
1424
|
+
#
|
1425
|
+
# @param [Rubinius::AST::Node] node
|
1426
|
+
#
|
1427
|
+
# @return [undefined]
|
1428
|
+
#
|
1429
|
+
# @api private
|
1430
|
+
#
|
1431
|
+
def scoped_constant(node)
|
1432
|
+
dispatch(node.parent)
|
1433
|
+
emit('::')
|
1434
|
+
emit(node.name)
|
1435
|
+
end
|
1436
|
+
alias_method :scoped_class_name, :scoped_constant
|
1437
|
+
alias_method :scoped_module_name, :scoped_constant
|
1438
|
+
|
1439
|
+
# Emit toplevel class name
|
1440
|
+
#
|
1441
|
+
# @param [Rubinius::AST::Node] node
|
1442
|
+
#
|
1443
|
+
# @return [undefined]
|
1444
|
+
#
|
1445
|
+
# @api private
|
1446
|
+
#
|
1447
|
+
def toplevel_class_name(node)
|
1448
|
+
emit("::#{node.name}")
|
274
1449
|
end
|
275
1450
|
|
276
|
-
|
1451
|
+
# Emit if expression
|
1452
|
+
#
|
1453
|
+
# @param [Rubinius::AST::Node] node
|
1454
|
+
#
|
1455
|
+
# @return [undefined]
|
1456
|
+
#
|
1457
|
+
# @api private
|
1458
|
+
#
|
1459
|
+
def if(node)
|
277
1460
|
body, else_body = node.body, node.else
|
1461
|
+
|
278
1462
|
keyword = 'if'
|
279
1463
|
|
280
1464
|
if node.body.is_a?(Rubinius::AST::NilLiteral) && !node.else.is_a?(Rubinius::AST::NilLiteral)
|
281
|
-
|
282
1465
|
body, else_body = else_body, body
|
283
1466
|
keyword = 'unless'
|
284
1467
|
end
|
285
1468
|
|
286
|
-
emit
|
287
|
-
|
288
|
-
|
1469
|
+
emit(keyword)
|
1470
|
+
emit(' ')
|
1471
|
+
dispatch(node.condition)
|
1472
|
+
nl
|
289
1473
|
|
290
|
-
|
291
|
-
|
292
|
-
if body.is_a?(Rubinius::AST::Block)
|
293
|
-
body.lazy_visit self, parent, true
|
294
|
-
else
|
295
|
-
emit current_indentation
|
296
|
-
body.lazy_visit self, parent
|
297
|
-
end
|
298
|
-
|
299
|
-
emit "\n"
|
1474
|
+
body(body)
|
300
1475
|
|
301
1476
|
if else_body.is_a?(Rubinius::AST::NilLiteral)
|
302
|
-
|
1477
|
+
kend
|
303
1478
|
return
|
304
1479
|
end
|
305
1480
|
|
306
|
-
emit
|
1481
|
+
emit('else')
|
1482
|
+
nl
|
307
1483
|
|
308
|
-
|
309
|
-
else_body.lazy_visit self, parent, true
|
310
|
-
else
|
311
|
-
emit current_indentation
|
312
|
-
else_body.lazy_visit self, parent
|
313
|
-
end
|
1484
|
+
body(else_body)
|
314
1485
|
|
315
|
-
|
316
|
-
emit 'end'
|
1486
|
+
kend
|
317
1487
|
end
|
318
1488
|
|
319
|
-
|
1489
|
+
# Dispatch node
|
1490
|
+
#
|
1491
|
+
# @param [Rubinius::AST::Node] node
|
1492
|
+
#
|
1493
|
+
# @return [undefined]
|
1494
|
+
#
|
1495
|
+
# @api private
|
1496
|
+
#
|
1497
|
+
def while(node)
|
320
1498
|
emit 'while '
|
321
|
-
node.condition
|
322
|
-
|
1499
|
+
dispatch(node.condition)
|
1500
|
+
nl
|
323
1501
|
|
324
|
-
|
1502
|
+
body(node.body)
|
325
1503
|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
1504
|
+
kend
|
1505
|
+
end
|
1506
|
+
|
1507
|
+
# Emit until
|
1508
|
+
#
|
1509
|
+
# @param [Rubinius::AST::Node] node
|
1510
|
+
#
|
1511
|
+
# @return [undefined]
|
1512
|
+
#
|
1513
|
+
# @api private
|
1514
|
+
#
|
1515
|
+
def until(node)
|
1516
|
+
emit 'until '
|
1517
|
+
dispatch(node.condition)
|
1518
|
+
nl
|
1519
|
+
|
1520
|
+
body(node.body)
|
1521
|
+
|
1522
|
+
kend
|
1523
|
+
end
|
1524
|
+
|
1525
|
+
# Emit formal arguments as shared between ruby18 and ruby19 mode
|
1526
|
+
#
|
1527
|
+
# @param [Rubinius::AST::Node] node
|
1528
|
+
#
|
1529
|
+
# @return [undefined]
|
1530
|
+
#
|
1531
|
+
# @api private
|
1532
|
+
#
|
1533
|
+
def formal_arguments_generic(node,open,close)
|
1534
|
+
return if node.names.empty?
|
1535
|
+
required, defaults, splat = node.required, node.defaults, node.splat
|
1536
|
+
|
1537
|
+
emit(open)
|
1538
|
+
emit(required.join(', '))
|
1539
|
+
|
1540
|
+
empty = required.empty?
|
1541
|
+
|
1542
|
+
if defaults
|
1543
|
+
emit(', ') unless empty
|
1544
|
+
dispatch(node.defaults)
|
1545
|
+
end
|
1546
|
+
|
1547
|
+
if splat
|
1548
|
+
emit(', ') unless empty
|
1549
|
+
emit('*')
|
1550
|
+
unless splat == :@unnamed_splat
|
1551
|
+
emit(splat)
|
1552
|
+
end
|
331
1553
|
end
|
332
1554
|
|
333
|
-
|
334
|
-
|
1555
|
+
if node.block_arg
|
1556
|
+
emit(', ') unless empty
|
1557
|
+
|
1558
|
+
dispatch(node.block_arg)
|
1559
|
+
end
|
1560
|
+
|
1561
|
+
emit(close)
|
335
1562
|
end
|
336
1563
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
1564
|
+
# Emit formal arguments for ruby19 and ruby18
|
1565
|
+
#
|
1566
|
+
# @param [Rubinius::AST::Node] node
|
1567
|
+
#
|
1568
|
+
# @return [undefined]
|
1569
|
+
#
|
1570
|
+
# @api private
|
1571
|
+
#
|
1572
|
+
def formal_arguments(node)
|
1573
|
+
formal_arguments_generic(node,'(',')')
|
1574
|
+
end
|
1575
|
+
alias_method :formal_arguments19, :formal_arguments
|
1576
|
+
|
1577
|
+
# Emit block argument
|
1578
|
+
#
|
1579
|
+
# @param [Rubinius::AST::Node] node
|
1580
|
+
#
|
1581
|
+
# @return [undefined]
|
1582
|
+
#
|
1583
|
+
# @api private
|
1584
|
+
#
|
1585
|
+
def block_argument(node)
|
1586
|
+
emit('&')
|
1587
|
+
emit(node.name)
|
1588
|
+
end
|
341
1589
|
|
342
|
-
|
1590
|
+
# Emit default arguments
|
1591
|
+
#
|
1592
|
+
# @param [Rubinius::AST::Node] node
|
1593
|
+
#
|
1594
|
+
# @return [undefined]
|
1595
|
+
#
|
1596
|
+
# @api private
|
1597
|
+
#
|
1598
|
+
def default_arguments(node)
|
1599
|
+
last = node.arguments.length - 1
|
1600
|
+
node.arguments.each_with_index do |argument, index|
|
1601
|
+
dispatch(argument)
|
1602
|
+
emit(',') unless index == last
|
1603
|
+
end
|
1604
|
+
end
|
343
1605
|
|
344
|
-
|
345
|
-
|
1606
|
+
# Emit begin
|
1607
|
+
#
|
1608
|
+
# @param [Rubinius::AST::Node] node
|
1609
|
+
#
|
1610
|
+
# @return [undefined]
|
1611
|
+
#
|
1612
|
+
# @api private
|
1613
|
+
#
|
1614
|
+
def begin(node)
|
1615
|
+
emit('begin')
|
1616
|
+
nl
|
1617
|
+
|
1618
|
+
body = node.rescue
|
1619
|
+
case body
|
1620
|
+
when Rubinius::AST::Rescue
|
1621
|
+
# Rescue is reserved keyword
|
1622
|
+
__send__(:rescue,body)
|
1623
|
+
when Rubinius::AST::Ensure
|
1624
|
+
# Ensure is reserved keyword
|
1625
|
+
__send__(:ensure,body)
|
346
1626
|
else
|
347
|
-
|
348
|
-
node.body.lazy_visit self, parent
|
1627
|
+
body(node.rescue)
|
349
1628
|
end
|
350
1629
|
|
351
|
-
|
352
|
-
emit "end"
|
1630
|
+
kend
|
353
1631
|
end
|
354
1632
|
|
355
|
-
|
356
|
-
|
357
|
-
|
1633
|
+
# Emit define on instances
|
1634
|
+
#
|
1635
|
+
# @param [Rubinius::AST::Node] node
|
1636
|
+
#
|
1637
|
+
# @return [undefined]
|
1638
|
+
#
|
1639
|
+
# @api private
|
1640
|
+
#
|
1641
|
+
def define(node)
|
1642
|
+
emit('def ')
|
1643
|
+
|
1644
|
+
emit(node.name)
|
1645
|
+
dispatch(node.arguments)
|
1646
|
+
nl
|
1647
|
+
|
1648
|
+
body(node.body)
|
1649
|
+
kend
|
358
1650
|
end
|
359
1651
|
|
360
|
-
|
1652
|
+
# Emit define on singletons
|
1653
|
+
#
|
1654
|
+
# @param [Rubinius::AST::Node] node
|
1655
|
+
#
|
1656
|
+
# @return [undefined]
|
1657
|
+
#
|
1658
|
+
# @api private
|
1659
|
+
#
|
1660
|
+
def define_singleton(node)
|
1661
|
+
emit('def ')
|
1662
|
+
dispatch(node.receiver)
|
1663
|
+
emit('.')
|
1664
|
+
dispatch(node.body)
|
1665
|
+
end
|
361
1666
|
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
1667
|
+
# Emit singleton scope
|
1668
|
+
#
|
1669
|
+
# @param [Rubinius::AST::Node] node
|
1670
|
+
#
|
1671
|
+
# @return [undefined]
|
1672
|
+
#
|
1673
|
+
# @api private
|
1674
|
+
#
|
1675
|
+
def define_singleton_scope(node)
|
1676
|
+
emit(node.name)
|
1677
|
+
dispatch(node.arguments)
|
1678
|
+
nl
|
1679
|
+
|
1680
|
+
body(node.body)
|
1681
|
+
|
1682
|
+
kend
|
1683
|
+
end
|
366
1684
|
|
367
|
-
|
1685
|
+
# Emit block pass
|
1686
|
+
#
|
1687
|
+
# @param [Rubinius::AST::Node] node
|
1688
|
+
#
|
1689
|
+
# @return [undefined]
|
1690
|
+
#
|
1691
|
+
# @api private
|
1692
|
+
#
|
1693
|
+
def block_pass(node)
|
1694
|
+
emit('&')
|
1695
|
+
dispatch(node.body)
|
1696
|
+
end
|
368
1697
|
|
369
|
-
|
370
|
-
|
1698
|
+
# Emit return statement
|
1699
|
+
#
|
1700
|
+
# @param [Rubinius::AST::Node] node
|
1701
|
+
#
|
1702
|
+
# @return [undefined]
|
1703
|
+
#
|
1704
|
+
# @api private
|
1705
|
+
#
|
1706
|
+
def return(node)
|
1707
|
+
emit('return')
|
1708
|
+
if node.value
|
1709
|
+
emit(' ')
|
1710
|
+
dispatch(node.value)
|
371
1711
|
end
|
1712
|
+
end
|
1713
|
+
|
1714
|
+
OPERATORS = %w(
|
1715
|
+
+ - * / & | && || << >> ==
|
1716
|
+
=== != <= < <=> > >= =~ !~ ^
|
1717
|
+
**
|
1718
|
+
).map(&:to_sym).to_set
|
1719
|
+
|
1720
|
+
# Process binary operator
|
1721
|
+
#
|
1722
|
+
# @param [Rubinius::AST::Node] node
|
1723
|
+
#
|
1724
|
+
# @return [self]
|
1725
|
+
# if node was handled
|
1726
|
+
#
|
1727
|
+
# @return [nil]
|
1728
|
+
# otherwise
|
1729
|
+
#
|
1730
|
+
# @api private
|
1731
|
+
#
|
1732
|
+
def process_binary_operator(node)
|
1733
|
+
name = node.name
|
1734
|
+
return unless OPERATORS.include?(name)
|
1735
|
+
return if node.arguments.array.length != 1
|
1736
|
+
|
1737
|
+
operand = node.arguments.array[0]
|
1738
|
+
|
1739
|
+
dispatch(node.receiver)
|
1740
|
+
|
1741
|
+
emit(" #{name.to_s} ")
|
1742
|
+
dispatch(operand)
|
372
1743
|
|
373
|
-
|
374
|
-
operand.lazy_visit self, node
|
1744
|
+
self
|
375
1745
|
end
|
376
1746
|
end
|
377
1747
|
end
|