@llxlr/silq 0.1.3-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,288 @@
1
+ # Silq (Rust implementation)
2
+
3
+ > 用 Rust 重构的 Silq 量子编程语言编译器
4
+
5
+ Silq 是 ETH Zurich 开发的高阶量子编程语言,具有强静态类型系统和自动去计算(uncomputation)功能。本项目是用 **Rust** 对原始 D 语言实现的完整重写。
6
+
7
+ ## 项目状态
8
+
9
+ | 模块 | 状态 | 描述 |
10
+ |------|------|------|
11
+ | 词法分析器 (Lexer) | ✅ 完整 | UTF-8, Unicode 数学符号, 注解, 嵌套注释 |
12
+ | 语法分析器 (Parser) | ✅ 完整 | Pratt 表达式解析, `:=` 中缀赋值, 声明, 控制流 |
13
+ | AST 定义 | ✅ 完整 | 30+ 表达式节点, 完整类型系统 |
14
+ | 语义分析 | ✅ 基本 | 名称解析, 声明注册 |
15
+ | 线性检查器 | ✅ 基本 | const/moved 跟踪 |
16
+ | 量子模拟器 (QSim) | ✅ 核心 | 状态向量, qubit 分配, H/X/Y/Z/CNOT/随机测量 |
17
+ | HQIR 后端 | 🔧 骨架 | 框架就绪 |
18
+ | 标准库 | ✅ | prelude.slq 包含 |
19
+
20
+ **代码规模:** 5,754 行 Rust 代码 | **测试:** 10/10 通过
21
+
22
+ ## 快速开始
23
+
24
+ ### 构建
25
+
26
+ ```bash
27
+ cd silq-rs
28
+ cargo build --release
29
+ ```
30
+
31
+ ### 运行
32
+
33
+ ```bash
34
+ # 运行量子程序
35
+ cargo run -- --run test/bell.slq
36
+
37
+ # 仅类型检查
38
+ cargo run -- --check examples.slq
39
+
40
+ # 跟踪执行过程
41
+ cargo run -- --run --trace test/bell.slq
42
+
43
+ # dump 量子态
44
+ cargo run -- --run --dump test/bell.slq
45
+ ```
46
+
47
+ ## Silq 语言特性
48
+
49
+ ### 量子/经典类型区分
50
+
51
+ Silq 用 `!` 前缀标记经典类型,无前缀为量子类型:
52
+
53
+ ```
54
+ x: 𝔹 // 量子比特 (qubit)
55
+ x: !𝔹 // 经典布尔值 (classical bool)
56
+ ```
57
+
58
+ 数值类型层级: `𝔹 <: ℕ <: ℤ <: ℚ <: ℝ <: ℂ`
59
+
60
+ ### 基本量子门
61
+
62
+ ```
63
+ H(x) // Hadamard 门
64
+ X(x) // Pauli-X (NOT) 门
65
+ Y(x) // Pauli-Y 门
66
+ Z(x) // Pauli-Z 门
67
+ phase(φ) // 全局相位旋转
68
+ CNOT(x, y) // 受控非门
69
+ measure(x) // 测量量子比特
70
+ ```
71
+
72
+ ### 示例: Bell 态
73
+
74
+ ```
75
+ def main() {
76
+ x := H(0); // 创建叠加态
77
+ y := 0;
78
+ if x {
79
+ y := X(y); // CNOT 的 if-实现
80
+ }
81
+ forget(x=y); // 去计算 x
82
+ assert(!measure(H(y))); // 验证 Bell 态
83
+ }
84
+ ```
85
+
86
+ ### 示例: Deutsch 算法
87
+
88
+ ```
89
+ def solve(const O_f: B x B !-> B x B) {
90
+ x := H(0);
91
+ y := H(1);
92
+ (x, y) := O_f(x, y);
93
+ x := H(x);
94
+ measure(y);
95
+ return measure(x);
96
+ }
97
+
98
+ def main() {
99
+ // 四种 oracle 类型
100
+ def O_id(x: B, y: B) { y xor= x; return (x, y); }
101
+ def O_not(x: B, y: B) { y xor= !x; return (x, y); }
102
+ def O_zero(x: B, y: B) { y xor= 0; return (x, y); }
103
+ def O_one(x: B, y: B) { y xor= 1; return (x, y); }
104
+
105
+ assert(solve(O_id)); // id 是平衡的 → 1
106
+ assert(solve(O_not)); // not 是平衡的 → 1
107
+ assert(!solve(O_zero)); // zero 是常数的 → 0
108
+ assert(!solve(O_one)); // one 是常数的 → 0
109
+ }
110
+ ```
111
+
112
+ ## 核心特性
113
+
114
+ ### 1. 自动去计算 (Automatic Uncomputation)
115
+
116
+ Silq 自动生成量子电路的反向(伴随)变换,实现安全的量子资源释放:
117
+
118
+ ```
119
+ def reverse[τ, χ, φ](f: const τ×χ →mfree φ)(c: τ, x: φ): χ {
120
+ f(c, y) := x;
121
+ return y;
122
+ }
123
+ ```
124
+
125
+ ### 2. 线性类型系统
126
+
127
+ - `const` — 可安全复制(仅限经典值)
128
+ - `moved` — 线性使用,恰好一次
129
+ - 编译器自动检测违反量子不可克隆定理的操作
130
+
131
+ ### 3. 依赖类型
132
+
133
+ 类型可以依赖值:
134
+
135
+ ```
136
+ dat int[n: !ℕ] quantum {} // 固定宽度整数
137
+ def vector[τ](n: !ℕ, x: τ): τ^n // 固定长度向量
138
+ ```
139
+
140
+ ## 编译管线
141
+
142
+ ```
143
+ 源码 (.slq)
144
+
145
+ [Lexer] → Token 流 (Unicode math, UTF-8)
146
+
147
+ [Parser] → AST (Pratt 表达式解析)
148
+
149
+ [Semantic] → 类型标注 AST (名称解析, 类型推断)
150
+
151
+ [Checker] → 线性资源校验 (const/moved)
152
+
153
+ [Backend]
154
+ ├─ QSim → 量子模拟执行
155
+ └─ HQIR → 量子中间表示输出
156
+ ```
157
+
158
+ ## 命令行选项
159
+
160
+ ```
161
+ Usage: silq [OPTION]... [FILE]...
162
+
163
+ Options:
164
+ --run 运行模拟器
165
+ --compile 编译到 HQIR 格式
166
+ --check 仅静态检查
167
+ --trace 跟踪执行
168
+ --verbose, -v 详细输出
169
+ --dump, --dump-state 执行后输出量子态
170
+ --help, -h 显示帮助
171
+ ```
172
+
173
+ ## WebAssembly (WASM)
174
+
175
+ 项目支持编译到 WebAssembly,可在浏览器中运行 Silq 量子程序。
176
+
177
+ ### 编译
178
+
179
+ ```bash
180
+ # 浏览器目标 (生成 .wasm + JS 绑定)
181
+ cargo build --target wasm32-unknown-unknown --no-default-features --features wasm --release
182
+
183
+ # Rust 库目标 (嵌入其他 wasm32 Rust 项目)
184
+ cargo build --target wasm32-unknown-unknown --no-default-features --release
185
+ ```
186
+
187
+ 编译后使用 `wasm-bindgen` 生成 JS 胶水代码:
188
+ ```bash
189
+ wasm-bindgen --target web target/wasm32-unknown-unknown/release/silq.wasm --out-dir pkg/
190
+ ```
191
+
192
+ ### WAM 导出的函数
193
+
194
+ | 函数 | 说明 |
195
+ |------|------|
196
+ | `run_silq(source)` | 解析并执行 Silq 程序,返回结果字符串 |
197
+ | `run_silq_dump(source)` | 解析并执行,返回完整量子态振幅输出 |
198
+ | `parse_silq(source)` | 仅解析,返回 AST 调试输出 |
199
+ | `tokenize_silq(source)` | 仅词法分析,返回 Token 列表 |
200
+
201
+ ### 浏览器中使用
202
+
203
+ ```javascript
204
+ import init, { run_silq, run_silq_dump } from "./pkg/silq.js";
205
+
206
+ await init();
207
+
208
+ const result = run_silq(`
209
+ x := H(0:𝔹);
210
+ return measure(x);
211
+ `);
212
+ console.log(result);
213
+ ```
214
+
215
+ ### 在线游乐场
216
+
217
+ `test/wasm/` 目录包含两个浏览器演示页面:
218
+
219
+ - **`demo.html`** — 最小演示,Bell 态示例,Run 按钮
220
+ - **`index.html`** — 完整量子游乐场,Prism.js 语法高亮,多示例切换,Shift+Click 导出量子态,深色主题
221
+
222
+ 使用方式(需先完成上述 WASM 编译 + wasm-bindgen 步骤):
223
+ ```bash
224
+ cp pkg/silq_bg.wasm pkg/silq.js test/wasm/
225
+ cd test/wasm && python -m http.server # 浏览器打开 localhost:8000
226
+ ```
227
+
228
+ ### Cargo Features
229
+
230
+ | Feature | 说明 |
231
+ |---------|------|
232
+ | `default` (= `terminal`) | 启用 ANSI 彩色输出 (native only) |
233
+ | `wasm` | 启用 `wasm-bindgen`,导出 JS 可调用的函数 |
234
+ | `terminal` | 引入 `colored` 依赖 |
235
+
236
+ WASM 构建时必须使用 `--no-default-features` 禁用终端彩色输出。
237
+
238
+ ## 项目结构
239
+
240
+ ```
241
+ silq-rs/
242
+ ├── Cargo.toml
243
+ ├── README.md
244
+ ├── ARCHITECTURE.md
245
+ ├── library/
246
+ │ ├── prelude.slq # 标准库 (487 行)
247
+ │ └── __internal/operators.slq # 运算符实现
248
+ ├── src/
249
+ │ ├── main.rs # CLI 入口 (196 行)
250
+ │ ├── lib.rs # 库根
251
+ │ ├── token.rs # Token/关键字/优先级 (348 行)
252
+ │ ├── lexer.rs # 词法分析器 (759 行)
253
+ │ ├── parser.rs # Pratt 解析器 (1045 行)
254
+ │ ├── ast.rs # AST 定义 (916 行)
255
+ │ ├── scope.rs # 符号表 (102 行)
256
+ │ ├── semantic.rs # 语义分析 (269 行)
257
+ │ ├── checker.rs # 线性检查 (153 行)
258
+ │ ├── consteval.rs # 常量求值 (131 行)
259
+ │ ├── conversion.rs # 类型转换 (45 行)
260
+ │ ├── reverse.rs # 量子逆变换 (103 行)
261
+ │ ├── modules.rs # 模块系统 (133 行)
262
+ │ ├── errors.rs # 错误处理 (272 行)
263
+ │ ├── qsim.rs # 量子模拟器 (1097 行)
264
+ │ ├── hqir.rs # HQIR 后端 (84 行)
265
+ │ ├── wasm.rs # WASM 绑定 (94 行)
266
+ │ └── options.rs # 配置 (56 行)
267
+ └── test/
268
+ ├── bell.slq # Bell 态示例
269
+ └── wasm/
270
+ ├── demo.html # WASM 最小演示
271
+ ├── index.html # 完整量子游乐场
272
+ └── prism-silq.js # Silq 语法高亮 (Prism.js)
273
+ ```
274
+
275
+ ## 构建要求
276
+
277
+ - **Rust** 1.75+
278
+ - 依赖项: `num-complex`, `num-bigint`, `itertools`, `colored`, `fastrand`
279
+
280
+ ## 参考
281
+
282
+ - [Silq 官方项目](https://github.com/tgehr/silq)
283
+ - [Silq 论文](https://silq.ethz.ch)
284
+ - [原始 D 语言实现](https://github.com/tgehr/silq)
285
+
286
+ ## License
287
+
288
+ Boost Software License 1.0 (与原始项目保持一致)
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@llxlr/silq",
3
+ "type": "module",
4
+ "description": "Silq quantum programming language - Rust implementation",
5
+ "version": "0.1.3-dev",
6
+ "license": "BSL-1.0",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/llxlr/silq-rs.git"
10
+ },
11
+ "files": [
12
+ "silq_bg.wasm.d.ts",
13
+ "silq_bg.wasm",
14
+ "silq.js",
15
+ "silq.d.ts"
16
+ ],
17
+ "main": "silq.js",
18
+ "types": "silq.d.ts",
19
+ "sideEffects": [
20
+ "./snippets/*"
21
+ ]
22
+ }
package/silq.d.ts ADDED
@@ -0,0 +1,47 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /**
5
+ * Parse and run a Silq program string, returning the result as a string.
6
+ */
7
+ export function run_silq(source: string): string;
8
+
9
+ /**
10
+ * Run a Silq program with quantum state dump.
11
+ */
12
+ export function run_silq_dump(source: string): string;
13
+
14
+ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
15
+
16
+ export interface InitOutput {
17
+ readonly memory: WebAssembly.Memory;
18
+ readonly run_silq: (a: number, b: number) => [number, number];
19
+ readonly run_silq_dump: (a: number, b: number) => [number, number];
20
+ readonly __wbindgen_externrefs: WebAssembly.Table;
21
+ readonly __wbindgen_malloc: (a: number, b: number) => number;
22
+ readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
23
+ readonly __wbindgen_free: (a: number, b: number, c: number) => void;
24
+ readonly __wbindgen_start: () => void;
25
+ }
26
+
27
+ export type SyncInitInput = BufferSource | WebAssembly.Module;
28
+
29
+ /**
30
+ * Instantiates the given `module`, which can either be bytes or
31
+ * a precompiled `WebAssembly.Module`.
32
+ *
33
+ * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
34
+ *
35
+ * @returns {InitOutput}
36
+ */
37
+ export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
38
+
39
+ /**
40
+ * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
41
+ * for everything else, calls `WebAssembly.instantiate` directly.
42
+ *
43
+ * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
44
+ *
45
+ * @returns {Promise<InitOutput>}
46
+ */
47
+ export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
package/silq.js ADDED
@@ -0,0 +1,230 @@
1
+ /* @ts-self-types="./silq.d.ts" */
2
+
3
+ /**
4
+ * Parse and run a Silq program string, returning the result as a string.
5
+ * @param {string} source
6
+ * @returns {string}
7
+ */
8
+ export function run_silq(source) {
9
+ let deferred2_0;
10
+ let deferred2_1;
11
+ try {
12
+ const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
13
+ const len0 = WASM_VECTOR_LEN;
14
+ const ret = wasm.run_silq(ptr0, len0);
15
+ deferred2_0 = ret[0];
16
+ deferred2_1 = ret[1];
17
+ return getStringFromWasm0(ret[0], ret[1]);
18
+ } finally {
19
+ wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
20
+ }
21
+ }
22
+
23
+ /**
24
+ * Run a Silq program with quantum state dump.
25
+ * @param {string} source
26
+ * @returns {string}
27
+ */
28
+ export function run_silq_dump(source) {
29
+ let deferred2_0;
30
+ let deferred2_1;
31
+ try {
32
+ const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
33
+ const len0 = WASM_VECTOR_LEN;
34
+ const ret = wasm.run_silq_dump(ptr0, len0);
35
+ deferred2_0 = ret[0];
36
+ deferred2_1 = ret[1];
37
+ return getStringFromWasm0(ret[0], ret[1]);
38
+ } finally {
39
+ wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
40
+ }
41
+ }
42
+ function __wbg_get_imports() {
43
+ const import0 = {
44
+ __proto__: null,
45
+ __wbindgen_init_externref_table: function() {
46
+ const table = wasm.__wbindgen_externrefs;
47
+ const offset = table.grow(4);
48
+ table.set(0, undefined);
49
+ table.set(offset + 0, undefined);
50
+ table.set(offset + 1, null);
51
+ table.set(offset + 2, true);
52
+ table.set(offset + 3, false);
53
+ },
54
+ };
55
+ return {
56
+ __proto__: null,
57
+ "./silq_bg.js": import0,
58
+ };
59
+ }
60
+
61
+ function getStringFromWasm0(ptr, len) {
62
+ return decodeText(ptr >>> 0, len);
63
+ }
64
+
65
+ let cachedUint8ArrayMemory0 = null;
66
+ function getUint8ArrayMemory0() {
67
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
68
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
69
+ }
70
+ return cachedUint8ArrayMemory0;
71
+ }
72
+
73
+ function passStringToWasm0(arg, malloc, realloc) {
74
+ if (realloc === undefined) {
75
+ const buf = cachedTextEncoder.encode(arg);
76
+ const ptr = malloc(buf.length, 1) >>> 0;
77
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
78
+ WASM_VECTOR_LEN = buf.length;
79
+ return ptr;
80
+ }
81
+
82
+ let len = arg.length;
83
+ let ptr = malloc(len, 1) >>> 0;
84
+
85
+ const mem = getUint8ArrayMemory0();
86
+
87
+ let offset = 0;
88
+
89
+ for (; offset < len; offset++) {
90
+ const code = arg.charCodeAt(offset);
91
+ if (code > 0x7F) break;
92
+ mem[ptr + offset] = code;
93
+ }
94
+ if (offset !== len) {
95
+ if (offset !== 0) {
96
+ arg = arg.slice(offset);
97
+ }
98
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
99
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
100
+ const ret = cachedTextEncoder.encodeInto(arg, view);
101
+
102
+ offset += ret.written;
103
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
104
+ }
105
+
106
+ WASM_VECTOR_LEN = offset;
107
+ return ptr;
108
+ }
109
+
110
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
111
+ cachedTextDecoder.decode();
112
+ const MAX_SAFARI_DECODE_BYTES = 2146435072;
113
+ let numBytesDecoded = 0;
114
+ function decodeText(ptr, len) {
115
+ numBytesDecoded += len;
116
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
117
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
118
+ cachedTextDecoder.decode();
119
+ numBytesDecoded = len;
120
+ }
121
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
122
+ }
123
+
124
+ const cachedTextEncoder = new TextEncoder();
125
+
126
+ if (!('encodeInto' in cachedTextEncoder)) {
127
+ cachedTextEncoder.encodeInto = function (arg, view) {
128
+ const buf = cachedTextEncoder.encode(arg);
129
+ view.set(buf);
130
+ return {
131
+ read: arg.length,
132
+ written: buf.length
133
+ };
134
+ };
135
+ }
136
+
137
+ let WASM_VECTOR_LEN = 0;
138
+
139
+ let wasmModule, wasmInstance, wasm;
140
+ function __wbg_finalize_init(instance, module) {
141
+ wasmInstance = instance;
142
+ wasm = instance.exports;
143
+ wasmModule = module;
144
+ cachedUint8ArrayMemory0 = null;
145
+ wasm.__wbindgen_start();
146
+ return wasm;
147
+ }
148
+
149
+ async function __wbg_load(module, imports) {
150
+ if (typeof Response === 'function' && module instanceof Response) {
151
+ if (typeof WebAssembly.instantiateStreaming === 'function') {
152
+ try {
153
+ return await WebAssembly.instantiateStreaming(module, imports);
154
+ } catch (e) {
155
+ const validResponse = module.ok && expectedResponseType(module.type);
156
+
157
+ if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
158
+ console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
159
+
160
+ } else { throw e; }
161
+ }
162
+ }
163
+
164
+ const bytes = await module.arrayBuffer();
165
+ return await WebAssembly.instantiate(bytes, imports);
166
+ } else {
167
+ const instance = await WebAssembly.instantiate(module, imports);
168
+
169
+ if (instance instanceof WebAssembly.Instance) {
170
+ return { instance, module };
171
+ } else {
172
+ return instance;
173
+ }
174
+ }
175
+
176
+ function expectedResponseType(type) {
177
+ switch (type) {
178
+ case 'basic': case 'cors': case 'default': return true;
179
+ }
180
+ return false;
181
+ }
182
+ }
183
+
184
+ function initSync(module) {
185
+ if (wasm !== undefined) return wasm;
186
+
187
+
188
+ if (module !== undefined) {
189
+ if (Object.getPrototypeOf(module) === Object.prototype) {
190
+ ({module} = module)
191
+ } else {
192
+ console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
193
+ }
194
+ }
195
+
196
+ const imports = __wbg_get_imports();
197
+ if (!(module instanceof WebAssembly.Module)) {
198
+ module = new WebAssembly.Module(module);
199
+ }
200
+ const instance = new WebAssembly.Instance(module, imports);
201
+ return __wbg_finalize_init(instance, module);
202
+ }
203
+
204
+ async function __wbg_init(module_or_path) {
205
+ if (wasm !== undefined) return wasm;
206
+
207
+
208
+ if (module_or_path !== undefined) {
209
+ if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
210
+ ({module_or_path} = module_or_path)
211
+ } else {
212
+ console.warn('using deprecated parameters for the initialization function; pass a single object instead')
213
+ }
214
+ }
215
+
216
+ if (module_or_path === undefined) {
217
+ module_or_path = new URL('silq_bg.wasm', import.meta.url);
218
+ }
219
+ const imports = __wbg_get_imports();
220
+
221
+ if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
222
+ module_or_path = fetch(module_or_path);
223
+ }
224
+
225
+ const { instance, module } = await __wbg_load(await module_or_path, imports);
226
+
227
+ return __wbg_finalize_init(instance, module);
228
+ }
229
+
230
+ export { initSync, __wbg_init as default };
package/silq_bg.wasm ADDED
Binary file
@@ -0,0 +1,10 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ export const memory: WebAssembly.Memory;
4
+ export const run_silq: (a: number, b: number) => [number, number];
5
+ export const run_silq_dump: (a: number, b: number) => [number, number];
6
+ export const __wbindgen_externrefs: WebAssembly.Table;
7
+ export const __wbindgen_malloc: (a: number, b: number) => number;
8
+ export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
9
+ export const __wbindgen_free: (a: number, b: number, c: number) => void;
10
+ export const __wbindgen_start: () => void;