forked from rhysd/wain
-
Notifications
You must be signed in to change notification settings - Fork 0
/
invoke.rs
100 lines (93 loc) · 2.7 KB
/
invoke.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
extern crate wain_exec;
extern crate wain_syntax_text;
extern crate wain_validate;
use futures::executor::block_on;
use std::io;
use std::process::exit;
use wain_exec::{DefaultImporter, Runtime, Value};
use wain_syntax_text::parse;
use wain_validate::validate;
const MODULE_ADD: &str = r#"
(module
(type (;0;) (func (param i32 i32) (result i32)))
(func $add (type 0) (param i32 i32) (result i32)
(local i32 i32 i32 i32 i32 i32)
global.get 0
local.set 2
i32.const 16
local.set 3
local.get 2
local.get 3
i32.sub
local.set 4
local.get 4
local.get 0
i32.store offset=12
local.get 4
local.get 1
i32.store offset=8
local.get 4
i32.load offset=12
local.set 5
local.get 4
i32.load offset=8
local.set 6
local.get 5
local.get 6
i32.add
local.set 7
local.get 7
return)
(table (;0;) 1 1 funcref)
(memory (;0;) 2)
(global (;0;) (mut i32) (i32.const 66560))
(export "memory" (memory 0))
(export "add" (func $add)))
"#;
fn main() {
// Parse WAT text into syntax tree
let tree = match parse(MODULE_ADD) {
Ok(tree) => tree,
Err(err) => {
eprintln!("Parse failed: {}", err);
exit(1);
}
};
// Validate module
if let Err(err) = validate(&tree) {
eprintln!("This .wat file is invalid: {}", err);
exit(1);
}
// Create default importer to call external function supported by default
let stdin = io::stdin();
let stdout = io::stdout();
let importer = DefaultImporter::with_stdio(stdin.lock(), stdout.lock());
// Make abstract machine runtime. This instantiates Wasm module
let mut runtime = match Runtime::instantiate(&tree.module, importer, core::u16::MAX) {
Ok(rt) => rt,
Err(err) => {
eprintln!("could not instantiate module: {}", err);
exit(1);
}
};
block_on(async {
// `int add(int, int)` is exported as `(func (param i32) (result i32))`.
// Let's invoke add(10, 32). `Value` is an enum to represent arbitrary value of Wasm. Wasm has
// i32, i64, f32, f64 basic types.
match runtime
.invoke("add", &[Value::I32(10), Value::I32(32)])
.await
{
Ok(ret) => {
// `ret` is type of `Option<Value>` where it contains `Some` value when the invoked
// function returned a value. Otherwise it's `None` value.
if let Some(Value::I32(i)) = ret {
println!("10 + 32 = {}", i);
} else {
unreachable!();
}
}
Err(trap) => eprintln!("Execution was trapped: {}", trap),
}
});
}