view release on metacpan or search on metacpan
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).
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;
#!/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;
}
#!/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;
}
#!/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;
}
#!/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';
}
#!/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';