File Coverage

blib/lib/Language/Prolog/Types/Abstract.pm
Criterion Covered Total %
statement 27 74 36.4
branch 0 24 0.0
condition 0 24 0.0
subroutine 9 40 22.5
pod 10 10 100.0
total 46 172 26.7


line stmt bran cond sub pod time code
1             package Language::Prolog::Types::Abstract;
2              
3             our $VERSION = '0.10';
4              
5             =head1 NAME
6              
7             Language::Prolog::Types::Abstract - Abstract classes for Prolog terms in Perl.
8              
9             =head1 SYNOPSIS
10              
11             use Language::Prolog::Types::Abstract;
12             if prolog_is_atom('hello') {
13             print "'hello' is a Prolog atom\n"
14             }
15              
16             ...
17              
18             etc.
19              
20             =head1 ABSTRACT
21              
22             Language::Prolog::Types::Abstract defines a set of abstract classes
23             for Prolog terms.
24              
25             It also includes functions to check for Prolog types and some utility
26             functions to perform explicit conversion between Prolog and Perl.
27              
28             =head1 DESCRIPTION
29              
30             This module define abstract classes for the usual Prolog functors,
31             lists, variables and nil.
32              
33             Atoms are not included because perl scalars do the work.
34              
35             Perl C is equivalent to Prolog nil (C<[]>), although a
36             different representation is allowed for the Prolog term.
37              
38             Perl lists can be directly used as Prolog lists. The inverse is not
39             always true and depends of the implementations used.
40              
41             =head2 EXPORT
42              
43             =over 4
44              
45             =cut
46              
47              
48 1     1   5 use strict;
  1         2  
  1         30  
49 1     1   6 use warnings;
  1         1  
  1         21  
50              
51 1     1   12 use Carp;
  1         2  
  1         710  
