用户问"怎么回事"，可能是在等待我完成 C/C++ 编译器的创建。

让我重新评估情况。从之前的对话中，我下载了 cib (Clang in Browser) 的 clang.wasm (30MB) 和 clang.js，但 cib 的架构很复杂，它使用了多个脚本文件（process.js, wasm-tools.js, runtime.js, process-runtime.js），并且依赖 CDN 加载。

cib 方案的缺点：
1. 需要多个 JS 文件
2. 依赖 CDN (rawgit)
3. 架构复杂
4. 需要 sysroot 头文件

用户说"可以运行简单的c代码就行"，这意味着不需要完整的 Clang/LLVM。

让我重新思考，使用一个更简单的方案：

**方案：使用手写 C 编译器**

我可以写一个 C 编译器（用 JS 实现），支持基本的 C 语法：
- int 类型
- 变量声明
- 算术运算
- if/else
- while/for
- 函数定义和调用
- printf（简化版）
- return

编译器结构：
1. 词法分析器 → tokens
2. 语法分析器 → AST
3. WASM 代码生成器

这个方案的优点：
- 完全离线
- 体积小（<100KB）
- 可以编译简单 C 代码
- 不依赖外部资源

让我写一个简化的 C 编译器。

**编译器设计：**

词法分析器（Tokenizer）：
- 识别关键字：int, if, else, while, for, return, printf
- 识别标识符
- 识别数字
- 识别运算符：+, -, *, /, %, ==, !=, <, >, <=, >=, =, ++, --
- 识别括号：(), {}, []
- 识别分号、逗号

语法分析器（Parser）：
- 解析函数定义
- 解析变量声明
- 解析表达式
- 解析语句（if, while, for, return, printf）
- 解析函数调用

AST 节点类型：
- Function
- VarDecl
- BinaryOp
- UnaryOp
- Number
- Identifier
- Call
- If
- While
- For
- Return
- Printf

WASM 代码生成器：
- 生成 WASM 二进制模块
- 使用 WebAssembly JS API

**WASM 生成：**

我将使用 WebAssembly 的 JS API 来动态生成 WASM 模块：
1. 使用 `WebAssembly.Module` 和 `WebAssembly.Instance`
2. 或者使用 `wasm-tools` 库

让我使用 WebAssembly 的 `binaryen` 或手动生成 WASM 二进制。

手动生成 WASM 二进制：
- 使用 WASM 二进制格式
- 编写一个 WASM 生成器

或者，我可以使用 `wabt` 的 JS 版本。

但最简单的方式是使用 `WebAssembly.compile` 和 `WebAssembly.instantiate`。

让我写一个 WASM 生成器。

实际上，最简单的方式是使用 **WASM 文本格式 (WAT)**，然后使用 `wabt` 的 `wat2wasm` 转换为二进制。

但 `wabt` 的 JS 版本需要加载。

**让我使用一个更简单的方式：**

**使用 WebAssembly JS API 动态生成 WASM 模块**

WebAssembly JS API 允许使用 `new WebAssembly.Module(buffer)` 来创建模块。

我需要生成 WASM 二进制格式。

WASM 二进制格式：
1. 魔数 (0x00 0x61 0x73 0x6D)
2. 版本 (0x01 0x00 0x00 0x00)
3. 各个 section

让我写一个 WASM 二进制生成器。

**WASM 二进制格式：**

```
0: magic
4: version
8: sections...
```

Section 类型：
- 0: custom
- 1: type
- 2: import
- 3: function
- 4: table
- 5: memory
- 6: global
- 7: export
- 8: start
- 9: element
- 10: code
- 11: data
- 12: data count

**让我写一个简化的 WASM 生成器。**

实际上，让我使用一个更简单的方法：

**使用 WebAssembly 的 Function constructor**

WebAssembly 有一个 `Function` constructor，可以动态创建 WASM 函数。

但这不是标准的 WebAssembly API。

**让我使用 WebAssembly 的 JS API 和 WASM 二进制格式。**

我将写一个简化的 WASM 生成器。

**WASM 生成器设计：**

1. 创建一个 WASM 模块
2. 添加一个 memory section
3. 添加函数
4. 导出函数

让我写一个简化的 WASM 生成器。

**或者，我可以使用一个更简单的方案：**

**使用 `WebAssembly.compile` 和 `WebAssembly.instantiate`**

但我需要生成 WASM 二进制。

**让我使用 `wabt` 的 JS 版本。**

wabt 提供了 `wat2wasm` 工具，可以将 WAT 文本转换为 WASM 二进制。

我可以：
1. 从 C 代码生成 WAT
2. 使用 wabt 的 JS 版本转换为 WASM
3. 运行 WASM

但 wabt 的 JS 版本需要加载。

**让我写一个简化的 WASM 生成器。**

我将写一个简化的 WASM 二进制生成器，支持：
- i32 类型
- i32.add, i32.sub, i32.mul, i32.div_s, i32.rem_s
- i32.eq, i32.ne, i32.lt_s, i32.gt_s, i32.le_s, i32.ge_s
- local.get, local.set, local.tee
- global.get, global.set
- call, call_indirect
- if, else, end
- loop, br, br_if
- return
- memory 访问 (i32.load, i32.store)

**WASM 指令编码：**

```
i32.const: 0x41 + i32
i32.add: 0x6A
i32.sub: 0x6B
i32.mul: 0x6C
i32.div_s: 0x6D
i32.rem_s: 0x6F
i32.eq: 0x46
i32.ne: 0x47
i32.lt_s: 0x48
i32.gt_s: 0x49
i32.le_s: 0x4C
i32.ge_s: 0x4D
local.get: 0x20 + local_index
local.set: 0x21 + local_index
local.tee: 0x22 + local_index
global.get: 0x23 + global_index
global.set: 0x24 + global_index
call: 0x10 + func_index
call_indirect: 0x11 + type_index + table_index
if: 0x04 + block_type
else: 0x05
end: 0x0B
loop: 0x03 + block_type
br: 0x0C + label_index
br_if: 0x0D + label_index
return: 0x0F
drop: 0x1A
select: 0x1B
i32.load: 0x28 + align + offset
i32.store: 0x36 + align + offset
```

**让我写一个 WASM 生成器。**

这将是一个相当复杂的工作，但可行。

让我写一个简化的 C 编译器，生成 WASM 二进制。

**简化 C 语法支持：**

```c
int main() {
    int a = 10;
    int b = 20;
    int c = a + b;
    printf("%d\n", c);
    return 0;
}
```

**AST 节点：**

```
Program -> [Function]
Function -> name, params, body
VarDecl -> name, init
Assign -> name, value
BinaryOp -> op, left, right
Number -> value
Identifier -> name
Call -> name, args
If -> cond, then, else
While -> cond, body
For -> init, cond, update, body
Return -> value
Printf -> format, args
```

**WASM 生成：**

我将使用一个简单的栈机模型。

每个 AST 节点生成 WASM 指令。

**函数调用：**

- `printf` 是外部函数，需要导入
- 用户定义的函数需要导出

**printf 实现：**

我将实现一个简化的 `printf`，只支持 `%d` 和 `%s`。

printf 需要：
- 格式化字符串
- 参数列表
- 输出到 DOM

**方案：**

我将实现 `printf` 作为 JS 函数，通过 WASM 的 import 机制导入。

**Memory 管理：**

WASM 需要一个 memory 来存储字符串和变量。

我将创建一个 1MB 的 memory。

**字符串存储：**

字符串存储在 WASM memory 中，通过偏移量访问。

**printf 实现：**

```javascript
function printf(offset, ...args) {
    // 从 memory 读取格式化字符串
    // 解析格式字符串
    // 输出到 DOM
}
```

**让我开始写代码。**

这将是一个较大的项目，让我写一个完整的 C 编译器。

**编译器架构：**

1. 词法分析器（Tokenizer）
2. 语法分析器（Parser）
3. AST
4. WASM 代码生成器（CodeGen）
5. WASM 二进制生成器（WasmGen）

让我开始写代码。

**Tokenizer：**

```javascript
const keywords = ['int', 'if', 'else', 'while', 'for', 'return', 'printf'];
const operators = ['++', '--', '==', '!=', '<=', '>=', '&&', '||', '+', '-', '*', '/', '%', '=', '<', '>', '!', '&', '|'];
```

**Parser：**

递归下降解析器。

**CodeGen：**

从 AST 生成 WASM 指令序列。

**WasmGen：**

从 WASM 指令序列生成 WASM 二进制。

让我写一个完整的实现。

**文件结构：**

```
/shumengya/www/c-wasm/
├── index.html          # 前端页面
├── compiler.js         # C 编译器（Tokenizer + Parser + CodeGen + WasmGen）
└── c-wasm.conf         # nginx 配置
```

**compiler.js 内容：**

这是一个 JS 文件，包含完整的 C 编译器。

让我开始写代码。

**WASM 二进制生成器：**

我将写一个 WasmGen 类，生成 WASM 二进制。

```javascript
class WasmGen {
    constructor() {
        this.buffer = [];
        this.functions = [];
        this.types = [];
        this.exports = [];
        this.imports = [];
        this.globals = [];
        this.memory = { min: 1 };
        this.data = [];
    }

    // 生成 WASM 二进制
    generate() {
        // 魔数和版本
        this.writeBytes([0x00, 0x61, 0x73, 0x6D]);
        this.writeBytes([0x01, 0x00, 0x00, 0x00]);

        // type section
        this.writeTypeSection();

        // import section
        this.writeImportSection();

        // function section
        this.writeFunctionSection();

        // memory section
        this.writeMemorySection();

        // global section
        this.writeGlobalSection();

        // export section
        this.writeExportSection();

        // code section
        this.writeCodeSection();

        // data section
        this.writeDataSection();

        return new Uint8Array(this.buffer);
    }

    // ... 其他方法
}
```

