#!/usr/bin/perl -w use strict; use Message::Util::QName::Filter { d => q, dis2pm => q, DISCore => q, DISLang => q, DISPerl => q, disPerl => q, DOMCore => q, DOMMain => q, lang => q, Perl => q, license => q, ManakaiDOM => q, MDOMX => q, owl => q, rdf => q, rdfs => q, TreeCore => q<>, }; use Getopt::Long; use Pod::Usage; use Storable; my %Opt; GetOptions ( 'for=s' => \$Opt{For}, 'help' => \$Opt{help}, 'module-name=s' => \$Opt{module_name}, 'module-uri=s' => \$Opt{module_uri}, 'verbose!' => $Opt{verbose}, ) or pod2usage (2); pod2usage ({-exitval => 0, -verbose => 1}) if $Opt{help}; $Opt{file_name} = shift; pod2usage ({-exitval => 2, -verbose => 0}) unless $Opt{file_name}; pod2usage (2) if not $Opt{module_uri} and not $Opt{module_name}; BEGIN { require 'manakai/genlib.pl'; require 'manakai/dis.pl'; } our $State = retrieve ($Opt{file_name}) or die "$0: $Opt{file_name}: Cannot load"; our $result = ''; eval q{ sub impl_msg ($;%) { warn shift () . "\n"; } } unless $Opt{verbose}; sub perl_change_package (%) { my %opt = @_; my $fn = $opt{full_name}; impl_err (qq<$fn: Bad package name>) unless $fn; unless ($fn eq $State->{ExpandedURI q}) { $State->{ExpandedURI q} = $fn; return perl_statement qq; } else { return ''; } } # perl_change_package =item $code = dispm_perl_throws (%opt) Generates a code to throw an exception. =cut sub dispm_perl_throws (%) { my %opt = @_; my $x = $opt{class_resource} || $State->{Type}->{$opt{class}}; my $r = 'report '; unless (defined $x->{Name}) { $opt{class} = dis_typeforuris_to_uri ($opt{class}, $opt{class_for}, %opt); $x = $State->{Type}->{$opt{class}}; } valid_err (qq is not defined>, node => $opt{node}) unless defined $x->{Name}; if ($x->{ExpandedURI q} and { ExpandedURI q => 1, ExpandedURI q => 1, }->{$x->{ExpandedURI q}}) { $opt{type} = $opt{type_resource}->{Name} unless defined $opt{type}; valid_err qq{Exception code must be specified}, node => $opt{type_resource}->{src} || $opt{node} unless defined $opt{type}; $opt{subtype} = $opt{subtype_resource}->{NameURI} || $opt{subtype_resource}->{URI} unless defined $opt{subtype}; $opt{xparam}->{ExpandedURI q} = $opt{subtype} if defined $opt{subtype}; $r .= $x->{ExpandedURI q} . ' ' . perl_list -type => $opt{type}, -object => perl_code_literal ('$self'), %{$opt{xparam} || {}}; } else { no warnings 'uninitialized'; valid_err (qq{Resource <$opt{class}> [<$x->{ExpandedURI q}>] }. q. q, node => $opt{node}); } return $r; } # dispm_perl_throw my $RegQNameChar = qr/[^\s<>"'\\\[\]\{\}]/; { use re 'eval'; my $RegBlockContent; $RegBlockContent = qr/(?>[^{}\\]*)(?>(?>[^{}\\]+|\\.|\{(??{$RegBlockContent})\})*)/s; ## Defined by genlib.pl but overridden. sub perl_code ($;%) { my ($s, %opt) = @_; valid_err q, node => $opt{node} unless defined $s; local $State->{Namespace} = $State->{Module}->{$opt{resource}->{parentModule}}->{nsBinding}; $s =~ s[<($RegQNameChar[^<>]+)>|\b(null|true|false)\b][ my ($q, $l) = ($1, $2); my $r; if (defined $q) { if ($q =~ /\}/) { valid_warn qq<"<$q>" has a "}" - it might be a typo>; } if ($q =~ s/^(.+?):://) { my $et = dis_qname_to_uri ($1, %opt, use_default_namespace => ExpandedURI q); if ($et eq ExpandedURI q) { ## QName constant $r = perl_literal (dis_qname_to_uri ($q, use_default_namespace => 1, %opt)); } elsif ({ ExpandedURI q => 1, ExpandedURI q => 1, ExpandedURI q => 1, ExpandedURI q => 1, }->{$et}) { ## Method call my ($clsq, $mtdq) = split /\s*\.\s*/, $q, 2; my $clsu = dis_typeforqnames_to_uri ($clsq, use_default_namespace => 1, %opt); my $cls = $State->{Type}->{$clsu}; my $clsp = $cls->{ExpandedURI q}; if ($cls->{ExpandedURI q} and { ExpandedURI q => 1, ExpandedURI q => 1, }->{$cls->{ExpandedURI q}}) { valid_err q<"disPerl:ClassM" cannot be used for interface methods>, node => $opt{node} if $et eq ExpandedURI q; $clsp = ''; } else { valid_err qq must be defined>, node => $opt{node} unless defined $clsp; $State->{Module}->{$State->{module}} ->{ExpandedURI q} ->{$State->{Module}->{$cls->{parentModule}} ->{ExpandedURI q}} = 1; } if ($mtdq =~ /:/) { valid_err qq<$mtdq: Prefixed method name not supported>, node => $opt{node}; } else { my $mtd; for (values %{$cls->{ExpandedURI q}}) { if (defined $_->{Name} and $_->{Name} eq $mtdq) { $mtd = $_; last; } } valid_err qq. q, node => $mtd->{src} || $opt{node} if not defined $mtd or not defined $mtd->{ExpandedURI q}; $r = ' ' . ($clsp ? $clsp . { ExpandedURI q => '::', ExpandedURI q => '::', ExpandedURI q => '::', ExpandedURI q => '->', }->{$et} : '') . $mtd->{ExpandedURI q} . ' '; } } elsif ($et eq ExpandedURI q || $et eq ExpandedURI q) { ## Perl package name my $uri = dis_typeforqnames_to_uri ($q, use_default_namespace => 1, %opt); if (defined $State->{Type}->{$uri}->{Name} and defined $State->{Type}->{$uri} ->{ExpandedURI q}) { $r = perl_literal ($State->{Type}->{$uri} ->{ExpandedURI q}); } else { valid_err qq must be defined>, node => $opt{node}; } } elsif ($et eq ExpandedURI q) { ## CODE constant my $uri = dis_typeforqnames_to_uri ($q, use_default_namespace => 1, %opt); if (defined $State->{Type}->{$uri}->{Name} and dis_resource_ctype_match (ExpandedURI q, $State->{Type}->{$uri}, %opt)) { ## ISSUE: It might be required to check loop referring $r = dispm_get_code (%opt, resource => $State->{Type}->{$uri}, For => [keys %{$State->{Type}->{$uri} ->{For}}]->[0], is_inline => 1); } else { valid_err qq must be defined>, node => $opt{node}; } } else { valid_err qq<"$et": Unknown element type>, node => $opt{node}; } } else { valid_err qq<"<$q>": Element type must be specified>, node => $opt{node}; } } else { $r = {true => 1, false => 0, null => 'undef'}->{$l}; } $r; ]ge; ## TODO: Ensure Message::Util::Error imported if "try"ing. ## ISSUE: __FILE__ & __LINE__ will break if multiline substition happens. $s =~ s{ \b__([A-Z]+) (?:\{($RegBlockContent)\})? __\b }{ my ($name, $data) = ($1, $2); my $r; my $et = dis_qname_to_uri ($name, %opt, use_default_namespace => ExpandedURI q); if ($name eq 'XINT') { ## Inserting point of the for-internal code if (defined $data) { if ($data =~ /^{($RegBlockContent)}$/o) { $data = $1; my $name = $1 if $data =~ s/^\s*(\w+)\s*(?:$|:\s*)// or valid_err qq, node => $opt{node}; #local $Status->{preprocess_variable} # = {%{$Status->{preprocess_variable}||{}}}; while ($data =~ /\G(\S+)\s*(?:=>\s*(\S+)\s*)?(?:,\s*|$)/g) { my ($n, $v) = ($1, defined $2 ? $2 : 1); for ($n, $v) { s/^'([^']+)'$/$1/; ## ISSUE: Doesn't support quoted-' } #$Status->{preprocess_variable}->{$n} = $v; } valid_err q unless $opt{internal}; $r = perl_comment ("INT: $name"). $opt{internal}->($name); } elsif ($data =~ s/^SP://) { $r = '___'.$data; } else { $r = perl_internal_name $data; } } else { valid_err q unless $opt{internal}; $r = $opt{internal}->(); } } elsif ($name eq 'DEEP') { ## Deep Method Call $r = '{'.perl_statement ('local $Error::Depth = $Error::Depth + 1'). perl_code ($data) . '}'; } elsif ($name eq 'EXCEPTION' or $name eq 'WARNING') { ## Raising an Exception or Warning if ($data =~ s/^ \s* ((?>(?! ::|\.)$RegQNameChar)+) \s* (?: \. \s* ((?>(?! ::|\.)$RegQNameChar)+) \s* (?: \. \s* ((?>(>! ::|\.)$RegQNameChar)+) \s* )? )? (?: ::\s* | $)//ox) { my ($q, $constq, $subtypeq) = ($1, $2, $3); $q =~ s/\|\|/::/g; my $clsuri; my $cls; my $consturi; my $const; my $subtypeuri; my $subtype; if (defined $constq and not defined $subtypeq) { $clsuri = dis_typeforqnames_to_uri ($q, use_default_namespace => 1, %opt); $cls = $State->{Type}->{$clsuri}; valid_err qq{Exception/warning class definition for }. qq{<$clsuri> is required}, node => $opt{node} unless defined $cls->{Name}; my ($consttq, $constfq) = split /\|\|/, $constq, 2; if (defined $constfq) { if ($consttq !~ /:/) { valid_err qq<"$constq": Unprefixed exception code QName must >. q, node => $opt{node}; } else { $consturi = dis_typeforqnames_to_uri ($consttq.'::'.$constfq, use_default_namespace => 1, %opt); } } else { if ($consttq !~ /:/) { $consturi = $consttq; CONSTCLS: { for (values %{$cls->{ExpandedURI q}}) { if (defined $_->{Name} and $_->{Name} eq $consturi) { $const = $_; last CONSTCLS; } } valid_err qq{Exception/warning code "$consturi" must be }. qq{defined in the exception/warning class }. qq{<$clsuri>}, node => $opt{node}; } } else { $consturi = dis_typeforqnames_to_uri ($consttq.'::'.$constfq, use_default_namespace => 1, %opt); } } unless ($const) { CONSTCLS: { for (values %{$cls->{ExpandedURI q}}) { if (defined $_->{Name} and $_->{URI} and $_->{URI} eq $consturi) { $const = $_; last CONSTCLS; } } valid_err qq{Exception/warning code <$consturi> must be }. qq{defined in the exception/warning class }. qq{<$clsuri>}, node => $opt{node}; } } } else { ## By code/subtype QName $subtypeq = $q unless defined $constq; $subtypeuri = dis_typeforqnames_to_uri ($subtypeq, use_default_namespace => 1, %opt); $subtype = $State->{Type}->{$subtypeuri}; valid_err qq{Exception/warning code/subtype <$subtypeuri> must }. qq{be defined}, node => $opt{node} unless defined $subtype->{Name} and defined $subtype->{ExpandedURI q}; if ($subtype->{ExpandedURI q} eq ExpandedURI q) { $const = $subtype->{ExpandedURI q}; $cls = $subtype->{ExpandedURI q}; } elsif ($subtype->{ExpandedURI q} eq ExpandedURI q) { $const = $subtype; $subtype = undef; $cls = $const->{ExpandedURI q}; } else { valid_err qq{Type of <$subtypeuri> must be either }. q{"ManakaiDOM:Const" or }. q{"ManakaiDOM:ExceptionOrWarningSubType"}, node => $opt{node}; } } ## Parameter my %xparam; while ($data =~ s/^\s*($RegQNameChar+)\s*//) { my $pnameuri = dis_qname_to_uri ($1, use_default_namespace => 1, %opt); if (defined $xparam{$pnameuri}) { valid_err qq is already specified>, node => $opt{node}; } if ($data =~ s/^=>\s*'([^']*)'\s*//) { ## String $xparam{$pnameuri} = $1; } elsif ($data =~ s/^=>\s*\{($RegBlockContent)\}\s*//) { ## Code $xparam{$pnameuri} = perl_code_literal ($1); } elsif ($data =~ /^,|$/) { ## Boolean $xparam{$pnameuri} = 1; } else { valid_err qq<<$pnameuri>: Parameter value is expected>, node => $opt{node}; } $data =~ s/^\,\s*// or last; } valid_err qq<"$data": Broken exception parameter specification>, node => $opt{node} if length $data; for ( ExpandedURI q, ExpandedURI q, ExpandedURI q, ExpandedURI q, ) { $xparam{$_} = $opt{$_} if defined $opt{$_}; } $r = dispm_perl_throws (%opt, class_resource => $cls, class_for => $opt{For}, type_resource => $const, subtype_resource => $subtype, xparam => \%xparam); } else { valid_err qq, node => $opt{node}; } } elsif ($et eq ExpandedURI q) { my ($nm, %param); $data =~ s/^\s+//; if ($data =~ s/^((?>(?!::).)+)//) { $nm = $1; } else { valid_err q, node => $opt{node}; } $data =~ s/^::\s*//; while ($data =~ s/^($RegQNameChar+)\s*(?:=>\s*($RegQNameChar+)\s*)?(?:,\s*|$)//o) { my ($n, $v) = ($1, $2); $v = 1 unless defined $v; if ($n =~ /^\$/) { $param{$n} = $v; } else { $param{dis_qname_to_uri ($n, %opt, use_default_namespace => '')} = $v; } } valid_err qq, node => $opt{node} if length $data; my $uri = dis_typeforqnames_to_uri ($nm, use_default_namespace => 1, %opt); if (defined $State->{Type}->{$uri}->{Name} and dis_resource_ctype_match (ExpandedURI q, $State->{Type}->{$uri}, %opt)) { local $State->{ExpandedURI q} = \%param; ## ISSUE: It might be required to detect a loop $r = dispm_get_code (%opt, resource => $State->{Type}->{$uri}, For => [keys %{$State->{Type}->{$uri} ->{For}}]->[0]); for (grep {/^\$/} keys %param) { $r =~ s/\Q$_\E\b/ $param{$_} /g; } $r = "\n{\n$r\n}\n"; } else { valid_err qq must be defined>, node => $opt{node}; } } elsif ($name eq 'XPACKAGE' and $data) { if ($data eq 'Global') { #$r = $ManakaiDOMModulePrefix; } else { valid_err qq; } } elsif ($name eq 'XREQUIRE') { #$r = perl_statement (q. perl_package_name name => $data); } elsif ($et eq ExpandedURI q) { if ($data =~ s/^\s*IS\s*\{($RegBlockContent)\}::\s*//o) { my $v = dis_qname_to_uri ($1, use_default_namespace => 1, %opt); if ($State->{ExpandedURI q}->{$v}) { $r = perl_code ($data, %opt); } } else { valid_err qq, node => $opt{node}; } } elsif ($et eq ExpandedURI q) { if ($data =~ s/^((?>(?!::).)*)::\s*//) { my @For = ($opt{For} || ExpandedURI q, @{$opt{'For+'} || []}); V: for (split /\s*\|\s*/, $1) { my $for = dis_qname_to_uri ($_, %opt, use_default_namespace => 1, node => $opt{node}); for (@For) { if (dis_uri_for_match ($for, $_, %opt)) { $r = perl_code ($data, %opt); last V; } } } } else { valid_err (qq block: "$data">, node => $opt{node}); } } elsif ($name eq 'FILE' or $name eq 'LINE' or $name eq 'PACKAGE') { $r = qq<__${name}__>; } else { valid_err qq not supported>, node => $opt{node}; } $r; }goex; $s; } } ## Defined in genlib.pl but overridden. sub perl_code_source ($%) { my ($s, %opt) = @_; my $npk = [qw/Name QName Label/]; my $f1 = sprintf q Node <%s> [Chunk #%d]>, $opt{file} || $State->{Module}->{$opt{resource}->{parentModule}}->{FileName}, $opt{path} || ($opt{resource}->{src} ? $opt{resource}->{src}->node_path (key => $npk) : $opt{node} ? $opt{node}->node_path (key => $npk) : 'x:unknown ()'), ++($State->{ExpandedURI q} ||= 0); my $f2 = sprintf q [Chunk #%d]>, $opt{file} || $State->{Module}->{$State->{module}}->{URI}, ++($State->{ExpandedURI q} ||= 0); $f1 =~ s/"/\"/g; $f2 =~ s/"/\"/g; sprintf qq<\n#line %d "%s"\n%s\n#line 1 "%s"\n>, $opt{line} || 1, $f1, $s, $f2; } =item $code = dispm_get_code (resource => $res, %opt) Generates a Perl code fragment from resource(s). =cut sub dispm_get_code (%) { my %opt = @_; if (($opt{ExpandedURI q} and defined $opt{resource}->{Name}) or ($opt{resource}->{ExpandedURI q} and { ExpandedURI q => 1, ExpandedURI q => 1, ExpandedURI q => 1, }->{$opt{resource}->{ExpandedURI q}}) or (dis_resource_ctype_match ([ExpandedURI q, ExpandedURI q], $opt{resource}, %opt, node => $opt{resource}->{src}))) { local $State->{Namespace} = $State->{Module}->{$opt{resource}->{parentModule}}->{nsBinding} if defined $opt{resource}->{Name}; my $key = $opt{ExpandedURI q} || ExpandedURI q; my $n = dis_get_attr_node (%opt, parent => $opt{resource}->{src}, name => {uri => $key}, ContentType => ExpandedURI q) || dis_get_attr_node (%opt, parent => $opt{resource}->{src}, name => {uri => $key}, ContentType => ExpandedURI q); if ($n) { return disperl_to_perl (%opt, node => $n); } $n = dis_get_attr_node (%opt, parent => $opt{resource}->{src}, name => {uri => $key}, ContentType => ExpandedURI q); if ($n) { my $code = ''; for (@{dis_get_elements_nodes (%opt, parent => $n, name => 'require')}) { $code .= perl_statement 'require ' . $_->value; } $code .= perl_code ($n->value, %opt, node => $n); if ($opt{is_inline} and dis_resource_ctype_match ([ExpandedURI q], $opt{resource}, %opt, node => $opt{resource}->{src})) { $code =~ s/\n/\x20/g; return $code; } else { return perl_code_source ($code, %opt, node => $n); } } return undef; } else { impl_err ("Bad resource for dispm_get_code: ". $opt{resource}->{ExpandedURI q}, node => $opt{resource}->{src}); } } # dispm_get_code =item $code = dispm_get_value (%opt) Gets value property and returns it as a Perl code fragment. =cut sub dispm_get_value (%) { my %opt = @_; my $key = $opt{ExpandedURI q} || ExpandedURI q; my $vt = $opt{ExpandedURI q} || ExpandedURI q; local $State->{Namespace} = $State->{Module}->{$opt{resource}->{parentModule}}->{nsBinding} if defined $opt{resource}->{Name}; my $n = $opt{node} ? [$opt{node}] : dis_get_elements_nodes (%opt, parent => $opt{resource}->{src}, name => {uri => $key}); for my $n (@$n) { my $t = dis_get_attr_node (%opt, parent => $n, name => 'ContentType'); my $type; if ($t) { $type = dis_qname_to_uri ($t->value, %opt, node => $t); } else { $type = ExpandedURI q; } valid_err (qq is not defined>, node => $t || $n) unless defined $State->{Type}->{$type}->{Name}; if (dis_uri_ctype_match (ExpandedURI q, $type, %opt)) { ## ISSUE: Is some pre-process required? return $n->value; } elsif (dis_uri_ctype_match (ExpandedURI q, $type, %opt)) { return perl_literal $n->value; } elsif (dis_uri_ctype_match (ExpandedURI q, $type, %opt)) { ## NOTE: This might not be a valid Perl code fragment. return $n->value; } } ## No explicit value specified if ($opt{ExpandedURI q}) { if (dis_uri_ctype_match (ExpandedURI q, $vt, %opt)) { return q<"">; } } return undef; } # dispm_get_value =item $code = dispm_const_value (resource => $const, %opt) Returns a code fragment corresponding to the vaue of C<$const>. =cut sub dispm_const_value (%) { my %opt = @_; my $for = [keys %{$opt{resource}->{For}}]->[0]; my $value = dispm_get_value (%opt, ExpandedURI q => ExpandedURI q, ExpandedURI q => $opt{resource} ->{ExpandedURI q}, For => $for); valid_err q, node => $opt{resource}->{src} unless defined $value; return $value; } # dispm_const_value =item $code = dispm_const_value_sub (resource => $const, %opt) Returns a code fragment to declare and define a constant function corresponding to the definition of C<$const>. =cut sub dispm_const_value_sub (%) { my %opt = @_; my $value = dispm_const_value (%opt); return perl_sub (name => $opt{resource}->{ExpandedURI q}, prototype => '', code => $value); } # dispm_const_value_sub =item $code = dispm_const_group (resource => $const_group, %opt) Returns a code fragment to define a constant value group. =cut sub dispm_const_group (%) { my %opt = @_; my $name = $opt{resource}->{ExpandedURI q}; for my $cg (values %{$opt{resource}->{ExpandedURI q}}) { if (defined $cg->{ExpandedURI q}) { valid_err (qq{"$name"."$cg->{ExpandedURI q}": }. qq{Nesting constant group not supported}, node => $cg->{src}); } } my $result = ''; my @cname; if (length $name) { if (defined $opt{ExpandedURI q}->{$name}) { valid_err qq, node => $opt{resource}->{src}; } $opt{ExpandedURI q}->{$name} = \@cname; } for my $cv (values %{$opt{resource}->{ExpandedURI q}}) { next unless defined $cv->{ExpandedURI q}; $result .= dispm_const_value_sub (%opt, resource => $cv); push @cname, $cv->{ExpandedURI q}; } return $result; } # dispm_const_group =item $code = disperl_to_perl (node => $node, %opt) Converts a C node to a Perl code fragment. =cut sub disperl_to_perl (%) { my %opt = @_; my $code = ''; for (@{$opt{node}->child_nodes}) { next unless $_->node_type eq '#element'; next unless dis_node_for_match ($_, $opt{For}, %opt); my $et = dis_element_type_to_uri ($_->local_name, %opt, node => $_); if ($et eq ExpandedURI q) { my $cn = $_->value; if ($cn =~ /^((?>(?!\.)$RegQNameChar)*)\.($RegQNameChar+)$/o) { my ($cls, $constn) = ($1, $2); if (length $cls) { my $clsu = dis_typeforqnames_to_uri ($cls, %opt, use_default_namespace => 1, node => $_); $cls = $State->{Type}->{$clsu}; valid_err qq must be defined>, node => $_ unless defined $cls->{Name}; } else { $cls = $State->{ExpandedURI q}; valid_err q, node => $_ unless defined $cls->{Name}; } my $const = $cls->{ExpandedURI q}->{$constn}; valid_err qq. qq{"$cls->{Name}" (<$cls->{URI}>)}, node => $_ unless defined $const->{Name}; $code .= perl_statement perl_assign perl_var (type => '$', local_name => 'r') => dispm_const_value (resource => $const); } else { valid_err q, node => $_; } } elsif ($et eq ExpandedURI q) { my $v = dispm_get_value (%opt, node => $_); $code .= perl_statement perl_assign perl_var (type => '$', local_name => 'r') => $v; } elsif ($et eq ExpandedURI q or $et eq ExpandedURI q) { my $uri = dis_qname_to_uri ($_->value, %opt, node => $_, use_default_namespace => 1); $code .= perl_statement perl_assign perl_var (type => '$', local_name => 'r') => '$self->{'.(ExpandedURI q). '}->{'.(perl_literal $uri).'}'; if ($et eq ExpandedURI q) { $code .= perl_if 'defined $r', perl_code (q{ ($r)}, %opt, node => $_); } } elsif ($et eq ExpandedURI q) { my $prop = dis_get_attr_node (%opt, parent => $_, name => {uri => ExpandedURI q}); my $propvalue; if ($prop) { $prop = dis_qname_to_uri ($prop->value, use_default_namespace => 1, %opt, node => $prop); $prop = dis_get_attr_node (%opt, parent => $opt{Type}, name => {uri => $prop}) if $opt{Type}; unless ($prop) { if ($prop) { valid_err q, node => $opt{node}; } else { $propvalue = ''; } } else { $propvalue = $prop->value; } } else { valid_err q, node => $_; } my $selcase; for my $case (@{$_->child_nodes}) { next unless $case->node_type eq '#element'; next unless dis_node_for_match ($case, $opt{For}, %opt); my $et = dis_element_type_to_uri ($case->local_name, %opt, node => $case); if ($et eq ExpandedURI q) { my $val = dis_get_attr_node (%opt, parent => $case, name => 'Value', ContentType => ExpandedURI q, defaultContentType => ExpandedURI q); if ($val and $val->value eq $propvalue) { $selcase = $case; last; } elsif (not $val and not $val->value) { $selcase = $case; last; } } elsif ($et eq ExpandedURI q) { $selcase = $case; last; } else { valid_err q not allowed here>, node => $case; } } if ($selcase) { my $lcode = perl_code ($selcase->value, %opt, node => $selcase); $code .= perl_code_source ($lcode, %opt, node => $selcase); } } elsif ({ ExpandedURI q => 1, ExpandedURI q => 1, ExpandedURI q => 1, ExpandedURI q => 1, }->{$et}) { # } else { valid_err qq not supported>, node => $opt{node}; } } my $val = $opt{node}->value; if (defined $val and length $val) { $code .= perl_code_source (perl_code ($val, %opt), %opt); } return $code; } # disperl_to_perl ## Outputed module and "For" my $mf = dis_get_module_uri (module_name => $Opt{module_name}, module_uri => $Opt{module_uri}, For => $Opt{For}); $State->{DefaultFor} = $mf->{For}; $State->{module} = $mf->{module}; valid_err (qq{Perl module <$State->{module}> not defined for <$State->{DefaultFor}>}, node => $State->{Module}->{$State->{module}}->{src}) unless $State->{Module}->{$State->{module}} ->{ExpandedURI q}; $State->{ExpandedURI q} = 'main'; $result .= "#!/usr/bin/perl \n"; $result .= perl_comment q . "\n" . q<"> . $Opt{file_name} . q<" at > . rfc3339_date (time) . qq<.\n> . q; $result .= perl_comment qq{Module <$State->{module}>}; $result .= perl_comment qq{For <$State->{DefaultFor}>}; $result .= perl_statement q; $result .= perl_change_package (full_name => $State->{Module}->{$State->{module}} ->{ExpandedURI q}); $result .= perl_statement perl_assign perl_var (type => '$', local_name => 'VERSION', scope => 'our') => perl_literal version_date time; ## -- Classes my %opt; for my $pack (values %{$State->{Module}->{$State->{module}} ->{ExpandedURI q}||{}}) { next unless defined $pack->{Name}; if ({ ExpandedURI q => 1, ExpandedURI q => 1, ExpandedURI q => 1, ExpandedURI q => 1, ExpandedURI q => 1, }->{$pack->{ExpandedURI q}}) { ## Package name and version $result .= perl_change_package (full_name => $pack->{ExpandedURI q}); $result .= perl_statement perl_assign perl_var (type => '$', local_name => 'VERSION', scope => 'our') => perl_literal version_date time; ## Inheritance ## TODO: IF "isa" should be expanded my $isa = []; for my $uri (@{$pack->{ISA}||[]}, @{$pack->{Implement}||[]}) { my $pack = $State->{Type}->{$uri}; if (defined $pack->{ExpandedURI q}) { push @$isa, $pack->{ExpandedURI q}; } else { impl_msg ("Inheriting package name for <$uri> not defined", node => $pack->{src}) if $Opt{verbose}; } } $isa = array_uniq $isa; $result .= perl_inherit $isa; $result .= '$' . $_ . "::;\n" for @$isa; ## Members if ({ ExpandedURI q => 1, ExpandedURI q => 1, ExpandedURI q => 1, }->{$pack->{ExpandedURI q}}) { local $State->{ExpandedURI q} => $pack; local $opt{ExpandedURI q} = $pack->{ExpandedURI q}; for my $method (values %{$pack->{ExpandedURI q}}) { next unless defined $method->{Name}; next unless length $method->{ExpandedURI q}; if ($method->{ExpandedURI q} eq ExpandedURI q) { local $opt{ExpandedURI q} = $method->{ExpandedURI q}; my $proto = '$'; my @param = ('self'); my $param_norm = ''; my $param_opt = 0; my $for = [keys %{$method->{For}}]->[0]; for my $param (@{$method->{ExpandedURI q}||[]}) { if ($param->{ExpandedURI q}) { $proto .= ';' unless $param_opt; $param_opt++; } $proto .= '$'; push @param, $param->{ExpandedURI q}; my $nm = dispm_get_code (%opt, resource => $State->{Type} ->{$param->{ExpandedURI q}}, ExpandedURI q => ExpandedURI q, For => $for, ExpandedURI q => 1); if (defined $nm) { $nm =~ s/\$INPUT\b/\$$param[-1] /g; $param_norm .= $nm; } } my $code = dispm_get_code (%opt, resource => $method->{ExpandedURI q}, For => $for); if (defined $code) { my $my = perl_statement ('my ('.join (", ", map {"\$$_"} @param). ') = @_'); my $return = defined $method->{ExpandedURI q}->{Name} ? $method->{ExpandedURI q} : undef; if ($return->{ExpandedURI q} ? 1 : 0) { my $default = dispm_get_value (%opt, resource => $return, ExpandedURI q => ExpandedURI q, ExpandedURI q => 1, ExpandedURI q => $return->{ExpandedURI q}); $code = $my . $param_norm . perl_statement (defined $default ? 'my $r = '.$default : 'my $r'). $code . "\n" . perl_statement ('$r'); } else { $code = $my . $code; } } else { ## Code not defined my $for1 = $for; unless (dis_uri_for_match (ExpandedURI q, $for, node => $method->{src})) { $for1 = ExpandedURI q; } $code = perl_statement dispm_perl_throws class => ExpandedURI q, class_for => $for1, type => 'NOT_SUPPORTED_ERR', subtype => ExpandedURI q, xparam => { ExpandedURI q => $pack->{ExpandedURI q}, ExpandedURI q => $method->{ExpandedURI q}, }; } $result .= perl_sub (name => $method->{ExpandedURI q}, code => $code, prototype => $proto); } elsif ($method->{ExpandedURI q} eq ExpandedURI q) { local $opt{ExpandedURI q} = $method->{ExpandedURI q}; my $getter = $method->{ExpandedURI q}; valid_err qq{Getter for attribute "$method->{Name}" must be }. q{defined}, node => $method->{src} unless $getter; my $setter = defined $method->{ExpandedURI q}->{Name} ? $method->{ExpandedURI q} : undef; my $for = [keys %{$method->{For}}]->[0]; my $for1 = $for; unless (dis_uri_for_match (ExpandedURI q, $for, node => $method->{src})) { $for1 = ExpandedURI q; } local $opt{ExpandedURI q} = 'get'; my $get_code = dispm_get_code (resource => $getter, For => $for); if (defined $get_code) { my $default = dispm_get_value (%opt, resource => $getter, ExpandedURI q => ExpandedURI q, ExpandedURI q => 1, ExpandedURI q => $getter->{ExpandedURI q}); $get_code = perl_statement (defined $default ? 'my $r = '.$default : 'my $r'). $get_code. "\n" . perl_statement ('$r'); } else { ## Get code not defined $get_code = perl_statement dispm_perl_throws class => ExpandedURI q, class_for => $for1, type => 'NOT_SUPPORTED_ERR', subtype => ExpandedURI q, xparam => { ExpandedURI q => $pack->{ExpandedURI q}, ExpandedURI q => $method->{ExpandedURI q}, ExpandedURI q => 'get', }; } if ($setter) { local $opt{ExpandedURI q} = 'set'; my $set_code = dispm_get_code (%opt, resource => $setter, For => $for); if (defined $set_code) { my $nm = dispm_get_code (%opt, resource => $State->{Type} ->{$setter->{ExpandedURI q}}, ExpandedURI q => ExpandedURI q, For => $for, ExpandedURI q => 1); if (defined $nm) { $nm =~ s/\$INPUT\b/\$given /g; } else { $nm = ''; } my $default = dispm_get_value (%opt, resource => $setter, ExpandedURI q => ExpandedURI q, ExpandedURI q => 1, ExpandedURI q => $getter->{ExpandedURI q}); $set_code = $nm . perl_statement (defined $default ? 'my $r = '.$default : 'my $r'). $set_code. "\n" . perl_statement ('$r'); } else { ## Set code not defined $set_code = perl_statement dispm_perl_throws class => ExpandedURI q, class_for => $for1, type => 'NOT_SUPPORTED_ERR', subtype => ExpandedURI q, xparam => { ExpandedURI q => $pack->{ExpandedURI q}, ExpandedURI q => $method->{ExpandedURI q}, ExpandedURI q => 'set', }; } $get_code = perl_if '@_ == 2', perl_statement ('my ($self, $given) = @_'). $set_code, perl_statement ('my ($self) = @_'). $get_code; } else { $get_code = perl_statement ('my ($self) = @_'). $get_code; } $result .= perl_sub (name => $method->{ExpandedURI q}, prototype => $setter ? '$;$' : '$', code => $get_code); } } # package method for my $cg (values %{$pack->{ExpandedURI q}}) { next unless defined $cg->{Name}; $result .= dispm_const_group (resource => $cg); } # package const group for my $cv (values %{$pack->{ExpandedURI q}}) { next unless defined $cv->{Name}; $result .= dispm_const_value (resource => $cv); } # package const value } } # root object } for (keys %{$State->{Module}->{$State->{module}} ->{ExpandedURI q}||{}}) { next if $_ eq $State->{Module}->{$State->{module}} ->{ExpandedURI q}; $result .= perl_statement ('require ' . $_); } $result .= perl_statement 1; output_result $result; 1;