nudge 0.2.3 → 0.2.4

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 CHANGED
@@ -17,7 +17,6 @@ begin
17
17
 
18
18
  # dependencies
19
19
  gemspec.add_dependency('activesupport', '>= 2.3.5')
20
- gemspec.add_dependency('thor', '>= 0.13')
21
20
 
22
21
  # files
23
22
  gemspec.files.exclude '_spikes/**'
data/Thorfile CHANGED
@@ -6,10 +6,26 @@ class Extend_Nudge < Thor::Group
6
6
  # Define arguments and options
7
7
  argument :project_name
8
8
  class_option :test_framework, :default => :rspec
9
-
9
+ desc "Creates a new project folder structure for Nudge types, instructions and specs"
10
+
11
+
10
12
  def self.source_root
11
13
  File.dirname(__FILE__)
12
14
  end
15
+
16
+ def create_project_folder
17
+ dirname = "#{Extend_Nudge.source_root}/#{project_name}"
18
+ puts dirname
19
+ if Dir.exist?(dirname) then
20
+ puts "project directory 'dirname' already exists"
21
+ else
22
+ empty_directory(dirname)
23
+ empty_directory("#{dirname}/lib")
24
+ empty_directory("#{dirname}/lib/instructions")
25
+ empty_directory("#{dirname}/lib/interpreter/types")
26
+ empty_directory("#{dirname}/spec")
27
+ end
28
+ end
13
29
  end
14
30
 
15
31
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.3
1
+ 0.2.4
@@ -2,16 +2,20 @@
2
2
  module Nudge
3
3
 
4
4
  # The Interpreter class executes the Push3-like language loop:
5
- # 1. Pop the top item off the <b>:exec</b> Stack
5
+ # 1. Pop the top item off the <tt>:exec</tt> Stack
6
6
  # 2. If it is a(n)...
7
7
  # * ... InstructionPoint, execute that instruction's go() method;
8
8
  # * ... ValuePoint, push its value to the Stack it names;
9
- # * ... ReferencePoint (Variable or Name), ...
9
+ # * ... ReferencePoint (a reference to a Variable or Name), ...
10
10
  # * ... if it's bound to a value, push the bound value onto the <b>:exec</b> Stack;
11
11
  # * ... if it's not bound, push the name itself onto the <b>:name</b> Stack;
12
12
  # * ... CodeblockPoint, push its #contents (in the same order) back onto the <b>:exec</b> Stack
13
13
  # * ... NilPoint, do nothing
14
-
14
+ #
15
+ # This cycle repeats until one of the termination conditions is met:
16
+ # * nothing more remains on the <tt>:exec/tt> stack
17
+ # * the number of cycles meets or exceeds the <tt>step_limit</tt>
18
+ # * the wall-clock time meets or exceeds the <tt>time_limit</tt>
15
19
  class Interpreter
16
20
  attr_accessor :program, :step_limit, :steps
17
21
  attr_accessor :stacks, :instructions_library, :variables, :names, :types
@@ -21,7 +25,6 @@ module Nudge
21
25
  attr_accessor :start_time, :time_limit
22
26
 
23
27
 
24
- # A program to be interpreted can be passed in as an optional parameter
25
28
  def initialize(program = nil, params = {})
26
29
  initialProgram = program
27
30
  @program = initialProgram
@@ -55,7 +58,10 @@ module Nudge
55
58
  # * parses the program
56
59
  # * if it parses, pushes it onto the <b>:exec</b> Stack
57
60
  # * (and if it doesn't parse, leaves all stacks empty)
58
- # * resets the @step counter.
61
+ # * resets the @step counter
62
+ # * resets the name assignments
63
+ # * resets the start_time (intentional redundancy)
64
+ # * resets a number of state variables
59
65
  def reset(program=nil)
60
66
  @program = program
61
67
  self.clear_stacks
@@ -70,38 +76,46 @@ module Nudge
70
76
  end
71
77
 
72
78
 
79
+
80
+ # Deletes all items from all stacks
73
81
  def clear_stacks
74
82
  @stacks = Hash.new {|hash, key| hash[key] = Stack.new(key) }
75
83
  end
76
84
 
77
85
 
86
+ # Returns the count of items in a given stack
78
87
  def depth(stackname)
79
88
  @stacks[stackname].depth
80
89
  end
81
90
 
82
91
 
92
+ # Returns a link to the top item in a given stack (not its value)
83
93
  def peek(stackname)
84
94
  @stacks[stackname].peek
85
95
  end
