Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 47 additions & 40 deletions tools/witx/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,27 @@ impl Document {
entries,
}
}
pub fn datatype(&self, name: &Id) -> Option<Rc<Datatype>> {
pub fn typename(&self, name: &Id) -> Option<Rc<NamedType>> {
self.entries.get(name).and_then(|e| match e {
Entry::Datatype(d) => Some(d.upgrade().expect("always possible to upgrade entry")),
Entry::Typename(nt) => Some(nt.upgrade().expect("always possible to upgrade entry")),
_ => None,
})
}
pub fn datatypes<'a>(&'a self) -> impl Iterator<Item = Rc<Datatype>> + 'a {
pub fn typenames<'a>(&'a self) -> impl Iterator<Item = Rc<NamedType>> + 'a {
self.definitions.iter().filter_map(|d| match d {
Definition::Datatype(d) => Some(d.clone()),
Definition::Typename(nt) => Some(nt.clone()),
_ => None,
})
}
pub fn module(&self, name: &Id) -> Option<Rc<Module>> {
self.entries.get(&name).and_then(|e| match e {
Entry::Module(d) => Some(d.upgrade().expect("always possible to upgrade entry")),
Entry::Module(m) => Some(m.upgrade().expect("always possible to upgrade entry")),
_ => None,
})
}
pub fn modules<'a>(&'a self) -> impl Iterator<Item = Rc<Module>> + 'a {
self.definitions.iter().filter_map(|d| match d {
Definition::Module(d) => Some(d.clone()),
Definition::Module(m) => Some(m.clone()),
_ => None,
})
}
Expand All @@ -66,20 +66,20 @@ impl Eq for Document {}

#[derive(Debug, Clone)]
pub enum Definition {
Datatype(Rc<Datatype>),
Typename(Rc<NamedType>),
Module(Rc<Module>),
}

#[derive(Debug, Clone)]
pub enum Entry {
Datatype(Weak<Datatype>),
Typename(Weak<NamedType>),
Module(Weak<Module>),
}

