Compiler construction 闭包转换和高阶函数调用的单独编译
在编译高阶函数调用时,是否有处理单独编译和不同类型闭包转换之间交互的标准方法 我知道在大多数编程语言中都有三种类似函数的结构:闭包、(顶级)函数和C++风格的函数对象。从语法上讲,它们的调用方式相同,但编译器会以最佳方式生成形状明显的调用站点:Compiler construction 闭包转换和高阶函数调用的单独编译,compiler-construction,programming-languages,functional-programming,closures,Compiler Construction,Programming Languages,Functional Programming,Closures,在编译高阶函数调用时,是否有处理单独编译和不同类型闭包转换之间交互的标准方法 我知道在大多数编程语言中都有三种类似函数的结构:闭包、(顶级)函数和C++风格的函数对象。从语法上讲,它们的调用方式相同,但编译器会以最佳方式生成形状明显的调用站点: Syntax: | clo(args) | func(args) | obj(args) ---------------------------------------------------------
Syntax: | clo(args) | func(args) | obj(args)
--------------------------------------------------------------------------------
Codegen: | clo.fnc(&clo.env, args) | func(args) | cls_call(&obj, args)
^ ^ ^ ^ ^
fn ptr | +--"top level" fn --+ |
+--- "extra" param, compared to source type -----+
<>(在C++中,代码> CLSYLIDE/<代码>将是<代码> >:操作程序()/<代码> <代码> Obj>代码>类>代码>,C++还允许虚拟函子,但这基本上是一个额外的间接关闭情况。
此时,调用map(x=>x>3)lst
和map(x=>x>y)lst
应该调用不同的map
函数,因为第一个函数是提升后的简单函数指针,第二个函数是闭包
我可以想出四种方法来处理这个问题:
< L> > P> C++,98方法,它强制被调用方选择一个调用站点形状(通过形式参数类型:虚拟函子、函数指针或非虚函子)或使用模板删除单独编译,有效地指定下面的解2。
映射
和所有其他高阶函数进行多个实例化,并使用适当的名称进行修改。实际上,每个调用站点形状都有一个单独的内部函数类型,重载解析会选择正确的类型env
参数,即使它们不需要它,并且必须引入“额外”闭包来包装非闭包参数env
参数。这似乎比选项3更优雅,但更难有效实施。编译器要么生成大量调用约定独立包装器,要么使用少量调用约定敏感包装器- 这个问题在文献中有明确的名称吗
- 除了上述四种方法外,还有其他方法吗
- 方法之间是否存在众所周知的权衡
- 已知调用表示一个调用站点,在该站点中,编译器确切地知道调用什么函数,以及它需要多少参数
- 未知调用意味着编译器无法确定可能调用的函数
- 如果被调用的函数获得了它所期望的所有参数,并且直接进行编码,则已知调用是完全饱和的。如果函数得到的参数比预期的少,则该函数将部分应用,并且调用只会分配闭包
mapints :: (Integer -> a) -> [a]
mapints f = map f [1..]
然后对map
的调用是已知的,并且完全饱和。如果我写
inclist :: [Integer] -> [Integer]
inclist = map (1+)
然后对map
的调用是已知的,并且部分应用。最后,如果我写
compose :: (b -> c) -> (a -> c) -> (a -> c)
compose f g x = f (g x)
然后对f
和g
的调用都是未知的
成熟的编译器所做的主要工作是优化已知调用。在您上面的分类中,此策略主要属于#2
- 如果一个函数的所有调用位置都是已知的,那么一个好的编译器将为该函数创建一个专用的调用约定,例如,在正确的寄存器中传递参数以使事情顺利进行
- 如果某个函数的某些调用位置已知,但并非所有调用位置都已知,编译器可能会认为值得为已知调用创建一个特殊用途的调用约定,该约定可以是内联的,也可以使用只有编译器知道的特殊名称。在源代码中以名称导出的函数将使用标准调用约定,它的实现通常是对专用版本进行优化尾部调用的薄层
- 如果一个已知调用没有完全饱和,编译器只会生成代码,在调用方中分配闭包
关于你最后的问题