endlessruby 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -13,62 +13,49 @@ module Kernel
13
13
  # pathが./または/で以外で始まる場合は$LOAD_PATHと$:をそれぞれ参照してpathを探します。
14
14
  # もしpathがそれらで始まる場合はそれぞれ参照しません。(つまり通常のrequireの動作と同じです)
15
15
  def require path
16
- at = caller
17
16
  endlessruby_original_require path
18
17
  rescue SyntaxError, LoadError
19
- case path
20
- when /^\.\/.*?$/, /^\/.*?$/
21
- unless File.exist? path
22
- if File.exist? "#{path}.er"
23
- path = "#{path}.er"
18
+
19
+ load = lambda do |path, abspath|
20
+
21
+ if !File.exist?(abspath) || File.directory?(abspath)
22
+ if File.exist? "#{abspath}.er"
23
+ abspath = "#{abspath}.er"
24
24
  else
25
- $@ = at
26
25
  raise LoadError, "no such file to load -- #{path}"
27
26
  end
28
27
  end
29
28
 
30
- if File.directory? path
31
- $@ = at
29
+ return false if $".include? abspath
30
+
31
+ if File.directory? abspath
32
32
  raise LoadError, "Is a directory - #{path}"
33
33
  end
34
34
 
35
- open(path) do |file|
36
- begin
37
- EndlessRuby.ereval file.read, TOPLEVEL_BINDING, path
38
- rescue Exception => e
39
- $@ = at
40
- raise e
41
- end
35
+ open(abspath) do |file|
36
+ EndlessRuby.ereval file.read, TOPLEVEL_BINDING, abspath
37
+ $" << abspath
42
38
  return true
43
39
  end
40
+ end
41
+
42
+ case path
43
+ when /^\~(.*?)$/
44
+ load.call path, File.join(ENV['HOME'], $1)
45
+ when /^\.\/.*?$/, /^\/.*?$/
46
+ load.call path, path
44
47
  else
45
48
  is_that_dir = false
46
- ($LOAD_PATH | $:).each do |load_path|
47
- real_path = File.join load_path, path
48
- unless File.exist? real_path
49
- if File.exist? "#{real_path}.er"
50
- real_path = "#{real_path}.er"
51
- else
52
- next
53
- end
54
- end
55
-
56
- next is_that_dir = true if File.directory? real_path
57
- open(real_path) do |file|
58
- begin
59
- EndlessRuby.ereval file.read, TOPLEVEL_BINDING, real_path
60
- rescue Exception => e
61
- $@ = at
62
- raise e
63
- end
49
+ $:.each do |load_path|
50
+ abspath = File.join load_path, path
51
+ begin
52
+ return load.call path, abspath
53
+ rescue SyntaxError => e
54
+ $stderr.puts "*ENDLESSRUBY BUG*"
55
+ raise e
56
+ rescue LoadError => e
57
+ raise e if load_path == $:.last
64
58
  end
65
- return true
66
- end
67
- $@ = at
68
- if is_that_dir
69
- raise LoadError, "Is a directory - #{path}"
70
- else
71
- raise LoadError, "no such file to load -- #{path}"
72
59
  end
73
60
  end
74
61
  end
@@ -9,23 +9,14 @@ module EndlessRuby::Main
9
9
 
10
10
  # er ファイルから読み込みそれをピュアなRubyにコンパイルしてrbに書き出します
11
11
  def compile er, rb
12
- open(er) do |erfile|
13
- open(rb, "w") do |rbfile|
14
- rbfile.write ER2PR(erfile.read)
15
- end
16
- end
12
+ ER2PR({ :in => { :any => er }, :out => { :any => rb } })
17
13
  end
18
14
 
19
15
  # rbファイルを読み込みそれからすべてのendを取り除きます。
20
16
  def decompile rb, er
21
- open(rb) do |rbfile|
22
- open(er, "w") do |erfile|
23
- erfile.write PR2ER(rbfile.read)
24
- end
25
- end
17
+ PR2ER({ :in => { :any => rb }, :out => { :any => er } })
26
18
  end
27
19
 
28
-
29
20
  # EndlessRuby::Main.main と同じ動作をします。このモジュールをincludeした場合に使用します。
30
21
  def endlessruby argv
31
22
  EndlessRuby::Main.main argv
@@ -48,19 +39,22 @@ module EndlessRuby::Main
48
39
  }
