Skip to content

Commit

Permalink
RakuAST: implement simple trimming of heredocs
Browse files Browse the repository at this point in the history
  • Loading branch information
niner committed Jan 29, 2023
1 parent 445a224 commit 4a53b6b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/Raku/Grammar.nqp
Expand Up @@ -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<ws>.Str;
my int $actualchars := nqp::chars($ws);
$heredoc.set-indent($actualchars);
$heredoc.trim;
}
else {
Expand Down
34 changes: 33 additions & 1 deletion src/Raku/ast/literals.rakumod
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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');
Expand All @@ -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;
}
}
}
}
}

Expand Down

0 comments on commit 4a53b6b

Please sign in to comment.