凹语言是国内首个面向WebAssembly设计通用编程语言,也是目前被 CNCF基金会wasm全景图 收录的的唯一一个来自中国的开源编程语言项目。凹语言项目诞生时的一个愿景就是简化WebAssembly网页应用的开发。这里我们将展示如何快速开启一个WebAssembly应用。
- 安装凹语言命令行
凹语言采用Go语言实现,目前可以通过以下Go命令安装最新的凹语言命令行:
$ go install wa-lang.org/wa[@master](https://my.oschina.net/u/48054)
安装完成后输出wa
命令查看帮助信息:
$ wa
NAME:
Wa - Wa is a tool for managing Wa source code.
USAGE:
wa [global options] command [command options] [arguments...]
VERSION:
v0.17.0
COMMANDS:
play start Wa playground
init init a sketch Wa module
build compile Wa source code
run compile and run Wa program
fmt format Wa source code file
test test Wa packages
lsp run Wa langugage server (dev)
yacc generates parsers for LALR(1) grammars
logo print Wa text format logo
GLOBAL OPTIONS:
--debug, -d set debug mode (default: false)
--trace value, -t value set trace mode (*|app|compiler|loader)
--help, -h show help (default: false)
--version, -v print the version (default: false)
COPYRIGHT:
Copyright 2018 The Wa Authors. All rights reserved.
See "https://wa-lang.org" for more information.
- 初始化凹语言工程
通过wa init
命令初始化一个名为hello
的工程:
$ wa init
$ cd hello
$ tree
.
├── README.md
├── output
│ └── index.html
├── src
│ └── main.wa
└── wa.mod
3 directories, 4 files
其中 wa.mod
是工程文件:
$ cat wa.mod
# 版权 @2024 hello 作者。保留所有权利。
name = "hello"
pkgpath = "myapp"
target = "js
其中 main.wa
是主程序:
$ cat src/main.wa
// 版权 @2024 hello 作者。保留所有权利。
func main {
println("你好,凹语言!")
println(Sum(100))
}
func Sum(n: int) => int {
v: int
for i := 1; i <= n; i++ {
v += i
}
return v
}
此外还有一个output/index.html
网页文件,该文件内容稍后说明。
- 编译并执行凹语言程序
在hello
目录对应的命令行环境通过wa run
命令编译并执行:
$ wa run
listen at http://localhost:8000
...
该命令在编译得到wasm文件后,会在output命令启动一个web服务。然后通过以上网址可以访问index.html
页面。效果如下:
在开发者控制台窗口输出了"你好,凹语言!"和5050
结果。此时output
目录文件如下:
$ tree output/
output/
├── hello.js
├── hello.wasm
├── hello.wat
└── index.html
1 directory, 4 files
首先是main.wa
编译得到hello.wat
,然后转化为hello.wasm
二进制格式。hello.js
是hello.wasm
文件和JavaScript之间的胶水代码。
当然也可以通过增加-target=wasi
参数输出wasi
规范的wasm文件,并在命令行执行:
$ wa run -target=wasi
你好,凹语言!
5050
注意:凹语言的main
函数对应输出的wasm
文件导出的函数,并不会自动执行。因此如果使用wasmer
等第三方工具执行,需要将main
函数的代码移动到init
函数中。
- 看看页面输出的是什么
打开网页看到的是1+2+3+...+100 = 5050
,这是在output/index.html
网页调用Sum
函数计算的结果。index.html
文件如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>hello</title>
</head>
<body>
<div style="text-align: center;">
<pre id="output"></pre>
</div>
<script type="text/javascript" src="./hello.js"></script>
<script>
let app = new WaApp();
app.init().then((result) => {
app.main();
document.getElementById('output').innerText = `1+2+3+...+100 = ${app.Sum(100)}`;
})
</script>
</body>
</html>
首先是通过hello.js
胶水代码初始化wasm
模块,得到了WaApp
对象。然后通过app.init()
执行凹语言的init
初始化代码,然后通过app.main()
执行main
函数代码。app.Sum
对应的是导出的Sum
函数,然后将计算结果更新到页面的output
区域。
- 凹语言版本的Brainfuck解释器
在 "st0013:凹语言、图灵机和 BF 语言" 文章中,我们介绍过用凹语言写了一个命令行版本的Brainfuck解释器,现在可以将其改造为网页版本。
首先是修改 main.wa
导出 Run
函数(waroot/examples/brainfuck):
import "brainfuck/bfpkg"
func main {
// print hi
const code = "++++++++++[>++++++++++<-]>++++.+."
vm := bfpkg.NewBrainFuck(code)
println(string(vm.Run()))
}
func Run(code: string) => string {
vm := bfpkg.NewBrainFuck(code)
return string(vm.Run())
}
然后修改 output/index.html
页面:
<!DOCTYPE html>
<html lang="en">
<body>
<label for="source">Brainfuck Source</label>
<br>
<textarea name="source" id="source" cols="30" rows="10">++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.</textarea>
<br>
<button id="btn">Run</button>
<br>
<p>Output</p>
<pre id="output"></pre>
<script type="text/javascript" src="./brainfuck.js"></script>
<script>
let app = new WaApp();
app.init().then((result) => {
document.getElementById('btn').addEventListener('click', function () {
let code = document.getElementById('source').value;
let output = app.Run(code);
document.getElementById('output').innerText = output;
})
})
</script>
</body>
</html>
其中app.Run(code)
就是调用导出的Run
函数,解释执行Brainfuck代码。
在线地址: https://wa-lang.org/wa/brainfuck/,执行效果如下:
- 展望
WebAssembly 是一个非常有前景的基础技术,但是至少使用门槛较高。凹语言作为面向WebAssembly设计的通用语言,希望通过简化流程让大家更方便地使用该技术从而享受技术发展带来的红利。也希望对该技术方向感兴趣的同学一起共建。