Class: Porolog::Predicate

Inherits:
Object
  • Object
show all
Defined in:
lib/porolog/predicate.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.

Author:

  • Luis Esteban

Defined Under Namespace

Classes: NameError, PredicateError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, scope_name = Predicate.scope.name) ⇒ Predicate

Initializes a Porolog::Predicate and registers it by its name.

Parameters:

  • name (#to_sym)

    the input object to read from

  • scope_name (defaults to: Predicate.scope.name)

    the name of the scope in which to register the Predicate; if omitted, defaults to the name of the current scope

Raises:



68
69
70
71
72
73
74
75
76
# File 'lib/porolog/predicate.rb', line 68

def initialize(name, scope_name = Predicate.scope.name)
  @name  = name.to_sym
  @rules = []
  
  raise NameError.new("Cannot name a predicate 'predicate'") if @name == :predicate
  
  scope = Scope[scope_name] || Scope.new(scope_name)
  scope[@name] = self
end

Instance Attribute Details

#nameObject (readonly)

Name of the Predicate.



18
19
20
21
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
# File 'lib/porolog/predicate.rb', line 18

class Predicate
  
  # Error class for rescuing or detecting any Predicate error.
  class PredicateError < PorologError   ; end
  # Error class indicating an error with the name of a Predicate.
  class NameError      < PredicateError ; end
  
  attr_reader :name, :rules
  
  # 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)
    if scope_name
      @@current_scope = Scope[scope_name] || Scope.new(scope_name)
    end
    @@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)
    @name  = name.to_sym
    @rules = []
    
    raise NameError.new("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.
  # @return [Porolog::Predicate] a new or existing Predicate.
  def self.new(*args)
    name, _ = *args
    scope[name.to_sym] || super
  end
  
  # Create Arguments for the Predicate.
  # Provides the syntax options:
  # * p.(x,y,z)
  # @return [Porolog::Arguments] Arguments of the Predicate with the given arguments.
  def call(*args)
    Arguments.new(self,args)
  end
  
  # Create Arguments for the Predicate.
  def arguments(*args)
    Arguments.new(self,args)
  end
  
  # Add a Rule to the Predicate.
  # @param rule [Object] the name (or otherwise object) used to register a scope.
  # @return [Array<Porolog::Rule>] the Predicate's rule.
  def <<(rule)
    @rules << rule
  end
  
  # A pretty print String of the Predicate.
  # @return [String] the Predicate as a String.
  def inspect
    lines = []
    
    if @rules.size == 1
      lines << "#{@name}:-#{@rules.first.inspect}"
    else
      lines << "#{@name}:-"
      @rules.each do |rule|
        lines << rule.inspect
      end
    end
      
    lines.join("\n")
  end
  
  # Return a builtin Predicate based on its key.
  # @param key [Symbol] the name (or otherwise object) used to register a scope.
  # @return [Porolog::Predicate] a Predicate with the next id based on the key.
  def self.builtin(key)
    @builtin_predicate_ids[key] ||= 0
    @builtin_predicate_ids[key]  += 1
    
    self.new("_#{key}_#{@builtin_predicate_ids[key]}")
  end
  
end

#rulesObject (readonly)

Rules of the Predicate.



18
19
20
21
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
# File 'lib/porolog/predicate.rb', line 18

class Predicate
  
  # Error class for rescuing or detecting any Predicate error.
  class PredicateError < PorologError   ; end
  # Error class indicating an error with the name of a Predicate.
  class NameError      < PredicateError ; end
  
  attr_reader :name, :rules
  
  # 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)
    if scope_name
      @@current_scope = Scope[scope_name] || Scope.new(scope_name)
    end
    @@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)
    @name  = name.to_sym
    @rules = []
    
    raise NameError.new("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.
  # @return [Porolog::Predicate] a new or existing Predicate.
  def self.new(*args)
    name, _ = *args
    scope[name.to_sym] || super
  end
  
  # Create Arguments for the Predicate.
  # Provides the syntax options:
  # * p.(x,y,z)
  # @return [Porolog::Arguments] Arguments of the Predicate with the given arguments.
  def call(*args)
    Arguments.new(self,args)
  end
  
  # Create Arguments for the Predicate.
  def arguments(*args)
    Arguments.new(self,args)
  end
  
  # Add a Rule to the Predicate.
  # @param rule [Object] the name (or otherwise object) used to register a scope.
  # @return [Array<Porolog::Rule>] the Predicate's rule.
  def <<(rule)
    @rules << rule
  end
  
  # A pretty print String of the Predicate.
  # @return [String] the Predicate as a String.
  def inspect
    lines = []
    
    if @rules.size == 1
      lines << "#{@name}:-#{@rules.first.inspect}"
    else
      lines << "#{@name}:-"
      @rules.each do |rule|
        lines << rule.inspect
      end
    end
      
    lines.join("\n")
  end
  
  # Return a builtin Predicate based on its key.
  # @param key [Symbol] the name (or otherwise object) used to register a scope.
  # @return [Porolog::Predicate] a Predicate with the next id based on the key.
  def self.builtin(key)
    @builtin_predicate_ids[key] ||= 0
    @builtin_predicate_ids[key]  += 1
    
    self.new("_#{key}_#{@builtin_predicate_ids[key]}")
  end
  
end

Class Method Details

.[](name) ⇒ Porolog::Predicate

Looks up a Predicate in the current scope by its name.

Parameters:

  • name (Object)

    the name (or otherwise object) used to register a scope.

Returns:



59
60
61
# File 'lib/porolog/predicate.rb', line 59

def self.[](name)
  @@current_scope[name]
end

.builtin(key) ⇒ Porolog::Predicate

Return a builtin Predicate based on its key.

Parameters:

  • key (Symbol)

    the name (or otherwise object) used to register a scope.

Returns:



125
126
127
128
129
130
# File 'lib/porolog/predicate.rb', line 125

def self.builtin(key)
  @builtin_predicate_ids[key] ||= 0
  @builtin_predicate_ids[key]  += 1
  
  self.new("_#{key}_#{@builtin_predicate_ids[key]}")
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.

Returns:



80
81
82
83
# File 'lib/porolog/predicate.rb', line 80

def self.new(*args)
  name, _ = *args
  scope[name.to_sym] || super
end

.resetPorolog::Scope

Resets the current scope to default and deregisters builtin predicates.

Returns:



51
52
53
54
# File 'lib/porolog/predicate.rb', line 51

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).

