1
0
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:
Ivan Enderlin 2019-09-19 23:05:17 +02:00
parent 2f3c37fbd5
commit c63345029e
2 changed files with 95 additions and 34 deletions
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);
}
}