Skip to content

Instantly share code, notes, and snippets.

@arnsholt
Created July 28, 2012 12:07
Show Gist options
  • Save arnsholt/3193047 to your computer and use it in GitHub Desktop.
Save arnsholt/3193047 to your computer and use it in GitHub Desktop.
Why U segfault?
diff --git a/src/Perl6/Actions.pm b/src/Perl6/Actions.pm
index c790afb..5176b8c 100644
--- a/src/Perl6/Actions.pm
+++ b/src/Perl6/Actions.pm
@@ -229,7 +229,7 @@ class Perl6::Actions is HLL::Actions {
# Finish up code object for the mainline.
if $*DECLARAND {
- $*W.attach_signature($*DECLARAND, $*W.create_signature([]));
+ $*W.attach_signature($*DECLARAND, $*W.create_signature(nqp::hash('parameters', [])));
$*W.finish_code_object($*DECLARAND, $*UNIT);
}
@@ -598,6 +598,7 @@ class Perl6::Actions is HLL::Actions {
}
else {
# Locate or build a set of parameters.
+ my %sig_info;
my @params;
my $block := $<blockoid>.ast;
if $block<placeholder_sig> && $<signature> {
@@ -605,9 +606,11 @@ class Perl6::Actions is HLL::Actions {
}
elsif $block<placeholder_sig> {
@params := $block<placeholder_sig>;
+ %sig_info<parameters> := @params;
}
elsif $<signature> {
- @params := $<signature>.ast;
+ %sig_info := $<signature>.ast;
+ @params := %sig_info<parameters>;
}
else {
unless $block.symbol('$_') {
@@ -620,6 +623,7 @@ class Perl6::Actions is HLL::Actions {
}
add_implicit_var($block, '$_');
}
+ %sig_info<parameters> := @params;
}
# Create signature object and set up binding.
@@ -627,7 +631,7 @@ class Perl6::Actions is HLL::Actions {
for @params { $_<is_rw> := 1 }
}
set_default_parameter_type(@params, 'Mu');
- my $signature := create_signature_object($<signature>, @params, $block);
+ my $signature := create_signature_object($<signature>, %sig_info, $block);
add_signature_binding_code($block, $signature, @params);
# Add a slot for a $*DISPATCHER, and a call to take one.
@@ -660,7 +664,7 @@ class Perl6::Actions is HLL::Actions {
);
}
($*W.cur_lexpad())[0].push(my $uninst := PAST::Stmts.new($block));
- $*W.attach_signature($*DECLARAND, $*W.create_signature([]));
+ $*W.attach_signature($*DECLARAND, $*W.create_signature(nqp::hash('parameters', [])));
$*W.finish_code_object($*DECLARAND, $block);
my $ref := reference_to_code_object($*DECLARAND, $block);
$ref<uninstall_if_immediately_used> := $uninst;
@@ -1319,13 +1323,14 @@ class Perl6::Actions is HLL::Actions {
if $*PKGDECL eq 'role' {
# Set up signature. Needs to have $?CLASS as an implicit
# parameter, since any mention of it is generic.
- my @params := $<signature> ?? $<signature>[0].ast !! [];
+ my %sig_info := $<signature> ?? $<signature>[0].ast !! hash(parameters => []);
+ my @params := %sig_info<parameters>;
@params.unshift(hash(
is_multi_invocant => 1,
type_captures => ['$?CLASS', '::?CLASS']
));
set_default_parameter_type(@params, 'Mu');
- my $sig := create_signature_object($<signature>, @params, $block);
+ my $sig := create_signature_object($<signature>, %sig_info, $block);
add_signature_binding_code($block, $sig, @params);
$block.blocktype('declaration');
@@ -1340,7 +1345,7 @@ class Perl6::Actions is HLL::Actions {
$throwaway_block_past<outer> := $block;
$block[0].push($throwaway_block_past);
my $throwaway_block := $*W.create_code_object($throwaway_block_past,
- 'Block', $*W.create_signature([]));
+ 'Block', $*W.create_signature(nqp::hash('parameters', [])));
my $fixup := $*W.create_lexical_capture_fixup();
$fixup.push(PAST::Op.new(
:pasttype('callmethod'), :name('clone'),
@@ -1434,7 +1439,7 @@ class Perl6::Actions is HLL::Actions {
# Go over the params and declare the variable defined
# in them.
my $list := PAST::Op.new( :pasttype('call'), :name('&infix:<,>') );
- my @params := $<signature>.ast;
+ my @params := $<signature>.ast<parameters>;
for @params {
if $_<variable_name> {
my $past := PAST::Var.new( :name($_<variable_name>) );
@@ -1632,8 +1637,9 @@ class Perl6::Actions is HLL::Actions {
# Produce a code object and install it.
my $invocant_type := $*W.find_symbol([$*W.is_lexical('$?CLASS') ?? '$?CLASS' !! 'Mu']);
+ my %sig_info := hash(parameters => []);
my $code := methodize_block($/, $*W.stub_code_object('Method'),
- $a_past, [], $invocant_type);
+ $a_past, %sig_info, $invocant_type);
install_method($/, $meth_name, 'has', $code, $install_in);
}
@@ -1671,12 +1677,17 @@ class Perl6::Actions is HLL::Actions {
if $block<placeholder_sig> && $<multisig> {
$*W.throw($/, ['X', 'Signature', 'Placeholder']);
}
- my @params :=
- $<multisig> ?? $<multisig>[0].ast !!
- $block<placeholder_sig> ?? $block<placeholder_sig> !!
- [];
+ my %sig_info;
+ if $<multisig> {
+ %sig_info := $<multisig>[0].ast;
+ }
+ else {
+ %sig_info<parameters> := $block<placeholder_sig> ?? $block<placeholder_sig> !!
+ [];
+ }
+ my @params := %sig_info<parameters>;
set_default_parameter_type(@params, 'Any');
- my $signature := create_signature_object($<multisig> ?? $<multisig>[0] !! $/, @params, $block);
+ my $signature := create_signature_object($<multisig> ?? $<multisig>[0] !! $/, %sig_info, $block);
add_signature_binding_code($block, $signature, @params);
# Needs a slot that can hold a (potentially unvivified) dispatcher;
@@ -1818,7 +1829,7 @@ class Perl6::Actions is HLL::Actions {
$*W.pop_lexpad();
$install_in.push(PAST::Stmt.new($p_past));
my @p_params := [hash(is_capture => 1, nominal_type => $*W.find_symbol(['Mu']) )];
- my $p_sig := $*W.create_signature([$*W.create_parameter(@p_params[0])]);
+ my $p_sig := $*W.create_signature(nqp::hash('parameters', [$*W.create_parameter(@p_params[0])]));
add_signature_binding_code($p_past, $p_sig, @p_params);
$*W.create_code_object($p_past, 'Sub', $p_sig, 1);
}
@@ -1942,10 +1953,10 @@ class Perl6::Actions is HLL::Actions {
$past.nsentry('');
# Do the various tasks to trun the block into a method code object.
- my @params := $<multisig> ?? $<multisig>[0].ast !! [];
+ my %sig_info := $<multisig> ?? $<multisig>[0].ast !! hash(parameters => []);
my $inv_type := $*W.find_symbol([
$<longname> && $*W.is_lexical('$?CLASS') ?? '$?CLASS' !! 'Mu']);
- my $code := methodize_block($/, $*DECLARAND, $past, @params, $inv_type, :yada(is_yada($/)));
+ my $code := methodize_block($/, $*DECLARAND, $past, %sig_info, $inv_type, :yada(is_yada($/)));
# Document it
Perl6::Pod::document($code, $*DOC);
@@ -1998,12 +2009,17 @@ class Perl6::Actions is HLL::Actions {
if $block<placeholder_sig> && $<multisig> {
$*W.throw($/, 'X::Signature::Placeholder');
}
- my @params :=
- $<multisig> ?? $<multisig>[0].ast !!
- $block<placeholder_sig> ?? $block<placeholder_sig> !!
- [];
+ my %sig_info;
+ if $<multisig> {
+ %sig_info := $<multisig>[0].ast;
+ }
+ else {
+ %sig_info<parameters> := $block<placeholder_sig> ?? $block<placeholder_sig> !!
+ [];
+ }
+ my @params := %sig_info<parameters>;
set_default_parameter_type(@params, 'Any');
- my $signature := create_signature_object($<multisig> ?? $<multisig>[0] !! $/, @params, $block);
+ my $signature := create_signature_object($<multisig> ?? $<multisig>[0] !! $/, %sig_info, $block);
add_signature_binding_code($block, $signature, @params);
# Create code object.
@@ -2065,8 +2081,9 @@ class Perl6::Actions is HLL::Actions {
make $closure;
}
- sub methodize_block($/, $code, $past, @params, $invocant_type, :$yada) {
+ sub methodize_block($/, $code, $past, %sig_info, $invocant_type, :$yada) {
# Get signature and ensure it has an invocant and *%_.
+ my @params := %sig_info<parameters>;
if $past<placeholder_sig> {
$/.CURSOR.panic('Placeholder variables cannot be used in a method');
}
@@ -2089,7 +2106,7 @@ class Perl6::Actions is HLL::Actions {
$past.symbol('%_', :scope('lexical_6model'));
}
set_default_parameter_type(@params, 'Any');
- my $signature := create_signature_object($/, @params, $past);
+ my $signature := create_signature_object($/, %sig_info, $past);
add_signature_binding_code($past, $signature, @params);
# Place to store invocant.
@@ -2210,7 +2227,7 @@ class Perl6::Actions is HLL::Actions {
my $coderef;
my $name := ~%*RX<name>;
- my @params := $<signature> ?? $<signature>[0].ast !! [];
+ my %sig_info := $<signature> ?? $<signature>[0].ast !! hash(parameters => []);
if $*MULTINESS eq 'proto' {
unless $<onlystar> {
$/.CURSOR.panic("Proto regex body must be \{*\} (or <*> or <...>, which are deprecated)");
@@ -2219,9 +2236,9 @@ class Perl6::Actions is HLL::Actions {
:pasttype('callmethod'), :name('!protoregex'),
PAST::Var.new( :name('self'), :scope('register') ),
$name);
- $coderef := regex_coderef($/, $*DECLARAND, $proto_body, $*SCOPE, $name, @params, $*CURPAD, $<trait>, :proto(1));
+ $coderef := regex_coderef($/, $*DECLARAND, $proto_body, $*SCOPE, $name, %sig_info, $*CURPAD, $<trait>, :proto(1));
} else {
- $coderef := regex_coderef($/, $*DECLARAND, $<p6regex>.ast, $*SCOPE, $name, @params, $*CURPAD, $<trait>);
+ $coderef := regex_coderef($/, $*DECLARAND, $<p6regex>.ast, $*SCOPE, $name, %sig_info, $*CURPAD, $<trait>);
}
# Return closure if not in sink context.
@@ -2230,7 +2247,7 @@ class Perl6::Actions is HLL::Actions {
make $closure;
}
- sub regex_coderef($/, $code, $qast, $scope, $name, @params, $block, $traits?, :$proto, :$use_outer_match) {
+ sub regex_coderef($/, $code, $qast, $scope, $name, %sig_info, $block, $traits?, :$proto, :$use_outer_match) {
# create a code reference from a regex qast tree
my $past;
if $proto {
@@ -2262,7 +2279,7 @@ class Perl6::Actions is HLL::Actions {
# Do the various tasks to turn the block into a method code object.
my $inv_type := $*W.find_symbol([ # XXX Maybe Cursor below, not Mu...
$name && $*W.is_lexical('$?CLASS') ?? '$?CLASS' !! 'Mu']);
- methodize_block($/, $code, $past, @params, $inv_type);
+ methodize_block($/, $code, $past, %sig_info, $inv_type);
# Need to put self into a register for the regex engine.
$past[0].push(PAST::Var.new(
@@ -2534,9 +2551,10 @@ class Perl6::Actions is HLL::Actions {
}
method fakesignature($/) {
- my @params := $<signature>.ast;
+ my %sig_info := $<signature>.ast;
+ my @params := %sig_info<parameters>;
set_default_parameter_type(@params, 'Mu');
- my $sig := create_signature_object($/, @params, $*FAKE_PAD, :no_attr_check(1));
+ my $sig := create_signature_object($/, %sig_info, $*FAKE_PAD, :no_attr_check(1));
my $past := $*W.get_ref($sig);
$past<has_compile_time_value> := 1;
$past<compile_time_value> := $sig;
@@ -2545,6 +2563,9 @@ class Perl6::Actions is HLL::Actions {
method signature($/) {
# Fix up parameters with flags according to the separators.
+ # TODO: Handle $<typename>, which contains the return type declared
+ # with the --> syntax.
+ my %signature;
my @parameter_infos;
my $param_idx := 0;
my $multi_invocant := 1;
@@ -2564,12 +2585,16 @@ class Perl6::Actions is HLL::Actions {
@parameter_infos.push(%info);
$param_idx := $param_idx + 1;
}
+ %signature<parameters> := @parameter_infos;
+ if $<typename> {
+ %signature<returns> := $<typename>[0].ast;
+ }
# Mark current block as having a signature.
$*W.mark_cur_lexpad_signatured();
# Result is set of parameter descriptors.
- make @parameter_infos;
+ make %signature;
}
method parameter($/) {
@@ -2822,7 +2847,7 @@ class Perl6::Actions is HLL::Actions {
$_<nominal_type> := $type;
}
if nqp::existskey($_, 'sub_signature_params') {
- set_default_parameter_type($_<sub_signature_params>, $type_name);
+ set_default_parameter_type($_<sub_signature_params><parameters>, $type_name);
}
}
}
@@ -2830,10 +2855,10 @@ class Perl6::Actions is HLL::Actions {
# Create Parameter objects, along with container descriptors
# if needed. Parameters will be bound into the specified
# lexpad.
- sub create_signature_object($/, @parameter_infos, $lexpad, :$no_attr_check) {
+ sub create_signature_object($/, %signature_info, $lexpad, :$no_attr_check) {
my @parameters;
my %seen_names;
- for @parameter_infos {
+ for %signature_info<parameters> {
# Check we don't have duplicated named parameter names.
if $_<named_names> {
for $_<named_names> {
@@ -2876,7 +2901,8 @@ class Perl6::Actions is HLL::Actions {
# Add it to the signature.
@parameters.push($param_obj);
}
- $*W.create_signature(@parameters)
+ %signature_info<parameters> := @parameters;
+ $*W.create_signature(%signature_info)
}
method trait($/) {
@@ -4481,8 +4507,10 @@ class Perl6::Actions is HLL::Actions {
}
method quote:sym</ />($/) {
my $block := PAST::Block.new(PAST::Stmts.new, PAST::Stmts.new, :node($/));
+ my %sig_info := hash(parameters => []);
+ %sig_info<parameters> := [];
my $coderef := regex_coderef($/, $*W.stub_code_object('Regex'),
- $<p6regex>.ast, 'anon', '', [], $block, :use_outer_match(1));
+ $<p6regex>.ast, 'anon', '', %sig_info, $block, :use_outer_match(1));
# Return closure if not in sink context.
my $closure := block_closure($coderef);
$closure<sink_past> := PAST::Op.new( :pasttype('null') );
@@ -4492,14 +4520,16 @@ class Perl6::Actions is HLL::Actions {
method quote:sym<rx>($/) {
my $block := PAST::Block.new(PAST::Stmts.new, PAST::Stmts.new, :node($/));
self.handle_and_check_adverbs($/, %SHARED_ALLOWED_ADVERBS, 'rx', $block);
+ my %sig_info := hash(parameters => []);
my $coderef := regex_coderef($/, $*W.stub_code_object('Regex'),
- $<p6regex>.ast, 'anon', '', [], $block, :use_outer_match(1));
+ $<p6regex>.ast, 'anon', '', %sig_info, $block, :use_outer_match(1));
make block_closure($coderef);
}
method quote:sym<m>($/) {
my $block := PAST::Block.new(PAST::Stmts.new, PAST::Stmts.new, :node($/));
+ my %sig_info := hash(parameters => []);
my $coderef := regex_coderef($/, $*W.stub_code_object('Regex'),
- $<p6regex>.ast, 'anon', '', [], $block, :use_outer_match(1));
+ $<p6regex>.ast, 'anon', '', %sig_info, $block, :use_outer_match(1));
my $past := PAST::Op.new(
:node($/),
@@ -4542,8 +4572,9 @@ class Perl6::Actions is HLL::Actions {
# Build the regex.
my $rx_block := PAST::Block.new(PAST::Stmts.new, PAST::Stmts.new, :node($/));
+ my %sig_info := hash(parameters => []);
my $rx_coderef := regex_coderef($/, $*W.stub_code_object('Regex'),
- $<p6regex>.ast, 'anon', '', [], $rx_block, :use_outer_match(1));
+ $<p6regex>.ast, 'anon', '', %sig_info, $rx_block, :use_outer_match(1));
# Quote needs to be closure-i-fied.
my $closure := block_closure(make_thunk_ref($<quote_EXPR> ?? $<quote_EXPR>.ast !! $<EXPR>.ast, $/));
@@ -4808,7 +4839,7 @@ class Perl6::Actions is HLL::Actions {
} else {
$param<is_parcel> := 1;
}
- my $sig := $*W.create_signature([$*W.create_parameter($param)]);
+ my $sig := $*W.create_signature(nqp::hash('parameters', [$*W.create_parameter($param)]));
add_signature_binding_code($block, $sig, [$param]);
return reference_to_code_object(
$*W.create_code_object($block, 'Block', $sig),
@@ -4839,8 +4870,7 @@ class Perl6::Actions is HLL::Actions {
my $param := hash(
variable_name => '$_',
nominal_type => $*W.find_symbol(['Mu']));
- my $sig := $*W.create_signature([
- $*W.create_parameter($param)]);
+ my $sig := $*W.create_signature(nqp::hash('parameters', [$*W.create_parameter($param)]));
add_signature_binding_code($past, $sig, [$param]);
return $*W.create_code_object($past, 'Block', $sig);
}
@@ -5006,10 +5036,10 @@ class Perl6::Actions is HLL::Actions {
hash( is_invocant => 1, nominal_type => $*PACKAGE),
hash( variable_name => '$_', nominal_type => $*W.find_symbol(['Mu']))
];
- my $sig := $*W.create_signature([
+ my $sig := $*W.create_signature(nqp::hash('parameters', [
$*W.create_parameter(@params[0]),
$*W.create_parameter(@params[1])
- ]);
+ ]));
$block[0].push(PAST::Var.new( :name('self'), :scope('lexical_6model'), :isdecl(1) ));
$block[0].push(PAST::Var.new( :name('$_'), :scope('lexical_6model'), :isdecl(1) ));
$block.push(PAST::Stmts.new( $initializer ));
@@ -5120,7 +5150,8 @@ class Perl6::Actions is HLL::Actions {
}
$i++;
}
- my $signature := create_signature_object($/, @params, $block);
+ my %sig_info := hash(parameters => @params);
+ my $signature := create_signature_object($/, %sig_info, $block);
add_signature_binding_code($block, $signature, @params);
my $code := $*W.create_code_object($block, 'WhateverCode', $signature);
$past := block_closure(reference_to_code_object($code, $block));
diff --git a/src/Perl6/World.pm b/src/Perl6/World.pm
index 55e76aa..8733c56 100644
--- a/src/Perl6/World.pm
+++ b/src/Perl6/World.pm
@@ -567,14 +567,18 @@ class Perl6::World is HLL::World {
}
# Creates a signature object from a set of parameters.
- method create_signature(@parameters) {
+ method create_signature(%signature_info) {
# Create signature object now.
- my $sig_type := self.find_symbol(['Signature']);
- my $signature := nqp::create($sig_type);
+ my $sig_type := self.find_symbol(['Signature']);
+ my $signature := nqp::create($sig_type);
+ my @parameters := %signature_info<parameters>;
self.add_object($signature);
# Set parameters.
nqp::bindattr($signature, $sig_type, '$!params', @parameters);
+ if %signature_info<returns> {
+ nqp::bindattr($signature, $sig_type, '$!returns', %signature_info<returns>);
+ }
# Return created signature.
$signature
@@ -597,7 +601,7 @@ class Perl6::World is HLL::World {
# Creates a simple code object with an empty signature
method create_simple_code_object($block, $type) {
self.cur_lexpad()[0].push($block);
- my $sig := self.create_signature([]);
+ my $sig := self.create_signature(nqp::hash('parameters', []));
return self.create_code_object($block, $type, $sig);
}
@@ -878,7 +882,7 @@ class Perl6::World is HLL::World {
# Add as phaser.
$block[0].push($phaser_block);
self.add_phaser($/, $phaser,
- self.create_code_object($phaser_block, 'Code', self.create_signature([])));
+ self.create_code_object($phaser_block, 'Code', self.create_signature(nqp::hash('parameters', []))));
}
# Adds a multi candidate to a proto/dispatch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment