/[suikacvs]/messaging/manakai/bin/cdis2pm.pl
Suika

Contents of /messaging/manakai/bin/cdis2pm.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.32 - (show annotations) (download)
Sun Feb 26 14:32:38 2006 UTC (18 years, 9 months ago) by wakaba
Branch: MAIN
CVS Tags: HEAD
Changes since 1.31: +1 -1 lines
File MIME type: text/plain
Error occurred while calculating annotation data.
FILE REMOVED
++ manakai/t/ChangeLog	26 Feb 2006 14:32:29 -0000
	* Makefile (distclean): New rule.

2006-02-26  Wakaba  <wakaba@suika.fam.cx>

++ manakai/bin/ChangeLog	26 Feb 2006 14:18:44 -0000
	* daf.pl: Request for |fe:GenericLS| feature was missing.
	Sets the |pc:preserve-line-break| parameter for test
	code as |dac2test.pl| had been.

	* dac.pl, dac2pm.pl, dac2test.pl: Removed.

	* disc.pl, cdis2pm.pl, cdis2rdf.pl: Removed.

2006-02-26  Wakaba  <wakaba@suika.fam.cx>

++ manakai/lib/Message/ChangeLog	26 Feb 2006 14:19:17 -0000
2006-02-26  Wakaba  <wakaba@suika.fam.cx>

	* Makefile (distclean): New rule.

++ manakai/lib/Message/Body/ChangeLog	26 Feb 2006 14:19:35 -0000
2006-02-26  Wakaba  <wakaba@suika.fam.cx>

	* Makefile (distclean): New rule.

++ manakai/lib/Message/Field/ChangeLog	26 Feb 2006 14:24:08 -0000
2006-02-26  Wakaba  <wakaba@suika.fam.cx>

	* Makefile (distclean): New rule.

++ manakai/lib/Message/MIME/ChangeLog	26 Feb 2006 14:24:31 -0000
2006-02-26  Wakaba  <wakaba@suika.fam.cx>

	* Makefile (distclean): New rule.

++ manakai/lib/Message/Markup/ChangeLog	26 Feb 2006 14:24:49 -0000
	* Makefile (distclean): New rule.

2006-02-26  Wakaba  <wakaba@suika.fam.cx>

++ manakai/lib/Message/Util/ChangeLog	26 Feb 2006 14:27:24 -0000
	* PerlCode.dis (PerlStringLiteral.stringify): If some character
	are escaped, the string should have been quoted by |QUOTATION MARK|.

	* Makefile (.discore-all.pm): The parameter for |DIS/DPG.dis|
	module was misplaced.
	(distclean): New rule.
	(clean): Cleans subdirectories, too.

2006-02-26  Wakaba  <wakaba@suika.fam.cx>

++ manakai/lib/Message/Util/DIS/ChangeLog	26 Feb 2006 14:31:14 -0000
	* Perl.dis (plUpdate): Reads |dis:DefaultFor| property
	from the source if it is not available from the module
	in the database, i.e. the |readProperties| method
	is not performed for the module.
	(getPerlInterfaceMemberCode): Renamed
	from |getPerlErrorInterfaceMemberCode|.
	(DISLang:Const.getPerlInterfaceMemberCode): New
	method implementation.  Constants defined in interfaces
	were not reflected to the generated Perl module code
	since the split of |plGeneratePerlModule| method.

	* DPG.dis (Require): Reference to |DIS:Perl| module was missing.

2006-02-26  Wakaba  <wakaba@suika.fam.cx>

++ manakai/lib/Message/DOM/ChangeLog	26 Feb 2006 14:21:51 -0000
	* SimpleLS.dis (Require): Reference to the |MDOM:Tree|
	module was missing.

	* ManakaiDOMLS2003.dis: Some property names was incorrect.

	* Makefile (distclean): New rule.

2006-02-26  Wakaba  <wakaba@suika.fam.cx>

	* DOMLS.dis: Removed from the CVS repository, since
	it has been no longer required to make the |daf| system
	itself.

2006-02-26  Wakaba  <wakaba@suika.fam.cx>

++ manakai/lib/manakai/ChangeLog	26 Feb 2006 14:32:09 -0000
	* Makefile (distclean): New rule.

2006-02-26  Wakaba  <wakaba@suika.fam.cx>

++ manakai/lib/ChangeLog	26 Feb 2006 14:19:00 -0000
2006-02-26  Wakaba  <wakaba@suika.fam.cx>

	* Makefile (distclean): New rule.

