Next Generation WASM Microkernel Operating System
at trap_handler 334 lines 12 kB view raw
1use crate::annotation; 2use crate::component::*; 3use crate::core::Producers; 4use crate::kw; 5use crate::parser::{Parse, Parser, Result}; 6use crate::token::Index; 7use crate::token::{Id, NameAnnotation, Span}; 8use alloc::vec::Vec; 9 10/// A parsed WebAssembly component module. 11#[derive(Debug)] 12#[non_exhaustive] 13pub struct Component<'a> { 14 /// Where this `component` was defined 15 pub span: Span, 16 /// An optional identifier this component is known by 17 pub id: Option<Id<'a>>, 18 /// An optional `@name` annotation for this component 19 pub name: Option<NameAnnotation<'a>>, 20 /// What kind of component this was parsed as. 21 pub kind: ComponentKind<'a>, 22} 23 24/// The different kinds of ways to define a component. 25#[derive(Debug)] 26pub enum ComponentKind<'a> { 27 /// A component defined in the textual s-expression format. 28 Text(Vec<ComponentField<'a>>), 29 /// A component that had its raw binary bytes defined via the `binary` 30 /// directive. 31 Binary(Vec<&'a [u8]>), 32} 33 34impl<'a> Component<'a> { 35 /// Performs a name resolution pass on this [`Component`], resolving all 36 /// symbolic names to indices. 37 /// 38 /// The WAT format contains a number of shorthands to make it easier to 39 /// write, such as inline exports, inline imports, inline type definitions, 40 /// etc. Additionally it allows using symbolic names such as `$foo` instead 41 /// of using indices. This module will postprocess an AST to remove all of 42 /// this syntactic sugar, preparing the AST for binary emission. This is 43 /// where expansion and name resolution happens. 44 /// 45 /// This function will mutate the AST of this [`Component`] and replace all 46 /// [`Index`](crate::token::Index) arguments with `Index::Num`. This will 47 /// also expand inline exports/imports listed on fields and handle various 48 /// other shorthands of the text format. 49 /// 50 /// If successful the AST was modified to be ready for binary encoding. 51 /// 52 /// # Errors 53 /// 54 /// If an error happens during resolution, such a name resolution error or 55 /// items are found in the wrong order, then an error is returned. 56 pub fn resolve(&mut self) -> ::core::result::Result<(), crate::Error> { 57 match &mut self.kind { 58 ComponentKind::Text(fields) => { 59 crate::component::expand::expand(fields); 60 } 61 ComponentKind::Binary(_) => {} 62 } 63 crate::component::resolve::resolve(self) 64 } 65 66 /// Encodes this [`Component`] to its binary form. 67 /// 68 /// This function will take the textual representation in [`Component`] and 69 /// perform all steps necessary to convert it to a binary WebAssembly 70 /// component, suitable for writing to a `*.wasm` file. This function may 71 /// internally modify the [`Component`], for example: 72 /// 73 /// * Name resolution is performed to ensure that `Index::Id` isn't present 74 /// anywhere in the AST. 75 /// 76 /// * Inline shorthands such as imports/exports/types are all expanded to be 77 /// dedicated fields of the component. 78 /// 79 /// * Component fields may be shuffled around to preserve index ordering from 80 /// expansions. 81 /// 82 /// After all of this expansion has happened the component will be converted to 83 /// its binary form and returned as a `Vec<u8>`. This is then suitable to 84 /// hand off to other wasm runtimes and such. 85 /// 86 /// # Errors 87 /// 88 /// This function can return an error for name resolution errors and other 89 /// expansion-related errors. 90 pub fn encode(&mut self) -> core::result::Result<Vec<u8>, crate::Error> { 91 crate::core::EncodeOptions::default().encode_component(self) 92 } 93 94 pub(crate) fn validate(&self, parser: Parser<'_>) -> Result<()> { 95 let mut starts = 0; 96 if let ComponentKind::Text(fields) = &self.kind { 97 for item in fields.iter() { 98 if let ComponentField::Start(_) = item { 99 starts += 1; 100 } 101 } 102 } 103 if starts > 1 { 104 return Err(parser.error("multiple start sections found")); 105 } 106 Ok(()) 107 } 108 109 pub(crate) fn parse_without_component_keyword( 110 component_keyword_span: Span, 111 parser: Parser<'a>, 112 ) -> Result<Self> { 113 let id = parser.parse()?; 114 let name = parser.parse()?; 115 116 let kind = if parser.peek::<kw::binary>()? { 117 parser.parse::<kw::binary>()?; 118 let mut data = Vec::new(); 119 while !parser.is_empty() { 120 data.push(parser.parse()?); 121 } 122 ComponentKind::Binary(data) 123 } else { 124 ComponentKind::Text(ComponentField::parse_remaining(parser)?) 125 }; 126 Ok(Component { 127 span: component_keyword_span, 128 id, 129 name, 130 kind, 131 }) 132 } 133} 134 135impl<'a> Parse<'a> for Component<'a> { 136 fn parse(parser: Parser<'a>) -> Result<Self> { 137 parser.with_standard_annotations_registered(|parser| { 138 let span = parser.parse::<kw::component>()?.0; 139 Component::parse_without_component_keyword(span, parser) 140 }) 141 } 142} 143 144/// A listing of all possible fields that can make up a WebAssembly component. 145#[allow(missing_docs)] 146#[derive(Debug)] 147pub enum ComponentField<'a> { 148 CoreModule(CoreModule<'a>), 149 CoreInstance(CoreInstance<'a>), 150 CoreType(CoreType<'a>), 151 CoreRec(crate::core::Rec<'a>), 152 Component(NestedComponent<'a>), 153 Instance(Instance<'a>), 154 Alias(Alias<'a>), 155 Type(Type<'a>), 156 CanonicalFunc(CanonicalFunc<'a>), 157 CoreFunc(CoreFunc<'a>), // Supports inverted forms of other items 158 Func(Func<'a>), // Supports inverted forms of other items 159 Start(Start<'a>), 160 Import(ComponentImport<'a>), 161 Export(ComponentExport<'a>), 162 Custom(Custom<'a>), 163 Producers(Producers<'a>), 164} 165 166impl<'a> ComponentField<'a> { 167 fn parse_remaining(parser: Parser<'a>) -> Result<Vec<ComponentField<'a>>> { 168 let mut fields = Vec::new(); 169 while !parser.is_empty() { 170 fields.push(parser.parens(ComponentField::parse)?); 171 } 172 Ok(fields) 173 } 174} 175 176impl<'a> Parse<'a> for ComponentField<'a> { 177 fn parse(parser: Parser<'a>) -> Result<Self> { 178 if parser.peek::<kw::core>()? { 179 if parser.peek2::<kw::module>()? { 180 return Ok(Self::CoreModule(parser.parse()?)); 181 } 182 if parser.peek2::<kw::instance>()? { 183 return Ok(Self::CoreInstance(parser.parse()?)); 184 } 185 if parser.peek2::<kw::r#type>()? { 186 return Ok(Self::CoreType(parser.parse()?)); 187 } 188 if parser.peek2::<kw::func>()? { 189 return Ok(Self::CoreFunc(parser.parse()?)); 190 } 191 if parser.peek2::<kw::rec>()? { 192 parser.parse::<kw::core>()?; 193 return Ok(Self::CoreRec(parser.parse()?)); 194 } 195 } else { 196 if parser.peek::<kw::component>()? { 197 return Ok(Self::Component(parser.parse()?)); 198 } 199 if parser.peek::<kw::instance>()? { 200 return Ok(Self::Instance(parser.parse()?)); 201 } 202 if parser.peek::<kw::alias>()? { 203 return Ok(Self::Alias(parser.parse()?)); 204 } 205 if parser.peek::<kw::r#type>()? { 206 return Ok(Self::Type(Type::parse_maybe_with_inline_exports(parser)?)); 207 } 208 if parser.peek::<kw::import>()? { 209 return Ok(Self::Import(parser.parse()?)); 210 } 211 if parser.peek::<kw::func>()? { 212 return Ok(Self::Func(parser.parse()?)); 213 } 214 if parser.peek::<kw::export>()? { 215 return Ok(Self::Export(parser.parse()?)); 216 } 217 if parser.peek::<kw::start>()? { 218 return Ok(Self::Start(parser.parse()?)); 219 } 220 if parser.peek::<kw::canon>()? { 221 return Ok(Self::CanonicalFunc(parser.parse()?)); 222 } 223 if parser.peek::<annotation::custom>()? { 224 return Ok(Self::Custom(parser.parse()?)); 225 } 226 if parser.peek::<annotation::producers>()? { 227 return Ok(Self::Producers(parser.parse()?)); 228 } 229 } 230 Err(parser.error("expected valid component field")) 231 } 232} 233 234/// A function to call at instantiation time. 235#[derive(Debug)] 236pub struct Start<'a> { 237 /// The function to call. 238 pub func: Index<'a>, 239 /// The arguments to pass to the function. 240 pub args: Vec<ItemRef<'a, kw::value>>, 241 /// Names of the result values. 242 pub results: Vec<Option<Id<'a>>>, 243} 244 245impl<'a> Parse<'a> for Start<'a> { 246 fn parse(parser: Parser<'a>) -> Result<Self> { 247 parser.parse::<kw::start>()?; 248 let func = parser.parse()?; 249 let mut args = Vec::new(); 250 while !parser.is_empty() && !parser.peek2::<kw::result>()? { 251 args.push(parser.parens(|parser| parser.parse())?); 252 } 253 254 let mut results = Vec::new(); 255 while !parser.is_empty() && parser.peek2::<kw::result>()? { 256 results.push(parser.parens(|parser| { 257 parser.parse::<kw::result>()?; 258 parser.parens(|parser| { 259 parser.parse::<kw::value>()?; 260 parser.parse() 261 }) 262 })?); 263 } 264 265 Ok(Start { 266 func, 267 args, 268 results, 269 }) 270 } 271} 272 273/// A nested WebAssembly component. 274#[derive(Debug)] 275pub struct NestedComponent<'a> { 276 /// Where this `component` was defined 277 pub span: Span, 278 /// An optional identifier this component is known by 279 pub id: Option<Id<'a>>, 280 /// An optional `@name` annotation for this component 281 pub name: Option<NameAnnotation<'a>>, 282 /// If present, inline export annotations which indicate names this 283 /// definition should be exported under. 284 pub exports: InlineExport<'a>, 285 /// What kind of component this was parsed as. 286 pub kind: NestedComponentKind<'a>, 287} 288 289/// The different kinds of ways to define a nested component. 290#[derive(Debug)] 291pub enum NestedComponentKind<'a> { 292 /// This is actually an inline import of a component 293 Import { 294 /// The information about where this is being imported from. 295 import: InlineImport<'a>, 296 /// The type of component being imported. 297 ty: ComponentTypeUse<'a, ComponentType<'a>>, 298 }, 299 /// The component is defined inline as a local definition with its fields 300 /// listed here. 301 Inline(Vec<ComponentField<'a>>), 302} 303 304impl<'a> Parse<'a> for NestedComponent<'a> { 305 fn parse(parser: Parser<'a>) -> Result<Self> { 306 parser.depth_check()?; 307 308 let span = parser.parse::<kw::component>()?.0; 309 let id = parser.parse()?; 310 let name = parser.parse()?; 311 let exports = parser.parse()?; 312 313 let kind = if let Some(import) = parser.parse()? { 314 NestedComponentKind::Import { 315 import, 316 ty: parser.parse()?, 317 } 318 } else { 319 let mut fields = Vec::new(); 320 while !parser.is_empty() { 321 fields.push(parser.parens(|p| p.parse())?); 322 } 323 NestedComponentKind::Inline(fields) 324 }; 325 326 Ok(NestedComponent { 327 span, 328 id, 329 name, 330 exports, 331 kind, 332 }) 333 } 334}