use v6-alpha;
use File::Spec;

my $dat = splitpath($*PROGRAM_NAME)[1] ~ "/p6explain.dat";
my %things;

# Parsing the dat
my $fh = open $dat err die "Couldn't open \"$dat\" for reading: $!\n";
for =$fh {
  state $cur_entry;

  # Skip comments
  # next if m:Perl5/^\s*a/;

  # Extract title
  when m:Perl5/^(\S.*)$/ {
    $cur_entry  = $0;
  }

  # Extract explanation
  when m:Perl5/^(\s+)(.+)$/ {
    %things{$cur_entry} ~= "$1\n";
  }
}

# Expansion
# This part is a bit complicated, it'd be much easier if
#   s:Perl5/.../{ any ... }/
# would work in Pugs. But as it doesn't currently (read: it will do tomorrow
# :)), we have to fake it by using lots of loops.
for %things.kv -> $key_, $value {
  my &deref = -> $key_ {
    my @ret = ($key_);

    # Check if we have to substitute some references.
    while any(@ret) ~~ rx:Perl5/\@\w+/ {
      my @new_ret;
      for @ret -> $key {
        if $key ~~ rx:Perl5/\@(\w+)/ {
          # This is the thing we want to replace, for example 'infix_ops'.
          my $ref   = $0;

          # These are all substitutions.
          my @subst = split rx:Perl5/\s+/, %things{$ref};

          # These are the original keys.
          my @k     = ($key) xx @subst;

          # Now we substitute all @infix_ops by the values in @subst.
          $_ ~~ s:Perl5/\@\Q$ref/{ shift @subst }/ for @k;

          # Finally, we add that to our array of return values.
          push @new_ret, @k;
        } else {
          push @new_ret, $key;
        }
      }
      @ret = @new_ret;
    }
    @ret;
  };

  my @new = deref $key_;
  %things{$_} //= $value for @new;
}

die "Usage: $*PROGRAM_NAME thing1_to_explain thing2_to_explain...\n"
  unless @*ARGS;

# Finally, output!
for @*ARGS -> $lookup {
  say $lookup;
  say "    $_" for
    split "\n",
    %things{$lookup} // "Sorry, didn't found an entry for \"$lookup\".\n";
}
