mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-18 17:10:52 +00:00
feat(interface-types) Draft instruction interpreter.
This commit is contained in:
parent
fc9389d932
commit
dc3c72ea19
@ -1,3 +1,4 @@
|
||||
use crate::instructions::Instruction;
|
||||
use std::str;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
@ -21,30 +22,6 @@ pub(crate) enum AdapterKind {
|
||||
HelperFunction,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum Instruction<'input> {
|
||||
ArgumentGet(u64),
|
||||
Call(u64),
|
||||
CallExport(&'input str),
|
||||
ReadUtf8,
|
||||
WriteUtf8(&'input str),
|
||||
AsWasm(InterfaceType),
|
||||
AsInterface(InterfaceType),
|
||||
TableRefAdd,
|
||||
TableRefGet,
|
||||
CallMethod(u64),
|
||||
MakeRecord(InterfaceType),
|
||||
GetField(InterfaceType, u64),
|
||||
Const(InterfaceType, u64),
|
||||
FoldSeq(u64),
|
||||
Add(InterfaceType),
|
||||
MemToSeq(InterfaceType, &'input str),
|
||||
Load(InterfaceType, &'input str),
|
||||
SeqNew(InterfaceType),
|
||||
ListPush,
|
||||
RepeatWhile(u64, u64),
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct Export<'input> {
|
||||
pub name: &'input str,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::ast::*;
|
||||
use crate::{ast::*, instructions::Instruction};
|
||||
use nom::{
|
||||
error::{make_error, ErrorKind, ParseError},
|
||||
Err, IResult,
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::ast::{
|
||||
Adapter, Export, Forward, ImportedFunction, Instruction, InterfaceType, Interfaces, Type,
|
||||
use crate::{
|
||||
ast::{Adapter, Export, Forward, ImportedFunction, InterfaceType, Interfaces, Type},
|
||||
instructions::Instruction,
|
||||
};
|
||||
|
||||
impl From<&InterfaceType> for String {
|
||||
@ -267,7 +268,7 @@ impl<'input> From<&Interfaces<'input>> for String {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ast::*;
|
||||
use crate::{ast::*, instructions::Instruction};
|
||||
|
||||
#[test]
|
||||
fn test_interface_types() {
|
||||
|
83
lib/interface-types/src/instructions/interpreter.rs
Normal file
83
lib/interface-types/src/instructions/interpreter.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use crate::instructions::{stack::Stack, Instruction};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
type ExecutableInstruction = dyn Fn(&mut Stack);
|
||||
//trait ExecutableInstruction: Fn(&mut Stack) {}
|
||||
|
||||
pub(crate) struct Interpreter {
|
||||
stack: Stack,
|
||||
instructions: Vec<Box<dyn Fn(&mut Stack) + 'static>>,
|
||||
}
|
||||
|
||||
impl Interpreter {
|
||||
pub(crate) fn is_eos(&self) -> bool {
|
||||
self.stack.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'binary_input> TryFrom<&Vec<Instruction<'binary_input>>> for Interpreter {
|
||||
type Error = &'static str;
|
||||
|
||||
fn try_from(instructions: &Vec<Instruction>) -> Result<Self, Self::Error> {
|
||||
let executable_instructions = instructions
|
||||
.iter()
|
||||
.map(|instruction| -> Box<dyn Fn(&mut Stack) + 'static> {
|
||||
match instruction {
|
||||
Instruction::ArgumentGet(index) => {
|
||||
let index = index.to_owned();
|
||||
|
||||
Box::new(move |stack: &mut Stack| {
|
||||
println!("argument get {}", index);
|
||||
})
|
||||
}
|
||||
Instruction::CallExport(export_name) => {
|
||||
let export_name = (*export_name).to_owned();
|
||||
|
||||
Box::new(move |stack: &mut Stack| {
|
||||
println!("call export {}", export_name);
|
||||
})
|
||||
}
|
||||
Instruction::ReadUtf8 => Box::new(|stack: &mut Stack| {
|
||||
println!("read utf8");
|
||||
}),
|
||||
Instruction::Call(index) => {
|
||||
let index = index.to_owned();
|
||||
|
||||
Box::new(move |stack: &mut Stack| {
|
||||
println!("call {}", index);
|
||||
})
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok(Interpreter {
|
||||
stack: Stack::new(),
|
||||
instructions: executable_instructions,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Interpreter;
|
||||
use crate::instructions::Instruction;
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[test]
|
||||
fn test_interpreter_from_instructions() {
|
||||
let instructions = vec![
|
||||
Instruction::ArgumentGet(0),
|
||||
Instruction::ArgumentGet(0),
|
||||
Instruction::CallExport("strlen"),
|
||||
Instruction::ReadUtf8,
|
||||
Instruction::Call(7),
|
||||
];
|
||||
let interpreter: Result<Interpreter, _> = (&instructions).try_into();
|
||||
assert!(interpreter.is_ok());
|
||||
|
||||
let interpreter = interpreter.unwrap();
|
||||
assert_eq!(interpreter.is_eos(), true);
|
||||
}
|
||||
}
|
28
lib/interface-types/src/instructions/mod.rs
Normal file
28
lib/interface-types/src/instructions/mod.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use crate::ast::InterfaceType;
|
||||
|
||||
pub mod interpreter;
|
||||
mod stack;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum Instruction<'input> {
|
||||
ArgumentGet(u64),
|
||||
Call(u64),
|
||||
CallExport(&'input str),
|
||||
ReadUtf8,
|
||||
WriteUtf8(&'input str),
|
||||
AsWasm(InterfaceType),
|
||||
AsInterface(InterfaceType),
|
||||
TableRefAdd,
|
||||
TableRefGet,
|
||||
CallMethod(u64),
|
||||
MakeRecord(InterfaceType),
|
||||
GetField(InterfaceType, u64),
|
||||
Const(InterfaceType, u64),
|
||||
FoldSeq(u64),
|
||||
Add(InterfaceType),
|
||||
MemToSeq(InterfaceType, &'input str),
|
||||
Load(InterfaceType, &'input str),
|
||||
SeqNew(InterfaceType),
|
||||
ListPush,
|
||||
RepeatWhile(u64, u64),
|
||||
}
|
66
lib/interface-types/src/instructions/stack.rs
Normal file
66
lib/interface-types/src/instructions/stack.rs
Normal file
@ -0,0 +1,66 @@
|
||||
use std::{iter::Rev, vec::Drain};
|
||||
|
||||
pub(super) struct Stack {
|
||||
inner: Vec<u32>,
|
||||
}
|
||||
|
||||
impl Stack {
|
||||
pub(super) fn new() -> Self {
|
||||
Self { inner: Vec::new() }
|
||||
}
|
||||
|
||||
pub(super) fn is_empty(&self) -> bool {
|
||||
self.inner.is_empty()
|
||||
}
|
||||
|
||||
pub(super) fn push(&mut self, item: u32) {
|
||||
self.inner.push(item);
|
||||
}
|
||||
|
||||
pub(super) fn pop(&mut self) -> Option<u32> {
|
||||
self.inner.pop()
|
||||
}
|
||||
|
||||
pub(super) fn pop_n(&mut self, n: usize) -> Rev<Drain<u32>> {
|
||||
self.inner.drain(self.inner.len() - n..).rev()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Stack;
|
||||
|
||||
#[test]
|
||||
fn test_is_empty() {
|
||||
let mut stack = Stack::new();
|
||||
assert_eq!(stack.is_empty(), true);
|
||||
|
||||
stack.push(1);
|
||||
assert_eq!(stack.is_empty(), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_push_pop() {
|
||||
let mut stack = Stack::new();
|
||||
stack.push(1);
|
||||
|
||||
assert_eq!(stack.pop(), Some(1));
|
||||
assert_eq!(stack.is_empty(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pop_n() {
|
||||
let mut stack = Stack::new();
|
||||
stack.push(1);
|
||||
stack.push(2);
|
||||
stack.push(3);
|
||||
stack.push(4);
|
||||
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.is_empty(), true);
|
||||
}
|
||||
}
|
@ -3,12 +3,13 @@ pub mod ast;
|
||||
mod macros;
|
||||
pub mod decoders;
|
||||
pub mod encoders;
|
||||
pub mod instructions;
|
||||
|
||||
pub use decoders::binary::parse as parse_binary;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{ast::*, encoders::wat::*, parse_binary};
|
||||
use crate::{ast::*, encoders::wat::*, instructions::Instruction, parse_binary};
|
||||
use std::fs;
|
||||
use wasmer_clif_backend::CraneliftCompiler;
|
||||
use wasmer_runtime_core as runtime;
|
||||
|
Loading…
x
Reference in New Issue
Block a user