automake: Don't rely on List::Util to provide 'none'
[automake.git] / lib / Automake / Item.pm
blobfe61256125a424de3b81d21c0d8f7b69c1369033
1 # Copyright (C) 2003-2018 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2, or (at your option)
6 # any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <https://www.gnu.org/licenses/>.
16 package Automake::Item;
18 use 5.006;
19 use strict;
20 use Carp;
21 use Automake::ChannelDefs;
22 use Automake::DisjConditions;
24 =head1 NAME
26 Automake::Item - base class for Automake::Variable and Automake::Rule
28 =head1 DESCRIPTION
30 =head2 Methods
32 =over 4
34 =item C<new Automake::Item $name>
36 Create and return an empty Item called C<$name>.
38 =cut
40 sub new ($$)
42 my ($class, $name) = @_;
43 my $self = {
44 name => $name,
45 defs => {},
46 conds => {},
48 bless $self, $class;
49 return $self;
52 =item C<$item-E<gt>name>
54 Return the name of C<$item>.
56 =cut
58 sub name ($)
60 my ($self) = @_;
61 return $self->{'name'};
64 =item C<$item-E<gt>def ($cond)>
66 Return the definition for this item in condition C<$cond>, if it
67 exists. Return 0 otherwise.
69 =cut
71 sub def ($$)
73 # This method is called very often, so keep it small and fast. We
74 # don't mind the extra undefined items introduced by lookup failure;
75 # avoiding this with 'exists' means doing two hash lookup on
76 # success, and proved worse on benchmark.
77 my $def = $_[0]->{'defs'}{$_[1]};
78 return defined $def && $def;
81 =item C<$item-E<gt>rdef ($cond)>
83 Return the definition for this item in condition C<$cond>. Abort with
84 an internal error if the item was not defined under this condition.
86 The I<r> in front of C<def> stands for I<required>. One
87 should call C<rdef> to assert the conditional definition's existence.
89 =cut
91 sub rdef ($$)
93 my ($self, $cond) = @_;
94 my $d = $self->def ($cond);
95 prog_error ("undefined condition '" . $cond->human . "' for '"
96 . $self->name . "'\n" . $self->dump)
97 unless $d;
98 return $d;
101 =item C<$item-E<gt>set ($cond, $def)>
103 Add a new definition to an existing item.
105 =cut
107 sub set ($$$)
109 my ($self, $cond, $def) = @_;
110 $self->{'defs'}{$cond} = $def;
111 $self->{'conds'}{$cond} = $cond;
114 =item C<$var-E<gt>conditions>
116 Return an L<Automake::DisjConditions> describing the conditions that
117 that an item is defined in.
119 These are all the conditions for which is would be safe to call
120 C<rdef>.
122 =cut
124 sub conditions ($)
126 my ($self) = @_;
127 prog_error ("self is not a reference")
128 unless ref $self;
129 return new Automake::DisjConditions (values %{$self->{'conds'}});
132 =item C<@missing_conds = $var-E<gt>not_always_defined_in_cond ($cond)>
134 Check whether C<$var> is always defined for condition C<$cond>.
135 Return a list of conditions where the definition is missing.
137 For instance, given
139 if COND1
140 if COND2
141 A = foo
142 D = d1
143 else
144 A = bar
145 D = d2
146 endif
147 else
148 D = d3
149 endif
150 if COND3
151 A = baz
152 B = mumble
153 endif
154 C = mumble
156 we should have (we display result as conditional strings in this
157 illustration, but we really return DisjConditions objects):
159 var ('A')->not_always_defined_in_cond ('COND1_TRUE COND2_TRUE')
160 => ()
161 var ('A')->not_always_defined_in_cond ('COND1_TRUE')
162 => ()
163 var ('A')->not_always_defined_in_cond ('TRUE')
164 => ("COND1_FALSE COND3_FALSE")
165 var ('B')->not_always_defined_in_cond ('COND1_TRUE')
166 => ("COND1_TRUE COND3_FALSE")
167 var ('C')->not_always_defined_in_cond ('COND1_TRUE')
168 => ()
169 var ('D')->not_always_defined_in_cond ('TRUE')
170 => ()
171 var ('Z')->not_always_defined_in_cond ('TRUE')
172 => ("TRUE")
174 =cut
176 sub not_always_defined_in_cond ($$)
178 my ($self, $cond) = @_;
180 # Compute the subconditions where $var isn't defined.
181 return
182 $self->conditions
183 ->sub_conditions ($cond)
184 ->invert
185 ->multiply ($cond);