52              
53             require Exporter;
54             our @ISA=qw(Exporter);
55             our @EXPORT=qw( prolog_is_term
56             prolog_is_atom
57             prolog_is_nil
58             prolog_is_functor
59             prolog_is_list
60             prolog_is_list_or_nil
61             prolog_is_variable
62             prolog_is_var
63             prolog_is_ulist
64             prolog_list2perl_list );
65              
66              
67             # prolog_is functions:
68              
69             # basic perl types ($ and @) are automatically coerced.
70              
71             =item C
72              
73             returns true if C<$term> is a valid Prolog term (actually a perl
74             number, string or array or any object descending from
75             L).
76              
77             =cut
78              
79             sub prolog_is_term ($ ) {
80 0 0 0 0 1   !ref($_[0])
81             or ref($_[0]) eq 'ARRAY'
82             or UNIVERSAL::isa('Language::Prolog::Types::Term',$_[0])
83             }
84              
85             =item C
86              
87             returns true if C<$term> is a valid Prolog atom (actually a perl
88             number or string).
89              
90             =cut
91              
92 0 0   0 1   sub prolog_is_atom ($ ) { defined($_[0]) and !ref($_[0]) }
93              
94             =item C
95              
96             returns true if C<$term> is Prolog nil value (C<[]>).
97              
98             =cut
99              
100             sub prolog_is_nil ($ ) {
101 0     0 1   my $self=shift;
102 0 0 0       !defined($self)
      0        
103             or UNIVERSAL::isa($self, 'Language::Prolog::Types::Nil')
104             or (ref($self) eq 'ARRAY' and @$self==0)
105             }
106              
107             =item C
108              
109             returns true if $term is a Prolog functor.
110              
111             It should be noted that lists are equivalent to functor '.'/2 and
112             because of that, this function will also return true when $term is a
113             list.
114              
115             =cut
116              
117             sub prolog_is_functor ($ ) {
118 0     0 1   my $self=shift;
119 0           UNIVERSAL::isa($self, 'Language::Prolog::Types::Functor')
120 0 0 0       or (ref($self) eq 'ARRAY' and @{$self}>0)
121             }
122              
123              
124             =item C
125              
126             returns true if C<$term> is a Prolog list.
127              
128             It should be noted that although Prolog nil is usually represented as
129             the empty list C<[]>, it is not really a Prolog list and this function
130             will return false for it.
131              
132             =cut
133              
134             sub prolog_is_list ($ ) {
135 0     0 1   my $self=shift;
136 0 0 0       UNIVERSAL::isa($self, 'Language::Prolog::Types::List')
137             or (ref($self) eq 'ARRAY' and @$self>0);
138             }
139              
140             =item C
141              
142             returns true if C<$term> is Prolog nil or a list.
143              
144             =cut
145              
146             sub prolog_is_list_or_nil ($ ) {
147 0     0 1   my $self=shift;
148 0 0 0       !defined($self)
149             or UNIVERSAL::isa($self, 'Language::Prolog::Types::ListOrNil')
150             or ref($self) eq 'ARRAY'
151             }
152              
153             =item C
154              
155             =item C
156              
157             return true if C<$term> is a free (unbounded) Prolog variable
158              
159             =cut
160              
161             sub prolog_is_variable ($ ) {
162 0     0 1   UNIVERSAL::isa(shift, 'Language::Prolog::Types::Variable');
163             }
164             *prolog_is_var=\&prolog_is_variable;
165              
166              
167             =item C
168              
169             returns true if $term is an unfinished Prolog list, that means, one
170             with doesn't end in nil. i.e. difference lists.
171              
172             =cut
173              
174             sub prolog_is_ulist ($ ) {
175 0     0 1   UNIVERSAL::isa(shift, 'Language::Prolog::Types::UList');
176             }
177              
178             # util functorions:
179              
180             =item C
181              
182             converts a Prolog list or nil to a Perl array.
183              
184             =cut
185              
186             sub prolog_list2perl_list {
187 0     0 1   my $self=shift;
188 0 0         return () if !defined($self);
189 0 0         return @{$self} if ref($self) eq 'ARRAY';
  0            
190 0           my @result=eval { $self->largs };
  0            
191 0 0         croak "object '$self' is not a valid Prolog list" if $@;
192 0           @result;
193             }
194              
195             =item C
196              
197             Strings are usually represented in Prolog as lists of numbers. This
198             function do the oposite conversion, from a list of numbers to a Perl
199             string.
200              
201             It should be noted that all the elements in the Prolog list have to be
202             integers in the range [0..255] or an execption will be raised.
203              
204             =cut
205              
206             sub prolog_list2perl_string {
207 0 0 0       pack "C*", ( grep {
      0        
208 0     0 1   ( prolog_is_atom($_) and /^\d+$/ and $_<256 )
209             or croak "Prolog list is not a valid string"
210             } (prolog_list2perl_list $_[0]) )
211             }
212              
213              
214             # abstract classes for Prolog types:
215              
216             =back
217              
218             =head2 ABSTRACT CLASSES
219              
220             =head3 Language::Prolog::Types::Term
221              
222             common abstract class for every Prolog term.
223              
224             =cut
225              
226             package Language::Prolog::Types::Term;
227              
228              
229              
230             =head3 Language::Prolog::Types::ListOrNil
231              
232             This class is used to account for the intrinsec differences between
233             empty lists in Perl and Prolog.
234              
235             In Prolog, nil although represented as the empty list, is not really a
236             list.
237              
238             This class provides a set of methods that apply both to lists and nil
239             if it is considered to be the empty list.
240              
241             BTW, you should mostly ignore this class and use
242             L or L
243             instead.
244              
245              
246             =head4 Inherits:
247              
248             =over 4
249              
250             =item L
251              
252             =back
253              
254             =head4 Methods:
255              
256             =over 4
257              
258             =item C<$lon-Elength()>
259              
260             returns the number of terms in the list. If the list is unfinished,
261             the tail is not counted.
262              
263             =item C<$lon-Elargs()>
264              
265             returns the terms in the list. If the list is unfinished, the tail
266             is ignored.
267              
268             =item C<$lon-Etail()>
269              
270             returns the list tail, that will be nil if the list is finished or is nil
271              
272             =item C<$lon-Elarg($index)>
273              
274             returns element number C<$index> on the list, if $index is negative,
275             the list is indexed from the end.
276              
277             =back
278              
279             =cut
280              
281             package Language::Prolog::Types::ListOrNil;
282             our @ISA=qw(Language::Prolog::Types::Term);
283              
284 1     1   5 use Carp;
  1         2  
  1         198  