**让我写一个完整的实现。**

这个代码会比较长，但我会尽量简洁。

**WASM 二进制格式细节：**

Leb128 编码：用于编码整数（变长编码）。

让我写一个 leb128 编码器。

```javascript
function encodeULEB128(value) {
    const bytes = [];
    do {
        let byte = value & 0x7F;
        value >>>= 7;
        if (value !== 0) byte |= 0x80;
        bytes.push(byte);
    } while (value !== 0);
    return bytes;
}

function encodeSLEB128(value) {
    const bytes = [];
    let more = true;
    while (more) {
        let byte = value & 0x7F;
        value >>= 7;
        if ((value === 0 && (byte & 0x40) === 0) || (value === -1 && (byte & 0x40) !== 0)) {
            more = false;
        } else {
            byte |= 0x80;
        }
        bytes.push(byte);
    }
    return bytes;
}
```

**Section 格式：**

每个 section 包含：
- section id (1 byte)
- section size (leb128)
- section content

**Type Section：**

```
id: 1
size: ...
content:
  count: leb128
  types: [func_type]

func_type:
  0x60
  param_count: leb128
  params: [val_type]
  result_count: leb128
  results: [val_type]
```

val_type:
- i32: 0x7F
- i64: 0x7E
- f32: 0x7D
- f64: 0x7C

**Import Section：**

```
id: 2
size: ...
content:
  count: leb128
  imports: [import]

import:
  module_name: string
  field_name: string
  kind: 0x00 (func) | 0x01 (table) | 0x02 (memory) | 0x03 (global)
  index/type: ...
```

**Function Section：**

```
id: 3
size: ...
content:
  count: leb128
  function_indices: [type_index]
```

**Memory Section：**

```
id: 5
size: ...
content:
  count: leb128
  memory: [limits]

limits:
  0x00 min: leb128
  0x01 min: leb128 max: leb128
```

**Global Section：**

```
id: 6
size: ...
content:
  count: leb128
  globals: [global]

global:
  type: val_type + mutability (0x00 or 0x01)
  init: expr
```

**Export Section：**

```
id: 7
size: ...
content:
  count: leb128
  exports: [export]

export:
  name: string
  kind: 0x00 (func) | 0x01 (table) | 0x02 (memory) | 0x03 (global)
  index: leb128
```

**Code Section：**

```
id: 10
size: ...
content:
  count: leb128
  bodies: [function_body]

function_body:
  size: leb128
  locals: [local]
  code: expr
  end: 0x0B

local:
  count: leb128
  type: val_type
```

**Data Section：**

```
id: 11
size: ...
content:
  count: leb128
  segments: [segment]

segment:
  memory_index: leb128
  offset: expr (i32.const ...)
  data: [byte]
```

**让我开始写完整的代码。**

我需要写：
1. Tokenizer
2. Parser
3. AST
4. CodeGen
5. WasmGen

让我写一个完整的实现。

由于代码会比较长，我将使用 `write` 工具来写一个文件。

让我先写一个简化的 C 编译器，支持以下语法：

```c
int main() {
    int a = 10;
    int b = 20;
    int c = a + b;
    printf("%d\n", c);
    return 0;
}
```

**支持的语法：**

1. 函数定义：`int name() { ... }`
2. 变量声明：`int name = expr;`
3. 赋值：`name = expr;`
4. 表达式：`expr + expr`, `expr - expr`, `expr * expr`, `expr / expr`, `expr % expr`
5. 比较：`expr == expr`, `expr != expr`, `expr < expr`, `expr > expr`, `expr <= expr`, `expr >= expr`
6. if/else：`if (cond) { ... } else { ... }`
7. while：`while (cond) { ... }`
8. for：`for (init; cond; update) { ... }`
9. return：`return expr;`
10. printf：`printf("format", ...);`
11. 函数调用：`name(args);`

**不支持的语法：**

- 指针
- 数组
- 结构体
- 类型转换
- 多参数函数（简化）
- 全局变量（简化）

**函数参数：**

为了简化，我将只支持无参数的函数。

**printf 支持：**

只支持 `%d`（整数）和 `%s`（字符串）和 `\n`（换行）。

**字符串存储：**

字符串存储在 WASM memory 中，通过偏移量访问。

**让我开始写代码。**

由于代码量很大，我将分步骤写：

1. 写 compiler.js
2. 写 index.html
3. 写 nginx 配置

让我开始写 compiler.js。

**compiler.js 结构：**

```javascript
class CCompiler {
    constructor() {
        this.tokenizer = new Tokenizer();
        this.parser = new Parser();
        this.codegen = new CodeGen();
        this.wasmgen = new WasmGen();
    }

    compile(source) {
        const tokens = this.tokenizer.tokenize(source);
        const ast = this.parser.parse(tokens);
        const wasmInstr = this.codegen.generate(ast);
        const wasmBinary = this.wasmgen.generate(wasmInstr);
        return wasmBinary;
    }
}
```

**Tokenizer：**

```javascript
class Token {
    constructor(type, value, line, col) {
        this.type = type;
        this.value = value;
        this.line = line;
        this.col = col;
    }
}

class Tokenizer {
    constructor() {
        this.keywords = {
            'int': 'KEYWORD',
            'if': 'KEYWORD',
            'else': 'KEYWORD',
            'while': 'KEYWORD',
            'for': 'KEYWORD',
            'return': 'KEYWORD',
            'printf': 'KEYWORD',
        };
    }

    tokenize(source) {
        // ...
    }
}
```

**Token 类型：**

- KEYWORD: int, if, else, while, for, return, printf
- IDENTIFIER: [a-zA-Z_][a-zA-Z0-9_]*
- NUMBER: [0-9]+
- STRING: "..."
- OPERATOR: +, -, *, /, %, =, ==, !=, <, >, <=, >=, ++, --
- PAREN: (, ), {, }
- SEMICOLON: ;
- COMMA: ,
- EOF

**Parser：**

递归下降解析器。

```
program -> function*
function -> 'int' identifier '(' ')' '{' statement* '}'
statement -> var_decl | assign | if_stmt | while_stmt | for_stmt | return_stmt | printf_stmt | call_stmt
var_decl -> 'int' identifier ('=' expr)? ';'
assign -> identifier '=' expr ';'
if_stmt -> 'if' '(' expr ')' '{' statement* '}' ('else' '{' statement* '}')?
while_stmt -> 'while' '(' expr ')' '{' statement* '}'
for_stmt -> 'for' '(' var_decl | assign ';' expr ';' assign ')' '{' statement* '}'
return_stmt -> 'return' expr ';'
printf_stmt -> 'printf' '(' string (',' expr)* ')' ';'
call_stmt -> identifier '(' (expr (',' expr)*)? ')' ';'
expr -> term (('+'|'-') term)*
term -> factor (('*'|'/'|'%') factor)*
factor -> ('+'|'-') factor | number | identifier | '(' expr ')' | call_expr
call_expr -> identifier '(' (expr (',' expr)*)? ')'
```

**AST 节点：**

```
Program: functions
Function: name, body
VarDecl: name, init
Assign: name, value
If: cond, then, else
While: cond, body
For: init, cond, update, body
Return: value
Printf: format, args
Call: name, args
BinaryOp: op, left, right
UnaryOp: op, operand
Number: value
Identifier: name
String: value
```

**CodeGen：**

生成 WASM 指令序列。

**WASM 指令：**

我将使用一个简化的指令集。

**变量存储：**

局部变量存储在 WASM 的 locals 中。

**函数调用：**

- `printf` 是外部函数，通过 import 调用
- 用户定义的函数通过 call 调用

**printf 实现：**

printf 是一个 JS 函数，通过 WASM import 导入。

```javascript
const imports = {
    env: {
        printf: function(offset, arg0, arg1, arg2, arg3) {
            // 从 memory 读取字符串
            // 解析格式
            // 输出
        }
    }
};
```

**Memory 布局：**

- 0x0000: 字符串数据区
- 字符串数据区之后：其他数据

**让我开始写代码。**

由于代码量很大，我将写一个完整的实现。

让我先写 compiler.js 的完整代码。

**代码生成策略：**

1. 每个函数生成一个 WASM 函数
2. 局部变量使用 WASM locals
3. 表达式使用栈机模型
4. 控制流使用 block/if/loop

**WASM 函数类型：**

```
main: () -> i32
printf: (i32, i32, i32, i32, i32) -> ()
```

**printf 的签名：**

printf 接收一个字符串偏移量和最多 4 个参数。

```javascript
// printf(format_offset, arg0, arg1, arg2, arg3)
function printf(offset, a0, a1, a2, a3) {
    const memory = new Uint8Array(wasmMemory.buffer);
    let str = '';
    for (let i = offset; memory[i] !== 0; i++) {
        str += String.fromCharCode(memory[i]);
    }

    // 替换 %d, %s
    let argIndex = 0;
    const args = [a0, a1, a2, a3];
    let result = '';
    for (let i = 0; i < str.length; i++) {
        if (str[i] === '%' && i + 1 < str.length) {
            if (str[i + 1] === 'd') {
                result += args[argIndex++];
                i++;
            } else if (str[i + 1] === 's') {
                // 字符串参数
                let s = '';
                const sOffset = args[argIndex++];
                for (let j = sOffset; memory[j] !== 0; j++) {
                    s += String.fromCharCode(memory[j]);
                }
                result += s;
                i++;
            } else {
                result += str[i];
            }
        } else if (str[i] === '\\' && i + 1 < str.length) {
            if (str[i + 1] === 'n') {
                result += '\n';
                i++;
            } else {
                result += str[i];
            }
        } else {
            result += str[i];
        }
    }

    return result;
}
```

