Next Generation WASM Microkernel Operating System
at trap_handler 232 lines 6.9 kB view raw
1use super::{ComponentExternName, ItemRef, ItemSigNoName}; 2use crate::kw; 3use crate::parser::{Cursor, Parse, Parser, Peek, Result}; 4use crate::token::{Id, Index, NameAnnotation, Span}; 5use alloc::vec::Vec; 6 7/// An entry in a WebAssembly component's export section. 8#[derive(Debug)] 9pub struct ComponentExport<'a> { 10 /// Where this export was defined. 11 pub span: Span, 12 /// Optional identifier bound to this export. 13 pub id: Option<Id<'a>>, 14 /// An optional name for this instance stored in the custom `name` section. 15 pub debug_name: Option<NameAnnotation<'a>>, 16 /// The name of this export from the component. 17 pub name: ComponentExternName<'a>, 18 /// The kind of export. 19 pub kind: ComponentExportKind<'a>, 20 /// The kind of export. 21 pub ty: Option<ItemSigNoName<'a>>, 22} 23 24impl<'a> Parse<'a> for ComponentExport<'a> { 25 fn parse(parser: Parser<'a>) -> Result<Self> { 26 let span = parser.parse::<kw::export>()?.0; 27 let id = parser.parse()?; 28 let debug_name = parser.parse()?; 29 let name = parser.parse()?; 30 let kind = parser.parse()?; 31 let ty = if !parser.is_empty() { 32 Some(parser.parens(|p| p.parse())?) 33 } else { 34 None 35 }; 36 Ok(ComponentExport { 37 span, 38 id, 39 debug_name, 40 name, 41 kind, 42 ty, 43 }) 44 } 45} 46 47impl<'a> Parse<'a> for Vec<ComponentExport<'a>> { 48 fn parse(parser: Parser<'a>) -> Result<Self> { 49 let mut exports = Vec::new(); 50 while !parser.is_empty() { 51 exports.push(parser.parens(|parser| parser.parse())?); 52 } 53 Ok(exports) 54 } 55} 56 57/// The kind of exported item. 58#[derive(Debug)] 59pub enum ComponentExportKind<'a> { 60 /// The export is a core module. 61 /// 62 /// Note this isn't a core item ref as currently only 63 /// components can export core modules. 64 CoreModule(ItemRef<'a, kw::module>), 65 /// The export is a function. 66 Func(ItemRef<'a, kw::func>), 67 /// The export is a value. 68 Value(ItemRef<'a, kw::value>), 69 /// The export is a type. 70 Type(ItemRef<'a, kw::r#type>), 71 /// The export is a component. 72 Component(ItemRef<'a, kw::component>), 73 /// The export is an instance. 74 Instance(ItemRef<'a, kw::instance>), 75} 76 77impl<'a> ComponentExportKind<'a> { 78 pub(crate) fn module(span: Span, id: Id<'a>) -> Self { 79 Self::CoreModule(ItemRef { 80 kind: kw::module(span), 81 idx: Index::Id(id), 82 export_names: Default::default(), 83 }) 84 } 85 86 pub(crate) fn component(span: Span, id: Id<'a>) -> Self { 87 Self::Component(ItemRef { 88 kind: kw::component(span), 89 idx: Index::Id(id), 90 export_names: Default::default(), 91 }) 92 } 93 94 pub(crate) fn instance(span: Span, id: Id<'a>) -> Self { 95 Self::Instance(ItemRef { 96 kind: kw::instance(span), 97 idx: Index::Id(id), 98 export_names: Default::default(), 99 }) 100 } 101 102 pub(crate) fn func(span: Span, id: Id<'a>) -> Self { 103 Self::Func(ItemRef { 104 kind: kw::func(span), 105 idx: Index::Id(id), 106 export_names: Default::default(), 107 }) 108 } 109 110 pub(crate) fn ty(span: Span, id: Id<'a>) -> Self { 111 Self::Type(ItemRef { 112 kind: kw::r#type(span), 113 idx: Index::Id(id), 114 export_names: Default::default(), 115 }) 116 } 117} 118 119impl<'a> Parse<'a> for ComponentExportKind<'a> { 120 fn parse(parser: Parser<'a>) -> Result<Self> { 121 parser.parens(|parser| { 122 let mut l = parser.lookahead1(); 123 if l.peek::<kw::core>()? { 124 // Remove core prefix 125 parser.parse::<kw::core>()?; 126 Ok(Self::CoreModule(parser.parse()?)) 127 } else if l.peek::<kw::func>()? { 128 Ok(Self::Func(parser.parse()?)) 129 } else if l.peek::<kw::value>()? { 130 Ok(Self::Value(parser.parse()?)) 131 } else if l.peek::<kw::r#type>()? { 132 Ok(Self::Type(parser.parse()?)) 133 } else if l.peek::<kw::component>()? { 134 Ok(Self::Component(parser.parse()?)) 135 } else if l.peek::<kw::instance>()? { 136 Ok(Self::Instance(parser.parse()?)) 137 } else { 138 Err(l.error()) 139 } 140 }) 141 } 142} 143 144impl Peek for ComponentExportKind<'_> { 145 fn peek(cursor: Cursor) -> Result<bool> { 146 let cursor = match cursor.lparen()? { 147 Some(c) => c, 148 None => return Ok(false), 149 }; 150 151 let cursor = match cursor.keyword()? { 152 Some(("core", c)) => match c.keyword()? { 153 Some(("module", c)) => c, 154 _ => return Ok(false), 155 }, 156 Some(("func", c)) 157 | Some(("value", c)) 158 | Some(("type", c)) 159 | Some(("component", c)) 160 | Some(("instance", c)) => c, 161 _ => return Ok(false), 162 }; 163 164 Index::peek(cursor) 165 } 166 167 fn display() -> &'static str { 168 "component export" 169 } 170} 171 172/// A listing of inline `(export "foo" <url>)` statements on a WebAssembly 173/// component item in its textual format. 174#[derive(Debug, Default)] 175pub struct InlineExport<'a> { 176 /// The extra names to export an item as, if any. 177 pub names: Vec<ComponentExternName<'a>>, 178} 179 180impl<'a> Parse<'a> for InlineExport<'a> { 181 fn parse(parser: Parser<'a>) -> Result<Self> { 182 let mut names = Vec::new(); 183 while parser.peek::<Self>()? { 184 names.push(parser.parens(|p| { 185 p.parse::<kw::export>()?; 186 p.parse() 187 })?); 188 } 189 Ok(InlineExport { names }) 190 } 191} 192 193impl Peek for InlineExport<'_> { 194 fn peek(cursor: Cursor<'_>) -> Result<bool> { 195 let cursor = match cursor.lparen()? { 196 Some(cursor) => cursor, 197 None => return Ok(false), 198 }; 199 let cursor = match cursor.keyword()? { 200 Some(("export", cursor)) => cursor, 201 _ => return Ok(false), 202 }; 203 204 // (export "foo") 205 if let Some((_, cursor)) = cursor.string()? { 206 return Ok(cursor.rparen()?.is_some()); 207 } 208 209 // (export (interface "foo")) 210 let cursor = match cursor.lparen()? { 211 Some(cursor) => cursor, 212 None => return Ok(false), 213 }; 214 let cursor = match cursor.keyword()? { 215 Some(("interface", cursor)) => cursor, 216 _ => return Ok(false), 217 }; 218 let cursor = match cursor.string()? { 219 Some((_, cursor)) => cursor, 220 _ => return Ok(false), 221 }; 222 let cursor = match cursor.rparen()? { 223 Some(cursor) => cursor, 224 _ => return Ok(false), 225 }; 226 Ok(cursor.rparen()?.is_some()) 227 } 228 229 fn display() -> &'static str { 230 "inline export" 231 } 232}