Skip to content
On this page

凹语言在开源社Coscon2023成都-Web分论坛的分享视频


视频回放地址: https://www.bilibili.com/video/BV12G411U7ck/

或扫描二维码观看:


讲稿全文:

大家好,我是凹语言项目的联合发起人丁尔男,很荣幸参加这次开源年会,感谢出品人水歌、主持人刘老师以及所有的大会志愿者。凹语言是一个开源的、针对WebAssembly设计的通用编程语言项目,借此机会呢,给各位朋友介绍一下它的由来、发展过程、现状、中期目标,以及我们在开源实践中的一些感受。

我就职于一家传统的地理信息软件企业,负责空间数据三维应用的开发工作。过去公司几乎所有的产品都是使用C系语言开发的桌面应用,与Web很难扯上关系,但这种情况在2018年发生了一些变化,当时柴树杉是我的同事,他发现Emscripten工具链可以把C++代码编译到WebAssembly从而在网页中直接运行,于是我用这条技术路线做了一个网页版的实景三维平台,它的数据调度引擎是用C++写的,底层调用WebGL进行三维绘制,它可以装载上千平方公里的城市实景三维模型并支持各种空间应用。

这套方案的落地依赖于WebAssembly(简称Wasm)技术,它的核心思想是提供一套中间表达指令集和虚拟机,C++之类的高级语言代码编译为Wasm指令集后,运行在浏览器内置的Wasm虚拟机中,这和Java程序编译为Java字节码后运行在JavaVM中是类似的,虽然说技术方案并不新奇,但是在2019年,柴树杉和我就意识到Wasm有可能成为一项被广泛使用的、横跨云边端的技术,得出这个结论的主要原因有两点:一是Wasm已经进入了W3C标准,被浏览器所广泛支持;二是当时的Wasm指令集非常简单,不考虑极致性能的话,很多软件开发者都可以自己手工做一个Wasm虚拟机,这降低了计算自由的门槛。基于这种判断,我们在19年底和人民邮电出版了《WebAssembly标准入门》这本书,尝试在国内推广这一技术。后来Docker创始人之一SolomonHykes说如果Wasm早几年出现,Docker可能就不会出现了,这多少可以佐证我们当时的观点。也是在2019年,我和柴树杉就产生了做一门针对Wasm的语言的念头。

2020年,我们把之前开发那套实景三维引擎的实践经验总结成章,在机械工业出版了《面向WebAssembly编程》一书,系统的介绍了如何通过Emscripten使用C++开发Wasm程序,对C++代码如何与JavaScript代码交换数据、如何相互调用等问题进行了重点讲解。虽然Emscripten已经非常成熟了,但哪怕对于C++程序员来说,学习如何开发Wasm程序仍然有额外的成本,他至少得先弄清楚Wasm的体系结构和内存模型。而且老实说,做了十几年开发工作,我实在是不想再写C++程序了。因为起意的原点是我们在实际工作中,使用现有的语言和工具链开发Wasm程序时存在各种不便,所以“实用化”是最重要的目标,不能只是玩具,至少我们自己要能把它用于实际项目的开发。在此前提下,它的基本特征是:静态数据类型的编译型通用语言,对WebAssembly友好,并且在拥有足够表达能力的同时对使用者的心智负担要尽可能的低。

由于它针对的是Wasm应用,所以最开始我们选的名字是的Wa-lang。最下面这个是Wasm图标,忽略中间的“WA”字母的话,它和中间这个汉字的外形相似,都是一个方块儿上边缺了个口,而且这个字曾经是多音字,其中有个读音正好是Wa,这种象形文字独有的音形双似挺有趣的,于是我们把它的名字定为现在的“凹语言”。Logo也是在进一步强调这种关系。

在发起凹语言项目之前,我和柴树杉都没有做过编译器的专职工作,所以花了不少时间考察、讨论技术路线。Golang的风格是我们三人偏好的最大公约数,因此决定语法以Golang蓝本,但Golang针对的是服务端的高并发场景,这和网页前端差异很大,因此我们需要自制一套后端以匹配网页Wasm环境。Golang编译器本身是开源的,这极大的降低了起步的难度,我们经常说,凹语言是站在Golang的腰上长起来的。2021年我们出版了《Go语言定制指南》介绍了Go编译器的前端部分,并且首次公开了“凹语言”这个概念。

项目进入实际开发阶段是在去年1月份,凹编译器使用Golang开发,编译流程很传统,从源代码到虚拟语法树再到静态单赋值的部分在Go编译器的基础上改造,SSA之后的部分是完全自制的。Golang的内存是自动管理的,这是降低使用负担很重要的一环,我们希望凹语言保持这个特性,但是内存自动管理会影响到运行时行为的方方面面,因此在真正着手生成Wasm代码之前,先开发了一个生成C++代码的原型后端,来验证技术路线是否可行。

到2022年7月份,C++后端的验证通过了,于是开发重点切到了生成Wasm代码的分支上,同时我们把项目开源了。

开源的效果立竿见影,很快就有社区小伙伴加入。9月份来自上海的扈梦明贡献了VSCode插件,和在线的Playground。Playground是一个纯前端的凹语言IDE环境,它不需要安装任何程序,打开网页就能进行代码编辑、编译和运行,非常便于爱好者了解和测试凹语言语法。扈梦明目前负责凹的宿主框架和外部工具链。开源软件和自由软件有一些微妙的差别,我们倾向于后者,所以最终选用了AGPL V3协议。

今年1月份,凹语言完成了结构体、切片、闭包等特性,基于这些功能我们做了一个贪吃蛇的小Demo

