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

Improve unions. Members of a union are now scoped within the union, although…

Improve unions.  Members of a union are now scoped within the union, although they share ordinal space with the parent struct.
parent e48068e2
......@@ -119,19 +119,19 @@ TEST(Encoding, Unions) {
MallocMessageBuilder builder;
TestUnion::Builder root = builder.getRoot<TestUnion>();
EXPECT_EQ(TestUnion::Union0::U0F0S0, root.whichUnion0());
EXPECT_EQ(Void::VOID, root.getU0f0s0());
EXPECT_DEBUG_ANY_THROW(root.getU0f0s1());
root.setU0f0s1(true);
EXPECT_EQ(TestUnion::Union0::U0F0S1, root.whichUnion0());
EXPECT_TRUE(root.getU0f0s1());
EXPECT_DEBUG_ANY_THROW(root.getU0f0s0());
root.setU0f0s8(123);
EXPECT_EQ(TestUnion::Union0::U0F0S8, root.whichUnion0());
EXPECT_EQ(123, root.getU0f0s8());
EXPECT_DEBUG_ANY_THROW(root.getU0f0s1());
EXPECT_EQ(TestUnion::Union0::U0F0S0, root.getUnion0().which());
EXPECT_EQ(Void::VOID, root.getUnion0().getU0f0s0());
EXPECT_DEBUG_ANY_THROW(root.getUnion0().getU0f0s1());
root.getUnion0().setU0f0s1(true);
EXPECT_EQ(TestUnion::Union0::U0F0S1, root.getUnion0().which());
EXPECT_TRUE(root.getUnion0().getU0f0s1());
EXPECT_DEBUG_ANY_THROW(root.getUnion0().getU0f0s0());
root.getUnion0().setU0f0s8(123);
EXPECT_EQ(TestUnion::Union0::U0F0S8, root.getUnion0().which());
EXPECT_EQ(123, root.getUnion0().getU0f0s8());
EXPECT_DEBUG_ANY_THROW(root.getUnion0().getU0f0s1());
}
struct UnionState {
......@@ -169,14 +169,15 @@ template <typename T> T one() { return static_cast<T>(1); }
template <> Text::Reader one() { return "1"; }
template <> Void one() { return Void::VOID; }
template <typename T>
UnionState initUnion(void (TestUnion::Builder::*setter)(T value)) {
template <typename T, typename U>
UnionState initUnion(U (TestUnion::Builder::*unionGetter)(),
void (U::Builder::*setter)(T value)) {
// Use the given setter to initialize the given union field and then return a struct indicating
// the location of the data that was written as well as the values of the four union
// discriminants.
MallocMessageBuilder builder;
(builder.getRoot<TestUnion>().*setter)(one<T>());
((builder.getRoot<TestUnion>().*unionGetter)().*setter)(one<T>());
ArrayPtr<const word> segment = builder.getSegmentsForOutput()[0];
CHECK(segment.size() > 2, segment.size());
......@@ -203,55 +204,58 @@ found:
offset);
}
#define INIT_UNION(unionName, fieldName) \
initUnion(&TestUnion::Builder::get##unionName, &TestUnion::unionName::Builder::set##fieldName)
TEST(Encoding, UnionLayout) {
EXPECT_EQ(UnionState({ 0,0,0,0}, -1), initUnion(&TestUnion::Builder::setU0f0s0));
EXPECT_EQ(UnionState({ 1,0,0,0}, 0), initUnion(&TestUnion::Builder::setU0f0s1));
EXPECT_EQ(UnionState({ 2,0,0,0}, 0), initUnion(&TestUnion::Builder::setU0f0s8));
EXPECT_EQ(UnionState({ 3,0,0,0}, 0), initUnion(&TestUnion::Builder::setU0f0s16));
EXPECT_EQ(UnionState({ 4,0,0,0}, 0), initUnion(&TestUnion::Builder::setU0f0s32));
EXPECT_EQ(UnionState({ 5,0,0,0}, 0), initUnion(&TestUnion::Builder::setU0f0s64));
EXPECT_EQ(UnionState({ 6,0,0,0}, 448), initUnion(&TestUnion::Builder::setU0f0sp));
EXPECT_EQ(UnionState({ 7,0,0,0}, -1), initUnion(&TestUnion::Builder::setU0f1s0));
EXPECT_EQ(UnionState({ 8,0,0,0}, 0), initUnion(&TestUnion::Builder::setU0f1s1));
EXPECT_EQ(UnionState({ 9,0,0,0}, 0), initUnion(&TestUnion::Builder::setU0f1s8));
EXPECT_EQ(UnionState({10,0,0,0}, 0), initUnion(&TestUnion::Builder::setU0f1s16));
EXPECT_EQ(UnionState({11,0,0,0}, 0), initUnion(&TestUnion::Builder::setU0f1s32));
EXPECT_EQ(UnionState({12,0,0,0}, 0), initUnion(&TestUnion::Builder::setU0f1s64));
EXPECT_EQ(UnionState({13,0,0,0}, 448), initUnion(&TestUnion::Builder::setU0f1sp));
EXPECT_EQ(UnionState({0, 0,0,0}, -1), initUnion(&TestUnion::Builder::setU1f0s0));
EXPECT_EQ(UnionState({0, 1,0,0}, 65), initUnion(&TestUnion::Builder::setU1f0s1));
EXPECT_EQ(UnionState({0, 2,0,0}, 65), initUnion(&TestUnion::Builder::setU1f1s1));
EXPECT_EQ(UnionState({0, 3,0,0}, 72), initUnion(&TestUnion::Builder::setU1f0s8));
EXPECT_EQ(UnionState({0, 4,0,0}, 72), initUnion(&TestUnion::Builder::setU1f1s8));
EXPECT_EQ(UnionState({0, 5,0,0}, 80), initUnion(&TestUnion::Builder::setU1f0s16));
EXPECT_EQ(UnionState({0, 6,0,0}, 80), initUnion(&TestUnion::Builder::setU1f1s16));
EXPECT_EQ(UnionState({0, 7,0,0}, 96), initUnion(&TestUnion::Builder::setU1f0s32));
EXPECT_EQ(UnionState({0, 8,0,0}, 96), initUnion(&TestUnion::Builder::setU1f1s32));
EXPECT_EQ(UnionState({0, 9,0,0}, 128), initUnion(&TestUnion::Builder::setU1f0s64));
EXPECT_EQ(UnionState({0,10,0,0}, 128), initUnion(&TestUnion::Builder::setU1f1s64));
EXPECT_EQ(UnionState({0,11,0,0}, 512), initUnion(&TestUnion::Builder::setU1f0sp));
EXPECT_EQ(UnionState({0,12,0,0}, 512), initUnion(&TestUnion::Builder::setU1f1sp));
EXPECT_EQ(UnionState({0,13,0,0}, -1), initUnion(&TestUnion::Builder::setU1f2s0));
EXPECT_EQ(UnionState({0,14,0,0}, 128), initUnion(&TestUnion::Builder::setU1f2s1));
EXPECT_EQ(UnionState({0,15,0,0}, 128), initUnion(&TestUnion::Builder::setU1f2s8));
EXPECT_EQ(UnionState({0,16,0,0}, 128), initUnion(&TestUnion::Builder::setU1f2s16));
EXPECT_EQ(UnionState({0,17,0,0}, 128), initUnion(&TestUnion::Builder::setU1f2s32));
EXPECT_EQ(UnionState({0,18,0,0}, 128), initUnion(&TestUnion::Builder::setU1f2s64));
EXPECT_EQ(UnionState({0,19,0,0}, 512), initUnion(&TestUnion::Builder::setU1f2sp));
EXPECT_EQ(UnionState({0,0,0,0}, 192), initUnion(&TestUnion::Builder::setU2f0s1));
EXPECT_EQ(UnionState({0,0,0,0}, 193), initUnion(&TestUnion::Builder::setU3f0s1));
EXPECT_EQ(UnionState({0,0,1,0}, 200), initUnion(&TestUnion::Builder::setU2f0s8));
EXPECT_EQ(UnionState({0,0,0,1}, 208), initUnion(&TestUnion::Builder::setU3f0s8));
EXPECT_EQ(UnionState({0,0,2,0}, 224), initUnion(&TestUnion::Builder::setU2f0s16));
EXPECT_EQ(UnionState({0,0,0,2}, 240), initUnion(&TestUnion::Builder::setU3f0s16));
EXPECT_EQ(UnionState({0,0,3,0}, 256), initUnion(&TestUnion::Builder::setU2f0s32));
EXPECT_EQ(UnionState({0,0,0,3}, 288), initUnion(&TestUnion::Builder::setU3f0s32));
EXPECT_EQ(UnionState({0,0,4,0}, 320), initUnion(&TestUnion::Builder::setU2f0s64));
EXPECT_EQ(UnionState({0,0,0,4}, 384), initUnion(&TestUnion::Builder::setU3f0s64));
EXPECT_EQ(UnionState({ 0,0,0,0}, -1), INIT_UNION(Union0, U0f0s0));
EXPECT_EQ(UnionState({ 1,0,0,0}, 0), INIT_UNION(Union0, U0f0s1));
EXPECT_EQ(UnionState({ 2,0,0,0}, 0), INIT_UNION(Union0, U0f0s8));
EXPECT_EQ(UnionState({ 3,0,0,0}, 0), INIT_UNION(Union0, U0f0s16));
EXPECT_EQ(UnionState({ 4,0,0,0}, 0), INIT_UNION(Union0, U0f0s32));
EXPECT_EQ(UnionState({ 5,0,0,0}, 0), INIT_UNION(Union0, U0f0s64));
EXPECT_EQ(UnionState({ 6,0,0,0}, 448), INIT_UNION(Union0, U0f0sp));
EXPECT_EQ(UnionState({ 7,0,0,0}, -1), INIT_UNION(Union0, U0f1s0));
EXPECT_EQ(UnionState({ 8,0,0,0}, 0), INIT_UNION(Union0, U0f1s1));
EXPECT_EQ(UnionState({ 9,0,0,0}, 0), INIT_UNION(Union0, U0f1s8));
EXPECT_EQ(UnionState({10,0,0,0}, 0), INIT_UNION(Union0, U0f1s16));
EXPECT_EQ(UnionState({11,0,0,0}, 0), INIT_UNION(Union0, U0f1s32));
EXPECT_EQ(UnionState({12,0,0,0}, 0), INIT_UNION(Union0, U0f1s64));
EXPECT_EQ(UnionState({13,0,0,0}, 448), INIT_UNION(Union0, U0f1sp));
EXPECT_EQ(UnionState({0, 0,0,0}, -1), INIT_UNION(Union1, U1f0s0));
EXPECT_EQ(UnionState({0, 1,0,0}, 65), INIT_UNION(Union1, U1f0s1));
EXPECT_EQ(UnionState({0, 2,0,0}, 65), INIT_UNION(Union1, U1f1s1));
EXPECT_EQ(UnionState({0, 3,0,0}, 72), INIT_UNION(Union1, U1f0s8));
EXPECT_EQ(UnionState({0, 4,0,0}, 72), INIT_UNION(Union1, U1f1s8));
EXPECT_EQ(UnionState({0, 5,0,0}, 80), INIT_UNION(Union1, U1f0s16));
EXPECT_EQ(UnionState({0, 6,0,0}, 80), INIT_UNION(Union1, U1f1s16));
EXPECT_EQ(UnionState({0, 7,0,0}, 96), INIT_UNION(Union1, U1f0s32));
EXPECT_EQ(UnionState({0, 8,0,0}, 96), INIT_UNION(Union1, U1f1s32));
EXPECT_EQ(UnionState({0, 9,0,0}, 128), INIT_UNION(Union1, U1f0s64));
EXPECT_EQ(UnionState({0,10,0,0}, 128), INIT_UNION(Union1, U1f1s64));
EXPECT_EQ(UnionState({0,11,0,0}, 512), INIT_UNION(Union1, U1f0sp));
EXPECT_EQ(UnionState({0,12,0,0}, 512), INIT_UNION(Union1, U1f1sp));
EXPECT_EQ(UnionState({0,13,0,0}, -1), INIT_UNION(Union1, U1f2s0));
EXPECT_EQ(UnionState({0,14,0,0}, 128), INIT_UNION(Union1, U1f2s1));
EXPECT_EQ(UnionState({0,15,0,0}, 128), INIT_UNION(Union1, U1f2s8));
EXPECT_EQ(UnionState({0,16,0,0}, 128), INIT_UNION(Union1, U1f2s16));
EXPECT_EQ(UnionState({0,17,0,0}, 128), INIT_UNION(Union1, U1f2s32));
EXPECT_EQ(UnionState({0,18,0,0}, 128), INIT_UNION(Union1, U1f2s64));
EXPECT_EQ(UnionState({0,19,0,0}, 512), INIT_UNION(Union1, U1f2sp));
EXPECT_EQ(UnionState({0,0,0,0}, 192), INIT_UNION(Union2, U2f0s1));
EXPECT_EQ(UnionState({0,0,0,0}, 193), INIT_UNION(Union3, U3f0s1));
EXPECT_EQ(UnionState({0,0,1,0}, 200), INIT_UNION(Union2, U2f0s8));
EXPECT_EQ(UnionState({0,0,0,1}, 208), INIT_UNION(Union3, U3f0s8));
EXPECT_EQ(UnionState({0,0,2,0}, 224), INIT_UNION(Union2, U2f0s16));
EXPECT_EQ(UnionState({0,0,0,2}, 240), INIT_UNION(Union3, U3f0s16));
EXPECT_EQ(UnionState({0,0,3,0}, 256), INIT_UNION(Union2, U2f0s32));
EXPECT_EQ(UnionState({0,0,0,3}, 288), INIT_UNION(Union3, U3f0s32));
EXPECT_EQ(UnionState({0,0,4,0}, 320), INIT_UNION(Union2, U2f0s64));
EXPECT_EQ(UnionState({0,0,0,4}, 384), INIT_UNION(Union3, U3f0s64));
}
TEST(Encoding, UnionDefault) {
......@@ -260,26 +264,26 @@ TEST(Encoding, UnionDefault) {
{
auto field = reader.getS16s8s64s8Set();
EXPECT_EQ(TestUnion::Union0::U0F0S16, field.whichUnion0());
EXPECT_EQ(TestUnion::Union1::U1F0S8 , field.whichUnion1());
EXPECT_EQ(TestUnion::Union2::U2F0S64, field.whichUnion2());
EXPECT_EQ(TestUnion::Union3::U3F0S8 , field.whichUnion3());
EXPECT_EQ(321, field.getU0f0s16());
EXPECT_EQ(123, field.getU1f0s8());
EXPECT_EQ(12345678901234567ll, field.getU2f0s64());
EXPECT_EQ(55, field.getU3f0s8());
EXPECT_EQ(TestUnion::Union0::U0F0S16, field.getUnion0().which());
EXPECT_EQ(TestUnion::Union1::U1F0S8 , field.getUnion1().which());
EXPECT_EQ(TestUnion::Union2::U2F0S64, field.getUnion2().which());
EXPECT_EQ(TestUnion::Union3::U3F0S8 , field.getUnion3().which());
EXPECT_EQ(321, field.getUnion0().getU0f0s16());
EXPECT_EQ(123, field.getUnion1().getU1f0s8());
EXPECT_EQ(12345678901234567ll, field.getUnion2().getU2f0s64());
EXPECT_EQ(55, field.getUnion3().getU3f0s8());
}
{
auto field = reader.getS0sps1s32Set();
EXPECT_EQ(TestUnion::Union0::U0F1S0 , field.whichUnion0());
EXPECT_EQ(TestUnion::Union1::U1F0SP , field.whichUnion1());
EXPECT_EQ(TestUnion::Union2::U2F0S1 , field.whichUnion2());
EXPECT_EQ(TestUnion::Union3::U3F0S32, field.whichUnion3());
EXPECT_EQ(Void::VOID, field.getU0f1s0());
EXPECT_EQ("foo", field.getU1f0sp());
EXPECT_EQ(true, field.getU2f0s1());
EXPECT_EQ(12345678, field.getU3f0s32());
EXPECT_EQ(TestUnion::Union0::U0F1S0 , field.getUnion0().which());
EXPECT_EQ(TestUnion::Union1::U1F0SP , field.getUnion1().which());
EXPECT_EQ(TestUnion::Union2::U2F0S1 , field.getUnion2().which());
EXPECT_EQ(TestUnion::Union3::U3F0S32, field.getUnion3().which());
EXPECT_EQ(Void::VOID, field.getUnion0().getU0f1s0());
EXPECT_EQ("foo", field.getUnion1().getU1f0sp());
EXPECT_EQ(true, field.getUnion2().getU2f0s1());
EXPECT_EQ(12345678, field.getUnion3().getU3f0s32());
}
}
......
......@@ -153,55 +153,54 @@ struct TestDefaults {
}
struct TestUnion {
union union0 @0;
union union1 @1;
union union2 @2;
union union3 @3;
union0 @0 union {
# Pack union 0 under ideal conditions: there is no unused padding space prior to it.
u0f0s0 @4 in union0: Void;
u0f0s1 @5 in union0: Bool;
u0f0s8 @6 in union0: Int8;
u0f0s16 @7 in union0: Int16;
u0f0s32 @8 in union0: Int32;
u0f0s64 @9 in union0: Int64;
u0f0sp @10 in union0: Text;
u0f0s0 @4: Void;
u0f0s1 @5: Bool;
u0f0s8 @6: Int8;
u0f0s16 @7: Int16;
u0f0s32 @8: Int32;
u0f0s64 @9: Int64;
u0f0sp @10: Text;
# Pack more stuff into union1 -- should go in same space.
u0f1s0 @11 in union0: Void;
u0f1s1 @12 in union0: Bool;
u0f1s8 @13 in union0: Int8;
u0f1s16 @14 in union0: Int16;
u0f1s32 @15 in union0: Int32;
u0f1s64 @16 in union0: Int64;
u0f1sp @17 in union0: Text;
# Pack more stuff into union0 -- should go in same space.
u0f1s0 @11: Void;
u0f1s1 @12: Bool;
u0f1s8 @13: Int8;
u0f1s16 @14: Int16;
u0f1s32 @15: Int32;
u0f1s64 @16: Int64;
u0f1sp @17: Text;
}
# Pack one bit in order to make pathological situation for union1.
bit0 @18: Bool;
union1 @1 union {
# Pack pathologically bad case. Each field takes up new space.
u1f0s0 @19 in union1: Void;
u1f0s1 @20 in union1: Bool;
u1f1s1 @21 in union1: Bool;
u1f0s8 @22 in union1: Int8;
u1f1s8 @23 in union1: Int8;
u1f0s16 @24 in union1: Int16;
u1f1s16 @25 in union1: Int16;
u1f0s32 @26 in union1: Int32;
u1f1s32 @27 in union1: Int32;
u1f0s64 @28 in union1: Int64;
u1f1s64 @29 in union1: Int64;
u1f0sp @30 in union1: Text;
u1f1sp @31 in union1: Text;
u1f0s0 @19: Void;
u1f0s1 @20: Bool;
u1f1s1 @21: Bool;
u1f0s8 @22: Int8;
u1f1s8 @23: Int8;
u1f0s16 @24: Int16;
u1f1s16 @25: Int16;
u1f0s32 @26: Int32;
u1f1s32 @27: Int32;
u1f0s64 @28: Int64;
u1f1s64 @29: Int64;
u1f0sp @30: Text;
u1f1sp @31: Text;
# Pack more stuff into union1 -- should go into same space as u1f0s64.
u1f2s0 @32 in union1: Void;
u1f2s1 @33 in union1: Bool;
u1f2s8 @34 in union1: Int8;
u1f2s16 @35 in union1: Int16;
u1f2s32 @36 in union1: Int32;
u1f2s64 @37 in union1: Int64;
u1f2sp @38 in union1: Text;
u1f2s0 @32: Void;
u1f2s1 @33: Bool;
u1f2s8 @34: Int8;
u1f2s16 @35: Int16;
u1f2s32 @36: Int32;
u1f2s64 @37: Int64;
u1f2sp @38: Text;
}
# Fill in the rest of that bitfield from earlier.
bit2 @39: Bool;
......@@ -215,23 +214,30 @@ struct TestUnion {
# Interleave two unions to be really annoying.
# Also declare in reverse order to make sure union discriminant values are sorted by field number
# and not by declaration order.
u3f0s64 @55 in union3: Int64;
u2f0s64 @54 in union2: Int64;
u3f0s32 @53 in union3: Int32;
u2f0s32 @52 in union2: Int32;
u3f0s16 @51 in union3: Int16;
u2f0s16 @50 in union2: Int16;
u3f0s8 @48 in union3: Int8;
u2f0s8 @47 in union2: Int8;
u3f0s1 @46 in union3: Bool;
u2f0s1 @45 in union2: Bool;
union2 @2 union {
u2f0s64 @54: Int64;
u2f0s32 @52: Int32;
u2f0s16 @50: Int16;
u2f0s8 @47: Int8;
u2f0s1 @45: Bool;
}
union3 @3 union {
u3f0s64 @55: Int64;
u3f0s32 @53: Int32;
u3f0s16 @51: Int16;
u3f0s8 @48: Int8;
u3f0s1 @46: Bool;
}
}
struct TestUnionDefaults {
s16s8s64s8Set @0 :TestUnion =
(u0f0s16 = 321, u1f0s8 = 123, u2f0s64 = 12345678901234567, u3f0s8 = 55);
(union0 = u0f0s16(321), union1 = u1f0s8(123), union2 = u2f0s64(12345678901234567),
union3 = u3f0s8(55));
s0sps1s32Set @1 :TestUnion =
(u0f1s0 = void, u1f0sp = "foo", u2f0s1 = true, u3f0s32 = 12345678);
(union0 = u0f1s0(void), union1 = u1f0sp("foo"), union2 = u2f0s1(true),
union3 = u3f0s32(12345678));
}
struct TestNestedTypes {
......
......@@ -169,6 +169,14 @@ compileFieldAssignment desc (Located namePos name, Located valPos val) =
case lookupMember name (structMemberMap desc) of
Just (DescField field) ->
fmap (\x -> (field, x)) (compileValue valPos (fieldType field) val)
Just (DescUnion union) -> case val of
UnionFieldValue uName uVal ->
case lookupMember uName (unionMemberMap union) of
Just (DescField field) ->
fmap (\x -> (field, x)) (compileValue valPos (fieldType field) uVal)
_ -> makeError namePos (printf "Union %s has no member %s."
(unionName union) uName)
_ -> makeExpectError valPos "union value"
_ -> makeError namePos (printf "Struct %s has no field %s." (structName desc) name)
compileValue :: SourcePos -> TypeDesc -> FieldValue -> Status ValueDesc
......@@ -334,6 +342,11 @@ requireNoMoreThanOneFieldNumberLessThan name pos num fields = Active () errors w
then []
else [newErrorMessage (Message message) pos]
extractFieldNumbers :: [Declaration] -> [Located Integer]
extractFieldNumbers decls = concat
([ num | FieldDecl _ num _ _ <- decls ]
:[ num:extractFieldNumbers uDecls | UnionDecl _ num uDecls <- decls ])
------------------------------------------------------------------------------------------
initialPackingState = PackingState 0 0 0 0 0 0
......@@ -455,8 +468,10 @@ packUnion _ state unionState = (offset, newState, unionState) where
packFields :: [FieldDesc] -> [UnionDesc]
-> (PackingState, Map.Map Integer UnionPackingState, Map.Map Integer (Integer, PackingState))
packFields fields unions = (finalState, finalUnionState, Map.fromList packedItems) where
items = [(fieldNumber d, packField d) | d <- fields] ++
[(unionNumber d, packUnion d) | d <- unions]
items = concat (
[(fieldNumber d, packField d) | d <- fields]:
[(unionNumber d, packUnion d):[(fieldNumber d2, packField d2) | d2 <- unionFields d]
| d <- unions])
itemsByNumber = List.sortBy compareNumbers items
compareNumbers (a, _) (b, _) = compare a b
......@@ -549,8 +564,7 @@ compileDecl scope (StructDecl (Located _ name) decls) =
CompiledMemberStatus name (feedback (\desc -> do
(members, memberMap, options, statements) <- compileChildDecls desc decls
requireNoDuplicateNames decls
let fieldNums = [ num | FieldDecl _ num _ _ _ _ <- decls ] ++
[ num | UnionDecl _ num _ <- decls ]
let fieldNums = extractFieldNumbers decls
requireSequentialNumbering "Fields" fieldNums
requireOrdinalsInRange fieldNums
return (let
......@@ -576,8 +590,8 @@ compileDecl scope (StructDecl (Located _ name) decls) =
compileDecl (DescStruct parent) (UnionDecl (Located _ name) (Located numPos number) decls) =
CompiledMemberStatus name (feedback (\desc -> do
(_, _, options, statements) <- compileChildDecls desc decls
let fields = [f | f <- structFields parent, fieldInUnion name f]
(members, memberMap, options, statements) <- compileChildDecls desc decls
let fields = [f | DescField f <- members]
orderedFieldNumbers = List.sort $ map fieldNumber fields
discriminantMap = Map.fromList $ zip orderedFieldNumbers [0..]
requireNoMoreThanOneFieldNumberLessThan name numPos number fields
......@@ -591,28 +605,27 @@ compileDecl (DescStruct parent) (UnionDecl (Located _ name) (Located numPos numb
, unionTagPacking = tagPacking
, unionFields = fields
, unionOptions = options
, unionMemberMap = memberMap
, unionStatements = statements
, unionFieldDiscriminantMap = discriminantMap
})))
compileDecl _ (UnionDecl (Located pos name) _ _) =
CompiledMemberStatus name (makeError pos "Unions can only appear inside structs.")
compileDecl scope@(DescStruct parent)
(FieldDecl (Located _ name) (Located _ number) union typeExp defaultValue decls) =
CompiledMemberStatus name (feedback (\desc -> do
unionDesc <- case union of
Nothing -> return Nothing
Just (Located p n) -> do
udesc <- maybeError (descMember n scope) p
(printf "No union '%s' defined in '%s'." n (structName parent))
case udesc of
DescUnion d -> return (Just (d, unionFieldDiscriminantMap d ! number))
_ -> makeError p (printf "'%s' is not a union." n)
compileDecl scope
(FieldDecl (Located pos name) (Located _ number) typeExp defaultValue) =
CompiledMemberStatus name (do
parent <- case scope of
DescStruct s -> return s
DescUnion u -> return (unionParent u)
_ -> makeError pos "Fields can only appear inside structs."
let unionDesc = case scope of
DescUnion u -> Just (u, unionFieldDiscriminantMap u ! number)
_ -> Nothing
typeDesc <- compileType scope typeExp
defaultDesc <- case defaultValue of
Just (Located pos value) -> fmap Just (compileValue pos typeDesc value)
Just (Located defaultPos value) -> fmap Just (compileValue defaultPos typeDesc value)
Nothing -> return Nothing
(_, _, options, statements) <- compileChildDecls desc decls
return (let
(offset, packing) = structFieldPackingMap parent ! number
in DescField FieldDesc
......@@ -624,11 +637,8 @@ compileDecl scope@(DescStruct parent)
, fieldUnion = unionDesc
, fieldType = typeDesc
, fieldDefaultValue = defaultDesc
, fieldOptions = options
, fieldStatements = statements
})))
compileDecl _ (FieldDecl (Located pos name) _ _ _ _ _) =
CompiledMemberStatus name (makeError pos "Fields can only appear inside structs.")
, fieldOptions = Map.empty -- TODO
}))
compileDecl scope (InterfaceDecl (Located _ name) decls) =
CompiledMemberStatus name (feedback (\desc -> do
......
......@@ -58,12 +58,14 @@ scopePrefix desc = fullName desc ++ "::"
globalName (DescFile _) = " " -- TODO: namespaces
globalName desc = globalName (descParent desc) ++ "::" ++ descName desc
-- Flatten the descriptor tree in pre-order, returning struct and interface descriptors only. We
-- skip enums because they are always declared directly in their parent scope.
-- Flatten the descriptor tree in pre-order, returning struct, union, and interface descriptors
-- only. We skip enums because they are always declared directly in their parent scope.
flattenTypes :: [Desc] -> [Desc]
flattenTypes [] = []
flattenTypes (d@(DescStruct s):rest) = d:(flattenTypes children ++ flattenTypes rest) where
children = catMaybes $ Map.elems $ structMemberMap s
flattenTypes (d@(DescUnion u):rest) = d:(flattenTypes children ++ flattenTypes rest) where
children = catMaybes $ Map.elems $ unionMemberMap u
flattenTypes (d@(DescInterface i):rest) = d:(flattenTypes children ++ flattenTypes rest) where
children = catMaybes $ Map.elems $ interfaceMemberMap i
flattenTypes (_:rest) = flattenTypes rest
......@@ -237,12 +239,21 @@ fieldContext parent desc = mkStrContext context where
context s = parent s
unionContext parent desc = mkStrContext context where
titleCase = toTitleCase $ unionName desc
context "typeStruct" = MuBool False
context "typeUnion" = MuBool True
context "typeName" = MuVariable titleCase
context "typeFullName" = context "unionFullName"
context "typeFields" = context "unionFields"
context "unionName" = MuVariable $ unionName desc
context "unionFullName" = MuVariable $ fullName (DescStruct $ unionParent desc) ++
"::" ++ titleCase
context "unionDecl" = MuVariable $ descDecl $ DescUnion desc
context "unionTitleCase" = MuVariable $ toTitleCase $ unionName desc
context "unionTitleCase" = MuVariable titleCase
context "unionTagOffset" = MuVariable $ unionTagOffset desc
context "unionFields" = MuList $ map (fieldContext context) $ unionFields desc
context "unionHasRetro" = MuBool $ unionHasRetro desc
context s = parent s
childContext parent name = mkStrContext context where
......@@ -250,6 +261,12 @@ childContext parent name = mkStrContext context where
context s = parent s
structContext parent desc = mkStrContext context where
context "typeStruct" = MuBool True
context "typeUnion" = MuBool False
context "typeName" = context "structName"
context "typeFullName" = context "structFullName"
context "typeFields" = context "structFields"
context "structName" = MuVariable $ structName desc
context "structFullName" = MuVariable $ fullName (DescStruct desc)
context "structFields" = MuList $ map (fieldContext context) $ structFields desc
......@@ -265,8 +282,9 @@ structContext parent desc = mkStrContext context where
context s = parent s
typeContext parent desc = mkStrContext context where
context "typeStruct" = case desc of
context "typeStructOrUnion" = case desc of
DescStruct d -> muJust $ structContext context d
DescUnion u -> muJust $ unionContext context u
_ -> muNull
context "typeEnum" = case desc of
DescEnum d -> muJust $ enumContext context d
......
......@@ -42,6 +42,7 @@ data FieldValue = VoidFieldValue
| IdentifierFieldValue String
| ListFieldValue [Located FieldValue]
| RecordFieldValue [(Located String, Located FieldValue)]
| UnionFieldValue String FieldValue
deriving (Show)
data Declaration = AliasDecl (Located String) DeclName
......@@ -49,8 +50,8 @@ data Declaration = AliasDecl (Located String) DeclName
| EnumDecl (Located String) [Declaration]
| EnumValueDecl (Located String) (Located Integer) [Declaration]
| StructDecl (Located String) [Declaration]
| FieldDecl (Located String) (Located Integer) (Maybe (Located String))
TypeExpression (Maybe (Located FieldValue)) [Declaration]
| FieldDecl (Located String) (Located Integer)
TypeExpression (Maybe (Located FieldValue))
| UnionDecl (Located String) (Located Integer) [Declaration]
| InterfaceDecl (Located String) [Declaration]
| MethodDecl (Located String) (Located Integer)
......@@ -65,7 +66,7 @@ declarationName (ConstantDecl n _ _) = Just n
declarationName (EnumDecl n _) = Just n
declarationName (EnumValueDecl n _ _) = Just n
declarationName (StructDecl n _) = Just n
declarationName (FieldDecl n _ _ _ _ _) = Just n
declarationName (FieldDecl n _ _ _) = Just n
declarationName (UnionDecl n _ _) = Just n
declarationName (InterfaceDecl n _) = Just n
declarationName (MethodDecl n _ _ _ _) = Just n
......
......@@ -74,7 +74,7 @@ located p = do
return (Located (locatedPos (head input)) t)
matchUnary :: (Data a, Data b) => (a -> b) -> Located b -> Maybe a
matchUnary c t = if toConstr(c undefined) == toConstr(v)
matchUnary c t = if toConstr (c undefined) == toConstr v
then Just $ gmapQi 0 (undefined `mkQ` id) v
else Nothing
where v = locatedValue t
......@@ -101,7 +101,7 @@ anyIdentifier = tokenParser matchIdentifier
literalInt = tokenParser (matchUnary LiteralInt) <?> "integer"
literalFloat = tokenParser (matchUnary LiteralFloat) <?> "floating-point number"
literalString = tokenParser (matchUnary LiteralString) <?> "string"
literalBool = tokenParser (matchLiteralBool) <?> "boolean"
literalBool = tokenParser matchLiteralBool <?> "boolean"
literalVoid = tokenParser (matchSimpleToken VoidKeyword) <?> "\"void\""
atSign = tokenParser (matchSimpleToken AtSign) <?> "\"@\""
......@@ -109,8 +109,6 @@ colon = tokenParser (matchSimpleToken Colon) <?> "\":\""
period = tokenParser (matchSimpleToken Period) <?> "\".\""
equalsSign = tokenParser (matchSimpleToken EqualsSign) <?> "\"=\""
minusSign = tokenParser (matchSimpleToken MinusSign) <?> "\"=\""
exclamationPoint = tokenParser (matchSimpleToken ExclamationPoint) <?> "\"!\""
inKeyword = tokenParser (matchSimpleToken InKeyword) <?> "\"in\""
importKeyword = tokenParser (matchSimpleToken ImportKeyword) <?> "\"import\""
usingKeyword = tokenParser (matchSimpleToken UsingKeyword) <?> "\"using\""
constKeyword = tokenParser (matchSimpleToken ConstKeyword) <?> "\"const\""
......@@ -123,6 +121,11 @@ optionKeyword = tokenParser (matchSimpleToken OptionKeyword) <?> "\"option\""
parenthesizedList parser = do
items <- tokenParser (matchUnary ParenthesizedList)
parseList parser items
parenthesized parser = do
items <- tokenParser (matchUnary ParenthesizedList)
unless (length items == 1) (fail "Expected exactly one item in parentheses.")
[result] <- parseList parser items
return result
bracketedList parser = do
items <- tokenParser (matchUnary BracketedList)
parseList parser items
......@@ -201,27 +204,25 @@ structDecl statements = do
return (StructDecl name children)
structLine :: Maybe [Located Statement] -> TokenParser Declaration
structLine Nothing = optionDecl <|> constantDecl <|> unionDecl [] <|> fieldDecl []
structLine (Just statements) = typeDecl statements <|> unionDecl statements <|> fieldDecl statements
structLine Nothing = optionDecl <|> constantDecl <|> fieldDecl
structLine (Just statements) = typeDecl statements <|> unionDecl statements <|> unionDecl statements
unionDecl statements = do
unionKeyword
(name, ordinal) <- nameWithOrdinal
unionKeyword
children <- parseBlock unionLine statements
return (UnionDecl name ordinal children)
unionLine :: Maybe [Located Statement] -> TokenParser Declaration
unionLine Nothing = optionDecl <|> fieldDecl []
unionLine (Just statements) = fieldDecl statements
unionLine Nothing = optionDecl <|> fieldDecl
unionLine (Just _) = fail "Blocks not allowed here."
fieldDecl statements = do
fieldDecl = do
(name, ordinal) <- nameWithOrdinal
union <- optionMaybe (inKeyword >> located varIdentifier)
colon
t <- typeExpression
value <- optionMaybe (equalsSign >> located fieldValue)
children <- parseBlock fieldLine statements
return (FieldDecl name ordinal union t value children)
return (FieldDecl name ordinal t value)
negativeFieldValue = liftM (IntegerFieldValue . negate) literalInt
<|> liftM (FloatFieldValue . negate) literalFloat
......@@ -231,22 +232,24 @@ fieldValue = (literalVoid >> return VoidFieldValue)
<|> liftM IntegerFieldValue literalInt
<|> liftM FloatFieldValue literalFloat
<|> liftM StringFieldValue literalString
<|> liftM IdentifierFieldValue varIdentifier
<|> enumOrUnionFieldValue
<|> liftM ListFieldValue (bracketedList (located fieldValue))
<|> liftM RecordFieldValue (parenthesizedList fieldAssignment)
<|> (minusSign >> negativeFieldValue)
<?> "default value"
enumOrUnionFieldValue = do
name <- varIdentifier
liftM (UnionFieldValue name) (try (parenthesized fieldValue))
<|> liftM (UnionFieldValue name . RecordFieldValue) (parenthesizedList fieldAssignment)
<|> return (IdentifierFieldValue name)
fieldAssignment = do
name <- located varIdentifier
equalsSign
value <- located fieldValue
return (name, value)
fieldLine :: Maybe [Located Statement] -> TokenParser Declaration
fieldLine Nothing = optionDecl
fieldLine (Just _) = fail "Blocks not allowed here."
interfaceDecl statements = do
interfaceKeyword
name <- located typeIdentifier
......
......@@ -134,7 +134,12 @@ valueString (TextDesc s) = show s
valueString (DataDesc s) = show (map (chr . fromIntegral) s)
valueString (EnumValueValueDesc v) = enumValueName v
valueString (StructValueDesc l) = "(" ++ delimit ", " (map assignmentString l) ++ ")" where
assignmentString (field, value) = fieldName field ++ " = " ++ valueString value
assignmentString (field, value) = case fieldUnion field of
Nothing -> fieldName field ++ " = " ++ valueString value
Just (u, _) -> unionName u ++ " = " ++ fieldName field ++
(case value of
StructValueDesc _ -> valueString value
_ -> "(" ++ valueString value ++ ")")
valueString (ListDesc l) = "[" ++ delimit ", " (map valueString l) ++ "]" where
data TypeDesc = BuiltinType BuiltinType
......@@ -323,16 +328,13 @@ data UnionDesc = UnionDesc
, unionTagPacking :: PackingState
, unionFields :: [FieldDesc]
, unionOptions :: OptionMap
, unionMemberMap :: MemberMap
, unionStatements :: [CompiledStatement]
-- Maps field numbers to discriminants for all fields in the union.
, unionFieldDiscriminantMap :: Map.Map Integer Integer
}
unionHasRetro desc = case unionFields desc of
[] -> False
f:_ -> fieldNumber f < unionNumber desc
data FieldDesc = FieldDesc
{ fieldName :: String
, fieldParent :: StructDesc
......@@ -343,7 +345,6 @@ data FieldDesc = FieldDesc
, fieldType :: TypeDesc
, fieldDefaultValue :: Maybe ValueDesc
, fieldOptions :: OptionMap
, fieldStatements :: [CompiledStatement]
}
data InterfaceDesc = InterfaceDesc
......@@ -401,14 +402,16 @@ descToCode indent (DescConstant desc) = printf "%sconst %s: %s = %s;\n" indent
(constantName desc)
(typeName (constantParent desc) (constantType desc))
(valueString (constantValue desc))
descToCode indent (DescEnum desc) = printf "%senum %s%s" indent
descToCode indent (DescEnum desc) = printf "%senum %s {\n%s%s}\n" indent
(enumName desc)
(blockCode indent (enumStatements desc))
indent
descToCode indent (DescEnumValue desc) = printf "%s%s @%d%s" indent
(enumValueName desc) (enumValueNumber desc) (maybeBlockCode indent $ enumValueStatements desc)
descToCode indent (DescStruct desc) = printf "%sstruct %s%s" indent
descToCode indent (DescStruct desc) = printf "%sstruct %s {\n%s%s}\n" indent
(structName desc)
(blockCode indent (structStatements desc))
indent
descToCode indent (DescField desc) = printf "%s%s@%d%s: %s%s; # %s\n" indent
(fieldName desc) (fieldNumber desc)
(case fieldUnion desc of { Nothing -> ""; Just (u, _) -> " in " ++ unionName u})
......@@ -421,14 +424,15 @@ descToCode indent (DescField desc) = printf "%s%s@%d%s: %s%s; # %s\n" indent
bits = sizeInBits s
offset = fieldOffset desc
in printf "bits[%d, %d)" (offset * bits) ((offset + 1) * bits))
-- (maybeBlockCode indent $ fieldStatements desc)
descToCode indent (DescUnion desc) = printf "%sunion %s@%d; # [%d, %d)\n" indent
descToCode indent (DescUnion desc) = printf "%sunion %s@%d { # [%d, %d)\n%s%s}\n" indent
(unionName desc) (unionNumber desc)
(unionTagOffset desc * 16) (unionTagOffset desc * 16 + 16)
-- (maybeBlockCode indent $ unionStatements desc)
descToCode indent (DescInterface desc) = printf "%sinterface %s%s" indent
(blockCode indent $ unionStatements desc)
indent
descToCode indent (DescInterface desc) = printf "%sinterface %s {\n%s%s}\n" indent
(interfaceName desc)
(blockCode indent (interfaceStatements desc))
indent
descToCode indent (DescMethod desc) = printf "%s%s@%d(%s): %s%s" indent
(methodName desc) (methodNumber desc)
(delimit ", " (map paramToCode (methodParams desc)))
......@@ -451,12 +455,10 @@ statementToCode indent (CompiledOption desc) = printf "%s%s.%s = %s;\n" indent
maybeBlockCode :: String -> [CompiledStatement] -> String
maybeBlockCode _ [] = ";\n"
maybeBlockCode indent statements = blockCode indent statements
maybeBlockCode indent statements = printf " {\n%s%s}\n" (blockCode indent statements) indent
blockCode :: String -> [CompiledStatement] -> String
blockCode indent statements = printf " {\n%s%s}\n"
(concatMap (statementToCode (" " ++ indent)) statements)
indent
blockCode indent = concatMap (statementToCode (" " ++ indent))
instance Show FileDesc where { show desc = descToCode "" (DescFile desc) }
instance Show AliasDesc where { show desc = descToCode "" (DescAlias desc) }
......
......@@ -34,14 +34,18 @@ namespace {{namespaceName}} {
{{/fileNamespaces}}
{{! =========================================================================================== }}
{{#fileTypes}}
{{#typeStruct}}
{{#typeStructOrUnion}}
struct {{structFullName}} {
struct {{typeFullName}} {
class Reader;
class Builder;
{{#typeStruct}}
{{#structNestedStructs}}
struct {{nestedName}};
{{/structNestedStructs}}
{{#structUnions}}
struct {{unionTitleCase}};
{{/structUnions}}
{{#structNestedInterfaces}}
struct {{nestedName}};
{{/structNestedInterfaces}}
......@@ -57,22 +61,24 @@ struct {{structFullName}} {
static constexpr ::capnproto::internal::StructSize STRUCT_SIZE =
::capnproto::internal::StructSize({{structDataSize}} * ::capnproto::WORDS,
{{structReferenceCount}} * ::capnproto::REFERENCES);
{{#structFields}}
{{#fieldDefaultBytes}}
static const ::capnproto::internal::AlignedData<{{defaultWordCount}}> DEFAULT_{{fieldUpperCase}};
{{/fieldDefaultBytes}}
{{/structFields}}
{{#structUnions}}
// {{unionDecl}}
enum class {{unionTitleCase}}: uint16_t {
{{/typeStruct}}
{{#typeUnion}}
enum Which: uint16_t {
{{#unionFields}}
{{fieldUpperCase}} = {{fieldUnionDiscriminant}},
{{/unionFields}}
};
{{/structUnions}}
{{/typeUnion}}
{{#typeFields}}
{{#fieldDefaultBytes}}
static const ::capnproto::internal::AlignedData<{{defaultWordCount}}> DEFAULT_{{fieldUpperCase}};
{{/fieldDefaultBytes}}
{{/typeFields}}
};
{{/typeStruct}}
{{/typeStructOrUnion}}
{{/fileTypes}}
{{! ------------------------------------------------------------------------------------------- }}
{{#fileEnums}}
......@@ -85,18 +91,24 @@ enum class {{enumName}}: uint16_t {
{{/fileEnums}}
{{! =========================================================================================== }}
{{#fileTypes}}
{{#typeStruct}}
{{#typeStructOrUnion}}
class {{structFullName}}::Reader {
class {{typeFullName}}::Reader {
public:
Reader() = default;
inline explicit Reader(::capnproto::internal::StructReader base): _reader(base) {}
{{#typeStruct}}
{{#structUnions}}
// {{unionDecl}}
inline {{unionTitleCase}} which{{unionTitleCase}}();
inline {{unionTitleCase}}::Reader get{{unionTitleCase}}();
{{/structUnions}}
{{#structFields}}
{{/typeStruct}}
{{#typeUnion}}
inline Which which();
{{/typeUnion}}
{{#typeFields}}
// {{fieldDecl}}
{{#fieldIsPrimitive}}
......@@ -111,28 +123,30 @@ public:
{{#fieldIsList}}
inline {{fieldType}}::Reader get{{fieldTitleCase}}();
{{/fieldIsList}}
{{/structFields}}
{{/typeFields}}
private:
::capnproto::internal::StructReader _reader;
};
{{/typeStruct}}
{{/fileTypes}}
{{! ------------------------------------------------------------------------------------------- }}
{{#fileTypes}}
{{#typeStruct}}
class {{structFullName}}::Builder {
class {{typeFullName}}::Builder {
public:
Builder() = default;
inline explicit Builder(::capnproto::internal::StructBuilder base): _builder(base) {}
inline operator Reader() { return Reader(_builder.asReader()); }
inline Reader asReader() { return *this; }
{{#typeStruct}}
{{#structUnions}}
// {{unionDecl}}
inline {{unionTitleCase}} which{{unionTitleCase}}();
inline {{unionTitleCase}}::Builder get{{unionTitleCase}}();
{{/structUnions}}
{{#structFields}}
{{/typeStruct}}
{{#typeUnion}}
inline Which which();
{{/typeUnion}}
{{#typeFields}}
// {{fieldDecl}}
{{#fieldIsPrimitive}}
......@@ -164,112 +178,88 @@ public:
inline {{fieldType}}::Builder init{{fieldTitleCase}}(unsigned int size);
inline {{fieldType}}::Builder get{{fieldTitleCase}}();
{{/fieldIsStructList}}
{{/structFields}}
{{/typeFields}}
private:
::capnproto::internal::StructBuilder _builder;
};
{{/typeStruct}}
{{/typeStructOrUnion}}
{{/fileTypes}}
{{! =========================================================================================== }}
{{#fileTypes}}
{{#typeStructOrUnion}}
{{#typeStruct}}
{{#structUnions}}
// {{structFullName}}.{{unionDecl}}
inline {{structFullName}}::{{unionTitleCase}} {{structFullName}}::Reader::which{{unionTitleCase}}() {
return _reader.getDataField<{{unionTitleCase}}>({{unionTagOffset}} * ::capnproto::ELEMENTS);
inline {{unionFullName}}::Reader {{structFullName}}::Reader::get{{unionTitleCase}}() {
return {{unionFullName}}::Reader(_reader);
}
inline {{unionFullName}}::Builder {{structFullName}}::Builder::get{{unionTitleCase}}() {
return {{unionFullName}}::Builder(_builder);
}
{{/structUnions}}
{{#structFields}}
{{/typeStruct}}
{{#typeUnion}}
// {{unionFullName}}
inline {{unionFullName}}::Which {{unionFullName}}::Reader::which() {
return _reader.getDataField<Which>({{unionTagOffset}} * ::capnproto::ELEMENTS);
}
inline {{unionFullName}}::Which {{unionFullName}}::Builder::which() {
return _builder.getDataField<Which>({{unionTagOffset}} * ::capnproto::ELEMENTS);
}
{{/typeUnion}}
{{! ------------------------------------------------------------------------------------------- }}
{{#typeFields}}
// {{structFullName}}.{{fieldDecl}}
// {{typeFullName}}::{{fieldDecl}}
{{! ------------------------------------------------------------------------------------------- }}
{{#fieldIsPrimitive}}
inline {{fieldType}} {{structFullName}}::Reader::get{{fieldTitleCase}}() {
inline {{fieldType}} {{typeFullName}}::Reader::get{{fieldTitleCase}}() {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which{{unionTitleCase}}() == {{unionTitleCase}}::{{fieldUpperCase}},
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return _reader.getDataField<{{fieldType}}>(
{{fieldOffset}} * ::capnproto::ELEMENTS{{fieldDefaultMask}});
}
{{/fieldIsPrimitive}}
{{#fieldIsBlob}}
inline {{fieldType}}::Reader {{structFullName}}::Reader::get{{fieldTitleCase}}() {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which{{unionTitleCase}}() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return _reader.get{{fieldBlobType}}Field(
{{fieldOffset}} * ::capnproto::REFERENCES,
{{#fieldDefaultBytes}}
DEFAULT_{{fieldUpperCase}}.words, {{defaultBlobSize}} * ::capnproto::BYTES
{{/fieldDefaultBytes}}
{{^fieldDefaultBytes}}nullptr, 0 * ::capnproto::BYTES{{/fieldDefaultBytes}});
}
{{/fieldIsBlob}}
{{#fieldIsStruct}}
inline {{fieldType}}::Reader {{structFullName}}::Reader::get{{fieldTitleCase}}() {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which{{unionTitleCase}}() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return {{fieldType}}::Reader(_reader.getStructField(
{{fieldOffset}} * ::capnproto::REFERENCES,
{{#fieldDefaultBytes}}DEFAULT_{{fieldUpperCase}}.words{{/fieldDefaultBytes}}
{{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}}));
}
{{/fieldIsStruct}}
{{#fieldIsList}}
inline {{fieldType}}::Reader {{structFullName}}::Reader::get{{fieldTitleCase}}() {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which{{unionTitleCase}}() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return {{fieldType}}::Reader(_reader.getListField(
{{fieldOffset}} * ::capnproto::REFERENCES,
::capnproto::internal::FieldSize::{{fieldElementSize}},
{{#fieldDefaultBytes}}DEFAULT_{{fieldUpperCase}}.words{{/fieldDefaultBytes}}
{{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}}));
}
{{/fieldIsList}}
{{/structFields}}
{{/typeStruct}}
{{/fileTypes}}
{{! =========================================================================================== }}
{{#fileTypes}}
{{#typeStruct}}
{{#structUnions}}
// {{structFullName}}.{{unionDecl}}
inline {{structFullName}}::{{unionTitleCase}} {{structFullName}}::Builder::which{{unionTitleCase}}() {
return _builder.getDataField<{{unionTitleCase}}>({{unionTagOffset}} * ::capnproto::ELEMENTS);
}
{{/structUnions}}
{{#structFields}}
// {{structFullName}}.{{fieldDecl}}
{{#fieldIsPrimitive}}
inline {{fieldType}} {{structFullName}}::Builder::get{{fieldTitleCase}}() {
inline {{fieldType}} {{typeFullName}}::Builder::get{{fieldTitleCase}}() {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which{{unionTitleCase}}() == {{unionTitleCase}}::{{fieldUpperCase}},
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return _builder.getDataField<{{fieldType}}>(
{{fieldOffset}} * ::capnproto::ELEMENTS{{fieldDefaultMask}});
}
inline void {{structFullName}}::Builder::set{{fieldTitleCase}}({{fieldType}} value) {
inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}({{fieldType}} value) {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}>(
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
return _builder.setDataField<{{fieldType}}>(
{{fieldOffset}} * ::capnproto::ELEMENTS, value{{fieldDefaultMask}});
}
{{/fieldIsPrimitive}}
{{! ------------------------------------------------------------------------------------------- }}
{{#fieldIsBlob}}
inline {{fieldType}}::Builder {{structFullName}}::Builder::get{{fieldTitleCase}}() {
inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return _reader.get{{fieldBlobType}}Field(
{{fieldOffset}} * ::capnproto::REFERENCES,
{{#fieldDefaultBytes}}
DEFAULT_{{fieldUpperCase}}.words, {{defaultBlobSize}} * ::capnproto::BYTES
{{/fieldDefaultBytes}}
{{^fieldDefaultBytes}}nullptr, 0 * ::capnproto::BYTES{{/fieldDefaultBytes}});
}
inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}() {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which{{unionTitleCase}}() == {{unionTitleCase}}::{{fieldUpperCase}},
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return _builder.get{{fieldBlobType}}Field({{fieldOffset}} * ::capnproto::REFERENCES,
......@@ -278,34 +268,46 @@ inline {{fieldType}}::Builder {{structFullName}}::Builder::get{{fieldTitleCase}}
{{/fieldDefaultBytes}}
{{^fieldDefaultBytes}}nullptr, 0 * ::capnproto::BYTES{{/fieldDefaultBytes}});
}
inline void {{structFullName}}::Builder::set{{fieldTitleCase}}({{fieldType}}::Reader value) {
inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}({{fieldType}}::Reader value) {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}>(
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
_builder.set{{fieldBlobType}}Field({{fieldOffset}} * ::capnproto::REFERENCES, value);
}
inline {{fieldType}}::Builder {{structFullName}}::Builder::init{{fieldTitleCase}}(unsigned int size) {
inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(unsigned int size) {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}>(
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
return _builder.init{{fieldBlobType}}Field(
{{fieldOffset}} * ::capnproto::REFERENCES, size * ::capnproto::BYTES);
}
{{/fieldIsBlob}}
{{! ------------------------------------------------------------------------------------------- }}
{{#fieldIsStruct}}
inline {{fieldType}}::Builder {{structFullName}}::Builder::init{{fieldTitleCase}}() {
inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}>(
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return {{fieldType}}::Reader(_reader.getStructField(
{{fieldOffset}} * ::capnproto::REFERENCES,
{{#fieldDefaultBytes}}DEFAULT_{{fieldUpperCase}}.words{{/fieldDefaultBytes}}
{{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}}));
}
inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}() {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
return {{fieldType}}::Builder(_builder.initStructField(
{{fieldOffset}} * ::capnproto::REFERENCES, {{fieldType}}::STRUCT_SIZE));
}
inline {{fieldType}}::Builder {{structFullName}}::Builder::get{{fieldTitleCase}}() {
inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}() {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which{{unionTitleCase}}() == {{unionTitleCase}}::{{fieldUpperCase}},
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return {{fieldType}}::Builder(_builder.getStructField(
......@@ -314,10 +316,25 @@ inline {{fieldType}}::Builder {{structFullName}}::Builder::get{{fieldTitleCase}}
{{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}}));
}
{{/fieldIsStruct}}
{{! ------------------------------------------------------------------------------------------- }}
{{#fieldIsList}}
inline {{fieldType}}::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}() {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return {{fieldType}}::Reader(_reader.getListField(
{{fieldOffset}} * ::capnproto::REFERENCES,
::capnproto::internal::FieldSize::{{fieldElementSize}},
{{#fieldDefaultBytes}}DEFAULT_{{fieldUpperCase}}.words{{/fieldDefaultBytes}}
{{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}}));
}
{{/fieldIsList}}
{{! ------------------------------------------------------------------------------------------- }}
{{#fieldIsNonStructList}}
inline {{fieldType}}::Builder {{structFullName}}::Builder::init{{fieldTitleCase}}(unsigned int size) {
inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(unsigned int size) {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}>(
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
return {{fieldType}}::Builder(_builder.initListField(
......@@ -325,9 +342,9 @@ inline {{fieldType}}::Builder {{structFullName}}::Builder::init{{fieldTitleCase}
::capnproto::internal::FieldSize::{{fieldElementSize}},
size * ::capnproto::ELEMENTS));
}
inline {{fieldType}}::Builder {{structFullName}}::Builder::get{{fieldTitleCase}}() {
inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}() {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which{{unionTitleCase}}() == {{unionTitleCase}}::{{fieldUpperCase}},
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return {{fieldType}}::Builder(_builder.getListField(
......@@ -336,47 +353,50 @@ inline {{fieldType}}::Builder {{structFullName}}::Builder::get{{fieldTitleCase}}
{{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}}));
}
template <typename _t>
inline void {{structFullName}}::Builder::set{{fieldTitleCase}}(const _t& other) {
inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}(const _t& other) {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}>(
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
init{{fieldTitleCase}}(other.size()).copyFrom(other);
}
{{! ------------------------------------------------------------------------------------------- }}
{{#fieldIsPrimitiveList}}
inline void {{structFullName}}::Builder::set{{fieldTitleCase}}(
inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}(
std::initializer_list<{{fieldElementType}}> other) {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}>(
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
init{{fieldTitleCase}}(other.size()).copyFrom(other);
}
{{/fieldIsPrimitiveList}}
{{! ------------------------------------------------------------------------------------------- }}
{{^fieldIsPrimitiveList}}
inline void {{structFullName}}::Builder::set{{fieldTitleCase}}(
inline void {{typeFullName}}::Builder::set{{fieldTitleCase}}(
std::initializer_list<{{fieldElementType}}::Reader> other) {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}>(
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
init{{fieldTitleCase}}(other.size()).copyFrom(other);
}
{{/fieldIsPrimitiveList}}
{{/fieldIsNonStructList}}
{{! ------------------------------------------------------------------------------------------- }}
{{#fieldIsStructList}}
inline {{fieldType}}::Builder {{structFullName}}::Builder::init{{fieldTitleCase}}(unsigned int size) {
inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(unsigned int size) {
{{#fieldUnion}}
_builder.setDataField<{{unionTitleCase}}>(
_builder.setDataField<{{unionTitleCase}}::Which>(
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
return {{fieldType}}::Builder(_builder.initStructListField(
{{fieldOffset}} * ::capnproto::REFERENCES, size * ::capnproto::ELEMENTS,
{{fieldElementType}}::STRUCT_SIZE));
}
inline {{fieldType}}::Builder {{structFullName}}::Builder::get{{fieldTitleCase}}() {
inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}() {
{{#fieldUnion}}
CAPNPROTO_INLINE_DPRECOND(which{{unionTitleCase}}() == {{unionTitleCase}}::{{fieldUpperCase}},
CAPNPROTO_INLINE_DPRECOND(which() == {{unionTitleCase}}::{{fieldUpperCase}},
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return {{fieldType}}::Builder(_builder.getListField(
......@@ -385,8 +405,8 @@ inline {{fieldType}}::Builder {{structFullName}}::Builder::get{{fieldTitleCase}}
{{^fieldDefaultBytes}}nullptr{{/fieldDefaultBytes}}));
}
{{/fieldIsStructList}}
{{/structFields}}
{{/typeStruct}}
{{/typeFields}}
{{/typeStructOrUnion}}
{{/fileTypes}}
{{! =========================================================================================== }}
......
......@@ -32,6 +32,7 @@ namespace {{namespaceName}} {
{{/fileNamespaces}}
{{#fileTypes}}
{{#typeStructOrUnion}}
{{#typeStruct}}
constexpr ::capnproto::internal::StructSize {{structFullName}}::STRUCT_SIZE;
......@@ -44,6 +45,7 @@ const ::capnproto::internal::AlignedData<{{defaultWordCount}}>
{{/fieldDefaultBytes}}
{{/structFields}}
{{/typeStruct}}
{{/typeStructOrUnion}}
{{/fileTypes}}
{{#fileNamespaces}}
......
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