add dup and swap2 instructions

This commit is contained in:
vms 2020-06-01 14:06:00 +03:00
parent c2f2a23c38
commit 52c28b80bc
10 changed files with 81 additions and 2 deletions

4
.gitignore vendored
View File

@ -1 +1,3 @@
/target
.idea
/target

View File

@ -256,6 +256,10 @@ fn instruction<'input, E: ParseError<&'input [u8]>>(
)
}
0x34 => (input, Instruction::Dup),
0x35 => (input, Instruction::Swap2),
_ => return Err(Err::Error(make_error(input, ErrorKind::ParseTo))),
})
}

View File

@ -67,6 +67,8 @@ mod keyword {
custom_keyword!(string_size = "string.size");
custom_keyword!(record_lift = "record.lift");
custom_keyword!(record_lower = "record.lower");
custom_keyword!(dup = "dup");
custom_keyword!(swap2 = "swap2");
}
impl Parse<'_> for InterfaceType {
@ -326,6 +328,14 @@ impl<'a> Parse<'a> for Instruction {
Ok(Instruction::RecordLower {
type_index: parser.parse()?,
})
} else if lookahead.peek::<keyword::dup>() {
parser.parse::<keyword::dup>()?;
Ok(Instruction::Dup)
} else if lookahead.peek::<keyword::swap2>() {
parser.parse::<keyword::swap2>()?;
Ok(Instruction::Swap2)
} else {
Err(lookahead.error())
}

View File

@ -342,6 +342,8 @@ where
0x26_u8.to_bytes(writer)?;
(*type_index as u64).to_bytes(writer)?
}
Instruction::Dup => 0x34_u8.to_bytes(writer)?,
Instruction::Swap2 => 0x35_u8.to_bytes(writer)?,
}
Ok(())

View File

@ -140,6 +140,8 @@ impl ToString for &Instruction {
Instruction::StringSize => "string.size".into(),
Instruction::RecordLift { type_index } => format!("record.lift {}", type_index),
Instruction::RecordLower { type_index } => format!("record.lower {}", type_index),
Instruction::Dup => "dup".into(),
Instruction::Swap2 => "swap2".into(),
}
}
}

View File

@ -54,6 +54,8 @@ executable_instruction!(
)
})?;
for output in outputs.into_iter() {
runtime.stack.push(output)
}

View File

@ -0,0 +1,22 @@
use crate::{
errors::{InstructionError, InstructionErrorKind},
interpreter::Instruction,
};
executable_instruction!(
dup(instruction: Instruction) -> _ {
move |runtime| -> _ {
let value = runtime.stack.peek1().ok_or_else(|| {
InstructionError::new(
instruction,
InstructionErrorKind::StackIsTooSmall { needed: 1 },
)
})?;
let value = value.clone();
runtime.stack.push(value);
Ok(())
}
}
);

View File

@ -3,6 +3,8 @@ mod call_core;
mod numbers;
mod records;
mod strings;
mod dup;
mod swap2;
use crate::{
errors::{InstructionError, InstructionErrorKind, InstructionResult, WasmValueNativeCastError},
@ -14,6 +16,8 @@ pub(crate) use numbers::*;
pub(crate) use records::*;
use std::convert::TryFrom;
pub(crate) use strings::*;
pub(crate) use dup::dup;
pub(crate) use swap2::swap2;
/// Represents all the possible WIT instructions.
#[derive(PartialEq, Debug, Clone, Copy)]
@ -146,6 +150,12 @@ pub enum Instruction {
/// The type index of the record.
type_index: u32,
},
/// The `dup` instructions.
Dup,
/// The `swap` instructions.
Swap2,
}
/// Just a short helper to map the error of a cast from an

View File

@ -0,0 +1,22 @@
use crate::{
errors::{InstructionError, InstructionErrorKind},
interpreter::Instruction,
};
executable_instruction!(
swap2(instruction: Instruction) -> _ {
move |runtime| -> _ {
let mut values = runtime.stack.pop(2).ok_or_else(|| {
InstructionError::new(
instruction,
InstructionErrorKind::StackIsTooSmall { needed: 1 },
)
})?;
runtime.stack.push(values.remove(1));
runtime.stack.push(values.remove(0));
Ok(())
}
}
);

View File

@ -162,6 +162,7 @@ where
invocation_inputs: &[InterfaceValue],
wasm_instance: &mut Instance,
) -> InterpreterResult<Stack<InterfaceValue>> {
println!("into interpreter run");
let mut runtime = Runtime {
invocation_inputs,
stack: Stack::new(),
@ -243,7 +244,9 @@ where
}
Instruction::RecordLower { type_index } => {
instructions::record_lower(*type_index, *instruction)
}
},
Instruction::Dup => instructions::dup(*instruction),
Instruction::Swap2 => instructions::swap2(*instruction),
})
.collect();