Parameters:

  • scope_name (Object) (defaults to: nil)

    the name (or otherwise object) used to register a scope.

Returns:



31
32
33
34
35
36
37
# File 'lib/porolog/predicate.rb', line 31

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.

Parameters:

  • scope_name (Object)

    the name (or otherwise object) used to register a scope.

Returns:



42
43
44
45
46
47
# File 'lib/porolog/predicate.rb', line 42

def self.scope=(scope_name)
  if scope_name
    @@current_scope = Scope[scope_name] || Scope.new(scope_name)
  end
  @@current_scope
end

Instance Method Details

#<<(rule) ⇒ Array<Porolog::Rule>

Add a Rule to the Predicate.

Parameters:

  • rule (Object)

    the name (or otherwise object) used to register a scope.

Returns:

  • (Array<Porolog::Rule>)

    the Predicate’s rule.



101
102
103
# File 'lib/porolog/predicate.rb', line 101

def <<(rule)
  @rules << rule
end

#arguments(*args) ⇒ Object

Create Arguments for the Predicate.



94
95
96
# File 'lib/porolog/predicate.rb', line 94

def arguments(*args)
  Arguments.new(self,args)
end

#call(*args) ⇒ Porolog::Arguments

Create Arguments for the Predicate. Provides the syntax options:

  • p.(x,y,z)

Returns:

  • (Porolog::Arguments)

    Arguments of the Predicate with the given arguments.



89
90
91
# File 'lib/porolog/predicate.rb', line 89

def call(*args)
  Arguments.new(self,args)
end

#inspectString

A pretty print String of the Predicate.

Returns:

  • (String)

    the Predicate as a String.



107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/porolog/predicate.rb', line 107

def inspect
  lines = []
  
  if @rules.size == 1
    lines << "#{@name}:-#{@rules.first.inspect}"
  else
    lines << "#{@name}:-"
    @rules.each do |rule|
      lines << rule.inspect
    end
  end
    
  lines.join("\n")
end