Affix
view release on metacpan or search on metacpan
lib/Affix/Wrap.pm view on Meta::CPAN
}
class #
Affix::Wrap::Member {
use Affix qw[Void];
field $name : reader : param //= '';
field $type : reader : param //= '';
field $doc : reader : param //= ();
field $definition : reader : param //= ();
method affix_type {
return $definition->affix_type if defined $definition;
return $type->affix_type if builtin::blessed($type);
return 'Void';
}
method affix {
return $definition->affix if defined $definition;
builtin::blessed($type) ? $type->affix : Void;
}
}
class #
Affix::Wrap::Macro : isa(Affix::Wrap::Entity) {
field $value : reader : param //= ();
method set_value ($v) { $value = $v }
method affix_type {
$value // return '';
my $v = $value // '';
$v =~ s/^\s+|\s+$//g;
return '' unless length $v;
if ( $v =~ /^-?(?:0x[\da-fA-F]+|\d+(?:\.\d+)?)$/ ) {
return sprintf 'use constant %s => %s', $self->name, $v;
}
if ( $v =~ /^".*"$/ || $v =~ /^'.*'$/ ) {
return sprintf 'use constant %s => %s', $self->name, $v;
}
$v =~ s/'/\\'/g;
sprintf 'use constant %s => \'%s\'', $self->name, $v;
}
method affix ( $lib //= (), $pkg //= () ) {
if ( $pkg && defined $value && length $value ) {
my $val = $value;
if ( $val =~ /^"(.*)"$/ || $val =~ /^'(.*)'$/ ) { $val = $1; }
no strict 'refs';
no warnings 'redefine';
*{ "${pkg}::" . $self->name } = sub () {$val};
}
sub () {$value};
}
} class Affix::Wrap::Variable : isa(Affix::Wrap::Entity) {
field $type : reader : param;
method affix_type { sprintf 'pin my $%s, $lib, \'%s\' => %s', $self->name, $self->name, $type->affix_type }
method affix ( $lib, $pkg //= () ) {
if ($lib) {
my $t = $type->affix;
if ($pkg) {
no strict 'refs';
# Vivify package variable and bind it
Affix::pin( ${ "${pkg}::" . $self->name }, $lib, $self->name, $t );
}
else {
my $var;
Affix::pin( $var, $lib, $self->name, $t );
return $var;
}
}
$type->affix;
}
} class #
Affix::Wrap::Typedef : isa(Affix::Wrap::Entity) {
field $underlying : reader : param;
method affix_type { 'typedef \'' . $self->name . '\' => ' . $underlying->affix_type }
method affix ( $lib //= (), $pkg //= () ) {
my $t = $underlying->affix;
Affix::typedef $self->name, $t;
# If the underlying type is an Enum, we must manually export the constants to the target package.
# Affix::typedef only installs them into the *caller* (which is this class).
if ( $pkg && builtin::blessed($t) && $t->isa('Affix::Type::Enum') ) {
my ( $const_map, $val_map ) = $t->resolve();
no strict 'refs';
while ( my ( $const_name, $val ) = each %$const_map ) {
*{"${pkg}::${const_name}"} = sub () {$val};
}
}
}
} class Affix::Wrap::Struct : isa(Affix::Wrap::Entity) {
field $tag : reader : param //= 'struct';
field $members : reader : param //= [];
method affix_type {
my $type_name = $tag eq 'union' ? 'Union' : 'Struct';
sprintf '%s[ %s ]', $type_name, join( ', ', map { $_->name . ' => ' . $_->affix_type } @$members );
}
method affix ( $lib //= (), $pkg //= () ) {
use Affix qw[Struct Union];
if ( $tag eq 'union' ) {
return Union [ map { $_->name, $_->affix } @$members ];
}
Struct [ map { $_->name, $_->affix } @$members ];
}
} class #
Affix::Wrap::Enum : isa(Affix::Wrap::Entity) {
field $constants : reader : param //= [];
method affix_type {
my @defs;
for my $c (@$constants) {
if ( !defined $c->{value} ) {
push @defs, $c->{name};
next;
}
my $v = $c->{value} // 0;
$v = "'$v'" if $v !~ /^-?\d+$/;
push @defs, sprintf( '[%s => %s]', $c->{name}, $v );
}
( run in 1.330 second using v1.01-cache-2.11-cpan-2398b32b56e )