Resource **pp = p;
while (*pp) {
Resource *cur = *pp;
- cur->destroy(aTHX_ cur->data);
+ if (cur->destroy) {
+ cur->destroy(aTHX_ cur->data);
+ }
cur->data = (void *)"no";
cur->destroy = NULL;
*pp = cur->next;
}
}
-static void sentinel_register(Sentinel sen, void *data, void (*destroy)(pTHX_ void *)) {
+static Resource *sentinel_register(Sentinel sen, void *data, void (*destroy)(pTHX_ void *)) {
Resource *cur;
Newx(cur, 1, Resource);
cur->destroy = destroy;
cur->next = *sen;
*sen = cur;
+
+ return cur;
+}
+
+static void sentinel_disarm(Resource *p) {
+ p->destroy = NULL;
}
static void my_sv_refcnt_dec_void(pTHX_ void *p) {
) {
I32 c;
char sigil;
- SV *name, *typeobj, *typename;
+ SV *name;
assert(!*pinit);
*pflags = 0;
if (c == '(') {
I32 floor;
OP *expr;
+ Resource *expr_sentinel;
lex_read_unichar(0);
- floor = start_subparse(FALSE, CVf_ANON);
+ floor = start_subparse(FALSE, 0);
+ SAVEFREESV(PL_compcv);
+ CvSPECIAL_on(PL_compcv);
if (!(expr = parse_fullexpr(PARSE_OPTIONAL))) {
croak("In %"SVf": invalid type expression", SVfARG(declarator));
}
- sentinel_register(sen, expr, free_op_void);
+ expr_sentinel = sentinel_register(sen, expr, free_op_void);
lex_read_space(0);
c = lex_peek_unichar(0);
lex_read_unichar(0);
lex_read_space(0);
+ SvREFCNT_inc_simple_void(PL_compcv);
+ sentinel_disarm(expr_sentinel);
*ptype = my_eval(aTHX_ sen, floor, expr);
+ *ptype = reify_type(aTHX_ sen, declarator, *ptype);
if (!sv_isobject(*ptype)) {
croak("In %"SVf": (%"SVf") doesn't look like a type object", SVfARG(declarator), SVfARG(*ptype));
}
c = lex_peek_unichar(0);
} else if (my_is_uni_xidfirst(aTHX_ c)) {
- typename = parse_type(aTHX_ sen, declarator);
+ *ptype = parse_type(aTHX_ sen, declarator);
my_require(aTHX_ "Moose/Util/TypeConstraints.pm");
- typeobj = reify_type(aTHX_ sen, declarator, typename);
- *ptype = typeobj;
+ *ptype = reify_type(aTHX_ sen, declarator, *ptype);
c = lex_peek_unichar(0);
}
--- /dev/null
+#!perl
+use warnings FATAL => 'all';
+use strict;
+
+use Test::More
+ eval { require Moose; 1 }
+ ? (tests => 49)
+ : (skip_all => "Moose required for testing types")
+;
+use Test::Fatal;
+
+use Function::Parameters qw(:strict);
+
+fun foo(Int $n, CodeRef $f, $x) {
+ $x = $f->($x) for 1 .. $n;
+ $x
+}
+
+is foo(0, fun {}, undef), undef;
+is foo(0, fun {}, "o hai"), "o hai";
+is foo(3, fun ($x) { "($x)" }, 1.5), "(((1.5)))";
+is foo(3, fun (Str $x) { "($x)" }, 1.5), "(((1.5)))";
+
+{
+ my $info = Function::Parameters::info \&foo;
+ is $info->invocant, undef;
+ is $info->slurpy, undef;
+ is $info->positional_optional, 0;
+ is $info->named_required, 0;
+ is $info->named_optional, 0;
+ my @req = $info->positional_required;
+ is @req, 3;
+ is $req[0]->name, '$n';
+ ok $req[0]->type->equals('Int');
+ is $req[1]->name, '$f';
+ ok $req[1]->type->equals('CodeRef');
+ is $req[2]->name, '$x';
+ is $req[2]->type, undef;
+}
+
+like exception { foo("ermagerd", fun {}, undef) }, qr/\bparameter 1.+\$n\b.+\bValidation failed\b.+\bInt\b.+ermagerd/;
+like exception { foo(0, {}, undef) }, qr/\bparameter 2.+\$f\b.+\bValidation failed\b.+\bCodeRef\b/;
+
+fun bar(((Function::Parameters::info(\&foo)->positional_required)[0]->type) $whoa) { $whoa * 2 }
+
+is bar(21), 42;
+{
+ my $info = Function::Parameters::info \&bar;
+ is $info->invocant, undef;
+ is $info->slurpy, undef;
+ is $info->positional_optional, 0;
+ is $info->named_required, 0;
+ is $info->named_optional, 0;
+ my @req = $info->positional_required;
+ is @req, 1;
+ is $req[0]->name, '$whoa';
+ ok $req[0]->type->equals('Int');
+}
+
+{
+ my $info = Function::Parameters::info(fun ( ArrayRef [ Int | CodeRef ]@nom) {});
+ is $info->invocant, undef;
+ is $info->positional_required, 0;
+ is $info->positional_optional, 0;
+ is $info->named_required, 0;
+ is $info->named_optional, 0;
+ my $slurpy = $info->slurpy;
+ is $slurpy->name, '@nom';
+ ok $slurpy->type->equals(Moose::Util::TypeConstraints::find_or_parse_type_constraint('ArrayRef[Int|CodeRef]'));
+}
+
+{
+ my $phase = 'runtime';
+ BEGIN { $phase = 'A'; }
+ fun
+ baz
+ (
+ (
+ is
+ (
+ $phase
+ ++
+ ,
+ 'A'
+ )
+ ,
+ 'Int'
+ )
+ :
+ $marco
+ ,
+ (
+ is
+ (
+ $phase
+ ++
+ ,
+ 'B'
+ )
+ ,
+ q
+ $ArrayRef[Str]$
+ )
+ :
+ $polo
+ )
+ {
+ [
+ $marco
+ ,
+ $polo
+ ]
+ }
+ BEGIN { is $phase, 'C'; }
+ is $phase, 'runtime';
+
+ is_deeply baz(polo => [qw(foo bar baz)], marco => 11), [11, [qw(foo bar baz)]];
+
+ my $info = Function::Parameters::info \&baz;
+ is $info->invocant, undef;
+ is $info->slurpy, undef;
+ is $info->positional_required, 0;
+ is $info->positional_optional, 0;
+ is $info->named_optional, 0;
+ my @req = $info->named_required;
+ is @req, 2;
+ is $req[0]->name, '$marco';
+ ok $req[0]->type->equals('Int');
+ is $req[1]->name, '$polo';
+ ok $req[1]->type->equals('ArrayRef[Str]');
+}