Commit c1e33ebf authored by Kenton Varda's avatar Kenton Varda

Groups WIP

parent 608d7ed7
...@@ -898,17 +898,18 @@ private: ...@@ -898,17 +898,18 @@ private:
kj::strTree( kj::strTree(
makeReaderDef(fullName, titleCase, "unionString", kj::strTree( makeReaderDef(fullName, titleCase, "unionString", kj::strTree(
"inline Which which() const;\n", " inline Which which() const;\n",
kj::mv(subText.readerMethodDecls))), kj::mv(subText.readerMethodDecls))),
makeBuilderDef(fullName, titleCase, "unionString", kj::strTree( makeBuilderDef(fullName, titleCase, "unionString", kj::strTree(
"inline Which which();\n", " inline Which which();\n",
kj::mv(subText.builderMethodDecls)))), kj::mv(subText.builderMethodDecls))),
kj::mv(subText.innerTypeReaderBuilderDefs)),
kj::strTree( kj::strTree(
"inline ", titleCase, "::Reader get", titleCase, "() const;\n"), " inline ", titleCase, "::Reader get", titleCase, "() const;\n"),
kj::strTree( kj::strTree(
"inline ", titleCase, "::Builder get", titleCase, "();\n"), " inline ", titleCase, "::Builder get", titleCase, "();\n"),
kj::strTree( kj::strTree(
"inline ", fullName, "::Reader ", containingType, "::Reader::get", titleCase, "() const {\n" "inline ", fullName, "::Reader ", containingType, "::Reader::get", titleCase, "() const {\n"
...@@ -955,7 +956,7 @@ private: ...@@ -955,7 +956,7 @@ private:
" class Reader;\n" " class Reader;\n"
" class Builder;\n", " class Builder;\n",
kj::mv(subText.innerTypeDecls), kj::mv(subText.innerTypeDecls),
"}\n" "};\n"
"\n", "\n",
kj::mv(subText.innerTypeDefs)), kj::mv(subText.innerTypeDefs)),
...@@ -963,13 +964,14 @@ private: ...@@ -963,13 +964,14 @@ private:
makeReaderDef(fullName, titleCase, "groupString", makeReaderDef(fullName, titleCase, "groupString",
kj::mv(subText.readerMethodDecls)), kj::mv(subText.readerMethodDecls)),
makeBuilderDef(fullName, titleCase, "groupString", makeBuilderDef(fullName, titleCase, "groupString",
kj::mv(subText.builderMethodDecls))), kj::mv(subText.builderMethodDecls)),
kj::mv(subText.innerTypeReaderBuilderDefs)),
kj::strTree( kj::strTree(
"inline ", titleCase, "::Reader get", titleCase, "() const;\n"), " inline ", titleCase, "::Reader get", titleCase, "() const;\n"),
kj::strTree( kj::strTree(
"inline ", titleCase, "::Builder get", titleCase, "();\n"), " inline ", titleCase, "::Builder get", titleCase, "();\n"),
kj::strTree( kj::strTree(
"inline ", fullName, "::Reader ", containingType, "::Reader::get", titleCase, "() const {\n" "inline ", fullName, "::Reader ", containingType, "::Reader::get", titleCase, "() const {\n"
...@@ -980,8 +982,15 @@ private: ...@@ -980,8 +982,15 @@ private:
"}\n", "}\n",
kj::mv(subText.inlineMethodDefs)), kj::mv(subText.inlineMethodDefs)),
kj::mv(subText.capnpPrivateDecls), kj::strTree(
kj::mv(subText.capnpPrivateDefs), "CAPNP_DECLARE_GROUP(\n"
" ", namespace_, "::", fullName, ",\n"
" ", namespace_, "::", containingType, ", ", member.getIndex(), ");\n",
kj::mv(subText.capnpPrivateDecls)),
kj::strTree(
"CAPNP_DEFINE_GROUP(\n"
" ", namespace_, "::", fullName, ");\n",
kj::mv(subText.capnpPrivateDefs)),
}; };
} }
} }
......
...@@ -723,11 +723,13 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, const ErrorReporter& errorRep ...@@ -723,11 +723,13 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, const ErrorReporter& errorRep
})); }));
parsers.groupDecl = arena.copy(p::transform( parsers.groupDecl = arena.copy(p::transform(
p::sequence(keyword("group"), p::many(parsers.annotation)), p::sequence(identifier, keyword("group"), p::many(parsers.annotation)),
[this](kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations) [this](Located<Text::Reader>&& name,
kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
-> DeclParserResult { -> DeclParserResult {
auto decl = orphanage.newOrphan<Declaration>(); auto decl = orphanage.newOrphan<Declaration>();
auto builder = decl.get(); auto builder = decl.get();
name.copyTo(builder.getName());
builder.getId().setUnspecified(); builder.getId().setUnspecified();
auto list = builder.initAnnotations(annotations.size()); auto list = builder.initAnnotations(annotations.size());
for (uint i = 0; i < annotations.size(); i++) { for (uint i = 0; i < annotations.size(); i++) {
......
...@@ -160,6 +160,32 @@ private: ...@@ -160,6 +160,32 @@ private:
// Nothing needs validation. // Nothing needs validation.
} }
uint countOrdinals(const List<schema::StructNode::Member>::Reader& members) {
uint result = 0;
for (auto member: members) {
switch (member.getBody().which()) {
case schema::StructNode::Member::Body::FIELD_MEMBER:
++result;
break;
case schema::StructNode::Member::Body::UNION_MEMBER: {
auto uMembers = member.getBody().getUnionMember().getMembers();
if (uMembers.size() == 0 || member.getOrdinal() != uMembers[0].getOrdinal()) {
// Union has explicit ordinal.
++result;
}
result += countOrdinals(uMembers);
break;
}
case schema::StructNode::Member::Body::GROUP_MEMBER:
result += countOrdinals(member.getBody().getGroupMember().getMembers());
break;
}
}
return result;
}
void validate(const schema::StructNode::Reader& structNode) { void validate(const schema::StructNode::Reader& structNode) {
uint dataSizeInBits; uint dataSizeInBits;
uint pointerCount; uint pointerCount;
...@@ -208,15 +234,8 @@ private: ...@@ -208,15 +234,8 @@ private:
structNode.getPointerSectionSize() == pointerCount, structNode.getPointerSectionSize() == pointerCount,
"Struct size does not match preferredListEncoding."); "Struct size does not match preferredListEncoding.");
uint ordinalCount = 0;
auto members = structNode.getMembers(); auto members = structNode.getMembers();
for (auto member: members) { uint ordinalCount = countOrdinals(members);
++ordinalCount;
if (member.getBody().which() == schema::StructNode::Member::Body::UNION_MEMBER) {
ordinalCount += member.getBody().getUnionMember().getMembers().size();
}
}
KJ_STACK_ARRAY(bool, sawCodeOrder, members.size(), 32, 256); KJ_STACK_ARRAY(bool, sawCodeOrder, members.size(), 32, 256);
memset(sawCodeOrder.begin(), 0, sawCodeOrder.size() * sizeof(sawCodeOrder[0])); memset(sawCodeOrder.begin(), 0, sawCodeOrder.size() * sizeof(sawCodeOrder[0]));
...@@ -282,8 +301,8 @@ private: ...@@ -282,8 +301,8 @@ private:
for (auto uMember: uMembers) { for (auto uMember: uMembers) {
KJ_CONTEXT("validating union member", uMember.getName()); KJ_CONTEXT("validating union member", uMember.getName());
VALIDATE_SCHEMA( VALIDATE_SCHEMA(
uMember.getBody().which() == schema::StructNode::Member::Body::FIELD_MEMBER, uMember.getBody().which() != schema::StructNode::Member::Body::UNION_MEMBER,
"Union members must be fields."); "Union members must be fields or groups.");
uint subScopeOrdinal; uint subScopeOrdinal;
uint indexAdjustment; uint indexAdjustment;
...@@ -308,6 +327,32 @@ private: ...@@ -308,6 +327,32 @@ private:
} }
break; break;
} }
case schema::StructNode::Member::Body::GROUP_MEMBER: {
auto g = member.getBody().getGroupMember();
auto gMembers = g.getMembers();
VALIDATE_SCHEMA(gMembers.size() >= 2, "Group must have at least two members.");
KJ_STACK_ARRAY(bool, uSawCodeOrder, gMembers.size(), 32, 256);
memset(uSawCodeOrder.begin(), 0, uSawCodeOrder.size() * sizeof(uSawCodeOrder[0]));
uint subIndex = 0;
for (auto gMember: gMembers) {
KJ_CONTEXT("validating group member", gMember.getName());
VALIDATE_SCHEMA(
gMember.getBody().which() != schema::StructNode::Member::Body::GROUP_MEMBER,
"Group members must be fields or unions.");
validate(gMember, uSawCodeOrder, sawOrdinal, dataSizeInBits, pointerCount,
member.getOrdinal() + 1, gMembers.size(), subIndex++);
}
// Group ordinal must match the ordinal of its first member.
VALIDATE_SCHEMA(member.getOrdinal() == gMembers[0].getOrdinal(),
"Invalid ordinal.", member.getOrdinal());
break;
}
} }
} }
...@@ -656,6 +701,25 @@ private: ...@@ -656,6 +701,25 @@ private:
replacementIsOlder(); replacementIsOlder();
} }
for (uint i = 0; i < count; i++) {
checkCompatibility(members[i], replacementMembers[i]);
}
break;
}
case schema::StructNode::Member::Body::GROUP_MEMBER: {
auto existingGroup = member.getBody().getGroupMember();
auto replacementGroup = replacement.getBody().getGroupMember();
auto members = existingGroup.getMembers();
auto replacementMembers = replacementGroup.getMembers();
uint count = std::min(members.size(), replacementMembers.size());
if (replacementMembers.size() > members.size()) {
replacementIsNewer();
} else if (replacementMembers.size() < members.size()) {
replacementIsOlder();
}
for (uint i = 0; i < count; i++) { for (uint i = 0; i < count; i++) {
checkCompatibility(members[i], replacementMembers[i]); checkCompatibility(members[i], replacementMembers[i]);
} }
......
...@@ -269,6 +269,26 @@ struct TestUnnamedUnion { ...@@ -269,6 +269,26 @@ struct TestUnnamedUnion {
after @4 :Text; after @4 :Text;
} }
struct TestGroups {
groups union {
foo group {
fooCorge @0 :Int32;
fooGrault @2 :Int64;
bazGarply @8 :Text;
}
bar group {
barCorge @3 :Int32;
barGrault @4 :Text;
barGarply @5 :Int64;
}
baz group {
bazCorge @1 :Int32;
bazGrault @6 :Text;
bazGarply @7 :Text;
}
}
}
struct TestUnionDefaults { struct TestUnionDefaults {
s16s8s64s8Set @0 :TestUnion = s16s8s64s8Set @0 :TestUnion =
(union0 = u0f0s16(321), union1 = u1f0s8(123), union2 = u2f0s64(12345678901234567), (union0 = u0f0s16(321), union1 = u1f0s8(123), union2 = u2f0s64(12345678901234567),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment