Permalink
Browse files

Implement $() @() %() special forms, make $/.ast default to undef

  • Loading branch information...
1 parent b8a5ff0 commit 45041d2562152000460e517ad75aaa03384fcbf0 @sorear committed Dec 15, 2011
Showing with 93 additions and 7 deletions.
  1. +0 −2 docs/TODO.S05
  2. +1 −4 lib/Cursor.cs
  3. +84 −0 src/niecza
  4. +1 −1 test.pl
  5. +7 −0 test2.pl
View
@@ -51,8 +51,6 @@ All line numbers are relative to c4882a67. Also, deliberate discrepencies.)
(2460) $foo ~~ rule { } does not automatically dual-anchor (DISCUSS)
(2501) No <prior> (probable fossil) DISCUSS
(2738) No success value; failed matches return Match
-(2788) $/.ast doesn't correctly return undefined
-(2789) No special case for $(), @(), %()
(2818) In list context, $match[0] will return $match if $match[0] does not
otherwise exist; useful for improving DWIM ness of lists
(2851) @<foo> does not seem to work
View
@@ -726,10 +726,7 @@ public Cursor(P6any proto, string text, P6any actions)
public string Reduced() { return reduced; }
public P6any AST() {
P6any a = (feedback != null) ? feedback.ast : ast;
- if (a != null)
- return a;
- else
- return Kernel.BoxRaw<string>(GetBacking().Substring(from, pos - from), Kernel.StrMO);
+ return a ?? Kernel.AnyMO.typeObject;
}
// TODO: cache generated lists
View
@@ -26,6 +26,90 @@ use STD;
# }
augment class NieczaActions {
+method circumfix:sigil ($/) {
+ # XXX duplicates logic in variable
+ if $<semilist>.ast.elems == 0 {
+ if $<sigil> eq '$' {
+ make ::Op::ShortCircuit.new(|node($/), kind => '//',
+ args => [ ::Op::CallMethod.new(name => 'ast',
+ receiver => mklex($/, '$/')),
+ ::Op::CallMethod.new(name => 'Str',
+ receiver => mklex($/, '$/')) ] );
+ } elsif $<sigil> eq any < @ % > {
+ make self.docontext($/, ~$<sigil>, mklex($/, '$/'));
+ } else {
+ make mklex($/, 'Mu');
+ $/.CURSOR.sorry("Missing argument for contextualizer");
+ }
+ return;
+ }
+ self.circumfix:sym<( )>($/);
+ make self.docontext($/, ~$<sigil>, $/.ast);
+}
+
+method variable($/) {
+ my $sigil = $<sigil> ?? ~$<sigil> !! substr(~$/, 0, 1);
+ my $twigil = $<twigil> ?? $<twigil>[0]<sym> !! '';
+
+ my ($name, $pkg);
+ my ($dsosl) = $<desigilname> ?? $<desigilname>.ast !!
+ $<sublongname> ?? $<sublongname>.ast !!
+ $<longname> ?? self.process_name($<longname>, :defer) !!
+ Any;
+ if defined($dsosl<ind>) {
+ make { term => self.docontext($/, $sigil, $dsosl<ind>) };
+ return;
+ } elsif defined($dsosl<iname>) {
+ make { term => ::Op::IndirectVar.new(|node($/),
+ name => mkstringycat($/, $sigil ~ $twigil, $dsosl<iname>)) };
+ return;
+ } elsif defined $dsosl {
+ ($name, $pkg) = $dsosl<name pkg>;
+ } elsif $<infixish> {
+ make { term => $<infixish>.ast.as_function($/) };
+ return;
+ } elsif $<special_variable> {
+ $name = substr(~$<special_variable>, 1);
+ } elsif $<index> {
+ make { capid => $<index>.ast, term =>
+ mkcall($/, '&postcircumfix:<[ ]>',
+ ::Op::Lexical.new(name => '$/'),
+ ::Op::Num.new(value => $<index>.ast))
+ };
+ return Nil;
+ } elsif $<postcircumfix> {
+ if $<postcircumfix>[0].reduced eq 'postcircumfix:sym<< >>' { #XXX fiddly
+ make { capid => $<postcircumfix>[0].ast.args[0].text, term =>
+ mkcall($/, '&postcircumfix:<{ }>',
+ ::Op::Lexical.new(name => '$/'),
+ @( $<postcircumfix>[0].ast.args))
+ };
+ return;
+ } else {
+ if $<postcircumfix>[0].ast.args[0] -> $arg {
+ make { term => self.docontext($/, $sigil, $arg) };
+ } elsif $sigil eq '$' {
+ make { term => ::Op::ShortCircuit.new(|node($/), kind => '//',
+ args => [ ::Op::CallMethod.new(name => 'ast',
+ receiver => mklex($/, '$/')),
+ ::Op::CallMethod.new(name => 'Str',
+ receiver => mklex($/, '$/')) ] ) };
+ } elsif $sigil eq any < @ % > {
+ make { term => self.docontext($/, $sigil, mklex($/, '$/')) };
+ } else {
+ make { term => mklex($/, 'Mu') };
+ $/.CURSOR.sorry("Missing argument for contextualizer");
+ }
+ return;
+ }
+ } else {
+ $name = '';
+ }
+
+ make {
+ sigil => $sigil, twigil => $twigil, name => $name, pkg => $pkg
+ };
+}
}
augment class RxOp::Quantifier {
View
@@ -1532,7 +1532,7 @@
{
"foo" ~~ /oo/;
- is $/.ast, 'oo', '.ast defaults to .Str';
+ ok !$/.ast.defined, '.ast defaults to undefined';
"foo" ~~ /oo { make 15 }/;
is $/.ast, 15, 'make can change .ast';
"foo" ~~ /{make 30} oo/;
View
@@ -12,6 +12,13 @@
is ("a,b,c" ~~ / <alpha>+ %% ','/), 'a,b,c', '%% works like %';
is ("a,b,c" ~~ / <alpha>* %% ','/), 'a,b,c', '% works on *';
is ("XX" ~~ / X <alpha>* %% ',' X/), 'XX', '% works on * (null string)';
+"foo" ~~ / (<.alpha>) <alpha> /;
+is $(), "fo", '$() gets the string';
+ok !$/.ast.defined, '$/.ast not defined without make';
+is @().join("|"), "f", '@() returns positional captures';
+is %().kv.join("|"), "alpha|o", '%() returns named captures';
+"bar" ~~ / { make 5 } /;
+is $(), 5, '$() gets AST';
{
my class Bt {

0 comments on commit 45041d2

Please sign in to comment.