use crate::structure::*;
#[derive(Debug, Clone, PartialEq, Copy)]
pub struct Name<'a> {
pub name: &'a str,
}
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum IntWidth {
I8,
I16,
I32,
I64,
}
impl IntWidth {
pub fn width(self) -> u8 {
match self {
IntWidth::I8 => 8,
IntWidth::I16 => 16,
IntWidth::I32 => 32,
IntWidth::I64 => 64,
}
}
}
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum FloatWidth {
F32,
F64,
}
impl FloatWidth {
pub fn width(self) -> u8 {
match self {
FloatWidth::F32 => 32,
FloatWidth::F64 => 64,
}
}
}
#[derive(Debug, Clone)]
pub struct RecordField<'a> {
pub name: Name<'a>,
pub ty: Value<'a>,
}
#[derive(Debug, Clone)]
pub struct VariantCase<'a> {
pub name: Name<'a>,
pub ty: Option<Value<'a>>,
}
#[derive(Debug, Clone)]
pub enum Value<'a> {
Bool,
S(IntWidth),
U(IntWidth),
F(FloatWidth),
Char,
String,
List(Box<Value<'a>>),
FixList(Box<Value<'a>>, u32),
Record(Vec<RecordField<'a>>),
Tuple(Vec<Value<'a>>),
Flags(Vec<Name<'a>>),
Variant(Vec<VariantCase<'a>>),
Enum(Vec<Name<'a>>),
Option(Box<Value<'a>>),
Result(Box<Option<Value<'a>>>, Box<Option<Value<'a>>>),
Own(Handleable),
Borrow(Handleable),
Var(Option<Tyvar>, Box<Value<'a>>),
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ResourceId {
pub(super) id: u32,
}
#[derive(Debug, Clone)]
pub enum FreeTyvar {
U(u32, u32),
E(u32, u32),
}
#[derive(Debug, Clone)]
pub enum Tyvar {
Bound(u32),
Free(FreeTyvar),
}
#[derive(Debug, Clone)]
pub struct Param<'a> {
pub name: Name<'a>,
pub ty: Value<'a>,
}
pub type Result<'a> = Option<Value<'a>>;
#[derive(Debug, Clone)]
pub struct Func<'a> {
pub params: Vec<Param<'a>>,
pub result: Result<'a>,
}
#[derive(Debug, Clone)]
pub enum Handleable {
Var(Tyvar),
Resource(ResourceId),
}
#[derive(Debug, Clone)]
pub enum Defined<'a> {
Handleable(Handleable),
Value(Value<'a>),
Func(Func<'a>),
Instance(QualifiedInstance<'a>),
Component(Component<'a>),
}
#[derive(Debug, Clone)]
pub enum TypeBound<'a> {
Eq(Defined<'a>),
SubResource,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ImportExport<'a> {
Import(&'a str),
Export(&'a str),
}
impl<'a> ImportExport<'a> {
pub fn name(&self) -> &'a str {
match self {
ImportExport::Import(s) => s,
ImportExport::Export(s) => s,
}
}
pub fn imported(&self) -> bool {
match self {
ImportExport::Import(_) => true,
ImportExport::Export(_) => false,
}
}
}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct TyvarOrigin<'a> {
pub path: Option<Vec<ImportExport<'a>>>,
}
impl<'a> TyvarOrigin<'a> {
pub fn new() -> Self {
TyvarOrigin { path: Some(vec![]) }
}
pub fn push(&self, x: Option<ImportExport<'a>>) -> Self {
match (&self.path, x) {
(None, _) => TyvarOrigin { path: None },
(_, None) => self.clone(),
(Some(xs), Some(x)) => {
let mut xs = xs.clone();
xs.push(x);
TyvarOrigin { path: Some(xs) }
}
}
}
pub fn matches<I: Iterator<Item = &'a ImportExport<'a>>>(&self, path: I) -> bool {
self.path
.as_ref()
.map(|p| p.iter().rev().eq(path))
.unwrap_or(false)
}
pub fn is_local<
I: DoubleEndedIterator<Item = &'a ImportExport<'a>>
+ ExactSizeIterator<Item = &'a ImportExport<'a>>,
>(
&self,
path: I,
) -> Option<Vec<ImportExport<'a>>> {
let other = path.rev().skip(1).rev();
let path = self.path.as_ref()?;
let path = path.iter();
let mut path = path.rev();
for elem in other {
match path.next() {
None => break,
Some(oe) if oe != elem => return None,
_ => (),
}
}
Some(path.cloned().collect())
}
pub fn last_name(&self) -> Option<&'a str> {
self.path
.as_ref()
.and_then(|x| x.first())
.map(|ie| ie.name())
}
pub fn is_imported(&self) -> bool {
let Some(p) = &self.path else {
return false;
};
p[p.len() - 1].imported()
}
}
#[derive(Debug, Clone)]
pub struct BoundedTyvar<'a> {
pub origin: TyvarOrigin<'a>,
pub bound: TypeBound<'a>,
}
impl<'a> BoundedTyvar<'a> {
pub fn new(bound: TypeBound<'a>) -> Self {
BoundedTyvar {
origin: TyvarOrigin::new(),
bound,
}
}
pub fn push_origin(&self, x: Option<ImportExport<'a>>) -> Self {
BoundedTyvar {
origin: self.origin.push(x),
..self.clone()
}
}
}
#[derive(Debug, Clone)]
pub enum ExternDesc<'a> {
CoreModule(CoreModule<'a>),
Func(Func<'a>),
Type(Defined<'a>),
Instance(Instance<'a>),
Component(Component<'a>),
}
#[derive(Debug, Clone)]
pub enum CoreOrComponentExternDesc<'a> {
Core(CoreExternDesc),
Component(ExternDesc<'a>),
}
#[derive(Debug, Clone)]
pub struct ExternDecl<'a> {
pub kebab_name: &'a str,
pub desc: ExternDesc<'a>,
}
#[derive(Debug, Clone)]
pub struct Instance<'a> {
pub exports: Vec<ExternDecl<'a>>,
}
#[derive(Debug, Clone)]
pub struct QualifiedInstance<'a> {
pub evars: Vec<BoundedTyvar<'a>>,
pub unqualified: Instance<'a>,
}
#[derive(Debug, Clone)]
pub struct Component<'a> {
pub uvars: Vec<BoundedTyvar<'a>>,
pub imports: Vec<ExternDecl<'a>>,
pub instance: QualifiedInstance<'a>,
}
#[derive(Debug, Clone)]
pub enum CoreExternDesc {
Func(wasmparser::FuncType),
Table(wasmparser::TableType),
Memory(wasmparser::MemoryType),
Global(wasmparser::GlobalType),
}
#[derive(Debug, Clone)]
pub struct CoreExportDecl<'a> {
pub name: Name<'a>,
pub desc: CoreExternDesc,
}
#[derive(Debug, Clone)]
pub struct CoreInstance<'a> {
pub exports: Vec<CoreExportDecl<'a>>,
}
#[derive(Debug, Clone)]
pub struct CoreModule<'a> {
pub _imports: Vec<wasmparser::Import<'a>>,
pub _exports: Vec<CoreExportDecl<'a>>,
}
#[derive(Debug, Clone)]
pub enum CoreDefined<'a> {
Func(wasmparser::FuncType),
Module(CoreModule<'a>),
}
#[derive(Default, Debug, Clone)]
pub struct CoreCtx<'a> {
pub types: Vec<CoreDefined<'a>>,
pub funcs: Vec<wasmparser::FuncType>,
pub modules: Vec<CoreModule<'a>>,
pub instances: Vec<CoreInstance<'a>>,
pub tables: Vec<wasmparser::TableType>,
pub mems: Vec<wasmparser::MemoryType>,
pub globals: Vec<wasmparser::GlobalType>,
}
impl<'a> CoreCtx<'a> {
pub fn new() -> Self {
CoreCtx {
types: Vec::new(),
funcs: Vec::new(),
modules: Vec::new(),
instances: Vec::new(),
tables: Vec::new(),
mems: Vec::new(),
globals: Vec::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct Resource {
pub _dtor: Option<FuncIdx>,
}
#[derive(Debug, Clone)]
pub struct Ctx<'p, 'a> {
pub parent: Option<&'p Ctx<'p, 'a>>,
pub outer_boundary: bool,
pub core: CoreCtx<'a>,
pub uvars: Vec<(BoundedTyvar<'a>, bool)>,
pub evars: Vec<(BoundedTyvar<'a>, Option<Defined<'a>>)>,
pub rtypes: Vec<Resource>,
pub types: Vec<Defined<'a>>,
pub components: Vec<Component<'a>>,
pub instances: Vec<Instance<'a>>,
pub funcs: Vec<Func<'a>>,
}
impl<'p, 'a> Ctx<'p, 'a> {
pub fn new<'c>(parent: Option<&'p Ctx<'c, 'a>>, outer_boundary: bool) -> Self {
Ctx {
parent,
outer_boundary,
core: CoreCtx::new(),
uvars: Vec::new(),
evars: Vec::new(),
rtypes: Vec::new(),
types: Vec::new(),
components: Vec::new(),
instances: Vec::new(),
funcs: Vec::new(),
}
}
}
pub struct CtxParentIterator<'i, 'p: 'i, 'a: 'i> {
ctx: Option<&'i Ctx<'p, 'a>>,
}
impl<'i, 'p, 'a> Iterator for CtxParentIterator<'i, 'p, 'a> {
type Item = &'i Ctx<'p, 'a>;
fn next(&mut self) -> Option<Self::Item> {
match self.ctx {
Some(ctx) => {
self.ctx = ctx.parent;
Some(ctx)
}
None => None,
}
}
}
impl<'p, 'a> Ctx<'p, 'a> {
pub fn parents<'i>(&'i self) -> CtxParentIterator<'i, 'p, 'a> {
CtxParentIterator { ctx: Some(self) }
}
}