|
| 1 | +# 凹语言 WebAssembly 3 分钟入门 |
| 2 | + |
| 3 | +- 时间:2024-09-25 |
| 4 | +- 撰稿:凹语言开发组 |
| 5 | +- 转载请注明原文链接:[https://wa-lang.org/smalltalk/st0053.html](https://wa-lang.org/smalltalk/st0053.html) |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +凹语言是国内首个面向WebAssembly设计通用编程语言,也是目前被 [CNCF基金会wasm全景图](https://landscape.cncf.io/?item=wasm--languages--wa-lang) 收录的的唯一一个来自中国的开源编程语言项目。凹语言项目诞生时的一个愿景就是简化WebAssembly网页应用的开发。这里我们将展示如何快速开启一个WebAssembly应用。 |
| 10 | + |
| 11 | +## 1. 安装凹语言命令行 |
| 12 | + |
| 13 | +凹语言采用Go语言实现,目前可以通过以下Go命令安装最新的凹语言命令行: |
| 14 | + |
| 15 | +``` |
| 16 | +$ go install wa-lang.org/wa@master |
| 17 | +``` |
| 18 | + |
| 19 | +安装完成后输出`wa`命令查看帮助信息: |
| 20 | + |
| 21 | +``` |
| 22 | +$ wa |
| 23 | +NAME: |
| 24 | + Wa - Wa is a tool for managing Wa source code. |
| 25 | +
|
| 26 | +USAGE: |
| 27 | + wa [global options] command [command options] [arguments...] |
| 28 | +
|
| 29 | +VERSION: |
| 30 | + v0.17.0 |
| 31 | +
|
| 32 | +COMMANDS: |
| 33 | + play start Wa playground |
| 34 | + init init a sketch Wa module |
| 35 | + build compile Wa source code |
| 36 | + run compile and run Wa program |
| 37 | + fmt format Wa source code file |
| 38 | + test test Wa packages |
| 39 | + lsp run Wa langugage server (dev) |
| 40 | + yacc generates parsers for LALR(1) grammars |
| 41 | + logo print Wa text format logo |
| 42 | +
|
| 43 | +GLOBAL OPTIONS: |
| 44 | + --debug, -d set debug mode (default: false) |
| 45 | + --trace value, -t value set trace mode (*|app|compiler|loader) |
| 46 | + --help, -h show help (default: false) |
| 47 | + --version, -v print the version (default: false) |
| 48 | +
|
| 49 | +COPYRIGHT: |
| 50 | + Copyright 2018 The Wa Authors. All rights reserved. |
| 51 | +
|
| 52 | +See "https://wa-lang.org" for more information. |
| 53 | +``` |
| 54 | + |
| 55 | +## 2. 初始化凹语言工程 |
| 56 | + |
| 57 | +通过`wa init`命令初始化一个名为`hello`的工程: |
| 58 | + |
| 59 | +``` |
| 60 | +$ wa init |
| 61 | +$ cd hello |
| 62 | +$ tree |
| 63 | +. |
| 64 | +├── README.md |
| 65 | +├── output |
| 66 | +│ └── index.html |
| 67 | +├── src |
| 68 | +│ └── main.wa |
| 69 | +└── wa.mod |
| 70 | +
|
| 71 | +3 directories, 4 files |
| 72 | +``` |
| 73 | + |
| 74 | +其中 `wa.mod` 是工程文件: |
| 75 | + |
| 76 | +```ini |
| 77 | +$ cat wa.mod |
| 78 | +# 版权 @2024 hello 作者。保留所有权利。 |
| 79 | + |
| 80 | +name = "hello" |
| 81 | +pkgpath = "myapp" |
| 82 | +target = "js |
| 83 | +``` |
| 84 | +
|
| 85 | +其中 `main.wa` 是主程序: |
| 86 | +
|
| 87 | +```wa |
| 88 | +$ cat src/main.wa |
| 89 | +// 版权 @2024 hello 作者。保留所有权利。 |
| 90 | +
|
| 91 | +func main { |
| 92 | + println("你好,凹语言!") |
| 93 | + println(Sum(100)) |
| 94 | +} |
| 95 | +
|
| 96 | +func Sum(n: int) => int { |
| 97 | + v: int |
| 98 | + for i := 1; i <= n; i++ { |
| 99 | + v += i |
| 100 | + } |
| 101 | + return v |
| 102 | +} |
| 103 | +``` |
| 104 | +
|
| 105 | +此外还有一个`output/index.html`网页文件,该文件内容稍后说明。 |
| 106 | +
|
| 107 | +## 3. 编译并执行凹语言程序 |
| 108 | +
|
| 109 | +在`hello`目录对应的命令行环境通过`wa run`命令编译并执行: |
| 110 | +
|
| 111 | +``` |
| 112 | +$ wa run |
| 113 | +listen at http://localhost:8000 |
| 114 | +... |
| 115 | +``` |
| 116 | +
|
| 117 | +该命令在编译得到wasm文件后,会在output命令启动一个web服务。然后通过以上网址可以访问`index.html`页面。效果如下: |
| 118 | +
|
| 119 | + |
| 120 | +
|
| 121 | +在开发者控制台窗口输出了“你好,凹语言!”和`5050`结果。此时`output`目录文件如下: |
| 122 | +
|
| 123 | +``` |
| 124 | +$ tree output/ |
| 125 | +output/ |
| 126 | +├── hello.js |
| 127 | +├── hello.wasm |
| 128 | +├── hello.wat |
| 129 | +└── index.html |
| 130 | +
|
| 131 | +1 directory, 4 files |
| 132 | +``` |
| 133 | +
|
| 134 | +首先是`main.wa`编译得到`hello.wat`,然后转化为`hello.wasm`二进制格式。`hello.js`是`hello.wasm`文件和JavaScript之间的胶水代码。 |
| 135 | +
|
| 136 | +当然也可以通过增加`-target=wasi`参数输出`wasi`规范的wasm文件,并在命令行执行: |
| 137 | +
|
| 138 | +``` |
| 139 | +$ wa run -target=wasi |
| 140 | +你好,凹语言! |
| 141 | +5050 |
| 142 | +``` |
| 143 | +
|
| 144 | +*注意:凹语言的`main`函数对应输出的`wasm`文件导出的函数,并不会自动执行。因此如果使用`wasmer`等第三方工具执行,需要将`main`函数的代码移动到`init`函数中。* |
| 145 | +
|
| 146 | +## 4. 看看页面输出的是什么 |
| 147 | +
|
| 148 | +打开网页看到的是`1+2+3+...+100 = 5050`,这是在`output/index.html`网页调用`Sum`函数计算的结果。`index.html`文件如下: |
| 149 | +
|
| 150 | +```htm |
| 151 | +<!DOCTYPE html> |
| 152 | +<html lang="en"> |
| 153 | +<head> |
| 154 | + <meta charset="UTF-8"> |
| 155 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 156 | + <title>hello</title> |
| 157 | +</head> |
| 158 | +<body> |
| 159 | + <div style="text-align: center;"> |
| 160 | + <pre id="output"></pre> |
| 161 | + </div> |
| 162 | + |
| 163 | + <script type="text/javascript" src="./hello.js"></script> |
| 164 | + |
| 165 | + <script> |
| 166 | + let app = new WaApp(); |
| 167 | + app.init().then((result) => { |
| 168 | + app.main(); |
| 169 | + document.getElementById('output').innerText = `1+2+3+...+100 = ${app.Sum(100)}`; |
| 170 | + }) |
| 171 | + </script> |
| 172 | +</body> |
| 173 | +</html> |
| 174 | +``` |
| 175 | + |
| 176 | +首先是通过`hello.js`胶水代码初始化`wasm`模块,得到了`WaApp`对象。然后通过`app.init()`执行凹语言的`init`初始化代码,然后通过`app.main()`执行`main`函数代码。`app.Sum`对应的是导出的`Sum`函数,然后将计算结果更新到页面的`output`区域。 |
| 177 | + |
| 178 | +## 5. 凹语言版本的Brainfuck解释器 |
| 179 | + |
| 180 | +在 [凹语言、图灵机和 BF 语言](https://wa-lang.org/smalltalk/st0013.html) 文章中,我们介绍过用凹语言写了一个命令行版本的Brainfuck解释器,现在可以将其改造为网页版本。 |
| 181 | + |
| 182 | +首先是修改 `main.wa` 导出 `Run` 函数(waroot/examples/brainfuck): |
| 183 | + |
| 184 | +``` |
| 185 | +import "brainfuck/bfpkg" |
| 186 | +
|
| 187 | +func main { |
| 188 | + // print hi |
| 189 | + const code = "++++++++++[>++++++++++<-]>++++.+." |
| 190 | + vm := bfpkg.NewBrainFuck(code) |
| 191 | + println(string(vm.Run())) |
| 192 | +} |
| 193 | +
|
| 194 | +func Run(code: string) => string { |
| 195 | + vm := bfpkg.NewBrainFuck(code) |
| 196 | + return string(vm.Run()) |
| 197 | +} |
| 198 | +``` |
| 199 | + |
| 200 | +然后修改 `output/index.html` 页面: |
| 201 | + |
| 202 | +```html |
| 203 | +<!DOCTYPE html> |
| 204 | +<html lang="en"> |
| 205 | +<body> |
| 206 | + <label for="source">Brainfuck Source</label> |
| 207 | + <br> |
| 208 | + <textarea name="source" id="source" cols="30" rows="10">++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.</textarea> |
| 209 | + <br> |
| 210 | + <button id="btn">Run</button> |
| 211 | + <br> |
| 212 | + <p>Output</p> |
| 213 | + <pre id="output"></pre> |
| 214 | + |
| 215 | + <script type="text/javascript" src="./brainfuck.js"></script> |
| 216 | + |
| 217 | + <script> |
| 218 | + let app = new WaApp(); |
| 219 | + app.init().then((result) => { |
| 220 | + document.getElementById('btn').addEventListener('click', function () { |
| 221 | + let code = document.getElementById('source').value; |
| 222 | + let output = app.Run(code); |
| 223 | + document.getElementById('output').innerText = output; |
| 224 | + }) |
| 225 | + }) |
| 226 | + </script> |
| 227 | +</body> |
| 228 | +</html> |
| 229 | +``` |
| 230 | + |
| 231 | +在线地址: [https://wa-lang.org/wa/brainfuck/](https://wa-lang.org/wa/brainfuck/),执行效果如下: |
| 232 | + |
| 233 | + |
| 234 | + |
| 235 | +## 6. 展望 |
| 236 | + |
| 237 | +WebAssembly 是一个非常有前景的基础技术,但是至少使用门槛较高。凹语言作为面向WebAssembly设计的通用语言,希望通过简化流程让大家更方便地使用该技术从而享受技术发展带来的红利。也希望对该技术方向感兴趣的同学一起共建。 |
0 commit comments