impl Entry {
pub fn kind(&self) -> &'static str {
match self {
Entry::Datatype { .. } => "datatype",
Entry::Typename { .. } => "typename",
Entry::Module { .. } => "module",
}
}
Expand All @@ -88,10 +88,10 @@ impl Entry {
impl PartialEq for Entry {
fn eq(&self, rhs: &Entry) -> bool {
match (self, rhs) {
(Entry::Datatype(d), Entry::Datatype(d_rhs)) => {
d.upgrade()
(Entry::Typename(t), Entry::Typename(t_rhs)) => {
t.upgrade()
.expect("possible to upgrade entry when part of document")
== d_rhs
== t_rhs
.upgrade()
.expect("possible to upgrade entry when part of document")
}
Expand All @@ -108,51 +108,63 @@ impl PartialEq for Entry {
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DatatypeIdent {
Builtin(BuiltinType),
Array(Box<DatatypeIdent>),
Pointer(Box<DatatypeIdent>),
ConstPointer(Box<DatatypeIdent>),
Ident(Rc<Datatype>),
pub enum TypeRef {
Name(Rc<NamedType>),
Value(Rc<Type>),
}

impl TypeRef {
pub fn type_(&self) -> Rc<Type> {
match self {
TypeRef::Name(named) => named.type_(),
TypeRef::Value(ref v) => v.clone(),
}
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Datatype {
pub struct NamedType {
pub name: Id,
pub variant: DatatypeVariant,
pub dt: TypeRef,
pub docs: String,
}

impl NamedType {
pub fn type_(&self) -> Rc<Type> {
self.dt.type_()
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DatatypeVariant {
Alias(AliasDatatype),
pub enum Type {
Enum(EnumDatatype),
Flags(FlagsDatatype),
Struct(StructDatatype),
Union(UnionDatatype),
Handle(HandleDatatype),
Array(TypeRef),
Pointer(TypeRef),
ConstPointer(TypeRef),
Builtin(BuiltinType),
}

impl DatatypeVariant {
impl Type {
pub fn kind(&self) -> &'static str {
use DatatypeVariant::*;
use Type::*;
match self {
Alias(_) => "alias",
Enum(_) => "enum",
Flags(_) => "flags",
Struct(_) => "struct",
Union(_) => "union",
Handle(_) => "handle",
Array(_) => "array",
Pointer(_) => "pointer",
ConstPointer(_) => "constpointer",
Builtin(_) => "builtin",
}
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AliasDatatype {
pub name: Id,
pub to: DatatypeIdent,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum IntRepr {
U8,
Expand All @@ -163,7 +175,6 @@ pub enum IntRepr {

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnumDatatype {
pub name: Id,
pub repr: IntRepr,
pub variants: Vec<EnumVariant>,
}
Expand All @@ -176,7 +187,6 @@ pub struct EnumVariant {

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FlagsDatatype {
pub name: Id,
pub repr: IntRepr,
pub flags: Vec<FlagsMember>,
}
Expand All @@ -189,34 +199,31 @@ pub struct FlagsMember {

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StructDatatype {
pub name: Id,
pub members: Vec<StructMember>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StructMember {
pub name: Id,
pub type_: DatatypeIdent,
pub tref: TypeRef,
pub docs: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UnionDatatype {
pub name: Id,
pub variants: Vec<UnionVariant>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UnionVariant {
pub name: Id,
pub type_: DatatypeIdent,
pub tref: TypeRef,
pub docs: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HandleDatatype {
pub name: Id,
pub supertypes: Vec<DatatypeIdent>,
pub supertypes: Vec<TypeRef>,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -333,7 +340,7 @@ pub struct InterfaceFunc {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InterfaceFuncParam {
pub name: Id,
pub type_: DatatypeIdent,
pub tref: TypeRef,
pub position: InterfaceFuncParamPosition,
pub docs: String,
}
Expand Down
55 changes: 23 additions & 32 deletions tools/witx/src/coretypes.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use crate::{
BuiltinType, DatatypeIdent, DatatypeVariant, IntRepr, InterfaceFunc, InterfaceFuncParam,
};
use crate::{BuiltinType, IntRepr, InterfaceFunc, InterfaceFuncParam, Type};

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
/// Enumerates the types permitted for function arguments in the WebAssembly spec
Expand All @@ -22,7 +20,7 @@ impl From<IntRepr> for AtomType {

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
/// Enumerates the strategies which may be used to pass a datatype as an argument
pub enum DatatypePassedBy {
pub enum TypePassedBy {
/// Pass by value specifies the AtomType used to represent that value
Value(AtomType),
/// Pass by a pointer into linear memory
Expand All @@ -31,36 +29,29 @@ pub enum DatatypePassedBy {
PointerLengthPair,
}

impl DatatypeIdent {
impl Type {
/// Determine the simplest strategy by which a type may be passed. Value always preferred over
/// Pointer.
pub fn passed_by(&self) -> DatatypePassedBy {
match &self {
DatatypeIdent::Builtin(b) => match b {
BuiltinType::String => DatatypePassedBy::PointerLengthPair,
pub fn passed_by(&self) -> TypePassedBy {
match self {
Type::Builtin(b) => match b {
BuiltinType::String => TypePassedBy::PointerLengthPair,
BuiltinType::U8
| BuiltinType::U16
| BuiltinType::U32
| BuiltinType::S8
| BuiltinType::S16
| BuiltinType::S32 => DatatypePassedBy::Value(AtomType::I32),
BuiltinType::U64 | BuiltinType::S64 => DatatypePassedBy::Value(AtomType::I64),
BuiltinType::F32 => DatatypePassedBy::Value(AtomType::F32),
BuiltinType::F64 => DatatypePassedBy::Value(AtomType::F64),
},
DatatypeIdent::Array { .. } => DatatypePassedBy::PointerLengthPair,
DatatypeIdent::Pointer { .. } | DatatypeIdent::ConstPointer { .. } => {
DatatypePassedBy::Value(AtomType::I32)
}
DatatypeIdent::Ident(i) => match &i.variant {
DatatypeVariant::Alias(a) => a.to.passed_by(),
DatatypeVariant::Enum(e) => DatatypePassedBy::Value(e.repr.into()),
DatatypeVariant::Flags(f) => DatatypePassedBy::Value(f.repr.into()),
DatatypeVariant::Struct { .. } | DatatypeVariant::Union { .. } => {
DatatypePassedBy::Pointer
}
DatatypeVariant::Handle { .. } => DatatypePassedBy::Value(AtomType::I32),
| BuiltinType::S32 => TypePassedBy::Value(AtomType::I32),
BuiltinType::U64 | BuiltinType::S64 => TypePassedBy::Value(AtomType::I64),
BuiltinType::F32 => TypePassedBy::Value(AtomType::F32),
BuiltinType::F64 => TypePassedBy::Value(AtomType::F64),
},
Type::Array { .. } => TypePassedBy::PointerLengthPair,
Type::Pointer { .. } | Type::ConstPointer { .. } => TypePassedBy::Value(AtomType::I32),
Type::Enum(e) => TypePassedBy::Value(e.repr.into()),
Type::Flags(f) => TypePassedBy::Value(f.repr.into()),
Type::Struct { .. } | Type::Union { .. } => TypePassedBy::Pointer,
Type::Handle { .. } => TypePassedBy::Value(AtomType::I32),
}
}
}
Expand Down Expand Up @@ -108,25 +99,25 @@ impl InterfaceFuncParam {
/// Gives the WebAssembly type that corresponds to passing this interface func parameter by value.
/// Not all types can be passed by value: those which cannot return None
pub fn pass_by_value(&self) -> Option<CoreParamType> {
match self.type_.passed_by() {
DatatypePassedBy::Value(atom) => Some(CoreParamType {
match self.tref.type_().passed_by() {
TypePassedBy::Value(atom) => Some(CoreParamType {
signifies: CoreParamSignifies::Value(atom),
param: self.clone(),
}),
DatatypePassedBy::Pointer | DatatypePassedBy::PointerLengthPair => None,
TypePassedBy::Pointer | TypePassedBy::PointerLengthPair => None,
}
}

/// Gives the WebAssembly types that correspond to passing this interface func parameter
/// by reference. Some types are passed by reference using a single pointer, others
/// require both a pointer and length.
pub fn pass_by_reference(&self) -> Vec<CoreParamType> {
match self.type_.passed_by() {
DatatypePassedBy::Value(_) | DatatypePassedBy::Pointer => vec![CoreParamType {
match self.tref.type_().passed_by() {
TypePassedBy::Value(_) | TypePassedBy::Pointer => vec![CoreParamType {
signifies: CoreParamSignifies::PointerTo,
param: self.clone(),
}],
DatatypePassedBy::PointerLengthPair => vec![
TypePassedBy::PointerLengthPair => vec![
CoreParamType {
signifies: CoreParamSignifies::PointerTo,
param: self.clone(),
Expand Down
Loading