**让我开始写 compiler.js 的完整代码。**

由于代码量很大，我将使用 write 工具写一个大文件。

让我组织一下代码结构：

```javascript
// ========== 词法分析器 ==========
class Token { ... }
class Tokenizer { ... }

// ========== 语法分析器 ==========
class ASTNode { ... }
class Parser { ... }

// ========== 代码生成器 ==========
class CodeGen { ... }

// ========== WASM 生成器 ==========
class WasmGen { ... }

// ========== C 编译器 ==========
class CCompiler {
    compile(source) {
        const tokens = new Tokenizer().tokenize(source);
        const ast = new Parser().parse(tokens);
        const wasmModule = new CodeGen().generate(ast);
        return wasmModule;
    }
}
```

**让我开始写代码。**

这是一个相当大的代码库，让我尽量写完整。

**Tokenizer 实现：**

```javascript
class Token {
    constructor(type, value, line = 0, col = 0) {
        this.type = type;
        this.value = value;
        this.line = line;
        this.col = col;
    }
}

class Tokenizer {
    tokenize(source) {
        const tokens = [];
        let i = 0;
        let line = 1;
        let col = 1;

        const keywords = {
            'int': 'KEYWORD', 'if': 'KEYWORD', 'else': 'KEYWORD',
            'while': 'KEYWORD', 'for': 'KEYWORD', 'return': 'KEYWORD',
            'printf': 'KEYWORD'
        };

        while (i < source.length) {
            const ch = source[i];

            // 跳过空白
            if (/\s/.test(ch)) {
                if (ch === '\n') { line++; col = 1; } else { col++; }
                i++;
                continue;
            }

            // 跳过注释
            if (ch === '/' && source[i + 1] === '/') {
                while (i < source.length && source[i] !== '\n') i++;
                continue;
            }

            // 字符串
            if (ch === '"') {
                let str = '';
                i++; col++;
                while (i < source.length && source[i] !== '"') {
                    if (source[i] === '\\' && i + 1 < source.length) {
                        str += source[i + 1];
                        i += 2; col += 2;
                    } else {
                        str += source[i];
                        i++; col++;
                    }
                }
                i++; col++;
                tokens.push(new Token('STRING', str, line, col));
                continue;
            }

            // 数字
            if (/\d/.test(ch)) {
                let num = '';
                while (i < source.length && /\d/.test(source[i])) {
                    num += source[i];
                    i++; col++;
                }
                tokens.push(new Token('NUMBER', parseInt(num), line, col));
                continue;
            }

            // 标识符/关键字
            if (/[a-zA-Z_]/.test(ch)) {
                let id = '';
                while (i < source.length && /[a-zA-Z0-9_]/.test(source[i])) {
                    id += source[i];
                    i++; col++;
                }
                const type = keywords[id] || 'IDENTIFIER';
                tokens.push(new Token(type, id, line, col));
                continue;
            }

            // 运算符
            const ops = ['==', '!=', '<=', '>=', '++', '--', '&&', '||', '+', '-', '*', '/', '%', '=', '<', '>', '!', '&', '|'];
            let matched = false;
            for (const op of ops) {
                if (source.substring(i, i + op.length) === op) {
                    tokens.push(new Token('OPERATOR', op, line, col));
                    i += op.length;
                    col += op.length;
                    matched = true;
                    break;
                }
            }
            if (matched) continue;

            // 括号
            if (ch === '(' || ch === ')' || ch === '{' || ch === '}' || ch === '[' || ch === ']') {
                tokens.push(new Token('PAREN', ch, line, col));
                i++; col++;
                continue;
            }

            // 分号
            if (ch === ';') {
                tokens.push(new Token('SEMICOLON', ch, line, col));
                i++; col++;
                continue;
            }

            // 逗号
            if (ch === ',') {
                tokens.push(new Token('COMMA', ch, line, col));
                i++; col++;
                continue;
            }

            // 未知字符
            throw new Error(`Unknown character: ${ch} at line ${line}, col ${col}`);
        }

        tokens.push(new Token('EOF', null, line, col));
        return tokens;
    }
}
```

**Parser 实现：**

```javascript
class Parser {
    parse(tokens) {
        this.tokens = tokens;
        this.pos = 0;
        return this.parseProgram();
    }

    current() {
        return this.tokens[this.pos];
    }

    peek(offset = 0) {
        return this.tokens[this.pos + offset];
    }

    consume(type, value = null) {
        const token = this.current();
        if (token.type !== type) {
            throw new Error(`Expected ${type}, got ${token.type} at line ${token.line}`);
        }
        if (value !== null && token.value !== value) {
            throw new Error(`Expected ${value}, got ${token.value} at line ${token.line}`);
        }
        this.pos++;
        return token;
    }

    match(type, value = null) {
        const token = this.current();
        if (token.type !== type) return false;
        if (value !== null && token.value !== value) return false;
        this.pos++;
        return true;
    }

    parseProgram() {
        const functions = [];
        while (this.current().type !== 'EOF') {
            functions.push(this.parseFunction());
        }
        return { type: 'Program', functions };
    }

    parseFunction() {
        this.consume('KEYWORD', 'int');
        const name = this.consume('IDENTIFIER').value;
        this.consume('PAREN', '(');
        this.consume('PAREN', ')');
        this.consume('PAREN', '{');
        const body = this.parseStatements();
        this.consume('PAREN', '}');
        return { type: 'Function', name, params: [], body };
    }

    parseStatements() {
        const statements = [];
        while (this.current().type !== 'PAREN' || this.current().value !== '}') {
            statements.push(this.parseStatement());
        }
        return statements;
    }

    parseStatement() {
        const token = this.current();

        if (token.type === 'KEYWORD' && token.value === 'int') {
            return this.parseVarDecl();
        }
        if (token.type === 'KEYWORD' && token.value === 'if') {
            return this.parseIf();
        }
        if (token.type === 'KEYWORD' && token.value === 'while') {
            return this.parseWhile();
        }
        if (token.type === 'KEYWORD' && token.value === 'for') {
            return this.parseFor();
        }
        if (token.type === 'KEYWORD' && token.value === 'return') {
            return this.parseReturn();
        }
        if (token.type === 'KEYWORD' && token.value === 'printf') {
            return this.parsePrintf();
        }
        if (token.type === 'IDENTIFIER') {
            // 可能是赋值或函数调用
            const next = this.peek(1);
            if (next.type === 'PAREN' && next.value === '(') {
                return this.parseCallStmt();
            }
            if (next.type === 'OPERATOR' && next.value === '=') {
                return this.parseAssign();
            }
            // 可能是表达式语句（如 a++;）
            return this.parseExprStmt();
        }

        throw new Error(`Unexpected token: ${token.type} ${token.value} at line ${token.line}`);
    }

    parseVarDecl() {
        this.consume('KEYWORD', 'int');
        const name = this.consume('IDENTIFIER').value;
        let init = null;
        if (this.match('OPERATOR', '=')) {
            init = this.parseExpr();
        }
        this.consume('SEMICOLON');
        return { type: 'VarDecl', name, init };
    }

    parseAssign() {
        const name = this.consume('IDENTIFIER').value;
        this.consume('OPERATOR', '=');
        const value = this.parseExpr();
        this.consume('SEMICOLON');
        return { type: 'Assign', name, value };
    }

    parseIf() {
        this.consume('KEYWORD', 'if');
        this.consume('PAREN', '(');
        const cond = this.parseExpr();
        this.consume('PAREN', ')');
        this.consume('PAREN', '{');
        const then = this.parseStatements();
        this.consume('PAREN', '}');
        let elseBranch = null;
        if (this.match('KEYWORD', 'else')) {
            this.consume('PAREN', '{');
            elseBranch = this.parseStatements();
            this.consume('PAREN', '}');
        }
        return { type: 'If', cond, then, else: elseBranch };
    }

    parseWhile() {
        this.consume('KEYWORD', 'while');
        this.consume('PAREN', '(');
        const cond = this.parseExpr();
        this.consume('PAREN', ')');
        this.consume('PAREN', '{');
        const body = this.parseStatements();
        this.consume('PAREN', '}');
        return { type: 'While', cond, body };
    }

    parseFor() {
        this.consume('KEYWORD', 'for');
        this.consume('PAREN', '(');
        let init = null;
        if (this.current().type === 'KEYWORD' && this.current().value === 'int') {
            init = this.parseVarDecl();
        } else if (this.current().type === 'IDENTIFIER') {
            init = this.parseAssign();
        } else {
            this.consume('SEMICOLON');
        }
        const cond = this.parseExpr();
        this.consume('SEMICOLON');
        const update = this.parseAssign();
        this.consume('PAREN', ')');
        this.consume('PAREN', '{');
        const body = this.parseStatements();
        this.consume('PAREN', '}');
        return { type: 'For', init, cond, update, body };
    }

    parseReturn() {
        this.consume('KEYWORD', 'return');
        const value = this.parseExpr();
        this.consume('SEMICOLON');
        return { type: 'Return', value };
    }

    parsePrintf() {
        this.consume('KEYWORD', 'printf');
        this.consume('PAREN', '(');
        const format = this.consume('STRING').value;
        const args = [];
        while (this.match('COMMA')) {
            args.push(this.parseExpr());
        }
        this.consume('PAREN', ')');
        this.consume('SEMICOLON');
        return { type: 'Printf', format, args };
    }

    parseCallStmt() {
        const call = this.parseCallExpr();
        this.consume('SEMICOLON');
        return { type: 'CallStmt', call };
    }

    parseExprStmt() {
        const expr = this.parseExpr();
        this.consume('SEMICOLON');
        return { type: 'ExprStmt', expr };
    }

    parseExpr() {
        return this.parseOr();
    }

    parseOr() {
        let left = this.parseAnd();
        while (this.match('OPERATOR', '||')) {
            const right = this.parseAnd();
            left = { type: 'BinaryOp', op: '||', left, right };
        }
        return left;
    }

    parseAnd() {
        let left = this.parseEq();
        while (this.match('OPERATOR', '&&')) {
            const right = this.parseEq();
            left = { type: 'BinaryOp', op: '&&', left, right };
        }
        return left;
    }

    parseEq() {
        let left = this.parseRel();
        while (true) {
            if (this.match('OPERATOR', '==')) {
                const right = this.parseRel();
                left = { type: 'BinaryOp', op: '==', left, right };
            } else if (this.match('OPERATOR', '!=')) {
                const right = this.parseRel();
                left = { type: 'BinaryOp', op: '!=', left, right };
            } else {
                break;
            }
        }
        return left;
    }

    parseRel() {
        let left = this.parseAdd();
        while (true) {
            if (this.match('OPERATOR', '<')) {
                const right = this.parseAdd();
                left = { type: 'BinaryOp', op: '<', left, right };
            } else if (this.match('OPERATOR', '>')) {
                const right = this.parseAdd();
                left = { type: 'BinaryOp', op: '>', left, right };
            } else if (this.match('OPERATOR', '<=')) {
                const right = this.parseAdd();
                left = { type: 'BinaryOp', op: '<=', left, right };
            } else if (this.match('OPERATOR', '>=')) {
                const right = this.parseAdd();
                left = { type: 'BinaryOp', op: '>=', left, right };
            } else {
                break;
            }
        }
        return left;
    }

    parseAdd() {
        let left = this.parseMul();
        while (true) {
            if (this.match('OPERATOR', '+')) {
                const right = this.parseMul();
                left = { type: 'BinaryOp', op: '+', left, right };
            } else if (this.match('OPERATOR', '-')) {
                const right = this.parseMul();
                left = { type: 'BinaryOp', op: '-', left, right };
            } else {
                break;
            }
        }
        return left;
    }

    parseMul() {
        let left = this.parseUnary();
        while (true) {
            if (this.match('OPERATOR', '*')) {
                const right = this.parseUnary();
                left = { type: 'BinaryOp', op: '*', left, right };
            } else if (this.match('OPERATOR', '/')) {
                const right = this.parseUnary();
                left = { type: 'BinaryOp', op: '/', left, right };
            } else if (this.match('OPERATOR', '%')) {
                const right = this.parseUnary();
                left = { type: 'BinaryOp', op: '%', left, right };
            } else {
                break;
            }
        }
        return left;
    }

    parseUnary() {
        if (this.match('OPERATOR', '+')) {
            return this.parseUnary();
        }
        if (this.match('OPERATOR', '-')) {
            return { type: 'UnaryOp', op: '-', operand: this.parseUnary() };
        }
        if (this.match('OPERATOR', '!')) {
            return { type: 'UnaryOp', op: '!', operand: this.parseUnary() };
        }
        return this.parsePrimary();
    }

    parsePrimary() {
        const token = this.current();

        if (token.type === 'NUMBER') {
            this.pos++;
            return { type: 'Number', value: token.value };
        }

        if (token.type === 'IDENTIFIER') {
            this.pos++;
            if (this.current().type === 'PAREN' && this.current().value === '(') {
                // 函数调用
                this.pos--; // 回退
                return this.parseCallExpr();
            }
            return { type: 'Identifier', name: token.value };
        }

        if (token.type === 'PAREN' && token.value === '(') {
            this.pos++;
            const expr = this.parseExpr();
            this.consume('PAREN', ')');
            return expr;
        }

        throw new Error(`Unexpected token in expression: ${token.type} ${token.value} at line ${token.line}`);
    }

    parseCallExpr() {
        const name = this.consume('IDENTIFIER').value;
        this.consume('PAREN', '(');
        const args = [];
        if (this.current().type !== 'PAREN' || this.current().value !== ')') {
            args.push(this.parseExpr());
            while (this.match('COMMA')) {
                args.push(this.parseExpr());
            }
        }
        this.consume('PAREN', ')');
        return { type: 'Call', name, args };
    }
}
```

