build_hello_wasm.rs (5124B)
1 /// Compiles the hello WAT module to a .wasm file and places it in 2 /// the notedeck wasm_apps directory for testing. 3 /// 4 /// Usage: cargo run -p notedeck_wasm --example build_hello_wasm 5 fn main() { 6 let wat = r#"(module 7 (import "env" "nd_heading" (func $nd_heading (param i32 i32))) 8 (import "env" "nd_label" (func $nd_label (param i32 i32))) 9 (import "env" "nd_button" (func $nd_button (param i32 i32) (result i32))) 10 (import "env" "nd_add_space" (func $nd_add_space (param f32))) 11 12 (memory (export "memory") 1) 13 14 ;; Static strings 15 (data (i32.const 0) "Hello from WASM!") ;; 16 bytes 16 (data (i32.const 16) "Click me") ;; 8 bytes 17 (data (i32.const 24) "Clicks: ") ;; 8 bytes 18 (data (i32.const 32) "0123456789") ;; digit table 19 20 ;; App metadata 21 (data (i32.const 500) "Hello WASM") 22 (global (export "nd_app_name_ptr") i32 (i32.const 500)) 23 (global (export "nd_app_name_len") i32 (i32.const 10)) 24 25 ;; Global click counter 26 (global $count (mut i32) (i32.const 0)) 27 28 ;; Simple itoa: writes decimal digits at ptr, returns length 29 (func $itoa (param $n i32) (param $ptr i32) (result i32) 30 (local $len i32) 31 (local $tmp i32) 32 (local $start i32) 33 (local $end i32) 34 (local $swap i32) 35 36 ;; Handle zero 37 (if (i32.eqz (local.get $n)) 38 (then 39 (i32.store8 (local.get $ptr) (i32.const 48)) ;; '0' 40 (return (i32.const 1)) 41 ) 42 ) 43 44 ;; Write digits in reverse 45 (local.set $tmp (local.get $n)) 46 (local.set $len (i32.const 0)) 47 (block $done 48 (loop $digits 49 (br_if $done (i32.eqz (local.get $tmp))) 50 (i32.store8 51 (i32.add (local.get $ptr) (local.get $len)) 52 (i32.add (i32.const 48) 53 (i32.rem_u (local.get $tmp) (i32.const 10)))) 54 (local.set $tmp (i32.div_u (local.get $tmp) (i32.const 10))) 55 (local.set $len (i32.add (local.get $len) (i32.const 1))) 56 (br $digits) 57 ) 58 ) 59 60 ;; Reverse the digits in place 61 (local.set $start (i32.const 0)) 62 (local.set $end (i32.sub (local.get $len) (i32.const 1))) 63 (block $rev_done 64 (loop $rev 65 (br_if $rev_done (i32.ge_u (local.get $start) (local.get $end))) 66 ;; swap 67 (local.set $swap 68 (i32.load8_u (i32.add (local.get $ptr) (local.get $start)))) 69 (i32.store8 70 (i32.add (local.get $ptr) (local.get $start)) 71 (i32.load8_u (i32.add (local.get $ptr) (local.get $end)))) 72 (i32.store8 73 (i32.add (local.get $ptr) (local.get $end)) 74 (local.get $swap)) 75 (local.set $start (i32.add (local.get $start) (i32.const 1))) 76 (local.set $end (i32.sub (local.get $end) (i32.const 1))) 77 (br $rev) 78 ) 79 ) 80 81 (local.get $len) 82 ) 83 84 (func (export "nd_update") 85 (local $num_len i32) 86 87 ;; Heading 88 (call $nd_heading (i32.const 0) (i32.const 16)) 89 (call $nd_add_space (f32.const 8.0)) 90 91 ;; Button 92 (if (call $nd_button (i32.const 16) (i32.const 8)) 93 (then 94 (global.set $count 95 (i32.add (global.get $count) (i32.const 1))) 96 ) 97 ) 98 (call $nd_add_space (f32.const 4.0)) 99 100 ;; "Clicks: " prefix is at offset 24 (8 bytes) 101 ;; Write the number starting at offset 100 (scratch space) 102 (local.set $num_len 103 (call $itoa (global.get $count) (i32.const 100))) 104 105 ;; Copy "Clicks: " to offset 200, then append the number 106 ;; offset 200: "Clicks: " 107 (memory.copy (i32.const 200) (i32.const 24) (i32.const 8)) 108 ;; offset 208: number digits 109 (memory.copy 110 (i32.const 208) 111 (i32.const 100) 112 (local.get $num_len)) 113 114 ;; Label with total length = 8 + num_len 115 (call $nd_label 116 (i32.const 200) 117 (i32.add (i32.const 8) (local.get $num_len))) 118 ) 119 )"#; 120 121 let wasm = wat::parse_str(wat).expect("failed to parse WAT"); 122 123 // Write to the notedeck wasm_apps directory 124 let dir = dirs::data_dir() 125 .expect("data dir") 126 .join("notedeck") 127 .join("cache") 128 .join("wasm_apps"); 129 std::fs::create_dir_all(&dir).expect("create wasm_apps dir"); 130 131 let path = dir.join("hello.wasm"); 132 std::fs::write(&path, &wasm).expect("write hello.wasm"); 133 println!("Wrote {} bytes to {}", wasm.len(), path.display()); 134 }