1 #!/usr/bin/perl -w
2 use strict;
3
4 =head1 NAME
5
6 cdis2pm - Generating Perl Module from a Compiled "dis"
7
8 =head1 SYNOPSIS
9
10 perl path/to/cdis2pm.pl input.cdis \
11 {--module-name=ModuleName | --module-uri=module-uri} \
12 [--for=for-uri] [options] > ModuleName.pm
13 perl path/to/cdis2pm.pl --help
14
15 =head1 DESCRIPTION
16
17 The C<cdis2pm> script generates a Perl module from a compiled "dis"
18 ("cdis") file. It is intended to be used to generate a manakai
19 DOM Perl module files, although it might be useful for other purpose.
20
21 This script is part of manakai.
22
23 =cut
24
25 use Message::Util::QName::Filter {
26 d => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/lang#dis-->,
27 dis2pm => q<http://suika.fam.cx/~wakaba/archive/2004/11/8/dis2pm#>,
28 DISCore => q<http://suika.fam.cx/~wakaba/archive/2004/dis/Core#>,
29 DISLang => q<http://suika.fam.cx/~wakaba/archive/2004/dis/Lang#>,
30 DISPerl => q<http://suika.fam.cx/~wakaba/archive/2004/dis/Perl#>,
31 disPerl => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/lang#dis--Perl-->,
32 DOMCore => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/dom-core#>,
33 DOMEvents => q<http://suika.fam.cx/~wakaba/archive/2004/dom/events#>,
34 DOMMain => q<http://suika.fam.cx/~wakaba/archive/2004/dom/main#>,
35 DOMXML => q<http://suika.fam.cx/~wakaba/archive/2004/dom/xml#>,
36 DX => q<http://suika.fam.cx/~wakaba/archive/2005/manakai/Util/Error/DOMException#>,
37 lang => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/lang#>,
38 Perl => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/lang#Perl-->,
39 license => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/license#>,
40 ManakaiDOM => q<http://suika.fam.cx/~wakaba/archive/2004/8/18/manakai-dom#>,
41 MDOMX => q<http://suika.fam.cx/~wakaba/archive/2004/8/4/manakai-dom-exception#>,
42 owl => q<http://www.w3.org/2002/07/owl#>,
43 rdf => q<http://www.w3.org/1999/02/22-rdf-syntax-ns#>,
44 rdfs => q<http://www.w3.org/2000/01/rdf-schema#>,
45 swcfg21 => q<http://suika.fam.cx/~wakaba/archive/2005/swcfg21#>,
46 TreeCore => q<>,
47 };
48
49 =head1 OPTIONS
50
51 =over 4
52
53 =item --enable-assertion / --noenable-assertion (default)
54
55 Whether assertion codes should be outputed or not.
56
57 =item --for=I<for-uri> (Optional)
58
59 Specifies the "For" URI reference for which the outputed module is.
60 If this parameter is ommitted, the default "For" URI reference
61 for the module, if any, or the C<ManakaiDOM:all> is assumed.
62
63 =item --help
64
65 Shows the help message.
66
67 =item --module-name=I<ModuleName>
68
69 The name of module to output. It is the local name part of
70 the C<Module> C<QName> in the source "dis" file. Either
71 C<--module-name> or C<--module-uri> is required.
72
73 =item --module-uri=I<module-uri>
74
75 A URI reference that identifies a module to output. Either
76 C<--module-name> or C<--module-uri> is required.
77
78 =item --output-module-version (default) / --nooutput-module-version
79
80 Whether the C<$VERSION> special variable should be generated or not.
81
82 =item --verbose / --noverbose (default)
83
84 Whether a verbose message mode should be selected or not.
85
86 =back
87
88 =cut
89
90 use Getopt::Long;
91 use Pod::Usage;
92 use Storable;
93 my %Opt;
94 GetOptions (
95 'enable-assertion!' => \$Opt{outputAssertion},
96 'for=s' => \$Opt{For},
97 'help' => \$Opt{help},
98 'module-name=s' => \$Opt{module_name},
99 'module-uri=s' => \$Opt{module_uri},
100 'output-module-version!' => \$Opt{outputModuleVersion},
101 'verbose!' => $Opt{verbose},
102 ) or pod2usage (2);
103 pod2usage ({-exitval => 0, -verbose => 1}) if $Opt{help};
104 $Opt{file_name} = shift;
105 pod2usage ({-exitval => 2, -verbose => 0}) unless $Opt{file_name};
106 pod2usage (2) if not $Opt{module_uri} and not $Opt{module_name};
107 $Opt{outputModuleVersion} = 1 unless defined $Opt{outputModuleVersion};
108
109 BEGIN {
110 require 'manakai/genlib.pl';
111 require 'manakai/dis.pl';
112 }
113 our $State = retrieve ($Opt{file_name})
114 or die "$0: $Opt{file_name}: Cannot load";
115
116 eval q{
117 sub impl_msg ($;%) {
118 warn shift () . "\n";
119 }
120 } unless $Opt{verbose};
121
122 =head1 FUNCTIONS
123
124 This section describes utility functions defined in this script
125 for the sake of developer.
126
127 =over 4
128
129 =item $result = perl_change_package (full_name => I<fully qualified Perl package name>)
130
131 Changes the current Perl package in the output Perl code.
132 C<dispm_package_declarations> is also called in this function.
133
134 =cut
135
136 sub perl_change_package (%) {
137 my %opt = @_;
138 my $fn = $opt{full_name};
139 impl_err (qq<$fn: Bad package name>) unless $fn;
140 unless ($fn eq $State->{ExpandedURI q<dis2pm:currentPackage>}) {
141 my $r = dispm_package_declarations (%opt);
142 $State->{ExpandedURI q<dis2pm:currentPackage>} = $fn;
143 $State->{ExpandedURI q<dis2pm:referredPackage>}->{$fn} = -1;
144 return $r . perl_statement qq<package $fn>;
145 } else {
146 return '';
147 }
148 } # perl_change_package
149
150 =item $code = dispm_package_declarations (%opt)
151
152 Generates a code fragment that declares what is required
153 in the current package, including import statements for
154 character classes.
155
156 =cut
157
158 sub dispm_package_declarations (%) {
159 my %opt = @_;
160 my $pack_name = $State->{ExpandedURI q<dis2pm:currentPackage>};
161 my $pack = $State->{ExpandedURI q<dis2pm:Package>}->{$pack_name};
162 my $r = '';
163 my @xml_class;
164 for (keys %{$pack->{ExpandedURI q<dis2pm:requiredCharClass>}||{}}) {
165 my $val = $pack->{ExpandedURI q<dis2pm:requiredCharClass>}->{$_};
166 next if not ref $val and $val <= 0;
167 if (/^InXML/) {
168 push @xml_class, $_;
169 $pack->{ExpandedURI q<dis2pm:requiredCharClass>}->{$_} = -1;
170 } else {
171 valid_err (qq<"$_": Unknown character class>,
172 node => ref $val ? $val : $opt{node});
173 }
174 }
175 if (@xml_class) {
176 $State->{Module}->{$State->{module}}
177 ->{ExpandedURI q<dis2pm:requiredModule>}
178 ->{'Char::Class::XML'} = 1;
179 $r .= perl_statement 'Char::Class::XML->import ('.
180 perl_list (@xml_class).')';
181 }
182 $r;
183 } # dispm_package_declarations
184
185 =item $code = dispm_perl_throws (%opt)
186
187 Generates a code to throw an exception.
188
189 =cut
190
191 sub dispm_perl_throws (%) {
192 my %opt = @_;
193 my $x = $opt{class_resource} || $State->{Type}->{$opt{class}};
194 my $r = 'report ';
195 unless (defined $x->{Name}) {
196 $opt{class} = dis_typeforuris_to_uri ($opt{class}, $opt{class_for}, %opt);
197 $x = $State->{Type}->{$opt{class}};
198 }
199 valid_err (qq<Exception class <$opt{class}> is not defined>,
200 node => $opt{node}) unless defined $x->{Name};
201 if ($x->{ExpandedURI q<dis2pm:type>} and
202 {
203 ExpandedURI q<ManakaiDOM:ExceptionClass> => 1,
204 ExpandedURI q<DOMMain:ErrorClass> => 1,
205 ExpandedURI q<ManakaiDOM:WarningClass> => 1,
206 }->{$x->{ExpandedURI q<dis2pm:type>}}) {
207 $opt{type} = $opt{type_resource}->{Name} unless defined $opt{type};
208 valid_err qq{Exception code must be specified},
209 node => $opt{type_resource}->{src} || $opt{node}
210 unless defined $opt{type};
211 $opt{subtype} = $opt{subtype_resource}->{NameURI} ||
212 $opt{subtype_resource}->{URI} unless defined $opt{subtype};
213 $opt{xparam}->{ExpandedURI q<MDOMX:subtype>} = $opt{subtype}
214 if defined $opt{subtype};
215 $r .= $x->{ExpandedURI q<dis2pm:packageName>} . ' ' .
216 perl_list -type => $opt{type},
217 -object => perl_code_literal ('$self'),
218 %{$opt{xparam} || {}};
219 $State->{Module}->{$State->{module}}
220 ->{ExpandedURI q<dis2pm:requiredModule>}
221 ->{$State->{Module}->{$x->{parentModule}}
222 ->{ExpandedURI q<dis2pm:packageName>}} = 1;
223 } else {
224 no warnings 'uninitialized';
225 valid_err (qq{Resource <$opt{class}> [<$x->{ExpandedURI q<dis2pm:type>}>] }.
226 q<is neither an exception class nor >.
227 q<a warning class>, node => $opt{node});
228 }
229 return $r;
230 } # dispm_perl_throw
231
232 =item Lexical Variable $RegQNameChar
233
234 The regular expression pattern for a QName character.
235
236 =item Lexical Variable $RegBlockContent
237
238 The regular expression pattern for a "block", i.e. a nestable section
239 of "{" ... "}".
240
241 =cut
242
243 my $RegQNameChar = qr/[^\s<>"'\\\[\]\{\},=]/;
244 use re 'eval';
245 my $RegBlockContent;
246 $RegBlockContent = qr/(?>[^{}\\]*)(?>(?>[^{}\\]+|\\.|\{(??{$RegBlockContent})\})*)/s;
247
248 =item $result = perl_code ($code, %opt)
249
250 Converts preprocessing instructions in the <$code> and returns it.
251
252 Note that this function is also defined in F<genlib.pl> but
253 redefined here for the purpose of this script.
254
255 =cut
256
257 sub perl_code ($;%) {
258 my ($s, %opt) = @_;
259 valid_err q<Uninitialized value in perl_code>,
260 node => $opt{node} unless defined $s;
261 $s = $$s if ref $s eq '__code';
262 local $State->{Namespace}
263 = $State->{Module}->{$opt{resource}->{parentModule}}->{nsBinding};
264 $s =~ s[(?<![qwr])<($RegQNameChar[^<>]+)>|\b(null|true|false)\b][
265 my ($q, $l) = ($1, $2);
266 my $r;
267 if (defined $q) {
268 if ($q =~ /\}/) {
269 valid_warn qq<Inline element "<$q>" has a "}" - it might be a typo>;
270 }
271 if ($q =~ /=$/) {
272 valid_warn qq<Inline element "<$q>" ends with a "=" - >.
273 q{should "=" be used place of "=>"?};
274 }
275 if ($q =~ s/^(.+?):://) {
276 my $et = dis_qname_to_uri
277 ($1, %opt,
278 use_default_namespace => ExpandedURI q<disPerl:>);
279 if ($et eq ExpandedURI q<disPerl:Q>) { ## QName constant
280 $r = perl_literal (dis_qname_to_uri ($q, use_default_namespace => 1,
281 %opt));
282 } elsif ({
283 ExpandedURI q<disPerl:M> => 1,
284 ExpandedURI q<disPerl:ClassM> => 1,
285 ExpandedURI q<disPerl:AG> => 1,
286 ExpandedURI q<disPerl:AS> => 1,
287 }->{$et}) { ## Method call
288 my ($clsq, $mtdq) = split /\s*\.\s*/, $q, 2;
289 my $clsu = dis_typeforqnames_to_uri ($clsq,
290 use_default_namespace => 1, %opt);
291 my $cls = $State->{Type}->{$clsu};
292 my $clsp = $cls->{ExpandedURI q<dis2pm:packageName>};
293 if ($cls->{ExpandedURI q<dis2pm:type>} and
294 {
295 ExpandedURI q<ManakaiDOM:IF> => 1,
296 ExpandedURI q<ManakaiDOM:ExceptionIF> => 1,
297 }->{$cls->{ExpandedURI q<dis2pm:type>}}) {
298 valid_err q<"disPerl:ClassM" cannot be used for interface methods>,
299 node => $opt{node} if $et eq ExpandedURI q<disPerl:ClassM>;
300 $clsp = '';
301 } else {
302 valid_err qq<Package name of class <$clsu> must be defined>,
303 node => $opt{node} unless defined $clsp;
304 $State->{Module}->{$State->{module}}
305 ->{ExpandedURI q<dis2pm:requiredModule>}
306 ->{$State->{Module}->{$cls->{parentModule}}
307 ->{ExpandedURI q<dis2pm:packageName>}} = 1;
308 }
309 if ($mtdq =~ /:/) {
310 valid_err qq<$mtdq: Prefixed method name not supported>,
311 node => $opt{node};
312 } else {
313 my $mtd;
314 for (values %{$cls->{ExpandedURI q<dis2pm:method>}}) {
315 if (defined $_->{Name} and $_->{Name} eq $mtdq) {
316 $mtd = $_;
317 last;
318 }
319 }
320 valid_err qq<Perl method name for method "$clsp.$mtdq" must >.
321 q<be defined>, node => $mtd->{src} || $opt{node}
322 if not defined $mtd or
323 not defined $mtd->{ExpandedURI q<dis2pm:methodName>};
324 $r = ' ' . ($clsp ? $clsp .
325 {
326 ExpandedURI q<disPerl:M> => '::',
327 ExpandedURI q<disPerl:AG> => '::',
328 ExpandedURI q<disPerl:AS> => '::',
329 ExpandedURI q<disPerl:ClassM> => '->',
330 }->{$et}
331 : '') .
332 $mtd->{ExpandedURI q<dis2pm:methodName>} . ' ';
333 }
334 } elsif ({
335 ExpandedURI q<disPerl:Class> => 1,
336 ExpandedURI q<disPerl:IF> => 1,
337 ExpandedURI q<disPerl:ClassName> => 1,
338 ExpandedURI q<disPerl:IFName> => 1,
339 }->{$et}) { ## Perl package name
340 my $uri = dis_typeforqnames_to_uri ($q,
341 use_default_namespace => 1, %opt);
342 if (defined $State->{Type}->{$uri}->{Name} and
343 defined $State->{Type}->{$uri}
344 ->{ExpandedURI q<dis2pm:packageName>}) {
345 $r = $State->{Type}->{$uri}->{ExpandedURI q<dis2pm:packageName>};
346 if ({
347 ExpandedURI q<disPerl:ClassName> => 1,
348 ExpandedURI q<disPerl:IFName> => 1,
349 }->{$et}) {
350 $r = perl_literal $r;
351 }
352 } else {
353 valid_err qq<Package name of class <$uri> must be defined>,
354 node => $opt{node};
355 }
356 } elsif ($et eq ExpandedURI q<disPerl:Code>) { ## CODE constant
357 my ($nm);
358 $q =~ s/^\s+//;
359 if ($q =~ s/^((?>(?!::).)+)//s) {
360 $nm = $1;
361 $nm =~ tr/|/:/;
362 } else {
363 valid_err qq<"$q": Code name required>, node => $opt{node};
364 }
365 $q =~ s/^::\s*//;
366 my $param = dispm_parse_param (\$q, %opt,
367 ExpandedURI q<dis2pm:endOrErr> => 1,
368 use_default_namespace => '');
369 my $uri = dis_typeforqnames_to_uri
370 ($nm, use_default_namespace => 1,
371 %opt);
372 if (defined $State->{Type}->{$uri}->{Name} and
373 dis_resource_ctype_match (ExpandedURI q<dis2pm:InlineCode>,
374 $State->{Type}->{$uri}, %opt)) {
375 local $State->{ExpandedURI q<dis2pm:blockCodeParam>} = $param;
376 ## ISSUE: It might be required to check loop referring
377 $r = dispm_get_code (%opt, resource => $State->{Type}->{$uri},
378 For => [keys %{$State->{Type}->{$uri}
379 ->{For}}]->[0],
380 'For+' => [keys %{$State->{Type}->{$uri}
381 ->{'For+'}||{}}],
382 is_inline => 1,
383 ExpandedURI q<dis2pm:selParent> => $param,
384 ExpandedURI q<dis2pm:DefKeyName>
385 => ExpandedURI q<d:Def>);
386 for (grep {/^\$/} keys %$param) {
387 $r =~ s/\Q$_\E\b/$param->{$_}/g;
388 }
389 } else {
390 valid_err qq<Inline code constant <$uri> must be defined>,
391 node => $opt{node};
392 }
393 } elsif ($et eq ExpandedURI q<disPerl:C>) {
394 if ($q =~ /^((?>(?!\.)$RegQNameChar)*)\.($RegQNameChar+)$/o) {
395 my ($cls, $constn) = ($1, $2);
396 if (length $cls) {
397 my $clsu = dis_typeforqnames_to_uri ($cls, %opt,
398 use_default_namespace => 1,
399 node => $_);
400 $cls = $State->{Type}->{$clsu};
401 valid_err qq<Class/IF <$clsu> must be defined>, node => $_
402 unless defined $cls->{Name};
403 } else {
404 $cls = $State->{ExpandedURI q<dis2pm:thisClass>};
405 valid_err q<Class/IF name required in this context>, node => $_
406 unless defined $cls->{Name};
407 }
408
409 my $const = $cls->{ExpandedURI q<dis2pm:const>}->{$constn};
410 valid_err qq<Constant value "$constn" not defined in class/IF >.
411 qq{"$cls->{Name}" (<$cls->{URI}>)}, node => $_
412 unless defined $const->{Name};
413 $r = dispm_const_value (resource => $const);
414 } else {
415 valid_err qq<"$q": Syntax error>, node => $opt{node};
416 }
417 } else {
418 valid_err qq<"$et": Unknown element type>, node => $opt{node};
419 }
420 } else {
421 valid_err qq<"<$q>": Element type must be specified>, node => $opt{node};
422 }
423 } else {
424 $r = {true => 1, false => 0, null => 'undef'}->{$l};
425 }
426 $r;
427 ]ge;
428 if ($s =~ /\btry\b/) {
429 $s = q<use Message::Util::Error;>.$s;
430 }
431 ## ISSUE: __FILE__ & __LINE__ will break if multiline substition happens.
432 $s =~ s{
433 \b__($RegQNameChar+)
434 (?:\{($RegBlockContent)\})?
435 __\b
436 }{
437 my ($name, $data) = ($1, $2);
438 my $r;
439 my $et = dis_qname_to_uri
440 ($name, %opt,
441 use_default_namespace => ExpandedURI q<disPerl:>);
442 if ($et eq ExpandedURI q<disPerl:DEEP>) { ## Deep Method Call
443 $r = '{'.perl_statement ('local $Error::Depth = $Error::Depth + 1').
444 perl_code ($data, %opt) .
445 '}';
446 } elsif ($et eq ExpandedURI q<disPerl:UNDEEP>) { ## Shallow Method Call
447 $r = '{'.perl_statement ('local $Error::Depth = $Error::Depth - 1').
448 perl_code ($data, %opt) .
449 '}';
450 } elsif ({
451 ExpandedURI q<disPerl:EXCEPTION> => 1,
452 ExpandedURI q<disPerl:WARNING> => 1,
453 }->{$et}) {
454 ## Raising an Exception or Warning
455 if ($data =~ s/^ \s* ((?>(?! ::|\.)$RegQNameChar)+) \s*
456 (?: \. \s* ((?>(?! ::|\.)$RegQNameChar)+) \s*
457 (?: \. \s* ((?>(>! ::|\.)$RegQNameChar)+) \s*
458 )?
459 )?
460 (?: ::\s* | $)//ox) {
461 my ($q, $constq, $subtypeq) = ($1, $2, $3);
462 s/\|/:/g for $q, $constq, $subtypeq;
463 my ($cls, $const, $subtype) = dispm_xcref_to_resources
464 ([$q, $constq, $subtypeq], %opt);
465
466 ## Parameter
467 my %xparam;
468 while ($data =~ s/^\s*($RegQNameChar+)\s*//) {
469 my $pnameuri = dis_qname_to_uri ($1, use_default_namespace => 1, %opt);
470 if (defined $xparam{$pnameuri}) {
471 valid_err qq<Exception parameter <$pnameuri> is already specified>,
472 node => $opt{node};
473 }
474 if ($data =~ s/^=>\s*'([^']*)'\s*//) { ## String
475 $xparam{$pnameuri} = $1;
476 } elsif ($data =~ s/^=>\s*\{($RegBlockContent)\}\s*//) { ## Code
477 $xparam{$pnameuri} = perl_code_literal ($1);
478 } elsif ($data =~ /^,|$/) { ## Boolean
479 $xparam{$pnameuri} = 1;
480 } else {
481 valid_err qq<<$pnameuri>: Parameter value is expected>,
482 node => $opt{node};
483 }
484 $data =~ s/^\,\s*// or last;
485 }
486 valid_err qq<"$data": Broken exception parameter specification>,
487 node => $opt{node} if length $data;
488 for (
489 ExpandedURI q<MDOMX:class>,
490 ExpandedURI q<MDOMX:method>,
491 ExpandedURI q<MDOMX:attr>,
492 ExpandedURI q<MDOMX:on>,
493 ) {
494 $xparam{$_} = $opt{$_} if defined $opt{$_};
495 }
496
497 $r = dispm_perl_throws
498 (%opt,
499 class_resource => $cls,
500 type_resource => $const,
501 subtype_resource => $subtype,
502 xparam => \%xparam);
503 } else {
504 valid_err qq<Exception type and name required: "$data">,
505 node => $opt{node};
506 }
507 } elsif ($et eq ExpandedURI q<disPerl:CODE>) {
508 my ($nm);
509 $data =~ s/^\s+//;
510 if ($data =~ s/^((?>(?!::).)+)//) {
511 $nm = $1;
512 } else {
513 valid_err q<Code name required>, node => $opt{node};
514 }
515 $data =~ s/^::\s*//;
516 my $param = dispm_parse_param (\$data, %opt,
517 use_default_namespace => '',
518 ExpandedURI q<dis2pm:endOrErr> => 1);
519 my $uri = dis_typeforqnames_to_uri ($nm, use_default_namespace => 1,
520 %opt);
521 if (defined $State->{Type}->{$uri}->{Name} and
522 dis_resource_ctype_match (ExpandedURI q<dis2pm:BlockCode>,
523 $State->{Type}->{$uri}, %opt)) {
524 local $State->{ExpandedURI q<dis2pm:blockCodeParam>} = $param;
525 ## ISSUE: It might be required to detect a loop
526 $r = dispm_get_code (%opt, resource => $State->{Type}->{$uri},
527 For => [keys %{$State->{Type}->{$uri}
528 ->{For}}]->[0],
529 'For+' => [keys %{$State->{Type}->{$uri}
530 ->{'For+'}||{}}],
531 ExpandedURI q<dis2pm:selParent> => $param,
532 ExpandedURI q<dis2pm:DefKeyName>
533 => ExpandedURI q<d:Def>);
534 for (grep {/^\$/} keys %$param) {
535 $r =~ s/\Q$_\E\b/ref $param->{$_} ? ${$param->{$_}} : $param->{$_}/ge;
536 }
537 valid_err qq<Block code <$uri> is empty>, node => $opt{node}
538 unless length $r;
539 $r = "\n{\n$r\n}\n";
540 } else {
541 valid_err qq<Block code constant <$uri> must be defined>,
542 node => $opt{node};
543 }
544 } elsif ($et eq ExpandedURI q<ManakaiDOM:InputNormalize>) {
545 my $method = $opt{ExpandedURI q<dis2pm:currentMethodResource>};
546 valid_err q<Element <ManakaiDOM:InputNroamlize> cannot be used here>,
547 node => $opt{node} unless defined $method->{Name};
548 PARAM: {
549 for my $param (@{$method->{ExpandedURI q<dis2pm:param>}||[]}) {
550 if ($data eq $param->{ExpandedURI q<dis2pm:paramName>}) {
551 ## NOTE: <ManakaiDOM:noInputNormalize> property is not
552 ## checked for this element.
553 my $nm = dispm_get_code
554 (%opt, resource => $State->{Type}
555 ->{$param->{ExpandedURI q<d:actualType>}},
556 ExpandedURI q<dis2pm:DefKeyName>
557 => ExpandedURI q<ManakaiDOM:inputNormalizer>,
558 ExpandedURI q<dis2pm:getCodeNoTypeCheck> => 1,
559 ExpandedURI q<dis2pm:selParent>
560 => $param->{ExpandedURI q<dis2pm:actualTypeNode>});
561 if (defined $nm) {
562 $nm =~ s[\$INPUT\b][\$$param->{ExpandedURI q<dis2pm:paramName>} ]g;
563 $r = $nm;
564 } else {
565 $r = '';
566 }
567 last PARAM;
568 }
569 }
570 valid_err q<Parameter "$data" is not found>, node => $opt{node};
571 }
572 } elsif ($et eq ExpandedURI q<disPerl:WHEN>) {
573 if ($data =~ s/^\s*IS\s*\{($RegBlockContent)\}::\s*//o) {
574 my $v = dis_qname_to_uri ($1, use_default_namespace => 1, %opt);
575 if ($State->{ExpandedURI q<dis2pm:blockCodeParam>}->{$v}) {
576 $r = perl_code ($data, %opt);
577 }
578 } else {
579 valid_err qq<Syntax for preprocessing macro "WHEN" is invalid>,
580 node => $opt{node};
581 }
582 } elsif ($et eq ExpandedURI q<disPerl:FOR>) {
583 if ($data =~ s/^((?>(?!::).)*)::\s*//) {
584 my @For = ($opt{For} || ExpandedURI q<ManakaiDOM:all>,
585 @{$opt{'For+'} || []});
586 V: for (split /\s*\|\s*/, $1) {
587 my $for = dis_qname_to_uri ($_, %opt, use_default_namespace => 1,
588 node => $opt{node});
589 for (@For) {
590 if (dis_uri_for_match ($for, $_, %opt)) {
591 $r = perl_code ($data, %opt);
592 last V;
593 }
594 }
595 }
596 } else {
597 valid_err (qq<Broken <$et> block: "$data">, node => $opt{node});
598 }
599 } elsif ($et eq ExpandedURI q<disPerl:ASSERT>) {
600 my $atype;
601 if ($data =~ s/^\s*($RegQNameChar+)\s*::\s*//) {
602 $atype = dis_qname_to_uri ($1, %opt, use_default_namespace => 1);
603 } else {
604 valid_err (qq<"$data": Assertion type QName is required>,
605 node => $opt{node});
606 }
607 my $param = dispm_parse_param (\$data, %opt,
608 use_default_namespace => '',
609 ExpandedURI q<dis2pm:endOrErr> => 1);
610 my %xparam;
611 my $cond;
612 my $pre = '';
613 my $post = '';
614 if ($atype eq ExpandedURI q<DISPerl:isPositive>) {
615 $pre = perl_statement
616 perl_assign
617 'my $asActual' =>
618 '('.perl_code ($param->{actual}, %opt).')';
619 $cond = '$asActual > 0';
620 $xparam{ExpandedURI q<DOMMain:expectedLabel>} = 'a positive value';
621 $xparam{ExpandedURI q<DOMMain:actualValue>}
622 = perl_code_literal q<$asActual>;
623 } elsif ($atype eq ExpandedURI q<DISPerl:invariant>) {
624 $cond = '0';
625 $xparam{ExpandedURI q<DOMMain:expectedLabel>} = $param->{msg};
626 $xparam{ExpandedURI q<DOMMain:actualValue>} = '(invariant)';
627 } else {
628 valid_err (qq<Assertion type <$atype> is not supported>,
629 node => $opt{node});
630 }
631 if (defined $param->{pre}) {
632 $pre = perl_code ($param->{pre}, %opt) . $pre;
633 }
634 if (defined $param->{post}) {
635 $post .= perl_code ($param->{post}, %opt);
636 }
637
638 for (
639 ExpandedURI q<MDOMX:class>,
640 ExpandedURI q<MDOMX:method>,
641 ExpandedURI q<MDOMX:attr>,
642 ExpandedURI q<MDOMX:on>,
643 ) {
644 $xparam{$_} = $opt{$_} if defined $opt{$_};
645 }
646 if ($Opt{outputAssertion}) {
647 $r = $pre . perl_if
648 $cond,
649 undef,
650 perl_statement
651 dispm_perl_throws
652 class =>
653 ExpandedURI q<DX:CoreException>,
654 class_for => ExpandedURI q<ManakaiDOM:Perl>,
655 type => 'MDOM_DEBUG_BUG',
656 subtype => ExpandedURI q<DOMMain:ASSERTION_ERR>,
657 xparam => {
658 ExpandedURI q<DOMMain:assertionType> => $atype,
659 ExpandedURI q<DOMMain:traceText>
660 => perl_code_literal
661 q<(sprintf 'at %s line %s%s%s',
662 __FILE__, __LINE__, "\n\t",
663 Carp::longmess ())>,
664 %xparam,
665 };
666 $r .= $post;
667 $r = "{$r}";
668 } else {
669 $r = '';
670 }
671 } elsif ({
672 ExpandedURI q<disPerl:FILE> => 1,
673 ExpandedURI q<disPerl:LINE> => 1,
674 ExpandedURI q<disPerl:PACKAGE> => 1,
675 }->{$et}) {
676 $r = qq<__${name}__>;
677 valid_err (q<Block element content cannot be specified for >.
678 qq<element type <$et>>, node => $opt{node})
679 if length $data;
680 } else {
681 valid_err qq<Preprocessing macro <$et> not supported>, node => $opt{node};
682 }
683 $r;
684 }goex;
685
686 ## Checks \p character classes
687 while ($s =~ /\\p{([^{}]+)}/gs) {
688 my $name = $1;
689 $State->{ExpandedURI q<dis2pm:Package>}
690 ->{$State->{ExpandedURI q<dis2pm:currentPackage>}}
691 ->{ExpandedURI q<dis2pm:requiredCharClass>}
692 ->{$name} ||= $opt{node} || 1;
693 }
694
695 $s;
696 }
697
698 =item {%param} = dispm_parse_param (\$paramspec, %opt)
699
700 Parses parameter specification and returns it as a reference
701 to hash.
702
703 =cut
704
705 sub dispm_parse_param ($%) {
706 my ($src, %opt) = @_;
707 my %param;
708 while ($$src =~ s/^
709 ## Parameter name
710 (\$? $RegQNameChar+)\s*
711
712 (?: =>? \s*
713
714 ## Parameter value
715 (
716 ## Bare string
717 $RegQNameChar+
718 |
719 ## Quoted string
720 '(?>[^'\\]*)' ## ISSUE: escape mechanism required?
721 |
722 ## Code
723 \{$RegBlockContent\}
724
725 )
726
727 \s*)?
728
729 (?:,\s*|$)//ox) {
730 my ($n, $v) = ($1, $2);
731 if (defined $v) {
732 if ($v =~ /^'/) {
733 $v = substr ($v, 1, length ($v) - 2);
734 } elsif ($v =~ /^\{/) {
735 $v = perl_code_literal substr ($v, 1, length ($v) - 2);
736 } else {
737 #
738 }
739 } else {
740 $v = 1;
741 }
742
743 if ($n =~ /^\$/) {
744 $param{$n} = $v;
745 } else {
746 $param{dis_qname_to_uri ($n, %opt)} = $v;
747 }
748 }
749 if ($opt{ExpandedURI q<dis2pm:endOrErr>} and length $$src) {
750 valid_err qq<Broken parameter specification: "$$src">, node => $opt{node};
751 }
752 \%param;
753 } # dispm_parse_param
754
755 =item $result = perl_code_source ($code, %opt)
756
757 Attaches the source file information to a Perl code fragment.
758
759 Note that the same name function is defined in F<genlib.pl>
760 but redefined here for the purpose of this script.
761
762 TODO: Non-debug purpose output should remove source information; otherwise
763 it is too verbose.
764
765 =cut
766
767 sub perl_code_source ($%) {
768 my ($s, %opt) = @_;
769 my $npk = [qw/Name QName Label/];
770 my $f1 = sprintf q<File <%s> Node <%s> [Chunk #%d]>,
771 $opt{file} || $State->{Module}->{$opt{resource}->{parentModule}}->{FileName},
772 $opt{path} || ($opt{resource}->{src}
773 ? $opt{resource}->{src}->node_path (key => $npk)
774 : $opt{node} ? $opt{node}->node_path (key => $npk)
775 : 'x:unknown ()'),
776 ++($State->{ExpandedURI q<dis2pm:generatedChunk>} ||= 0);
777 my $f2 = sprintf q<Module <%s> [Chunk #%d]>,
778 $opt{file} || $State->{Module}->{$State->{module}}->{URI},
779 ++($State->{ExpandedURI q<dis2pm:generatedChunk>} ||= 0);
780 $f1 =~ s/"/\"/g; $f2 =~ s/"/\"/g;
781 sprintf qq<\n#line %d "%s"\n%s\n#line 1 "%s"\n>,
782 $opt{line} || 1, $f1, $s, $f2;
783 } # perl_code_source
784
785
786
787
788 =item $code = dispm_get_code (resource => $res, %opt)
789
790 Generates a Perl code fragment from resource(s).
791
792 =cut
793
794 sub dispm_get_code (%) {
795 my %opt = @_;
796 if (($opt{ExpandedURI q<dis2pm:getCodeNoTypeCheck>} and
797 defined $opt{resource}->{Name}) or
798 ($opt{resource}->{ExpandedURI q<dis2pm:type>} and
799 {
800 ExpandedURI q<DISLang:MethodReturn> => 1,
801 ExpandedURI q<DISLang:AttributeGet> => 1,
802 ExpandedURI q<DISLang:AttributeSet> => 1,
803 }->{$opt{resource}->{ExpandedURI q<dis2pm:type>}}) or
804 (dis_resource_ctype_match ([ExpandedURI q<dis2pm:InlineCode>,
805 ExpandedURI q<dis2pm:BlockCode>],
806 $opt{resource}, %opt,
807 node => $opt{resource}->{src}))) {
808 local $State->{Namespace}
809 = $State->{Module}->{$opt{resource}->{parentModule}}->{nsBinding}
810 if defined $opt{resource}->{Name};
811 my $key = $opt{ExpandedURI q<dis2pm:DefKeyName>} || ExpandedURI q<d:Def>;
812
813 my $n = dis_get_attr_node (%opt, parent => $opt{resource}->{src},
814 name => {uri => $key},
815 ContentType => ExpandedURI q<d:Perl>) ||
816 dis_get_attr_node (%opt, parent => $opt{resource}->{src},
817 name => {uri => $key},
818 ContentType => ExpandedURI q<lang:dis>);
819 if ($n) {
820 return disperl_to_perl (%opt, node => $n);
821 }
822
823 $n = dis_get_attr_node (%opt, parent => $opt{resource}->{src},
824 name => {uri => $key},
825 ContentType => ExpandedURI q<lang:Perl>);
826 if ($n) {
827 my $code = '';
828 for (@{dis_get_elements_nodes (%opt, parent => $n,
829 name => 'require')}) {
830 $code .= perl_statement 'require ' . $_->value;
831 }
832 my $v = $n->value;
833 valid_err q<Perl code is required>, node => $n unless defined $v;
834 $code .= perl_code ($v, %opt, node => $n);
835 if ($opt{is_inline} and
836 dis_resource_ctype_match ([ExpandedURI q<dis2pm:InlineCode>],
837 $opt{resource}, %opt,
838 node => $opt{resource}->{src})) {
839 $code =~ s/\n/\x20/g;
840 return $code;
841 } else {
842 return perl_code_source ($code, %opt, node => $n);
843 }
844 }
845 return undef;
846 } else {
847 impl_err ("Bad resource for dispm_get_code: ".
848 $opt{resource}->{ExpandedURI q<dis2pm:type>},
849 node => $opt{resource}->{src});
850 }
851 } # dispm_get_code
852
853 =item $code = dispm_get_value (%opt)
854
855 Gets value property and returns it as a Perl code fragment.
856
857 =cut
858
859 sub dispm_get_value (%) {
860 my %opt = @_;
861 my $key = $opt{ExpandedURI q<dis2pm:ValueKeyName>} || ExpandedURI q<d:Value>;
862 my $vt = $opt{ExpandedURI q<dis2pm:valueType>} || ExpandedURI q<DOMMain:any>;
863 local $State->{Namespace}
864 = $State->{Module}->{$opt{resource}->{parentModule}}->{nsBinding}
865 if defined $opt{resource}->{Name};
866 local $opt{For} = [keys %{$opt{resource}->{For}}]->[0]
867 if defined $opt{resource}->{Name};
868 local $opt{'For+'} = [keys %{$opt{resource}->{'For+'}||{}}]
869 if defined $opt{resource}->{Name};
870 my $n = $opt{node} ? [$opt{node}]
871 : dis_get_elements_nodes
872 (%opt, parent => $opt{resource}->{src},
873 name => {uri => $key});
874 for my $n (@$n) {
875 my $t = dis_get_attr_node (%opt, parent => $n, name => 'ContentType');
876 my $type;
877 if ($t) {
878 $type = dis_qname_to_uri ($t->value, %opt, node => $t);
879 } elsif ($opt{resource}->{ExpandedURI q<d:actualType>}) {
880 $type = $opt{resource}->{ExpandedURI q<d:actualType>};
881 } else {
882 $type = ExpandedURI q<lang:dis>;
883 }
884 valid_err (qq<Type <$type> is not defined>, node => $t || $n)
885 unless defined $State->{Type}->{$type}->{Name};
886
887 if (dis_uri_ctype_match (ExpandedURI q<lang:Perl>, $type, %opt)) {
888 return perl_code ($n->value, %opt, node => $n);
889 } elsif (dis_uri_ctype_match (ExpandedURI q<DISCore:String>, $type, %opt) or
890 dis_uri_ctype_match (ExpandedURI q<DOMMain:DOMString>, $type, %opt)) {
891 return perl_literal $n->value;
892 } elsif (dis_uri_ctype_match (ExpandedURI q<DOMMain:unsigned-short>, $type, %opt) or
893 dis_uri_ctype_match (ExpandedURI q<DOMMain:unsigned-long>, $type, %opt) or
894 dis_uri_ctype_match (ExpandedURI q<DOMMain:short>, $type, %opt) or
895 dis_uri_ctype_match (ExpandedURI q<DOMMain:long>, $type, %opt)) {
896 return $n->value;
897 } elsif (dis_uri_ctype_match (ExpandedURI q<DOMMain:boolean>, $type, %opt)) {
898 return ($n->value and ($n->value eq 'true' or $n->value eq '1')) ? 1 : 0;
899 } elsif (dis_uri_ctype_match (ExpandedURI q<d:Boolean>, $type, %opt)) {
900 return $n->value ? 1 : 0;
901 } elsif (dis_uri_ctype_match (ExpandedURI q<lang:dis>, $type, %opt)) {
902 return perl_literal $n->value;
903 }
904 }
905
906 ## No explicit value specified
907 if ($opt{ExpandedURI q<dis2pm:useDefaultValue>}) {
908 if (dis_uri_ctype_match (ExpandedURI q<DOMMain:DOMString>, $vt, %opt)) {
909 return q<"">;
910 } elsif (dis_uri_ctype_match (ExpandedURI q<DOMMain:unsigned-short>, $vt, %opt) or
911 dis_uri_ctype_match (ExpandedURI q<DOMMain:unsigned-long>, $vt, %opt) or
912 dis_uri_ctype_match (ExpandedURI q<DOMMain:short>, $vt, %opt) or
913 dis_uri_ctype_match (ExpandedURI q<DOMMain:long>, $vt, %opt) or
914 dis_uri_ctype_match (ExpandedURI q<DOMMain:boolean>, $vt, %opt)) {
915 return q<0>;
916 } elsif (dis_uri_ctype_match (ExpandedURI q<Perl:ARRAY>, $vt, %opt)) {
917 return q<[]>;
918 } elsif (dis_uri_ctype_match (ExpandedURI q<Perl:hash>, $vt, %opt)) {
919 return q<{}>;
920 }
921 }
922 return undef;
923 } # dispm_get_value
924
925
926
927 =item $code = dispm_const_value (resource => $const, %opt)
928
929 Returns a code fragment corresponding to the vaue of C<$const>.
930
931 =cut
932
933 sub dispm_const_value (%) {
934 my %opt = @_;
935 my $for = [keys %{$opt{resource}->{For}}]->[0];
936 local $opt{'For+'} = [keys %{$opt{resource}->{'For+'}||{}}];
937 my $value = dispm_get_value
938 (%opt,
939 ExpandedURI q<dis2pm:ValueKeyName>
940 => ExpandedURI q<d:Value>,
941 ExpandedURI q<dis2pm:valueType>
942 => $opt{resource}
943 ->{ExpandedURI q<dis2pm:actualType>},
944 For => $for);
945 valid_err q<Constant value must be specified>, node => $opt{resource}->{src}
946 unless defined $value;
947 return $value;
948 } # dispm_const_value
949
950 =item $code = dispm_const_value_sub (resource => $const, %opt)
951
952 Returns a code fragment to declare and define a constant function
953 corresponding to the definition of C<$const>.
954
955 =cut
956
957 sub dispm_const_value_sub (%) {
958 my %opt = @_;
959 my $value = dispm_const_value (%opt);
960 my $name = $opt{resource}->{ExpandedURI q<dis2pm:constName>};
961 my $pc = $State->{ExpandedURI q<dis2pm:Package>}
962 ->{$State->{Module}->{$State->{module}}
963 ->{ExpandedURI q<dis2pm:packageName>}}
964 ->{ExpandedURI q<dis2pm:const>} ||= {};
965 valid_err qq<Constant value "$name" is already defined in the same module>,
966 node => $opt{resource}->{src} if defined $pc->{$name}->{resource}->{Name};
967 $pc->{$name} = {
968 name => $name, resource => $opt{resource},
969 package => $State->{ExpandedURI q<dis2pm:currentPackage>},
970 };
971 return perl_sub
972 (name => $name,
973 prototype => '',
974 code => $value);
975 } # dispm_const_value_sub
976
977 =item $code = dispm_const_group (resource => $const_group, %opt)
978
979 Returns a code fragment to define a constant value group.
980
981 =cut
982
983 sub dispm_const_group (%) {
984 my %opt = @_;
985 my $name = $opt{resource}->{ExpandedURI q<dis2pm:constGroupName>};
986 for my $cg (values %{$opt{resource}->{ExpandedURI q<dis2pm:constGroup>}}) {
987 if (defined $cg->{ExpandedURI q<dis2pm:constGroupName>}) {
988 valid_err (qq{"$name"."$cg->{ExpandedURI q<dis2pm:constGroupName>}": }.
989 qq{Nesting constant group not supported},
990 node => $cg->{src});
991 }
992 }
993
994 my $result = '';
995 my @cname;
996 if (length $name) {
997 if (defined $opt{ExpandedURI q<dis2pm:constGroupParentPackage>}->{$name}) {
998 valid_err qq<Const group "$name" is already defined>,
999 node => $opt{resource}->{src};
1000 }
1001 $opt{ExpandedURI q<dis2pm:constGroupParentPackage>}->{$name} = \@cname;
1002 }
1003
1004 my $pc = $State->{ExpandedURI q<dis2pm:Package>}
1005 ->{$State->{Module}->{$State->{module}}
1006 ->{ExpandedURI q<dis2pm:packageName>}}
1007 ->{ExpandedURI q<dis2pm:constGroup>} ||= {};
1008 valid_err qq<Constant group "$name" is already defined in the same module>,
1009 node => $opt{resource}->{src} if defined $pc->{$name}->{resource}->{Name};
1010 $pc->{$name} = {
1011 name => $name, resource => $opt{resource},
1012 member => \@cname,
1013 };
1014
1015 for my $cv (values %{$opt{resource}->{ExpandedURI q<dis2pm:const>}}) {
1016 next unless defined $cv->{ExpandedURI q<dis2pm:constName>};
1017 #$result .= dispm_const_value_sub (%opt, resource => $cv);
1018 push @cname, $cv->{ExpandedURI q<dis2pm:constName>};
1019 }
1020 return $result;
1021 } # dispm_const_group
1022
1023 =item $desc = dispm_muf_description (%opt, resource => $res)
1024
1025 Gets a <IF::Message::Util::Formatter> template for a resource.
1026
1027 =cut
1028
1029 sub dispm_muf_description (%) {
1030 my %opt = @_;
1031 my $key = $opt{ExpandedURI q<dis2pm:DefKeyName>} || ExpandedURI q<d:Def>;
1032
1033 local $State->{Namespace}
1034 = $State->{Module}->{$opt{resource}->{parentModule}}->{nsBinding};
1035 local $opt{For} = [keys %{$opt{resource}->{For}}]->[0];
1036 local $opt{'For+'} = [keys %{$opt{resource}->{'For+'}||{}}];
1037
1038 my $def = dis_get_attr_node (%opt, parent => $opt{resource}->{src},
1039 name => {uri => $key},
1040 ContentType => ExpandedURI q<lang:muf>);
1041 if ($def) {
1042 my $template = $def->value;
1043 $template =~ s/<Q::([^<>]+)>/dis_qname_to_uri ($1, %opt,
1044 node => $opt{resource}
1045 ->{src})/ge;
1046 $template =~ s/\s+/ /g;
1047 $template =~ s/^ //;
1048 $template =~ s/ $//;
1049 return $template;
1050 }
1051
1052 $key = $opt{ExpandedURI q<dis2pm:DescriptionKeyName>} ||
1053 ExpandedURI q<d:Description>;
1054
1055 my $template = '';
1056 for $def (@{dis_get_elements_nodes
1057 (%opt, parent => $opt{resource}->{src},
1058 name => {uri => $key},
1059 ContentType => ExpandedURI q<lang:disdoc>,
1060 defaultContentType => ExpandedURI q<lang:disdoc>)}) {
1061 $template .= disdoc2text ($def->value, %opt, node => $def);
1062 }
1063 $template =~ s/\s+/ /g;
1064 $template =~ s/^ //;
1065 $template =~ s/ $//;
1066 return $template;
1067 } # dispm_muf_description
1068
1069 =item $code = disperl_to_perl (node => $node, %opt)
1070
1071 Converts a C<d:Perl> node to a Perl code fragment.
1072
1073 =cut
1074
1075 sub disperl_to_perl (%) {
1076 my %opt = @_;
1077 my $code = '';
1078 for (@{$opt{node}->child_nodes}) {
1079 next unless $_->node_type eq '#element';
1080 next unless dis_node_for_match ($_, $opt{For}, %opt);
1081 my $et = dis_element_type_to_uri ($_->local_name, %opt, node => $_);
1082 if ($et eq ExpandedURI q<DISLang:constValue>) {
1083 my $cn = $_->value;
1084 if ($cn =~ /^((?>(?!\.)$RegQNameChar)*)\.($RegQNameChar+)$/o) {
1085 my ($cls, $constn) = ($1, $2);
1086 if (length $cls) {
1087 my $clsu = dis_typeforqnames_to_uri ($cls, %opt,
1088 use_default_namespace => 1,
1089 node => $_);
1090 $cls = $State->{Type}->{$clsu};
1091 valid_err qq<Class/IF <$clsu> must be defined>, node => $_
1092 unless defined $cls->{Name};
1093 } else {
1094 $cls = $State->{ExpandedURI q<dis2pm:thisClass>};
1095 valid_err q<Class/IF name required in this context>, node => $_
1096 unless defined $cls->{Name};
1097 }
1098
1099 my $const = $cls->{ExpandedURI q<dis2pm:const>}->{$constn};
1100 valid_err qq<Constant value "$constn" not defined in class/IF >.
1101 qq{"$cls->{Name}" (<$cls->{URI}>)}, node => $_
1102 unless defined $const->{Name};
1103 $code .= perl_statement
1104 perl_assign
1105 perl_var (type => '$', local_name => 'r')
1106 => dispm_const_value (resource => $const);
1107 } else {
1108 valid_err q<Syntax error>, node => $_;
1109 }
1110 } elsif ($et eq ExpandedURI q<DISLang:value>) {
1111 my $v = dispm_get_value (%opt, node => $_);
1112 $code .= perl_statement
1113 perl_assign
1114 perl_var (type => '$', local_name => 'r') => $v;
1115 } elsif ($et eq ExpandedURI q<d:GetProp> or
1116 $et eq ExpandedURI q<d:GetPropNode> or
1117 $et eq ExpandedURI q<swcfg21:GetPropNode>) {
1118 my $uri = dis_qname_to_uri ($_->value, %opt, node => $_,
1119 use_default_namespace => 1);
1120 $code .= perl_statement
1121 perl_assign
1122 perl_var (type => '$', local_name => 'r')
1123 => '$self->{'.(ExpandedURI q<TreeCore:node>).
1124 '}->{'.(perl_literal $uri).'}';
1125 if ($et eq ExpandedURI q<d:GetPropNode>) {
1126 $code .= perl_if
1127 'defined $r',
1128 perl_code (q{$r = <ClassM::DOMCore:ManakaiDOMNode
1129 .getNodeReference> ($r)},
1130 %opt, node => $_);
1131 } elsif ($et eq ExpandedURI q<swcfg21:GetPropNode>) {
1132 $code .= perl_if
1133 'defined $r',
1134 perl_code (q{$r = <ClassM::swcfg21:ManakaiSWCFGNode
1135 .getNodeReference> ($r)},
1136 %opt, node => $_);
1137 }
1138 } elsif ($et eq ExpandedURI q<d:SetProp>) {
1139 my $uri = dis_qname_to_uri ($_->value, %opt, node => $_,
1140 use_default_namespace => 1);
1141 my $chk = dis_get_attr_node (%opt, parent => $_, name => 'CheckReadOnly');
1142 if ($chk and $chk->value) {
1143 my $for1 = $opt{For} || ExpandedURI q<ManakaiDOM:all>;
1144 unless (dis_uri_for_match (ExpandedURI q<ManakaiDOM:ManakaiDOM1>,
1145 $for1, node => $_)) {
1146 $for1 = ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>;
1147 }
1148 $code .= perl_if
1149 q[$self->{].(perl_literal ExpandedURI q<TreeCore:node>).
1150 q[}->{].(perl_literal ExpandedURI q<DOMCore:read-only>).
1151 q[}],
1152 perl_statement
1153 dispm_perl_throws
1154 (%opt, class_for => $for1,
1155 class => ExpandedURI q<DOMCore:ManakaiDOMException>,
1156 type => 'NO_MODIFICATION_ALLOWED_ERR',
1157 subtype => ExpandedURI q<MDOMX:NOMOD_THIS>);
1158 }
1159 $code .= perl_statement
1160 perl_assign
1161 '$self->{'.(ExpandedURI q<TreeCore:node>).
1162 '}->{'.(perl_literal $uri).'}'
1163 => perl_var (type => '$', local_name => 'given');
1164 } elsif ($et eq ExpandedURI q<DISPerl:cloneCode>) {
1165 my $memref = $_->value;
1166 my $mem = dispm_memref_to_resource
1167 ($memref, %opt, node => $_,
1168 return_method_returner => 1,
1169 use_default_type_resource =>
1170 $State->{ExpandedURI q<dis2pm:thisClass>},
1171 ## ISSUE: Reference in a resource that is
1172 ## referred from another resource might
1173 ## not be interpreted correctly.
1174 );
1175 ## ISSUE: It might be required to detect a loop
1176 $code .= dispm_get_code (%opt, resource => $mem,
1177 For => [keys %{$mem->{For}}]->[0],
1178 'For+' => [keys %{$mem->{'For+'}||{}}],
1179 ExpandedURI q<dis2pm:DefKeyName>
1180 => ExpandedURI q<d:Def>);
1181 } elsif ($et eq ExpandedURI q<DOMMain:raiseException>) {
1182 my ($cls, $type, $subtype) = dispm_xcref_to_resources
1183 ($_->value, %opt, node => $_);
1184 ## TODO: Parameter
1185 my %xparam;
1186
1187 for (
1188 ExpandedURI q<MDOMX:class>,
1189 ExpandedURI q<MDOMX:method>,
1190 ExpandedURI q<MDOMX:attr>,
1191 ExpandedURI q<MDOMX:on>,
1192 ) {
1193 $xparam{$_} = $opt{$_} if defined $opt{$_};
1194 }
1195
1196 $code .= perl_statement dispm_perl_throws
1197 (%opt,
1198 class_resource => $cls,
1199 type_resource => $type,
1200 subtype_resource => $subtype,
1201 xparam => \%xparam);
1202 } elsif ($et eq ExpandedURI q<DISPerl:selectByProp>) {
1203 my $cprop = dis_get_attr_node
1204 (%opt, parent => $_,
1205 name => {uri => ExpandedURI q<DISPerl:propName>});
1206 my $propvalue;
1207 if ($cprop) {
1208 my $cpropuri = dis_qname_to_uri ($cprop->value,
1209 use_default_namespace => 1,
1210 %opt, node => $cprop);
1211 my $prop;
1212 if ($opt{ExpandedURI q<dis2pm:selParent>}) {
1213 if (ref $opt{ExpandedURI q<dis2pm:selParent>} eq 'HASH') {
1214 $prop = $opt{ExpandedURI q<dis2pm:selParent>};
1215 if (defined $prop->{$cpropuri}) {
1216 $propvalue = $prop->{$cpropuri};
1217 } else {
1218 $propvalue = '';
1219 }
1220 } else {
1221 $prop = dis_get_attr_node
1222 (%opt, parent => $opt{ExpandedURI q<dis2pm:selParent>},
1223 name => {uri => $cpropuri});
1224 if ($prop) {
1225 $propvalue = $prop->value;
1226 } else {
1227 $propvalue = '';
1228 }
1229 }
1230 } else {
1231 valid_err q<Element "DISPerl:selectByProp" cannot be used here>,
1232 node => $_;
1233 }
1234 } else {
1235 valid_err q<Attribute "DISPerl:propName" required>,
1236 node => $_;
1237 }
1238 my $selcase;
1239 for my $case (@{$_->child_nodes}) {
1240 next unless $case->node_type eq '#element';
1241 next unless dis_node_for_match ($case, $opt{For}, %opt);
1242 my $et = dis_element_type_to_uri ($case->local_name,
1243 %opt, node => $case);
1244 if ($et eq ExpandedURI q<DISPerl:case>) {
1245 my $val = dis_get_attr_node
1246 (%opt, parent => $case,
1247 name => 'Value',
1248 ContentType => ExpandedURI q<lang:dis>,
1249 defaultContentType => ExpandedURI q<lang:dis>);
1250 if ($val and $val->value eq $propvalue) {
1251 $selcase = $case; last;
1252 } elsif ($propvalue eq '' and (not $val or not $val->value)) {
1253 $selcase = $case; last;
1254 }
1255 } elsif ($et eq ExpandedURI q<DISPerl:else>) {
1256 $selcase = $case; last;
1257 } elsif ({
1258 ExpandedURI q<DISPerl:propName> => 1,
1259 }->{$et}) {
1260 #
1261 } else {
1262 valid_err qq<Element type <$et> not allowed here>,
1263 node => $case;
1264 }
1265 }
1266 if ($selcase) {
1267 my $lcode = perl_code ($selcase->value, %opt, node => $selcase);
1268 if ($opt{is_inline}) {
1269 $code .= $lcode;
1270 } else {
1271 $code .= perl_code_source ($lcode, %opt, node => $selcase);
1272 }
1273 }
1274 } elsif ({
1275 ExpandedURI q<d:ContentType> => 1,
1276 ExpandedURI q<d:For> => 1,
1277 ExpandedURI q<d:ForCheck> => 1,
1278 ExpandedURI q<d:ImplNote> => 1,
1279 ExpandedURI q<DISLang:nop> => 1,
1280 }->{$et}) {
1281 #
1282 } else {
1283 valid_err qq<Element type <$et> not supported>,
1284 node => $opt{node};
1285 }
1286 }
1287
1288 my $val = $opt{node}->value;
1289 if (defined $val and length $val) {
1290 my $lcode = perl_code ($val, %opt);
1291 if ($opt{is_inline}) {
1292 $code .= $lcode;
1293 } else {
1294 $code .= perl_code_source ($lcode, %opt);
1295 }
1296 }
1297 return $code;
1298 } # disperl_to_perl
1299
1300 =item $res = dispm_memref_to_resource ($memref, %opt)
1301
1302 Converts a C<DISPerl:MemRef> (a reference to a class member,
1303 i.e. either method, attribute, attribute getter or attribute
1304 setter) to a resource.
1305
1306 =cut
1307
1308 sub dispm_memref_to_resource ($%) {
1309 my ($memref, %opt) = @_;
1310 my ($clsq, $memq) = split /\./, $memref, 2;
1311 unless (defined $memq) {
1312 valid_err qq<"$memref": Member name required>. node => $opt{node};
1313 } elsif ($memq =~ /:/) {
1314 valid_err qq<"$memref": Prefixed member name not supported>,
1315 node => $opt{node};
1316 }
1317
1318 ## Class
1319 my $cls;
1320 my $clsuri;
1321 if ($clsq eq '') {
1322 if (defined $opt{use_default_type_resource}->{Name}) {
1323 $cls = $opt{use_default_type_resource};
1324 $clsuri = $cls->{URI};
1325 } elsif ($opt{use_default_type}) {
1326 $clsuri = $opt{use_default_type};
1327 } else {
1328 $clsuri = dis_typeforqnames_to_uri
1329 ($clsq, use_default_namespace => 1, %opt);
1330 }
1331 } else {
1332 $clsuri = dis_typeforqnames_to_uri
1333 ($clsq, use_default_namespace => 1, %opt);
1334 }
1335 unless ($cls) {
1336 $cls = $State->{Type}->{$clsuri};
1337 valid_err qq<Class <$clsuri> must be defined>, node => $opt{node}
1338 unless defined $cls->{Name};
1339 }
1340
1341 ## Method or attribute
1342 my $memname = $memq;
1343 my $mem;
1344 for (values %{$cls->{ExpandedURI q<dis2pm:method>}||{}}) {
1345 if (defined $_->{Name} and $_->{Name} eq $memname) {
1346 $mem = $_;
1347 last;
1348 }
1349 }
1350 if ($mem) {
1351 if ($opt{return_method_returner}) {
1352 if (defined $mem->{ExpandedURI q<dis2pm:return>}->{Name}) {
1353 $mem = $mem->{ExpandedURI q<dis2pm:return>};
1354 } elsif (defined $mem->{ExpandedURI q<dis2pm:getter>}->{Name}) {
1355 $mem = $mem->{ExpandedURI q<dis2pm:getter>};
1356 } else {
1357 valid_err qq{Neither "return" nor "getter" is defined for }.
1358 qq{the class "$cls->{Name}" <$cls->{URI}>},
1359 node => $opt{node};
1360 }
1361 }
1362 } elsif ($memname =~ s/^([gs]et)(?=.)//) {
1363 my $gs = $1;
1364 $memname = lcfirst $memname;
1365 my $memp;
1366 for (values %{$cls->{ExpandedURI q<dis2pm:method>}||{}}) {
1367 if (defined $_->{Name} and $_->{Name} eq $memname) {
1368 $memp = $_;
1369 last;
1370 }
1371 }
1372 if ($memp) {
1373 if ($gs eq 'set') {
1374 $mem = $memp->{ExpandedURI q<dis2pm:setter>};
1375 unless (defined $mem->{Name}) {
1376 valid_err qq{Setter for "$memp->{Name}" <$memp->{URI}> is not defined},
1377 node => $opt{node};
1378 }
1379 } else {
1380 $mem = $memp->{ExpandedURI q<dis2pm:getter>};
1381 unless (defined $mem->{Name}) {
1382 valid_err qq{Getter for "$memp->{Name}" <$memp->{URI}> is not defined},
1383 node => $opt{node};
1384 }
1385 }
1386 }
1387 }
1388 valid_err qq<Member "$memq" for class <$clsuri> is not defined>,
1389 node => $opt{node} unless defined $mem->{Name};
1390 return $mem;
1391 } # dispm_memref_to_resource
1392
1393 =item ($clsres, $coderef, $subcoderef) = dispm_xcref_to_resources ($xcref, %opt)
1394
1395 Converts a "DOMMain:XCodeRef" (exception or warning code reference)
1396 to its "resource" objects.
1397
1398 =over 4
1399
1400 =item $clsres
1401
1402 The resource object for the exception or warning class or interface identified
1403 by the XCodeRef.
1404
1405 =item $coderef
1406
1407 The resource object for the exception or warning code identified
1408 by the XCodeRef.
1409
1410 =item $subcoderef
1411
1412 The resource object for the exception or warning code idnetified by
1413 the XCodeRef, if any. If the XCodeRef identifies no subtype resource,
1414 an C<undef> is returned as C<$subcodref>.
1415
1416 =back
1417
1418 =cut
1419
1420 sub dispm_xcref_to_resources ($%) {
1421 my ($xcref, %opt) = @_;
1422 my $q;
1423 my $constq;
1424 my $subtypeq;
1425 if (ref $xcref) {
1426 ($q, $constq, $subtypeq) = @$xcref;
1427 } else {
1428 ($q, $constq, $subtypeq) = split /\./, $xcref, 3;
1429 }
1430 my $clsuri;
1431 my $cls;
1432 my $consturi;
1433 my $const;
1434 my $subtypeuri;
1435 my $subtype;
1436 if (defined $constq and not defined $subtypeq) {
1437 $clsuri = dis_typeforqnames_to_uri ($q,
1438 use_default_namespace => 1,
1439 %opt);
1440 $cls = $State->{Type}->{$clsuri};
1441 valid_err qq{Exception/warning class definition for }.
1442 qq{<$clsuri> is required}, node => $opt{node}
1443 unless defined $cls->{Name};
1444 my ($consttq, $constfq) = split /\|\|/, $constq, 2;
1445 if (defined $constfq) {
1446 if ($consttq !~ /:/) {
1447 valid_err qq<"$constq": Unprefixed exception code QName must >.
1448 q<not be followed by a "For" QName>,
1449 node => $opt{node};
1450 } else {
1451 $consturi = dis_typeforqnames_to_uri ($consttq.'::'.$constfq,
1452 use_default_namespace => 1,
1453 %opt);
1454 }
1455 } else {
1456 if ($consttq !~ /:/) {
1457 $consturi = $consttq;
1458 CONSTCLS: {
1459 for (values %{$cls->{ExpandedURI q<dis2pm:xConst>}}) {
1460 if (defined $_->{Name} and $_->{Name} eq $consturi) {
1461 $const = $_;
1462 last CONSTCLS;
1463 }
1464 }
1465 valid_err qq{Exception/warning code "$consturi" must be }.
1466 qq{defined in the exception/warning class }.
1467 qq{<$clsuri>}, node => $opt{node};
1468 }
1469 } else {
1470 $consturi = dis_typeforqnames_to_uri ($consttq.'::'.$constfq,
1471 use_default_namespace => 1,
1472 %opt);
1473 }
1474 }
1475 unless ($const) {
1476 CONSTCLS: {
1477 for (values %{$cls->{ExpandedURI q<dis2pm:xConst>}}) {
1478 if (defined $_->{Name} and $_->{URI} and
1479 $_->{URI} eq $consturi) {
1480 $const = $_;
1481 last CONSTCLS;
1482 }
1483 }
1484 valid_err qq{Exception/warning code <$consturi> must be }.
1485 qq{defined in the exception/warning class }.
1486 qq{<$clsuri>}, node => $opt{node};
1487 }
1488 }
1489 } else { ## By code/subtype QName
1490 $subtypeq = $q unless defined $constq;
1491 $subtypeuri = dis_typeforqnames_to_uri ($subtypeq,
1492 use_default_namespace => 1,
1493 %opt);
1494 $subtype = $State->{Type}->{$subtypeuri};
1495 valid_err qq{Exception/warning code/subtype <$subtypeuri> must }.
1496 qq{be defined}, node => $opt{node}
1497 unless defined $subtype->{Name} and
1498 defined $subtype->{ExpandedURI q<dis2pm:type>};
1499 if ($subtype->{ExpandedURI q<dis2pm:type>} eq
1500 ExpandedURI q<ManakaiDOM:ExceptionOrWarningSubType>) {
1501 $const = $subtype->{ExpandedURI q<dis2pm:parentResource>};
1502 $cls = $subtype->{ExpandedURI q<dis2pm:grandGrandParentResource>};
1503 } elsif ($subtype->{ExpandedURI q<dis2pm:type>} eq
1504 ExpandedURI q<ManakaiDOM:Const>) {
1505 $const = $subtype;
1506 $subtype = undef;
1507 $cls = $const->{ExpandedURI q<dis2pm:grandParentResource>};
1508 } else {
1509 valid_err qq{Type of <$subtypeuri> must be either }.
1510 q{"ManakaiDOM:Const" or }.
1511 q{"ManakaiDOM:ExceptionOrWarningSubType"},
1512 node => $opt{node};
1513 }
1514 }
1515 return ($cls, $const, $subtype);
1516 } # dispm_xcref_to_resources
1517
1518 =item $hash = dispm_collect_hash_prop_value ($resource, $propuri, %opt)
1519
1520 Get property values from a resource and its superclasses
1521 (C<dis:ISA>s - C<dis:Implement>s are not checked).
1522
1523 =cut
1524
1525 our $DispmCollectHashPropValueDepth = 0;
1526 sub dispm_collect_hash_prop_value ($$%) {
1527 my ($res, $propu, %opt) = @_;
1528 my %r;
1529 local $DispmCollectHashPropValueDepth = $DispmCollectHashPropValueDepth + 1;
1530 return {} if $DispmCollectHashPropValueDepth == 10;
1531 for (@{$res->{ISA}||[]}) {
1532 %r = (%{dispm_collect_hash_prop_value ($State->{Type}->{$_}, $propu, %opt)},
1533 %r);
1534 }
1535 %r = (%r, %{$res->{$propu}||{}});
1536 \%r;
1537 } # dispm_collect_hash_prop_value
1538
1539 =back
1540
1541 =cut
1542
1543 ## Outputed module and "For"
1544 my $mf = dis_get_module_uri (module_name => $Opt{module_name},
1545 module_uri => $Opt{module_uri},
1546 For => $Opt{For});
1547 $State->{DefaultFor} = $mf->{For};
1548 $State->{module} = $mf->{module};
1549 our $result = '';
1550
1551 valid_err
1552 (qq{Perl module <$State->{module}> not defined for <$State->{DefaultFor}>},
1553 node => $State->{Module}->{$State->{module}}->{src})
1554 unless $State->{Module}->{$State->{module}}
1555 ->{ExpandedURI q<dis2pm:packageName>};
1556
1557 $State->{ExpandedURI q<dis2pm:currentPackage>} = 'main';
1558 my $header = "#!/usr/bin/perl \n";
1559 $header .= perl_comment q<This file is automatically generated from> . "\n" .
1560 q<"> . $Opt{file_name} . q<" at > .
1561 rfc3339_date (time) . qq<.\n> .
1562 q<Don't edit by hand!>;
1563 $header .= perl_comment qq{Module <$State->{module}>};
1564 $header .= perl_comment qq{For <$State->{DefaultFor}>};
1565 $header .= perl_statement q<use strict>;
1566 $header .= perl_change_package
1567 (full_name => $State->{Module}->{$State->{module}}
1568 ->{ExpandedURI q<dis2pm:packageName>});
1569 $header .= perl_statement
1570 perl_assign
1571 perl_var (type => '$', local_name => 'VERSION',
1572 scope => 'our')
1573 => perl_literal version_date time
1574 if $Opt{outputModuleVersion};
1575
1576 ## -- Classes
1577 my %opt;
1578 for my $pack (values %{$State->{Module}->{$State->{module}}
1579 ->{ExpandedURI q<dis2pm:package>}||{}}) {
1580 next unless defined $pack->{Name};
1581 if ({
1582 ExpandedURI q<ManakaiDOM:Class> => 1,
1583 ExpandedURI q<ManakaiDOM:IF> => 1,
1584 ExpandedURI q<ManakaiDOM:ExceptionClass> => 1,
1585 ExpandedURI q<DOMMain:ErrorClass> => 1,
1586 ExpandedURI q<ManakaiDOM:ExceptionIF> => 1,
1587 ExpandedURI q<ManakaiDOM:WarningClass> => 1,
1588 }->{$pack->{ExpandedURI q<dis2pm:type>}}) {
1589 ## Package name and version
1590 $result .= perl_change_package
1591 (full_name => $pack->{ExpandedURI q<dis2pm:packageName>});
1592 $result .= perl_statement
1593 perl_assign
1594 perl_var (type => '$', local_name => 'VERSION',
1595 scope => 'our')
1596 => perl_literal version_date time;
1597 ## Inheritance
1598 ## TODO: IF "isa" should be expanded
1599 my $isa = $pack->{ExpandedURI q<dis2pm:AppISA>} || [];
1600 for (@$isa) {
1601 $State->{Module}->{$State->{module}}
1602 ->{ExpandedURI q<dis2pm:requiredModule>}->{$_} ||= 1;
1603 }
1604 $State->{ExpandedURI q<dis2pm:xifReferred>}
1605 ->{$pack->{ExpandedURI q<dis2pm:packageName>}} = -1;
1606 for my $uri (@{$pack->{ISA}||[]},
1607 @{$pack->{Implement}||[]}) {
1608 my $ipack = $State->{Type}->{$uri};
1609 if (defined $ipack->{ExpandedURI q<dis2pm:packageName>} and
1610 $ipack->{ExpandedURI q<dis2pm:packageName>}
1611 ne $pack->{ExpandedURI q<dis2pm:packageName>}) {
1612 push @$isa, $ipack->{ExpandedURI q<dis2pm:packageName>};
1613 if ($ipack->{ExpandedURI q<dis2pm:type>} eq
1614 ExpandedURI q<ManakaiDOM:ExceptionIF>) {
1615 $State->{ExpandedURI q<dis2pm:xifReferred>}
1616 ->{$ipack->{ExpandedURI q<dis2pm:packageName>}} ||= 1;
1617 }
1618 } else {
1619 impl_msg ("Inheriting package name for <$uri> not defined",
1620 node => $pack->{src}) if $Opt{verbose};
1621 }
1622 }
1623 $isa = array_uniq $isa;
1624 $result .= perl_inherit $isa;
1625 $State->{ExpandedURI q<dis2pm:referredPackage>}->{$_} ||= $pack->{src} || 1
1626 for @$isa;
1627
1628 ## Role
1629 my $role = dispm_collect_hash_prop_value
1630 ($pack, ExpandedURI q<d:Role>, %opt);
1631 my $feature;
1632 for (values %$role) {
1633 my $roleres = $State->{Type}->{$_->{Role}};
1634 my $compatres;
1635 $compatres = $State->{Type}->{$_->{compat}} if defined $_->{compat};
1636 valid_err qq{Perl package name for interface <$_->{Role}> must be defined},
1637 node => $roleres->{src}
1638 unless defined $roleres->{ExpandedURI q<dis2pm:packageName>};
1639 valid_err qq{Perl package name for class <$_->{compat}> must be defined},
1640 node => $compatres->{src}
1641 if $compatres and
1642 not defined $compatres->{ExpandedURI q<dis2pm:packageName>};
1643 if ({
1644 dis_typeforuris_to_uri
1645 (ExpandedURI q<DOMCore:DOMImplementation>,
1646 ExpandedURI q<ManakaiDOM:ManakaiDOM>, %opt) => 1,
1647
1648 dis_typeforuris_to_uri
1649 (ExpandedURI q<DOMCore:ManakaiDOMNode>,
1650 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt) => 1,
1651 dis_typeforuris_to_uri
1652 (ExpandedURI q<DOMCore:ManakaiDOMAttr>,
1653 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt) => 1,
1654 dis_typeforuris_to_uri
1655 (ExpandedURI q<DOMXML:ManakaiDOMCDATASection>,
1656 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt) => 1,
1657 dis_typeforuris_to_uri
1658 (ExpandedURI q<DOMCore:ManakaiDOMComment>,
1659 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt) => 1,
1660 dis_typeforuris_to_uri
1661 (ExpandedURI q<DOMCore:ManakaiDOMDocument>,
1662 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt) => 1,
1663 dis_typeforuris_to_uri
1664 (ExpandedURI q<DOMCore:ManakaiDOMDocumentFragment>,
1665 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt) => 1,
1666 dis_typeforuris_to_uri
1667 (ExpandedURI q<DOMXML:ManakaiDOMDocumentType>,
1668 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt) => 1,
1669 dis_typeforuris_to_uri
1670 (ExpandedURI q<DOMCore:ManakaiDOMElement>,
1671 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt) => 1,
1672 dis_typeforuris_to_uri
1673 (ExpandedURI q<DOMXML:ManakaiDOMEntity>,
1674 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt) => 1,
1675 dis_typeforuris_to_uri
1676 (ExpandedURI q<DOMXML:ManakaiDOMEntityReference>,
1677 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt) => 1,
1678 dis_typeforuris_to_uri
1679 (ExpandedURI q<DOMXML:ManakaiDOMNotation>,
1680 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt) => 1,
1681 dis_typeforuris_to_uri
1682 (ExpandedURI q<DOMXML:ManakaiDOMProcessingInstruction>,
1683 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt) => 1,
1684 dis_typeforuris_to_uri
1685 (ExpandedURI q<DOMCore:ManakaiDOMText>,
1686 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt) => 1,
1687
1688 (my $ev = dis_typeforuris_to_uri
1689 (ExpandedURI q<DOMEvents:ManakaiDOMEvent>,
1690 ExpandedURI q<ManakaiDOM:ManakaiDOMLatest>, %opt)) => 1,
1691 }->{$_->{Role}}) {
1692 unless ($feature) {
1693 $feature = {};
1694 for (keys %{dispm_collect_hash_prop_value
1695 ($pack, ExpandedURI q<DOMMain:implementFeature>, %opt)}) {
1696 my @f = ([$State->{Type}->{$_}, [], 1]);
1697 while (defined (my $f = shift @f)) {
1698 my $version = $f->[0]->{ExpandedURI q<d:Version>};
1699 $version = '' unless defined $version;
1700 $f->[0]->{ExpandedURI q<dis2pm:notImplemented>}
1701 = length $version
1702 ? $f->[0]->{ExpandedURI q<dis2pm:notImplemented>}
1703 ? 1 : 0
1704 : 0;
1705 for my $fname (keys %{$f->[0]
1706 ->{ExpandedURI q<dis2pm:featureName>}}) {
1707 $feature->{$fname}->{$version}
1708 = 1
1709 #= $f->[0]->{ExpandedURI q<dis2pm:notImplemented>} ? 0 : 1
1710 if $f->[2];
1711 unless ($feature->{$fname}->{$version}) {
1712 $feature->{$_->[0]}->{$_->[1]} = 0 for @{$f->[1]};
1713 }
1714 }
1715 push @f,
1716 map {[$State->{Type}->{$_},
1717 ($f->[2]
1718 ? [@{$f->[1]},
1719 map {[$_, $version]}
1720 keys %{$f->[0]
1721 ->{ExpandedURI q<dis2pm:featureName>}}]
1722 : $f->[1]),
1723 $f->[2]]}
1724 @{$f->[0]->{ISA}||[]};
1725 push @f,
1726 map {[$State->{Type}->{$_},
1727 ($f->[2]
1728 ? [@{$f->[1]},
1729 map {[$_, $version]}
1730 keys %{$f->[0]
1731 ->{ExpandedURI q<dis2pm:featureName>}}]
1732 : $f->[1]), 0]}
1733 keys %{$f->[0]->{ExpandedURI q<dis2pm:requireFeature>}||{}}
1734 if not $f->[0]->{ExpandedURI q<dis2pm:notImplemented>};
1735 }
1736 }
1737 }
1738 my %f = (
1739 packageName => $pack->{ExpandedURI q<dis2pm:packageName>},
1740 feature => $feature,
1741 );
1742
1743 if ($_->{Role} eq $ev) {
1744 my @p = ($pack);
1745 my %pu;
1746 while (defined (my $p = shift @p)) {
1747 if ($p->{ExpandedURI q<dis2pm:type>} eq
1748 ExpandedURI q<ManakaiDOM:IF>) {
1749 $f{eventType}->{$p->{Name}} = 1;
1750 }
1751 $f{eventType}->{$_} = 1
1752 for keys %{$p->{ExpandedURI q<DOMEvents:createEventType>}||{}};
1753 $pu{defined $p->{URI} ? $p->{URI} : ''} = 1;
1754 push @p, grep {!$pu{defined $_->{URI} ? $_->{URI} : ''}}
1755 map {$State->{Type}->{$_}}
1756 (@{$p->{ISA}||[]}, @{$p->{Implement}||[]});
1757 }
1758 }
1759
1760 $result .= perl_statement
1761 (($compatres
1762 ? perl_var (type => '$',
1763 package => $compatres
1764 ->{ExpandedURI q<dis2pm:packageName>},
1765 local_name => 'Class').
1766 '{'.(perl_literal ($f{packageName})).'} = '
1767 : '').
1768 perl_var (type => '$',
1769 package => $roleres
1770 ->{ExpandedURI q<dis2pm:packageName>},
1771 local_name => 'Class').
1772 '{'.(perl_literal ($f{packageName})).'} = '.
1773 perl_literal \%f);
1774 } elsif ({
1775 dis_typeforuris_to_uri
1776 (ExpandedURI q<DOMCore:DOMImplementationSource>,
1777 ExpandedURI q<ManakaiDOM:ManakaiDOM>, %opt) => 1,
1778 }->{$_->{Role}}) {
1779 $result .= perl_statement
1780 'push @org::w3c::dom::DOMImplementationSourceList, '.
1781 perl_literal ($pack->{ExpandedURI q<dis2pm:packageName>});
1782 } else {
1783 valid_err qq{Role <$_->{Role}> not supported}, $_->{node};
1784 }
1785 }
1786
1787 ## Members
1788 if ({
1789 ExpandedURI q<ManakaiDOM:Class> => 1,
1790 ExpandedURI q<ManakaiDOM:ExceptionClass> => 1,
1791 ExpandedURI q<DOMMain:ErrorClass> => 1,
1792 ExpandedURI q<ManakaiDOM:WarningClass> => 1,
1793 }->{$pack->{ExpandedURI q<dis2pm:type>}}) {
1794 local $State->{ExpandedURI q<dis2pm:thisClass>} = $pack;
1795 local $opt{ExpandedURI q<MDOMX:class>}
1796 = $pack->{ExpandedURI q<dis2pm:packageName>};
1797
1798 ## -- Variables
1799 for my $var (values %{$pack->{ExpandedURI q<dis2pm:variable>}}) {
1800 next unless defined $var->{Name};
1801 my $default = dispm_get_value
1802 (%opt, resource => $var,
1803 ExpandedURI q<dis2pm:ValueKeyName>
1804 => ExpandedURI q<d:DefaultValue>,
1805 ExpandedURI q<dis2pm:useDefaultValue> => 1,
1806 ExpandedURI q<dis2pm:valueType>
1807 => $var->{ExpandedURI q<d:actualType>});
1808
1809 my $v = perl_var
1810 (type => $var->{ExpandedURI q<dis2pm:variableType>},
1811 scope => (($var->{ExpandedURI q<dis2pm:variableName>} =~ /::/ or
1812 (defined $default and
1813 index ($default,
1814 $var->{ExpandedURI q<dis2pm:variableName>})
1815 > -1)) ? undef : 'our'),
1816 local_name => $var->{ExpandedURI q<dis2pm:variableName>});
1817 if (defined $default and length $default) {
1818 if (not $var->{ExpandedURI q<dis2pm:variableName>} =~ /::/ and
1819 index ($default, $var->{ExpandedURI q<dis2pm:variableName>})
1820 > -1) {
1821 $result .= perl_statement 'our '.$v;
1822 }
1823 $result .= perl_statement
1824 perl_assign $v => $default;
1825 } else {
1826 $result .= perl_statement $v;
1827 }
1828 }
1829
1830 ## -- Subroutines
1831 for my $method (values %{$pack->{ExpandedURI q<dis2pm:method>}}) {
1832 next unless defined $method->{Name};
1833 if ($method->{ExpandedURI q<dis2pm:type>} eq
1834 ExpandedURI q<DISLang:Method>) {
1835 local $opt{ExpandedURI q<MDOMX:method>}
1836 = $method->{ExpandedURI q<dis2pm:methodName+>};
1837 local $opt{ExpandedURI q<dis2pm:currentMethodResource>} = $method;
1838 my $proto = '$';
1839 my @param = ('$self');
1840 my $param_norm = '';
1841 my $param_opt = 0;
1842 my $named_param = 0;
1843 my %param_replace;
1844 my $for = [keys %{$method->{For}}]->[0];
1845 local $opt{'For+'} = [keys %{$method->{'For+'}||{}}];
1846 for my $param (@{$method->{ExpandedURI q<dis2pm:param>}||[]}) {
1847 my $atype = $param->{ExpandedURI q<d:actualType>};
1848 if ($param->{ExpandedURI q<dis2pm:nullable>}) {
1849 $proto .= ';' unless $param_opt;
1850 $param_opt++;
1851 }
1852 my $is_np = dis_get_attr_node
1853 (%opt, parent => $param->{src},
1854 name => {uri =>
1855 ExpandedURI q<DISPerl:isNamedParameter>});
1856 if ($named_param) {
1857 if (not $is_np or not $is_np->value) {
1858 valid_err (q<Named parameter is expected>,
1859 node => $param->{src});
1860 }
1861 } else {
1862 if ($is_np and $is_np->value) {
1863 $named_param = 1;
1864 $proto .= '%';
1865 push @param, '%opt';
1866 }
1867 }
1868 my $param_var;
1869 if (dis_uri_ctype_match (ExpandedURI q<Perl:Array>, $atype, %opt)) {
1870 if ($named_param) {
1871 valid_err (qq<Type "$atype" is unable to be used as >.
1872 q<a named parameter>, node => $param->{src});
1873 }
1874 $proto .= '@';
1875 push @param,
1876 $param_var = '@'.$param->{ExpandedURI q<dis2pm:paramName>};
1877 } elsif (dis_uri_ctype_match (ExpandedURI q<Perl:Hash>, $atype,
1878 %opt)) {
1879 if ($named_param) {
1880 valid_err (qq<Type "$atype" is unable to be used as >.
1881 q<a named parameter>, node => $param->{src});
1882 }
1883 $proto .= '%';
1884 push @param,
1885 $param_var = '%'.$param->{ExpandedURI q<dis2pm:paramName>};
1886 } else {
1887 unless ($named_param) {
1888 $proto .= '$';
1889 push @param,
1890 $param_var = '$'.$param->{ExpandedURI q<dis2pm:paramName>};
1891 } else {
1892 $param_var = '$opt{'
1893 . dis_camelCase_to_underscore_name
1894 ($param->{ExpandedURI q<dis2pm:paramName>})
1895 . '}';
1896 }
1897 $param_replace{'$'.$param->{ExpandedURI q<dis2pm:paramName>}}
1898 = $param_var;
1899 }
1900 my $nin = dis_get_attr_node
1901 (%opt,
1902 parent =>
1903 $param->{ExpandedURI q<dis2pm:actualTypeNode>},
1904 name => {uri =>
1905 ExpandedURI q<ManakaiDOM:noInputNormalize>},
1906 );
1907 if ($nin and $nin->value) {
1908 ## No input normalizing
1909 } else {
1910 my $nm = dispm_get_code
1911 (%opt, resource => $State->{Type}->{$atype},
1912 ExpandedURI q<dis2pm:DefKeyName>
1913 => ExpandedURI q<ManakaiDOM:inputNormalizer>,
1914 For => $for,
1915 ExpandedURI q<dis2pm:getCodeNoTypeCheck> => 1,
1916 ExpandedURI q<dis2pm:selParent>
1917 => $param->{ExpandedURI q<dis2pm:actualTypeNode>});
1918 if (defined $nm) {
1919 $nm =~ s/\$INPUT\b/$param_var/g;
1920 ## NOTE: "Perl:Array" or "Perl:Hash" is not supported.
1921 $param_norm .= $nm;
1922 }
1923 }
1924 }
1925 my $code = dispm_get_code
1926 (%opt,
1927 resource => $method->{ExpandedURI q<dis2pm:return>},
1928 For => $for,
1929 ExpandedURI q<dis2pm:DefKeyName>
1930 => ExpandedURI q<d:Def>);
1931 if (defined $code) {
1932 my $my = perl_statement ('my ('.join (", ", @param).
1933 ') = @_');
1934 my $return = defined $method->{ExpandedURI q<dis2pm:return>}->{Name}
1935 ? $method->{ExpandedURI q<dis2pm:return>} : undef;
1936 for (keys %param_replace) {
1937 $code =~ s/\Q$_\E\b/$param_replace{$_}/g;
1938 }
1939 if ($return->{ExpandedURI q<d:actualType>} ? 1 : 0) {
1940 my $default = dispm_get_value
1941 (%opt, resource => $return,
1942 ExpandedURI q<dis2pm:ValueKeyName>
1943 => ExpandedURI q<d:DefaultValue>,
1944 ExpandedURI q<dis2pm:useDefaultValue> => 1,
1945 ExpandedURI q<dis2pm:valueType>
1946 => $return->{ExpandedURI q<d:actualType>});
1947 $code = $my . $param_norm .
1948 perl_statement
1949 (defined $default ? 'my $r = '.$default : 'my $r').
1950 $code . "\n" .
1951 perl_statement ('$r');
1952 } else {
1953 $code = $my . $code;
1954 }
1955 } else { ## Code not defined
1956 $code = perl_statement 'my $self = shift;';
1957 $code .= perl_statement
1958 dispm_perl_throws
1959 class => ExpandedURI q<DX:CoreException>,
1960 class_for => ExpandedURI q<ManakaiDOM:Perl>,
1961 type => 'NOT_SUPPORTED_ERR',
1962 subtype =>
1963 ExpandedURI q<MDOMX:MDOM_IMPL_METHOD_NOT_IMPLEMENTED>,
1964 xparam => {
1965 ExpandedURI q<MDOMX:class>
1966 => $pack->{ExpandedURI q<dis2pm:packageName>},
1967 ExpandedURI q<MDOMX:method>
1968 => $method->{ExpandedURI q<dis2pm:methodName+>},
1969 };
1970 }
1971 if (length $method->{ExpandedURI q<dis2pm:methodName>}) {
1972 $result .= perl_sub
1973 (name => $method->{ExpandedURI q<dis2pm:methodName>},
1974 code => $code, prototype => $proto);
1975 } else {
1976 $method->{ExpandedURI q<dis2pm:methodCodeRef>}
1977 = perl_sub (name => '', code => $code, prototype => $proto);
1978 }
1979 } elsif ($method->{ExpandedURI q<dis2pm:type>} eq
1980 ExpandedURI q<DISLang:Attribute>) {
1981 local $opt{ExpandedURI q<MDOMX:attr>}
1982 = $method->{ExpandedURI q<dis2pm:methodName+>};
1983 my $getter = $method->{ExpandedURI q<dis2pm:getter>};
1984 valid_err qq{Getter for attribute "$method->{Name}" must be }.
1985 q{defined}, node => $method->{src} unless $getter;
1986 my $setter = defined $method->{ExpandedURI q<dis2pm:setter>}->{Name}
1987 ? $method->{ExpandedURI q<dis2pm:setter>} : undef;
1988 my $for = [keys %{$method->{For}}]->[0];
1989 local $opt{'For+'} = [keys %{$method->{'For+'}||{}}];
1990 local $opt{ExpandedURI q<MDOMX:on>} = 'get';
1991 my $get_code = dispm_get_code (%opt, resource => $getter, For => $for,
1992 ExpandedURI q<dis2pm:DefKeyName>
1993 => ExpandedURI q<d:Def>);
1994 if (defined $get_code) {
1995 my $default = dispm_get_value
1996 (%opt, resource => $getter,
1997 ExpandedURI q<dis2pm:ValueKeyName>
1998 => ExpandedURI q<d:DefaultValue>,
1999 ExpandedURI q<dis2pm:useDefaultValue> => 1,
2000 ExpandedURI q<dis2pm:valueType>
2001 => $getter->{ExpandedURI q<d:actualType>});
2002 $get_code = perl_statement
2003 (defined $default ? 'my $r = '.$default : 'my $r').
2004 $get_code. "\n" .
2005 perl_statement ('$r');
2006 } else { ## Get code not defined
2007 $get_code = perl_statement
2008 dispm_perl_throws
2009 class => ExpandedURI q<DX:CoreException>,
2010 class_for => ExpandedURI q<ManakaiDOM:Perl>,
2011 type => 'NOT_SUPPORTED_ERR',
2012 subtype =>
2013 ExpandedURI q<MDOMX:MDOM_IMPL_ATTR_NOT_IMPLEMENTED>,
2014 xparam => {
2015 ExpandedURI q<MDOMX:class>
2016 => $pack->{ExpandedURI q<dis2pm:packageName>},
2017 ExpandedURI q<MDOMX:attr>
2018 => $method->{ExpandedURI q<dis2pm:methodName+>},
2019 ExpandedURI q<MDOMX:on> => 'get',
2020 };
2021 }
2022 if ($setter) {
2023 local $opt{ExpandedURI q<MDOMX:on>} = 'set';
2024 my $set_code = dispm_get_code
2025 (%opt, resource => $setter, For => $for,
2026 ExpandedURI q<dis2pm:DefKeyName>
2027 => ExpandedURI q<d:Def>);
2028 if (defined $set_code) {
2029 my $nm = dispm_get_code
2030 (%opt, resource => $State->{Type}
2031 ->{$setter->{ExpandedURI q<d:actualType>}},
2032 ExpandedURI q<dis2pm:DefKeyName>
2033 => ExpandedURI q<ManakaiDOM:inputNormalizer>,
2034 For => $for,
2035 ExpandedURI q<dis2pm:getCodeNoTypeCheck> => 1);
2036 if (defined $nm) {
2037 $nm =~ s/\$INPUT\b/\$given/g;
2038 } else {
2039 $nm = '';
2040 }
2041 $set_code = $nm .
2042 $set_code. "\n";
2043 } else { ## Set code not defined
2044 $set_code = perl_statement
2045 dispm_perl_throws
2046 class => ExpandedURI q<DX:CoreException>,
2047 class_for => ExpandedURI q<ManakaiDOM:Perl>,
2048 type => 'NOT_SUPPORTED_ERR',
2049 subtype =>
2050 ExpandedURI q<MDOMX:MDOM_IMPL_ATTR_NOT_IMPLEMENTED>,
2051 xparam => {
2052 ExpandedURI q<MDOMX:class>
2053 => $pack->{ExpandedURI q<dis2pm:packageName>},
2054 ExpandedURI q<MDOMX:attr>
2055 => $method->{ExpandedURI q<dis2pm:methodName+>},
2056 ExpandedURI q<MDOMX:on> => 'set',
2057 };
2058 }
2059 $get_code = perl_if '@_ == 2',
2060 perl_statement ('my ($self, $given) = @_').
2061 $set_code,
2062 perl_statement ('my ($self) = @_').
2063 $get_code;
2064 } else {
2065 $get_code = perl_statement ('my ($self) = @_').
2066 $get_code;
2067 }
2068 if (length $method->{ExpandedURI q<dis2pm:methodName>}) {
2069 $result .= perl_sub
2070 (name => $method->{ExpandedURI q<dis2pm:methodName>},
2071 prototype => $setter ? '$;$' : '$',
2072 code => $get_code);
2073 } else {
2074 $method->{ExpandedURI q<dis2pm:methodCodeRef>}
2075 = perl_sub (name => '', code => $get_code,
2076 prototype => $setter ? '$;$' : '$');
2077 }
2078 }
2079 } # package method
2080
2081 ## -- Constants
2082 for my $cg (values %{$pack->{ExpandedURI q<dis2pm:constGroup>}}) {
2083 next unless defined $cg->{Name};
2084 $result .= dispm_const_group (resource => $cg);
2085 } # package const group
2086 for my $cv (values %{$pack->{ExpandedURI q<dis2pm:const>}}) {
2087 next unless defined $cv->{Name};
2088 $result .= dispm_const_value_sub (resource => $cv);
2089 } # package const value
2090
2091 ## -- Error codes
2092 if ({
2093 ExpandedURI q<ManakaiDOM:ExceptionClass> => 1,
2094 ExpandedURI q<DOMMain:ErrorClass> => 1,
2095 ExpandedURI q<ManakaiDOM:WarningClass> => 1,
2096 }->{$pack->{ExpandedURI q<dis2pm:type>}}) {
2097 $result .= perl_sub
2098 name => '___error_def',
2099 prototype => '',
2100 code => perl_list {
2101 map {
2102 $_->{Name} => {
2103 ExpandedURI q<DOMCore:code>
2104 => perl_code_literal
2105 dispm_const_value (%opt, resource => $_),
2106 description => dispm_muf_description
2107 (%opt, resource => $_),
2108 ($_->{ExpandedURI q<DOMCore:severity>}
2109 ? (ExpandedURI q<DOMCore:severity>
2110 => $_->{ExpandedURI q<DOMCore:severity>},
2111 ExpandedURI q<DOMCore:type>
2112 => $_->{ExpandedURI q<DOMCore:type>})
2113 : ()),
2114 ExpandedURI q<MDOMX:subtype> => {
2115 map {
2116 $_->{NameURI} => {
2117 description => dispm_muf_description
2118 (%opt, resource => $_),
2119 ($_->{ExpandedURI q<DOMCore:severity>}
2120 ? (ExpandedURI q<DOMCore:severity>
2121 => $_->{ExpandedURI q<DOMCore:severity>},
2122 ExpandedURI q<DOMCore:type>
2123 => $_->{ExpandedURI q<DOMCore:type>})
2124 : ()),
2125 },
2126 } grep {defined $_->{Name}}
2127 values %{$_->{ExpandedURI q<dis2pm:xSubType>}||{}}
2128 },
2129 },
2130 } grep {defined $_->{Name}}
2131 values %{$pack->{ExpandedURI q<dis2pm:xConst>}||{}}
2132 };
2133 }
2134
2135 ## -- Operators
2136 my %ol;
2137 my %mtd;
2138 for (values %{$pack->{ExpandedURI q<dis2pm:overload>}||{}}) {
2139 next unless defined $_->{resource}->{Name};
2140 if ($_->{resource}->{ExpandedURI q<dis2pm:methodName+>} =~ /^\#/) {
2141 if ($_->{operator} =~ /^[A-Z]+$/) {
2142 my $code = $_->{resource}->{ExpandedURI q<dis2pm:methodCodeRef>};
2143 $code =~ s/\bsub /sub $_->{operator} /;
2144 $result .= $code;
2145 $mtd{$_->{operator}} = 1;
2146 } else {
2147 $ol{$_->{operator}} = perl_code_literal $_->{resource}
2148 ->{ExpandedURI q<dis2pm:methodCodeRef>};
2149 }
2150 } else {
2151 if ($_->{operator} =~ /^[A-Z]+$/) {
2152 $mtd{$_->{operator}} = 1;
2153 $result .= perl_statement
2154 perl_assign
2155 perl_var (type => '*',
2156 local_name => $_->{operator})
2157 => perl_var (type => '\&',
2158 local_name => $_->{resource}
2159 ->{ExpandedURI q<dis2pm:methodName>});
2160 } else {
2161 $ol{$_->{operator}}
2162 = $_->{resource}->{ExpandedURI q<dis2pm:methodName>};
2163 }
2164 }
2165 }
2166 if (keys %ol) {
2167 $ol{fallback} = 1;
2168 $ol{bool} ||= perl_code_literal 'sub () {1}';
2169 $result .= perl_statement 'use overload '.perl_list %ol;
2170 }
2171 my $op2perl = {
2172 ExpandedURI q<ManakaiDOM:MUErrorHandler> => {
2173 method_name => '___report_error',
2174 },
2175 ExpandedURI q<DISPerl:AsStringMethod> => {
2176 method_name => 'as_string',
2177 },
2178 ExpandedURI q<DISPerl:NewMethod> => {
2179 method_name => 'new',
2180 },
2181 ExpandedURI q<DISPerl:CloneMethod> => {
2182 method_name => 'clone',
2183 },
2184 };
2185 for (values %{$pack->{ExpandedURI q<d:Operator>}||{}}) {
2186 next unless defined $_->{resource}->{Name};
2187 if ($op2perl->{$_->{operator}}) {
2188 if ($_->{resource}->{ExpandedURI q<dis2pm:methodName+>} =~ /^\#/) {
2189 my $code = $_->{resource}->{ExpandedURI q<dis2pm:methodCodeRef>};
2190 $code =~ s/\bsub /sub $op2perl->{$_->{operator}}->{method_name} /;
2191 $result .= $code;
2192 } else {
2193 $result .= perl_statement
2194 perl_assign
2195 perl_var (type => '*',
2196 local_name => $op2perl->{$_->{operator}}
2197 ->{method_name})
2198 => perl_var (type => '\&',
2199 local_name => $_->{resource}
2200 ->{ExpandedURI q<dis2pm:methodName>});
2201 }
2202 if ($_->{operator} eq ExpandedURI q<DISPerl:AsStringMethod>) {
2203 $result .= perl_statement
2204 perl_assign
2205 perl_var (type => '*',
2206 local_name => 'stringify')
2207 => perl_var (type => '\&',
2208 local_name => $op2perl->{$_->{operator}}
2209 ->{method_name});
2210 }
2211 } else {
2212 valid_err qq{Operator <$_->{operator}> is not supported},
2213 node => $_->{resource}->{src};
2214 }
2215 }
2216
2217
2218 } # Class
2219 } # root object
2220 }
2221
2222
2223 ## -- Variables
2224 for my $var (values %{$State->{Module}->{$State->{module}}
2225 ->{ExpandedURI q<dis2pm:variable>}}) {
2226 next unless defined $var->{Name};
2227 my $default = dispm_get_value
2228 (%opt, resource => $var,
2229 ExpandedURI q<dis2pm:ValueKeyName>
2230 => ExpandedURI q<d:DefaultValue>,
2231 ExpandedURI q<dis2pm:useDefaultValue> => 1,
2232 ExpandedURI q<dis2pm:valueType>
2233 => $var->{ExpandedURI q<d:actualType>});
2234
2235 my $v = perl_var
2236 (type => $var->{ExpandedURI q<dis2pm:variableType>},
2237 scope => ($var->{ExpandedURI q<dis2pm:variableName>}
2238 =~ /::/ ? undef : 'our'),
2239 local_name => $var->{ExpandedURI q<dis2pm:variableName>});
2240 if (defined $default and length $default) {
2241 $result .= perl_statement
2242 perl_assign $v => $default;
2243 } else {
2244 $result .= perl_statement $v;
2245 }
2246
2247 if ($var->{ExpandedURI q<DISPerl:isExportOK>}) {
2248 $State->{ExpandedURI q<dis2pm:Package>}
2249 ->{$State->{Module}->{$State->{module}}
2250 ->{ExpandedURI q<dis2pm:packageName>}}
2251 ->{ExpandedURI q<dis2pm:variable>}->{$v} = 1;
2252 ## NOTE: Variable name uniqueness is assured in dis.pl.
2253 }
2254 }
2255
2256 ## Constant exportion
2257 {
2258 my @xok;
2259 my $xr = '';
2260 my $cg = $State->{ExpandedURI q<dis2pm:Package>}
2261 ->{$State->{Module}->{$State->{module}}
2262 ->{ExpandedURI q<dis2pm:packageName>}}
2263 ->{ExpandedURI q<dis2pm:constGroup>};
2264 my %etag;
2265 for (keys %$cg) {
2266 $etag{$_} = $cg->{$_}->{member};
2267 }
2268 $xr .= perl_statement
2269 perl_assign
2270 perl_var (type => '%', local_name => 'EXPORT_TAG',
2271 scope => 'our')
2272 => '('.(perl_list %etag).')'
2273 if keys %etag;
2274
2275 my $c = $State->{ExpandedURI q<dis2pm:Package>}
2276 ->{$State->{Module}->{$State->{module}}
2277 ->{ExpandedURI q<dis2pm:packageName>}}
2278 ->{ExpandedURI q<dis2pm:const>};
2279 if (keys %$c) {
2280 push @xok, keys %$c;
2281 $xr .= join '', map {perl_statement "sub $_ ()"} keys %$c;
2282 my $al = perl_literal {map {$_ =>
2283 $c->{$_}->{package}.'::'.$_} keys %$c};
2284 my $AL = '$al';
2285 my $ALD = '$AUTOLOAD';
2286 my $XL = '$Exporter::ExportLevel';
2287 my $SELF = '$self';
2288 my $ARGS = '@_';
2289 my $IT = '$_';
2290 my $REF = '\\';
2291 my $NONAME = '\W';
2292 $xr .= qq{
2293 sub AUTOLOAD {
2294 my $AL = our $ALD;
2295 $AL =~ s/.+:://;
2296 if ($al -> {$AL}) {
2297 no strict 'refs';
2298 *{$ALD} = $REF &{$al -> {$AL}};
2299 goto &{$ALD};
2300 } else {
2301 require Carp;
2302 Carp::croak (qq<Can't locate method "$ALD">);
2303 }
2304 }
2305 sub import {
2306 my $SELF = shift;
2307 if ($ARGS) {
2308 local $XL = $XL + 1;
2309 $SELF->SUPER::import ($ARGS);
2310 for (grep {not /$NONAME/} $ARGS) {
2311 eval qq{$IT};
2312 }
2313 }
2314 }
2315 };
2316 }
2317
2318 for (keys %{$State->{ExpandedURI q<dis2pm:Package>}
2319 ->{$State->{Module}->{$State->{module}}
2320 ->{ExpandedURI q<dis2pm:packageName>}}
2321 ->{ExpandedURI q<dis2pm:variable>}}) {
2322 push @xok, $_;
2323 }
2324
2325 if (@xok) {
2326 $xr .= perl_statement
2327 perl_assign
2328 perl_var (type => '@', local_name => 'EXPORT_OK',
2329 scope => 'our')
2330 => '('.(perl_list @xok).')';
2331 }
2332
2333 if ($xr) {
2334 $result .= perl_change_package (full_name => $State->{Module}
2335 ->{$State->{module}}
2336 ->{ExpandedURI q<dis2pm:packageName>});
2337 $result .= $xr;
2338 $result .= perl_statement 'use Exporter';
2339 $result .= perl_statement 'push our @ISA, "Exporter"';
2340 }
2341 }
2342
2343 ## Required modules
2344 $result .= dispm_package_declarations;
2345 my $begin = '';
2346 for (keys %{$State->{Module}->{$State->{module}}
2347 ->{ExpandedURI q<dis2pm:requiredModule>}||{}}) {
2348 next if $_ eq $State->{Module}->{$State->{module}}
2349 ->{ExpandedURI q<dis2pm:packageName>};
2350 $begin .= perl_statement ('require ' . $_);
2351 $State->{ExpandedURI q<dis2pm:referredPackage>}->{$_} = -1;
2352 }
2353 $result = $begin . $result if $begin;
2354
2355 ## Exception interfaces
2356 for my $p (keys %{$State->{ExpandedURI q<dis2pm:xifReferred>}||{}}) {
2357 my $v = $State->{ExpandedURI q<dis2pm:xifReferred>}->{$p};
2358 if (ref $v or $v > 0) {
2359 $result .= perl_inherit ['Message::Util::Error'], $p;
2360 $State->{ExpandedURI q<dis2pm:referredPackage>}->{$p} = -1;
2361 }
2362 }
2363
2364 my @ref;
2365 for (keys %{$State->{ExpandedURI q<dis2pm:referredPackage>}||{}}) {
2366 my $v = $State->{ExpandedURI q<dis2pm:referredPackage>}->{$_};
2367 if (ref $v or $v > 0) {
2368 push @ref, $_;
2369 }
2370 }
2371 $result .= "for (" . join (", ", map {'$'.$_.'::'} @ref) . ") {}"
2372 if @ref;
2373
2374 $result = $header . $result . perl_statement 1;
2375
2376 output_result $result;
2377
2378 =head1 BUGS
2379
2380 Dynamic change for namespace binding, current "For", ... is poorly
2381 supported - it a code or element refers another code or element
2382 in the same or different source file, then their own bindings, not the former
2383 code or element's, should be used for resolution. The current
2384 implementation does not do so perfectly. So authors of
2385 "dis" files are encouraged not to bind the same namespace prefix
2386 to different namespace URIs and to prefer prefixed QName.
2387
2388 =head1 SEE ALSO
2389
2390 L<lib/manakai/dis.pl> - "dis" common utility.
2391
2392 L<lib/manakai/DISCore.dis> - The definition for the "dis" format.
2393
2394 L<lib/manakai/DISPerl.dis> - The definition for the "dis" Perl-specific
2395 vocabulary.
2396
2397 =head1 LICENSE
2398
2399 Copyright 2004-2005 Wakaba <w@suika.fam.cx>. All rights reserved.
2400
2401 This program is free software; you can redistribute it and/or
2402 modify it under the same terms as Perl itself.
2403
2404 =cut
2405
2406 1; # $Date: 2005/05/01 12:44:05 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24