wain_syntax_text/
parser.rs

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, // TODO: Make 'expected' better
21    },
22    UnexpectedEndOfFile {
23        expected: &'static str, // TODO: Make 'expected' better
24    },
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// iter::Peekable is not sufficient to parse WAT tokens
148// WAT requires LL(1) parser to see a token after '('
149#[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        // This implementation can be better. We can delay calling self.it.next() until it is really
178        // necessary. In the case, peek() and lookahead() will be `&mut self` method.
179        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; // Clear next index for parsing next module
227        mem::take(&mut self.indices)
228    }
229}
230
231// TODO: Remember offset of place where the identifier is defined for better error
232struct ParseContext<'s> {
233    // types are put in Parser context due to abbreviation of typeuse
234    // https://webassembly.github.io/spec/core/text/modules.html#abbreviations
235    types: Vec<TypeDef<'s>>,
236    exports: Vec<Export<'s>>,
237    // Indices for each spaces.
238    // https://webassembly.github.io/spec/core/syntax/modules.html#syntax-index
239    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
278// TODO: Add index-to-id tables for types, funcs, tables, mems, globals, locals and labels
279// https://webassembly.github.io/spec/core/text/modules.html#indices
280pub 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        // TODO: Implement parsing floating number literals without allocation
459        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(); // Eat 'offset' keyword
490                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(); // Eat 'align' keyword
503                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        // Handle abbreviation:
523        //   https://webassembly.github.io/spec/core/text/modules.html#abbreviations
524        //
525        // A typeuse may also be replaced entirely by inline parameter and result declarations.
526        // In that case, a type index is automatically inserted.
527        //
528        //   {param}* {result}* == (type {x}) {param}* {result}*
529        //
530        // where {x} is an existing function type which has the same signature.
531        // If no function exists, insert new function type in module
532        //
533        //   (type (func {param}* {result}*))
534        //
535
536        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
562// TODO: Use trait rather than macros to avoid duplication of implementations
563macro_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                    // Skip delimiter
571                    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            // Parse logic is explained in Japanese at https://github.com/rhysd/wain/pull/9/files#r429552186
598
599            // Parse exponent part
600            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                        // Ok(exp) means u32::MAX <= exp < i32::MIN or i32::MAX < exp <= u32::MAX.
606                        // Err(_) means exp_str is larger than u32::MAX because the lexer guarantees
607                        // that invalid digit cannot occur.
608                        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            // Parse significand as unsigned integer. and adjust exponent
622            // For example, 0x123.456 is parsed into 0x123456p-12 (temp_sig = 0x123456 and temp_exp -= 12)
623            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                    // There are not enough significant digits. It means that SIGNIFICAND_BITS bits
630                    // are not filled yet in temp_sig
631                    _ if temp_sig < 1 << SIGNIFICAND_BITS + 1 => {
632                        // Shift significand & append significant digit
633                        // .unwrap() assumes `c` has hexadecimal character thanks to lexer
634                        temp_sig = (temp_sig << 4) | c.to_digit(16).unwrap() as $uint;
635                        if saw_dot {
636                            // Adjust exponent if fractional part (16=2^4)
637                            temp_exp = temp_exp.saturating_sub(4);
638                        }
639                    }
640                    // There are enough significant digits. It means that all SIGNIFICAND_BITS bits
641                    // were filled. All digits after SIGNIFICAND_BITS are dropped. But only LSB of temp_sig
642                    // needs be updated for rounding to nearest
643                    _ => {
644                        // Set lsb of significand to 1 if non-zero digit (for "round to nearest even")
645                        temp_sig |= (c != '0') as $uint;
646                        if !saw_dot {
647                            // Adjust exponent if integer part
648                            temp_exp = temp_exp.saturating_add(4);
649                        }
650                    }
651                }
652            }
653
654            // Encode float bits
655            if temp_sig != 0 {
656                const BITS: i32 = (mem::size_of::<$float>() * 8) as i32;
657                // For rounding to nearest, at least two more bits than actual fraction is necessary.
658                // Since digits are hexadecimal, it requires 4 bits to read one digit. And 1 bit is
659                // necessary to remember all bits are 1 or not to determine round up or round down.
660                //
661                // Explained at 2. of https://github.com/rhysd/wain/pull/9/files#r429552186
662                const TEMP_SIG_BITS: i32 = SIGNIFICAND_BITS + 4 + 1;
663                // This bias considers to adjust significand to IEEE 754 format. We compute the significand
664                // as unsigned integer. But integer part is 1 bit in IEEE 754 format. (e.g. 0b1011101 -> 0b1.011101).
665                // Since the unsigned integer significand has TEMP_SIG_BITS bits, the value should be multiplid
666                // with 1 / 2^(TEMP_SIG_BITS - 1). It means adding TEMP_SIG_BITS - 1 to exp value.
667                //
668                // https://github.com/rhysd/wain/pull/9/files#r429528984
669                const TEMP_EXP_BIAS: i32 = (<$float>::MAX_EXP - 1) + (TEMP_SIG_BITS - 1);
670                // The same reason as above comment for TEMP_SIG_BITS - 1.
671                // https://github.com/rhysd/wain/pull/9/files#r429529571
672                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                    // Normalize significand and adjust exponent. Adjust temp_sig to use all
677                    // TEMP_SIG_BITS bits.
678                    // Explained at 3. in https://github.com/rhysd/wain/pull/9#discussion_r429552186
679                    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                    // In range of normal numbers or infinity
686                    // Explained at 4.i. in https://github.com/rhysd/wain/pull/9#discussion_r429552186
687
688                    // Mask "implicit" bit. Extract TEMP_SIG_BITS bits from temp_sig
689                    temp_sig &= (1 << TEMP_SIG_BITS - 1) - 1;
690
691                    // Round to nearest even
692                    // 0x2f is 0b101111 and 0x10 is 0b001_0000.
693                    // Lower 7 bits before/after this process is as follows:
694                    //
695                    //   000_0000 -> 000_0000 (round down): as-is
696                    //   000_0001 -> 001_0001 (round down): + 0b001_0000
697                    //   000_1111 -> 001_1111 (round down): + 0b001_0000
698                    //   001_0000 -> 001_0000 (round down): as-is
699                    //   001_0001 -> 010_0001 (round up)  : + 0b001_0000
700                    //   001_1111 -> 010_1111 (round up)  : + 0b001_0000
701                    //   010_0000 -> 011_0000 (round down): + 0b001_0000
702                    //   010_0001 -> 011_0001 (round down): + 0b001_0000
703                    //   010_1111 -> 011_1111 (round down): + 0b001_0000
704                    //   011_0000 -> 100_0000 (round up)  : + 0b001_0000
705                    //   011_0001 -> 100_0001 (round up)  : + 0b001_0000
706                    //   011_1111 -> 100_1111 (round up)  : + 0b001_0000
707                    //
708                    // Note: We don't need to consider a carry of temp_sig because carried '1' is
709                    // added to exponent part later
710                    if (temp_sig & 0x2f) != 0 {
711                        temp_sig += 0x10;
712                    }
713
714                    // Encode significand & biased exponent (it may be infinity)
715                    (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                    // Subnormal or zero
718                    // Explained at 4.ii. in https://github.com/rhysd/wain/pull/9#discussion_r429552186
719
720                    // Adjust significand to set exponent part to MIN_EXP - 1. Here, set 1 to LSB
721                    // for rounding to nearest when the shifted bits contain 1
722                    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                    // Round to nearest even
727                    if (temp_sig & 0x2f) != 0 {
728                        temp_sig += 0x10;
729                    }
730
731                    // Encode significand (biased exponent = 0). Note that significand may be zero
732                    temp_sig >> 5
733                } else if TEMP_MAX_EXP < temp_exp {
734                    // Infinity
735                    (1 << BITS - SIGNIFICAND_BITS) - 1 << SIGNIFICAND_BITS - 1
736                } else {
737                    // Zero
738                    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            // Set sign bit
752            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
778// https://webassembly.github.io/spec/core/text/modules.html
779impl<'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// Helper enum to parse module field
793//
794// https://webassembly.github.io/spec/core/text/modules.html#text-modulefield
795#[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
809// https://webassembly.github.io/spec/core/text/modules.html#text-module
810impl<'s> Parse<'s> for Module<'s> {
811    fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
812        // Note: Abbreviation
813        // In a source file, the toplevel (module ...) surrounding the module body may be omitted.
814        // {modulefield}* == (module {modulefield}*)
815
816        // XXX: By this, at least 2 tokens are necessary to parse module but empty string should be
817        // valid for module with abbreviation.
818        let (keyword, start) = parser.peek_fold_start("module")?;
819        let abbreviated = keyword != Some("module");
820        if !abbreviated {
821            parser.eat_token(); // eat '('
822            parser.eat_token(); // eat 'module
823        }
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        // Any import must be put before other definitions because indices of imports must precede
836        // indices of other definitions
837        //
838        // https://webassembly.github.io/spec/core/syntax/modules.html#indices
839        //
840        // > The index space for functions, tables, memories and globals includes respective imports
841        // > declared in the same module. The indices of these imports precede the indices of other
842        // > definitions in the same index space.
843        let mut can_import = true;
844
845        // Note: types are put in Parser struct field due to abbreviation of typeuse
846        // https://webassembly.github.io/spec/core/text/modules.html#abbreviations
847        parser.ctx.types.clear();
848        parser.ctx.exports.clear();
849
850        loop {
851            match parser.tokens.peek() {
852                Some(Ok((Token::LParen, _))) => {} // fallthrough
853                Some(Ok(_)) => break,
854                Some(Err(err)) => return Err(err.clone().into()),
855                None if abbreviated => break, // with abbreviation, it may reach EOF
856                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(), // This consumes parser.ctx.implicit_type_uses
983            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
996// https://webassembly.github.io/spec/core/text/modules.html#text-modulefield
997impl<'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
1022// https://webassembly.github.io/spec/core/text/modules.html#text-typedef
1023impl<'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
1035// https://webassembly.github.io/spec/core/text/types.html#text-functype
1036impl<'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
1049// https://webassembly.github.io/spec/core/text/types.html#text-param
1050// Not impl for Param<'s> considering abbreviation
1051impl<'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(); // eat '('
1056            parser.eat_token(); // eat 'param'
1057
1058            let id = parser.maybe_ident("identifier for param")?;
1059            if id.is_some() {
1060                // ID is not available for abbreviation
1061                let ty = parser.parse()?;
1062                parser.closing_paren("parameter")?;
1063                params.push(Param { start, id, ty });
1064                continue;
1065            }
1066
1067            // Abbreviation:
1068            //   (param {valtype}*) == (param {valtype})*
1069            loop {
1070                match parser.peek("value type for param or closing ')'")? {
1071                    (Token::RParen, _) => {
1072                        parser.eat_token(); // eat ')'
1073                        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
1086// https://webassembly.github.io/spec/core/text/types.html#text-valtype
1087impl<'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
1101// https://webassembly.github.io/spec/core/text/types.html#text-result
1102// Not impl for FuncResult considering abbreviation
1103impl<'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(); // eat '('
1108            parser.eat_token(); // eat 'result'
1109
1110            // Abbreviation:
1111            //   (result {valtype}*) == (result {valtype})*
1112            loop {
1113                match parser.peek("value type for result or closing ')'")? {
1114                    (Token::RParen, _) => {
1115                        parser.eat_token(); // eat ')'
1116                        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
1129// https://webassembly.github.io/spec/core/text/values.html#text-name
1130impl<'s> Parse<'s> for Name<'s> {
1131    fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1132        // A name string must form a valid UTF-8 encoding as defined by Unicode (Section 2.5)
1133        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
1146// https://webassembly.github.io/spec/core/text/modules.html#text-import
1147// Parse "mod name" "name" sequence in import section
1148impl<'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// https://webassembly.github.io/spec/core/text/modules.html#text-import
1157#[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        // https://webassembly.github.io/spec/core/text/modules.html#text-importdesc
1177        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
1223// https://webassembly.github.io/spec/core/text/modules.html#type-uses
1224impl<'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(); // Eat '('
1229            parser.eat_token(); // Eat 'type'
1230            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, &params, &results)),
1245            },
1246            params,
1247            results,
1248        })
1249    }
1250}
1251
1252// https://webassembly.github.io/spec/core/text/modules.html#indices
1253impl<'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
1267// https://webassembly.github.io/spec/core/text/types.html#text-tabletype
1268impl<'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
1276// https://webassembly.github.io/spec/core/text/types.html#text-limits
1277impl<'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
1290// https://webassembly.github.io/spec/core/text/types.html#text-memtype
1291impl<'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
1297// https://webassembly.github.io/spec/core/text/types.html#text-globaltype
1298impl<'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(); // eat '('
1303                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
1316// https://webassembly.github.io/spec/core/text/modules.html#text-export
1317impl<'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
1341// https://webassembly.github.io/spec/core/text/modules.html#text-func
1342impl<'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        // Note: func has some abbreviations
1348        // https://webassembly.github.io/spec/core/text/modules.html#text-func-abbrev
1349
1350        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                    // `(func $id (import "m" "n") {typeuse})` is a syntax sugar of
1356                    // `(import "m" "n" (func $id {typeuse}))`
1357                    parser.opening_paren("import in func")?;
1358                    parser.eat_token(); // Eat 'import' keyword
1359                    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                    // `(func $id (export "n") {typeuse})` is a syntax sugar of
1372                    // `(export "n" (func $id)) (func $id {typeuse})`
1373                    let export_start = parser.opening_paren("export in func")?;
1374                    parser.eat_token(); // Eat 'export' keyword
1375                    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
1401// Implement Parse for Vec due to abbreviation
1402// https://webassembly.github.io/spec/core/text/modules.html#text-func-abbrev
1403//
1404// https://webassembly.github.io/spec/core/text/modules.html#text-local
1405impl<'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(); // Eat '(' keyword
1410            parser.eat_token(); // Eat 'local' keyword
1411
1412            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                // Only when ID is omitted, multiple types can be combined into one local statement
1421                // `(local ty*)` means `(local ty)*`. Here parse `i64 f32` of `(local i32 i64 f32)`
1422                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
1440// Instructions has special abbreviation. It can be folded and nested. This struct parses sequence
1441// of instructions with the abbreviation.
1442//
1443//   1: ({plaininstr} {foldedinstr}*) == {foldedinstr}* {plaininstr}
1444//   2: (block {label} {resulttype} {instr}*) == block {label} {resulttype} {instr}* end
1445//   3: (loop {label} {resulttype} {instr}*) == 'loop' {label} {resulttype} {instr}* end
1446//   4: (if {label} {resulttype} {foldedinstr}* (then {instr}*) (else {instr}*)?) ==
1447//          {foldedinstr}* if {label} {resulttype} {instr}* else {instr}* end
1448//
1449// e.g.
1450//   (local.get $x) (i32.const 2) i32.add (i32.const 3) i32.mul ==
1451//       (i32.mul (i32.add (local.get $x) (i32.const 2)) (i32.const 3))
1452//
1453// https://webassembly.github.io/spec/core/text/instructions.html#folded-instructions
1454struct MaybeFoldedInsn<'s, 'p> {
1455    insns: Vec<Instruction<'s>>,
1456    parser: &'p mut Parser<'s>,
1457}
1458
1459// Note: These are free functions not to modify `insns` field of MaybeFoldedInsn.
1460
1461fn parse_maybe_result_type<'s>(parser: &mut Parser<'s>) -> Result<'s, Option<ValType>> {
1462    // Note: This requires that next token exists
1463    if let Some("result") = parser.peek_fold_start("result type")?.0 {
1464        parser.eat_token(); // Eat '('
1465        parser.eat_token(); // Eat 'result'
1466        let ty = parser.parse()?;
1467        parser.closing_paren("result type")?;
1468        Ok(Some(ty))
1469    } else {
1470        Ok(None)
1471    }
1472}
1473
1474// https://webassembly.github.io/spec/core/text/instructions.html#folded-instructions
1475impl<'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            // Control instructions
1484            // https://webassembly.github.io/spec/core/text/instructions.html#control-instructions
1485            "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                // Note: 'else' can be omitted when else clause is empty
1503                // https://webassembly.github.io/spec/core/text/instructions.html#abbreviations
1504                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                // Folded 'if' instruction abbreviation:
1509                //   (if {label} {resulttype} {foldedinstr}* (then {instr}*) (else {instr}*))
1510                //      == {foldedinstr}* if {label} {resulttype} {instr}* else {instr}* end
1511
1512                // foldedinstr* for condition
1513                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                // (then {instr}*)
1527                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                // (else {instr}*))
1537                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(); // Eat '('
1542                        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(); // Eat 'else'
1553                        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                // No identifier can be bound in any param declaration appearing in the type annotation
1604                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            // Parametric instructions
1610            // https://webassembly.github.io/spec/core/text/instructions.html#parametric-instructions
1611            "drop" => InsnKind::Drop,
1612            "select" => InsnKind::Select,
1613            // Variable instructions
1614            // https://webassembly.github.io/spec/core/text/instructions.html#variable-instructions
1615            "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            // Memory instructions
1621            // https://webassembly.github.io/spec/core/text/instructions.html#memory-instructions
1622            "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            // Numeric instructions
1648            // https://webassembly.github.io/spec/core/text/instructions.html#numeric-instructions
1649            // Constants
1650            "i32.const" => {
1651                // Note: i32.const operand takes range of i32::MIN <= i <= u32::MAX
1652                // When the value is over i32::MAX, it is treated as u32 value and bitcasted to i32
1653                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                // Note: i64.const operand takes range of i64::MIN <= i <= u64::MAX
1666                // When the value is over i64::MAX, it is treated as u64 value and bitcasted to i64
1667                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                            // Encode  f32 NaN value via u32 assuming IEEE-754 format for NaN boxing.
1688                            // Palyload must be
1689                            //   - within 23bits (fraction of f32 is 23bits)
1690                            //   - >= 2^(23-1) meant that most significant bit must be 1 (since frac cannot be zero for NaN value)
1691                            // https://webassembly.github.io/spec/core/syntax/values.html#floating-point
1692                            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                            // NaN boxing. 1 <= payload_u < 2^23 and floating point number is in IEEE754 format.
1701                            // This will encode the payload into fraction of NaN.
1702                            //   0x{sign}11111111{payload}
1703                            let sign = match sign {
1704                                Sign::Plus => 0,
1705                                Sign::Minus => 1u32 << 31, // most significant bit is 1 for negative number
1706                            };
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                            // Note: Better algorithm should be considered
1721                            // https://github.com/rust-lang/rust/blob/3982d3514efbb65b3efac6bb006b3fa496d16663/src/libcore/num/dec2flt/algorithm.rs
1722                            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                            // Encode f64 NaN value via u64 assuming IEEE-754 format for NaN boxing.
1749                            // Palyload must be
1750                            //   - within 52bits (since fraction of f64 is 52bits)
1751                            //   - >= 2^(52-1) meant that most significant bit must be 1 (since frac cannot be zero for NaN value)
1752                            // https://webassembly.github.io/spec/core/syntax/values.html#floating-point
1753                            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                            // NaN boxing. 1 <= payload_u < 2^52 and floating point number is in IEEE754 format.
1762                            // This will encode the payload into fraction of NaN.
1763                            //   0x{sign}11111111111{payload}
1764                            let sign = match sign {
1765                                Sign::Plus => 0,
1766                                Sign::Minus => 1u64 << 63, // most significant bit is 1 for negative number
1767                            };
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        // Parse {instr}. Even if one {instr}, result is sequence of instructions because of
1950        // folded form
1951        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        // Parse {instr}*
1962        loop {
1963            // This assumes that instr* is always ending with
1964            //   - ')' and 'end' for end of instruction
1965            //   - 'else' for 'then' clause of 'if' instruction
1966            //   - other than keyword except for above
1967            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
1988// https://webassembly.github.io/spec/core/text/modules.html#element-segments
1989impl<'s> Parse<'s> for Elem<'s> {
1990    fn parse(parser: &mut Parser<'s>) -> Result<'s, Self> {
1991        // Need to parse several abbreviations
1992        // https://webassembly.github.io/spec/core/text/modules.html#id7
1993        let start = parser.opening_paren("elem")?;
1994        match_token!(parser, "'elem' keyword", Token::Keyword("elem"));
1995
1996        // tableidx can be omitted
1997        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(); // Eat '('
2004            parser.eat_token(); // Eat 'offset'
2005            let expr = parser.parse()?;
2006            parser.closing_paren("offset parameter of elem segment")?;
2007            expr
2008        } else {
2009            // Abbreviation: {instr} == (offset {instr})
2010            let mut parser = MaybeFoldedInsn::new(parser);
2011            parser.parse_one()?;
2012            parser.insns
2013        };
2014
2015        // This token is not defined in webassembly.github.io/spec but wasm2wat emits it. It seems that this is not
2016        // included in Wasm MVP, but it is necessary to parse .wat files emitted by wasm2wat.
2017        // https://github.com/WebAssembly/wabt/blob/142c52678acf7decf6a48190c395ed73bb91170a/src/wat-writer.cc#L1271
2018        if let (Token::Keyword("func"), _) = parser.peek("")? {
2019            parser.eat_token(); // eat 'func'
2020        }
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// Helper struct to resolve import/export/elem abbreviation in 'table' section
2041// https://webassembly.github.io/spec/core/text/modules.html#text-table-abbrev
2042#[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(); // eat '('
2060                    let (keyword, offset) =
2061                        match_token!(parser, "'import' or 'export' for table section", Token::Keyword(k) => k);
2062                    match keyword {
2063                        "import" => {
2064                            // (table {id}? (import {name} {name} ) {tabletype}) ==
2065                            //    (import {name} {name} (table {id}? {tabletype}))
2066                            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                            // (table {id}? (export {name}) ...) ==
2079                            //   (export {name} (table {id}')) (table {id}' ...)
2080                            //   note that this occurs repeatedly
2081                            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                            // 'export' can be chained by'import', 'export', 'elem' and tabletype
2090                        }
2091                        kw => return parser.error(ParseErrorKind::UnexpectedKeyword(kw), offset),
2092                    }
2093                }
2094                Token::Keyword("funcref") => {
2095                    // (table {id}? funcref (elem  {funcidx}*)) ==
2096                    //   (table {id}' n n funcref) (elem {id}' (i32.const 0) {funcidx}*)
2097                    //   where n is length of {funcidx}*
2098                    parser.eat_token(); // eat 'funcref' (elemtype)
2099                    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; // TODO: Check length <= 2^32
2112                    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                    // tabletype
2133                    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        // the memory index can be omitted, defaulting to 𝟶.
2153        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(); // Eat '('
2160            parser.eat_token(); // Eat 'offset'
2161            let offset = parser.parse()?;
2162            parser.closing_paren("offset of data segment")?;
2163            offset
2164        } else {
2165            // Abbreviation: {instr} == (offset {instr})
2166            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// Helper struct to resolve import/export/data abbreviation in memory section
2192// https://webassembly.github.io/spec/core/text/modules.html#memories
2193#[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(); // eat '('
2210                    let (keyword, offset) = match_token!(parser, "'import' or 'export' or 'data' for memory section", Token::Keyword(k) => k);
2211                    match keyword {
2212                        "import" => {
2213                            // (memory {id}? (import {name} {name} ) {memtype}) ==
2214                            //    (import {name} {name} (memory {id}? {memtype}))
2215                            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                            // (memory {id}? (export {name}) ...) ==
2228                            //   (export {name} (memory {id}')) (memory {id}' ...)
2229                            //   note that this occurs repeatedly
2230                            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                            // 'export' can be chained by'import', 'export', 'data' and tabletype
2239                        }
2240                        "data" => {
2241                            // (memory {id}? (data  {datastring})) ==
2242                            //   (memory {id}' m m) (data {id}' (i32.const 0) {datastring})
2243                            //   where n = data bytes, m = ceil(n / 64Ki), Note: 64Ki means page size
2244
2245                            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                            // Infer memory limits from page size (64 * 1024 = 65536)
2262                            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                    // memtype
2289                    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
2303// https://webassembly.github.io/spec/core/text/modules.html#globals
2304impl<'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        // Note: Global section has import/export abbreviation
2313        // https://webassembly.github.io/spec/core/text/modules.html#globals
2314        loop {
2315            match parser.peek("argument of global section")?.0 {
2316                Token::LParen => {
2317                    parser.eat_token(); // Eat '('
2318                    let (keyword, offset) =
2319                        match_token!(parser, "'import' or 'export' for global section", Token::Keyword(k) => k);
2320                    match keyword {
2321                        "import" => {
2322                            // (global {id}? (import {name} {name} ) {globaltype}) ==
2323                            //    (import {name} {name} (global {id}? {globaltype}))
2324                            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                            // (global {id}? (export {name}) ...) ==
2337                            //   (export {name} (global {id}')) (global {id}' ...)
2338                            //   note that this occurs repeatedly
2339                            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                            // globaltype with mut
2350                            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                    // globaltype without mut
2367                    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
2383// https://webassembly.github.io/spec/core/text/modules.html#text-start
2384impl<'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        // Index is reset after move_out
2447        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 => { /* OK */ }
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 => { /* OK */ }
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        // abbreviation
2600        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        // abbreviation
2624        assert_error!(
2625            r#"(type $f1 (func)) )"#,
2626            Module<'_>,
2627            ExpectEndOfFile {
2628                token: Token::RParen,
2629                ..
2630            }
2631        );
2632        // imports must be put before other definitions
2633        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        // Abbreviation
2728
2729        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, ')'); // ) is necessary to avoid unexpected EOF
2758                let mut parser = Parser::new(input);
2759                let params: Vec<Param<'_>> = parser.parse().unwrap();
2760                match params.as_slice() {
2761                    $expect => { /* OK */ }
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, ')'); // ) is necessary to avoid unexpected EOF
2901                let mut parser = Parser::new(input);
2902                let results: Vec<FuncResult> = parser.parse().unwrap();
2903                match results.as_slice() {
2904                    $expect => { /* OK */ }
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        // XXX: Parsing TypeUse<'s> directly does not work since parser tries to parse (param)* and
3097        // (result)* and fails with unexpected EOF when they are missing. This is not a real-world
3098        // problem because typeuse is always used within other statement.
3099        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        // Abbreviation
3140        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        // typeuse has special abbreviation and it affects entire module. It means that assert_parse!
3166        // is not available
3167        {
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            // First function type which has the same signature is chosen
3178            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            // First function type which has the same signature is chosen
3191            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            // If there is no function type matching to the function's signature, new function type
3202            // is inserted to the module
3203            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        // Note: {typeuse} accepts empty string due to abbreviation. Empty string is accepted as
3221        // TypeUse { idx: None, params: [], results: [], .. } with (type (func)) inserted to module.
3222        // https://webassembly.github.io/spec/core/text/modules.html#abbreviations
3223    }
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" => { /* OK */ }
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        // Multiple exports
3567        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 => { /* OK */ }
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        // Note: 'loop' instruction is parsed with the same logic as 'block' instruction. Only one test case is sufficient
3782        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)]); // INT32_MAX
4082        assert_insn!(r#"i32.const 0x7fffffff"#, [I32Const(0x7fffffff)]); // INT32_MAX
4083        assert_insn!(r#"i32.const -2147483648"#, [I32Const(-2147483648)]); // INT32_MIN
4084        assert_insn!(r#"i32.const -0x80000000"#, [I32Const(-0x80000000)]); // INT32_MAX
4085        assert_insn!(r#"i32.const 0xfedc6543"#, [I32Const(-19110589)]); // INT32_MAX < i < UINT32_MAX
4086        assert_insn!(r#"i32.const 4294967295"#, [I32Const(-1)]); // UINT32_MAX
4087        assert_insn!(r#"i32.const 0xffffffff"#, [I32Const(-1)]); // UINT32_MAX
4088
4089        assert_error!(
4090            r#"i32.const 0.123"#,
4091            Vec<Instruction<'_>>,
4092            UnexpectedToken {
4093                expected: "integer for i32.const operand",
4094                ..
4095            }
4096        );
4097        // uint32_max + 1
4098        assert_error!(
4099            r#"i32.const 4294967296"#,
4100            Vec<Instruction<'_>>,
4101            CannotParseNum{ reason, .. } if reason == "too big integer"
4102        );
4103        // uint32_max + 1
4104        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"#, // INT64_MAX
4129            [I64Const(9223372036854775807)]
4130        );
4131        assert_insn!(
4132            r#"i64.const -9223372036854775808"#, // INT64_MIN
4133            [I64Const(-9223372036854775808)]
4134        );
4135        assert_insn!(
4136            r#"i64.const 0x7fffffffffffffff"#, // INT64_MAX
4137            [I64Const(0x7fffffffffffffff)]
4138        );
4139        assert_insn!(
4140            r#"i64.const -0x8000000000000000"#, // INT64_MIN
4141            [I64Const(-0x8000000000000000)]
4142        );
4143        assert_insn!(
4144            r#"i64.const 0x8000000000000000"#, // INT64_MAX + 1
4145            [I64Const(-9223372036854775808)]
4146        );
4147        assert_insn!(
4148            r#"i64.const 0xffffffffffffffff"#, // UINT64_MAX
4149            [I64Const(-1)]
4150        );
4151        assert_insn!(
4152            r#"i64.const 18446744073709551615"#, // UINT64_MAX
4153            [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"#, // UINT64_MAX + 1
4166            Vec<Instruction<'_>>,
4167            CannotParseNum{ reason, .. }
4168            if reason == "too big integer"
4169        );
4170        assert_error!(
4171            r#"i64.const 18446744073709551616"#, // UINT64_MAX + 1
4172            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); // ≈ (2 - 2^(-23)) * 2^127
4210        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); // ≈ 2^(-149)
4212        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"#, // Larger than 0x80_0000
4229            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"#, // Larger than 0x10_0000_0000_0000
4270            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" => { /* OK */ }
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" => { /* OK */ }
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" => { /* OK */ }
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" => { /* OK */ }
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" => { /* OK */ }
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        // f32, small exponent
5018        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        // f32, large exponent
5030        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        // f32, subnormal
5040        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        // f64, small exponent
5062        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        // f64, large exponent
5072        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        // f64, subnormal
5084        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}