From 9a31d7e351910191af2c00a9834bcb2e81a28d12 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Mon, 29 Jan 2024 15:36:41 -0800 Subject: [Parser] Parse tuple types (#6249) Use the new `(tuple ...)` syntax. Enforce that tuples have a valid number of elements and are not nested to avoid assertion failures when parsing invalid input. --- src/parser/contexts.h | 13 ++++++++++++- src/parser/parsers.h | 37 +++++++++++++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/parser/contexts.h b/src/parser/contexts.h index fb9218cbc..73be5e46e 100644 --- a/src/parser/contexts.h +++ b/src/parser/contexts.h @@ -78,6 +78,7 @@ struct TypeUse { struct NullTypeParserCtx { using IndexT = Ok; using HeapTypeT = Ok; + using TupleElemListT = Ok; using TypeT = Ok; using ParamsT = Ok; using ResultsT = size_t; @@ -122,6 +123,10 @@ struct NullTypeParserCtx { TypeT makeRefType(HeapTypeT, Nullability) { return Ok{}; } + TupleElemListT makeTupleElemList() { return Ok{}; } + void appendTupleElem(TupleElemListT&, TypeT) {} + TypeT makeTupleType(TupleElemListT) { return Ok{}; } + ParamsT makeParams() { return Ok{}; } void appendParam(ParamsT&, Name, TypeT) {} @@ -219,7 +224,13 @@ template struct TypeParserCtx { return Type(ht, nullability); } - TypeT makeTupleType(const std::vector types) { return Tuple(types); } + std::vector makeTupleElemList() { return {}; } + void appendTupleElem(std::vector& elems, Type elem) { + elems.push_back(elem); + } + Result makeTupleType(const std::vector& types) { + return Tuple(types); + } ParamsT makeParams() { return {}; } void appendParam(ParamsT& params, Name id, TypeT type) { diff --git a/src/parser/parsers.h b/src/parser/parsers.h index 0c7c5550f..706c6525e 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h @@ -28,6 +28,7 @@ using namespace std::string_view_literals; // Types template Result heaptype(Ctx&); template MaybeResult reftype(Ctx&); +template MaybeResult tupletype(Ctx&); template Result valtype(Ctx&); template MaybeResult params(Ctx&); template MaybeResult results(Ctx&); @@ -365,15 +366,34 @@ template MaybeResult reftype(Ctx& ctx) { return ctx.makeRefType(*type, nullability); } +// tupletype ::= '(' 'tuple' valtype* ')' +template MaybeResult tupletype(Ctx& ctx) { + if (!ctx.in.takeSExprStart("tuple"sv)) { + return {}; + } + auto elems = ctx.makeTupleElemList(); + size_t numElems = 0; + while (!ctx.in.takeRParen()) { + auto elem = singlevaltype(ctx); + CHECK_ERR(elem); + ctx.appendTupleElem(elems, *elem); + ++numElems; + } + if (numElems < 2) { + return ctx.in.err("tuples must have at least two elements"); + } + return ctx.makeTupleType(elems); +} + // numtype ::= 'i32' => i32 // | 'i64' => i64 // | 'f32' => f32 // | 'f64' => f64 // vectype ::= 'v128' => v128 -// valtype ::= t:numtype => t -// | t:vectype => t -// | t:reftype => t -template Result valtype(Ctx& ctx) { +// singlevaltype ::= t:numtype => t +// | t:vectype => t +// | t:reftype => t +template Result singlevaltype(Ctx& ctx) { if (ctx.in.takeKeyword("i32"sv)) { return ctx.makeI32(); } else if (ctx.in.takeKeyword("i64"sv)) { @@ -392,6 +412,15 @@ template Result valtype(Ctx& ctx) { } } +// valtype ::= singlevaltype | tupletype +template Result valtype(Ctx& ctx) { + if (auto type = tupletype(ctx)) { + CHECK_ERR(type); + return *type; + } + return singlevaltype(ctx); +} + // param ::= '(' 'param id? t:valtype ')' => [t] // | '(' 'param t*:valtype* ')' => [t*] // params ::= param* -- cgit v1.2.3