chore(fmt): add legacy stubs and strip trailing whitespace to unblock cargo fmt
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* WASM Runtime Imports - External function imports for WASM modules
|
||||
*
|
||||
*
|
||||
* Phase 8.2 PoC1: Implements env.print import for debugging
|
||||
* Future: Additional runtime functions (file I/O, network, etc.)
|
||||
*/
|
||||
@ -27,12 +27,12 @@ impl RuntimeImports {
|
||||
let mut runtime = Self {
|
||||
imports: Vec::new(),
|
||||
};
|
||||
|
||||
|
||||
// Add standard runtime imports
|
||||
runtime.add_standard_imports();
|
||||
runtime
|
||||
}
|
||||
|
||||
|
||||
/// Add standard runtime function imports
|
||||
fn add_standard_imports(&mut self) {
|
||||
// env.print for debugging output
|
||||
@ -42,7 +42,7 @@ impl RuntimeImports {
|
||||
params: vec!["i32".to_string()],
|
||||
result: None,
|
||||
});
|
||||
|
||||
|
||||
// env.print_str for string debugging (ptr, len)
|
||||
self.imports.push(ImportFunction {
|
||||
module: "env".to_string(),
|
||||
@ -50,9 +50,9 @@ impl RuntimeImports {
|
||||
params: vec!["i32".to_string(), "i32".to_string()],
|
||||
result: None,
|
||||
});
|
||||
|
||||
|
||||
// Phase 9.7: Box FFI/ABI imports per BID specifications
|
||||
|
||||
|
||||
// env.console_log for console.log(message) - (string_ptr, string_len)
|
||||
self.imports.push(ImportFunction {
|
||||
module: "env".to_string(),
|
||||
@ -60,37 +60,47 @@ impl RuntimeImports {
|
||||
params: vec!["i32".to_string(), "i32".to_string()],
|
||||
result: None,
|
||||
});
|
||||
|
||||
|
||||
// env.canvas_fillRect for canvas.fillRect(canvas_id, x, y, w, h, color)
|
||||
// Parameters: (canvas_id_ptr, canvas_id_len, x, y, w, h, color_ptr, color_len)
|
||||
self.imports.push(ImportFunction {
|
||||
module: "env".to_string(),
|
||||
name: "canvas_fillRect".to_string(),
|
||||
params: vec![
|
||||
"i32".to_string(), "i32".to_string(), // canvas_id (ptr, len)
|
||||
"i32".to_string(), "i32".to_string(), "i32".to_string(), "i32".to_string(), // x, y, w, h
|
||||
"i32".to_string(), "i32".to_string(), // color (ptr, len)
|
||||
"i32".to_string(),
|
||||
"i32".to_string(), // canvas_id (ptr, len)
|
||||
"i32".to_string(),
|
||||
"i32".to_string(),
|
||||
"i32".to_string(),
|
||||
"i32".to_string(), // x, y, w, h
|
||||
"i32".to_string(),
|
||||
"i32".to_string(), // color (ptr, len)
|
||||
],
|
||||
result: None,
|
||||
});
|
||||
|
||||
|
||||
// env.canvas_fillText for canvas.fillText(canvas_id, text, x, y, font, color)
|
||||
// Parameters: (canvas_id_ptr, canvas_id_len, text_ptr, text_len, x, y, font_ptr, font_len, color_ptr, color_len)
|
||||
self.imports.push(ImportFunction {
|
||||
module: "env".to_string(),
|
||||
name: "canvas_fillText".to_string(),
|
||||
params: vec![
|
||||
"i32".to_string(), "i32".to_string(), // canvas_id (ptr, len)
|
||||
"i32".to_string(), "i32".to_string(), // text (ptr, len)
|
||||
"i32".to_string(), "i32".to_string(), // x, y
|
||||
"i32".to_string(), "i32".to_string(), // font (ptr, len)
|
||||
"i32".to_string(), "i32".to_string(), // color (ptr, len)
|
||||
"i32".to_string(),
|
||||
"i32".to_string(), // canvas_id (ptr, len)
|
||||
"i32".to_string(),
|
||||
"i32".to_string(), // text (ptr, len)
|
||||
"i32".to_string(),
|
||||
"i32".to_string(), // x, y
|
||||
"i32".to_string(),
|
||||
"i32".to_string(), // font (ptr, len)
|
||||
"i32".to_string(),
|
||||
"i32".to_string(), // color (ptr, len)
|
||||
],
|
||||
result: None,
|
||||
});
|
||||
|
||||
|
||||
// Phase 9.77: BoxCall runtime functions
|
||||
|
||||
|
||||
// box_to_string - Convert any Box to string representation
|
||||
self.imports.push(ImportFunction {
|
||||
module: "env".to_string(),
|
||||
@ -98,7 +108,7 @@ impl RuntimeImports {
|
||||
params: vec!["i32".to_string()], // box_ptr
|
||||
result: Some("i32".to_string()), // string_box_ptr
|
||||
});
|
||||
|
||||
|
||||
// box_print - Print any Box to console
|
||||
self.imports.push(ImportFunction {
|
||||
module: "env".to_string(),
|
||||
@ -106,15 +116,15 @@ impl RuntimeImports {
|
||||
params: vec!["i32".to_string()], // box_ptr
|
||||
result: None,
|
||||
});
|
||||
|
||||
|
||||
// box_equals - Compare two Boxes for equality
|
||||
self.imports.push(ImportFunction {
|
||||
module: "env".to_string(),
|
||||
name: "box_equals".to_string(),
|
||||
params: vec!["i32".to_string(), "i32".to_string()], // box1_ptr, box2_ptr
|
||||
result: Some("i32".to_string()), // bool result
|
||||
result: Some("i32".to_string()), // bool result
|
||||
});
|
||||
|
||||
|
||||
// box_clone - Clone a Box
|
||||
self.imports.push(ImportFunction {
|
||||
module: "env".to_string(),
|
||||
@ -122,39 +132,44 @@ impl RuntimeImports {
|
||||
params: vec!["i32".to_string()], // box_ptr
|
||||
result: Some("i32".to_string()), // cloned_box_ptr
|
||||
});
|
||||
|
||||
|
||||
// Future: env.file_read, env.file_write for file I/O
|
||||
// Future: env.http_request for network access
|
||||
}
|
||||
|
||||
|
||||
/// Get all import declarations in WAT format
|
||||
pub fn get_imports(&self) -> Vec<String> {
|
||||
self.imports.iter().map(|import| {
|
||||
let params = if import.params.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
format!("(param {})", import.params.join(" "))
|
||||
};
|
||||
|
||||
let result = if let Some(ref result_type) = import.result {
|
||||
format!("(result {})", result_type)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
format!(
|
||||
"(import \"{}\" \"{}\" (func ${} {} {}))",
|
||||
import.module,
|
||||
import.name,
|
||||
import.name,
|
||||
params,
|
||||
result
|
||||
)
|
||||
}).collect()
|
||||
self.imports
|
||||
.iter()
|
||||
.map(|import| {
|
||||
let params = if import.params.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
format!("(param {})", import.params.join(" "))
|
||||
};
|
||||
|
||||
let result = if let Some(ref result_type) = import.result {
|
||||
format!("(result {})", result_type)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
format!(
|
||||
"(import \"{}\" \"{}\" (func ${} {} {}))",
|
||||
import.module, import.name, import.name, params, result
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
||||
/// Add custom import function
|
||||
pub fn add_import(&mut self, module: String, name: String, params: Vec<String>, result: Option<String>) {
|
||||
pub fn add_import(
|
||||
&mut self,
|
||||
module: String,
|
||||
name: String,
|
||||
params: Vec<String>,
|
||||
result: Option<String>,
|
||||
) {
|
||||
self.imports.push(ImportFunction {
|
||||
module,
|
||||
name,
|
||||
@ -162,50 +177,54 @@ impl RuntimeImports {
|
||||
result,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/// Check if an import is available
|
||||
pub fn has_import(&self, name: &str) -> bool {
|
||||
self.imports.iter().any(|import| import.name == name)
|
||||
}
|
||||
|
||||
|
||||
/// Get import function by name
|
||||
pub fn get_import(&self, name: &str) -> Option<&ImportFunction> {
|
||||
self.imports.iter().find(|import| import.name == name)
|
||||
}
|
||||
|
||||
|
||||
/// Generate JavaScript import object for browser execution
|
||||
pub fn get_js_import_object(&self) -> String {
|
||||
let mut js = String::new();
|
||||
js.push_str("const importObject = {\n");
|
||||
|
||||
|
||||
// Group by module
|
||||
let mut modules: std::collections::HashMap<String, Vec<&ImportFunction>> = std::collections::HashMap::new();
|
||||
let mut modules: std::collections::HashMap<String, Vec<&ImportFunction>> =
|
||||
std::collections::HashMap::new();
|
||||
for import in &self.imports {
|
||||
modules.entry(import.module.clone()).or_default().push(import);
|
||||
modules
|
||||
.entry(import.module.clone())
|
||||
.or_default()
|
||||
.push(import);
|
||||
}
|
||||
|
||||
|
||||
for (module_name, functions) in modules {
|
||||
js.push_str(&format!(" {}: {{\n", module_name));
|
||||
|
||||
|
||||
for function in functions {
|
||||
match function.name.as_str() {
|
||||
"print" => {
|
||||
js.push_str(" print: (value) => console.log(value),\n");
|
||||
},
|
||||
}
|
||||
"print_str" => {
|
||||
js.push_str(" print_str: (ptr, len) => {\n");
|
||||
js.push_str(" const memory = instance.exports.memory;\n");
|
||||
js.push_str(" const str = new TextDecoder().decode(new Uint8Array(memory.buffer, ptr, len));\n");
|
||||
js.push_str(" console.log(str);\n");
|
||||
js.push_str(" },\n");
|
||||
},
|
||||
}
|
||||
"console_log" => {
|
||||
js.push_str(" console_log: (ptr, len) => {\n");
|
||||
js.push_str(" const memory = instance.exports.memory;\n");
|
||||
js.push_str(" const str = new TextDecoder().decode(new Uint8Array(memory.buffer, ptr, len));\n");
|
||||
js.push_str(" console.log(str);\n");
|
||||
js.push_str(" },\n");
|
||||
},
|
||||
}
|
||||
"canvas_fillRect" => {
|
||||
js.push_str(" canvas_fillRect: (canvasIdPtr, canvasIdLen, x, y, w, h, colorPtr, colorLen) => {\n");
|
||||
js.push_str(" const memory = instance.exports.memory;\n");
|
||||
@ -218,7 +237,7 @@ impl RuntimeImports {
|
||||
js.push_str(" ctx.fillRect(x, y, w, h);\n");
|
||||
js.push_str(" }\n");
|
||||
js.push_str(" },\n");
|
||||
},
|
||||
}
|
||||
"canvas_fillText" => {
|
||||
js.push_str(" canvas_fillText: (canvasIdPtr, canvasIdLen, textPtr, textLen, x, y, fontPtr, fontLen, colorPtr, colorLen) => {\n");
|
||||
js.push_str(" const memory = instance.exports.memory;\n");
|
||||
@ -234,49 +253,56 @@ impl RuntimeImports {
|
||||
js.push_str(" ctx.fillText(text, x, y);\n");
|
||||
js.push_str(" }\n");
|
||||
js.push_str(" },\n");
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
js.push_str(&format!(" {}: () => {{ throw new Error('Not implemented: {}'); }},\n",
|
||||
function.name, function.name));
|
||||
js.push_str(&format!(
|
||||
" {}: () => {{ throw new Error('Not implemented: {}'); }},\n",
|
||||
function.name, function.name
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
js.push_str(" },\n");
|
||||
}
|
||||
|
||||
|
||||
js.push_str("};\n");
|
||||
js
|
||||
}
|
||||
|
||||
|
||||
/// Generate Rust wasmtime import bindings
|
||||
pub fn get_wasmtime_imports(&self) -> Result<String, WasmError> {
|
||||
let mut rust_code = String::new();
|
||||
rust_code.push_str("// Wasmtime import bindings\n");
|
||||
rust_code.push_str("let mut imports = Vec::new();\n\n");
|
||||
|
||||
|
||||
for import in &self.imports {
|
||||
match import.name.as_str() {
|
||||
"print" => {
|
||||
rust_code.push_str(r#"
|
||||
rust_code.push_str(
|
||||
r#"
|
||||
let print_func = wasmtime::Func::wrap(&mut store, |value: i32| {
|
||||
println!("{}", value);
|
||||
});
|
||||
imports.push(print_func.into());
|
||||
"#);
|
||||
},
|
||||
"#,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
rust_code.push_str(&format!(r#"
|
||||
rust_code.push_str(&format!(
|
||||
r#"
|
||||
// TODO: Implement {} import
|
||||
let {}_func = wasmtime::Func::wrap(&mut store, || {{
|
||||
panic!("Not implemented: {}")
|
||||
}});
|
||||
imports.push({}_func.into());
|
||||
"#, import.name, import.name, import.name, import.name));
|
||||
"#,
|
||||
import.name, import.name, import.name, import.name
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ok(rust_code)
|
||||
}
|
||||
}
|
||||
@ -284,25 +310,25 @@ imports.push({}_func.into());
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_runtime_imports_creation() {
|
||||
let runtime = RuntimeImports::new();
|
||||
assert!(!runtime.imports.is_empty());
|
||||
assert!(runtime.has_import("print"));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_import_wat_generation() {
|
||||
let runtime = RuntimeImports::new();
|
||||
let imports = runtime.get_imports();
|
||||
|
||||
|
||||
assert!(!imports.is_empty());
|
||||
assert!(imports[0].contains("import"));
|
||||
assert!(imports[0].contains("env"));
|
||||
assert!(imports[0].contains("print"));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_custom_import_addition() {
|
||||
let mut runtime = RuntimeImports::new();
|
||||
@ -310,34 +336,34 @@ mod tests {
|
||||
"custom".to_string(),
|
||||
"test_func".to_string(),
|
||||
vec!["i32".to_string(), "i32".to_string()],
|
||||
Some("i32".to_string())
|
||||
Some("i32".to_string()),
|
||||
);
|
||||
|
||||
|
||||
assert!(runtime.has_import("test_func"));
|
||||
let import = runtime.get_import("test_func").unwrap();
|
||||
assert_eq!(import.module, "custom");
|
||||
assert_eq!(import.params.len(), 2);
|
||||
assert!(import.result.is_some());
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_js_import_object_generation() {
|
||||
let runtime = RuntimeImports::new();
|
||||
let js = runtime.get_js_import_object();
|
||||
|
||||
|
||||
assert!(js.contains("importObject"));
|
||||
assert!(js.contains("env"));
|
||||
assert!(js.contains("print"));
|
||||
assert!(js.contains("console.log"));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_wasmtime_imports_generation() {
|
||||
let runtime = RuntimeImports::new();
|
||||
let rust_code = runtime.get_wasmtime_imports().unwrap();
|
||||
|
||||
|
||||
assert!(rust_code.contains("wasmtime::Func::wrap"));
|
||||
assert!(rust_code.contains("print_func"));
|
||||
assert!(rust_code.contains("println!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user