49
40
 
50
41
  parser = OptionParser.new do |opts|
51
- opts.on '-o OUT' do |out|
42
+
43
+ opts.version = EndlessRuby::VERSION
44
+
45
+ opts.on '-o OUT', 'appoint output directory.' do |out|
52
46
  options[:out] = out
53
47
  end
54
48
 
55
- opts.on '-c', '--compile' do |c|
49
+ opts.on '-c', '--compile', 'compile endlessruby source code to pure ruby' do |c|
56
50
  options[:compile] = true
57
51
  end
58
52
 
59
- opts.on '-d', '--decompile' do |d|
53
+ opts.on '-d', '--decompile', 'decompile pure ruby source code to endless ruby' do |d|
60
54
  options[:decompile] = true
61
55
  end
62
56
 
63
- opts.on '-r' do |r|
57
+ opts.on '-r', 'unimplemented' do |r|
64
58
  options[:recursive] = true
65
59
  end
66
60
  end
@@ -12,8 +12,8 @@ describe EndlessRuby, "must can compile self" do
12
12
  "#{lib}/endlessruby.rb",
13
13
  "#{src}/endlessruby/main.er",
14
14
  "#{lib}/endlessruby/main.rb",
15
- "#{src}/endlessruby/extensions.er",
16
- "#{lib}/endlessruby/extensions.rb",
15
+ "#{src}/endlessruby/custom_require.er",
16
+ "#{lib}/endlessruby/custom_require.rb",
17
17
  "#{src}/er.er",
18
18
  "#{bin}/endlessruby",
19
19
  ]
@@ -8,3 +8,5 @@ require "require_spec"
8
8
  require "build_self_spec"
9
9
  require "concrete_examples_spec"
10
10
  require "semicolon_spec"
11
+ require "block_expr_spec"
12
+ require "use_end_case_spec"
data/spec/require_spec.rb CHANGED
@@ -26,4 +26,12 @@ describe "require" do
26
26
  TestData.test_data.should == "ruby script"
27
27
  end
28
28
 
29
+ it "require ellipsis of 'er' and exist same name directory" do
30
+
31
+ require 'test_data/exist_same_name_directory'
32
+
33
+ $test_data.should == "exist same name directory"
34
+ TestData.test_data.should == "exist same name directory"
35
+ end
36
+
29
37
  end
@@ -7,8 +7,17 @@ describe "split with semicolon lines is inner lines" do
7
7
  def method; statements; end
8
8
  DEFINE
9
9
  <<DEFINE.chomp!
10
- def method
11
- statements
10
+ def method; statements; end
11
+ DEFINE
12
+
13
+ end
14
+
15
+ it "example" do
16
+ ER2RB(<<DEFINE).should ==
17
+ def method; statements
18
+ DEFINE
19
+ <<DEFINE.chomp!
20
+ def method; statements
12
21
  end
13
22
  DEFINE
14
23
 
data/spec/simply_spec.rb CHANGED
@@ -461,6 +461,22 @@ DEFINE
461
461
 
462
462
  end
463
463
 
464
+ describe "for expression case" do
465
+
466
+ it "for" do
467
+ ER2RB(<<DEFINE).should ==
468
+ for i in enu
469
+ pass
470
+ DEFINE
471
+ <<DEFINE.chomp!
472
+ for i in enu
473
+ pass
474
+ end
475
+ DEFINE
476
+ end
477
+
478
+ end
479
+
464
480
  describe "exception expression case" do
465
481
 
466
482
  it "try only" do
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe "use end case" do
4
+
5
+ it "example" do
6
+ ER2RB(<<DEFINE).should ==
7
+ def m
8
+ if true
9
+ case a
10
+ when b then 1
11
+ end
12
+ else
13
+ end
14
+ DEFINE
15
+ <<DEFINE.chomp!
16
+ def m
17
+ if true
18
+ case a
19
+ when b then 1
20
+ end
21
+ else
22
+ end
23
+ end
24
+ DEFINE
25
+
26
+ end
27
+ end
data/src/endlessruby.er CHANGED
@@ -4,7 +4,9 @@
4
4
  $:.unshift(File.dirname(__FILE__)) unless
5
5
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
6
6
 
7
- require 'endlessruby/extensions'
7
+ require 'endlessruby/custom_require'
8
+ require "tempfile"
9
+ require "irb"
8
10
 
