use v6-alpha; use Test; plan 111; my $foo = "FOO"; my $bar = "BAR"; =kwid Tests quoting constructs as defined in L =todo * q:t - heredocs (done) * q:n, q:b, and other interpolation levels (half-done) * meaningful quotations (qx, rx, etc) * review shell quoting semantics of «» * arrays in «» * interpolation of scalar, array, hash, function and closure syntaxes * q : a d verb s // parsing =cut # L { my $s = q{ foo bar }; is $s, ' foo bar ', 'string using q{}'; } { my $s = q「this is a string」; is $s, 'this is a string', 'q-style string with LEFT/RIGHT CORNER BRACKET'; } { my $s = q『blah blah blah』; is $s, 'blah blah blah', 'q-style string with LEFT/RIGHT WHITE CORNER BRACKET'; } { my @list = 'a'..'c'; my $var = @list[ q(2) ]; is $var, 'c', 'q-style string with FULLWIDTH LEFT/RIGHT PARENTHESIS'; $var = @list[ q《0》]; is $var, 'a', 'q-style string with LEFT/RIGHT DOUBLE ANGLE BRACKET'; $var = @list[q〈1〉]; is $var, 'b', 'q-style string with LEFT/RIGHT ANGLE BRACKET'; } # L { my @q = (); @q = (q/$foo $bar/); is(+@q, 1, 'q// is singular'); is(@q[0], '$foo $bar', 'single quotes are non interpolating'); }; { # and it's complement ;-) my @q = (); @q = '$foo $bar'; is(+@q, 1, "'' is singular"); is(@q[0], '$foo $bar', 'and did not interpolate either'); }; # L # non interpolating single quotes with nested parens { my @q = (); @q = (q (($foo $bar))); is(+@q, 1, 'q (()) is singular'); is(@q[0], '$foo $bar', 'and nests parens appropriately'); }; { # non interpolating single quotes with nested parens L my @q = (); @q = (q ( ($foo $bar))); is(+@q, 1, 'q () is singular'); is(@q[0], ' ($foo $bar)', 'and nests parens appropriately'); }; { # q() is bad L my @q; sub q { @_ } @q = q($foo,$bar); is(+@q, 2, 'q() is always sub call'); }; { # adverb variation L my @q = (); @q = (q:q/$foo $bar/); is(+@q, 1, "q:q// is singular"); is(@q[0], '$foo $bar', "and again, non interpolating"); }; { # nested brackets my @q = (); @q = (q[ [$foo $bar]]); is(+@q, 1, 'q[] is singular'); is(@q[0], ' [$foo $bar]', 'and nests brackets appropriately'); }; { # nested brackets my @q = (); @q = (q[[$foo $bar]]); is(+@q, 1, 'q[[]] is singular'); is(@q[0], '$foo $bar', 'and nests brackets appropriately'); }; { # interpolating quotes L my @q = (); @q = qq/$foo $bar/; is(+@q, 1, 'qq// is singular'); is(@q[0], 'FOO BAR', 'variables were interpolated'); }; { # "" variation my @q = (); @q = "$foo $bar"; is(+@q, 1, '"" is singular'); is(@q[0], "FOO BAR", '"" interpolates'); }; { # adverb variation L my @q = (); @q = q:qq/$foo $bar/; is(+@q, 1, "q:qq// is singular"); is(@q[0], "FOO BAR", "blah blah interp"); }; { # \qq[] constructs interpolate in q[] L my( @q1, @q2, @q3, @q4 ) = (); @q1 = q[$foo \qq[$bar]]; is(+@q1, 1, "q[...\\qq[...]...] is singular"); is(@q1[0], '$foo BAR', "and interpolates correctly"); @q2 = '$foo \qq[$bar]'; is(+@q2, 1, "'...\\qq[...]...' is singular"); is(@q2[0], '$foo BAR', "and interpolates correctly"); @q3 = q[$foo \q:s{$bar}]; is(+@q3, 1, 'q[...\\q:s{...}...] is singular'); is(@q3[0], '$foo BAR', "and interpolates correctly"); @q4 = q{$foo \q/$bar/}; is(+@q4, 1, 'q{...\\q/.../...} is singular'); is(@q4[0], '$foo $bar', "and interpolates correctly"); } { # quote with \0 as delimiters L my @q = (); eval "\@q = (q\0foo bar\0)"; is(+@q, 1, "single quote with \\0 delims are parsed ok"); is(@q[0], "foo bar", "and return correct value"); }; { # traditional quote word my @q = (); @q = (qw/$foo $bar/); is(+@q, 2, "qw// is plural"); is(@q[0], '$foo', "and non interpolating"); is(@q[1], '$bar', "..."); }; { # angle brackets L my @q = (); @q = <$foo $bar>; is(+@q, 2, "<> behaves the same way"); is(@q[0], '$foo', 'for interpolation too'); is(@q[1], '$bar', '...'); }; { # angle brackets L my @q = (); @q = < $foo $bar >; is(+@q, 2, "<> behaves the same way, with leading (and trailing) whitespace"); is(@q[0], '$foo', 'for interpolation too'); is(@q[1], '$bar', '...'); }; { # adverb variation my @q = (); @q = (q:w/$foo $bar/); is(+@q, 2, "q:w// is like <>"); is(@q[0], '$foo', "..."); is(@q[1], '$bar', "..."); }; { # whitespace sep aration does not break quote constructor # L my @q = (); @q = (q :w /$foo $bar/); is(+@q, 2, "q :w // is the same as q:w//"); is(@q[0], '$foo', "..."); is(@q[1], '$bar', "..."); }; { # qq:w,Interpolating quote constructor with words adverb # L my (@q1, @q2) = (); @q1 = qq:w/$foo "gorch $bar"/; @q2 = qq:words/$foo "gorch $bar"/; is(+@q1, 3, 'qq:w// correct number of elements'); is(+@q2, 3, 'qq:words correct number of elements'); is(~@q1, 'FOO "gorch BAR"', "explicit quote word interpolates"); is(~@q2, 'FOO "gorch BAR"', "long form output is the same as the short"); }; { # qq:ww, interpolating L # L my (@q1, @q2, @q3, @q4) = (); @q1 = qq:ww/$foo "gorch $bar"/; @q2 = «$foo "gorch $bar"»; # french @q3 = <<$foo "gorch $bar">>; # texas @q4 = qq:quotewords/$foo "gorch $bar"/; # long is(+@q1, 2, 'qq:ww// correct number of elements'); is(+@q2, 2, 'french double angle'); is(+@q3, 2, 'texas double angle'); is(+@q4, 2, 'long form'); is(~@q1, 'FOO gorch BAR', "explicit quote word interpolates"); is(~@q2, 'FOO gorch BAR', "output is the same as french"); # L is(~@q3, 'FOO gorch BAR', ", texas quotes"); is(~@q4, 'FOO gorch BAR', ", and long form"); }; { #L # Pugs was having trouble with this. Fixed in r12785. my ($x, $y) = ; ok(«$x $y» === , "«$x $y» interpolation works correctly"); }; { # qw, interpolating, shell quoting L my (@q1, @q2) = (); my $gorch = "foo bar"; @q1 = «$foo $gorch $bar»; is(+@q1, 4, "4 elements in unquoted «» list"); is(@q1[2], "bar", '$gorch was exploded'); is(@q1[3], "BAR", '$bar was interpolated'); @q2 = «$foo "$gorch" '$bar'»; is(+@q2, 3, "3 elementes in sub quoted «» list"); is(@q2[1], $gorch, 'second element is both parts of $gorch, interpolated'); is(@q2[2], '$bar', 'single quoted $bar was not interpolated'); }; { # qq:t L my @q = (); @q = qq:t/FOO/; blah $bar blah $foo FOO is(+@q, 1, "q:t// is singular"); is(@q[0], "blah\nBAR\nblah\nFOO\n", "here doc interpolated"); }; { # q:t indented L my @q = (); @q = q:t/FOO/; blah blah $foo FOO is(+@q, 1, "q:t// is singular, also when indented"); is(@q[0], "blah blah\n\$foo\n", "indentation stripped"); }; { # q:to backslash bug my @q = q:to/FOO/ yoink\n splort\\n FOO ; is(+@q, 1, "q:to// is singular"); is(@q[0], "yoink\\n\nsplort\\n\n", "backslashes"); } { # q:n L my @q = (); my $backslash = "\\"; @q = (q:n/foo\\bar$foo/); is(+@q, 1, "q:n// is singular"); is(@q[0], "foo\\\\bar\$foo", "special chars are meaningless"); # double quoting is to be more explicit }; { # q:n L my @q = (); my $backslash = "\\"; @q = (qn/foo\\bar$foo/); is(+@q, 1, "qn// is singular"); is(@q[0], "foo\\\\bar\$foo", "special chars are meaningless"); # double quoting is to be more explicit }; { # L # <<:Pair>> diag "XXX: pair.perl is broken atm so these tests may be unreliable"; my @q = <<:p(1)>>; is(@q[0].perl, (:p(1)).perl, "pair inside <<>>-quotes - simple", :todo); @q = <<:p(1) junk>>; is(@q[0].perl, (:p(1)).perl, "pair inside <<>>-quotes - with some junk", :todo); is(@q[1], 'junk', "pair inside <<>>-quotes - junk preserved"); @q = <<:def>>; is(@q[0].perl, (def => 1).perl, ":pair in <<>>-quotes with no explicit value", :todo); @q = "(eval failed)"; try { eval '@q = <<:p>>;' }; is(@q[0].perl, (p => "moose").perl, ":pair", :todo); }; { # weird char escape sequences is("\d97", "a", '\d97 is "a"'); is("\d102oo", "foo", '\d102 is "f", works next to other letters'); is("\d123", chr 123, '"\dXXX" and chr XXX are equivalent'); is("\d[12]3", chr(12) ~ "3", '\d[12]3 is the same as chr(12) concatenated with "3"'); is("\d[12] 3", chr(12) ~ " 3", 'respects spaces when interpolating a space character'); is("\x41", "A", 'hex interpolation - \x41 is "A"'); is("\o101", "A", 'octal interpolation - \o101 is also "A"' ); is("\c@", "\0", 'Unicode code point "@" converts correctly to "\0"'); is("\cA", chr 1, 'Unicode "A" is #1!'); is("\cZ", chr 26, 'Unicode "Z" is chr 26 (or \d26)'); } { # simple test for nested-bracket quoting, per S02 my $hi = q<>; is($hi, "hi", 'q<> is "hi"'); } # L # q:t { my $t; $t = q:t /STREAM/; Hello, World STREAM is $t, "Hello, World\n", "Testing for q:t operator."; $t = q:t /结束/; Hello, World 结束 is $t, "Hello, World\n", "Testing for q:t operator. (utf8)"; } # q:n { my $s1 = "hello"; my $t1 = q:n /$s1, world/; is $t1, '$s1, world', "Testing for q:n operator."; my $s2 = "你好"; my $t2 = q:n /$s2, 世界/; is $t2, '$s2, 世界', "Testing for q:n operator. (utf8)"; } # q:b { my $t = q:b /\n\n\n/; is $t, "\n\n\n", "Testing for q:b operator."; } # q:x { is q:x/echo hello/, "hello\n", "Testing for q:x operator."; } # utf8 { # 一 means "One" in Chinese. is q:x/echo 一/, "一\n", "Testing for q:x operator. (utf8)"; } # L # q:h { # Pugs can't parse q:h currently. my %t = (a => "perl", b => "rocks"); my $s; $s = q:h /%t<>/; is $s, ~%t, "Testing for q:h operator."; } # q:f { sub f { "hello" }; my $t = q:f /&f(), world/; is $t, f() ~ ", world", "Testing for q:f operator."; sub f_utf8 { "你好" }; $t = q:f /&f_utf8(), 世界/; is $t, f_utf8() ~ ", 世界", "Testing for q:f operator. (utf8)"; } # q:c { sub f { "hello" }; my $t = q:c /{f}, world/; is $t, f() ~ ", world", "Testing for q:c operator."; } # q:a { my @t = qw/a b c/; my $s = q:a /@t[]/; is $s, ~@t, "Testing for q:a operator."; } # q:s { my $s = "someone is laughing"; my $t = q:s /$s/; is $t, $s, "Testing for q:s operator."; my $s = "有人在笑"; my $t = q:s /$s/; is $t, $s, "Testing for q:s operator. (utf8)"; }