Skip to content

Commit 9a31d7e

Browse files
authored
[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.
1 parent 053b591 commit 9a31d7e

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

src/parser/contexts.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ struct TypeUse {
7878
struct NullTypeParserCtx {
7979
using IndexT = Ok;
8080
using HeapTypeT = Ok;
81+
using TupleElemListT = Ok;
8182
using TypeT = Ok;
8283
using ParamsT = Ok;
8384
using ResultsT = size_t;
@@ -122,6 +123,10 @@ struct NullTypeParserCtx {
122123

123124
TypeT makeRefType(HeapTypeT, Nullability) { return Ok{}; }
124125

126+
TupleElemListT makeTupleElemList() { return Ok{}; }
127+
void appendTupleElem(TupleElemListT&, TypeT) {}
128+
TypeT makeTupleType(TupleElemListT) { return Ok{}; }
129+
125130
ParamsT makeParams() { return Ok{}; }
126131
void appendParam(ParamsT&, Name, TypeT) {}
127132

@@ -219,7 +224,13 @@ template<typename Ctx> struct TypeParserCtx {
219224
return Type(ht, nullability);
220225
}
221226

222-
TypeT makeTupleType(const std::vector<Type> types) { return Tuple(types); }
227+
std::vector<Type> makeTupleElemList() { return {}; }
228+
void appendTupleElem(std::vector<Type>& elems, Type elem) {
229+
elems.push_back(elem);
230+
}
231+
Result<TypeT> makeTupleType(const std::vector<Type>& types) {
232+
return Tuple(types);
233+
}
223234

224235
ParamsT makeParams() { return {}; }
225236
void appendParam(ParamsT& params, Name id, TypeT type) {

src/parser/parsers.h

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ using namespace std::string_view_literals;
2828
// Types
2929
template<typename Ctx> Result<typename Ctx::HeapTypeT> heaptype(Ctx&);
3030
template<typename Ctx> MaybeResult<typename Ctx::RefTypeT> reftype(Ctx&);
31+
template<typename Ctx> MaybeResult<typename Ctx::TypeT> tupletype(Ctx&);
3132
template<typename Ctx> Result<typename Ctx::TypeT> valtype(Ctx&);
3233
template<typename Ctx> MaybeResult<typename Ctx::ParamsT> params(Ctx&);
3334
template<typename Ctx> MaybeResult<typename Ctx::ResultsT> results(Ctx&);
@@ -365,15 +366,34 @@ template<typename Ctx> MaybeResult<typename Ctx::TypeT> reftype(Ctx& ctx) {
365366
return ctx.makeRefType(*type, nullability);
366367
}
367368

369+
// tupletype ::= '(' 'tuple' valtype* ')'
370+
template<typename Ctx> MaybeResult<typename Ctx::TypeT> tupletype(Ctx& ctx) {
371+
if (!ctx.in.takeSExprStart("tuple"sv)) {
372+
return {};
373+
}
374+
auto elems = ctx.makeTupleElemList();
375+
size_t numElems = 0;
376+
while (!ctx.in.takeRParen()) {
377+
auto elem = singlevaltype(ctx);
378+
CHECK_ERR(elem);
379+
ctx.appendTupleElem(elems, *elem);
380+
++numElems;
381+
}
382+
if (numElems < 2) {
383+
return ctx.in.err("tuples must have at least two elements");
384+
}
385+
return ctx.makeTupleType(elems);
386+
}
387+
368388
// numtype ::= 'i32' => i32
369389
// | 'i64' => i64
370390
// | 'f32' => f32
371391
// | 'f64' => f64
372392
// vectype ::= 'v128' => v128
373-
// valtype ::= t:numtype => t
374-
// | t:vectype => t
375-
// | t:reftype => t
376-
template<typename Ctx> Result<typename Ctx::TypeT> valtype(Ctx& ctx) {
393+
// singlevaltype ::= t:numtype => t
394+
// | t:vectype => t
395+
// | t:reftype => t
396+
template<typename Ctx> Result<typename Ctx::TypeT> singlevaltype(Ctx& ctx) {
377397
if (ctx.in.takeKeyword("i32"sv)) {
378398
return ctx.makeI32();
379399
} else if (ctx.in.takeKeyword("i64"sv)) {
@@ -392,6 +412,15 @@ template<typename Ctx> Result<typename Ctx::TypeT> valtype(Ctx& ctx) {
392412
}
393413
}
394414

415+
// valtype ::= singlevaltype | tupletype
416+
template<typename Ctx> Result<typename Ctx::TypeT> valtype(Ctx& ctx) {
417+
if (auto type = tupletype(ctx)) {
418+
CHECK_ERR(type);
419+
return *type;
420+
}
421+
return singlevaltype(ctx);
422+
}
423+
395424
// param ::= '(' 'param id? t:valtype ')' => [t]
396425
// | '(' 'param t*:valtype* ')' => [t*]
397426
// params ::= param*

test/lit/wat-kitchen-sink.wast

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,12 @@
457457
;; CHECK-NEXT: )
458458
(func $f4 (type 18) (local i32 i64) (local $l f32))
459459

460+
;; CHECK: (func $tuple-locals (type $void)
461+
;; CHECK-NEXT: (local $0 (tuple i32 i32))
462+
;; CHECK-NEXT: (nop)
463+
;; CHECK-NEXT: )
464+
(func $tuple-locals (local (tuple i32 i32)))
465+
460466
;; CHECK: (func $nop-skate (type $void)
461467
;; CHECK-NEXT: (nop)
462468
;; CHECK-NEXT: (nop)
@@ -3519,7 +3525,7 @@
35193525
(func $ref-func
35203526
ref.func $ref-func
35213527
drop
3522-
ref.func 151
3528+
ref.func 152
35233529
drop
35243530
)
35253531

0 commit comments

Comments
 (0)