【问题标题】:How to override the NQPMatch.Str function如何覆盖 NQPMatch.Str 函数
【发布时间】:2020-07-13 21:58:39
【问题描述】:

... 或者如何从token sigil { ... } 更改$<sigil>.Str独立于匹配的文本。是的,我在问如何欺骗上面的语法(即打电话给我)。

我正在尝试写一个Slang for Raku without 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;,因为它们被视为方法调用。

@Arne-Sommer 已经创建了 postarticle。这是密切相关的。但这个问题的目的是:

我们如何自定义编译时令牌的返回值,而不是如何声明它。

【问题讨论】:

  • 也许尝试将覆盖Str 的角色混合到匹配对象中,也许在sigil 操作方法中。虽然我怀疑这只会让你到目前为止。最终,Raku 语法在没有 sigil 的情况下形式上是模棱两可的(这就是为什么必须使用 my \foo = ... 引入无符号变量的原因),所以我怀疑你会在尝试这样做时遇到无穷无尽的问题。
  • @JonathanWorthington 我认为您的意思是,实用的 raku 语法通常主要是预测性的;并且现有的 raku 被写入预测性地期望,例如,my foo... 中的foo 是一种类型;这个和其他这样的预测假设很深。然而,aiui,一个实际的 raku 语法“应该”永远不会在形式上模棱两可,除非它涉及 "specified" scenarios declared to be ambiguous。是吗?
  • @JonathanWorthington:你解决了我的问题。我确实忽略了mixin 与作文。 Compose 方法在 NQPMatch 中不存在,但 mixin 正在工作。谢谢!
  • @Tinmarino 我在那儿有点不拘小节,是的;一个具体的 Raku 语法具有决定将被解析的内容的决胜局,因此解析不会因某种歧义错误而失败。我的观点是,Raku 本身的语言设计非常依赖于印记。有很多例子;例如,:$foo 表示:foo($foo),但:foo 表示:foo(True),因此您无法使用冒号对构造的便捷形式来传递没有符号的变量 - 或者您必须放弃该符号通过True
  • @Tinmarino 不过,更根本的是,您还必须安排将声明为变量的内容识别为术语而不是列表。否则,foo + bar 将解析为 foo (listop) 调用 bar 并将前缀 + 运算符应用于它。不是两个变量的中缀运算符。

标签: raku nqp


【解决方案1】:

简介:@JonathanWorthington 指出的答案:

简介:使用mixin 元函数。 (并且不是需要compose 方法的but。)

演示:

  1. 通过检索另一个token 创建一个NQPMatch 对象:这里是self.sigil-my 调用的令牌sigil-my
  2. ^mixin 与角色一起使用
method sigil { return self.sigil-my.^mixin(Nogil::StrGil); }

上下文:完整的可重现代码:

所以你可以看到sigil-myNogil::StrGil是什么类型。但我告诉过你:token(不仅仅是方法)和role(不可实例化的类)。

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 {};

}

注意:这为解决更多问题打开了大门(jnthn question cmets 也指出了这一点)-> -0fun !

【讨论】:

  • @p6steve,是的,这太疯狂了,一次修改很多东西很容易。出于这个原因,我猜 Raku 中的模块非常小。
猜你喜欢
  • 2011-07-21
  • 2016-05-04
  • 2012-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-25
相关资源
最近更新 更多