4月份完成了一个很重要的特性,接口。接口是功能抽象能力重要的组成部分。

7月底8月初,在开源一周年之际,开发组发布了最小可用产品(MVP)版本,这个版本的内容包含了常用操作系统的本地版凹语言编译器、完整的使用手册、以及在线的编译运行环境。MVP版的发布意味着凹语言的语法和语义已经基本稳定,符合手册规范的源代码在未来很长一段时间内都将是合法的,以MVP为基础,可以开始标准库的建设,以及在实际项目中进行实验性的应用。接下来我们看一下凹语言的现状,也就是MVP版中所包含的特性。

这些是目前支持的基本数据类型,包括常用的整型、布尔型、浮点型,作为易用性的一部分,字符串在凹语言中也属于基本类型,原生支持。

这些是基本类型的常用操作,包括算数、逻辑、位运算等。

这些是复合数据类型,包括引用(也就是指针)、数组、切片、函数值,函数在凹语言中属于一等对象,可以携带状态进而实现闭包,这与Golang是一致的。

结构体属于自定义类型,可以拥有方法。在Golang中时不时会面临使用值作为接收器还是使用引用作为接收器的选择,我们对此进行了简化,方法只能属于引用。从语法上看,凹语言中对于方法的定义更类似于C++,但它内在的设计哲学还是Golang风格的,它仍然使用了匿名嵌入组合的方式进行对象复用,而没有使用C++的继承模式。

接口也是隐式合约。空接口作为万能封装器、接口具体类型断言、接口互查等特性都完整支持。

我们很荣幸进入了CNCF的Wasm全景图。参照最初的设计目标,凹语言MVP版已经完成了语法特性的90%,当然这其中大部分的实现都很粗糙,只是解决了有无问题,改进、优化的待办事项清单几乎是无穷无尽的。接下来我们将投入下面这些方面:

首先是一套易用的Javascript交互接口。前面曾经提到,现在实用的、支持Wasm的高级语言,大多数都不是专门针对Wasm设计的,在使用这些语言进行开发的时候,与宿主JS环境交互操作都存在不同程度的痛点,这个问题是凹语言立项的起因之一,因此在核心语法特性告一段落之后,我们将着力尝试解决它。来自南宁的赵普明前几天提供了一个初始版本的胶水代码生成器,已经能自动生成基本数据类型的全局变量、函数在JS侧读写调用的胶水代码,后续我们会根据需要支持更多的数据类型和对象的自动导出。赵普明同时也是凹语言中文语法方向的负责人。

然后是标准库建设。标准库的重要性是不言而喻的,一些被广泛使用的语言之所以成功,与它们自带了高质量的、有针对性的标准库密不可分。标准库的建设是一个长期的事情,这部分的工作目前是柴树杉在负责。

曾经有人问我们为什么不输出LLVMIR,通过LLVM来实现对Wasm的支持。实际上在技术选型阶段确实考虑过这条路线。使用LLVM的好处是显而易见的,强力的优化、广泛的后端支持等等,但一旦走上这条路,我们能学习到的可能更多是LLVM这套工具的使用方法,而不是完整的后端技术。另外,更多的外部依赖,意味着选择的自由更少,这与我们追求自由的指导思想是背离的,因此最终放弃了LLVM而选择了目前的方案。由于凹语言的语法从虚拟语法树角度来看是Golang的子集,而且我们在使用Golang开发凹编译器时对语言特性的使用非常保守,因此如果沿着“减少外部依赖”的方向继续发展下去,实现自举对凹来说并不是高不可攀的障碍。

社区对一些更贴近落地场景的模块呼声比较高,比如图形编程、三维引擎、小型趣味游戏等等。后续开发组会围绕着这些实用项目,有针对性的在各个方面补短板。

到目前为止凹语言项目所做的事情,对整个开源生态来说不值一提。但对开发组来说,在不到两年的时间内利用业余时间把一门语言拉过了勉强可用的门槛,我们自己倒觉得挺开心的。在这次开源实践的过程中我们有很多感受,在此跟大家分享其中一些:

凹语言项目组2020年就成立了,但是我们花了两年的时间才做好正式开干的思想准备,实际上回过头看,当时由于技术问题尚不清楚而引发的很多担忧都是没有必要的。在不熟悉的领域开启一个全新的项目,克服启动阻力往往很困难,这其中心理上的不安占了很大一部分。行为会反作用于思想,尽早开源可以卸下思想上犹豫不决的包袱,所以即使单从改善项目发起人心态的角度来说,开源也是克服启动阻力最好的办法。

最近有一篇帖子挺火的,谈到了对开源抱有的几条常见幻想,大体上里面所说的内容都是事实。开源生态中头部效应非常明显,大多数项目不可能从社区获得决定性的帮助,关键特性和重要功能往往只能由发起人亲自完成。但这并不意味着项目无法通过开源获得任何帮助。以我们为例,编程语言类的项目在开源生态中是非常小众的方向,但凹语言开源后,CSDN、开源中国等媒体进行了报道,入围了InfoQ2022新锐开源项目榜单,还吸引到了扈梦明、赵普明这样的活跃核心成员。虽然这个过程充满了偶然性,无法在所有项目上复现,但中国的程序员群体这么大,再稀奇的想法,一定也会有同道中人。

这一条就不用说了,没有外部反馈的话,长周期的项目很难坚持下去。正面反馈和负面反馈都是项目的推动力,甚至我觉得负面反馈的效力会更大。

最后,凹语言项目是一次草根程序员重新掌握工具的尝试,我们希望这次努力能换来更多的自由,更重要的是,这个过程既有趣,又浪漫。