line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Data::Variant.pm -- Algebraic datatypes for Perl |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# Copyright (c) 2004-2013 Viktor Leijon (leijon@ludd.ltu.se) All rights reserved. |
4
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify |
5
|
|
|
|
|
|
|
# it under the same terms as Perl itself. |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 NAME |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
Data::Variant - Variant datatypes for perl. |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 SYNOPSIS |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
use Data::Variant; |
15
|
|
|
|
|
|
|
use vars qw(&Empty &Leaf &Node); |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
register_variant("Tree","Empty","Leaf ","Node Tree Tree"); |
18
|
|
|
|
|
|
|
my $tree = Node((Node ((Leaf 3), (Leaf 4))), Leaf 5); |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub printTree { |
21
|
|
|
|
|
|
|
my $tree = shift; |
22
|
|
|
|
|
|
|
my ($data, $left, $right); |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
print "Data $data\n" |
25
|
|
|
|
|
|
|
if (match $tree,"Leaf", $data); |
26
|
|
|
|
|
|
|
printTree($left), printTree($right) |
27
|
|
|
|
|
|
|
if (match $tree,"Node",$left,$right); |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head1 DESCRIPTION |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
This module offers a Haskell/O'Caml-style for variant data types. You |
33
|
|
|
|
|
|
|
can register data types and then both construct them using the |
34
|
|
|
|
|
|
|
constructors give, and match against them as conditionals. The best |
35
|
|
|
|
|
|
|
way to understand what the module does is probably to look at the |
36
|
|
|
|
|
|
|
included examples. Pattern matching together with variants is (in the |
37
|
|
|
|
|
|
|
author's opinion) one of the very most useful features in Haskell and |
38
|
|
|
|
|
|
|
while this implementation is very informal it serves the same |
39
|
|
|
|
|
|
|
practical purpose. |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
There is some (very limited) typechecking available to make sure that |
42
|
|
|
|
|
|
|
you use your data structure as intended (well, as declared really but |
43
|
|
|
|
|
|
|
if you are wise these two coincide). |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
For the programmer unused to pattern matching, looking at the |
46
|
|
|
|
|
|
|
synoposis or the examples is probably the easiest way to get an idea |
47
|
|
|
|
|
|
|
of how to use the module. |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=head1 FUNCTIONS |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=over 4 |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=cut |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
package Data::Variant; |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# Requires perl 5.8.0 |
58
|
1
|
|
|
1
|
|
25740
|
use 5.8.0; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
48
|
|
59
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
26
|
|
60
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
7
|
|
|
1
|
|
|
|
|
41
|
|
61
|
1
|
|
|
1
|
|
5
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
75
|
|
62
|
1
|
|
|
1
|
|
7
|
use Exporter; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
45
|
|
63
|
1
|
|
|
1
|
|
1063
|
use Data::Dumper; |
|
1
|
|
|
|
|
11830
|
|
|
1
|
|
|
|
|
76
|
|
64
|
1
|
|
|
1
|
|
1081
|
use Switch; |
|
1
|
|
|
|
|
43911
|
|
|
1
|
|
|
|
|
6
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
our $VERSION = "0.05"; |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
69
|
|
|
|
|
|
|
our @EXPORT = qw(register_variant match set_match mkpat); |
70
|
|
|
|
|
|
|
our $DEBUG = 0; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub constructor; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# Keep track of all existing datatypes. |
75
|
|
|
|
|
|
|
our %dataTypes; |
76
|
|
|
|
|
|
|
# This is a back-mapping from constructors to variant datatypes. |
77
|
|
|
|
|
|
|
# Do we need both this and dataTypes? Yes, it is handy. |
78
|
|
|
|
|
|
|
our %constructors; |
79
|
|
|
|
|
|
|
# This is the object pre-set for following calls to match |
80
|
|
|
|
|
|
|
our $matchObject; |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=item register_variant(NAME [, CONSTRUCTORS]) |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
This function registers a variant with the module. The C should |
85
|
|
|
|
|
|
|
be a string uniquely naming the variant. |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
Next should come a list of constructors. A constructor can come in one |
88
|
|
|
|
|
|
|
of two forms: |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=over 8 |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=item * A list reference |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
The first element of the list should be a string, containing the name |
95
|
|
|
|
|
|
|
of the constructor. This name will be the name of the constructor |
96
|
|
|
|
|
|
|
function that will be used to construct new instances of this |
97
|
|
|
|
|
|
|
variant. By convention constructors start with a capital letter. |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
The other elements should be strings indicating the type of the |
100
|
|
|
|
|
|
|
variable stored in this position. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
We are allowed the following types in this version: |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=over 12 |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=item * C<< >> - Numbers |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=item * C<< >> - Strings |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=item * C<< [ >> - References ] |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
=item * C<< * >> - wildcard, allow any type for this field |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=item * I< Type > - allow only other variants of I. |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=back |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
This information is later used for some basic typechecking, see |
119
|
|
|
|
|
|
|
L"Typechecking">. |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=item * A single string |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
The string should just be a space separated list, basically containing |
124
|
|
|
|
|
|
|
the same as if it was list reference instead. |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=back |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
B The constructor has to be globally unique within your program. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Examples: |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
# Registers the variant Tree with the constructors: |
134
|
|
|
|
|
|
|
# Empty, Leaf and Node. |
135
|
|
|
|
|
|
|
# The Empty node carries no data, the leaf node carries an int |
136
|
|
|
|
|
|
|
# and an internal node carries two subtrees. |
137
|
|
|
|
|
|
|
register_variant("Tree","Empty","Leaf ","Node Tree Tree"); |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# Essentially the same, but using list reference form. |
140
|
|
|
|
|
|
|
register_variant("Tree2", ["Empty2"],["Leaf2",""],["Node2", "Tree2","Tree2"]); |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
# The Maybe type from Haskell, often called an "optional value". |
143
|
|
|
|
|
|
|
register_variant("Maybe", "Nothing", "Just *"); |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=cut |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
sub register_variant { |
148
|
1
|
|
|
1
|
1
|
849
|
my $dt = shift; |
149
|
|
|
|
|
|
|
|
150
|
1
|
50
|
|
|
|
7
|
if (exists $dataTypes{$dt}) { |
151
|
0
|
|
|
|
|
0
|
carp "Registering datatype $dt twice"; |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
1
|
|
|
|
|
4
|
my %altHash; |
155
|
1
|
|
|
|
|
6
|
while($_ = shift) { |
156
|
3
|
|
|
|
|
3
|
my ($con,@fields); |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# The function can be called either with space separated strings |
159
|
|
|
|
|
|
|
# or with array references. |
160
|
3
|
50
|
|
|
|
9
|
if (ref $_) { |
161
|
0
|
|
|
|
|
0
|
($con, @fields) = @{$_}; |
|
0
|
|
|
|
|
0
|
|
162
|
|
|
|
|
|
|
} else { |
163
|
3
|
|
|
|
|
11
|
($con, @fields) = split; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
3
|
50
|
|
|
|
9
|
carp "The constructor $con is repeated. in $dt\n" |
167
|
|
|
|
|
|
|
if exists $altHash{$con}; |
168
|
|
|
|
|
|
|
|
169
|
3
|
|
|
|
|
6
|
$altHash{$con} = \@fields; |
170
|
3
|
|
|
|
|
13
|
$constructors{$con} = $dt; |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
|
174
|
1
|
|
|
|
|
3
|
$dataTypes{$dt} = \%altHash; |
175
|
1
|
50
|
|
|
|
7
|
print Dumper(\%dataTypes) if $DEBUG; |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# Last, export this variant to the caller so he gets the constructors. |
178
|
1
|
|
|
|
|
8
|
export_variant($dt,caller()); |
179
|
|
|
|
|
|
|
|
180
|
1
|
|
|
|
|
5
|
return 1; |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=item export_variant(VARIANT) |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=item $val->export_variant |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
As a function, this function exports the variant named by the argument |
188
|
|
|
|
|
|
|
C to the calling module, making the constructors available in |
189
|
|
|
|
|
|
|
the module. |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
As a method call, on an object that is a variant value, it exports the |
192
|
|
|
|
|
|
|
constructors for the variant that the object is an instance of. |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=cut |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub export_variant { |
197
|
1
|
|
|
1
|
1
|
5
|
my ($dt,$module) = @_; |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
# This function is also called by register_variant. |
200
|
1
|
50
|
|
|
|
4
|
$module = defined $module ? $module : caller; |
201
|
|
|
|
|
|
|
|
202
|
1
|
50
|
|
|
|
15
|
$dt = $dt->{Type} if $dt->isa("Data::Variant"); |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
# We need to export all symbols to the caller so we can use them to |
205
|
|
|
|
|
|
|
# construct new instances of the variant. |
206
|
1
|
|
|
|
|
3
|
foreach my $cons (keys %{$dataTypes{$dt}}) { |
|
1
|
|
|
|
|
6
|
|
207
|
1
|
|
|
1
|
|
99220
|
no strict; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
1263
|
|
208
|
3
|
|
|
4
|
|
13
|
*{"$module\::$cons"} = sub { constructor($cons, @_) }; |
|
3
|
|
|
|
|
26
|
|
|
4
|
|
|
|
|
15
|
|
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
|
211
|
1
|
|
|
|
|
3
|
1; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=item Constructor([VARLIST]) |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
The constructors that you gave C will be exported as |
217
|
|
|
|
|
|
|
functions to the calling package, and are used to create new instances |
218
|
|
|
|
|
|
|
of the variant. It is during this instantiation phase that type |
219
|
|
|
|
|
|
|
checking is performed. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
Note that if you want to use the functions without paranteses, or if |
222
|
|
|
|
|
|
|
you have warnings turned on (and you probably should) you will have to |
223
|
|
|
|
|
|
|
predeclare your constructors somehow, either by C |
224
|
|
|
|
|
|
|
or by C. |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
B The constructor will return an object with the appropriate data. |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
Examples: |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
# Creation of some simple trees |
231
|
|
|
|
|
|
|
my $left = Node ((Leaf 1), (Leaf 4)); |
232
|
|
|
|
|
|
|
my $right = Node ((Leaf 3), Empty); |
233
|
|
|
|
|
|
|
my $tree = Node $left, $right; |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
# A few maybe variants |
236
|
|
|
|
|
|
|
my $nth = Nothing |
237
|
|
|
|
|
|
|
my $sth = Just "A string"; |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=cut |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub constructor { |
244
|
4
|
|
|
4
|
0
|
7
|
my $cons = shift; |
245
|
|
|
|
|
|
|
|
246
|
4
|
50
|
|
|
|
13
|
croak "Tried to use non-existing constructor $cons" |
247
|
|
|
|
|
|
|
unless (exists $constructors{$cons}); |
248
|
|
|
|
|
|
|
|
249
|
4
|
|
|
|
|
7
|
my $type = $constructors{$cons}; |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
# This is the actual data object |
252
|
4
|
|
|
|
|
13
|
my $object = { Type => $type, Cons => $cons }; |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
# Assign all the fields. |
255
|
4
|
|
|
|
|
6
|
my @fields = @{$dataTypes{$type}->{$cons}}; |
|
4
|
|
|
|
|
13
|
|
256
|
4
|
|
|
|
|
8
|
my @vals; |
257
|
4
|
|
|
|
|
26
|
foreach my $index (0..$#fields) { |
258
|
6
|
|
|
|
|
10
|
my $var = $fields[$index]; |
259
|
6
|
|
|
|
|
9
|
my $val = shift; |
260
|
6
|
50
|
|
|
|
13
|
carp "Missing argument $var for constructor $cons" |
261
|
|
|
|
|
|
|
unless (defined $val); |
262
|
|
|
|
|
|
|
|
263
|
6
|
50
|
|
|
|
16
|
print "Setting $val = $var (cons: $cons)\n" |
264
|
|
|
|
|
|
|
if ($DEBUG); |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
# Simple run time typechecking. |
267
|
6
|
|
|
|
|
7
|
my $badtype = 0; |
268
|
6
|
|
|
|
|
29
|
switch ($var) { |
|
6
|
|
|
|
|
9
|
|
|
6
|
|
|
|
|
19
|
|
|
4
|
|
|
|
|
9
|
|
269
|
|
|
|
|
|
|
# Tests "borrowed" from Switch.pm |
270
|
6
|
50
|
|
|
|
104
|
case "" { $badtype = 1 unless ((~$val&$val) eq 0) } |
|
2
|
100
|
|
|
|
36
|
|
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
15
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
271
|
4
|
0
|
|
|
|
55
|
case "" { $badtype = 1 unless (ref $val eq "") } |
|
0
|
50
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
272
|
4
|
0
|
|
|
|
50
|
case "[" { $badtype = 1 unless ref $val } ] |
|
0
|
50
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
273
|
4
|
50
|
|
|
|
47
|
case "*" { $badtype = 0 } |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
274
|
|
|
|
|
|
|
else { # Variant type! |
275
|
4
|
50
|
33
|
|
|
86
|
$badtype = 1 unless (($val->isa("Data::Variant")) && |
276
|
|
|
|
|
|
|
$val->{Type} eq $var); |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
|
281
|
6
|
50
|
|
|
|
14
|
carp "Bad type, expected $var in position ".($index+1)." for $cons" |
282
|
|
|
|
|
|
|
if $badtype; |
283
|
|
|
|
|
|
|
|
284
|
6
|
|
|
|
|
20
|
push @vals, $val; |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
|
287
|
4
|
|
|
|
|
11
|
$object->{VALS} = \@vals; |
288
|
|
|
|
|
|
|
|
289
|
4
|
50
|
|
|
|
10
|
croak "Too many arguments for constructor $cons" |
290
|
|
|
|
|
|
|
if (@_ > 0); |
291
|
|
|
|
|
|
|
|
292
|
4
|
|
|
|
|
6
|
bless $object; |
293
|
|
|
|
|
|
|
|
294
|
4
|
50
|
|
|
|
9
|
print Dumper(\$object) |
295
|
|
|
|
|
|
|
if $DEBUG; |
296
|
|
|
|
|
|
|
|
297
|
4
|
|
|
|
|
16
|
return $object; |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
=item match([OBJ], CONS, [VARLIST]) |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=item $obj->match(CONS,[VARLIST] |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
=item match(OBJ) |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
In its first two forms C checks is C is constructed using |
307
|
|
|
|
|
|
|
the constructor C given. If it matches the variables in |
308
|
|
|
|
|
|
|
C are filled with the values of the fields of the object. |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
The number of elements in C must match the number of values |
311
|
|
|
|
|
|
|
in the object. |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
The first argument C can be left out if it has been pre-set using |
314
|
|
|
|
|
|
|
C. |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
It its second form, with only an object as parameter, it returns a |
317
|
|
|
|
|
|
|
function reference that is useful in a C statement. The |
318
|
|
|
|
|
|
|
contents of each C must then be created using C. |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=cut |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
sub match { |
323
|
19
|
|
|
19
|
1
|
930
|
my $obj; |
324
|
|
|
|
|
|
|
|
325
|
19
|
100
|
|
|
|
51
|
if (@_ == 1) { |
326
|
7
|
50
|
|
|
|
29
|
croak "A lone argument has to be a variant reference" |
327
|
|
|
|
|
|
|
unless $_[0]->isa("Data::Variant"); |
328
|
7
|
|
|
|
|
10
|
my $obj = $_[0]; |
329
|
|
|
|
|
|
|
# Create a closure and return it. |
330
|
|
|
|
|
|
|
return sub { |
331
|
7
|
|
|
7
|
|
87
|
match($obj,@_) |
332
|
7
|
|
|
|
|
41
|
}; |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
# Find out which object to use. |
336
|
12
|
50
|
|
|
|
31
|
if (ref $_[0] ne "") { |
337
|
12
|
|
|
|
|
18
|
$obj = shift; |
338
|
|
|
|
|
|
|
} else { |
339
|
0
|
0
|
|
|
|
0
|
croak "No object pre-set" unless defined $matchObject; |
340
|
0
|
|
|
|
|
0
|
$obj = $matchObject; |
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
|
343
|
12
|
50
|
|
|
|
50
|
croak "I need a valid object for match" |
344
|
|
|
|
|
|
|
unless $obj->isa("Data::Variant"); |
345
|
|
|
|
|
|
|
|
346
|
12
|
|
|
|
|
16
|
my $constr = shift; |
347
|
|
|
|
|
|
|
|
348
|
12
|
|
|
|
|
22
|
my $reqtype = $constructors{$constr}; |
349
|
|
|
|
|
|
|
|
350
|
12
|
50
|
|
|
|
34
|
if ($reqtype ne $obj->{Type}) { |
351
|
0
|
|
|
|
|
0
|
carp "Non matching datatype. Has $obj->{Type} expected $reqtype"; |
352
|
|
|
|
|
|
|
# You know, if this was Haskell this would have been a |
353
|
|
|
|
|
|
|
# static type error to begin with. |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
|
356
|
12
|
100
|
|
|
|
26
|
if ($obj->{Cons} ne $constr) { |
357
|
|
|
|
|
|
|
# Not a match |
358
|
4
|
|
|
|
|
19
|
return 0; |
359
|
|
|
|
|
|
|
} else { |
360
|
|
|
|
|
|
|
# A match. |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
# 1) Bind all variables |
363
|
|
|
|
|
|
|
# YYY: Can we detect unbindables?? |
364
|
8
|
|
|
|
|
12
|
my $valsize = $#{$obj->{VALS}} + 1; |
|
8
|
|
|
|
|
18
|
|
365
|
8
|
50
|
|
|
|
19
|
carp "Wrong number of parameters to $constr matching" |
366
|
|
|
|
|
|
|
if ($valsize != @_); |
367
|
|
|
|
|
|
|
|
368
|
8
|
|
|
|
|
18
|
foreach my $v (0..$valsize) { |
369
|
18
|
100
|
|
|
|
39
|
if (ref $_[$v]) { |
370
|
5
|
|
|
|
|
10
|
${$_[$v]} = $obj->{VALS}->[$v]; |
|
5
|
|
|
|
|
20
|
|
371
|
|
|
|
|
|
|
} else { |
372
|
13
|
|
|
|
|
39
|
$_[$v] = $obj->{VALS}->[$v]; |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
# 2) return true |
377
|
8
|
|
|
|
|
50
|
return 1; |
378
|
|
|
|
|
|
|
} |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
=item mkpat(CONS, [VARLIST]) |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
This creates a reference to an array containing what would normally be |
385
|
|
|
|
|
|
|
the input to match. This is mainly useful when working with C |
386
|
|
|
|
|
|
|
statements. |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
=cut |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
sub mkpat { |
391
|
7
|
|
|
7
|
1
|
9
|
my @rv; |
392
|
|
|
|
|
|
|
|
393
|
7
|
50
|
|
|
|
43
|
croak "mkpat needs at least one argument" |
394
|
|
|
|
|
|
|
unless defined $_[0]; |
395
|
|
|
|
|
|
|
|
396
|
7
|
|
|
|
|
16
|
push @rv, $_[0]; |
397
|
|
|
|
|
|
|
|
398
|
7
|
|
|
|
|
19
|
foreach my $i (1..$#_) { |
399
|
7
|
|
|
|
|
20
|
push @rv,\$_[$i]; |
400
|
|
|
|
|
|
|
} |
401
|
7
|
|
|
|
|
26
|
return \@rv; |
402
|
|
|
|
|
|
|
} |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
=item set_match(OBJ) |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
=item $object->set_match |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
Presets an object to match against so that the first parameter of |
410
|
|
|
|
|
|
|
C can be left out in subsequent calls. |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
=cut |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
sub set_match { |
415
|
1
|
|
|
1
|
1
|
3
|
$matchObject = shift; |
416
|
1
|
50
|
|
|
|
6
|
warn "Parameter to set_match not a Data::Variant" |
417
|
|
|
|
|
|
|
unless ($matchObject->isa("Data::Variant")); |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
1; |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
__END__ |