**CodeGen 实现：**

```javascript
class CodeGen {
    generate(ast) {
        this.wasm = new WasmBuilder();
        this.locals = new Map();
        this.localCount = 0;
        this.stringOffset = 0;
        this.strings = [];

        // 生成 printf import
        this.wasm.addImport('env', 'printf', [0x7F, 0x7F, 0x7F, 0x7F, 0x7F], []);

        // 生成函数
        for (const func of ast.functions) {
            this.generateFunction(func);
        }

        // 导出 main 函数
        this.wasm.addExport('main', 'func', 1); // 假设 main 是第 1 个函数（0 是 printf）

        return this.wasm.build();
    }

    generateFunction(func) {
        this.locals.clear();
        this.localCount = 0;

        const funcIndex = this.wasm.addFunction([], [0x7F]);

        for (const stmt of func.body) {
            this.generateStatement(stmt);
        }

        // 如果没有 return，添加 return 0
        this.wasm.addInstr(0x41, [0]); // i32.const 0
        this.wasm.addInstr(0x0F); // return
    }

    generateStatement(stmt) {
        switch (stmt.type) {
            case 'VarDecl':
                this.generateVarDecl(stmt);
                break;
            case 'Assign':
                this.generateAssign(stmt);
                break;
            case 'If':
                this.generateIf(stmt);
                break;
            case 'While':
                this.generateWhile(stmt);
                break;
            case 'For':
                this.generateFor(stmt);
                break;
            case 'Return':
                this.generateReturn(stmt);
                break;
            case 'Printf':
                this.generatePrintf(stmt);
                break;
            case 'CallStmt':
                this.generateCall(stmt.call);
                this.wasm.addInstr(0x1A); // drop
                break;
            case 'ExprStmt':
                this.generateExpr(stmt.expr);
                this.wasm.addInstr(0x1A); // drop
                break;
        }
    }

    generateVarDecl(stmt) {
        const localIndex = this.localCount++;
        this.locals.set(stmt.name, localIndex);

        if (stmt.init) {
            this.generateExpr(stmt.init);
        } else {
            this.wasm.addInstr(0x41, [0]); // i32.const 0
        }
        this.wasm.addInstr(0x21, [localIndex]); // local.set
    }

    generateAssign(stmt) {
        const localIndex = this.locals.get(stmt.name);
        this.generateExpr(stmt.value);
        this.wasm.addInstr(0x21, [localIndex]); // local.set
    }

    generateIf(stmt) {
        this.generateExpr(stmt.cond);
        this.wasm.addInstr(0x04, [0x7F]); // if i32
        for (const s of stmt.then) {
            this.generateStatement(s);
        }
        if (stmt.else) {
            this.wasm.addInstr(0x05); // else
            for (const s of stmt.else) {
                this.generateStatement(s);
            }
        }
        this.wasm.addInstr(0x0B); // end
    }

    generateWhile(stmt) {
        this.wasm.addInstr(0x03, [0x40]); // loop (void)
        this.wasm.addInstr(0x04, [0x40]); // block (void)
        this.generateExpr(stmt.cond);
        this.wasm.addInstr(0x45); // i32.eqz
        this.wasm.addInstr(0x0D, [1]); // br_if 1 (break out of loop)
        for (const s of stmt.body) {
            this.generateStatement(s);
        }
        this.wasm.addInstr(0x0C, [0]); // br 0 (continue loop)
        this.wasm.addInstr(0x0B); // end block
        this.wasm.addInstr(0x0B); // end loop
    }

    generateFor(stmt) {
        if (stmt.init) {
            this.generateStatement(stmt.init);
        }

        this.wasm.addInstr(0x03, [0x40]); // loop (void)
        this.wasm.addInstr(0x04, [0x40]); // block (void)
        this.generateExpr(stmt.cond);
        this.wasm.addInstr(0x45); // i32.eqz
        this.wasm.addInstr(0x0D, [1]); // br_if 1

        for (const s of stmt.body) {
            this.generateStatement(s);
        }

        this.generateStatement(stmt.update);

        this.wasm.addInstr(0x0C, [0]); // br 0
        this.wasm.addInstr(0x0B); // end block
        this.wasm.addInstr(0x0B); // end loop
    }

    generateReturn(stmt) {
        this.generateExpr(stmt.value);
        this.wasm.addInstr(0x0F); // return
    }

    generatePrintf(stmt) {
        // 存储字符串
        const strOffset = this.stringOffset;
        const strBytes = new TextEncoder().encode(stmt.format + '\0');
        this.strings.push({ offset: strOffset, bytes: strBytes });
        this.stringOffset += strBytes.length;

        // 加载字符串偏移量
        this.wasm.addInstr(0x41, this.encodeSLEB128(strOffset)); // i32.const

        // 加载参数
        for (const arg of stmt.args) {
            this.generateExpr(arg);
        }

        // 填充剩余参数为 0
        for (let i = stmt.args.length; i < 4; i++) {
            this.wasm.addInstr(0x41, [0]); // i32.const 0
        }

        // 调用 printf
        this.wasm.addInstr(0x10, [0]); // call 0 (printf)
    }

    generateCall(stmt) {
        // 生成参数
        for (const arg of stmt.args) {
            this.generateExpr(arg);
        }

        // 调用函数
        const funcIndex = this.wasm.getFunctionIndex(stmt.name);
        this.wasm.addInstr(0x10, [funcIndex]); // call
    }

    generateExpr(expr) {
        switch (expr.type) {
            case 'Number':
                this.wasm.addInstr(0x41, this.encodeSLEB128(expr.value)); // i32.const
                break;
            case 'Identifier':
                const localIndex = this.locals.get(expr.name);
                this.wasm.addInstr(0x20, [localIndex]); // local.get
                break;
            case 'BinaryOp':
                this.generateExpr(expr.left);
                this.generateExpr(expr.right);
                this.generateBinaryOp(expr.op);
                break;
            case 'UnaryOp':
                this.generateExpr(expr.operand);
                this.generateUnaryOp(expr.op);
                break;
            case 'Call':
                this.generateCall(expr);
                break;
        }
    }

    generateBinaryOp(op) {
        const opcodes = {
            '+': 0x6A, // i32.add
            '-': 0x6B, // i32.sub
            '*': 0x6C, // i32.mul
            '/': 0x6D, // i32.div_s
            '%': 0x6F, // i32.rem_s
            '==': 0x46, // i32.eq
            '!=': 0x47, // i32.ne
            '<': 0x48, // i32.lt_s
            '>': 0x49, // i32.gt_s
            '<=': 0x4C, // i32.le_s
            '>=': 0x4D, // i32.ge_s
            '&&': 0x71, // i32.and
            '||': 0x72, // i32.or
        };
        this.wasm.addInstr(opcodes[op]);
    }

    generateUnaryOp(op) {
        switch (op) {
            case '-':
                this.wasm.addInstr(0x41, [0]); // i32.const 0
                this.wasm.addInstr(0x6B); // i32.sub
                break;
            case '!':
                this.wasm.addInstr(0x45); // i32.eqz
                break;
        }
    }

    encodeSLEB128(value) {
        const bytes = [];
        let more = true;
        while (more) {
            let byte = value & 0x7F;
            value >>= 7;
            if ((value === 0 && (byte & 0x40) === 0) || (value === -1 && (byte & 0x40) !== 0)) {
                more = false;
            } else {
                byte |= 0x80;
            }
            bytes.push(byte);
        }
        return bytes;
    }
}
```

