Class: Porolog::Predicate
- Defined in:
- lib/porolog/predicate.rb,
lib/porolog/predicate/builtin.rb
Overview
A Porolog::Predicate corresponds to a Prolog predicate. It contains rules (Porolog::Rule) and belongs to a Porolog::Scope. When provided with arguments, it produces a Porolog::Arguments.
Defined Under Namespace
Modules: Builtin Classes: Error, NameError
Instance Attribute Summary collapse
-
#name ⇒ Object
readonly
Name of the Predicate.
-
#rules ⇒ Object
readonly
Rules of the Predicate.
Class Method Summary collapse
-
.[](name) ⇒ Porolog::Predicate
Looks up a Predicate in the current scope by its name.
-
.call_builtin(predicate, *args, &arg_block) ⇒ Boolean
Call a builtin predicate.
-
.new(*args) ⇒ Porolog::Predicate
Creates a new Predicate, or returns an existing Predicate if one already exists with the given name in the current scope.
-
.reset ⇒ Porolog::Scope
Resets the current scope to default and deregisters builtin predicates.
-
.scope(scope_name = nil) ⇒ Porolog::Scope
Returns the current scope, or sets the current scope if a paramter is provided (creating the new scope if necessary).
-
.scope=(scope_name) ⇒ Porolog::Scope
Sets the current scope (creating the new scope if necessary..
Instance Method Summary collapse
-
#<<(rule) ⇒ Porolog::Predicate
Add a Rule to the Predicate.
-
#arguments(*args, &block) ⇒ Porolog::Arguments
Create Arguments for the Predicate.
-
#builtin? ⇒ Boolean
Whether the Predicate is a builtin predicate.
-
#call(*args, &block) ⇒ Porolog::Arguments
Create Arguments for the Predicate.
-
#initialize(name, scope_name = Predicate.scope.name, builtin: false) ⇒ Predicate
constructor
Initializes a Porolog::Predicate and registers it by its name.
-
#inspect ⇒ String
A pretty print String of the Predicate.
-
#satisfy(goal, &block) ⇒ Boolean
Satisfy the Predicate within the supplied Goal.
-
#satisfy_builtin(goal, &block) ⇒ Boolean
Satisfy the builtin Predicate within the supplied Goal.
Constructor Details
#initialize(name, scope_name = Predicate.scope.name, builtin: false) ⇒ Predicate
Initializes a Porolog::Predicate and registers it by its name.
74 75 76 77 78 79 80 81 82 83 |
# File 'lib/porolog/predicate.rb', line 74 def initialize(name, scope_name = Predicate.scope.name, builtin: false) @name = name.to_sym @rules = [] @builtin = builtin raise NameError, "Cannot name a predicate 'predicate'" if @name == :predicate scope = Scope[scope_name] || Scope.new(scope_name) scope[@name] = self end |
Instance Attribute Details
#name ⇒ Object (readonly)
Name of the Predicate.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/porolog/predicate.rb', line 22 class Predicate # Error class for rescuing or detecting any Predicate error. class Error < PorologError ; end # Error class indicating an error with the name of a Predicate. class NameError < Error ; end attr_reader :name, :rules # A unique value used to verify instantiations. UNIQUE_VALUE = Object.new.freeze private_constant :UNIQUE_VALUE # Returns the current scope, or sets the current scope if a paramter is provided # (creating the new scope if necessary). # @param scope_name [Object] the name (or otherwise object) used to register a scope. # @return [Porolog::Scope] the current Scope. def self.scope(scope_name = nil) if scope_name @@current_scope = Scope[scope_name] || Scope.new(scope_name) else @@current_scope end end # Sets the current scope (creating the new scope if necessary. # @param scope_name [Object] the name (or otherwise object) used to register a scope. # @return [Porolog::Scope] the current Scope. def self.scope=(scope_name) @@current_scope = Scope[scope_name] || Scope.new(scope_name) if scope_name @@current_scope end # Resets the current scope to default and deregisters builtin predicates. # @return [Porolog::Scope] the current Scope. def self.reset scope(:default) @builtin_predicate_ids = {} end # Looks up a Predicate in the current scope by its name. # @param name [Object] the name (or otherwise object) used to register a scope. # @return [Porolog::Predicate] the Predicate with the given name. def self.[](name) @@current_scope[name] end reset # Initializes a Porolog::Predicate and registers it by its name. # @param name [#to_sym] the input object to read from # @param scope_name the name of the scope in which to register the Predicate; if omitted, defaults to the name of the current scope def initialize(name, scope_name = Predicate.scope.name, builtin: false) @name = name.to_sym @rules = [] @builtin = builtin raise NameError, "Cannot name a predicate 'predicate'" if @name == :predicate scope = Scope[scope_name] || Scope.new(scope_name) scope[@name] = self end # Creates a new Predicate, or returns an existing Predicate if one already exists with the given name in the current scope. # @param args the args to be passed to initialize, first of which is the name of the predicate. # @return [Porolog::Predicate] a new or existing Predicate. def self.new(*args, **) scope[args.first.to_sym] || super end # Create Arguments for the Predicate. # Provides the syntax option: # p.(x,y,z) # for # p.arguments(x,y,z) # @return [Porolog::Arguments] Arguments of the Predicate with the given arguments. def call(*args, &block) Arguments.new(self, args, &block) end # Create Arguments for the Predicate. # @param args the args of the Predicate. # @param block [Proc,nil] the block to be called when satisfying the Predicate. # @return [Porolog::Arguments] Arguments of the Predicate with the given arguments. def arguments(*args, &block) Arguments.new(self, args, &block) end # Add a Rule to the Predicate. # @param rule [Object] a rule to add to the Predicate. # @return [Porolog::Predicate] the Predicate. def <<(rule) @rules << rule self end # A pretty print String of the Predicate. # @return [String] the Predicate as a String. def inspect if @rules.size == 1 "#{@name}:-#{@rules.first.inspect}" else @rules.each_with_object(["#{@name}:-"]) do |rule, lines| lines << rule.inspect end.join("\n") end end # Satisfy the Predicate within the supplied Goal. # Satisfy of each rule of the Predicate is called with the Goal and success block. # @param goal [Porolog::Goal] the Goal within which to satisfy the Predicate. # @param block [Proc] the block to be called each time a Rule of the Predicate is satisfied. # @return [Boolean] whether any Rule was satisfied. def satisfy(goal, &block) if builtin? satisfy_builtin(goal, &block) else satisfied = false @rules.each do |rule| rule.satisfy(goal) do |subgoal| satisfied = true block.call(subgoal) end break if goal.terminated? end satisfied end end # @return [Boolean] whether the Predicate is a builtin predicate. def builtin? @builtin end # Satisfy the builtin Predicate within the supplied Goal. # Call the builtin Predicate method with the Goal and success block. # The arguments and block are extracted from the Goal's Arguments. # @param goal [Porolog::Goal] the Goal within which to satisfy the Predicate. # @param block [Proc] the block to be called each time a Rule of the Predicate is satisfied. # @return [Boolean] whether any Rule was satisfied. def satisfy_builtin(goal, &block) predicate = goal.arguments.predicate.name arguments = goal.arguments.arguments arg_block = goal.arguments.block Predicate.call_builtin(predicate, goal, block, *arguments, &arg_block) end # Call a builtin predicate # @param predicate [Symbol] the name of the predicate to call. # @param args [Array<Object>] arguments for the predicate call. # @param arg_block [Proc] the block provided in the Arguments of the Predicate. # @return [Boolean] whether the predicate was satisfied. def self.call_builtin(predicate, *args, &arg_block) Porolog::Predicate::Builtin.instance_method(predicate).bind(self).call(*args, &arg_block) end end |
#rules ⇒ Object (readonly)
Rules of the Predicate.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/porolog/predicate.rb', line 22 class Predicate # Error class for rescuing or detecting any Predicate error. class Error < PorologError ; end # Error class indicating an error with the name of a Predicate. class NameError < Error ; end attr_reader :name, :rules # A unique value used to verify instantiations. UNIQUE_VALUE = Object.new.freeze private_constant :UNIQUE_VALUE # Returns the current scope, or sets the current scope if a paramter is provided # (creating the new scope if necessary). # @param scope_name [Object] the name (or otherwise object) used to register a scope. # @return [Porolog::Scope] the current Scope. def self.scope(scope_name = nil) if scope_name @@current_scope = Scope[scope_name] || Scope.new(scope_name) else @@current_scope end end # Sets the current scope (creating the new scope if necessary. # @param scope_name [Object] the name (or otherwise object) used to register a scope. # @return [Porolog::Scope] the current Scope. def self.scope=(scope_name) @@current_scope = Scope[scope_name] || Scope.new(scope_name) if scope_name @@current_scope end # Resets the current scope to default and deregisters builtin predicates. # @return [Porolog::Scope] the current Scope. def self.reset scope(:default) @builtin_predicate_ids = {} end # Looks up a Predicate in the current scope by its name. # @param name [Object] the name (or otherwise object) used to register a scope. # @return [Porolog::Predicate] the Predicate with the given name. def self.[](name) @@current_scope[name] end reset # Initializes a Porolog::Predicate and registers it by its name. # @param name [#to_sym] the input object to read from # @param scope_name the name of the scope in which to register the Predicate; if omitted, defaults to the name of the current scope def initialize(name, scope_name = Predicate.scope.name, builtin: false) @name = name.to_sym @rules = [] @builtin = builtin raise NameError, "Cannot name a predicate 'predicate'" if @name == :predicate scope = Scope[scope_name] || Scope.new(scope_name) scope[@name] = self end # Creates a new Predicate, or returns an existing Predicate if one already exists with the given name in the current scope. # @param args the args to be passed to initialize, first of which is the name of the predicate. # @return [Porolog::Predicate] a new or existing Predicate. def self.new(*args, **) scope[args.first.to_sym] || super end # Create Arguments for the Predicate. # Provides the syntax option: # p.(x,y,z) # for # p.arguments(x,y,z) # @return [Porolog::Arguments] Arguments of the Predicate with the given arguments. def call(*args, &block) Arguments.new(self, args, &block) end # Create Arguments for the Predicate. # @param args the args of the Predicate. # @param block [Proc,nil] the block to be called when satisfying the Predicate. # @return [Porolog::Arguments] Arguments of the Predicate with the given arguments. def arguments(*args, &block) Arguments.new(self, args, &block) end # Add a Rule to the Predicate. # @param rule [Object] a rule to add to the Predicate. # @return [Porolog::Predicate] the Predicate. def <<(rule) @rules << rule self end # A pretty print String of the Predicate. # @return [String] the Predicate as a String. def inspect if @rules.size == 1 "#{@name}:-#{@rules.first.inspect}" else @rules.each_with_object(["#{@name}:-"]) do |rule, lines| lines << rule.inspect end.join("\n") end end # Satisfy the Predicate within the supplied Goal. # Satisfy of each rule of the Predicate is called with the Goal and success block. # @param goal [Porolog::Goal] the Goal within which to satisfy the Predicate. # @param block [Proc] the block to be called each time a Rule of the Predicate is satisfied. # @return [Boolean] whether any Rule was satisfied. def satisfy(goal, &block) if builtin? satisfy_builtin(goal, &block) else satisfied = false @rules.each do |rule| rule.satisfy(goal) do |subgoal| satisfied = true block.call(subgoal) end break if goal.terminated? end satisfied end end # @return [Boolean] whether the Predicate is a builtin predicate. def builtin? @builtin end # Satisfy the builtin Predicate within the supplied Goal. # Call the builtin Predicate method with the Goal and success block. # The arguments and block are extracted from the Goal's Arguments. # @param goal [Porolog::Goal] the Goal within which to satisfy the Predicate. # @param block [Proc] the block to be called each time a Rule of the Predicate is satisfied. # @return [Boolean] whether any Rule was satisfied. def satisfy_builtin(goal, &block) predicate = goal.arguments.predicate.name arguments = goal.arguments.arguments arg_block = goal.arguments.block Predicate.call_builtin(predicate, goal, block, *arguments, &arg_block) end # Call a builtin predicate # @param predicate [Symbol] the name of the predicate to call. # @param args [Array<Object>] arguments for the predicate call. # @param arg_block [Proc] the block provided in the Arguments of the Predicate. # @return [Boolean] whether the predicate was satisfied. def self.call_builtin(predicate, *args, &arg_block) Porolog::Predicate::Builtin.instance_method(predicate).bind(self).call(*args, &arg_block) end end |
Class Method Details
.[](name) ⇒ Porolog::Predicate
Looks up a Predicate in the current scope by its name.
65 66 67 |
# File 'lib/porolog/predicate.rb', line 65 def self.[](name) @@current_scope[name] end |
.call_builtin(predicate, *args, &arg_block) ⇒ Boolean
Call a builtin predicate
175 176 177 |
# File 'lib/porolog/predicate.rb', line 175 def self.call_builtin(predicate, *args, &arg_block) Porolog::Predicate::Builtin.instance_method(predicate).bind(self).call(*args, &arg_block) end |
.new(*args) ⇒ Porolog::Predicate
Creates a new Predicate, or returns an existing Predicate if one already exists with the given name in the current scope.
88 89 90 |
# File 'lib/porolog/predicate.rb', line 88 def self.new(*args, **) scope[args.first.to_sym] || super end |
.reset ⇒ Porolog::Scope
Resets the current scope to default and deregisters builtin predicates.
57 58 59 60 |
# File 'lib/porolog/predicate.rb', line 57 def self.reset scope(:default) @builtin_predicate_ids = {} end |
.scope(scope_name = nil) ⇒ Porolog::Scope
Returns the current scope, or sets the current scope if a paramter is provided (creating the new scope if necessary).
39 40 41 42 43 44 45 |
# File 'lib/porolog/predicate.rb', line 39 def self.scope(scope_name = nil) if scope_name @@current_scope = Scope[scope_name] || Scope.new(scope_name) else @@current_scope end end |
.scope=(scope_name) ⇒ Porolog::Scope
Sets the current scope (creating the new scope if necessary.
50 51 52 53 |
# File 'lib/porolog/predicate.rb', line 50 def self.scope=(scope_name) @@current_scope = Scope[scope_name] || Scope.new(scope_name) if scope_name @@current_scope end |
Instance Method Details
#<<(rule) ⇒ Porolog::Predicate
Add a Rule to the Predicate.
113 114 115 116 |
# File 'lib/porolog/predicate.rb', line 113 def <<(rule) @rules << rule self end |
#arguments(*args, &block) ⇒ Porolog::Arguments
Create Arguments for the Predicate.
106 107 108 |
# File 'lib/porolog/predicate.rb', line 106 def arguments(*args, &block) Arguments.new(self, args, &block) end |
#builtin? ⇒ Boolean
Returns whether the Predicate is a builtin predicate.
152 153 154 |
# File 'lib/porolog/predicate.rb', line 152 def builtin? @builtin end |
#call(*args, &block) ⇒ Porolog::Arguments
Create Arguments for the Predicate. Provides the syntax option:
p.(x,y,z)
for
p.arguments(x,y,z)
98 99 100 |
# File 'lib/porolog/predicate.rb', line 98 def call(*args, &block) Arguments.new(self, args, &block) end |
#inspect ⇒ String
A pretty print String of the Predicate.
120 121 122 123 124 125 126 127 128 |
# File 'lib/porolog/predicate.rb', line 120 def inspect if @rules.size == 1 "#{@name}:-#{@rules.first.inspect}" else @rules.each_with_object(["#{@name}:-"]) do |rule, lines| lines << rule.inspect end.join("\n") end end |
#satisfy(goal, &block) ⇒ Boolean
Satisfy the Predicate within the supplied Goal. Satisfy of each rule of the Predicate is called with the Goal and success block.
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/porolog/predicate.rb', line 135 def satisfy(goal, &block) if builtin? satisfy_builtin(goal, &block) else satisfied = false @rules.each do |rule| rule.satisfy(goal) do |subgoal| satisfied = true block.call(subgoal) end break if goal.terminated? end satisfied end end |
#satisfy_builtin(goal, &block) ⇒ Boolean
Satisfy the builtin Predicate within the supplied Goal. Call the builtin Predicate method with the Goal and success block. The arguments and block are extracted from the Goal’s Arguments.
162 163 164 165 166 167 168 |
# File 'lib/porolog/predicate.rb', line 162 def satisfy_builtin(goal, &block) predicate = goal.arguments.predicate.name arguments = goal.arguments.arguments arg_block = goal.arguments.block Predicate.call_builtin(predicate, goal, block, *arguments, &arg_block) end |