1use crate::ast::*;
2use crate::lexer::{Float, LexError, Lexer, NumBase, Sign, Token};
3use crate::source::describe_position;
4use std::borrow::Cow;
5use std::char;
6use std::collections::HashMap;
7use std::f32;
8use std::f64;
9use std::fmt;
10use std::mem;
11use std::ops;
12use std::str;
13use std::str::FromStr;
14
15#[cfg_attr(test, derive(Debug))]
16pub enum ParseErrorKind<'source> {
17 LexError(LexError<'source>),
18 UnexpectedToken {
19 got: Token<'source>,
20 expected: &'static str, },
22 UnexpectedEndOfFile {
23 expected: &'static str, },
25 UnexpectedKeyword(&'source str),
26 InvalidValType(&'source str),
27 MalformedUtf8Encoding,
28 MissingParen {
29 paren: char,
30 got: Option<Token<'source>>,
31 what: &'source str,
32 },
33 InvalidOperand {
34 insn: &'static str,
35 msg: &'static str,
36 },
37 NumberMustBePositive(NumBase, &'source str),
38 CannotParseNum {
39 reason: String,
40 ty: &'static str,
41 },
42 MultipleEntrypoints(Start<'source>, Start<'source>),
43 IdAlreadyDefined {
44 id: &'source str,
45 prev_idx: u32,
46 what: &'static str,
47 scope: &'static str,
48 },
49 ExpectEndOfFile {
50 token: Token<'source>,
51 after: &'static str,
52 },
53 ImportMustPrecedeOtherDefs {
54 what: &'static str,
55 },
56 InvalidAlignment(u32),
57 IdBoundToParam(&'source str),
58}
59
60#[cfg_attr(test, derive(Debug))]
61pub struct ParseError<'s> {
62 kind: ParseErrorKind<'s>,
63 offset: usize,
64 source: &'s str,
65}
66
67impl<'s> ParseError<'s> {
68 fn new(kind: ParseErrorKind<'s>, offset: usize, source: &'s str) -> Box<ParseError<'s>> {
69 Box::new(ParseError { kind, offset, source })
70 }
71
72 pub fn offset(&self) -> usize {
73 self.offset
74 }
75
76 pub fn source(&self) -> &'s str {
77 self.source
78 }
79}
80
81impl<'s> fmt::Display for ParseError<'s> {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 use ParseErrorKind::*;
84 match &self.kind {
85 LexError(err) => return err.fmt(f),
86 UnexpectedToken { got, expected } => write!(f, "expected {} but got {}", expected, got)?,
87 UnexpectedEndOfFile { expected } => write!(f, "expected {} but reached EOF", expected)?,
88 UnexpectedKeyword(kw) => write!(f, "unexpected keyword '{}'", kw)?,
89 InvalidValType(ty) => write!(
90 f,
91 "value type must be one of 'i32', 'i64', 'f32', 'f64' but got '{}'",
92 ty
93 )?,
94 MalformedUtf8Encoding => write!(f, "Name must be valid UTF-8 encoding characters")?,
95 NumberMustBePositive(base, s) => write!(f, "number must be positive but got -{}{}", base.prefix(), s)?,
96 MissingParen {
97 paren,
98 got: Some(tok),
99 what,
100 } => write!(f, "expected paren '{}' for {} but got {}", paren, what, tok)?,
101 MissingParen { paren, got: None, what } => {
102 write!(f, "expected paren '{}' for {} but reached EOF", paren, what)?
103 }
104 InvalidOperand { insn, msg } => write!(f, "invalid operand for '{}' instruction: {}", insn, msg)?,
105 CannotParseNum { reason, ty } => write!(f, "cannot parse {} number: {}", ty, reason)?,
106 MultipleEntrypoints(prev, cur) => write!(
107 f,
108 "module cannot contain multiple 'start' functions {}. previous start function was {} at offset {}",
109 cur.idx, prev.idx, prev.start
110 )?,
111 IdAlreadyDefined {
112 id,
113 prev_idx,
114 what,
115 scope,
116 } => write!(
117 f,
118 "identifier '{}' for {} is already defined for index {} in the {}",
119 id, what, prev_idx, scope
120 )?,
121 ExpectEndOfFile { after, token } => write!(f, "expect EOF but got {} after parsing {}", token, after)?,
122 ImportMustPrecedeOtherDefs { what } => write!(
123 f,
124 "import {} must be put before other function, memory, table and global definitions",
125 what
126 )?,
127 InvalidAlignment(align) => write!(f, "alignment must be power of two but got {}", align)?,
128 IdBoundToParam(id) => write!(f, "id '{}' must not be bound to parameter of call_indirect", id)?,
129 };
130
131 describe_position(f, self.source, self.offset)
132 }
133}
134
135impl<'s> From<Box<LexError<'s>>> for Box<ParseError<'s>> {
136 fn from(err: Box<LexError<'s>>) -> Box<ParseError<'s>> {
137 Box::new(ParseError {
138 source: err.source(),
139 offset: err.offset(),
140 kind: ParseErrorKind::LexError(*err),
141 })
142 }
143}
144
145type Result<'s, T> = ::std::result::Result<T, Box<ParseError<'s>>>;
146
147#[derive(Clone)]
150pub struct LookAhead<I: Iterator> {
151 it: I,
152 current: Option<I::Item>,
153 incoming: Option<I::Item>,
154}
155
156impl<I: Iterator> LookAhead<I> {
157 pub fn new(mut it: I) -> Self {
158 let current = it.next();
159 let incoming = it.next();
160 LookAhead { it, current, incoming }
161 }
162 pub fn peek(&self) -> Option<&I::Item> {
163 self.current.as_ref()
164 }
165 pub fn lookahead(&self) -> Option<&I::Item> {
166 self.incoming.as_ref()
167 }
168 pub fn inner(&self) -> &I {
169 &self.it
170 }
171}
172
173impl<I: Iterator> Iterator for LookAhead<I> {
174 type Item = I::Item;
175
176 fn next(&mut self) -> Option<Self::Item> {
177 mem::replace(&mut self.current, mem::replace(&mut self.incoming, self.it.next()))
180 }
181}
182
183struct Indices<'s> {
184 source: &'s str,
185 next_idx: u32,
186 indices: HashMap<&'s str, u32>,
187 what: &'static str,
188 scope: &'static str,
189}
190
191impl<'s> Indices<'s> {
192 fn new(source: &'s str, what: &'static str, scope: &'static str) -> Self {
193 Self {
194 source,
195 next_idx: 0,
196 indices: HashMap::new(),
197 what,
198 scope,
199 }
200 }
201
202 fn error<T>(&self, kind: ParseErrorKind<'s>, offset: usize) -> Result<'s, T> {
203 Err(ParseError::new(kind, offset, self.source))
204 }
205
206 fn new_idx(&mut self, id: Option<&'s str>, offset: usize) -> Result<'s, u32> {
207 let idx = self.next_idx;
208 if let Some(id) = id {
209 if let Some(prev_idx) = self.indices.insert(id, idx) {
210 return self.error(
211 ParseErrorKind::IdAlreadyDefined {
212 id,
213 prev_idx,
214 what: self.what,
215 scope: self.scope,
216 },
217 offset,
218 );
219 }
220 }
221 self.next_idx += 1;
222 Ok(idx)
223 }
224
225 fn move_out(&mut self) -> HashMap<&'s str, u32> {
226 self.next_idx = 0; mem::take(&mut self.indices)
228 }
229}
230
231struct ParseContext<'s> {
233 types: Vec<TypeDef<'s>>,
236 exports: Vec<Export<'s>>,
237 type_indices: Indices<'s>,
240 func_indices: Indices<'s>,
241 table_indices: Indices<'s>,
242 mem_indices: Indices<'s>,
243 global_indices: Indices<'s>,
244 implicit_type_uses: Vec<ImplicitTypeUse<'s>>,
245}
246
247impl<'s> ParseContext<'s> {
248 fn new(source: &'s str) -> Self {
249 ParseContext {
250 types: vec![],
251 exports: vec![],
252 type_indices: Indices::new(source, "type", "module"),
253 func_indices: Indices::new(source, "func", "module"),
254 table_indices: Indices::new(source, "table", "module"),
255 mem_indices: Indices::new(source, "memory", "module"),
256 global_indices: Indices::new(source, "global", "module"),
257 implicit_type_uses: vec![],
258 }
259 }
260}
261
262trait IsInfinite: Copy {
263 fn is_infinite(self) -> bool;
264}
265
266impl IsInfinite for f32 {
267 fn is_infinite(self) -> bool {
268 self.is_infinite()
269 }
270}
271
272impl IsInfinite for f64 {
273 fn is_infinite(self) -> bool {
274 self.is_infinite()
275 }
276}
277
278pub struct Parser<'s> {
281 source: &'s str,
282 tokens: LookAhead<Lexer<'s>>,
283 ctx: ParseContext<'s>,
284}
285
286impl<'s> Parser<'s> {
287 pub fn new(source: &'s str) -> Self {
288 Parser {
289 source,
290 tokens: LookAhead::new(Lexer::new(source)),
291 ctx: ParseContext::new(source),
292 }
293 }
294
295 pub fn with_lexer(lexer: LookAhead<Lexer<'s>>) -> Self {
296 Parser {
297 source: lexer.inner().source(),
298 ctx: ParseContext::new(lexer.inner().source()),
299 tokens: lexer,
300 }
301 }
302
303 pub fn source(&self) -> &'s str {
304 self.source
305 }
306
307 pub fn into_lexer(self) -> LookAhead<Lexer<'s>> {
308 self.tokens
309 }
310
311 pub fn is_done(&self) -> bool {
312 self.tokens.peek().is_none()
313 }
314
315 pub fn parse_wat(mut self) -> Result<'s, Parsed<'s>> {
316 self.parse()
317 }
318
319 pub fn parse<P: Parse<'s>>(&mut self) -> Result<'s, P> {
320 Parse::<'s>::parse(self)
321 }
322
323 fn error<T>(&self, kind: ParseErrorKind<'s>, offset: usize) -> Result<'s, T> {
324 Err(ParseError::new(kind, offset, self.source))
325 }
326
327 fn unexpected_token<T>(&self, got: Token<'s>, expected: &'static str, offset: usize) -> Result<'s, T> {
328 self.error(ParseErrorKind::UnexpectedToken { got, expected }, offset)
329 }
330
331 fn unexpected_eof<T>(&self, expected: &'static str) -> Result<'s, T> {
332 self.error(ParseErrorKind::UnexpectedEndOfFile { expected }, self.source().len())
333 }
334
335 fn cannot_parse_num<T, S: ToString>(&self, ty: &'static str, reason: S, offset: usize) -> Result<'s, T> {
336 self.error(
337 ParseErrorKind::CannotParseNum {
338 reason: reason.to_string(),
339 ty,
340 },
341 offset,
342 )
343 }
344
345 fn maybe_eof<'p>(
346 &'p self,
347 lexed: Option<&'p <Lexer<'s> as Iterator>::Item>,
348 expected: &'static str,
349 ) -> Result<'s, (&Token<'s>, usize)> {
350 match lexed {
351 Some(Ok((tok, offset))) => Ok((tok, *offset)),
352 Some(Err(err)) => Err(err.clone().into()),
353 None => self.unexpected_eof(expected),
354 }
355 }
356
357 fn lookahead(&self, expected: &'static str) -> Result<'s, (&Token<'s>, usize)> {
358 self.maybe_eof(self.tokens.lookahead(), expected)
359 }
360
361 fn peek(&self, expected: &'static str) -> Result<'s, (&Token<'s>, usize)> {
362 self.maybe_eof(self.tokens.peek(), expected)
363 }
364
365 pub fn current_pos(&self) -> Result<'s, Option<usize>> {
366 match self.tokens.peek() {
367 Some(Ok((_, pos))) => Ok(Some(*pos)),
368 Some(Err(err)) => Err(err.clone().into()),
369 None => Ok(None),
370 }
371 }
372
373 fn next_token(&mut self, expected: &'static str) -> Result<'s, (Token<'s>, usize)> {
374 match self.tokens.next() {
375 Some(lexed) => Ok(lexed?),
376 None => self.unexpected_eof(expected),
377 }
378 }
379
380 fn eat_token(&mut self) -> bool {
381 self.tokens.next().is_some()
382 }
383
384 fn peek_fold_start(&self, expected: &'static str) -> Result<'s, (Option<&'s str>, usize)> {
385 match self.peek(expected)? {
386 (Token::LParen, offset) => match self.lookahead(expected)? {
387 (Token::Keyword(kw), _) => Ok((Some(*kw), offset)),
388 (tok, offset) => self.unexpected_token(tok.clone(), expected, offset),
389 },
390 (_, offset) => Ok((None, offset)),
391 }
392 }
393
394 fn maybe_ident(&mut self, expected: &'static str) -> Result<'s, Option<&'s str>> {
395 Ok(match self.peek(expected)? {
396 (Token::Ident(id), _) => {
397 let id = *id;
398 self.eat_token();
399 Some(id)
400 }
401 _ => None,
402 })
403 }
404
405 fn missing_paren<T>(
406 &mut self,
407 paren: char,
408 got: Option<Token<'s>>,
409 what: &'static str,
410 offset: usize,
411 ) -> Result<'s, T> {
412 self.error(ParseErrorKind::MissingParen { paren, got, what }, offset)
413 }
414
415 fn opening_paren(&mut self, what: &'static str) -> Result<'s, usize> {
416 if let Some(lexed) = self.tokens.next() {
417 match lexed? {
418 (Token::LParen, offset) => Ok(offset),
419 (tok, offset) => self.missing_paren('(', Some(tok), what, offset),
420 }
421 } else {
422 self.missing_paren('(', None, what, self.source.len())
423 }
424 }
425
426 fn closing_paren(&mut self, what: &'static str) -> Result<'s, usize> {
427 if let Some(lexed) = self.tokens.next() {
428 match lexed? {
429 (Token::RParen, offset) => Ok(offset),
430 (tok, offset) => self.missing_paren(')', Some(tok), what, offset),
431 }
432 } else {
433 self.missing_paren(')', None, what, self.source.len())
434 }
435 }
436
437 fn parse_u32(&mut self, expected: &'static str) -> Result<'s, u32> {
438 match self.next_token(expected)? {
439 (Token::Int(Sign::Minus, base, s), offset) => {
440 self.error(ParseErrorKind::NumberMustBePositive(base, s), offset)
441 }
442 (Token::Int(Sign::Plus, base, s), offset) => parse_u32_str(self, s, base, offset),
443 (tok, offset) => self.unexpected_token(tok.clone(), expected, offset),
444 }
445 }
446
447 fn parse_dec_float<F>(
448 &self,
449 sign: Sign,
450 frac: &'s str,
451 exp: Option<(Sign, &'s str)>,
452 offset: usize,
453 ) -> Result<'s, F>
454 where
455 F: FromStr + ops::Neg<Output = F> + IsInfinite,
456 F::Err: fmt::Display,
457 {
458 let mut s: String = frac.chars().filter(|c| *c != '_').collect();
460 if let Some((sign, exp)) = exp {
461 s.push('e');
462 if sign == Sign::Minus {
463 s.push('-');
464 }
465 for c in exp.chars().filter(|c| *c != '_') {
466 s.push(c);
467 }
468 }
469 match s.parse::<F>() {
470 Ok(f) if f.is_infinite() => self.cannot_parse_num("float", "float constant out of range", offset),
471 Ok(f) => Ok(sign.apply(f)),
472 Err(e) => self.cannot_parse_num("float", format!("{}", e), offset),
473 }
474 }
475
476 fn parse_mem_arg(&mut self, default_align: u32) -> Result<'s, Mem> {
477 fn base_and_digits(s: &str) -> (NumBase, &'_ str) {
478 if let Some(hex) = s.strip_prefix("0x") {
479 (NumBase::Hex, hex)
480 } else {
481 (NumBase::Dec, s)
482 }
483 }
484
485 let offset = match self.peek("'offset' keyword for memory instruction")? {
486 (Token::Keyword(kw), offset) if kw.starts_with("offset=") => {
487 let (base, digits) = base_and_digits(&kw[7..]);
488 let u = parse_u32_str(self, digits, base, offset)?;
489 self.eat_token(); u
491 }
492 _ => 0,
493 };
494
495 let align = match self.peek("'align' keyword for memory instruction")? {
496 (Token::Keyword(kw), offset) if kw.starts_with("align=") => {
497 let (base, digits) = base_and_digits(&kw[6..]);
498 let u = parse_u32_str(self, digits, base, offset)?;
499 if u.count_ones() != 1 {
500 return self.error(ParseErrorKind::InvalidAlignment(u), offset);
501 }
502 self.eat_token(); u.trailing_zeros()
504 }
505 _ => default_align,
506 };
507
508 Ok(Mem { align, offset })
509 }
510
511 fn create_inline_typeuse(&mut self, start: usize, params: &[Param<'s>], results: &[FuncResult]) -> u32 {
512 let idx = self.ctx.implicit_type_uses.len();
513 self.ctx.implicit_type_uses.push(ImplicitTypeUse {
514 start,
515 params: params.to_vec(),
516 results: results.to_vec(),
517 });
518 idx as u32
519 }
520
521 fn resolve_implicit_type_uses(&mut self) -> Vec<u32> {
522 let mut resolved = Vec::with_capacity(self.ctx.implicit_type_uses.len());
537 for ImplicitTypeUse { start, params, results } in mem::take(&mut self.ctx.implicit_type_uses).into_iter() {
538 let idx = if let Some(idx) = self.ctx.types.iter().enumerate().find_map(|(i, TypeDef { ty, .. })| {
539 if ty.params.iter().map(|t| t.ty).eq(params.iter().map(|t| t.ty))
540 && ty.results.iter().map(|t| t.ty).eq(results.iter().map(|t| t.ty))
541 {
542 Some(i)
543 } else {
544 None
545 }
546 }) {
547 idx
548 } else {
549 self.ctx.types.push(TypeDef {
550 start,
551 id: None,
552 ty: FuncType { start, params, results },
553 });
554 self.ctx.types.len() - 1
555 };
556 resolved.push(idx as u32);
557 }
558 resolved
559 }
560}
561
562macro_rules! parse_uint_function {
564 ($name:ident, $uint:ty) => {
565 fn $name<'s>(parser: &Parser<'s>, input: &'s str, base: NumBase, offset: usize) -> Result<'s, $uint> {
566 let radix = base.radix();
567 let mut ret: $uint = 0;
568 for c in input.chars() {
569 if c == '_' {
570 continue;
572 }
573 if let Some(d) = c.to_digit(radix) {
574 if let Some(added) = ret
575 .checked_mul(radix as $uint)
576 .and_then(|i| i.checked_add(d as $uint))
577 {
578 ret = added;
579 } else {
580 return parser.cannot_parse_num(stringify!($uint), "too big integer", offset);
581 }
582 } else {
583 return parser.cannot_parse_num(stringify!($uint), format!("invalid digit '{}'", c), offset);
584 }
585 }
586 Ok(ret)
587 }
588 };
589}
590
591parse_uint_function!(parse_u32_str, u32);
592parse_uint_function!(parse_u64_str, u64);
593
594macro_rules! parse_hex_float_fn {
595 ($name:ident, $float:ty, $uint:ty) => {
596 fn $name<'s>(parser: &Parser<'s>, sign: Sign, m_str: &'s str, exp: Option<(Sign, &'s str)>, offset: usize) -> Result<'s, $float> {
597 let mut temp_exp = if let Some((exp_sign, exp_str)) = exp {
601 match parse_u32_str(parser, exp_str, NumBase::Dec, offset) {
602 Ok(exp) if exp_sign == Sign::Plus && exp as i32 >= 0 => exp as i32,
603 Ok(exp) if exp_sign == Sign::Minus && exp.wrapping_neg() as i32 <= 0 => exp.wrapping_neg() as i32,
604 _ => {
605 return parser.cannot_parse_num(
609 stringify!($float),
610 format!("exponent value out of range '{}{}'", exp_sign, exp_str),
611 offset,
612 );
613 }
614 }
615 } else {
616 0
617 };
618
619 const SIGNIFICAND_BITS: i32 = <$float>::MANTISSA_DIGITS as i32;
620
621 let mut temp_sig: $uint = 0;
624 let mut saw_dot = false;
625 for c in m_str.chars() {
626 match c {
627 '.' => saw_dot = true,
628 '_' => continue,
629 _ if temp_sig < 1 << SIGNIFICAND_BITS + 1 => {
632 temp_sig = (temp_sig << 4) | c.to_digit(16).unwrap() as $uint;
635 if saw_dot {
636 temp_exp = temp_exp.saturating_sub(4);
638 }
639 }
640 _ => {
644 temp_sig |= (c != '0') as $uint;
646 if !saw_dot {
647 temp_exp = temp_exp.saturating_add(4);
649 }
650 }
651 }
652 }
653
654 if temp_sig != 0 {
656 const BITS: i32 = (mem::size_of::<$float>() * 8) as i32;
657 const TEMP_SIG_BITS: i32 = SIGNIFICAND_BITS + 4 + 1;
663 const TEMP_EXP_BIAS: i32 = (<$float>::MAX_EXP - 1) + (TEMP_SIG_BITS - 1);
670 const TEMP_MAX_EXP: i32 = (<$float>::MAX_EXP - 1) - (TEMP_SIG_BITS - 1);
673 const TEMP_MIN_EXP: i32 = (<$float>::MIN_EXP - 1) - (TEMP_SIG_BITS - 1);
674
675 if temp_sig < 1 << TEMP_SIG_BITS - 1 {
676 let shift = temp_sig.leading_zeros() as i32 - (BITS - TEMP_SIG_BITS);
680 temp_sig <<= shift;
681 temp_exp = temp_exp.saturating_sub(shift);
682 }
683
684 temp_sig = if TEMP_MIN_EXP <= temp_exp && temp_exp <= TEMP_MAX_EXP {
685 temp_sig &= (1 << TEMP_SIG_BITS - 1) - 1;
690
691 if (temp_sig & 0x2f) != 0 {
711 temp_sig += 0x10;
712 }
713
714 (temp_sig >> 5) + ((temp_exp + TEMP_EXP_BIAS) as $uint << SIGNIFICAND_BITS - 1)
716 } else if TEMP_MIN_EXP - SIGNIFICAND_BITS <= temp_exp && temp_exp < TEMP_MIN_EXP {
717 let shift = TEMP_MIN_EXP - temp_exp;
723 let lsb = ((temp_sig & (1 << shift) - 1) != 0) as $uint;
724 temp_sig = (temp_sig >> shift) | lsb;
725
726 if (temp_sig & 0x2f) != 0 {
728 temp_sig += 0x10;
729 }
730
731 temp_sig >> 5
733 } else if TEMP_MAX_EXP < temp_exp {
734 (1 << BITS - SIGNIFICAND_BITS) - 1 << SIGNIFICAND_BITS - 1
736 } else {
737 0
739 };
740 }
741
742 let f = <$float>::from_bits(temp_sig);
743 if f.is_infinite() {
744 return parser.cannot_parse_num(
745 stringify!($float),
746 "float constant out of range",
747 offset,
748 );
749 }
750
751 Ok(sign.apply(f))
753 }
754 };
755}
756
757parse_hex_float_fn!(parse_hex_float_f32, f32, u32);
758parse_hex_float_fn!(parse_hex_float_f64, f64, u64);
759
760macro_rules! match_token {
761 ($parser:expr, $expected:expr, $pattern:pat => $ret:expr) => {
762 match $parser.next_token($expected)? {
763 ($pattern, offset) => ($ret, offset),
764 (tok, offset) => {
765 return $parser.unexpected_token(tok, $expected, offset);
766 }
767 }
768 };
769 ($parser:expr, $expected:expr, $pattern:pat) => {
770 match_token!($parser, $expected, $pattern => ())
771 };
772}
773
774pub trait Parse<'s>: Sized {
775 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self>;
776}
777
778impl<'s> Parse<'s> for Parsed<'s> {
780 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
781 Ok(Parsed {
782 module: parser.parse()?,
783 type_indices: parser.ctx.type_indices.move_out(),
784 func_indices: parser.ctx.func_indices.move_out(),
785 table_indices: parser.ctx.table_indices.move_out(),
786 mem_indices: parser.ctx.mem_indices.move_out(),
787 global_indices: parser.ctx.global_indices.move_out(),
788 })
789 }
790}
791
792#[cfg_attr(test, derive(Debug))]
796enum ModuleField<'s> {
797 Type(TypeDef<'s>),
798 Import(ImportItem<'s>),
799 Export(Export<'s>),
800 Func(Func<'s>),
801 Elem(Elem<'s>),
802 Table(TableAbbrev<'s>),
803 Data(Data<'s>),
804 Memory(MemoryAbbrev<'s>),
805 Global(Global<'s>),
806 Start(Start<'s>),
807}
808
809impl<'s> Parse<'s> for Module<'s> {
811 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
812 let (keyword, start) = parser.peek_fold_start("module")?;
819 let abbreviated = keyword != Some("module");
820 if !abbreviated {
821 parser.eat_token(); parser.eat_token(); }
824
825 let id = parser.maybe_ident("identifier for module")?;
826
827 let mut funcs = vec![];
828 let mut elems = vec![];
829 let mut tables = vec![];
830 let mut data = vec![];
831 let mut memories = vec![];
832 let mut globals = vec![];
833 let mut entrypoint = None;
834
835 let mut can_import = true;
844
845 parser.ctx.types.clear();
848 parser.ctx.exports.clear();
849
850 loop {
851 match parser.tokens.peek() {
852 Some(Ok((Token::LParen, _))) => {} Some(Ok(_)) => break,
854 Some(Err(err)) => return Err(err.clone().into()),
855 None if abbreviated => break, None => return parser.unexpected_eof("opening paren for starting module field"),
857 }
858
859 match parser.parse()? {
860 ModuleField::Type(ty) => parser.ctx.types.push(ty),
861 ModuleField::Import(ImportItem::Func(func)) if !can_import => {
862 return parser.error(
863 ParseErrorKind::ImportMustPrecedeOtherDefs { what: "function" },
864 func.start,
865 );
866 }
867 ModuleField::Import(ImportItem::Func(func)) => funcs.push(func),
868 ModuleField::Import(ImportItem::Table(table)) if !can_import => {
869 return parser.error(
870 ParseErrorKind::ImportMustPrecedeOtherDefs { what: "table" },
871 table.start,
872 );
873 }
874 ModuleField::Import(ImportItem::Table(table)) => tables.push(table),
875 ModuleField::Import(ImportItem::Memory(memory)) if !can_import => {
876 return parser.error(
877 ParseErrorKind::ImportMustPrecedeOtherDefs { what: "memory" },
878 memory.start,
879 );
880 }
881 ModuleField::Import(ImportItem::Memory(memory)) => memories.push(memory),
882 ModuleField::Import(ImportItem::Global(global)) if !can_import => {
883 return parser.error(
884 ParseErrorKind::ImportMustPrecedeOtherDefs { what: "global" },
885 global.start,
886 );
887 }
888 ModuleField::Import(ImportItem::Global(global)) => globals.push(global),
889 ModuleField::Export(export) => parser.ctx.exports.push(export),
890 ModuleField::Func(func) => {
891 if let FuncKind::Body { .. } = func.kind {
892 can_import = false;
893 } else if !can_import {
894 return parser.error(
895 ParseErrorKind::ImportMustPrecedeOtherDefs { what: "function" },
896 func.start,
897 );
898 }
899 funcs.push(func);
900 }
901 ModuleField::Elem(elem) => elems.push(elem),
902 ModuleField::Table(TableAbbrev::Table(table)) => {
903 if table.import.is_none() {
904 can_import = false;
905 } else if !can_import {
906 return parser.error(
907 ParseErrorKind::ImportMustPrecedeOtherDefs { what: "table" },
908 table.start,
909 );
910 }
911 tables.push(table);
912 }
913 ModuleField::Table(TableAbbrev::Elem(table, elem)) => {
914 if table.import.is_none() {
915 can_import = false;
916 } else if !can_import {
917 return parser.error(
918 ParseErrorKind::ImportMustPrecedeOtherDefs { what: "table" },
919 table.start,
920 );
921 }
922 tables.push(table);
923 elems.push(elem);
924 }
925 ModuleField::Data(d) => data.push(d),
926 ModuleField::Memory(MemoryAbbrev::Memory(m)) => {
927 if m.import.is_none() {
928 can_import = false;
929 } else if !can_import {
930 return parser.error(ParseErrorKind::ImportMustPrecedeOtherDefs { what: "memory" }, m.start);
931 }
932 memories.push(m);
933 }
934 ModuleField::Memory(MemoryAbbrev::Data(m, d)) => {
935 if m.import.is_none() {
936 can_import = false;
937 } else if !can_import {
938 return parser.error(ParseErrorKind::ImportMustPrecedeOtherDefs { what: "memory" }, m.start);
939 }
940 memories.push(m);
941 data.push(d);
942 }
943 ModuleField::Global(global) => {
944 if let GlobalKind::Init(_) = global.kind {
945 can_import = false;
946 } else if !can_import {
947 return parser.error(
948 ParseErrorKind::ImportMustPrecedeOtherDefs { what: "global" },
949 global.start,
950 );
951 }
952 globals.push(global);
953 }
954 ModuleField::Start(start) => {
955 if let Some(prev) = entrypoint {
956 let offset = start.start;
957 return parser.error(ParseErrorKind::MultipleEntrypoints(prev, start), offset);
958 } else {
959 entrypoint = Some(start);
960 }
961 }
962 }
963 }
964
965 if abbreviated {
966 if let Some(Ok((token, offset))) = parser.tokens.peek() {
967 return parser.error(
968 ParseErrorKind::ExpectEndOfFile {
969 token: token.clone(),
970 after: "abbreviated module",
971 },
972 *offset,
973 );
974 }
975 } else {
976 parser.closing_paren("module")?;
977 }
978
979 Ok(Module {
980 start,
981 id,
982 implicit_type_uses: parser.resolve_implicit_type_uses(), types: mem::take(&mut parser.ctx.types),
984 exports: mem::take(&mut parser.ctx.exports),
985 funcs,
986 elems,
987 tables,
988 data,
989 memories,
990 globals,
991 entrypoint,
992 })
993 }
994}
995
996impl<'s> Parse<'s> for ModuleField<'s> {
998 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
999 let expected = "one of 'type', 'import', 'export', 'func', 'elem', 'table', 'data', 'memory', 'global', 'start' sections in module";
1000 match parser.peek_fold_start(expected)? {
1001 (Some(kw), offset) => match kw {
1002 "type" => Ok(ModuleField::Type(parser.parse()?)),
1003 "import" => Ok(ModuleField::Import(parser.parse()?)),
1004 "export" => Ok(ModuleField::Export(parser.parse()?)),
1005 "func" => Ok(ModuleField::Func(parser.parse()?)),
1006 "elem" => Ok(ModuleField::Elem(parser.parse()?)),
1007 "table" => Ok(ModuleField::Table(parser.parse()?)),
1008 "data" => Ok(ModuleField::Data(parser.parse()?)),
1009 "memory" => Ok(ModuleField::Memory(parser.parse()?)),
1010 "global" => Ok(ModuleField::Global(parser.parse()?)),
1011 "start" => Ok(ModuleField::Start(parser.parse()?)),
1012 _ => parser.error(ParseErrorKind::UnexpectedKeyword(kw), offset),
1013 },
1014 (None, offset) => {
1015 let token = parser.peek(expected)?.0.clone();
1016 parser.unexpected_token(token, expected, offset)
1017 }
1018 }
1019 }
1020}
1021
1022impl<'s> Parse<'s> for TypeDef<'s> {
1024 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1025 let start = parser.opening_paren("type")?;
1026 match_token!(parser, "'type' keyword", Token::Keyword("type"));
1027 let id = parser.maybe_ident("identifier for type")?;
1028 let ty = parser.parse()?;
1029 parser.closing_paren("type")?;
1030 parser.ctx.type_indices.new_idx(id, start)?;
1031 Ok(TypeDef { start, id, ty })
1032 }
1033}
1034
1035impl<'s> Parse<'s> for FuncType<'s> {
1037 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1038 let start = parser.opening_paren("function type")?;
1039 match_token!(parser, "'func' keyword", Token::Keyword("func"));
1040
1041 let params = parser.parse()?;
1042 let results = parser.parse()?;
1043
1044 parser.closing_paren("function type")?;
1045 Ok(FuncType { start, params, results })
1046 }
1047}
1048
1049impl<'s> Parse<'s> for Vec<Param<'s>> {
1052 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1053 let mut params = vec![];
1054 while let (Some("param"), start) = parser.peek_fold_start("parameter")? {
1055 parser.eat_token(); parser.eat_token(); let id = parser.maybe_ident("identifier for param")?;
1059 if id.is_some() {
1060 let ty = parser.parse()?;
1062 parser.closing_paren("parameter")?;
1063 params.push(Param { start, id, ty });
1064 continue;
1065 }
1066
1067 loop {
1070 match parser.peek("value type for param or closing ')'")? {
1071 (Token::RParen, _) => {
1072 parser.eat_token(); break;
1074 }
1075 (_, start) => {
1076 let ty = parser.parse()?;
1077 params.push(Param { start, id, ty });
1078 }
1079 }
1080 }
1081 }
1082 Ok(params)
1083 }
1084}
1085
1086impl<'s> Parse<'s> for ValType {
1088 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1089 let expected = "keyword for value type";
1090 match parser.next_token(expected)? {
1091 (Token::Keyword("i32"), _) => Ok(ValType::I32),
1092 (Token::Keyword("i64"), _) => Ok(ValType::I64),
1093 (Token::Keyword("f32"), _) => Ok(ValType::F32),
1094 (Token::Keyword("f64"), _) => Ok(ValType::F64),
1095 (Token::Keyword(id), offset) => parser.error(ParseErrorKind::InvalidValType(id), offset),
1096 (tok, offset) => parser.unexpected_token(tok, expected, offset),
1097 }
1098 }
1099}
1100
1101impl<'s> Parse<'s> for Vec<FuncResult> {
1104 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1105 let mut results = vec![];
1106 while let Some("result") = parser.peek_fold_start("result type")?.0 {
1107 parser.eat_token(); parser.eat_token(); loop {
1113 match parser.peek("value type for result or closing ')'")? {
1114 (Token::RParen, _) => {
1115 parser.eat_token(); break;
1117 }
1118 (_, start) => {
1119 let ty = parser.parse()?;
1120 results.push(FuncResult { start, ty });
1121 }
1122 }
1123 }
1124 }
1125 Ok(results)
1126 }
1127}
1128
1129impl<'s> Parse<'s> for Name<'s> {
1131 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1132 let (content, offset) = match_token!(parser, "string literal for name", Token::String(s, _) => s);
1134 let encoded = match content {
1135 Cow::Borrowed(slice) => str::from_utf8(slice).ok().map(Cow::Borrowed),
1136 Cow::Owned(vec) => String::from_utf8(vec).ok().map(Cow::Owned),
1137 };
1138 if let Some(encoded) = encoded {
1139 Ok(Name(encoded))
1140 } else {
1141 parser.error(ParseErrorKind::MalformedUtf8Encoding, offset)
1142 }
1143 }
1144}
1145
1146impl<'s> Parse<'s> for Import<'s> {
1149 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1150 let mod_name = parser.parse()?;
1151 let name = parser.parse()?;
1152 Ok(Import { mod_name, name })
1153 }
1154}
1155
1156#[cfg_attr(test, derive(Debug))]
1158enum ImportItem<'s> {
1159 Func(Func<'s>),
1160 Table(Table<'s>),
1161 Memory(Memory<'s>),
1162 Global(Global<'s>),
1163}
1164impl<'s> Parse<'s> for ImportItem<'s> {
1165 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1166 let start = parser.opening_paren("import")?;
1167 match_token!(parser, "'import' keyword", Token::Keyword("import"));
1168 let import = parser.parse()?;
1169
1170 parser.opening_paren("import item")?;
1171 let (keyword, offset) =
1172 match_token!(parser, "one of 'func', 'table', 'memory', 'global'", Token::Keyword(kw) => kw);
1173
1174 let id = parser.maybe_ident("identifier for import item")?;
1175
1176 let item = match keyword {
1178 "func" => {
1179 parser.ctx.func_indices.new_idx(id, start)?;
1180 ImportItem::Func(Func {
1181 start,
1182 id,
1183 ty: parser.parse()?,
1184 kind: FuncKind::Import(import),
1185 })
1186 }
1187 "table" => {
1188 parser.ctx.table_indices.new_idx(id, start)?;
1189 ImportItem::Table(Table {
1190 start,
1191 id,
1192 ty: parser.parse()?,
1193 import: Some(import),
1194 })
1195 }
1196 "memory" => {
1197 parser.ctx.mem_indices.new_idx(id, start)?;
1198 ImportItem::Memory(Memory {
1199 start,
1200 id,
1201 ty: parser.parse()?,
1202 import: Some(import),
1203 })
1204 }
1205 "global" => {
1206 parser.ctx.global_indices.new_idx(id, start)?;
1207 ImportItem::Global(Global {
1208 start,
1209 id,
1210 ty: parser.parse()?,
1211 kind: GlobalKind::Import(import),
1212 })
1213 }
1214 kw => return parser.error(ParseErrorKind::UnexpectedKeyword(kw), offset),
1215 };
1216
1217 parser.closing_paren("import item")?;
1218 parser.closing_paren("import")?;
1219 Ok(item)
1220 }
1221}
1222
1223impl<'s> Parse<'s> for TypeUse<'s> {
1225 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1226 let (keyword, start) = parser.peek_fold_start("type or param or result in typeuse")?;
1227 let idx = if let Some("type") = keyword {
1228 parser.eat_token(); parser.eat_token(); let idx = parser.parse()?;
1231 parser.closing_paren("type")?;
1232 Some(idx)
1233 } else {
1234 None
1235 };
1236
1237 let params: Vec<Param<'s>> = parser.parse()?;
1238 let results: Vec<FuncResult> = parser.parse()?;
1239
1240 Ok(TypeUse {
1241 start,
1242 idx: match idx {
1243 Some(idx) => TypeIndex::Explicit(idx),
1244 None => TypeIndex::Implicit(parser.create_inline_typeuse(start, ¶ms, &results)),
1245 },
1246 params,
1247 results,
1248 })
1249 }
1250}
1251
1252impl<'s> Parse<'s> for Index<'s> {
1254 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1255 let expected = "number or identifier for index";
1256 match parser.next_token(expected)? {
1257 (Token::Int(Sign::Minus, base, s), offset) => {
1258 parser.error(ParseErrorKind::NumberMustBePositive(base, s), offset)
1259 }
1260 (Token::Int(Sign::Plus, base, s), offset) => parse_u32_str(parser, s, base, offset).map(Index::Num),
1261 (Token::Ident(id), _) => Ok(Index::Ident(id)),
1262 (tok, offset) => parser.unexpected_token(tok.clone(), expected, offset),
1263 }
1264 }
1265}
1266
1267impl<'s> Parse<'s> for TableType {
1269 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1270 let limit = parser.parse()?;
1271 match_token!(parser, "'funcref' keyword for table type", Token::Keyword("funcref"));
1272 Ok(TableType { limit })
1273 }
1274}
1275
1276impl<'s> Parse<'s> for Limits {
1278 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1279 let min = parser.parse_u32("u32 for min table limit")?;
1280 Ok(match parser.peek("u32 for max table limit")? {
1281 (Token::Int(..), _) => {
1282 let max = parser.parse_u32("u32 for min table limit")?;
1283 Limits::Range { min, max }
1284 }
1285 _ => Limits::From { min },
1286 })
1287 }
1288}
1289
1290impl<'s> Parse<'s> for MemType {
1292 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1293 parser.parse().map(|limit| MemType { limit })
1294 }
1295}
1296
1297impl<'s> Parse<'s> for GlobalType {
1299 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1300 match parser.peek("'(' for mut or value type of global type")? {
1301 (Token::LParen, _) => {
1302 parser.eat_token(); match_token!(parser, "'mut' keyword for global type", Token::Keyword("mut"));
1304 let ty = parser.parse()?;
1305 parser.closing_paren("mutable global type")?;
1306 Ok(GlobalType { mutable: true, ty })
1307 }
1308 _ => Ok(GlobalType {
1309 mutable: false,
1310 ty: parser.parse()?,
1311 }),
1312 }
1313 }
1314}
1315
1316impl<'s> Parse<'s> for Export<'s> {
1318 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1319 let start = parser.opening_paren("export")?;
1320 match_token!(parser, "'export' keyword for export", Token::Keyword("export"));
1321 let name = parser.parse()?;
1322
1323 parser.opening_paren("export item")?;
1324 let (keyword, offset) = match_token!(parser, "keyword for export item", Token::Keyword(kw) => kw);
1325 let kind = match keyword {
1326 "func" => ExportKind::Func,
1327 "table" => ExportKind::Table,
1328 "memory" => ExportKind::Memory,
1329 "global" => ExportKind::Global,
1330 _ => return parser.error(ParseErrorKind::UnexpectedKeyword(keyword), offset),
1331 };
1332 let idx = parser.parse()?;
1333 parser.closing_paren("export item")?;
1334
1335 parser.closing_paren("export")?;
1336
1337 Ok(Export { start, name, kind, idx })
1338 }
1339}
1340
1341impl<'s> Parse<'s> for Func<'s> {
1343 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1344 let start = parser.opening_paren("func")?;
1345 match_token!(parser, "'func' keyword for func field", Token::Keyword("func"));
1346
1347 let id = parser.maybe_ident("identifier for func field")?;
1351 let idx = parser.ctx.func_indices.new_idx(id, start)?;
1352 loop {
1353 match parser.peek_fold_start("'import', 'export' or typeuse in func field")?.0 {
1354 Some("import") => {
1355 parser.opening_paren("import in func")?;
1358 parser.eat_token(); let import = parser.parse()?;
1360 parser.closing_paren("import in func")?;
1361 let ty = parser.parse()?;
1362 parser.closing_paren("func")?;
1363 return Ok(Func {
1364 start,
1365 id,
1366 ty,
1367 kind: FuncKind::Import(import),
1368 });
1369 }
1370 Some("export") => {
1371 let export_start = parser.opening_paren("export in func")?;
1374 parser.eat_token(); let name = parser.parse()?;
1376 parser.closing_paren("export in func")?;
1377 parser.ctx.exports.push(Export {
1378 start: export_start,
1379 name,
1380 kind: ExportKind::Func,
1381 idx: Index::Num(idx),
1382 });
1383 }
1384 _ => {
1385 let ty = parser.parse()?;
1386 let locals = parser.parse()?;
1387 let body = parser.parse()?;
1388 parser.closing_paren("func")?;
1389 return Ok(Func {
1390 start,
1391 id,
1392 ty,
1393 kind: FuncKind::Body { locals, body },
1394 });
1395 }
1396 }
1397 }
1398 }
1399}
1400
1401impl<'s> Parse<'s> for Vec<Local<'s>> {
1406 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1407 let mut locals = vec![];
1408 while let (Some("local"), start) = parser.peek_fold_start("local")? {
1409 parser.eat_token(); parser.eat_token(); if let Some(id) = parser.maybe_ident("identifier for local")? {
1413 let ty = parser.parse()?;
1414 locals.push(Local {
1415 start,
1416 id: Some(id),
1417 ty,
1418 });
1419 } else {
1420 loop {
1423 match parser.peek("')' or typeuse for local")? {
1424 (Token::RParen, _) => break,
1425 _ => locals.push(Local {
1426 start,
1427 id: None,
1428 ty: parser.parse()?,
1429 }),
1430 }
1431 }
1432 }
1433
1434 parser.closing_paren("local")?;
1435 }
1436 Ok(locals)
1437 }
1438}
1439
1440struct MaybeFoldedInsn<'s, 'p> {
1455 insns: Vec<Instruction<'s>>,
1456 parser: &'p mut Parser<'s>,
1457}
1458
1459fn parse_maybe_result_type<'s>(parser: &mut Parser<'s>) -> Result<'s, Option<ValType>> {
1462 if let Some("result") = parser.peek_fold_start("result type")?.0 {
1464 parser.eat_token(); parser.eat_token(); let ty = parser.parse()?;
1467 parser.closing_paren("result type")?;
1468 Ok(Some(ty))
1469 } else {
1470 Ok(None)
1471 }
1472}
1473
1474impl<'s, 'p> MaybeFoldedInsn<'s, 'p> {
1476 fn new(parser: &'p mut Parser<'s>) -> MaybeFoldedInsn<'s, 'p> {
1477 MaybeFoldedInsn { insns: vec![], parser }
1478 }
1479
1480 fn parse_naked_insn(&mut self, end: bool) -> Result<'s, Instruction<'s>> {
1481 let (kw, start) = match_token!(self.parser, "keyword for instruction", Token::Keyword(k) => k);
1482 let kind = match kw {
1483 "block" | "loop" => {
1486 let label = self.parser.maybe_ident("label for block or loop")?;
1487 let ty = parse_maybe_result_type(self.parser)?;
1488 let body = self.parser.parse()?;
1489 let id = if end {
1490 match_token!(self.parser, "'end' keyword for block or loop", Token::Keyword("end"));
1491 self.parser.maybe_ident("ID for block or loop")?
1492 } else {
1493 None
1494 };
1495 if kw == "block" {
1496 InsnKind::Block { label, ty, body, id }
1497 } else {
1498 InsnKind::Loop { label, ty, body, id }
1499 }
1500 }
1501 "if" => {
1502 let is_folded = !end;
1505 let label = self.parser.maybe_ident("label for block or loop")?;
1506 let ty = parse_maybe_result_type(self.parser)?;
1507
1508 if is_folded {
1514 loop {
1515 let kw = self
1516 .parser
1517 .peek_fold_start("folded instructions for condition in folded 'if' instruction")?
1518 .0;
1519 match kw {
1520 Some("then") => break,
1521 _ => self.parse_folded()?,
1522 }
1523 }
1524 }
1525
1526 if is_folded {
1528 self.parser.opening_paren("'then' clause in folded 'if'")?;
1529 match_token!(self.parser, "'then' keyword for folded 'if'", Token::Keyword("then"));
1530 }
1531 let then_body = self.parser.parse()?;
1532 if is_folded {
1533 self.parser.closing_paren("then clause in folded 'if'")?;
1534 }
1535
1536 let (else_body, else_id) = match self.parser.peek("'else', 'end', '(' or ')' in 'if'")? {
1538 (Token::Keyword("end"), _) if end && !is_folded => (vec![], None),
1539 (Token::RParen, _) if !end => (vec![], None),
1540 (Token::LParen, _) if is_folded => {
1541 self.parser.eat_token(); match_token!(
1543 self.parser,
1544 "'else' keyword in else clause of folded 'if'",
1545 Token::Keyword("else")
1546 );
1547 let body = self.parser.parse()?;
1548 self.parser.closing_paren("else clause in folded 'if'")?;
1549 (body, None)
1550 }
1551 (Token::Keyword("else"), _) if !is_folded => {
1552 self.parser.eat_token(); let id = self.parser.maybe_ident("ID for 'else' in 'if'")?;
1554 let body = self.parser.parse()?;
1555 (body, id)
1556 }
1557 (tok, offset) => {
1558 return self
1559 .parser
1560 .unexpected_token(tok.clone(), "'else' or 'end' in 'if'", offset);
1561 }
1562 };
1563 let end_id = if end {
1564 match_token!(self.parser, "'end' keyword for 'if'", Token::Keyword("end"));
1565 self.parser.maybe_ident("ID for end of 'if'")?
1566 } else {
1567 None
1568 };
1569 InsnKind::If {
1570 label,
1571 ty,
1572 then_body,
1573 else_id,
1574 else_body,
1575 end_id,
1576 }
1577 }
1578 "unreachable" => InsnKind::Unreachable,
1579 "nop" => InsnKind::Nop,
1580 "br" => InsnKind::Br(self.parser.parse()?),
1581 "br_if" => InsnKind::BrIf(self.parser.parse()?),
1582 "br_table" => {
1583 let mut labels = vec![];
1584 while let (Token::Int(..), _) | (Token::Ident(_), _) = self.parser.peek("labels for 'br_table'")? {
1585 labels.push(self.parser.parse()?);
1586 }
1587 if let Some(default_label) = labels.pop() {
1588 InsnKind::BrTable { labels, default_label }
1589 } else {
1590 return self.parser.error(
1591 ParseErrorKind::InvalidOperand {
1592 insn: "br_table",
1593 msg: "at least one label is necessary",
1594 },
1595 start,
1596 );
1597 }
1598 }
1599 "return" => InsnKind::Return,
1600 "call" => InsnKind::Call(self.parser.parse()?),
1601 "call_indirect" => {
1602 let ty: TypeUse = self.parser.parse()?;
1603 if let Some(id) = ty.params.iter().find_map(|p| p.id) {
1605 return self.parser.error(ParseErrorKind::IdBoundToParam(id), start);
1606 }
1607 InsnKind::CallIndirect(ty)
1608 }
1609 "drop" => InsnKind::Drop,
1612 "select" => InsnKind::Select,
1613 "local.get" => InsnKind::LocalGet(self.parser.parse()?),
1616 "local.set" => InsnKind::LocalSet(self.parser.parse()?),
1617 "local.tee" => InsnKind::LocalTee(self.parser.parse()?),
1618 "global.get" => InsnKind::GlobalGet(self.parser.parse()?),
1619 "global.set" => InsnKind::GlobalSet(self.parser.parse()?),
1620 "i32.load" => InsnKind::I32Load(self.parser.parse_mem_arg(2)?),
1623 "i64.load" => InsnKind::I64Load(self.parser.parse_mem_arg(3)?),
1624 "f32.load" => InsnKind::F32Load(self.parser.parse_mem_arg(2)?),
1625 "f64.load" => InsnKind::F64Load(self.parser.parse_mem_arg(3)?),
1626 "i32.load8_s" => InsnKind::I32Load8S(self.parser.parse_mem_arg(0)?),
1627 "i32.load8_u" => InsnKind::I32Load8U(self.parser.parse_mem_arg(0)?),
1628 "i32.load16_s" => InsnKind::I32Load16S(self.parser.parse_mem_arg(1)?),
1629 "i32.load16_u" => InsnKind::I32Load16U(self.parser.parse_mem_arg(1)?),
1630 "i64.load8_s" => InsnKind::I64Load8S(self.parser.parse_mem_arg(0)?),
1631 "i64.load8_u" => InsnKind::I64Load8U(self.parser.parse_mem_arg(0)?),
1632 "i64.load16_s" => InsnKind::I64Load16S(self.parser.parse_mem_arg(1)?),
1633 "i64.load16_u" => InsnKind::I64Load16U(self.parser.parse_mem_arg(1)?),
1634 "i64.load32_s" => InsnKind::I64Load32S(self.parser.parse_mem_arg(2)?),
1635 "i64.load32_u" => InsnKind::I64Load32U(self.parser.parse_mem_arg(2)?),
1636 "i32.store" => InsnKind::I32Store(self.parser.parse_mem_arg(2)?),
1637 "i64.store" => InsnKind::I64Store(self.parser.parse_mem_arg(3)?),
1638 "f32.store" => InsnKind::F32Store(self.parser.parse_mem_arg(2)?),
1639 "f64.store" => InsnKind::F64Store(self.parser.parse_mem_arg(3)?),
1640 "i32.store8" => InsnKind::I32Store8(self.parser.parse_mem_arg(0)?),
1641 "i32.store16" => InsnKind::I32Store16(self.parser.parse_mem_arg(1)?),
1642 "i64.store8" => InsnKind::I64Store8(self.parser.parse_mem_arg(0)?),
1643 "i64.store16" => InsnKind::I64Store16(self.parser.parse_mem_arg(1)?),
1644 "i64.store32" => InsnKind::I64Store32(self.parser.parse_mem_arg(2)?),
1645 "memory.size" => InsnKind::MemorySize,
1646 "memory.grow" => InsnKind::MemoryGrow,
1647 "i32.const" => {
1651 let ((sign, base, digits), offset) =
1654 match_token!(self.parser, "integer for i32.const operand", Token::Int(s, b, d) => (s, b, d));
1655 let u = parse_u32_str(self.parser, digits, base, offset)?;
1656 if sign == Sign::Plus {
1657 InsnKind::I32Const(u as i32)
1658 } else if u <= i32::MAX as u32 + 1 {
1659 InsnKind::I32Const(u.wrapping_neg() as i32)
1660 } else {
1661 return self.parser.cannot_parse_num("i32", "too small integer", offset);
1662 }
1663 }
1664 "i64.const" => {
1665 let ((sign, base, digits), offset) =
1668 match_token!(self.parser, "integer for i64.const operand", Token::Int(s, b, d) => (s, b, d));
1669 let u = parse_u64_str(self.parser, digits, base, offset)?;
1670 if sign == Sign::Plus {
1671 InsnKind::I64Const(u as i64)
1672 } else if u <= i64::MAX as u64 + 1 {
1673 InsnKind::I64Const(u.wrapping_neg() as i64)
1674 } else {
1675 return self.parser.cannot_parse_num("i64", "too small integer", offset);
1676 }
1677 }
1678 "f32.const" => {
1679 let val = match self.parser.next_token("float number or integer for f32.const")? {
1680 (Token::Float(sign, float), offset) => match float {
1681 Float::Inf => match sign {
1682 Sign::Plus => f32::INFINITY,
1683 Sign::Minus => f32::NEG_INFINITY,
1684 },
1685 Float::Nan(None) => sign.apply(f32::NAN),
1686 Float::Nan(Some(payload)) => {
1687 let payload_u = parse_u32_str(self.parser, payload, NumBase::Hex, offset)?;
1693 if payload_u == 0 || 0x80_0000 <= payload_u {
1694 return self.parser.cannot_parse_num(
1695 "f32",
1696 "payload of NaN must be in range of 1 <= payload < 2^23",
1697 offset,
1698 );
1699 }
1700 let sign = match sign {
1704 Sign::Plus => 0,
1705 Sign::Minus => 1u32 << 31, };
1707 let exp = 0b1111_1111u32 << (31 - 8);
1708 f32::from_bits(sign | exp | payload_u)
1709 }
1710 Float::Val {
1711 base: NumBase::Dec,
1712 frac,
1713 exp,
1714 } => self.parser.parse_dec_float(sign, frac, exp, offset)?,
1715 Float::Val {
1716 base: NumBase::Hex,
1717 frac,
1718 exp,
1719 } => {
1720 parse_hex_float_f32(self.parser, sign, frac, exp, offset)?
1723 }
1724 },
1725 (Token::Int(sign, NumBase::Dec, digits), offset) => {
1726 self.parser.parse_dec_float(sign, digits, None, offset)?
1727 }
1728 (Token::Int(sign, NumBase::Hex, digits), offset) => {
1729 parse_hex_float_f32(self.parser, sign, digits, None, offset)?
1730 }
1731 (tok, offset) => {
1732 return self
1733 .parser
1734 .unexpected_token(tok, "float number or integer for f32.const", offset)
1735 }
1736 };
1737 InsnKind::F32Const(val)
1738 }
1739 "f64.const" => {
1740 let val = match self.parser.next_token("float number or integer for f64.const")? {
1741 (Token::Float(sign, float), offset) => match float {
1742 Float::Inf => match sign {
1743 Sign::Plus => f64::INFINITY,
1744 Sign::Minus => f64::NEG_INFINITY,
1745 },
1746 Float::Nan(None) => sign.apply(f64::NAN),
1747 Float::Nan(Some(payload)) => {
1748 let payload_u = parse_u64_str(self.parser, payload, NumBase::Hex, offset)?;
1754 if payload_u == 0 || 0x10_0000_0000_0000 <= payload_u {
1755 return self.parser.cannot_parse_num(
1756 "f64",
1757 "payload of NaN must be in range of 1 <= payload < 2^52",
1758 offset,
1759 );
1760 }
1761 let sign = match sign {
1765 Sign::Plus => 0,
1766 Sign::Minus => 1u64 << 63, };
1768 let exp = 0b111_1111_1111u64 << (63 - 11);
1769 f64::from_bits(sign | exp | payload_u)
1770 }
1771 Float::Val {
1772 base: NumBase::Dec,
1773 frac,
1774 exp,
1775 } => self.parser.parse_dec_float(sign, frac, exp, offset)?,
1776 Float::Val {
1777 base: NumBase::Hex,
1778 frac,
1779 exp,
1780 } => parse_hex_float_f64(self.parser, sign, frac, exp, offset)?,
1781 },
1782 (Token::Int(sign, NumBase::Dec, digits), offset) => {
1783 self.parser.parse_dec_float(sign, digits, None, offset)?
1784 }
1785 (Token::Int(sign, NumBase::Hex, digits), offset) => {
1786 parse_hex_float_f64(self.parser, sign, digits, None, offset)?
1787 }
1788 (tok, offset) => {
1789 return self
1790 .parser
1791 .unexpected_token(tok, "float number or integer for f64.const", offset)
1792 }
1793 };
1794 InsnKind::F64Const(val)
1795 }
1796 "i32.clz" => InsnKind::I32Clz,
1797 "i32.ctz" => InsnKind::I32Ctz,
1798 "i32.popcnt" => InsnKind::I32Popcnt,
1799 "i32.add" => InsnKind::I32Add,
1800 "i32.sub" => InsnKind::I32Sub,
1801 "i32.mul" => InsnKind::I32Mul,
1802 "i32.div_s" => InsnKind::I32DivS,
1803 "i32.div_u" => InsnKind::I32DivU,
1804 "i32.rem_s" => InsnKind::I32RemS,
1805 "i32.rem_u" => InsnKind::I32RemU,
1806 "i32.and" => InsnKind::I32And,
1807 "i32.or" => InsnKind::I32Or,
1808 "i32.xor" => InsnKind::I32Xor,
1809 "i32.shl" => InsnKind::I32Shl,
1810 "i32.shr_s" => InsnKind::I32ShrS,
1811 "i32.shr_u" => InsnKind::I32ShrU,
1812 "i32.rotl" => InsnKind::I32Rotl,
1813 "i32.rotr" => InsnKind::I32Rotr,
1814 "i64.clz" => InsnKind::I64Clz,
1815 "i64.ctz" => InsnKind::I64Ctz,
1816 "i64.popcnt" => InsnKind::I64Popcnt,
1817 "i64.add" => InsnKind::I64Add,
1818 "i64.sub" => InsnKind::I64Sub,
1819 "i64.mul" => InsnKind::I64Mul,
1820 "i64.div_s" => InsnKind::I64DivS,
1821 "i64.div_u" => InsnKind::I64DivU,
1822 "i64.rem_s" => InsnKind::I64RemS,
1823 "i64.rem_u" => InsnKind::I64RemU,
1824 "i64.and" => InsnKind::I64And,
1825 "i64.or" => InsnKind::I64Or,
1826 "i64.xor" => InsnKind::I64Xor,
1827 "i64.shl" => InsnKind::I64Shl,
1828 "i64.shr_s" => InsnKind::I64ShrS,
1829 "i64.shr_u" => InsnKind::I64ShrU,
1830 "i64.rotl" => InsnKind::I64Rotl,
1831 "i64.rotr" => InsnKind::I64Rotr,
1832 "f32.abs" => InsnKind::F32Abs,
1833 "f32.neg" => InsnKind::F32Neg,
1834 "f32.ceil" => InsnKind::F32Ceil,
1835 "f32.floor" => InsnKind::F32Floor,
1836 "f32.trunc" => InsnKind::F32Trunc,
1837 "f32.nearest" => InsnKind::F32Nearest,
1838 "f32.sqrt" => InsnKind::F32Sqrt,
1839 "f32.add" => InsnKind::F32Add,
1840 "f32.sub" => InsnKind::F32Sub,
1841 "f32.mul" => InsnKind::F32Mul,
1842 "f32.div" => InsnKind::F32Div,
1843 "f32.min" => InsnKind::F32Min,
1844 "f32.max" => InsnKind::F32Max,
1845 "f32.copysign" => InsnKind::F32Copysign,
1846 "f64.abs" => InsnKind::F64Abs,
1847 "f64.neg" => InsnKind::F64Neg,
1848 "f64.ceil" => InsnKind::F64Ceil,
1849 "f64.floor" => InsnKind::F64Floor,
1850 "f64.trunc" => InsnKind::F64Trunc,
1851 "f64.nearest" => InsnKind::F64Nearest,
1852 "f64.sqrt" => InsnKind::F64Sqrt,
1853 "f64.add" => InsnKind::F64Add,
1854 "f64.sub" => InsnKind::F64Sub,
1855 "f64.mul" => InsnKind::F64Mul,
1856 "f64.div" => InsnKind::F64Div,
1857 "f64.min" => InsnKind::F64Min,
1858 "f64.max" => InsnKind::F64Max,
1859 "f64.copysign" => InsnKind::F64Copysign,
1860 "i32.eqz" => InsnKind::I32Eqz,
1861 "i32.eq" => InsnKind::I32Eq,
1862 "i32.ne" => InsnKind::I32Ne,
1863 "i32.lt_s" => InsnKind::I32LtS,
1864 "i32.lt_u" => InsnKind::I32LtU,
1865 "i32.gt_s" => InsnKind::I32GtS,
1866 "i32.gt_u" => InsnKind::I32GtU,
1867 "i32.le_s" => InsnKind::I32LeS,
1868 "i32.le_u" => InsnKind::I32LeU,
1869 "i32.ge_s" => InsnKind::I32GeS,
1870 "i32.ge_u" => InsnKind::I32GeU,
1871 "i64.eqz" => InsnKind::I64Eqz,
1872 "i64.eq" => InsnKind::I64Eq,
1873 "i64.ne" => InsnKind::I64Ne,
1874 "i64.lt_s" => InsnKind::I64LtS,
1875 "i64.lt_u" => InsnKind::I64LtU,
1876 "i64.gt_s" => InsnKind::I64GtS,
1877 "i64.gt_u" => InsnKind::I64GtU,
1878 "i64.le_s" => InsnKind::I64LeS,
1879 "i64.le_u" => InsnKind::I64LeU,
1880 "i64.ge_s" => InsnKind::I64GeS,
1881 "i64.ge_u" => InsnKind::I64GeU,
1882 "f32.eq" => InsnKind::F32Eq,
1883 "f32.ne" => InsnKind::F32Ne,
1884 "f32.lt" => InsnKind::F32Lt,
1885 "f32.gt" => InsnKind::F32Gt,
1886 "f32.le" => InsnKind::F32Le,
1887 "f32.ge" => InsnKind::F32Ge,
1888 "f64.eq" => InsnKind::F64Eq,
1889 "f64.ne" => InsnKind::F64Ne,
1890 "f64.lt" => InsnKind::F64Lt,
1891 "f64.gt" => InsnKind::F64Gt,
1892 "f64.le" => InsnKind::F64Le,
1893 "f64.ge" => InsnKind::F64Ge,
1894 "i32.wrap_i64" => InsnKind::I32WrapI64,
1895 "i32.trunc_f32_s" => InsnKind::I32TruncF32S,
1896 "i32.trunc_f32_u" => InsnKind::I32TruncF32U,
1897 "i32.trunc_f64_s" => InsnKind::I32TruncF64S,
1898 "i32.trunc_f64_u" => InsnKind::I32TruncF64U,
1899 "i64.extend_i32_s" => InsnKind::I64ExtendI32S,
1900 "i64.extend_i32_u" => InsnKind::I64ExtendI32U,
1901 "i64.trunc_f32_s" => InsnKind::I64TruncF32S,
1902 "i64.trunc_f32_u" => InsnKind::I64TruncF32U,
1903 "i64.trunc_f64_s" => InsnKind::I64TruncF64S,
1904 "i64.trunc_f64_u" => InsnKind::I64TruncF64U,
1905 "f32.convert_i32_s" => InsnKind::F32ConvertI32S,
1906 "f32.convert_i32_u" => InsnKind::F32ConvertI32U,
1907 "f32.convert_i64_s" => InsnKind::F32ConvertI64S,
1908 "f32.convert_i64_u" => InsnKind::F32ConvertI64U,
1909 "f32.demote_f64" => InsnKind::F32DemoteF64,
1910 "f64.convert_i32_s" => InsnKind::F64ConvertI32S,
1911 "f64.convert_i32_u" => InsnKind::F64ConvertI32U,
1912 "f64.convert_i64_s" => InsnKind::F64ConvertI64S,
1913 "f64.convert_i64_u" => InsnKind::F64ConvertI64U,
1914 "f64.promote_f32" => InsnKind::F64PromoteF32,
1915 "i32.reinterpret_f32" => InsnKind::I32ReinterpretF32,
1916 "i64.reinterpret_f64" => InsnKind::I64ReinterpretF64,
1917 "f32.reinterpret_i32" => InsnKind::F32ReinterpretI32,
1918 "f64.reinterpret_i64" => InsnKind::F64ReinterpretI64,
1919 "i32.extend8_s" => InsnKind::I32Extend8S,
1920 "i32.extend16_s" => InsnKind::I32Extend16S,
1921 "i64.extend8_s" => InsnKind::I64Extend8S,
1922 "i64.extend16_s" => InsnKind::I64Extend16S,
1923 "i64.extend32_s" => InsnKind::I64Extend32S,
1924 _ => return self.parser.error(ParseErrorKind::UnexpectedKeyword(kw), start),
1925 };
1926 Ok(Instruction { start, kind })
1927 }
1928
1929 fn parse_folded(&mut self) -> Result<'s, ()> {
1930 let start = self.parser.opening_paren("folded instruction")?;
1931 let mut insn = self.parse_naked_insn(false)?;
1932 insn.start = start;
1933
1934 if !insn.kind.is_block() {
1935 while let (Token::LParen, _) = self
1936 .parser
1937 .peek("')' for ending folded instruction or '(' for nested instruction")?
1938 {
1939 self.parse_folded()?;
1940 }
1941 }
1942
1943 self.parser.closing_paren("folded instruction")?;
1944 self.insns.push(insn);
1945 Ok(())
1946 }
1947
1948 fn parse_one(&mut self) -> Result<'s, ()> {
1949 if let Token::LParen = self.parser.peek("instruction keyword or '('")?.0 {
1952 self.parse_folded()?;
1953 } else {
1954 let insn = self.parse_naked_insn(true)?;
1955 self.insns.push(insn);
1956 }
1957 Ok(())
1958 }
1959
1960 fn parse(&mut self) -> Result<'s, ()> {
1961 loop {
1963 match self.parser.peek("instruction keyword or '(' for folded instruction")?.0 {
1968 Token::LParen => self.parse_folded()?,
1969 Token::RParen | Token::Keyword("end") | Token::Keyword("else") => return Ok(()),
1970 Token::Keyword(_) => {
1971 let insn = self.parse_naked_insn(true)?;
1972 self.insns.push(insn)
1973 }
1974 _ => return Ok(()),
1975 };
1976 }
1977 }
1978}
1979
1980impl<'s> Parse<'s> for Vec<Instruction<'s>> {
1981 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1982 let mut parser = MaybeFoldedInsn::new(parser);
1983 parser.parse()?;
1984 Ok(parser.insns)
1985 }
1986}
1987
1988impl<'s> Parse<'s> for Elem<'s> {
1990 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1991 let start = parser.opening_paren("elem")?;
1994 match_token!(parser, "'elem' keyword", Token::Keyword("elem"));
1995
1996 let idx = match parser.peek("table index of elem segment")?.0 {
1998 Token::Int(..) | Token::Ident(_) => parser.parse()?,
1999 _ => Index::Num(0),
2000 };
2001
2002 let offset = if let Some("offset") = parser.peek_fold_start("offset in elem segment")?.0 {
2003 parser.eat_token(); parser.eat_token(); let expr = parser.parse()?;
2006 parser.closing_paren("offset parameter of elem segment")?;
2007 expr
2008 } else {
2009 let mut parser = MaybeFoldedInsn::new(parser);
2011 parser.parse_one()?;
2012 parser.insns
2013 };
2014
2015 if let (Token::Keyword("func"), _) = parser.peek("")? {
2019 parser.eat_token(); }
2021
2022 let mut init = vec![];
2023 loop {
2024 if let (Token::RParen, _) = parser.peek("')' for elem segment")? {
2025 break;
2026 }
2027 init.push(parser.parse()?);
2028 }
2029
2030 parser.closing_paren("elem")?;
2031 Ok(Elem {
2032 start,
2033 idx,
2034 offset,
2035 init,
2036 })
2037 }
2038}
2039
2040#[cfg_attr(test, derive(Debug))]
2043enum TableAbbrev<'s> {
2044 Elem(Table<'s>, Elem<'s>),
2045 Table(Table<'s>),
2046}
2047
2048impl<'s> Parse<'s> for TableAbbrev<'s> {
2049 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
2050 let start = parser.opening_paren("table")?;
2051 match_token!(parser, "'table' keyword", Token::Keyword("table"));
2052
2053 let id = parser.maybe_ident("identifier for table section")?;
2054 let idx = parser.ctx.table_indices.new_idx(id, start)?;
2055
2056 loop {
2057 match parser.peek("argument of table section")?.0 {
2058 Token::LParen => {
2059 parser.eat_token(); let (keyword, offset) =
2061 match_token!(parser, "'import' or 'export' for table section", Token::Keyword(k) => k);
2062 match keyword {
2063 "import" => {
2064 let import = parser.parse()?;
2067 parser.closing_paren("import argument of table section")?;
2068 let ty = parser.parse()?;
2069 parser.closing_paren("table")?;
2070 return Ok(TableAbbrev::Table(Table {
2071 start,
2072 id,
2073 ty,
2074 import: Some(import),
2075 }));
2076 }
2077 "export" => {
2078 let name = parser.parse()?;
2082 parser.closing_paren("export argument in table section")?;
2083 parser.ctx.exports.push(Export {
2084 start,
2085 name,
2086 kind: ExportKind::Table,
2087 idx: Index::Num(idx),
2088 });
2089 }
2091 kw => return parser.error(ParseErrorKind::UnexpectedKeyword(kw), offset),
2092 }
2093 }
2094 Token::Keyword("funcref") => {
2095 parser.eat_token(); let elem_start = parser.opening_paren("elem argument in table section")?;
2100 match_token!(parser, "'elem' keyword for table section", Token::Keyword("elem"));
2101
2102 let mut init = vec![];
2103 while let Token::Int(..) | Token::Ident(_) =
2104 parser.peek("function indices in elem in table section")?.0
2105 {
2106 init.push(parser.parse()?);
2107 }
2108
2109 parser.closing_paren("elem argument in table section")?;
2110 parser.closing_paren("table")?;
2111 let n = init.len() as u32; let table = Table {
2113 start,
2114 id,
2115 ty: TableType {
2116 limit: Limits::Range { min: n, max: n },
2117 },
2118 import: None,
2119 };
2120 let elem = Elem {
2121 start: elem_start,
2122 idx: Index::Num(idx),
2123 offset: vec![Instruction {
2124 start: elem_start,
2125 kind: InsnKind::I32Const(0),
2126 }],
2127 init,
2128 };
2129 return Ok(TableAbbrev::Elem(table, elem));
2130 }
2131 _ => {
2132 let ty = parser.parse()?;
2134 parser.closing_paren("table")?;
2135 return Ok(TableAbbrev::Table(Table {
2136 start,
2137 id,
2138 ty,
2139 import: None,
2140 }));
2141 }
2142 }
2143 }
2144 }
2145}
2146
2147impl<'s> Parse<'s> for Data<'s> {
2148 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
2149 let start = parser.opening_paren("data")?;
2150 match_token!(parser, "'data' keyword", Token::Keyword("data"));
2151
2152 let idx = match parser.peek("memory index for data")?.0 {
2154 Token::Int(..) | Token::Ident(_) => parser.parse()?,
2155 _ => Index::Num(0),
2156 };
2157
2158 let offset = if let Some("offset") = parser.peek_fold_start("offset in data segment")?.0 {
2159 parser.eat_token(); parser.eat_token(); let offset = parser.parse()?;
2162 parser.closing_paren("offset of data segment")?;
2163 offset
2164 } else {
2165 let mut parser = MaybeFoldedInsn::new(parser);
2167 parser.parse_one()?;
2168 parser.insns
2169 };
2170
2171 let mut data = vec![];
2172 loop {
2173 match parser.next_token("')' or string literal for data segment")? {
2174 (Token::RParen, _) => {
2175 return Ok(Data {
2176 start,
2177 idx,
2178 offset,
2179 data: Cow::Owned(data),
2180 });
2181 }
2182 (Token::String(content, _), _) => data.extend_from_slice(content.as_ref()),
2183 (tok, offset) => {
2184 return parser.unexpected_token(tok.clone(), "')' or string literal for data segment", offset)
2185 }
2186 }
2187 }
2188 }
2189}
2190
2191#[cfg_attr(test, derive(Debug))]
2194enum MemoryAbbrev<'s> {
2195 Memory(Memory<'s>),
2196 Data(Memory<'s>, Data<'s>),
2197}
2198impl<'s> Parse<'s> for MemoryAbbrev<'s> {
2199 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
2200 let start = parser.opening_paren("memory")?;
2201 match_token!(parser, "'memory' keyword", Token::Keyword("memory"));
2202
2203 let id = parser.maybe_ident("identifier for memory section")?;
2204 let idx = parser.ctx.mem_indices.new_idx(id, start)?;
2205
2206 loop {
2207 match parser.peek("argument of memory section")?.0 {
2208 Token::LParen => {
2209 parser.eat_token(); let (keyword, offset) = match_token!(parser, "'import' or 'export' or 'data' for memory section", Token::Keyword(k) => k);
2211 match keyword {
2212 "import" => {
2213 let import = parser.parse()?;
2216 parser.closing_paren("import argument of memory section")?;
2217 let ty = parser.parse()?;
2218 parser.closing_paren("memory")?;
2219 return Ok(MemoryAbbrev::Memory(Memory {
2220 start,
2221 id,
2222 ty,
2223 import: Some(import),
2224 }));
2225 }
2226 "export" => {
2227 let name = parser.parse()?;
2231 parser.closing_paren("export argument in memory section")?;
2232 parser.ctx.exports.push(Export {
2233 start,
2234 name,
2235 kind: ExportKind::Memory,
2236 idx: Index::Num(idx),
2237 });
2238 }
2240 "data" => {
2241 let mut data = vec![];
2246 loop {
2247 match parser.next_token("')' or string literal for data of memory section")? {
2248 (Token::RParen, _) => break,
2249 (Token::String(content, _), _) => data.extend_from_slice(content.as_ref()),
2250 (tok, offset) => {
2251 return parser.unexpected_token(
2252 tok.clone(),
2253 "')' or string literal for data of memory section",
2254 offset,
2255 )
2256 }
2257 }
2258 }
2259 parser.closing_paren("memory")?;
2260
2261 let n = (data.len() as f64 / 65536.0).ceil() as u32;
2263
2264 return Ok(MemoryAbbrev::Data(
2265 Memory {
2266 start,
2267 id,
2268 ty: MemType {
2269 limit: Limits::Range { min: n, max: n },
2270 },
2271 import: None,
2272 },
2273 Data {
2274 start,
2275 idx: Index::Num(idx),
2276 offset: vec![Instruction {
2277 start,
2278 kind: InsnKind::I32Const(0),
2279 }],
2280 data: Cow::Owned(data),
2281 },
2282 ));
2283 }
2284 kw => return parser.error(ParseErrorKind::UnexpectedKeyword(kw), offset),
2285 }
2286 }
2287 _ => {
2288 let ty = parser.parse()?;
2290 parser.closing_paren("memory")?;
2291 return Ok(MemoryAbbrev::Memory(Memory {
2292 start,
2293 id,
2294 ty,
2295 import: None,
2296 }));
2297 }
2298 }
2299 }
2300 }
2301}
2302
2303impl<'s> Parse<'s> for Global<'s> {
2305 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
2306 let start = parser.opening_paren("global")?;
2307 match_token!(parser, "'global' keyword", Token::Keyword("global"));
2308
2309 let id = parser.maybe_ident("identifier for global section")?;
2310 let idx = parser.ctx.global_indices.new_idx(id, start)?;
2311
2312 loop {
2315 match parser.peek("argument of global section")?.0 {
2316 Token::LParen => {
2317 parser.eat_token(); let (keyword, offset) =
2319 match_token!(parser, "'import' or 'export' for global section", Token::Keyword(k) => k);
2320 match keyword {
2321 "import" => {
2322 let import = parser.parse()?;
2325 parser.closing_paren("import argument of global section")?;
2326 let ty = parser.parse()?;
2327 parser.closing_paren("global")?;
2328 return Ok(Global {
2329 start,
2330 id,
2331 ty,
2332 kind: GlobalKind::Import(import),
2333 });
2334 }
2335 "export" => {
2336 let name = parser.parse()?;
2340 parser.closing_paren("export argument in global section")?;
2341 parser.ctx.exports.push(Export {
2342 start,
2343 name,
2344 kind: ExportKind::Global,
2345 idx: Index::Num(idx),
2346 });
2347 }
2348 "mut" => {
2349 let ty = parser.parse()?;
2351 parser.closing_paren("global mutable type")?;
2352 let init = parser.parse()?;
2353 parser.closing_paren("global")?;
2354 let ty = GlobalType { mutable: true, ty };
2355 return Ok(Global {
2356 start,
2357 id,
2358 ty,
2359 kind: GlobalKind::Init(init),
2360 });
2361 }
2362 kw => return parser.error(ParseErrorKind::UnexpectedKeyword(kw), offset),
2363 }
2364 }
2365 _ => {
2366 let ty = parser.parse()?;
2368 let init = parser.parse()?;
2369 parser.closing_paren("global")?;
2370 let ty = GlobalType { mutable: false, ty };
2371 return Ok(Global {
2372 start,
2373 id,
2374 ty,
2375 kind: GlobalKind::Init(init),
2376 });
2377 }
2378 }
2379 }
2380 }
2381}
2382
2383impl<'s> Parse<'s> for Start<'s> {
2385 fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
2386 let start = parser.opening_paren("start")?;
2387 match_token!(parser, "'start' keyword", Token::Keyword("start"));
2388 let idx = parser.parse()?;
2389 parser.closing_paren("start")?;
2390 Ok(Start { start, idx })
2391 }
2392}
2393
2394#[cfg(test)]
2395mod tests {
2396 use super::*;
2397
2398 #[test]
2399 fn lookahead() {
2400 let v = vec![1, 2, 3, 4];
2401 let mut i = LookAhead::new(v.into_iter());
2402 assert_eq!(i.peek(), Some(&1));
2403 assert_eq!(i.lookahead(), Some(&2));
2404 assert_eq!(i.next(), Some(1));
2405
2406 assert_eq!(i.peek(), Some(&2));
2407 assert_eq!(i.lookahead(), Some(&3));
2408 assert_eq!(i.next(), Some(2));
2409
2410 assert_eq!(i.peek(), Some(&3));
2411 assert_eq!(i.lookahead(), Some(&4));
2412 assert_eq!(i.next(), Some(3));
2413
2414 assert_eq!(i.peek(), Some(&4));
2415 assert_eq!(i.lookahead(), None);
2416 assert_eq!(i.next(), Some(4));
2417
2418 assert_eq!(i.peek(), None);
2419 assert_eq!(i.lookahead(), None);
2420 assert_eq!(i.next(), None);
2421
2422 assert_eq!(i.peek(), None);
2423 assert_eq!(i.lookahead(), None);
2424
2425 let v: Vec<i32> = vec![];
2426 let mut i = LookAhead::new(v.into_iter());
2427 assert_eq!(i.peek(), None);
2428 assert_eq!(i.lookahead(), None);
2429 assert_eq!(i.next(), None);
2430 assert_eq!(i.peek(), None);
2431 assert_eq!(i.lookahead(), None);
2432 }
2433
2434 #[test]
2435 fn indices() {
2436 let mut i = Indices::new("source", "what", "scope");
2437 i.new_idx(None, 0).unwrap();
2438 i.new_idx(Some("hi"), 0).unwrap();
2439 i.new_idx(None, 0).unwrap();
2440 i.new_idx(Some("bye"), 0).unwrap();
2441 let m = i.move_out();
2442 assert_eq!(m.get("hi"), Some(&1));
2443 assert_eq!(m.get("bye"), Some(&3));
2444 assert_eq!(m.get("hey"), None);
2445
2446 i.new_idx(Some("hi"), 0).unwrap();
2448 let m = i.move_out();
2449 assert_eq!(m.get("hi"), Some(&0));
2450
2451 let mut i = Indices::new("source", "what", "scope");
2452 i.new_idx(Some("hi"), 0).unwrap();
2453 i.new_idx(Some("hi"), 0).unwrap_err();
2454 }
2455
2456 macro_rules! assert_parse {
2457 ($input:expr, $node:ty, $expect:pat if $cond:expr) => {{
2458 let input = $input;
2459 let mut parser = Parser::new(input);
2460 let node: $node = match parser.parse() {
2461 Ok(n) => n,
2462 Err(e) => panic!("parse failed!: {}\n{:?}", e, e),
2463 };
2464 match node {
2465 $expect if $cond => { }
2466 _ => panic!(
2467 "assertion failed: {:?} did not match to {}",
2468 node,
2469 stringify!($expect if $cond)
2470 ),
2471 }
2472 assert!(parser.is_done(), "token is remaining: {:?}", parser.tokens.collect::<Vec<_>>());
2473 parser
2474 }};
2475 ($input:expr, $node:ty, $expect:pat) => {
2476 assert_parse!($input, $node, $expect if true)
2477 };
2478 }
2479
2480 macro_rules! assert_error {
2481 ($input:expr, $node:ty, $expect:pat if $cond:expr) => {{
2482 use ParseErrorKind::*;
2483 let input = $input;
2484 match Parser::new(input).parse::<$node>().unwrap_err().kind {
2485 $expect if $cond => { }
2486 err => panic!("assertion failed: {:?} did not match to pattern {}", err, stringify!($expect if $cond)),
2487 }
2488 }};
2489 ($input:expr, $node:ty, $expect:pat) => {
2490 assert_error!($input, $node, $expect if true);
2491 };
2492 }
2493
2494 #[test]
2495 fn root() {
2496 assert_parse!(
2497 r#"
2498 (module $m1
2499 (type $t1 (func))
2500 (type $t2 (func))
2501 (import "m" "n" (func $f2 (type 0)))
2502 (import "m" "n" (table $tb2 0 funcref))
2503 (import "m" "n" (memory $m2 3))
2504 (import "m" "n" (global $g2 i32))
2505 (func $f1)
2506 (table $tb1 0 funcref)
2507 (memory $m1 3)
2508 (global $g1 i32 i32.const 0)
2509 (start $f1)
2510 )
2511 "#,
2512 Parsed<'_>,
2513 Parsed {
2514 module: Module {
2515 id: Some("$m1"),
2516 types,
2517 exports,
2518 elems,
2519 tables,
2520 data,
2521 memories,
2522 globals,
2523 funcs,
2524 entrypoint,
2525 ..
2526 },
2527 type_indices,
2528 func_indices,
2529 table_indices,
2530 mem_indices,
2531 global_indices,
2532 }
2533 if types.len() == 2
2534 && elems.is_empty()
2535 && tables.len() == 2
2536 && data.is_empty()
2537 && memories.len() == 2
2538 && globals.len() == 2
2539 && funcs.len() == 2
2540 && exports.is_empty()
2541 && entrypoint.is_some()
2542 && type_indices.contains_key("$t1")
2543 && type_indices.contains_key("$t2")
2544 && type_indices.len() == 2
2545 && func_indices.contains_key("$f1")
2546 && func_indices.contains_key("$f2")
2547 && func_indices.len() == 2
2548 && table_indices.contains_key("$tb1")
2549 && table_indices.contains_key("$tb2")
2550 && table_indices.len() == 2
2551 && mem_indices.contains_key("$m1")
2552 && mem_indices.contains_key("$m2")
2553 && mem_indices.len() == 2
2554 && global_indices.contains_key("$g1")
2555 && global_indices.contains_key("$g2")
2556 && global_indices.len() == 2
2557 );
2558 }
2559
2560 #[test]
2561 fn module() {
2562 assert_parse!(r#"(module)"#, Module<'_>, Module { id: None, types, .. } if types.is_empty());
2563 assert_parse!(r#"(module $foo)"#, Module<'_>, Module { id: Some("$foo"), types, .. } if types.is_empty());
2564 assert_parse!(r#"(module $foo (type $f1 (func)))"#, Module<'_>, Module { id: Some("$foo"), types, .. } if types.len() == 1);
2565 assert_parse!(
2566 r#"
2567 (module
2568 (type $f1 (func))
2569 (type $f2 (func)))
2570 "#,
2571 Module<'_>,
2572 Module { id: None, types, .. } if types.len() == 2
2573 );
2574 assert_parse!(
2575 r#"(module (start $f))"#,
2576 Module<'_>,
2577 Module {
2578 id: None,
2579 entrypoint: Some(Start {
2580 idx: Index::Ident("$f"),
2581 ..
2582 }),
2583 ..
2584 }
2585 );
2586 assert_parse!(r#"(module (func))"#, Module<'_>, Module { funcs, .. } if funcs.len() == 1);
2587 assert_parse!(
2588 r#"(module (start $f))"#,
2589 Module<'_>,
2590 Module {
2591 id: None,
2592 entrypoint: Some(Start {
2593 idx: Index::Ident("$f"),
2594 ..
2595 }),
2596 ..
2597 }
2598 );
2599 assert_parse!(
2601 r#"(type $f1 (func)) (type $f2 (func))"#,
2602 Module<'_>,
2603 Module { id: None, types, .. } if types.len() == 2
2604 );
2605
2606 assert_error!(r#"(module"#, Module<'_>, UnexpectedEndOfFile { .. });
2607 assert_error!(
2608 r#"(module $foo (type $f (func))"#,
2609 Module<'_>,
2610 UnexpectedEndOfFile { .. }
2611 );
2612 assert_error!(
2613 r#"(module $foo (start $f) (start 3))"#,
2614 Module<'_>,
2615 MultipleEntrypoints(
2616 Start {
2617 idx: Index::Ident("$f"),
2618 ..
2619 },
2620 Start { idx: Index::Num(3), .. },
2621 )
2622 );
2623 assert_error!(
2625 r#"(type $f1 (func)) )"#,
2626 Module<'_>,
2627 ExpectEndOfFile {
2628 token: Token::RParen,
2629 ..
2630 }
2631 );
2632 assert_error!(
2634 r#"
2635 (module
2636 (type $t1 (func))
2637 (func $f1)
2638 (import "m" "n" (func $f2 (type 0)))
2639 )
2640 "#,
2641 Module<'_>,
2642 ImportMustPrecedeOtherDefs { .. }
2643 );
2644 assert_error!(
2645 r#"
2646 (module
2647 (table $tb1 0 funcref)
2648 (import "m" "n" (table $tb2 0 funcref))
2649 )
2650 "#,
2651 Module<'_>,
2652 ImportMustPrecedeOtherDefs { .. }
2653 );
2654 assert_error!(
2655 r#"
2656 (module
2657 (memory $m1 3)
2658 (import "m" "n" (memory $m2 3))
2659 )
2660 "#,
2661 Module<'_>,
2662 ImportMustPrecedeOtherDefs { .. }
2663 );
2664 assert_error!(
2665 r#"
2666 (module
2667 (global $g1 i32 i32.const 0)
2668 (import "m" "n" (global $g2 i32))
2669 )
2670 "#,
2671 Module<'_>,
2672 ImportMustPrecedeOtherDefs { .. }
2673 );
2674 }
2675
2676 #[test]
2677 fn module_field() {
2678 assert_parse!(r#"(type $f1 (func))"#, ModuleField<'_>, ModuleField::Type(..));
2679 assert_parse!(r#"(import "m" "n" (func))"#, ModuleField<'_>, ModuleField::Import(..));
2680 assert_parse!(r#"(export "n" (func $foo))"#, ModuleField<'_>, ModuleField::Export(..));
2681 assert_parse!(
2682 r#"(elem (offset i32.const 10) $func)"#,
2683 ModuleField<'_>,
2684 ModuleField::Elem(..)
2685 );
2686 assert_parse!(r#"(table 0 funcref)"#, ModuleField<'_>, ModuleField::Table(..));
2687 assert_parse!(
2688 r#"(data 0 i32.const 0 "hello")"#,
2689 ModuleField<'_>,
2690 ModuleField::Data(..)
2691 );
2692 assert_parse!(r#"(memory 3)"#, ModuleField<'_>, ModuleField::Memory(..));
2693 assert_parse!(
2694 r#"(global (mut i32) i32.const 0)"#,
2695 ModuleField<'_>,
2696 ModuleField::Global(..)
2697 );
2698 assert_parse!(r#"(start 3)"#, ModuleField<'_>, ModuleField::Start(..));
2699 assert_parse!(r#"(func)"#, ModuleField<'_>, ModuleField::Func(..));
2700
2701 assert_error!(r#"(hello!)"#, ModuleField<'_>, UnexpectedKeyword("hello!"));
2702 }
2703
2704 #[test]
2705 fn type_def() {
2706 assert_parse!(r#"(type $f1 (func))"#, TypeDef<'_>, TypeDef { id: Some("$f1"), .. });
2707 assert_parse!(r#"(type (func))"#, TypeDef<'_>, TypeDef { id: None, .. });
2708
2709 assert_error!(r#"(type (func) (func))"#, TypeDef<'_>, MissingParen { paren: ')', .. });
2710 assert_error!(r#"(type)"#, TypeDef<'_>, MissingParen { paren: '(', .. });
2711 assert_error!(r#"(type"#, TypeDef<'_>, UnexpectedEndOfFile { .. });
2712 }
2713
2714 #[test]
2715 fn func_type() {
2716 assert_parse!(r#"(func)"#, FuncType<'_>, FuncType{ params, results, .. } if params.is_empty() && results.is_empty());
2717 assert_parse!(r#"(func (param $a i32) (result i32))"#, FuncType<'_>, FuncType{ params, results, .. } if params.len() == 1 && results.len() == 1);
2718 assert_parse!(r#"(func (param $a i32))"#, FuncType<'_>, FuncType{ params, results, .. } if params.len() == 1 && results.is_empty());
2719 assert_parse!(r#"(func (result i32))"#, FuncType<'_>, FuncType{ params, results, .. } if params.is_empty() && results.len() == 1);
2720 assert_parse!(r#"
2721 (func
2722 (param $a i32)
2723 (param $a i32)
2724 (result i32)
2725 (result i32))
2726 "#, FuncType<'_>, FuncType{ params, results, .. } if params.len() == 2 && results.len() == 2);
2727 assert_error!(r#"func"#, FuncType<'_>, MissingParen { paren: '(', .. });
2730 assert_error!(
2731 r#"(type"#,
2732 FuncType<'_>,
2733 UnexpectedToken {
2734 expected: "'func' keyword",
2735 ..
2736 }
2737 );
2738 assert_error!(
2739 r#"(func "#,
2740 FuncType<'_>,
2741 UnexpectedEndOfFile {
2742 expected: "parameter",
2743 ..
2744 }
2745 );
2746 assert_error!(
2747 r#"(func (result i32) foo"#,
2748 FuncType<'_>,
2749 MissingParen { paren: ')', .. }
2750 );
2751 }
2752
2753 #[test]
2754 fn params() {
2755 macro_rules! assert_params {
2756 ($input:expr, $expect:pat) => {
2757 let input = concat!($input, ')'); let mut parser = Parser::new(input);
2759 let params: Vec<Param<'_>> = parser.parse().unwrap();
2760 match params.as_slice() {
2761 $expect => { }
2762 params => panic!(
2763 "assertion failed: {:?} did not match to {}",
2764 params,
2765 stringify!($expect)
2766 ),
2767 }
2768 assert!(matches!(parser.tokens.next(), Some(Ok((Token::RParen, _)))));
2769 };
2770 }
2771
2772 assert_params!(
2773 "(param $a i32)",
2774 [Param {
2775 id: Some("$a"),
2776 ty: ValType::I32,
2777 ..
2778 }]
2779 );
2780 assert_params!(
2781 "(param i32)",
2782 [Param {
2783 id: None,
2784 ty: ValType::I32,
2785 ..
2786 }]
2787 );
2788 assert_params!(
2789 "(param $a i32) (param i64) (param f32) (param $b f64)",
2790 [
2791 Param {
2792 id: Some("$a"),
2793 ty: ValType::I32,
2794 ..
2795 },
2796 Param {
2797 id: None,
2798 ty: ValType::I64,
2799 ..
2800 },
2801 Param {
2802 id: None,
2803 ty: ValType::F32,
2804 ..
2805 },
2806 Param {
2807 id: Some("$b"),
2808 ty: ValType::F64,
2809 ..
2810 }
2811 ]
2812 );
2813
2814 assert_params!("", []);
2815 assert_params!("(param)", []);
2816 assert_params!(
2817 "(param i32 i64 f32 f64)",
2818 [
2819 Param {
2820 id: None,
2821 ty: ValType::I32,
2822 ..
2823 },
2824 Param {
2825 id: None,
2826 ty: ValType::I64,
2827 ..
2828 },
2829 Param {
2830 id: None,
2831 ty: ValType::F32,
2832 ..
2833 },
2834 Param {
2835 id: None,
2836 ty: ValType::F64,
2837 ..
2838 }
2839 ]
2840 );
2841 assert_params!(
2842 "(param i32 i64) (param $a i32) (param) (param f32 f64) (param $b i64)",
2843 [
2844 Param {
2845 id: None,
2846 ty: ValType::I32,
2847 ..
2848 },
2849 Param {
2850 id: None,
2851 ty: ValType::I64,
2852 ..
2853 },
2854 Param {
2855 id: Some("$a"),
2856 ty: ValType::I32,
2857 ..
2858 },
2859 Param {
2860 id: None,
2861 ty: ValType::F32,
2862 ..
2863 },
2864 Param {
2865 id: None,
2866 ty: ValType::F64,
2867 ..
2868 },
2869 Param {
2870 id: Some("$b"),
2871 ty: ValType::I64,
2872 ..
2873 }
2874 ]
2875 );
2876 }
2877
2878 #[test]
2879 fn value_type() {
2880 assert_parse!(r#"i32"#, ValType, ValType::I32);
2881 assert_parse!(r#"i64"#, ValType, ValType::I64);
2882 assert_parse!(r#"f32"#, ValType, ValType::F32);
2883 assert_parse!(r#"f64"#, ValType, ValType::F64);
2884
2885 assert_error!(r#"string"#, ValType, InvalidValType("string"));
2886 assert_error!(
2887 r#"$hello"#,
2888 ValType,
2889 UnexpectedToken {
2890 expected: "keyword for value type",
2891 ..
2892 }
2893 );
2894 }
2895
2896 #[test]
2897 fn func_results() {
2898 macro_rules! assert_results {
2899 ($input:expr, $expect:pat) => {
2900 let input = concat!($input, ')'); let mut parser = Parser::new(input);
2902 let results: Vec<FuncResult> = parser.parse().unwrap();
2903 match results.as_slice() {
2904 $expect => { }
2905 results => panic!(
2906 "assertion failed: {:?} did not match to {}",
2907 results,
2908 stringify!($expect)
2909 ),
2910 }
2911 assert!(matches!(parser.tokens.next(), Some(Ok((Token::RParen, _)))));
2912 };
2913 }
2914
2915 assert_results!("", []);
2916 assert_results!("(result)", []);
2917 assert_results!("(result i32)", [FuncResult { ty: ValType::I32, .. }]);
2918 assert_results!(
2919 "(result i32) (result i64) (result f32) (result f64) ",
2920 [
2921 FuncResult { ty: ValType::I32, .. },
2922 FuncResult { ty: ValType::I64, .. },
2923 FuncResult { ty: ValType::F32, .. },
2924 FuncResult { ty: ValType::F64, .. }
2925 ]
2926 );
2927 assert_results!(
2928 "(result i32 i64 f32 f64) ",
2929 [
2930 FuncResult { ty: ValType::I32, .. },
2931 FuncResult { ty: ValType::I64, .. },
2932 FuncResult { ty: ValType::F32, .. },
2933 FuncResult { ty: ValType::F64, .. }
2934 ]
2935 );
2936 assert_results!(
2937 "(result i32 i64) (result f32) (result) (result f64 i32) (result i64)",
2938 [
2939 FuncResult { ty: ValType::I32, .. },
2940 FuncResult { ty: ValType::I64, .. },
2941 FuncResult { ty: ValType::F32, .. },
2942 FuncResult { ty: ValType::F64, .. },
2943 FuncResult { ty: ValType::I32, .. },
2944 FuncResult { ty: ValType::I64, .. }
2945 ]
2946 );
2947 }
2948
2949 #[test]
2950 fn name() {
2951 assert_parse!(r#""n""#, Name, Name(n) if n == "n");
2952 assert_parse!(r#""name""#, Name, Name(n) if n == "name");
2953 assert_parse!(r#""a\tb\nc""#, Name, Name(n) if n == "a\tb\nc");
2954 assert_parse!(r#""""#, Name, Name(n) if n.is_empty());
2955 assert_parse!(r#""\t\n\r\"\'\\\u{3042}\41""#, Name, Name(n) if n == "\t\n\r\"'\\あA");
2956
2957 assert_error!(r#""\80""#, Name, MalformedUtf8Encoding);
2958 }
2959
2960 #[test]
2961 fn import() {
2962 assert_parse!(
2963 r#"(import "mod" "name" (func (type 0)))"#,
2964 ImportItem<'_>,
2965 ImportItem::Func(Func {
2966 kind: FuncKind::Import(Import {
2967 mod_name: Name(mn),
2968 name: Name(n),
2969 }),
2970 ..
2971 }) if mn == "mod" && n == "name"
2972 );
2973 assert_parse!(
2974 r#"(import "env" "print" (func $print (param i32)))"#,
2975 ImportItem<'_>,
2976 ImportItem::Func(Func {
2977 kind: FuncKind::Import(Import { .. }),
2978 ..
2979 })
2980 );
2981
2982 assert_error!(r#"import"#, ImportItem<'_>, MissingParen { paren: '(', .. });
2983 assert_error!(
2984 r#"(hello"#,
2985 ImportItem<'_>,
2986 UnexpectedToken {
2987 expected: "'import' keyword",
2988 ..
2989 }
2990 );
2991 assert_error!(
2992 r#"(import "mod" "name" (func)"#,
2993 ImportItem<'_>,
2994 MissingParen { paren: ')', .. }
2995 );
2996 assert_error!(r#"(import "mod" (func)"#, ImportItem<'_>, UnexpectedToken { .. });
2997 assert_error!(r#"(import (func)"#, ImportItem<'_>, UnexpectedToken { .. });
2998 }
2999
3000 #[test]
3001 fn import_item() {
3002 assert_parse!(
3003 r#"(import "m" "n" (func))"#,
3004 ImportItem<'_>,
3005 ImportItem::Func(Func {
3006 id: None,
3007 kind: FuncKind::Import(_),
3008 ..
3009 })
3010 );
3011 assert_parse!(
3012 r#"(import "m" "n" (func $foo))"#,
3013 ImportItem<'_>,
3014 ImportItem::Func(Func {
3015 id: Some("$foo"),
3016 kind: FuncKind::Import(_),
3017 ..
3018 })
3019 );
3020 assert_parse!(
3021 r#"(import "m" "n" (table 0 funcref))"#,
3022 ImportItem<'_>,
3023 ImportItem::Table(Table {
3024 id: None,
3025 import: Some(_),
3026 ..
3027 })
3028 );
3029 assert_parse!(
3030 r#"(import "m" "n" (table $foo 0 funcref))"#,
3031 ImportItem<'_>,
3032 ImportItem::Table(Table {
3033 id: Some("$foo"),
3034 import: Some(_),
3035 ..
3036 })
3037 );
3038 assert_parse!(
3039 r#"(import "m" "n" (memory 0))"#,
3040 ImportItem<'_>,
3041 ImportItem::Memory(Memory {
3042 id: None,
3043 import: Some(_),
3044 ..
3045 })
3046 );
3047 assert_parse!(
3048 r#"(import "m" "n" (memory $foo 0))"#,
3049 ImportItem<'_>,
3050 ImportItem::Memory(Memory {
3051 id: Some("$foo"),
3052 import: Some(_),
3053 ..
3054 })
3055 );
3056 assert_parse!(
3057 r#"(import "m" "n" (global i32))"#,
3058 ImportItem<'_>,
3059 ImportItem::Global(Global {
3060 id: None,
3061 kind: GlobalKind::Import(_),
3062 ..
3063 })
3064 );
3065 assert_parse!(
3066 r#"(import "m" "n" (global $foo i32))"#,
3067 ImportItem<'_>,
3068 ImportItem::Global(Global {
3069 id: Some("$foo"),
3070 kind: GlobalKind::Import(_),
3071 ..
3072 })
3073 );
3074 let parser = assert_parse!(
3075 r#"(module
3076 (import "m" "f" (func $x))
3077 (import "m" "t" (table $x 0 funcref))
3078 (import "m" "m" (memory $x 1))
3079 (import "m" "g" (global $x i32))
3080 )"#,
3081 Module<'_>,
3082 Module{ funcs, tables, memories, globals, .. }
3083 if funcs.len() == 1 && tables.len() == 1 && memories.len() == 1 && globals.len() == 1
3084 );
3085 assert_eq!(parser.ctx.func_indices.indices.len(), 1);
3086 assert_eq!(parser.ctx.table_indices.indices.len(), 1);
3087 assert_eq!(parser.ctx.mem_indices.indices.len(), 1);
3088 assert_eq!(parser.ctx.global_indices.indices.len(), 1);
3089
3090 assert_error!(r#"func"#, ImportItem<'_>, MissingParen { paren: '(', .. });
3091 assert_error!(r#"(import "m" "n" (func"#, ImportItem<'_>, UnexpectedEndOfFile { .. });
3092 }
3093
3094 #[test]
3095 fn type_use() {
3096 assert_parse!(
3100 r#"(import "m" "n" (func (type 0)))"#,
3101 ImportItem<'_>,
3102 ImportItem::Func(Func {
3103 ty: TypeUse { params, results, idx: TypeIndex::Explicit(Index::Num(0)), .. },
3104 ..
3105 }) if params.is_empty() && results.is_empty()
3106 );
3107 assert_parse!(
3108 r#"(import "m" "n" (func (type $f)))"#,
3109 ImportItem<'_>,
3110 ImportItem::Func(Func {
3111 ty: TypeUse { params, results, idx: TypeIndex::Explicit(Index::Ident("$f")), .. },
3112 ..
3113 }) if params.is_empty() && results.is_empty()
3114 );
3115 assert_parse!(
3116 r#"(import "m" "n" (func (type 0) (param i32)))"#,
3117 ImportItem<'_>,
3118 ImportItem::Func(Func {
3119 ty: TypeUse { params, results, idx: TypeIndex::Explicit(Index::Num(0)), .. },
3120 ..
3121 }) if params.len() == 1 && results.is_empty()
3122 );
3123 assert_parse!(
3124 r#"(import "m" "n" (func (type 0) (result i32)))"#,
3125 ImportItem<'_>,
3126 ImportItem::Func(Func {
3127 ty: TypeUse { params, results, idx: TypeIndex::Explicit(Index::Num(0)), .. },
3128 ..
3129 }) if params.is_empty() && results.len() == 1
3130 );
3131 assert_parse!(
3132 r#"(import "m" "n" (func (type 0) (param i32) (result i32)))"#,
3133 ImportItem<'_>,
3134 ImportItem::Func(Func {
3135 ty: TypeUse { params, results, idx: TypeIndex::Explicit(Index::Num(0)), .. },
3136 ..
3137 }) if params.len() == 1 && results.len() == 1
3138 );
3139 assert_parse!(
3141 r#"(import "m" "n" (func (param i32) (result i32)))"#,
3142 ImportItem<'_>,
3143 ImportItem::Func(Func {
3144 ty: TypeUse { params, results, idx: TypeIndex::Implicit(0), .. },
3145 ..
3146 }) if params.len() == 1 && results.len() == 1
3147 );
3148 assert_parse!(
3149 r#"(import "m" "n" (func (result i32)))"#,
3150 ImportItem<'_>,
3151 ImportItem::Func(Func {
3152 ty: TypeUse { params, results, idx: TypeIndex::Implicit(0), .. },
3153 ..
3154 }) if params.is_empty() && results.len() == 1
3155 );
3156 assert_parse!(
3157 r#"(import "m" "n" (func))"#,
3158 ImportItem<'_>,
3159 ImportItem::Func(Func {
3160 ty: TypeUse { params, results, idx: TypeIndex::Implicit(0), .. },
3161 ..
3162 }) if params.is_empty() && results.is_empty()
3163 );
3164
3165 {
3168 let input = r#"
3169 (module
3170 (type $f (func (param i32) (result i32)))
3171 (type $g (func (param i32) (result i32)))
3172 (func (param i32) (result i32))
3173 )
3174 "#;
3175 let mut parser = Parser::new(input);
3176 let m: Module<'_> = parser.parse().unwrap();
3177 assert_eq!(m.funcs[0].ty.idx, TypeIndex::Implicit(0));
3179 }
3180 {
3181 let input = r#"
3182 (module
3183 (type $f (func (param i32) (result i32)))
3184 (type $g (func (param i32) (result i64)))
3185 (func (param i32) (result i64))
3186 )
3187 "#;
3188 let mut parser = Parser::new(input);
3189 let m: Module<'_> = parser.parse().unwrap();
3190 assert_eq!(m.funcs[0].ty.idx, TypeIndex::Implicit(0));
3192 }
3193 {
3194 let input = r#"
3195 (module
3196 (func (param f32) (result i32))
3197 )
3198 "#;
3199 let mut parser = Parser::new(input);
3200 let m: Module<'_> = parser.parse().unwrap();
3201 assert_eq!(m.types.len(), 1);
3204 match &m.types[0] {
3205 TypeDef {
3206 id: None,
3207 ty: FuncType { params, results, .. },
3208 ..
3209 } => {
3210 assert_eq!(params.len(), 1);
3211 assert_eq!(params[0].id, None);
3212 assert_eq!(params[0].ty, ValType::F32);
3213 assert_eq!(results.len(), 1);
3214 assert_eq!(results[0].ty, ValType::I32);
3215 }
3216 t => panic!("Type section entry is not set correctly: {:?}", t),
3217 }
3218 }
3219
3220 }
3224
3225 #[test]
3226 fn index() {
3227 assert_parse!(r#"0"#, Index<'_>, Index::Num(0));
3228 assert_parse!(r#"0x1f"#, Index<'_>, Index::Num(0x1f));
3229 assert_parse!(r#"$foo"#, Index<'_>, Index::Ident("$foo"));
3230
3231 assert_error!(
3232 r#"hi"#,
3233 Index<'_>,
3234 UnexpectedToken {
3235 expected: "number or identifier for index",
3236 ..
3237 }
3238 );
3239 assert_error!(
3240 r#""#,
3241 Index<'_>,
3242 UnexpectedEndOfFile {
3243 expected: "number or identifier for index",
3244 ..
3245 }
3246 );
3247 }
3248
3249 #[test]
3250 fn table_type_and_limits() {
3251 assert_parse!(
3252 r#"0 funcref"#,
3253 TableType,
3254 TableType {
3255 limit: Limits::From { min: 0 }
3256 }
3257 );
3258 assert_parse!(
3259 r#"0 1 funcref"#,
3260 TableType,
3261 TableType {
3262 limit: Limits::Range { min: 0, max: 1 }
3263 }
3264 );
3265
3266 assert_error!(
3267 r#"0 1 hi"#,
3268 TableType,
3269 UnexpectedToken {
3270 expected: "'funcref' keyword for table type",
3271 ..
3272 }
3273 );
3274 assert_error!(
3275 r#"hi"#,
3276 TableType,
3277 UnexpectedToken {
3278 expected: "u32 for min table limit",
3279 ..
3280 }
3281 );
3282 }
3283
3284 #[test]
3285 fn memtype() {
3286 assert_parse!(
3287 r#"0 10"#,
3288 MemType,
3289 MemType {
3290 limit: Limits::Range { min: 0, max: 10 }
3291 }
3292 );
3293 }
3294
3295 #[test]
3296 fn global_type() {
3297 assert_parse!(
3298 r#"i32"#,
3299 GlobalType,
3300 GlobalType {
3301 mutable: false,
3302 ty: ValType::I32
3303 }
3304 );
3305 assert_parse!(
3306 r#"(mut i32)"#,
3307 GlobalType,
3308 GlobalType {
3309 mutable: true,
3310 ty: ValType::I32
3311 }
3312 );
3313
3314 assert_error!(
3315 r#""#,
3316 GlobalType,
3317 UnexpectedEndOfFile {
3318 expected: "'(' for mut or value type of global type",
3319 ..
3320 }
3321 );
3322 assert_error!(
3323 r#"(hello"#,
3324 GlobalType,
3325 UnexpectedToken {
3326 expected: "'mut' keyword for global type",
3327 ..
3328 }
3329 );
3330 assert_error!(r#"(mut i32"#, GlobalType, MissingParen { paren: ')', .. });
3331 }
3332
3333 #[test]
3334 fn export() {
3335 assert_parse!(
3336 r#"(export "hi" (func 0))"#,
3337 Export<'_>,
3338 Export{ name: Name(n), kind: ExportKind::Func, idx: Index::Num(0), .. } if n == "hi"
3339 );
3340 assert_parse!(
3341 r#"(export "hi" (table $foo))"#,
3342 Export<'_>,
3343 Export{ name: Name(n), kind: ExportKind::Table, idx: Index::Ident("$foo"), .. } if n == "hi"
3344 );
3345 assert_parse!(
3346 r#"(export "hi" (memory 0))"#,
3347 Export<'_>,
3348 Export{ name: Name(n), kind: ExportKind::Memory, idx: Index::Num(0), .. } if n == "hi"
3349 );
3350 assert_parse!(
3351 r#"(export "hi" (global 0))"#,
3352 Export<'_>,
3353 Export{ name: Name(n), kind: ExportKind::Global, idx: Index::Num(0), .. } if n == "hi"
3354 );
3355
3356 assert_error!(r#"export"#, Export<'_>, MissingParen { paren: '(', .. });
3357 assert_error!(r#"(export "hi" (func 0"#, Export<'_>, MissingParen { paren: ')', .. });
3358 assert_error!(r#"(export "hi" (func 0)"#, Export<'_>, MissingParen { paren: ')', .. });
3359 assert_error!(
3360 r#"(hello"#,
3361 Export<'_>,
3362 UnexpectedToken {
3363 expected: "'export' keyword for export",
3364 ..
3365 }
3366 );
3367 assert_error!(r#"(export "hi" (hello 0))"#, Export<'_>, UnexpectedKeyword("hello"));
3368 }
3369
3370 #[test]
3371 fn func_field() {
3372 assert_parse!(
3373 r#"(func $f (import "m" "n") (type 0))"#,
3374 Func<'_>,
3375 Func {
3376 kind: FuncKind::Import(Import {
3377 mod_name: Name(m),
3378 name: Name(n),
3379 }),
3380 ..
3381 } if m == "m" && n == "n"
3382 );
3383 let parser = assert_parse!(
3384 r#"(func $f (export "n") (type 0))"#,
3385 Func<'_>,
3386 Func {
3387 ty: TypeUse {
3388 idx: TypeIndex::Explicit(Index::Num(0)),
3389 ..
3390 },
3391 kind: FuncKind::Body {
3392 locals,
3393 body,
3394 },
3395 ..
3396 }
3397 if locals.is_empty() && body.is_empty()
3398 );
3399 assert_eq!(parser.ctx.exports.len(), 1);
3400 match &parser.ctx.exports[0] {
3401 Export {
3402 name: Name(n),
3403 kind: ExportKind::Func,
3404 idx: Index::Num(0),
3405 ..
3406 } if n == "n" => { }
3407 e => panic!("did not match: {:?}", e),
3408 }
3409 assert_parse!(
3410 r#"(func (type 0))"#,
3411 Func<'_>,
3412 Func {
3413 id: None,
3414 ty: TypeUse {
3415 idx: TypeIndex::Explicit(Index::Num(0)),
3416 ..
3417 },
3418 kind: FuncKind::Body {
3419 locals,
3420 body,
3421 },
3422 ..
3423 } if locals.is_empty() && body.is_empty()
3424 );
3425 assert_parse!(
3426 r#"(func $f (type 0))"#,
3427 Func<'_>,
3428 Func {
3429 id: Some("$f"),
3430 ty: TypeUse {
3431 idx: TypeIndex::Explicit(Index::Num(0)),
3432 ..
3433 },
3434 ..
3435 }
3436 );
3437 assert_parse!(
3438 r#"(func $f)"#,
3439 Func<'_>,
3440 Func {
3441 id: Some("$f"),
3442 ty: TypeUse {
3443 idx: TypeIndex::Implicit(0),
3444 ..
3445 },
3446 ..
3447 }
3448 );
3449 assert_parse!(
3450 r#"(func $f (type 0) (local))"#,
3451 Func<'_>,
3452 Func {
3453 id: Some("$f"),
3454 ty: TypeUse {
3455 idx: TypeIndex::Explicit(Index::Num(0)),
3456 ..
3457 },
3458 kind: FuncKind::Body {
3459 locals,
3460 ..
3461 },
3462 ..
3463 } if locals.is_empty()
3464 );
3465 assert_parse!(
3466 r#"(func $f (type 0) (local i32))"#,
3467 Func<'_>,
3468 Func {
3469 id: Some("$f"),
3470 ty: TypeUse {
3471 idx: TypeIndex::Explicit(Index::Num(0)),
3472 ..
3473 },
3474 kind: FuncKind::Body {
3475 locals,
3476 ..
3477 },
3478 ..
3479 } if locals[0].ty == ValType::I32 && locals[0].id.is_none()
3480 );
3481 assert_parse!(
3482 r#"(func $f (type 0) (local $l i32))"#,
3483 Func<'_>,
3484 Func {
3485 id: Some("$f"),
3486 ty: TypeUse {
3487 idx: TypeIndex::Explicit(Index::Num(0)),
3488 ..
3489 },
3490 kind: FuncKind::Body {
3491 locals,
3492 ..
3493 },
3494 ..
3495 } if locals[0].ty == ValType::I32 && locals[0].id == Some("$l")
3496 );
3497 assert_parse!(
3498 r#"(func $f (type 0) (local i32 f64))"#,
3499 Func<'_>,
3500 Func {
3501 id: Some("$f"),
3502 ty: TypeUse {
3503 idx: TypeIndex::Explicit(Index::Num(0)),
3504 ..
3505 },
3506 kind: FuncKind::Body {
3507 locals,
3508 ..
3509 },
3510 ..
3511 } if locals.iter().map(|l| l.ty).collect::<Vec<_>>() == vec![ValType::I32, ValType::F64] &&
3512 locals.iter().map(|l| l.id).collect::<Vec<_>>() == vec![None, None]
3513 );
3514 assert_parse!(
3515 r#"(func $f (type 0) (local i32) (local f64))"#,
3516 Func<'_>,
3517 Func {
3518 id: Some("$f"),
3519 ty: TypeUse {
3520 idx: TypeIndex::Explicit(Index::Num(0)),
3521 ..
3522 },
3523 kind: FuncKind::Body {
3524 locals,
3525 ..
3526 },
3527 ..
3528 } if locals.iter().map(|l| l.ty).collect::<Vec<_>>() == vec![ValType::I32, ValType::F64] &&
3529 locals.iter().map(|l| l.id).collect::<Vec<_>>() == vec![None, None]
3530 );
3531 assert_parse!(
3532 r#"(func $f (type 0) (local $l1 i32) (local $l2 f64))"#,
3533 Func<'_>,
3534 Func {
3535 id: Some("$f"),
3536 ty: TypeUse {
3537 idx: TypeIndex::Explicit(Index::Num(0)),
3538 ..
3539 },
3540 kind: FuncKind::Body {
3541 locals,
3542 ..
3543 },
3544 ..
3545 } if locals.iter().map(|l| l.ty).collect::<Vec<_>>() == vec![ValType::I32, ValType::F64] &&
3546 locals.iter().map(|l| l.id).collect::<Vec<_>>() == vec![Some("$l1"), Some("$l2")]
3547 );
3548 assert_parse!(
3549 r#"(func $_start (result i32))"#,
3550 Func<'_>,
3551 Func {
3552 id: Some("$_start"),
3553 ty: TypeUse {
3554 idx: TypeIndex::Implicit(0),
3555 params,
3556 results,
3557 ..
3558 },
3559 kind: FuncKind::Body {
3560 locals,
3561 ..
3562 },
3563 ..
3564 } if params.is_empty() && results[0].ty == ValType::I32 && locals.is_empty()
3565 );
3566 let parser = assert_parse!(
3568 r#"(func (export "a") (export "b") (export "c"))"#,
3569 Func<'_>,
3570 Func { .. }
3571 );
3572 assert!(matches!(parser.ctx.exports.as_slice(), [
3573 Export {
3574 name: Name(n1),
3575 kind: ExportKind::Func,
3576 idx: Index::Num(0),
3577 ..
3578 },
3579 Export {
3580 name: Name(n2),
3581 kind: ExportKind::Func,
3582 idx: Index::Num(0),
3583 ..
3584 },
3585 Export {
3586 name: Name(n3),
3587 kind: ExportKind::Func,
3588 idx: Index::Num(0),
3589 ..
3590 },
3591 ] if n1 == "a" && n2 == "b" && n3 == "c"));
3592 let parser = assert_parse!(
3593 r#"(func $f (export "a") (export "b") (type 0) (local i32 f64) (i32.const 10))"#,
3594 Func<'_>,
3595 Func {
3596 id: Some("$f"),
3597 ty: TypeUse {
3598 idx: TypeIndex::Explicit(Index::Num(0)),
3599 ..
3600 },
3601 kind: FuncKind::Body {
3602 locals,
3603 body,
3604 },
3605 ..
3606 }
3607 if locals.len() == 2 && body.len() == 1
3608 );
3609 assert!(matches!(parser.ctx.exports.as_slice(), [
3610 Export {
3611 name: Name(n1),
3612 kind: ExportKind::Func,
3613 idx: Index::Num(0),
3614 ..
3615 },
3616 Export {
3617 name: Name(n2),
3618 kind: ExportKind::Func,
3619 idx: Index::Num(0),
3620 ..
3621 },
3622 ] if n1 == "a" && n2 == "b"));
3623 }
3624
3625 macro_rules! assert_insn {
3626 ($p:ident => $init:expr, $input:expr, $expect:pat if $cond:expr) => {
3627 let input = concat!($input, ')');
3628 let mut $p = Parser::new(input);
3629 { $init; }
3630 let insns: Vec<Instruction> = $p.parse().unwrap();
3631 let kinds = insns.into_iter().map(|i| i.kind).collect::<Vec<_>>();
3632 match kinds.as_slice() {
3633 $expect if $cond => { }
3634 i => panic!(
3635 "assertion failed: {:?} did not match to {}",
3636 i,
3637 stringify!($expect if $cond)
3638 ),
3639 }
3640 match $p.tokens.next() {
3641 Some(Ok((Token::RParen, _))) => (),
3642 tok => assert!(false, "Tokens still remain: {:?} and then {:?}", tok, $p.tokens.collect::<Vec<_>>()),
3643 }
3644 };
3645 ($p:ident => $init:expr, $input:expr, $expect:pat) => {
3646 assert_insn!($p => $init, $input, $expect if true);
3647 };
3648 ($input:expr, $expect:pat if $cond:expr) => {
3649 assert_insn!(p => (), $input, $expect if $cond);
3650 };
3651 ($input:expr, $expect:pat) => {
3652 assert_insn!($input, $expect if true);
3653 };
3654 }
3655
3656 #[test]
3657 fn insn_abbrev() {
3658 use InsnKind::*;
3659 assert_insn!(r#"nop"#, [Nop]);
3660 assert_insn!(r#"(nop)"#, [Nop]);
3661 assert_insn!(r#"(unreachable (nop))"#, [Nop, Unreachable]);
3662 assert_insn!(r#"(return (nop) (unreachable))"#, [Nop, Unreachable, Return]);
3663 assert_insn!(r#"(return (unreachable (nop)))"#, [Nop, Unreachable, Return]);
3664 assert_insn!(r#"(nop (return (nop) (unreachable)))"#, [Nop, Unreachable, Return, Nop]);
3665 assert_insn!(r#"nop unreachable return"#, [Nop, Unreachable, Return]);
3666 assert_insn!(r#"nop (nop) (nop)"#, [Nop, Nop, Nop]);
3667 assert_insn!(r#"(nop) nop (nop)"#, [Nop, Nop, Nop]);
3668 assert_insn!(r#"(nop) (nop) nop"#, [Nop, Nop, Nop]);
3669 assert_insn!(r#"nop (nop (nop))"#, [Nop, Nop, Nop]);
3670 assert_insn!(r#"(nop (nop)) nop"#, [Nop, Nop, Nop]);
3671 assert_insn!(r#"block block block end end end"#, [Block { body, .. }]
3672 if match &body[0].kind {
3673 Block { body, ..} => match &body[0].kind {
3674 Block { body, .. } => body.is_empty(),
3675 n => panic!("nest 2: {:?}", n),
3676 }
3677 n => panic!("nest 1: {:?}", n),
3678 }
3679 );
3680 assert_insn!(r#"(block (block (block )))"#, [Block { body, .. }]
3681 if match &body[0].kind {
3682 Block { body, ..} => match &body[0].kind {
3683 Block { body, .. } => body.is_empty(),
3684 n => panic!("nest 2: {:?}", n),
3685 }
3686 n => panic!("nest 1: {:?}", n),
3687 }
3688 );
3689 assert_insn!(r#"block (block block end) end"#, [Block { body, .. }]
3690 if match &body[0].kind {
3691 Block { body, ..} => match &body[0].kind {
3692 Block { body, .. } => body.is_empty(),
3693 n => panic!("nest 2: {:?}", n),
3694 }
3695 n => panic!("nest 1: {:?}", n),
3696 }
3697 );
3698
3699 assert_error!(
3700 r#"(nop nop)"#,
3701 Vec<Instruction>,
3702 MissingParen {
3703 paren: ')',
3704 what: "folded instruction",
3705 ..
3706 }
3707 );
3708 assert_error!(r#"not-exist"#, Vec<Instruction>, UnexpectedKeyword("not-exist"));
3709 assert_error!(r#"(not-exist)"#, Vec<Instruction>, UnexpectedKeyword("not-exist"));
3710 }
3711
3712 #[test]
3713 fn control_instructions() {
3714 use InsnKind::*;
3715 assert_insn!(
3716 r#"block end"#,
3717 [
3718 Block{ label: None, ty: None, body, id: None }
3719 ] if body.is_empty()
3720 );
3721 assert_insn!(
3722 r#"block $blk end $id"#,
3723 [
3724 Block{ label: Some("$blk"), ty: None, body, id: Some("$id") }
3725 ] if body.is_empty()
3726 );
3727 assert_insn!(
3728 r#"block $blk (result i32) end"#,
3729 [
3730 Block{ label: Some("$blk"), ty: Some(ValType::I32), body, id: None }
3731 ] if body.is_empty()
3732 );
3733 assert_insn!(
3734 r#"block (result i32) end"#,
3735 [
3736 Block{ label: None, ty: Some(ValType::I32), body, id: None }
3737 ] if body.is_empty()
3738 );
3739 assert_insn!(
3740 r#"block nop end"#,
3741 [
3742 Block{ label: None, ty: None, body, id: None }
3743 ] if matches!(body[0].kind, Nop)
3744 );
3745 assert_insn!(
3746 r#"block $blk nop end"#,
3747 [
3748 Block{ label: Some("$blk"), ty: None, body, id: None }
3749 ] if matches!(body[0].kind, Nop)
3750 );
3751 assert_insn!(
3752 r#"block (result i32) nop end"#,
3753 [
3754 Block{ label: None, ty: Some(ValType::I32), body, id: None }
3755 ] if matches!(body[0].kind, Nop)
3756 );
3757 assert_insn!(
3758 r#"(block)"#,
3759 [
3760 Block{ label: None, ty: None, body, id: None }
3761 ] if body.is_empty()
3762 );
3763 assert_insn!(
3764 r#"(block $blk)"#,
3765 [
3766 Block{ label: Some("$blk"), ty: None, body, id: None }
3767 ] if body.is_empty()
3768 );
3769 assert_insn!(
3770 r#"(block (result i32))"#,
3771 [
3772 Block{ label: None, ty: Some(ValType::I32), body, id: None }
3773 ] if body.is_empty()
3774 );
3775 assert_insn!(
3776 r#"(block nop)"#,
3777 [
3778 Block{ label: None, ty: None, body, id: None }
3779 ] if matches!(body[0].kind, Nop)
3780 );
3781 assert_insn!(
3783 r#"loop end"#,
3784 [
3785 Loop{ label: None, ty: None, body, id: None }
3786 ] if body.is_empty()
3787 );
3788 assert_insn!(
3789 r#"if end"#,
3790 [
3791 If{ label: None, ty: None, then_body, else_id: None, else_body, end_id: None }
3792 ] if then_body.is_empty() && else_body.is_empty()
3793 );
3794 assert_insn!(
3795 r#"if else end"#,
3796 [
3797 If{ label: None, ty: None, then_body, else_id: None, else_body, end_id: None }
3798 ] if then_body.is_empty() && else_body.is_empty()
3799 );
3800 assert_insn!(
3801 r#"if $l (result i32) else $a end $b"#,
3802 [
3803 If{ label: Some("$l"), ty: Some(ValType::I32), then_body, else_id: Some("$a"), else_body, end_id: Some("$b") }
3804 ] if then_body.is_empty() && else_body.is_empty()
3805 );
3806 assert_insn!(
3807 r#"if $l (result i32) else $a end $b"#,
3808 [
3809 If{ label: Some("$l"), ty: Some(ValType::I32), then_body, else_id: Some("$a"), else_body, end_id: Some("$b") }
3810 ] if then_body.is_empty() && else_body.is_empty()
3811 );
3812 assert_insn!(
3813 r#"if $l (result i32) end $b"#,
3814 [
3815 If{ label: Some("$l"), ty: Some(ValType::I32), then_body, else_id: None, else_body, end_id: Some("$b") }
3816 ] if then_body.is_empty() && else_body.is_empty()
3817 );
3818 assert_insn!(
3819 r#"if $l end"#,
3820 [
3821 If{ label: Some("$l"), ty: None, then_body, else_id: None, else_body, end_id: None }
3822 ] if then_body.is_empty() && else_body.is_empty()
3823 );
3824 assert_insn!(
3825 r#"if (result i32) end"#,
3826 [
3827 If{ label: None, ty: Some(ValType::I32), then_body, else_id: None, else_body, end_id: None }
3828 ] if then_body.is_empty() && else_body.is_empty()
3829 );
3830 assert_insn!(
3831 r#"if nop end"#,
3832 [
3833 If{ label: None, ty: None, then_body, else_id: None, else_body, end_id: None }
3834 ] if matches!(then_body[0].kind, Nop) && else_body.is_empty()
3835 );
3836 assert_insn!(
3837 r#"if $l nop end"#,
3838 [
3839 If{ label: Some("$l"), ty: None, then_body, else_id: None, else_body, end_id: None }
3840 ] if matches!(then_body[0].kind, Nop) && else_body.is_empty()
3841 );
3842 assert_insn!(
3843 r#"if $l (result i32) nop end"#,
3844 [
3845 If{ label: Some("$l"), ty: Some(ValType::I32), then_body, else_id: None, else_body, end_id: None }
3846 ] if matches!(then_body[0].kind, Nop) && else_body.is_empty()
3847 );
3848 assert_insn!(
3849 r#"if nop else unreachable end"#,
3850 [
3851 If{ label: None, ty: None, then_body, else_id: None, else_body, end_id: None }
3852 ] if matches!(then_body[0].kind, Nop) && matches!(else_body[0].kind, Unreachable)
3853 );
3854 assert_insn!(
3855 r#"(if (then))"#,
3856 [
3857 If{ label: None, ty: None, then_body, else_id: None, else_body, end_id: None }
3858 ] if then_body.is_empty() && else_body.is_empty()
3859 );
3860 assert_insn!(
3861 r#"(if $l (then))"#,
3862 [
3863 If{ label: Some("$l"), ty: None, then_body, else_id: None, else_body, end_id: None }
3864 ] if then_body.is_empty() && else_body.is_empty()
3865 );
3866 assert_insn!(
3867 r#"(if $l (result i32) (then))"#,
3868 [
3869 If{ label: Some("$l"), ty: Some(ValType::I32), then_body, else_id: None, else_body, end_id: None }
3870 ] if then_body.is_empty() && else_body.is_empty()
3871 );
3872 assert_insn!(
3873 r#"(if (then) (else))"#,
3874 [
3875 If{ label: None, ty: None, then_body, else_id: None, else_body, end_id: None }
3876 ] if then_body.is_empty() && else_body.is_empty()
3877 );
3878 assert_insn!(
3879 r#"(if $l (then) (else))"#,
3880 [
3881 If{ label: Some("$l"), ty: None, then_body, else_id: None, else_body, end_id: None }
3882 ] if then_body.is_empty() && else_body.is_empty()
3883 );
3884 assert_insn!(
3885 r#"(if $l (result i32) (then) (else))"#,
3886 [
3887 If{ label: Some("$l"), ty: Some(ValType::I32), then_body, else_id: None, else_body, end_id: None }
3888 ] if then_body.is_empty() && else_body.is_empty()
3889 );
3890 assert_insn!(
3891 r#"(if (then nop))"#,
3892 [
3893 If{ label: None, ty: None, then_body, else_id: None, else_body, end_id: None }
3894 ] if matches!(then_body[0].kind, Nop) && else_body.is_empty()
3895 );
3896 assert_insn!(
3897 r#"(if (then nop) (else nop))"#,
3898 [
3899 If{ label: None, ty: None, then_body, else_id: None, else_body, end_id: None }
3900 ] if matches!(then_body[0].kind, Nop) && matches!(else_body[0].kind, Nop)
3901 );
3902 assert_insn!(
3903 r#"(if (then (nop)) (else (nop)))"#,
3904 [
3905 If{ label: None, ty: None, then_body, else_id: None, else_body, end_id: None }
3906 ] if matches!(then_body[0].kind, Nop) && matches!(else_body[0].kind, Nop)
3907 );
3908 assert_insn!(
3909 r#"(if (then nop nop) (else nop nop))"#,
3910 [
3911 If{ label: None, ty: None, then_body, else_id: None, else_body, end_id: None }
3912 ] if then_body.len() == 2 && else_body.len() == 2
3913 );
3914 assert_insn!(
3915 r#"(if (then (nop (nop))) (else (nop (nop))))"#,
3916 [
3917 If{ label: None, ty: None, then_body, else_id: None, else_body, end_id: None }
3918 ] if then_body.len() == 2 && else_body.len() == 2
3919 );
3920 assert_insn!(
3921 r#"(if (nop) (then) (else))"#,
3922 [
3923 Nop,
3924 If{ label: None, ty: None, then_body, else_id: None, else_body, end_id: None }
3925 ] if then_body.is_empty() && else_body.is_empty()
3926 );
3927 assert_insn!(
3928 r#"(if (nop) (nop) (nop) (then))"#,
3929 [
3930 Nop, Nop, Nop,
3931 If{ label: None, ty: None, then_body, else_id: None, else_body, end_id: None }
3932 ] if then_body.is_empty() && else_body.is_empty()
3933 );
3934 assert_insn!(r#"unreachable"#, [Unreachable]);
3935 assert_insn!(r#"br 0"#, [Br(Index::Num(0))]);
3936 assert_insn!(r#"br $blk"#, [Br(Index::Ident("$blk"))]);
3937 assert_insn!(r#"br_if 0"#, [BrIf(Index::Num(0))]);
3938 assert_insn!(r#"br_if $blk"#, [BrIf(Index::Ident("$blk"))]);
3939 assert_insn!(
3940 r#"br_table 0"#,
3941 [BrTable {
3942 labels,
3943 default_label: Index::Num(0)
3944 }] if labels.is_empty()
3945 );
3946 assert_insn!(
3947 r#"br_table 1 2 3 0"#,
3948 [
3949 BrTable {
3950 labels,
3951 default_label: Index::Num(0)
3952 }
3953 ] if labels
3954 .iter()
3955 .map(|i| match i {
3956 Index::Num(n) => *n,
3957 Index::Ident(i) => panic!("unexpected index: {}", i),
3958 })
3959 .collect::<Vec<_>>() == vec![1, 2, 3]
3960 );
3961 assert_insn!(
3962 r#"br_table $a $b $c $x"#,
3963 [
3964 BrTable {
3965 labels,
3966 default_label: Index::Ident("$x")
3967 }
3968 ] if labels
3969 .iter()
3970 .map(|i| match i {
3971 Index::Num(n) => panic!("unexpected index: {}", n),
3972 Index::Ident(i) => *i,
3973 })
3974 .collect::<Vec<_>>() == vec!["$a", "$b", "$c"]
3975 );
3976 assert_insn!(r#"call 0"#, [Call(Index::Num(0))]);
3977 assert_insn!(r#"call $f"#, [Call(Index::Ident("$f"))]);
3978 assert_insn!(
3979 r#"call_indirect (type 0)"#,
3980 [CallIndirect(TypeUse {
3981 idx: TypeIndex::Explicit(Index::Num(0)),
3982 ..
3983 })]
3984 );
3985
3986 assert_error!(r#"br_table)"#, Vec<Instruction<'_>>, InvalidOperand { .. });
3987 assert_error!(
3988 r#"(if (then nop) else nop)"#,
3989 Vec<Instruction<'_>>,
3990 UnexpectedToken {
3991 got: Token::Keyword("else"),
3992 ..
3993 }
3994 );
3995 assert_error!(
3996 r#"call_indirect (type 0) (param $p i32))"#,
3997 Vec<Instruction<'_>>,
3998 IdBoundToParam("$p")
3999 );
4000 }
4001
4002 #[test]
4003 fn parametric_instructions() {
4004 use InsnKind::*;
4005 assert_insn!(r#"drop"#, [Drop]);
4006 assert_insn!(r#"select"#, [Select]);
4007 }
4008
4009 #[test]
4010 fn variable_instructions() {
4011 use InsnKind::*;
4012 assert_insn!(r#"local.get 0"#, [LocalGet(Index::Num(0))]);
4013 assert_insn!(r#"local.get $x"#, [LocalGet(Index::Ident("$x"))]);
4014 assert_insn!(r#"local.set 0"#, [LocalSet(Index::Num(0))]);
4015 assert_insn!(r#"local.tee 0"#, [LocalTee(Index::Num(0))]);
4016 assert_insn!(r#"global.get 0"#, [GlobalGet(Index::Num(0))]);
4017 assert_insn!(r#"global.set 0"#, [GlobalSet(Index::Num(0))]);
4018
4019 assert_error!(r#"local.get foo"#, Vec<Instruction<'_>>, UnexpectedToken { .. });
4020 }
4021
4022 #[test]
4023 fn memory_instructions() {
4024 use InsnKind::*;
4025 assert_insn!(r#"i32.load"#, [I32Load(Mem { align: 2, offset: 0 })]);
4026 assert_insn!(r#"i32.load align=32"#, [I32Load(Mem { align: 5, offset: 0 })]);
4027 assert_insn!(r#"i32.load offset=10"#, [I32Load(Mem { align: 2, offset: 10 })]);
4028 assert_insn!(
4029 r#"i32.load offset=10 align=32"#,
4030 [I32Load(Mem { align: 5, offset: 10 })]
4031 );
4032 assert_insn!(
4033 r#"i32.load offset=0x1f align=0x80"#,
4034 [I32Load(Mem { align: 7, offset: 0x1f })]
4035 );
4036 assert_insn!(r#"i64.load"#, [I64Load(..)]);
4037 assert_insn!(r#"f32.load"#, [F32Load(..)]);
4038 assert_insn!(r#"f64.load"#, [F64Load(..)]);
4039 assert_insn!(r#"i32.load8_s"#, [I32Load8S(..)]);
4040 assert_insn!(r#"i32.load8_u"#, [I32Load8U(..)]);
4041 assert_insn!(r#"i32.load16_s"#, [I32Load16S(..)]);
4042 assert_insn!(r#"i32.load16_u"#, [I32Load16U(..)]);
4043 assert_insn!(r#"i64.load8_s"#, [I64Load8S(..)]);
4044 assert_insn!(r#"i64.load8_u"#, [I64Load8U(..)]);
4045 assert_insn!(r#"i64.load16_s"#, [I64Load16S(..)]);
4046 assert_insn!(r#"i64.load16_u"#, [I64Load16U(..)]);
4047 assert_insn!(r#"i64.load32_s"#, [I64Load32S(..)]);
4048 assert_insn!(r#"i64.load32_u"#, [I64Load32U(..)]);
4049 assert_insn!(r#"i32.store"#, [I32Store(..)]);
4050 assert_insn!(r#"i64.store"#, [I64Store(..)]);
4051 assert_insn!(r#"f32.store"#, [F32Store(..)]);
4052 assert_insn!(r#"f64.store"#, [F64Store(..)]);
4053 assert_insn!(r#"i32.store8"#, [I32Store8(..)]);
4054 assert_insn!(r#"i32.store16"#, [I32Store16(..)]);
4055 assert_insn!(r#"i64.store8"#, [I64Store8(..)]);
4056 assert_insn!(r#"i64.store16"#, [I64Store16(..)]);
4057 assert_insn!(r#"i64.store32"#, [I64Store32(..)]);
4058 assert_insn!(r#"memory.size"#, [MemorySize]);
4059 assert_insn!(r#"memory.grow"#, [MemoryGrow]);
4060
4061 assert_error!(
4062 r#"i32.load align=32 offset=10"#,
4063 Vec<Instruction<'_>>,
4064 UnexpectedKeyword("offset=10")
4065 );
4066 assert_error!(r#"i32.load align=pqr"#, Vec<Instruction<'_>>, CannotParseNum { .. });
4067 assert_error!(r#"i32.load align=0"#, Vec<Instruction<'_>>, InvalidAlignment(0));
4068 assert_error!(r#"i32.load align=7"#, Vec<Instruction<'_>>, InvalidAlignment(7));
4069 }
4070
4071 #[test]
4072 fn const_instructions() {
4073 use InsnKind::*;
4074 assert_insn!(r#"i32.const 0"#, [I32Const(0)]);
4075 assert_insn!(r#"i32.const 42"#, [I32Const(42)]);
4076 assert_insn!(r#"i32.const 4_2"#, [I32Const(42)]);
4077 assert_insn!(r#"i32.const 0x1f"#, [I32Const(0x1f)]);
4078 assert_insn!(r#"i32.const -0"#, [I32Const(-0)]);
4079 assert_insn!(r#"i32.const -42"#, [I32Const(-42)]);
4080 assert_insn!(r#"i32.const -0x1f"#, [I32Const(-0x1f)]);
4081 assert_insn!(r#"i32.const 2147483647"#, [I32Const(2147483647)]); assert_insn!(r#"i32.const 0x7fffffff"#, [I32Const(0x7fffffff)]); assert_insn!(r#"i32.const -2147483648"#, [I32Const(-2147483648)]); assert_insn!(r#"i32.const -0x80000000"#, [I32Const(-0x80000000)]); assert_insn!(r#"i32.const 0xfedc6543"#, [I32Const(-19110589)]); assert_insn!(r#"i32.const 4294967295"#, [I32Const(-1)]); assert_insn!(r#"i32.const 0xffffffff"#, [I32Const(-1)]); assert_error!(
4090 r#"i32.const 0.123"#,
4091 Vec<Instruction<'_>>,
4092 UnexpectedToken {
4093 expected: "integer for i32.const operand",
4094 ..
4095 }
4096 );
4097 assert_error!(
4099 r#"i32.const 4294967296"#,
4100 Vec<Instruction<'_>>,
4101 CannotParseNum{ reason, .. } if reason == "too big integer"
4102 );
4103 assert_error!(
4105 r#"i32.const 0x100000000"#,
4106 Vec<Instruction<'_>>,
4107 CannotParseNum{ reason, .. } if reason == "too big integer"
4108 );
4109 assert_error!(
4110 r#"i32.const -0x80000001"#,
4111 Vec<Instruction<'_>>,
4112 CannotParseNum{ reason, .. } if reason == "too small integer"
4113 );
4114 assert_error!(
4115 r#"i32.const -0x99999999"#,
4116 Vec<Instruction<'_>>,
4117 CannotParseNum{ reason, .. } if reason == "too small integer"
4118 );
4119
4120 assert_insn!(r#"i64.const 0"#, [I64Const(0)]);
4121 assert_insn!(r#"i64.const 42"#, [I64Const(42)]);
4122 assert_insn!(r#"i64.const 4_2"#, [I64Const(42)]);
4123 assert_insn!(r#"i64.const 0x1f"#, [I64Const(0x1f)]);
4124 assert_insn!(r#"i64.const 0x1_f"#, [I64Const(0x1f)]);
4125 assert_insn!(r#"i64.const -42"#, [I64Const(-42)]);
4126 assert_insn!(r#"i64.const -0x1f"#, [I64Const(-0x1f)]);
4127 assert_insn!(
4128 r#"i64.const 9223372036854775807"#, [I64Const(9223372036854775807)]
4130 );
4131 assert_insn!(
4132 r#"i64.const -9223372036854775808"#, [I64Const(-9223372036854775808)]
4134 );
4135 assert_insn!(
4136 r#"i64.const 0x7fffffffffffffff"#, [I64Const(0x7fffffffffffffff)]
4138 );
4139 assert_insn!(
4140 r#"i64.const -0x8000000000000000"#, [I64Const(-0x8000000000000000)]
4142 );
4143 assert_insn!(
4144 r#"i64.const 0x8000000000000000"#, [I64Const(-9223372036854775808)]
4146 );
4147 assert_insn!(
4148 r#"i64.const 0xffffffffffffffff"#, [I64Const(-1)]
4150 );
4151 assert_insn!(
4152 r#"i64.const 18446744073709551615"#, [I64Const(-1)]
4154 );
4155
4156 assert_error!(
4157 r#"i64.const 0.123"#,
4158 Vec<Instruction<'_>>,
4159 UnexpectedToken {
4160 expected: "integer for i64.const operand",
4161 ..
4162 }
4163 );
4164 assert_error!(
4165 r#"i64.const 0x10000000000000000"#, Vec<Instruction<'_>>,
4167 CannotParseNum{ reason, .. }
4168 if reason == "too big integer"
4169 );
4170 assert_error!(
4171 r#"i64.const 18446744073709551616"#, Vec<Instruction<'_>>,
4173 CannotParseNum{ reason, .. }
4174 if reason == "too big integer"
4175 );
4176 assert_error!(
4177 r#"i64.const -0x8000000000000001"#,
4178 Vec<Instruction<'_>>,
4179 CannotParseNum{ reason, .. }
4180 if reason == "too small integer"
4181 );
4182 assert_error!(
4183 r#"i64.const -0x9999999999999999"#,
4184 Vec<Instruction<'_>>,
4185 CannotParseNum{ reason, .. }
4186 if reason == "too small integer"
4187 );
4188
4189 assert_insn!(r#"f32.const 42"#, [F32Const(f)] if *f == 42.0);
4190 assert_insn!(r#"f32.const 0x42"#, [F32Const(f)] if *f == 66.0);
4191 assert_insn!(r#"f32.const 8589934592"#, [F32Const(f)] if *f > 85899e5 && *f < 85900e5);
4192 assert_insn!(r#"f32.const 42."#, [F32Const(f)] if *f == 42.0);
4193 assert_insn!(r#"f32.const 42.0"#, [F32Const(f)] if *f == 42.0);
4194 assert_insn!(r#"f32.const 4_2."#, [F32Const(f)] if *f == 42.0);
4195 assert_insn!(r#"f32.const 0x1f."#, [F32Const(f)] if *f == 31.0);
4196 assert_insn!(r#"f32.const -42."#, [F32Const(f)] if *f == -42.0);
4197 assert_insn!(r#"f32.const -4_2."#, [F32Const(f)] if *f == -42.0);
4198 assert_insn!(r#"f32.const -0x1f."#, [F32Const(f)] if *f == -31.0);
4199 assert_insn!(r#"f32.const 1.2_3"#, [F32Const(f)] if *f == 1.23);
4200 assert_insn!(r#"f32.const 1.2_3E3"#, [F32Const(f)] if *f == 1.23e3);
4201 assert_insn!(r#"f32.const 120.4E-3"#, [F32Const(f)] if *f == 120.4e-3);
4202 assert_insn!(r#"f32.const 99E+1_3"#, [F32Const(f)] if *f == 99e13);
4203 assert_insn!(r#"f32.const 0xe."#, [F32Const(f)] if *f == 0xe as f32);
4204 assert_insn!(r#"f32.const 0xe_f."#, [F32Const(f)] if *f == 0xef as f32);
4205 assert_insn!(r#"f32.const 0x1_f.2_e"#, [F32Const(f)] if *f == 0x1f as f32 + 2.0 / 16.0 + 14.0 / (16.0 * 16.0));
4206 assert_insn!(r#"f32.const 0xe.f"#, [F32Const(f)] if *f == 14.0 + 15.0 / 16.0);
4207 assert_insn!(r#"f32.const 0xe.fP3"#, [F32Const(f)] if *f == (14.0 + 15.0 / 16.0) * 2.0 * 2.0 * 2.0);
4208 assert_insn!(r#"f32.const 0xe.fP-1"#, [F32Const(f)] if *f == (14.0 + 15.0 / 16.0) / 2.0);
4209 assert_insn!(r#"f32.const 3.4E38"#, [F32Const(f)] if *f == 3.4E38); assert_insn!(r#"f32.const 2.E-149"#, [F32Const(f)] if *f == 2.0e-149);
4211 assert_insn!(r#"f32.const 1.4E-45"#, [F32Const(f)] if *f == 1.4E-45); assert_insn!(r#"f32.const inf"#, [F32Const(f)] if *f == f32::INFINITY);
4213 assert_insn!(r#"f32.const nan"#, [F32Const(f)] if f.is_nan());
4214 assert_insn!(r#"f32.const nan:0x401234"#, [F32Const(f)] if f.is_nan());
4215 assert_insn!(r#"f32.const nan:0x1"#, [F32Const(f)] if f.is_nan());
4216 assert_insn!(r#"f32.const -inf"#, [F32Const(f)] if *f == f32::NEG_INFINITY);
4217 assert_insn!(r#"f32.const -nan"#, [F32Const(f)] if f.is_nan());
4218 assert_insn!(r#"f32.const -nan:0x401234"#, [F32Const(f)] if f.is_nan());
4219 assert_insn!(r#"f32.const 1.32"#, [F32Const(f)] if *f == 1.32);
4220
4221 assert_error!(
4222 r#"f32.const nan:0x0"#,
4223 Vec<Instruction<'_>>,
4224 CannotParseNum{ reason, .. }
4225 if reason == "payload of NaN must be in range of 1 <= payload < 2^23"
4226 );
4227 assert_error!(
4228 r#"f32.const nan:0x100_0000"#, Vec<Instruction<'_>>,
4230 CannotParseNum{ reason, .. }
4231 if reason == "payload of NaN must be in range of 1 <= payload < 2^23"
4232 );
4233
4234 assert_insn!(r#"f64.const 42"#, [F64Const(f)] if *f == 42.0);
4235 assert_insn!(r#"f64.const 0x42"#, [F64Const(f)] if *f == 66.0);
4236 assert_insn!(r#"f64.const 36893488147419103232"#, [F64Const(f)] if *f == 36893488147419103232.0);
4237 assert_insn!(r#"f64.const 42."#, [F64Const(f)] if *f == 42.0);
4238 assert_insn!(r#"f64.const 42.0"#, [F64Const(f)] if *f == 42.0);
4239 assert_insn!(r#"f64.const 4_2."#, [F64Const(f)] if *f == 42.0);
4240 assert_insn!(r#"f64.const 0x1f."#, [F64Const(f)] if *f == 31.0);
4241 assert_insn!(r#"f64.const -42."#, [F64Const(f)] if *f == -42.0);
4242 assert_insn!(r#"f64.const -4_2."#, [F64Const(f)] if *f == -42.0);
4243 assert_insn!(r#"f64.const -0x1f."#, [F64Const(f)] if *f == -31.0);
4244 assert_insn!(r#"f64.const 1.2_3"#, [F64Const(f)] if *f == 1.23);
4245 assert_insn!(r#"f64.const 1.2_3E3"#, [F64Const(f)] if *f == 1.23e3);
4246 assert_insn!(r#"f64.const 100.4E-2"#, [F64Const(f)] if *f == 100.4e-2);
4247 assert_insn!(r#"f64.const 99E+1_3"#, [F64Const(f)] if *f == 99e+13);
4248 assert_insn!(r#"f64.const 0xe."#, [F64Const(f)] if *f == 0xe as f64);
4249 assert_insn!(r#"f64.const 0xe_f."#, [F64Const(f)] if *f == 0xef as f64);
4250 assert_insn!(r#"f64.const 0x1_f.2_e"#, [F64Const(f)] if *f == 0x1f as f64 + 2.0 / 16.0 + 14.0 / (16.0 * 16.0));
4251 assert_insn!(r#"f64.const 0xe.f"#, [F64Const(f)] if *f == 14.0 + 15.0 / 16.0);
4252 assert_insn!(r#"f64.const 0xe.fP3"#, [F64Const(f)] if *f == (14.0 + 15.0 / 16.0) * 2.0 * 2.0 * 2.0);
4253 assert_insn!(r#"f64.const 0xe.fP-1"#, [F64Const(f)] if *f == (14.0 + 15.0 / 16.0) / 2.0);
4254 assert_insn!(r#"f64.const inf"#, [F64Const(f)] if *f == f64::INFINITY);
4255 assert_insn!(r#"f64.const nan"#, [F64Const(f)] if f.is_nan());
4256 assert_insn!(r#"f64.const nan:0x8_0000_0000_1245"#, [F64Const(f)] if f.is_nan());
4257 assert_insn!(r#"f64.const nan:0x1"#, [F64Const(f)] if f.is_nan());
4258 assert_insn!(r#"f64.const -inf"#, [F64Const(f)] if *f == f64::NEG_INFINITY);
4259 assert_insn!(r#"f64.const -nan"#, [F64Const(f)] if f.is_nan());
4260 assert_insn!(r#"f64.const -nan:0x8_0000_0000_1245"#, [F64Const(f)] if f.is_nan());
4261
4262 assert_error!(
4263 r#"f64.const nan:0x0"#,
4264 Vec<Instruction<'_>>,
4265 CannotParseNum{ reason, .. }
4266 if reason == "payload of NaN must be in range of 1 <= payload < 2^52"
4267 );
4268 assert_error!(
4269 r#"f64.const nan:0x20_0000_0000_0000"#, Vec<Instruction<'_>>,
4271 CannotParseNum{ reason, .. }
4272 if reason == "payload of NaN must be in range of 1 <= payload < 2^52"
4273 );
4274 }
4275
4276 #[test]
4277 fn numeric_instructions() {
4278 use InsnKind::*;
4279 assert_insn!(r#"i32.clz"#, [I32Clz]);
4280 assert_insn!(r#"i32.ctz"#, [I32Ctz]);
4281 assert_insn!(r#"i32.popcnt"#, [I32Popcnt]);
4282 assert_insn!(r#"i32.add"#, [I32Add]);
4283 assert_insn!(r#"i32.sub"#, [I32Sub]);
4284 assert_insn!(r#"i32.mul"#, [I32Mul]);
4285 assert_insn!(r#"i32.div_s"#, [I32DivS]);
4286 assert_insn!(r#"i32.div_u"#, [I32DivU]);
4287 assert_insn!(r#"i32.rem_s"#, [I32RemS]);
4288 assert_insn!(r#"i32.rem_u"#, [I32RemU]);
4289 assert_insn!(r#"i32.and"#, [I32And]);
4290 assert_insn!(r#"i32.or"#, [I32Or]);
4291 assert_insn!(r#"i32.xor"#, [I32Xor]);
4292 assert_insn!(r#"i32.shl"#, [I32Shl]);
4293 assert_insn!(r#"i32.shr_s"#, [I32ShrS]);
4294 assert_insn!(r#"i32.shr_u"#, [I32ShrU]);
4295 assert_insn!(r#"i32.rotl"#, [I32Rotl]);
4296 assert_insn!(r#"i32.rotr"#, [I32Rotr]);
4297 assert_insn!(r#"i64.clz"#, [I64Clz]);
4298 assert_insn!(r#"i64.ctz"#, [I64Ctz]);
4299 assert_insn!(r#"i64.popcnt"#, [I64Popcnt]);
4300 assert_insn!(r#"i64.add"#, [I64Add]);
4301 assert_insn!(r#"i64.sub"#, [I64Sub]);
4302 assert_insn!(r#"i64.mul"#, [I64Mul]);
4303 assert_insn!(r#"i64.div_s"#, [I64DivS]);
4304 assert_insn!(r#"i64.div_u"#, [I64DivU]);
4305 assert_insn!(r#"i64.rem_s"#, [I64RemS]);
4306 assert_insn!(r#"i64.rem_u"#, [I64RemU]);
4307 assert_insn!(r#"i64.and"#, [I64And]);
4308 assert_insn!(r#"i64.or"#, [I64Or]);
4309 assert_insn!(r#"i64.xor"#, [I64Xor]);
4310 assert_insn!(r#"i64.shl"#, [I64Shl]);
4311 assert_insn!(r#"i64.shr_s"#, [I64ShrS]);
4312 assert_insn!(r#"i64.shr_u"#, [I64ShrU]);
4313 assert_insn!(r#"i64.rotl"#, [I64Rotl]);
4314 assert_insn!(r#"i64.rotr"#, [I64Rotr]);
4315 assert_insn!(r#"f32.abs"#, [F32Abs]);
4316 assert_insn!(r#"f32.neg"#, [F32Neg]);
4317 assert_insn!(r#"f32.ceil"#, [F32Ceil]);
4318 assert_insn!(r#"f32.floor"#, [F32Floor]);
4319 assert_insn!(r#"f32.trunc"#, [F32Trunc]);
4320 assert_insn!(r#"f32.nearest"#, [F32Nearest]);
4321 assert_insn!(r#"f32.sqrt"#, [F32Sqrt]);
4322 assert_insn!(r#"f32.add"#, [F32Add]);
4323 assert_insn!(r#"f32.sub"#, [F32Sub]);
4324 assert_insn!(r#"f32.mul"#, [F32Mul]);
4325 assert_insn!(r#"f32.div"#, [F32Div]);
4326 assert_insn!(r#"f32.min"#, [F32Min]);
4327 assert_insn!(r#"f32.max"#, [F32Max]);
4328 assert_insn!(r#"f32.copysign"#, [F32Copysign]);
4329 assert_insn!(r#"f64.abs"#, [F64Abs]);
4330 assert_insn!(r#"f64.neg"#, [F64Neg]);
4331 assert_insn!(r#"f64.ceil"#, [F64Ceil]);
4332 assert_insn!(r#"f64.floor"#, [F64Floor]);
4333 assert_insn!(r#"f64.trunc"#, [F64Trunc]);
4334 assert_insn!(r#"f64.nearest"#, [F64Nearest]);
4335 assert_insn!(r#"f64.sqrt"#, [F64Sqrt]);
4336 assert_insn!(r#"f64.add"#, [F64Add]);
4337 assert_insn!(r#"f64.sub"#, [F64Sub]);
4338 assert_insn!(r#"f64.mul"#, [F64Mul]);
4339 assert_insn!(r#"f64.div"#, [F64Div]);
4340 assert_insn!(r#"f64.min"#, [F64Min]);
4341 assert_insn!(r#"f64.max"#, [F64Max]);
4342 assert_insn!(r#"f64.copysign"#, [F64Copysign]);
4343 assert_insn!(r#"i32.eqz"#, [I32Eqz]);
4344 assert_insn!(r#"i32.eq"#, [I32Eq]);
4345 assert_insn!(r#"i32.ne"#, [I32Ne]);
4346 assert_insn!(r#"i32.lt_s"#, [I32LtS]);
4347 assert_insn!(r#"i32.lt_u"#, [I32LtU]);
4348 assert_insn!(r#"i32.gt_s"#, [I32GtS]);
4349 assert_insn!(r#"i32.gt_u"#, [I32GtU]);
4350 assert_insn!(r#"i32.le_s"#, [I32LeS]);
4351 assert_insn!(r#"i32.le_u"#, [I32LeU]);
4352 assert_insn!(r#"i32.ge_s"#, [I32GeS]);
4353 assert_insn!(r#"i32.ge_u"#, [I32GeU]);
4354 assert_insn!(r#"i64.eqz"#, [I64Eqz]);
4355 assert_insn!(r#"i64.eq"#, [I64Eq]);
4356 assert_insn!(r#"i64.ne"#, [I64Ne]);
4357 assert_insn!(r#"i64.lt_s"#, [I64LtS]);
4358 assert_insn!(r#"i64.lt_u"#, [I64LtU]);
4359 assert_insn!(r#"i64.gt_s"#, [I64GtS]);
4360 assert_insn!(r#"i64.gt_u"#, [I64GtU]);
4361 assert_insn!(r#"i64.le_s"#, [I64LeS]);
4362 assert_insn!(r#"i64.le_u"#, [I64LeU]);
4363 assert_insn!(r#"i64.ge_s"#, [I64GeS]);
4364 assert_insn!(r#"i64.ge_u"#, [I64GeU]);
4365 assert_insn!(r#"f32.eq"#, [F32Eq]);
4366 assert_insn!(r#"f32.ne"#, [F32Ne]);
4367 assert_insn!(r#"f32.lt"#, [F32Lt]);
4368 assert_insn!(r#"f32.gt"#, [F32Gt]);
4369 assert_insn!(r#"f32.le"#, [F32Le]);
4370 assert_insn!(r#"f32.ge"#, [F32Ge]);
4371 assert_insn!(r#"f64.eq"#, [F64Eq]);
4372 assert_insn!(r#"f64.ne"#, [F64Ne]);
4373 assert_insn!(r#"f64.lt"#, [F64Lt]);
4374 assert_insn!(r#"f64.gt"#, [F64Gt]);
4375 assert_insn!(r#"f64.le"#, [F64Le]);
4376 assert_insn!(r#"f64.ge"#, [F64Ge]);
4377 assert_insn!(r#"i32.wrap_i64"#, [I32WrapI64]);
4378 assert_insn!(r#"i32.trunc_f32_s"#, [I32TruncF32S]);
4379 assert_insn!(r#"i32.trunc_f32_u"#, [I32TruncF32U]);
4380 assert_insn!(r#"i32.trunc_f64_s"#, [I32TruncF64S]);
4381 assert_insn!(r#"i32.trunc_f64_u"#, [I32TruncF64U]);
4382 assert_insn!(r#"i64.extend_i32_s"#, [I64ExtendI32S]);
4383 assert_insn!(r#"i64.extend_i32_u"#, [I64ExtendI32U]);
4384 assert_insn!(r#"i64.trunc_f32_s"#, [I64TruncF32S]);
4385 assert_insn!(r#"i64.trunc_f32_u"#, [I64TruncF32U]);
4386 assert_insn!(r#"i64.trunc_f64_s"#, [I64TruncF64S]);
4387 assert_insn!(r#"i64.trunc_f64_u"#, [I64TruncF64U]);
4388 assert_insn!(r#"f32.convert_i32_s"#, [F32ConvertI32S]);
4389 assert_insn!(r#"f32.convert_i32_u"#, [F32ConvertI32U]);
4390 assert_insn!(r#"f32.convert_i64_s"#, [F32ConvertI64S]);
4391 assert_insn!(r#"f32.convert_i64_u"#, [F32ConvertI64U]);
4392 assert_insn!(r#"f32.demote_f64"#, [F32DemoteF64]);
4393 assert_insn!(r#"f64.convert_i32_s"#, [F64ConvertI32S]);
4394 assert_insn!(r#"f64.convert_i32_u"#, [F64ConvertI32U]);
4395 assert_insn!(r#"f64.convert_i64_s"#, [F64ConvertI64S]);
4396 assert_insn!(r#"f64.convert_i64_u"#, [F64ConvertI64U]);
4397 assert_insn!(r#"f64.promote_f32"#, [F64PromoteF32]);
4398 assert_insn!(r#"i32.reinterpret_f32"#, [I32ReinterpretF32]);
4399 assert_insn!(r#"i64.reinterpret_f64"#, [I64ReinterpretF64]);
4400 assert_insn!(r#"f32.reinterpret_i32"#, [F32ReinterpretI32]);
4401 assert_insn!(r#"f64.reinterpret_i64"#, [F64ReinterpretI64]);
4402 assert_insn!(r#"i32.extend8_s"#, [I32Extend8S]);
4403 assert_insn!(r#"i32.extend16_s"#, [I32Extend16S]);
4404 assert_insn!(r#"i64.extend8_s"#, [I64Extend8S]);
4405 assert_insn!(r#"i64.extend16_s"#, [I64Extend16S]);
4406 assert_insn!(r#"i64.extend32_s"#, [I64Extend32S]);
4407 }
4408
4409 #[test]
4410 fn elem_segment() {
4411 use InsnKind::*;
4412 assert_parse!(
4413 r#"(elem i32.const 10)"#,
4414 Elem<'_>,
4415 Elem {
4416 idx: Index::Num(0),
4417 offset,
4418 init,
4419 ..
4420 } if matches!(offset[0].kind, I32Const(10)) && init.is_empty()
4421 );
4422 assert_parse!(
4423 r#"(elem 0x1f i32.const 10)"#,
4424 Elem<'_>,
4425 Elem {
4426 idx: Index::Num(0x1f),
4427 offset,
4428 init,
4429 ..
4430 } if matches!(offset[0].kind, I32Const(10)) && init.is_empty()
4431 );
4432 assert_parse!(
4433 r#"(elem $e i32.const 10)"#,
4434 Elem<'_>,
4435 Elem {
4436 idx: Index::Ident("$e"),
4437 offset,
4438 init,
4439 ..
4440 } if matches!(offset[0].kind, I32Const(10)) && init.is_empty()
4441 );
4442 assert_parse!(
4443 r#"(elem (offset))"#,
4444 Elem<'_>,
4445 Elem {
4446 offset,
4447 init,
4448 ..
4449 } if offset.is_empty() && init.is_empty()
4450 );
4451 assert_parse!(
4452 r#"(elem (offset nop))"#,
4453 Elem<'_>,
4454 Elem {
4455 offset,
4456 init,
4457 ..
4458 } if matches!(offset[0].kind, Nop) && init.is_empty()
4459 );
4460 assert_parse!(
4461 r#"(elem (offset (nop (nop))))"#,
4462 Elem<'_>,
4463 Elem {
4464 offset,
4465 init,
4466 ..
4467 } if offset.len() == 2 && init.is_empty()
4468 );
4469 assert_parse!(
4470 r#"(elem (offset nop nop))"#,
4471 Elem<'_>,
4472 Elem {
4473 offset,
4474 init,
4475 ..
4476 } if offset.len() == 2 && init.is_empty()
4477 );
4478 assert_parse!(
4479 r#"(elem (offset nop) 0xf $f)"#,
4480 Elem<'_>,
4481 Elem {
4482 offset,
4483 init,
4484 ..
4485 } if offset.len() == 1 &&
4486 matches!(init.as_slice(), [Index::Num(0xf), Index::Ident("$f")])
4487 );
4488 assert_parse!(
4489 r#"(elem nop 0xf)"#,
4490 Elem<'_>,
4491 Elem {
4492 offset,
4493 init,
4494 ..
4495 } if matches!(offset[0].kind, Nop) &&
4496 matches!(init.as_slice(), [Index::Num(0xf)])
4497 );
4498 assert_parse!(
4499 r#"(elem nop $f)"#,
4500 Elem<'_>,
4501 Elem {
4502 offset,
4503 init,
4504 ..
4505 } if matches!(offset[0].kind, Nop) &&
4506 matches!(init.as_slice(), [Index::Ident("$f")])
4507 );
4508 assert_parse!(
4509 r#"(elem block end 0)"#,
4510 Elem<'_>,
4511 Elem { offset, .. } if matches!(offset[0].kind, Block{..})
4512 );
4513 assert_parse!(
4514 r#"(elem (i32.const 42) 0)"#,
4515 Elem<'_>,
4516 Elem { offset, .. } if matches!(offset[0].kind, I32Const(42))
4517 );
4518 assert_parse!(r#"(elem i32.const 0 func $f)"#, Elem<'_>, Elem { .. });
4519 }
4520
4521 #[test]
4522 fn table_section_abbrev() {
4523 assert_parse!(
4524 r#"(table 0 0 funcref)"#,
4525 TableAbbrev<'_>,
4526 TableAbbrev::Table(Table { id: None, .. })
4527 );
4528 assert_parse!(
4529 r#"(table $tbl 0 0 funcref)"#,
4530 TableAbbrev<'_>,
4531 TableAbbrev::Table(Table { id: Some("$tbl"), .. })
4532 );
4533 assert_parse!(
4534 r#"(table $tbl funcref (elem 0 1))"#,
4535 TableAbbrev<'_>,
4536 TableAbbrev::Elem(
4537 Table{ id: Some("$tbl"), ty: TableType{ limit: Limits::Range{ min: 2, max: 2 } }, .. },
4538 Elem{ idx: Index::Num(0), offset, init, .. }
4539 )
4540 if matches!(offset[0].kind, InsnKind::I32Const(0)) &&
4541 matches!(init[0], Index::Num(0)) && matches!(init[1], Index::Num(1))
4542 );
4543 assert_parse!(
4544 r#"(table $tbl (import "m" "n") 2 2 funcref)"#,
4545 TableAbbrev<'_>,
4546 TableAbbrev::Table(Table {
4547 id: Some("$tbl"),
4548 ty: TableType {
4549 limit: Limits::Range{ min: 2, max: 2 },
4550 },
4551 import: Some(Import {
4552 mod_name: Name(m),
4553 name: Name(n),
4554 }),
4555 ..
4556 })
4557 if m == "m" && n == "n"
4558 );
4559 let parser = assert_parse!(
4560 r#"(table $tbl (export "n") 2 funcref)"#,
4561 TableAbbrev<'_>,
4562 TableAbbrev::Table(Table {
4563 id: Some("$tbl"),
4564 ty: TableType {
4565 limit: Limits::From { min: 2 }
4566 },
4567 ..
4568 })
4569 );
4570 match &parser.ctx.exports[0] {
4571 Export {
4572 name: Name(n),
4573 kind: ExportKind::Table,
4574 idx: Index::Num(0),
4575 ..
4576 } if n == "n" => { }
4577 e => panic!("did not match: {:?}", e),
4578 }
4579 let parser = assert_parse!(
4580 r#"(table $tbl (export "n1") (export "n2") 2 funcref)"#,
4581 TableAbbrev<'_>,
4582 TableAbbrev::Table(Table {
4583 id: Some("$tbl"),
4584 ty: TableType {
4585 limit: Limits::From { min: 2 }
4586 },
4587 ..
4588 })
4589 );
4590 assert_eq!(parser.ctx.exports.len(), 2);
4591 let parser = assert_parse!(
4592 r#"(table $tbl (export "n1") (import "m" "n2") 2 funcref)"#,
4593 TableAbbrev<'_>,
4594 TableAbbrev::Table(Table {
4595 id: Some("$tbl"),
4596 ty: TableType {
4597 limit: Limits::From{ min: 2 },
4598 },
4599 import: Some(Import {
4600 mod_name: Name(m),
4601 name: Name(n),
4602 }),
4603 ..
4604 })
4605 if m == "m" && n == "n2"
4606 );
4607 assert_eq!(parser.ctx.exports.len(), 1);
4608 match &parser.ctx.exports[0] {
4609 Export {
4610 name: Name(n),
4611 kind: ExportKind::Table,
4612 idx: Index::Num(0),
4613 ..
4614 } if n == "n1" => { }
4615 e => panic!("did not match: {:?}", e),
4616 }
4617 let parser = assert_parse!(
4618 r#"(table $tbl (export "n1") (export "n2") (import "m" "n3") 2 funcref)"#,
4619 TableAbbrev<'_>,
4620 TableAbbrev::Table(Table { import: Some(_), .. })
4621 );
4622 assert_eq!(parser.ctx.exports.len(), 2);
4623 let parser = assert_parse!(
4624 r#"(table $tbl (export "n1") funcref (elem 1 2 3))"#,
4625 TableAbbrev<'_>,
4626 TableAbbrev::Elem(..)
4627 );
4628 assert_eq!(parser.ctx.exports.len(), 1);
4629
4630 assert_error!(
4631 r#"(table $t (import "m" "n") (export "n2") 2 funcref)"#,
4632 TableAbbrev<'_>,
4633 UnexpectedToken { .. }
4634 );
4635 assert_error!(
4636 r#"(table $t funcref (elem 1) (export "n"))"#,
4637 TableAbbrev<'_>,
4638 MissingParen { paren: ')', .. }
4639 );
4640 }
4641
4642 #[test]
4643 fn data_segment() {
4644 assert_parse!(
4645 r#"(data 0 i32.const 0)"#,
4646 Data<'_>,
4647 Data{
4648 idx: Index::Num(0),
4649 offset,
4650 data,
4651 ..
4652 } if matches!(offset[0].kind, InsnKind::I32Const(0)) && data.is_empty()
4653 );
4654 assert_parse!(
4655 r#"(data 0 (offset i32.const 0))"#,
4656 Data<'_>,
4657 Data{
4658 idx: Index::Num(0),
4659 offset,
4660 data,
4661 ..
4662 } if matches!(offset[0].kind, InsnKind::I32Const(0)) && data.is_empty()
4663 );
4664 assert_parse!(
4665 r#"(data 0 (offset i32.const 0) "hello")"#,
4666 Data<'_>,
4667 Data{ data, .. } if data.as_ref() == b"hello".as_ref()
4668 );
4669 assert_parse!(
4670 r#"(data 0 (offset i32.const 0) "hello" " dogs!")"#,
4671 Data<'_>,
4672 Data{ data, .. } if data.as_ref() == b"hello dogs!".as_ref()
4673 );
4674 assert_parse!(
4675 r#"(data 0 (offset i32.const 0) "\t\n\r" "\"\'\\" "\u{3042}\41")"#,
4676 Data<'_>,
4677 Data{ data, .. } if data.as_ref() == b"\t\n\r\"'\\\xe3\x81\x82A".as_ref()
4678 );
4679 assert_parse!(
4680 r#"(data 0 (offset i32.const 0) "\01\02\03\ff")"#,
4681 Data<'_>,
4682 Data{ data, .. } if data.as_ref() == &[1, 2, 3, 255]
4683 );
4684 assert_parse!(
4685 r#"(data (i32.const 1024) "Hello, world\n\00")"#,
4686 Data<'_>,
4687 Data{
4688 idx: Index::Num(0),
4689 offset,
4690 data,
4691 ..
4692 } if matches!(offset[0].kind, InsnKind::I32Const(1024)) &&
4693 data.as_ref() == b"Hello, world\n\0".as_ref()
4694 );
4695
4696 assert_error!(r#"(data 0 "hello")"#, Data<'_>, UnexpectedToken { .. });
4697 }
4698
4699 #[test]
4700 fn memory_section_abbrev() {
4701 assert_parse!(
4702 r#"(memory 3)"#,
4703 MemoryAbbrev<'_>,
4704 MemoryAbbrev::Memory(Memory {
4705 id: None,
4706 ty: MemType {
4707 limit: Limits::From { min: 3 }
4708 },
4709 ..
4710 })
4711 );
4712 assert_parse!(
4713 r#"(memory 1 3)"#,
4714 MemoryAbbrev<'_>,
4715 MemoryAbbrev::Memory(Memory {
4716 id: None,
4717 ty: MemType {
4718 limit: Limits::Range { min: 1, max: 3 },
4719 },
4720 ..
4721 })
4722 );
4723 assert_parse!(
4724 r#"(memory $m 1 3)"#,
4725 MemoryAbbrev<'_>,
4726 MemoryAbbrev::Memory(Memory {
4727 id: Some("$m"),
4728 ty: MemType {
4729 limit: Limits::Range { min: 1, max: 3 },
4730 },
4731 ..
4732 })
4733 );
4734 assert_parse!(
4735 r#"(memory $m (data "foo" "bar"))"#,
4736 MemoryAbbrev<'_>,
4737 MemoryAbbrev::Data(
4738 Memory{
4739 ty: MemType{ limit: Limits::Range{ min: 1, max: 1 } },
4740 ..
4741 },
4742 Data {
4743 idx: Index::Num(0),
4744 offset,
4745 data,
4746 ..
4747 },
4748 )
4749 if matches!(offset[0].kind, InsnKind::I32Const(0)) &&
4750 data.as_ref() == b"foobar".as_ref()
4751 );
4752 assert_parse!(
4753 r#"(memory $m (import "m" "n") 2)"#,
4754 MemoryAbbrev<'_>,
4755 MemoryAbbrev::Memory(Memory {
4756 id: Some("$m"),
4757 ty: MemType {
4758 limit: Limits::From{ min: 2 },
4759 },
4760 import: Some(Import {
4761 mod_name: Name(m),
4762 name: Name(n),
4763 }),
4764 ..
4765 })
4766 if m == "m" && n == "n"
4767 );
4768 let parser = assert_parse!(
4769 r#"(memory $m (export "n") 0)"#,
4770 MemoryAbbrev<'_>,
4771 MemoryAbbrev::Memory(Memory {
4772 ty: MemType {
4773 limit: Limits::From { min: 0 }
4774 },
4775 ..
4776 })
4777 );
4778 match &parser.ctx.exports[0] {
4779 Export {
4780 name: Name(n),
4781 kind: ExportKind::Memory,
4782 idx: Index::Num(0),
4783 ..
4784 } if n == "n" => { }
4785 e => panic!("did not match: {:?}", e),
4786 }
4787 let parser = assert_parse!(
4788 r#"(memory $m (export "n") (export "n2") 0)"#,
4789 MemoryAbbrev<'_>,
4790 MemoryAbbrev::Memory(Memory {
4791 ty: MemType {
4792 limit: Limits::From { min: 0 }
4793 },
4794 ..
4795 })
4796 );
4797 assert_eq!(parser.ctx.exports[0].name.0, "n");
4798 assert_eq!(parser.ctx.exports[1].name.0, "n2");
4799 let parser = assert_parse!(
4800 r#"(memory $m (export "e") (import "m" "n") 2)"#,
4801 MemoryAbbrev<'_>,
4802 MemoryAbbrev::Memory(Memory {
4803 id: Some("$m"),
4804 ty: MemType {
4805 limit: Limits::From{ min: 2 },
4806 },
4807 import: Some(Import {
4808 mod_name: Name(m),
4809 name: Name(n),
4810 }),
4811 ..
4812 })
4813 if m == "m" && n == "n"
4814 );
4815 match &parser.ctx.exports[0] {
4816 Export {
4817 name: Name(n),
4818 kind: ExportKind::Memory,
4819 idx: Index::Num(0),
4820 ..
4821 } if n == "e" => { }
4822 e => panic!("did not match: {:?}", e),
4823 }
4824 let parser = assert_parse!(
4825 r#"(memory $m (export "e1") (export "e2") (import "m" "n") 2)"#,
4826 MemoryAbbrev<'_>,
4827 MemoryAbbrev::Memory(Memory { import: Some(_), .. })
4828 );
4829 assert_eq!(parser.ctx.exports.len(), 2);
4830 let parser = assert_parse!(
4831 r#"(memory $m (export "e") (data "hello"))"#,
4832 MemoryAbbrev<'_>,
4833 MemoryAbbrev::Data(..)
4834 );
4835 assert_eq!(parser.ctx.exports.len(), 1);
4836
4837 assert_error!(
4838 r#"(memory $m (import "m" "n") (export "n2") 0)"#,
4839 MemoryAbbrev<'_>,
4840 UnexpectedToken { .. }
4841 );
4842 assert_error!(
4843 r#"(memory $m (data "hello") (export "n"))"#,
4844 MemoryAbbrev<'_>,
4845 MissingParen { paren: ')', .. }
4846 );
4847 }
4848
4849 #[test]
4850 fn global_section_abbrev() {
4851 assert_parse!(
4852 r#"(global i32)"#,
4853 Global<'_>,
4854 Global {
4855 id: None,
4856 ty: GlobalType {
4857 mutable: false,
4858 ty: ValType::I32,
4859 },
4860 kind: GlobalKind::Init(init),
4861 ..
4862 } if init.is_empty()
4863 );
4864 assert_parse!(
4865 r#"(global $g i32)"#,
4866 Global<'_>,
4867 Global {
4868 id: Some("$g"),
4869 ty: GlobalType {
4870 mutable: false,
4871 ty: ValType::I32,
4872 },
4873 kind: GlobalKind::Init(init),
4874 ..
4875 } if init.is_empty()
4876 );
4877 assert_parse!(
4878 r#"(global (mut i32))"#,
4879 Global<'_>,
4880 Global {
4881 ty: GlobalType {
4882 mutable: true,
4883 ty: ValType::I32,
4884 },
4885 kind: GlobalKind::Init(init),
4886 ..
4887 } if init.is_empty()
4888 );
4889 let parser = assert_parse!(
4890 r#"(global $g (export "n") i32)"#,
4891 Global<'_>,
4892 Global {
4893 ty: GlobalType {
4894 mutable: false,
4895 ty: ValType::I32
4896 },
4897 ..
4898 }
4899 );
4900 match &parser.ctx.exports[0] {
4901 Export {
4902 name: Name(n),
4903 kind: ExportKind::Global,
4904 idx: Index::Num(0),
4905 ..
4906 } if n == "n" => { }
4907 e => panic!("did not match: {:?}", e),
4908 }
4909 let parser = assert_parse!(
4910 r#"(global $g (export "n1") (export "n2") i32)"#,
4911 Global<'_>,
4912 Global { .. }
4913 );
4914 assert_eq!(parser.ctx.exports[0].name.0, "n1");
4915 assert_eq!(parser.ctx.exports[1].name.0, "n2");
4916 assert_parse!(
4917 r#"(global $g (import "m" "n") i32)"#,
4918 Global<'_>,
4919 Global {
4920 ty: GlobalType {
4921 mutable: false,
4922 ty: ValType::I32
4923 },
4924 id: Some("$g"),
4925 kind: GlobalKind::Import(Import {
4926 mod_name: Name(m),
4927 name: Name(n),
4928 }),
4929 ..
4930 }
4931 if m == "m" && n == "n"
4932 );
4933 let parser = assert_parse!(
4934 r#"(global $g (export "e") (import "m" "n") i32)"#,
4935 Global<'_>,
4936 Global {
4937 kind: GlobalKind::Import(_),
4938 ..
4939 }
4940 );
4941 assert_eq!(parser.ctx.exports.len(), 1);
4942 assert_parse!(
4943 r#"(global i32 i32.const 32 i32.load align=8)"#,
4944 Global<'_>,
4945 Global { kind: GlobalKind::Init(init), .. }
4946 if matches!(&init[0].kind, InsnKind::I32Const(32)) &&
4947 matches!(&init[1].kind, InsnKind::I32Load(Mem{ align: 3, .. }))
4948 );
4949 assert_parse!(
4950 r#"(global i32 (i32.add (i32.const 4)))"#,
4951 Global<'_>,
4952 Global { kind: GlobalKind::Init(init), .. }
4953 if matches!(&init[0].kind, InsnKind::I32Const(4)) &&
4954 matches!(&init[1].kind, InsnKind::I32Add)
4955 );
4956
4957 assert_error!(
4958 r#"(global $g (import "m" "n") (export "e") i32)"#,
4959 Global<'_>,
4960 UnexpectedToken { .. }
4961 );
4962 assert_error!(
4963 r#"(global $g (mut i32) (export "e"))"#,
4964 Global<'_>,
4965 UnexpectedKeyword("export")
4966 );
4967 }
4968
4969 #[test]
4970 fn start_function() {
4971 assert_parse!(r#"(start 3)"#, Start<'_>, Start { idx: Index::Num(3), .. });
4972 assert_parse!(
4973 r#"(start $f)"#,
4974 Start<'_>,
4975 Start {
4976 idx: Index::Ident("$f"),
4977 ..
4978 }
4979 );
4980 }
4981
4982 #[test]
4983 fn hex_float_out_of_range() {
4984 macro_rules! assert_out_of_range {
4985 ($lit:expr) => {
4986 assert_error!(
4987 $lit,
4988 Vec<Instruction<'_>>,
4989 CannotParseNum { reason, .. } if reason == "float constant out of range"
4990 );
4991 }
4992 }
4993
4994 assert_out_of_range!("f32.const 0x1p128");
4995 assert_out_of_range!("f32.const -0x1p128");
4996 assert_out_of_range!("f32.const 0x1.ffffffp127");
4997 assert_out_of_range!("f32.const -0x1.ffffffp127");
4998 assert_out_of_range!("f64.const 0x1p1024");
4999 assert_out_of_range!("f64.const -0x1p1024");
5000 assert_out_of_range!("f64.const 0x1.fffffffffffff8p1023");
5001 assert_out_of_range!("f64.const -0x1.fffffffffffff8p1023");
5002 }
5003
5004 #[test]
5005 fn hex_f32_literal_edge_cases() {
5006 use InsnKind::F32Const;
5007
5008 macro_rules! assert_f32_eq {
5009 ($left:expr, $right:expr) => {
5010 assert_insn!(
5011 concat!("(f32.const ", $left, ") (f32.const ", $right, ")"),
5012 [F32Const(a), F32Const(b)] if a == b
5013 );
5014 }
5015 }
5016
5017 assert_f32_eq!("+0x1.00000100000000001p-50", "+0x1.000002p-50");
5019 assert_f32_eq!("-0x1.00000100000000001p-50", "-0x1.000002p-50");
5020 assert_f32_eq!("+0x1.000001fffffffffffp-50", "+0x1.000002p-50");
5021 assert_f32_eq!("-0x1.000001fffffffffffp-50", "-0x1.000002p-50");
5022 assert_f32_eq!("+0x1.00000500000000001p-50", "+0x1.000006p-50");
5023 assert_f32_eq!("-0x1.00000500000000001p-50", "-0x1.000006p-50");
5024 assert_f32_eq!("+0x4000.004000001p-64", "+0x1.000002p-50");
5025 assert_f32_eq!("-0x4000.004000001p-64", "-0x1.000002p-50");
5026 assert_f32_eq!("+0x4000.014000001p-64", "+0x1.000006p-50");
5027 assert_f32_eq!("-0x4000.014000001p-64", "-0x1.000006p-50");
5028
5029 assert_f32_eq!("+0x1.00000100000000001p+50", "+0x1.000002p+50");
5031 assert_f32_eq!("-0x1.00000100000000001p+50", "-0x1.000002p+50");
5032 assert_f32_eq!("+0x1.000001fffffffffffp+50", "+0x1.000002p+50");
5033 assert_f32_eq!("-0x1.000001fffffffffffp+50", "-0x1.000002p+50");
5034 assert_f32_eq!("+0x1.00000500000000001p+50", "+0x1.000006p+50");
5035 assert_f32_eq!("-0x1.00000500000000001p+50", "-0x1.000006p+50");
5036 assert_f32_eq!("+0x4000004000001", "+0x1.000002p+50");
5037 assert_f32_eq!("-0x4000004000001", "-0x1.000002p+50");
5038
5039 assert_f32_eq!("+0x0.00000100000000001p-126", "+0x0.000002p-126");
5041 assert_f32_eq!("-0x0.00000100000000001p-126", "-0x0.000002p-126");
5042 assert_f32_eq!("+0x0.000002fffffffffffp-126", "+0x0.000002p-126");
5043 assert_f32_eq!("-0x0.000002fffffffffffp-126", "-0x0.000002p-126");
5044 assert_f32_eq!("+0x0.00000500000000001p-126", "+0x0.000006p-126");
5045 assert_f32_eq!("-0x0.00000500000000001p-126", "-0x0.000006p-126");
5046 }
5047
5048 #[test]
5049 fn hex_f64_literal_edge_cases() {
5050 use InsnKind::F64Const;
5051
5052 macro_rules! assert_f64_eq {
5053 ($left:expr, $right:expr) => {
5054 assert_insn!(
5055 concat!("(f64.const ", $left, ") (f64.const ", $right, ")"),
5056 [F64Const(a), F64Const(b)] if a == b
5057 );
5058 }
5059 }
5060
5061 assert_f64_eq!("+0x1.000000000000080000000001p-600", "+0x1.0000000000001p-600");
5063 assert_f64_eq!("-0x1.000000000000080000000001p-600", "-0x1.0000000000001p-600");
5064 assert_f64_eq!("+0x1.000000000000280000000001p-600", "+0x1.0000000000003p-600");
5065 assert_f64_eq!("-0x1.000000000000280000000001p-600", "-0x1.0000000000003p-600");
5066 assert_f64_eq!("+0x8000000.000000400000000001p-627", "+0x1.0000000000001p-600");
5067 assert_f64_eq!("-0x8000000.000000400000000001p-627", "-0x1.0000000000001p-600");
5068 assert_f64_eq!("+0x8000000.000001400000000001p-627", "+0x1.0000000000003p-600");
5069 assert_f64_eq!("-0x8000000.000001400000000001p-627", "-0x1.0000000000003p-600");
5070
5071 assert_f64_eq!("+0x1.000000000000080000000001p+600", "+0x1.0000000000001p+600");
5073 assert_f64_eq!("-0x1.000000000000080000000001p+600", "-0x1.0000000000001p+600");
5074 assert_f64_eq!("+0x1.000000000000280000000001p+600", "+0x1.0000000000003p+600");
5075 assert_f64_eq!("-0x1.000000000000280000000001p+600", "-0x1.0000000000003p+600");
5076 assert_f64_eq!("+0x2000000000000100000000001", "+0x1.0000000000001p+97");
5077 assert_f64_eq!("-0x2000000000000100000000001", "-0x1.0000000000001p+97");
5078 assert_f64_eq!("+0x20000000000001fffffffffff", "+0x1.0000000000001p+97");
5079 assert_f64_eq!("-0x20000000000001fffffffffff", "-0x1.0000000000001p+97");
5080 assert_f64_eq!("+0x2000000000000500000000001", "+0x1.0000000000003p+97");
5081 assert_f64_eq!("-0x2000000000000500000000001", "-0x1.0000000000003p+97");
5082
5083 assert_f64_eq!("+0x1.000000000000280000000001p-1022", "+0x1.0000000000003p-1022");
5085 assert_f64_eq!("-0x1.000000000000280000000001p-1022", "-0x1.0000000000003p-1022");
5086 }
5087
5088 #[test]
5089 fn hello_world() {
5090 assert_parse!(
5091 r#"
5092 (module
5093 (type $i32_=>_none (func (param i32)))
5094 (type $none_=>_i32 (func (result i32)))
5095 (import "env" "print" (func $print (param i32)))
5096 (memory $0 2)
5097 (data (i32.const 1024) "Hello, world\n\00")
5098 (table $0 1 1 funcref)
5099 (global $global$0 (mut i32) (i32.const 66576))
5100 (export "memory" (memory $0))
5101 (export "_start" (func $_start))
5102 (func $_start (; 1 ;) (result i32)
5103 (call $print
5104 (i32.const 1024)
5105 )
5106 (i32.const 0)
5107 )
5108 ;; custom section "producers", size 27
5109 )
5110 "#,
5111 Module<'_>,
5112 Module { .. }
5113 );
5114 }
5115}