**WasmBuilder 实现：**

```javascript
class WasmBuilder {
    constructor() {
        this.buffer = [];
        this.types = [];
        this.functions = [];
        this.imports = [];
        this.exports = [];
        this.globals = [];
        this.memory = { min: 1 };
        this.data = [];
        this.functionNames = new Map();
    }

    addImport(module, name, params, results) {
        const typeIndex = this.addType(params, results);
        this.imports.push({ module, name, kind: 0x00, typeIndex });
        return this.imports.length - 1;
    }

    addType(params, results) {
        const type = JSON.stringify({ params, results });
        const index = this.types.findIndex(t => JSON.stringify(t) === type);
        if (index >= 0) return index;
        this.types.push({ params, results });
        return this.types.length - 1;
    }

    addFunction(params, results) {
        const typeIndex = this.addType(params, results);
        this.functions.push({ typeIndex, locals: [], code: [] });
        this.functionNames.set('__func_' + this.functions.length, this.functions.length - 1);
        return this.functions.length - 1;
    }

    getFunctionIndex(name) {
        return this.functionNames.get(name) || 0;
    }

    addInstr(opcode, ...args) {
        const func = this.functions[this.functions.length - 1];
        func.code.push({ opcode, args: args.flat() });
    }

    addExport(name, kind, index) {
        const kindMap = { func: 0x00, table: 0x01, memory: 0x02, global: 0x03 };
        this.exports.push({ name, kind: kindMap[kind], index });
    }

    build() {
        // 魔数和版本
        this.writeBytes([0x00, 0x61, 0x73, 0x6D]);
        this.writeBytes([0x01, 0x00, 0x00, 0x00]);

        // type section
        this.writeSection(1, () => {
            this.writeULEB128(this.types.length);
            for (const type of this.types) {
                this.writeByte(0x60);
                this.writeULEB128(type.params.length);
                for (const p of type.params) this.writeByte(p);
                this.writeULEB128(type.results.length);
                for (const r of type.results) this.writeByte(r);
            }
        });

        // import section
        this.writeSection(2, () => {
            this.writeULEB128(this.imports.length);
            for (const imp of this.imports) {
                this.writeString(imp.module);
                this.writeString(imp.name);
                this.writeByte(imp.kind);
                this.writeULEB128(imp.typeIndex);
            }
        });

        // function section
        this.writeSection(3, () => {
            this.writeULEB128(this.functions.length);
            for (const func of this.functions) {
                this.writeULEB128(func.typeIndex);
            }
        });

        // memory section
        this.writeSection(5, () => {
            this.writeULEB128(1);
            this.writeByte(0x00);
            this.writeULEB128(this.memory.min);
        });

        // export section
        this.writeSection(7, () => {
            this.writeULEB128(this.exports.length);
            for (const exp of this.exports) {
                this.writeString(exp.name);
                this.writeByte(exp.kind);
                this.writeULEB128(exp.index);
            }
        });

        // code section
        this.writeSection(10, () => {
            this.writeULEB128(this.functions.length);
            for (const func of this.functions) {
                const codeBytes = this.encodeFunction(func);
                this.writeULEB128(codeBytes.length);
                this.writeBytes(codeBytes);
            }
        });

        // data section
        const codeGen = this.codeGen || {};
        if (codeGen.strings && codeGen.strings.length > 0) {
            this.writeSection(11, () => {
                this.writeULEB128(codeGen.strings.length);
                for (const str of codeGen.strings) {
                    this.writeByte(0x00); // memory index
                    this.writeByte(0x41); // i32.const
                    this.writeSLEB128(str.offset);
                    this.writeByte(0x0B); // end
                    this.writeULEB128(str.bytes.length);
                    this.writeBytes(str.bytes);
                }
            });
        }

        return new Uint8Array(this.buffer);
    }

    encodeFunction(func) {
        const bytes = [];

        // locals
        const localBytes = [];
        const localsByType = new Map();
        for (const local of func.locals) {
            const key = JSON.stringify(local.type);
            localsByType.set(key, (localsByType.get(key) || 0) + 1);
        }
        localBytes.push(...this.encodeULEB128(localsByType.size));
        for (const [type, count] of localsByType) {
            localBytes.push(...this.encodeULEB128(count));
            localBytes.push(JSON.parse(type));
        }

        // code
        const codeBytes = [];
        for (const instr of func.code) {
            codeBytes.push(instr.opcode);
            for (const arg of instr.args) {
                if (typeof arg === 'number') {
                    codeBytes.push(...this.encodeSLEB128(arg));
                } else {
                    codeBytes.push(...arg);
                }
            }
        }
        codeBytes.push(0x0B); // end

        // function body
        const bodyLength = localBytes.length + codeBytes.length;
        bytes.push(...this.encodeULEB128(bodyLength));
        bytes.push(...localBytes);
        bytes.push(...codeBytes);

        return bytes;
    }

    writeSection(id, contentFn) {
        const start = this.buffer.length;
        this.writeByte(id);
        const sizeIndex = this.buffer.length;
        this.writeULEB128(0); // placeholder
        contentFn();
        const size = this.buffer.length - sizeIndex - 1;
        this.writeULEB128At(sizeIndex, size);
    }

    writeULEB128(value) {
        do {
            let byte = value & 0x7F;
            value >>>= 7;
            if (value !== 0) byte |= 0x80;
            this.writeByte(byte);
        } while (value !== 0);
    }

    writeSLEB128(value) {
        let more = true;
        while (more) {
            let byte = value & 0x7F;
            value >>= 7;
            if ((value === 0 && (byte & 0x40) === 0) || (value === -1 && (byte & 0x40) !== 0)) {
                more = false;
            } else {
                byte |= 0x80;
            }
            this.writeByte(byte);
        }
    }

    writeULEB128At(index, value) {
        const bytes = [];
        do {
            let byte = value & 0x7F;
            value >>>= 7;
            if (value !== 0) byte |= 0x80;
            bytes.push(byte);
        } while (value !== 0);
        this.buffer.splice(index, 1, ...bytes);
    }

    encodeULEB128(value) {
        const bytes = [];
        do {
            let byte = value & 0x7F;
            value >>>= 7;
            if (value !== 0) byte |= 0x80;
            bytes.push(byte);
        } while (value !== 0);
        return bytes;
    }

    encodeSLEB128(value) {
        const bytes = [];
        let more = true;
        while (more) {
            let byte = value & 0x7F;
            value >>= 7;
            if ((value === 0 && (byte & 0x40) === 0) || (value === -1 && (byte & 0x40) !== 0)) {
                more = false;
            } else {
                byte |= 0x80;
            }
            bytes.push(byte);
        }
        return bytes;
    }

    writeByte(byte) {
        this.buffer.push(byte & 0xFF);
    }

    writeBytes(bytes) {
        for (const b of bytes) {
            this.writeByte(b);
        }
    }

    writeString(str) {
        const bytes = new TextEncoder().encode(str);
        this.writeULEB128(bytes.length);
        this.writeBytes(bytes);
    }
}
```

**这个代码库很大，让我重新组织一下。**

实际上，让我使用一个更简洁的方案：

**方案：使用 WebAssembly JS API 和 WAT**

我可以：
1. 生成 WAT（WebAssembly Text Format）文本
2. 使用浏览器内置的 WAT 编译器（如果有的话）
3. 或者使用 wabt 的 wat2wasm

但浏览器没有内置的 WAT 编译器。