9
11
  # EndlessRubyはRubyをendを取り除いて書けます。
10
12
  #
@@ -34,179 +36,243 @@ require 'endlessruby/extensions'
34
36
  module EndlessRuby
35
37
 
36
38
  # EndlessRuby のバージョンです
37
- VERSION = "0.0.1"
39
+ VERSION = "0.1.0"
38
40
 
39
41
  extend self
40
42
 
41
- private
42
-
43
- # 内部で使用します。空業かどうか判定します。
44
- def blank_line? line
45
- return true unless line
46
- (line.chomp.gsub /\s+?/, '') == ""
47
-
48
- # 内部で使用します。インデントを取り除きます
49
- def unindent line
50
- line =~ /^\s*?(\S.*?)$/
51
- $1
52
- # 内部で使用します。インデントします
53
- def indent line, level, indent=" "
54
- "#{indent * level}#{line}"
55
-
56
- # 内部で使用します。インデントの数を数えます。
57
- def indent_count line, indent=" "
58
- return 0 unless line
59
- if line =~ /^#{indent}(.*?)$/
60
- 1 + (indent_count $1, indent)
61
- else
62
- 0
63
-
64
- # 内部で使用します。ブロックを作るキーワード群です。
65
- BLOCK_KEYWORDS = [
66
- [/^if(:?\s|\().*?$/, /^elsif(:?\s|\().*?$/, /^else(?:$|\s+)/],
67
- [/^unless(:?\s|\().*?$/, /^elsif(:?\s|\().*?$/, /^else(?:$|\s+)/],
68
- [/^while(:?\s|\().*?$/],
69
- [/^until(:?\s|\().*?$/],
70
- [/^case(:?\s|\().*?$/, /^when(:?\s|\().*?$/, /^else(?:$|\s+)/],
71
- [/^def\s.*?$/, /^rescue(:?$|\s|\().*?$/, /^else(?:$|\s+)/, /^ensure(?:$|\s+)/],
72
- [/^class\s.*?$/],
73
- [/^module\s.*?$/],
74
- [/^begin(?:$|\s+)/, /^rescue(:?$|\s|\().*?$/, /^else(?:$|\s+)/, /^ensure(?:$|\s+)/],
75
- [/^.*?\s+do(:?$|\s|\|)/]
76
- ]
77
-
78
43
  public
79
44
 
80
45
  # 文字列をEndlessRubyの構文として実行します。引数の意味はKernel#evalと同じです
81
46
  def ereval(src, binding=TOPLEVEL_BINDING, filename=__FILE__, lineno=1)
82
- at = caller
83
47
  eval(ER2PR(src), binding, filename, lineno)
84
- rescue Exception => e
85
- $@ = at
86
- raise e
87
48
 
88
- # Rubyの構文をEndlessRubyの構文に変換します。
89
- def pure_ruby_to_endless_ruby src
90
- @decompile = true
91
- s = ER2RB(src)
92
- @decompile = nil
93
- s
49
+ # EndlessRubyの構文をピュアなRubyの構文に変換します。<br />
50
+ # options: オプションを表すHashまたはto_hashを実装したオブジェクト、構文を読み出すIOまたはto_ioを実装したオブジェクト、EndlessRubyの構文を表すStringまたはto_strを実装したオブジェクト、またはファイルのパス<br />
51
+ # optionsが文字列ならばそれをピュアなRubyの構文にします。それがIOならばIOから読み出してそれをピュアなRubyの構文にします。<br />
52
+ # ファイルのパスならばそのファイルかあ読み込みます
53
+ # それがHashならばそれはオプションです。それぞれHashを指定します。<br />
54
+ # options: {
55
+ # in: {
56
+ # io: optionsにIOを指定した場合と同じです
57
+ # any: それが存在するファイルのパスを表す文字列ならばそのファイルから読み出します。この場合のanyはoptionsにそのような文字列を指定するのと同じ意味です。
58
+ # そうでない文字列ならばそれ自体をEndlessRubyの構文として読み出します。この場合のanyはoptionsに文字列を指定するのと同じ意味です。
59
+ # それがIOならばそのIOから読み出します。この場合のany はin.ioを直接指定するのと同じです。
60
+ # }
61
+ # out: {
62
+ # io: このIOに結果を書き出します。
63
+ # any: ファイルのパスかIOです。ファイルのパスならばそのファイルに書き出します。IOならばそのIOに書き出します。
64
+ # }
65
+ # decompile: trueならばコンパイルではなくてでコンパイルします。
66
+ # }
67
+ #
68
+ # opts[:out][:io] には書き出すioを指定します。<br />
69
+ # from a file on disk:<br />
70
+ # EndlessRuby.ER2RB("filename.er")
71
+ # <br />
72
+ # from string that is source code:<br />
73
+ # EndlessRuby.ER2RB(<<DEFINE)
74
+ # # endlessruby syntax
75
+ # DEFINE
76
+ # <br />
77
+ # from IO:<br />
78
+ # file = open 'filename.er'
79
+ # EndlessRuby.ER2RB(file)
80
+ #
81
+ # appoint input file and output file:
82
+ # ER2PR({ :in => { :any => 'filename.er' }, :out => { :any => 'filename.rb' } })
83
+ # ER2PR({ :in => { :io => in_io }, :out => { :io => out_io } })
84
+ def endless_ruby_to_pure_ruby options
85
+ converting_helper options
86
+
87
+ alias to_pure_ruby endless_ruby_to_pure_ruby
88
+ alias ER2PR endless_ruby_to_pure_ruby
89
+ alias ER2RB endless_ruby_to_pure_ruby
94
90
 
91
+ # Rubyの構文をEndlessRubyの構文に変換します。optionsはendlessruby_to_pure_rubyと同じです。
92
+ def pure_ruby_to_endless_ruby options
93
+ options = merge_options options
94
+ options[:decompile] = true
95
+ converting_helper options
95
96
 
96
97
  alias RB2ER pure_ruby_to_endless_ruby
97
98
  alias PR2ER pure_ruby_to_endless_ruby
98
99
 
99
- # EndlessRubyの構文をピュアなRubyの構文に変換します。
100
- def endless_ruby_to_pure_ruby src
101
- endless = src.split "\n"
102
-
103
- pure = []
104
- i = 0
105
- while i < endless.length
106
- pure << (currently_line = endless[i])
107
-
108
- if currently_line =~ /(.*)(?:^|(?:(?!\\).))\#(?!\{).*$/
109
- currently_line = $1
110
-
111
- if blank_line? currently_line
112
- i += 1
113
- next
114
-
115
- # ブロックを作らない構文なら単に無視する
116
- next i += 1 unless BLOCK_KEYWORDS.any? { |k| k[0] =~ unindent(currently_line) }
117
-
118
- # ブロックに入る
119
- keyword = BLOCK_KEYWORDS.each { |k| break k if k[0] =~ unindent(currently_line) }
120
-
121
- currently_indent_depth = indent_count currently_line
122
- base_indent_depth = currently_indent_depth
123
-
124
- inner_statements = []
125
- # def method1
126
- # statemetns
127
- # # document of method2
128
- # def method2
129
- # statements
130
- # のような場合にコメントの部分はmethod1内に含まないようにする。
131
- # def method1
132
- # statemetns
133
- # # comment
134
- # return
135
- # のような場合と区別するため。
136
- comment_count = 0
137
- in_here_document = nil
138
- while i < endless.length
139
-
140
- inner_currently_line = endless[i + 1]
141
-
142
- if inner_currently_line =~ /(.*)(?:^|(?:(?!\\).))\#(?!\{).*$/
143
- if blank_line?($1) && currently_indent_depth >= indent_count(inner_currently_line)
144
- comment_count += 1
145
- inner_currently_line = $1
146
- elsif blank_line? inner_currently_line
147
- comment_count += 1
148
-
149
- if blank_line? inner_currently_line
150
- inner_statements << endless[i + 1]
151
- i += 1
152
- next
100
+ private
101
+
102
+ def merge_options options
103
+
104
+ opts = {
105
+ :in => {}, :out => {}
106
+ }
153
107
 
154
- just_after_indent_depth = indent_count inner_currently_line
108
+ if options.respond_to? :to_hash
109
+ opts = opts.merge options.to_hash
110
+ elsif options.respond_to?(:to_io) || options.respond_to?(:to_str)
111
+ opts[:in][:any] = options
112
+ else
113
+ raise ArgumentError, "options is IO, String, or Hash"
114
+
115
+ if opts[:in][:any]
116
+ if opts[:in][:any].respond_to?(:to_str) && File.exist?(opts[:in][:any].to_str) # from a file on the disk.
117
+ opts[:in] = {
118
+ :io => (in_io = open opts[:in][:any].to_str),
119
+ :ensure => proc { in_io.close }
120
+ }
121
+ elsif opts[:in][:any].respond_to? :to_io # from IO that can read source code.
122
+ opts[:in] = {
123
+ :io => options.to_io,
124
+ :ensure => proc {}
125
+ }
126
+ elsif opts[:in][:any].respond_to? :to_str # from String that is source code.
127
+ in_io = Tempfile.new "endlessruby from temp file"
128
+ in_io.write options.to_str
129
+ in_io.seek 0
130
+ opts[:in] = {
131
+ :io => in_io,
132
+ :ensure => proc { in_io.close }
133
+ }
134
+ else
135
+ raise ArgumentError, "options[:in][:any] is IO, String which is path, or String which is source code"
136
+
137
+ opts[:in][:any] = nil
138
+
139
+ if opts[:out][:any]
140
+ if opts[:out][:any].respond_to?(:to_str) # to a file on the disk.
141
+ opts[:out] = {
142
+ :io => (out_io = open opts[:out][:any].to_str, "w+"),
143
+ :ensure => proc { out_io.close }
144
+ }
145
+ elsif opts[:out][:any].respond_to? :to_io # to IO that can read source code.
146
+ opts[:out] = {
147
+ :io => options.to_io,
148
+ :ensure => proc {}
149
+ }
150
+ else
151
+ raise ArgumentError, "options[:out][:any] is IO, or String which is Path"
152
+ elsif !opts[:out][:io]
153
+ opts[:out] = { :io => (out_io = Tempfile.new("endlessruby pure temp file")), :ensure => proc { out_io.close } }
155
154
 
156
- # 次の行がendならば意図のあるものなのでendを持ちあ揚げない
157
- if inner_currently_line =~ /^\s*end(?!\w).*$/
158
- comment_count = 0
155
+ opts[:out][:any] = nil
156
+ opts
159
157
 
160
- if base_indent_depth < just_after_indent_depth
161
- comment_count = 0
158
+ def converting_helper options
159
+ opts = merge_options options
162
160
 
163
- if in_here_document
164
- if (in_here_document[0] == '' && inner_currently_line =~ /^#{in_here_document[1]}\s*$/) || # <<DEFINE case
165
- (in_here_document[0] == '-' && inner_currently_line =~ /^\s*#{in_here_document[1]}\s*$/) # <<-DEFINE case
166
- in_here_document = nil
167
- inner_statements << endless[i + 1]
168
- i += 1
169
- next
170
- else
171
- inner_statements << endless[i + 1]
172
- i += 1
173
- next
161
+ io = opts[:in][:io]
174
162
 
175
- if inner_currently_line =~ /^.*?\<\<(\-?)(\w+)(?!\w).*$/
176
- in_here_document = [$1, $2]
163
+ r = RubyLex.new
164
+ r.set_input io
165
+ r.skip_space = false
177
166
 
178
- if base_indent_depth > indent_count(inner_currently_line)
179
- break
167
+ pure = opts[:out][:io]
180
168
 
181
- if base_indent_depth == indent_count(inner_currently_line)
182
- unless keyword[1..-1].any? { |k| k =~ unindent(inner_currently_line) }
183
- break
169
+ indent = []
170
+ pass = []
171
+ bol = true
172
+ last = [0, 0]
173
+ bol_indent = 0
174
+
175
+ while t = r.token
184
176
 
185
- inner_statements << endless[i + 1]
186
- i += 1
177
+ if bol && !(RubyToken::TkSPACE === t) && !(RubyToken::TkNL === t)
187
178
 
188
- # endをコメントより上の行へ持ち上げる
189
- if 0 < comment_count
190
- comment_count.times do
191
- inner_statements.pop
192
- i -= comment_count
179
+ bol_indent = this_indent = t.char_no
180
+ while (indent.last && pass.last) && ((this_indent < indent.last) || (this_indent <= indent.last && !pass.last.include?(t.class)))
181
+ if RubyToken::TkEND === t && this_indent == indent.last
182
+ break
193
183
 
194
- pure += ER2PR(inner_statements.join("\n")).split "\n"
195
- # 次の行がendならばendを補完しない(ワンライナーのため)
196
- unless @decompile
197
- unless endless[i + 1] && endless[i + 1] =~ /^\s*end(?!\w).*$/
198
- pure << "#{' '*currently_indent_depth}end"
184
+ _indent = indent.pop
185
+ pass.pop
186
+ idt = []
187
+ loop do
188
+ pure.seek pure.pos - 1
189
+ if RUBY_VERSION < "1.9" # 1.8
190
+ c = pure.read(1)
191
+ else
192
+ c = pure.getc
193
+ break if pure.pos == 0 || !(["\n", ' '].include?(c))
194
+ pure.seek pure.pos - 1
195
+ idt.unshift c
196
+ if idt.first == "\n"
197
+ pure.write idt.shift
198
+ pure.write "#{' '*_indent}end\n"
199
+ pure.write idt.join
200
+ bol = false
201
+
202
+ case t
203
+ when RubyToken::TkNL
204
+ bol = true
205
+ when RubyToken::TkEND
206
+ indent.pop
207
+ pass.pop
208
+ if opts[:decompile]
209
+ last[0] += 3
210
+ last[1] += 3
211
+ next
212
+ when RubyToken::TkIF, RubyToken::TkUNLESS
213
+ pass << [RubyToken::TkELSE, RubyToken::TkELSIF]
214
+ indent << t.char_no
215
+ when RubyToken::TkFOR
216
+ pass << []
217
+ indent << t.char_no
218
+ when RubyToken::TkWHILE, RubyToken::TkUNTIL
219
+ pass << []
220
+ indent << t.char_no
221
+ when RubyToken::TkBEGIN
222
+ pass << [RubyToken::TkRESCUE, RubyToken::TkELSE, RubyToken::TkENSURE]
223
+ indent << t.char_no
224
+ when RubyToken::TkDEF
225
+ pass << [RubyToken::TkRESCUE, RubyToken::TkELSE, RubyToken::TkENSURE]
226
+ indent << t.char_no
227
+ when RubyToken::TkCLASS, RubyToken::TkMODULE
228
+ pass << []
229
+ indent << t.char_no
230
+ when RubyToken::TkCASE
231
+ pass << [RubyToken::TkWHEN, RubyToken::TkELSE]
232
+ indent << t.char_no
233
+ when RubyToken::TkDO
234
+ pass << []
235
+ indent << bol_indent
236
+ when RubyToken::TkSPACE
237
+
238
+
239
+ pos = io.pos
240
+ io.seek pos
241
+
242
+ pos = io.pos
243
+
244
+ if RUBY_VERSION < "1.9" # 1.8
245
+ io.seek t.seek
246
+ pure.write io.read(r.seek - t.seek)
247
+ else # 1.9
248
+ io.seek last[0]
249
+ (r.seek - last[1]).times do
250
+ pure.write io.getc
251
+ last = [io.pos, r.seek]
252
+
253
+ io.seek pos
254
+
255
+ until opts[:decompile] || (indent.empty? && pass.empty?)
256
+ _indent = indent.pop
257
+ pass.pop
258
+ pure.seek pure.pos - 1
259
+ if RUBY_VERSION < "1.9" # 1.8
260
+ c = pure.read 1
261
+ else
262
+ c = pure.getc
263
+ if c == "\n"
264
+ pure.write "#{' '*_indent}end"
199
265
  else
200
- # メソッドチェインは削除しない
201
- if endless[i + 1] && endless[i + 1] =~ /^\s*end(?:\s|$)\s*$/
202
- i += 1
266
+ pure.write "\n#{' '*_indent}end"
203
267
 
204
- i += 1
205
- pure.join "\n"
268
+ pure.seek 0
269
+ ret = pure.read.chomp
270
+ pure.seek 0
206
271
 
207
- alias to_pure_ruby endless_ruby_to_pure_ruby
208
- alias ER2PR endless_ruby_to_pure_ruby
209
- alias ER2RB endless_ruby_to_pure_ruby
272
+ opts[:out][:ensure] && opts[:out][:ensure].call
273
+ opts[:in][:ensure] && opts[:in][:ensure].call
274
+
275
+ ret
210
276
 
211
277
  if __FILE__ == $PROGRAM_NAME
212
278
  require 'endlessruby/main'