在阅读 Crystal-lang 内部代码时,我遇到了一些片段,例如:
@[Primitive(:some_name)]
def some_method
end
任何人都可以向我解释该Primitive
属性的作用以及它是如何工作的(例如,告诉编译器使用 LLVM 函数)?
这是纯水晶无法表达的功能。任何时候出现对此类方法的调用,都需要由编译器直接替换为低级指令 ( LLVM IR ),而不是由实际函数支持。
这是必需的,因为某些操作已经处于最低级别。例如,如何实现两个数的相加?呃,a+b
?等等,但这就是我们正在努力实现的。因此,除了诉诸if a==1 && b==1 ...
这种荒谬的事情之外,还需要将其推迟到 CPU(通过LLVM IR)。
文件primitives.cr只包含这些方法的空壳,以及它们的文档,所以它们看起来像标准库的正常部分。它们由注释标记,以便编译器知道何时替换它们。真正的动作发生在compiler/crystal/codegen/primitives.cr 中:case
每个注释名称都有一个分支,这会导致生成适当代码的代码。
为了完整起见,这里是primitives.cr的摘录:
此处定义的方法是原语,因为它们要么:
- 不能用Crystal表示(需要用LLVM表示)。例如,一元和二元数学运算符就属于这一类。
- 出于性能原因,即使在非发布版本中,也应始终与 LLVM 指令内联。这方面的一个例子是
Char#ord
,它可以在 Crystal 中通过分配self
给一个变量并将指向它的指针转换为Int32
,然后读回该值来实现。
旁注:
这不是编译器用于实现不能是普通 stdlib 方法的方法的唯一方法。这也发生在像,在语法层面上的伪方法。这是一种甚至“更强”的能力,它是一种方法的伪装被丢弃(你不会在Object 的文档中找到)。这种构造与编译器紧密相连,会影响类型信息。obj.is_a?
is_a?
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句