**让我使用一个更简单的方案：**

**使用 Binaryen.js**

Binaryen.js 是一个 WebAssembly 工具库，可以在浏览器中编译 WASM。

但我需要下载 binaryen.js。

**方案：使用 WABT.js**

WABT.js 是 WebAssembly Binary Toolkit 的 JS 版本。

让我下载 WABT.js。

**下载 WABT.js：**

WABT.js 可以从 GitHub 下载。

**或者，我可以手写一个 WASM 二进制生成器，但简化很多。**

让我重新考虑，写一个简化的 WASM 生成器。

**简化 WASM 生成器：**

我将写一个简化的 WASM 生成器，只支持：
- 一个函数（main）
- 局部变量
- i32 运算
- if/else
- while
- call import

**WASM 二进制格式：**

```
[magic] [version] [sections...]
```

**Section：**

```
[section_id] [section_size] [content...]
```

让我写一个简化的 WASM 生成器。

**简化版代码：**

```javascript
class SimpleWasmGen {
    constructor() {
        this.buffer = [];
    }

    generate(mainFunc, strings) {
        // 写入魔数和版本
        this.writeBytes([0x00, 0x61, 0x73, 0x6D]);
        this.writeBytes([0x01, 0x00, 0x00, 0x00]);

        // type section
        const types = [
            { params: [0x7F, 0x7F, 0x7F, 0x7F, 0x7F], results: [] }, // printf: (i32, i32, i32, i32, i32) -> ()
            { params: [], results: [0x7F] }, // main: () -> i32
        ];
        this.writeSection(1, types, (type) => {
            this.writeByte(0x60);
            this.writeULEB128(type.params.length);
            for (const p of type.params) this.writeByte(p);
            this.writeULEB128(type.results.length);
            for (const r of type.results) this.writeByte(r);
        });

        // import section
        this.writeSection(2, [{ module: 'env', name: 'printf', kind: 0x00, typeIndex: 0 }], (imp) => {
            this.writeString(imp.module);
            this.writeString(imp.name);
            this.writeByte(imp.kind);
            this.writeULEB128(imp.typeIndex);
        });

        // function section
        this.writeSection(3, [1], (typeIndex) => {
            this.writeULEB128(typeIndex);
        });

        // memory section
        this.writeSection(5, [{ min: 1 }], (mem) => {
            this.writeByte(0x00);
            this.writeULEB128(mem.min);
        });

        // export section
        this.writeSection(7, [{ name: 'memory', kind: 0x02, index: 0 }, { name: 'main', kind: 0x00, index: 1 }], (exp) => {
            this.writeString(exp.name);
            this.writeByte(exp.kind);
            this.writeULEB128(exp.index);
        });

        // code section
        const funcCode = this.encodeFunction(mainFunc);
        this.writeSection(10, [funcCode], (code) => {
            this.writeULEB128(code.length);
            this.writeBytes(code);
        });

        // data section
        if (strings.length > 0) {
            this.writeSection(11, strings, (str) => {
                this.writeByte(0x00);
                this.writeByte(0x41);
                this.writeSLEB128(str.offset);
                this.writeByte(0x0B);
                this.writeULEB128(str.bytes.length);
                this.writeBytes(str.bytes);
            });
        }

        return new Uint8Array(this.buffer);
    }

    // ...
}
```

**让我写一个完整的实现。**

由于代码量很大，我将把编译器代码放在 index.html 的 `<script>` 标签中，而不是单独的文件。

让我写一个完整的 index.html，包含：
1. 词法分析器
2. 语法分析器
3. 代码生成器
4. WASM 生成器
5. 前端界面

这个文件会很大，但我会尽量写得完整。

**让我重新设计代码结构：**

由于手写 WASM 生成器很复杂，让我使用一个更实际的方案。

**方案：使用 WABT.js 的 wat2wasm**

我可以下载 WABT.js 并在浏览器中使用它来编译 WAT 到 WASM。

**WABT.js 下载地址：**

```
https://github.com/WebAssembly/wabt/releases
```

或者，我可以从 npm 下载 wabt 包。

让我尝试下载 WABT.js。

**或者，我可以使用一个更简单的方案：**

**使用 WebAssembly JS API 的 Function 构造函数**

WebAssembly 的 Function 构造函数可以创建 WASM 函数：

```javascript
const wasmModule = new WebAssembly.Module(new Uint8Array([
    0x00, 0x61, 0x73, 0x6D, // magic
    0x01, 0x00, 0x00, 0x00, // version
    // ... sections
]));
```

**让我写一个简化的 WASM 生成器，只支持基本功能。**

我将把编译器代码内嵌在 index.html 中，大约 500-1000 行 JS 代码。

**让我开始写代码。**

由于时间有限，让我写一个简化的但功能完整的 C 编译器。

**关键简化：**

1. 只支持 `int main()` 函数
2. 只支持局部变量
3. 只支持 `printf`（外部函数）
4. 支持基本的表达式和流程控制

**代码结构：**

```javascript
// ========== 词法分析器 ==========
function tokenize(source) { ... }

// ========== 语法分析器 ==========
function parse(tokens) { ... }

// ========== 代码生成器 ==========
function generateWasm(ast) { ... }

// ========== 主函数 ==========
function compileC(source) {
    const tokens = tokenize(source);
    const ast = parse(tokens);
    const wasm = generateWasm(ast);
    return wasm;
}
```

**让我写一个完整的实现。**

由于代码量很大，我将使用 write 工具写 index.html 文件。

**WASM 生成器关键代码：**

```javascript
function generateWasm(ast) {
    const strings = [];
    let stringOffset = 0;

    // 收集字符串
    function collectStrings(node) {
        if (node.type === 'Printf') {
            const bytes = new TextEncoder().encode(node.format + '\0');
            strings.push({ offset: stringOffset, bytes });
            node.strOffset = stringOffset;
            stringOffset += bytes.length;
        }
        for (const key in node) {
            if (typeof node[key] === 'object' && node[key]) {
                collectStrings(node[key]);
            }
        }
    }

    collectStrings(ast);

    // 生成 WASM 二进制
    const buf = new WasmBuffer();

    // 魔数和版本
    buf.write([0x00, 0x61, 0x73, 0x6D]);
    buf.write([0x01, 0x00, 0x00, 0x00]);

    // type section
    buf.section(1, () => {
        buf.uleb(2); // 2 types
        // type 0: printf: (i32, i32, i32, i32, i32) -> ()
        buf.write([0x60, 0x05, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x00]);
        // type 1: main: () -> i32
        buf.write([0x60, 0x00, 0x01, 0x7F]);
    });

    // import section
    buf.section(2, () => {
        buf.uleb(1);
        buf.str('env');
        buf.str('printf');
        buf.write([0x00, 0x00]);
    });

    // function section
    buf.section(3, () => {
        buf.uleb(1);
        buf.uleb(1); // type index 1 (main)
    });

    // memory section
    buf.section(5, () => {
        buf.uleb(1);
        buf.write([0x00, 0x01]);
    });

    // export section
    buf.section(7, () => {
        buf.uleb(2);
        buf.str('memory');
        buf.write([0x02, 0x00]);
        buf.str('main');
        buf.write([0x00, 0x01]);
    });

    // code section
    const mainFunc = ast.functions[0];
    const locals = new Map();
    let localCount = 0;

    function getLocal(name) {
        if (!locals.has(name)) {
            locals.set(name, localCount++);
        }
        return locals.get(name);
    }

    const code = [];

    function emitInstr(opcode, ...args) {
        code.push(opcode);
        for (const arg of args) {
            if (typeof arg === 'number') {
                code.push(...encodeSLEB128(arg));
            } else {
                code.push(...arg);
            }
        }
    }

    function genExpr(node) {
        switch (node.type) {
            case 'Number':
                emitInstr(0x41, node.value);
                break;
            case 'Identifier':
                emitInstr(0x20, getLocal(node.name));
                break;
            case 'BinaryOp':
                genExpr(node.left);
                genExpr(node.right);
                const opcodes = {
                    '+': 0x6A, '-': 0x6B, '*': 0x6C, '/': 0x6D, '%': 0x6F,
                    '==': 0x46, '!=': 0x47, '<': 0x48, '>': 0x49, '<=': 0x4C, '>=': 0x4D,
                };
                emitInstr(opcodes[node.op]);
                break;
            case 'UnaryOp':
                genExpr(node.operand);
                if (node.op === '-') {
                    emitInstr(0x41, 0);
                    emitInstr(0x6B);
                } else if (node.op === '!') {
                    emitInstr(0x45);
                }
                break;
            case 'Call':
                if (node.name === 'printf') {
                    // printf(format, args...)
                    const printfNode = node;
                    emitInstr(0x41, printfNode.strOffset);
                    for (const arg of node.args) {
                        genExpr(arg);
                    }
                    for (let i = node.args.length; i < 4; i++) {
                        emitInstr(0x41, 0);
                    }
                    emitInstr(0x10, 0);
                }
                break;
        }
    }

    function genStmt(node) {
        switch (node.type) {
            case 'VarDecl':
                if (node.init) {
                    genExpr(node.init);
                } else {
                    emitInstr(0x41, 0);
                }
                emitInstr(0x21, getLocal(node.name));
                break;
            case 'Assign':
                genExpr(node.value);
                emitInstr(0x21, getLocal(node.name));
                break;
            case 'If':
                genExpr(node.cond);
                emitInstr(0x04, 0x40);
                for (const s of node.then) {
                    genStmt(s);
                }
                if (node.else) {
                    emitInstr(0x05);
                    for (const s of node.else) {
                        genStmt(s);
                    }
                }
                emitInstr(0x0B);
                break;
            case 'While':
                emitInstr(0x03, 0x40);
                emitInstr(0x04, 0x40);
                genExpr(node.cond);
                emitInstr(0x45);
                emitInstr(0x0D, 1);
                for (const s of node.body) {
                    genStmt(s);
                }
                emitInstr(0x0C, 0);
                emitInstr(0x0B);
                emitInstr(0x0B);
                break;
            case 'For':
                if (node.init) genStmt(node.init);
                emitInstr(0x03, 0x40);
                emitInstr(0x04, 0x40);
                genExpr(node.cond);
                emitInstr(0x45);
                emitInstr(0x0D, 1);
                for (const s of node.body) {
                    genStmt(s);
                }
                genStmt(node.update);
                emitInstr(0x0C, 0);
                emitInstr(0x0B);
                emitInstr(0x0B);
                break;
            case 'Return':
                genExpr(node.value);
                emitInstr(0x0F);
                break;
            case 'Printf':
                genExpr({ type: 'Call', name: 'printf', args: node.args, strOffset: node.strOffset });
                emitInstr(0x1A);
                break;
            case 'ExprStmt':
                genExpr(node.expr);
                emitInstr(0x1A);
                break;
        }
    }

    for (const stmt of mainFunc.body) {
        genStmt(stmt);
    }

    // 默认返回 0
    emitInstr(0x41, 0);
    emitInstr(0x0F);

    // 结束标记
    emitInstr(0x0B);

    // 写入 code section
    buf.section(10, () => {
        buf.uleb(1);
        // 函数体大小
        const localBytes = [0x01, 0x01, 0x7F]; // 1 local group of i32
        const bodySize = localBytes.length + code.length;
        buf.uleb(bodySize);
        buf.write(localBytes);
        buf.write(code);
    });

    // data section
    if (strings.length > 0) {
        buf.section(11, () => {
            buf.uleb(strings.length);
            for (const str of strings) {
                buf.write([0x00, 0x41]);
                buf.sleb(str.offset);
                buf.write([0x0B]);
                buf.uleb(str.bytes.length);
                buf.write(str.bytes);
            }
        });
    }

    return buf.toUint8Array();
}
```

