# possible syntax for Signature DSL my $Bit = new signature q| role ANY {} role Coerceable [::T] { to_bit (::T $self:) returns BIT; to_str (::T $self:) returns STR; to_num (::T $self:) returns NUM; } role BIT { does Coerceable[BIT]; not (BIT $self:) returns BIT; and (BIT $self: BLOCK $block) returns BIT; or (BIT $self: BLOCK $block) returns BIT; } role OPAQUE { does Coerceable[OPAQUE]; id (OPAQUE $self:) returns NUM; class (OPAQUE $self:) returns OPAQUE; change_class (OPAQUE $self: OPAQUE $class) returns NIL; get_attr (OPAQUE $self: SYMBOL $name) returns ANY; set_attr (OPAQUE $self: SYMBOL $name, ANY $value) returns NIL; add_attr (OPAQUE $self: SYMBOL $name) returns NIL; } class Bit does BIT { map_native "Perl6::Core::Bit"; } class Opaque does OPAQUE { map_native "Perl6::MM::Opaque"; } |; # the raw p5 code which the DSL might generate my $Bit = module::signature->new( symbol->new('to_bit') => method::signature->new( params => method::params->new(symbol->new('$self:' => 'Bit')), returns => 'Bit' ), symbol->new('to_str') => method::signature->new( params => method::params->new(symbol->new('$self:' => 'Bit')), returns => 'Str' ), symbol->new('to_num') => method::signature->new( params => method::params->new(symbol->new('$self:' => 'Bit')), returns => 'Num' ), symbol->new('not') => method::signature->new( params => method::params->new(symbol->new('$self:' => 'Bit')), returns => 'Bit' ), symbol->new('and') => method::signature->new( params => method::params->new( symbol->new('$self:' => 'Bit'), symbol->new('$block' => 'Block') ), returns => 'Bit' ), symbol->new('or') => method::signature->new( params => method::params->new( symbol->new('$self:' => 'Bit'), symbol->new('$block' => 'Block') ), returns => 'Bit' ), ); # create a new module which *Bit = module->new( signature => $BIT, native => 'Perl6::Core::Bit' ); # now we have the Bit available Bit->new(1); # code sketch of how we can wrap a native # function with a signature my $wrapped_or = module::native::wrap( $Bit->get_signature(symbol->new('or')) \&bit::or ); sub module::native::wrap { my ($sig, $body) = @_; closure->new( $e, $sig->params, sub { my $e = shift; # extract the args from the environment my @args; foreach my $param ($sig->params->to_native) { my $name = $param->name; push @args => $e->get($name->to_native); } # execute the body of the method return $body->(@args); # closure will automatically check the type of the return value ... } ); }