lib/y_petri/place/guarded.rb in y_petri-2.2.2 vs lib/y_petri/place/guarded.rb in y_petri-2.2.3
- old
+ new
@@ -1,83 +1,75 @@
# encoding: utf-8
-# A mixin to make a place support guards.
+# Support of places' marking guards.
#
module YPetri::Place::Guarded
# Expects a guard assertion in natural language, and a guard block. Guard
- # block is a unary block capable of validating a marking value. The validation
- # is considered as having failed if:
+ # block is a unary block that validates marking. A validation fails when:
#
# 1. The block returns _false_.
# 2. The block raises +YPetri::GuardError+.
#
- # In all other cases, including the block returning _nil_, the validation is
- # considered as having passed! The block is evaluated in the context of a
- # special "Lab" object, which has +#fail+ method redefined so that it can
- # (and must) be called without parameters, and produces an appropriately
- # worded +GuardError+. (Other exceptions can be still raised using +#raise+
- # method.)
- #
- # As for the NL assertion, apart from self-documenting the code, it is used
- # for constructing appropriately worded +GuardError+ messages:
+ # In all other cases, including when the block returns _nil_ (beware!),
+ # the marking is considered valid! Inside the block, +#fail+ keyword is
+ # redefined so that it can (and must) be called without arguments, and it
+ # raises an appropriately worded +GuardError+. (Other exceptions can still
+ # be raised using +#raise+ keyword.) Practical example:
#
# guard "should be a number" do |m| fail unless m.is_a? Numeric end
#
- # Then +guard! :foobar+ raises +GuardError+ with message "Marking foobar:Symbol
- # should be a number!"
+ # Then <code>guard! :foobar</code> raises +GuardError+ with a message "Marking
+ # foobar:Symbol should be a number!"
#
- # The method returns the reference to the +YPetri::Guard+ object, that has
- # been constructed and already included in the collection of this place's
- # guards.
- #
# Finally, this method is overloaded in such way, that if no block is
- # given to it, it acts as a frontend for the +#federated_guard_closure+
- # method: It either applies the federated closure to the marking value given
- # in the argument, or returns the federated closure itself if no arguemnts
- # were given (behaving as +#federated_guard_closure+ alias in this case).
+ # given to it, it acts as an alias of +#common_guard_closure+ method.
#
def guard *args, &block
if block then
@guards << YPetri::Place::Guard.new( *args, place: self, &block )
elsif args.size == 1 then
- federated_guard_closure.( args[0] )
+ common_guard_closure.( args[0] )
elsif args.empty? then
- federated_guard_closure
+ common_guard_closure
end
end
- # Returns a joint guard closure, composed of all the guards defined for the
- # place at the moment. Joint closure passes if and only if all the guard
- # blocks pass for the given marking value.
+ # Returns a closure combining all the guards defined for the place so far,
+ # which passes if, and only if, all the included guards pass. The common
+ # closure, if it passes, returns the tested marking value.
#
- def federated_guard_closure
+ def common_guard_closure
place_name, lineup = name.to_s, guards.dup
- -> m { lineup.each { |g| g.validate( m ) }; return m }
+ -> marking { lineup.each { |g| g.validate marking }; marking }
end
- # Applies guards on the marking currently owned by the place.
+ # Applies the guards defined for the place on the current marking (contents
+ # of +@marking+ instance variable).
#
def guard!
guard.( marking )
end
private
- # If no guards were specified by the user, this method can make them up in a
- # standard way, using user-supplied marking / default marking as a type
- # reference. Numeric types are an exception – they are considered mutually
- # interchangeable, except complex numbers.
+ # If no guards were specified by the user, this method can construct standard
+ # guards based on the data type of places' +marking+ and/or +default_marking+.
+ # (For most data types, default guards enfore type compliance. Numeric
+ # descendants, however, are considered interchangeable, except for Complex
+ # class.)
#
def add_default_guards!( reference_marking )
case reference_marking
- when Complex then marking "should be Numeric" do |m| m.is_a? Numeric end
- when Numeric then
+ when Complex then # 1 guard
marking "should be Numeric" do |m| m.is_a? Numeric end
+ when Numeric then # 3 guards
+ marking "should be Numeric" do |m| m.is_a? Numeric end
marking "should not be complex" do |m| fail if m.is_a? Complex end
marking "should not be negative" do |m| m >= 0 end
when nil then # no guards
- when true, false then marking "should be Boolean" do |m| m == !!m end
- else
+ when true, false then # 1 guard
+ marking "should be Boolean" do |m| m == !!m end
+ else # 1 guard
reference_marking.class.tap do |klass|
marking "should be a #{klass}" do |m| m.is_a? klass end
end
end
return nil