From d1a2ce4049429e3e7198a2e066a5829cd929750f Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Mon, 27 Oct 2014 13:29:16 -0400 Subject: [PATCH] a start on generics --- compiler/src/main/cpp/capnpc-java.c++ | 44 +++++++++++++++++++++------ compiler/src/test/schema/test.capnp | 25 +++++++++++++++ 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/compiler/src/main/cpp/capnpc-java.c++ b/compiler/src/main/cpp/capnpc-java.c++ index f6a01ad..4d71c50 100644 --- a/compiler/src/main/cpp/capnpc-java.c++ +++ b/compiler/src/main/cpp/capnpc-java.c++ @@ -1091,11 +1091,23 @@ private: } - kj::StringTree makeReaderDef(kj::StringPtr fullName, kj::StringPtr unqualifiedParentType, - StructSchema schema, kj::Array&& methodDecls, + kj::Vector getTypeParameters(Schema schema) { + auto node = schema.getProto(); + kj::Vector result; + if (node.getScopeId() != 0) { + Schema parent = schemaLoader.get(node.getScopeId()); + result = getTypeParameters(parent); + } + for (auto parameter : node.getParameters()) { + result.add(kj::str(parameter.getName(), "_", kj::hex(node.getId()))); + } + return kj::mv(result); + } + + kj::StringTree makeReaderDef(StructSchema schema, kj::StringPtr typeParams, kj::Array&& methodDecls, int indent) { return kj::strTree( - spaces(indent), "public static final class Reader extends org.capnproto.StructReader {\n", + spaces(indent), "public static final class Reader", typeParams, " extends org.capnproto.StructReader {\n", spaces(indent), " Reader(org.capnproto.SegmentReader segment, int data, int pointers,", "int dataSize, short pointerCount, int nestingLimit){\n", spaces(indent), " super(segment, data, pointers, dataSize, pointerCount, nestingLimit);\n", @@ -1107,11 +1119,10 @@ private: "\n"); } - kj::StringTree makeBuilderDef(kj::StringPtr fullName, kj::StringPtr unqualifiedParentType, - StructSchema schema, kj::Array&& methodDecls, + kj::StringTree makeBuilderDef(StructSchema schema, kj::StringPtr typeParams, kj::Array&& methodDecls, int indent) { return kj::strTree( - spaces(indent), "public static final class Builder extends org.capnproto.StructBuilder {\n", + spaces(indent), "public static final class Builder", typeParams, " extends org.capnproto.StructBuilder {\n", spaces(indent), " Builder(org.capnproto.SegmentBuilder segment, int data, int pointers,", "int dataSize, short pointerCount){\n", spaces(indent), " super(segment, data, pointers, dataSize, pointerCount);\n", @@ -1136,12 +1147,25 @@ private: uint discrimOffset = structNode.getDiscriminantOffset(); structNode.getPointerCount(); + auto typeParamVec = getTypeParameters(schema); + + kj::StringTree typeParamsTree; + if (typeParamVec.size() > 0) { + typeParamsTree = kj::strTree( + "<", + kj::StringTree(KJ_MAP(p, typeParamVec) { + return kj::strTree(p); + }, ", "), + ">"); + } + kj::String typeParams = typeParamsTree.flatten(); + return StructText { kj::strTree( spaces(indent), "public static class ", name, " {\n", kj::strTree( - spaces(indent), " public static final org.capnproto.StructSize STRUCT_SIZE =\n", - spaces(indent), " new org.capnproto.StructSize((short)", structNode.getDataWordCount(), + spaces(indent), " public static final org.capnproto.StructSize STRUCT_SIZE =", + " new org.capnproto.StructSize((short)", structNode.getDataWordCount(), ",(short)", structNode.getPointerCount(), ");\n"), spaces(indent), " public static final class Factory extends org.capnproto.StructFactory {\n", @@ -1167,10 +1191,10 @@ private: spaces(indent), " new org.capnproto.StructList.Factory(factory);\n", - kj::strTree(makeReaderDef(fullName, name, schema, + kj::strTree(makeReaderDef(schema, typeParams, KJ_MAP(f, fieldTexts) { return kj::mv(f.readerMethodDecls); }, indent + 1), - makeBuilderDef(fullName, name, schema, + makeBuilderDef(schema, typeParams, KJ_MAP(f, fieldTexts) { return kj::mv(f.builderMethodDecls); }, indent + 1)), diff --git a/compiler/src/test/schema/test.capnp b/compiler/src/test/schema/test.capnp index 28146c1..58eaf22 100644 --- a/compiler/src/test/schema/test.capnp +++ b/compiler/src/test/schema/test.capnp @@ -322,6 +322,31 @@ struct TestNewVersion { new2 @4 :Text = "baz"; } +struct TestGenerics(Foo, Bar) { + foo @0 :Foo; +# rev @1 :TestGenerics(Bar, Foo); + +# struct Inner { +# foo @0 :Foo; +# bar @1 :Bar; +# } + +# struct Inner2(Baz) { +# bar @0 :Bar; +# baz @1 :Baz; +# innerBound @2 :Inner; +# innerUnbound @3 :TestGenerics.Inner; + +# struct DeepNest(Qux) { +# foo @0 :Foo; +# bar @1 :Bar; +# baz @2 :Baz; +# qux @3 :Qux; +# } +# } +} + + struct TestEmptyStruct {} struct TestConstants {