nudge 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.2.0
@@ -28,6 +28,10 @@ class Instruction
28
28
  class MissingInstructionError < RuntimeError
29
29
  end
30
30
 
31
+ class CodeOversizeError < ArgumentError
32
+ end
33
+
34
+
31
35
  def initialize(context)
32
36
  @context = context
33
37
  end
@@ -51,6 +55,9 @@ class Instruction
51
55
 
52
56
 
53
57
  def pushes(stackName, literal)
58
+ if (stackName.to_s == "code") && (literal.value.length > self.context.code_char_limit)
59
+ raise(CodeOversizeError, ":code cannot have more than #{self.context.code_char_limit} chars")
60
+ end
54
61
  @context.stacks[stackName].push literal
55
62
  end
56
63
 
@@ -62,7 +69,7 @@ class Instruction
62
69
  self.cleanup
63
70
  end
64
71
  rescue NotEnoughStackItems, MissingInstructionError,
65
- InstructionMethodError, NaNResultError, FloatDomainError => exc
72
+ InstructionMethodError, NaNResultError, FloatDomainError, CodeOversizeError => exc
66
73
  msg = ValuePoint.new("error", exc.message)
67
74
  pushes :error, msg
68
75
  end
@@ -17,6 +17,8 @@ module Nudge
17
17
  attr_accessor :stacks, :instructions_library, :variables, :names, :types
18
18
  attr_accessor :last_name, :evaluate_references
19
19
  attr_accessor :sensors
20
+ attr_accessor :code_char_limit
21
+ attr_accessor :start_time, :time_limit
20
22
 
21
23
 
22
24
  # A program to be interpreted can be passed in as an optional parameter
@@ -25,6 +27,8 @@ module Nudge
25
27
  @program = initialProgram
26
28
  @types = params[:types] || NudgeType.all_types
27
29
  @step_limit = params[:step_limit] || 3000
30
+ @time_limit = params[:time_limit] || 60.0 # seconds
31
+ @code_char_limit = params[:code_char_limit] || 2000
28
32
  @sensors = Hash.new
29
33
 
30
34
  instructions = params[:instructions] || Instruction.all_instructions
@@ -61,6 +65,7 @@ module Nudge
61
65
  @stacks[:exec].push(NudgeProgram.new(program).linked_code)
62
66
  end
63
67
  @steps = 0
68
+ @start_time = Time.now
64
69
  @evaluate_references = true
65
70
  end
66
71
 
@@ -107,7 +112,9 @@ module Nudge
107
112
  # 1. Is the <b>:exec</b> stack empty?
108
113
  # 2. Are the number of steps greater than self.step_limit?
109
114
  def notDone?
110
- @stacks[:exec].depth > 0 && @steps < @step_limit
115
+ @stacks[:exec].depth > 0 &&
116
+ @steps < @step_limit &&
117
+ (Time.now-@start_time)<@time_limit
111
118
  end
112
119
 
113
120
 
@@ -132,6 +139,7 @@ module Nudge
132
139
 
133
140
  # invoke self.step() until a termination condition is true
134
141
  def run
142
+ @start_time = Time.now
135
143
  while notDone?
136
144
  self.step
137
145
  end
@@ -1,7 +1,4 @@
1
1
  #encoding: utf-8
2
- require 'treetop'
3
- Treetop.load(File.join(File.dirname(__FILE__),'grammars', "nudge_codeblock.treetop"))
4
-
5
2
 
6
3
  module Nudge
7
4
  class NudgeProgram
@@ -22,14 +19,10 @@ module Nudge
22
19
  raise(ArgumentError, "NudgeProgram.new should be passed a string") unless sourcecode.kind_of?(String)
23
20
  @raw_code = sourcecode
24
21
 
25
- # snipped out:
26
- # program_split!
27
22
  split_at_first_guillemet=@raw_code.partition( /^(?=«)/ )
28
23
  @code_section = split_at_first_guillemet[0].strip
29
24
  @footnote_section = split_at_first_guillemet[2].strip
30
25
 
