Skip to content

Commit

Permalink
Fine-tune bytes literal parsing further.
Browse files Browse the repository at this point in the history
This now optimizes the generated code for parsing a `bytes` literal
based on what we're going to use it for, or not (require literal vs.
look-ahead vs skip).

The standard case of a parsing an expected literal now looks like
this:

```
    # Begin parsing production: Ctor: b1  -> b"abc" (const bytes)
    (*self).b1 = spicy_rt::expectBytesLiteral(__data, __cur, b"abc", "../tests/spicy/types/bytes/parse-length.spicy:20:10-20:15", Null);
    __cur = __cur.advance(3);

    if ( __trim )
        (*__data).trim(begin(__cur));

    # End parsing production: Ctor: b1  -> b"abc" (const bytes)
```
  • Loading branch information
rsmmr committed Sep 26, 2024
1 parent a17e39b commit 1278d63
Show file tree
Hide file tree
Showing 11 changed files with 168 additions and 130 deletions.
2 changes: 1 addition & 1 deletion spicy/lib/spicy_rt.hlt
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,6 @@ declare public void backtrack() &cxxname="spicy::rt::detail::backtrack" &have_pr
declare public void initializeParsedUnit(inout ParsedUnit punit, any unit, TypeInfo ti) &cxxname="spicy::rt::ParsedUnit::initialize" &have_prototype;

declare public bytes extractBytes(inout value_ref<stream> data, view<stream> cur, uint<64> n, bool eod_ok, string location, inout strong_ref<Filters> filters) &cxxname="spicy::rt::detail::extractBytes" &have_prototype;
declare public void expectBytesLiteral(inout value_ref<stream> data, view<stream> cur, bytes literal, string location, inout strong_ref<Filters> filters) &cxxname="spicy::rt::detail::expectBytesLiteral" &have_prototype;
declare public bytes expectBytesLiteral(inout value_ref<stream> data, view<stream> cur, bytes literal, string location, inout strong_ref<Filters> filters) &cxxname="spicy::rt::detail::expectBytesLiteral" &have_prototype;

}
8 changes: 5 additions & 3 deletions spicy/runtime/include/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,11 +553,13 @@ hilti::rt::Bytes extractBytes(hilti::rt::ValueReference<hilti::rt::Stream>& data
* @param literal raw bytes representation of the literal to extract
* @param location location associated with the situation
* @param filters filter state associated with current unit instance (which may be null)
* @returns `literal` (for convenience)
* @throws ParseError if the literal isn't found at the beginning of *cur*
*/
void expectBytesLiteral(hilti::rt::ValueReference<hilti::rt::Stream>& data, const hilti::rt::stream::View& cur,
const hilti::rt::Bytes& literal, std::string_view location,
const hilti::rt::StrongReference<spicy::rt::filter::detail::Filters>& filters);
hilti::rt::Bytes expectBytesLiteral(hilti::rt::ValueReference<hilti::rt::Stream>& data,
const hilti::rt::stream::View& cur, hilti::rt::Bytes literal,
std::string_view location,
const hilti::rt::StrongReference<spicy::rt::filter::detail::Filters>& filters);

} // namespace detail
} // namespace spicy::rt
8 changes: 5 additions & 3 deletions spicy/runtime/src/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,9 @@ hilti::rt::Bytes detail::extractBytes(hilti::rt::ValueReference<hilti::rt::Strea
return cur.sub(cur.begin() + size).data();
}

