mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-01 23:41:03 +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;
|
use std::str;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
@ -21,30 +22,6 @@ pub(crate) enum AdapterKind {
|
|||||||
HelperFunction,
|
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)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub struct Export<'input> {
|
pub struct Export<'input> {
|
||||||
pub name: &'input str,
|
pub name: &'input str,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::ast::*;
|
use crate::{ast::*, instructions::Instruction};
|
||||||
use nom::{
|
use nom::{
|
||||||
error::{make_error, ErrorKind, ParseError},
|
error::{make_error, ErrorKind, ParseError},
|
||||||
Err, IResult,
|
Err, IResult,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::ast::{
|
use crate::{
|
||||||
Adapter, Export, Forward, ImportedFunction, Instruction, InterfaceType, Interfaces, Type,
|
ast::{Adapter, Export, Forward, ImportedFunction, InterfaceType, Interfaces, Type},
|
||||||
|
instructions::Instruction,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl From<&InterfaceType> for String {
|
impl From<&InterfaceType> for String {
|
||||||
@ -267,7 +268,7 @@ impl<'input> From<&Interfaces<'input>> for String {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::ast::*;
|
use crate::{ast::*, instructions::Instruction};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_interface_types() {
|
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;
|
mod macros;
|
||||||
pub mod decoders;
|
pub mod decoders;
|
||||||
pub mod encoders;
|
pub mod encoders;
|
||||||
|
pub mod instructions;
|
||||||
|
|
||||||
pub use decoders::binary::parse as parse_binary;
|
pub use decoders::binary::parse as parse_binary;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{ast::*, encoders::wat::*, parse_binary};
|
use crate::{ast::*, encoders::wat::*, instructions::Instruction, parse_binary};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use wasmer_clif_backend::CraneliftCompiler;
|
use wasmer_clif_backend::CraneliftCompiler;
|
||||||
use wasmer_runtime_core as runtime;
|
use wasmer_runtime_core as runtime;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user