use v6.e.PREVIEW;
use Test;

plan 11;

my $ast;
my $deparsed;
my $raku;
sub ast(RakuAST::Node:D $node --> Nil) {
    $ast      := $node;
    $deparsed := $node.DEPARSE;
    $raku     := 'use experimental :rakuast; ' ~ $node.raku;
    diag $deparsed.chomp;
}

subtest 'simple documentation' => {
    #   =begin doc␤␤  This is documentation␤␤  =end doc␤␤
    ast RakuAST::Doc::Block.new(
      margin      => '  ',
      type        => 'doc',
      paragraphs  => (
        "This is documentation\n\n",
      )
    );
    for 'Str', $deparsed, 'Raku', $raku.EVAL.DEPARSE -> $type, $it {
        is-deeply $it, q:to/CODE/, "$type: deparse";
  =begin doc

  This is documentation

  =end doc

CODE
    }
}

subtest 'simple documentation abbreviated' => {
    # =doc This is documentation␤␤
    ast RakuAST::Doc::Block.new(
      margin      => '  ',
      type        => 'doc',
      abbreviated => True,
      paragraphs  => (
        "This is documentation\n",
      )
    );
    for 'Str', $deparsed, 'Raku', $raku.EVAL.DEPARSE -> $type, $it {
        is-deeply $it, q:to/CODE/, "$type: deparse";
  =doc This is documentation
CODE
    }
}

subtest 'simple documentation with markup' => {
    #   =begin doc␤␤  This is B<doc>umentation␤␤  =end doc␤␤
    ast RakuAST::Doc::Block.new(
      margin      => '  ',
      type        => 'doc',
      paragraphs  => (
        RakuAST::Doc::Paragraph.new(
          "This is ",
          RakuAST::Doc::Markup.new(
            letter => "B",
            atoms  => (
              "doc",
            )
          ),
          "umentation\n\n",
        ),
      )
    );
    for 'Str', $deparsed, 'Raku', $raku.EVAL.DEPARSE -> $type, $it {
        is-deeply $it, q:to/CODE/, "$type: deparse";
  =begin doc

  This is B<doc>umentation

  =end doc

CODE
    }
}

subtest 'simple documentation in a statementlist (1)' => {
    # 42␤  =begin doc␤␤  This is documentation␤␤  =end doc␤␤
    ast RakuAST::StatementList.new(
      RakuAST::Statement::Expression.new(
        expression => RakuAST::IntLiteral.new(42)
      ),
      RakuAST::Doc::Block.new(
        margin      => '  ',
        type        => 'doc',
        paragraphs  => (
          "This is documentation\n\n",
        )
      )
    );
    is-deeply $ast.EVAL, 42, 'do we get the final result';
    for 'Str', $deparsed, 'Raku', $raku.EVAL.DEPARSE -> $type, $it {
        is-deeply $it, q:to/CODE/, "$type: deparse";
42
  =begin doc

  This is documentation

  =end doc

CODE
    }
}

subtest 'simple documentation in a statementlist (2)' => {
    #   =begin doc␤␤  This is documentation␤␤=  end doc␤␤42␤
    ast RakuAST::StatementList.new(
      RakuAST::Doc::Block.new(
        margin      => '  ',
        type        => 'doc',
        paragraphs  => (
          "This is documentation\n\n",
        )
      ),
      RakuAST::Statement::Expression.new(
        expression => RakuAST::IntLiteral.new(42)
      )
    );
    is-deeply $ast.EVAL, 42, 'do we get the final result';
    for 'Str', $deparsed, 'Raku', $raku.EVAL.DEPARSE -> $type, $it {
        is-deeply $it, q:to/CODE/, "$type: deparse";
  =begin doc

  This is documentation

  =end doc

42
CODE
    }
}

