nudge 0.1.2 → 0.1.3
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/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
|