class RubyProlog::Core
Public Class Methods
new()
click to toggle source
# File lib/ruby-prolog/ruby-prolog.rb, line 470 def initialize @db = Database.new # These predicates are made available in all environments write[:X].calls{|env| print env[:X]; true} writenl[:X].calls{|env| puts env[:X]; true} nl[:X].calls{|e| puts; true} eq[:X,:Y].calls{|env| env.unify(env[:X], env[:Y])} noteq[:X,:Y].calls{|env| env[:X] != env[:Y]} atomic[:X].calls do |env| case env[:X] when Symbol, Predicate, Goal; false else true end end notatomic[:X].calls do |env| case env[:X] when Symbol, Predicate, Goal; true else false end end numeric[:X].calls{|env| Numeric === env[:X] } not_[:X].calls do |env| found_solution = false resolve(env[:X], :CUT) { found_solution = true } found_solution == false end # Enable here so the predicates above don't make it in to_prolog output @db.enable_listing end
Public Instance Methods
_resolve_body(body, env, cut) { || ... }
click to toggle source
# File lib/ruby-prolog/ruby-prolog.rb, line 377 def _resolve_body(body, env, cut) if body.nil? yield else goal, rest = body if goal == :CUT _resolve_body(rest, env, cut) { yield } cut[0] = true else d_env = Environment.new d_cut = [false] for d_head, d_body in @db.by_id[goal.pred_id].clauses break if d_cut[0] or cut[0] trail = [] if _unify_(goal, env, d_head, d_env, trail, d_env) if Proc === d_body if d_body[CallbackEnvironment.new(d_env, trail, self)] _resolve_body(rest, env, cut) { yield } end else _resolve_body(d_body, d_env, d_cut) { _resolve_body(rest, env, cut) { yield } d_cut[0] ||= cut[0] } end end for x, x_env in trail x_env.delete(x) end d_env.clear end end end end
_unify(x, x_env, y, y_env, trail, tmp_env)
click to toggle source
# File lib/ruby-prolog/ruby-prolog.rb, line 319 def _unify(x, x_env, y, y_env, trail, tmp_env) loop { if x == :_ return true elsif Symbol === x xp = x_env.get(x) if xp.nil? y, y_env = y_env.dereference(y) unless x == y and x_env == y_env x_env.put(x, [y, y_env]) trail << [x, x_env] unless x_env == tmp_env end return true else x, x_env = xp x, x_env = x_env.dereference(x) end elsif Symbol === y x, x_env, y, y_env = y, y_env, x, x_env else break end } if Goal === x and Goal === y return false unless x.pred_id == y.pred_id x, y = x.args, y.args end if Array === x and Array === y return false unless x.length == y.length for i in 0 ... x.length # x.each_index do |i| も可 return false unless _unify(x[i], x_env, y[i], y_env, trail, tmp_env) end return true else return x == y end end
_unify_(x, x_env, y, y_env, trail, tmp_env)
click to toggle source
# File lib/ruby-prolog/ruby-prolog.rb, line 425 def _unify_(x, x_env, y, y_env, trail, tmp_env) lhs, rhs = x_env[x].inspect, y.inspect if $_trace unified = _unify(x, x_env, y, y_env, trail, tmp_env) printf("\t%s %s %s\n", lhs, (unified ? "~" : "!~"), rhs) if $_trace return unified end
initialize_copy(orig)
click to toggle source
Calls superclass method
# File lib/ruby-prolog/ruby-prolog.rb, line 502 def initialize_copy(orig) super @db = @db.clone end
is(*syms,&block)
click to toggle source
# File lib/ruby-prolog/ruby-prolog.rb, line 445 def is(*syms,&block) $is_cnt ||= 0 is = @db.register("IS_#{$is_cnt += 1}", skip_listing: true) raise "At least one symbol needed" unless syms.size > 0 is[*syms].calls do |env| value = block.call(*syms[1..-1].map{|x| env[x]}) env.unify(syms.first, value) end is[*syms] end
list(*x)
click to toggle source
# File lib/ruby-prolog/ruby-prolog.rb, line 362 def list(*x) y = nil x.reverse_each {|e| y = Cons.new(e, y)} return y end
method_missing(meth, *args)
click to toggle source
# File lib/ruby-prolog/ruby-prolog.rb, line 456 def method_missing(meth, *args) pred = @db.register(meth) # We only want to define the method on this specific object instance to avoid polluting global namespaces. define_singleton_method(meth){ @db.by_name[meth] } pred end
query(&block)
click to toggle source
# File lib/ruby-prolog/ruby-prolog.rb, line 433 def query(&block) goals = instance_eval(&block) goals = [goals] unless goals.is_a?(Array) results = [] resolve(*goals.map(&:to_goal)) {|env| results << env.solution } return results end
resolve(*goals) { |env| ... }
click to toggle source
# File lib/ruby-prolog/ruby-prolog.rb, line 369 def resolve(*goals) env = Environment.new _resolve_body(list(*goals), env, [false]) { yield env } end
to_prolog()
click to toggle source
# File lib/ruby-prolog/ruby-prolog.rb, line 465 def to_prolog @db.listing.map(&:to_prolog).join("\n\n") end
trace(flag)
click to toggle source
# File lib/ruby-prolog/ruby-prolog.rb, line 420 def trace(flag) $_trace = flag end