subtest 'abbreviated documentation in a statementlist (1)' => {
    # 42␤  =head1 This is documentation␤
    ast RakuAST::StatementList.new(
      RakuAST::Statement::Expression.new(
        expression => RakuAST::IntLiteral.new(42)
      ),
      RakuAST::Doc::Block.new(
        margin      => '  ',
        type        => 'head',
        level       => 1,
        abbreviated => True,
        paragraphs  => (
          "This is documentation\n",
        )
      )
    );
    is-deeply $ast.EVAL, 42, 'do we get the final result';
    for 'Str', $deparsed, 'Raku', $raku.EVAL.DEPARSE -> $type, $it {
        is-deeply $it, q:to/CODE/, "$type: deparse";
42
  =head1 This is documentation
CODE
    }
}

subtest 'abbreviated documentation in a statementlist (2)' => {
    #   =head1 This is documentation␤42␤
    ast RakuAST::StatementList.new(
      RakuAST::Doc::Block.new(
        margin      => '  ',
        type        => 'head',
        level       => 1,
        abbreviated => True,
        config      => { :numbered },
        paragraphs  => (
          "This is documentation\n\n",
        )
      ),
      RakuAST::Statement::Expression.new(
        expression => RakuAST::IntLiteral.new(42)
      )
    );

    is-deeply $ast.EVAL, 42, 'do we get the final result';
    for 'Str', $deparsed, 'Raku', $raku.EVAL.DEPARSE -> $type, $it {
        is-deeply $it, q:to/CODE/, "$type: deparse";
  =head1 # This is documentation

42
CODE
    }
}

subtest 'alias directive in a statement list' => {
    #   =alias FOO bar␤  = 137␤42␤
    ast RakuAST::StatementList.new(
      RakuAST::Doc::Block.new(
        margin      => '  ',
        type        => 'alias',
        directive   => True,
        paragraphs  => (
          "FOO",
          "bar\n137",
        )
      ),
      RakuAST::Statement::Expression.new(
        expression => RakuAST::IntLiteral.new(42)
      )
    );

    is-deeply $ast.EVAL, 42, 'do we get the final result';
    for 'Str', $deparsed, 'Raku', $raku.EVAL.DEPARSE -> $type, $it {
        is-deeply $it, q:to/CODE/, "$type: deparse";
  =alias FOO bar
  =          137
42
CODE
    }
}

for <row column> -> $name {
    subtest "$name directive in a statement list" => {
        #   =$type :align<left middle>␤42␤
        ast RakuAST::StatementList.new(
          RakuAST::Doc::Block.new(
            margin     => "  ",
            type       => "table",
            paragraphs => (
              RakuAST::Doc::Block.new(
                margin     => "  ",
                type      => $name,
                directive => True,
                config    => ${:align(RakuAST::QuotedString.new(
                  processors => <words val>,
                  segments   => (
                    RakuAST::StrLiteral.new("left middle"),
                  )
                ))},
              )
            )
          ),
          RakuAST::Statement::Expression.new(
            expression => RakuAST::IntLiteral.new(42)
          )
        );

# Complains about an unexplained RakuAST::Var::Lexical::Setting not
# having been resolved, so skip for now
#        is-deeply $ast.EVAL, 42, 'do we get the final result';
        for 'Str', $deparsed, 'Raku', $raku.EVAL.DEPARSE -> $type, $it {
            is-deeply $it, qq:to/CODE/, "$type: deparse";
      =begin table

      =$name :align<left middle>
      =end table

    42
    CODE
        }
    }
}

subtest 'abbreviated defn in a statement list' => {
    #   =defn Foo Bar␤  baz␤42␤
    ast RakuAST::StatementList.new(
      RakuAST::Doc::Block.new(
        margin      => '  ',
        type        => 'defn',
        abbreviated => True,
        paragraphs  => (
          "Foo Bar",
          "baz\n\n",
        )
      ),
      RakuAST::Statement::Expression.new(
        expression => RakuAST::IntLiteral.new(42)
      )
    );

    is-deeply $ast.EVAL, 42, 'do we get the final result';
    for 'Str', $deparsed, 'Raku', $raku.EVAL.DEPARSE -> $type, $it {
        is-deeply $it, q:to/CODE/, "$type: deparse";
  =defn Foo Bar
  baz

42
CODE
    }
}

# vim: expandtab shiftwidth=4
