mirror of
https://github.com/fluencelabs/marine.git
synced 2025-06-12 22:41:26 +00:00
Print Aqua-compatible types (#86)
This commit is contained in:
26
crates/module-interface/Cargo.toml
Normal file
26
crates/module-interface/Cargo.toml
Normal file
@ -0,0 +1,26 @@
|
||||
[package]
|
||||
name = "marine-module-interface"
|
||||
description = "Fluence Marine module interface"
|
||||
version = "0.1.0"
|
||||
authors = ["Fluence Labs"]
|
||||
license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "marine_module_interface"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
marine-it-interfaces = { path = "../it-interfaces", version = "0.4.0" }
|
||||
#marine-it-generator = { path = "../it-generator", verision = "0.5.2"}
|
||||
|
||||
anyhow = "1.0.31"
|
||||
walrus = "0.18.0"
|
||||
wasmer-core = { package = "wasmer-runtime-core-fl", version = "0.17.0"}
|
||||
wasmer-it = { package = "wasmer-interface-types-fl", version = "0.20.0" }
|
||||
nom = "5.1"
|
||||
|
||||
itertools = "0.10.0"
|
||||
semver = "0.11.0"
|
||||
serde = "=1.0.118"
|
||||
thiserror = "1.0.24"
|
27
crates/module-interface/src/interface/errors.rs
Normal file
27
crates/module-interface/src/interface/errors.rs
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::it_interface::ITInterfaceError;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum InterfaceError {
|
||||
#[error("record type with type id {0} not found")]
|
||||
NotFoundRecordTypeId(u64),
|
||||
|
||||
#[error("{0}")]
|
||||
ITInterfaceError(#[from] ITInterfaceError),
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::ModuleInterface;
|
||||
use super::InterfaceResult;
|
||||
use super::FunctionSignature;
|
||||
use super::records_transformer::RecordsTransformer;
|
||||
use crate::it_interface::IModuleInterface;
|
||||
use crate::it_interface::IFunctionSignature;
|
||||
use crate::it_interface::IRecordTypes;
|
||||
|
||||
pub fn it_to_module_interface(mm_interface: IModuleInterface) -> InterfaceResult<ModuleInterface> {
|
||||
let record_types = mm_interface.export_record_types;
|
||||
|
||||
let function_signatures = mm_interface
|
||||
.function_signatures
|
||||
.into_iter()
|
||||
.map(|sign| serialize_function_signature(sign, &record_types))
|
||||
.collect();
|
||||
|
||||
let record_types = RecordsTransformer::transform(&record_types)?;
|
||||
|
||||
let interface = ModuleInterface {
|
||||
function_signatures,
|
||||
record_types,
|
||||
};
|
||||
|
||||
Ok(interface)
|
||||
}
|
||||
|
||||
fn serialize_function_signature(
|
||||
signature: IFunctionSignature,
|
||||
record_types: &IRecordTypes,
|
||||
) -> FunctionSignature {
|
||||
use super::itype_text_view;
|
||||
|
||||
let arguments = signature
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|arg| (arg.name.clone(), itype_text_view(&arg.ty, record_types)))
|
||||
.collect();
|
||||
|
||||
let output_types = signature
|
||||
.outputs
|
||||
.iter()
|
||||
.map(|itype| itype_text_view(itype, record_types))
|
||||
.collect();
|
||||
|
||||
FunctionSignature {
|
||||
name: signature.name.to_string(),
|
||||
arguments,
|
||||
output_types,
|
||||
}
|
||||
}
|
50
crates/module-interface/src/interface/itype_to_text.rs
Normal file
50
crates/module-interface/src/interface/itype_to_text.rs
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use crate::it_interface::IRecordTypes;
|
||||
|
||||
use wasmer_it::IType;
|
||||
|
||||
/// Converts the supplied IType to a Aqua0compatible text representation.
|
||||
///
|
||||
/// SAFETY:
|
||||
/// It's assumed that arguments are well-formed and all records have a corresponded type in
|
||||
/// record_types.
|
||||
pub fn itype_text_view(arg_ty: &IType, record_types: &IRecordTypes) -> String {
|
||||
match arg_ty {
|
||||
IType::Record(record_type_id) => {
|
||||
// assumed that this functions called with well-formed args
|
||||
let record = record_types.get(record_type_id).unwrap();
|
||||
record.name.clone()
|
||||
}
|
||||
IType::Array(array_ty) => format!("[]{}", itype_text_view(array_ty, record_types)),
|
||||
IType::Boolean => "bool".to_string(),
|
||||
IType::S8 => "i8".to_string(),
|
||||
IType::S16 => "i16".to_string(),
|
||||
IType::S32 => "i32".to_string(),
|
||||
IType::S64 => "i64".to_string(),
|
||||
IType::U8 => "u8".to_string(),
|
||||
IType::U16 => "u16".to_string(),
|
||||
IType::U32 => "u32".to_string(),
|
||||
IType::U64 => "u64".to_string(),
|
||||
IType::F32 => "f32".to_string(),
|
||||
IType::F64 => "f64".to_string(),
|
||||
IType::String => "string".to_string(),
|
||||
IType::ByteArray => "[]u8".to_string(),
|
||||
IType::I32 => "i32".to_string(),
|
||||
IType::I64 => "i64".to_string(),
|
||||
}
|
||||
}
|
38
crates/module-interface/src/interface/mod.rs
Normal file
38
crates/module-interface/src/interface/mod.rs
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
mod errors;
|
||||
mod interface_transformer;
|
||||
mod itype_to_text;
|
||||
mod module_interface;
|
||||
mod records_transformer;
|
||||
|
||||
pub use errors::InterfaceError;
|
||||
pub use interface_transformer::it_to_module_interface;
|
||||
pub use itype_to_text::*;
|
||||
pub use module_interface::*;
|
||||
|
||||
pub type InterfaceResult<T> = std::result::Result<T, InterfaceError>;
|
||||
|
||||
use marine_it_interfaces::MITInterfaces;
|
||||
|
||||
/// Returns interface of a Marine module.
|
||||
pub fn get_interface(mit: &MITInterfaces<'_>) -> InterfaceResult<ModuleInterface> {
|
||||
let it_interface = crate::it_interface::get_interface(mit)?;
|
||||
let interface = it_to_module_interface(it_interface)?;
|
||||
|
||||
Ok(interface)
|
||||
}
|
78
crates/module-interface/src/interface/module_interface.rs
Normal file
78
crates/module-interface/src/interface/module_interface.rs
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use serde::Serialize;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct FunctionSignature {
|
||||
pub name: String,
|
||||
pub arguments: Vec<(String, String)>,
|
||||
pub output_types: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct RecordField {
|
||||
pub name: String,
|
||||
pub ty: String,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct RecordType {
|
||||
pub name: String,
|
||||
pub id: u64,
|
||||
pub fields: Vec<RecordField>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct ModuleInterface {
|
||||
pub function_signatures: Vec<FunctionSignature>,
|
||||
// record types are guaranteed to be topological sorted
|
||||
pub record_types: Vec<RecordType>,
|
||||
}
|
||||
|
||||
use std::fmt;
|
||||
|
||||
impl fmt::Display for FunctionSignature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use itertools::Itertools;
|
||||
|
||||
let output = match self.output_types.len() {
|
||||
0 => "()",
|
||||
1 => &self.output_types[0],
|
||||
_ => unimplemented!("more than 1 output type is unsupported"),
|
||||
};
|
||||
|
||||
if self.arguments.is_empty() {
|
||||
writeln!(f, "{}: -> {}", self.name, output)
|
||||
} else {
|
||||
let args = self.arguments.iter().map(|(_, ty)| ty).format(",");
|
||||
writeln!(f, "{}: {} -> {}", self.name, args, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RecordType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "data {}:", self.name)?;
|
||||
|
||||
for field in self.fields.iter() {
|
||||
writeln!(f, " {}: {}", field.name, field.ty)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
128
crates/module-interface/src/interface/records_transformer.rs
Normal file
128
crates/module-interface/src/interface/records_transformer.rs
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::RecordType;
|
||||
use super::RecordField;
|
||||
use super::InterfaceResult;
|
||||
use super::InterfaceError;
|
||||
use crate::it_interface::IRecordTypes;
|
||||
|
||||
use wasmer_it::IRecordType;
|
||||
use wasmer_it::IType;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub(crate) struct RecordsTransformer {
|
||||
used: HashSet<u64>,
|
||||
sorted_order: Vec<u64>,
|
||||
}
|
||||
|
||||
impl RecordsTransformer {
|
||||
pub(crate) fn transform(record_types: &IRecordTypes) -> InterfaceResult<Vec<RecordType>> {
|
||||
let records_count = record_types.len();
|
||||
|
||||
let mut transformer = Self {
|
||||
used: HashSet::with_capacity(records_count),
|
||||
sorted_order: Vec::with_capacity(records_count),
|
||||
};
|
||||
|
||||
// TODO: check for cycles
|
||||
transformer.topological_sort(record_types)?;
|
||||
let record_types = transformer.into_transformed_records(record_types);
|
||||
|
||||
Ok(record_types)
|
||||
}
|
||||
|
||||
fn topological_sort(&mut self, exported_records: &IRecordTypes) -> InterfaceResult<()> {
|
||||
for (id, record) in exported_records {
|
||||
self.dfs(*id, record, exported_records)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dfs(
|
||||
&mut self,
|
||||
record_id: u64,
|
||||
record: &Rc<IRecordType>,
|
||||
exported_records: &IRecordTypes,
|
||||
) -> InterfaceResult<()> {
|
||||
if !self.used.insert(record_id) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
for field in (&record.fields).iter() {
|
||||
self.type_dfs(&field.ty, exported_records)?;
|
||||
}
|
||||
|
||||
self.sorted_order.push(record_id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn type_dfs(
|
||||
&mut self,
|
||||
field_ty: &IType,
|
||||
exported_records: &IRecordTypes,
|
||||
) -> InterfaceResult<()> {
|
||||
match field_ty {
|
||||
IType::Record(type_id) => {
|
||||
let child_record = exported_records
|
||||
.get(type_id)
|
||||
.ok_or(InterfaceError::NotFoundRecordTypeId(*type_id))?;
|
||||
|
||||
self.dfs(*type_id, child_record, exported_records)
|
||||
}
|
||||
IType::Array(ty) => self.type_dfs(ty, exported_records),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn into_transformed_records(self, record_types: &IRecordTypes) -> Vec<RecordType> {
|
||||
self.sorted_order
|
||||
.into_iter()
|
||||
.map(|id| {
|
||||
// unwrap is safe here because sorted_order is constructed based on record_types
|
||||
let record = record_types.get(&id).unwrap();
|
||||
Self::convert_record(id, record, &record_types)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn convert_record(
|
||||
id: u64,
|
||||
record: &Rc<IRecordType>,
|
||||
record_types: &IRecordTypes,
|
||||
) -> RecordType {
|
||||
use super::itype_text_view;
|
||||
|
||||
let fields = record
|
||||
.fields
|
||||
.iter()
|
||||
.map(|field| RecordField {
|
||||
name: field.name.clone(),
|
||||
ty: itype_text_view(&field.ty, record_types),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
RecordType {
|
||||
name: record.name.clone(),
|
||||
id,
|
||||
fields,
|
||||
}
|
||||
}
|
||||
}
|
33
crates/module-interface/src/it_interface/errors.rs
Normal file
33
crates/module-interface/src/it_interface/errors.rs
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use marine_it_interfaces::MITInterfacesError;
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum ITInterfaceError {
|
||||
#[error("type with idx = {0} isn't a function type")]
|
||||
ITTypeNotFunction(u32),
|
||||
|
||||
#[error("record type with type id {0} not found")]
|
||||
NotFoundRecordTypeId(u64),
|
||||
|
||||
#[error("mailformed module: a record contains more recursion level then allowed")]
|
||||
TooManyRecursionLevels,
|
||||
|
||||
#[error("{0}")]
|
||||
MITInterfacesError(#[from] MITInterfacesError),
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::IFunctionSignature;
|
||||
use super::ITInterfaceError;
|
||||
use super::RIResult;
|
||||
|
||||
use marine_it_interfaces::MITInterfaces;
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct ITExportFuncDescriptor<'n> {
|
||||
pub adapter_function_type: u32,
|
||||
pub name: &'n str,
|
||||
}
|
||||
|
||||
/// Returns all exported IT functions descriptors.
|
||||
pub fn get_export_funcs_descriptors<'i>(
|
||||
mit: &'i MITInterfaces<'_>,
|
||||
) -> Vec<ITExportFuncDescriptor<'i>> {
|
||||
// An IT function is exported if it lies in export functions and have implementation.
|
||||
// An export IT function without implementation is a hack and used to call core function from
|
||||
// a Wasm module. This hack is needed because there is only one call instruction in the
|
||||
// interface-types crates and it's needed to distinguish somehow between calling export IT or
|
||||
// core functions. This scheme is a kind of mess and it needs to be refactored one day.
|
||||
mit.implementations()
|
||||
.filter_map(|(adapter_function_type, core_function_type)| {
|
||||
mit.exports_by_type(*core_function_type)
|
||||
.map(|export_function_name| (adapter_function_type, export_function_name))
|
||||
})
|
||||
.map(|(&adapter_function_type, export_function_names)| {
|
||||
export_function_names
|
||||
.iter()
|
||||
.map(move |name| ITExportFuncDescriptor {
|
||||
adapter_function_type,
|
||||
name,
|
||||
})
|
||||
})
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
/// Returns all exported IT functions.
|
||||
pub fn get_export_funcs(mit: &MITInterfaces<'_>) -> RIResult<Vec<IFunctionSignature>> {
|
||||
use marine_it_interfaces::ITAstType;
|
||||
|
||||
let funcs_descriptors = get_export_funcs_descriptors(mit);
|
||||
|
||||
funcs_descriptors
|
||||
.into_iter()
|
||||
.map(|descriptor| {
|
||||
let it_type = mit.type_by_idx_r(descriptor.adapter_function_type)?;
|
||||
|
||||
match it_type {
|
||||
ITAstType::Function {
|
||||
arguments,
|
||||
output_types,
|
||||
} => {
|
||||
let signature = IFunctionSignature {
|
||||
name: Rc::new(descriptor.name.to_string()),
|
||||
arguments: arguments.clone(),
|
||||
outputs: output_types.clone(),
|
||||
adapter_function_type: descriptor.adapter_function_type,
|
||||
};
|
||||
Ok(signature)
|
||||
}
|
||||
_ => Err(ITInterfaceError::ITTypeNotFunction(
|
||||
descriptor.adapter_function_type,
|
||||
)),
|
||||
}
|
||||
})
|
||||
.collect::<RIResult<Vec<IFunctionSignature>>>()
|
||||
}
|
129
crates/module-interface/src/it_interface/export_it_records.rs
Normal file
129
crates/module-interface/src/it_interface/export_it_records.rs
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use super::IRecordTypes;
|
||||
use super::RIResult;
|
||||
use super::ITInterfaceError;
|
||||
use super::IFunctionSignature;
|
||||
|
||||
use marine_it_interfaces::MITInterfaces;
|
||||
use wasmer_it::IType;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
const TYPE_RESOLVE_RECURSION_LIMIT: u32 = 1024;
|
||||
|
||||
pub struct FullRecordTypes {
|
||||
pub record_types: IRecordTypes,
|
||||
pub export_record_types: IRecordTypes,
|
||||
}
|
||||
|
||||
pub fn get_record_types<'f>(
|
||||
mit: &MITInterfaces<'_>,
|
||||
export_funcs: impl ExactSizeIterator<Item = &'f IFunctionSignature>,
|
||||
) -> RIResult<FullRecordTypes> {
|
||||
let all_record_types = get_all_records(mit);
|
||||
let mut export_record_types = HashMap::new();
|
||||
|
||||
let itypes = export_funcs.flat_map(|s| {
|
||||
s.arguments
|
||||
.as_ref()
|
||||
.iter()
|
||||
.map(|a| &a.ty)
|
||||
.chain(s.outputs.as_ref().iter())
|
||||
});
|
||||
|
||||
for itype in itypes {
|
||||
handle_itype(itype, &all_record_types, &mut export_record_types, 0)?;
|
||||
}
|
||||
|
||||
let full_record_types = FullRecordTypes {
|
||||
record_types: all_record_types,
|
||||
export_record_types,
|
||||
};
|
||||
|
||||
Ok(full_record_types)
|
||||
}
|
||||
|
||||
fn handle_itype(
|
||||
itype: &IType,
|
||||
all_record_types: &IRecordTypes,
|
||||
export_record_types: &mut IRecordTypes,
|
||||
recursion_level: u32,
|
||||
) -> RIResult<()> {
|
||||
if recursion_level > TYPE_RESOLVE_RECURSION_LIMIT {
|
||||
return Err(ITInterfaceError::TooManyRecursionLevels);
|
||||
}
|
||||
|
||||
match itype {
|
||||
IType::Record(record_type_id) => handle_record_type(
|
||||
*record_type_id,
|
||||
all_record_types,
|
||||
export_record_types,
|
||||
recursion_level + 1,
|
||||
)?,
|
||||
IType::Array(array_ty) => handle_itype(
|
||||
array_ty,
|
||||
all_record_types,
|
||||
export_record_types,
|
||||
recursion_level + 1,
|
||||
)?,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_record_type(
|
||||
record_type_id: u64,
|
||||
all_record_types: &IRecordTypes,
|
||||
export_record_types: &mut IRecordTypes,
|
||||
recursion_level: u32,
|
||||
) -> RIResult<()> {
|
||||
let record_type = all_record_types
|
||||
.get(&record_type_id)
|
||||
.ok_or(ITInterfaceError::NotFoundRecordTypeId(record_type_id))?;
|
||||
|
||||
export_record_types.insert(record_type_id, record_type.clone());
|
||||
|
||||
for field in record_type.fields.iter() {
|
||||
handle_itype(
|
||||
&field.ty,
|
||||
all_record_types,
|
||||
export_record_types,
|
||||
recursion_level + 1,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_all_records(mit: &MITInterfaces<'_>) -> IRecordTypes {
|
||||
use marine_it_interfaces::ITAstType;
|
||||
|
||||
mit.types()
|
||||
.enumerate()
|
||||
.fold(HashMap::new(), |mut record_types_by_id, (id, ty)| {
|
||||
match ty {
|
||||
ITAstType::Record(record_type) => {
|
||||
record_types_by_id.insert(id as u64, record_type.clone());
|
||||
}
|
||||
ITAstType::Function { .. } => {}
|
||||
};
|
||||
|
||||
record_types_by_id
|
||||
})
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use wasmer_it::IType;
|
||||
use wasmer_it::ast::FunctionArg as IFunctionArg;
|
||||
use wasmer_it::IRecordType;
|
||||
|
||||
use serde::Serialize;
|
||||
use serde::Deserialize;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type IRecordTypes = HashMap<u64, Rc<IRecordType>>;
|
||||
|
||||
/// Represent a function type inside Marine module.
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct IFunctionSignature {
|
||||
pub name: Rc<String>,
|
||||
pub arguments: Rc<Vec<IFunctionArg>>,
|
||||
pub outputs: Rc<Vec<IType>>,
|
||||
pub adapter_function_type: u32,
|
||||
}
|
||||
|
||||
/// Represent an interface of a Wasm module.
|
||||
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct IModuleInterface {
|
||||
pub export_record_types: IRecordTypes,
|
||||
pub record_types: IRecordTypes,
|
||||
pub function_signatures: Vec<IFunctionSignature>,
|
||||
}
|
46
crates/module-interface/src/it_interface/mod.rs
Normal file
46
crates/module-interface/src/it_interface/mod.rs
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
mod errors;
|
||||
mod export_it_functions;
|
||||
mod export_it_records;
|
||||
mod it_module_interface;
|
||||
|
||||
pub use errors::*;
|
||||
pub use export_it_functions::*;
|
||||
pub use export_it_records::*;
|
||||
pub use it_module_interface::*;
|
||||
|
||||
pub type RIResult<T> = std::result::Result<T, ITInterfaceError>;
|
||||
|
||||
use marine_it_interfaces::MITInterfaces;
|
||||
|
||||
/// Returns Marine module interface that includes both export and all record types.
|
||||
pub fn get_interface(mit: &MITInterfaces<'_>) -> RIResult<IModuleInterface> {
|
||||
let function_signatures = get_export_funcs(mit)?;
|
||||
let FullRecordTypes {
|
||||
record_types,
|
||||
export_record_types,
|
||||
} = get_record_types(mit, function_signatures.iter())?;
|
||||
|
||||
let mm_interface = IModuleInterface {
|
||||
record_types,
|
||||
export_record_types,
|
||||
function_signatures,
|
||||
};
|
||||
|
||||
Ok(mm_interface)
|
||||
}
|
29
crates/module-interface/src/lib.rs
Normal file
29
crates/module-interface/src/lib.rs
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2021 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![deny(
|
||||
dead_code,
|
||||
nonstandard_style,
|
||||
unused_imports,
|
||||
unused_mut,
|
||||
unused_variables,
|
||||
unused_unsafe,
|
||||
unreachable_patterns
|
||||
)]
|
||||
|
||||
pub mod interface;
|
||||
pub mod it_interface;
|
Reference in New Issue
Block a user