spec/interpreter/interpreter_spec.rb in nudge-0.0.2 vs spec/interpreter/interpreter_spec.rb in nudge-0.1.0
- old
+ new
@@ -1,25 +1,21 @@
+#encoding: utf-8
require File.join(File.dirname(__FILE__), "/../spec_helper")
-
include Nudge
describe "initialization" do
before(:each) do
@ii = Interpreter.new()
@ii.clear_stacks
end
- it "should have a #parser, which defaults to a new NudgeLanguageParser" do
- @ii.parser.should be_a_kind_of(NudgeLanguageParser)
- end
-
- it "should have an empty stacks Hash, empty initially" do
+ it "should have a #stacks Hash" do
@ii.stacks.should == {}
end
- it "should keep have an empty instructions attribute, a Hash" do
- @ii.instructions_library.should == Hash.new
+ it "should keep have (by default) a complete #instructions Hash" do
+ @ii.instructions_library.should_not == {}
end
it "should automatically create an entry if an unmentioned stack is referenced by a method" do
lambda{@ii.stacks[:pirate].peek}.should_not raise_error
@ii.stacks.should include(:pirate)
@@ -31,54 +27,54 @@
@ii.stacks.should_not include(:robot)
lambda{@ii.stacks[:robot].pop}.should_not raise_error
@ii.stacks.should include(:robot)
end
- it "should respond to #reset(listing) by parsing the listing and pushing it onto its exec stack" do
- checker = NudgeLanguageParser.new()
+ it "should respond to #reset(blueprint) by parsing the blueprint and pushing it onto its exec stack" do
myCode = "ref x"
@ii.reset(myCode)
@ii.stacks.should include(:exec)
@ii.stacks[:exec].should be_a_kind_of(Stack)
@ii.stacks[:exec].depth.should == 1
- @ii.stacks[:exec].peek.should be_a_kind_of(ChannelPoint)
- @ii.stacks[:exec].peek.name.should == checker.parse(myCode).to_points.name
+ @ii.stacks[:exec].peek.should be_a_kind_of(ReferencePoint)
+ @ii.stacks[:exec].peek.name.should == "x"
end
it "#reset should reset the #steps counter, too" do
@ii.steps = 100
@ii.reset("channel x")
@ii.steps.should == 0
end
it "should load a complex CodeBlock as a single item on the exec stack" do
- checker = NudgeLanguageParser.new()
myCode = "block {\ndo foo\n do bar\n block {\ndo baz}}"
@ii.reset(myCode)
@ii.stacks.should include(:exec)
@ii.stacks[:exec].depth.should == 1
whatGotPushed = @ii.stacks[:exec].peek
- whatGotPushed.should be_a_kind_of(CodeBlock)
- whatGotPushed.contents.length.should == checker.parse(myCode).to_points.contents.length
+ whatGotPushed.should be_a_kind_of(CodeblockPoint)
+ whatGotPushed.contents.length.should == 3
whatGotPushed.contents[1].name.should == "bar"
whatGotPushed.contents[2].contents[0].name.should == "baz"
end
- it "should accept a listing, which should default to an empty string" do
- ij = Interpreter.new(program:"literal int(7)")
- ij.stacks[:exec].peek.should be_a_kind_of(LiteralPoint)
+ it "should accept a blueprint, which should default to an empty string" do
+ Interpreter.new(program:"value «int» \n«int» 7").program.should == "value «int» \n«int» 7"
+ # Interpreter.new().program.should == ""
end
it "should have an #enable method that works for Instructions, adding them to the #instructions hash" do
+ @ii.disable_all_instructions
@ii.instructions_library.should == {}
@ii.enable(IntAddInstruction)
@ii.instructions_library[IntAddInstruction].should_not== nil
@ii.instructions_library[IntAddInstruction].should be_a_kind_of(IntAddInstruction)
@ii.instructions_library[IntAddInstruction].context.should == @ii
end
it "should have an #enable_all_instructions method" do
+ @ii.disable_all_instructions
@ii.instructions_library.should == {}
@ii.enable_all_instructions
@ii.instructions_library.keys.should == Instruction.all_instructions
end
@@ -100,31 +96,36 @@
it "should be an empty hash initially (by deafult)" do
@ii.variables.should == {}
end
it "should create a new entry when #bind_variable is called" do
- @ii.bind_variable("x",LiteralPoint.new(:int,88))
- @ii.variables["x"].should be_a_kind_of(LiteralPoint)
+ @ii.bind_variable("x",ValuePoint.new(:int,"88"))
+ @ii.variables["x"].should be_a_kind_of(ValuePoint)
@ii.variables["x"].type.should == :int
- @ii.variables["x"].value.should == 88
+ @ii.variables["x"].raw.should == "88"
end
- it "should raise an exception if the bound value is anything but a LiteralPoint" do
+ it "should raise an exception if the bound value is anything but a ProgramPoint" do
lambda {@ii.bind_variable("x", 88)}.should raise_error(ArgumentError)
lambda {@ii.bind_variable("x", [1,2])}.should raise_error(ArgumentError)
lambda {@ii.bind_variable("x", nil)}.should raise_error(ArgumentError)
+
+ lambda {@ii.bind_variable("x", ValuePoint.new("int", 88))}.should_not raise_error(ArgumentError)
+ lambda {@ii.bind_variable("x", ReferencePoint.new("x2"))}.should_not raise_error(ArgumentError)
+ lambda {@ii.bind_variable("x", InstructionPoint.new("matrix_a"))}.should_not raise_error(ArgumentError)
+ lambda {@ii.bind_variable("x", CodeblockPoint.new([]))}.should_not raise_error(ArgumentError)
end
it "should remove an new entry when #unbind_variable is called" do
- @ii.bind_variable("x",LiteralPoint.new(:int,88))
- @ii.variables["x"].value.should == 88
+ @ii.bind_variable("x",ValuePoint.new(:int,"99"))
+ @ii.variables["x"].raw.should == "99"
@ii.unbind_variable("x")
@ii.variables["x"].should == nil
end
it "should be resettable" do
- @ii.bind_variable("x",LiteralPoint.new(:int,88))
+ @ii.bind_variable("x",ValuePoint.new(:int,"77"))
@ii.reset_variables
@ii.variables.should_not include("x")
end
end
@@ -132,41 +133,41 @@
it "should be an empty hash initially" do
@ii.names.should == {}
end
it "should create a new entry when #bind_name is called" do
- @ii.bind_name("x",LiteralPoint.new(:bool,false))
- @ii.names["x"].should be_a_kind_of(LiteralPoint)
+ @ii.bind_name("x",ValuePoint.new(:bool,"false"))
+ @ii.names["x"].should be_a_kind_of(ValuePoint)
@ii.names["x"].type.should == :bool
- @ii.names["x"].value.should == false
+ @ii.names["x"].raw.should == "false"
end
- it "should raise an exception if the bound value is anything but a LiteralPoint" do
+ it "should raise an exception if the bound value is anything but a ValuePoint" do
lambda {@ii.bind_name("x", 88)}.should raise_error(ArgumentError)
lambda {@ii.bind_name("x", [1,2])}.should raise_error(ArgumentError)
lambda {@ii.bind_name("x", nil)}.should raise_error(ArgumentError)
end
it "should remove an new entry when #unbind_name is called" do
- @ii.bind_name("x",LiteralPoint.new(:int,88))
- @ii.names["x"].value.should == 88
+ @ii.bind_name("x",ValuePoint.new(:int,"55"))
+ @ii.names["x"].raw.should == "55"
@ii.unbind_name("x")
@ii.names["x"].should == nil
end
it "should be resettable" do
- @ii.bind_name("x",LiteralPoint.new(:int,88))
+ @ii.bind_name("x",ValuePoint.new(:int,"44"))
@ii.reset_names
@ii.names.should_not include("x")
end
end
describe "references" do
it "should return an Array of keys obtained by mergine variables into names (not vice versa)" do
- @ii.bind_name("x",LiteralPoint.new(:int,88))
- @ii.bind_variable("y",LiteralPoint.new(:int,88))
- @ii.bind_name("y",LiteralPoint.new(:bool,false))
+ @ii.bind_name("x",ValuePoint.new(:foo,"bar"))
+ @ii.bind_variable("y",ValuePoint.new(:baz,"qux"))
+ @ii.bind_name("y",ValuePoint.new(:bool,"false"))
@ii.references.should == @ii.names.merge(@ii.variables).keys
@ii.references.should_not == @ii.variables.merge(@ii.names).keys
end
end
@@ -200,13 +201,168 @@
@ii.enable(IntType)
@ii.enable(IntType)
@ii.types.length.should == 1
end
end
+end
+
+
+describe "Interpreter#peek" do
+ before(:each) do
+ @ii = Interpreter.new()
+ @ii.clear_stacks
+ end
+ it "should invoke a particular stack's #peek method" do
+ @ii.stacks[:donut].push(ValuePoint.new("donut", "0"))
+ lambda{@ii.peek(:donut)}.should_not raise_error
+ @ii.peek(:donut).value.should == "0"
+ end
+
+ it "should return nil if the stack doesn't exist" do
+ lambda{@ii.peek(:nonexistent)}.should_not raise_error
+ @ii.peek(:nonexistent).should == nil
+ end
+
+ it "should validate the stackname as a symbol" do
+ lambda{@ii.peek("not there")}.should raise_error(ArgumentError)
+ lambda{@ii.peek(99)}.should raise_error(ArgumentError)
+ end
end
+
+
+describe "Interpreter#peek_value" do
+ before(:each) do
+ @ii = Interpreter.new()
+ @ii.clear_stacks
+ end
+
+ it "should invoke a particular stack's #peek method" do
+ @ii.stacks[:donut].push(ValuePoint.new("donut", "0"))
+ lambda{@ii.peek_value(:donut)}.should_not raise_error
+ @ii.stacks[:donut].push(ValuePoint.new("donut", "O"))
+ @ii.peek_value(:donut).should == "O"
+ end
+
+ it "should return the value, not the entire ValuePoint" do
+ @ii.stacks[:int].push(ValuePoint.new("int", "8817"))
+ @ii.peek_value(:int).should == 8817
+ end
+
+
+ it "should return nil if the stack doesn't exist" do
+ lambda{@ii.peek_value(:nonexistent)}.should_not raise_error
+ @ii.peek_value(:nonexistent).should == nil
+ end
+
+ it "should validate the stackname as a symbol" do
+ lambda{@ii.peek_value("not there")}.should raise_error(ArgumentError)
+ lambda{@ii.peek_value(99)}.should raise_error(ArgumentError)
+ end
+end
+
+
+describe "Interpreter#pop" do
+ before(:each) do
+ @ii = Interpreter.new()
+ @ii.clear_stacks
+ end
+
+ it "should invoke a particular stack's #pop method" do
+ @ii.stacks[:crown].push(ValuePoint.new("crown", "WWW"))
+ lambda{@ii.pop(:crown)}.should_not raise_error
+
+ @ii.stacks[:crown].push(ValuePoint.new("crown", "WWW"))
+ got_crown = @ii.pop(:crown)
+ got_crown.should be_a_kind_of(ValuePoint)
+ got_crown.value.should == "WWW"
+ end
+
+ it "should return nil if the stack doesn't exist" do
+ lambda{@ii.pop(:nonexistent)}.should_not raise_error
+ @ii.pop(:nonexistent).should == nil
+ end
+
+ it "should validate the stackname as a symbol" do
+ lambda{@ii.pop("not there")}.should raise_error(ArgumentError)
+ lambda{@ii.pop(99)}.should raise_error(ArgumentError)
+ end
+end
+
+
+describe "Interpreter#pop_value" do
+ before(:each) do
+ @ii = Interpreter.new()
+ @ii.clear_stacks
+ end
+
+ it "should invoke a particular stack's #pop method" do
+ @ii.stacks[:box].push(ValuePoint.new("box", "[_]"))
+ lambda{@ii.pop_value(:box)}.should_not raise_error
+
+ @ii.stacks[:box].push(ValuePoint.new("box", "[_]"))
+ holder = @ii.pop_value(:box)
+ holder.should be_a_kind_of(String)
+ holder.should == "[_]"
+ end
+
+ it "should return nil if the stack doesn't exist" do
+ lambda{@ii.pop_value(:nonexistent)}.should_not raise_error
+ @ii.pop_value(:nonexistent).should == nil
+ end
+
+ it "should validate the stackname as a symbol" do
+ lambda{@ii.pop_value("not there")}.should raise_error(ArgumentError)
+ lambda{@ii.pop_value(99)}.should raise_error(ArgumentError)
+ end
+end
+
+
+describe "Interpreter#push" do
+ before(:each) do
+ @ii = Interpreter.new()
+ @ii.clear_stacks
+ end
+
+ it "should invoke a particular stack's #push method" do
+ lambda{@ii.push(:int,"9")}.should_not raise_error
+
+ @ii.push(:foo,"bar")
+ @ii.pop_value(:foo).should == "bar"
+
+ @ii.push(:baz,"qux")
+ @ii.peek(:baz).should be_a_kind_of(ValuePoint)
+ @ii.peek(:baz).value.should == "qux"
+ end
+
+ it "should allow passing in valid non-string values for that type" do
+ @ii.push(:int,9182)
+ @ii.pop_value(:int).should == 9182
+
+ @ii.push(:float,8.765)
+ @ii.pop_value(:float).should == 8.765
+
+ @ii.push(:bool,true)
+ @ii.pop_value(:bool).should == true
+
+ @ii.push(:bool,false)
+ @ii.peek(:bool).raw.should == "false"
+ end
+
+ it "should have a default value of an empty string" do
+ @ii.push(:matrix)
+ @ii.pop(:matrix).raw.should == ""
+ end
+
+ it "should validate the stackname as a symbol" do
+ lambda{@ii.push("backwards", :int)}.should raise_error(ArgumentError)
+ lambda{@ii.push("int")}.should raise_error(ArgumentError)
+ end
+end
+
+
describe "stepping" do
before(:each) do
@ii = Interpreter.new()
@ii.clear_stacks
end
@@ -254,13 +410,51 @@
@ii.steps.should == 20
end
it "should do nothing if the :exec stack starts empty" do
@ii.reset()
+ puts @ii.stacks[:exec].depth
@ii.run
@ii.steps.should == 0
end
end
-describe "channel setup" do
+
+describe "resetting" do
+ it "should clear the steps" do
+ ii = Interpreter.new(program:"block {ref a ref b}")
+ ii.run
+ ii.steps.should == 3
+ ii.reset
+ ii.steps.should == 0
+ end
+
+ it "should clear all names" do
+ ii = Interpreter.new
+ ii.bind_name("a", ValuePoint.new("int",3))
+ ii.names.keys.should == ["a"]
+ ii.reset
+ ii.names.keys.should == []
+ end
+
+ it "should clear all stacks, except the program" do
+ ii = Interpreter.new
+ ii.stacks[:foo].push(ValuePoint.new("foo", "100101"))
+ ii.reset
+ ii.stacks[:foo].depth.should == 0
+ end
+
+ it "should clear the program, if none is given" do
+ ii = Interpreter.new(program:"block {}")
+ ii.reset
+ ii.program.should == nil
+ end
+
+ it "should not affect variable bindings" do
+ ii = Interpreter.new
+ ii.bind_variable("a", ValuePoint.new("int",3))
+ ii.variables.keys.should == ["a"]
+ ii.reset
+ ii.variables.keys.should == ["a"]
+ end
end