285 0     0     sub larg { croak "unimplemented virtual method" }
286 0     0     sub largs { croak "unimplemented virtual method" }
287 0     0     sub length { croak "unimplemented virtual method" }
288 0     0     sub tail { croak "unimplemented virtual method" }
289              
290              
291             =head3 Language::Prolog::Types::Nil
292              
293             Common abstract class for Prolog nil term representation.
294              
295             =head4 Inherits
296              
297             =over 4
298              
299             =item L
300              
301             =back
302              
303             =head4 Methods
304              
305             This class doesn't define any method on its own.
306              
307             =cut
308              
309             package Language::Prolog::Types::Nil;
310             our @ISA=qw(Language::Prolog::Types::ListOrNil);
311              
312             =head3 Language::Prolog::Types::Variable
313              
314             Common abstract class for Prolog variable representation.
315              
316             =head4 Inherits:
317              
318             =over 4
319              
320             =item L
321              
322             =back
323              
324             =head4 Methods:
325              
326             =over 4
327              
328             =item C<$var-Ename()>
329              
330             returns the variable name.
331              
332             =back
333              
334             =cut
335              
336             package Language::Prolog::Types::Variable;
337             our @ISA=qw(Language::Prolog::Types::Term);
338              
339 1     1   5 use Carp;
  1         1  
  1         129  
340 0     0     sub name { croak "unimplemented virtual method" }
341 0     0     sub rename { croak "unimplemented virtual method" }
342              
343             =head3 Language::Prolog::Types::Functor
344              
345             Common abstract class for Prolog functor representations.
346              
347             =head4 Inherits:
348              
349             =over 4
350              
351             =item L
352              
353             =back
354              
355             =head4 Methods:
356              
357             =over 4
358              
359             =item C<$f-Efunctor()>
360              
361             returns the functor name.
362              
363             =item C<$f-Earity()>
364              
365             returns the number of arguments of the functor.
366              
367             =item C<$f-Efargs()>
368              
369             returns the arguments of the functor.
370              
371             =item C<$f-Efarg($index)>
372              
373             returns the argument of the functor in the position C<$index>, if
374             C<$index> is negative the arguments are indexed begining from the end.
375              
376             Be aware that arguments are indexed from 0, not from 1 as in prolog.
377              
378             =back
379              
380             =cut
381              
382             package Language::Prolog::Types::Functor;
383             our @ISA=qw(Language::Prolog::Types::Term);
384              
385 1     1   5 use Carp;
  1         1  
  1         178  
386 0     0     sub functor { croak "unimplemented virtual method" }
387 0     0     sub arity { croak "unimplemented virtual method" }
388 0     0     sub farg { croak "unimplemented virtual method" }
389 0     0     sub fargs { croak "unimplemented virtual method" }
390              
391              
392             =head3 Language::Prolog::Types::List
393              
394             Common abstract class for Prolog list representations.
395              
396             =head4 Inherits:
397              
398             =over 4
399              
400             =item L
401              
402             A Prolog list is actually the functor '.'/2. i.e.
403              
404             [1, 4, hello, foo]
405              
406             is equivalent to:
407              
408             '.'(1, '.'(4, '.'(hello, '.'(foo, []))))
409              
410              
411             =item L
412              
413             List methods are shared with L and this
414             is the reasong, to descent also from this class.
415              
416             =back
417              
418             =head4 Methods:
419              
420             =over 4
421              
422             =item C<$l-Ecar()>
423              
424             returns the list C.
425              
426             =item C<$l-Ecdr()>
427              
428             returns the list C.
429              
430             =item C<$l-Ecar_cdr()>
431              
432             returns both the C and the C of the list.
433              
434             =back
435              
436             =cut
437              
438             package Language::Prolog::Types::List;
439             our @ISA=qw(Language::Prolog::Types::Functor
440             Language::Prolog::Types::ListOrNil);
441 1     1   6 use Carp;
  1         1  
  1         294  
