Commit 87ea5bdb authored by Kenton Varda's avatar Kenton Varda

Generics: Schema/dynamic API support.

parent d7b612a1
...@@ -30,7 +30,7 @@ static const ::capnp::_::AlignedData<21> b_b9c6f99ebf805f2c = { ...@@ -30,7 +30,7 @@ static const ::capnp::_::AlignedData<21> b_b9c6f99ebf805f2c = {
}; };
const ::capnp::_::RawSchema s_b9c6f99ebf805f2c = { const ::capnp::_::RawSchema s_b9c6f99ebf805f2c = {
0xb9c6f99ebf805f2c, b_b9c6f99ebf805f2c.words, 21, nullptr, nullptr, 0xb9c6f99ebf805f2c, b_b9c6f99ebf805f2c.words, 21, nullptr, nullptr,
0, 0, nullptr, nullptr, nullptr 0, 0, nullptr, nullptr, nullptr, { &s_b9c6f99ebf805f2c, nullptr, nullptr, 0, 0, nullptr }
}; };
static const ::capnp::_::AlignedData<20> b_f264a779fef191ce = { static const ::capnp::_::AlignedData<20> b_f264a779fef191ce = {
{ 0, 0, 0, 0, 5, 0, 6, 0, { 0, 0, 0, 0, 5, 0, 6, 0,
...@@ -56,7 +56,7 @@ static const ::capnp::_::AlignedData<20> b_f264a779fef191ce = { ...@@ -56,7 +56,7 @@ static const ::capnp::_::AlignedData<20> b_f264a779fef191ce = {
}; };
const ::capnp::_::RawSchema s_f264a779fef191ce = { const ::capnp::_::RawSchema s_f264a779fef191ce = {
0xf264a779fef191ce, b_f264a779fef191ce.words, 20, nullptr, nullptr, 0xf264a779fef191ce, b_f264a779fef191ce.words, 20, nullptr, nullptr,
0, 0, nullptr, nullptr, nullptr 0, 0, nullptr, nullptr, nullptr, { &s_f264a779fef191ce, nullptr, nullptr, 0, 0, nullptr }
}; };
} // namespace schemas } // namespace schemas
namespace _ { // private namespace _ { // private
......
...@@ -1005,8 +1005,6 @@ public: ...@@ -1005,8 +1005,6 @@ public:
// Set up stuff for the ValueTranslator. // Set up stuff for the ValueTranslator.
ValueResolverGlue resolver(compiler->getLoader(), errorReporter); ValueResolverGlue resolver(compiler->getLoader(), errorReporter);
auto type = arena.getOrphanage().newOrphan<schema::Type>();
type.get().initStruct().setTypeId(rootType.getProto().getId());
// Set up output stream. // Set up output stream.
kj::FdOutputStream rawOutput(STDOUT_FILENO); kj::FdOutputStream rawOutput(STDOUT_FILENO);
...@@ -1019,7 +1017,7 @@ public: ...@@ -1019,7 +1017,7 @@ public:
segmentSize == 0 ? SUGGESTED_ALLOCATION_STRATEGY : AllocationStrategy::FIXED_SIZE); segmentSize == 0 ? SUGGESTED_ALLOCATION_STRATEGY : AllocationStrategy::FIXED_SIZE);
ValueTranslator translator(resolver, errorReporter, item.getOrphanage()); ValueTranslator translator(resolver, errorReporter, item.getOrphanage());
KJ_IF_MAYBE(value, translator.compileValue(expression->getReader(), type.getReader())) { KJ_IF_MAYBE(value, translator.compileValue(expression->getReader(), rootType)) {
if (segmentSize == 0) { if (segmentSize == 0) {
writeFlat(value->getReader().as<DynamicStruct>(), output); writeFlat(value->getReader().as<DynamicStruct>(), output);
} else { } else {
......
...@@ -1679,7 +1679,7 @@ private: ...@@ -1679,7 +1679,7 @@ private:
membersByName.size() == 0 ? kj::strTree("nullptr") : kj::strTree("m_", hexId), ",\n", membersByName.size() == 0 ? kj::strTree("nullptr") : kj::strTree("m_", hexId), ",\n",
" ", deps.size(), ", ", membersByName.size(), ", ", " ", deps.size(), ", ", membersByName.size(), ", ",
membersByDiscrim.size() == 0 ? kj::strTree("nullptr") : kj::strTree("i_", hexId), membersByDiscrim.size() == 0 ? kj::strTree("nullptr") : kj::strTree("i_", hexId),
", nullptr, nullptr\n" ", nullptr, nullptr, { &s_", hexId, ", nullptr, nullptr, 0, 0, nullptr }\n"
"};\n"); "};\n");
NodeTextNoSchema top = makeNodeTextWithoutNested( NodeTextNoSchema top = makeNodeTextWithoutNested(
......
...@@ -122,7 +122,16 @@ private: ...@@ -122,7 +122,16 @@ private:
std::map<uint64_t, List<schema::TypeEnvironment::Binding>::Reader> scopeBindings; std::map<uint64_t, List<schema::TypeEnvironment::Binding>::Reader> scopeBindings;
for (auto scopeEnv: env.getScopes()) { for (auto scopeEnv: env.getScopes()) {
scopeBindings[scopeEnv.getScopeId()] = scopeEnv.getBindings(); switch (scopeEnv.which()) {
case schema::TypeEnvironment::Scope::BIND:
scopeBindings[scopeEnv.getScopeId()] = scopeEnv.getBind();
break;
case schema::TypeEnvironment::Scope::INHERIT:
// TODO(someday): We need to pay attention to INHERIT and be sure to explicitly override
// any bindings that are not inherited. This requires a way to determine which of our
// parent scopes have a non-empty parameter list.
break;
}
} }
{ {
...@@ -283,7 +292,7 @@ private: ...@@ -283,7 +292,7 @@ private:
return true; return true;
} }
kj::StringTree genValue(schema::Type::Reader type, schema::Value::Reader value, Schema scope) { kj::StringTree genValue(Type type, schema::Value::Reader value) {
switch (value.which()) { switch (value.which()) {
case schema::Value::VOID: return kj::strTree("void"); case schema::Value::VOID: return kj::strTree("void");
case schema::Value::BOOL: case schema::Value::BOOL:
...@@ -303,23 +312,19 @@ private: ...@@ -303,23 +312,19 @@ private:
case schema::Value::DATA: case schema::Value::DATA:
return kj::strTree(DynamicValue::Reader(value.getData())); return kj::strTree(DynamicValue::Reader(value.getData()));
case schema::Value::LIST: { case schema::Value::LIST: {
KJ_REQUIRE(type.isList(), "type/value mismatch"); auto listValue = value.getList().getAs<DynamicList>(type.asList());
auto listValue = value.getList().getAs<DynamicList>(
ListSchema::of(type.getList().getElementType(), scope));
return kj::strTree(listValue); return kj::strTree(listValue);
} }
case schema::Value::ENUM: { case schema::Value::ENUM: {
KJ_REQUIRE(type.isEnum(), "type/value mismatch"); auto enumNode = type.asEnum().getProto();
auto enumNode = schemaLoader.get(type.getEnum().getTypeId()).asEnum().getProto();
auto enumerants = enumNode.getEnum().getEnumerants(); auto enumerants = enumNode.getEnum().getEnumerants();
KJ_REQUIRE(value.getEnum() < enumerants.size(), KJ_REQUIRE(value.getEnum() < enumerants.size(),
"Enum value out-of-range.", value.getEnum(), enumNode.getDisplayName()); "Enum value out-of-range.", value.getEnum(), enumNode.getDisplayName());
return kj::strTree(enumerants[value.getEnum()].getName()); return kj::strTree(enumerants[value.getEnum()].getName());
} }
case schema::Value::STRUCT: { case schema::Value::STRUCT: {
KJ_REQUIRE(type.isStruct(), "type/value mismatch"); KJ_REQUIRE(type.which() == schema::Type::STRUCT, "type/value mismatch");
auto structValue = value.getStruct().getAs<DynamicStruct>( auto structValue = value.getStruct().getAs<DynamicStruct>(type.asStruct());
schemaLoader.get(type.getStruct().getTypeId()).asStruct());
return kj::strTree(structValue); return kj::strTree(structValue);
} }
case schema::Value::INTERFACE: { case schema::Value::INTERFACE: {
...@@ -348,12 +353,13 @@ private: ...@@ -348,12 +353,13 @@ private:
kj::StringTree genAnnotation(schema::Annotation::Reader annotation, kj::StringTree genAnnotation(schema::Annotation::Reader annotation,
Schema scope, Schema scope,
const char* prefix = " ", const char* suffix = "") { const char* prefix = " ", const char* suffix = "") {
auto decl = schemaLoader.get(annotation.getId()); auto decl = schemaLoader.get(annotation.getId(), annotation.getTypeEnvironment(), scope);
auto proto = decl.getProto(); auto proto = decl.getProto();
KJ_REQUIRE(proto.isAnnotation()); KJ_REQUIRE(proto.isAnnotation());
auto annDecl = proto.getAnnotation(); auto annDecl = proto.getAnnotation();
auto value = genValue(annDecl.getType(), annotation.getValue(), decl).flatten(); auto value = genValue(schemaLoader.getType(annDecl.getType(), decl),
annotation.getValue()).flatten();
if (value.startsWith("(")) { if (value.startsWith("(")) {
return kj::strTree(prefix, "$", nodeName(decl, scope, annotation.getTypeEnvironment()), return kj::strTree(prefix, "$", nodeName(decl, scope, annotation.getTypeEnvironment()),
value, suffix); value, suffix);
...@@ -419,42 +425,42 @@ private: ...@@ -419,42 +425,42 @@ private:
return kj::strTree( return kj::strTree(
indent, "union { # tag bits [", offset * 16, ", ", offset * 16 + 16, ")\n", indent, "union { # tag bits [", offset * 16, ", ", offset * 16 + 16, ")\n",
KJ_MAP(uField, unionFields) { KJ_MAP(uField, unionFields) {
return genStructField(uField.getProto(), schema, indent.next()); return genStructField(uField, schema, indent.next());
}, },
indent, "}\n"); indent, "}\n");
} }
} else { } else {
return genStructField(field.getProto(), schema, indent); return genStructField(field, schema, indent);
} }
}; };
} }
kj::StringTree genStructField(schema::Field::Reader field, Schema scope, Indent indent) { kj::StringTree genStructField(StructSchema::Field field, Schema scope, Indent indent) {
switch (field.which()) { auto proto = field.getProto();
switch (proto.which()) {
case schema::Field::SLOT: { case schema::Field::SLOT: {
auto slot = field.getSlot(); auto slot = proto.getSlot();
int size = typeSizeBits(slot.getType()); int size = typeSizeBits(slot.getType());
return kj::strTree( return kj::strTree(
indent, field.getName(), " @", field.getOrdinal().getExplicit(), indent, proto.getName(), " @", proto.getOrdinal().getExplicit(),
" :", genType(slot.getType(), scope), " :", genType(slot.getType(), scope),
isEmptyValue(slot.getDefaultValue()) ? kj::strTree("") : isEmptyValue(slot.getDefaultValue()) ? kj::strTree("") :
kj::strTree(" = ", genValue( kj::strTree(" = ", genValue(field.getType(), slot.getDefaultValue())),
slot.getType(), slot.getDefaultValue(), scope)), genAnnotations(proto.getAnnotations(), scope),
genAnnotations(field.getAnnotations(), scope),
"; # ", size == -1 ? kj::strTree("ptr[", slot.getOffset(), "]") "; # ", size == -1 ? kj::strTree("ptr[", slot.getOffset(), "]")
: kj::strTree("bits[", slot.getOffset() * size, ", ", : kj::strTree("bits[", slot.getOffset() * size, ", ",
(slot.getOffset() + 1) * size, ")"), (slot.getOffset() + 1) * size, ")"),
hasDiscriminantValue(field) hasDiscriminantValue(proto)
? kj::strTree(", union tag = ", field.getDiscriminantValue()) : kj::strTree(), ? kj::strTree(", union tag = ", proto.getDiscriminantValue()) : kj::strTree(),
"\n"); "\n");
} }
case schema::Field::GROUP: { case schema::Field::GROUP: {
auto group = schemaLoader.get(field.getGroup().getTypeId()).asStruct(); auto group = field.getType().asStruct();
return kj::strTree( return kj::strTree(
indent, field.getName(), indent, proto.getName(),
" :group", genAnnotations(field.getAnnotations(), scope), " {", " :group", genAnnotations(proto.getAnnotations(), scope), " {",
hasDiscriminantValue(field) hasDiscriminantValue(proto)
? kj::strTree(" # union tag = ", field.getDiscriminantValue()) : kj::strTree(), ? kj::strTree(" # union tag = ", proto.getDiscriminantValue()) : kj::strTree(),
"\n", "\n",
genStructFields(group, indent.next()), genStructFields(group, indent.next()),
indent, "}\n"); indent, "}\n");
...@@ -475,8 +481,7 @@ private: ...@@ -475,8 +481,7 @@ private:
return kj::strTree( return kj::strTree(
proto.getName(), " :", genType(slot.getType(), interface), proto.getName(), " :", genType(slot.getType(), interface),
isEmptyValue(slot.getDefaultValue()) ? kj::strTree("") : isEmptyValue(slot.getDefaultValue()) ? kj::strTree("") :
kj::strTree(" = ", genValue( kj::strTree(" = ", genValue(field.getType(), slot.getDefaultValue())),
slot.getType(), slot.getDefaultValue(), interface)),
genAnnotations(proto.getAnnotations(), interface)); genAnnotations(proto.getAnnotations(), interface));
}, ", "), ")"); }, ", "), ")");
} else { } else {
...@@ -518,7 +523,8 @@ private: ...@@ -518,7 +523,8 @@ private:
structProto.getPointerCount(), " ptrs", structProto.getPointerCount(), " ptrs",
structProto.getPreferredListEncoding() == schema::ElementSize::INLINE_COMPOSITE structProto.getPreferredListEncoding() == schema::ElementSize::INLINE_COMPOSITE
? kj::strTree() ? kj::strTree()
: kj::strTree(", packed as ", elementSizeName(structProto.getPreferredListEncoding())), : kj::strTree(", packed as ",
elementSizeName(structProto.getPreferredListEncoding())),
"\n", "\n",
genStructFields(schema.asStruct(), indent.next()), genStructFields(schema.asStruct(), indent.next()),
genNestedDecls(schema, indent.next()), genNestedDecls(schema, indent.next()),
...@@ -560,7 +566,7 @@ private: ...@@ -560,7 +566,7 @@ private:
return kj::strTree( return kj::strTree(
indent, "const ", name, " @0x", kj::hex(proto.getId()), " :", indent, "const ", name, " @0x", kj::hex(proto.getId()), " :",
genType(constProto.getType(), schema), " = ", genType(constProto.getType(), schema), " = ",
genValue(constProto.getType(), constProto.getValue(), schema), genValue(schema.asConst().getType(), constProto.getValue()),
genAnnotations(schema), ";\n"); genAnnotations(schema), ";\n");
} }
case schema::Node::ANNOTATION: { case schema::Node::ANNOTATION: {
......
...@@ -86,10 +86,13 @@ public: ...@@ -86,10 +86,13 @@ public:
kj::Maybe<kj::OneOf<ResolvedDecl, ResolvedParameter, ResolvedAlias>> kj::Maybe<kj::OneOf<ResolvedDecl, ResolvedParameter, ResolvedAlias>>
resolve(kj::StringPtr name) override; resolve(kj::StringPtr name) override;
kj::Maybe<kj::OneOf<ResolvedDecl, ResolvedAlias>> resolveMember(kj::StringPtr name) override; kj::Maybe<kj::OneOf<ResolvedDecl, ResolvedAlias>> resolveMember(kj::StringPtr name) override;
kj::Maybe<ResolvedDecl> getParent() override;
ResolvedDecl getTopScope() override; ResolvedDecl getTopScope() override;
kj::Maybe<Schema> resolveBootstrapSchema(uint64_t id) override; kj::Maybe<Schema> resolveBootstrapSchema(
uint64_t id, schema::TypeEnvironment::Reader environment) override;
kj::Maybe<schema::Node::Reader> resolveFinalSchema(uint64_t id) override; kj::Maybe<schema::Node::Reader> resolveFinalSchema(uint64_t id) override;
kj::Maybe<ResolvedDecl> resolveImport(kj::StringPtr name) override; kj::Maybe<ResolvedDecl> resolveImport(kj::StringPtr name) override;
kj::Maybe<Type> resolveBootstrapType(schema::Type::Reader type, Schema scope) override;
private: private:
CompiledModule* module; // null iff isBuiltin is true CompiledModule* module; // null iff isBuiltin is true
...@@ -732,14 +735,20 @@ void Compiler::Node::traverseEnvironment( ...@@ -732,14 +735,20 @@ void Compiler::Node::traverseEnvironment(
std::unordered_map<Node*, uint>& seen, std::unordered_map<Node*, uint>& seen,
const SchemaLoader& finalLoader) { const SchemaLoader& finalLoader) {
for (auto scope: env.getScopes()) { for (auto scope: env.getScopes()) {
for (auto binding: scope.getBindings()) { switch (scope.which()) {
switch (binding.which()) { case schema::TypeEnvironment::Scope::BIND:
case schema::TypeEnvironment::Binding::UNBOUND: for (auto binding: scope.getBind()) {
break; switch (binding.which()) {
case schema::TypeEnvironment::Binding::TYPE: case schema::TypeEnvironment::Binding::UNBOUND:
traverseType(binding.getType(), eagerness, seen, finalLoader); break;
break; case schema::TypeEnvironment::Binding::TYPE:
} traverseType(binding.getType(), eagerness, seen, finalLoader);
break;
}
}
break;
case schema::TypeEnvironment::Scope::INHERIT:
break;
} }
} }
} }
...@@ -841,14 +850,28 @@ Compiler::Node::resolveMember(kj::StringPtr name) { ...@@ -841,14 +850,28 @@ Compiler::Node::resolveMember(kj::StringPtr name) {
return nullptr; return nullptr;
} }
kj::Maybe<NodeTranslator::Resolver::ResolvedDecl> Compiler::Node::getParent() {
return parent.map([](Node& parent) {
uint64_t scopeId = parent.parent.map([](Node& gp) { return gp.id; }).orDefault(0);
return ResolvedDecl { parent.id, parent.genericParamCount, scopeId, parent.kind, &parent };
});
}
NodeTranslator::Resolver::ResolvedDecl Compiler::Node::getTopScope() { NodeTranslator::Resolver::ResolvedDecl Compiler::Node::getTopScope() {
Node& node = module->getRootNode(); Node& node = module->getRootNode();
return ResolvedDecl { node.id, 0, 0, node.kind, &node }; return ResolvedDecl { node.id, 0, 0, node.kind, &node };
} }
kj::Maybe<Schema> Compiler::Node::resolveBootstrapSchema(uint64_t id) { kj::Maybe<Schema> Compiler::Node::resolveBootstrapSchema(
uint64_t id, schema::TypeEnvironment::Reader environment) {
KJ_IF_MAYBE(node, module->getCompiler().findNode(id)) { KJ_IF_MAYBE(node, module->getCompiler().findNode(id)) {
return node->getBootstrapSchema(); // Make sure the bootstrap schema is loaded into the SchemaLoader.
if (node->getBootstrapSchema() == nullptr) {
return nullptr;
}
// Now we actually invoke get() to evaluate the environment.
return module->getCompiler().getWorkspace().bootstrapLoader.get(id, environment);
} else { } else {
KJ_FAIL_REQUIRE("Tried to get schema for ID we haven't seen before."); KJ_FAIL_REQUIRE("Tried to get schema for ID we haven't seen before.");
} }
...@@ -872,6 +895,22 @@ Compiler::Node::resolveImport(kj::StringPtr name) { ...@@ -872,6 +895,22 @@ Compiler::Node::resolveImport(kj::StringPtr name) {
} }
} }
kj::Maybe<Type> Compiler::Node::resolveBootstrapType(schema::Type::Reader type, Schema scope) {
// TODO(someday): Arguably should return null if the type or its dependencies are placeholders.
kj::Maybe<Type> result;
KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() {
result = module->getCompiler().getWorkspace().bootstrapLoader.getType(type, scope);
})) {
result = nullptr;
if (!module->getErrorReporter().hadErrors()) {
addError(kj::str("Internal compiler bug: Bootstrap schema failed to load:\n",
*exception));
}
}
return result;
}
// ======================================================================================= // =======================================================================================
Compiler::CompiledModule::CompiledModule(Compiler::Impl& compiler, Module& parserModule) Compiler::CompiledModule::CompiledModule(Compiler::Impl& compiler, Module& parserModule)
......
This diff is collapsed.
...@@ -209,7 +209,7 @@ static const uint16_t m_91cc55cd57de5419[] = {9, 6, 8, 3, 0, 2, 4, 5, 7, 1}; ...@@ -209,7 +209,7 @@ static const uint16_t m_91cc55cd57de5419[] = {9, 6, 8, 3, 0, 2, 4, 5, 7, 1};
static const uint16_t i_91cc55cd57de5419[] = {0, 1, 2, 3, 4, 5, 6, 9, 7, 8}; static const uint16_t i_91cc55cd57de5419[] = {0, 1, 2, 3, 4, 5, 6, 9, 7, 8};
const ::capnp::_::RawSchema s_91cc55cd57de5419 = { const ::capnp::_::RawSchema s_91cc55cd57de5419 = {
0x91cc55cd57de5419, b_91cc55cd57de5419.words, 195, d_91cc55cd57de5419, m_91cc55cd57de5419, 0x91cc55cd57de5419, b_91cc55cd57de5419.words, 195, d_91cc55cd57de5419, m_91cc55cd57de5419,
1, 10, i_91cc55cd57de5419, nullptr, nullptr 1, 10, i_91cc55cd57de5419, nullptr, nullptr, { &s_91cc55cd57de5419, nullptr, nullptr, 0, 0, nullptr }
}; };
static const ::capnp::_::AlignedData<119> b_c6725e678d60fa37 = { static const ::capnp::_::AlignedData<119> b_c6725e678d60fa37 = {
{ 0, 0, 0, 0, 5, 0, 6, 0, { 0, 0, 0, 0, 5, 0, 6, 0,
...@@ -340,7 +340,7 @@ static const uint16_t m_c6725e678d60fa37[] = {2, 3, 5, 1, 4, 0}; ...@@ -340,7 +340,7 @@ static const uint16_t m_c6725e678d60fa37[] = {2, 3, 5, 1, 4, 0};
static const uint16_t i_c6725e678d60fa37[] = {1, 2, 0, 3, 4, 5}; static const uint16_t i_c6725e678d60fa37[] = {1, 2, 0, 3, 4, 5};
const ::capnp::_::RawSchema s_c6725e678d60fa37 = { const ::capnp::_::RawSchema s_c6725e678d60fa37 = {
0xc6725e678d60fa37, b_c6725e678d60fa37.words, 119, d_c6725e678d60fa37, m_c6725e678d60fa37, 0xc6725e678d60fa37, b_c6725e678d60fa37.words, 119, d_c6725e678d60fa37, m_c6725e678d60fa37,
2, 6, i_c6725e678d60fa37, nullptr, nullptr 2, 6, i_c6725e678d60fa37, nullptr, nullptr, { &s_c6725e678d60fa37, nullptr, nullptr, 0, 0, nullptr }
}; };
static const ::capnp::_::AlignedData<38> b_9e69a92512b19d18 = { static const ::capnp::_::AlignedData<38> b_9e69a92512b19d18 = {
{ 0, 0, 0, 0, 5, 0, 6, 0, { 0, 0, 0, 0, 5, 0, 6, 0,
...@@ -389,7 +389,7 @@ static const uint16_t m_9e69a92512b19d18[] = {0}; ...@@ -389,7 +389,7 @@ static const uint16_t m_9e69a92512b19d18[] = {0};
static const uint16_t i_9e69a92512b19d18[] = {0}; static const uint16_t i_9e69a92512b19d18[] = {0};
const ::capnp::_::RawSchema s_9e69a92512b19d18 = { const ::capnp::_::RawSchema s_9e69a92512b19d18 = {
0x9e69a92512b19d18, b_9e69a92512b19d18.words, 38, d_9e69a92512b19d18, m_9e69a92512b19d18, 0x9e69a92512b19d18, b_9e69a92512b19d18.words, 38, d_9e69a92512b19d18, m_9e69a92512b19d18,
1, 1, i_9e69a92512b19d18, nullptr, nullptr 1, 1, i_9e69a92512b19d18, nullptr, nullptr, { &s_9e69a92512b19d18, nullptr, nullptr, 0, 0, nullptr }
}; };
static const ::capnp::_::AlignedData<40> b_a11f97b9d6c73dd4 = { static const ::capnp::_::AlignedData<40> b_a11f97b9d6c73dd4 = {
{ 0, 0, 0, 0, 5, 0, 6, 0, { 0, 0, 0, 0, 5, 0, 6, 0,
...@@ -440,7 +440,7 @@ static const uint16_t m_a11f97b9d6c73dd4[] = {0}; ...@@ -440,7 +440,7 @@ static const uint16_t m_a11f97b9d6c73dd4[] = {0};
static const uint16_t i_a11f97b9d6c73dd4[] = {0}; static const uint16_t i_a11f97b9d6c73dd4[] = {0};
const ::capnp::_::RawSchema s_a11f97b9d6c73dd4 = { const ::capnp::_::RawSchema s_a11f97b9d6c73dd4 = {
0xa11f97b9d6c73dd4, b_a11f97b9d6c73dd4.words, 40, d_a11f97b9d6c73dd4, m_a11f97b9d6c73dd4, 0xa11f97b9d6c73dd4, b_a11f97b9d6c73dd4.words, 40, d_a11f97b9d6c73dd4, m_a11f97b9d6c73dd4,
1, 1, i_a11f97b9d6c73dd4, nullptr, nullptr 1, 1, i_a11f97b9d6c73dd4, nullptr, nullptr, { &s_a11f97b9d6c73dd4, nullptr, nullptr, 0, 0, nullptr }
}; };
} // namespace schemas } // namespace schemas
namespace _ { // private namespace _ { // private
......
This diff is collapsed.
...@@ -73,13 +73,17 @@ public: ...@@ -73,13 +73,17 @@ public:
virtual kj::Maybe<kj::OneOf<ResolvedDecl, ResolvedAlias>> resolveMember(kj::StringPtr name) = 0; virtual kj::Maybe<kj::OneOf<ResolvedDecl, ResolvedAlias>> resolveMember(kj::StringPtr name) = 0;
// Look up a member of this node. // Look up a member of this node.
virtual kj::Maybe<ResolvedDecl> getParent() = 0;
// Returns the parent of this scope, or null if this is the top scope.
virtual ResolvedDecl getTopScope() = 0; virtual ResolvedDecl getTopScope() = 0;
// Get the top-level scope containing this node. // Get the top-level scope containing this node.
virtual kj::Maybe<Schema> resolveBootstrapSchema(uint64_t id) = 0; virtual kj::Maybe<Schema> resolveBootstrapSchema(uint64_t id,
schema::TypeEnvironment::Reader environment) = 0;
// Get the schema for the given ID. If a schema is returned, it must be safe to traverse its // Get the schema for the given ID. If a schema is returned, it must be safe to traverse its
// dependencies using Schema::getDependency(). A schema that is only at the bootstrap stage // dependencies via the Schema API. A schema that is only at the bootstrap stage is
// is acceptable. // acceptable.
// //
// Throws an exception if the id is not one that was found by calling resolve() or by // Throws an exception if the id is not one that was found by calling resolve() or by
// traversing other schemas. Returns null if the ID is recognized, but the corresponding // traversing other schemas. Returns null if the ID is recognized, but the corresponding
...@@ -97,6 +101,13 @@ public: ...@@ -97,6 +101,13 @@ public:
virtual kj::Maybe<ResolvedDecl> resolveImport(kj::StringPtr name) = 0; virtual kj::Maybe<ResolvedDecl> resolveImport(kj::StringPtr name) = 0;
// Get the ID of an imported file given the import path. // Get the ID of an imported file given the import path.
virtual kj::Maybe<Type> resolveBootstrapType(schema::Type::Reader type, Schema scope) = 0;
// Compile a schema::Type into a Type whose dependencies may safely be traversed via the schema
// API. These dependencies may have only bootstrap schemas. Returns null if the type could not
// be constructed due to already-reported errors.
//
// `scope` is the schema
}; };
NodeTranslator(Resolver& resolver, ErrorReporter& errorReporter, NodeTranslator(Resolver& resolver, ErrorReporter& errorReporter,
...@@ -106,6 +117,8 @@ public: ...@@ -106,6 +117,8 @@ public:
// `displayName`, `id`, `scopeId`, and `nestedNodes` already initialized. The `NodeTranslator` // `displayName`, `id`, `scopeId`, and `nestedNodes` already initialized. The `NodeTranslator`
// fills in the rest. // fills in the rest.
~NodeTranslator();
struct NodeSet { struct NodeSet {
schema::Node::Reader node; schema::Node::Reader node;
// The main node. // The main node.
...@@ -130,10 +143,18 @@ public: ...@@ -130,10 +143,18 @@ public:
// bootstrap node) and return it. // bootstrap node) and return it.
private: private:
class DuplicateNameDetector;
class DuplicateOrdinalDetector;
class StructLayout;
class StructTranslator;
class DeclInstance;
class TypeEnvironment;
Resolver& resolver; Resolver& resolver;
ErrorReporter& errorReporter; ErrorReporter& errorReporter;
Orphanage orphanage; Orphanage orphanage;
bool compileAnnotations; bool compileAnnotations;
kj::Own<TypeEnvironment> baseEnvironment;
Orphan<schema::Node> wipNode; Orphan<schema::Node> wipNode;
// The work-in-progress schema node. // The work-in-progress schema node.
...@@ -148,6 +169,7 @@ private: ...@@ -148,6 +169,7 @@ private:
struct UnfinishedValue { struct UnfinishedValue {
Expression::Reader source; Expression::Reader source;
schema::Type::Reader type; schema::Type::Reader type;
Schema typeScope;
schema::Value::Builder target; schema::Value::Builder target;
}; };
kj::Vector<UnfinishedValue> unfinishedValues; kj::Vector<UnfinishedValue> unfinishedValues;
...@@ -162,13 +184,6 @@ private: ...@@ -162,13 +184,6 @@ private:
void compileAnnotation(Declaration::Annotation::Reader decl, void compileAnnotation(Declaration::Annotation::Reader decl,
schema::Node::Annotation::Builder builder); schema::Node::Annotation::Builder builder);
class DuplicateNameDetector;
class DuplicateOrdinalDetector;
class StructLayout;
class StructTranslator;
class DeclInstance;
class TypeEnvironment;
void compileEnum(Void decl, List<Declaration>::Reader members, void compileEnum(Void decl, List<Declaration>::Reader members,
schema::Node::Builder builder); schema::Node::Builder builder);
void compileStruct(Void decl, List<Declaration>::Reader members, void compileStruct(Void decl, List<Declaration>::Reader members,
...@@ -198,23 +213,26 @@ private: ...@@ -198,23 +213,26 @@ private:
void compileDefaultDefaultValue(schema::Type::Reader type, schema::Value::Builder target); void compileDefaultDefaultValue(schema::Type::Reader type, schema::Value::Builder target);
// Initializes `target` to contain the "default default" value for `type`. // Initializes `target` to contain the "default default" value for `type`.
void compileBootstrapValue(Expression::Reader source, schema::Type::Reader type, void compileBootstrapValue(
schema::Value::Builder target); Expression::Reader source, schema::Type::Reader type, schema::Value::Builder target,
Schema typeScope = Schema());
// Calls compileValue() if this value should be interpreted at bootstrap time. Otheriwse, // Calls compileValue() if this value should be interpreted at bootstrap time. Otheriwse,
// adds the value to `unfinishedValues` for later evaluation. // adds the value to `unfinishedValues` for later evaluation.
//
// If `type` comes from some other node, `typeScope` is the schema for that node. This is only
// really needed for looking up generic parameter bindings, therefore if the type comes from
// the node being built, an empty "Schema" (the default) works here because the node being built
// is of course being built for all possible bindings and thus none of its generic parameters are
// bound.
void compileValue(Expression::Reader source, schema::Type::Reader type, void compileValue(Expression::Reader source, schema::Type::Reader type,
schema::Value::Builder target, bool isBootstrap); Schema typeScope, schema::Value::Builder target, bool isBootstrap);
// Interprets the value expression and initializes `target` with the result. // Interprets the value expression and initializes `target` with the result.
kj::Maybe<DynamicValue::Reader> readConstant(Expression::Reader name, bool isBootstrap); kj::Maybe<DynamicValue::Reader> readConstant(Expression::Reader name, bool isBootstrap);
// Get the value of the given constant. May return null if some error occurs, which will already // Get the value of the given constant. May return null if some error occurs, which will already
// have been reported. // have been reported.
kj::Maybe<ListSchema> makeListSchemaOf(schema::Type::Reader elementType);
// Construct a list schema representing a list of elements of the given type. May return null if
// some error occurs, which will already have been reported.
Orphan<List<schema::Annotation>> compileAnnotationApplications( Orphan<List<schema::Annotation>> compileAnnotationApplications(
List<Declaration::AnnotationApplication>::Reader annotations, List<Declaration::AnnotationApplication>::Reader annotations,
kj::StringPtr targetsFlagName); kj::StringPtr targetsFlagName);
...@@ -224,29 +242,28 @@ class ValueTranslator { ...@@ -224,29 +242,28 @@ class ValueTranslator {
public: public:
class Resolver { class Resolver {
public: public:
virtual kj::Maybe<Schema> resolveType(uint64_t id) = 0;
virtual kj::Maybe<DynamicValue::Reader> resolveConstant(Expression::Reader name) = 0; virtual kj::Maybe<DynamicValue::Reader> resolveConstant(Expression::Reader name) = 0;
}; };
ValueTranslator(Resolver& resolver, ErrorReporter& errorReporter, Orphanage orphanage) ValueTranslator(Resolver& resolver, ErrorReporter& errorReporter, Orphanage orphanage)
: resolver(resolver), errorReporter(errorReporter), orphanage(orphanage) {} : resolver(resolver), errorReporter(errorReporter), orphanage(orphanage) {}
kj::Maybe<Orphan<DynamicValue>> compileValue(Expression::Reader src, schema::Type::Reader type); kj::Maybe<Orphan<DynamicValue>> compileValue(Expression::Reader src, Type type);
private: private:
Resolver& resolver; Resolver& resolver;
ErrorReporter& errorReporter; ErrorReporter& errorReporter;
Orphanage orphanage; Orphanage orphanage;
Orphan<DynamicValue> compileValueInner(Expression::Reader src, schema::Type::Reader type); Orphan<DynamicValue> compileValueInner(Expression::Reader src, Type type);
// Helper for compileValue(). // Helper for compileValue().
void fillStructValue(DynamicStruct::Builder builder, void fillStructValue(DynamicStruct::Builder builder,
List<Expression::Param>::Reader assignments); List<Expression::Param>::Reader assignments);
// Interprets the given assignments and uses them to fill in the given struct builder. // Interprets the given assignments and uses them to fill in the given struct builder.
kj::String makeNodeName(uint64_t id); kj::String makeNodeName(Schema node);
kj::String makeTypeName(schema::Type::Reader type); kj::String makeTypeName(Type type);
kj::Maybe<ListSchema> makeListSchemaOf(schema::Type::Reader elementType); kj::Maybe<ListSchema> makeListSchemaOf(schema::Type::Reader elementType);
}; };
......
This diff is collapsed.
...@@ -208,7 +208,7 @@ private: ...@@ -208,7 +208,7 @@ private:
template <typename T, ::capnp::Kind k> template <typename T, ::capnp::Kind k>
friend struct ::capnp::ToDynamic_; friend struct ::capnp::ToDynamic_;
friend kj::StringTree _::structString( friend kj::StringTree _::structString(
_::StructReader reader, const _::RawSchema& schema); _::StructReader reader, const _::RawBrandedSchema& schema);
friend class Orphanage; friend class Orphanage;
friend class Orphan<DynamicStruct>; friend class Orphan<DynamicStruct>;
friend class Orphan<DynamicValue>; friend class Orphan<DynamicValue>;
......
...@@ -43,6 +43,97 @@ struct DynamicStruct; // So that it can be declared a friend. ...@@ -43,6 +43,97 @@ struct DynamicStruct; // So that it can be declared a friend.
namespace _ { // private namespace _ { // private
struct RawSchema;
struct RawBrandedSchema {
// Represents a combination of a schema and bindings for its generic parameters.
//
// Note that while we generate one `RawSchema` per type, we generate a `RawBrandedSchema` for
// every _instance_ of a generic type -- or, at least, every instance that is actually used. For
// generated-code types, we use template magic to initialize these.
const RawSchema* generic = nullptr;
// Generic type which we're branding.
struct Binding {
uint8_t which; // Numeric value of one of schema::Type::Which.
uint16_t listDepth; // Number of times to wrap the base type in List().
const RawBrandedSchema* schema; // may be null
};
struct Scope {
uint64_t typeId;
// Type ID whose parameters are being bound.
const Binding* bindings;
uint bindingCount;
// Bindings for those parameters.
};
const Scope* scopes = nullptr;
// Array of enclosing scopes for which generic variables have been bound, sorted by type ID.
struct Dependency {
uint location;
const RawBrandedSchema* schema;
};
const Dependency* dependencies = nullptr;
// Map of branded schemas for dependencies of this type, given our brand. Only dependencies that
// are branded are included in this map; if a dependency is missing, use its `defaultBrand`.
uint32_t scopeCount = 0;
uint32_t dependencyCount = 0;
enum class DepKind {
// Component of a Dependency::location. Specifies what sort of dependency this is.
INVALID,
// Mostly defined to ensure that zero is not a valid location.
FIELD,
// Binding needed for a field's type. The index is the field index (NOT ordinal!).
METHOD_PARAMS,
// Bindings needed for a method's params type. The index is the method number.
METHOD_RESULTS,
// Bindings needed for a method's results type. The index is the method ordinal.
SUPERCLASS,
// Bindings needed for a superclass type. The index is the superclass's index in the
// "extends" list.
CONST_TYPE
// Bindings needed for the type of a constant. The index is zero.
};
static inline uint makeDepLocation(DepKind kind, uint index) {
// Make a number representing the location of a particular dependency within its parent
// schema.
return (static_cast<uint>(kind) << 24) | index;
}
class Initializer {
public:
virtual void init(const RawBrandedSchema* generic) const = 0;
};
const Initializer* lazyInitializer = nullptr;
// Lazy initializer, invoked by ensureInitialized().
inline void ensureInitialized() const {
// Lazy initialization support. Invoke to ensure that initialization has taken place. This
// is required in particular when traversing the dependency list. RawSchemas for compiled-in
// types are always initialized; only dynamically-loaded schemas may be lazy.
const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_ACQUIRE);
if (i != nullptr) i->init(this);
}
};
struct RawSchema { struct RawSchema {
// The generated code defines a constant RawSchema for every compiled declaration. // The generated code defines a constant RawSchema for every compiled declaration.
// //
...@@ -96,6 +187,13 @@ struct RawSchema { ...@@ -96,6 +187,13 @@ struct RawSchema {
const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_ACQUIRE); const Initializer* i = __atomic_load_n(&lazyInitializer, __ATOMIC_ACQUIRE);
if (i != nullptr) i->init(this); if (i != nullptr) i->init(this);
} }
RawBrandedSchema defaultBrand;
// Specifies the brand to use for this schema if no generic parameters have been bound to
// anything. Generally, in the default brand, all generic parameters are treated as if they were
// bound to `AnyPointer`.
//
// TODO(now): Remove initializer; it's just to assist incremental changes.
}; };
template <typename T> template <typename T>
...@@ -106,6 +204,12 @@ inline const RawSchema& rawSchema() { ...@@ -106,6 +204,12 @@ inline const RawSchema& rawSchema() {
return RawSchema_<T>::get(); return RawSchema_<T>::get();
} }
template <typename T>
inline const RawBrandedSchema& rawBrandedSchema() {
// TODO(now): implement properly
return rawSchema<T>().defaultBrand;
}
template <typename T> struct TypeId_; template <typename T> struct TypeId_;
extern const RawSchema NULL_INTERFACE_SCHEMA; // defined in schema.c++ extern const RawSchema NULL_INTERFACE_SCHEMA; // defined in schema.c++
...@@ -124,13 +228,15 @@ struct UnionParentType_; ...@@ -124,13 +228,15 @@ struct UnionParentType_;
template <typename T> template <typename T>
using UnionParentType = typename UnionParentType_<T>::Type; using UnionParentType = typename UnionParentType_<T>::Type;
kj::StringTree structString(StructReader reader, const RawSchema& schema); kj::StringTree structString(StructReader reader, const RawBrandedSchema& schema);
// Declared here so that we can declare inline stringify methods on generated types. // Declared here so that we can declare inline stringify methods on generated types.
// Defined in stringify.c++, which depends on dynamic.c++, which is allowed not to be linked in. // Defined in stringify.c++, which depends on dynamic.c++, which is allowed not to be linked in.
//
// TODO(now): No default for env.
template <typename T> template <typename T>
inline kj::StringTree structString(StructReader reader) { inline kj::StringTree structString(StructReader reader) {
return structString(reader, rawSchema<T>()); return structString(reader, rawBrandedSchema<T>());
} }
// TODO(cleanup): Unify ConstStruct and ConstList. // TODO(cleanup): Unify ConstStruct and ConstList.
......
...@@ -36,7 +36,7 @@ static const ::capnp::_::AlignedData<26> b_9fd69ebc87b9719c = { ...@@ -36,7 +36,7 @@ static const ::capnp::_::AlignedData<26> b_9fd69ebc87b9719c = {
static const uint16_t m_9fd69ebc87b9719c[] = {1, 0}; static const uint16_t m_9fd69ebc87b9719c[] = {1, 0};
const ::capnp::_::RawSchema s_9fd69ebc87b9719c = { const ::capnp::_::RawSchema s_9fd69ebc87b9719c = {
0x9fd69ebc87b9719c, b_9fd69ebc87b9719c.words, 26, nullptr, m_9fd69ebc87b9719c, 0x9fd69ebc87b9719c, b_9fd69ebc87b9719c.words, 26, nullptr, m_9fd69ebc87b9719c,
0, 2, nullptr, nullptr, nullptr 0, 2, nullptr, nullptr, nullptr, { &s_9fd69ebc87b9719c, nullptr, nullptr, 0, 0, nullptr }
}; };
static const ::capnp::_::AlignedData<35> b_e615e371b1036508 = { static const ::capnp::_::AlignedData<35> b_e615e371b1036508 = {
{ 0, 0, 0, 0, 5, 0, 6, 0, { 0, 0, 0, 0, 5, 0, 6, 0,
...@@ -82,7 +82,7 @@ static const uint16_t m_e615e371b1036508[] = {0}; ...@@ -82,7 +82,7 @@ static const uint16_t m_e615e371b1036508[] = {0};
static const uint16_t i_e615e371b1036508[] = {0}; static const uint16_t i_e615e371b1036508[] = {0};
const ::capnp::_::RawSchema s_e615e371b1036508 = { const ::capnp::_::RawSchema s_e615e371b1036508 = {
0xe615e371b1036508, b_e615e371b1036508.words, 35, d_e615e371b1036508, m_e615e371b1036508, 0xe615e371b1036508, b_e615e371b1036508.words, 35, d_e615e371b1036508, m_e615e371b1036508,
1, 1, i_e615e371b1036508, nullptr, nullptr 1, 1, i_e615e371b1036508, nullptr, nullptr, { &s_e615e371b1036508, nullptr, nullptr, 0, 0, nullptr }
}; };
static const ::capnp::_::AlignedData<34> b_b88d09a9c5f39817 = { static const ::capnp::_::AlignedData<34> b_b88d09a9c5f39817 = {
{ 0, 0, 0, 0, 5, 0, 6, 0, { 0, 0, 0, 0, 5, 0, 6, 0,
...@@ -124,7 +124,7 @@ static const uint16_t m_b88d09a9c5f39817[] = {0}; ...@@ -124,7 +124,7 @@ static const uint16_t m_b88d09a9c5f39817[] = {0};
static const uint16_t i_b88d09a9c5f39817[] = {0}; static const uint16_t i_b88d09a9c5f39817[] = {0};
const ::capnp::_::RawSchema s_b88d09a9c5f39817 = { const ::capnp::_::RawSchema s_b88d09a9c5f39817 = {
0xb88d09a9c5f39817, b_b88d09a9c5f39817.words, 34, nullptr, m_b88d09a9c5f39817, 0xb88d09a9c5f39817, b_b88d09a9c5f39817.words, 34, nullptr, m_b88d09a9c5f39817,
0, 1, i_b88d09a9c5f39817, nullptr, nullptr 0, 1, i_b88d09a9c5f39817, nullptr, nullptr, { &s_b88d09a9c5f39817, nullptr, nullptr, 0, 0, nullptr }
}; };
static const ::capnp::_::AlignedData<18> b_89f389b6fd4082c1 = { static const ::capnp::_::AlignedData<18> b_89f389b6fd4082c1 = {
{ 0, 0, 0, 0, 5, 0, 6, 0, { 0, 0, 0, 0, 5, 0, 6, 0,
...@@ -148,7 +148,7 @@ static const ::capnp::_::AlignedData<18> b_89f389b6fd4082c1 = { ...@@ -148,7 +148,7 @@ static const ::capnp::_::AlignedData<18> b_89f389b6fd4082c1 = {
}; };
const ::capnp::_::RawSchema s_89f389b6fd4082c1 = { const ::capnp::_::RawSchema s_89f389b6fd4082c1 = {
0x89f389b6fd4082c1, b_89f389b6fd4082c1.words, 18, nullptr, nullptr, 0x89f389b6fd4082c1, b_89f389b6fd4082c1.words, 18, nullptr, nullptr,
0, 0, nullptr, nullptr, nullptr 0, 0, nullptr, nullptr, nullptr, { &s_89f389b6fd4082c1, nullptr, nullptr, 0, 0, nullptr }
}; };
static const ::capnp::_::AlignedData<19> b_b47f4979672cb59d = { static const ::capnp::_::AlignedData<19> b_b47f4979672cb59d = {
{ 0, 0, 0, 0, 5, 0, 6, 0, { 0, 0, 0, 0, 5, 0, 6, 0,
...@@ -173,7 +173,7 @@ static const ::capnp::_::AlignedData<19> b_b47f4979672cb59d = { ...@@ -173,7 +173,7 @@ static const ::capnp::_::AlignedData<19> b_b47f4979672cb59d = {
}; };
const ::capnp::_::RawSchema s_b47f4979672cb59d = { const ::capnp::_::RawSchema s_b47f4979672cb59d = {
0xb47f4979672cb59d, b_b47f4979672cb59d.words, 19, nullptr, nullptr, 0xb47f4979672cb59d, b_b47f4979672cb59d.words, 19, nullptr, nullptr,
0, 0, nullptr, nullptr, nullptr 0, 0, nullptr, nullptr, nullptr, { &s_b47f4979672cb59d, nullptr, nullptr, 0, 0, nullptr }
}; };
static const ::capnp::_::AlignedData<65> b_95b29059097fca83 = { static const ::capnp::_::AlignedData<65> b_95b29059097fca83 = {
{ 0, 0, 0, 0, 5, 0, 6, 0, { 0, 0, 0, 0, 5, 0, 6, 0,
...@@ -246,7 +246,7 @@ static const uint16_t m_95b29059097fca83[] = {0, 1, 2}; ...@@ -246,7 +246,7 @@ static const uint16_t m_95b29059097fca83[] = {0, 1, 2};
static const uint16_t i_95b29059097fca83[] = {0, 1, 2}; static const uint16_t i_95b29059097fca83[] = {0, 1, 2};
const ::capnp::_::RawSchema s_95b29059097fca83 = { const ::capnp::_::RawSchema s_95b29059097fca83 = {
0x95b29059097fca83, b_95b29059097fca83.words, 65, nullptr, m_95b29059097fca83, 0x95b29059097fca83, b_95b29059097fca83.words, 65, nullptr, m_95b29059097fca83,
0, 3, i_95b29059097fca83, nullptr, nullptr 0, 3, i_95b29059097fca83, nullptr, nullptr, { &s_95b29059097fca83, nullptr, nullptr, 0, 0, nullptr }
}; };
static const ::capnp::_::AlignedData<65> b_9d263a3630b7ebee = { static const ::capnp::_::AlignedData<65> b_9d263a3630b7ebee = {
{ 0, 0, 0, 0, 5, 0, 6, 0, { 0, 0, 0, 0, 5, 0, 6, 0,
...@@ -319,7 +319,7 @@ static const uint16_t m_9d263a3630b7ebee[] = {2, 0, 1}; ...@@ -319,7 +319,7 @@ static const uint16_t m_9d263a3630b7ebee[] = {2, 0, 1};
static const uint16_t i_9d263a3630b7ebee[] = {0, 1, 2}; static const uint16_t i_9d263a3630b7ebee[] = {0, 1, 2};
const ::capnp::_::RawSchema s_9d263a3630b7ebee = { const ::capnp::_::RawSchema s_9d263a3630b7ebee = {
0x9d263a3630b7ebee, b_9d263a3630b7ebee.words, 65, nullptr, m_9d263a3630b7ebee, 0x9d263a3630b7ebee, b_9d263a3630b7ebee.words, 65, nullptr, m_9d263a3630b7ebee,
0, 3, i_9d263a3630b7ebee, nullptr, nullptr 0, 3, i_9d263a3630b7ebee, nullptr, nullptr, { &s_9d263a3630b7ebee, nullptr, nullptr, 0, 0, nullptr }
}; };
} // namespace schemas } // namespace schemas
namespace _ { // private namespace _ { // private
......
This diff is collapsed.
...@@ -328,6 +328,45 @@ TEST(SchemaLoader, LazyLoadGetDependency) { ...@@ -328,6 +328,45 @@ TEST(SchemaLoader, LazyLoadGetDependency) {
EXPECT_EQ(dep, loader.get(typeId<TestAllTypes>())); EXPECT_EQ(dep, loader.get(typeId<TestAllTypes>()));
} }
TEST(SchemaLoader, Generics) {
SchemaLoader loader;
StructSchema allTypes = loader.load(Schema::from<TestAllTypes>().getProto()).asStruct();
StructSchema tap = loader.load(Schema::from<test::TestAnyPointer>().getProto()).asStruct();
loader.load(Schema::from<test::TestGenerics::Inner>().getProto());
loader.load(Schema::from<test::TestGenerics::Inner2>().getProto());
loader.load(Schema::from<test::TestGenerics::Interface>().getProto());
loader.load(Schema::from<test::TestGenerics>().getProto());
StructSchema schema = loader.load(Schema::from<test::TestUseGenerics>().getProto()).asStruct();
{
StructSchema::Field basic = schema.getFieldByName("basic");
StructSchema instance = basic.getType().asStruct();
StructSchema::Field foo = instance.getFieldByName("foo");
EXPECT_TRUE(foo.getType().asStruct() == allTypes);
EXPECT_TRUE(foo.getType().asStruct() != tap);
StructSchema instance2 = instance.getFieldByName("rev").getType().asStruct();
StructSchema::Field foo2 = instance2.getFieldByName("foo");
EXPECT_TRUE(foo2.getType().asStruct() == tap);
EXPECT_TRUE(foo2.getType().asStruct() != allTypes);
}
{
StructSchema inner2 = schema.getFieldByName("inner2").getType().asStruct();
StructSchema bound = inner2.getFieldByName("innerBound").getType().asStruct();
Type boundFoo = bound.getFieldByName("foo").getType();
EXPECT_FALSE(boundFoo.isAnyPointer());
EXPECT_TRUE(boundFoo.asStruct() == allTypes);
StructSchema unbound = inner2.getFieldByName("innerUnbound").getType().asStruct();
Type unboundFoo = unbound.getFieldByName("foo").getType();
EXPECT_TRUE(unboundFoo.isAnyPointer());
}
}
} // namespace } // namespace
} // namespace _ (private) } // namespace _ (private)
} // namespace capnp } // namespace capnp
This diff is collapsed.
...@@ -65,15 +65,30 @@ public: ...@@ -65,15 +65,30 @@ public:
~SchemaLoader() noexcept(false); ~SchemaLoader() noexcept(false);
KJ_DISALLOW_COPY(SchemaLoader); KJ_DISALLOW_COPY(SchemaLoader);
Schema get(uint64_t id) const; typedef schema::TypeEnvironment::Reader GenericBindings;
Schema get(uint64_t id, GenericBindings bindings = GenericBindings(),
Schema scope = Schema()) const;
// Gets the schema for the given ID, throwing an exception if it isn't present. // Gets the schema for the given ID, throwing an exception if it isn't present.
// //
// The returned schema may be invalidated if load() is called with a new schema for the same ID. // The returned schema may be invalidated if load() is called with a new schema for the same ID.
// In general, you should not call load() while a schema from this loader is in-use. // In general, you should not call load() while a schema from this loader is in-use.
//
kj::Maybe<Schema> tryGet(uint64_t id) const; // `bindings` and `scope` are used to determine generic parameter bindings where relevant.
// `bindings` gives parameter bindings for the target type's generic parameters that were
// specified at the reference site. `scope` specifies the scope in which the type ID appeared --
// if the target type and the scope share some common super-scope which is parameterized,
// and bindings for those parameters weren't specified in `bindings`, they will be carried over
// from the scope.
kj::Maybe<Schema> tryGet(uint64_t id, GenericBindings bindings = GenericBindings(),
Schema scope = Schema()) const;
// Like get() but doesn't throw. // Like get() but doesn't throw.
Type getType(schema::Type::Reader type, Schema scope = Schema()) const;
// Convenience method which interprets a schema::Type to produce a Type object. Implemented in
// terms of get().
Schema load(const schema::Node::Reader& reader); Schema load(const schema::Node::Reader& reader);
// Loads the given schema node. Validates the node and throws an exception if invalid. This // Loads the given schema node. Validates the node and throws an exception if invalid. This
// makes a copy of the schema, so the object passed in can be destroyed after this returns. // makes a copy of the schema, so the object passed in can be destroyed after this returns.
...@@ -134,6 +149,7 @@ private: ...@@ -134,6 +149,7 @@ private:
class CompatibilityChecker; class CompatibilityChecker;
class Impl; class Impl;
class InitializerImpl; class InitializerImpl;
class BrandedInitializerImpl;
kj::MutexGuarded<kj::Own<Impl>> impl; kj::MutexGuarded<kj::Own<Impl>> impl;
void loadNative(const _::RawSchema* nativeSchema); void loadNative(const _::RawSchema* nativeSchema);
......
...@@ -156,22 +156,29 @@ TEST(SchemaParser, Constants) { ...@@ -156,22 +156,29 @@ TEST(SchemaParser, Constants) {
"struct Foo {\n" "struct Foo {\n"
" bar @0 :Int16;\n" " bar @0 :Int16;\n"
" baz @1 :Text;\n" " baz @1 :Text;\n"
"}\n"
"const genericConst :TestGeneric(Text) = (value = \"text\");\n"
"struct TestGeneric(T) {\n"
" value @0 :T;\n"
"}\n"); "}\n");
ParsedSchema barSchema = parser.parseFile(SchemaFile::newDiskFile( ParsedSchema fileSchema = parser.parseFile(SchemaFile::newDiskFile(
"const.capnp", "const.capnp", nullptr, reader)); "const.capnp", "const.capnp", nullptr, reader));
EXPECT_EQ(1234, barSchema.getNested("uint32Const").asConst().as<uint32_t>()); EXPECT_EQ(1234, fileSchema.getNested("uint32Const").asConst().as<uint32_t>());
auto list = barSchema.getNested("listConst").asConst().as<DynamicList>(); auto list = fileSchema.getNested("listConst").asConst().as<DynamicList>();
ASSERT_EQ(3u, list.size()); ASSERT_EQ(3u, list.size());
EXPECT_EQ(1.25, list[0].as<float>()); EXPECT_EQ(1.25, list[0].as<float>());
EXPECT_EQ(2.5, list[1].as<float>()); EXPECT_EQ(2.5, list[1].as<float>());
EXPECT_EQ(3e4f, list[2].as<float>()); EXPECT_EQ(3e4f, list[2].as<float>());
auto structConst = barSchema.getNested("structConst").asConst().as<DynamicStruct>(); auto structConst = fileSchema.getNested("structConst").asConst().as<DynamicStruct>();
EXPECT_EQ(123, structConst.get("bar").as<int16_t>()); EXPECT_EQ(123, structConst.get("bar").as<int16_t>());
EXPECT_EQ("qux", structConst.get("baz").as<Text>()); EXPECT_EQ("qux", structConst.get("baz").as<Text>());
auto genericConst = fileSchema.getNested("genericConst").asConst().as<DynamicStruct>();
EXPECT_EQ("text", genericConst.get("value").as<Text>());
} }
} // namespace } // namespace
......
This diff is collapsed.
...@@ -342,8 +342,14 @@ struct TypeEnvironment { ...@@ -342,8 +342,14 @@ struct TypeEnvironment {
scopeId @0 :Id; scopeId @0 :Id;
# ID of the scope to which these params apply. # ID of the scope to which these params apply.
bindings @1 :List(Binding); union {
# List of parameter bindings. bind @1 :List(Binding);
# List of parameter bindings.
inherit @2 :Void;
# The place where this TypeEnivornment appears is actually within this scope or a sub-scope,
# and the bindings for this scope should be inherited from the reference point.
}
} }
struct Binding { struct Binding {
......
This diff is collapsed.
...@@ -265,6 +265,10 @@ struct TypeEnvironment::Scope { ...@@ -265,6 +265,10 @@ struct TypeEnvironment::Scope {
class Reader; class Reader;
class Builder; class Builder;
class Pipeline; class Pipeline;
enum Which: uint16_t {
BIND,
INHERIT,
};
}; };
struct TypeEnvironment::Binding { struct TypeEnvironment::Binding {
...@@ -468,7 +472,7 @@ CAPNP_DECLARE_STRUCT( ...@@ -468,7 +472,7 @@ CAPNP_DECLARE_STRUCT(
0, 1, POINTER); 0, 1, POINTER);
CAPNP_DECLARE_STRUCT( CAPNP_DECLARE_STRUCT(
::capnp::schema::TypeEnvironment::Scope, 8343d91197413c18, ::capnp::schema::TypeEnvironment::Scope, 8343d91197413c18,
1, 1, INLINE_COMPOSITE); 2, 1, INLINE_COMPOSITE);
CAPNP_DECLARE_STRUCT( CAPNP_DECLARE_STRUCT(
::capnp::schema::TypeEnvironment::Binding, f5b4269b6dd5cd38, ::capnp::schema::TypeEnvironment::Binding, f5b4269b6dd5cd38,
1, 1, INLINE_COMPOSITE); 1, 1, INLINE_COMPOSITE);
...@@ -2770,10 +2774,15 @@ public: ...@@ -2770,10 +2774,15 @@ public:
return _reader.totalSize().asPublic(); return _reader.totalSize().asPublic();
} }
inline Which which() const;
inline ::uint64_t getScopeId() const; inline ::uint64_t getScopeId() const;
inline bool hasBindings() const; inline bool isBind() const;
inline ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Reader getBindings() const; inline bool hasBind() const;
inline ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Reader getBind() const;
inline bool isInherit() const;
inline ::capnp::Void getInherit() const;
private: private:
::capnp::_::StructReader _reader; ::capnp::_::StructReader _reader;
...@@ -2805,15 +2814,21 @@ public: ...@@ -2805,15 +2814,21 @@ public:
inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); }
inline Which which();
inline ::uint64_t getScopeId(); inline ::uint64_t getScopeId();
inline void setScopeId( ::uint64_t value); inline void setScopeId( ::uint64_t value);
inline bool hasBindings(); inline bool isBind();
inline ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Builder getBindings(); inline bool hasBind();
inline void setBindings( ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Reader value); inline ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Builder getBind();
inline ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Builder initBindings(unsigned int size); inline void setBind( ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Reader value);
inline void adoptBindings(::capnp::Orphan< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>&& value); inline ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Builder initBind(unsigned int size);
inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>> disownBindings(); inline void adoptBind(::capnp::Orphan< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>&& value);
inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>> disownBind();
inline bool isInherit();
inline ::capnp::Void getInherit();
inline void setInherit( ::capnp::Void value = ::capnp::VOID);
private: private:
::capnp::_::StructBuilder _builder; ::capnp::_::StructBuilder _builder;
...@@ -5818,6 +5833,13 @@ inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::TypeEnvironment::Scope>> ...@@ -5818,6 +5833,13 @@ inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::TypeEnvironment::Scope>>
_builder.getPointerField(0 * ::capnp::POINTERS)); _builder.getPointerField(0 * ::capnp::POINTERS));
} }
inline TypeEnvironment::Scope::Which TypeEnvironment::Scope::Reader::which() const {
return _reader.getDataField<Which>(4 * ::capnp::ELEMENTS);
}
inline TypeEnvironment::Scope::Which TypeEnvironment::Scope::Builder::which() {
return _builder.getDataField<Which>(4 * ::capnp::ELEMENTS);
}
inline ::uint64_t TypeEnvironment::Scope::Reader::getScopeId() const { inline ::uint64_t TypeEnvironment::Scope::Reader::getScopeId() const {
return _reader.getDataField< ::uint64_t>( return _reader.getDataField< ::uint64_t>(
0 * ::capnp::ELEMENTS); 0 * ::capnp::ELEMENTS);
...@@ -5832,38 +5854,84 @@ inline void TypeEnvironment::Scope::Builder::setScopeId( ::uint64_t value) { ...@@ -5832,38 +5854,84 @@ inline void TypeEnvironment::Scope::Builder::setScopeId( ::uint64_t value) {
0 * ::capnp::ELEMENTS, value); 0 * ::capnp::ELEMENTS, value);
} }
inline bool TypeEnvironment::Scope::Reader::hasBindings() const { inline bool TypeEnvironment::Scope::Reader::isBind() const {
return which() == TypeEnvironment::Scope::BIND;
}
inline bool TypeEnvironment::Scope::Builder::isBind() {
return which() == TypeEnvironment::Scope::BIND;
}
inline bool TypeEnvironment::Scope::Reader::hasBind() const {
if (which() != TypeEnvironment::Scope::BIND) return false;
return !_reader.getPointerField(0 * ::capnp::POINTERS).isNull(); return !_reader.getPointerField(0 * ::capnp::POINTERS).isNull();
} }
inline bool TypeEnvironment::Scope::Builder::hasBindings() { inline bool TypeEnvironment::Scope::Builder::hasBind() {
if (which() != TypeEnvironment::Scope::BIND) return false;
return !_builder.getPointerField(0 * ::capnp::POINTERS).isNull(); return !_builder.getPointerField(0 * ::capnp::POINTERS).isNull();
} }
inline ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Reader TypeEnvironment::Scope::Reader::getBindings() const { inline ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Reader TypeEnvironment::Scope::Reader::getBind() const {
KJ_IREQUIRE(which() == TypeEnvironment::Scope::BIND,
"Must check which() before get()ing a union member.");
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>::get( return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>::get(
_reader.getPointerField(0 * ::capnp::POINTERS)); _reader.getPointerField(0 * ::capnp::POINTERS));
} }
inline ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Builder TypeEnvironment::Scope::Builder::getBindings() { inline ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Builder TypeEnvironment::Scope::Builder::getBind() {
KJ_IREQUIRE(which() == TypeEnvironment::Scope::BIND,
"Must check which() before get()ing a union member.");
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>::get( return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>::get(
_builder.getPointerField(0 * ::capnp::POINTERS)); _builder.getPointerField(0 * ::capnp::POINTERS));
} }
inline void TypeEnvironment::Scope::Builder::setBindings( ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Reader value) { inline void TypeEnvironment::Scope::Builder::setBind( ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Reader value) {
_builder.setDataField<TypeEnvironment::Scope::Which>(
4 * ::capnp::ELEMENTS, TypeEnvironment::Scope::BIND);
::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>::set( ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>::set(
_builder.getPointerField(0 * ::capnp::POINTERS), value); _builder.getPointerField(0 * ::capnp::POINTERS), value);
} }
inline ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Builder TypeEnvironment::Scope::Builder::initBindings(unsigned int size) { inline ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>::Builder TypeEnvironment::Scope::Builder::initBind(unsigned int size) {
_builder.setDataField<TypeEnvironment::Scope::Which>(
4 * ::capnp::ELEMENTS, TypeEnvironment::Scope::BIND);
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>::init( return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>::init(
_builder.getPointerField(0 * ::capnp::POINTERS), size); _builder.getPointerField(0 * ::capnp::POINTERS), size);
} }
inline void TypeEnvironment::Scope::Builder::adoptBindings( inline void TypeEnvironment::Scope::Builder::adoptBind(
::capnp::Orphan< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>&& value) { ::capnp::Orphan< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>&& value) {
_builder.setDataField<TypeEnvironment::Scope::Which>(
4 * ::capnp::ELEMENTS, TypeEnvironment::Scope::BIND);
::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>::adopt( ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>::adopt(
_builder.getPointerField(0 * ::capnp::POINTERS), kj::mv(value)); _builder.getPointerField(0 * ::capnp::POINTERS), kj::mv(value));
} }
inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>> TypeEnvironment::Scope::Builder::disownBindings() { inline ::capnp::Orphan< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>> TypeEnvironment::Scope::Builder::disownBind() {
KJ_IREQUIRE(which() == TypeEnvironment::Scope::BIND,
"Must check which() before get()ing a union member.");
return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>::disown( return ::capnp::_::PointerHelpers< ::capnp::List< ::capnp::schema::TypeEnvironment::Binding>>::disown(
_builder.getPointerField(0 * ::capnp::POINTERS)); _builder.getPointerField(0 * ::capnp::POINTERS));
} }
inline bool TypeEnvironment::Scope::Reader::isInherit() const {
return which() == TypeEnvironment::Scope::INHERIT;
}
inline bool TypeEnvironment::Scope::Builder::isInherit() {
return which() == TypeEnvironment::Scope::INHERIT;
}
inline ::capnp::Void TypeEnvironment::Scope::Reader::getInherit() const {
KJ_IREQUIRE(which() == TypeEnvironment::Scope::INHERIT,
"Must check which() before get()ing a union member.");
return _reader.getDataField< ::capnp::Void>(
0 * ::capnp::ELEMENTS);
}
inline ::capnp::Void TypeEnvironment::Scope::Builder::getInherit() {
KJ_IREQUIRE(which() == TypeEnvironment::Scope::INHERIT,
"Must check which() before get()ing a union member.");
return _builder.getDataField< ::capnp::Void>(
0 * ::capnp::ELEMENTS);
}
inline void TypeEnvironment::Scope::Builder::setInherit( ::capnp::Void value) {
_builder.setDataField<TypeEnvironment::Scope::Which>(
4 * ::capnp::ELEMENTS, TypeEnvironment::Scope::INHERIT);
_builder.setDataField< ::capnp::Void>(
0 * ::capnp::ELEMENTS, value);
}
inline TypeEnvironment::Binding::Which TypeEnvironment::Binding::Reader::which() const { inline TypeEnvironment::Binding::Which TypeEnvironment::Binding::Reader::which() const {
return _reader.getDataField<Which>(0 * ::capnp::ELEMENTS); return _reader.getDataField<Which>(0 * ::capnp::ELEMENTS);
} }
......
This diff is collapsed.
...@@ -282,8 +282,8 @@ kj::StringTree KJ_STRINGIFY(const DynamicList::Builder& value) { return stringif ...@@ -282,8 +282,8 @@ kj::StringTree KJ_STRINGIFY(const DynamicList::Builder& value) { return stringif
namespace _ { // private namespace _ { // private
kj::StringTree structString(StructReader reader, const RawSchema& schema) { kj::StringTree structString(StructReader reader, const RawBrandedSchema& schema) {
return stringify(DynamicStruct::Reader(StructSchema(&schema), reader)); return stringify(DynamicStruct::Reader(Schema(&schema).asStruct(), reader));
} }
} // namespace _ (private) } // namespace _ (private)
......
...@@ -515,19 +515,42 @@ struct TestGenerics(Foo, Bar) { ...@@ -515,19 +515,42 @@ struct TestGenerics(Foo, Bar) {
struct Inner2(Baz) { struct Inner2(Baz) {
bar @0 :Bar; bar @0 :Bar;
baz @1 :Baz; baz @1 :Baz;
innerBound @2 :Inner;
innerUnbound @3 :TestGenerics.Inner;
} }
interface Interface(Qux) { interface Interface(Qux) {
call @0 Inner2(Text) -> (qux :Qux, gen :TestGenerics(TestAllTypes, TestDefaults)); call @0 Inner2(Text) -> (qux :Qux, gen :TestGenerics(TestAllTypes, TestDefaults));
} }
annotation ann(struct) :Foo;
}
struct TestGenericsWrapper(Foo, Bar) {
value @0 :TestGenerics(Foo, Bar);
} }
struct TestUseGenerics { struct TestGenericsWrapper2 {
basic @0 :TestGenerics(TestAllTypes, TestDefaults); value @0 :TestGenericsWrapper(Text, TestAllTypes);
inner @1 :TestGenerics(TestAllTypes, TestDefaults).Inner; }
inner2 @2 :TestGenerics(TestAllTypes, TestDefaults).Inner2(Text);
struct TestUseGenerics $TestGenerics(Text, Data).ann("foo") {
basic @0 :TestGenerics(TestAllTypes, TestAnyPointer);
inner @1 :TestGenerics(TestAllTypes, TestAnyPointer).Inner;
inner2 @2 :TestGenerics(TestAllTypes, TestAnyPointer).Inner2(Text);
unspecified @3 :TestGenerics; unspecified @3 :TestGenerics;
unspecifiedInner @4 :TestGenerics.Inner2(Text); unspecifiedInner @4 :TestGenerics.Inner2(Text);
wrapper @8 :TestGenericsWrapper(TestAllTypes, TestAnyPointer);
default @5 :TestGenerics(TestAllTypes, Text) =
(foo = (int16Field = 123), rev = (foo = "text", rev = (foo = (int16Field = 321))));
defaultInner @6 :TestGenerics(TestAllTypes, Text).Inner =
(foo = (int16Field = 123), bar = "text");
defaultUser @7 :TestUseGenerics = (basic = (foo = (int16Field = 123)));
defaultWrapper @9 :TestGenericsWrapper(Text, TestAllTypes) =
(value = (foo = "text", rev = (foo = (int16Field = 321))));
defaultWrapper2 @10 :TestGenericsWrapper2 =
(value = (value = (foo = "text", rev = (foo = (int16Field = 321)))));
} }
struct TestEmptyStruct {} struct TestEmptyStruct {}
...@@ -623,6 +646,9 @@ const derivedConstant :TestAllTypes = ( ...@@ -623,6 +646,9 @@ const derivedConstant :TestAllTypes = (
int16List = TestConstants.int16ListConst, int16List = TestConstants.int16ListConst,
structList = TestConstants.structListConst); structList = TestConstants.structListConst);
const genericConstant :TestGenerics(TestAllTypes, Text) =
(foo = (int16Field = 123), rev = (foo = "text", rev = (foo = (int16Field = 321))));
interface TestInterface { interface TestInterface {
foo @0 (i :UInt32, j :Bool) -> (x :Text); foo @0 (i :UInt32, j :Bool) -> (x :Text);
bar @1 () -> (); bar @1 () -> ();
......
...@@ -143,6 +143,14 @@ typedef unsigned char byte; ...@@ -143,6 +143,14 @@ typedef unsigned char byte;
#define KJ_UNUSED_MEMBER #define KJ_UNUSED_MEMBER
#endif #endif
#if __clang__
#define KJ_DEPRECATED(reason) \
__attribute__((deprecated(reason)))
#else
#define KJ_DEPRECATED(reason) \
__attribute__((deprecated))
#endif
namespace _ { // private namespace _ { // private
void inlineRequireFailure( void inlineRequireFailure(
......
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