mirror of
https://github.com/fluencelabs/interface-types
synced 2024-12-04 15:20:20 +00:00
commute arg name and type to one struct
This commit is contained in:
parent
e28914ae01
commit
37458bc559
21
src/ast.rs
21
src/ast.rs
@ -17,6 +17,16 @@ pub enum TypeKind {
|
||||
Record,
|
||||
}
|
||||
|
||||
/// Represents the function argument type.
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub struct FunctionArg {
|
||||
/// A function argument name.
|
||||
pub name: String,
|
||||
|
||||
/// A function argument type.
|
||||
pub ty: InterfaceType,
|
||||
}
|
||||
|
||||
/// Represents a type.
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub enum Type {
|
||||
@ -26,15 +36,8 @@ pub enum Type {
|
||||
/// (@interface type (func (param i32 i32) (result string)))
|
||||
/// ```
|
||||
Function {
|
||||
/// Name of a function.
|
||||
name: String,
|
||||
|
||||
/// Types for the parameters (`(param …)`).
|
||||
arg_types: Vec<InterfaceType>,
|
||||
|
||||
/// Name of function argument types.
|
||||
// TODO: introduce a struct combines name and type of a field
|
||||
arg_names: Vec<String>,
|
||||
/// Types for the parameters (`(param (name i32))`).
|
||||
arguments: Vec<FunctionArg>,
|
||||
|
||||
/// Types for the results (`(result …)`).
|
||||
output_types: Vec<InterfaceType>,
|
||||
|
@ -77,16 +77,23 @@ fn record_field<'input, E: ParseError<&'input [u8]>>(
|
||||
return Err(Err::Error(make_error(input, ErrorKind::Eof)));
|
||||
}
|
||||
|
||||
consume!((input, name) = string(input)?);
|
||||
consume!((input, name) = owned_string(input)?);
|
||||
consume!((input, ty) = ty(input)?);
|
||||
|
||||
Ok((
|
||||
input,
|
||||
RecordFieldType {
|
||||
name: name.to_owned(),
|
||||
ty,
|
||||
},
|
||||
))
|
||||
Ok((input, RecordFieldType { name, ty }))
|
||||
}
|
||||
|
||||
fn function_arg<'input, E: ParseError<&'input [u8]>>(
|
||||
mut input: &'input [u8],
|
||||
) -> IResult<&'input [u8], FunctionArg, E> {
|
||||
if input.is_empty() {
|
||||
return Err(Err::Error(make_error(input, ErrorKind::Eof)));
|
||||
}
|
||||
|
||||
consume!((input, name) = owned_string(input)?);
|
||||
consume!((input, ty) = ty(input)?);
|
||||
|
||||
Ok((input, FunctionArg { name, ty }))
|
||||
}
|
||||
|
||||
/// Parse an interface type.
|
||||
@ -116,9 +123,9 @@ fn ty<'input, E: ParseError<&'input [u8]>>(
|
||||
0x0c => InterfaceType::I32,
|
||||
0x0d => InterfaceType::I64,
|
||||
0x0e => {
|
||||
consume!((input, record_name) = string(input)?);
|
||||
consume!((input, record_name) = owned_string(input)?);
|
||||
|
||||
InterfaceType::Record(record_name.to_owned())
|
||||
InterfaceType::Record(record_name)
|
||||
}
|
||||
_ => return Err(Err::Error(make_error(input, ErrorKind::ParseTo))),
|
||||
};
|
||||
@ -132,13 +139,13 @@ fn record_type<'input, E: ParseError<&'input [u8]>>(
|
||||
) -> IResult<&'input [u8], RecordType, E> {
|
||||
use crate::vec1::Vec1;
|
||||
|
||||
let (output, name) = string(input)?;
|
||||
let (output, name) = owned_string(input)?;
|
||||
let (output, fields) = list(output, record_field)?;
|
||||
|
||||
Ok((
|
||||
output,
|
||||
RecordType {
|
||||
name: name.to_owned(),
|
||||
name,
|
||||
fields: Vec1::new(fields).expect("Record must have at least one field, zero given."),
|
||||
},
|
||||
))
|
||||
@ -352,15 +359,11 @@ fn types<'input, E: ParseError<&'input [u8]>>(
|
||||
|
||||
match type_kind {
|
||||
TypeKind::Function => {
|
||||
consume!((input, name) = string(input)?);
|
||||
consume!((input, arg_types) = list(input, ty)?);
|
||||
consume!((input, arg_names) = list(input, owned_string)?);
|
||||
consume!((input, arguments) = list(input, function_arg)?);
|
||||
consume!((input, output_types) = list(input, ty)?);
|
||||
|
||||
types.push(Type::Function {
|
||||
name: String::from(name),
|
||||
arg_types,
|
||||
arg_names,
|
||||
arguments,
|
||||
output_types,
|
||||
});
|
||||
}
|
||||
|
@ -416,7 +416,7 @@ impl Parse<'_> for AtInterface {
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
enum FunctionType {
|
||||
Header(String, Vec<String>, Vec<InterfaceType>),
|
||||
Header(Vec<FunctionArg>),
|
||||
Output(Vec<InterfaceType>),
|
||||
}
|
||||
|
||||
@ -427,17 +427,19 @@ impl Parse<'_> for FunctionType {
|
||||
|
||||
if lookahead.peek::<keyword::param>() {
|
||||
parser.parse::<keyword::param>()?;
|
||||
let func_name = parser.parse()?;
|
||||
|
||||
let mut names = vec![];
|
||||
let mut types = vec![];
|
||||
let mut arguments = vec![];
|
||||
|
||||
while !parser.is_empty() {
|
||||
names.push(parser.parse()?);
|
||||
types.push(parser.parse()?);
|
||||
let arg_name: String = parser.parse()?;
|
||||
let arg_type: InterfaceType = parser.parse()?;
|
||||
arguments.push(FunctionArg {
|
||||
name: arg_name,
|
||||
ty: arg_type,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(FunctionType::Header(func_name, names, types))
|
||||
Ok(FunctionType::Header(arguments))
|
||||
} else if lookahead.peek::<keyword::result>() {
|
||||
parser.parse::<keyword::result>()?;
|
||||
|
||||
@ -504,38 +506,22 @@ impl<'a> Parse<'a> for Type {
|
||||
if lookahead.peek::<keyword::func>() {
|
||||
parser.parse::<keyword::func>()?;
|
||||
|
||||
let mut arg_types = vec![];
|
||||
let mut arg_names = vec![];
|
||||
let mut arguments = vec![];
|
||||
let mut output_types = vec![];
|
||||
let mut name: Option<String> = None;
|
||||
|
||||
while !parser.is_empty() {
|
||||
let function_type = parser.parse::<FunctionType>()?;
|
||||
|
||||
match function_type {
|
||||
FunctionType::Header(func_name, mut names, mut types) => {
|
||||
name = Some(func_name);
|
||||
arg_names.append(&mut names);
|
||||
arg_types.append(&mut types);
|
||||
},
|
||||
FunctionType::Header(mut func_arguments) => {
|
||||
arguments.append(&mut func_arguments);
|
||||
}
|
||||
FunctionType::Output(mut outputs) => output_types.append(&mut outputs),
|
||||
}
|
||||
}
|
||||
|
||||
if name.is_none() {
|
||||
return Err(parser.error("Malformed wast: function doesn't contain name"));
|
||||
}
|
||||
|
||||
if arg_types.len() != arg_names.len() {
|
||||
return Err(parser.error("Malformed wast: function argument types count should be equal to argument names count"));
|
||||
}
|
||||
|
||||
// It's has been already checked for None.
|
||||
let name = name.unwrap();
|
||||
Ok(Type::Function {
|
||||
name,
|
||||
arg_types,
|
||||
arg_names,
|
||||
arguments,
|
||||
output_types,
|
||||
})
|
||||
} else if lookahead.peek::<keyword::record>() {
|
||||
|
@ -186,6 +186,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> ToBytes<W> for FunctionArg
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
self.name.to_bytes(writer)?;
|
||||
self.ty.to_bytes(writer)
|
||||
}
|
||||
}
|
||||
|
||||
/// Encode a `Type` into bytes.
|
||||
///
|
||||
/// Decoder is in `decoders::binary::types`.
|
||||
@ -196,15 +206,11 @@ where
|
||||
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
|
||||
match self {
|
||||
Type::Function {
|
||||
name,
|
||||
arg_types,
|
||||
arg_names,
|
||||
arguments,
|
||||
output_types,
|
||||
} => {
|
||||
TypeKind::Function.to_bytes(writer)?;
|
||||
name.to_bytes(writer)?;
|
||||
arg_types.to_bytes(writer)?;
|
||||
arg_names.to_bytes(writer)?;
|
||||
arguments.to_bytes(writer)?;
|
||||
output_types.to_bytes(writer)?;
|
||||
}
|
||||
|
||||
|
@ -165,16 +165,16 @@ impl ToString for &Instruction {
|
||||
|
||||
/// Encode a list of `InterfaceType` representing inputs into a
|
||||
/// string.
|
||||
fn encode_arguments(arg_types: &[InterfaceType], arg_names: &[String]) -> String {
|
||||
fn encode_function_arguments(arguments: &[FunctionArg]) -> String {
|
||||
// here we know that arg_names and arg_types have the same length
|
||||
if arg_names.is_empty() {
|
||||
if arguments.is_empty() {
|
||||
String::from("")
|
||||
} else {
|
||||
format!(
|
||||
"\n (param{})",
|
||||
arg_names.iter().zip(arg_types.iter()).fold(
|
||||
arguments.iter().fold(
|
||||
String::new(),
|
||||
|mut accumulator, (name, ty)| {
|
||||
|mut accumulator, FunctionArg { name, ty }| {
|
||||
accumulator.push(' ');
|
||||
accumulator.push_str(name);
|
||||
accumulator.push_str(": ");
|
||||
@ -210,14 +210,11 @@ impl<'input> ToString for &Type {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
Type::Function {
|
||||
name,
|
||||
arg_types,
|
||||
arg_names,
|
||||
arguments,
|
||||
output_types,
|
||||
} => format!(
|
||||
r#"(@interface type (func {name} {args}{output_types}))"#,
|
||||
name = name,
|
||||
args = encode_arguments(arg_types, arg_names),
|
||||
r#"(@interface type (func {args} {output_types}))"#,
|
||||
args = encode_function_arguments(arguments),
|
||||
output_types = output_types_to_result(&output_types),
|
||||
),
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user