442 0     0     sub car { croak "unimplemented virtual method" }
443 0     0     sub cdr { croak "unimplemented virtual method" }
444 0     0     sub car_cdr { croak "unimplemented virtual method" }
445              
446             # default implementation of Functor methods for Lists
447 0     0     sub functor { '.' }
448 0     0     sub fargs { shift->car_cdr }
449             sub farg {
450 0     0     my ($self, $index)=@_;
451 0 0         return $self->car if $index==0;
452 0 0         return $self->cdr if $index==1;
453 0           croak "farg index $index out of range for '.'/2";
454             }
455              
456              
457             =head3 Language::Prolog::Types::UList
458              
459             Common abstract class to represent unfinished lists (those whose tail
460             is not nil).
461              
462             =head4 Inherits:
463              
464             =over 4
465              
466             =item L
467              
468             =back
469              
470             =head4 Methods:
471              
472             None of its own.
473              
474             =cut
475              
476             package Language::Prolog::Types::UList;
477             our @ISA=qw(Language::Prolog::Types::List);
478 1     1   6 use Carp;
  1         1  
  1         148  
479              
480              
481             =head3 Language::Prolog::Types::Unknow
482              
483             just in case...
484              
485             =head4 Inherits:
486              
487             =over 4
488              
489             =item L
490              
491             =back
492              
493             =head4 Methods:
494              
495             None.
496              
497             =cut
498              
499              
500             package Language::Prolog::Types::Unknow;
501             our @ISA=qw(Language::Prolog::Types::Term);
502              
503 0     0     sub id { '*unknow*' }
504              
505             =head3 Language::Prolog::Types::Opaque
506              
507             This class should be only used by Prolog <-> Perl interface authors.
508              
509             Usually Perl objects are converted to Prolog structures when passed to
510             a Prolog implementation. This class defines a proxy that stops the
511             conversion to happen and just pass a reference to the Perl object.
512              
513             Opaque objects should not be returned from Prolog interfaces, they
514             should only be used to indicate to the Prolog implementations to not
515             convert Perl data to Prolog. When returning from Prolog the original
516             object should be directly returned to improve usability.
517              
518             It should be noted that not all prolog implementations would support
519             this type.
520              
521              
522             =head4 Inherits:
523              
524             =over 4
525              
526             =item L
527              
528             =back
529              
530             =head4 Methods:
531              
532             =over 4
533              
534             =item C<$this-Eopaque_reference>
535              
536             returns the object that it shields from prolog
537              
538             =item C<$this->Eopaque_comment>
539              
540             returns comment string that will show in Prolog representation
541              
542             =item C<$this->Eopaque_class>
543              
544             returns object class as should been seen from Prolog side
545              
546             =back
547              
548             =cut
549              
550             package Language::Prolog::Types::Opaque;
551             our @ISA=qw(Language::Prolog::Types::Term);
552 1     1   5 use Carp;
  1         8  
  1         247  
553              
554 0     0     sub opaque_reference { croak "unimplemented virtual method" }
555              
556 0     0     sub opaque_comment { return '-' }
557              
558 0     0     sub opaque_class { return ref shift }
559              
560              
561             =head3 Language::Prolog::Types::Opaque::Auto
562              
563             Not really an abstract class but a simple implementation to be used as
564             a base class to provide automatic opacity to objects.
565              
566             So, objects of any class that has it as an ancestor will be passed to
567             prolog as a reference.
568              
569             =cut
570              
571              
572             package Language::Prolog::Types::Opaque::Auto;
573             our @ISA=qw(Language::Prolog::Types::Opaque);
574              
575 0     0     sub opaque_reference { return shift }
576              
577              
578             1; # module ok
579              
580              
581             =head1 SEE ALSO
582              
583             L.
584              
585             L contains an actual implementation
586             for the classes defined in this module.
587              
588             Any good Prolog book will also help :-)
589              
590             =head1 AUTHOR
591              
592             Salvador Fandiņo, Esfandino@yahoo.comE
593              
594             =head1 COPYRIGHT AND LICENSE
595              
596             Copyright 2002-2007 by Salvador Fandiņo
597              
598             This library is free software; you can redistribute it and/or modify
599             it under the same terms as Perl itself.
600              
601             =cut