Skip to content

Instantly share code, notes, and snippets.

@scovit
Last active January 9, 2019 00:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scovit/d328be9817eef73fbe98cc98f99ee3a3 to your computer and use it in GitHub Desktop.
Save scovit/d328be9817eef73fbe98cc98f99ee3a3 to your computer and use it in GitHub Desktop.
use nqp;
my $SIG_ELEM_BIND_CAPTURE := 1;
my $SIG_ELEM_BIND_PRIVATE_ATTR := 2;
my $SIG_ELEM_BIND_PUBLIC_ATTR := 4;
my $SIG_ELEM_SLURPY_POS := 8;
my $SIG_ELEM_SLURPY_NAMED := 16;
my $SIG_ELEM_SLURPY_LOL := 32;
my $SIG_ELEM_INVOCANT := 64;
my $SIG_ELEM_MULTI_INVOCANT := 128;
my $SIG_ELEM_IS_RW := 256;
my $SIG_ELEM_IS_COPY := 512;
my $SIG_ELEM_IS_RAW := 1024;
my $SIG_ELEM_IS_OPTIONAL := 2048;
my $SIG_ELEM_ARRAY_SIGIL := 4096;
my $SIG_ELEM_HASH_SIGIL := 8192;
my $SIG_ELEM_DEFAULT_FROM_OUTER := 16384;
my $SIG_ELEM_IS_CAPTURE := 32768;
my $SIG_ELEM_UNDEFINED_ONLY := 65536;
my $SIG_ELEM_DEFINED_ONLY := 131072;
my $SIG_ELEM_NOMINAL_GENERIC := 524288;
my $SIG_ELEM_DEFAULT_IS_LITERAL := 1048576;
my $SIG_ELEM_NATIVE_INT_VALUE := 2097152;
my $SIG_ELEM_NATIVE_NUM_VALUE := 4194304;
my $SIG_ELEM_NATIVE_STR_VALUE := 8388608;
my $SIG_ELEM_SLURPY_ONEARG := 16777216;
my $SIG_ELEM_CODE_SIGIL := 33554432;
# Creates a parameter object.
sub create_parameter(%param_info) {
# Create parameter object now.
my $par_type := Parameter;
my $parameter := nqp::create($par_type);
# Calculate flags.
my Int $flags := 0;
if %param_info<optional> {
$flags := $flags + $SIG_ELEM_IS_OPTIONAL;
}
if %param_info<is_invocant> {
$flags := $flags + $SIG_ELEM_INVOCANT;
}
if %param_info<is_multi_invocant> {
$flags := $flags + $SIG_ELEM_MULTI_INVOCANT;
}
if %param_info<is_rw> {
$flags := $flags + $SIG_ELEM_IS_RW;
}
if %param_info<is_raw> {
$flags := $flags + $SIG_ELEM_IS_RAW;
}
if %param_info<pos_onearg> {
$flags := $flags + $SIG_ELEM_SLURPY_ONEARG;
}
if %param_info<is_capture> {
$flags := $flags + $SIG_ELEM_IS_CAPTURE + $SIG_ELEM_IS_RAW;
}
if %param_info<undefined_only> {
$flags := $flags + $SIG_ELEM_UNDEFINED_ONLY;
}
if %param_info<defined_only> {
$flags := $flags + $SIG_ELEM_DEFINED_ONLY;
}
if %param_info<pos_slurpy> {
$flags := $flags + $SIG_ELEM_SLURPY_POS;
}
if %param_info<named_slurpy> {
$flags := $flags + $SIG_ELEM_SLURPY_NAMED;
}
if %param_info<pos_lol> {
$flags := $flags + $SIG_ELEM_SLURPY_LOL;
}
if %param_info<bind_attr> {
$flags := $flags + $SIG_ELEM_BIND_PRIVATE_ATTR;
}
if %param_info<bind_accessor> {
$flags := $flags + $SIG_ELEM_BIND_PUBLIC_ATTR;
}
if %param_info<sigil> eq '@' {
$flags := $flags + $SIG_ELEM_ARRAY_SIGIL;
}
elsif %param_info<sigil> eq '%' {
$flags := $flags + $SIG_ELEM_HASH_SIGIL;
}
elsif %param_info<sigil> eq '&' {
$flags := $flags + $SIG_ELEM_CODE_SIGIL;
}
if %param_info<default_from_outer> {
$flags := $flags + $SIG_ELEM_DEFAULT_FROM_OUTER;
}
if %param_info<nominal_generic> {
$flags := $flags + $SIG_ELEM_NOMINAL_GENERIC;
}
if %param_info<default_is_literal> {
$flags := $flags + $SIG_ELEM_DEFAULT_IS_LITERAL;
}
my $primspec := nqp::objprimspec(%param_info<nominal_type>);
if $primspec == 1 {
$flags := $flags + $SIG_ELEM_NATIVE_INT_VALUE;
}
elsif $primspec == 2 {
$flags := $flags + $SIG_ELEM_NATIVE_NUM_VALUE;
}
elsif $primspec == 3 {
$flags := $flags + $SIG_ELEM_NATIVE_STR_VALUE;
}
# Populate it.
if nqp::existskey(%param_info, 'variable_name') {
nqp::bindattr_s($parameter, $par_type, '$!variable_name', %param_info<variable_name>);
}
nqp::bindattr($parameter, $par_type, '$!nominal_type', %param_info<nominal_type>);
nqp::bindattr_i($parameter, $par_type, '$!flags', $flags);
if %param_info<named_names> {
nqp::bindattr($parameter, $par_type, '@!named_names', %param_info<named_names>);
}
if %param_info<type_captures> {
nqp::bindattr($parameter, $par_type, '@!type_captures', %param_info<type_captures>);
}
if %param_info<post_constraints> {
nqp::bindattr($parameter, $par_type, '@!post_constraints',
%param_info<post_constraints>);
}
if nqp::existskey(%param_info, 'default_value') {
nqp::bindattr($parameter, $par_type, '$!default_value', %param_info<default_value>);
}
if nqp::existskey(%param_info, 'container_descriptor') {
nqp::bindattr($parameter, $par_type, '$!container_descriptor', %param_info<container_descriptor>);
}
if nqp::existskey(%param_info, 'attr_package') {
nqp::bindattr($parameter, $par_type, '$!attr_package', %param_info<attr_package>);
}
if nqp::existskey(%param_info, 'sub_signature') {
nqp::bindattr($parameter, $par_type, '$!sub_signature', %param_info<sub_signature>);
}
if nqp::existskey(%param_info, 'coerce_type') {
$parameter.set_coercion(%param_info<coerce_type>);
}
if nqp::existskey(%param_info, 'dummy') {
my $dummy := %param_info<dummy>;
my $why := $dummy.WHY;
if $why {
$parameter.set_why($why);
}
}
# Return created parameter.
$parameter
}
my %par1 = nqp::hash(
'nominal_type', Str,
'sigil', '$',
'variable_name', '$text',
'is_multi_invocant', 1
);
my $signature := nqp::create(Signature);
my $pars := nqp::list;
nqp::push($pars, create_parameter(%par1));
nqp::bindattr($signature, Signature, '@!params', $pars);
nqp::bindattr_i($signature, Signature, '$!arity', 1);
$signature.set_returns(int32);
my $sign = $signature;
dd $sign;
use NativeCall;
sub dlsym(Pointer, Str --> Pointer) is native { };
my $point = dlsym(Pointer.new(0), "puts");
my &f = nativecast($signature, $point);
f("This comes from a dynamically generated nativecast of puts obtained by dlsym!");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment