update types

This commit is contained in:
vms 2020-08-18 03:48:10 +03:00
parent 8a18ba607f
commit e28914ae01
8 changed files with 111 additions and 131 deletions

View File

@ -285,29 +285,28 @@ fn instruction<'input, E: ParseError<&'input [u8]>>(
0x38 => (input, Instruction::ByteArrayLowerMemory),
0x39 => (input, Instruction::ByteArraySize),
/*
0x25 => {
consume!((input, argument_0) = uleb(input)?);
/*
0x25 => {
consume!((input, argument_0) = uleb(input)?);
(
input,
Instruction::RecordLift {
type_index: argument_0 as u32,
},
)
}
0x26 => {
consume!((input, argument_0) = uleb(input)?);
(
input,
Instruction::RecordLower {
type_index: argument_0 as u32,
},
)
}
*/
(
input,
Instruction::RecordLift {
type_index: argument_0 as u32,
},
)
}
0x26 => {
consume!((input, argument_0) = uleb(input)?);
(
input,
Instruction::RecordLower {
type_index: argument_0 as u32,
},
)
}
*/
0x3A => {
consume!((input, argument_0) = uleb(input)?);

View File

@ -178,6 +178,7 @@ impl Parse<'_> for RecordType {
}
}
#[allow(clippy::suspicious_else_formatting)]
impl<'a> Parse<'a> for Instruction {
#[allow(clippy::cognitive_complexity)]
fn parse(parser: Parser<'a>) -> Result<Self> {
@ -348,7 +349,7 @@ impl<'a> Parse<'a> for Instruction {
Ok(Instruction::ByteArraySize)
}
/*
/*
else if lookahead.peek::<keyword::record_lift>() {
parser.parse::<keyword::record_lift>()?;
@ -363,7 +364,7 @@ impl<'a> Parse<'a> for Instruction {
})
}
*/
else if lookahead.peek::<keyword::record_lift_memory>() {
else if lookahead.peek::<keyword::record_lift_memory>() {
parser.parse::<keyword::record_lift_memory>()?;
Ok(Instruction::RecordLiftMemory {

View File

@ -170,6 +170,9 @@ pub enum InstructionErrorKind {
type_name: String,
},
/// Corrupted record's been popped from the stack.
CorruptedRecord(String),
/// Read a type that has an unexpected type.
InvalidTypeKind {
/// The expected kind.
@ -274,6 +277,13 @@ impl Display for InstructionErrorKind {
"type with `{}` is missing in a Wasm binary",
type_name
),
Self::CorruptedRecord(err) => write!(
formatter,
"{}",
err
),
Self::SerdeError(err) => write!(
formatter,
"serde error: {}", err,

View File

@ -8,7 +8,8 @@ mod strings;
mod swap2;
use crate::interpreter::wasm;
use crate::types::InterfaceType;
use crate::types::{InterfaceType, RecordType};
use crate::vec1::Vec1;
use crate::{
errors::{InstructionError, InstructionErrorKind, InstructionResult, WasmValueNativeCastError},
values::{InterfaceValue, NativeType},
@ -169,7 +170,6 @@ pub enum Instruction {
},
*/
/// The `record.lift_memory` instruction.
RecordLiftMemory {
/// The type index of the record.
@ -277,26 +277,7 @@ where
)
})?;
if record_fields.len() != record_type.fields.len() {
return Err(InstructionError::new(
instruction,
InstructionErrorKind::InvalidValueOnTheStack {
expected_type: interface_type.clone(),
received_value: interface_value.clone(),
},
));
}
for (record_type_field, record_value_field) in
record_type.fields.iter().zip(record_fields.iter())
{
is_value_compatible_to_type(
instance,
&record_type_field.ty,
record_value_field,
instruction,
)?;
}
is_record_fields_compatible_to_type(instance, record_type, record_fields, instruction)?;
Ok(())
}
@ -310,6 +291,58 @@ where
}
}
pub(crate) fn is_record_fields_compatible_to_type<
'instance,
Instance,
Export,
LocalImport,
Memory,
MemoryView,
>(
instance: &'instance Instance,
record_type: &RecordType,
record_fields: &[InterfaceValue],
instruction: Instruction,
) -> Result<(), InstructionError>
where
Export: wasm::structures::Export + 'instance,
LocalImport: wasm::structures::LocalImport + 'instance,
Memory: wasm::structures::Memory<MemoryView> + 'instance,
MemoryView: wasm::structures::MemoryView,
Instance: wasm::structures::Instance<Export, LocalImport, Memory, MemoryView>,
{
if record_fields.is_empty() {
return Err(InstructionError::new(
instruction,
InstructionErrorKind::CorruptedRecord(String::from("record contains no fields")),
));
}
if record_fields.len() != record_type.fields.len() {
return Err(InstructionError::new(
instruction,
InstructionErrorKind::InvalidValueOnTheStack {
expected_type: InterfaceType::Record(record_type.name.clone()),
// unwrap is safe here - len's been already checked
received_value: InterfaceValue::Record(Vec1::new(record_fields.to_vec()).unwrap()),
},
));
}
for (record_type_field, record_value_field) in
record_type.fields.iter().zip(record_fields.iter())
{
is_value_compatible_to_type(
instance,
&record_type_field.ty,
record_value_field,
instruction,
)?;
}
Ok(())
}
#[cfg(test)]
pub(crate) mod tests {
use crate::{ast::*, interpreter::wasm, types::*, values::*};

View File

@ -3,11 +3,8 @@ mod utils;
use utils::read_from_instance_mem;
use utils::write_to_instance_mem;
// use crate::interpreter::wasm;
use crate::interpreter::instructions::to_native;
use crate::interpreter::instructions::{is_record_fields_compatible_to_type, to_native};
use crate::{
ast::{Type, TypeKind},
errors::{InstructionError, InstructionErrorKind},
interpreter::Instruction,
types::{InterfaceType, RecordType},
@ -287,25 +284,14 @@ where
// TODO: size = 0
let instance = &runtime.wasm_instance;
let record_type = match instance.wit_type_by_id(type_index).ok_or_else(|| {
let record_type = instance.wit_record_by_id(type_index).ok_or_else(|| {
InstructionError::new(
instruction,
InstructionErrorKind::TypeIsMissing { type_index },
)
})? {
Type::Record(record_type) => record_type.clone(),
Type::Function { .. } => {
return Err(InstructionError::new(
instruction,
InstructionErrorKind::InvalidTypeKind {
expected_kind: TypeKind::Record,
received_kind: TypeKind::Function,
},
))
}
};
})?;
let record = record_lift_memory_(&**instance, &record_type, offset, instruction)?;
let record = record_lift_memory_(&**instance, record_type, offset, instruction)?;
runtime.stack.push(record);
Ok(())
@ -395,40 +381,22 @@ where
Box::new({
move |runtime| -> _ {
let instance = &mut runtime.wasm_instance;
let record_type = match instance.wit_type_by_id(type_index).ok_or_else(|| {
let record_type = instance.wit_record_by_id(type_index).ok_or_else(|| {
InstructionError::new(
instruction,
InstructionErrorKind::TypeIsMissing { type_index },
)
})? {
Type::Record(record_type) => record_type,
Type::Function { .. } => {
return Err(InstructionError::new(
instruction,
InstructionErrorKind::InvalidTypeKind {
expected_kind: TypeKind::Record,
received_kind: TypeKind::Function,
},
))
}
};
})?;
match runtime.stack.pop1() {
Some(InterfaceValue::Record(record_values)) => {
/*
let value: Vec<u8> = crate::serde::de::from_interface_values(&record_values)
.map_err(|e| {
InstructionError::new(
instruction,
InstructionErrorKind::SerdeError(e.to_string()),
)
})?;
let value_pointer = write_to_instance_mem(*instance, instruction, &value)?;
runtime.stack.push(InterfaceValue::I32(value_pointer));
runtime.stack.push(InterfaceValue::I32(value.len() as _));
*/
let offset = record_lower_memory_(*instance, instruction, record_values)?;
Some(InterfaceValue::Record(record_fields)) => {
is_record_fields_compatible_to_type(
&**instance,
record_type,
&record_fields,
instruction,
)?;
let offset = record_lower_memory_(*instance, instruction, record_fields)?;
runtime.stack.push(InterfaceValue::I32(offset));
Ok(())

View File

@ -148,7 +148,12 @@ where
)
})?;
crate::interpreter::instructions::check_function_signature(instance, local_or_import, &inputs, instruction)?;
crate::interpreter::instructions::check_function_signature(
instance,
local_or_import,
&inputs,
instruction,
)?;
let outputs = local_or_import.call(&inputs).map_err(|_| {
InstructionError::new(

View File

@ -1,7 +1,7 @@
#![allow(missing_docs)]
use crate::types::RecordType;
use crate::{ast, types::InterfaceType, values::InterfaceValue};
use crate::{types::InterfaceType, values::InterfaceValue};
use std::{cell::Cell, ops::Deref};
pub trait TypedIndex: Copy + Clone {
@ -75,7 +75,7 @@ where
fn export(&self, export_name: &str) -> Option<&E>;
fn local_or_import<I: TypedIndex + LocalImportIndex>(&self, index: I) -> Option<&LI>;
fn memory(&self, index: usize) -> Option<&M>;
fn wit_type_by_id(&self, index: u32) -> Option<&ast::Type>;
fn wit_record_by_id(&self, index: u32) -> Option<&RecordType>;
fn wit_record_by_name(&self, name: &str) -> Option<&RecordType>;
}
@ -160,7 +160,7 @@ where
None
}
fn wit_type_by_id(&self, _index: u32) -> Option<&ast::Type> {
fn wit_record_by_id(&self, _index: u32) -> Option<&RecordType> {
None
}

View File

@ -56,48 +56,12 @@ pub enum InterfaceValue {
Record(Vec1<InterfaceValue>),
}
/*
impl From<&InterfaceValue> for InterfaceType {
fn from(value: &InterfaceValue) -> Self {
match value {
InterfaceValue::S8(_) => Self::S8,
InterfaceValue::S16(_) => Self::S16,
InterfaceValue::S32(_) => Self::S32,
InterfaceValue::S64(_) => Self::S64,
InterfaceValue::U8(_) => Self::U8,
InterfaceValue::U16(_) => Self::U16,
InterfaceValue::U32(_) => Self::U32,
InterfaceValue::U64(_) => Self::U64,
InterfaceValue::F32(_) => Self::F32,
InterfaceValue::F64(_) => Self::F64,
InterfaceValue::String(_) => Self::String,
InterfaceValue::ByteArray(_) => Self::ByteArray,
//InterfaceValue::Anyref(_) => Self::Anyref,
InterfaceValue::I32(_) => Self::I32,
InterfaceValue::I64(_) => Self::I64,
InterfaceValue::Record(name) => Self::Record(name.to_owned()),
}
}
}
*/
impl Default for InterfaceValue {
fn default() -> Self {
Self::I32(0)
}
}
/*
impl From<&Vec<InterfaceValue>> for RecordType {
fn from(values: &Vec<InterfaceValue>) -> Self {
RecordType {
fields: Vec1::new(values.iter().map(Into::into).collect())
.expect("Record must have at least one field, zero given."),
}
}
}
*/
/// Represents a native type supported by WIT.
pub trait NativeType {
/// The associated interface type that maps to the native type.