diff --git a/.gitignore b/.gitignore index c41cc9e..643d32d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -/target \ No newline at end of file +.idea +/target + diff --git a/src/decoders/binary.rs b/src/decoders/binary.rs index 54dc1e1..e8b18c4 100644 --- a/src/decoders/binary.rs +++ b/src/decoders/binary.rs @@ -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))), }) } diff --git a/src/decoders/wat.rs b/src/decoders/wat.rs index 292a8f5..57edcb3 100644 --- a/src/decoders/wat.rs +++ b/src/decoders/wat.rs @@ -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::() { + parser.parse::()?; + + Ok(Instruction::Dup) + } else if lookahead.peek::() { + parser.parse::()?; + + Ok(Instruction::Swap2) } else { Err(lookahead.error()) } diff --git a/src/encoders/binary.rs b/src/encoders/binary.rs index 77cd98a..38eaef3 100644 --- a/src/encoders/binary.rs +++ b/src/encoders/binary.rs @@ -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(()) diff --git a/src/encoders/wat.rs b/src/encoders/wat.rs index b4b1fe1..e3feaff 100644 --- a/src/encoders/wat.rs +++ b/src/encoders/wat.rs @@ -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(), } } } diff --git a/src/interpreter/instructions/call_core.rs b/src/interpreter/instructions/call_core.rs index fb72b33..731f844 100644 --- a/src/interpreter/instructions/call_core.rs +++ b/src/interpreter/instructions/call_core.rs @@ -54,6 +54,8 @@ executable_instruction!( ) })?; + + for output in outputs.into_iter() { runtime.stack.push(output) } diff --git a/src/interpreter/instructions/dup.rs b/src/interpreter/instructions/dup.rs new file mode 100644 index 0000000..f6c6c42 --- /dev/null +++ b/src/interpreter/instructions/dup.rs @@ -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(()) + } + } +); diff --git a/src/interpreter/instructions/mod.rs b/src/interpreter/instructions/mod.rs index cddc165..1ce533d 100644 --- a/src/interpreter/instructions/mod.rs +++ b/src/interpreter/instructions/mod.rs @@ -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 diff --git a/src/interpreter/instructions/swap2.rs b/src/interpreter/instructions/swap2.rs new file mode 100644 index 0000000..5e465b4 --- /dev/null +++ b/src/interpreter/instructions/swap2.rs @@ -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(()) + } + } +); diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index e7d93ce..8aa21f2 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -162,6 +162,7 @@ where invocation_inputs: &[InterfaceValue], wasm_instance: &mut Instance, ) -> InterpreterResult> { + 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();