Commit | Line | Data |
3fea05b9 |
1 | #================================================================= -*-Perl-*- |
2 | # |
3 | # Template::Namespace::Constants |
4 | # |
5 | # DESCRIPTION |
6 | # Plugin compiler module for performing constant folding at compile time |
7 | # on variables in a particular namespace. |
8 | # |
9 | # AUTHOR |
10 | # Andy Wardley <abw@wardley.org> |
11 | # |
12 | # COPYRIGHT |
13 | # Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved. |
14 | # |
15 | # This module is free software; you can redistribute it and/or |
16 | # modify it under the same terms as Perl itself. |
17 | # |
18 | #============================================================================ |
19 | |
20 | package Template::Namespace::Constants; |
21 | |
22 | use strict; |
23 | use warnings; |
24 | use base 'Template::Base'; |
25 | use Template::Config; |
26 | use Template::Directive; |
27 | use Template::Exception; |
28 | |
29 | our $VERSION = 1.27; |
30 | our $DEBUG = 0 unless defined $DEBUG; |
31 | |
32 | |
33 | sub _init { |
34 | my ($self, $config) = @_; |
35 | $self->{ STASH } = Template::Config->stash($config) |
36 | || return $self->error(Template::Config->error()); |
37 | return $self; |
38 | } |
39 | |
40 | |
41 | |
42 | #------------------------------------------------------------------------ |
43 | # ident(\@ident) foo.bar(baz) |
44 | #------------------------------------------------------------------------ |
45 | |
46 | sub ident { |
47 | my ($self, $ident) = @_; |
48 | my @save = @$ident; |
49 | |
50 | # discard first node indicating constants namespace |
51 | splice(@$ident, 0, 2); |
52 | |
53 | my $nelems = @$ident / 2; |
54 | my ($e, $result); |
55 | local $" = ', '; |
56 | |
57 | print STDERR "constant ident [ @$ident ] " if $DEBUG; |
58 | |
59 | foreach $e (0..$nelems-1) { |
60 | # node name must be a constant |
61 | unless ($ident->[$e * 2] =~ s/^'(.+)'$/$1/s) { |
62 | $self->DEBUG(" * deferred (non-constant item: ", $ident->[$e * 2], ")\n") |
63 | if $DEBUG; |
64 | return Template::Directive->ident(\@save); |
65 | } |
66 | |
67 | # if args is non-zero then it must be eval'ed |
68 | if ($ident->[$e * 2 + 1]) { |
69 | my $args = $ident->[$e * 2 + 1]; |
70 | my $comp = eval "$args"; |
71 | if ($@) { |
72 | $self->DEBUG(" * deferred (non-constant args: $args)\n") if $DEBUG; |
73 | return Template::Directive->ident(\@save); |
74 | } |
75 | $self->DEBUG("($args) ") if $comp && $DEBUG; |
76 | $ident->[$e * 2 + 1] = $comp; |
77 | } |
78 | } |
79 | |
80 | |
81 | $result = $self->{ STASH }->get($ident); |
82 | |
83 | if (! length $result || ref $result) { |
84 | my $reason = length $result ? 'reference' : 'no result'; |
85 | $self->DEBUG(" * deferred ($reason)\n") if $DEBUG; |
86 | return Template::Directive->ident(\@save); |
87 | } |
88 | |
89 | $result =~ s/'/\\'/g; |
90 | |
91 | $self->DEBUG(" * resolved => '$result'\n") if $DEBUG; |
92 | |
93 | return "'$result'"; |
94 | } |
95 | |
96 | 1; |
97 | |
98 | __END__ |
99 | |
100 | =head1 NAME |
101 | |
102 | Template::Namespace::Constants - Compile time constant folding |
103 | |
104 | =head1 SYNOPSIS |
105 | |
106 | # easy way to define constants |
107 | use Template; |
108 | |
109 | my $tt = Template->new({ |
110 | CONSTANTS => { |
111 | pi => 3.14, |
112 | e => 2.718, |
113 | }, |
114 | }); |
115 | |
116 | # nitty-gritty, hands-dirty way |
117 | use Template::Namespace::Constants; |
118 | |
119 | my $tt = Template->new({ |
120 | NAMESPACE => { |
121 | constants => Template::Namespace::Constants->new({ |
122 | pi => 3.14, |
123 | e => 2.718, |
124 | }, |
125 | }, |
126 | }); |
127 | |
128 | =head1 DESCRIPTION |
129 | |
130 | The C<Template::Namespace::Constants> module implements a namespace handler |
131 | which is plugged into the C<Template::Directive> compiler module. This then |
132 | performs compile time constant folding of variables in a particular namespace. |
133 | |
134 | =head1 METHODS |
135 | |
136 | =head2 new(\%constants) |
137 | |
138 | The new() constructor method creates and returns a reference to a new |
139 | Template::Namespace::Constants object. This creates an internal stash |
140 | to store the constant variable definitions passed as arguments. |
141 | |
142 | my $handler = Template::Namespace::Constants->new({ |
143 | pi => 3.14, |
144 | e => 2.718, |
145 | }); |
146 | |
147 | =head2 ident(\@ident) |
148 | |
149 | Method called to resolve a variable identifier into a compiled form. In this |
150 | case, the method fetches the corresponding constant value from its internal |
151 | stash and returns it. |
152 | |
153 | =head1 AUTHOR |
154 | |
155 | Andy Wardley E<lt>abw@wardley.orgE<gt> L<http://wardley.org/> |
156 | |
157 | =head1 COPYRIGHT |
158 | |
159 | Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved. |
160 | |
161 | This module is free software; you can redistribute it and/or |
162 | modify it under the same terms as Perl itself. |
163 | |
164 | =head1 SEE ALSO |
165 | |
166 | L<Template::Directive> |
167 | |
168 | =cut |
169 | |
170 | # Local Variables: |
171 | # mode: perl |
172 | # perl-indent-level: 4 |
173 | # indent-tabs-mode: nil |
174 | # End: |
175 | # |
176 | # vim: expandtab shiftwidth=4: |