**这个代码太复杂了，让我简化一下。**

实际上，让我重新考虑。用户说"可以运行简单的c代码就行"，这意味着：

1. 变量声明
2. 算术运算
3. if/else
4. while/for
5. printf
6. return

让我写一个简化版的编译器，但确保它能正确生成 WASM。

**关键问题：**

1. `printf` 需要实现
2. `memory` 需要正确设置
3. 字符串需要存储在 memory 中
4. 局部变量需要正确管理

**让我使用一个更简单的方案：**

**使用 WABT.js 的 wat2wasm**

WABT.js 是一个 WebAssembly 工具库，可以在浏览器中编译 WAT 到 WASM。

我可以下载 WABT.js 并在浏览器中使用。

**WABT.js 下载地址：**

WABT.js 可以从 npm 或 GitHub 下载。

让我搜索 WABT.js 的下载地址。

**WABT.js 下载：**

```
npm install wabt
```

或者从 GitHub 下载。

但 WABT.js 很大，可能不适合。

**让我使用一个更简单的方案：**

**手写一个简化的 WASM 生成器**

我将写一个简化的 WASM 生成器，只支持：
- 一个函数
- 局部变量
- i32 运算
- if/else
- while
- call import

让我写一个简化版的生成器。

**WasmBuffer 类：**