31
- #snipped out:
32
- #relink_code!
33
26
  parsed_code = NudgeTree.from(@raw_code)
34
27
  @linked_code = parsed_code[:tree]
35
28
  @footnotes = parsed_code[:unused]
@@ -152,14 +145,13 @@ module Nudge
152
145
 
153
146
 
154
147
  def parses?(program_blueprint = @code_section)
155
- (NudgeCodeblockParser.new.parse(program_blueprint) != nil)
148
+ !NudgeTree.from(program_blueprint)[:tree].kind_of?(NilPoint)
156
149
  end
157
150
 
158
151
 
159
152
 
160
153
  def tidy
161
- framework = NudgeCodeblockParser.new.parse(@code_section)
162
- framework ? framework.tidy : ""
154
+ NudgeTree.from(@raw_code)[:tree].tidy
163
155
  end
164
156
 
165
157
 
data/lib/nudge.rb CHANGED
@@ -1,22 +1,10 @@
1
1
  $: << File.join(File.dirname(__FILE__), "/../lib")
2
2
 
3
3
  require 'rubygems'
4
- require 'treetop'
5
4
  require 'active_support'
6
5
 
7
6
  require 'interpreter/parse.tab'
8
7
 
9
- require 'interpreter/grammars/nudge_common'
10
-
11
- require 'interpreter/grammars/nudge_value_helpers'
12
- require 'interpreter/grammars/nudge_reference_helpers'
13
- require 'interpreter/grammars/nudge_instruction_helpers'
14
- require 'interpreter/grammars/nudge_codeblock_helpers'
15
- require 'interpreter/grammars/nudge_reference'
16
- require 'interpreter/grammars/nudge_instruction'
17
- require 'interpreter/grammars/nudge_value'
18
- require 'interpreter/grammars/nudge_codeblock'
19
-
20
8
  require 'interpreter/nudge_program'
21
9
 
22
10
  require 'cli/runner'
data/readme.md CHANGED
@@ -58,7 +58,9 @@ The interpreter code relies heavily on functional programming features of Ruby 1
58
58
 
59
59
  The following gems need to be present to run the code:
60
60
 
