Commit 0c7c610c authored by Kenton Varda's avatar Kenton Varda

More WIP.

parent 1dcb66b1
...@@ -59,52 +59,46 @@ static constexpr const char* FIELD_SIZE_NAMES[] = { ...@@ -59,52 +59,46 @@ static constexpr const char* FIELD_SIZE_NAMES[] = {
"VOID", "BIT", "BYTE", "TWO_BYTES", "FOUR_BYTES", "EIGHT_BYTES", "POINTER", "INLINE_COMPOSITE" "VOID", "BIT", "BYTE", "TWO_BYTES", "FOUR_BYTES", "EIGHT_BYTES", "POINTER", "INLINE_COMPOSITE"
}; };
void enumerateDeps(schema::Type::Reader type, std::set<uint64_t>& deps) { void enumerateDeps(schema2::Type::Reader type, std::set<uint64_t>& deps) {
switch (type.getBody().which()) { switch (type.which()) {
case schema::Type::Body::STRUCT_TYPE: case schema2::Type::STRUCT:
deps.insert(type.getBody().getStructType()); deps.insert(type.getStruct());
break; break;
case schema::Type::Body::ENUM_TYPE: case schema2::Type::ENUM:
deps.insert(type.getBody().getEnumType()); deps.insert(type.getEnum());
break; break;
case schema::Type::Body::INTERFACE_TYPE: case schema2::Type::INTERFACE:
deps.insert(type.getBody().getInterfaceType()); deps.insert(type.getInterface());
break; break;
case schema::Type::Body::LIST_TYPE: case schema2::Type::LIST:
enumerateDeps(type.getBody().getListType(), deps); enumerateDeps(type.getList(), deps);
break; break;
default: default:
break; break;
} }
} }
void enumerateDeps(schema::StructNode::Member::Reader member, std::set<uint64_t>& deps) { void enumerateDeps(schema2::Node::Reader node, std::set<uint64_t>& deps) {
switch (member.getBody().which()) { switch (node.which()) {
case schema::StructNode::Member::Body::FIELD_MEMBER: case schema2::Node::STRUCT: {
enumerateDeps(member.getBody().getFieldMember().getType(), deps); auto structNode = node.getStruct();
break; for (auto field: structNode.getFields()) {
case schema::StructNode::Member::Body::UNION_MEMBER: switch (field.which()) {
for (auto subMember: member.getBody().getUnionMember().getMembers()) { case schema2::Field::REGULAR:
enumerateDeps(subMember, deps); enumerateDeps(field.getRegular().getType(), deps);
} break;
break; case schema2::Field::GROUP:
case schema::StructNode::Member::Body::GROUP_MEMBER: deps.insert(field.getGroup());
for (auto subMember: member.getBody().getGroupMember().getMembers()) { break;
enumerateDeps(subMember, deps); }
} }
break; if (structNode.getIsGroup()) {
} deps.insert(node.getScopeId());
}
void enumerateDeps(schema::Node::Reader node, std::set<uint64_t>& deps) {
switch (node.getBody().which()) {
case schema::Node::Body::STRUCT_NODE:
for (auto member: node.getBody().getStructNode().getMembers()) {
enumerateDeps(member, deps);
} }
break; break;
case schema::Node::Body::INTERFACE_NODE: }
for (auto method: node.getBody().getInterfaceNode().getMethods()) { case schema2::Node::INTERFACE:
for (auto method: node.getInterface()) {
for (auto param: method.getParams()) { for (auto param: method.getParams()) {
enumerateDeps(param.getType(), deps); enumerateDeps(param.getType(), deps);
} }
...@@ -119,92 +113,15 @@ void enumerateDeps(schema::Node::Reader node, std::set<uint64_t>& deps) { ...@@ -119,92 +113,15 @@ void enumerateDeps(schema::Node::Reader node, std::set<uint64_t>& deps) {
struct OrderByName { struct OrderByName {
template <typename T> template <typename T>
inline bool operator()(const T& a, const T& b) const { inline bool operator()(const T& a, const T& b) const {
return a.member.getProto().getName() < b.member.getProto().getName(); return a.getProto().getName() < b.getProto().getName();
}
};
template <typename MemberList>
void makeMemberInfoTable(uint parent, MemberList&& members,
kj::Vector<capnp::_::RawSchema::MemberInfo>& info);
void makeSubMemberInfoTable(const StructSchema::Member& member,
kj::Vector<capnp::_::RawSchema::MemberInfo>& info) {
switch (member.getProto().getBody().which()) {
case schema::StructNode::Member::Body::FIELD_MEMBER:
break;
case schema::StructNode::Member::Body::UNION_MEMBER:
// Only create a sub-table if the union is named.
if (member.getProto().getName().size() > 0) {
makeMemberInfoTable(1 + member.getProto().getOrdinal(),
member.asUnion().getMembers(), info);
}
break;
case schema::StructNode::Member::Body::GROUP_MEMBER:
makeMemberInfoTable(1 + member.getProto().getOrdinal(), member.asGroup().getMembers(), info);
break;
} }
}
void makeSubMemberInfoTable(const EnumSchema::Enumerant& member,
kj::Vector<capnp::_::RawSchema::MemberInfo>& info) {}
void makeSubMemberInfoTable(const InterfaceSchema::Method& member,
kj::Vector<capnp::_::RawSchema::MemberInfo>& info) {}
template <typename Member>
struct MemberAndIndex {
Member member;
uint index;
MemberAndIndex(Member member): member(member), index(member.getIndex()) {}
MemberAndIndex(Member member, uint index): member(member), index(index) {}
}; };
void enumerateScope(const StructSchema::MemberList& members,
kj::Vector<MemberAndIndex<StructSchema::Member>>& vec,
uint offset = 0) {
// Given a member list, flatten all members of the scope into one vector. This basically means
// copying all the members to the vector, except that unnamed unions are flattened, with their
// members' indexes being offset by the size of the parent scope.
for (auto member: members) {
vec.add(member, member.getIndex() + offset);
if (member.getProto().getName().size() == 0) {
// Flatten unnamed union.
enumerateScope(member.asUnion().getMembers(), vec, offset + members.size());
}
}
}
void enumerateScope(const EnumSchema::EnumerantList& members,
kj::Vector<MemberAndIndex<EnumSchema::Enumerant>>& vec) {
for (auto member: members) {
vec.add(member);
}
}
void enumerateScope(const InterfaceSchema::MethodList& members,
kj::Vector<MemberAndIndex<InterfaceSchema::Method>>& vec) {
for (auto member: members) {
vec.add(member);
}
}
template <typename MemberList> template <typename MemberList>
void makeMemberInfoTable(uint parent, MemberList&& members, kj::Array<uint> makeMembersByName(MemberList&& members) {
kj::Vector<capnp::_::RawSchema::MemberInfo>& info) { auto sorted = KJ_MAP(members, member) { return member; };
kj::Vector<MemberAndIndex<decltype(members[0])>> sorted(members.size());
enumerateScope(members, sorted);
std::sort(sorted.begin(), sorted.end(), OrderByName()); std::sort(sorted.begin(), sorted.end(), OrderByName());
return KJ_MAP(sorted, member) { return member.getIndex(); };
for (auto& member: sorted) {
info.add(capnp::_::RawSchema::MemberInfo {
kj::implicitCast<uint16_t>(parent),
kj::implicitCast<uint16_t>(member.index)
});
}
for (auto member: members) {
makeSubMemberInfoTable(member, info);
}
} }
kj::StringPtr baseName(kj::StringPtr path) { kj::StringPtr baseName(kj::StringPtr path) {
...@@ -242,7 +159,7 @@ private: ...@@ -242,7 +159,7 @@ private:
usedImports.insert(node.getId()); usedImports.insert(node.getId());
for (auto annotation: node.getAnnotations()) { for (auto annotation: node.getAnnotations()) {
if (annotation.getId() == NAMESPACE_ANNOTATION_ID) { if (annotation.getId() == NAMESPACE_ANNOTATION_ID) {
return kj::strTree(" ::", annotation.getValue().getBody().getTextValue()); return kj::strTree(" ::", annotation.getValue().getText());
} }
} }
return kj::strTree(" "); return kj::strTree(" ");
...@@ -284,36 +201,36 @@ private: ...@@ -284,36 +201,36 @@ private:
return kj::mv(result); return kj::mv(result);
} }
kj::StringTree typeName(schema::Type::Reader type) { kj::StringTree typeName(schema2::Type::Reader type) {
switch (type.getBody().which()) { switch (type.which()) {
case schema::Type::Body::VOID_TYPE: return kj::strTree(" ::capnp::Void"); case schema2::Type::VOID: return kj::strTree(" ::capnp::Void");
case schema::Type::Body::BOOL_TYPE: return kj::strTree("bool"); case schema2::Type::BOOL: return kj::strTree("bool");
case schema::Type::Body::INT8_TYPE: return kj::strTree(" ::int8_t"); case schema2::Type::INT8: return kj::strTree(" ::int8_t");
case schema::Type::Body::INT16_TYPE: return kj::strTree(" ::int16_t"); case schema2::Type::INT16: return kj::strTree(" ::int16_t");
case schema::Type::Body::INT32_TYPE: return kj::strTree(" ::int32_t"); case schema2::Type::INT32: return kj::strTree(" ::int32_t");
case schema::Type::Body::INT64_TYPE: return kj::strTree(" ::int64_t"); case schema2::Type::INT64: return kj::strTree(" ::int64_t");
case schema::Type::Body::UINT8_TYPE: return kj::strTree(" ::uint8_t"); case schema2::Type::UINT8: return kj::strTree(" ::uint8_t");
case schema::Type::Body::UINT16_TYPE: return kj::strTree(" ::uint16_t"); case schema2::Type::UINT16: return kj::strTree(" ::uint16_t");
case schema::Type::Body::UINT32_TYPE: return kj::strTree(" ::uint32_t"); case schema2::Type::UINT32: return kj::strTree(" ::uint32_t");
case schema::Type::Body::UINT64_TYPE: return kj::strTree(" ::uint64_t"); case schema2::Type::UINT64: return kj::strTree(" ::uint64_t");
case schema::Type::Body::FLOAT32_TYPE: return kj::strTree("float"); case schema2::Type::FLOAT32: return kj::strTree("float");
case schema::Type::Body::FLOAT64_TYPE: return kj::strTree("double"); case schema2::Type::FLOAT64: return kj::strTree("double");
case schema::Type::Body::TEXT_TYPE: return kj::strTree(" ::capnp::Text"); case schema2::Type::TEXT: return kj::strTree(" ::capnp::Text");
case schema::Type::Body::DATA_TYPE: return kj::strTree(" ::capnp::Data"); case schema2::Type::DATA: return kj::strTree(" ::capnp::Data");
case schema::Type::Body::ENUM_TYPE: case schema2::Type::ENUM:
return cppFullName(schemaLoader.get(type.getBody().getEnumType())); return cppFullName(schemaLoader.get(type.getEnum()));
case schema::Type::Body::STRUCT_TYPE: case schema2::Type::STRUCT:
return cppFullName(schemaLoader.get(type.getBody().getStructType())); return cppFullName(schemaLoader.get(type.getStruct()));
case schema::Type::Body::INTERFACE_TYPE: case schema2::Type::INTERFACE:
return cppFullName(schemaLoader.get(type.getBody().getInterfaceType())); return cppFullName(schemaLoader.get(type.getInterface()));
case schema::Type::Body::LIST_TYPE: case schema2::Type::LIST:
return kj::strTree(" ::capnp::List<", typeName(type.getBody().getListType()), ">"); return kj::strTree(" ::capnp::List<", typeName(type.getList()), ">");
case schema::Type::Body::OBJECT_TYPE: case schema2::Type::OBJECT:
// Not used. // Not used.
return kj::strTree(); return kj::strTree();
} }
...@@ -329,29 +246,19 @@ private: ...@@ -329,29 +246,19 @@ private:
DiscriminantChecks makeDiscriminantChecks(kj::StringPtr scope, DiscriminantChecks makeDiscriminantChecks(kj::StringPtr scope,
kj::StringPtr memberName, kj::StringPtr memberName,
StructSchema::Union containingUnion) { StructSchema containingStruct) {
auto unionProto = containingUnion.getProto(); auto discrimOffset = containingStruct.getProto().getStruct().getDiscriminantOffset();
kj::StringPtr unionScope;
kj::String ownUnionScope;
if (unionProto.getName().size() > 0) {
ownUnionScope = kj::str(toTitleCase(unionProto.getName()), "::");
unionScope = ownUnionScope;
} else {
// Anonymous union.
unionScope = scope;
}
auto discrimOffset = unionProto.getBody().getUnionMember().getDiscriminantOffset();
kj::String upperCase = toUpperCase(memberName); kj::String upperCase = toUpperCase(memberName);
return DiscriminantChecks { return DiscriminantChecks {
kj::str( kj::str(
" KJ_IREQUIRE(which() == ", unionScope, upperCase, ",\n" " KJ_IREQUIRE(which() == ", scope, upperCase, ",\n"
" \"Must check which() before get()ing a union member.\");\n"), " \"Must check which() before get()ing a union member.\");\n"),
kj::str( kj::str(
" _builder.setDataField<", unionScope, "Which>(\n" " _builder.setDataField<", scope, "Which>(\n"
" ", discrimOffset, " * ::capnp::ELEMENTS, ", " ", discrimOffset, " * ::capnp::ELEMENTS, ",
unionScope, upperCase, ");\n") scope, upperCase, ");\n")
}; };
} }
...@@ -372,31 +279,71 @@ private: ...@@ -372,31 +279,71 @@ private:
OBJECT OBJECT
}; };
FieldText makeFieldText(kj::StringPtr scope, StructSchema::Field member) { FieldText makeFieldText(kj::StringPtr scope, StructSchema::Field field) {
auto proto = member.getProto(); auto proto = field.getProto();
auto field = proto.getBody().getFieldMember(); kj::String titleCase = toTitleCase(proto.getName());
DiscriminantChecks unionDiscrim;
if (proto.hasDiscriminantValue()) {
unionDiscrim = makeDiscriminantChecks(scope, proto.getName(), field.getContainingStruct());
}
switch (proto.which()) {
case schema2::Field::REGULAR:
// Continue below.
break;
case schema2::Field::GROUP:
return FieldText {
kj::strTree(
" inline ", titleCase, "::Reader get", titleCase, "() const;\n"
"\n"),
kj::strTree(
" inline ", titleCase, "::Builder get", titleCase, "();\n"
" inline ", titleCase, "::Builder init", titleCase, "();\n"
"\n"),
kj::strTree(
"inline ", scope, titleCase, "::Reader ", scope, "Reader::get", titleCase, "() const {\n",
unionDiscrim.check,
" return ", scope, titleCase, "::Reader(_reader);\n"
"}\n"
"inline ", scope, titleCase, "::Builder ", scope, "Builder::get", titleCase, "() {\n",
unionDiscrim.check,
" return ", scope, titleCase, "::Builder(_builder);\n"
"}\n"
"inline ", scope, titleCase, "::Builder ", scope, "Builder::init", titleCase, "() {\n",
unionDiscrim.set,
// TODO(soon): Zero out fields.
" return ", scope, titleCase, "::Builder(_builder);\n"
"}\n")
};
}
auto regularField = proto.getRegular();
FieldKind kind; FieldKind kind;
kj::String ownedType; kj::String ownedType;
kj::String type = typeName(field.getType()).flatten(); kj::String type = typeName(regularField.getType()).flatten();
kj::StringPtr setterDefault; // only for void kj::StringPtr setterDefault; // only for void
kj::String defaultMask; // primitives only kj::String defaultMask; // primitives only
size_t defaultOffset = 0; // pointers only: offset of the default value within the schema. size_t defaultOffset = 0; // pointers only: offset of the default value within the schema.
size_t defaultSize = 0; // blobs only: byte size of the default value. size_t defaultSize = 0; // blobs only: byte size of the default value.
auto typeBody = field.getType().getBody(); auto typeBody = regularField.getType();
auto defaultBody = field.getDefaultValue().getBody(); auto defaultBody = regularField.getDefaultValue();
switch (typeBody.which()) { switch (typeBody.which()) {
case schema::Type::Body::VOID_TYPE: case schema2::Type::VOID:
kind = FieldKind::PRIMITIVE; kind = FieldKind::PRIMITIVE;
setterDefault = " = ::capnp::Void::VOID"; setterDefault = " = ::capnp::Void::VOID";
break; break;
#define HANDLE_PRIMITIVE(discrim, typeName, defaultName, suffix) \ #define HANDLE_PRIMITIVE(discrim, typeName, defaultName, suffix) \
case schema::Type::Body::discrim##_TYPE: \ case schema2::Type::discrim: \
kind = FieldKind::PRIMITIVE; \ kind = FieldKind::PRIMITIVE; \
if (defaultBody.get##defaultName##Value() != 0) { \ if (defaultBody.get##defaultName() != 0) { \
defaultMask = kj::str(defaultBody.get##defaultName##Value(), #suffix); \ defaultMask = kj::str(defaultBody.get##defaultName(), #suffix); \
} \ } \
break; break;
...@@ -411,69 +358,69 @@ private: ...@@ -411,69 +358,69 @@ private:
HANDLE_PRIMITIVE(UINT64, ::uint64_t, Uint64, ull); HANDLE_PRIMITIVE(UINT64, ::uint64_t, Uint64, ull);
#undef HANDLE_PRIMITIVE #undef HANDLE_PRIMITIVE
case schema::Type::Body::FLOAT32_TYPE: case schema2::Type::FLOAT32:
kind = FieldKind::PRIMITIVE; kind = FieldKind::PRIMITIVE;
if (defaultBody.getFloat32Value() != 0) { if (defaultBody.getFloat32() != 0) {
uint32_t mask; uint32_t mask;
float value = defaultBody.getFloat32Value(); float value = defaultBody.getFloat32();
static_assert(sizeof(mask) == sizeof(value), "bug"); static_assert(sizeof(mask) == sizeof(value), "bug");
memcpy(&mask, &value, sizeof(mask)); memcpy(&mask, &value, sizeof(mask));
defaultMask = kj::str(mask, "u"); defaultMask = kj::str(mask, "u");
} }
break; break;
case schema::Type::Body::FLOAT64_TYPE: case schema2::Type::FLOAT64:
kind = FieldKind::PRIMITIVE; kind = FieldKind::PRIMITIVE;
if (defaultBody.getFloat64Value() != 0) { if (defaultBody.getFloat64() != 0) {
uint64_t mask; uint64_t mask;
double value = defaultBody.getFloat64Value(); double value = defaultBody.getFloat64();
static_assert(sizeof(mask) == sizeof(value), "bug"); static_assert(sizeof(mask) == sizeof(value), "bug");
memcpy(&mask, &value, sizeof(mask)); memcpy(&mask, &value, sizeof(mask));
defaultMask = kj::str(mask, "ull"); defaultMask = kj::str(mask, "ull");
} }
break; break;
case schema::Type::Body::TEXT_TYPE: case schema2::Type::TEXT:
kind = FieldKind::BLOB; kind = FieldKind::BLOB;
if (defaultBody.hasTextValue()) { if (defaultBody.hasText()) {
defaultOffset = member.getDefaultValueSchemaOffset(); defaultOffset = field.getDefaultValueSchemaOffset();
defaultSize = defaultBody.getTextValue().size(); defaultSize = defaultBody.getText().size();
} }
break; break;
case schema::Type::Body::DATA_TYPE: case schema2::Type::DATA:
kind = FieldKind::BLOB; kind = FieldKind::BLOB;
if (defaultBody.hasDataValue()) { if (defaultBody.hasData()) {
defaultOffset = member.getDefaultValueSchemaOffset(); defaultOffset = field.getDefaultValueSchemaOffset();
defaultSize = defaultBody.getDataValue().size(); defaultSize = defaultBody.getData().size();
} }
break; break;
case schema::Type::Body::ENUM_TYPE: case schema2::Type::ENUM:
kind = FieldKind::PRIMITIVE; kind = FieldKind::PRIMITIVE;
if (defaultBody.getEnumValue() != 0) { if (defaultBody.getEnum() != 0) {
defaultMask = kj::str(defaultBody.getEnumValue(), "u"); defaultMask = kj::str(defaultBody.getEnum(), "u");
} }
break; break;
case schema::Type::Body::STRUCT_TYPE: case schema2::Type::STRUCT:
kind = FieldKind::STRUCT; kind = FieldKind::STRUCT;
if (defaultBody.hasStructValue()) { if (defaultBody.hasStruct()) {
defaultOffset = member.getDefaultValueSchemaOffset(); defaultOffset = field.getDefaultValueSchemaOffset();
} }
break; break;
case schema::Type::Body::LIST_TYPE: case schema2::Type::LIST:
kind = FieldKind::LIST; kind = FieldKind::LIST;
if (defaultBody.hasListValue()) { if (defaultBody.hasList()) {
defaultOffset = member.getDefaultValueSchemaOffset(); defaultOffset = field.getDefaultValueSchemaOffset();
} }
break; break;
case schema::Type::Body::INTERFACE_TYPE: case schema2::Type::INTERFACE:
kind = FieldKind::INTERFACE; kind = FieldKind::INTERFACE;
break; break;
case schema::Type::Body::OBJECT_TYPE: case schema2::Type::OBJECT:
kind = FieldKind::OBJECT; kind = FieldKind::OBJECT;
if (defaultBody.hasObjectValue()) { if (defaultBody.hasObject()) {
defaultOffset = member.getDefaultValueSchemaOffset(); defaultOffset = field.getDefaultValueSchemaOffset();
} }
break; break;
} }
...@@ -483,14 +430,7 @@ private: ...@@ -483,14 +430,7 @@ private:
defaultMaskParam = kj::str(", ", defaultMask); defaultMaskParam = kj::str(", ", defaultMask);
} }
kj::String titleCase = toTitleCase(proto.getName()); uint offset = regularField.getOffset();
DiscriminantChecks unionDiscrim;
KJ_IF_MAYBE(u, member.getContainingUnion()) {
unionDiscrim = makeDiscriminantChecks(scope, proto.getName(), *u);
}
uint offset = field.getOffset();
if (kind == FieldKind::PRIMITIVE) { if (kind == FieldKind::PRIMITIVE) {
return FieldText { return FieldText {
...@@ -635,7 +575,7 @@ private: ...@@ -635,7 +575,7 @@ private:
} else { } else {
// Blob, struct, or list. These have only minor differences. // Blob, struct, or list. These have only minor differences.
uint64_t typeId = member.getContainingStruct().getProto().getId(); uint64_t typeId = field.getContainingStruct().getProto().getId();
kj::String defaultParam = defaultOffset == 0 ? kj::str() : kj::str( kj::String defaultParam = defaultOffset == 0 ? kj::str() : kj::str(
",\n ::capnp::schemas::s_", kj::hex(typeId), ".encodedNode + ", defaultOffset, ",\n ::capnp::schemas::s_", kj::hex(typeId), ".encodedNode + ", defaultOffset,
defaultSize == 0 ? kj::strTree() : kj::strTree(", ", defaultSize)); defaultSize == 0 ? kj::strTree() : kj::strTree(", ", defaultSize));
...@@ -644,38 +584,38 @@ private: ...@@ -644,38 +584,38 @@ private:
bool isStructList = false; bool isStructList = false;
if (kind == FieldKind::LIST) { if (kind == FieldKind::LIST) {
bool primitiveElement = false; bool primitiveElement = false;
switch (typeBody.getListType().getBody().which()) { switch (typeBody.getList().which()) {
case schema::Type::Body::VOID_TYPE: case schema2::Type::VOID:
case schema::Type::Body::BOOL_TYPE: case schema2::Type::BOOL:
case schema::Type::Body::INT8_TYPE: case schema2::Type::INT8:
case schema::Type::Body::INT16_TYPE: case schema2::Type::INT16:
case schema::Type::Body::INT32_TYPE: case schema2::Type::INT32:
case schema::Type::Body::INT64_TYPE: case schema2::Type::INT64:
case schema::Type::Body::UINT8_TYPE: case schema2::Type::UINT8:
case schema::Type::Body::UINT16_TYPE: case schema2::Type::UINT16:
case schema::Type::Body::UINT32_TYPE: case schema2::Type::UINT32:
case schema::Type::Body::UINT64_TYPE: case schema2::Type::UINT64:
case schema::Type::Body::FLOAT32_TYPE: case schema2::Type::FLOAT32:
case schema::Type::Body::FLOAT64_TYPE: case schema2::Type::FLOAT64:
case schema::Type::Body::ENUM_TYPE: case schema2::Type::ENUM:
primitiveElement = true; primitiveElement = true;
break; break;
case schema::Type::Body::TEXT_TYPE: case schema2::Type::TEXT:
case schema::Type::Body::DATA_TYPE: case schema2::Type::DATA:
case schema::Type::Body::LIST_TYPE: case schema2::Type::LIST:
case schema::Type::Body::INTERFACE_TYPE: case schema2::Type::INTERFACE:
case schema::Type::Body::OBJECT_TYPE: case schema2::Type::OBJECT:
primitiveElement = false; primitiveElement = false;
break; break;
case schema::Type::Body::STRUCT_TYPE: case schema2::Type::STRUCT:
isStructList = true; isStructList = true;
primitiveElement = false; primitiveElement = false;
break; break;
} }
elementReaderType = kj::str( elementReaderType = kj::str(
typeName(typeBody.getListType()), typeName(typeBody.getList()),
primitiveElement ? "" : "::Reader"); primitiveElement ? "" : "::Reader");
} }
...@@ -766,7 +706,7 @@ private: ...@@ -766,7 +706,7 @@ private:
// ----------------------------------------------------------------- // -----------------------------------------------------------------
kj::StringTree makeReaderDef(kj::StringPtr fullName, kj::StringPtr unqualifiedParentType, kj::StringTree makeReaderDef(kj::StringPtr fullName, kj::StringPtr unqualifiedParentType,
kj::StringPtr stringifier, kj::StringTree&& methodDecls) { bool isUnion, kj::Array<kj::StringTree>&& methodDecls) {
return kj::strTree( return kj::strTree(
"class ", fullName, "::Reader {\n" "class ", fullName, "::Reader {\n"
"public:\n" "public:\n"
...@@ -779,6 +719,7 @@ private: ...@@ -779,6 +719,7 @@ private:
" return _reader.totalSize() / ::capnp::WORDS;\n" " return _reader.totalSize() / ::capnp::WORDS;\n"
" }\n" " }\n"
"\n", "\n",
isUnion ? kj::strTree(" inline Which which() const;\n") : kj::strTree(),
kj::mv(methodDecls), kj::mv(methodDecls),
"private:\n" "private:\n"
" ::capnp::_::StructReader _reader;\n" " ::capnp::_::StructReader _reader;\n"
...@@ -792,16 +733,15 @@ private: ...@@ -792,16 +733,15 @@ private:
" friend class ::capnp::Orphanage;\n" " friend class ::capnp::Orphanage;\n"
" friend ::kj::StringTree KJ_STRINGIFY(", fullName, "::Reader reader);\n" " friend ::kj::StringTree KJ_STRINGIFY(", fullName, "::Reader reader);\n"
"};\n" "};\n"
"\n", "\n"
stringifier.size() > 0 ? kj::strTree( "inline ::kj::StringTree KJ_STRINGIFY(", fullName, "::Reader reader) {\n"
"inline ::kj::StringTree KJ_STRINGIFY(", fullName, "::Reader reader) {\n" " return ::capnp::_::structString<", fullName, ">(reader._reader);\n"
" return ::capnp::_::", stringifier, "<", fullName, ">(reader._reader);\n" "}\n"
"}\n" "\n");
"\n") : kj::strTree());
} }
kj::StringTree makeBuilderDef(kj::StringPtr fullName, kj::StringPtr unqualifiedParentType, kj::StringTree makeBuilderDef(kj::StringPtr fullName, kj::StringPtr unqualifiedParentType,
kj::StringPtr stringifier, kj::StringTree&& methodDecls) { bool isUnion, kj::Array<kj::StringTree>&& methodDecls) {
return kj::strTree( return kj::strTree(
"class ", fullName, "::Builder {\n" "class ", fullName, "::Builder {\n"
"public:\n" "public:\n"
...@@ -814,6 +754,7 @@ private: ...@@ -814,6 +754,7 @@ private:
"\n" "\n"
" inline size_t totalSizeInWords() { return asReader().totalSizeInWords(); }\n" " inline size_t totalSizeInWords() { return asReader().totalSizeInWords(); }\n"
"\n", "\n",
isUnion ? kj::strTree(" inline Which which();\n") : kj::strTree(),
kj::mv(methodDecls), kj::mv(methodDecls),
"private:\n" "private:\n"
" ::capnp::_::StructBuilder _builder;\n" " ::capnp::_::StructBuilder _builder;\n"
...@@ -822,235 +763,11 @@ private: ...@@ -822,235 +763,11 @@ private:
" friend class ::capnp::Orphanage;\n" " friend class ::capnp::Orphanage;\n"
" friend ::kj::StringTree KJ_STRINGIFY(", fullName, "::Builder builder);\n" " friend ::kj::StringTree KJ_STRINGIFY(", fullName, "::Builder builder);\n"
"};\n" "};\n"
"\n", "\n"
stringifier.size() > 0 ? kj::strTree( "inline ::kj::StringTree KJ_STRINGIFY(", fullName, "::Builder builder) {\n"
"inline ::kj::StringTree KJ_STRINGIFY(", fullName, "::Builder builder) {\n" " return ::capnp::_::structString<", fullName, ">(builder._builder.asReader());\n"
" return ::capnp::_::", stringifier, "<", fullName, ">(builder._builder.asReader());\n" "}\n"
"}\n" "\n");
"\n") : kj::strTree());
}
// -----------------------------------------------------------------
struct MembersText {
kj::StringTree innerTypeDecls;
kj::StringTree innerTypeDefs;
kj::StringTree innerTypeReaderBuilderDefs;
kj::StringTree readerMethodDecls;
kj::StringTree builderMethodDecls;
kj::StringTree inlineMethodDefs;
kj::StringTree capnpPrivateDecls;
kj::StringTree capnpPrivateDefs;
};
MembersText makeMemberText(kj::StringPtr namespace_, kj::StringPtr containingType,
StructSchema::Member member) {
auto proto = member.getProto();
switch (proto.getBody().which()) {
case schema::StructNode::Member::Body::FIELD_MEMBER: {
auto fieldText = makeFieldText(kj::str(containingType, "::"), member.asField());
return MembersText {
kj::strTree(),
kj::strTree(),
kj::strTree(),
kj::mv(fieldText.readerMethodDecls),
kj::mv(fieldText.builderMethodDecls),
kj::mv(fieldText.inlineMethodDefs),
kj::strTree(),
kj::strTree(),
};
}
case schema::StructNode::Member::Body::UNION_MEMBER: {
auto subMembers = member.asUnion().getMembers();
auto unionName = proto.getName();
uint discrimOffset = proto.getBody().getUnionMember().getDiscriminantOffset();
auto whichEnumDef = kj::strTree(
" enum Which: uint16_t {\n",
KJ_MAP(subMembers, subMember) {
return kj::strTree(
" ", toUpperCase(subMember.getProto().getName()), ",\n");
},
" };\n");
if (unionName.size() == 0) {
// Anonymous union.
auto subText = makeMembersText(namespace_, containingType, subMembers);
return MembersText {
kj::strTree(kj::mv(whichEnumDef), kj::mv(subText.innerTypeDecls)),
kj::mv(subText.innerTypeDefs),
kj::mv(subText.innerTypeReaderBuilderDefs),
kj::strTree(
" inline Which which() const;\n",
kj::mv(subText.readerMethodDecls)),
kj::strTree(
" inline Which which();\n",
kj::mv(subText.builderMethodDecls)),
kj::strTree(
"inline ", containingType, "::Which ", containingType, "::Reader::which() const {\n"
" return _reader.getDataField<Which>(", discrimOffset, " * ::capnp::ELEMENTS);\n"
"}\n"
"inline ", containingType, "::Which ", containingType, "::Builder::which() {\n"
" return _builder.getDataField<Which>(", discrimOffset, " * ::capnp::ELEMENTS);\n"
"}\n"
"\n",
kj::mv(subText.inlineMethodDefs)),
kj::mv(subText.capnpPrivateDecls),
kj::mv(subText.capnpPrivateDefs),
};
} else {
// Named union.
auto titleCase = toTitleCase(unionName);
auto fullName = kj::str(containingType, "::", titleCase);
auto subText = makeMembersText(namespace_, fullName, subMembers);
return MembersText {
kj::strTree(
" struct ", titleCase, ";\n"),
kj::strTree(
"struct ", fullName, " {\n"
" ", titleCase, "() = delete;\n"
" class Reader;\n"
" class Builder;\n"
"\n",
kj::mv(whichEnumDef),
kj::mv(subText.innerTypeDecls),
"};\n"
"\n",
kj::mv(subText.innerTypeDefs)),
kj::strTree(
makeReaderDef(fullName, titleCase, "unionString", kj::strTree(
" inline Which which() const;\n",
kj::mv(subText.readerMethodDecls))),
makeBuilderDef(fullName, titleCase, "unionString", kj::strTree(
" inline Which which();\n",
kj::mv(subText.builderMethodDecls))),
kj::mv(subText.innerTypeReaderBuilderDefs)),
kj::strTree(
" inline ", titleCase, "::Reader get", titleCase, "() const;\n"),
kj::strTree(
" inline ", titleCase, "::Builder get", titleCase, "();\n"),
kj::strTree(
"inline ", fullName, "::Reader ", containingType, "::Reader::get", titleCase, "() const {\n"
" return ", fullName, "::Reader(_reader);\n"
"}\n"
"inline ", fullName, "::Builder ", containingType, "::Builder::get", titleCase, "() {\n"
" return ", fullName, "::Builder(_builder);\n"
"}\n"
"inline ", fullName, "::Which ", fullName, "::Reader::which() const {\n"
" return _reader.getDataField<Which>(", discrimOffset, " * ::capnp::ELEMENTS);\n"
"}\n"
"inline ", fullName, "::Which ", fullName, "::Builder::which() {\n"
" return _builder.getDataField<Which>(", discrimOffset, " * ::capnp::ELEMENTS);\n"
"}\n"
"\n",
kj::mv(subText.inlineMethodDefs)),
kj::strTree(
"CAPNP_DECLARE_UNION(\n"
" ", namespace_, "::", fullName, ",\n"
" ", namespace_, "::", containingType, ", ", member.getIndex(), ");\n",
kj::mv(subText.capnpPrivateDecls)),
kj::strTree(
"CAPNP_DEFINE_UNION(\n"
" ", namespace_, "::", fullName, ");\n",
kj::mv(subText.capnpPrivateDefs)),
};
}
}
case schema::StructNode::Member::Body::GROUP_MEMBER: {
auto titleCase = toTitleCase(proto.getName());
auto fullName = kj::str(containingType, "::", titleCase);
auto subText = makeMembersText(namespace_, fullName, member.asGroup().getMembers());
DiscriminantChecks unionDiscrim;
KJ_IF_MAYBE(u, member.getContainingUnion()) {
unionDiscrim = makeDiscriminantChecks(
kj::str(containingType, "::"), proto.getName(), *u);
}
return MembersText {
kj::strTree(
" struct ", titleCase, ";\n"),
kj::strTree(
"struct ", containingType, "::", titleCase, " {\n"
" ", titleCase, "() = delete;\n"
"\n",
" class Reader;\n"
" class Builder;\n",
kj::mv(subText.innerTypeDecls),
"};\n"
"\n",
kj::mv(subText.innerTypeDefs)),
kj::strTree(
makeReaderDef(fullName, titleCase, "",
kj::mv(subText.readerMethodDecls)),
makeBuilderDef(fullName, titleCase, "",
kj::mv(subText.builderMethodDecls)),
kj::mv(subText.innerTypeReaderBuilderDefs)),
kj::strTree(
" inline ", titleCase, "::Reader get", titleCase, "() const;\n"),
kj::strTree(
" inline ", titleCase, "::Builder get", titleCase, "();\n"
" inline ", titleCase, "::Builder init", titleCase, "();\n"),
kj::strTree(
"inline ", fullName, "::Reader ", containingType, "::Reader::get", titleCase, "() const {\n",
unionDiscrim.check,
" return ", fullName, "::Reader(_reader);\n"
"}\n"
"inline ", fullName, "::Builder ", containingType, "::Builder::get", titleCase, "() {\n",
unionDiscrim.check,
" return ", fullName, "::Builder(_builder);\n"
"}\n"
// TODO(soon): This should really zero out the existing group. Maybe unions should
// support zeroing out the whole union?
"inline ", fullName, "::Builder ", containingType, "::Builder::init", titleCase, "() {\n",
unionDiscrim.set,
" return ", fullName, "::Builder(_builder);\n"
"}\n",
kj::mv(subText.inlineMethodDefs)),
kj::mv(subText.capnpPrivateDecls),
kj::mv(subText.capnpPrivateDefs),
};
}
}
KJ_UNREACHABLE;
}
MembersText makeMembersText(kj::StringPtr namespace_, kj::StringPtr containingType,
StructSchema::MemberList members) {
auto memberTexts = KJ_MAP(members, member) {
return makeMemberText(namespace_, containingType, member);
};
return MembersText {
kj::strTree(KJ_MAP(memberTexts, m) { return kj::mv(m.innerTypeDecls); }),
kj::strTree(KJ_MAP(memberTexts, m) { return kj::mv(m.innerTypeDefs); }),
kj::strTree(KJ_MAP(memberTexts, m) { return kj::mv(m.innerTypeReaderBuilderDefs); }),
kj::strTree(KJ_MAP(memberTexts, m) { return kj::mv(m.readerMethodDecls); }),
kj::strTree(KJ_MAP(memberTexts, m) { return kj::mv(m.builderMethodDecls); }),
kj::strTree(KJ_MAP(memberTexts, m) { return kj::mv(m.inlineMethodDefs); }),
kj::strTree(KJ_MAP(memberTexts, m) { return kj::mv(m.capnpPrivateDecls); }),
kj::strTree(KJ_MAP(memberTexts, m) { return kj::mv(m.capnpPrivateDefs); }),
};
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
...@@ -1071,14 +788,27 @@ private: ...@@ -1071,14 +788,27 @@ private:
auto proto = schema.getProto(); auto proto = schema.getProto();
auto fullName = kj::str(scope, name); auto fullName = kj::str(scope, name);
auto subScope = kj::str(fullName, "::"); auto subScope = kj::str(fullName, "::");
auto nestedTexts = KJ_MAP(proto.getNestedNodes(), nested) {
return makeNodeText(namespace_, subScope, nested.getName(), schemaLoader.get(nested.getId()));
};
auto hexId = kj::hex(proto.getId()); auto hexId = kj::hex(proto.getId());
kj::ArrayPtr<const word> rawSchema = schema.asUncheckedMessage(); // Compute nested nodes, including groups.
kj::Vector<NodeText> nestedTexts(proto.getNestedNodes().size());
for (auto nested: proto.getNestedNodes()) {
nestedTexts.add(makeNodeText(
namespace_, subScope, nested.getName(), schemaLoader.get(nested.getId())));
};
if (proto.which() == schema2::Node::STRUCT) {
for (auto field: proto.getStruct().getFields()) {
if (field.which() == schema2::Field::GROUP) {
nestedTexts.add(makeNodeText(
namespace_, subScope, toTitleCase(field.getName()),
schemaLoader.get(field.getGroup())));
}
}
}
// Convert the encoded schema to a literal byte array. // Convert the encoded schema to a literal byte array.
kj::ArrayPtr<const word> rawSchema = schema.asUncheckedMessage();
auto schemaLiteral = kj::StringTree(KJ_MAP(rawSchema, w) { auto schemaLiteral = kj::StringTree(KJ_MAP(rawSchema, w) {
const byte* bytes = reinterpret_cast<const byte*>(&w); const byte* bytes = reinterpret_cast<const byte*>(&w);
...@@ -1094,16 +824,16 @@ private: ...@@ -1094,16 +824,16 @@ private:
std::set<uint64_t> deps; std::set<uint64_t> deps;
enumerateDeps(proto, deps); enumerateDeps(proto, deps);
kj::Vector<capnp::_::RawSchema::MemberInfo> memberInfos; kj::Array<uint> membersByName;
switch (proto.getBody().which()) { switch (proto.which()) {
case schema::Node::Body::STRUCT_NODE: case schema2::Node::STRUCT:
makeMemberInfoTable(0, schema.asStruct().getMembers(), memberInfos); membersByName = makeMembersByName(schema.asStruct().getFields());
break; break;
case schema::Node::Body::ENUM_NODE: case schema2::Node::ENUM:
makeMemberInfoTable(0, schema.asEnum().getEnumerants(), memberInfos); membersByName = makeMembersByName(schema.asEnum().getEnumerants());
break; break;
case schema::Node::Body::INTERFACE_NODE: case schema2::Node::INTERFACE:
makeMemberInfoTable(0, schema.asInterface().getMethods(), memberInfos); membersByName = makeMembersByName(schema.asInterface().getMethods());
break; break;
default: default:
break; break;
...@@ -1119,51 +849,66 @@ private: ...@@ -1119,51 +849,66 @@ private:
}, },
"};\n" "};\n"
"static const ::capnp::_::RawSchema::MemberInfo m_", hexId, "[] = {\n", "static const ::capnp::_::RawSchema::MemberInfo m_", hexId, "[] = {\n",
KJ_MAP(memberInfos, info) { kj::StringTree(KJ_MAP(membersByName, index) { return kj::strTree(index); }, ", "),
return kj::strTree(" { ", info.scopeOrdinal, ", ", info.index, " },\n");
},
"};\n" "};\n"
"const ::capnp::_::RawSchema s_", hexId, " = {\n" "const ::capnp::_::RawSchema s_", hexId, " = {\n"
" 0x", hexId, ", b_", hexId, ".words, ", rawSchema.size(), ", d_", hexId, ", m_", hexId, ",\n" " 0x", hexId, ", b_", hexId, ".words, ", rawSchema.size(), ", d_", hexId, ", m_", hexId, ",\n"
" ", deps.size(), ", ", memberInfos.size(), ", nullptr, nullptr\n" " ", deps.size(), ", ", membersByName.size(), ", nullptr, nullptr\n"
"};\n"); "};\n");
switch (proto.getBody().which()) { switch (proto.which()) {
case schema::Node::Body::FILE_NODE: case schema2::Node::FILE:
KJ_FAIL_REQUIRE("This method shouldn't be called on file nodes."); KJ_FAIL_REQUIRE("This method shouldn't be called on file nodes.");
case schema::Node::Body::STRUCT_NODE: { case schema2::Node::STRUCT: {
auto membersText = makeMembersText(namespace_, fullName, schema.asStruct().getMembers()); auto fieldTexts =
KJ_MAP(schema.asStruct().getFields(), f) { return makeFieldText(subScope, f); };
auto structNode = proto.getBody().getStructNode(); auto structNode = proto.getStruct();
uint discrimOffset = structNode.getDiscriminantOffset();
return NodeText { return NodeText {
kj::strTree( kj::strTree(
" struct ", name, ";\n"), " struct ", name, ";\n"),
kj::strTree( kj::strTree(
"struct ", scope, name, " {\n", "struct ", fullName, " {\n",
" ", name, "() = delete;\n" " ", name, "() = delete;\n"
"\n" "\n"
" class Reader;\n" " class Reader;\n"
" class Builder;\n", " class Builder;\n",
kj::mv(membersText.innerTypeDecls), structNode.getDiscriminantCount() == 0 ? kj::strTree() : kj::strTree(
" enum Which: uint16_t {\n",
KJ_MAP(structNode.getFields(), f) {
if (f.hasDiscriminantValue()) {
return kj::strTree(" ", toUpperCase(f.getName()), ",\n");
} else {
return kj::strTree();
}
},
" };\n"),
KJ_MAP(nestedTexts, n) { return kj::mv(n.outerTypeDecl); }, KJ_MAP(nestedTexts, n) { return kj::mv(n.outerTypeDecl); },
"};\n" "};\n"
"\n", "\n",
kj::mv(membersText.innerTypeDefs),
KJ_MAP(nestedTexts, n) { return kj::mv(n.outerTypeDef); }), KJ_MAP(nestedTexts, n) { return kj::mv(n.outerTypeDef); }),
kj::strTree( kj::strTree(
makeReaderDef(fullName, name, "structString", makeReaderDef(fullName, name, structNode.getDiscriminantCount() != 0,
kj::mv(membersText.readerMethodDecls)), KJ_MAP(fieldTexts, f) { return kj::mv(f.readerMethodDecls); }),
makeBuilderDef(fullName, name, "structString", makeBuilderDef(fullName, name, structNode.getDiscriminantCount() != 0,
kj::mv(membersText.builderMethodDecls)), KJ_MAP(fieldTexts, f) { return kj::mv(f.builderMethodDecls); }),
kj::mv(membersText.innerTypeReaderBuilderDefs),
KJ_MAP(nestedTexts, n) { return kj::mv(n.readerBuilderDefs); }), KJ_MAP(nestedTexts, n) { return kj::mv(n.readerBuilderDefs); }),
kj::strTree( kj::strTree(
kj::mv(membersText.inlineMethodDefs), structNode.getDiscriminantCount() == 0 ? kj::strTree() : kj::strTree(
"inline ", fullName, "::Which ", fullName, "::Reader::which() const {\n"
" return _reader.getDataField<Which>(", discrimOffset, " * ::capnp::ELEMENTS);\n"
"}\n"
"inline ", fullName, "::Which ", fullName, "::Builder::which() {\n"
" return _builder.getDataField<Which>(", discrimOffset, " * ::capnp::ELEMENTS);\n"
"}\n"
"\n"),
KJ_MAP(fieldTexts, f) { return kj::mv(f.inlineMethodDefs); },
KJ_MAP(nestedTexts, n) { return kj::mv(n.inlineMethodDefs); }), KJ_MAP(nestedTexts, n) { return kj::mv(n.inlineMethodDefs); }),
kj::strTree( kj::strTree(
...@@ -1181,18 +926,16 @@ private: ...@@ -1181,18 +926,16 @@ private:
structNode.getPointerSectionSize(), ", ", structNode.getPointerSectionSize(), ", ",
FIELD_SIZE_NAMES[static_cast<uint>(structNode.getPreferredListEncoding())], FIELD_SIZE_NAMES[static_cast<uint>(structNode.getPreferredListEncoding())],
");\n", ");\n",
kj::mv(membersText.capnpPrivateDecls),
KJ_MAP(nestedTexts, n) { return kj::mv(n.capnpPrivateDecls); }), KJ_MAP(nestedTexts, n) { return kj::mv(n.capnpPrivateDecls); }),
kj::strTree( kj::strTree(
"CAPNP_DEFINE_STRUCT(\n" "CAPNP_DEFINE_STRUCT(\n"
" ", namespace_, "::", fullName, ");\n", " ", namespace_, "::", fullName, ");\n",
kj::mv(membersText.capnpPrivateDefs),
KJ_MAP(nestedTexts, n) { return kj::mv(n.capnpPrivateDefs); }), KJ_MAP(nestedTexts, n) { return kj::mv(n.capnpPrivateDefs); }),
}; };
} }
case schema::Node::Body::ENUM_NODE: { case schema2::Node::ENUM: {
auto enumerants = schema.asEnum().getEnumerants(); auto enumerants = schema.asEnum().getEnumerants();
return NodeText { return NodeText {
...@@ -1227,7 +970,7 @@ private: ...@@ -1227,7 +970,7 @@ private:
}; };
} }
case schema::Node::Body::INTERFACE_NODE: { case schema2::Node::INTERFACE: {
return NodeText { return NodeText {
kj::strTree(), kj::strTree(),
kj::strTree(), kj::strTree(),
...@@ -1246,7 +989,7 @@ private: ...@@ -1246,7 +989,7 @@ private:
}; };
} }
case schema::Node::Body::CONST_NODE: { case schema2::Node::CONST: {
return NodeText { return NodeText {
kj::strTree(), kj::strTree(),
kj::strTree(), kj::strTree(),
...@@ -1261,7 +1004,7 @@ private: ...@@ -1261,7 +1004,7 @@ private:
}; };
} }
case schema::Node::Body::ANNOTATION_NODE: { case schema2::Node::ANNOTATION: {
return NodeText { return NodeText {
kj::strTree(), kj::strTree(),
kj::strTree(), kj::strTree(),
...@@ -1287,7 +1030,8 @@ private: ...@@ -1287,7 +1030,8 @@ private:
kj::StringTree source; kj::StringTree source;
}; };
FileText makeFileText(Schema schema) { FileText makeFileText(Schema schema,
schema2::CodeGeneratorRequest::RequestedFile::Reader request) {
usedImports.clear(); usedImports.clear();
auto node = schema.getProto(); auto node = schema.getProto();
...@@ -1298,7 +1042,7 @@ private: ...@@ -1298,7 +1042,7 @@ private:
for (auto annotation: node.getAnnotations()) { for (auto annotation: node.getAnnotations()) {
if (annotation.getId() == NAMESPACE_ANNOTATION_ID) { if (annotation.getId() == NAMESPACE_ANNOTATION_ID) {
kj::StringPtr ns = annotation.getValue().getBody().getTextValue(); kj::StringPtr ns = annotation.getValue().getText();
kj::StringPtr ns2 = ns; kj::StringPtr ns2 = ns;
namespacePrefix = kj::str("::", ns); namespacePrefix = kj::str("::", ns);
...@@ -1327,7 +1071,7 @@ private: ...@@ -1327,7 +1071,7 @@ private:
kj::String separator = kj::str("// ", kj::repeat('=', 87), "\n"); kj::String separator = kj::str("// ", kj::repeat('=', 87), "\n");
kj::Vector<kj::StringPtr> includes; kj::Vector<kj::StringPtr> includes;
for (auto import: node.getBody().getFileNode().getImports()) { for (auto import: request.getImports()) {
if (usedImports.count(import.getId()) > 0) { if (usedImports.count(import.getId()) > 0) {
includes.add(import.getName()); includes.add(import.getName());
} }
...@@ -1430,7 +1174,7 @@ private: ...@@ -1430,7 +1174,7 @@ private:
ReaderOptions options; ReaderOptions options;
options.traversalLimitInWords = 1 << 30; // Don't limit. options.traversalLimitInWords = 1 << 30; // Don't limit.
StreamFdMessageReader reader(STDIN_FILENO, options); StreamFdMessageReader reader(STDIN_FILENO, options);
auto request = reader.getRoot<schema::CodeGeneratorRequest>(); auto request = reader.getRoot<schema2::CodeGeneratorRequest>();
for (auto node: request.getNodes()) { for (auto node: request.getNodes()) {
schemaLoader.load(node); schemaLoader.load(node);
...@@ -1439,9 +1183,9 @@ private: ...@@ -1439,9 +1183,9 @@ private:
kj::FdOutputStream rawOut(STDOUT_FILENO); kj::FdOutputStream rawOut(STDOUT_FILENO);
kj::BufferedOutputStreamWrapper out(rawOut); kj::BufferedOutputStreamWrapper out(rawOut);
for (auto fileId: request.getRequestedFiles()) { for (auto requestedFile: request.getRequestedFiles()) {
auto schema = schemaLoader.get(fileId); auto schema = schemaLoader.get(requestedFile.getId());
auto fileText = makeFileText(schema); auto fileText = makeFileText(schema, requestedFile);
writeFile(kj::str(schema.getProto().getDisplayName(), ".h"), fileText.header); writeFile(kj::str(schema.getProto().getDisplayName(), ".h"), fileText.header);
writeFile(kj::str(schema.getProto().getDisplayName(), ".c++"), fileText.source); writeFile(kj::str(schema.getProto().getDisplayName(), ".c++"), fileText.source);
......
...@@ -810,10 +810,7 @@ public: ...@@ -810,10 +810,7 @@ public:
} }
schema2::Field::Builder fieldBuilder = member.getSchema(); schema2::Field::Builder fieldBuilder = member.getSchema();
fieldBuilder.setName(member.decl.getName().getValue());
fieldBuilder.getOrdinal().setExplicit(entry.first); fieldBuilder.getOrdinal().setExplicit(entry.first);
fieldBuilder.setCodeOrder(member.codeOrder);
switch (member.decl.getBody().which()) { switch (member.decl.getBody().which()) {
case Declaration::Body::FIELD_DECL: { case Declaration::Body::FIELD_DECL: {
...@@ -891,7 +888,7 @@ public: ...@@ -891,7 +888,7 @@ public:
// OK, we should have built all the members. Now go through and make sure the discriminant // OK, we should have built all the members. Now go through and make sure the discriminant
// offsets have been copied over to the schemas and annotations have been applied. // offsets have been copied over to the schemas and annotations have been applied.
root.setDiscriminantOffsetInSchema(); root.finishGroup();
for (auto member: allMembers) { for (auto member: allMembers) {
kj::StringPtr targetsFlagName; kj::StringPtr targetsFlagName;
switch (member->decl.getBody().which()) { switch (member->decl.getBody().which()) {
...@@ -900,13 +897,12 @@ public: ...@@ -900,13 +897,12 @@ public:
break; break;
case Declaration::Body::UNION_DECL: case Declaration::Body::UNION_DECL:
member->setDiscriminantOffsetInSchema(); member->finishGroup();
targetsFlagName = "targetsUnion"; targetsFlagName = "targetsUnion";
break; break;
case Declaration::Body::GROUP_DECL: case Declaration::Body::GROUP_DECL:
member->setDiscriminantOffsetInSchema(); // in case it contains an unnamed union member->finishGroup();
member->node.setId(generateGroupId(member->parent->node.getId(), member->index));
targetsFlagName = "targetsGroup"; targetsFlagName = "targetsGroup";
break; break;
...@@ -1026,6 +1022,8 @@ private: ...@@ -1026,6 +1022,8 @@ private:
if (isInUnion) { if (isInUnion) {
builder.setDiscriminantValue(parent->unionDiscriminantCount++); builder.setDiscriminantValue(parent->unionDiscriminantCount++);
} }
builder.setName(decl.getName().getValue());
builder.setCodeOrder(codeOrder);
schema = builder; schema = builder;
return builder; return builder;
} }
...@@ -1039,20 +1037,28 @@ private: ...@@ -1039,20 +1037,28 @@ private:
auto structNode = node.getStruct(); auto structNode = node.getStruct();
if (!structNode.hasFields()) { if (!structNode.hasFields()) {
getSchema(); // Make sure field exists in parent once the first child is added. if (parent != nullptr) {
getSchema(); // Make sure field exists in parent once the first child is added.
}
return structNode.initFields(childCount)[childInitializedCount++]; return structNode.initFields(childCount)[childInitializedCount++];
} else { } else {
return structNode.getFields()[childInitializedCount++]; return structNode.getFields()[childInitializedCount++];
} }
} }
void setDiscriminantOffsetInSchema() { void finishGroup() {
if (unionScope != nullptr) { if (unionScope != nullptr) {
unionScope->addDiscriminant(); // if it hasn't happened already unionScope->addDiscriminant(); // if it hasn't happened already
auto structNode = node.getStruct(); auto structNode = node.getStruct();
structNode.setDiscriminantCount(unionDiscriminantCount); structNode.setDiscriminantCount(unionDiscriminantCount);
structNode.setDiscriminantOffset(KJ_ASSERT_NONNULL(unionScope->discriminantOffset)); structNode.setDiscriminantOffset(KJ_ASSERT_NONNULL(unionScope->discriminantOffset));
} }
if (parent != nullptr) {
uint64_t groupId = generateGroupId(parent->node.getId(), index);
node.setId(groupId);
getSchema().setGroup(groupId);
}
} }
}; };
...@@ -1064,9 +1070,7 @@ private: ...@@ -1064,9 +1070,7 @@ private:
// All members, including ones that don't have ordinals. // All members, including ones that don't have ordinals.
void traverseUnion(List<Declaration>::Reader members, MemberInfo& parent, void traverseUnion(List<Declaration>::Reader members, MemberInfo& parent,
StructLayout::Union& layout) { StructLayout::Union& layout, uint& codeOrder) {
uint codeOrder = 0;
if (members.size() < 2) { if (members.size() < 2) {
errorReporter.addErrorOn(parent.decl, "Union must have at least two members."); errorReporter.addErrorOn(parent.decl, "Union must have at least two members.");
} }
...@@ -1145,8 +1149,11 @@ private: ...@@ -1145,8 +1149,11 @@ private:
case Declaration::Body::UNION_DECL: { case Declaration::Body::UNION_DECL: {
StructLayout::Union& unionLayout = arena.allocate<StructLayout::Union>(layout); StructLayout::Union& unionLayout = arena.allocate<StructLayout::Union>(layout);
uint independentSubCodeOrder = 0;
uint* subCodeOrder = &independentSubCodeOrder;
if (member.getName().getValue() == "") { if (member.getName().getValue() == "") {
memberInfo = &parent; memberInfo = &parent;
subCodeOrder = &codeOrder;
} else { } else {
parent.childCount++; parent.childCount++;
memberInfo = &arena.allocate<MemberInfo>( memberInfo = &arena.allocate<MemberInfo>(
...@@ -1156,7 +1163,7 @@ private: ...@@ -1156,7 +1163,7 @@ private:
allMembers.add(memberInfo); allMembers.add(memberInfo);
} }
memberInfo->unionScope = &unionLayout; memberInfo->unionScope = &unionLayout;
traverseUnion(member.getNestedDecls(), *memberInfo, unionLayout); traverseUnion(member.getNestedDecls(), *memberInfo, unionLayout, *subCodeOrder);
if (member.getId().which() == Declaration::Id::ORDINAL) { if (member.getId().which() == Declaration::Id::ORDINAL) {
ordinal = member.getId().getOrdinal().getValue(); ordinal = member.getId().getOrdinal().getValue();
} }
...@@ -1517,8 +1524,17 @@ void NodeTranslator::compileValue(ValueExpression::Reader source, schema2::Type: ...@@ -1517,8 +1524,17 @@ void NodeTranslator::compileValue(ValueExpression::Reader source, schema2::Type:
schema2::Value::Builder target, bool isBootstrap) { schema2::Value::Builder target, bool isBootstrap) {
#warning "temporary hack for schema transition" #warning "temporary hack for schema transition"
switch (type.which()) { switch (type.which()) {
case schema2::Type::TEXT:
target.setText(source.getBody().getString());
break;
case schema2::Type::UINT16:
target.setUint16(source.getBody().getPositiveInt());
break;
default: default:
KJ_FAIL_ASSERT("Need to compile value type:", (uint)type.which()); KJ_FAIL_ASSERT("Need to compile value type:", (uint)type.which(),
wipNode.getReader().getDisplayName());
} }
#if 0 #if 0
......
...@@ -240,7 +240,8 @@ inline kj::StringTree structString(StructReader reader) { ...@@ -240,7 +240,8 @@ inline kj::StringTree structString(StructReader reader) {
template <typename T> template <typename T>
inline kj::StringTree unionString(StructReader reader) { inline kj::StringTree unionString(StructReader reader) {
return unionString(reader, rawSchema<UnionParentType<T>>(), unionMemberIndex<T>()); #warning "remove this"
return kj::strTree();
} }
} // namespace _ (private) } // namespace _ (private)
......
...@@ -71,7 +71,8 @@ public: ...@@ -71,7 +71,8 @@ public:
TryGetResult tryGet(uint64_t typeId) const; TryGetResult tryGet(uint64_t typeId) const;
kj::Array<Schema> getAllLoaded() const; kj::Array<Schema> getAllLoaded() const;
void requireStructSize(uint64_t id, uint dataWordCount, uint pointerCount); void requireStructSize(uint64_t id, uint dataWordCount, uint pointerCount,
schema2::ElementSize preferredListEncoding);
// Require any struct nodes loaded with this ID -- in the past and in the future -- to have at // Require any struct nodes loaded with this ID -- in the past and in the future -- to have at
// least the given sizes. Struct nodes that don't comply will simply be rewritten to comply. // least the given sizes. Struct nodes that don't comply will simply be rewritten to comply.
// This is used to ensure that parents of group nodes have at least the size of the group node, // This is used to ensure that parents of group nodes have at least the size of the group node,
...@@ -86,6 +87,7 @@ private: ...@@ -86,6 +87,7 @@ private:
struct RequiredSize { struct RequiredSize {
uint16_t dataWordCount; uint16_t dataWordCount;
uint16_t pointerCount; uint16_t pointerCount;
schema2::ElementSize preferredListEncoding;
}; };
std::unordered_map<uint64_t, RequiredSize> structSizeRequirements; std::unordered_map<uint64_t, RequiredSize> structSizeRequirements;
...@@ -103,13 +105,15 @@ private: ...@@ -103,13 +105,15 @@ private:
// (but at least can't cause memory corruption). // (but at least can't cause memory corruption).
kj::ArrayPtr<word> rewriteStructNodeWithSizes( kj::ArrayPtr<word> rewriteStructNodeWithSizes(
schema2::Node::Reader node, uint dataWordCount, uint pointerCount); schema2::Node::Reader node, uint dataWordCount, uint pointerCount,
schema2::ElementSize preferredListEncoding);
// Make a copy of the given node (which must be a struct node) and set its sizes to be the max // Make a copy of the given node (which must be a struct node) and set its sizes to be the max
// of what it said already and the given sizes. // of what it said already and the given sizes.
// If the encoded node does not meet the given struct size requirements, make a new copy that // If the encoded node does not meet the given struct size requirements, make a new copy that
// does. // does.
void applyStructSizeRequirement(_::RawSchema* raw, uint dataWordCount, uint pointerCount); void applyStructSizeRequirement(_::RawSchema* raw, uint dataWordCount, uint pointerCount,
schema2::ElementSize preferredListEncoding);
}; };
// ======================================================================================= // =======================================================================================
...@@ -340,7 +344,8 @@ private: ...@@ -340,7 +344,8 @@ private:
// Require that the group's scope has at least the same size as the group, so that anyone // Require that the group's scope has at least the same size as the group, so that anyone
// constructing an instance of the outer scope can safely read/write the group. // constructing an instance of the outer scope can safely read/write the group.
loader.requireStructSize(scopeId, structNode.getDataSectionWordSize(), loader.requireStructSize(scopeId, structNode.getDataSectionWordSize(),
structNode.getPointerSectionSize()); structNode.getPointerSectionSize(),
structNode.getPreferredListEncoding());
// Require that the parent type is a struct. // Require that the parent type is a struct.
validateTypeId(scopeId, schema2::Node::STRUCT); validateTypeId(scopeId, schema2::Node::STRUCT);
...@@ -1131,7 +1136,8 @@ _::RawSchema* SchemaLoader::Impl::loadNative(const _::RawSchema* nativeSchema) { ...@@ -1131,7 +1136,8 @@ _::RawSchema* SchemaLoader::Impl::loadNative(const _::RawSchema* nativeSchema) {
auto reqIter = structSizeRequirements.find(nativeSchema->id); auto reqIter = structSizeRequirements.find(nativeSchema->id);
if (reqIter != structSizeRequirements.end()) { if (reqIter != structSizeRequirements.end()) {
applyStructSizeRequirement(result, reqIter->second.dataWordCount, applyStructSizeRequirement(result, reqIter->second.dataWordCount,
reqIter->second.pointerCount); reqIter->second.pointerCount,
reqIter->second.preferredListEncoding);
} }
} else { } else {
// The existing schema is newer. // The existing schema is newer.
...@@ -1200,14 +1206,21 @@ kj::Array<Schema> SchemaLoader::Impl::getAllLoaded() const { ...@@ -1200,14 +1206,21 @@ kj::Array<Schema> SchemaLoader::Impl::getAllLoaded() const {
return result; return result;
} }
void SchemaLoader::Impl::requireStructSize(uint64_t id, uint dataWordCount, uint pointerCount) { void SchemaLoader::Impl::requireStructSize(uint64_t id, uint dataWordCount, uint pointerCount,
schema2::ElementSize preferredListEncoding) {
auto& slot = structSizeRequirements[id]; auto& slot = structSizeRequirements[id];
slot.dataWordCount = kj::max(slot.dataWordCount, dataWordCount); slot.dataWordCount = kj::max(slot.dataWordCount, dataWordCount);
slot.pointerCount = kj::max(slot.pointerCount, pointerCount); slot.pointerCount = kj::max(slot.pointerCount, pointerCount);
if (slot.dataWordCount + slot.pointerCount >= 2) {
slot.preferredListEncoding = schema2::ElementSize::INLINE_COMPOSITE;
} else {
slot.preferredListEncoding = kj::max(slot.preferredListEncoding, preferredListEncoding);
}
auto iter = schemas.find(id); auto iter = schemas.find(id);
if (iter != schemas.end()) { if (iter != schemas.end()) {
applyStructSizeRequirement(iter->second, dataWordCount, pointerCount); applyStructSizeRequirement(iter->second, dataWordCount, pointerCount, preferredListEncoding);
} }
} }
...@@ -1227,9 +1240,11 @@ kj::ArrayPtr<word> SchemaLoader::Impl::makeUncheckedNodeEnforcingSizeRequirement ...@@ -1227,9 +1240,11 @@ kj::ArrayPtr<word> SchemaLoader::Impl::makeUncheckedNodeEnforcingSizeRequirement
auto requirement = iter->second; auto requirement = iter->second;
auto structNode = node.getStruct(); auto structNode = node.getStruct();
if (structNode.getDataSectionWordSize() < requirement.dataWordCount || if (structNode.getDataSectionWordSize() < requirement.dataWordCount ||
structNode.getPointerSectionSize() < requirement.pointerCount) { structNode.getPointerSectionSize() < requirement.pointerCount ||
structNode.getPreferredListEncoding() < requirement.preferredListEncoding) {
return rewriteStructNodeWithSizes(node, requirement.dataWordCount, return rewriteStructNodeWithSizes(node, requirement.dataWordCount,
requirement.pointerCount); requirement.pointerCount,
requirement.preferredListEncoding);
} }
} }
} }
...@@ -1238,7 +1253,8 @@ kj::ArrayPtr<word> SchemaLoader::Impl::makeUncheckedNodeEnforcingSizeRequirement ...@@ -1238,7 +1253,8 @@ kj::ArrayPtr<word> SchemaLoader::Impl::makeUncheckedNodeEnforcingSizeRequirement
} }
kj::ArrayPtr<word> SchemaLoader::Impl::rewriteStructNodeWithSizes( kj::ArrayPtr<word> SchemaLoader::Impl::rewriteStructNodeWithSizes(
schema2::Node::Reader node, uint dataWordCount, uint pointerCount) { schema2::Node::Reader node, uint dataWordCount, uint pointerCount,
schema2::ElementSize preferredListEncoding) {
MallocMessageBuilder builder; MallocMessageBuilder builder;
builder.setRoot(node); builder.setRoot(node);
...@@ -1247,18 +1263,28 @@ kj::ArrayPtr<word> SchemaLoader::Impl::rewriteStructNodeWithSizes( ...@@ -1247,18 +1263,28 @@ kj::ArrayPtr<word> SchemaLoader::Impl::rewriteStructNodeWithSizes(
newStruct.setDataSectionWordSize(kj::max(newStruct.getDataSectionWordSize(), dataWordCount)); newStruct.setDataSectionWordSize(kj::max(newStruct.getDataSectionWordSize(), dataWordCount));
newStruct.setPointerSectionSize(kj::max(newStruct.getPointerSectionSize(), pointerCount)); newStruct.setPointerSectionSize(kj::max(newStruct.getPointerSectionSize(), pointerCount));
if (newStruct.getDataSectionWordSize() + newStruct.getPointerSectionSize() >= 2) {
newStruct.setPreferredListEncoding(schema2::ElementSize::INLINE_COMPOSITE);
} else {
newStruct.setPreferredListEncoding(
kj::max(newStruct.getPreferredListEncoding(), preferredListEncoding));
}
return makeUncheckedNode(root); return makeUncheckedNode(root);
} }
void SchemaLoader::Impl::applyStructSizeRequirement( void SchemaLoader::Impl::applyStructSizeRequirement(
_::RawSchema* raw, uint dataWordCount, uint pointerCount) { _::RawSchema* raw, uint dataWordCount, uint pointerCount,
schema2::ElementSize preferredListEncoding) {
auto node = readMessageUnchecked<schema2::Node>(raw->encodedNode); auto node = readMessageUnchecked<schema2::Node>(raw->encodedNode);
auto structNode = node.getStruct(); auto structNode = node.getStruct();
if (structNode.getDataSectionWordSize() < dataWordCount || if (structNode.getDataSectionWordSize() < dataWordCount ||
structNode.getPointerSectionSize() < pointerCount) { structNode.getPointerSectionSize() < pointerCount ||
structNode.getPreferredListEncoding() < preferredListEncoding) {
// Sizes need to be increased. Must rewrite. // Sizes need to be increased. Must rewrite.
kj::ArrayPtr<word> words = rewriteStructNodeWithSizes(node, dataWordCount, pointerCount); kj::ArrayPtr<word> words = rewriteStructNodeWithSizes(
node, dataWordCount, pointerCount, preferredListEncoding);
// We don't need to re-validate the node because we know this change could not possibly have // We don't need to re-validate the node because we know this change could not possibly have
// invalidated it. Just remake the unchecked message. // invalidated it. Just remake the unchecked message.
......
...@@ -154,8 +154,6 @@ private: ...@@ -154,8 +154,6 @@ private:
friend class Schema; friend class Schema;
friend kj::StringTree _::structString( friend kj::StringTree _::structString(
_::StructReader reader, const _::RawSchema& schema); _::StructReader reader, const _::RawSchema& schema);
friend kj::StringTree _::unionString(
_::StructReader reader, const _::RawSchema& schema, uint fieldIndex);
}; };
class StructSchema::Field { class StructSchema::Field {
......
...@@ -42,7 +42,7 @@ struct Node { ...@@ -42,7 +42,7 @@ struct Node {
# If you want a shorter version of `displayName` (just naming this node, without its surrounding # If you want a shorter version of `displayName` (just naming this node, without its surrounding
# scope), chop off this many characters from the beginning of `displayName`. # scope), chop off this many characters from the beginning of `displayName`.
scopeId @3 :Id = 0; scopeId @3 :Id;
# ID of the lexical parent node. Typically, the scope node will have a NestedNode pointing back # ID of the lexical parent node. Typically, the scope node will have a NestedNode pointing back
# at this node, but robust code should avoid relying on this (and, in fact, group nodes are not # at this node, but robust code should avoid relying on this (and, in fact, group nodes are not
# listed in the outer struct's nestedNodes, since they are listed in the fields). `scopeId` is # listed in the outer struct's nestedNodes, since they are listed in the fields). `scopeId` is
...@@ -105,7 +105,8 @@ struct Node { ...@@ -105,7 +105,8 @@ struct Node {
# `isGroup` = true. # `isGroup` = true.
discriminantOffset @12 :UInt32; discriminantOffset @12 :UInt32;
# If `isUnion` is true, this is the offset of the union discriminant, in multiples of 16 bits. # If `discriminantCount` is non-zero, this is the offset of the union discriminant, in
# multiples of 16 bits.
fields @13 :List(Field); fields @13 :List(Field);
# Fields defined within this scope (either the struct's top-level fields, or the fields of # Fields defined within this scope (either the struct's top-level fields, or the fields of
......
...@@ -99,21 +99,19 @@ private: ...@@ -99,21 +99,19 @@ private:
} }
}; };
schema::Type::Body::Which whichMemberType(const StructSchema::Member& member) { static schema2::Type::Which whichFieldType(const StructSchema::Field& field) {
auto body = member.getProto().getBody(); auto proto = field.getProto();
switch (body.which()) { switch (proto.which()) {
case schema::StructNode::Member::Body::UNION_MEMBER: case schema2::Field::REGULAR:
return schema::Type::Body::VOID_TYPE; return proto.getRegular().getType().which();
case schema::StructNode::Member::Body::GROUP_MEMBER: case schema2::Field::GROUP:
return schema::Type::Body::STRUCT_TYPE; return schema2::Type::STRUCT;
case schema::StructNode::Member::Body::FIELD_MEMBER:
return body.getFieldMember().getType().getBody().which();
} }
KJ_UNREACHABLE; KJ_UNREACHABLE;
} }
static kj::StringTree print(const DynamicValue::Reader& value, static kj::StringTree print(const DynamicValue::Reader& value,
schema::Type::Body::Which which, Indent indent, schema2::Type::Which which, Indent indent,
PrintMode mode) { PrintMode mode) {
switch (value.getType()) { switch (value.getType()) {
case DynamicValue::UNKNOWN: case DynamicValue::UNKNOWN:
...@@ -127,7 +125,7 @@ static kj::StringTree print(const DynamicValue::Reader& value, ...@@ -127,7 +125,7 @@ static kj::StringTree print(const DynamicValue::Reader& value,
case DynamicValue::UINT: case DynamicValue::UINT:
return kj::strTree(value.as<uint64_t>()); return kj::strTree(value.as<uint64_t>());
case DynamicValue::FLOAT: case DynamicValue::FLOAT:
if (which == schema::Type::Body::FLOAT32_TYPE) { if (which == schema2::Type::FLOAT32) {
return kj::strTree(value.as<float>()); return kj::strTree(value.as<float>());
} else { } else {
return kj::strTree(value.as<double>()); return kj::strTree(value.as<double>());
...@@ -192,40 +190,31 @@ static kj::StringTree print(const DynamicValue::Reader& value, ...@@ -192,40 +190,31 @@ static kj::StringTree print(const DynamicValue::Reader& value,
} }
case DynamicValue::STRUCT: { case DynamicValue::STRUCT: {
auto structValue = value.as<DynamicStruct>(); auto structValue = value.as<DynamicStruct>();
auto memberSchemas = structValue.getSchema().getMembers(); auto unionFields = structValue.getSchema().getUnionFields();
auto nonUnionFields = structValue.getSchema().getNonUnionFields();
kj::Vector<kj::StringTree> printedMembers(memberSchemas.size());
for (auto member: memberSchemas) { kj::Vector<kj::StringTree> printedFields(nonUnionFields.size() + (unionFields.size() != 0));
if (structValue.has(member)) {
auto name = member.getProto().getName(); KJ_IF_MAYBE(field, structValue.which()) {
if (name.size() == 0) { if (structValue.has(*field)) {
// Unnamed union. Just print the content. printedFields.add(kj::strTree(
printedMembers.add(kj::strTree( field->getProto().getName(), " = ",
print(structValue.get(member), whichMemberType(member), indent.next(), BARE))); print(structValue.get(*field), whichFieldType(*field), indent.next(), PREFIXED)));
} else {
printedMembers.add(kj::strTree(
name, " = ",
print(structValue.get(member), whichMemberType(member), indent.next(), PREFIXED)));
}
} }
} }
if (mode == PARENTHESIZED) { for (auto field: nonUnionFields) {
return indent.delimit(printedMembers.releaseAsArray(), mode); if (structValue.has(field)) {
} else { printedFields.add(kj::strTree(
return kj::strTree('(', indent.delimit(printedMembers.releaseAsArray(), mode), ')'); field.getProto().getName(), " = ",
print(structValue.get(field), whichFieldType(field), indent.next(), PREFIXED)));
}
} }
}
case DynamicValue::UNION: { if (mode == PARENTHESIZED) {
auto unionValue = value.as<DynamicUnion>(); return indent.delimit(printedFields.releaseAsArray(), mode);
KJ_IF_MAYBE(tag, unionValue.which()) {
return kj::strTree(
tag->getProto().getName(), '(',
print(unionValue.get(), whichMemberType(*tag), indent, PARENTHESIZED), ')');
} else { } else {
// Unknown union member; must have come from newer return kj::strTree('(', indent.delimit(printedFields.releaseAsArray(), mode), ')');
// version of the protocol.
return kj::strTree("<unknown union member>");
} }
} }
case DynamicValue::INTERFACE: case DynamicValue::INTERFACE:
...@@ -240,17 +229,17 @@ static kj::StringTree print(const DynamicValue::Reader& value, ...@@ -240,17 +229,17 @@ static kj::StringTree print(const DynamicValue::Reader& value,
} }
kj::StringTree stringify(DynamicValue::Reader value) { kj::StringTree stringify(DynamicValue::Reader value) {
return print(value, schema::Type::Body::STRUCT_TYPE, Indent(false), BARE); return print(value, schema2::Type::STRUCT, Indent(false), BARE);
} }
} // namespace } // namespace
kj::StringTree prettyPrint(DynamicStruct::Reader value) { kj::StringTree prettyPrint(DynamicStruct::Reader value) {
return print(value, schema::Type::Body::STRUCT_TYPE, Indent(true), BARE); return print(value, schema2::Type::STRUCT, Indent(true), BARE);
} }
kj::StringTree prettyPrint(DynamicList::Reader value) { kj::StringTree prettyPrint(DynamicList::Reader value) {
return print(value, schema::Type::Body::LIST_TYPE, Indent(true), BARE); return print(value, schema2::Type::LIST, Indent(true), BARE);
} }
kj::StringTree prettyPrint(DynamicStruct::Builder value) { return prettyPrint(value.asReader()); } kj::StringTree prettyPrint(DynamicStruct::Builder value) { return prettyPrint(value.asReader()); }
...@@ -260,8 +249,6 @@ kj::StringTree KJ_STRINGIFY(const DynamicValue::Reader& value) { return stringif ...@@ -260,8 +249,6 @@ kj::StringTree KJ_STRINGIFY(const DynamicValue::Reader& value) { return stringif
kj::StringTree KJ_STRINGIFY(const DynamicValue::Builder& value) { return stringify(value.asReader()); } kj::StringTree KJ_STRINGIFY(const DynamicValue::Builder& value) { return stringify(value.asReader()); }
kj::StringTree KJ_STRINGIFY(DynamicEnum value) { return stringify(value); } kj::StringTree KJ_STRINGIFY(DynamicEnum value) { return stringify(value); }
kj::StringTree KJ_STRINGIFY(const DynamicObject& value) { return stringify(value); } kj::StringTree KJ_STRINGIFY(const DynamicObject& value) { return stringify(value); }
kj::StringTree KJ_STRINGIFY(const DynamicUnion::Reader& value) { return stringify(value); }
kj::StringTree KJ_STRINGIFY(const DynamicUnion::Builder& value) { return stringify(value.asReader()); }
kj::StringTree KJ_STRINGIFY(const DynamicStruct::Reader& value) { return stringify(value); } kj::StringTree KJ_STRINGIFY(const DynamicStruct::Reader& value) { return stringify(value); }
kj::StringTree KJ_STRINGIFY(const DynamicStruct::Builder& value) { return stringify(value.asReader()); } kj::StringTree KJ_STRINGIFY(const DynamicStruct::Builder& value) { return stringify(value.asReader()); }
kj::StringTree KJ_STRINGIFY(const DynamicList::Reader& value) { return stringify(value); } kj::StringTree KJ_STRINGIFY(const DynamicList::Reader& value) { return stringify(value); }
...@@ -273,11 +260,6 @@ kj::StringTree structString(StructReader reader, const RawSchema& schema) { ...@@ -273,11 +260,6 @@ kj::StringTree structString(StructReader reader, const RawSchema& schema) {
return stringify(DynamicStruct::Reader(StructSchema(&schema), reader)); return stringify(DynamicStruct::Reader(StructSchema(&schema), reader));
} }
kj::StringTree unionString(StructReader reader, const RawSchema& schema, uint memberIndex) {
return stringify(DynamicUnion::Reader(
StructSchema(&schema).getMembers()[memberIndex].asUnion(), reader));
}
} // namespace _ (private) } // namespace _ (private)
} // namespace capnp } // namespace capnp
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