# NOTE: if you're adding / adapting tests here, you probably want to do # the same in t/12-rakuast/strings.t use v6.e.PREVIEW; use Test; plan 12; my $ast; my $deparsed; my $raku; my @type = ; sub ast(RakuAST::Node:D $node --> Nil) { $ast := $node; $deparsed := $ast.DEPARSE; $raku := 'use experimental :rakuast; ' ~ $ast.raku; diag $deparsed.chomp; } subtest 'One-part heredoc with literal piece' => { # "hello\n\ngoodbye\n" ast RakuAST::Heredoc.new( # :segments[RakuAST::StrLiteral.new(" hello\n\n goodbye\n")], # XX enable after trimfix :segments[RakuAST::StrLiteral.new("hello\n\ngoodbye\n")], :stop(" CODE\n") ); is-deeply $deparsed, "qq:to/CODE/\n hello\n\n goodbye\n CODE\n", 'deparse'; is-deeply $_, "hello\n\ngoodbye\n", @type[$++] for EVAL($ast), EVAL($deparsed), EVAL(EVAL $raku); } subtest 'Heredoc with interpolated string variable works' => { my $str = 'hello,'; # "$str world\n" ast RakuAST::Heredoc.new( :segments[ RakuAST::Var::Lexical.new('$str'), RakuAST::StrLiteral.new(" world\n") ], :stop("MESSAGE\n") ); is-deeply $deparsed, qq:!s|qq:to/MESSAGE/\n$str world\nMESSAGE\n|, 'deparse'; is-deeply $_, "hello, world\n", @type[$++] for EVAL($ast), EVAL($deparsed), EVAL(EVAL $raku); } subtest 'Heredoc with interpolated integer variable' => { my $int = 42; # "$int is the answer\n" ast RakuAST::Heredoc.new( :segments[ # RakuAST::StrLiteral.new(" "), # XXX enable after trim fix RakuAST::Var::Lexical.new('$int'), RakuAST::StrLiteral.new(" is the answer\n") ], :stop(" INTY\n") ); is-deeply $deparsed, qq:!s|qq:to/INTY/\n $int is the answer\n INTY\n|, 'deparse'; is-deeply $_, "42 is the answer\n", @type[$++] for EVAL($ast), EVAL($deparsed), EVAL(EVAL $raku); } subtest 'Heredoc with 3 parts works' => { my $int = 42; # "The answer is $int of course" ast RakuAST::Heredoc.new( :segments[ # RakuAST::StrLiteral.new(' The answer is '), # XXX enable after trim fix RakuAST::StrLiteral.new('The answer is '), RakuAST::Var::Lexical.new('$int'), RakuAST::StrLiteral.new(" of course!\n") ], :stop(" MORE\n") ); is-deeply $deparsed, qq:!s|qq:to/MORE/\n The answer is $int of course!\n MORE\n|, 'deparse'; is-deeply $_, "The answer is 42 of course!\n", @type[$++] for EVAL($ast), EVAL($deparsed), EVAL(EVAL $raku); } subtest 'Heredoc involving an interpolated block' => { my $bv = 'interpolated'; # "An { $bv } block\n" ast RakuAST::Heredoc.new( :segments[ RakuAST::StrLiteral.new('An '), RakuAST::Block.new( body => RakuAST::Blockoid.new( RakuAST::StatementList.new( RakuAST::Statement::Expression.new( expression => RakuAST::Var::Lexical.new('$bv') ) ) ) ), RakuAST::StrLiteral.new(" block\n") ], :stop("\n") ); is-deeply $deparsed, qq:!s:!c|qq:to//\nAn {\n $bv\n} block\n\n|, 'deparse'; is-deeply $_, "An interpolated block\n", @type[$++] for EVAL($ast), EVAL($deparsed), EVAL(EVAL $raku); } subtest 'words processor splits a heredoc into words' => { # qqw/ foo bar 42 / ast RakuAST::Heredoc.new( :segments[RakuAST::StrLiteral.new("foo bar 42\n")], :processors['words'], :stop("WORDS\n") ); is-deeply $deparsed, qq|qq:w:to/WORDS/\nfoo bar 42\nWORDS\n|, 'deparse'; is-deeply $_, ("foo", "bar", "42"), @type[$++] for EVAL($ast), EVAL($deparsed), EVAL(EVAL $raku); } subtest 'Words processor applied to a heredoc with interpolation' => { my $stuff = 'r baz'; # qqw/ ba$stuff 66 / ast RakuAST::Heredoc.new( :segments[ RakuAST::StrLiteral.new('ba'), RakuAST::Var::Lexical.new('$stuff'), RakuAST::StrLiteral.new(" 66\n") ], :processors['words'], :stop("WORDS\n") ); is-deeply $deparsed, qq:!s|qq:w:to/WORDS/\nba$stuff 66\nWORDS\n|, 'deparse'; is-deeply $_, ("bar", "baz", "66"), @type[$++] for EVAL($ast), EVAL($deparsed), EVAL(EVAL $raku); } subtest 'Using the val processor alone on a heredoc' => { # qq:v/42/ ast RakuAST::Heredoc.new( :segments[RakuAST::StrLiteral.new("42\n")], :processors['val'], :stop("VAL\n") ); is-deeply $deparsed, qq|qq:v:to/VAL/\n42\nVAL\n|, 'deparse'; for 'AST', $ast, 'Str', $deparsed, 'Raku', EVAL($raku) -> $type, $it { todo("problem in parsing static heredocs and :v") if $type eq 'Str' | 'Raku'; is-deeply EVAL($it), IntStr.new(42,"42\n"), $type; } } subtest 'Using the val processor in heredoc with interpolation' => { my $end = '6'; # qq:v/4$end/ ast RakuAST::Heredoc.new( :segments[ RakuAST::StrLiteral.new('4'), RakuAST::Var::Lexical.new('$end'), RakuAST::StrLiteral.new("\n") ], :processors['val'], :stop("VAL\n") ); is-deeply $deparsed, qq:!s|qq:v:to/VAL/\n4$end\nVAL\n|, 'deparse'; is-deeply $_, IntStr.new(46,"46\n"), @type[$++] for EVAL($ast), EVAL($deparsed), EVAL(EVAL $raku); } subtest 'Using the words and val processor in a heredoc' => { # ast RakuAST::Heredoc.new( :segments[RakuAST::StrLiteral.new("foo bar 42\n")], :processors['words', 'val'], :stop("VALS\n") ); is-deeply $deparsed, qq|qq:w:v:to/VALS/\nfoo bar 42\nVALS\n|, 'deparse'; is-deeply $_, ("foo", "bar", IntStr.new(42,"42")), @type[$++] for EVAL($ast), EVAL($deparsed), EVAL(EVAL $raku); } subtest 'Words processor applied to a heredoc with interpolation' => { my $stuff = 'r baz'; # qq:w:v/ba$stuff 66/ ast RakuAST::Heredoc.new( :segments[ RakuAST::StrLiteral.new('ba'), RakuAST::Var::Lexical.new('$stuff'), RakuAST::StrLiteral.new(" 66\n") ], :processors['words', 'val'], :stop("HUH\n") ); is-deeply $deparsed, qq:!s|qq:w:v:to/HUH/\nba$stuff 66\nHUH\n|, 'deparse'; is-deeply $_, ('bar', 'baz', IntStr.new(66,"66")), @type[$++] for EVAL($ast), EVAL($deparsed), EVAL(EVAL $raku); } subtest 'Using the exec processor alone gives expected result' => { # qx/ echo 123 / ast RakuAST::Heredoc.new( :segments[RakuAST::StrLiteral.new('echo 123')], :processors['exec'], :stop("GO\n") ); is-deeply $deparsed, qq|qq:x:to/GO/\necho 123\nGO\n|, 'deparse'; is-deeply $_, "123\n", @type[$++] for EVAL($ast), EVAL($deparsed), EVAL(EVAL $raku); } # vim: expandtab shiftwidth=4