61
- * [treetop](http://treetop.rubyforge.org/)
62
- * [activesupport](http://as.rubyonrails.org/)
61
+ * [activesupport](http://as.rubyonrails.org/) (`gem install activesupport`)
62
+
63
+ To use the fancypants command line generators we're building, you'll need thor:
64
+ * [thor](http://github.com/wycats/thor/) (`gem install thor`)
63
65
 
64
- and you will want [rspec](http://rspec.info/) to be able to run the specs and confirm the codebase works on your system.
66
+ and you will definitely want [rspec](http://rspec.info/) to be able to run the specs and confirm the codebase works on your system: `gem install rspec`.
@@ -15,6 +15,7 @@ describe "Instruction has a master list" do
15
15
  end
16
16
  end
17
17
 
18
+
18
19
  describe "capturing errors" do
19
20
  describe "NotEnoughStackItems" do
20
21
  describe "#preconditions?" do
@@ -36,5 +37,16 @@ describe "capturing errors" do
36
37
  context.stacks[:error].peek.blueprint.should include "needs IntAddInstruction"
37
38
  end
38
39
  end
39
-
40
+ end
41
+
42
+
43
+ describe ":code stack has a special rule" do
44
+ it "should be impossible to use #pushes to push a :code item that is too large for the context" do
45
+ small_box = Interpreter.new("block {}", code_char_limit:20)
46
+ small_code = ValuePoint.new("code","block { do a }")
47
+ long_code = ValuePoint.new("code","block { do a do b do c do d do e do f do g }")
48
+ throwaway = IntAddInstruction.new(small_box)
49
+ lambda{throwaway.pushes(:code, long_code)}.should raise_error(Instruction::CodeOversizeError)
50
+ lambda{throwaway.pushes(:code, small_code)}.should_not raise_error(Instruction::CodeOversizeError)
51
+ end
40
52
  end
@@ -68,6 +68,7 @@ describe IntPowerInstruction do
68
68
  context.peek(:error).blueprint.should include("Infinity")
69
69
  context.stacks[:int].depth.should == 0
70
70
  end
71
+
71
72
  end
72
73
  end
73
74
  end
@@ -45,12 +45,30 @@ describe "initialization" do
45
45
  @ii.steps.should == 0
46
46
  end
47
47
 
48
+ it "#reset should reset the start_time counter to 0" do
49
+ @ii.start_time = 999999999999
50
+ @ii.reset
51
+ @ii.start_time.should be_a_kind_of(Time)
52
+ end
53
+
48
54
  it "#reset should reset the #sensors Hash" do
49
55
  @ii.register_sensor("z") {1201}
50
56
  @ii.reset
51
57
  @ii.sensors["z"].should == nil
52
58
  end
53
59
 
60
+ it "should have a code_char_limit" do
61
+ lambda{@ii.code_char_limit}.should_not raise_error
62
+ end
63
+
64
+ it "should have a default code_char_limit of 2000 characters" do
65
+ @ii.code_char_limit.should == 2000
66
+ end
67
+
68
+ it "should be possible to set code_char_limit with an option" do
69
+ Interpreter.new("block {}",code_char_limit:171).code_char_limit.should == 171
70
+ end
71
+
54
72
 
55
73
  it "should load a complex CodeBlock as a single item on the exec stack" do
56
74
  myCode = "block {\ndo foo\n do bar\n block {\ndo baz}}"
@@ -421,6 +439,13 @@ describe "stepping" do
421
439
  @ii.steps.should == 20
422
440
  end
423
441
 
442
+ it "should step only until its time_limit is reached or exceeded" do
443
+ @ii.reset("block {}")
444
+ @ii.start_time = (Time.now - 10000)
445
+ @ii.run
446
+ @ii.steps.should == 1
447
+ end
448
+
424
449
  end
425
450
 
426
451
  describe "running" do
@@ -489,7 +514,7 @@ describe "resetting" do
489
514
  end
490
515
 
491
516
  it "should not affect variable bindings" do
492
- ii = Interpreter.new
517
+ ii = Interpreter.new("block {}")
493
518
  ii.bind_variable("a", ValuePoint.new("int",3))
494
519
  ii.variables.keys.should == ["a"]
495
520
  ii.reset
@@ -1,6 +1,5 @@
1
1
  #encoding: utf-8
2
2
  require File.join(File.dirname(__FILE__), "./../spec_helper")
3
- load_grammar('codeblock')
4
3
  include Nudge
5
4
 
6
5
 
data/spec/spec_helper.rb CHANGED
@@ -4,7 +4,7 @@ $: << File.join(File.dirname(__FILE__), "/../lib")
4
4
 
5
5
  require 'spec'
6
6
  require 'pp'
7
- require 'nudge'
7
+ require 'lib/nudge'
8
8
  require 'erb'
9
9
 
10
10
  Spec::Runner.configure do |config|
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
- - 3
9
- version: 0.1.3
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Bill Tozier
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-04-01 00:00:00 -04:00
19
+ date: 2010-04-08 00:00:00 -04:00
20
20
  default_executable: nudge
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -216,15 +216,6 @@ files:
216
216
  - lib/instructions/name/name_unbind.rb
217
217
  - lib/instructions/name/name_yank.rb
218
218
  - lib/instructions/name/name_yankdup.rb
219
- - lib/interpreter/grammars/nudge_codeblock.treetop
220
- - lib/interpreter/grammars/nudge_codeblock_helpers.rb
221
- - lib/interpreter/grammars/nudge_common.treetop
222
- - lib/interpreter/grammars/nudge_instruction.treetop
223
- - lib/interpreter/grammars/nudge_instruction_helpers.rb
224
- - lib/interpreter/grammars/nudge_reference.treetop
225
- - lib/interpreter/grammars/nudge_reference_helpers.rb
226
- - lib/interpreter/grammars/nudge_value.treetop
227
- - lib/interpreter/grammars/nudge_value_helpers.rb
228
219
  - lib/interpreter/interpreter.rb
229
220
  - lib/interpreter/nudge_program.rb
230
221
  - lib/interpreter/parse.tab.rb
@@ -1,17 +0,0 @@
1
- require 'nudge'
2
-
3
-
4
- grammar NudgeCodeblock
5
- include NudgeCommon
6
- include NudgeReference
7
- include NudgeInstruction
8
- include NudgeValue
9
-
10
- rule codesection
11
- value / instruction / reference / (block_statement <CodeblockParseNode>)
12
- end
13
-
14
- rule block_statement
15
- 'block' spcs? '{' spcs? block_contents:(codesection spcs?)* '}'
16
- end
17
- end
@@ -1,19 +0,0 @@
1
- # coding: utf-8
2
- module CodeblockParseNode
3
- def contents
4
- block_contents.elements.collect {|e| e.elements[0]}
5
- end
6
-
7
- def tidy(level=1)
8
- tt = "block {"
9
- indent = level*2
10
- contents.each {|item| tt += ("\n" + (" "*indent) + item.tidy(level+1))}
11
- tt += "}"
12
- return tt
13
- end
14
-
15
- def to_point
16
- c = CodeblockPoint.new(contents.collect {|e| e.to_point})
17
- end
18
- end
19
-
@@ -1,15 +0,0 @@
1
- # encoding: utf-8
2
- grammar NudgeCommon
3
- rule common
4
- spcs / alphas_and_underscores
5
- end
6
-
7
- rule spcs
8
- [\s\t\n]+
9
- end
10
-
11
- rule alphas_and_underscores
12
- [\p{Alpha}] [_\p{Alnum}/u]*
13
- end
14
-
15
- end
@@ -1,14 +0,0 @@
1
- #encoding: utf-8
2
- require 'interpreter/grammars/nudge_common'
3
-
4
- grammar NudgeInstruction
5
- include NudgeCommon
6
-
7
- rule instruction
8
- 'do' spcs opcode <InstructionParseNode>
9
- end
10
-
11
- rule opcode
12
- alphas_and_underscores
13
- end
14
- end
@@ -1,14 +0,0 @@
1
- # coding: utf-8
2
- class InstructionParseNode < Treetop::Runtime::SyntaxNode
3
- def instruction_name
4
- opcode.text_value
5
- end
6
-
7
- def tidy(level=1)
8
- "do #{instruction_name}"
9
- end
10
-
11
- def to_point
12
- InstructionPoint.new(instruction_name)
13
- end
14
- end
@@ -1,9 +0,0 @@
1
- require 'interpreter/grammars/nudge_common'
2
-
3
- grammar NudgeReference
4
- include NudgeCommon
5
-
6
- rule reference
7
- 'ref' spcs vname:alphas_and_underscores <ReferenceParseNode>
8
- end
9
- end
@@ -1,14 +0,0 @@
1
- # coding: utf-8
2
- class ReferenceParseNode < Treetop::Runtime::SyntaxNode
3
- def variable_name
4
- vname.text_value
5
- end
6
-
7
- def tidy(level=1)
8
- "ref #{variable_name}"
9
- end
10
-
11
- def to_point
12
- ReferencePoint.new(variable_name)
13
- end
14
- end
@@ -1,14 +0,0 @@
1
- # encoding: utf-8
2
- require 'interpreter/grammars/nudge_common'
3
-
4
- grammar NudgeValue
5
- include NudgeCommon
6
-
7
- rule value
8
- 'value' spcs? '«' footnote_type '»' <ValueParseNode>
9
- end
10
-
11
- rule footnote_type
12
- alphas_and_underscores
13
- end
14
- end
@@ -1,19 +0,0 @@
1
- # coding: utf-8
2
- class ValueParseNode < Treetop::Runtime::SyntaxNode
3
- def type=(new_type)
4
- @type = new_type
5
- end
6
-
7
- def type
8
- @type ||= footnote_type.text_value
9
- end
10
-
11
- def tidy(level=1)
12
- "value «#{type}»"
13
- end
14
-
15
- def to_point
16
- return ValuePoint.new(type)
17
- end
18
-
19
- end