diff --git a/Niecza/Actions.pm b/Niecza/Actions.pm index 53161b91..9a632098 100644 --- a/Niecza/Actions.pm +++ b/Niecza/Actions.pm @@ -186,7 +186,7 @@ sub quote__S_Slash_Slash { my ($cl, $M) = @_; my $slot = $cl->gensym; # TODO should be a real pass. local $::parenid = 0; - $M->{_ast} = RxOp::Export->new(zyg => [$M->{nibble}{_ast}])->closure; + $M->{_ast} = $M->{nibble}{_ast}->close_rx; } sub regex_block { my ($cl, $M) = @_; @@ -209,7 +209,6 @@ sub regex_def { my ($cl, $M) = @_; my $sig = $M->{signature}[0] ? $M->{signature}[0]{_ast} : $cl->get_placeholder_sig($M); - $sig = $sig->for_regex; if ($scope =~ /state|augment|supercede/) { $M->sorry("Nonsensical scope $scope for regex"); @@ -220,13 +219,14 @@ sub regex_def { my ($cl, $M) = @_; : '&' . $name; local $::parenid = 0; + my ($cn, $op) = $M->{regex_block}{_ast}->term_rx; $M->{_ast} = Op::SubDef->new( var => $var, class => 'Regex', method_too => ($scope eq 'has' ? $name : undef), body => Body->new( type => 'regex', - signature => $sig, - do => RxOp::Export->new(zyg => [$M->{regex_block}{_ast}])->op)); + signature => $sig->for_regex($cn), + do => $op)); } sub regex_declarator { my ($cl, $M) = @_; diff --git a/RxOp.pm b/RxOp.pm index d68e6171..c89a78af 100644 --- a/RxOp.pm +++ b/RxOp.pm @@ -11,41 +11,49 @@ use CgOp; has zyg => (isa => 'ArrayRef[RxOp]', is => 'ro', default => sub { [] }); - my $i = 0; - sub _closurize { - my ($self, $op) = @_; - Op::SubDef->new(var => 'rx!' . ($i++), class => 'Regex', body => - Body->new( - type => 'regex', - signature => Sig->simple('$¢'), -# XXX transparent bodies with signatures are not yet handled well -# transparent => 1, + # op(cn, cont): provides cn in environment, calls cont per result, then + # returns; -> (cn, cont) + # closure: like op but just returns a function, takes cn/cont though + + sub _close { + my ($self, $type, $parms, $op) = @_; + Op::SubDef->new(var => Niecza::Actions->gensym, class => ucfirst($type), + body => Body->new( + type => $type, + signature => Sig->simple(@$parms), do => $op)); } - sub closure { - my ($self) = @_; - $self->_closurize($self->op); + sub _close_k { + my ($self, $cn, $cont) = @_; + $self->_close('sub', [$cn], $cont); } - __PACKAGE__->meta->make_immutable; - no Moose; -} - -{ - package RxOp::String; - use Moose; - extends 'RxOp'; + sub _close_op { + my ($self, $op) = @_; + my $icn = Niecza::Actions->gensym; + my $icv = Niecza::Actions->gensym; + my $icont = Op::CallSub->new( + invocant => Op::Lexical->new(name => $icv), + positionals => [ Op::Lexical->new(name => $icn) ]); + my ($cn, $cont) = $op->op($icn, $icont); + $self->_close('sub', [$cn, $icv], $cont); + } - has text => (isa => 'Str', is => 'ro', required => 1); + sub term_rx { + my ($self) = @_; + my $icn = Niecza::Actions->gensym; + my $icont = Op::Take->new(value => Op::Lexical->new(name => $icn)); + my ($cn, $cont) = $self->op($icn, $icont); + $cn, Op::Gather->new( + var => Niecza::Actions->gensym, + body => Body->new(type => 'gather', do => $cont)); + } - sub op { + sub close_rx { my ($self) = @_; - Op::CallSub->new( - invocant => Op::Lexical->new(name => '&_rxstr'), - positionals => [ - Op::Lexical->new(name => '$¢'), - Op::StringLiteral->new(text => $self->text)]); + my ($cn, $op) = $self->term_rx; + $self->_close('regex', [$cn], $op); } __PACKAGE__->meta->make_immutable; @@ -53,17 +61,22 @@ use CgOp; } { - package RxOp::Export; + package RxOp::String; use Moose; extends 'RxOp'; - # zyg * 1 + has text => (isa => 'Str', is => 'ro', required => 1); sub op { - my ($self) = @_; - Op::CallSub->new( - invocant => Op::Lexical->new(name => '&_rxexport'), - positionals => [$self->zyg->[0]->op]); + my ($self, $cn, $cont) = @_; + my $icn = Niecza::Actions->gensym; + $icn, Op::CallSub->new( + invocant => Op::Lexical->new(name => '&_rxstr'), + positionals => [ + Op::Lexical->new(name => $icn), + Op::StringLiteral->new(text => $self->text), + $self->_close_k($cn, $cont) + ]); } __PACKAGE__->meta->make_immutable; @@ -81,12 +94,14 @@ use CgOp; my %qf = ( '+', 'plus', '*', 'star', '?', 'opt' ); sub op { - my ($self) = @_; - Op::CallSub->new( + my ($self, $cn, $cont) = @_; + my $icn = Niecza::Actions->gensym; + $icn, Op::CallSub->new( invocant => Op::Lexical->new(name => '&_rx' . $qf{$self->type}), positionals => [ - Op::Lexical->new(name => '$¢'), - $self->zyg->[0]->closure]); + Op::Lexical->new(name => $icn), + $self->_close_op($self->zyg->[0]), + $self->_close_k($cn, $cont)]); } __PACKAGE__->meta->make_immutable; @@ -101,20 +116,13 @@ use CgOp; # zyg * N sub op { - my ($self) = @_; - my @zyg = map { $_->op } @{ $self->zyg }; - - while (@zyg >= 2) { - my $r = pop @zyg; - my $l = pop @zyg; - push @zyg, Op::CallSub->new( - invocant => Op::Lexical->new(name => '&_rxlazymap'), - positionals => [ $l, $self->_closurize($r) ]); + my ($self, $cn, $cont) = @_; + + for (reverse @{ $self->zyg }) { + ($cn, $cont) = $_->op($cn, $cont); } - $zyg[0] || Op::CallSub->new( - invocant => Op::Lexical->new(name => '&_rxone'), - positionals => [ Op::Lexical->new(name => '$¢') ]); + $cn, $cont; } __PACKAGE__->meta->make_immutable; diff --git a/SAFE.setting b/SAFE.setting index 3fe658f7..fb073c72 100644 --- a/SAFE.setting +++ b/SAFE.setting @@ -887,75 +887,29 @@ my class Cursor { (cast Int32 (unbox Double (@ (l $np)))))) } } } -# Outside a regex, a result is a lazy list. -# Inside a regex, a result is a coroutiney thing (details will change) - -sub _rxexport($cs) { unfold({ $cs() // EMPTY }) } - -sub _rxlazymap($cs, $sub) { - my $k = sub { Any }; - #say "in rxlazymap (1)"; - sub get() { - #say "in rxlazymap (2)"; - $k && ($k() || do { - #say "in rxlazymap (3)"; - $k = $cs(); - $k = ($k && $sub($k)); - #say "in rxlazymap (4)"; - get(); - }) - } -} - -sub _rxdisj($cs1, $cs2) { - my $k1 = $cs1; - my $k2 = $cs2; - sub { - #say "in rxdisj (1)"; - $k1() || ($k2 && do { - $k1 = $k2; - $k2 = Any; - #say "in rxdisj (2)"; - $k1(); - }) - } -} - -sub _rxone($C) { - my $k = $C; - sub { - my $x = $k; - $k = Any; - #say "in rxone" ~ $x; - $x; - } -} - -sub _rxnone { Any }; - -sub _rxstar($C, $sub) { - #say "in rxstar recursion"; - _rxdisj(_rxlazymap($sub($C), sub ($C) { _rxstar($C, $sub) }), - _rxone($C)); +sub _rxstar($C, $f, $k) { + $f($C, -> $nC { _rxstar($nC, $f, $k) }); + $k($C); } -sub _rxopt($C, $sub) { - _rxdisj($sub($C), _rxone($C)) +sub _rxopt($C, $f, $k) { + $f($C, $k); + $k($C); } -sub _rxplus($C, $sub) { - _rxlazymap($sub($C), sub ($C) { _rxstar($C, $sub) }) +sub _rxplus($C, $f, $k) { + $f($C, -> $nC { _rxstar($nC, $f, $k) }); } -sub _rxstr($C, $str) { +sub _rxstr($C, $str, $k) { #say "_rxstr : " ~ ($C.str ~ (" @ " ~ ($C.from ~ (" ? " ~ $str)))); Q:CgOp { (letn rt (rawcall (unbox Cursor (@ (l $C))) Exact (unbox String (@ (l $str)))) [ternary (!= (l rt) (null Cursor)) - (subcall (@ (l &_rxone)) (box (@ (l $C)) (l rt))) - (l &_rxnone)]) + (subcall (@ (l $k)) (box (@ (l $C)) (l rt))) + (null Variable)]) }; } diff --git a/Sig.pm b/Sig.pm index af80c573..ef1e306f 100644 --- a/Sig.pm +++ b/Sig.pm @@ -132,8 +132,8 @@ use 5.010; } sub for_regex { - my $self = shift; - my $sp = Sig::Parameter->new(slot => '$¢', name => '$¢'); + my ($self, $cn) = @_; + my $sp = Sig::Parameter->new(slot => $cn, name => '$¢'); Sig->new(params => [ $sp, @{ $self->params } ]); }