use anyhow::{anyhow, Result};
use wasmtime::*;
use std::collections::HashMap;
// 1. 脚本解析器
#[derive(Debug, Clone)]
enum ASTNode {
Print(String),
}
fn parse_script(script: &str) -> Result<Vec<ASTNode>> {
let mut ast = Vec::new();
for line in script.lines() {
let line = line.trim();
if line.is_empty() {
continue;
}
if let Some(text) = line.strip_prefix("print ") {
let text = text.trim();
if let Some(text) = text.strip_prefix('"').and_then(|s| s.strip_suffix('"')) {
ast.push(ASTNode::Print(text.to_string()));
} else {
return Err(anyhow!("Invalid print statement: {}", line));
}
} else {
return Err(anyhow!("Unsupported command: {}", line));
}
}
Ok(ast)
}
// 2. WASM编译器(简化版)
fn compile_to_wasm(ast: &[ASTNode]) -> Result<Vec<u8>> {
use wasm_encoder::*;
let mut module = Module::new();
// 类型段 (print: (i32, i32) -> ())
let mut types = TypeSection::new();
types.function(vec![ValType::I32, ValType::I32], vec![]);
module.section(&types);
// 导入段 (从env导入print)
let mut imports = ImportSection::new();
imports.import("env", "print", TypeRef::Func(0));
module.section(&imports);
// 函数段 (主函数)
let mut functions = FunctionSection::new();
functions.function(0); // 使用类型0
module.section(&functions);
// 内存段 (1页)
let mut memories = MemorySection::new();
memories.memory(MemoryType {
minimum: 1,
maximum: None,
memory64: false,
shared: false,
});
module.section(&memories);
// 导出段 (导出main函数)
let mut exports = ExportSection::new();
exports.export("main", ExportKind::Func, 0); // 导出函数0
module.section(&exports);
// 代码段
let mut code = CodeSection::new();
// 主函数体
let mut func = Function::new(vec![]);
for node in ast {
match node {
ASTNode::Print(text) => {
// 在内存偏移0处写入字符串长度
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::I32Const(text.len() as i32));
func.instruction(&Instruction::I32Store(MemArg::new(2, 0)));
// 在内存偏移4处写入字符串内容
for (i, byte) in text.as_bytes().iter().enumerate() {
func.instruction(&Instruction::I32Const(4 + i as i32));
func.instruction(&Instruction::I32Const(*byte as i32));
func.instruction(&Instruction::I32Store(MemArg::new(0, 0)));
}
// 调用print函数 (ptr=0, len=text.len())
func.instruction(&Instruction::I32Const(0));
func.instruction(&Instruction::I32Const(text.len() as i32));
func.instruction(&Instruction::Call(0));
}
}
}
// 函数结束
func.instruction(&Instruction::End);
code.function(&func);
module.section(&code);
Ok(module.finish())
}
// 3. 引擎实现
struct GameEngine {
print_history: Vec<String>,
}
impl GameEngine {
fn new() -> Self {
GameEngine {
print_history: Vec::new(),
}
}
fn engine_print(&mut self, memory: &Memory, ptr: i32, len: i32) {
// 读取内存中的字符串
let mut buffer = vec![0u8; len as usize];
memory
.read(&mut (), ptr as u64 as usize, &mut buffer)
.expect("Failed to read memory");
let text = String::from_utf8_lossy(&buffer).into_owned();
// 记录打印历史
self.print_history.push(text.clone());
// 模拟执行打印
println!("[ENGINE] PRINT: {}", text);
}
}
// 4. 主执行流程
fn main() -> Result<()> {
// 1. 用户脚本
let script = r#"print "123""#;
println!("[PARSER] Script: {}", script);
// 2. 解析脚本为AST
let ast = parse_script(script)?;
println!("[PARSER] AST: {:?}", ast);
// 3. 编译为WASM
let wasm_bytes = compile_to_wasm(&ast)?;
println!("[COMPILER] Generated WASM module ({} bytes)", wasm_bytes.len());
// 4. 创建引擎状态
let engine_state = GameEngine::new();
// 5. 配置WASM引擎
let engine = Engine::default();
let mut store = Store::new(&engine, engine_state);
// 6. 创建链接器并定义print函数
let mut linker = Linker::new(&engine);
linker.func_wrap("env", "print", |mut caller: Caller<'_, GameEngine>, ptr: i32, len: i32| {
// 获取内存
let memory = caller.get_export("memory")
.expect("Memory export not found")
.into_memory()
.expect("Not a memory");
// 调用引擎的print实现
caller.data_mut().engine_print(&memory, ptr, len);
})?;
// 7. 加载WASM模块
let module = Module::new(&engine, &wasm_bytes)?;
// 8. 实例化并执行
let instance = linker.instantiate(&mut store, &module)?;
// 确保导出了内存
instance.get_memory(&mut store, "memory")
.expect("Memory not exported");
// 获取并执行main函数
let main = instance.get_typed_func::<(), ()>(&mut store, "main")?;
println!("[ENGINE] Executing WASM module...");
main.call(&mut store, ())?;
// 9. 验证执行结果
let state = store.data();
println!("\n[RESULT] Print history: {:?}", state.print_history);
assert_eq!(state.print_history, vec!["123"]);
println!("✅ Successfully executed script!");
Ok(())
}
// 测试
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parser() {
let script = r#"print "hello world""#;
let ast = parse_script(script).unwrap();
assert!(matches!(ast[0], ASTNode::Print(ref s) if s == "hello world"));
}
#[test]
fn test_wasm_generation() {
let ast = vec![ASTNode::Print("test".to_string())];
let wasm = compile_to_wasm(&ast).unwrap();
assert!(!wasm.is_empty());
assert!(wasm.starts_with(b"\0asm")); // WASM magic number
}
}