从游戏开发中的多种技术出发
Haxe最初写作haXe,由法国开发者尼古拉·卡纳斯在Motion-Twin的游戏开发工作背景下发起。项目手册把启动日记为2005年10月22日。它接续卡纳斯的ActionScript 2编译器MTASC,并吸收内部实验语言MTypes把类型推断用于面向对象程序的经验。
当时,一个网络应用可能同时涉及浏览器脚本、Flash界面和服务器逻辑。程序员面对的不仅是运行环境差异,也包括语言、工具及重复代码的切换。Haxe选择在这些技术前面提供共同的语言,再由编译器分别生成目标环境需要的程序。
2005年的雏形与2006年的1.0
编译器的原始变更记录显示,2005年11月14日的alpha 1列出词法分析器、语法分析器和类型检查器;11月25日的alpha 2增加SWF生成,12月10日的alpha 4加入Neko生成。这条顺序说明,最初发布的是逐步完善的语言实现,各个输出目标陆续接入。
2006年2月4日进入beta 1,3月11日的beta 3加入JavaScript生成器。经过候选版本,1.0于5月17日发布。其修订涉及JavaScript XML解析、Neko网络接口、远程调用代理和类型处理等具体问题,显示正式版本的形成同时依赖语言规则与平台接口的整理。
参考:[2]
同一种源代码,几种不同输出
到2008年,Haxe已经能够生成供Flash使用的SWF文件、浏览器执行的JavaScript文件,以及Neko虚拟机运行的字节码。Neko承载服务器端逻辑与命令行程序,Flash和JavaScript则面向网页中的不同交互需求。
可共享的部分通常是应用的规则和数据处理,显示、输入和宿主接口则通过平台专用代码与条件编译接入。开发者在共同的语言中组织这些部分,再选择相应的生成目标。
用一个输出程序理解工具链
一个最小例子可以把这层关系说清楚。现行手册中的Main类含有静态main入口,函数体调用“trace("Hello World")”,文件保存为Main.hx。选择Neko目标时,命令“haxe --neko hello.n --main Main”生成hello.n,再由Neko执行;源文件本身并不是交给虚拟机运行的成品。
同样的语言也能用于浏览器程序。手册的JavaScript例子创建按钮、设置点击处理函数,再把按钮加入页面;编译器生成.js文件,由HTML页面载入。这两条路径体现了Haxe的设计分工:开发者表达程序逻辑,编译器负责生成相应形式,宿主环境负责实际执行。这里的命令和接口属于后续手册中的演示写法。
参考:[1]
让类型检查承担一部分工作
Haxe采用静态类型系统,同时允许编译器从上下文推断类型。手册以空数组为例:声明“var x = []”时,只知道x是数组;随后执行“x.push("foo")”,元素类型便可确定为字符串,数组成为Array<String>。开发者省去了部分显式标注,类型之间的约束仍由编译器检查。
这种做法解释了它为何既保留类和接口等组织方式,又吸收函数式语言的推断思想。程序可以写得较简洁,但数据关系仍要满足类型规则。对多目标语言而言,先建立共同的程序结构和类型信息,也为随后生成不同平台代码提供了基础。
后续目标由协作者扩展
项目沿革记载,弗兰科·蓬蒂切利提供的PHP目标随2008年7月的Haxe 2.0发布,使程序能够接入PHP运行环境;休·桑德森的C++目标于2009年7月加入,其生成代码还需要交给C++编译器处理。
这些协作把Haxe从早期网页技术组合推向更广的应用环境。团队可以先共享程序逻辑,再为不同平台接入显示和宿主接口;多目标生成器使同一套语言工具能够参与多种项目。