86
96
 
87
97
 
98
+ # Returns a link to the value of the top item in a given stack
88
99
  def peek_value(stackname)
89
100
  item = @stacks[stackname].peek
90
101
  item.nil? ? nil : item.value
91
102
  end
92
103
 
93
104
 
105
+ # Removes the top item from a given stack and returns it
94
106
  def pop(stackname)
95
107
  @stacks[stackname].pop
96
108
  end
97
109
 
98
110
 
111
+ # Removes the top item from a given stack and returns its value
99
112
  def pop_value(stackname)
100
113
  item = @stacks[stackname].pop
101
114
  item.nil? ? nil : item.value
102
115
  end
103
116
 
104
117
 
118
+ # Adds a new ValuePoint item, with the given value, to the named stack
105
119
  def push(stackname, value="")
106
120
  @stacks[stackname].push(ValuePoint.new(stackname, value))
107
121
  end
@@ -111,6 +125,7 @@ module Nudge
111
125
  # Checks to see if either stopping condition applies:
112
126
  # 1. Is the <b>:exec</b> stack empty?
113
127
  # 2. Are the number of steps greater than self.step_limit?
128
+ # 3. Has the total time since recorded self.start_time exceeded self.time_limit?
114
129
  def notDone?
115
130
  @stacks[:exec].depth > 0 &&
116
131
  @steps < @step_limit &&
@@ -120,9 +135,12 @@ module Nudge
120
135
 
121
136
  # Execute one cycle of the Push3 interpreter rule:
122
137
  # 1. check termination conditions with self.notDone()?
123
- # 2. pop one item from <b>:exec</b>
124
- # 3. call its go() method
138
+ # 2. pop one item from <tt>:exec</tt>
139
+ # 3. call that item's #go method
125
140
  # 4. increment the step counter self#steps
141
+ #
142
+ # Note that the start_time attribute is not adjusted; if called a long time after resetting,
143
+ # it may time out unexpectedly.
126
144
  def step
127
145
  if notDone?
128
146
  nextPoint = @stacks[:exec].pop
@@ -132,6 +150,7 @@ module Nudge
132
150
  end
133
151
 
134
152
 
153
+ # Returns an Array containing the class names of all <i>active</i> instructions
135
154
  def instructions
136
155
  @instructions_library.keys
137
156
  end
@@ -147,16 +166,23 @@ module Nudge
147
166
  end
148
167
 
149
168
 
169
+ # given a string, checks the hash of defined variables, then the names (local variables),
170
+ # returning the bound value, or nil if it is not found
150
171
  def lookup(name)
151
172
  @variables[name] || @names[name]
152
173
  end
153
174
 
154
175
 
176
+ # returns an Array of all strings defined as variables or names
155
177
  def references
156
178
  @names.merge(@variables).keys
157
179
  end
158
180
 
159
181
 
182
+ # Convenience method that can be called with either an Instruction or NudgeType class as an
183
+ # argument. If an Instruction, that class is added to the Interpreter's #instruction_library.
184
+ # If a NudgeType, that class is added to the list of types that can be used to generate
185
+ # random code.
160
186
  def enable(item)
161
187
  if item.superclass == Instruction
162
188
  @instructions_library[item] = item.new(self)
@@ -166,6 +192,8 @@ module Nudge
166
192
  end
167
193
 
168
194
 
195
+ # Convenience method that checks to see whether an Instruction or NudgeType class is currently
196
+ # in the active state. Returns a boolean.
169
197
  def active?(item)
170
198
  if item.superclass == Instruction
171
199
  @instructions_library.include?(item)
@@ -175,6 +203,7 @@ module Nudge
175
203
  end
176
204
 
177
205
 
206
+ # Given a string and a ProgramPoint, binds a variable with that name to that ProgramPoint
178
207
  def bind_variable(name, value)
179
208
  raise(ArgumentError, "Variables can only be bound to ProgramPoints") unless
180
209
  value.kind_of?(ProgramPoint)
@@ -182,6 +211,7 @@ module Nudge
182
211
  end
183
212
 
184
213
 
214
+ # Given a string and a ProgramPoint, binds a name with that name to that ProgramPoint
185
215
  def bind_name(name, value)
186
216
  raise(ArgumentError, "Names can only be bound to ProgramPoints") unless
187
217
  value.kind_of?(ProgramPoint)
@@ -189,31 +219,38 @@ module Nudge
189
219
  end
190
220
 
191
221
 
