Class: Ambit::Generator
- Inherits:
-
Object
- Object
- Ambit::Generator
- Defined in:
- lib/ambit.rb
Constant Summary collapse
- @@trace =
0
Class Method Summary collapse
-
.trace(lvl = false) ⇒ Object
Turn on tracing (to standard error) of Ambit operations.
-
.untrace ⇒ Object
Turn off tracing (to standard error) of Ambit operations.
Instance Method Summary collapse
-
#assert(cond) ⇒ Object
(also: #require)
Fail unless a condition holds.
-
#choose(choices = []) ⇒ Object
(also: #amb)
Given an enumerator, begin a generate-and-test process.
-
#clear! ⇒ Object
Clear all outstanding choices registered with this generator.
-
#cut! ⇒ Object
Commit to all choices since the last #mark operation.
-
#fail! ⇒ Object
Indicate that the current combination of choices has failed, and roll execution back to the last #choose, continuing with the next choice.
-
#initialize ⇒ Generator
constructor
Allocate a new private Generator.
-
#mark ⇒ Object
Begin a mark/cut pair to commit to one branch of the current #choose operation.
-
#unmark! ⇒ Object
Remove the most recent mark.
-
#unmark_all! ⇒ Object
Remove all marks.
Constructor Details
#initialize ⇒ Generator
Allocate a new private Generator. Usually not needed – use Ambit::choose et al, instead.
See “Private Generators” in the README for details
24 25 26 27 |
# File 'lib/ambit.rb', line 24 def initialize @paths = [] @trace = 0 end |
Class Method Details
.trace(lvl = false) ⇒ Object
Turn on tracing (to standard error) of Ambit operations
intended for use by Ambit::trace
The optional level argument sets the verbosity – if not passed, each call to this method increases verbosity
35 36 37 38 39 40 41 |
# File 'lib/ambit.rb', line 35 def self.trace lvl=false if lvl @@trace = lvl else @@trace = @trace + 1 end end |
.untrace ⇒ Object
Turn off tracing (to standard error) of Ambit operations
intended for use by Ambit::untrace
46 47 48 |
# File 'lib/ambit.rb', line 46 def self.untrace @@trace = 0 end |
Instance Method Details
#assert(cond) ⇒ Object Also known as: require
Fail unless a condition holds.
96 97 98 |
# File 'lib/ambit.rb', line 96 def assert cond fail! unless cond end |
#choose(choices = []) ⇒ Object Also known as: amb
Given an enumerator, begin a generate-and-test process.
Returns with the first member of the enumerator. A later call to #fail! on the same generator will backtrack and try the next value in the enumerator, continuing from the point of this #choose as if that value had been chosen originally.
Multiple calls to #choose will nest, so that backtracking forms a tree-like execution path
calling #choose with no argument or an empty iterator is equivalent to calling #fail!
70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/ambit.rb', line 70 def choose choices = [] ch = choices.clone # clone it in case it's modified by the caller ch.each do |choice| callcc do |cc| STDERR.print "choosing from " + choices.inspect + ": " if @trace > 0 @paths.unshift cc STDERR.puts choice.inspect if @trace > 0 return choice end end self.fail! # if we get here, we've exhausted the choices end |
#clear! ⇒ Object
Clear all outstanding choices registered with this generator.
Returns the generator to the state it was in before all choices were made. Does not rewind execution.
54 55 56 |
# File 'lib/ambit.rb', line 54 def clear! @paths = [] end |
#cut! ⇒ Object
Commit to all choices since the last #mark operation.
See “Marking and Cutting” in README for details
131 132 133 134 135 136 137 138 |
# File 'lib/ambit.rb', line 131 def cut! STDERR.puts "cut!" if @trace > 0 return if @paths.empty? # rewind paths back to the last mark @paths = @paths.drop_while {|x| x.instance_of? Continuation} # drop up to one mark @paths = @paths.drop(1) unless @paths.empty? end |
#fail! ⇒ Object
Indicate that the current combination of choices has failed, and roll execution back to the last #choose, continuing with the next choice.
87 88 89 90 91 92 93 |
# File 'lib/ambit.rb', line 87 def fail! raise ChoicesExhausted.new if @paths.empty? cc = @paths.shift # if it quacks (or can be called) like a duck, call it -- it's either a Proc # from #mark or a Continuation from #choose cc.call end |
#mark ⇒ Object
Begin a mark/cut pair to commit to one branch of the current #choose operation.
See “Marking and Cutting” in README for details
105 106 107 |
# File 'lib/ambit.rb', line 105 def mark @paths.unshift Proc.new {self.fail!} end |
#unmark! ⇒ Object
Remove the most recent mark
See “Marking and Cutting” in README for details
112 113 114 115 116 117 |
# File 'lib/ambit.rb', line 112 def unmark! STDERR.puts "unmark!" if @trace > 0 return if @paths.empty? n = @paths.rindex {|x| x.instance_of? Proc} n and @paths.delete_at(n) end |
#unmark_all! ⇒ Object
Remove all marks
See “Marking and Cutting” in README for details
122 123 124 125 126 |
# File 'lib/ambit.rb', line 122 def unmark_all! STDERR.puts "unmark_all!" if @trace > 0 return if @paths.empty? @paths = @paths.reject {|x| x.instance_of? Proc} end |