2 changed files with 113 additions and 3 deletions
@ -0,0 +1,105 @@ |
|||
(module $list |
|||
|
|||
(type $list (struct |
|||
(field $head i32) |
|||
(field $tail (ref null $list)) |
|||
)) |
|||
|
|||
(func $nil (result (ref null $list)) |
|||
(return (ref.null $list)) |
|||
) |
|||
|
|||
(func $cons (param $head i32) (param $tail (ref null $list)) (result (ref $list)) |
|||
(struct.new $list (local.get $head) (local.get $tail) (rtt.canon $list)) |
|||
return |
|||
) |
|||
|
|||
(func $is_nil (param $list (ref null $list)) (result i32) |
|||
(block $l (result i32) |
|||
i32.const 1 |
|||
(br_on_null $l (local.get $list)) |
|||
drop |
|||
drop |
|||
i32.const 0 |
|||
) |
|||
return |
|||
) |
|||
|
|||
(func $head (param $list (ref $list)) (result i32) |
|||
(struct.get $list $head (local.get $list)) |
|||
return |
|||
) |
|||
|
|||
(func $tail (param $list (ref $list)) (result (ref null $list)) |
|||
(struct.get $list $tail (local.get $list)) |
|||
return |
|||
) |
|||
|
|||
(func $length_aux (param $acc i32) (param $list (ref null $list)) (result i32) |
|||
(if (result i32) (call $is_nil (local.get $list)) |
|||
(then |
|||
(return (local.get $acc)) |
|||
) (else |
|||
(return |
|||
(call $length_aux |
|||
(i32.add (local.get $acc) (i32.const 1)) |
|||
(call $tail (ref.as_non_null (local.get $list))) |
|||
) |
|||
) |
|||
) |
|||
) |
|||
) |
|||
|
|||
(func $length (param $list (ref null $list)) (result i32) |
|||
(return (call $length_aux (i32.const 0) (local.get $list))) |
|||
) |
|||
|
|||
(func $nth_aux (param $list (ref null $list)) (param $n i32) (result i32) |
|||
(if (call $is_nil (local.get $list)) |
|||
(then unreachable) |
|||
) |
|||
(if (result i32) (i32.eq (i32.const 0) (local.get $n)) |
|||
(then (call $head (ref.as_non_null (local.get $list)))) |
|||
(else |
|||
(call $nth_aux |
|||
(call $tail (ref.as_non_null (local.get $list))) |
|||
(i32.sub (local.get $n) (i32.const 1)) |
|||
) |
|||
)) |
|||
return |
|||
) |
|||
|
|||
(func $nth (param $list (ref null $list)) (param $n i32) (result i32) |
|||
(if (i32.lt_s (local.get $n) (i32.const 0)) |
|||
(then unreachable) |
|||
) |
|||
(return (call $nth_aux (local.get $list) (local.get $n))) |
|||
) |
|||
|
|||
(type $mapf (func (param i32) (result i32))) |
|||
|
|||
(func $map (param $f (ref $mapf)) (param $list (ref null $list)) (result (ref null $list)) |
|||
(if (result (ref null $list)) (call $is_nil (local.get $list)) |
|||
(then (call $nil)) |
|||
(else |
|||
(call $cons |
|||
(call_ref (call $head (ref.as_non_null (local.get $list))) (local.get $f)) |
|||
(call $map (local.get $f) (call $tail (ref.as_non_null (local.get $list)))) |
|||
) |
|||
)) |
|||
return |
|||
) |
|||
|
|||
(func (export "test_should_be_nil") (result i32) |
|||
(return (call $is_nil (call $nil))) |
|||
) |
|||
|
|||
(func (export "test_should_not_be_nil") (result i32) |
|||
(return |
|||
(call $is_nil |
|||
(call $cons (i32.const 42) (call $nil)))) |
|||
) |
|||
) |
|||
|
|||
(assert_return (invoke "test_should_be_nil") (i32.const 1)) |
|||
(assert_return (invoke "test_should_not_be_nil") (i32.const 0)) |
Loading…
Reference in new issue