Created
February 27, 2022 21:29
-
-
Save brecert/701f4371baf00ae7de7d44bd371b7fe8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(module | |
;; Import the required fd_write WASI function which will write the given io vectors to stdout | |
;; The function signature for fd_write is: | |
;; (File Descriptor, *iovs, iovs_len, nwritten) -> Returns number of bytes written | |
(import "wasi_unstable" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32))) | |
(import "wasi_unstable" "fd_read" (func $fd_read (param i32 i32 i32 i32) (result i32))) | |
(memory 1) | |
(export "memory" (memory 0)) | |
;; create new io vector within linear memory | |
(data (i32.const 0) "\18\00\00\00") ;; iovec.buf - pointer to the prompt string | |
(data (i32.const 4) "\03\00\00\00") ;; iovec.buf_len - | |
;; valid-list | |
(data (i32.const 8) "\1c\00\00\00") | |
(data (i32.const 12) "\03\00\00\00") | |
(data (i32.const 16) "\20\00\00\00") | |
(data (i32.const 20) "\03\00\00\00") | |
(data (i32.const 24) "foo") | |
(data (i32.const 28) "bar") | |
(data (i32.const 32) "bar") | |
;; create new cio vector within linear memory | |
(data (i32.const 36) "\78\00\00\00") ;; ciovec.buf - pointer to the input string | |
(data (i32.const 40) "\0b\00\00\00") ;; ciovec.buf_len - max length of 255 | |
;; comma | |
(data (i32.const 44) "\34\00\00\00") | |
(data (i32.const 48) "\02\00\00\00") | |
(data (i32.const 52) ", ") | |
;; braces | |
(data (i32.const 56) "\48\00\00\00") | |
(data (i32.const 60) "\01\00\00\00") | |
(data (i32.const 64) "\49\00\00\00") | |
(data (i32.const 68) "\03\00\00\00") | |
(data (i32.const 72) "(") | |
(data (i32.const 73) "): ") | |
;; invalid answer | |
(data (i32.const 78) "\5e\00\00\00") | |
(data (i32.const 82) "\01\00\00\00") | |
(data (i32.const 86) "\5f\00\00\00") | |
(data (i32.const 90) "\17\00\00\00") | |
(data (i32.const 94) "\"") | |
(data (i32.const 95) "\" is not a valid answer") | |
;; input string buffer | |
(data (i32.const 120) " bree \r\n") | |
(func $pointer.load8_u (export "mem_char_at") (param $ptr i32) (param $offset i32) (result i32) | |
( | |
i32.load8_u | |
(i32.add | |
(i32.load (local.get $ptr)) | |
(local.get $offset) | |
) | |
) | |
) | |
(func $iovec.buf_len (export "buf_len") (param $iov i32) (result i32) | |
(i32.load offset=4 (local.get $iov)) | |
) | |
(func $iovec.eq (param $iov1 i32) (param $iov2 i32) (result i32) | |
(local $idx i32) | |
(local $size i32) | |
(local.set $idx (i32.const 0)) | |
(local.set $size (call $iovec.buf_len (local.get $iov1))) | |
(if (i32.ne (local.get $size) (call $iovec.buf_len (local.get $iov2))) | |
(return (i32.const 0)) | |
) | |
(loop $loop | |
(if (i32.ne (call $pointer.load8_u (local.get $iov1) (local.get $idx)) (call $pointer.load8_u (local.get $iov2) (local.get $idx))) | |
(then (return (i32.const 0)))) | |
(local.set $idx (i32.add (local.get $idx) (i32.const 1))) | |
(br_if $loop (i32.ne (local.get $idx) (local.get $size))) | |
) | |
(return (i32.const 1)) | |
) | |
(func $char.is_whitespace (param $char i32) (result i32) | |
;; ' ' = 32 | |
;; '\r' = 13 | |
;; '\n' = 10 | |
(return | |
(i32.or | |
(i32.eq (local.get $char) (i32.const 32)) | |
(i32.or | |
(i32.eq (local.get $char) (i32.const 13)) | |
(i32.eq (local.get $char) (i32.const 10)) | |
) | |
) | |
) | |
) | |
;; returns slice (start-mem end-mem) | |
(func $iovec.trim (export "trim") (param $iov i32) (result i32 i32) | |
(local $start i32) | |
(local $end i32) | |
(local.set $start (i32.load (local.get $iov))) | |
(local.set $end (call $iovec.buf_len (local.get $iov))) | |
(loop $loop | |
(if (i32.and | |
(call $char.is_whitespace (call $pointer.load8_u (local.get $iov) (local.get $end))) | |
(i32.ne (local.get $end) (local.get $start)) | |
) | |
(then | |
(local.set $end (i32.sub (local.get $end) (i32.const 1))) | |
(br $loop) | |
) | |
) | |
) | |
(loop $loop | |
(if (i32.and | |
(call $char.is_whitespace (i32.load8_u (local.get $start)) ) | |
(i32.ne (local.get $start) (i32.add (local.get $iov (local.get $end)))) | |
) | |
(then | |
(local.set $start (i32.add (local.get $start) (i32.const 1))) | |
(br $loop) | |
) | |
) | |
) | |
(return (local.get $start) (local.get $end)) | |
) | |
;; -1 for nothing | |
;; otherwise return found item index | |
(func $list<iovec>.find (param $iov i32) (param $iovs i32) (param $iovs_len i32) (result i32) | |
(local $idx i32) | |
(local.set $idx (i32.const 0)) | |
(loop $loop | |
(if | |
(call $iovec.eq | |
(local.get $iov) | |
(i32.add | |
(local.get $iovs) | |
(i32.mul (local.get $idx) (i32.const 8)) | |
) | |
) | |
(then (return (local.get $idx))) | |
) | |
(local.set $idx (i32.add (local.get $idx) (i32.const 1))) | |
(br_if $loop (i32.ne (local.get $idx) (local.get $iovs_len))) | |
) | |
(return (i32.const -1)) | |
) | |
(func $print (param $iovec i32) | |
(call $fd_write | |
(i32.const 1) ;; file_descriptor - 1 for stdout | |
(local.get $iovec) ;; *iovs - The pointer to the iov array, which is stored at memory location 0 | |
(i32.const 1) ;; iovs_len - We're printing 1 string stored in an iov - so one. | |
(i32.const 512) ;; nwritten - A place in memory to store the number of bytes written | |
) | |
drop | |
) | |
(func $print_joined (param $iovs i32) (param $iovs.len i32) (param $iov_join_with i32) | |
(local $idx i32) | |
(local.set $idx (i32.const 0)) | |
(loop $loop | |
(call $print (i32.add | |
(local.get $iovs) | |
(i32.mul (local.get $idx) (i32.const 8)) | |
)) | |
(local.set $idx (i32.add (local.get $idx) (i32.const 1))) | |
(if (i32.ge_u (local.get $idx) (local.get $iovs.len)) (return)) | |
(call $print (local.get $iov_join_with)) | |
(br $loop) | |
) | |
) | |
(func $print_prompt | |
(call $print (i32.const 0)) | |
(call $print (i32.const 56)) | |
(call $print_joined | |
(i32.const 8) | |
(i32.const 2) | |
(i32.const 44) | |
) | |
(call $print (i32.const 64)) | |
) | |
(func $swap (param i32 i32) (result i32 i32) (local.get 1) (local.get 0)) | |
(func (export "test") (result i32 i32) | |
(call $iovec.trim (i32.const 36)) | |
;; not ideal, not sure how else to handle | |
(i32.store (i32.const 40) (call $swap)) | |
(i32.store (i32.const 36) (call $swap)) | |
(i32.load (i32.const 36)) | |
(i32.load (i32.const 40)) | |
) | |
(func $question (export "question") (param $prompt i32) (param $valid i32) (param $valid_len i32) | |
(local $ret i32) | |
(loop $loop | |
(i32.store (i32.const 36) (i32.const 120)) | |
(i32.store (i32.const 40) (i32.const 255)) | |
(call $print_prompt) | |
(local.set $ret | |
(call $fd_read | |
(i32.const 0) | |
(i32.const 36) | |
(i32.const 1) | |
(i32.const 40) | |
) | |
) | |
;; [temporary until trim implemented] remove \r\n | |
(i32.store (i32.const 40) (i32.sub (i32.load (i32.const 40)) (i32.const 2))) | |
(call $iovec.trim (i32.const 36)) | |
;; not ideal, not sure how else to handle | |
(i32.store (i32.const 40) (call $swap)) | |
(i32.store (i32.const 36) (call $swap)) | |
(call $print (i32.const 36)) | |
(local.set $ret (call $list<iovec>.find (i32.const 36) (local.get $valid) (local.get $valid_len))) | |
(if (i32.ne (local.get $ret) (i32.const -1)) (then (return (local.get $ret)))) | |
(br $loop) | |
) | |
) | |
(func $main (export "_start") | |
(call $question (i32.const 0) (i32.const 8) (i32.const 2)) | |
) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment