Commit 01200b96 authored by Kenton Varda's avatar Kenton Varda

Generics: Methods with implicit type parameters.

See changes to test.capnp for example.

Currently only supported through generated code, not in the dynamic API. Not exactly sure how to expose this in the dynamic API...
parent a211aa60
......@@ -796,6 +796,30 @@ TEST(Capability, Generics2) {
root.initCap().setFoo(test::TestInterface::Client(nullptr));
}
TEST(Capability, ImplicitParams) {
kj::EventLoop loop;
kj::WaitScope waitScope(loop);
typedef test::TestImplicitMethodParams Interface;
Interface::Client client = nullptr;
capnp::Request<Interface::CallParams<Text, TestAllTypes>,
test::TestGenerics<Text, TestAllTypes>> request =
client.callRequest<Text, TestAllTypes>();
request.setFoo("hello");
initTestMessage(request.initBar());
auto promise = request.send()
.then([](capnp::Response<test::TestGenerics<Text, TestAllTypes>>&& response) {
// This doesn't actually execute; we're just checking that it compiles.
Text::Reader text = response.getFoo();
text.size();
checkTestMessage(response.getRev().getFoo());
}, [](kj::Exception&& e) {});
promise.wait(waitScope);
}
} // namespace
} // namespace _
} // namespace capnp
This diff is collapsed.
......@@ -114,7 +114,8 @@ private:
return "(?)";
}
kj::StringTree nodeName(Schema target, Schema scope, schema::Brand::Reader brand) {
kj::StringTree nodeName(Schema target, Schema scope, schema::Brand::Reader brand,
kj::Maybe<InterfaceSchema::Method> method) {
kj::Vector<Schema> targetPath;
kj::Vector<Schema> scopeParts;
......@@ -178,7 +179,7 @@ private:
case schema::Brand::Binding::UNBOUND:
return kj::strTree("AnyPointer");
case schema::Brand::Binding::TYPE:
return genType(binding.getType(), scope);
return genType(binding.getType(), scope, method);
}
return kj::strTree("<unknown binding>");
};
......@@ -192,7 +193,8 @@ private:
return kj::StringTree(parts.finish(), ".");
}
kj::StringTree genType(schema::Type::Reader type, Schema scope) {
kj::StringTree genType(schema::Type::Reader type, Schema scope,
kj::Maybe<InterfaceSchema::Method> method) {
switch (type.which()) {
case schema::Type::VOID: return kj::strTree("Void");
case schema::Type::BOOL: return kj::strTree("Bool");
......@@ -209,16 +211,16 @@ private:
case schema::Type::TEXT: return kj::strTree("Text");
case schema::Type::DATA: return kj::strTree("Data");
case schema::Type::LIST:
return kj::strTree("List(", genType(type.getList().getElementType(), scope), ")");
return kj::strTree("List(", genType(type.getList().getElementType(), scope, method), ")");
case schema::Type::ENUM:
return nodeName(schemaLoader.get(type.getEnum().getTypeId()), scope,
type.getEnum().getBrand());
type.getEnum().getBrand(), method);
case schema::Type::STRUCT:
return nodeName(schemaLoader.get(type.getStruct().getTypeId()), scope,
type.getStruct().getBrand());
type.getStruct().getBrand(), method);
case schema::Type::INTERFACE:
return nodeName(schemaLoader.get(type.getInterface().getTypeId()), scope,
type.getInterface().getBrand());
type.getInterface().getBrand(), method);
case schema::Type::ANY_POINTER: {
auto anyPointer = type.getAnyPointer();
switch (anyPointer.which()) {
......@@ -235,6 +237,12 @@ private:
KJ_REQUIRE(param.getParameterIndex() < params.size());
return kj::strTree(params[param.getParameterIndex()].getName());
}
case schema::Type::AnyPointer::IMPLICIT_METHOD_PARAMETER: {
auto params = KJ_REQUIRE_NONNULL(method).getProto().getImplicitParameters();
uint index = anyPointer.getImplicitMethodParameter().getParameterIndex();
KJ_REQUIRE(index < params.size());
return kj::strTree(params[index].getName());
}
}
KJ_UNREACHABLE;
}
......@@ -361,10 +369,10 @@ private:
auto value = genValue(schemaLoader.getType(annDecl.getType(), decl),
annotation.getValue()).flatten();
if (value.startsWith("(")) {
return kj::strTree(prefix, "$", nodeName(decl, scope, annotation.getBrand()),
return kj::strTree(prefix, "$", nodeName(decl, scope, annotation.getBrand(), nullptr),
value, suffix);
} else {
return kj::strTree(prefix, "$", nodeName(decl, scope, annotation.getBrand()),
return kj::strTree(prefix, "$", nodeName(decl, scope, annotation.getBrand(), nullptr),
"(", value, ")", suffix);
}
}
......@@ -443,7 +451,7 @@ private:
int size = typeSizeBits(slot.getType());
return kj::strTree(
indent, proto.getName(), " @", proto.getOrdinal().getExplicit(),
" :", genType(slot.getType(), scope),
" :", genType(slot.getType(), scope, nullptr),
isEmptyValue(slot.getDefaultValue()) ? kj::strTree("") :
kj::strTree(" = ", genValue(field.getType(), slot.getDefaultValue())),
genAnnotations(proto.getAnnotations(), scope),
......@@ -470,7 +478,7 @@ private:
}
kj::StringTree genParamList(InterfaceSchema interface, StructSchema schema,
schema::Brand::Reader brand) {
schema::Brand::Reader brand, InterfaceSchema::Method method) {
if (schema.getProto().getScopeId() == 0) {
// A named parameter list.
return kj::strTree("(", kj::StringTree(
......@@ -479,13 +487,13 @@ private:
auto slot = proto.getSlot();
return kj::strTree(
proto.getName(), " :", genType(slot.getType(), interface),
proto.getName(), " :", genType(slot.getType(), interface, nullptr),
isEmptyValue(slot.getDefaultValue()) ? kj::strTree("") :
kj::strTree(" = ", genValue(field.getType(), slot.getDefaultValue())),
genAnnotations(proto.getAnnotations(), interface));
}, ", "), ")");
} else {
return nodeName(schema, interface, brand);
return nodeName(schema, interface, brand, method);
}
}
......@@ -496,7 +504,8 @@ private:
} else {
return kj::strTree(" superclasses(", kj::StringTree(
KJ_MAP(superclass, superclasses) {
return nodeName(schemaLoader.get(superclass.getId()), interface, superclass.getBrand());
return nodeName(schemaLoader.get(superclass.getId()), interface,
superclass.getBrand(), nullptr);
}, ", "), ")");
}
}
......@@ -549,12 +558,23 @@ private:
genAnnotations(schema), " {\n",
KJ_MAP(method, sortByCodeOrder(interface.getMethods())) {
auto methodProto = method.getProto();
auto implicits = methodProto.getImplicitParameters();
kj::StringTree implicitsStr;
if (implicits.size() > 0) {
implicitsStr = kj::strTree(
"[", kj::StringTree(KJ_MAP(implicit, implicits) {
return kj::strTree(implicit.getName());
}, ", "), "] ");
}
auto params = schemaLoader.get(methodProto.getParamStructType()).asStruct();
auto results = schemaLoader.get(methodProto.getResultStructType()).asStruct();
return kj::strTree(
indent.next(), methodProto.getName(), " @", method.getIndex(), " ",
genParamList(interface, params, methodProto.getParamBrand()), " -> ",
genParamList(interface, results, methodProto.getResultBrand()),
indent.next(), methodProto.getName(),
" @", method.getIndex(), " ", kj::mv(implicitsStr),
genParamList(interface, params, methodProto.getParamBrand(), method), " -> ",
genParamList(interface, results, methodProto.getResultBrand(), method),
genAnnotations(methodProto.getAnnotations(), interface), ";\n");
},
genNestedDecls(schema, indent.next()),
......@@ -564,7 +584,7 @@ private:
auto constProto = proto.getConst();
return kj::strTree(
indent, "const ", name, " @0x", kj::hex(proto.getId()), " :",
genType(constProto.getType(), schema), " = ",
genType(constProto.getType(), schema, nullptr), " = ",
genValue(schema.asConst().getType(), constProto.getValue()),
genAnnotations(schema), ";\n");
}
......@@ -596,7 +616,7 @@ private:
return kj::strTree(
indent, "annotation ", name, " @0x", kj::hex(proto.getId()),
" (", strArray(targets, ", "), ") :",
genType(annotationProto.getType(), schema), genAnnotations(schema), ";\n");
genType(annotationProto.getType(), schema, nullptr), genAnnotations(schema), ";\n");
}
}
......
This diff is collapsed.
......@@ -133,11 +133,11 @@ public:
private:
::capnp::_::StructReader _reader;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::List;
friend class ::capnp::MessageBuilder;
friend class ::capnp::Orphanage;
......@@ -224,7 +224,7 @@ public:
private:
::capnp::_::StructBuilder _builder;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
friend class ::capnp::Orphanage;
};
......@@ -239,7 +239,7 @@ public:
private:
::capnp::AnyPointer::Pipeline _typeless;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
};
......@@ -278,11 +278,11 @@ public:
private:
::capnp::_::StructReader _reader;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::List;
friend class ::capnp::MessageBuilder;
friend class ::capnp::Orphanage;
......@@ -337,7 +337,7 @@ public:
private:
::capnp::_::StructBuilder _builder;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
friend class ::capnp::Orphanage;
};
......@@ -352,7 +352,7 @@ public:
private:
::capnp::AnyPointer::Pipeline _typeless;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
};
......@@ -376,11 +376,11 @@ public:
private:
::capnp::_::StructReader _reader;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::List;
friend class ::capnp::MessageBuilder;
friend class ::capnp::Orphanage;
......@@ -409,7 +409,7 @@ public:
private:
::capnp::_::StructBuilder _builder;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
friend class ::capnp::Orphanage;
};
......@@ -424,7 +424,7 @@ public:
private:
::capnp::AnyPointer::Pipeline _typeless;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
};
......@@ -448,11 +448,11 @@ public:
private:
::capnp::_::StructReader _reader;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::List;
friend class ::capnp::MessageBuilder;
friend class ::capnp::Orphanage;
......@@ -481,7 +481,7 @@ public:
private:
::capnp::_::StructBuilder _builder;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
friend class ::capnp::Orphanage;
};
......@@ -496,7 +496,7 @@ public:
private:
::capnp::AnyPointer::Pipeline _typeless;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
};
......
This diff is collapsed.
......@@ -207,16 +207,34 @@ private:
// The `members` arrays contain only members with ordinal numbers, in code order. Other members
// are handled elsewhere.
struct ImplicitParams {
// Represents a set of implicit parameters visible in the current context.
uint64_t scopeId;
// If zero, then any reference to an implciit param in this context should be compiled to a
// `implicitMethodParam` AnyPointer. If non-zero, it should be complied to a `parameter`
// AnyPointer.
List<Declaration::BrandParameter>::Reader params;
};
static inline ImplicitParams noImplicitParams() {
return { 0, List<Declaration::BrandParameter>::Reader() };
}
template <typename InitBrandFunc>
uint64_t compileParamList(kj::StringPtr methodName, uint16_t ordinal, bool isResults,
Declaration::ParamList::Reader paramList,
List<Declaration::BrandParameter>::Reader implicitParams,
InitBrandFunc&& initBrand);
// Compile a param (or result) list and return the type ID of the struct type.
kj::Maybe<BrandedDecl> compileDeclExpression(Expression::Reader source);
kj::Maybe<BrandedDecl> compileDeclExpression(
Expression::Reader source, ImplicitParams implicitMethodParams);
// Compile an expression which is expected to resolve to a declaration or type expression.
bool compileType(Expression::Reader source, schema::Type::Builder target);
bool compileType(Expression::Reader source, schema::Type::Builder target,
ImplicitParams implicitMethodParams);
// Returns false if there was a problem, in which case value expressions of this type should
// not be parsed.
......
......@@ -344,16 +344,8 @@ Orphan<List<T>> arrayToList(Orphanage& orphanage, kj::Array<Orphan<T>>&& element
return kj::mv(result);
}
inline Declaration::Builder initDecl(
Declaration::Builder builder, Located<Text::Reader>&& name,
kj::Maybe<Orphan<LocatedInteger>>&& id,
kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParameters,
kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations) {
name.copyTo(builder.initName());
KJ_IF_MAYBE(i, id) {
builder.getId().adoptUid(kj::mv(*i));
}
static void initGenericParams(Declaration::Builder builder,
kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParameters) {
KJ_IF_MAYBE(p, genericParameters) {
auto params = builder.initParameters(p->value.size());
for (uint i: kj::indices(p->value)) {
......@@ -364,6 +356,19 @@ inline Declaration::Builder initDecl(
}
}
}
}
static Declaration::Builder initDecl(
Declaration::Builder builder, Located<Text::Reader>&& name,
kj::Maybe<Orphan<LocatedInteger>>&& id,
kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParameters,
kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations) {
name.copyTo(builder.initName());
KJ_IF_MAYBE(i, id) {
builder.getId().adoptUid(kj::mv(*i));
}
initGenericParams(builder, kj::mv(genericParameters));
auto list = builder.initAnnotations(annotations.size());
for (uint i = 0; i < annotations.size(); i++) {
......@@ -372,7 +377,7 @@ inline Declaration::Builder initDecl(
return builder;
}
inline Declaration::Builder initMemberDecl(
static Declaration::Builder initMemberDecl(
Declaration::Builder builder, Located<Text::Reader>&& name,
Orphan<LocatedInteger>&& ordinal,
kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations) {
......@@ -902,18 +907,24 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, ErrorReporter& errorReporterP
})));
parsers.methodDecl = arena.copy(p::transform(
p::sequence(identifier, parsers.ordinal, paramList,
p::sequence(identifier, parsers.ordinal,
p::optional(bracketedList(identifier, errorReporter)),
paramList,
p::optional(p::sequence(op("->"), paramList)),
p::many(parsers.annotation)),
[this](Located<Text::Reader>&& name, Orphan<LocatedInteger>&& ordinal,
kj::Maybe<Located<kj::Array<kj::Maybe<Located<Text::Reader>>>>>&& genericParams,
Orphan<Declaration::ParamList>&& params,
kj::Maybe<Orphan<Declaration::ParamList>>&& results,
kj::Array<Orphan<Declaration::AnnotationApplication>>&& annotations)
-> DeclParserResult {
auto decl = orphanage.newOrphan<Declaration>();
auto builder =
initMemberDecl(decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations))
.initMethod();
auto nodeBuilder = initMemberDecl(
decl.get(), kj::mv(name), kj::mv(ordinal), kj::mv(annotations));
initGenericParams(nodeBuilder, kj::mv(genericParams));
auto builder = nodeBuilder.initMethod();
builder.adoptParams(kj::mv(params));
......
......@@ -57,9 +57,13 @@ struct RawBrandedSchema {
struct Binding {
uint8_t which; // Numeric value of one of schema::Type::Which.
bool isImplicitParameter;
// For AnyPointer, true if it's an implicit method parameter.
uint16_t listDepth; // Number of times to wrap the base type in List().
uint32_t paramIndex; // for AnyPointer, if it's a type parameter.
uint16_t paramIndex; // for AnyPointer, if it's a type parameter.
union {
const RawBrandedSchema* schema; // for struct, enum, interface
......@@ -68,10 +72,15 @@ struct RawBrandedSchema {
Binding() = default;
inline constexpr Binding(uint8_t which, uint16_t listDepth, const RawBrandedSchema* schema)
: which(which), listDepth(listDepth), paramIndex(0), schema(schema) {}
: which(which), isImplicitParameter(false), listDepth(listDepth), paramIndex(0),
schema(schema) {}
inline constexpr Binding(uint8_t which, uint16_t listDepth,
uint64_t scopeId, uint32_t paramIndex)
: which(which), listDepth(listDepth), paramIndex(paramIndex), scopeId(scopeId) {}
uint64_t scopeId, uint16_t paramIndex)
: which(which), isImplicitParameter(false), listDepth(listDepth), paramIndex(paramIndex),
scopeId(scopeId) {}
inline constexpr Binding(uint8_t which, uint16_t listDepth, uint16_t implicitParamIndex)
: which(which), isImplicitParameter(true), listDepth(listDepth),
paramIndex(implicitParamIndex), scopeId(0) {}
};
struct Scope {
......@@ -264,7 +273,7 @@ struct BrandBindingFor_;
template <> \
struct BrandBindingFor_<Type, Kind::PRIMITIVE> { \
static constexpr RawBrandedSchema::Binding get(uint16_t listDepth) { \
return { which, listDepth, 0 }; \
return { which, listDepth, nullptr }; \
} \
}
HANDLE_TYPE(Void, 0);
......
......@@ -117,11 +117,11 @@ public:
private:
::capnp::_::StructReader _reader;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::List;
friend class ::capnp::MessageBuilder;
friend class ::capnp::Orphanage;
......@@ -146,7 +146,7 @@ public:
private:
::capnp::_::StructBuilder _builder;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
friend class ::capnp::Orphanage;
};
......@@ -161,7 +161,7 @@ public:
private:
::capnp::AnyPointer::Pipeline _typeless;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
};
......@@ -184,11 +184,11 @@ public:
private:
::capnp::_::StructReader _reader;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::List;
friend class ::capnp::MessageBuilder;
friend class ::capnp::Orphanage;
......@@ -213,7 +213,7 @@ public:
private:
::capnp::_::StructBuilder _builder;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
friend class ::capnp::Orphanage;
};
......@@ -228,7 +228,7 @@ public:
private:
::capnp::AnyPointer::Pipeline _typeless;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
};
......@@ -249,11 +249,11 @@ public:
private:
::capnp::_::StructReader _reader;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::List;
friend class ::capnp::MessageBuilder;
friend class ::capnp::Orphanage;
......@@ -275,7 +275,7 @@ public:
private:
::capnp::_::StructBuilder _builder;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
friend class ::capnp::Orphanage;
};
......@@ -290,7 +290,7 @@ public:
private:
::capnp::AnyPointer::Pipeline _typeless;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
};
......@@ -311,11 +311,11 @@ public:
private:
::capnp::_::StructReader _reader;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::List;
friend class ::capnp::MessageBuilder;
friend class ::capnp::Orphanage;
......@@ -337,7 +337,7 @@ public:
private:
::capnp::_::StructBuilder _builder;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
friend class ::capnp::Orphanage;
};
......@@ -352,7 +352,7 @@ public:
private:
::capnp::AnyPointer::Pipeline _typeless;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
};
......@@ -379,11 +379,11 @@ public:
private:
::capnp::_::StructReader _reader;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::List;
friend class ::capnp::MessageBuilder;
friend class ::capnp::Orphanage;
......@@ -414,7 +414,7 @@ public:
private:
::capnp::_::StructBuilder _builder;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
friend class ::capnp::Orphanage;
};
......@@ -429,7 +429,7 @@ public:
private:
::capnp::AnyPointer::Pipeline _typeless;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
};
......@@ -457,11 +457,11 @@ public:
private:
::capnp::_::StructReader _reader;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::_::PointerHelpers;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::List;
friend class ::capnp::MessageBuilder;
friend class ::capnp::Orphanage;
......@@ -493,7 +493,7 @@ public:
private:
::capnp::_::StructBuilder _builder;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
friend class ::capnp::Orphanage;
};
......@@ -508,7 +508,7 @@ public:
private:
::capnp::AnyPointer::Pipeline _typeless;
template <typename T, ::capnp::Kind k>
template <typename, ::capnp::Kind>
friend struct ::capnp::ToDynamic_;
};
......
This diff is collapsed.
......@@ -1714,7 +1714,7 @@ _::RawBrandedSchema::Binding SchemaLoader::Impl::makeDep(
case schema::Type::AnyPointer::PARAMETER: {
auto param = anyPointer.getParameter();
uint64_t id = param.getScopeId();
uint index = param.getParameterIndex();
uint16_t index = param.getParameterIndex();
KJ_IF_MAYBE(b, brandBindings) {
// TODO(perf): We could binary search here, but... bleh.
......@@ -1739,6 +1739,9 @@ _::RawBrandedSchema::Binding SchemaLoader::Impl::makeDep(
return { static_cast<uint8_t>(schema::Type::ANY_POINTER), 0, id, index };
}
}
case schema::Type::AnyPointer::IMPLICIT_METHOD_PARAMETER:
return { static_cast<uint8_t>(schema::Type::ANY_POINTER), 0,
anyPointer.getImplicitMethodParameter().getParameterIndex() };
}
KJ_UNREACHABLE;
}
......@@ -2061,6 +2064,9 @@ Type SchemaLoader::getType(schema::Type::Reader proto, Schema scope) const {
auto param = anyPointer.getParameter();
return scope.getBrandBinding(param.getScopeId(), param.getParameterIndex());
}
case schema::Type::AnyPointer::IMPLICIT_METHOD_PARAMETER:
// We don't support binding implicit method params here.
return schema::Type::ANY_POINTER;
}
KJ_UNREACHABLE;
......
......@@ -377,6 +377,9 @@ Type Schema::interpretType(schema::Type::Reader proto, uint location) const {
auto param = anyPointer.getParameter();
return getBrandBinding(param.getScopeId(), param.getParameterIndex());
}
case schema::Type::AnyPointer::IMPLICIT_METHOD_PARAMETER:
return Type(Type::ImplicitParameter {
anyPointer.getImplicitMethodParameter().getParameterIndex() });
}
KJ_UNREACHABLE;
......@@ -400,10 +403,12 @@ Type Schema::BrandArgumentList::operator[](uint index) const {
auto& binding = bindings[index];
if (binding.which == (uint)schema::Type::ANY_POINTER) {
if (binding.scopeId == 0) {
return Type(schema::Type::ANY_POINTER, binding.listDepth, nullptr);
} else {
if (binding.scopeId != 0) {
return Type::BrandParameter { binding.scopeId, binding.paramIndex };
} else if (binding.isImplicitParameter) {
return Type::ImplicitParameter { binding.paramIndex };
} else {
return Type(schema::Type::ANY_POINTER, binding.listDepth, nullptr);
}
} else if (binding.schema == nullptr) {
// Builtin / primitive type.
......@@ -798,6 +803,17 @@ kj::Maybe<Type::BrandParameter> Type::getBrandParameter() const {
}
}
kj::Maybe<Type::ImplicitParameter> Type::getImplicitParameter() const {
KJ_REQUIRE(isAnyPointer(),
"Type::getImplicitParameter() can only be called on AnyPointer types.");
if (isImplicitParam) {
return ImplicitParameter { paramIndex };
} else {
return nullptr;
}
}
bool Type::operator==(const Type& other) const {
if (baseType != other.baseType || listDepth != other.listDepth) {
return false;
......
......@@ -255,6 +255,10 @@ struct Method {
# Specifies order in which the methods were declared in the code.
# Like Struct.Field.codeOrder.
implicitParameters @7 :List(Node.Parameter);
# The parameters listed in [] (typically, type / generic parameters), whose bindings are intended
# to be inferred rather than specified explicitly, although not all languages support this.
paramStructType @2 :Id;
# ID of the parameter struct type. If a named parameter list was specified in the method
# declaration (rather than a single struct parameter type) then a corresponding struct type is
......@@ -328,6 +332,13 @@ struct Type {
parameterIndex @20 :UInt16;
# Index of the parameter within the generic type's parameter list.
}
implicitMethodParameter :group {
# This is actually a reference to an implicit (generic) parameter of a method. The only
# legal context for this type to appear is inside Method.paramBrand or Method.resultBrand.
parameterIndex @24 :UInt16;
}
}
}
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -570,6 +570,9 @@ public:
uint64_t scopeId;
uint index;
};
struct ImplicitParameter {
uint index;
};
inline Type();
inline Type(schema::Type::Which primitive);
......@@ -578,6 +581,7 @@ public:
inline Type(InterfaceSchema schema);
inline Type(ListSchema schema);
inline Type(BrandParameter param);
inline Type(ImplicitParameter param);
template <typename T>
inline static Type from();
......@@ -594,6 +598,10 @@ public:
// Only callable if which() returns ANY_POINTER. Returns null if the type is just a regular
// AnyPointer and not a parameter.
kj::Maybe<ImplicitParameter> getImplicitParameter() const;
// Only callable if which() returns ANY_POINTER. Returns null if the type is just a regular
// AnyPointer and not a parameter. "Implicit parameters" refer to type parameters on methods.
inline bool isVoid() const;
inline bool isBool() const;
inline bool isInt8() const;
......@@ -621,7 +629,11 @@ private:
schema::Type::Which baseType; // type not including applications of List()
uint8_t listDepth; // 0 for T, 1 for List(T), 2 for List(List(T)), ...
uint32_t paramIndex;
bool isImplicitParam;
// If true, this refers to an implicit method parameter. baseType must be ANY_POINTER, scopeId
// must be zero, and paramIndex indicates the parameter index.
uint16_t paramIndex;
// If baseType is ANY_POINTER but this Type actually refers to a type parameter, this is the
// index of the parameter among the parameters at its scope, and `scopeId` below is the type ID
// of the scope where the parameter was defined.
......@@ -806,7 +818,7 @@ struct ListSchema::FromImpl<List<T>> {
inline Type::Type(): baseType(schema::Type::VOID), listDepth(0), schema(nullptr) {}
inline Type::Type(schema::Type::Which primitive)
: baseType(primitive), listDepth(0), schema(nullptr) {
: baseType(primitive), listDepth(0), isImplicitParam(false), scopeId(0) {
KJ_IREQUIRE(primitive != schema::Type::STRUCT &&
primitive != schema::Type::ENUM &&
primitive != schema::Type::INTERFACE &&
......@@ -822,8 +834,11 @@ inline Type::Type(InterfaceSchema schema)
inline Type::Type(ListSchema schema)
: Type(schema.getElementType()) { ++listDepth; }
inline Type::Type(BrandParameter param)
: baseType(schema::Type::ANY_POINTER), listDepth(0), paramIndex(param.index),
scopeId(param.scopeId) {}
: baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(false),
paramIndex(param.index), scopeId(param.scopeId) {}
inline Type::Type(ImplicitParameter param)
: baseType(schema::Type::ANY_POINTER), listDepth(0), isImplicitParam(true),
paramIndex(param.index), scopeId(0) {}
inline schema::Type::Which Type::which() const {
return listDepth > 0 ? schema::Type::LIST : baseType;
......
......@@ -556,6 +556,10 @@ struct TestGenericsWrapper2 {
value @0 :TestGenericsWrapper(Text, TestAllTypes);
}
interface TestImplicitMethodParams {
call @0 [T, U] (foo :T, bar :U) -> TestGenerics(T, U);
}
struct TestUseGenerics $TestGenerics(Text, Data).ann("foo") {
basic @0 :TestGenerics(TestAllTypes, TestAnyPointer);
inner @1 :TestGenerics(TestAllTypes, TestAnyPointer).Inner;
......
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