AI-Prolog
view release on metacpan or search on metacpan
lib/AI/Prolog/Engine.pm view on Meta::CPAN
my $curr_term = $clause->{term}->refresh($vars);
if ( $curr_term->unify( $self->{_goal}->term, $self->{_stack} ) ) {
$clause = $clause->{next};
if ( $clause && $clause->isa(Primitive) ) {
if ( !$self->do_primitive( $self->{_goal}->{term}, $clause )
&& !$self->backtrack )
{
return;
}
}
elsif ( !$clause ) { # matching against fact
$self->{_goal} = $self->{_goal}->{next};
if ( $self->{_goal} ) {
$self->{_goal}->resolve( $self->{_db} );
}
}
else { # replace goal by clause body
my ( $p, $p1, $ptail ); # termlists
for ( my $i = 1; $clause; $i++ ) {
# will there only be one CUT?
if ( $clause->{term} eq Term->CUT ) {
$p = TermList->new( Cut->new($stackTop) );
}
else {
$p = TermList->new( $clause->{term}->refresh($vars) );
}
if ( $i == 1 ) {
$p1 = $ptail = $p;
}
else {
$ptail->next($p);
$ptail = $p; # XXX ?
}
$clause = $clause->{next};
}
$ptail->next( $self->{_goal}->{next} );
$self->{_goal} = $p1;
$self->{_goal}->resolve( $self->{_db} );
}
}
else { # unify failed. Must backtrack
return unless $self->backtrack;
}
}
}
sub backtrack {
my $self = shift;
_print(" <<== Backtrack: \n") if $self->{_trace};
while ( @{ $self->{_stack} } ) {
my $o = pop @{ $self->{_stack} };
if ( UNIVERSAL::isa( $o, Term ) ) {
$o->unbind;
}
elsif ( UNIVERSAL::isa( $o, ChoicePoint ) ) {
$self->{_goal} = $o->{goal};
# XXX This could be very dangerous if we accidentally try
# to assign a term to itself! See ChoicePoint->next_clause
$self->{_goal}->next_clause( $o->{clause} );
return 1;
}
}
return;
}
sub _print { # convenient testing hook
print @_;
}
sub _warn { # convenient testing hook
warn @_;
}
use constant RETURN => 2;
sub do_primitive { # returns false if fails
my ( $self, $term, $c ) = @_;
my $primitive = AI::Prolog::Engine::Primitives->find( $c->ID )
or die sprintf "Cannot find primitive for %s (ID: %d)\n",
$term->to_string, $c->ID;
return unless my $result = $primitive->( $self, $term, $c );
return 1 if RETURN == $result;
$self->{_goal} = $self->{_goal}->next;
if ( $self->{_goal} ) {
$self->{_goal}->resolve( $self->{_db} );
}
return 1;
}
1;
__END__
=head1 NAME
AI::Prolog::Engine - Run queries against a Prolog database.
=head1 SYNOPSIS
my $engine = AI::Prolog::Engine->new($query, $database).
while (my $results = $engine->results) {
print "$result\n";
}
=head1 DESCRIPTION
C<AI::Prolog::Engine> is a Prolog engine implemented in Perl.
The C<new()> function actually bootstraps some Prolog code onto your program to
give you access to the built in predicates listed in the
L<AI::Prolog::Builtins|AI::Prolog::Builtins> documentation.
This documentation is provided for completeness. You probably want to use
L<AI::Prolog|AI::Prolog>.
=head1 CLASS METHODS
( run in 1.050 second using v1.01-cache-2.11-cpan-39bf76dae61 )