Как переопределить функцию NQPMatch.Str - PullRequest
6 голосов
/ 02 апреля 2020

... или как изменить значение $<sigil>.Str с token sigil { ... } в зависимости от сопоставленного текста . Да, я спрашиваю, как обмануть грамматики выше (то есть вызывать) меня.

Я пытаюсь написать Сленг для Раку без сигил .

Итак, я хочу, чтобы токен nogil, соответствующий чему-либо <?>, возвращал NqpMatch со строкой: $<sigil>.Str в '$'.

В настоящее время мой сигил с токеном выглядит так

token sigil {
    | <[$@%&]>
    | <nogil> { say "Nogil returned: ", lk($/, 'nogil').Str; # Here It should print "$"
              }
}
token nogil-proxy {
    | '€'
    | <?>
    {log "No sigil:", get-stack; }
}

И метод с этим должен вернуть NQPMatch с методом Str перезаписанным

method nogil {
    my $cursor := self.nogil-proxy;
    # .. This si where Nqp expertise would be nice
    say "string is:", $cursor.Str;    # here also it should print "$"
    return $cursor;
}

Неудачная попытка:

$cursor.^cache_add('Str', sub { return '$'; } );
$cursor.^publish_method_cache;
for $cursor.^attributes { .name.say };
for $cursor.^methods { .name.say };
say $cursor.WHAT.Str;
nqp::setmethcacheauth($cursor, 0);

В настоящее время большинство мои тесты работают, но у меня есть проблемы в объявлениях без моего (с no strict) типа my-var = 42;, потому что они рассматриваются как вызов метода.

@ Арне-Соммер уже сделал сообщение и статья . Это тесно связано. Но этот вопрос имеет целью:

Как мы можем настроить возвращаемое значение токена времени компиляции, а не как его объявить.

1 Ответ

6 голосов
/ 02 апреля 2020

Введение: Ответ, указанный @JonathanWorthington:

Краткое описание: Использование мета-функции mixin . (И НЕ , но , требующий compose метод.)

Демонстрация:

  1. Создание NQPMatch объект путем получения другого токена : здесь токен sigil-my, вызываемый self.sigil-my.
  2. Использование ^mixin с ролью
method sigil { return self.sigil-my.^mixin(Nogil::StrGil); }

Контекст: полный воспроизводимый код:

Таким образом, вы можете видеть, какие типы sigil-my и Nogil::StrGil. Но я сказал вам: токен (больше, чем метод) и роль (нереализуемые классы).

role Nogil::StrGil {
    method Str() {
        return sigilize(callsame);
    }
}


sub EXPORT(|) {

# Save: main raku grammar
my $main-grammar = $*LANG.slang_grammar('MAIN');
my $main-actions = $*LANG.slang_actions('MAIN');

role Nogil::NogilGrammar {
    method sigil {
        return self.sigil-my.^mixin(Nogil::StrGil);
    }
}

token sigil-my { | <[$@%&]> | <?> }

# Mix
my $grammar = $main-grammar.^mixin(Nogil::NogilGrammar);
my $actions = $main-actions.^mixin(Nogil::NogilActions);
$*LANG.define_slang('MAIN', $grammar, $actions);

# Return empty hash -> specify that we’re not exporting anything extra
return {};

}

Примечание: Это открывает дверь к му sh больше проблем (также указано в комментариях к вопросу) -> -0fun!

...