nudge 0.1.1 → 0.1.2
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 +4 -2
- data/VERSION +1 -1
- data/bin/nudge +3 -0
- data/lib/cli/runner.rb +41 -0
- data/lib/interpreter/interpreter.rb +4 -4
- data/lib/interpreter/nudge_program.rb +8 -0
- data/lib/nudge.rb +2 -0
- data/readme.md +9 -1
- data/spec/command_line/command_line_spec.rb +131 -0
- data/spec/interpreter/interpreter_spec.rb +8 -5
- data/spec/interpreter/nudge_program_class_methods_spec.rb +32 -0
- metadata +12 -6
data/Rakefile
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'rake'
|
2
2
|
|
3
|
+
|
4
|
+
|
3
5
|
begin
|
4
6
|
require 'jeweler'
|
5
7
|
Jeweler::Tasks.new do |gemspec|
|
@@ -20,10 +22,10 @@ begin
|
|
20
22
|
# files
|
21
23
|
gemspec.files.exclude '_spikes/**'
|
22
24
|
gemspec.files.exclude('exploring_nudge/**')
|
23
|
-
|
24
25
|
end
|
25
26
|
|
26
27
|
Jeweler::GemcutterTasks.new
|
27
28
|
rescue LoadError
|
28
29
|
puts "Jeweler not available. Install it with: gem install jeweler"
|
29
|
-
end
|
30
|
+
end
|
31
|
+
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/bin/nudge
ADDED
data/lib/cli/runner.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
module Nudge
|
4
|
+
class CliRunner
|
5
|
+
attr_accessor :filename
|
6
|
+
attr_accessor :raw_code
|
7
|
+
attr_accessor :nudge_program
|
8
|
+
attr_accessor :interpreter
|
9
|
+
attr_accessor :options
|
10
|
+
attr_accessor :result
|
11
|
+
|
12
|
+
|
13
|
+
def initialize(filename, options={})
|
14
|
+
@filename = filename
|
15
|
+
@nudge_program = NudgeProgram.new("")
|
16
|
+
@options = options
|
17
|
+
@interpreter = Interpreter.new(@options)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def setup(options = {})
|
22
|
+
@raw_code = IO.open(@filename)
|
23
|
+
@interpreter.reset(@raw_code)
|
24
|
+
options[:variables].each {|name, val| @interpreter.bind_variable(name, val)} if options[:variables]
|
25
|
+
options[:sensors].each {|name, block| @interpreter.register_sensor(name, &block)} if options[:sensors]
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def run
|
30
|
+
return @interpreter.run
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
class CliParser
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -13,7 +13,7 @@ module Nudge
|
|
13
13
|
# * ... NilPoint, do nothing
|
14
14
|
|
15
15
|
class Interpreter
|
16
|
-
attr_accessor :program, :
|
16
|
+
attr_accessor :program, :step_limit, :steps
|
17
17
|
attr_accessor :stacks, :instructions_library, :variables, :names, :types
|
18
18
|
attr_accessor :last_name, :evaluate_references
|
19
19
|
attr_accessor :sensors
|
@@ -24,7 +24,7 @@ module Nudge
|
|
24
24
|
initialProgram = params[:program] || nil
|
25
25
|
@program = initialProgram
|
26
26
|
@types = params[:types] || NudgeType.all_types
|
27
|
-
@
|
27
|
+
@step_limit = params[:step_limit] || 3000
|
28
28
|
@sensors = Hash.new
|
29
29
|
|
30
30
|
instructions = params[:instructions] || Instruction.all_instructions
|
@@ -105,9 +105,9 @@ module Nudge
|
|
105
105
|
|
106
106
|
# Checks to see if either stopping condition applies:
|
107
107
|
# 1. Is the <b>:exec</b> stack empty?
|
108
|
-
# 2. Are the number of steps greater than self.
|
108
|
+
# 2. Are the number of steps greater than self.step_limit?
|
109
109
|
def notDone?
|
110
|
-
@stacks[:exec].depth > 0 && @steps < @
|
110
|
+
@stacks[:exec].depth > 0 && @steps < @step_limit
|
111
111
|
end
|
112
112
|
|
113
113
|
|
@@ -5,6 +5,12 @@ Treetop.load(File.join(File.dirname(__FILE__),'grammars', "nudge_codeblock.treet
|
|
5
5
|
|
6
6
|
module Nudge
|
7
7
|
class NudgeProgram
|
8
|
+
|
9
|
+
def self.random(options = {})
|
10
|
+
sourcecode = CodeType.any_value(options)
|
11
|
+
NudgeProgram.new(sourcecode)
|
12
|
+
end
|
13
|
+
|
8
14
|
|
9
15
|
attr_accessor :linked_code,:footnotes
|
10
16
|
attr_accessor :raw_code
|
@@ -22,6 +28,8 @@ module Nudge
|
|
22
28
|
|
23
29
|
|
24
30
|
|
31
|
+
|
32
|
+
|
25
33
|
def program_split!
|
26
34
|
split_at_first_guillemet=@raw_code.partition( /^(?=«)/ )
|
27
35
|
@code_section = split_at_first_guillemet[0].strip
|
data/lib/nudge.rb
CHANGED
data/readme.md
CHANGED
@@ -8,8 +8,16 @@ See the [project Wiki](http://github.com/Vaguery/Nudge/wikis) for a more thoroug
|
|
8
8
|
|
9
9
|
## Getting started
|
10
10
|
|
11
|
-
|
11
|
+
gem install nudge
|
12
12
|
|
13
|
+
As of this writing, the `nudge` gem can be used as a library in your Ruby programs. S Real Soon Now, it'll be part of a more interesting gem…
|
14
|
+
|
15
|
+
Meanwhile, try this:
|
16
|
+
|
17
|
+
require 'nudge'
|
18
|
+
include Nudge
|
19
|
+
|
20
|
+
my_program = Nudge.random(target_size_in_points:20) # generates
|
13
21
|
## Requirements
|
14
22
|
|
15
23
|
The interpreter code relies heavily on functional programming features of Ruby 1.9+. If you have not yet installed Ruby 1.9, I'd recommend using [rvm](http://rvm.beginrescueend.com/) to set up a special "sandbox" version of 1.9 until you're ready to upgrade your development or production machine.
|
@@ -0,0 +1,131 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "./../spec_helper")
|
3
|
+
include Nudge
|
4
|
+
|
5
|
+
|
6
|
+
describe "CliRunner" do
|
7
|
+
before(:each) do
|
8
|
+
IO.stub!(:open).and_return("xyz123") # to avoid hitting the file
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should capture the filename in an attribute" do
|
12
|
+
CliRunner.new("beeboop").filename.should == "beeboop"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should create an Interpreter instance" do
|
16
|
+
Interpreter.should_receive(:new)
|
17
|
+
CliRunner.new("beeboop")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should capture other options it gets" do
|
21
|
+
lambda{CliRunner.new("foo", types:["int"])}.should_not raise_error
|
22
|
+
a = CliRunner.new("bar", types:["bool"], step_limit: 10000)
|
23
|
+
a.options.should == {:types=>["bool"], :step_limit=>10000}
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should pass those options down into its Interpreter instance's initialization" do
|
27
|
+
lambda{CliRunner.new("foo", types:["int"])}.should_not raise_error
|
28
|
+
a = CliRunner.new("bar", types:["bool"], step_limit: 10000)
|
29
|
+
a.interpreter.step_limit.should == 10000
|
30
|
+
a.interpreter.types.should == ["bool"]
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
describe "setup" do
|
35
|
+
before(:each) do
|
36
|
+
IO.stub!(:open).and_return("ref g") # to avoid hitting the file
|
37
|
+
@cr = CliRunner.new("beebop")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should open the file and read in the program" do
|
41
|
+
IO.should_receive(:open).with("beebop").and_return("block {}")
|
42
|
+
CliRunner.new("beebop").setup
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should save the read filestream into #raw_code" do
|
46
|
+
@cr.setup
|
47
|
+
@cr.raw_code.should == "ref g"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should reset the Interpreter with the new program" do
|
51
|
+
@cr.setup
|
52
|
+
@cr.interpreter.program.should == @cr.raw_code
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should be able to accept an optional Hash of variable bindings" do
|
56
|
+
lambda{@cr.setup(variables:{"x" => ValuePoint.new("int", 9)})}.should_not raise_error
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should build those bindings into its interpreter" do
|
60
|
+
@cr.setup(variables:{"x" => ValuePoint.new("int",1002)})
|
61
|
+
@cr.interpreter.variables["x"].value.should == 1002
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should be able to accept an optional Hash of sensor definitions" do
|
65
|
+
lambda{@cr.setup(sensors:{"x" => Proc.new {|me| "hi there"}} )}.should_not raise_error
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should register those sensors in the interpreter" do
|
69
|
+
@cr.setup(sensors:{"x" => Proc.new {|me| "hi there"}})
|
70
|
+
@cr.interpreter.sensors["x"].call.should == "hi there"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
describe "run" do
|
76
|
+
before(:each) do
|
77
|
+
IO.stub!(:open).and_return("value «bool»\n«bool» false") # to avoid hitting the file
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should run the interpreter" do
|
81
|
+
cr = CliRunner.new("fakefile")
|
82
|
+
cr.setup
|
83
|
+
cr.interpreter.should_receive(:run)
|
84
|
+
cr.run
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should pass along the return value of the interpreter (the sensors' output)" do
|
88
|
+
cr = CliRunner.new("fakefile")
|
89
|
+
cr.setup
|
90
|
+
cr.interpreter.register_sensor("output") {|intrprtr| 82}
|
91
|
+
cr.run.should == {"output"=>82}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
describe CliParser do
|
98
|
+
describe "filename" do
|
99
|
+
it "should read the filename from ARGV"
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "step_limit" do
|
103
|
+
it "should be an optional parameter"
|
104
|
+
|
105
|
+
it "should parse the step_limit from ARGV"
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "types" do
|
109
|
+
it "should be an optional parameter"
|
110
|
+
|
111
|
+
it "should parse the type_names from ARGV"
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "instructions" do
|
115
|
+
it "should be an optional parameter"
|
116
|
+
|
117
|
+
it "should parse the instruction_names from ARGV"
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "variable bindings" do
|
121
|
+
it "should be an optional parameter"
|
122
|
+
|
123
|
+
it "should parse the variable bindings from ARGV"
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "sensors" do
|
127
|
+
it "should be an optional parameter"
|
128
|
+
|
129
|
+
it "should parse the sensor definitions from ARGV"
|
130
|
+
end
|
131
|
+
end
|
@@ -405,9 +405,9 @@ describe "stepping" do
|
|
405
405
|
lambda{3.times {@ii.step}}.should_not raise_error
|
406
406
|
end
|
407
407
|
|
408
|
-
it "should step only until the
|
408
|
+
it "should step only until the step_limit has not been reached, if the :exec stack is full" do
|
409
409
|
myCode = "block {"*20 + "}"*20
|
410
|
-
@ii.
|
410
|
+
@ii.step_limit = 3
|
411
411
|
@ii.reset(myCode)
|
412
412
|
lambda{15.times {@ii.step}}.should_not raise_error
|
413
413
|
end
|
@@ -431,8 +431,8 @@ describe "running" do
|
|
431
431
|
@ii.reset(myCode)
|
432
432
|
end
|
433
433
|
|
434
|
-
it "should run until the
|
435
|
-
@ii.
|
434
|
+
it "should run until the step_limit has been reached, if the :exec stack isn't empty" do
|
435
|
+
@ii.step_limit = 9
|
436
436
|
@ii.run
|
437
437
|
@ii.steps.should == 9
|
438
438
|
end
|
@@ -449,10 +449,13 @@ describe "running" do
|
|
449
449
|
@ii.steps.should == 0
|
450
450
|
end
|
451
451
|
|
452
|
-
it "should #fire_all_sensors at the end of running" do
|
452
|
+
it "should #fire_all_sensors at the end of running if any are defined" do
|
453
|
+
@ii.register_sensor("y")
|
453
454
|
@ii.should_receive(:fire_all_sensors)
|
454
455
|
@ii.run
|
455
456
|
end
|
457
|
+
|
458
|
+
it "should return Stack#inspect for all its stacks if no sensors are defined"
|
456
459
|
end
|
457
460
|
|
458
461
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "/../spec_helper")
|
3
|
+
include Nudge
|
4
|
+
|
5
|
+
|
6
|
+
describe NudgeProgram do
|
7
|
+
describe "#random" do
|
8
|
+
it "should return a new random-code program, given no params" do
|
9
|
+
lambda{NudgeProgram.random}.should_not raise_error
|
10
|
+
NudgeProgram.random.should be_a_kind_of(NudgeProgram)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should use the 'global' defaults as needed" do
|
14
|
+
NudgeProgram.random.points.should == 20
|
15
|
+
Instruction.should_receive(:all_instructions).at_least(1).times.and_return([IntAddInstruction])
|
16
|
+
NudgeType.should_receive(:all_types).at_least(1).times.and_return([IntType])
|
17
|
+
NudgeProgram.random
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should accept an overridden_parameters Hash" do
|
21
|
+
NudgeProgram.random(target_size_in_points:30).points.should == 30
|
22
|
+
NudgeProgram.random(probabilities: {b:10, r:0, v:0, i:0}).blueprint.
|
23
|
+
scan("block").length.should == 20 # there should be 20 occurrences of 'block' only!
|
24
|
+
NudgeProgram.random(reference_names:["x"], probabilities: {b:0, r:10, v:0, i:0}).blueprint.
|
25
|
+
scan("ref x").length.should == 19 # there should be 19 occurrences of 'ref x' in a wrapper
|
26
|
+
NudgeProgram.random(type_names:["foo"], probabilities: {b:0, r:0, v:10, i:0}).blueprint.
|
27
|
+
scan("foo").length.should == 38 # there should be 19 occurrences of 'value «foo»', plus fn's
|
28
|
+
NudgeProgram.random(instruction_names:["bool_xor"], probabilities: {b:0, r:0, v:0, i:10}).blueprint.
|
29
|
+
scan("bool_xor").length.should == 19 # there should be 19 occurrences of 'do bool_xor'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 2
|
9
|
+
version: 0.1.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Bill Tozier
|
@@ -16,8 +16,8 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-03-
|
20
|
-
default_executable:
|
19
|
+
date: 2010-03-28 00:00:00 -04:00
|
20
|
+
default_executable: nudge
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
23
|
name: treetop
|
@@ -49,8 +49,8 @@ dependencies:
|
|
49
49
|
version_requirements: *id002
|
50
50
|
description: Provides a Ruby library & CLI implementing a flexible Nudge Language interpreter, plus a set of generators for adding domain-specific instructions and types.
|
51
51
|
email: bill@vagueinnovation.com
|
52
|
-
executables:
|
53
|
-
|
52
|
+
executables:
|
53
|
+
- nudge
|
54
54
|
extensions: []
|
55
55
|
|
56
56
|
extra_rdoc_files:
|
@@ -60,6 +60,8 @@ files:
|
|
60
60
|
- LICENSE.txt
|
61
61
|
- Rakefile
|
62
62
|
- VERSION
|
63
|
+
- bin/nudge
|
64
|
+
- lib/cli/runner.rb
|
63
65
|
- lib/instructions/bool/bool_and.rb
|
64
66
|
- lib/instructions/bool/bool_define.rb
|
65
67
|
- lib/instructions/bool/bool_depth.rb
|
@@ -232,6 +234,7 @@ files:
|
|
232
234
|
- lib/interpreter/types/pushTypes.rb
|
233
235
|
- lib/nudge.rb
|
234
236
|
- readme.md
|
237
|
+
- spec/command_line/command_line_spec.rb
|
235
238
|
- spec/fixtures/just_block.example
|
236
239
|
- spec/fixtures/just_block_with_newline.example
|
237
240
|
- spec/fixtures/long_arithmetic.example
|
@@ -369,6 +372,7 @@ files:
|
|
369
372
|
- spec/interpreter/instruction_spec.rb
|
370
373
|
- spec/interpreter/interpreter_spec.rb
|
371
374
|
- spec/interpreter/nil_point_spec.rb
|
375
|
+
- spec/interpreter/nudge_program_class_methods_spec.rb
|
372
376
|
- spec/interpreter/nudge_program_spec.rb
|
373
377
|
- spec/interpreter/reference_point_spec.rb
|
374
378
|
- spec/interpreter/stack_spec.rb
|
@@ -411,6 +415,7 @@ signing_key:
|
|
411
415
|
specification_version: 3
|
412
416
|
summary: Nudge Language interpreter
|
413
417
|
test_files:
|
418
|
+
- spec/command_line/command_line_spec.rb
|
414
419
|
- spec/instructions/bool/bool_and_spec.rb
|
415
420
|
- spec/instructions/bool/bool_define_spec.rb
|
416
421
|
- spec/instructions/bool/bool_depth_spec.rb
|
@@ -542,6 +547,7 @@ test_files:
|
|
542
547
|
- spec/interpreter/instruction_spec.rb
|
543
548
|
- spec/interpreter/interpreter_spec.rb
|
544
549
|
- spec/interpreter/nil_point_spec.rb
|
550
|
+
- spec/interpreter/nudge_program_class_methods_spec.rb
|
545
551
|
- spec/interpreter/nudge_program_spec.rb
|
546
552
|
- spec/interpreter/reference_point_spec.rb
|
547
553
|
- spec/interpreter/stack_spec.rb
|