Class: RubyProlog::Core
- Inherits:
-
Object
- Object
- RubyProlog::Core
- Defined in:
- lib/ruby-prolog/ruby-prolog.rb
Instance Method Summary collapse
- #_resolve_body(body, env, cut) ⇒ Object
- #_unify(x, x_env, y, y_env, trail, tmp_env) ⇒ Object
- #_unify_(x, x_env, y, y_env, trail, tmp_env) ⇒ Object
-
#initialize ⇒ Core
constructor
A new instance of Core.
- #initialize_copy(orig) ⇒ Object
- #is(*syms, &block) ⇒ Object
- #list(*x) ⇒ Object
- #method_missing(meth, *args) ⇒ Object
- #query(&block) ⇒ Object
- #resolve(*goals) ⇒ Object
- #to_prolog ⇒ Object
- #trace(flag) ⇒ Object
Constructor Details
#initialize ⇒ Core
Returns a new instance of Core.
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 |
# 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 |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, *args) ⇒ Object
456 457 458 459 460 461 462 463 |
# 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 |
Instance Method Details
#_resolve_body(body, env, cut) ⇒ Object
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
# 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) ⇒ Object
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
# 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) ⇒ Object
425 426 427 428 429 430 |
# 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) ⇒ Object
502 503 504 505 |
# File 'lib/ruby-prolog/ruby-prolog.rb', line 502 def initialize_copy(orig) super @db = @db.clone end |
#is(*syms, &block) ⇒ Object
445 446 447 448 449 450 451 452 453 454 |
# 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) ⇒ Object
362 363 364 365 366 |
# 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 |
#query(&block) ⇒ Object
433 434 435 436 437 438 439 440 441 442 |
# 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) ⇒ Object
369 370 371 372 373 374 |
# 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 ⇒ Object
465 466 467 |
# File 'lib/ruby-prolog/ruby-prolog.rb', line 465 def to_prolog @db.listing.map(&:to_prolog).join("\n\n") end |
#trace(flag) ⇒ Object
420 421 422 |
# File 'lib/ruby-prolog/ruby-prolog.rb', line 420 def trace(flag) $_trace = flag end |