class Porolog::Rule

A Porolog::Rule is one clause of a Porolog::Predicate.

@author Luis Esteban

@!attribute [r] arguments

The Arguments of the Predicate for which this Rule applies.

@!attribute [r] definition

The definition of the Rule.

Attributes

arguments[R]
definition[R]

Public Class Methods

new(arguments, definition = nil) click to toggle source

Initializes the Rule. @param arguments [Porolog::Arguments] the Arguments of the Predicate for which this Rule applies. @param definition [Object] the definition of the Rule.

# File lib/porolog/rule.rb, line 40
def initialize(arguments, definition = nil)
  @arguments  = arguments
  @definition = definition
  @@rules << self
end
reset() click to toggle source

Clears all Rules. @return [Boolean] success

# File lib/porolog/rule.rb, line 30
def self.reset
  @@rules = []
  true
end

Public Instance Methods

inspect() click to toggle source

@return [String] pretty representation.

# File lib/porolog/rule.rb, line 53
def inspect
  "  #{@arguments.inspect}:- #{@definition.inspect}"
end
myid() click to toggle source

Convenience method for testing/debugging @return [String] pretty identification

# File lib/porolog/rule.rb, line 48
def myid
  "Rule#{(@@rules.index(self) || -1000) + 1}"
end
satisfy(goal, &block) click to toggle source

Try to satisfy the Rule for the given Goal. @param goal [Porolog::Goal] the Goal in which to satisfy this Rule. @param block [Proc] code to perform when the Rule is satisfied. @return [Boolean] the success of deleting the subgoal.

# File lib/porolog/rule.rb, line 61
def satisfy(goal, &block)
  subgoal = Goal.new self.arguments, goal
  
  unified_goals = Porolog::unify_goals(goal, subgoal)
  if unified_goals
    satisfy_definition(goal, subgoal) do |solution_goal|
      block.call(solution_goal)
    end
  else
    subgoal.log << "Dead-end: Cannot unify with #{goal.inspect}"
  end
  
  subgoal.delete!
end
satisfy_conjunction(goal, subgoal, conjunction, &block) click to toggle source

Try to satisfy the conjunction of the definition of the Rule for a given Goal. A conjunction is a sequence of expressions where the sequence is true if all the expressions are true.

@param goal [Porolog::Goal] the given Goal for the Rule. @param subgoal [Porolog::Goal] the subgoal for the Rule's definition. @param conjunction [Array] the conjunction to satisfy. @param block [Proc] code to perform when the definition is satisfied. @return [Boolean] whether the definition was satisfied.

# File lib/porolog/rule.rb, line 109
def satisfy_conjunction(goal, subgoal, conjunction, &block)
  arguments   = conjunction.first
  conjunction = conjunction[1..-1]
  
  # -- Handle non-Arguments --
  case arguments
    when :CUT, true
      subgoal.log << "CUTTING #{goal.inspect}..."
      result = true
      if conjunction.empty?
        !goal.terminated? && block.call(subgoal)
      else
        result = satisfy_conjunction(goal, subgoal, conjunction, &block)
      end
      
      if arguments == :CUT
        goal.terminate!
        goal.log << "TERMINATED after #{subgoal.inspect}"
      end
      
      return result
      
    when false
      return false
    
    when nil
      !goal.terminated? && block.call(subgoal)
      return true
  end
  
  # -- Unify Subsubgoal --
  subsubgoal = arguments.goal(subgoal)
  unified    = subsubgoal.inherit_variables(subgoal)
  
  # -- Satisfy Subgoal --
  result = false
  unified && subsubgoal.satisfy() do
    result = true
    if conjunction.empty?
      !goal.terminated? && block.call(goal)
    else
      result = !goal.terminated? && satisfy_conjunction(goal, subsubgoal, conjunction, &block)
    end
  end
  
  # -- Uninstantiate --
  subsubgoal.delete!
  
  result && !goal.terminated?
end
satisfy_definition(goal, subgoal, &block) click to toggle source

Try to satisfy the definition of the Rule for a given Goal. @param goal [Porolog::Goal] the given Goal for the Rule. @param subgoal [Porolog::Goal] the subgoal for the Rule's definition. @param block [Proc] code to perform when the definition is satisfied. @return [Boolean] whether the definition was satisfied.

# File lib/porolog/rule.rb, line 81
def satisfy_definition(goal, subgoal, &block)
  case @definition
    when TrueClass
      block.call(subgoal)
      true
    
    when FalseClass
      false
    
    when Array
      satisfy_conjunction(goal, subgoal, @definition) do |solution_goal|
        block.call(solution_goal)
      end
    
    else
      raise DefinitionError, "UNEXPECTED TYPE OF DEFINITION: #{@definition.inspect} (#{@definition.class})"
  end
end