Dart中是否有编译器预处理器?

10

由于在启动Dart应用程序之前需要进行编译,我想知道是否有编译器预处理程序可用,或者是否计划在不久的将来推出。
到目前为止,我在网络上和Dart网站内的搜索都没有找到答案。

(通过预处理器,我指的是类似于:

#define max(A,B)    ( (A) > (B) ? (A):(B)) 

或:
#define NumType double
#define NumTypeZero 0.0

// used with :
NumType myNum = NumTypeZero;

or :

#define DEBUG 

// use
#ifdef DEBUG
   print('var1 : $var1, var2:$var2, ...');
#endif

编辑:我想知道为什么还没有预处理器,因为似乎我们已经接近这个点了:
- Dart必须扫描文件以加载正确顺序的库依赖项。
- Dart编辑器还会扫描语法、类型检查和其他检查。
- 可以在编辑器中启动一些自动化文件处理(如果您有可靠的链接,请让我知道)。

4个回答

8

基本上其他人说的都对...

如果你正在使用dart2js编译,如果DEBUG是一个常量且为false,tree-shaking将会扔掉if(DEBUG){}块中的代码。所以你只需要使用if语句。

你也可以使用assert()语句。在生产模式下,编译时使用dart2js将抛弃assert和传递给它的表达式。

因此,这实际上是与#ifdefs相同的行为-您可以将dart2js视为预处理器 ;)

我也不明白你为什么要使用#define而不是constants。

如果你想在DartVM中运行你的代码,你可以使用dart2js --output-type=dart来进行对你的dart源代码的tree-shaking。

更新:还请参见String.fromEnvironment()bool.fromEnvironment()int.fromEnvironment()。你可以使用“dart2js -D<env-var-name>=<value>”设置这些环境变量进行编译。


1
请参阅http://blog.sethladd.com/2013/12/compile-time-dead-code-elimination-with.html。 - Seth Ladd

3

来自http://blog.sethladd.com/2013/12/compile-time-dead-code-elimination-with.html

假设您有以下代码:

log(String msg) {
  if (const String.fromEnvironment('DEBUG') != null) {
    print('debug: $msg');
  }
}

main() {
  log('In production, I do not exist');
}

使用 dart2js -DDEBUG=true app.dart 进行编译时,输出将包括日志记录行为:
  main: function() {
    H.printString("debug: In the production release, I do not exist");
  }

(日志函数是内联的,但打印仍然发生)
然而,如果未设置 -DDEBUG,则日志记录行为不包括在生成的JavaScript代码中:
  main: function() {
  }

你能确认一下 .fromEnvironment() 方法是否也允许以同样的方式忽略代码吗?这将允许实现与 #DEFINE 预处理器相同的功能。 - GameAlchemist

3

目前还没有Dart的预处理器。我也不认为在不久的将来会有计划推出。请参见Issue 7238

Dart不需要编译,只需要生成可供Dart VM外的应用程序使用的JavaScript。例如,服务器端的Dart脚本从不需要编译。它们可以生成快照以减少加载时间,但这更像是存储应用程序启动后VM状态的步骤,而不是编译步骤。

尽管如此,已经进行了许多关于基于环境的依赖注入或其他依赖项管理系统的讨论,但目前尚未达成共识或做出决定。请参见Issue 76

编辑:

1)我不确定是否应该使用“正确顺序”这个术语来加载库。对于Dart VM本身,它在加载脚本时基本上会加载所有库符号,然后开始执行代码并将符号与表中的符号匹配。dart2js编译器做类似的事情,但然后还会实现树摇以尝试隔离未使用的代码并从最终编译中省略它。但我远非VM或JavaScript编译器专家,无法提供有关该过程的更多信息。

2) 与其他解释型语言类似,许多/大多数检查都是在运行时而不是编译时进行的。实际上,Dart虚拟机被设计成可以在关闭类型检查的情况下运行。它仅在开发期间启用,并且实际上会对执行速度造成重大影响。

3) 我相信您指的是build.dart文件。您可以在Build.dart和Dart编辑器中找到更多信息。

还要注意,Dart编辑器实际上正在运行一个名为dart_analyzer的dart脚本,以在您输入代码时验证代码。它正在改善,但仍然远非完美。它会执行许多步骤,尝试假定和关联代码的类型和值,但它必须符合dart语言规范。因此,即使分析器能够根据周围的代码假定类型,它仍必须提供警告,例如类型Node没有与其关联的getter'value',即使分析器知道传递的Node实际上是文本输入字段。


1
没有,而且我怀疑不会有。
对于您的第一个示例,等效的方法只需定义 max(a,b) => a > b ? a : b;
或者更简单的方式是 import "dart:math";
它已经包含了。
第二个示例的等效方法是NumType的typedef,但是现在Dart typedef仅适用于函数类型。更通用的typedef似乎有望出现在以后的版本中。对于0.0部分,只需 const numTypeZero = 0.0;
目前没有类似于条件代码执行的ifdef等效方法。但是,如果在程序开头定义了 const DEBUG = false; 并编写了以下内容 if(DEBUG) print("stuff");
那将实现大致相同的功能。
您正在寻找的东西非常C风格,并且通常用于性能。 Dart的编译器非常聪明,不需要其中一些。
因此,例如以这种方式定义最大值是为了强制其内联。如果Dart认为它值得,它会自动内联,并且有能力在执行过程中改变主意。声明某些东西为“const”将使其成为编译时常量,因此与#define具有几乎相同的效果。通过定义像DEBUG这样的符号来减少代码大小的能力是Dart目前缺失的,尽管条件编译可能比大小更重要。如果您在浏览器中运行,并且编译器在浏览器中,则减小代码大小的重点在于下载。如果等到编译器运行,那就太晚了,您已经下载了代码。如果提前编译为JS,则会省略由常量false限定的if语句中的代码。还有一种dart2dart模式,可以进行这些类型的转换,以及对Dart源进行缩小。但是,在有原生运行Dart的浏览器之前,这并不重要。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接