222
+ # generates an arbitrary string for naming new local variables, by incrememnting
223
+ # from the starting point "aaa001"
192
224
  def next_name
193
225
  @last_name = @last_name.next
194
226
  end
195
227
 
196
228
 
229
+ # removes the named global variable from the Hash that defines them
197
230
  def unbind_variable(name)
198
231
  @variables.delete(name)
199
232
  end
200
233
 
201
234
 
235
+ # removes the named local variable from the Hash that defines them
202
236
  def unbind_name(name)
203
237
  @names.delete(name)
204
238
  end
205
239
 
206
240
 
241
+ # removes all global variable definitions
207
242
  def reset_variables
208
243
  @variables = Hash.new
209
244
  end
210
245
 
211
246
 
247
+ # removes all local variable definitions
212
248
  def reset_names
213
249
  @names = Hash.new
214
250
  end
215
251
 
216
252
 
253
+ # activates every Instruction subclass defined in any library
217
254
  def enable_all_instructions
218
255
  Instruction.all_instructions.each do |i|
219
256
  @instructions_library[i] = i.new(self)
@@ -221,11 +258,16 @@ module Nudge
221
258
  end
222
259
 
223
260
 
261
+ # activates every NudgeType subclass defined in any library
224
262
  def enable_all_types
225
263
  @types = NudgeType.all_types
226
264
  end
227
265
 
228
266
 
267
+ # Convenience method that can be called with either an Instruction or NudgeType class as an
268
+ # argument. If an Instruction, that class is removed from the Interpreter's #instruction_library.
269
+ # If a NudgeType, that class is removed to the list of types that can be used to generate
270
+ # random code.
229
271
  def disable(item)
230
272
  if item.superclass == Instruction
231
273
  @instructions_library.delete(item)
@@ -235,27 +277,37 @@ module Nudge
235
277
  end
236
278
 
237
279
 
280
+ # Completely empties the set of active Instructions. The interpreter will recognize InstructionPoints,
281
+ # but will not invoke their #go methods when it does.
238
282
  def disable_all_instructions
239
283
  @instructions_library = Hash.new
240
284
  end
241
285
 
242
286
 
287
+ # Completely empties the set of NudgeTypes in play. ValuePoints the Interpreter encounters will
288
+ # still be recognized in code, and will still be pushed to the appropriate stack, but new
289
+ # ValuePoints (made by various code-generating methods) will not be created.
243
290
  def disable_all_types
244
291
  @types = []
245
292
  end
246
293
 
247
294
 
295
+ # Create a new sensor with the given name, binding the associated block argument. All sensors are
296
+ # called, in the order registered, when the Interpreter#run cycle terminates normally.
248
297
  def register_sensor(name, &block)
249
298
  raise(ArgumentError, "Sensor name #{name} is not a string") unless name.kind_of?(String)
250
299
  @sensors[name] = block
251
300
  end
252
301
 
253
302
 
303
+ # Delete all sensors.
254
304
  def reset_sensors
255
305
  @sensors = Hash.new
256
306
  end
257
307
 
258
308
 
309
+ # Iterates through the Interpreter#sensors hash, #calling each one and passing in the current state
310
+ # of the Interpreter as an argument
259
311
  def fire_all_sensors
260
312
  @sensors.inject({}) do |result, (key, value)|
261
313
  result[key] = @sensors[key].call(self)
data/readme.md CHANGED
@@ -20,7 +20,7 @@ and getting something along the lines of `ruby 1.9.1p378 (2010-01-10 revision 26
20
20
 
21
21
  gem install nudge
22
22
 
23
- 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…
23
+ As of this writing, the `nudge` gem can be used as a library in your Ruby programs. So Real Soon Now, it'll be part of a more interesting gem…
24
24
 
25
25
  ### A test run
26
26
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 3
9
- version: 0.2.3
8
+ - 4
9
+ version: 0.2.4
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-09 00:00:00 -04:00
19
+ date: 2010-04-27 00:00:00 -04:00
20
20
  default_executable: nudge
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -33,19 +33,6 @@ dependencies:
33
33
  version: 2.3.5
34
34
  type: :runtime
35
35
  version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
37
- name: thor
38
- prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- segments:
44
- - 0
45
- - 13
46
- version: "0.13"
47
- type: :runtime
48
- version_requirements: *id002
49
36
  description: Provides a Ruby library & CLI implementing a flexible Nudge Language interpreter, plus a set of generators for adding domain-specific instructions and types.
50
37
  email: bill@vagueinnovation.com
51
38
  executables: