AI-Prolog

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

      Added math preprocessor.  This transforms proper Prolog math
        into internal predicates the parser recognizes:

        X is N + 1. % is(X, plus(N, 1)).
        
      Pushed all parsing back to the Parser class.  No more parsing
        in TermList and Term :)
      Added anonymous variables:  foo(bar, _, baz).  I don't have
        any efficiency gains from this (yet) because they're just
        variables with hidden names, but they work.
      Added Test::Exception to the PREREQ_PM (thanks to rjray for
        pointing that out).
      Updated the docs and examples.

0.65  Wed May 11, 2005
      Added Term::ReadLine support to aiprolog shell.
      Added Term::ReadKey support to aiprolog shell.
      Minor doc corrections.

0.64  Mon May 09, 2005
      Change default behavior to AI::Prolog->raw_results(1).

README  view on Meta::CPAN

   make test
   make install

DEPENDENCIES

This module requires these other modules and libraries:
  
 aliased
 Clone
 Exporter::Tidy
 Test::Differences
 Test::MockModule

COPYRIGHT AND LICENCE

Copyright (C) 2005 Curtis "Ovid" Poe

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself. 

examples/schedule.pl  view on Meta::CPAN

#!/usr/bin/perl 
# http://xbean.cs.ccu.edu.tw/~dan/PL/PLTests/PLFinal2002.htm
# Write a Prolog program to schedule classes for a department of NG University.
# There are 6 class periods, 6-8pm and 8-10pm on Monday, Wednesday, and Friday
# evenings.   There are classrooms A, B, and C, and teachers Jim, Sally, Susan,
# and George.  There are classes algebra, geometry, calculus, and analysis, each
# of which has to be taught 2 class periods per week.  Jim can only come on
# Mondays.  Sally and Susan want to work together.   George can only teach the
# 6-8pm periods. Just write the program to print all possible schedules that meet
# these constraints; don?t try to solve the scheduling problem.

use strict;

t/01pod.t  view on Meta::CPAN

#!/usr/bin/perl -w
use strict;
use Test::More;
eval "use Test::Pod 1.06";
plan skip_all => "Test::Pod 1.06 required for testing POD" if $@;
all_pod_files_ok();

t/05examples.t  view on Meta::CPAN

#!/usr/local/bin/perl
use strict;
use warnings;
#use Test::More 'no_plan';
use Test::More tests => 6;

my $CLASS;
BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
}

use lib '../lib/';
use aliased 'AI::Prolog';

t/10choicepoint.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 10choicepoint.t,v 1.2 2005/02/13 21:01:02 ovid Exp $';
use warnings;
use strict;
use Test::More tests => 11;

my $CLASS;
BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog::ChoicePoint';
    use_ok($CLASS) or die;
}

t/20term.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 20term.t,v 1.6 2005/08/06 23:28:40 ovid Exp $';
use warnings;
use strict;
use Test::More tests => 92;
#use Test::More 'no_plan';

my $CLASS;
BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog::Term';
    use_ok($CLASS) or die;
}

t/25cut.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 25cut.t,v 1.1 2005/02/20 18:27:55 ovid Exp $';
use warnings;
use strict;
use Test::More tests => 27;
#use Test::More 'no_plan';

#XXX This is a bit annoying.  Term knows about its subclass, CUT,
# and this forces us to use Term before we use_ok($CLASS).
use aliased 'AI::Prolog::Term';
my $CLASS;
BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog::Term::Cut';

t/25number.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 25number.t,v 1.1 2005/02/20 18:27:55 ovid Exp $';
use warnings;
use strict;
use Test::More tests => 34;
#use Test::More 'no_plan';

#XXX This is a bit annoying.  Term knows about its subclass, CUT,
# and this forces us to use Term before we use_ok($CLASS).
use aliased 'AI::Prolog::Term';
my $CLASS;
BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog::Term::Number';

t/30termlist.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 30termlist.t,v 1.3 2005/08/06 23:28:40 ovid Exp $';
use warnings;
use strict;
#use Test::More 'no_plan';
use Test::More tests => 14;

my $CLASS;
BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog::TermList';
    use_ok($CLASS) or die;
}

t/35clause.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 35clause.t,v 1.2 2005/08/06 23:28:40 ovid Exp $';
use warnings;
use strict;
#use Test::More 'no_plan';
use Test::More tests => 14;

my $CLASS;
BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog::TermList::Clause';
    use_ok($CLASS) or die;
}

t/35primitive.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 35primitive.t,v 1.2 2005/06/20 07:36:48 ovid Exp $';
use warnings;
use strict;
#use Test::More 'no_plan';
use Test::More tests => 6;

my $CLASS;
BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog::TermList::Primitive';
    use_ok($CLASS) or die;
}

t/35step.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 35step.t,v 1.2 2005/08/06 23:28:40 ovid Exp $';
use warnings;
use strict;
#use Test::More 'no_plan';
use Test::More tests => 12;

my $CLASS;
BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog::TermList::Step';
    use_ok($CLASS) or die;
}

t/40parser.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 40parser.t,v 1.6 2005/08/06 23:28:40 ovid Exp $';
use warnings;
use strict;
use Test::More;
BEGIN {
eval 'use Test::MockModule';
if ($@) {
    plan skip_all => 'Test::MockModule required for this';
} else {
    plan tests => 76;
}
}
#use Test::More 'no_plan';

my $CLASS;
BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog::Parser';
    use_ok($CLASS) or die;
}

t/40parser.t  view on Meta::CPAN

is $parser->_posn, 42, '... and the new posn is the first character after the number';

can_ok $parser, 'empty';
ok ! $parser->empty, '... and it should return false if there is more stuff to parse';
$parser->advance; # skip ')'
$parser->advance; # skip '.'
$parser->skipspace;
ok $parser->empty, '... and return true when there is nothing left to parse.  How sad.';

can_ok $parser, 'resolve';
my $termlist = Test::MockModule->new(TermList);
my $resolve = 0;
$termlist->mock('resolve', sub {$resolve++});
my $new_db = KnowledgeBase->new;
%{$new_db->ht} = map { $_ => TermList->new } 1 .. 3;
$parser->resolve($new_db);
is $resolve, 3, '... and TermList->resolve should be called once for each termlist in the db';

can_ok $CLASS, 'consult';
my $db = $CLASS->consult(<<'END_PROLOG');
owns(merlyn, gold).

t/50engine.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 50engine.t,v 1.10 2005/08/06 23:28:40 ovid Exp $';
use warnings;
use strict;
use Test::More tests => 35;

#use Test::More 'no_plan';
use Clone qw/clone/;

my $CLASS;

BEGIN {
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog::Engine';
    use_ok($CLASS) or die;
}

t/60aiprolog.t  view on Meta::CPAN

#!/usr/bin/perl
use warnings;
use strict;
use Test::More tests => 5;

my $CLASS;
BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog';
    use_ok($CLASS, ':all') or die;
}

t/70builtins.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 70builtins.t,v 1.7 2005/08/06 23:28:40 ovid Exp $';
use warnings;
use strict;
use Test::More;
BEGIN {
eval q{
use Test::MockModule;
use Test::Differences};
if ($@) {
    plan skip_all => "Test::MockModule, Test::Differences required for this";
} else {
    plan tests => 39;
}
}
#use Test::More qw/no_plan/;
use Clone qw/clone/;

BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
}
use aliased 'AI::Prolog';
use aliased 'AI::Prolog::Engine';
use aliased 'AI::Prolog::KnowledgeBase';

t/70builtins.t  view on Meta::CPAN

$prolog->query("steals(badguy,X).");
is $prolog->results, 'steals(badguy, rubies)',
    'if(X,Y,Z) should call Y if X is satisfied';
ok ! $prolog->results, '... and it should only provide correct results';

$prolog->query("steals(ovid,X).");
is $prolog->results, 'steals(ovid, nothing)',
    '... and it should call Z if X cannot be satisfied';
ok ! $prolog->results, '... and it should only provide correct results';

my $faux_engine = Test::MockModule->new(Engine);
my @stdout;
$faux_engine->mock(_print => sub { push @stdout => @_ });