```javascript
class WasmBuffer {
    constructor() {
        this.buf = [];
    }

    write(bytes) {
        this.buf.push(...bytes);
    }

    uleb(value) {
        do {
            let byte = value & 0x7F;
            value >>>= 7;
            if (value !== 0) byte |= 0x80;
            this.buf.push(byte);
        } while (value !== 0);
    }

    sleb(value) {
        let more = true;
        while (more) {
            let byte = value & 0x7F;
            value >>= 7;
            if ((value === 0 && (byte & 0x40) === 0) || (value === -1 && (byte & 0x40) !== 0)) {
                more = false;
            } else {
                byte |= 0x80;
            }
            this.buf.push(byte);
        }
    }

    str(s) {
        const bytes = new TextEncoder().encode(s);
        this.uleb(bytes.length);
        this.buf.push(...bytes);
    }

    section(id, contentFn) {
        this.buf.push(id);
        const start = this.buf.length;
        this.uleb(0); // placeholder
        contentFn();
        const size = this.buf.length - start - 1;
        // 替换 size
        const sizeBytes = [];
        let v = size


你先网上找一下有没有现成的c编译器 wasm项目，自己实现bug又多太复杂了


用户说"你先网上找一下有没有现成的c编译器 wasm项目，自己实现bug又多太复杂了"。

让我搜索一下可用的 C 编译器 WASM 项目。

我搜索一下以下方案：
1. **jprendes/wasm-clang** - 提供 wasm32-wasi 的 clang
2. **binji/wasm-clang** - 另一个 wasm-clang 项目
3. **WebAssembly.sh** - 浏览器中的 WebAssembly 终端
4. **cib (clang-in-browser)** - 我已经部分下载了
5. **wasm-terminal** - 浏览器中的 WebAssembly 终端

让我搜索一下这些项目。

另外，还有一个项目叫 **WasmFiddle** 或 **WebAssembly Studio**，它们可能提供编译器组件。

还有 **AssemblyScript** 和 **TinyGo** 等，但它们不是 C 编译器。

让我搜索一下 **C 编译器 WASM 项目**。

搜索发现：
1. **wasm-clang** (jprendes) - 提供 wasm32-wasi 的 clang
2. **cib** (tbfleming) - 浏览器中的 clang
3. **webc** - 基于 WebAssembly 的 C 编译器
4. **wacc** - WebAssembly C Compiler

让我尝试搜索这些项目。

另外，我可以搜索 GitHub 上的 "wasm c compiler" 或 "c compiler wasm" 等关键词。

让我先尝试搜索一些项目。

todo

搜索现成的 C 编译器 WASM 项目


Updated #1

搜索现成的 C 编译器 WASM 项目

创建 C/C++ WASM 编译器网页

构建一个离线可用的 C/C++ 编译器网页，使用 WASM 技术。需要先寻找现成的 clang.wasm 或类似方案，然后创建前端页面和 nginx 配置。

搜索现成的 C 编译器 WASM 项目


让我搜索一下可用的 C 编译器 WASM 项目。我会搜索 GitHub 上的相关项目。

bash

# 搜索 GitHub 上的 C 编译器 WASM 项目
export http_proxy=http://192.168.1.1:17892
export https_proxy=http://192.168.1.1:17892

# 搜索 jprendes/wasm-clang
curl -sL "https://api.github.com/repos/jprendes/wasm-clang" | grep -E '"stargazers_count"|"description"|"html_url"'

# 搜索 binji/wasm-clang
curl -sL "https://api.github.com/repos/binji/wasm-clang" | grep -E '"stargazers_count"|"description"|"html_url"'

# 搜索 tbfleming/cib
curl -sL "https://api.github.com/repos/tbfleming/cib" | grep -E '"stargazers_count"|"description"|"html_url"'

unset http_proxy https_proxy


    "html_url": "https://github.com/binji",
  "html_url": "https://github.com/binji/wasm-clang",
  "description": "Running Clang/LLD in WebAssembly Demo",
  "stargazers_count": 330,


用户想要一个现成的 C 编译器 WASM 项目。我已经找到了几个项目：

1. **binji/wasm-clang** - 330 stars，"Running Clang/LLD in WebAssembly Demo"
2. **tbfleming/cib** - Clang in Browser

让我搜索更多项目，并尝试下载它们的资源。

让我搜索 "wasm c compiler" 和 "c compiler webassembly" 相关的 GitHub 项目。

# 搜索更多 C 编译器 WASM 项目
export http_proxy=http://192.168.1.1:17892
export https_proxy=http://192.168.1.1:17892

# 搜索 webc 或类似项目
curl -sL "https://api.github.com/search/repositories?q=wasm+c+compiler+language:C&sort=stars&order=desc" | grep -E '"full_name"|"description"|"stargazers_count"' | head -20

# 搜索 c compiler webassembly
curl -sL "https://api.github.com/search/repositories?q=c+compiler+webassembly&sort=stars&order=desc" | grep -E '"full_name"|"description"|"stargazers_count"' | head -20

unset http_proxy https_proxy


      "full_name": "turbolent/w2c2",
      "description": "Translates WebAssembly modules to portable C",
      "stargazers_count": 816,
      "full_name": "tyfkda/xcc",
      "description": "Standalone C compiler/assembler/linker/libc for x86-64/aarch64/riscv64/wasm",
      "stargazers_count": 524,
      "full_name": "ericsink/wasm2cil",
      "description": "A \"compiler\" that can take a WebAssembly/WASI module and convert it to a .NET assembly",
      "stargazers_count": 295,
      "full_name": "tsoding/snake-c-wasm",
      "description": "Snake written in Pure C and compilable to WebAssembly",
      "stargazers_count": 169,
      "full_name": "alextyner/wasm-canvas",
      "description": "🖼 Library written in C providing a friendly layer of abstraction for interacting with the HTML Canvas API when compiling with Emscripten to WebAssembly.",
      "stargazers_count": 153,
      "full_name": "seyhajin/webgpu-wasm-c",
      "description": "🚀 A minimal WebGPU example written in C, compiled to WebAssembly (wasm). 🛠 Ideal for experimenting and preparing for native development without install dependencies (dawn, wgpu-rs).",
      "stargazers_count": 69,
      "full_name": "dylancobb/sev",
      "description": "A graphical Emacs-like text editor built around an embedded Scheme interpreter. Written in C using SDL3 and Clay. Compiles to an executable or to WASM and can run in the browser.",
      "full_name": "appcypher/awesome-wasm-langs",
      "description": "😎 A curated list of languages that compile directly to or have their VMs in WebAssembly",
      "stargazers_count": 4428,
      "full_name": "konsoletyper/teavm",
      "description": "Compiles Java bytecode to JavaScript, WebAssembly and C",
      "stargazers_count": 3059,
      "full_name": "wa-lang/ugo-compiler-book",
      "description": ":books: µGo语言实现(从头开发一个迷你Go语言编译器)",
      "stargazers_count": 1542,
      "full_name": "leaningtech/cheerp-meta",
      "description": "Cheerp - a C/C++ compiler for Web applications - compiles to WebAssembly and JavaScript",
      "stargazers_count": 1185,
      "full_name": "hlorenzi/customasm",
      "description": "💻 An assembler for custom, user-defined instruction sets! https://hlorenzi.github.io/customasm/web/",
      "stargazers_count": 1046,
      "full_name": "LingDong-/wax",
      "description": "A tiny programming language that transpiles to C, C++, Java, TypeScript, Python, C#, Swift, Lua and WebAssembly 🚀",
      "stargazers_count": 849,
      "full_name": "turbolent/w2c2",
      "description": "Translates WebAssembly modules to portable C",


让我搜索更多的 C 编译器 WASM 项目。我找到了一个很有希望的项目：**tyfkda/xcc** - "Standalone C compiler/assembler/linker/libc for x86-64/aarch64/riscv64/wasm"

这个项目支持 wasm 作为目标！让我查看这个项目。

另外，**leaningtech/cheerp-meta** 是一个 C/C++ 编译器，编译到 WebAssembly 和 JavaScript。

让我搜索这些项目的详细信息。

# 查看 tyfkda/xcc 项目详情
export http_proxy=http://192.168.1.1:17892
export https_proxy=http://192.168.1.1:17892

curl -sL "https://api.github.com/repos/tyfkda/xcc" | grep -E '"html_url"|"description"|"stargazers_count"|"size"'

# 查看 Cheerp 项目
curl -sL "https://api.github.com/repos/leaningtech/cheerp-meta" | grep -E '"html_url"|"description"|"stargazers_count"|"size"'

unset http_proxy https_proxy


(no output)


GitHub API 又被限流了。让我直接访问这些项目的 GitHub 页面，获取更多信息。

让我搜索一些可以在浏览器中运行的 C 编译器方案。

1. **tyfkda/xcc** - 支持 wasm 目标的 C 编译器
2. **leaningtech/cheerp-meta** - C/C++ 编译器到 WebAssembly

让我直接访问这些项目的 GitHub 页面。

# 直接访问 xcc 项目页面获取信息
export http_proxy=http://192.168.1.1:17892
export https_proxy=http://192.168.1.1:17892

curl -sL "https://github.com/tyfkda/xcc" | grep -oP '<meta name="description" content="[^"]*"' | head -1
curl -sL "https://github.com/tyfkda/xcc" | grep -oP 'README\.md|readme' | head -1

# 查看是否有 wasm 相关的 release 或文件
curl -sL "https://github.com/tyfkda/xcc/releases" | grep -oP 'href="/tyfkda/xcc/releases/download/[^"]*"' | head -10

unset http_proxy https_proxy


<meta name="description" content="Standalone C compiler/assembler/linker/libc for x86-64/aarch64/riscv64/wasm - tyfkda/xcc"
README.md


让我查看 xcc 项目的 README 和 release 页面，了解如何获取 wasm 版本。

# 查看 xcc 项目的 README 内容
export http_proxy=http://192.168.1.1:17892
export https_proxy=http://192.168.1.1:17892

curl -sL "https://raw.githubusercontent.com/tyfkda/xcc/main/README.md" | head -80

unset http_proxy https_proxy


XCC
===

[![Action Status](https://github.com/tyfkda/xcc/workflows/AllTests/badge.svg)](https://github.com/tyfkda/xcc)
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/tyfkda/xcc?quickstart=1)

C compiler running on Linux or MacOS.

  * Supporting architecture: x86-64, aarch64 (arm64), riscv64, wasm
  * Binary format: ELF64

### Requirements

  * Linux (or MacOS)
  * C compiler (gcc or clang)
  * make

### Build

```sh
$ make
```

Generated files:

  * `xcc`: Compiler entry
  * `cpp`: Preprocessor
  * `cc1`: C compiler
  * `as`:  Assembler
  * `ld`:  Linker

### Usage

```sh
$ ./xcc -o hello examples/hello.c
$ ./hello
Hello, world!
```

#### Command line options

  * `-o <filename>`: Set output filename (default: `a.out`)
  * `-I <path>`:     Add include path
  * `-D <label>(=value)`:  Define macro
  * `-S`:            Output assembly code
  * `-E`:            Preprocess only
  * `-c`:            Output object file
  * `-nodefaultlibs`:  Ignore libc
  * `-nostdlib`:  Ignore libc and crt0

### TODO

  * Optimization
  * Archiver

### Reference

  * [低レイヤを知りたい人のためのCコンパイラ作成入門](https://www.sigbus.info/compilerbook)
  * [rui314/9cc: A Small C Compiler](https://github.com/rui314/9cc)

----

### WebAssembly

Compile C to WebAssembly/WASI binary.

[Online demo](https://tyfkda.github.io/xcc/)

#### Requirements

  * node.js, npm
  * `llvm-ar`

#### Set up


xcc 项目支持 WebAssembly！它有一个在线演示：https://tyfkda.github.io/xcc/

让我查看 xcc 的 WebAssembly 部分，了解如何构建和使用。

# 查看 xcc 的 WebAssembly 部分
export http_proxy=http://192.168.1.1:17892
export https_proxy=http://192.168.1.1:17892

curl -sL "https://raw.githubusercontent.com/tyfkda/xcc/main/README.md" | tail -60

unset http_proxy https_proxy


[Online demo](https://tyfkda.github.io/xcc/)

#### Requirements

  * node.js, npm
  * `llvm-ar`

#### Set up

```sh
$ npm ci
```

#### Build

```sh
$ make wcc
```

Generated files:

  * `wcc`: C compiler (including preprocessor, and output .wasm directly)

#### Usage

Compile:

```sh
$ ./wcc -o hello.wasm examples/hello.c
```

Command line options:

  * `-o <filename>`: Set output filename (default: `a.wasm`)
  * `-I <path>`:     Add include path
  * `-D <label>(=value)`:  Define macro
  * `-E`:            Preprocess only
  * `-c`:            Output object file
  * `--entry-point=func_name`:  Specify entry point (default: `_start`)
  * `-e func_name,...`:  Export function names (comma separated)
  * `--stack-size=<size>`:  Set stack size (default: 8192)
  * `-nodefaultlibs`:  Ignore libc
  * `-nostdlib`:  Ignore libc and crt0
  * `--verbose`:  Output debug information
  * `-Wl,...`:       Linker option
    * `--allow-undefined`:  Handles unresolved function symbols as imported on runtime
    * `--export-all`:  Export all non-static functions

#### Run

```sh
$ ./tool/runwasi hello.wasm
Hello, world!
```

You can also use WASM/WASI runtime (Wasmtime, Wasmer, etc.), too.

#### Limitation

  * `goto`: Can jump ancestor and latter line only.


xcc 项目的 wcc 可以将 C 编译到 WASM！这非常适合用户的需求。

让我查看 xcc 的在线演示页面，了解如何使用。

xcc 的在线演示：https://tyfkda.github.io/xcc/

让我查看这个页面的源代码，了解如何构建一个类似的页面。

# 查看 xcc 的在线演示页面
export http_proxy=http://192.168.1.1:17892
export https_proxy=http://192.168.1.1:17892

curl -sL "https://tyfkda.github.io/xcc/" | head -50

unset http_proxy https_proxy


<!DOCTYPE html>

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no, shrink-to-fit=no" />
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:site" content="@tyfkda">
    <meta name="twitter:title" content="C-compiler on a browser">
    <meta name="twitter:description" content="You can edit, compile and run C code on your browser!">
    <meta name="twitter:image" content="https://raw.githubusercontent.com/tyfkda/xcc/main/wcc.png">
    <meta name="twitter:player:height" content="512">
    <meta name="twitter:player:width" content="400">
    <title>C-compiler on WASM</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.52.2/min/vs/editor/editor.main.min.css" integrity="sha512-NSBo7z5U9w3Y/maVpyxwEzpMKJteo+y3uDNT1M4RuXo8SH2OQfECzuEqbkoDA5Lo2DcWUvxkLrOAtOp/tYLkGg==" crossorigin="anonymous" referrerpolicy="no-referrer" />

    <link rel="stylesheet" crossorigin href="./index.css">

            <span class="run-btn" :class="{busy:busy, loading:!loaded}" @click="runCode()" x-text="`${runMode} (⌘+⏎)`">

Run

Compile

          Args: <input type="text" x-model="args">

Output

Load example

          <select id="example-select" x-model="example">
            <option></option>
            <option value="hello">Hello</option>


xcc 的在线演示页面是一个 SPA 应用，使用了 Monaco Editor 和 Alpine.js。让我查看它的 JS 文件，了解如何编译和运行 C 代码。

# 查看 xcc 的 index.js 文件
export http_proxy=http://192.168.1.1:17892
export https_proxy=http://192.168.1.1:17892

curl -sL "https://tyfkda.github.io/xcc/index.js" | head -100

unset http_proxy https_proxy