File Coverage

blib/lib/Devel/TypeCheck/Type.pm
Criterion Covered Total %
statement 18 93 19.3
branch 1 16 6.2
condition 0 6 0.0
subroutine 5 34 14.7
pod 24 28 85.7
total 48 177 27.1


line stmt bran cond sub pod time code
1             package Devel::TypeCheck::Type;
2              
3 1     1   6 use strict;
  1         2  
  1         46  
4 1     1   6 use Carp;
  1         2  
  1         121  
5              
6             require Exporter;
7              
8             our @ISA = qw(Exporter);
9             our @EXPORT = ();
10             our @EXPORT_OK = qw(n2s s2n);
11              
12 1     1   629 use Devel::TypeCheck::Util;
  1         3  
  1         232  
13              
14             =head1 NAME
15              
16             Devel::TypeCheck::Type - base type for the type language representation of Devel::TypeCheck
17              
18             =head1 SYNOPSIS
19              
20             Devel::TypeCheck::Type is an abstract class and should not be
21             instantiated directly. However, all types used in the type system are
22             inheritors of this class and rely on methods defined here.
23              
24             =head1 DESCRIPTION
25              
26             The data structure is essentially a linked list from Mu at the head of
27             the list to terminal or variable types at the end. Thus, most of the
28             functions defined here support that by relaying the request to the
29             subtype member (the next link in the linked list) instead of actually
30             doing anything themselves.
31              
32             =over 4
33              
34             =cut
35              
36             # This is the base class for the object system used to store the types
37             # when computing the run-time type inference.
38              
39             # **** CLASS ****
40              
41             our $AUTOLOAD; # Package global used in &AUTOLOAD
42              
43             our %name2number; # Mapping type names to numbers from @EXPORTS for &AUTOLOAD
44             our @number2name; # Mapping numbers to names for printing purposes
45              
46             our @SUBTYPES;
47             our @subtypes;
48              
49             =item B
50              
51             Class methods implemented through C<< AUTOLOAD >> to return a unique
52             number for each different function. This is used to represent type
53             for certain queries.
54              
55             =cut
56              
57             # Set up the tables for AUTOLOAD, n2s, and s2n operation.
58             BEGIN {
59 1     1   2 my $count = 0;
60 1         4 @EXPORT = qw(VAR M H K P N O X Y Z IO PV IV DV);
61              
62 1         9 for my $i (@EXPORT) {
63 14         25 $number2name[$count] = $i;
64 14         8080 $name2number{$i} = $count++;
65             }
66             }
67              
68             # For the Devel::TypeCheck::Type::{VAR,M,H,etc...}() methods
69             sub AUTOLOAD {
70 19     19   41 my $name = $AUTOLOAD;
71 19         95 $name =~ s/.*://; # strip fully-qualified portion
72              
73             # Die if the name this was called by isn't exported
74 19 50       73 if (!exists($name2number{$name})) {
75 0         0 confess("Method &$name not implemented");
76             }
77            
78 19         100 return $name2number{$name};
79             }
80              
81             # Number to string lookup on Type subclasses
82             sub n2s ($) {
83 0     0 0   my ($n) = @_;
84 0           return $number2name[$n];
85             }
86              
87             # String to number lookup on Type subclasses
88             sub s2n ($) {
89 0     0 0   my ($s) = @_;
90 0           return $name2number{$s};
91             }
92              
93             # Required, since AUTOLOAD will suck this up if not defined
94 0     0     sub DESTROY {}
95              
96             # **** INSTANCE ****
97              
98             =item B($subtype)
99              
100             Create a new Type instance with the given item as the next link in the
101             list data structure. This will control the subtypes allowed, so that
102             illegal types cannot be created when using this constructor. This
103             method is abstract for this class, but works with subtypes. Types are
104             never constructed by the user -- they should always be generated with
105             the fresh* and gen* methods of the type environment,
106             Devel::TypeCheck::Environment.
107              
108             =cut
109              
110             # Constructor
111             sub new {
112 0     0 1   my ($name, $subtype) = @_;
113              
114 0 0         if ($name eq "Devel::TypeCheck::Type") {
115 0           abstract("new", $name);
116             }
117              
118 0 0         if (! $subtype->isa("Devel::TypeCheck::Type")) {
119 0           croak("Subtype is not a member of class Devel::TypeCheck::Type");
120             }
121              
122 0           my $this = {};
123              
124 0           bless($this, $name);
125              
126 0 0         if (! $this->hasSubtype($subtype->type)) {
127 0           croak("Invalid subtype ", n2s($subtype->type), " for class $name");
128             }
129              
130 0           $this->{'subtype'} = $subtype;
131              
132 0           return $this;
133             }
134              
135             =item B
136              
137             Return the numerical type of the instance.
138              
139             =cut
140              
141             # Returns the type of an instance
142             sub type {
143 0     0 1   my ($this) = @_;
144 0           abstract("type", ref($this));
145             }
146              
147             =item B
148              
149             Returns the next link in the list.
150              
151             =cut
152              
153             # Returns the subtype
154             sub subtype {
155 0     0 1   my ($this) = @_;
156 0           return $this->{'subtype'};
157             }
158              
159             =item B($type)
160              
161             Returns true if the given instance has the given type.
162              
163             =cut
164              
165             # Determines if a given class has a given type as an allowed subtype
166             sub hasSubtype {
167 0     0 1   abstract("hasSubtype", "Devel::TypeCheck::Type");
168             }
169              
170             # Shouldn't ever be called except by a T::Environment or an inheritor of T.
171             sub unify {
172 0     0 0   my ($this, $that, $env) = @_;
173              
174 0           $this = $env->find($this);
175 0           $that = $env->find($that);
176              
177             # Make sure that types match and that subtypes are valid.
178 0 0 0       if ($this->type == $that->type &&
      0        
179             $this->hasSubtype($this->subtype->type) &&
180             $that->hasSubtype($that->subtype->type)) {
181 0           return $this->subtype->unify($that->subtype, $env);
182             } else {
183 0           return undef;
184             }
185             }
186              
187             # Do the occurs check against $that with the given environment $env.
188             sub occurs {
189 0     0 0   my ($this, $that, $env) = @_;
190            
191 0 0         if ($that->type != Devel::TypeCheck::Type::VAR()) {
192 0           die("Invalid type ", $that->str, " for occurs check");
193             }
194              
195 0           return $this->subtype->occurs($that, $env);
196             }
197              
198             =item B($env)
199              
200             Return a string constructed from this type and subtypes. This is the
201             "ugly" string as output by the B::TypeCheck backend module.
202              
203             =cut
204              
205             # Return a readable string
206             sub str {
207 0     0 1   my ($this, $env) = @_;
208 0           return (n2s($this->type) . $this->subtype->str($env));
209             }
210              
211             =item B
212              
213             The human readable description of this type.
214              
215             =cut
216              
217             sub pretty {
218 0     0 1   my ($this, $env) = @_;
219 0           return $this->subtype->pretty($env);
220             }
221              
222             =item B($type)
223              
224             Indicate whether some instance in the list of types is the same as the
225             numerical type passed to this method.
226              
227             =cut
228              
229             sub is {
230 0     0 1   my ($this, $type) = @_;
231 0 0         if ($this->type == $type) {
232 0           return TRUE;
233             } else {
234 0 0         if (defined($this->subtype)) {
235 0           return $this->subtype->is($type);
236             } else {
237 0           return FALSE();
238             }
239             }
240             }
241              
242             =item B
243              
244             Return the parent type of the instance. This always returns undef for
245             internal and most terminal types, but returns the variable's parent in
246             the union-find data structure (if it has one).
247              
248             =cut
249              
250             # If the return is undefined, then the type has no parent in the type
251             # classes. Incomplete and terminal types act this way. Type
252             # variables return the current type class that they belong to, if any.
253             sub getParent {
254 0     0 1   return undef;
255             }
256              
257             =item B
258              
259             True if the type is completely specified and has no unbound type variables.
260              
261             =cut
262              
263             # Returns a boolean value. If TRUE, then the type is complete and has
264             # no type variables.
265             sub complete {
266 0     0 1   my ($this) = @_;
267 0           return $this->subtype->complete;
268             }
269              
270             =item B
271              
272             Dereference this type.
273              
274             =cut
275              
276             sub deref {
277 0     0 1   my ($this) = @_;
278 0           return $this->subtype->deref;
279             }
280              
281             =item B
282              
283             Whether the underlying array or hash is homogeneous.
284              
285             =cut
286              
287             sub homogeneous {
288 0     0 1   my ($this) = @_;
289 0           return $this->subtype->homogeneous();
290             }
291              
292             =item B
293              
294             The size of the tuple, if the type at the end of the linked list is a
295             tuple type for an array. This fails otherwise.
296              
297             =cut
298              
299             sub arity {
300 0     0 1   my ($this) = @_;
301 0           return $this->subtype->arity;
302             }
303              
304             =item B
305              
306             Append a given type to an array type. Promotes to homogeneous list as necessary.
307              
308             =cut
309              
310             sub append {
311 0     0 1   my ($this, $that, $env) = @_;
312 0           return $this->subtype->append($that, $env, $this);
313             }
314              
315             =item B
316              
317             Get the underlying tuple from a tuple type.
318              
319             =cut
320              
321             sub ary {
322 0     0 1   my ($this) = @_;
323 0           return $this->subtype->ary();
324             }
325              
326             =item B($index, $env)
327              
328             Dereference the type from the array or hash at the given index.
329              
330             =cut
331              
332             sub derefIndex {
333 0     0 1   my ($this, $index, $env) = @_;
334 0           return $this->subtype->derefIndex($index, $env);
335             }
336              
337             =item B
338              
339             Dereference the homogeneous type for lists and associative arrays.
340              
341             =cut
342              
343             sub derefHomogeneous {
344 0     0 1   my ($this) = @_;
345 0           return $this->subtype->derefHomogeneous();
346             }
347              
348             =item B
349              
350             Generate a list of references from the underlying array. Exists solely to support the srefgen operator on items of array type.
351              
352             =cut
353              
354             sub referize {
355 0     0 1   my ($this, $env) = @_;
356 0           return $this->subtype->referize($env);
357             }
358              
359             =item B
360              
361             Get the scalar type out of a glob type. This is roughly equivalent to C<<*foo{SCALAR}>>.
362              
363             =cut
364             sub derefKappa {
365 0     0 1   my ($this) = @_;
366 0           return $this->subtype->derefKappa();
367             }
368              
369             =item B
370              
371             Get the array type out of a glob type. This is roughly equivalent to C<<*foo{ARRAY}>>.
372              
373             =cut
374             sub derefOmicron {
375 0     0 1   my ($this) = @_;
376 0           return $this->subtype->derefOmicron();
377             }
378              
379             =item B
380              
381             Get the hash type out of a glob type. This is roughly equivalent to C<<*foo{HASH}>>.
382              
383             =cut
384             sub derefChi {
385 0     0 1   my ($this) = @_;
386 0           return $this->subtype->derefChi();
387             }
388              
389             =item B
390              
391             Get the CV type out of a glob type. This is roughly equivalent to C<<*foo{CODE}>>.
392              
393             =cut
394             sub derefZeta {
395 0     0 1   my ($this) = @_;
396 0           return $this->subtype->derefZeta();
397             }
398              
399             =item B
400              
401             Coerce a hash in to an array.
402              
403             =cut
404             sub listCoerce {
405 0     0 1   my ($this, $env) = @_;
406 0           return $this->subtype->listCoerce($env);
407             }
408              
409             =item B
410              
411             Dereference the parameter list type from a CV.
412              
413             =cut
414             sub derefParam {
415 0     0 1   my ($this, $env) = @_;
416 0           return $this->subtype->derefParam();
417             }
418              
419             =item B
420              
421             Dereference the return value type from a CV.
422              
423             =cut
424             sub derefReturn {
425 0     0 1   my ($this, $env) = @_;
426 0           return $this->subtype->derefReturn();
427             }
428              
429             =back
430              
431             =cut
432              
433             TRUE;
434              
435             =head1 AUTHOR
436              
437             Gary Jackson, C<< >>
438              
439             =head1 BUGS
440              
441             This version is specific to Perl 5.8.1. It may work with other
442             versions that have the same opcode list and structure, but this is
443             entirely untested. It definitely will not work if those parameters
444             change.
445              
446             Please report any bugs or feature requests to
447             C, or through the web interface at
448             L.
449             I will be notified, and then you'll automatically be notified of progress on
450             your bug as I make changes.
451              
452             =head1 COPYRIGHT & LICENSE
453              
454             Copyright 2005 Gary Jackson, all rights reserved.
455              
456             This program is free software; you can redistribute it and/or modify it
457             under the same terms as Perl itself.
458              
459             =cut