mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-22 17:02:13 +00:00
feat(interface-types) Continue.
This commit is contained in:
parent
2f3c37fbd5
commit
c63345029e
@ -1,16 +1,31 @@
|
|||||||
use crate::instructions::{stack::Stack, Instruction};
|
use crate::instructions::{
|
||||||
|
stack::{Stack, Stackable},
|
||||||
|
Instruction,
|
||||||
|
};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
type ExecutableInstruction = Box<dyn Fn(&mut Stack)>;
|
type ExecutableInstruction = Box<dyn Fn(&mut Stack<u64>) -> Result<(), &'static str>>;
|
||||||
|
|
||||||
pub(crate) struct Interpreter {
|
pub(crate) struct Interpreter {
|
||||||
stack: Stack,
|
executable_instructions: Vec<ExecutableInstruction>,
|
||||||
instructions: Vec<ExecutableInstruction>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpreter {
|
impl Interpreter {
|
||||||
pub(crate) fn is_eos(&self) -> bool {
|
fn iter(&self) -> impl Iterator<Item = &ExecutableInstruction> + '_ {
|
||||||
self.stack.is_empty()
|
self.executable_instructions.iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn run(&self) -> Result<Stack<u64>, &'static str> {
|
||||||
|
let mut stack = Stack::new();
|
||||||
|
|
||||||
|
for executable_instruction in self.iter() {
|
||||||
|
match executable_instruction(&mut stack) {
|
||||||
|
Ok(_) => continue,
|
||||||
|
Err(message) => return Err(message),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(stack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,25 +40,34 @@ impl<'binary_input> TryFrom<&Vec<Instruction<'binary_input>>> for Interpreter {
|
|||||||
Instruction::ArgumentGet(index) => {
|
Instruction::ArgumentGet(index) => {
|
||||||
let index = index.to_owned();
|
let index = index.to_owned();
|
||||||
|
|
||||||
Box::new(move |stack: &mut Stack| {
|
Box::new(move |stack: &mut Stack<u64>| -> Result<(), _> {
|
||||||
println!("argument get {}", index);
|
println!("argument get {}", index);
|
||||||
|
stack.push(index);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Instruction::CallExport(export_name) => {
|
Instruction::CallExport(export_name) => {
|
||||||
let export_name = (*export_name).to_owned();
|
let export_name = (*export_name).to_owned();
|
||||||
|
|
||||||
Box::new(move |stack: &mut Stack| {
|
Box::new(move |_stack: &mut Stack<u64>| -> Result<(), _> {
|
||||||
println!("call export {}", export_name);
|
println!("call export {}", export_name);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Instruction::ReadUtf8 => Box::new(|stack: &mut Stack| {
|
Instruction::ReadUtf8 => Box::new(|_stack: &mut Stack<u64>| -> Result<(), _> {
|
||||||
println!("read utf8");
|
println!("read utf8");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}),
|
}),
|
||||||
Instruction::Call(index) => {
|
Instruction::Call(index) => {
|
||||||
let index = index.to_owned();
|
let index = index.to_owned();
|
||||||
|
|
||||||
Box::new(move |stack: &mut Stack| {
|
Box::new(move |_stack: &mut Stack<u64>| -> Result<(), _> {
|
||||||
println!("call {}", index);
|
println!("call {}", index);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
@ -52,8 +76,7 @@ impl<'binary_input> TryFrom<&Vec<Instruction<'binary_input>>> for Interpreter {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(Interpreter {
|
Ok(Interpreter {
|
||||||
stack: Stack::new(),
|
executable_instructions,
|
||||||
instructions: executable_instructions,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,7 +84,7 @@ impl<'binary_input> TryFrom<&Vec<Instruction<'binary_input>>> for Interpreter {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Interpreter;
|
use super::Interpreter;
|
||||||
use crate::instructions::Instruction;
|
use crate::instructions::{stack::Stackable, Instruction};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -73,10 +96,20 @@ mod tests {
|
|||||||
Instruction::ReadUtf8,
|
Instruction::ReadUtf8,
|
||||||
Instruction::Call(7),
|
Instruction::Call(7),
|
||||||
];
|
];
|
||||||
let interpreter: Result<Interpreter, _> = (&instructions).try_into();
|
let interpreter: Interpreter = (&instructions).try_into().unwrap();
|
||||||
assert!(interpreter.is_ok());
|
|
||||||
|
|
||||||
let interpreter = interpreter.unwrap();
|
assert_eq!(interpreter.executable_instructions.len(), 5);
|
||||||
assert_eq!(interpreter.is_eos(), true);
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_interpreter_argument_get() {
|
||||||
|
let interpreter: Interpreter = (&vec![Instruction::ArgumentGet(42)]).try_into().unwrap();
|
||||||
|
let run = interpreter.run();
|
||||||
|
|
||||||
|
assert!(run.is_ok());
|
||||||
|
|
||||||
|
let stack = run.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(stack.as_slice(), &[42]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,62 @@
|
|||||||
use std::{iter::Rev, vec::Drain};
|
pub(crate) trait Stackable {
|
||||||
|
type Item;
|
||||||
|
|
||||||
pub(super) struct Stack {
|
fn is_empty(&self) -> bool;
|
||||||
inner: Vec<u32>,
|
fn as_slice(&self) -> &[Self::Item];
|
||||||
|
fn push(&mut self, item: Self::Item);
|
||||||
|
fn pop1(&mut self) -> Option<Self::Item>;
|
||||||
|
fn pop(&mut self, n: usize) -> Option<Vec<Self::Item>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stack {
|
pub(crate) struct Stack<T> {
|
||||||
pub(super) fn new() -> Self {
|
inner: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Stack<T> {
|
||||||
|
pub fn new() -> Self {
|
||||||
Self { inner: Vec::new() }
|
Self { inner: Vec::new() }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn is_empty(&self) -> bool {
|
impl<T> Stackable for Stack<T> {
|
||||||
|
type Item = T;
|
||||||
|
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
self.inner.is_empty()
|
self.inner.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn push(&mut self, item: u32) {
|
fn as_slice(&self) -> &[Self::Item] {
|
||||||
|
self.inner.as_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push(&mut self, item: Self::Item) {
|
||||||
self.inner.push(item);
|
self.inner.push(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn pop(&mut self) -> Option<u32> {
|
fn pop1(&mut self) -> Option<Self::Item> {
|
||||||
self.inner.pop()
|
self.inner.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn pop_n(&mut self, n: usize) -> Rev<Drain<u32>> {
|
fn pop(&mut self, n: usize) -> Option<Vec<Self::Item>> {
|
||||||
self.inner.drain(self.inner.len() - n..).rev()
|
if self.inner.len() < n {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let items = self
|
||||||
|
.inner
|
||||||
|
.drain(self.inner.len() - n..)
|
||||||
|
.rev()
|
||||||
|
.collect::<Vec<Self::Item>>();
|
||||||
|
|
||||||
|
assert!(items.len() == n);
|
||||||
|
|
||||||
|
Some(items)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Stack;
|
use super::{Stack, Stackable};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_empty() {
|
fn test_is_empty() {
|
||||||
@ -40,16 +68,16 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_push_pop() {
|
fn test_push_pop1() {
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
stack.push(1);
|
stack.push(1);
|
||||||
|
|
||||||
assert_eq!(stack.pop(), Some(1));
|
assert_eq!(stack.pop1(), Some(1));
|
||||||
assert_eq!(stack.is_empty(), true);
|
assert_eq!(stack.is_empty(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pop_n() {
|
fn test_pop() {
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
stack.push(1);
|
stack.push(1);
|
||||||
stack.push(2);
|
stack.push(2);
|
||||||
@ -58,9 +86,9 @@ mod tests {
|
|||||||
stack.push(5);
|
stack.push(5);
|
||||||
stack.push(6);
|
stack.push(6);
|
||||||
|
|
||||||
assert_eq!(stack.pop_n(1).collect::<Vec<_>>(), &[6]);
|
assert_eq!(stack.pop(1), Some(vec![6]));
|
||||||
assert_eq!(stack.pop_n(2).collect::<Vec<_>>(), &[5, 4]);
|
assert_eq!(stack.pop(2), Some(vec![5, 4]));
|
||||||
assert_eq!(stack.pop_n(3).collect::<Vec<_>>(), &[3, 2, 1]);
|
assert_eq!(stack.pop(3), Some(vec![3, 2, 1]));
|
||||||
assert_eq!(stack.is_empty(), true);
|
assert_eq!(stack.is_empty(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user