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
22 23 24 25 |
# File 'lib/ambit.rb', line 22 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
33 34 35 36 37 38 39 |
# File 'lib/ambit.rb', line 33 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
44 45 46 |
# File 'lib/ambit.rb', line 44 def self.untrace @@trace = 0 end |
Instance Method Details
#assert(cond) ⇒ Object Also known as: require
Fail unless a condition holds.
94 95 96 |
# File 'lib/ambit.rb', line 94 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!
68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/ambit.rb', line 68 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.
52 53 54 |
# File 'lib/ambit.rb', line 52 def clear! @paths = [] end |
#cut! ⇒ Object
Commit to all choices since the last #mark operation.
See "Marking and Cutting" in README for details
129 130 131 132 133 134 135 136 |
# File 'lib/ambit.rb', line 129 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.
85 86 87 88 89 90 91 |
# File 'lib/ambit.rb', line 85 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
103 104 105 |
# File 'lib/ambit.rb', line 103 def mark @paths.unshift Proc.new {self.fail!} end |
#unmark! ⇒ Object
Remove the most recent mark
See "Marking and Cutting" in README for details
110 111 112 113 114 115 |
# File 'lib/ambit.rb', line 110 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
120 121 122 123 124 |
# File 'lib/ambit.rb', line 120 def unmark_all! STDERR.puts "unmark_all!" if @trace > 0 return if @paths.empty? @paths = @paths.reject {|x| x.instance_of? Proc} end |