考虑recent question中的一个简单功能:
myButLast :: [a] -> a
myButLast [x, y] = x
myButLast (x : xs) = myButLast xs
myButLast _ = error "List too short"
我们可以要求GHC使用ghc -ddump-simpl
给我们简化输出。 (可能与some
additional flags类似-dsuppress-module-prefixes
-dsuppress-uniques
。)据我了解,它
是编译的最后阶段,结果仍然与原始高点有相似之处
级别代码。所以这就是它的意思:
-- RHS size: {terms: 21, types: 22, coercions: 0, joins: 0/0}
myButLast :: forall a. [a] -> a
[GblId,
Arity=1,
Str=<S,1*U>,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True, Guidance=IF_ARGS [30] 100 0}]
myButLast
= \ (@ a) (ds :: [a]) ->
case ds of {
[] -> myButLast1 @ a;
: x ds1 ->
case ds1 of {
[] -> myButLast1 @ a;
: y ds2 ->
case ds2 of {
[] -> x;
: ipv ipv1 -> myButLast_$smyButLast1 @ a y ipv ipv1
}
}
}
这是怎么回事?让我们看看。
现在使用显式量词为类型签名附加一些注释。
我可能会猜到他们说“全局标识符,一元,顶级” ,这完全是对的
功能。其他注解,例如WorkFree=True
,Str=<S,1*U>
,对我来说是个秘密。
“值” 定义现在是一个lambda,除了列表之外,它还接受类型变量
论证,然后通过案例分析来研究列表。 [] -> myButLast1 @ a
是荣耀的
错误调用,因此让我们暂时忽略它。有趣的部分是
myButLast_$smyButLast1
(那是什么名字?我以为$
符号不能成为
标识符。),它实际上是遍历列表的尾部递归函数。
在这里,这是我们公认的相互递归块的单个成员:
Rec {
-- RHS size: {terms: 13, types: 12, coercions: 0, joins: 0/0}
myButLast_$smyButLast1 [Occ=LoopBreaker]
:: forall a. a -> a -> [a] -> a
[GblId,
Arity=3,
Caf=NoCafRefs,
Str=<L,1*U><L,1*U><S,1*U>,
Unf=OtherCon []]
myButLast_$smyButLast1
= \ (@ a) (sc :: a) (sc1 :: a) (sc2 :: [a]) ->
case sc2 of {
[] -> sc;
: ipv ipv1 -> myButLast_$smyButLast1 @ a sc1 ipv ipv1
}
end Rec }
这很清楚,但是它确实有一些新功能,例如递归块
定界符Rec ... end Rec
和隐含的注释[Occ=LoopBreaker]
。注释也
不同:Unf
数组为空,而出现Caf
字段。我只能推断
Unf
字段有趣的是程序员定义的名称质量,而
myButLast_$smyButLast1
由编译器创建。
因此,我可以通过行数了解到简化器给我的一半,但是在某些部分,我什至无法开始猜测其含义。
是前提,简化器输出通常是最有用的中间 表示,对吗?
我的阅读到目前为止是否正确?
是否有关于所有这些神秘言论的手册?他们是什么意思?
答案 0 :(得分:2)
我知道Core上没有任何手册或独立文档,它涉及到您正在寻找的详细信息。 Wiki中当然有这个page on Core,但它只是从较高的层次上解释了Core语言,并且主要是根据用于表示Core抽象语法树的编译器数据结构来解释的,而不是具体的。 “漂亮打印”语法。
获取所需详细信息的唯一方法是下载GHC源的副本并开始浏览ghc/compiler/coreSyn/
中的代码。
GHC既庞大又复杂,但是大多数代码是用Haskell编写的,因此很多代码都非常高级且可读性强,并且源代码受到大量注释,并附有出色的解释和注释。
例如,如果您想知道WorkFree=True
是什么意思,
在PprCore.hs
中查找生成注释的代码,以确定它是uf_is_work_free
的{{1}}字段。
检查CoreUnfolding
中CoreUnfolding
的定义及其相关注释,可以看到CoreSyn.hs
是标识符的表示,可以在内联时替换该标识符,并且Unfolding
标志是uf_is_work_free
的缓存副本,它某种程度上表明内联展开不会“浪费工作”。
在exprIsWorkFree
,CoreSyn.hs
和CoreUnfold.hs
中的注释中查找有关CoreUtils.hs
及其含义的其他解释:
exprIsWorkFree
用于确定是否内联某些内容;我们 如果这样做可能会重复工作,请不要内联,方法是将 表达式的完整副本。
举一个例子:
exprIsWorkFree
指出let x = a #+ b in x +# x -- I think `#+` is a typo and should be `+#`
不是“免费的”,因为如果在RHS上对其进行内联,则会导致x
操作被两次评估
在您的情况下,Core输出中的a +# b
版本是不工作的,因为它不会独立于每次应用myButLast
时都可以重用的参数来求值任何表达式。 / p>