$prolog->query("nl.");
$prolog->results;
is_deeply \@stdout, ["\n"], "nl should print a newline";

$prolog->query("not(thief(ovid)).");
is $prolog->results, 'not(thief(ovid))',
    'not() should succeed if query cannot be proven';

t/70builtins.t  view on Meta::CPAN

$prolog->query('test_var(X, Y)');
is $prolog->results, 'test_var(A, is_var)', 'var(X) should evaluate to true';
$prolog->query('test_var(42, Y)');
is $prolog->results, 'test_var(42, not_var)',
    '... and var(42) should evaluate to not true';
$prolog->query('test_var(ovid, Y)');
is $prolog->results, 'test_var(ovid, not_var)',
    '... and var(ovid) should evaluate to not true';

{
    my $faux_kb = Test::MockModule->new(KnowledgeBase);
    my @stdout;
    $faux_kb->mock(_print => sub { push @stdout => @_ });
    $prolog->query('listing.');
    $prolog->results;
    my $results = join ''=> @stdout;
    my $count = ($results =~ s/(\d+\.\s+\w+\/\d+:)//g);
    ok $count, 'listing should display a listing of the database';
}

t/80math.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 80math.t,v 1.5 2005/08/06 23:28:40 ovid Exp $';
use warnings;
use strict;
use Test::More tests => 31;

#use Test::More qw/no_plan/;
use Clone qw/clone/;

BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
}
use aliased 'AI::Prolog';
use aliased 'AI::Prolog::Engine';
use aliased 'AI::Prolog::KnowledgeBase';

t/80preprocessor.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 80preprocessor.t,v 1.2 2005/06/20 07:36:48 ovid Exp $';
use warnings;
use strict;
use Test::More tests => 8;
#use Test::More qw/no_plan/;
use aliased 'AI::Prolog';

my $CLASS;
BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog::Parser::PreProcessor';
    use_ok($CLASS) or die;
}

t/80preprocessor_math.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 80preprocessor_math.t,v 1.3 2005/08/06 23:28:40 ovid Exp $';
use warnings;
use strict;
use Test::More tests => 140;
#use Test::More qw/no_plan/;

my $CLASS;
BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog::Parser::PreProcessor::Math';
    use_ok($CLASS) or die;
}

t/90results.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 50engine.t,v 1.10 2005/08/06 23:28:40 ovid Exp $';
use warnings;
use strict;
use Test::More tests => 6;

my $CLASS;

BEGIN {
    chdir 't' if -d 't';
    unshift @INC => '../lib';
    $CLASS = 'AI::Prolog';
    use_ok($CLASS) or die;
}

t/99regression.t  view on Meta::CPAN

#!/usr/bin/perl
# '$Id: 99regression.t,v 1.4 2005/08/06 23:28:40 ovid Exp $';
use warnings;
use strict;
use Test::More;
BEGIN {
eval q{use Test::MockModule};
if ($@) {
    plan skip_all => "Test::MockModule, Test::Exception required for this";
} else {
    plan tests => 5;
}
}
#use Test::More qw/no_plan/;

BEGIN
{
    chdir 't' if -d 't';
    unshift @INC => '../lib';
}
use aliased 'AI::Prolog';
use aliased 'AI::Prolog::Engine';

Engine->formatted(1);

t/99regression.t  view on Meta::CPAN

my @expected = (
  [ 'a', 'b' ],
  [ 'a', 'c' ],
  [ 'b', 'a' ],
  [ 'b', 'c' ],
  [ 'c', 'a' ],
  [ 'c', 'b' ]
);
is_deeply \@results, \@expected, 'The .62 unify bug should be bye-bye';

my $faux_engine = Test::MockModule->new(Engine);
my @stdout;
$faux_engine->mock(_warn => sub { push @stdout => @_ });
$prolog->query('no_such_predicate(X).');
$prolog->results;
like $stdout[0], qr{WARNING:  undefined predicate \(no_such_predicate/1\)},
    'Non-existent predicates should warn';



( run in 0.491 second using v1.01-cache-2.11-cpan-4d50c553e7e )