### ----------------------------------------------------
### -- Polyglot::Regexen
### -- Licenses: Artistic-2.0
### -- Authors: Matthew Stuckwisch
### -- File: t/ecma/09-role.rakutest
### ----------------------------------------------------
use v6.d;
use Polyglot::Regex::ECMA262::Grammar:auth<zef:guifa>;
use Polyglot::Regex::ECMA262::Actions:auth<zef:guifa>;
use Polyglot::Regex::ECMA262::Role:auth<zef:guifa>;
use Test;

sub ecma($regex) {
    grammar G does ECMA262-Regex         { token  TOP      { <ECMA262-Regex-TOP>            } }
    class   A does ECMA262-Regex-Actions { method TOP ($/) { make $<ECMA262-Regex-TOP>.made } }
    use MONKEY-SEE-NO-EVAL;
    use experimental :rakuast;

    EVAL RakuAST::QuotedRegex.new(body => G.parse($regex, :actions(A)).made);
}

subtest 'Pretty print' => {
    'a' ~~ ecma '(a)';
    is $/.gist ~ "\n", q:to/END/;
        ｢a｣ ᴇᴄᴍᴀ
         1 => ｢a｣
        END

    'a' ~~ ecma '(?<A>a)';
    is $/.gist ~ "\n", q:to/END/;
        ｢a｣ ᴇᴄᴍᴀ
         1<A> => ｢a｣
        END

    'abcdefg' ~~ ecma '(?<A>a(b(c)))(?<D>d(?:e))(?:f)(g)';
    is $/.gist ~ "\n", q:to/END/;
        ｢abcdefg｣ ᴇᴄᴍᴀ
         1<A> => ｢abc｣
         2 => ｢bc｣
         3 => ｢c｣
         4<D> => ｢de｣
         5 => ｢g｣
        END
}
subtest 'Match variable functionality' => {
    'abcd' ~~ ecma '(a)(b)(?<c>c)(?<d>d)';
    ok  $/ ~~ Match;
    ok  $/ ~~ ECMA262-Regex-Match;
    is ~$0,   'abcd';
    is ~$1,   'a';
    is ~$2,   'b';
    is ~$<c>, 'c';
    is ~$<d>, 'd';
};
subtest 'Positional matches' => {
    'abc' ~~ ecma '(a)(b)(c)';
    ok $/.list ~~ <abc a b c>, 'Sequential';

    'abc' ~~ ecma '(a(b))c';
    ok $/.list ~~ <abc ab b>, 'Simple embedded';

    'abcde' ~~ ecma 'a(b(c(d(e))))';
    ok $/.list ~~ <abcde bcde cde de e>, 'Deep right embedded';

    'abcde' ~~ ecma '((((a)b)c)d)e';
    ok $/.list ~~ <abcde abcd abc ab a>, 'Deep left embedded';

    'abcdefghij' ~~ ecma '((((a)b)(c((d)e)f)g(h))i)j';
    ok $/.list ~~ <abcdefghij abcdefghi abcdefgh ab a cdef de d h>, 'Complex embedded';
}

subtest 'Named matches' => {
    my &hashy = { %($^hash.hash.map: {.key => ~.value}) };

    'abc' ~~ ecma '(?<a>a)(?<b>b)(?<c>c)';
    ok $/.&hashy ~~ %(<a a b b c c>), 'Sequential';

    'abc' ~~ ecma '(?<a>a(?<b>b))c';
    ok $/.&hashy ~~ %(<a ab b b>), 'Simple embedded';

    'abcde' ~~ ecma 'a(?<b>b(?<c>c(?<d>d(?<e>e))))';
    ok $/.&hashy ~~ %(<b bcde c cde d de e e>), 'Deep right embedded';

    'abcde' ~~ ecma '(?<d>(?<c>(?<b>(?<a>a)b)c)d)e';
    ok $/.&hashy ~~ %(<d abcd c abc b ab a a>), 'Deep left embedded';

    'abcdefghij' ~~ ecma '(?<i>(?<g>(?<b>(?<a>a)b)(?<c>c(?<e>(?<d>d)e)f)g(?<h>h))i)';
    say $*ERR, $/.&hashy;
    ok $/.&hashy ~~ %(<a a  b ab  c cdef  d d  e de  g abcdefgh  h h  i abcdefghi>), 'Complex embedded';
}

subtest 'Positional match backreferences' => {
    'aa' ~~ ecma '(a)\1';
    ok $/.list ~~ <aa a>, 'Sequential';

    'abb' ~~ ecma '(a(b))\2';
    ok $/.list ~~ <abb ab b>, 'Simple embedded';

    'abcdee' ~~ ecma 'a(b(c(d(e))))\4';
    ok $/.list ~~ <abcdee bcde cde de e>, 'Deep right embedded';

    'abcdea' ~~ ecma '((((a)b)c)d)e\4';
    ok $/.list ~~ <abcdea abcd abc ab a>, 'Deep left embedded';
    'abcdefghijh' ~~ ecma '((((a)b)(c((d)e)f)g(h))i)j\8';
    ok $/.list ~~ <abcdefghijh abcdefghi abcdefgh ab a cdef de d h>, 'Complex embedded';

    'aabb' ~~ ecma '(a)\1(b)\2';
    ok $/.list ~~ <aabb a b>, 'Multi sequential';
}

subtest 'Named match backreferences' => {

    my &hashy = { %($^hash.hash.map: {.key => ~.value}) };

    'aa' ~~ ecma '(?<a>a)\k<a>';
    ok $/.&hashy ~~ %(<a a>), 'Sequential';

    'abb' ~~ ecma '(?<a>a(?<b>b))\k<b>';
    ok $/.&hashy ~~ %(<a ab b b>), 'Simple embedded';

    'abcdee' ~~ ecma 'a(?<b>b(?<c>c(?<d>d(?<e>e))))\k<e>';
    ok $/.&hashy ~~ %(<b bcde c cde d de e e>), 'Deep right embedded';

    'abcdea' ~~ ecma '(?<d>(?<c>(?<b>(?<a>a)b)c)d)e\k<a>';
    ok $/.&hashy ~~ %(<d abcd c abc b ab a a>), 'Deep left embedded';

    'abcdefghijh' ~~ ecma '(?<i>(?<g>(?<b>(?<a>a)b)(?<c>c(?<e>(?<d>d)e)f)g(?<h>h))i)j\k<h>';
    ok $/.&hashy ~~ %(<a a  b ab  c cdef  d d  e de  g abcdefgh  h h  i abcdefghi>), 'Complex embedded';

    'aabb' ~~ ecma '(?<a>a)\k<a>(?<b>b)\k<b>';
    ok $/.&hashy ~~ %(<a a b b>), 'Multi sequential';
}

done-testing


