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