Unlike many languages, WebAssembly code does not automatically have access to global resources such as the console. Such functionality instead must be provided as imports.
In order to provide console.log
like functionality and a few other niceties, the Exercism WebAssembly track exposes a standard library of functions across all exercises.
These functions must be imported at the top of your WebAssembly module and then can be called from within your WebAssembly code.
The log_mem_*
functions expect to be able to access the linear memory of your WebAssembly module. By default, this is private state, so to make this accessible, you must export your linear memory under the export name mem
. This is accomplished as follows:
(memory (export "mem") 1)
We provide logging functions for each of the primitive WebAssembly types. This is useful for logging global and local variables.
(module
(import "console" "log_i32_s" (func $log_i32_s (param i32)))
(func $main
;; logs -1
(call $log_i32_s (i32.const -1))
)
)
(module
(import "console" "log_i32_u" (func $log_i32_u (param i32)))
(func $main
;; Logs 42 to console
(call $log_i32_u (i32.const 42))
)
)
(module
(import "console" "log_i64_s" (func $log_i64_s (param i64)))
(func $main
;; Logs -99 to console
(call $log_i32_u (i64.const -99))
)
)
(module
(import "console" "log_i64_u" (func $log_i64_u (param i64)))
(func $main
;; Logs 42 to console
(call $log_i64_u (i32.const 42))
)
)
(module
(import "console" "log_f32" (func $log_f32 (param f32)))
(func $main
;; Logs 3.140000104904175 to console
(call $log_f32 (f32.const 3.14))
)
)
(module
(import "console" "log_f64" (func $log_f64 (param f64)))
(func $main
;; Logs 3.14 to console
(call $log_f64 (f64.const 3.14))
)
)
WebAssembly Linear Memory is a byte-addressable array of values. This serves as the equivalent of virtual memory for WebAssembly programs
We provide logging functions to interpret a range of addresses within linear memory as static arrays of certain types. This acts similar to the TypedArrays of JavaScript. The length parameters are not measured in bytes. They are measured in the number of consecutive elements of the type associated with the function.
In order for these functions to work, your WebAssembly module must declare and export its linear memory using the named export "mem"
(memory (export "mem") 1)
(module
(import "console" "log_mem_as_utf8" (func $log_mem_as_utf8 (param $byteOffset i32) (param $length i32)))
(memory (export "mem") 1)
(data (i32.const 64) "Goodbye, Mars!")
(func $main
;; Logs "Goodbye, Mars!" to console
(call $log_mem_as_utf8 (i32.const 64) (i32.const 14))
)
)
(module
(import "console" "log_mem_as_i8" (func $log_mem_as_i8 (param $byteOffset i32) (param $length i32)))
(memory (export "mem") 1)
(func $main
(memory.fill (i32.const 128) (i32.const -42) (i32.const 10))
;; Logs an array of 10x -42 to console
(call $log_mem_as_u8 (i32.const 128) (i32.const 10))
)
)
(module
(import "console" "log_mem_as_u8" (func $log_mem_as_u8 (param $byteOffset i32) (param $length i32)))
(memory (export "mem") 1)
(func $main
(memory.fill (i32.const 128) (i32.const 42) (i32.const 10))
;; Logs an array of 10x 42 to console
(call $log_mem_as_u8 (i32.const 128) (i32.const 10))
)
)
(module
(import "console" "log_mem_as_i16" (func $log_mem_as_i16 (param $byteOffset i32) (param $length i32)))
(memory (export "mem") 1)
(func $main
(i32.store16 (i32.const 128) (i32.const -10000))
(i32.store16 (i32.const 130) (i32.const -10001))
(i32.store16 (i32.const 132) (i32.const -10002))
;; Logs [-10000, -10001, -10002] to console
(call $log_mem_as_i16 (i32.const 128) (i32.const 3))
)
)
(module
(import "console" "log_mem_as_u16" (func $log_mem_as_u16 (param $byteOffset i32) (param $length i32)))
(memory (export "mem") 1)
(func $main
(i32.store16 (i32.const 128) (i32.const 10000))
(i32.store16 (i32.const 130) (i32.const 10001))
(i32.store16 (i32.const 132) (i32.const 10002))
;; Logs [10000, 10001, 10002] to console
(call $log_mem_as_u16 (i32.const 128) (i32.const 3))
)
)
(module
(import "console" "log_mem_as_i32" (func $log_mem_as_i32 (param $byteOffset i32) (param $length i32)))
(memory (export "mem") 1)
(func $main
(i32.store (i32.const 128) (i32.const -10000000))
(i32.store (i32.const 132) (i32.const -10000001))
(i32.store (i32.const 136) (i32.const -10000002))
;; Logs [-10000000, -10000001, -10000002] to console
(call $log_mem_as_i32 (i32.const 128) (i32.const 3))
)
)
(module
(import "console" "log_mem_as_u32" (func $log_mem_as_u32 (param $byteOffset i32) (param $length i32)))
(memory (export "mem") 1)
(func $main
(i32.store (i32.const 128) (i32.const 100000000))
(i32.store (i32.const 132) (i32.const 100000001))
(i32.store (i32.const 136) (i32.const 100000002))
;; Logs [100000000, 100000001, 100000002] to console
(call $log_mem_as_u32 (i32.const 128) (i32.const 3))
)
)
(module
(import "console" "log_mem_as_i64" (func $log_mem_as_i64 (param $byteOffset i32) (param $length i32)))
(memory (export "mem") 1)
(func $main
(i64.store (i32.const 128) (i64.const -10000000000))
(i64.store (i32.const 136) (i64.const -10000000001))
(i64.store (i32.const 144) (i64.const -10000000002))
;; Logs [-10000000000, -10000000001, -10000000002] to console
(call $log_mem_as_i64 (i32.const 128) (i32.const 3))
)
)
(module
(import "console" "log_mem_as_u64" (func $log_mem_as_u64 (param $byteOffset i32) (param $length i32)))
(memory (export "mem") 1)
(func $main
(i64.store (i32.const 128) (i64.const 10000000000))
(i64.store (i32.const 136) (i64.const 10000000001))
(i64.store (i32.const 144) (i64.const 10000000002))
;; Logs [10000000000, 10000000001, 10000000002] to console
(call $log_mem_as_u64 (i32.const 128) (i32.const 3))
)
)
(module
(import "console" "log_mem_as_f32" (func $log_mem_as_f32 (param $byteOffset i32) (param $length i32)))
(memory (export "mem") 1)
(func $main
(f32.store (i32.const 128) (f32.const 3.14))
(f32.store (i32.const 132) (f32.const 3.14))
(f32.store (i32.const 136) (f32.const 3.14))
;; Logs [3.140000104904175, 3.140000104904175, 3.140000104904175] to console
(call $log_mem_as_u64 (i32.const 128) (i32.const 3))
)
)
(module
(import "console" "log_mem_as_f64" (func $log_mem_as_f64 (param $byteOffset i32) (param $length i32)))
(memory (export "mem") 1)
(f64.store (i32.const 128) (f64.const 3.14))
(f64.store (i32.const 136) (f64.const 3.14))
(f64.store (i32.const 144) (f64.const 3.14))
;; Logs [3.14, 3.14, 3.14] to console
(call $log_mem_as_u64 (i32.const 128) (i32.const 3))
)
)