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

时间:2013-11-29 14:30:46

标签: compilation dart

由于在启动dart应用程序之前需要编译,我想知道编译器预处理器是否可用,或者是否在不久的将来为Dart安排。
到目前为止,我在网站/飞镖网站内的搜索已被证明是不成功的。

(通过预处理器,我的意思是:

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

或:

#define NumType double
#define NumTypeZero 0.0

// used with :
NumType myNum = NumTypeZero;

或:

#define DEBUG 

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

编辑:我想知道为什么还没有预处理器,因为从那时起我们似乎已经“接近”了:   - Dart必须扫描文件以查找库依赖关系,以便按正确的顺序加载库   - Dart编辑器还扫描文件的语法,类型检查和其他检查   - 可以在编辑器中启动一些自动文件处理(我找不到有用的链接,请告诉我,如果你有的话)。

4 个答案:

答案 0 :(得分:4)

基本上其他人说的是什么......

如果您正在使用dart2js进行编译,那么如果DEBUG是常量且为false,那么树形抖动就会抛出if(DEBUG){}块内的代码。所以你可以使用if语句。

您也可以使用assert()语句。在使用dart2js进行生产模式编译时,断言以及传递给它的表达式将被丢弃。

所以这实际上与#ifdefs相同 - 您可以将dart2js视为预处理器;)

我也没有看到你为什么要使用#defines而不是常量的原因。

如果您想在DartVM中运行代码,可以使用dart2js --output-type = dart在您的dart源上进行树状抖动。

更新:另请参阅String.fromEnvironment()bool.fromEnvironment()int.fromEnvironment()。您可以在编译时使用“dart2js -D< env-var-name> =< value>”来设置这些环境变量。

答案 1 :(得分:3)

此时Dart没有预处理器。我不相信在不久的将来也有计划。见Issue 7238

Dart不需要编译。仅用于生成Dart VM外部应用程序可用的Javascript。例如,服务器端Dart脚本从不需要编译。他们可以生成快照以减少加载时间,但这不是编译步骤,而是在应用程序启动后更多地存储VM的状态。

尽管如此,有很多关于基于环境的依赖注入或其他依赖管理系统的讨论,但目前尚未达成共识或决定。见Issue 76

编辑:

1)我在加载库时使用“正确的顺序”一词犹豫不决。对于Dart VM本身,它实质上在加载脚本时加载所有库符号,然后开始执行代码并将符号与表中的符号相匹配。 dart2js编译器执行类似的操作,但之后还会实现树形操作尝试以隔离未使用的代码并从最终编译中省略它。但是,我远离虚拟机或JavaScript编译器大师,无法获得有关该过程如何完成的更多信息。

2)与其他解释语言类似,许多/大多数检查在运行时执行而不是编译时步骤。事实上,Dart VM设计为在禁用类型检查的情况下运行。它仅用于开发,并且实际上对执行速度施加了重大惩罚。

3)我相信你指的是build.dart文件。您可以在Build.dart and the Dart Editor

找到更多信息

另请注意,Dart编辑器实际上正在运行一个名为dart_analyzer的dart脚本,以便在您键入时验证代码。它正在改善,但仍然远非完美。它尝试并假设并将类型和值与代码相关联,但它还必须符合dart语言规范。因此,即使分析器能够采用基于周围代码的类型,它仍然必须提供警告,例如类型Node没有与之关联的getter'value',即使分析器知道传递的Node实际上是文本输入字段。

答案 2 :(得分:1)

不,没有,我怀疑会有。

对于您的第一个示例,等效只是定义 max(a,b)=> a> b? a:b;

或者,更简单 导入“dart:math”;

已经包含了。

第二个的等价物是NumType的typedef,但是现在Dart typedef仅适用于函数类型。更常见的typedef似乎可能会出现在更高版本中。对于0.0部分,只是 const numTypeZero = 0.0;

现在没有等效于ifdef的条件代码执行。但是,如果您在程序的开头定义了 const DEBUG = false; 并写道   if(DEBUG)print(“stuff”);

这将大致完成你想要的。

你正在寻找的东西是非常多的C语言,通常用于表现。 Dart的编译器非常聪明,不需要其中的一些。

因此,例如,定义最大化方式可能是为了强制它内联。如果Dart认为这是值得的话,Dart会自行将它全部内联,并且能够通过执行来改变它的思维。将某些内容声明为“const”会使其成为编译时常量,因此与#define的效果几乎相同。通过定义像DEBUG这样的符号来减小代码大小的能力是Dart现在所缺少的,尽管条件编译可能比大小更重要。如果您在浏览器中运行,并且编译器在浏览器中,则下载代码大小减少了。如果你等到编译器运行,那就太晚了,你已经下载了代码。如果提前编译为JS,则会省略if语句中由常量false限定的代码。还有一个dart2dart模式可以进行各种转换,以及Dart源的缩小。但是,在有本机运行Dart的浏览器之前,这一点就不那么重要了。

答案 3 :(得分:1)

来自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() {
  }