rubymacros 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|