summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2022-07-08 14:32:26 -0700
committerGitHub <noreply@github.com>2022-07-08 14:32:26 -0700
commit83f48ed96357cdde61d898ca05f201d38e6d4222 (patch)
treec3b70e21924fc7015ae6d09b18dfce9e78120dfb /src
parent395e9d43cc40f45b5388ddf1791cd2aa3249cec1 (diff)
downloadbinaryen-83f48ed96357cdde61d898ca05f201d38e6d4222.tar.gz
binaryen-83f48ed96357cdde61d898ca05f201d38e6d4222.tar.bz2
binaryen-83f48ed96357cdde61d898ca05f201d38e6d4222.zip
[Parser] Parse rec groups (#4785)
Diffstat (limited to 'src')
-rw-r--r--src/wasm/wat-parser.cpp50
1 files changed, 42 insertions, 8 deletions
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp
index b81a92464..bb756159b 100644
--- a/src/wasm/wat-parser.cpp
+++ b/src/wasm/wat-parser.cpp
@@ -314,6 +314,7 @@ struct ParseDeclsCtx {
// The module element definitions we are parsing in this phase.
std::vector<DefPos> typeDefs;
+ std::vector<DefPos> subtypeDefs;
std::vector<DefPos> globalDefs;
// Counters used for generating names for module elements.
@@ -350,7 +351,7 @@ struct ParseTypeDefsCtx {
// Parse the names of types and fields as we go.
std::vector<TypeNames> names;
- // The index of the type definition we are parsing.
+ // The index of the subtype definition we are parsing.
Index index = 0;
ParseTypeDefsCtx(TypeBuilder& builder, const IndexMap& typeIndices)
@@ -930,7 +931,7 @@ template<typename Ctx> Result<> strtype(Ctx& ctx, ParseInput& in) {
// subtype ::= '(' 'type' id? '(' 'sub' typeidx? strtype ')' ')'
// | '(' 'type' id? strtype ')'
template<typename Ctx> MaybeResult<> subtype(Ctx& ctx, ParseInput& in) {
- [[maybe_unused]] auto start = in.getPos();
+ [[maybe_unused]] auto pos = in.getPos();
if (!in.takeSExprStart("type"sv)) {
return {};
@@ -969,7 +970,10 @@ template<typename Ctx> MaybeResult<> subtype(Ctx& ctx, ParseInput& in) {
}
if constexpr (parsingDecls<Ctx>) {
- ctx.typeDefs.push_back({name, start});
+ ctx.subtypeDefs.push_back({name, pos});
+ }
+ if constexpr (parsingTypeDefs<Ctx>) {
+ ++ctx.index;
}
return Ok{};
@@ -978,8 +982,35 @@ template<typename Ctx> MaybeResult<> subtype(Ctx& ctx, ParseInput& in) {
// deftype ::= '(' 'rec' subtype* ')'
// | subtype
template<typename Ctx> MaybeResult<> deftype(Ctx& ctx, ParseInput& in) {
- // TODO: rec
- return subtype(ctx, in);
+ [[maybe_unused]] auto pos = in.getPos();
+
+ if (in.takeSExprStart("rec"sv)) {
+ [[maybe_unused]] size_t startIndex = 0;
+ if constexpr (parsingTypeDefs<Ctx>) {
+ startIndex = ctx.index;
+ }
+ size_t groupLen = 0;
+ while (auto type = subtype(ctx, in)) {
+ CHECK_ERR(type);
+ ++groupLen;
+ }
+ if (!in.takeRParen()) {
+ return in.err("expected type definition or end of recursion group");
+ }
+ if constexpr (parsingTypeDefs<Ctx>) {
+ ctx.builder.createRecGroup(startIndex, groupLen);
+ }
+ } else if (auto type = subtype(ctx, in)) {
+ CHECK_ERR(type);
+ } else {
+ return {};
+ }
+
+ if constexpr (parsingDecls<Ctx>) {
+ ctx.typeDefs.push_back({{}, pos});
+ }
+
+ return Ok{};
}
// global ::= '(' 'global' id? ('(' 'export' name ')')* gt:globaltype e:expr ')'
@@ -1175,15 +1206,18 @@ Result<> parseModule(Module& wasm, std::string_view input) {
}
}
- auto typeIndices = createIndexMap(input, decls.typeDefs);
+ auto typeIndices = createIndexMap(input, decls.subtypeDefs);
CHECK_ERR(typeIndices);
// Parse type definitions.
std::vector<HeapType> types;
{
- TypeBuilder builder(decls.typeDefs.size());
+ TypeBuilder builder(decls.subtypeDefs.size());
ParseTypeDefsCtx ctx(builder, *typeIndices);
- CHECK_ERR(parseDefs(ctx, input, decls.typeDefs, deftype));
+ for (auto& typeDef : decls.typeDefs) {
+ ParseInput in(input, typeDef.pos);
+ CHECK_ERR(deftype(ctx, in));
+ }
auto built = builder.build();
if (auto* err = built.getError()) {
std::stringstream msg;