nudge 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/Thorfile +59 -0
- data/VERSION +1 -1
- data/bin/nudge +1 -1
- data/lib/cli/runner.rb +1 -1
- data/lib/interpreter/interpreter.rb +3 -3
- data/lib/interpreter/nudge_program.rb +10 -77
- data/lib/interpreter/parse.tab.rb +39 -21
- data/lib/interpreter/programPoints.rb +3 -6
- data/readme.md +36 -2
- data/spec/command_line/thor_spec.rb +51 -0
- data/spec/instructions/code/code_noop_spec.rb +1 -1
- data/spec/interpreter/codeblock_point_spec.rb +3 -4
- data/spec/interpreter/interpreter_spec.rb +4 -5
- data/spec/interpreter/nudge_program_spec.rb +37 -122
- data/spec/interpreter/value_point_spec.rb +9 -4
- data/spec/parsers/nudge_program_parser_spec.rb +105 -20
- data/spec/spec_helper.rb +36 -23
- data/templates/nudge_define_instruction.erb +6 -0
- data/templates/nudge_duplicate_instruction.erb +6 -0
- data/templates/nudge_equal_q_instruction.erb +19 -0
- data/templates/nudge_flush_instruction.erb +6 -0
- data/templates/nudge_pop_instruction.erb +6 -0
- data/templates/nudge_random_instruction.erb +13 -0
- data/templates/nudge_rotate_instruction.erb +6 -0
- data/templates/nudge_shove_instruction.erb +6 -0
- data/templates/nudge_swap_instruction.erb +6 -0
- data/templates/nudge_type_class.erb +50 -0
- data/templates/nudge_type_spec.erb +32 -0
- data/templates/nudge_yank_instruction.erb +6 -0
- data/templates/nudge_yankdup_instruction.erb +6 -0
- metadata +27 -14
- data/spec/interpreter/treetophelpers.rb +0 -120
@@ -5,9 +5,6 @@ include Nudge
|
|
5
5
|
|
6
6
|
|
7
7
|
describe "Nudge Program parsing" do
|
8
|
-
before(:each) do
|
9
|
-
@parser = NudgeCodeblockParser.new()
|
10
|
-
end
|
11
8
|
|
12
9
|
describe ": initializing a new NudgeProgram from a string" do
|
13
10
|
it "should check that it's been given a string" do
|
@@ -46,50 +43,25 @@ describe "Nudge Program parsing" do
|
|
46
43
|
NudgeProgram.new("value «int» \n«int» 8 \n«code» value «bool»").footnote_section.should ==
|
47
44
|
"«int» 8 \n«code» value «bool»"
|
48
45
|
end
|
49
|
-
|
50
|
-
it "should capture each individual footnote into #footnotes" do
|
51
|
-
NudgeProgram.new("do int_add").footnotes.should == {}
|
52
|
-
NudgeProgram.new("value «int» \n«bool» false").footnotes[:bool].should include("false")
|
53
|
-
|
54
|
-
tricky = NudgeProgram.new("value «int» \n«int» 8 \n«code» value «bool»").footnotes
|
55
|
-
tricky.keys.length.should == 2
|
56
|
-
tricky[:code].should == ["value «bool»"]
|
57
|
-
end
|
58
46
|
end
|
59
47
|
|
60
48
|
describe ": trimming whitespace from footnote values" do
|
61
|
-
it "should ignore leading whitespace" do
|
62
|
-
NudgeProgram.new("value «
|
63
|
-
NudgeProgram.new("value «
|
64
|
-
NudgeProgram.new("value «baz» \n«baz» 8").tokenized_footnote_section[:baz][0].should == "8"
|
65
|
-
NudgeProgram.new("value «baz» \n«baz»8").tokenized_footnote_section[:baz][0].should == "8"
|
49
|
+
it "should ignore (and not need) leading whitespace" do
|
50
|
+
NudgeProgram.new("value «x»\n«x» \t\n \f\n 111").linked_code.value.should == "111"
|
51
|
+
NudgeProgram.new("value «x»\n«x»111").linked_code.value.should == "111"
|
66
52
|
end
|
67
53
|
|
68
|
-
it "should should ignore trailing whitespace" do
|
69
|
-
NudgeProgram.new("value «
|
70
|
-
NudgeProgram.new("value «
|
71
|
-
NudgeProgram.new("value «foo» \n«foo» 9 ").tokenized_footnote_section[:foo][0].should == "9"
|
54
|
+
it "should should ignore (and not need) trailing whitespace" do
|
55
|
+
NudgeProgram.new("value «y»\n«y» 111\t\n \f\n ").linked_code.value.should == "111"
|
56
|
+
NudgeProgram.new("value «y»\n«y» 111\n«y» something").linked_code.value.should == "111"
|
72
57
|
end
|
73
58
|
|
74
59
|
it "should capture whitespace inside values" do
|
75
|
-
NudgeProgram.new("value «
|
76
|
-
NudgeProgram.new("value «bar» \n«bar» 9\n\n\n\n9").tokenized_footnote_section[:bar][0].
|
77
|
-
should == "9\n\n\n\n9"
|
78
|
-
NudgeProgram.new("value «bar» \n«bar» 9 9").tokenized_footnote_section[:bar][0].should == "9 9"
|
60
|
+
NudgeProgram.new("value «y»\n«y» 1\t\n1\t\n1 ").linked_code.value.should == "1\t\n1\t\n1"
|
79
61
|
end
|
80
62
|
|
81
63
|
it "should trim whitespace between footnotes" do
|
82
|
-
NudgeProgram.new("value «
|
83
|
-
tokenized_footnote_section.keys.length.should == 2
|
84
|
-
NudgeProgram.new("value «bar» \n«bar» 9\n \n\t\n«baz»9").
|
85
|
-
tokenized_footnote_section.keys.should include(:bar)
|
86
|
-
NudgeProgram.new("value «bar» \n«bar» 9\n \n\t\n«baz»9").
|
87
|
-
tokenized_footnote_section.keys.should include(:baz)
|
88
|
-
end
|
89
|
-
|
90
|
-
it "should avoid capturing newlines between footnotes" do
|
91
|
-
known_risk = NudgeProgram.new("block {value «mya»\nvalue «myb»}\n«myb» this is a b\n«mya» a")
|
92
|
-
known_risk.tokenized_footnote_section[:myb][0].should == "this is a b"
|
64
|
+
NudgeProgram.new("block {value «y» value «z»}\n«y» 111\f\t\n\t\t \n«z» something").linked_code.contents[0].value.should == "111"
|
93
65
|
end
|
94
66
|
end
|
95
67
|
end
|
@@ -133,6 +105,16 @@ describe "Nudge Program parsing" do
|
|
133
105
|
jeez = "block {" + ("block { " * 20 + "block {}" + "}" * 20) * 3 + "}"
|
134
106
|
NudgeProgram.new(jeez).tidy.split(/\n/).length.should == 64
|
135
107
|
end
|
108
|
+
|
109
|
+
it "should not produce footnotes" do
|
110
|
+
wordy = "block {value «code»}\n«code» value «int»\n«int» 9"
|
111
|
+
NudgeProgram.new(wordy).tidy.should == "block {\n value «code»}"
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should not produce footnotes even when there are unassigned ones" do
|
115
|
+
forgetful = "block {value «a» value «b» value «c»}"
|
116
|
+
NudgeProgram.new(forgetful).tidy.should == "block {\n value «a»\n value «b»\n value «c»}"
|
117
|
+
end
|
136
118
|
end
|
137
119
|
end
|
138
120
|
|
@@ -165,15 +147,6 @@ describe "Nudge Program parsing" do
|
|
165
147
|
end
|
166
148
|
|
167
149
|
|
168
|
-
describe "#contains_codevalues? method" do
|
169
|
-
it "should return true iff the raw code (including footnote_section) includes 'value «code»" do
|
170
|
-
NudgeProgram.new("do int_add").contains_codevalues?.should == false
|
171
|
-
NudgeProgram.new("value \t\t«code»").contains_codevalues?.should == true
|
172
|
-
NudgeProgram.new("block {block {value \n «code»}}").contains_codevalues?.should == true
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
|
177
150
|
# some examples worked by hand to test the
|
178
151
|
# depth-first association of values to footnotes
|
179
152
|
#
|
@@ -260,9 +233,10 @@ describe "Nudge Program parsing" do
|
|
260
233
|
tree2.blueprint.should == tree2.tidy
|
261
234
|
end
|
262
235
|
|
263
|
-
it "should produce
|
236
|
+
it "should NOT produce self#tidy for a CodeblockPoint program with unassigned footnotes" do
|
264
237
|
dangling = NudgeProgram.new("block {\t\t value «a»\nvalue «b»\n \n value «c»}")
|
265
|
-
dangling.blueprint.should ==
|
238
|
+
dangling.blueprint.should ==
|
239
|
+
"block {\n value «a»\n value «b»\n value «c»} \n«a»\n«b»\n«c»"
|
266
240
|
end
|
267
241
|
|
268
242
|
it "should put out the tidy form AND the footnotes in the right order" do
|
@@ -303,6 +277,7 @@ block { value «int» value «code» value «int»}
|
|
303
277
|
|
304
278
|
end
|
305
279
|
|
280
|
+
|
306
281
|
describe "contains_valuepoints?" do
|
307
282
|
it "should accept a string and return true if it contains any «» markup AT ALL" do
|
308
283
|
np = NudgeProgram.new("")
|
@@ -316,50 +291,6 @@ block { value «int» value «code» value «int»}
|
|
316
291
|
end
|
317
292
|
|
318
293
|
|
319
|
-
describe "pursue_more_footnotes method" do
|
320
|
-
before(:each) do
|
321
|
-
@nasty = "block {value «code» \nvalue «code» \nvalue «foo»}\n«code» value «foo»\n«code» block {value «code»}\n«foo» 1\n«foo» 2\n«code» value «foo»\n«foo» 3"
|
322
|
-
@simple = "block {value «code»}\n«code» value «int»\n«int» 2"
|
323
|
-
@boring = "value «code»\n«code» block {}"
|
324
|
-
@stringy = "value «code»\n«code» value «code»\n«code» value «code»\n«code» do X"
|
325
|
-
@filler = '['+ (" \n "*100) + ']'
|
326
|
-
@spacey = "value «code»\n«code» value «spacer»\n«spacer»#{@filler}"
|
327
|
-
@staged_program = NudgeProgram.new("")
|
328
|
-
|
329
|
-
def reprocess_using(new_code)
|
330
|
-
@staged_program.instance_variable_set(:@raw_code,new_code)
|
331
|
-
@staged_program.program_split!
|
332
|
-
@staged_program.relink_code!
|
333
|
-
end
|
334
|
-
end
|
335
|
-
|
336
|
-
it "should determine if the blueprint contains any ValuePoints if it is type code" do
|
337
|
-
@staged_program.should_receive(:contains_valuepoints?).with("block {}")
|
338
|
-
reprocess_using(@boring)
|
339
|
-
end
|
340
|
-
|
341
|
-
it "should (in the end) return the collected_footnotes string for this depth-first traversal" do
|
342
|
-
reprocess_using(@nasty)
|
343
|
-
@staged_program.linked_code.contents[0].raw.should == "value «foo»\n«foo» 1"
|
344
|
-
@staged_program.linked_code.contents[1].raw.should ==
|
345
|
-
"block {value «code»}\n«code» value «foo»\n«foo» 2"
|
346
|
-
@staged_program.linked_code.contents[2].raw.should == "3"
|
347
|
-
|
348
|
-
reprocess_using(@simple)
|
349
|
-
@staged_program.linked_code.contents[0].raw.should == "value «int»\n«int» 2"
|
350
|
-
|
351
|
-
reprocess_using(@boring)
|
352
|
-
@staged_program.linked_code.raw.should == "block {}"
|
353
|
-
|
354
|
-
reprocess_using(@stringy)
|
355
|
-
@staged_program.linked_code.raw.should == "value «code»\n«code» value «code»\n«code» do X"
|
356
|
-
|
357
|
-
reprocess_using(@spacey)
|
358
|
-
@staged_program.linked_code.raw.should == "value «spacer»\n«spacer» #{@filler}"
|
359
|
-
end
|
360
|
-
end
|
361
|
-
|
362
|
-
|
363
294
|
describe "preserving unused footnotes" do
|
364
295
|
before(:each) do
|
365
296
|
@all_extras = "value «foo»\n«bar» baz\n«qux» nothing"
|
@@ -389,55 +320,40 @@ block { value «int» value «code» value «int»}
|
|
389
320
|
huh.footnotes.should == {} # they didn't get used
|
390
321
|
end
|
391
322
|
|
392
|
-
it "should interpret an unparseable codesection as no code at all,
|
323
|
+
it "should interpret an unparseable codesection as no code at all, and drop footnotes" do
|
393
324
|
got_nuthin = NudgeProgram.new("block { hunh \n«int» 2")
|
394
325
|
got_nuthin.code_section.should == "block { hunh"
|
395
326
|
got_nuthin.linked_code.should be_a_kind_of(NilPoint)
|
396
327
|
got_nuthin.footnote_section.should == "«int» 2"
|
397
|
-
got_nuthin.footnotes.should == {
|
328
|
+
got_nuthin.footnotes.should == {} # it's not been used
|
398
329
|
end
|
399
330
|
|
400
331
|
|
401
|
-
it "should
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
332
|
+
it "should include a footnote for every reference, even if it has to create an empty one" do
|
333
|
+
nasty =
|
334
|
+
"block {value «code»\nvalue «code» \nvalue «foo»}\n«code» value «foo»\n«code» block {value «code»}\n«foo» 1"
|
335
|
+
|
336
|
+
shortstop = NudgeProgram.new(nasty)
|
337
|
+
r0 = "value «code» \n«code» value «foo»\n«foo» 1"
|
338
|
+
r1 = "value «code» \n«code» block {value «code»}\n«code»"
|
339
|
+
r2 = "value «foo» \n«foo»"
|
340
|
+
shortstop.linked_code.contents[0].blueprint.should == r0
|
341
|
+
shortstop.linked_code.contents[1].blueprint.should == r1
|
411
342
|
|
412
|
-
nasty_shorter = "block {value «code» \nvalue «code» \nvalue «foo»}\n«code» value «foo»\n«code» block {value «code»}\n«foo» 1"
|
413
|
-
shortstop = NudgeProgram.new(nasty_shorter)
|
414
|
-
shortstop.linked_code.contents[0].raw.should == "value «foo»\n«foo» 1"
|
415
|
-
shortstop.linked_code.contents[1].raw.should == "block {value «code»}"
|
416
|
-
shortstop.linked_code.contents[2].raw.should == nil
|
417
343
|
end
|
418
344
|
|
419
345
|
it "should collect unused footnotes" do
|
420
346
|
hmm = NudgeProgram.new("do int_add\n«nob» nothing")
|
421
|
-
hmm.footnotes[
|
347
|
+
hmm.footnotes["nob"].should include("nothing")
|
422
348
|
end
|
423
349
|
|
424
350
|
it "should act as specified above when one or more footnote is unparseable" do
|
425
|
-
# stupid_shorter: | associated values:
|
426
|
-
# ------------- | ------------------
|
427
|
-
# block { |
|
428
|
-
# value «code» | <- "value «foo»\n«foo» 1"
|
429
|
-
# value «code» | <- "some junk"
|
430
|
-
# value «foo»} | <- nil
|
431
|
-
# «code» value «foo» |
|
432
|
-
# «code» some junk |
|
433
|
-
# «foo» 1 |
|
434
351
|
|
435
352
|
stupid_shorter = "block {value «code» \nvalue «code» \nvalue «foo»}\n«code» value «foo»\n«code» some junk\n«foo» 1"
|
436
353
|
busted = NudgeProgram.new(stupid_shorter)
|
437
354
|
busted.linked_code.contents[0].raw.should == "value «foo»\n«foo» 1"
|
438
355
|
busted.linked_code.contents[1].raw.should == "some junk"
|
439
356
|
busted.linked_code.contents[2].raw.should == nil
|
440
|
-
|
441
357
|
end
|
442
358
|
end
|
443
359
|
|
@@ -589,7 +505,7 @@ block { value «int» value «code» value «int»}
|
|
589
505
|
"value «foo» \n«foo» •••"
|
590
506
|
|
591
507
|
valueful.replace_point(2,addedvalue).blueprint.should ==
|
592
|
-
"block {\n value «foo»\n value «code»} \n«foo» •••\n«code» value «bool»"
|
508
|
+
"block {\n value «foo»\n value «code»} \n«foo» •••\n«code» value «bool»\n«bool»"
|
593
509
|
|
594
510
|
valueful.replace_point(3,addedvalue).blueprint.should ==
|
595
511
|
"block {\n value «code»\n value «foo»} \n«code» block {value «int»}\n«int» 7\n«foo» •••"
|
@@ -652,7 +568,6 @@ block { value «int» value «code» value «int»}
|
|
652
568
|
end
|
653
569
|
|
654
570
|
it "should return a new NudgeProgram with the right ProgramPoint deleted" do
|
655
|
-
# "block {\n block {\n block {\n block {\n block {\n block {\n ref a}}}}}}"
|
656
571
|
result = @lodgepole_tree.delete_point(1)
|
657
572
|
result.blueprint.should == "block {}"
|
658
573
|
|
@@ -674,7 +589,7 @@ block { value «int» value «code» value «int»}
|
|
674
589
|
"block {}"
|
675
590
|
|
676
591
|
valueful.delete_point(2).blueprint.should ==
|
677
|
-
"block {\n value «code»} \n«code» value «bool»"
|
592
|
+
"block {\n value «code»} \n«code» value «bool»\n«bool»"
|
678
593
|
|
679
594
|
valueful.delete_point(3).blueprint.should ==
|
680
595
|
"block {\n value «code»} \n«code» block {value «int»}\n«int» 7"
|
@@ -69,7 +69,7 @@ describe "ValuePoint" do
|
|
69
69
|
|
70
70
|
|
71
71
|
it "should move to the appropriate stack when removed from the exec stack" do
|
72
|
-
ii = Interpreter.new(
|
72
|
+
ii = Interpreter.new("value «bool»\n«bool»true")
|
73
73
|
ii.step
|
74
74
|
ii.stacks[:bool].peek.raw.should == "true"
|
75
75
|
|
@@ -147,14 +147,14 @@ describe "ValuePoint" do
|
|
147
147
|
|
148
148
|
|
149
149
|
describe "#blueprint_parts" do
|
150
|
-
it "should
|
150
|
+
it "should return an Array with two parts: (1) self#tidy (2) the footnotes as a string" do
|
151
151
|
myL = ValuePoint.new("float", "-99.121001")
|
152
152
|
myL.blueprint_parts.should == ["value «float»","«float» -99.121001"]
|
153
153
|
myURI = ValuePoint.new("uri", "http://googol.com")
|
154
154
|
myURI.blueprint_parts.should == ["value «uri»","«uri» http://googol.com"]
|
155
|
-
|
155
|
+
|
156
156
|
myHuh = ValuePoint.new("missing")
|
157
|
-
myHuh.blueprint_parts.should == ["value «missing»",""]
|
157
|
+
myHuh.blueprint_parts.should == ["value «missing»","«missing»"]
|
158
158
|
|
159
159
|
myFUcode = ValuePoint.new("code", "block { value «code»}\n«code» value «int»\n«int» 8")
|
160
160
|
myFUcode.blueprint_parts.should == ["value «code»","«code» block { value «code»}\n«code» value «int»\n«int» 8"]
|
@@ -169,5 +169,10 @@ describe "ValuePoint" do
|
|
169
169
|
num = ValuePoint.new("int", 812)
|
170
170
|
num.blueprint.should == "value «int» \n«int» 812"
|
171
171
|
end
|
172
|
+
|
173
|
+
it "should not fail for valueless footnotes" do
|
174
|
+
myHuh = ValuePoint.new("missing")
|
175
|
+
myHuh.blueprint.should == "value «missing» \n«missing»"
|
176
|
+
end
|
172
177
|
end
|
173
178
|
end
|
@@ -16,9 +16,54 @@ describe "Nudge Program parser" do
|
|
16
16
|
"block{do int_add}" ,
|
17
17
|
"block{do int_add\ndo int_add value «foo»}"].each do |exp|
|
18
18
|
lambda{NudgeTree.from(exp)}.should_not raise_error
|
19
|
+
NudgeTree.from(exp)[:tree].should_not == nil
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
23
|
+
it "should return the right ProgramPoint class for InstructionPoints" do
|
24
|
+
["do int_add",
|
25
|
+
"do foo_bar",
|
26
|
+
"do x_1"].each do |exp|
|
27
|
+
NudgeTree.from(exp)[:tree].should be_a_kind_of(InstructionPoint)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return the right ProgramPoint class for ReferencePoints" do
|
32
|
+
["ref x88",
|
33
|
+
"ref a_1"].each do |exp|
|
34
|
+
NudgeTree.from(exp)[:tree].should be_a_kind_of(ReferencePoint)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return the right ProgramPoint class for ValuePoints" do
|
39
|
+
["value «x»" ,
|
40
|
+
"value «x_1»" ,
|
41
|
+
"value «xyz»" ,
|
42
|
+
"value «my_type»",
|
43
|
+
"value «x»\n«x» 8" ,
|
44
|
+
"value «x_1»\n«x_1» 9" ,
|
45
|
+
"value «xyz»\n«xyz» 10" ,
|
46
|
+
"value «my_type»\n«my_type» 11"].each do |exp|
|
47
|
+
NudgeTree.from(exp)[:tree].should be_a_kind_of(ValuePoint)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
it "should return the right ProgramPoint class for CodeblockPoints" do
|
54
|
+
["block {}" ,
|
55
|
+
"block {\t}" ,
|
56
|
+
"block {\n }" ,
|
57
|
+
"block { block { block {block{block{}}}} }",
|
58
|
+
"block {do int_add}" ,
|
59
|
+
"block{do int_add}" ,
|
60
|
+
"block{do int_add\ndo int_add value «foo»}\n«foo» baz"].each do |exp|
|
61
|
+
NudgeTree.from(exp)[:tree].should be_a_kind_of(CodeblockPoint)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
|
22
67
|
it "should not parse these examples" do
|
23
68
|
["value int (1)\ndo int_add",
|
24
69
|
" ",
|
@@ -31,17 +76,18 @@ describe "Nudge Program parser" do
|
|
31
76
|
"do this_not_real!", # actually, I may want this one
|
32
77
|
"ref 1x1",
|
33
78
|
"ref 1 x 1"].each do |junk|
|
34
|
-
|
79
|
+
NudgeTree.from(junk)[:tree].should be_a_kind_of(NilPoint)
|
35
80
|
end
|
36
81
|
end
|
37
82
|
|
83
|
+
|
84
|
+
|
38
85
|
it "should be happy with unicode" do
|
39
|
-
|
40
|
-
["value «a_∫»",
|
86
|
+
["value «a_éüîøö»",
|
41
87
|
"do β_assay",
|
42
|
-
"
|
43
|
-
"value
|
44
|
-
|
88
|
+
"ref Ünt_ADD",
|
89
|
+
"block {value «β_distribution»}"].each do |exp|
|
90
|
+
NudgeTree.from(exp)[:tree].should_not be_a_kind_of(NilPoint)
|
45
91
|
end
|
46
92
|
end
|
47
93
|
|
@@ -52,35 +98,74 @@ describe "Nudge Program parser" do
|
|
52
98
|
"block {\t}" ,
|
53
99
|
"block \n{\t}" ,
|
54
100
|
"block {\n }\n"].each do |exp|
|
55
|
-
|
101
|
+
NudgeTree.from(exp)[:tree].should_not be_a_kind_of(NilPoint)
|
56
102
|
end
|
57
103
|
end
|
58
104
|
|
105
|
+
|
59
106
|
it "should parse well-formed footnotes" do
|
60
|
-
|
61
|
-
NudgeTree.from("value «code»\n«int» 9\n«code» value «int»")
|
107
|
+
NudgeTree.from("value «code»\n«int» 9\n«code» value «int»")[:tree].should_not be_a_kind_of(NilPoint)
|
108
|
+
nt = NudgeTree.from("value «code»\n«int» 9\n«code» value «int»")
|
109
|
+
nt[:tree].should be_a_kind_of(ValuePoint)
|
110
|
+
nt[:tree].blueprint.should == "value «code» \n«code» value «int»\n«int» 9"
|
62
111
|
end
|
63
112
|
|
113
|
+
|
64
114
|
it "should work with multi-line footnotes" do
|
65
|
-
|
66
|
-
lambda{NudgeTree.from(
|
115
|
+
wordy = "value «code»\n«code» block {\ndo thing_1\n do thing_2}\n«int» 5"
|
116
|
+
lambda{NudgeTree.from(wordy)}.should_not raise_error
|
117
|
+
NudgeTree.from(wordy)[:tree].blueprint.should ==
|
118
|
+
"value «code» \n«code» block {\ndo thing_1\n do thing_2}"
|
67
119
|
end
|
68
|
-
|
69
|
-
|
70
|
-
|
120
|
+
|
121
|
+
|
122
|
+
it "should parse code with malformed footnotes (but they'll turn out weird)" do
|
123
|
+
busted = "value «code» \n«code» do thing\n«float 2» 9"
|
124
|
+
NudgeTree.from(busted).should_not be_a_kind_of(NilPoint)
|
125
|
+
NudgeTree.from(busted)[:tree].blueprint.should == "value «code» \n«code» do thing"
|
126
|
+
|
127
|
+
strange = "value «code» \n«float 2» 9\n«code» do thing\n"
|
128
|
+
NudgeTree.from(strange).should_not be_a_kind_of(NilPoint)
|
129
|
+
NudgeTree.from(strange)[:tree].blueprint.should == "value «code» \n«code» do thing"
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
it "should parse code with missing footnote values" do
|
134
|
+
lacuna = "value «code» \n«code»"
|
135
|
+
NudgeTree.from(lacuna).should_not be_a_kind_of(NilPoint)
|
136
|
+
NudgeTree.from(lacuna)[:tree].blueprint.should == "value «code» \n«code»"
|
137
|
+
|
138
|
+
lacuna = "block {value «code» value «code» value «int»} \n«code» do a\n«code» \n«int» 77"
|
139
|
+
NudgeTree.from(lacuna).should_not be_a_kind_of(NilPoint)
|
140
|
+
NudgeTree.from(lacuna)[:tree].blueprint.should ==
|
141
|
+
"block {\n value «code»\n value «code»\n value «int»} \n«code» do a\n«code»\n«int» 77"
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
it "should strip whitespace off the front and back of footnote values" do
|
146
|
+
spacey = "value «code»\n«code» \t\t value «float» \t\t\n«float» \t\n1.234"
|
147
|
+
NudgeTree.from(spacey)[:tree].blueprint.should ==
|
148
|
+
"value «code» \n«code» value «float»\n«float» 1.234"
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
it "should work for well-formed programs with insufficient footnotes by creating placeholders" do
|
153
|
+
lacuna = "block {value «code» \nvalue «code» \nvalue «foo»}\n«code» value «foo»\n«code» block {value «code»}\n«foo» 1"
|
154
|
+
NudgeTree.from(lacuna).should_not be_a_kind_of(NilPoint)
|
155
|
+
NudgeTree.from(lacuna)[:tree].blueprint.should ==
|
156
|
+
"block {\n value «code»\n value «code»\n value «foo»} \n«code» value «foo»\n«foo» 1\n«code» block {value «code»}\n«code»\n«foo»"
|
71
157
|
end
|
72
158
|
|
73
|
-
it "should strip whitespace off footnote values"
|
74
159
|
|
75
160
|
it "should not parse a footnotes-only string" do
|
76
|
-
|
77
|
-
|
161
|
+
NudgeTree.from("\n«int» 9\n«code» value «int»")[:tree].should be_a_kind_of(NilPoint)
|
162
|
+
NudgeTree.from("«int» 9\n«code» value «int»")[:tree].should be_a_kind_of(NilPoint)
|
78
163
|
end
|
79
164
|
|
165
|
+
|
80
166
|
it "should return extra footnotes" do
|
81
167
|
hash = NudgeTree.from("do unrelated\n«int» 9\n«code» value «int»")
|
82
168
|
hash[:tree].blueprint.should == "do unrelated"
|
83
169
|
hash[:unused].should == {"int"=>["9"], "code"=>["value «int»"]}
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|
170
|
+
end
|
171
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,37 +3,50 @@ $: << File.join(File.dirname(__FILE__), "/../lib")
|
|
3
3
|
|
4
4
|
|
5
5
|
require 'spec'
|
6
|
-
require 'interpreter/treetophelpers'
|
7
6
|
require 'pp'
|
8
7
|
require 'nudge'
|
9
8
|
require 'erb'
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
Spec::Runner.configure do |config|
|
11
|
+
def capture(stream)
|
12
|
+
begin
|
13
|
+
stream = stream.to_s
|
14
|
+
eval "$#{stream} = StringIO.new"
|
15
|
+
yield
|
16
|
+
result = eval("$#{stream}").string
|
17
|
+
ensure
|
18
|
+
eval("$#{stream} = #{stream.upcase}")
|
19
|
+
end
|
15
20
|
|
16
|
-
|
17
|
-
|
18
|
-
'lib', 'interpreter', 'grammars', "nudge_#{name}.treetop"))
|
19
|
-
end
|
21
|
+
result
|
22
|
+
end
|
20
23
|
|
24
|
+
def fixture(name, data = binding)
|
25
|
+
text = File.read(File.join(File.dirname(__FILE__), "/fixtures/#{name}.example"))
|
26
|
+
ERB.new(text).result(data)
|
27
|
+
end
|
21
28
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
@i1.should respond_to(:preconditions?)
|
29
|
+
def load_grammar(name)
|
30
|
+
Treetop.load(File.join(File.dirname(__FILE__), '..',
|
31
|
+
'lib', 'interpreter', 'grammars', "nudge_#{name}.treetop"))
|
26
32
|
end
|
33
|
+
|
34
|
+
shared_examples_for "every Nudge Instruction" do
|
35
|
+
|
36
|
+
it "should respond to \#preconditions?" do
|
37
|
+
@i1.should respond_to(:preconditions?)
|
38
|
+
end
|
27
39
|
|
28
|
-
|
29
|
-
|
30
|
-
|
40
|
+
it "should respond to \#setup" do
|
41
|
+
@i1.should respond_to(:setup)
|
42
|
+
end
|
31
43
|
|
32
|
-
|
33
|
-
|
34
|
-
|
44
|
+
it "should respond to \#derive" do
|
45
|
+
@i1.should respond_to(:derive)
|
46
|
+
end
|
35
47
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
48
|
+
it "should respond to \#celanup" do
|
49
|
+
@i1.should respond_to(:cleanup)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class <%=@instname%> < Instruction
|
2
|
+
|
3
|
+
def preconditions?
|
4
|
+
needs :<%=@type%>, 2
|
5
|
+
end
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@arg1 = @context.pop_value(:<%=@type%>)
|
9
|
+
@arg2 = @context.pop_value(:<%=@type%>)
|
10
|
+
end
|
11
|
+
|
12
|
+
def derive
|
13
|
+
@result = ValuePoint.new("bool", @arg1 == @arg2)
|
14
|
+
end
|
15
|
+
|
16
|
+
def cleanup
|
17
|
+
pushes :bool, @result
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class <%=@instname%> < Instruction
|
2
|
+
def preconditions?
|
3
|
+
true # no preconditions
|
4
|
+
end
|
5
|
+
def setup
|
6
|
+
end
|
7
|
+
def derive
|
8
|
+
@result = ValuePoint.new("<%=@type%>", <%=@camelized_type%>.any_value)
|
9
|
+
end
|
10
|
+
def cleanup
|
11
|
+
pushes :<%=@type%>, @result
|
12
|
+
end
|
13
|
+
end
|