Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/wabt/wast-parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ class WastParser {
Result ParseTableModuleField(Module*);

Result ParseCustomSectionAnnotation(Module*);
bool PeekIsCustom();
bool PeekIsAnnotation(const char* name);

Result ParseExportDesc(Export*);
Result ParseInlineExports(ModuleFieldList*, ExternalKind);
Expand Down
23 changes: 15 additions & 8 deletions src/wast-parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ TokenType WastParser::Peek(size_t n) {
}
if ((options_->features.code_metadata_enabled() &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like maybe there's enough conditions here that they would benefit by getting broken out into a separate function at this point?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Honestly, I was a bit surprised to see this logic in the Peek method, too. Perhaps it would be better to put this all in it's own method anyway, with a more straightforward way of parsing/skipping certain annotations.

cur.text().find("metadata.code.") == 0) ||
cur.text() == "custom") {
cur.text() == "custom" || cur.text() == "name") {
tokens_.push_back(cur);
continue;
}
Expand Down Expand Up @@ -762,6 +762,13 @@ Result WastParser::ErrorIfLpar(const std::vector<std::string>& expected,

bool WastParser::ParseBindVarOpt(std::string* name) {
WABT_TRACE(ParseBindVarOpt);
if (PeekIsAnnotation("name")) {
// Should be the @name
Consume();
CHECK_RESULT(ParseQuotedText(name));
EXPECT(Rpar);
return true;
}
if (!PeekMatch(TokenType::Var)) {
return false;
}
Expand Down Expand Up @@ -1174,7 +1181,7 @@ Result WastParser::ParseModule(std::unique_ptr<Module>* out_module) {
auto module_command = cast<ScriptModuleCommand>(std::move(command));
*module = std::move(module_command->module);
}
} else if (IsModuleField(PeekPair()) || PeekIsCustom()) {
} else if (IsModuleField(PeekPair()) || PeekIsAnnotation("custom")) {
// Parse an inline module (i.e. one with no surrounding (module)).
CHECK_RESULT(ParseModuleFieldList(module.get()));
} else if (PeekMatch(TokenType::Eof)) {
Expand All @@ -1200,7 +1207,7 @@ Result WastParser::ParseScript(std::unique_ptr<Script>* out_script) {
// Don't consume the Lpar yet, even though it is required. This way the
// sub-parser functions (e.g. ParseFuncModuleField) can consume it and keep
// the parsing structure more regular.
if (IsModuleField(PeekPair()) || PeekIsCustom()) {
if (IsModuleField(PeekPair()) || PeekIsAnnotation("custom")) {
// Parse an inline module (i.e. one with no surrounding (module)).
auto command = std::make_unique<ModuleCommand>();
command->module.loc = GetLocation();
Expand Down Expand Up @@ -1273,17 +1280,17 @@ Result WastParser::ParseCustomSectionAnnotation(Module* module) {
return Result::Ok;
}

bool WastParser::PeekIsCustom() {
bool WastParser::PeekIsAnnotation(const char* name) {
// If IsLparAnn succeeds, tokens_.front() must have text, as it is an LparAnn
// token.
return options_->features.annotations_enabled() && IsLparAnn(PeekPair()) &&
tokens_.front().text() == "custom";
tokens_.front().text() == name;
}

Result WastParser::ParseModuleFieldList(Module* module) {
WABT_TRACE(ParseModuleFieldList);
while (IsModuleField(PeekPair()) || PeekIsCustom()) {
if (PeekIsCustom()) {
while (IsModuleField(PeekPair()) || PeekIsAnnotation("custom")) {
if (PeekIsAnnotation("custom")) {
CHECK_RESULT(ParseCustomSectionAnnotation(module));
continue;
}
Expand Down Expand Up @@ -3589,7 +3596,7 @@ Result WastParser::ParseScriptModule(
auto tsm = std::make_unique<TextScriptModule>();
tsm->module.name = name;
tsm->module.loc = loc;
if (IsModuleField(PeekPair()) || PeekIsCustom()) {
if (IsModuleField(PeekPair()) || PeekIsAnnotation("custom")) {
CHECK_RESULT(ParseModuleFieldList(&tsm->module));
} else if (!PeekMatch(TokenType::Rpar)) {
ConsumeIfLpar();
Expand Down
15 changes: 10 additions & 5 deletions src/wat-writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ class WatWriter : ModuleContext {
void WriteTypeEntry(const TypeEntry& type);
void WriteField(const Field& field);
void WriteStartFunction(const Var& start);
void WriteOpenAnnotation(const char* name);
void WriteCustom(const Custom& custom);

class ExprVisitorDelegate;
Expand Down Expand Up @@ -284,6 +285,11 @@ void WatWriter::WriteOpen(const char* name, NextChar next_char) {
Indent();
}

void WatWriter::WriteOpenAnnotation(const char* name) {
WriteOpen("@", NextChar::None);
WritePutsSpace(name);
}

void WatWriter::WriteOpenNewline(const char* name) {
WriteOpen(name, NextChar::Newline);
}
Expand Down Expand Up @@ -319,10 +325,9 @@ void WatWriter::WriteName(std::string_view str, NextChar next_char) {
str.begin(), str.end(), [](uint8_t c) { return !s_valid_name_chars[c]; });

if (has_invalid_chars) {
std::string valid_str;
std::transform(str.begin(), str.end(), std::back_inserter(valid_str),
[](uint8_t c) { return s_valid_name_chars[c] ? c : '_'; });
WriteDataWithNextChar(valid_str.data(), valid_str.length());
WriteOpenAnnotation("name");
WriteQuotedData(str.data(), str.length());
WriteCloseSpace();
} else {
WriteDataWithNextChar(str.data(), str.length());
}
Expand Down Expand Up @@ -1615,7 +1620,7 @@ void WatWriter::WriteStartFunction(const Var& start) {
}

void WatWriter::WriteCustom(const Custom& custom) {
WriteOpenSpace("@custom");
WriteOpenAnnotation("custom");
WriteQuotedString(custom.name, NextChar::Space);
WriteQuotedData(custom.data.data(), custom.data.size());
WriteCloseNewline();
Expand Down
2 changes: 1 addition & 1 deletion test/binary/invalid-name.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ section("name") {
(;; STDOUT ;;;
(module
(type (;0;) (func (result i32)))
(func $hi_hello_hey (type 0) (result i32)
(func (@name "$hi hello hey") (type 0) (result i32)
i32.const 42))
;;; STDOUT ;;)
2 changes: 1 addition & 1 deletion test/parse/all-features.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
(tag $e)

;; annotations
(func $f (@name "func") (result i32)
(func (@name "$f") (result i32)
(i32.const 0))

(func (result i32)
Expand Down
13 changes: 13 additions & 0 deletions test/roundtrip/invalid-name.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
;;; TOOL: run-roundtrip
;;; ARGS: --stdout --no-check --enable-annotations --debug-names
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is --no-check used here -- what makes the module invalid?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I think I must've left this in when looking at another roundtrip test for reference. Thanks for the catch!

(module
(type (;0;) (func (result i32)))
(func (@name "$hi hello hey") (type 0) (result i32)
i32.const 42))
(;; STDOUT ;;;
(module
(type (;0;) (func (result i32)))
(func (@name "$hi hello hey") (type 0) (result i32)
i32.const 42)
(@custom "name" "\01\0f\01\00\0chi hello hey\02\03\01\00\00"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to be printing both the @name annotation and also the @custom "name" annotation with the same info? (Not 100% sure what the right behavior is, but we do suppress the @custom annotation for most other cases that are already handled elsewhere...)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this is the current behavior of names in general. Even without the @name annotation, both are included. I'll work on suppressing this, though.

;;; STDOUT ;;)