rubymacros 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -0
- data/COPYING.LGPL +503 -158
- data/History.txt +115 -5
- data/Makefile +68 -0
- data/README.txt +29 -6
- data/TODO +1 -0
- data/bin/macroruby +69 -0
- data/example/__dir__.rb +18 -0
- data/example/__dir___wrap.rb +18 -0
- data/example/andand.rb +18 -0
- data/example/andand_wrap.rb +18 -0
- data/example/assert.rb +29 -8
- data/example/assert0.rb +11 -0
- data/example/assert0_wrap.rb +5 -0
- data/example/assert_does_nothing_when_disabled.rb +19 -0
- data/example/assert_wrap.rb +21 -0
- data/example/expected_output.txt +88 -0
- data/example/formless_macro.rb +123 -0
- data/example/formless_macro_wrap.rb +20 -0
- data/example/inline.rb +97 -0
- data/example/linenum.rb +19 -1
- data/example/linenum_user.rb +18 -0
- data/example/linenum_wrap.rb +18 -0
- data/example/loop.rb +18 -0
- data/example/loop_wrap.rb +18 -0
- data/example/meta.rb +25 -0
- data/example/meta_wrap.rb +20 -0
- data/example/nilresult.rb +26 -0
- data/example/nilresult_wrap.rb +21 -0
- data/example/pipeline.rb +37 -0
- data/example/rescuing.rb +33 -0
- data/example/rescuing_wrap.rb +21 -0
- data/example/role.rb +103 -0
- data/example/role_with_eval.rb +92 -0
- data/example/self_in_class.rb +27 -0
- data/example/separated_scope.rb +42 -0
- data/example/separated_scope_wrap.rb +20 -0
- data/example/simple.rb +18 -0
- data/example/simple_wrap.rb +18 -0
- data/example/unproc.rb +31 -0
- data/example/unproc_wrap.rb +21 -0
- data/example/unroll.rb +34 -0
- data/example/unroll_macros.rb +119 -0
- data/example/unroll_wrap.rb +22 -0
- data/example/with.rb +50 -7
- data/example/with_wrap.rb +19 -0
- data/lib/macro.rb +307 -72
- data/lib/macro/ReduceWithsFor_RedParse_RedParse__MacroMixin_RedParse__WithMacros_1_8.rb +18880 -0
- data/lib/macro/ReduceWithsFor_RedParse_RedParse__MacroMixin_RedParse__WithMacros_1_9.rb +19101 -0
- data/lib/macro/form.rb +136 -27
- data/lib/macro/node.rb +64 -0
- data/lib/macro/version.rb +2 -5
- data/lib/rubymacros.rb +19 -0
- data/lib/rubymacros/version.rb +23 -0
- data/lib/weakkeyhash.rb +18 -0
- data/rubymacros.gemspec +60 -0
- data/test/test_all.rb +27 -2
- data/test/test_examples.rb +91 -0
- data/test/test_expand.rb +56 -1
- data/test/test_form.rb +108 -10
- data/test/test_unroll.rb +120 -0
- metadata +93 -65
- data/Rakefile +0 -37
data/test/test_all.rb
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
=begin
|
2
|
+
rubymacros - a macro preprocessor for ruby
|
3
|
+
Copyright (C) 2008, 2016 Caleb Clausen
|
4
|
+
|
5
|
+
This program is free software: you can redistribute it and/or modify
|
6
|
+
it under the terms of the GNU Lesser General Public License as published by
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
8
|
+
(at your option) any later version.
|
9
|
+
|
10
|
+
This program is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU Lesser General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU Lesser General Public License
|
16
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
18
|
+
|
19
|
+
$:<<File.expand_path(File.dirname(__FILE__))
|
20
|
+
require 'test_form'
|
21
|
+
require 'test_expand'
|
22
|
+
|
23
|
+
#require 'test_unroll'
|
24
|
+
|
25
|
+
#require 'macro'
|
26
|
+
#Macro.
|
27
|
+
require 'test_examples'
|
3
28
|
|
@@ -0,0 +1,91 @@
|
|
1
|
+
=begin
|
2
|
+
rubymacros - a macro preprocessor for ruby
|
3
|
+
Copyright (C) 2008, 2016 Caleb Clausen
|
4
|
+
|
5
|
+
This program is free software: you can redistribute it and/or modify
|
6
|
+
it under the terms of the GNU Lesser General Public License as published by
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
8
|
+
(at your option) any later version.
|
9
|
+
|
10
|
+
This program is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU Lesser General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU Lesser General Public License
|
16
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
18
|
+
|
19
|
+
require 'test/unit'
|
20
|
+
require "macro"
|
21
|
+
|
22
|
+
def def_example_test(name,expect)
|
23
|
+
define_method "test_example_#{(name).gsub('/','Y')}" do
|
24
|
+
out,err=capture_std_out_err{
|
25
|
+
load name
|
26
|
+
}
|
27
|
+
# p [expect,out]
|
28
|
+
assert_equal expect,out
|
29
|
+
assert empty_but_for_warns?(err), "expected no warnings, but saw these:\n"+err.gsub!(/^/," ")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def capture_std_out_err #dangerous... hard to debug
|
34
|
+
old={:O=>STDOUT.dup,:o=>$stdout,:E=>STDERR.dup,:e=>$stderr}
|
35
|
+
o1,o2=IO::pipe
|
36
|
+
e1,e2=IO::pipe
|
37
|
+
STDOUT.reopen(o2)
|
38
|
+
STDERR.reopen(e2)
|
39
|
+
$stdout=STDOUT
|
40
|
+
$stderr=STDERR
|
41
|
+
begin
|
42
|
+
yield
|
43
|
+
ensure
|
44
|
+
STDOUT.reopen old[:O]
|
45
|
+
STDERR.reopen old[:E]
|
46
|
+
$stdout,$stderr=old[:o],old[:e]
|
47
|
+
end
|
48
|
+
|
49
|
+
o2.close; e2.close
|
50
|
+
out=o1.read
|
51
|
+
err=e1.read
|
52
|
+
o1.close; e1.close
|
53
|
+
|
54
|
+
return out,err
|
55
|
+
end
|
56
|
+
|
57
|
+
def empty_but_for_warns? str
|
58
|
+
str=str.dup
|
59
|
+
str.gsub!(/^([^:]+:\d+: warning: .*)$/){STDERR.puts $1;''}
|
60
|
+
str.gsub!(/\n{2,}/,"\n")
|
61
|
+
/\A\Z/===str
|
62
|
+
end
|
63
|
+
|
64
|
+
class ExamplesTest<Test::Unit::TestCase
|
65
|
+
def setup
|
66
|
+
Macro.delete_all!
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.example_dir
|
70
|
+
macropath=$LOADED_FEATURES.grep(/macro\.rb$/)[0]
|
71
|
+
unless %r{^[/\\]}===macropath
|
72
|
+
macropath=$LOAD_PATH.find{|dir| File.exist? dir+"/macro.rb"}
|
73
|
+
else
|
74
|
+
macropath=File.dirname(macropath)
|
75
|
+
end
|
76
|
+
File.dirname(macropath)+"/example/"
|
77
|
+
end
|
78
|
+
|
79
|
+
StringNode=RedParse::StringNode
|
80
|
+
can=File.read(example_dir+"/expected_output.txt").gsub(/^#.*$/,'').split(/^(.*) :\n/)
|
81
|
+
can.shift
|
82
|
+
#code=:()
|
83
|
+
# warn "unroll example disabled for now"
|
84
|
+
while name=can.shift
|
85
|
+
expect=can.shift
|
86
|
+
#code+=:(
|
87
|
+
def_example_test(name,expect) #unless /unroll/===name
|
88
|
+
end
|
89
|
+
#Macro.eval code
|
90
|
+
|
91
|
+
end
|
data/test/test_expand.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
=begin
|
2
2
|
rubymacros - a macro preprocessor for ruby
|
3
|
-
Copyright (C) 2008 Caleb Clausen
|
3
|
+
Copyright (C) 2008, 2016 Caleb Clausen
|
4
4
|
|
5
5
|
This program is free software: you can redistribute it and/or modify
|
6
6
|
it under the terms of the GNU Lesser General Public License as published by
|
@@ -19,11 +19,18 @@
|
|
19
19
|
# TODO: add a test for a method definition inside of a method definition
|
20
20
|
# to ensure that the inner method definition is properly postponed
|
21
21
|
|
22
|
+
$VERBOSE=1
|
22
23
|
|
23
24
|
|
24
25
|
require 'test/unit'
|
25
26
|
require "macro"
|
27
|
+
|
28
|
+
|
26
29
|
class ExpandTest < Test::Unit::TestCase
|
30
|
+
def setup
|
31
|
+
Macro.delete_all!
|
32
|
+
end
|
33
|
+
|
27
34
|
def test_simple_expand
|
28
35
|
Macro.eval "macro simple(a,b) :(^a+^b) end"
|
29
36
|
ttt=RedParse::CallNode[nil, "p", [RedParse::CallNode[nil, "simple", [RedParse::LiteralNode[1],
|
@@ -36,4 +43,52 @@ class ExpandTest < Test::Unit::TestCase
|
|
36
43
|
ttt.macro_expand(Macro::GLOBALS,{})
|
37
44
|
assert_equal ttt.unparse,'p((1+2))'
|
38
45
|
end
|
46
|
+
|
47
|
+
def test_expands_to_nil
|
48
|
+
Macro.eval "macro nilmacro; nil end"
|
49
|
+
tree=Macro.parse "foo; nilmacro; bar"
|
50
|
+
tree=Macro.expand tree
|
51
|
+
assert RedParse::SequenceNode===tree
|
52
|
+
assert_equal 2, tree.size
|
53
|
+
assert RedParse::CallNode===tree.first
|
54
|
+
assert_equal "foo", tree.first.name
|
55
|
+
assert RedParse::CallNode===tree.last
|
56
|
+
assert_equal "bar", tree.last.name
|
57
|
+
|
58
|
+
tree=Macro.parse "nilmacro; bar"
|
59
|
+
tree=Macro.expand tree
|
60
|
+
tree=tree.first if RedParse::SequenceNode===tree and tree.size==1
|
61
|
+
assert RedParse::CallNode===tree
|
62
|
+
assert_equal "bar", tree.name
|
63
|
+
|
64
|
+
tree=Macro.parse "foo; nilmacro"
|
65
|
+
tree=Macro.expand tree
|
66
|
+
tree=tree.first if RedParse::SequenceNode===tree and tree.size==1
|
67
|
+
assert RedParse::CallNode===tree
|
68
|
+
assert_equal "foo", tree.name
|
69
|
+
|
70
|
+
tree=Macro.parse "nilmacro"
|
71
|
+
tree=Macro.expand tree
|
72
|
+
assert RubyMacros::JustNilNode===tree
|
73
|
+
assert_equal tree.unparse, 'nil'
|
74
|
+
|
75
|
+
tree=Macro.parse "if nilmacro; p :oops; end"
|
76
|
+
tree=Macro.expand tree
|
77
|
+
assert RedParse::IfNode===tree
|
78
|
+
assert RubyMacros::JustNilNode===tree.condition
|
79
|
+
assert_equal 'if nil;p :oops;;end', tree.unparse
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_unparse_form_escape_on_assign_lhs
|
83
|
+
tree=Macro.parse "(^a)=^b"
|
84
|
+
assert_match( /\(\^a\) *= *\^b/, tree.unparse )
|
85
|
+
|
86
|
+
tree=Macro.parse '(^x),(^w), =^y'
|
87
|
+
assert_match( /\(\^x\), \(\^w\), *= *\^y/, tree.unparse )
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_call_method_on_form
|
91
|
+
$bar=2
|
92
|
+
assert_operator 0, :<, Macro.eval( ":(foo ^$bar).size" )
|
93
|
+
end
|
39
94
|
end
|
data/test/test_form.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
=begin
|
2
2
|
rubymacros - a macro preprocessor for ruby
|
3
|
-
Copyright (C) 2008 Caleb Clausen
|
3
|
+
Copyright (C) 2008, 2016 Caleb Clausen
|
4
4
|
|
5
5
|
This program is free software: you can redistribute it and/or modify
|
6
6
|
it under the terms of the GNU Lesser General Public License as published by
|
@@ -16,6 +16,7 @@
|
|
16
16
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
=end
|
18
18
|
|
19
|
+
$VERBOSE=1
|
19
20
|
|
20
21
|
require "macro"
|
21
22
|
require 'test/unit'
|
@@ -26,10 +27,30 @@ require 'pp'
|
|
26
27
|
|
27
28
|
|
28
29
|
class FormTest< Test::Unit::TestCase
|
30
|
+
def setup
|
31
|
+
Macro.delete_all!
|
32
|
+
end
|
33
|
+
|
29
34
|
EXAMPLES=TestCases::TESTCASES
|
30
35
|
|
31
|
-
|
36
|
+
SLOW=ENV['SLOW']
|
37
|
+
|
38
|
+
warn "some form tests disabled; set SLOW to enable them" unless SLOW
|
39
|
+
warn "some Macro.expand tests disabled; set SLOW to enable them" unless SLOW
|
40
|
+
|
41
|
+
nullfile= File.open(File.exist?( "/dev/null" )? "/dev/null" : "dev_null","w")
|
42
|
+
|
43
|
+
EXAMPLES.uniq.each_with_index{|x,i|
|
32
44
|
next if /__END__/===x
|
45
|
+
begin
|
46
|
+
#old_VERBOSE=$VERBOSE;$VERBOSE=false
|
47
|
+
oldSTDERR=STDERR.dup; STDERR.reopen(nullfile)
|
48
|
+
catch(:foo){ eval "BEGIN{throw :foo};"+x }
|
49
|
+
rescue SyntaxError
|
50
|
+
next
|
51
|
+
#ensure $VERBOSE=old_VERBOSE
|
52
|
+
ensure STDERR.reopen(oldSTDERR)
|
53
|
+
end
|
33
54
|
if / \^[^\s]/===x #and x.size>1000
|
34
55
|
while x['^']
|
35
56
|
warn "disabling tests of '#{x[/^.*\^.*$/]}'"
|
@@ -37,22 +58,52 @@ class FormTest< Test::Unit::TestCase
|
|
37
58
|
end
|
38
59
|
next
|
39
60
|
end
|
40
|
-
|
61
|
+
x.gsub!('v','vv') #hacky
|
62
|
+
escaped=x.gsub(/[^ -~]/){|ch|
|
63
|
+
ch=ch[0]
|
64
|
+
ch=ch.getbyte 0 if ch.respond_to? :getbyte
|
65
|
+
"\\x"+ch.to_s(16)
|
66
|
+
}
|
67
|
+
define_method "test_form_around_#{escaped}" do
|
41
68
|
check x
|
42
|
-
end
|
69
|
+
end if SLOW or rand<0.5
|
70
|
+
define_method "test_form_and_escape_around_#{escaped}" do
|
71
|
+
if /\A *undef /===x
|
72
|
+
err=RedParse::ParseError
|
73
|
+
end
|
74
|
+
begin
|
75
|
+
check_for_syntax_error x
|
76
|
+
rescue err||NilClass #ignore
|
77
|
+
else fail "#{err} expected, but none occurred" if err
|
78
|
+
end
|
79
|
+
end if SLOW or rand<0.5 unless /\A\s*(?:=begin|return|next|break)/===x
|
80
|
+
define_method "test_form_and_call_and_escape_around_#{escaped}" do
|
81
|
+
if /\A *undef /===x
|
82
|
+
err=RedParse::ParseError
|
83
|
+
end
|
84
|
+
begin
|
85
|
+
check_for_syntax_error x, ":(foo(^","\n))"
|
86
|
+
rescue err||NilClass #ignore
|
87
|
+
else fail "#{err} expected, but none occurred" if err
|
88
|
+
end
|
89
|
+
end if SLOW or rand<0.5 unless /\A\s*(?:=begin|return|next|break)/===x
|
90
|
+
define_method "test_Macro.expand_of_#{escaped}" do
|
91
|
+
check_for_syntax_error x,"",""
|
92
|
+
end if SLOW or rand<0.5
|
43
93
|
}
|
94
|
+
warn "#{__FILE__}:#{__LINE__}: warning: tests of :(^...) and Macro.expand are weak"
|
44
95
|
|
45
|
-
def check(code)
|
46
|
-
begin
|
96
|
+
def check(code,pre="\n",post="\n")
|
97
|
+
#begin
|
47
98
|
# puts code
|
48
|
-
begin as_form=Macro.eval(":(
|
99
|
+
begin as_form=Macro.eval(":("+pre+code+post+")")
|
49
100
|
rescue Exception=>formexc
|
50
101
|
0
|
51
102
|
end
|
52
103
|
|
53
104
|
begin
|
54
105
|
as_tree=RedParse.new(" \n"+code).parse
|
55
|
-
as_tree=RedParse::
|
106
|
+
as_tree=RedParse::SequenceNode[] if RedParse::NopNode===as_tree
|
56
107
|
rescue Exception=>treeexc
|
57
108
|
0
|
58
109
|
end
|
@@ -63,17 +114,44 @@ class FormTest< Test::Unit::TestCase
|
|
63
114
|
# as_form.delete_extraneous_ivars! if as_form
|
64
115
|
# as_tree.delete_extraneous_ivars! if as_tree
|
65
116
|
|
117
|
+
if as_tree and as_form and as_tree.offset != as_form.offset
|
118
|
+
warn "form and parse tree did not have same offsets, input: '#{code}'"
|
119
|
+
as_form.instance_variable_set :@offset, as_tree.offset
|
120
|
+
end
|
66
121
|
assert_equal as_tree, as_form
|
67
122
|
|
68
123
|
assert_equal as_form, as_form.deep_copy if as_form
|
69
|
-
end
|
124
|
+
#end
|
125
|
+
end
|
126
|
+
def check_for_syntax_error(code,pre=":(^",post="\n)")
|
127
|
+
# puts code
|
128
|
+
as_form=Macro.expand(pre+code+post)
|
129
|
+
|
130
|
+
assert_equal as_form, as_form.deep_copy
|
131
|
+
assert_unparses_wo_syntax_error(as_form) #weak weak
|
132
|
+
end
|
133
|
+
|
134
|
+
@@auwose=0
|
135
|
+
def assert_unparses_wo_syntax_error(tree) #weak test
|
136
|
+
warn "using assert_unparses_wo_syntax_error, which is weak" if (@@auwose+=1)==1
|
137
|
+
catch(:foo){
|
138
|
+
old_STDERR=$stderr
|
139
|
+
$stderr=open("/dev/null",'w') if File.exist? "/dev/null"
|
140
|
+
begin
|
141
|
+
eval "BEGIN{throw :foo};"+tree.unparse #weak test
|
142
|
+
ensure $stderr=old_STDERR if File.exist? "/dev/null"
|
143
|
+
end
|
144
|
+
}
|
70
145
|
end
|
71
146
|
end
|
72
147
|
|
73
148
|
class FormParameterTest< Test::Unit::TestCase
|
149
|
+
def setup
|
150
|
+
Macro.delete_all!
|
151
|
+
end
|
74
152
|
DATA=[
|
75
153
|
"1", "1.1", "nil", "false", "true",
|
76
|
-
"
|
154
|
+
"[1,2,3]", "{'a'=>4,:b=>6}", "'s'",
|
77
155
|
]
|
78
156
|
DIFFICULT_CHILDREN=[
|
79
157
|
"RedParse::ConstantNode[nil,'Object']","(a=[];a<<a)"
|
@@ -107,4 +185,24 @@ class FormParameterTest< Test::Unit::TestCase
|
|
107
185
|
assert_equal( $b.inspect, $a.inspect) #byaah, not the best way....
|
108
186
|
}
|
109
187
|
end
|
188
|
+
|
189
|
+
def test_escape_from_inner_form
|
190
|
+
Macro.parse ":(:(ielf=^rec))"
|
191
|
+
Macro.eval ":(:(ielf=^rec))"
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_marshal_of_form_param_with_hash
|
195
|
+
|
196
|
+
#why is this failing??? seems like a marshal bug??
|
197
|
+
#seems to be fixed in mri 1.9.2
|
198
|
+
tree=Macro.parse ":(^{'ffdf'=>4})"
|
199
|
+
assert_nothing_raised{
|
200
|
+
dumped=Marshal.dump tree
|
201
|
+
Marshal.load dumped
|
202
|
+
}
|
203
|
+
assert_nothing_raised{
|
204
|
+
dumped=Marshal.dump tree
|
205
|
+
Marshal.load dumped
|
206
|
+
}
|
207
|
+
end
|
110
208
|
end
|
data/test/test_unroll.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
=begin
|
2
|
+
rubymacros - a macro preprocessor for ruby
|
3
|
+
Copyright (C) 2008, 2016 Caleb Clausen
|
4
|
+
|
5
|
+
This program is free software: you can redistribute it and/or modify
|
6
|
+
it under the terms of the GNU Lesser General Public License as published by
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
8
|
+
(at your option) any later version.
|
9
|
+
|
10
|
+
This program is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU Lesser General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU Lesser General Public License
|
16
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
18
|
+
|
19
|
+
require 'test/unit'
|
20
|
+
require 'macro'
|
21
|
+
Macro.require 'example/unroll'
|
22
|
+
|
23
|
+
class UnrollTest<Test::Unit::TestCase
|
24
|
+
def setup
|
25
|
+
Macro.delete_all!
|
26
|
+
end
|
27
|
+
|
28
|
+
def setup(seed=Time.now.to_i)
|
29
|
+
srand(seed)
|
30
|
+
@data=loop()
|
31
|
+
end
|
32
|
+
|
33
|
+
def choose(list)
|
34
|
+
list[rand(list.size)]
|
35
|
+
end
|
36
|
+
|
37
|
+
def loop
|
38
|
+
choose(LOOPS).
|
39
|
+
gsub!("<<<cond>>>", loop_condition).
|
40
|
+
gsub!("<<<body>>>", loop_body)
|
41
|
+
end
|
42
|
+
|
43
|
+
def loop_condition
|
44
|
+
choose(LOOP_CONDITIONS)
|
45
|
+
end
|
46
|
+
|
47
|
+
def loop_body max=4
|
48
|
+
x=rand(20)
|
49
|
+
size=
|
50
|
+
if x==0; 0
|
51
|
+
else case x/2
|
52
|
+
when 1; 1
|
53
|
+
when 2; 2
|
54
|
+
when 9; 10
|
55
|
+
else 4
|
56
|
+
end
|
57
|
+
end
|
58
|
+
result=(1..size).map{ choose(LOOP_BODY_PARTS) }.join("\n")
|
59
|
+
if max>=0
|
60
|
+
result.gsub!("<<<body>>>", loop_body(max-1))
|
61
|
+
else
|
62
|
+
result.gsub!("<<<body>>>", "nil")
|
63
|
+
end
|
64
|
+
result.gsub!("redo(","log(")
|
65
|
+
result
|
66
|
+
end
|
67
|
+
|
68
|
+
LOOPS=[
|
69
|
+
"while <<<cond>>>\n <<<body>>>\nend\n",
|
70
|
+
"until <<<cond>>>\n <<<body>>>\nend\n",
|
71
|
+
"(\n<<<body>>>\n)while <<<cond>>>\n",
|
72
|
+
"(\n<<<body>>>\n)until <<<cond>>>\n",
|
73
|
+
"begin\n<<<body>>>\nend while <<<cond>>>\n",
|
74
|
+
"begin\n<<<body>>>\nend until <<<cond>>>\n",
|
75
|
+
]
|
76
|
+
LOOP_CONDITIONS=[
|
77
|
+
"true", "false", "rand<0.5", "rand<0.95"
|
78
|
+
]
|
79
|
+
LOOP_BODY_PARTS=[
|
80
|
+
"log(rand(100))",
|
81
|
+
"<<<fctl>>> if(rand<0.5)",
|
82
|
+
"<<<fctl>>> unless(rand<0.5)",
|
83
|
+
"<<<fctl>>>(<<<body>>>) if(rand<0.5)",
|
84
|
+
"<<<fctl>>>(<<<body>>>) unless(rand<0.5)",
|
85
|
+
"if(rand<0.5)\n <<<body>>>\nend",
|
86
|
+
"unless(rand<0.5)\n <<<body>>>\nend",
|
87
|
+
"log((<<<body>>>))",
|
88
|
+
]
|
89
|
+
|
90
|
+
FCTLS=%w[break next redo]
|
91
|
+
|
92
|
+
def clear_log; @log=[] end
|
93
|
+
def log x; @log<<x end
|
94
|
+
|
95
|
+
def test_unroll
|
96
|
+
10.times{
|
97
|
+
clear_log
|
98
|
+
normal=eval(@data)
|
99
|
+
nlog=@log
|
100
|
+
|
101
|
+
clear_log
|
102
|
+
macrod=Macro.eval("unroll #@data")
|
103
|
+
mlog=@log
|
104
|
+
|
105
|
+
assert_equal normal,macrod
|
106
|
+
assert_equal nlog,mlog
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_unroll_thorough times=1000,keys=(1..times).map{rand(0x1_0000_0000)}
|
111
|
+
keys.each{|key|
|
112
|
+
begin
|
113
|
+
setup key
|
114
|
+
test_unroll
|
115
|
+
rescue Exception=>e
|
116
|
+
raise e.class,"using setup key #{key}"+e.message,e.backtrace
|
117
|
+
end
|
118
|
+
}
|
119
|
+
end
|
120
|
+
end
|