From 4a53b6b9508b29056b6939796ca97b76d2c27fd0 Mon Sep 17 00:00:00 2001 From: Stefan Seifert Date: Sun, 29 Jan 2023 12:29:51 +0100 Subject: [PATCH] RakuAST: implement simple trimming of heredocs --- src/Raku/Grammar.nqp | 3 +++ src/Raku/ast/literals.rakumod | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/Raku/Grammar.nqp b/src/Raku/Grammar.nqp index a9e5df769eb..8342961542d 100644 --- a/src/Raku/Grammar.nqp +++ b/src/Raku/Grammar.nqp @@ -183,6 +183,9 @@ role Raku::Common { my $heredoc := $herestub.orignode.MATCH.ast; $heredoc.replace-segments-from($doc.MATCH.ast); $heredoc.set-stop(~$stop); + my str $ws := $stop.MATCH.Str; + my int $actualchars := nqp::chars($ws); + $heredoc.set-indent($actualchars); $heredoc.trim; } else { diff --git a/src/Raku/ast/literals.rakumod b/src/Raku/ast/literals.rakumod index 3bc5690114c..1b4cebc2faf 100644 --- a/src/Raku/ast/literals.rakumod +++ b/src/Raku/ast/literals.rakumod @@ -142,6 +142,10 @@ class RakuAST::StrLiteral is RakuAST::Term is RakuAST::CompileTimeValue { RakuAST::Type::Simple.new(RakuAST::Name.from-identifier('Str')) } + method set-value(Str $value) { + nqp::bindattr(self, RakuAST::StrLiteral, '$!value', $value); + } + method IMPL-EXPR-QAST(RakuAST::IMPL::QASTContext $context) { my $value := $!value; $context.ensure-sc($value); @@ -461,6 +465,7 @@ class RakuAST::QuotedString is RakuAST::ColonPairish is RakuAST::Term class RakuAST::Heredoc is RakuAST::QuotedString { has Str $!stop; + has int $!indent; method new(List :$segments!, List :$processors, Str :$stop) { my $obj := nqp::create(self).SET-SELF($segments, $processors); @@ -482,6 +487,10 @@ class RakuAST::Heredoc is RakuAST::QuotedString { } method stop() { $!stop } + method set-indent(int $indent) { + nqp::bindattr_i(self, RakuAST::Heredoc, '$!indent', $indent); + } + method trim() { # Remove heredoc postprocessor to defuse the "Premature heredoc consumption" error my $processors := nqp::getattr(self, RakuAST::QuotedString, '$!processors'); @@ -491,7 +500,30 @@ class RakuAST::Heredoc is RakuAST::QuotedString { nqp::push($new_processors, $_) if $_ ne 'heredoc'; } - #TODO actually trim there heredoc + if ($!indent) { + my int $indent := -$!indent; + + my $in-fresh-line := 1; + for self.IMPL-UNWRAP-LIST(self.segments) { + if nqp::istype($_, RakuAST::StrLiteral) { + if $in-fresh-line { + $_.set-value($_.value.indent($indent)); + } + else { + my $strval := $_.value; + if $strval ~~ /\n/ { # we have more lines + # add temporary indentation to the front, so every line will be indented + my $strbox := nqp::box_s(nqp::x(" ", -$indent) ~ nqp::unbox_s($strval), Str); + $in-fresh-line := 1; + $_.set-value($strbox.indent($indent)); + } + } + } + else { + $in-fresh-line := 0; + } + } + } } }