madderlib 0.1.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/CHANGELOG +3 -0
- data/LICENSE +22 -0
- data/README.rdoc +173 -0
- data/Rakefile +134 -0
- data/lib/madderlib.rb +27 -0
- data/lib/madderlib/builder.rb +659 -0
- data/lib/madderlib/conditional/allowed.rb +144 -0
- data/lib/madderlib/conditional/helper.rb +135 -0
- data/lib/madderlib/conditional/likely.rb +162 -0
- data/lib/madderlib/conditional/recur.rb +103 -0
- data/lib/madderlib/conditional/registry.rb +56 -0
- data/lib/madderlib/conditional/repeat.rb +130 -0
- data/lib/madderlib/context.rb +140 -0
- data/lib/madderlib/core.rb +217 -0
- data/lib/madderlib/extensions.rb +40 -0
- data/lib/madderlib/instruction.rb +171 -0
- data/lib/madderlib/phrase.rb +284 -0
- data/lib/madderlib/sequencer.rb +337 -0
- data/madderlib.gemspec +72 -0
- data/spec/benchmark_spec.rb +69 -0
- data/spec/builder_spec.rb +321 -0
- data/spec/builder_to_other_spec.rb +47 -0
- data/spec/builder_to_sequencer_spec.rb +388 -0
- data/spec/conditional_allowed_spec.rb +130 -0
- data/spec/conditional_helper_spec.rb +131 -0
- data/spec/conditional_likely_spec.rb +138 -0
- data/spec/conditional_recur_spec.rb +102 -0
- data/spec/conditional_registry_spec.rb +94 -0
- data/spec/conditional_repeat_spec.rb +88 -0
- data/spec/doc_spec.rb +550 -0
- data/spec/error_spec.rb +33 -0
- data/spec/examples_spec.rb +151 -0
- data/spec/extensions_spec.rb +47 -0
- data/spec/grammar_spec.rb +101 -0
- data/spec/instruction_spec.rb +133 -0
- data/spec/kernel_spec.rb +58 -0
- data/spec/phrase_spec.rb +7 -0
- data/spec/sequencer_spec.rb +317 -0
- data/spec/spec_helper.rb +54 -0
- metadata +98 -0
@@ -0,0 +1,94 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
module MadderLib
|
6
|
+
module Spec
|
7
|
+
class Phrase
|
8
|
+
class << self
|
9
|
+
include Conditional::Registry::Static
|
10
|
+
end
|
11
|
+
include Conditional::Registry::Instance
|
12
|
+
|
13
|
+
def instructions
|
14
|
+
@instructions ||= []
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Instruction
|
19
|
+
class << self
|
20
|
+
include Conditional::Registry::Static
|
21
|
+
end
|
22
|
+
include Conditional::Registry::Instance
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
describe MadderLib::Conditional::Registry do
|
30
|
+
it "accumulates phrase preprations" do
|
31
|
+
hits = []
|
32
|
+
|
33
|
+
# how to prepare each instruction
|
34
|
+
MadderLib::Spec::Instruction.add_prepare { hits << :instruction_bare }
|
35
|
+
MadderLib::Spec::Instruction.add_prepare {|context| hits << :instruction_context }
|
36
|
+
|
37
|
+
# how to prepare the phrase
|
38
|
+
MadderLib::Spec::Phrase.add_prepare { hits << :phrase_bare }
|
39
|
+
MadderLib::Spec::Phrase.add_prepare {|context| hits << :phrase_context }
|
40
|
+
|
41
|
+
# just confirming ...
|
42
|
+
MadderLib::Spec::Phrase.new.methods.include?('instructions').should be_true
|
43
|
+
|
44
|
+
# add 2 instructions
|
45
|
+
instance = MadderLib::Spec::Phrase.new
|
46
|
+
instance.instructions << MadderLib::Spec::Instruction.new
|
47
|
+
instance.instructions << MadderLib::Spec::Instruction.new
|
48
|
+
instance.instructions.should have(2).instructions
|
49
|
+
|
50
|
+
instance.prepare(MadderLib::Context::EMPTY)
|
51
|
+
|
52
|
+
hits.should eql([
|
53
|
+
:phrase_bare, :phrase_context,
|
54
|
+
:instruction_bare, :instruction_context,
|
55
|
+
:instruction_bare, :instruction_context,
|
56
|
+
])
|
57
|
+
end
|
58
|
+
|
59
|
+
it "accumulates test preprations" do
|
60
|
+
context = MadderLib::Context::EMPTY
|
61
|
+
hits = []
|
62
|
+
barely, contextual = true, true
|
63
|
+
|
64
|
+
# how to test each instruction
|
65
|
+
MadderLib::Spec::Instruction.add_test do |instance|
|
66
|
+
hits << :instruction_bare
|
67
|
+
barely
|
68
|
+
end
|
69
|
+
MadderLib::Spec::Instruction.add_test do |instance, context|
|
70
|
+
hits << :instruction_context
|
71
|
+
contextual
|
72
|
+
end
|
73
|
+
|
74
|
+
# all clear
|
75
|
+
hits.clear
|
76
|
+
instance = MadderLib::Spec::Instruction.new
|
77
|
+
instance.test(context).should be_true
|
78
|
+
hits.should eql([:instruction_bare, :instruction_context])
|
79
|
+
|
80
|
+
# bare terminate
|
81
|
+
hits.clear
|
82
|
+
barely = false
|
83
|
+
instance = MadderLib::Spec::Instruction.new
|
84
|
+
instance.test(context).should be_false
|
85
|
+
hits.should eql([:instruction_bare])
|
86
|
+
|
87
|
+
# contextual terminate
|
88
|
+
hits.clear
|
89
|
+
barely, contextual = true, false
|
90
|
+
instance = MadderLib::Spec::Instruction.new
|
91
|
+
instance.test(context).should be_false
|
92
|
+
hits.should eql([:instruction_bare, :instruction_context])
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
describe MadderLib::Conditional::Repeat do
|
6
|
+
|
7
|
+
it "no repeat = once" do
|
8
|
+
builder = madderlib do
|
9
|
+
say(:one)
|
10
|
+
say(:two)
|
11
|
+
end
|
12
|
+
|
13
|
+
builder.words.should eql(%w{ one two })
|
14
|
+
end
|
15
|
+
|
16
|
+
it "supports simple repeating" do
|
17
|
+
builder = madderlib do
|
18
|
+
say(:once)
|
19
|
+
say(:twice).repeat(2)
|
20
|
+
say(:thrice).times(3)
|
21
|
+
end
|
22
|
+
|
23
|
+
builder.words.should eql(%w{ once twice twice thrice thrice thrice })
|
24
|
+
end
|
25
|
+
|
26
|
+
it "supports a 0-repeat, which blocks the instruction" do
|
27
|
+
builder = madderlib do
|
28
|
+
say(:one)
|
29
|
+
say(:two).times(0)
|
30
|
+
end
|
31
|
+
|
32
|
+
builder.words.should eql(%w{ one })
|
33
|
+
end
|
34
|
+
|
35
|
+
it "supports Ranged repeating" do
|
36
|
+
builder = madderlib do
|
37
|
+
say(:once)
|
38
|
+
say(:few).repeat(Range.new(3, 5))
|
39
|
+
say(:couple).times(3, 5)
|
40
|
+
end
|
41
|
+
|
42
|
+
pound_on do
|
43
|
+
words = builder.words
|
44
|
+
words.shift.should eql('once')
|
45
|
+
|
46
|
+
repeat = []
|
47
|
+
repeat << words.shift while words.first == 'few'
|
48
|
+
repeat.size.should be_close(4, 1.1)
|
49
|
+
|
50
|
+
repeat = []
|
51
|
+
repeat << words.shift while words.first == 'couple'
|
52
|
+
repeat.size.should be_close(4, 1.1)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
it "supports arbitrary repeating, simple boolean tests" do
|
59
|
+
men = [:fred, :barney]
|
60
|
+
women = [:wilma, :betty]
|
61
|
+
|
62
|
+
builder = madderlib :repeat_exhausting do
|
63
|
+
say(:intro)
|
64
|
+
a(:man).says { men.shift }.repeat { ! men.empty? }
|
65
|
+
a(:woman).says { women.shift }.while { ! women.empty? }
|
66
|
+
end
|
67
|
+
|
68
|
+
builder.words.should eql(%w{ intro fred barney wilma betty })
|
69
|
+
|
70
|
+
# the next pass should be exhausted
|
71
|
+
builder.words.should eql(%w{ intro })
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
it "stops repeating after getting a nil value" do
|
77
|
+
values = [ :a, :b, nil, :c, :d, '', :e, :f ]
|
78
|
+
builder = madderlib :repeat_exhausting do
|
79
|
+
say { values.shift }.repeat { ! values.empty? }
|
80
|
+
end
|
81
|
+
|
82
|
+
builder.words.should eql(%w{ a b })
|
83
|
+
builder.words.should eql(%w{ c d })
|
84
|
+
builder.words.should eql(%w{ e f })
|
85
|
+
builder.words.should eql([])
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
data/spec/doc_spec.rb
ADDED
@@ -0,0 +1,550 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
describe MadderLib, "tests from the documentation" do
|
6
|
+
|
7
|
+
it "Builder.initialize" do
|
8
|
+
builder = MadderLib::Builder.new
|
9
|
+
builder.id.should be_nil
|
10
|
+
builder.should have(0).phrases
|
11
|
+
#
|
12
|
+
builder = MadderLib::Builder.new :id
|
13
|
+
builder.id.should equal(:id)
|
14
|
+
builder.should have(0).phrases
|
15
|
+
#
|
16
|
+
builder = MadderLib::Builder.new do
|
17
|
+
say 'no id'
|
18
|
+
end
|
19
|
+
builder.id.should be_nil
|
20
|
+
builder.sentence.should eql('no id')
|
21
|
+
#
|
22
|
+
builder = MadderLib::Builder.new :id do
|
23
|
+
say {|context| context.builder.id }
|
24
|
+
end
|
25
|
+
builder.sentence.should eql('id')
|
26
|
+
end
|
27
|
+
|
28
|
+
it "Builder.append" do
|
29
|
+
builder = MadderLib::Builder.new { say 'construct' }
|
30
|
+
builder.append { say 'extended' }
|
31
|
+
builder.extend { say 'appending' }
|
32
|
+
builder.words.should eql(%w{ construct extended appending })
|
33
|
+
end
|
34
|
+
|
35
|
+
it "Builder.clone" do
|
36
|
+
original = MadderLib::Builder.new do
|
37
|
+
meta[:meta] = :original
|
38
|
+
say 'original'
|
39
|
+
and_then(:shared).say('initial').likely(1)
|
40
|
+
end
|
41
|
+
#
|
42
|
+
cloned = original.clone
|
43
|
+
cloned[:meta] = :cloned
|
44
|
+
cloned.extend { say 'cloned' }
|
45
|
+
#
|
46
|
+
done = :original
|
47
|
+
cloned.setup { done = :cloned }
|
48
|
+
#
|
49
|
+
shared = original.phrases.find {|phrase| phrase.id == :shared }
|
50
|
+
shared.instructions.first.words << 'added'
|
51
|
+
#
|
52
|
+
original[:meta].should equal(:original)
|
53
|
+
original.sentence.should eql('original initial added')
|
54
|
+
done.should equal(:original)
|
55
|
+
#
|
56
|
+
cloned[:meta].should equal(:cloned)
|
57
|
+
cloned.sentence.should eql('original initial added cloned')
|
58
|
+
done.should equal(:cloned)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "Builder.setup" do
|
62
|
+
builder = MadderLib::Builder.new do
|
63
|
+
say {|context| context[:setup] }
|
64
|
+
end
|
65
|
+
builder.setup {|context| context[:setup] << 2 }
|
66
|
+
builder.setup {|context| context[:setup] << 3 }
|
67
|
+
builder.setup(:first) {|context| context[:setup] = [1] }
|
68
|
+
#
|
69
|
+
builder.sentence.should eql('1 2 3')
|
70
|
+
end
|
71
|
+
|
72
|
+
it "Builder.teardown" do
|
73
|
+
builder = MadderLib::Builder.new do
|
74
|
+
say 'teardown'
|
75
|
+
end
|
76
|
+
markers = []
|
77
|
+
builder.teardown {|context| markers << 2 }
|
78
|
+
builder.teardown {|context| markers << 3 }
|
79
|
+
builder.teardown(:first) {|context| markers = [1] }
|
80
|
+
#
|
81
|
+
builder.sentence.should eql('teardown')
|
82
|
+
markers.should eql([1, 2, 3])
|
83
|
+
end
|
84
|
+
|
85
|
+
it "Builder.meta accessors" do
|
86
|
+
builder = MadderLib::Builder.new do
|
87
|
+
meta[:key] = :value
|
88
|
+
end
|
89
|
+
builder[:key].should equal(:value)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "Builder.phrase" do
|
93
|
+
builder = MadderLib::Builder.new do
|
94
|
+
say 'yes'
|
95
|
+
phrase.if {|context| context.builder[:activated] == true }
|
96
|
+
it.repeat(3)
|
97
|
+
end
|
98
|
+
#
|
99
|
+
builder.should have(1).phrases
|
100
|
+
builder.phrase.should have(1).instructions
|
101
|
+
#
|
102
|
+
builder.should have(0).words
|
103
|
+
#
|
104
|
+
builder[:activated] = true
|
105
|
+
builder.sentence.should eql('yes yes yes')
|
106
|
+
end
|
107
|
+
|
108
|
+
it "Builder.and_then" do
|
109
|
+
builder = MadderLib::Builder.new do
|
110
|
+
say 'first'
|
111
|
+
and_then.say 'and_then'
|
112
|
+
also.say 'also'
|
113
|
+
end
|
114
|
+
builder.and.say 'and'
|
115
|
+
builder.then.say 'then'
|
116
|
+
|
117
|
+
builder.sentence.should eql('first and_then also and then')
|
118
|
+
end
|
119
|
+
|
120
|
+
it "Builder.an" do
|
121
|
+
builder = MadderLib::Builder.new do
|
122
|
+
say 'first'
|
123
|
+
a(:second).says 'second'
|
124
|
+
an(:other).says 'other'
|
125
|
+
end
|
126
|
+
|
127
|
+
builder.sentence.should eql('first second other')
|
128
|
+
end
|
129
|
+
|
130
|
+
it "Builder.first" do
|
131
|
+
builder = MadderLib::Builder.new do
|
132
|
+
say 'something'
|
133
|
+
first.say 'say'
|
134
|
+
end
|
135
|
+
builder.sentence.should eql('say something')
|
136
|
+
|
137
|
+
builder.first.say 'first'
|
138
|
+
builder.sentence.should eql('first say something')
|
139
|
+
end
|
140
|
+
|
141
|
+
it "Builder.last" do
|
142
|
+
builder = MadderLib::Builder.new do
|
143
|
+
last.say 'said'
|
144
|
+
say 'something'
|
145
|
+
end
|
146
|
+
builder.sentence.should eql('something said')
|
147
|
+
|
148
|
+
builder.last.say 'last'
|
149
|
+
builder.sentence.should eql('something said last')
|
150
|
+
end
|
151
|
+
|
152
|
+
it "Builder.anywhere" do
|
153
|
+
builder = MadderLib::Builder.new do
|
154
|
+
say 'top'
|
155
|
+
say 'here'
|
156
|
+
say 'there'
|
157
|
+
say 'bottom'
|
158
|
+
end
|
159
|
+
builder.anywhere.say 'anywhere'
|
160
|
+
|
161
|
+
words = builder.words
|
162
|
+
words.should have(5).words
|
163
|
+
words.find_all {|word| word == 'anywhere'}.should have(1).word
|
164
|
+
|
165
|
+
builder.it.recurs(2)
|
166
|
+
|
167
|
+
words = builder.words
|
168
|
+
words.should have(6).words
|
169
|
+
words.find_all {|word| word == 'anywhere'}.should have(2).word
|
170
|
+
end
|
171
|
+
|
172
|
+
it "Builder.before" do
|
173
|
+
builder = MadderLib::Builder.new do
|
174
|
+
an(:always).says 'always'
|
175
|
+
a(:sometimes).says('sometimes').if {|context| context.builder[:sometimes] == true }
|
176
|
+
before(:always).say 'before-always'
|
177
|
+
before(:sometimes, :depends).say 'before-sometimes'
|
178
|
+
before(:depends).say 'depends'
|
179
|
+
end
|
180
|
+
|
181
|
+
builder.sentence.should eql('before-always always')
|
182
|
+
|
183
|
+
builder[:sometimes] = true
|
184
|
+
|
185
|
+
builder.sentence.should eql('before-always always depends before-sometimes sometimes')
|
186
|
+
end
|
187
|
+
|
188
|
+
it "Builder.after" do
|
189
|
+
builder = MadderLib::Builder.new do
|
190
|
+
an(:always).says 'always'
|
191
|
+
a(:sometimes).says('sometimes').if {|context| context.builder[:sometimes] == true }
|
192
|
+
after(:always).say 'after-always'
|
193
|
+
after(:sometimes, :depends).say 'after-sometimes'
|
194
|
+
after(:depends).say 'depends'
|
195
|
+
end
|
196
|
+
|
197
|
+
builder.sentence.should eql('always after-always')
|
198
|
+
|
199
|
+
builder[:sometimes] = true
|
200
|
+
|
201
|
+
builder.sentence.should eql('always after-always sometimes after-sometimes depends')
|
202
|
+
end
|
203
|
+
|
204
|
+
it "Builder.say" do
|
205
|
+
builder = MadderLib::Builder.new do
|
206
|
+
says 'word'
|
207
|
+
say :symbol
|
208
|
+
say { 'lambda' }
|
209
|
+
end
|
210
|
+
builder.should have(3).phrases
|
211
|
+
builder.sentence.should eql('word symbol lambda')
|
212
|
+
end
|
213
|
+
|
214
|
+
it "Builder.alternately" do
|
215
|
+
builder = MadderLib::Builder.new do
|
216
|
+
says 'word'
|
217
|
+
alternately.says :symbol
|
218
|
+
end
|
219
|
+
builder.or.say { 'lambda' }
|
220
|
+
|
221
|
+
builder.should have(1).phrases
|
222
|
+
builder.phrase.should have(3).instructions
|
223
|
+
%w{ word symbol lambda}.include?(builder.sentence).should be_true
|
224
|
+
end
|
225
|
+
|
226
|
+
it "Build.words" do
|
227
|
+
builder = MadderLib::Builder.new do
|
228
|
+
says 'word'
|
229
|
+
say :symbol, [:with, :hierarchy]
|
230
|
+
say { 'lambda' }
|
231
|
+
end
|
232
|
+
builder.words.should eql(%w{ word symbol with hierarchy lambda })
|
233
|
+
end
|
234
|
+
|
235
|
+
it "Build.sentence" do
|
236
|
+
builder = MadderLib::Builder.new do
|
237
|
+
says 'word'
|
238
|
+
say :symbol, [:with, :hierarchy]
|
239
|
+
say { 'lambda' }
|
240
|
+
end
|
241
|
+
builder.sentence.should eql('word symbol with hierarchy lambda')
|
242
|
+
end
|
243
|
+
|
244
|
+
|
245
|
+
|
246
|
+
it "Context.state" do
|
247
|
+
context = MadderLib::Context.new
|
248
|
+
state = context.state(:state)
|
249
|
+
state.should_not be_nil
|
250
|
+
|
251
|
+
state[:key] = :value
|
252
|
+
context.state(:state)[:key].should equal(:value)
|
253
|
+
end
|
254
|
+
|
255
|
+
it "Context.data accessors" do
|
256
|
+
context = MadderLib::Context.new
|
257
|
+
context.data[:key] = :value
|
258
|
+
|
259
|
+
context[:key].should equal(:value)
|
260
|
+
end
|
261
|
+
|
262
|
+
it "Context::EMPTY" do
|
263
|
+
MadderLib::Context::EMPTY.frozen?.should be_true
|
264
|
+
|
265
|
+
lambda { MadderLib::Context::EMPTY.state(:immutable) }.should raise_error TypeError
|
266
|
+
lambda { MadderLib::Context::EMPTY[:immutable] = true }.should raise_error TypeError
|
267
|
+
end
|
268
|
+
|
269
|
+
|
270
|
+
|
271
|
+
it "KernelMethods.madderlib" do
|
272
|
+
builder = madderlib do
|
273
|
+
say 'no id'
|
274
|
+
end
|
275
|
+
madderlib_grammar.builders.include?(builder).should be_true
|
276
|
+
madderlib_grammar.builder_map.values.include?(builder).should_not be_true
|
277
|
+
|
278
|
+
builder = madderlib :id do
|
279
|
+
say 'has id'
|
280
|
+
end
|
281
|
+
madderlib_grammar.builders.include?(builder).should be_true
|
282
|
+
madderlib_grammar.builder_map.values.include?(builder).should be_true
|
283
|
+
end
|
284
|
+
|
285
|
+
it "KernelMethods.madderlib" do
|
286
|
+
builder = madderlib do
|
287
|
+
say 'no id'
|
288
|
+
end
|
289
|
+
madderlib_grammar.builders.include?(builder).should be_true
|
290
|
+
madderlib_grammar.builder_map.values.include?(builder).should_not be_true
|
291
|
+
|
292
|
+
builder = madderlib :id do
|
293
|
+
say 'has id'
|
294
|
+
end
|
295
|
+
madderlib_grammar.builders.include?(builder).should be_true
|
296
|
+
madderlib_grammar.builder_map.values.include?(builder).should be_true
|
297
|
+
end
|
298
|
+
|
299
|
+
|
300
|
+
|
301
|
+
it "Grammar.new_instance" do
|
302
|
+
current = MadderLib::Grammar.new_instance
|
303
|
+
current.should have(0).builders
|
304
|
+
current.should equal(MadderLib::Grammar.get_instance)
|
305
|
+
|
306
|
+
one = madderlib { say 'one' }
|
307
|
+
current.should have(1).builders
|
308
|
+
current.builders.include?(one).should be_true
|
309
|
+
|
310
|
+
fresh = MadderLib::Grammar.new_instance
|
311
|
+
fresh.should equal(MadderLib::Grammar.get_instance)
|
312
|
+
|
313
|
+
two = madderlib { say 'two' }
|
314
|
+
fresh.should have(1).builders
|
315
|
+
fresh.builders.include?(two).should be_true
|
316
|
+
|
317
|
+
current.should_not equal(MadderLib::Grammar.get_instance)
|
318
|
+
current.builders.include?(two).should_not be_true
|
319
|
+
end
|
320
|
+
|
321
|
+
it "Grammar.add" do
|
322
|
+
grammar = MadderLib::Grammar.new_instance
|
323
|
+
|
324
|
+
builder = madderlib { say 'exists' }
|
325
|
+
x = grammar.add(builder)
|
326
|
+
x.should equal(builder)
|
327
|
+
grammar.should have(1).builders
|
328
|
+
grammar.builder_map.should have(0).keys
|
329
|
+
|
330
|
+
builder = grammar.add { say 'no id' }
|
331
|
+
grammar.should have(2).builders
|
332
|
+
grammar.builder_map.should have(0).keys
|
333
|
+
builder.sentence.should eql('no id')
|
334
|
+
|
335
|
+
builder = grammar << :id
|
336
|
+
grammar.should have(3).builders
|
337
|
+
grammar.builder_map.values.include?(builder).should be_true
|
338
|
+
builder.sentence.should eql('')
|
339
|
+
end
|
340
|
+
|
341
|
+
it "Grammar.builder_map accessors" do
|
342
|
+
grammar = MadderLib::Grammar.new_instance
|
343
|
+
|
344
|
+
builder = grammar.add(:id) { say 'has id' }
|
345
|
+
grammar[:id].should equal(builder)
|
346
|
+
end
|
347
|
+
|
348
|
+
|
349
|
+
|
350
|
+
it "Instruction.speak" do
|
351
|
+
builder = madderlib do
|
352
|
+
say nil
|
353
|
+
say ''
|
354
|
+
end
|
355
|
+
builder.words.should eql([])
|
356
|
+
|
357
|
+
builder = madderlib do
|
358
|
+
say 'one'
|
359
|
+
say :two
|
360
|
+
say 3
|
361
|
+
end
|
362
|
+
builder.words.should eql(%w{ one two 3 })
|
363
|
+
|
364
|
+
builder = madderlib do
|
365
|
+
say []
|
366
|
+
say [ nil, 'one' ]
|
367
|
+
say [ :two, [ '', 3 ]]
|
368
|
+
end
|
369
|
+
builder.words.should eql(%w{ one two 3 })
|
370
|
+
|
371
|
+
builder = madderlib do
|
372
|
+
say madderlib { say 'one' }
|
373
|
+
say madderlib {
|
374
|
+
say madderlib { say :two }
|
375
|
+
say madderlib { say 3 }
|
376
|
+
}
|
377
|
+
end
|
378
|
+
builder.words.should eql(%w{ one two 3 })
|
379
|
+
|
380
|
+
words = [ 'one', lambda { :two }, madderlib { say 3 } ]
|
381
|
+
builder = madderlib do
|
382
|
+
say { words.shift }.repeat { ! words.empty? }
|
383
|
+
end
|
384
|
+
builder.words.should eql(%w{ one two 3 })
|
385
|
+
end
|
386
|
+
|
387
|
+
|
388
|
+
|
389
|
+
it "Phrase.alternately" do
|
390
|
+
builder = madderlib do
|
391
|
+
say('barnard').or.say('bryn mawr')
|
392
|
+
alternately(2).say('mount holyoke').alternately(2).say('radcliffe')
|
393
|
+
it.alternately(4).says('smith').or(4).says('vassar')
|
394
|
+
end
|
395
|
+
builder.phrase.says('wellesley').or(5).nothing
|
396
|
+
|
397
|
+
usage = {}
|
398
|
+
200.times do
|
399
|
+
key = builder.sentence
|
400
|
+
usage[key] = (usage[key] || 0) + 1
|
401
|
+
end
|
402
|
+
|
403
|
+
# if proportions were accurately reproducible:
|
404
|
+
# ['barnard', 'bryn mawr', 'wellesley'].each {|name| usage[name].should eql(10) }
|
405
|
+
# ['mount holyoke', 'radcliffe'].each {|name| usage[name].should eql(20) }
|
406
|
+
# ['smith', 'vassar'].each {|name| usage[name].should eql(40) }
|
407
|
+
# [''].each {|name| usage[name].should eql(50) }
|
408
|
+
end
|
409
|
+
|
410
|
+
|
411
|
+
|
412
|
+
it "AnywherePhrase.before" do
|
413
|
+
flag = true
|
414
|
+
builder = madderlib do
|
415
|
+
say 'top'
|
416
|
+
also(:limit).say('middle').if { flag }
|
417
|
+
say 'bottom'
|
418
|
+
|
419
|
+
anywhere.say('hello').before(:limit)
|
420
|
+
end
|
421
|
+
|
422
|
+
10.times do
|
423
|
+
words = builder.words
|
424
|
+
words.index('hello').should eql(1)
|
425
|
+
end
|
426
|
+
|
427
|
+
flag = false
|
428
|
+
10.times do
|
429
|
+
words = builder.words
|
430
|
+
(words.index('hello') < 2).should be_true
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
it "AnywherePhrase.before" do
|
435
|
+
flag = true
|
436
|
+
builder = madderlib do
|
437
|
+
say 'top'
|
438
|
+
also(:limit).say('middle').if { flag }
|
439
|
+
say 'bottom'
|
440
|
+
|
441
|
+
anywhere.say('hello').after(:limit)
|
442
|
+
end
|
443
|
+
|
444
|
+
10.times do
|
445
|
+
words = builder.words
|
446
|
+
words.index('hello').should eql(2)
|
447
|
+
end
|
448
|
+
|
449
|
+
flag = false
|
450
|
+
10.times do
|
451
|
+
words = builder.words
|
452
|
+
(words.index('hello') > 0).should be_true
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
it "AnywherePhrase.between" do
|
457
|
+
builder = madderlib do
|
458
|
+
say 'top'
|
459
|
+
also(:upper).say('upper')
|
460
|
+
also(:lower).say('lower')
|
461
|
+
say 'bottom'
|
462
|
+
|
463
|
+
anywhere.say('hello').between(:upper, :lower)
|
464
|
+
end
|
465
|
+
|
466
|
+
10.times do
|
467
|
+
words = builder.words
|
468
|
+
words.index('hello').should eql(2)
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
|
473
|
+
|
474
|
+
|
475
|
+
it "Instruction.assuming" do
|
476
|
+
switch = false
|
477
|
+
builder = madderlib do
|
478
|
+
an(:on).says('on').assuming { switch }
|
479
|
+
an(:off).says('off').if { ! switch }
|
480
|
+
say('bright').if :on
|
481
|
+
say('dark').if :off
|
482
|
+
end
|
483
|
+
|
484
|
+
builder.sentence.should eql('off dark')
|
485
|
+
switch = true
|
486
|
+
builder.sentence.should eql('on bright')
|
487
|
+
end
|
488
|
+
|
489
|
+
it "Instruction.forbidding" do
|
490
|
+
switch = false
|
491
|
+
builder = madderlib do
|
492
|
+
an(:on).says('on').forbidding { ! switch }
|
493
|
+
an(:off).says('off').unless { switch }
|
494
|
+
say('bright').unless :off
|
495
|
+
say('dark').unless :on
|
496
|
+
end
|
497
|
+
|
498
|
+
builder.sentence.should eql('off dark')
|
499
|
+
switch = true
|
500
|
+
builder.sentence.should eql('on bright')
|
501
|
+
end
|
502
|
+
|
503
|
+
it "Instruction.likely" do
|
504
|
+
builder = madderlib do
|
505
|
+
say('parsley').likely(4)
|
506
|
+
alternately(3).say('sage')
|
507
|
+
alternately.say('rosemary').weighted(2).or.say('thyme')
|
508
|
+
end
|
509
|
+
|
510
|
+
usage = {}
|
511
|
+
60.times do
|
512
|
+
key = builder.sentence
|
513
|
+
usage[key] = (usage[key] || 0) + 1
|
514
|
+
end
|
515
|
+
|
516
|
+
# if proportions were accurately reproducible:
|
517
|
+
# usage['parsley'].should eql(20)
|
518
|
+
# usage['sage'].should eql(15)
|
519
|
+
# usage['rosemary'].should eql(10)
|
520
|
+
# usage['thyme'].should eql(5)
|
521
|
+
end
|
522
|
+
|
523
|
+
it "Phrase.recurs" do
|
524
|
+
builder = madderlib do
|
525
|
+
say(:start)
|
526
|
+
say(:end)
|
527
|
+
anytime.recurring(2).say(:any)
|
528
|
+
anytime.recurring {|count| count < 2 }.say(:also)
|
529
|
+
end
|
530
|
+
|
531
|
+
words = builder.words
|
532
|
+
words.find_all {|word| word == 'any' }.should have(2).items
|
533
|
+
words.find_all {|word| word == 'also' }.should have(2).items
|
534
|
+
end
|
535
|
+
|
536
|
+
it "Phrase.repeat" do
|
537
|
+
builder = madderlib do
|
538
|
+
say(:twice).times(2)
|
539
|
+
say(:couple).repeats(1, 2)
|
540
|
+
say(:thrice).while {|count| count < 3 }
|
541
|
+
end
|
542
|
+
|
543
|
+
words = builder.words
|
544
|
+
words.find_all {|word| word == 'twice' }.should have(2).items
|
545
|
+
words.find_all {|word| word == 'thrice' }.should have(3).items
|
546
|
+
count = words.find_all {|word| word == 'couple' }.size
|
547
|
+
(count >= 1 && count <= 2).should be_true
|
548
|
+
end
|
549
|
+
|
550
|
+
end
|