void detail::expectBytesLiteral(hilti::rt::ValueReference<hilti::rt::Stream>& data, const hilti::rt::stream::View& cur,
const hilti::rt::Bytes& literal, std::string_view location,
const hilti::rt::StrongReference<spicy::rt::filter::detail::Filters>& filters) {
hilti::rt::Bytes detail::expectBytesLiteral(
hilti::rt::ValueReference<hilti::rt::Stream>& data, const hilti::rt::stream::View& cur, hilti::rt::Bytes literal,
std::string_view location, const hilti::rt::StrongReference<spicy::rt::filter::detail::Filters>& filters) {
detail::waitForInput(data, cur, literal.size(),
hilti::rt::fmt("expected %" PRIu64 R"( bytes for bytes literal "%s")", literal.size(),
literal),
Expand All @@ -212,4 +212,6 @@ void detail::expectBytesLiteral(hilti::rt::ValueReference<hilti::rt::Stream>& da
throw ParseError(hilti::rt::fmt(R"(expected bytes literal "%s" but input starts with "%s")", literal, content),
location);
}

return literal;
}
2 changes: 1 addition & 1 deletion spicy/runtime/src/tests/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ TEST_CASE("expectBytesLiteral") {
data->freeze();
auto view = data->view();

CHECK_NOTHROW(detail::expectBytesLiteral(data, data->view(), "123"_b, "<location>", {}));
CHECK_EQ(detail::expectBytesLiteral(data, data->view(), "123"_b, "<location>", {}), "123"_b);
CHECK_THROWS_WITH_AS(detail::expectBytesLiteral(data, data->view(), "abc"_b, "<location>", {}),
"expected bytes literal \"abc\" but input starts with \"123\" (<location>)",
const spicy::rt::ParseError&);
Expand Down
29 changes: 18 additions & 11 deletions spicy/toolchain/src/compiler/codegen/parsers/literals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,32 +89,39 @@ struct Visitor : public visitor::PreOrder {
pb()->parseError("unexpected token to consume", n->meta());
popBuilder();

pushBuilder(
builder()->addIf(builder()->unequal(builder()->expression(n),
builder()->memberCall(state().cur, "sub",
{builder()->begin(state().cur),
state().lahead_end}))));
auto literal = builder()->addTmp("literal", builder()->expression(n));

pushBuilder(builder()->addIf(
builder()->unequal(literal, builder()->memberCall(state().cur, "sub",
{builder()->begin(state().cur),
state().lahead_end}))));
pb()->parseError("unexpected data when consuming token", n->meta());
popBuilder();

builder()->addAssign(lp->destination(n->type()->type()), literal);

pb()->consumeLookAhead();
popBuilder();

pushBuilder(no_lah);
}

builder()->addCall("spicy_rt::expectBytesLiteral",
{state().data, state().cur, builder()->expression(n),
builder()->expression(n->meta()), pb()->currentFilters(state())});
auto expect_bytes_literal =
builder()->call("spicy_rt::expectBytesLiteral",
{state().data, state().cur, builder()->expression(n),
builder()->expression(n->meta()), pb()->currentFilters(state())});


if ( state().literal_mode != LiteralMode::Skip )
builder()->addAssign(lp->destination(n->type()->type()), expect_bytes_literal);
else
builder()->addExpression(expect_bytes_literal);

pb()->advanceInput(len);

if ( check_for_look_ahead )
popBuilder();

if ( state().literal_mode != LiteralMode::Skip )
builder()->addAssign(lp->destination(n->type()->type()), builder()->expression(n));

result = builder()->expression(n);
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
[debug/resolver] [spicy_rt.hlt:92:33-92:71] Attribute "&cxxname="spicy::rt::detail::backtrack"" -> Attribute "&cxxname="::spicy::rt::detail::backtrack""
[debug/resolver] [spicy_rt.hlt:94:89-94:132] Attribute "&cxxname="spicy::rt::ParsedUnit::initialize"" -> Attribute "&cxxname="::spicy::rt::ParsedUnit::initialize""
[debug/resolver] [spicy_rt.hlt:96:160-96:201] Attribute "&cxxname="spicy::rt::detail::extractBytes"" -> Attribute "&cxxname="::spicy::rt::detail::extractBytes""
[debug/resolver] [spicy_rt.hlt:97:155-97:202] Attribute "&cxxname="spicy::rt::detail::expectBytesLiteral"" -> Attribute "&cxxname="::spicy::rt::detail::expectBytesLiteral""
[debug/resolver] [spicy_rt.hlt:97:156-97:203] Attribute "&cxxname="spicy::rt::detail::expectBytesLiteral"" -> Attribute "&cxxname="::spicy::rt::detail::expectBytesLiteral""
[debug/resolver] [spicy.spicy:14:3-14:37] Attribute "&cxxname="hilti::rt::AddressFamily"" -> Attribute "&cxxname="::hilti::rt::AddressFamily""
[debug/resolver] [spicy.spicy:23:3-23:41] Attribute "&cxxname="hilti::rt::integer::BitOrder"" -> Attribute "&cxxname="::hilti::rt::integer::BitOrder""
[debug/resolver] [spicy.spicy:31:3-31:33] Attribute "&cxxname="hilti::rt::ByteOrder"" -> Attribute "&cxxname="::hilti::rt::ByteOrder""
Expand Down
18 changes: 15 additions & 3 deletions tests/Baseline/spicy.types.unit.canonical-ids-with-import/output
Original file line number Diff line number Diff line change
Expand Up @@ -990,9 +990,8 @@
[debug/ast-declarations] - Parameter "__lahe" (a::__lahe_3)
[debug/ast-declarations] - Parameter "__error" (a::__error_4)
[debug/ast-declarations] - LocalVariable "__result" (a::__result)
[debug/ast-declarations] - LocalVariable "__begin" (a::__begin_5)
[debug/ast-declarations] - LocalVariable "filtered" (a::filtered)
[debug/ast-declarations] - Parameter "__except" (a::__except_2)
[debug/ast-declarations] - LocalVariable "__begin" (a::__begin_5)
[debug/ast-declarations] - LocalVariable "filtered" (a::filtered)
[debug/ast-declarations] - Function "a::X::__parse_a__X_stage2" (a::a::X::__parse_a__X_stage2)
[debug/ast-declarations] - Parameter "__data" (a::__data_7)
[debug/ast-declarations] - Parameter "__begin" (a::__begin_6)
Expand Down Expand Up @@ -1281,6 +1280,19 @@
[debug/ast-declarations] - Parameter "punit" (spicy_rt::punit)
[debug/ast-declarations] - Parameter "unit" (spicy_rt::unit_9)
[debug/ast-declarations] - Parameter "ti" (spicy_rt::ti_3)
[debug/ast-declarations] - Function "extractBytes" (spicy_rt::extractBytes)
[debug/ast-declarations] - Parameter "data" (spicy_rt::data_10)
[debug/ast-declarations] - Parameter "cur" (spicy_rt::cur_9)
[debug/ast-declarations] - Parameter "n" (spicy_rt::n_3)
[debug/ast-declarations] - Parameter "eod_ok" (spicy_rt::eod_ok)
[debug/ast-declarations] - Parameter "location" (spicy_rt::location_3)
[debug/ast-declarations] - Parameter "filters" (spicy_rt::filters_7)
[debug/ast-declarations] - Function "expectBytesLiteral" (spicy_rt::expectBytesLiteral)
[debug/ast-declarations] - Parameter "data" (spicy_rt::data_11)
[debug/ast-declarations] - Parameter "cur" (spicy_rt::cur_10)
[debug/ast-declarations] - Parameter "literal" (spicy_rt::literal)
[debug/ast-declarations] - Parameter "location" (spicy_rt::location_4)
[debug/ast-declarations] - Parameter "filters" (spicy_rt::filters_8)
[debug/ast-declarations] - Module "spicy" (spicy)
[debug/ast-declarations] - Property "%skip-implementation" (spicy::%skip-implementation)
[debug/ast-declarations] - Type "AddressFamily" (spicy::AddressFamily)
Expand Down
23 changes: 17 additions & 6 deletions tests/Baseline/spicy.types.unit.canonical-ids/output
Original file line number Diff line number Diff line change
Expand Up @@ -1131,9 +1131,8 @@
[debug/ast-declarations] - Parameter "__lahe" (DNS::__lahe_5)
[debug/ast-declarations] - Parameter "__error" (DNS::__error_7)
[debug/ast-declarations] - LocalVariable "__result" (DNS::__result)
[debug/ast-declarations] - LocalVariable "__begin" (DNS::__begin_8)
[debug/ast-declarations] - LocalVariable "filtered" (DNS::filtered)
[debug/ast-declarations] - Parameter "__except" (DNS::__except_3)
[debug/ast-declarations] - LocalVariable "__begin" (DNS::__begin_8)
[debug/ast-declarations] - LocalVariable "filtered" (DNS::filtered)
[debug/ast-declarations] - Function "DNS::Label::__parse_DNS__Label_stage2" (DNS::DNS::Label::__parse_DNS__Label_stage2)
[debug/ast-declarations] - Parameter "__data" (DNS::__data_12)
[debug/ast-declarations] - Parameter "__begin" (DNS::__begin_9)
Expand Down Expand Up @@ -1161,9 +1160,8 @@
[debug/ast-declarations] - Parameter "__lahe" (DNS::__lahe_7)
[debug/ast-declarations] - Parameter "__error" (DNS::__error_12)
[debug/ast-declarations] - LocalVariable "__result" (DNS::__result_3)
[debug/ast-declarations] - LocalVariable "__begin" (DNS::__begin_11)
[debug/ast-declarations] - LocalVariable "filtered" (DNS::filtered_2)
[debug/ast-declarations] - Parameter "__except" (DNS::__except_4)
[debug/ast-declarations] - LocalVariable "__begin" (DNS::__begin_11)
[debug/ast-declarations] - LocalVariable "filtered" (DNS::filtered_2)
[debug/ast-declarations] - Function "DNS::Pointer::__parse_DNS__Pointer_2_stage2" (DNS::DNS::Pointer::__parse_DNS__Pointer_2_stage2)
[debug/ast-declarations] - Parameter "__data" (DNS::__data_17)
[debug/ast-declarations] - Parameter "__begin" (DNS::__begin_12)
Expand Down Expand Up @@ -1416,6 +1414,19 @@
[debug/ast-declarations] - Parameter "punit" (spicy_rt::punit)
[debug/ast-declarations] - Parameter "unit" (spicy_rt::unit_9)
[debug/ast-declarations] - Parameter "ti" (spicy_rt::ti_3)
[debug/ast-declarations] - Function "extractBytes" (spicy_rt::extractBytes)
[debug/ast-declarations] - Parameter "data" (spicy_rt::data_10)
[debug/ast-declarations] - Parameter "cur" (spicy_rt::cur_9)
[debug/ast-declarations] - Parameter "n" (spicy_rt::n_3)
[debug/ast-declarations] - Parameter "eod_ok" (spicy_rt::eod_ok)
[debug/ast-declarations] - Parameter "location" (spicy_rt::location_3)
[debug/ast-declarations] - Parameter "filters" (spicy_rt::filters_7)
[debug/ast-declarations] - Function "expectBytesLiteral" (spicy_rt::expectBytesLiteral)
[debug/ast-declarations] - Parameter "data" (spicy_rt::data_11)
[debug/ast-declarations] - Parameter "cur" (spicy_rt::cur_10)
[debug/ast-declarations] - Parameter "literal" (spicy_rt::literal)
[debug/ast-declarations] - Parameter "location" (spicy_rt::location_4)
[debug/ast-declarations] - Parameter "filters" (spicy_rt::filters_8)
[debug/ast-declarations] - Module "spicy" (spicy)
[debug/ast-declarations] - Property "%skip-implementation" (spicy::%skip-implementation)
[debug/ast-declarations] - Type "AddressFamily" (spicy::AddressFamily)
Expand Down
Loading

0 comments on commit 1278d63

Please sign in to comment.