20

我认为 Coffeescript 是一门很棒的语言!我正在寻找一些将静态分析添加到 Coffeescript 的项目/问题/功能。然而,经过一番搜索,我发现 Coffeescript常见问题解答和此页面表明静态分析可能不可行。

我想知道在Coffeescript中实现静态分析/静态类型检查是否存在基本问题,因为编译器中不存在这种类型的东西?

此外,对于非平凡的检查来说,这是不可能做的事情,但可能只适用于简单的分析?当我说直截了当时,我的意思是检查一些琐碎的事情,例如,用户是否以相同的名称(在一个类中)或在顶层(或者可能在相关的 .coffee 文件集合的顶层)定义了一个函数两次.

如果有人能指出一些例子来说明为什么实施静态分析/类型检查并不简单/可能/值得花时间,我将不胜感激?

非常感谢你!

4

2 回答 2

13

这个答案有点脑残,因为我也对此感兴趣。希望能帮助到你。

我使用 Google Closure Compiler 静态分析 CoffeeScript 生成的代码。它有一个非常好的静态分析器,我不确定是否有充分的理由在这里重新发明轮子。简单的方法是手动编写注释:

###*
   * @param {number} x
   * @param {number} y
   * @return {number}
###
adder = (x, y) -> x + y

这有点冗长,但另一方面,您正在借用闭包编译器的静态分析能力,它非常强大并且能够检查很多。我实际上以稍微简洁的方式编写类型注释,然后有一个脚本来重写咖啡文件。我的代码最终看起来像这样:

#! {number} x {number} y @return {number}
adder = (x, y) -> x + y

我相信您可以看到重写器非常简单。

在我继续之前快速说明。如果您通过闭包编译器运行代码,请务必使用-b(bare)编译您的代码。闭包编译器还是不错的,但是做数据流分析还不够聪明。CoffeeScript 默认将您的代码包装在一个匿名函数中,这会使编译器出错。

沿着相同路径的另一个选项(这会破坏与 CoffeeScript 的兼容性,但会更酷)是让 Coffee 编译器编译如下内容:

adder = (number x, number y): number -> x + y

像这样进入JS:

/***
  * @param {number} x
  * @param {number} y
  * @return {number
  */
var adder = function(x, y) {
  return x + y;
};

然后可以在编译时将其输入闭包编译器 - 如果没有错误,编译器可以删除所有注释。

的确,这家伙似乎就是这么做的。可悲的是,他的作品似乎处于不完整的状态。

在所有这些情况下,我们将艰苦的工作——静态类型检查——推迟到闭包编译器。如果您不想这样做,我会理解,但是很难说服我从头开始构建一个全新的静态分析工具是值得的。:)

一年后编辑:这些天我只使用打字稿。:)

于 2012-06-04T22:07:16.110 回答
8

我不是 CoffeeScript 专家,所以这可能是完全错误的答案,但它基本上可以归结为:CoffeeScript 是一种非常有表现力的语言,大部分语义都是动态确定的(可能还有奇怪的边缘情况)。这与标准 ML 等具有更严格定义的语义的语言形成鲜明对比。一般来说,对高阶语言进行静态分析被认为是非常困难的。即,对真正的高阶程序(Haskell,ML,尤其是javascript 因为 eval 之类的东西)只是很难,因为控制流更加灵活。事实上,高阶语言的静态分析解决方案实际上只是在过去二十年左右的时间里才被探索过。(值得注意的是,请参阅 Matt Might 关于CFA 教程风格描述的文章。)

基本上,原因是这样的:

  • 要进行分析,您必须处理来自流控制的表达语义问题,您可以通过猛烈抨击高阶函数。
  • 要进行打字,通常这些语言具有更丰富的可用类型集。例如,在非常典型的情况下,如果您尝试将静态类型分配给 Ruby 中的变量(如在 C、Java、ML 等中),您会收到错误,但因为您的程序的某些路径永远不会执行,一切正常。除此之外,像 Ruby 之类的其他语言添加了大量的隐式类型转换,这些转换确实用于进行很酷的编程。我所熟悉的这一领域的著名工作(Ruby 的静态类型的动态分析)来自与我一起工作的一些人,但肯定还有其他例子。
  • 基本上,该语言以更加动态的方式使用,具有更具表现力的语义,并且静态推理要困难得多,并且容易不精确。接近这一点(这些天)的基本前沿开始看起来是混合的:您可以静态分析程序的一部分,并且还需要程序员提供一些测试用例来进行某种精细分析。

我希望这在一定程度上回答了你的问题,再次抱歉,我无法直接解决你的问题的直接问题,因为它适用于 CoffeeScript,但现在在分析 JavaScript 之类的东西方面还有很多工作要做。我会注意到 Javascript 的一些真正问题来自它奇怪的语​​义,原型继承很难推理,尤其是 eval()!通常,这些语言的程序分析会施加某些限制(例如,完全抛弃 eval!)以使分析更可行!

于 2012-06-04T00:48:41.123 回答