use crate::ast::{kw, Float32, Float64, Index, HeapType};
use crate::parser::{Parse, Parser, Result};
#[derive(Debug)]
#[allow(missing_docs)]
pub enum AssertExpression<'a> {
I32(i32),
I64(i64),
F32(NanPattern<Float32>),
F64(NanPattern<Float64>),
V128(V128Pattern),
RefNull(Option<HeapType<'a>>),
RefExtern(u32),
RefFunc(Option<Index<'a>>),
LegacyArithmeticNaN,
LegacyCanonicalNaN,
}
impl<'a> Parse<'a> for AssertExpression<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let keyword = parser.step(|c| match c.keyword() {
Some(pair) => Ok(pair),
None => Err(c.error("expected a keyword")),
})?;
match keyword {
"i32.const" => Ok(AssertExpression::I32(parser.parse()?)),
"i64.const" => Ok(AssertExpression::I64(parser.parse()?)),
"f32.const" => Ok(AssertExpression::F32(parser.parse()?)),
"f64.const" => Ok(AssertExpression::F64(parser.parse()?)),
"v128.const" => Ok(AssertExpression::V128(parser.parse()?)),
"ref.null" => Ok(AssertExpression::RefNull(parser.parse()?)),
"ref.extern" => Ok(AssertExpression::RefExtern(parser.parse()?)),
"ref.func" => Ok(AssertExpression::RefFunc(parser.parse()?)),
_ => Err(parser.error("expected a [type].const expression")),
}
}
}
#[derive(Debug, PartialEq)]
#[allow(missing_docs)]
pub enum NanPattern<T> {
CanonicalNan,
ArithmeticNan,
Value(T),
}
impl<'a, T> Parse<'a> for NanPattern<T>
where
T: Parse<'a>,
{
fn parse(parser: Parser<'a>) -> Result<Self> {
if parser.peek::<kw::nan_canonical>() {
parser.parse::<kw::nan_canonical>()?;
Ok(NanPattern::CanonicalNan)
} else if parser.peek::<kw::nan_arithmetic>() {
parser.parse::<kw::nan_arithmetic>()?;
Ok(NanPattern::ArithmeticNan)
} else {
let val = parser.parse()?;
Ok(NanPattern::Value(val))
}
}
}
#[derive(Debug)]
#[allow(missing_docs)]
pub enum V128Pattern {
I8x16([i8; 16]),
I16x8([i16; 8]),
I32x4([i32; 4]),
I64x2([i64; 2]),
F32x4([NanPattern<Float32>; 4]),
F64x2([NanPattern<Float64>; 2]),
}
impl<'a> Parse<'a> for V128Pattern {
fn parse(parser: Parser<'a>) -> Result<Self> {
let mut l = parser.lookahead1();
if l.peek::<kw::i8x16>() {
parser.parse::<kw::i8x16>()?;
Ok(V128Pattern::I8x16([
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
]))
} else if l.peek::<kw::i16x8>() {
parser.parse::<kw::i16x8>()?;
Ok(V128Pattern::I16x8([
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
]))
} else if l.peek::<kw::i32x4>() {
parser.parse::<kw::i32x4>()?;
Ok(V128Pattern::I32x4([
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
]))
} else if l.peek::<kw::i64x2>() {
parser.parse::<kw::i64x2>()?;
Ok(V128Pattern::I64x2([parser.parse()?, parser.parse()?]))
} else if l.peek::<kw::f32x4>() {
parser.parse::<kw::f32x4>()?;
Ok(V128Pattern::F32x4([
parser.parse()?,
parser.parse()?,
parser.parse()?,
parser.parse()?,
]))
} else if l.peek::<kw::f64x2>() {
parser.parse::<kw::f64x2>()?;
Ok(V128Pattern::F64x2([parser.parse()?, parser.parse()?]))
} else {
Err(l.error())
}
}
}