Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
7f20d533
Commit
7f20d533
authored
Apr 25, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement inline structs.
parent
9e7acd4b
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1299 additions
and
437 deletions
+1299
-437
encoding-test.c++
c++/src/capnproto/encoding-test.c++
+368
-59
layout.c++
c++/src/capnproto/layout.c++
+21
-31
layout.h
c++/src/capnproto/layout.h
+88
-14
test-util.h
c++/src/capnproto/test-util.h
+3
-0
test.capnp
c++/src/capnproto/test.capnp
+139
-1
type-safety.h
c++/src/capnproto/type-safety.h
+5
-0
capnproto-compiler.cabal
compiler/capnproto-compiler.cabal
+7
-0
Compiler.hs
compiler/src/Compiler.hs
+288
-108
CxxGenerator.hs
compiler/src/CxxGenerator.hs
+27
-9
Grammar.hs
compiler/src/Grammar.hs
+4
-3
Lexer.hs
compiler/src/Lexer.hs
+1
-0
Parser.hs
compiler/src/Parser.hs
+34
-1
Semantics.hs
compiler/src/Semantics.hs
+117
-84
Token.hs
compiler/src/Token.hs
+1
-0
WireFormat.hs
compiler/src/WireFormat.hs
+167
-127
c++-header.mustache
compiler/src/c++-header.mustache
+29
-0
No files found.
c++/src/capnproto/encoding-test.c++
View file @
7f20d533
...
@@ -165,19 +165,14 @@ std::ostream& operator<<(std::ostream& os, const UnionState& us) {
...
@@ -165,19 +165,14 @@ std::ostream& operator<<(std::ostream& os, const UnionState& us) {
return
os
<<
"}, "
<<
us
.
dataOffset
<<
")"
;
return
os
<<
"}, "
<<
us
.
dataOffset
<<
")"
;
}
}
template
<
typename
T
>
T
one
()
{
return
static_cast
<
T
>
(
1
);
}
template
<
typename
StructType
,
typename
Func
>
template
<>
Text
::
Reader
one
()
{
return
"1"
;
}
UnionState
initUnion
(
Func
&&
initializer
)
{
template
<>
Void
one
()
{
return
Void
::
VOID
;
}
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
// 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
// the location of the data that was written as well as the values of the four union
// discriminants.
// discriminants.
MallocMessageBuilder
builder
;
MallocMessageBuilder
builder
;
((
builder
.
getRoot
<
TestUnion
>
().
*
unionGetter
)().
*
setter
)(
one
<
T
>
());
initializer
(
builder
.
getRoot
<
StructType
>
());
ArrayPtr
<
const
word
>
segment
=
builder
.
getSegmentsForOutput
()[
0
];
ArrayPtr
<
const
word
>
segment
=
builder
.
getSegmentsForOutput
()[
0
];
CHECK
(
segment
.
size
()
>
2
,
segment
.
size
());
CHECK
(
segment
.
size
()
>
2
,
segment
.
size
());
...
@@ -204,58 +199,60 @@ found:
...
@@ -204,58 +199,60 @@ found:
offset
);
offset
);
}
}
#define INIT_UNION(unionName, fieldName) \
initUnion(&TestUnion::Builder::get##unionName, &TestUnion::unionName::Builder::set##fieldName)
TEST
(
Encoding
,
UnionLayout
)
{
TEST
(
Encoding
,
UnionLayout
)
{
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
0
},
-
1
),
INIT_UNION
(
Union0
,
U0f0s0
));
#define INIT_UNION(setter) \
EXPECT_EQ
(
UnionState
({
1
,
0
,
0
,
0
},
0
),
INIT_UNION
(
Union0
,
U0f0s1
));
initUnion<TestUnion>([](TestUnion::Builder b) {b.setter;})
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
({
0
,
0
,
0
,
0
},
-
1
),
INIT_UNION
(
getUnion0
().
setU0f0s0
(
Void
::
VOID
)));
EXPECT_EQ
(
UnionState
({
4
,
0
,
0
,
0
},
0
),
INIT_UNION
(
Union0
,
U0f0s32
));
EXPECT_EQ
(
UnionState
({
1
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
setU0f0s1
(
1
)));
EXPECT_EQ
(
UnionState
({
5
,
0
,
0
,
0
},
0
),
INIT_UNION
(
Union0
,
U0f0s64
));
EXPECT_EQ
(
UnionState
({
2
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
setU0f0s8
(
1
)));
EXPECT_EQ
(
UnionState
({
6
,
0
,
0
,
0
},
448
),
INIT_UNION
(
Union0
,
U0f0sp
));
EXPECT_EQ
(
UnionState
({
3
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
setU0f0s16
(
1
)));
EXPECT_EQ
(
UnionState
({
4
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
setU0f0s32
(
1
)));
EXPECT_EQ
(
UnionState
({
7
,
0
,
0
,
0
},
-
1
),
INIT_UNION
(
Union0
,
U0f1s0
));
EXPECT_EQ
(
UnionState
({
5
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
setU0f0s64
(
1
)));
EXPECT_EQ
(
UnionState
({
8
,
0
,
0
,
0
},
0
),
INIT_UNION
(
Union0
,
U0f1s1
));
EXPECT_EQ
(
UnionState
({
6
,
0
,
0
,
0
},
448
),
INIT_UNION
(
getUnion0
().
setU0f0sp
(
"1"
)));
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
({
7
,
0
,
0
,
0
},
-
1
),
INIT_UNION
(
getUnion0
().
setU0f1s0
(
Void
::
VOID
)));
EXPECT_EQ
(
UnionState
({
11
,
0
,
0
,
0
},
0
),
INIT_UNION
(
Union0
,
U0f1s32
));
EXPECT_EQ
(
UnionState
({
8
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
setU0f1s1
(
1
)));
EXPECT_EQ
(
UnionState
({
12
,
0
,
0
,
0
},
0
),
INIT_UNION
(
Union0
,
U0f1s64
));
EXPECT_EQ
(
UnionState
({
9
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
setU0f1s8
(
1
)));
EXPECT_EQ
(
UnionState
({
13
,
0
,
0
,
0
},
448
),
INIT_UNION
(
Union0
,
U0f1sp
));
EXPECT_EQ
(
UnionState
({
10
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
setU0f1s16
(
1
)));
EXPECT_EQ
(
UnionState
({
11
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
setU0f1s32
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
0
},
-
1
),
INIT_UNION
(
Union1
,
U1f0s0
));
EXPECT_EQ
(
UnionState
({
12
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
setU0f1s64
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
1
,
0
,
0
},
65
),
INIT_UNION
(
Union1
,
U1f0s1
));
EXPECT_EQ
(
UnionState
({
13
,
0
,
0
,
0
},
448
),
INIT_UNION
(
getUnion0
().
setU0f1sp
(
"1"
)));
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
,
0
,
0
,
0
},
-
1
),
INIT_UNION
(
getUnion1
().
setU1f0s0
(
Void
::
VOID
)));
EXPECT_EQ
(
UnionState
({
0
,
4
,
0
,
0
},
72
),
INIT_UNION
(
Union1
,
U1f1s8
));
EXPECT_EQ
(
UnionState
({
0
,
1
,
0
,
0
},
65
),
INIT_UNION
(
getUnion1
().
setU1f0s1
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
5
,
0
,
0
},
80
),
INIT_UNION
(
Union1
,
U1f0s16
));
EXPECT_EQ
(
UnionState
({
0
,
2
,
0
,
0
},
65
),
INIT_UNION
(
getUnion1
().
setU1f1s1
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
6
,
0
,
0
},
80
),
INIT_UNION
(
Union1
,
U1f1s16
));
EXPECT_EQ
(
UnionState
({
0
,
3
,
0
,
0
},
72
),
INIT_UNION
(
getUnion1
().
setU1f0s8
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
7
,
0
,
0
},
96
),
INIT_UNION
(
Union1
,
U1f0s32
));
EXPECT_EQ
(
UnionState
({
0
,
4
,
0
,
0
},
72
),
INIT_UNION
(
getUnion1
().
setU1f1s8
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
8
,
0
,
0
},
96
),
INIT_UNION
(
Union1
,
U1f1s32
));
EXPECT_EQ
(
UnionState
({
0
,
5
,
0
,
0
},
80
),
INIT_UNION
(
getUnion1
().
setU1f0s16
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
9
,
0
,
0
},
128
),
INIT_UNION
(
Union1
,
U1f0s64
));
EXPECT_EQ
(
UnionState
({
0
,
6
,
0
,
0
},
80
),
INIT_UNION
(
getUnion1
().
setU1f1s16
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
10
,
0
,
0
},
128
),
INIT_UNION
(
Union1
,
U1f1s64
));
EXPECT_EQ
(
UnionState
({
0
,
7
,
0
,
0
},
96
),
INIT_UNION
(
getUnion1
().
setU1f0s32
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
11
,
0
,
0
},
512
),
INIT_UNION
(
Union1
,
U1f0sp
));
EXPECT_EQ
(
UnionState
({
0
,
8
,
0
,
0
},
96
),
INIT_UNION
(
getUnion1
().
setU1f1s32
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
12
,
0
,
0
},
512
),
INIT_UNION
(
Union1
,
U1f1sp
));
EXPECT_EQ
(
UnionState
({
0
,
9
,
0
,
0
},
128
),
INIT_UNION
(
getUnion1
().
setU1f0s64
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
10
,
0
,
0
},
128
),
INIT_UNION
(
getUnion1
().
setU1f1s64
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
13
,
0
,
0
},
-
1
),
INIT_UNION
(
Union1
,
U1f2s0
));
EXPECT_EQ
(
UnionState
({
0
,
11
,
0
,
0
},
512
),
INIT_UNION
(
getUnion1
().
setU1f0sp
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
14
,
0
,
0
},
128
),
INIT_UNION
(
Union1
,
U1f2s1
));
EXPECT_EQ
(
UnionState
({
0
,
12
,
0
,
0
},
512
),
INIT_UNION
(
getUnion1
().
setU1f1sp
(
"1"
)));
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
,
13
,
0
,
0
},
-
1
),
INIT_UNION
(
getUnion1
().
setU1f2s0
(
Void
::
VOID
)));
EXPECT_EQ
(
UnionState
({
0
,
17
,
0
,
0
},
128
),
INIT_UNION
(
Union1
,
U1f2s32
));
EXPECT_EQ
(
UnionState
({
0
,
14
,
0
,
0
},
128
),
INIT_UNION
(
getUnion1
().
setU1f2s1
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
18
,
0
,
0
},
128
),
INIT_UNION
(
Union1
,
U1f2s64
));
EXPECT_EQ
(
UnionState
({
0
,
15
,
0
,
0
},
128
),
INIT_UNION
(
getUnion1
().
setU1f2s8
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
19
,
0
,
0
},
512
),
INIT_UNION
(
Union1
,
U1f2sp
));
EXPECT_EQ
(
UnionState
({
0
,
16
,
0
,
0
},
128
),
INIT_UNION
(
getUnion1
().
setU1f2s16
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
17
,
0
,
0
},
128
),
INIT_UNION
(
getUnion1
().
setU1f2s32
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
0
},
192
),
INIT_UNION
(
Union2
,
U2f0s1
));
EXPECT_EQ
(
UnionState
({
0
,
18
,
0
,
0
},
128
),
INIT_UNION
(
getUnion1
().
setU1f2s64
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
0
},
193
),
INIT_UNION
(
Union3
,
U3f0s1
));
EXPECT_EQ
(
UnionState
({
0
,
19
,
0
,
0
},
512
),
INIT_UNION
(
getUnion1
().
setU1f2sp
(
"1"
)));
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
,
0
,
0
},
192
),
INIT_UNION
(
getUnion2
().
setU2f0s1
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
2
,
0
},
224
),
INIT_UNION
(
Union2
,
U2f0s16
));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
0
},
193
),
INIT_UNION
(
getUnion3
().
setU3f0s1
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
2
},
240
),
INIT_UNION
(
Union3
,
U3f0s16
));
EXPECT_EQ
(
UnionState
({
0
,
0
,
1
,
0
},
200
),
INIT_UNION
(
getUnion2
().
setU2f0s8
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
3
,
0
},
256
),
INIT_UNION
(
Union2
,
U2f0s32
));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
1
},
208
),
INIT_UNION
(
getUnion3
().
setU3f0s8
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
3
},
288
),
INIT_UNION
(
Union3
,
U3f0s32
));
EXPECT_EQ
(
UnionState
({
0
,
0
,
2
,
0
},
224
),
INIT_UNION
(
getUnion2
().
setU2f0s16
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
4
,
0
},
320
),
INIT_UNION
(
Union2
,
U2f0s64
));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
2
},
240
),
INIT_UNION
(
getUnion3
().
setU3f0s16
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
4
},
384
),
INIT_UNION
(
Union3
,
U3f0s64
));
EXPECT_EQ
(
UnionState
({
0
,
0
,
3
,
0
},
256
),
INIT_UNION
(
getUnion2
().
setU2f0s32
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
3
},
288
),
INIT_UNION
(
getUnion3
().
setU3f0s32
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
4
,
0
},
320
),
INIT_UNION
(
getUnion2
().
setU2f0s64
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
4
},
384
),
INIT_UNION
(
getUnion3
().
setU3f0s64
(
1
)));
#undef INIT_UNION
}
}
TEST
(
Encoding
,
UnionDefault
)
{
TEST
(
Encoding
,
UnionDefault
)
{
...
@@ -287,6 +284,318 @@ TEST(Encoding, UnionDefault) {
...
@@ -287,6 +284,318 @@ TEST(Encoding, UnionDefault) {
}
}
}
}
// =======================================================================================
TEST
(
Encoding
,
InlineStructUnionLayout
)
{
uint
ptrOffset
=
TestInlineUnions
::
STRUCT_SIZE
.
data
*
BITS_PER_WORD
/
BITS
-
64
;
auto
ptr
=
[
=
](
uint
i
)
{
return
ptrOffset
+
i
*
64
;
};
#define INIT_UNION(setter) \
initUnion<TestInlineUnions>([](TestInlineUnions::Builder b) {b.setter;})
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
0
},
-
1
),
INIT_UNION
(
getUnion0
().
initF0
()));
EXPECT_EQ
(
UnionState
({
1
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF1
().
setF
(
1
)));
EXPECT_EQ
(
UnionState
({
2
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF8
().
setF0
(
true
)));
EXPECT_EQ
(
UnionState
({
3
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF16
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
4
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF32
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
5
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF64
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
6
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF128
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
7
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF192
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
8
,
0
,
0
,
0
},
-
1
),
INIT_UNION
(
getUnion0
().
initF0p
().
initF
()));
EXPECT_EQ
(
UnionState
({
9
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF1p
().
initF
().
setF
(
1
)));
EXPECT_EQ
(
UnionState
({
10
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF8p
().
initF
().
setF0
(
true
)));
EXPECT_EQ
(
UnionState
({
11
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF16p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
12
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF32p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
13
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF64p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
14
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF128p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
15
,
0
,
0
,
0
},
0
),
INIT_UNION
(
getUnion0
().
initF192p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
8
,
0
,
0
,
0
},
ptr
(
0
)),
INIT_UNION
(
getUnion0
().
initF0p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
9
,
0
,
0
,
0
},
ptr
(
0
)),
INIT_UNION
(
getUnion0
().
initF1p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
10
,
0
,
0
,
0
},
ptr
(
0
)),
INIT_UNION
(
getUnion0
().
initF8p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
11
,
0
,
0
,
0
},
ptr
(
0
)),
INIT_UNION
(
getUnion0
().
initF16p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
12
,
0
,
0
,
0
},
ptr
(
0
)),
INIT_UNION
(
getUnion0
().
initF32p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
13
,
0
,
0
,
0
},
ptr
(
0
)),
INIT_UNION
(
getUnion0
().
initF64p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
14
,
0
,
0
,
0
},
ptr
(
0
)),
INIT_UNION
(
getUnion0
().
initF128p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
15
,
0
,
0
,
0
},
ptr
(
0
)),
INIT_UNION
(
getUnion0
().
initF192p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
0
},
-
1
),
INIT_UNION
(
getUnion1
().
initF0
()));
EXPECT_EQ
(
UnionState
({
0
,
1
,
0
,
0
},
193
),
INIT_UNION
(
getUnion1
().
initF1
().
setF
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
2
,
0
,
0
},
200
),
INIT_UNION
(
getUnion1
().
initF8
().
setF0
(
true
)));
EXPECT_EQ
(
UnionState
({
0
,
3
,
0
,
0
},
208
),
INIT_UNION
(
getUnion1
().
initF16
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
4
,
0
,
0
},
224
),
INIT_UNION
(
getUnion1
().
initF32
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
5
,
0
,
0
},
256
),
INIT_UNION
(
getUnion1
().
initF64
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
6
,
0
,
0
},
256
),
INIT_UNION
(
getUnion1
().
initF128
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
7
,
0
,
0
},
256
),
INIT_UNION
(
getUnion1
().
initF192
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
0
},
448
),
INIT_UNION
(
getUnion2
().
initF1p
().
initF
().
setF
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
0
},
449
),
INIT_UNION
(
getUnion3
().
initF1p
().
initF
().
setF
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
1
,
0
},
456
),
INIT_UNION
(
getUnion2
().
initF8p
().
initF
().
setF0
(
true
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
1
},
464
),
INIT_UNION
(
getUnion3
().
initF8p
().
initF
().
setF0
(
true
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
2
,
0
},
480
),
INIT_UNION
(
getUnion2
().
initF16p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
2
},
496
),
INIT_UNION
(
getUnion3
().
initF16p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
3
,
0
},
512
),
INIT_UNION
(
getUnion2
().
initF32p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
3
},
544
),
INIT_UNION
(
getUnion3
().
initF32p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
4
,
0
},
576
),
INIT_UNION
(
getUnion2
().
initF64p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
4
},
640
),
INIT_UNION
(
getUnion3
().
initF64p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
5
,
0
},
704
),
INIT_UNION
(
getUnion2
().
initF128p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
5
},
832
),
INIT_UNION
(
getUnion3
().
initF128p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
6
,
0
},
960
),
INIT_UNION
(
getUnion2
().
initF192p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
6
},
1152
),
INIT_UNION
(
getUnion3
().
initF192p
().
initF
().
setF0
(
1
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
0
},
ptr
(
3
)),
INIT_UNION
(
getUnion2
().
initF1p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
0
},
ptr
(
4
)),
INIT_UNION
(
getUnion3
().
initF1p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
1
,
0
},
ptr
(
3
)),
INIT_UNION
(
getUnion2
().
initF8p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
1
},
ptr
(
4
)),
INIT_UNION
(
getUnion3
().
initF8p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
2
,
0
},
ptr
(
5
)),
INIT_UNION
(
getUnion2
().
initF16p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
2
},
ptr
(
7
)),
INIT_UNION
(
getUnion3
().
initF16p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
3
,
0
},
ptr
(
5
)),
INIT_UNION
(
getUnion2
().
initF32p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
3
},
ptr
(
7
)),
INIT_UNION
(
getUnion3
().
initF32p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
4
,
0
},
ptr
(
5
)),
INIT_UNION
(
getUnion2
().
initF64p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
4
},
ptr
(
7
)),
INIT_UNION
(
getUnion3
().
initF64p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
5
,
0
},
ptr
(
9
)),
INIT_UNION
(
getUnion2
().
initF128p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
5
},
ptr
(
12
)),
INIT_UNION
(
getUnion3
().
initF128p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
6
,
0
},
ptr
(
9
)),
INIT_UNION
(
getUnion2
().
initF192p
().
setP0
(
"1"
)));
EXPECT_EQ
(
UnionState
({
0
,
0
,
0
,
6
},
ptr
(
12
)),
INIT_UNION
(
getUnion3
().
initF192p
().
setP0
(
"1"
)));
#undef INIT_UNION
}
TEST
(
Encoding
,
InitInlineStruct
)
{
MallocMessageBuilder
builder
;
auto
root
=
builder
.
getRoot
<
TestInlineLayout
>
();
// Set as many bits as we can.
root
.
initF1
().
setF
(
true
);
root
.
initF1Offset
().
setF
(
true
);
root
.
setBit
(
true
);
root
.
initF8
().
setF0
(
true
);
root
.
getF8
().
setF1
(
true
);
root
.
getF8
().
setF2
(
true
);
root
.
initF16
().
setF0
(
0xffu
);
root
.
getF16
().
setF1
(
0xffu
);
root
.
initF32
().
setF0
(
0xffu
);
root
.
getF32
().
setF1
(
0xffffu
);
root
.
initF64
().
setF0
(
0xffu
);
root
.
getF64
().
setF1
(
0xffffffffu
);
root
.
initF128
().
setF0
(
0xffffffffffffffffull
);
root
.
getF128
().
setF1
(
0xffffffffffffffffull
);
root
.
initF192
().
setF0
(
0xffffffffffffffffull
);
root
.
getF192
().
setF1
(
0xffffffffffffffffull
);
root
.
getF192
().
setF2
(
0xffffffffffffffffull
);
root
.
initF0p
().
setP0
(
"foo"
);
root
.
initF1p
().
setP0
(
"foo"
);
root
.
getF1p
().
initF
().
setF
(
true
);
root
.
initF8p
().
setP0
(
"foo"
);
root
.
initF16p
().
setP0
(
"foo"
);
root
.
getF16p
().
setP1
(
"foo"
);
root
.
initF32p
().
setP0
(
"foo"
);
root
.
getF32p
().
setP1
(
"foo"
);
root
.
initF64p
().
setP0
(
"foo"
);
root
.
getF64p
().
setP1
(
"foo"
);
root
.
initF128p
().
setP0
(
"foo"
);
root
.
getF128p
().
setP1
(
"foo"
);
root
.
getF128p
().
setP2
(
"foo"
);
root
.
initF192p
().
setP0
(
"foo"
);
root
.
getF192p
().
setP1
(
"foo"
);
root
.
getF192p
().
setP2
(
"foo"
);
// Now try re-initializing each thing and making sure the surrounding things aren't modified.
EXPECT_FALSE
(
root
.
initF1
().
getF
());
EXPECT_TRUE
(
root
.
getF1Offset
().
getF
());
root
.
getF1
().
setF
(
true
);
EXPECT_FALSE
(
root
.
initF1Offset
().
getF
());
EXPECT_TRUE
(
root
.
getF1
().
getF
());
EXPECT_TRUE
(
root
.
getBit
());
EXPECT_TRUE
(
root
.
getF8
().
getF0
());
root
.
getF1Offset
().
setF
(
true
);
EXPECT_FALSE
(
root
.
initF8
().
getF0
());
EXPECT_FALSE
(
root
.
getF8
().
getF1
());
EXPECT_FALSE
(
root
.
getF8
().
getF2
());
EXPECT_TRUE
(
root
.
getF1
().
getF
());
EXPECT_TRUE
(
root
.
getBit
());
EXPECT_EQ
(
0xffu
,
root
.
getF16
().
getF0
());
root
.
initF8
().
setF0
(
true
);
root
.
getF8
().
setF1
(
true
);
root
.
getF8
().
setF2
(
true
);
EXPECT_EQ
(
0u
,
root
.
initF16
().
getF0
());
EXPECT_EQ
(
0u
,
root
.
getF16
().
getF1
());
EXPECT_TRUE
(
root
.
getF8
().
getF0
());
EXPECT_TRUE
(
root
.
getF8
().
getF1
());
EXPECT_TRUE
(
root
.
getF8
().
getF2
());
EXPECT_EQ
(
0xffu
,
root
.
getF32
().
getF0
());
root
.
getF16
().
setF0
(
0xffu
);
root
.
getF16
().
setF1
(
0xffu
);
EXPECT_EQ
(
0u
,
root
.
initF32
().
getF0
());
EXPECT_EQ
(
0u
,
root
.
getF32
().
getF1
());
EXPECT_EQ
(
0xffu
,
root
.
getF16
().
getF0
());
EXPECT_EQ
(
0xffu
,
root
.
getF16
().
getF1
());
EXPECT_EQ
(
0xffu
,
root
.
getF64
().
getF0
());
root
.
getF32
().
setF0
(
0xffu
);
root
.
getF32
().
setF1
(
0xffffu
);
EXPECT_EQ
(
0u
,
root
.
initF64
().
getF0
());
EXPECT_EQ
(
0u
,
root
.
getF64
().
getF1
());
EXPECT_EQ
(
0xffu
,
root
.
getF32
().
getF0
());
EXPECT_EQ
(
0xffffu
,
root
.
getF32
().
getF1
());
EXPECT_EQ
(
0xffffffffffffffffull
,
root
.
getF128
().
getF0
());
root
.
getF64
().
setF0
(
0xffu
);
root
.
getF64
().
setF1
(
0xffffffffu
);
EXPECT_EQ
(
0u
,
root
.
initF128
().
getF0
());
EXPECT_EQ
(
0u
,
root
.
getF128
().
getF1
());
EXPECT_EQ
(
0xffu
,
root
.
getF64
().
getF0
());
EXPECT_EQ
(
0xffffffffu
,
root
.
getF64
().
getF1
());
EXPECT_EQ
(
0xffffffffffffffffull
,
root
.
getF192
().
getF0
());
root
.
getF128
().
setF0
(
0xffffffffffffffffull
);
root
.
getF128
().
setF1
(
0xffffffffffffffffull
);
EXPECT_EQ
(
0u
,
root
.
initF192
().
getF0
());
EXPECT_EQ
(
0u
,
root
.
getF192
().
getF1
());
EXPECT_EQ
(
0u
,
root
.
getF192
().
getF2
());
EXPECT_EQ
(
0xffffffffffffffffull
,
root
.
getF128
().
getF0
());
EXPECT_EQ
(
0xffffffffffffffffull
,
root
.
getF128
().
getF1
());
EXPECT_TRUE
(
root
.
getF1p
().
getF
().
getF
());
root
.
getF192
().
setF0
(
0xffffffffffffffffull
);
root
.
getF192
().
setF1
(
0xffffffffffffffffull
);
root
.
getF192
().
setF2
(
0xffffffffffffffffull
);
EXPECT_EQ
(
""
,
root
.
initF0p
().
getP0
());
EXPECT_EQ
(
"foo"
,
root
.
getF1p
().
getP0
());
root
.
getF0p
().
setP0
(
"foo"
);
EXPECT_EQ
(
""
,
root
.
initF1p
().
getP0
());
EXPECT_EQ
(
"foo"
,
root
.
getF0p
().
getP0
());
EXPECT_EQ
(
"foo"
,
root
.
getF8p
().
getP0
());
root
.
getF1p
().
setP0
(
"foo"
);
EXPECT_EQ
(
""
,
root
.
initF8p
().
getP0
());
EXPECT_EQ
(
"foo"
,
root
.
getF1p
().
getP0
());
EXPECT_EQ
(
"foo"
,
root
.
getF16p
().
getP0
());
root
.
initF8p
().
setP0
(
"foo"
);
EXPECT_EQ
(
""
,
root
.
initF16p
().
getP0
());
EXPECT_EQ
(
""
,
root
.
getF16p
().
getP1
());
EXPECT_EQ
(
"foo"
,
root
.
getF8p
().
getP0
());
EXPECT_EQ
(
"foo"
,
root
.
getF32p
().
getP0
());
root
.
initF16p
().
setP0
(
"foo"
);
root
.
getF16p
().
setP1
(
"foo"
);
EXPECT_EQ
(
""
,
root
.
initF32p
().
getP0
());
EXPECT_EQ
(
""
,
root
.
getF32p
().
getP1
());
EXPECT_EQ
(
"foo"
,
root
.
getF16p
().
getP1
());
EXPECT_EQ
(
"foo"
,
root
.
getF64p
().
getP0
());
root
.
initF32p
().
setP0
(
"foo"
);
root
.
getF32p
().
setP1
(
"foo"
);
EXPECT_EQ
(
""
,
root
.
initF64p
().
getP0
());
EXPECT_EQ
(
""
,
root
.
getF64p
().
getP1
());
EXPECT_EQ
(
"foo"
,
root
.
getF32p
().
getP1
());
EXPECT_EQ
(
"foo"
,
root
.
getF128p
().
getP0
());
root
.
initF64p
().
setP0
(
"foo"
);
root
.
getF64p
().
setP1
(
"foo"
);
EXPECT_EQ
(
""
,
root
.
initF128p
().
getP0
());
EXPECT_EQ
(
""
,
root
.
getF128p
().
getP1
());
EXPECT_EQ
(
""
,
root
.
getF128p
().
getP2
());
EXPECT_EQ
(
"foo"
,
root
.
getF64p
().
getP1
());
EXPECT_EQ
(
"foo"
,
root
.
getF192p
().
getP0
());
root
.
initF128p
().
setP0
(
"foo"
);
root
.
getF128p
().
setP1
(
"foo"
);
root
.
getF128p
().
setP2
(
"foo"
);
EXPECT_EQ
(
""
,
root
.
initF192p
().
getP0
());
EXPECT_EQ
(
""
,
root
.
getF192p
().
getP1
());
EXPECT_EQ
(
""
,
root
.
getF192p
().
getP2
());
EXPECT_EQ
(
"foo"
,
root
.
getF128p
().
getP2
());
root
.
initF192p
().
setP0
(
"foo"
);
root
.
getF192p
().
setP1
(
"foo"
);
root
.
getF192p
().
setP2
(
"foo"
);
}
TEST
(
Encoding
,
InlineDefaults
)
{
MallocMessageBuilder
builder
;
TestInlineDefaults
::
Reader
reader
=
builder
.
getRoot
<
TestInlineDefaults
>
().
asReader
();
{
auto
normal
=
reader
.
getNormal
();
EXPECT_TRUE
(
normal
.
getF1
().
getF
());
EXPECT_TRUE
(
normal
.
getF8
().
getF0
());
EXPECT_FALSE
(
normal
.
getF8
().
getF1
());
EXPECT_TRUE
(
normal
.
getF8
().
getF2
());
EXPECT_EQ
(
123u
,
normal
.
getF16
().
getF0
());
EXPECT_EQ
(
45u
,
normal
.
getF16
().
getF1
());
EXPECT_EQ
(
67u
,
normal
.
getF32
().
getF0
());
EXPECT_EQ
(
8901u
,
normal
.
getF32
().
getF1
());
EXPECT_EQ
(
234u
,
normal
.
getF64
().
getF0
());
EXPECT_EQ
(
567890123u
,
normal
.
getF64
().
getF1
());
EXPECT_EQ
(
1234567890123ull
,
normal
.
getF128
().
getF0
());
EXPECT_EQ
(
4567890123456ull
,
normal
.
getF128
().
getF1
());
EXPECT_EQ
(
7890123456789ull
,
normal
.
getF192
().
getF0
());
EXPECT_EQ
(
2345678901234ull
,
normal
.
getF192
().
getF1
());
EXPECT_EQ
(
5678901234567ull
,
normal
.
getF192
().
getF2
());
EXPECT_FALSE
(
normal
.
getF1p
().
getF
().
getF
());
EXPECT_TRUE
(
normal
.
getF8p
().
getF
().
getF0
());
EXPECT_TRUE
(
normal
.
getF8p
().
getF
().
getF1
());
EXPECT_FALSE
(
normal
.
getF8p
().
getF
().
getF2
());
EXPECT_EQ
(
98u
,
normal
.
getF16p
().
getF
().
getF0
());
EXPECT_EQ
(
76u
,
normal
.
getF16p
().
getF
().
getF1
());
EXPECT_EQ
(
54u
,
normal
.
getF32p
().
getF
().
getF0
());
EXPECT_EQ
(
32109u
,
normal
.
getF32p
().
getF
().
getF1
());
EXPECT_EQ
(
87u
,
normal
.
getF64p
().
getF
().
getF0
());
EXPECT_EQ
(
654321098u
,
normal
.
getF64p
().
getF
().
getF1
());
EXPECT_EQ
(
7654321098765ull
,
normal
.
getF128p
().
getF
().
getF0
());
EXPECT_EQ
(
4321098765432ull
,
normal
.
getF128p
().
getF
().
getF1
());
EXPECT_EQ
(
1098765432109ull
,
normal
.
getF192p
().
getF
().
getF0
());
EXPECT_EQ
(
8765432109876ull
,
normal
.
getF192p
().
getF
().
getF1
());
EXPECT_EQ
(
5432109876543ull
,
normal
.
getF192p
().
getF
().
getF2
());
EXPECT_EQ
(
"foo"
,
normal
.
getF0p
().
getP0
());
EXPECT_EQ
(
"bar"
,
normal
.
getF1p
().
getP0
());
EXPECT_EQ
(
"baz"
,
normal
.
getF8p
().
getP0
());
EXPECT_EQ
(
"qux"
,
normal
.
getF16p
().
getP0
());
EXPECT_EQ
(
"quux"
,
normal
.
getF16p
().
getP1
());
EXPECT_EQ
(
"corge"
,
normal
.
getF32p
().
getP0
());
EXPECT_EQ
(
"grault"
,
normal
.
getF32p
().
getP1
());
EXPECT_EQ
(
"garply"
,
normal
.
getF64p
().
getP0
());
EXPECT_EQ
(
"waldo"
,
normal
.
getF64p
().
getP1
());
EXPECT_EQ
(
"fred"
,
normal
.
getF128p
().
getP0
());
EXPECT_EQ
(
"plugh"
,
normal
.
getF128p
().
getP1
());
EXPECT_EQ
(
"xyzzy"
,
normal
.
getF128p
().
getP2
());
EXPECT_EQ
(
"thud"
,
normal
.
getF192p
().
getP0
());
EXPECT_EQ
(
"foobar"
,
normal
.
getF192p
().
getP1
());
EXPECT_EQ
(
"barbaz"
,
normal
.
getF192p
().
getP2
());
}
{
auto
unions
=
reader
.
getUnions
();
ASSERT_EQ
(
TestInlineUnions
::
Union0
::
F32
,
unions
.
getUnion0
().
which
());
EXPECT_EQ
(
67u
,
unions
.
getUnion0
().
getF32
().
getF0
());
EXPECT_EQ
(
8901u
,
unions
.
getUnion0
().
getF32
().
getF1
());
ASSERT_EQ
(
TestInlineUnions
::
Union1
::
F128
,
unions
.
getUnion1
().
which
());
EXPECT_EQ
(
1234567890123ull
,
unions
.
getUnion1
().
getF128
().
getF0
());
EXPECT_EQ
(
4567890123456ull
,
unions
.
getUnion1
().
getF128
().
getF1
());
ASSERT_EQ
(
TestInlineUnions
::
Union2
::
F1P
,
unions
.
getUnion2
().
which
());
EXPECT_EQ
(
"foo"
,
unions
.
getUnion2
().
getF1p
().
getP0
());
ASSERT_EQ
(
TestInlineUnions
::
Union3
::
F16P
,
unions
.
getUnion3
().
which
());
EXPECT_EQ
(
98u
,
unions
.
getUnion3
().
getF16p
().
getF
().
getF0
());
EXPECT_EQ
(
76u
,
unions
.
getUnion3
().
getF16p
().
getF
().
getF1
());
EXPECT_EQ
(
"qux"
,
unions
.
getUnion3
().
getF16p
().
getP0
());
EXPECT_EQ
(
"quux"
,
unions
.
getUnion3
().
getF16p
().
getP1
());
}
}
// =======================================================================================
// =======================================================================================
// Tests of generated code, not really of the encoding.
// Tests of generated code, not really of the encoding.
// TODO(cleanup): Move to a different test?
// TODO(cleanup): Move to a different test?
...
...
c++/src/capnproto/layout.c++
View file @
7f20d533
...
@@ -415,7 +415,7 @@ struct WireHelpers {
...
@@ -415,7 +415,7 @@ struct WireHelpers {
ref
->
structRef
.
set
(
size
);
ref
->
structRef
.
set
(
size
);
// Build the StructBuilder.
// Build the StructBuilder.
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
size
.
data
));
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
size
.
data
)
,
0
*
BITS
);
}
}
static
CAPNPROTO_ALWAYS_INLINE
(
StructBuilder
getWritableStructReference
(
static
CAPNPROTO_ALWAYS_INLINE
(
StructBuilder
getWritableStructReference
(
...
@@ -442,7 +442,7 @@ struct WireHelpers {
...
@@ -442,7 +442,7 @@ struct WireHelpers {
"Trying to update struct with incorrect reference count."
);
"Trying to update struct with incorrect reference count."
);
}
}
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
size
.
data
));
return
StructBuilder
(
segment
,
ptr
,
reinterpret_cast
<
WireReference
*>
(
ptr
+
size
.
data
)
,
0
*
BITS
);
}
}
static
CAPNPROTO_ALWAYS_INLINE
(
ListBuilder
initListReference
(
static
CAPNPROTO_ALWAYS_INLINE
(
ListBuilder
initListReference
(
...
@@ -603,7 +603,7 @@ struct WireHelpers {
...
@@ -603,7 +603,7 @@ struct WireHelpers {
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
if
(
ref
==
nullptr
||
ref
->
isNull
())
{
useDefault
:
useDefault
:
if
(
defaultValue
==
nullptr
)
{
if
(
defaultValue
==
nullptr
)
{
return
StructReader
(
nullptr
,
nullptr
,
nullptr
,
0
*
WORD
S
,
0
*
REFERENCES
,
0
*
BITS
,
return
StructReader
(
nullptr
,
nullptr
,
nullptr
,
0
*
BIT
S
,
0
*
REFERENCES
,
0
*
BITS
,
std
::
numeric_limits
<
int
>::
max
());
std
::
numeric_limits
<
int
>::
max
());
}
}
segment
=
nullptr
;
segment
=
nullptr
;
...
@@ -637,7 +637,7 @@ struct WireHelpers {
...
@@ -637,7 +637,7 @@ struct WireHelpers {
return
StructReader
(
return
StructReader
(
segment
,
ptr
,
reinterpret_cast
<
const
WireReference
*>
(
ptr
+
ref
->
structRef
.
dataSize
.
get
()),
segment
,
ptr
,
reinterpret_cast
<
const
WireReference
*>
(
ptr
+
ref
->
structRef
.
dataSize
.
get
()),
ref
->
structRef
.
dataSize
.
get
(),
ref
->
structRef
.
dataSize
.
get
()
*
BITS_PER_WORD
,
ref
->
structRef
.
refCount
.
get
(),
ref
->
structRef
.
refCount
.
get
(),
0
*
BITS
,
nestingLimit
-
1
);
0
*
BITS
,
nestingLimit
-
1
);
}
}
...
@@ -752,7 +752,8 @@ struct WireHelpers {
...
@@ -752,7 +752,8 @@ struct WireHelpers {
}
}
return
ListReader
(
segment
,
ptr
,
size
,
wordsPerElement
*
BITS_PER_WORD
,
return
ListReader
(
segment
,
ptr
,
size
,
wordsPerElement
*
BITS_PER_WORD
,
tag
->
structRef
.
dataSize
.
get
(),
tag
->
structRef
.
refCount
.
get
(),
nestingLimit
-
1
);
tag
->
structRef
.
dataSize
.
get
()
*
BITS_PER_WORD
,
tag
->
structRef
.
refCount
.
get
(),
nestingLimit
-
1
);
}
else
{
}
else
{
// The elements of the list are NOT structs.
// The elements of the list are NOT structs.
...
@@ -774,28 +775,17 @@ struct WireHelpers {
...
@@ -774,28 +775,17 @@ struct WireHelpers {
// old version of the protocol. We need to verify that the struct's first field matches
// old version of the protocol. We need to verify that the struct's first field matches
// what the sender sent us.
// what the sender sent us.
WordCount
dataSize
;
BitCount
dataSize
=
0
*
BITS
;
WireReferenceCount
referenceCount
;
WireReferenceCount
referenceCount
=
0
*
REFERENCES
;
switch
(
ref
->
listRef
.
elementSize
())
{
switch
(
ref
->
listRef
.
elementSize
())
{
case
FieldSize
:
:
VOID
:
case
FieldSize
:
:
VOID
:
break
;
dataSize
=
0
*
WORDS
;
case
FieldSize
:
:
BIT
:
dataSize
=
1
*
BITS
;
break
;
referenceCount
=
0
*
REFERENCES
;
case
FieldSize
:
:
BYTE
:
dataSize
=
8
*
BITS
;
break
;
break
;
case
FieldSize
:
:
TWO_BYTES
:
dataSize
=
16
*
BITS
;
break
;
case
FieldSize
:
:
FOUR_BYTES
:
dataSize
=
32
*
BITS
;
break
;
case
FieldSize
:
:
BIT
:
case
FieldSize
:
:
EIGHT_BYTES
:
dataSize
=
64
*
BITS
;
break
;
case
FieldSize
:
:
BYTE
:
case
FieldSize
:
:
REFERENCE
:
referenceCount
=
1
*
REFERENCES
;
break
;
case
FieldSize
:
:
TWO_BYTES
:
case
FieldSize
:
:
FOUR_BYTES
:
case
FieldSize
:
:
EIGHT_BYTES
:
dataSize
=
1
*
WORDS
;
referenceCount
=
0
*
REFERENCES
;
break
;
case
FieldSize
:
:
REFERENCE
:
dataSize
=
0
*
WORDS
;
referenceCount
=
1
*
REFERENCES
;
break
;
case
FieldSize
:
:
INLINE_COMPOSITE
:
case
FieldSize
:
:
INLINE_COMPOSITE
:
FAIL_CHECK
();
FAIL_CHECK
();
...
@@ -978,7 +968,7 @@ StructReader StructBuilder::asReader() const {
...
@@ -978,7 +968,7 @@ StructReader StructBuilder::asReader() const {
static_assert
(
sizeof
(
WireReference
::
structRef
.
refCount
)
==
2
,
static_assert
(
sizeof
(
WireReference
::
structRef
.
refCount
)
==
2
,
"Has the maximum reference count changed?"
);
"Has the maximum reference count changed?"
);
return
StructReader
(
segment
,
data
,
references
,
return
StructReader
(
segment
,
data
,
references
,
0xffff
*
WORD
S
,
0xffff
*
REFERENCES
,
0
*
BITS
,
std
::
numeric_limits
<
int
>::
max
());
0xffff
ffff
*
BIT
S
,
0xffff
*
REFERENCES
,
0
*
BITS
,
std
::
numeric_limits
<
int
>::
max
());
}
}
StructReader
StructReader
::
readRootTrusted
(
const
word
*
location
)
{
StructReader
StructReader
::
readRootTrusted
(
const
word
*
location
)
{
...
@@ -998,7 +988,7 @@ StructReader StructReader::readRoot(
...
@@ -998,7 +988,7 @@ StructReader StructReader::readRoot(
}
}
StructReader
StructReader
::
readEmpty
()
{
StructReader
StructReader
::
readEmpty
()
{
return
StructReader
(
nullptr
,
nullptr
,
nullptr
,
0
*
WORD
S
,
0
*
REFERENCES
,
0
*
BITS
,
return
StructReader
(
nullptr
,
nullptr
,
nullptr
,
0
*
BIT
S
,
0
*
REFERENCES
,
0
*
BITS
,
std
::
numeric_limits
<
int
>::
max
());
std
::
numeric_limits
<
int
>::
max
());
}
}
...
@@ -1031,7 +1021,7 @@ StructBuilder ListBuilder::getStructElement(
...
@@ -1031,7 +1021,7 @@ StructBuilder ListBuilder::getStructElement(
ElementCount
index
,
decltype
(
WORDS
/
ELEMENTS
)
elementSize
,
WordCount
structDataSize
)
const
{
ElementCount
index
,
decltype
(
WORDS
/
ELEMENTS
)
elementSize
,
WordCount
structDataSize
)
const
{
word
*
structPtr
=
ptr
+
elementSize
*
index
;
word
*
structPtr
=
ptr
+
elementSize
*
index
;
return
StructBuilder
(
segment
,
structPtr
,
return
StructBuilder
(
segment
,
structPtr
,
reinterpret_cast
<
WireReference
*>
(
structPtr
+
structDataSize
));
reinterpret_cast
<
WireReference
*>
(
structPtr
+
structDataSize
)
,
0
*
BITS
);
}
}
ListBuilder
ListBuilder
::
initListElement
(
ListBuilder
ListBuilder
::
initListElement
(
...
@@ -1087,9 +1077,9 @@ ListReader ListBuilder::asReader(FieldSize elementSize) const {
...
@@ -1087,9 +1077,9 @@ ListReader ListBuilder::asReader(FieldSize elementSize) const {
std
::
numeric_limits
<
int
>::
max
());
std
::
numeric_limits
<
int
>::
max
());
}
}
ListReader
ListBuilder
::
asReader
(
Word
Count
dataSize
,
WireReferenceCount
referenceCount
)
const
{
ListReader
ListBuilder
::
asReader
(
Bit
Count
dataSize
,
WireReferenceCount
referenceCount
)
const
{
return
ListReader
(
segment
,
ptr
,
elementCount
,
return
ListReader
(
segment
,
ptr
,
elementCount
,
(
dataSize
+
referenceCount
*
WORDS_PER_REFERENCE
)
*
BITS_PER_WORD
/
ELEMENTS
,
(
dataSize
+
referenceCount
*
WORDS_PER_REFERENCE
*
BITS_PER_WORD
)
/
ELEMENTS
,
dataSize
,
referenceCount
,
std
::
numeric_limits
<
int
>::
max
());
dataSize
,
referenceCount
,
std
::
numeric_limits
<
int
>::
max
());
}
}
...
@@ -1103,7 +1093,7 @@ StructReader ListReader::getStructElement(ElementCount index) const {
...
@@ -1103,7 +1093,7 @@ StructReader ListReader::getStructElement(ElementCount index) const {
const
byte
*
structPtr
=
reinterpret_cast
<
const
byte
*>
(
ptr
)
+
indexBit
/
BITS_PER_BYTE
;
const
byte
*
structPtr
=
reinterpret_cast
<
const
byte
*>
(
ptr
)
+
indexBit
/
BITS_PER_BYTE
;
return
StructReader
(
return
StructReader
(
segment
,
structPtr
,
segment
,
structPtr
,
reinterpret_cast
<
const
WireReference
*>
(
structPtr
+
structDataSize
*
BYTES_PER_WORD
),
reinterpret_cast
<
const
WireReference
*>
(
structPtr
+
structDataSize
/
BITS_PER_BYTE
),
structDataSize
,
structReferenceCount
,
indexBit
%
BITS_PER_BYTE
,
nestingLimit
-
1
);
structDataSize
,
structReferenceCount
,
indexBit
%
BITS_PER_BYTE
,
nestingLimit
-
1
);
}
}
...
...
c++/src/capnproto/layout.h
View file @
7f20d533
...
@@ -28,6 +28,11 @@
...
@@ -28,6 +28,11 @@
// as does other parts of the Cap'n proto library which provide a higher-level interface for
// as does other parts of the Cap'n proto library which provide a higher-level interface for
// dynamic introspection.
// dynamic introspection.
#ifdef __CDT_PARSER__
// Eclipse keeps thinking this is pre-defined for no apparent reason.
#undef CAPNPROTO_LAYOUT_H_
#endif
#ifndef CAPNPROTO_LAYOUT_H_
#ifndef CAPNPROTO_LAYOUT_H_
#define CAPNPROTO_LAYOUT_H_
#define CAPNPROTO_LAYOUT_H_
...
@@ -91,8 +96,8 @@ enum class FieldSize: uint8_t {
...
@@ -91,8 +96,8 @@ enum class FieldSize: uint8_t {
// 2) For struct fields of composite types where the field's total size is known at compile time,
// 2) For struct fields of composite types where the field's total size is known at compile time,
// we can embed the field directly into the parent struct to avoid indirection through a
// we can embed the field directly into the parent struct to avoid indirection through a
// reference. However, this means that the field size can never change -- e.g. if it is a
// reference. However, this means that the field size can never change -- e.g. if it is a
// struct, new fields cannot be added to it.
It's unclear if this is really useful so at this
// struct, new fields cannot be added to it.
The field's struct type is therefore required to
//
time it is not supported
.
//
be declared "inline" with a fixed width
.
};
};
typedef
decltype
(
BITS
/
ELEMENTS
)
BitsPerElement
;
typedef
decltype
(
BITS
/
ELEMENTS
)
BitsPerElement
;
...
@@ -276,6 +281,17 @@ public:
...
@@ -276,6 +281,17 @@ public:
// initialized, it is initialized as a deep copy of the given default value (a trusted message),
// initialized, it is initialized as a deep copy of the given default value (a trusted message),
// or to the empty state if defaultValue is nullptr.
// or to the empty state if defaultValue is nullptr.
CAPNPROTO_ALWAYS_INLINE
(
StructBuilder
initInlineStructField
(
BitCount
dataOffset
,
BitCount
inlineDataSize
,
WireReferenceCount
refIndex
,
WireReferenceCount
inlineRefCount
)
const
);
// Initialize an inlined struct field, given the position and size of the data and pointer
// sections.
CAPNPROTO_ALWAYS_INLINE
(
StructBuilder
getInlineStructField
(
BitCount
dataOffset
,
BitCount
inlineDataSize
,
WireReferenceCount
refIndex
,
WireReferenceCount
inlineRefCount
)
const
);
// Gets an inlined struct field, given the position and size of the data and pointer sections.
ListBuilder
initListField
(
WireReferenceCount
refIndex
,
FieldSize
elementSize
,
ListBuilder
initListField
(
WireReferenceCount
refIndex
,
FieldSize
elementSize
,
ElementCount
elementCount
)
const
;
ElementCount
elementCount
)
const
;
// Allocates a new list of the given size for the field at the given index in the reference
// Allocates a new list of the given size for the field at the given index in the reference
...
@@ -313,11 +329,16 @@ public:
...
@@ -313,11 +329,16 @@ public:
private
:
private
:
SegmentBuilder
*
segment
;
// Memory segment in which the struct resides.
SegmentBuilder
*
segment
;
// Memory segment in which the struct resides.
wor
d
*
data
;
// Pointer to the encoded data.
voi
d
*
data
;
// Pointer to the encoded data.
WireReference
*
references
;
// Pointer to the encoded references.
WireReference
*
references
;
// Pointer to the encoded references.
inline
StructBuilder
(
SegmentBuilder
*
segment
,
word
*
data
,
WireReference
*
references
)
BitCount8
bit0Offset
;
:
segment
(
segment
),
data
(
data
),
references
(
references
)
{}
// A special hack: When accessing a boolean with field number zero, pretend its offset is this
// instead of the usual zero. This is needed to support 1-bit inline structs.
inline
StructBuilder
(
SegmentBuilder
*
segment
,
void
*
data
,
WireReference
*
references
,
BitCount8
bit0Offset
)
:
segment
(
segment
),
data
(
data
),
references
(
references
),
bit0Offset
(
bit0Offset
)
{}
friend
class
ListBuilder
;
friend
class
ListBuilder
;
friend
struct
WireHelpers
;
friend
struct
WireHelpers
;
...
@@ -351,6 +372,11 @@ public:
...
@@ -351,6 +372,11 @@ public:
// struct reference, which in turn points at the struct value. The default value is allowed to
// struct reference, which in turn points at the struct value. The default value is allowed to
// be null, in which case an empty struct is used.
// be null, in which case an empty struct is used.
CAPNPROTO_ALWAYS_INLINE
(
StructReader
getInlineStructField
(
BitCount
dataOffset
,
BitCount
inlineDataSize
,
WireReferenceCount
refIndex
,
WireReferenceCount
inlineRefCount
)
const
);
// Gets an inlined struct field, given the position and size of the data and pointer sections.
ListReader
getListField
(
WireReferenceCount
refIndex
,
FieldSize
expectedElementSize
,
ListReader
getListField
(
WireReferenceCount
refIndex
,
FieldSize
expectedElementSize
,
const
word
*
defaultValue
)
const
;
const
word
*
defaultValue
)
const
;
// Get the list field at the given index in the reference segment, or the default value if not
// Get the list field at the given index in the reference segment, or the default value if not
...
@@ -370,20 +396,21 @@ private:
...
@@ -370,20 +396,21 @@ private:
const
void
*
data
;
const
void
*
data
;
const
WireReference
*
references
;
const
WireReference
*
references
;
WordCount8
dataSize
;
// Size of data segment.
BitCount32
dataSize
;
// Size of data segment.
WireReferenceCount
8
referenceCount
;
// Size of the reference segment.
WireReferenceCount
16
referenceCount
;
// Size of the reference segment.
BitCount8
bit0Offset
;
BitCount8
bit0Offset
;
// A special hack: When accessing a boolean with field number zero, pretend its offset is this
// A special hack: When accessing a boolean with field number zero, pretend its offset is this
// instead of the usual zero. This is needed to allow a boolean list to be upgraded to a list
// instead of the usual zero. This is needed to allow a boolean list to be upgraded to a list
// of structs.
// of structs
, and to support 1-bit inline structs
.
int
nestingLimit
;
int
nestingLimit
;
// Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
// Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
// Once this reaches zero, further pointers will be pruned.
// Once this reaches zero, further pointers will be pruned.
// TODO: Limit to 8 bits for better alignment?
inline
StructReader
(
SegmentReader
*
segment
,
const
void
*
data
,
const
WireReference
*
references
,
inline
StructReader
(
SegmentReader
*
segment
,
const
void
*
data
,
const
WireReference
*
references
,
Word
Count
dataSize
,
WireReferenceCount
referenceCount
,
Bit
Count
dataSize
,
WireReferenceCount
referenceCount
,
BitCount
bit0Offset
,
int
nestingLimit
)
BitCount
bit0Offset
,
int
nestingLimit
)
:
segment
(
segment
),
data
(
data
),
references
(
references
),
:
segment
(
segment
),
data
(
data
),
references
(
references
),
dataSize
(
dataSize
),
referenceCount
(
referenceCount
),
bit0Offset
(
bit0Offset
),
dataSize
(
dataSize
),
referenceCount
(
referenceCount
),
bit0Offset
(
bit0Offset
),
...
@@ -448,7 +475,7 @@ public:
...
@@ -448,7 +475,7 @@ public:
ListReader
asReader
(
FieldSize
elementSize
)
const
;
ListReader
asReader
(
FieldSize
elementSize
)
const
;
// Get a ListReader pointing at the same memory. Use this version only for non-struct lists.
// Get a ListReader pointing at the same memory. Use this version only for non-struct lists.
ListReader
asReader
(
Word
Count
dataSize
,
WireReferenceCount
referenceCount
)
const
;
ListReader
asReader
(
Bit
Count
dataSize
,
WireReferenceCount
referenceCount
)
const
;
// Get a ListReader pointing at the same memory. Use this version only for struct lists.
// Get a ListReader pointing at the same memory. Use this version only for struct lists.
private
:
private
:
...
@@ -503,7 +530,7 @@ private:
...
@@ -503,7 +530,7 @@ private:
// if the sender upgraded a data list to a struct list. It will always be aligned properly for
// if the sender upgraded a data list to a struct list. It will always be aligned properly for
// the type. Unsigned so that division by a constant power of 2 is efficient.
// the type. Unsigned so that division by a constant power of 2 is efficient.
Word
Count
structDataSize
;
Bit
Count
structDataSize
;
WireReferenceCount
structReferenceCount
;
WireReferenceCount
structReferenceCount
;
// If the elements are structs, the properties of the struct. The reference count is
// If the elements are structs, the properties of the struct. The reference count is
// only used to check for field presence; the data size is also used to compute the reference
// only used to check for field presence; the data size is also used to compute the reference
...
@@ -519,7 +546,7 @@ private:
...
@@ -519,7 +546,7 @@ private:
structDataSize
(
0
),
structReferenceCount
(
0
),
structDataSize
(
0
),
structReferenceCount
(
0
),
nestingLimit
(
nestingLimit
)
{}
nestingLimit
(
nestingLimit
)
{}
inline
ListReader
(
SegmentReader
*
segment
,
const
void
*
ptr
,
ElementCount
elementCount
,
inline
ListReader
(
SegmentReader
*
segment
,
const
void
*
ptr
,
ElementCount
elementCount
,
decltype
(
BITS
/
ELEMENTS
)
stepBits
,
Word
Count
structDataSize
,
decltype
(
BITS
/
ELEMENTS
)
stepBits
,
Bit
Count
structDataSize
,
WireReferenceCount
structReferenceCount
,
int
nestingLimit
)
WireReferenceCount
structReferenceCount
,
int
nestingLimit
)
:
segment
(
segment
),
ptr
(
ptr
),
elementCount
(
elementCount
),
stepBits
(
stepBits
),
:
segment
(
segment
),
ptr
(
ptr
),
elementCount
(
elementCount
),
stepBits
(
stepBits
),
structDataSize
(
structDataSize
),
structReferenceCount
(
structReferenceCount
),
structDataSize
(
structDataSize
),
structReferenceCount
(
structReferenceCount
),
...
@@ -541,6 +568,10 @@ inline T StructBuilder::getDataField(ElementCount offset) const {
...
@@ -541,6 +568,10 @@ inline T StructBuilder::getDataField(ElementCount offset) const {
template
<>
template
<>
inline
bool
StructBuilder
::
getDataField
<
bool
>
(
ElementCount
offset
)
const
{
inline
bool
StructBuilder
::
getDataField
<
bool
>
(
ElementCount
offset
)
const
{
BitCount
boffset
=
offset
*
(
1
*
BITS
/
ELEMENTS
);
BitCount
boffset
=
offset
*
(
1
*
BITS
/
ELEMENTS
);
// This branch should always be optimized away when inlining.
if
(
boffset
==
0
*
BITS
)
boffset
=
bit0Offset
;
byte
*
b
=
reinterpret_cast
<
byte
*>
(
data
)
+
boffset
/
BITS_PER_BYTE
;
byte
*
b
=
reinterpret_cast
<
byte
*>
(
data
)
+
boffset
/
BITS_PER_BYTE
;
return
(
*
reinterpret_cast
<
uint8_t
*>
(
b
)
&
(
1
<<
(
boffset
%
BITS_PER_BYTE
/
BITS
)))
!=
0
;
return
(
*
reinterpret_cast
<
uint8_t
*>
(
b
)
&
(
1
<<
(
boffset
%
BITS_PER_BYTE
/
BITS
)))
!=
0
;
}
}
...
@@ -564,6 +595,10 @@ inline void StructBuilder::setDataField(
...
@@ -564,6 +595,10 @@ inline void StructBuilder::setDataField(
template
<>
template
<>
inline
void
StructBuilder
::
setDataField
<
bool
>
(
ElementCount
offset
,
bool
value
)
const
{
inline
void
StructBuilder
::
setDataField
<
bool
>
(
ElementCount
offset
,
bool
value
)
const
{
BitCount
boffset
=
offset
*
(
1
*
BITS
/
ELEMENTS
);
BitCount
boffset
=
offset
*
(
1
*
BITS
/
ELEMENTS
);
// This branch should always be optimized away when inlining.
if
(
boffset
==
0
*
BITS
)
boffset
=
bit0Offset
;
byte
*
b
=
reinterpret_cast
<
byte
*>
(
data
)
+
boffset
/
BITS_PER_BYTE
;
byte
*
b
=
reinterpret_cast
<
byte
*>
(
data
)
+
boffset
/
BITS_PER_BYTE
;
uint
bitnum
=
boffset
%
BITS_PER_BYTE
/
BITS
;
uint
bitnum
=
boffset
%
BITS_PER_BYTE
/
BITS
;
*
reinterpret_cast
<
uint8_t
*>
(
b
)
=
(
*
reinterpret_cast
<
uint8_t
*>
(
b
)
&
~
(
1
<<
bitnum
))
*
reinterpret_cast
<
uint8_t
*>
(
b
)
=
(
*
reinterpret_cast
<
uint8_t
*>
(
b
)
&
~
(
1
<<
bitnum
))
...
@@ -579,11 +614,37 @@ inline void StructBuilder::setDataField(
...
@@ -579,11 +614,37 @@ inline void StructBuilder::setDataField(
setDataField
<
typename
MaskType
<
T
>::
Type
>
(
offset
,
mask
<
T
>
(
value
,
m
));
setDataField
<
typename
MaskType
<
T
>::
Type
>
(
offset
,
mask
<
T
>
(
value
,
m
));
}
}
inline
StructBuilder
StructBuilder
::
initInlineStructField
(
BitCount
dataOffset
,
BitCount
inlineDataSize
,
WireReferenceCount
refIndex
,
WireReferenceCount
inlineRefCount
)
const
{
// This branch should be optimized away.
if
(
inlineDataSize
==
1
*
BITS
)
{
setDataField
<
bool
>
(
dataOffset
/
(
1
*
BITS
/
ELEMENTS
),
false
);
}
else
{
memset
(
reinterpret_cast
<
byte
*>
(
data
)
+
dataOffset
/
BITS_PER_BYTE
/
BYTES
,
0
,
inlineDataSize
/
BITS_PER_BYTE
/
BYTES
);
}
memset
(
reinterpret_cast
<
word
*>
(
references
)
+
refIndex
*
WORDS_PER_REFERENCE
,
0
,
inlineRefCount
*
WORDS_PER_REFERENCE
*
BYTES_PER_WORD
/
BYTES
);
return
getInlineStructField
(
dataOffset
,
inlineDataSize
,
refIndex
,
inlineRefCount
);
}
inline
StructBuilder
StructBuilder
::
getInlineStructField
(
BitCount
dataOffset
,
BitCount
inlineDataSize
,
WireReferenceCount
refIndex
,
WireReferenceCount
inlineRefCount
)
const
{
return
StructBuilder
(
segment
,
reinterpret_cast
<
byte
*>
(
data
)
+
dataOffset
/
BITS_PER_BYTE
,
// WireReference is incomplete here so we have to cast around... Bah.
reinterpret_cast
<
WireReference
*>
(
reinterpret_cast
<
word
*>
(
references
)
+
refIndex
*
WORDS_PER_REFERENCE
),
dataOffset
==
0
*
BITS
?
BitCount
(
bit0Offset
)
:
dataOffset
%
BITS_PER_BYTE
);
}
// -------------------------------------------------------------------
// -------------------------------------------------------------------
template
<
typename
T
>
template
<
typename
T
>
T
StructReader
::
getDataField
(
ElementCount
offset
)
const
{
T
StructReader
::
getDataField
(
ElementCount
offset
)
const
{
if
(
offset
*
bytesPerElement
<
T
>
()
<
dataSize
*
BYTES_PER_WORD
)
{
if
(
offset
*
capnproto
::
bitsPerElement
<
T
>
()
<
dataSize
)
{
return
reinterpret_cast
<
const
WireValue
<
T
>*>
(
data
)[
offset
/
ELEMENTS
].
get
();
return
reinterpret_cast
<
const
WireValue
<
T
>*>
(
data
)[
offset
/
ELEMENTS
].
get
();
}
else
{
}
else
{
return
static_cast
<
T
>
(
0
);
return
static_cast
<
T
>
(
0
);
...
@@ -597,7 +658,7 @@ inline bool StructReader::getDataField<bool>(ElementCount offset) const {
...
@@ -597,7 +658,7 @@ inline bool StructReader::getDataField<bool>(ElementCount offset) const {
// This branch should always be optimized away when inlining.
// This branch should always be optimized away when inlining.
if
(
boffset
==
0
*
BITS
)
boffset
=
bit0Offset
;
if
(
boffset
==
0
*
BITS
)
boffset
=
bit0Offset
;
if
(
boffset
<
dataSize
*
BITS_PER_WORD
)
{
if
(
boffset
<
dataSize
)
{
const
byte
*
b
=
reinterpret_cast
<
const
byte
*>
(
data
)
+
boffset
/
BITS_PER_BYTE
;
const
byte
*
b
=
reinterpret_cast
<
const
byte
*>
(
data
)
+
boffset
/
BITS_PER_BYTE
;
return
(
*
reinterpret_cast
<
const
uint8_t
*>
(
b
)
&
(
1
<<
(
boffset
%
BITS_PER_BYTE
/
BITS
)))
!=
0
;
return
(
*
reinterpret_cast
<
const
uint8_t
*>
(
b
)
&
(
1
<<
(
boffset
%
BITS_PER_BYTE
/
BITS
)))
!=
0
;
}
else
{
}
else
{
...
@@ -615,6 +676,19 @@ T StructReader::getDataField(ElementCount offset, typename MaskType<T>::Type mas
...
@@ -615,6 +676,19 @@ T StructReader::getDataField(ElementCount offset, typename MaskType<T>::Type mas
return
unmask
<
T
>
(
getDataField
<
typename
MaskType
<
T
>::
Type
>
(
offset
),
mask
);
return
unmask
<
T
>
(
getDataField
<
typename
MaskType
<
T
>::
Type
>
(
offset
),
mask
);
}
}
inline
StructReader
StructReader
::
getInlineStructField
(
BitCount
dataOffset
,
BitCount
inlineDataSize
,
WireReferenceCount
refIndex
,
WireReferenceCount
inlineRefCount
)
const
{
return
StructReader
(
segment
,
reinterpret_cast
<
const
byte
*>
(
data
)
+
dataOffset
/
BITS_PER_BYTE
,
// WireReference is incomplete here so we have to cast around... Bah.
reinterpret_cast
<
const
WireReference
*>
(
reinterpret_cast
<
const
word
*>
(
references
)
+
refIndex
*
WORDS_PER_REFERENCE
),
dataSize
,
inlineRefCount
,
dataOffset
==
0
*
BITS
?
BitCount
(
bit0Offset
)
:
dataOffset
%
BITS_PER_BYTE
,
nestingLimit
);
}
// -------------------------------------------------------------------
// -------------------------------------------------------------------
inline
ElementCount
ListBuilder
::
size
()
{
return
elementCount
;
}
inline
ElementCount
ListBuilder
::
size
()
{
return
elementCount
;
}
...
...
c++/src/capnproto/test-util.h
View file @
7f20d533
...
@@ -57,6 +57,9 @@ using ::capnproto::test::TestUnion;
...
@@ -57,6 +57,9 @@ using ::capnproto::test::TestUnion;
using
::
capnproto
::
test
::
TestUnionDefaults
;
using
::
capnproto
::
test
::
TestUnionDefaults
;
using
::
capnproto
::
test
::
TestNestedTypes
;
using
::
capnproto
::
test
::
TestNestedTypes
;
using
::
capnproto
::
test
::
TestUsing
;
using
::
capnproto
::
test
::
TestUsing
;
using
::
capnproto
::
test
::
TestInlineLayout
;
using
::
capnproto
::
test
::
TestInlineUnions
;
using
::
capnproto
::
test
::
TestInlineDefaults
;
void
initTestMessage
(
test
::
TestAllTypes
::
Builder
builder
);
void
initTestMessage
(
test
::
TestAllTypes
::
Builder
builder
);
void
initTestMessage
(
test
::
TestDefaults
::
Builder
builder
);
void
initTestMessage
(
test
::
TestDefaults
::
Builder
builder
);
...
...
c++/src/capnproto/test.capnp
View file @
7f20d533
...
@@ -213,7 +213,6 @@ struct TestUnion {
...
@@ -213,7 +213,6 @@ struct TestUnion {
bit5 @42: Bool;
bit5 @42: Bool;
bit6 @43: Bool;
bit6 @43: Bool;
bit7 @44: Bool;
bit7 @44: Bool;
byte0 @49: UInt8;
# Interleave two unions to be really annoying.
# Interleave two unions to be really annoying.
# Also declare in reverse order to make sure union discriminant values are sorted by field number
# Also declare in reverse order to make sure union discriminant values are sorted by field number
...
@@ -233,6 +232,8 @@ struct TestUnion {
...
@@ -233,6 +232,8 @@ struct TestUnion {
u3f0s8 @48: Int8;
u3f0s8 @48: Int8;
u3f0s1 @46: Bool;
u3f0s1 @46: Bool;
}
}
byte0 @49: UInt8;
}
}
struct TestUnionDefaults {
struct TestUnionDefaults {
...
@@ -274,3 +275,140 @@ struct TestUsing {
...
@@ -274,3 +275,140 @@ struct TestUsing {
outerNestedEnum @1 :OuterNestedEnum = bar;
outerNestedEnum @1 :OuterNestedEnum = bar;
innerNestedEnum @0 :NestedEnum = quux;
innerNestedEnum @0 :NestedEnum = quux;
}
}
struct TestInline0 fixed(0 bits) {}
struct TestInline1 fixed(1 bits) { f @0: Bool; }
struct TestInline8 fixed(8 bits) { f0 @0: Bool; f1 @1: Bool; f2 @2: Bool; }
struct TestInline16 fixed(16 bits) { f0 @0: UInt8; f1 @1: UInt8; }
struct TestInline32 fixed(32 bits) { f0 @0: UInt8; f1 @1: UInt16; }
struct TestInline64 fixed(64 bits) { f0 @0: UInt8; f1 @1: UInt32; }
struct TestInline128 fixed(2 words) { f0 @0: UInt64; f1 @1: UInt64; }
struct TestInline192 fixed(3 words) { f0 @0: UInt64; f1 @1: UInt64; f2 @2: UInt64; }
struct TestInline0p fixed(0 bits, 1 pointers) { f @0 :Inline(TestInline0); p0 @1 :Text; }
struct TestInline1p fixed(1 bits, 1 pointers) { f @0 :Inline(TestInline1); p0 @1 :Text; }
struct TestInline8p fixed(8 bits, 1 pointers) { f @0 :Inline(TestInline8); p0 @1 :Text; }
struct TestInline16p fixed(16 bits, 2 pointers) { f @0 :Inline(TestInline16); p0 @1 :Text; p1 @2 :Text; }
struct TestInline32p fixed(32 bits, 2 pointers) { f @0 :Inline(TestInline32); p0 @1 :Text; p1 @2 :Text; }
struct TestInline64p fixed(64 bits, 2 pointers) { f @0 :Inline(TestInline64); p0 @1 :Text; p1 @2 :Text; }
struct TestInline128p fixed(2 words, 3 pointers) { f @0 :Inline(TestInline128); p0 @1 :Text; p1 @2 :Text; p2 @3 :Text; }
struct TestInline192p fixed(3 words, 3 pointers) { f @0 :Inline(TestInline192); p0 @1 :Text; p1 @2 :Text; p2 @3 :Text; }
struct TestInlineLayout {
f0 @0 :Inline(TestInline0);
f1 @1 :Inline(TestInline1);
f8 @2 :Inline(TestInline8);
f16 @3 :Inline(TestInline16);
f32 @4 :Inline(TestInline32);
f64 @5 :Inline(TestInline64);
f128 @6 :Inline(TestInline128);
f192 @7 :Inline(TestInline192);
f0p @8 :Inline(TestInline0p);
f1p @9 :Inline(TestInline1p);
f8p @10 :Inline(TestInline8p);
f16p @11 :Inline(TestInline16p);
f32p @12 :Inline(TestInline32p);
f64p @13 :Inline(TestInline64p);
f128p @14 :Inline(TestInline128p);
f192p @15 :Inline(TestInline192p);
f1Offset @16 :Inline(TestInline1);
bit @17 :Bool;
}
struct TestInlineUnions {
union0 @0 union {
f0 @4 :Inline(TestInline0);
f1 @5 :Inline(TestInline1);
f8 @6 :Inline(TestInline8);
f16 @7 :Inline(TestInline16);
f32 @8 :Inline(TestInline32);
f64 @9 :Inline(TestInline64);
f128 @10 :Inline(TestInline128);
f192 @11 :Inline(TestInline192);
f0p @12 :Inline(TestInline0p);
f1p @13 :Inline(TestInline1p);
f8p @14 :Inline(TestInline8p);
f16p @15 :Inline(TestInline16p);
f32p @16 :Inline(TestInline32p);
f64p @17 :Inline(TestInline64p);
f128p @18 :Inline(TestInline128p);
f192p @19 :Inline(TestInline192p);
}
# Pack one bit in order to make pathological situation for union1.
bit0 @20: Bool;
union1 @1 union {
f0 @21 :Inline(TestInline0);
f1 @22 :Inline(TestInline1);
f8 @23 :Inline(TestInline8);
f16 @24 :Inline(TestInline16);
f32 @25 :Inline(TestInline32);
f64 @26 :Inline(TestInline64);
f128 @27 :Inline(TestInline128);
f192 @28 :Inline(TestInline192);
}
# Fill in the rest of that bitfield from earlier.
bit2 @29: Bool;
bit3 @30: Bool;
bit4 @31: Bool;
bit5 @32: Bool;
bit6 @33: Bool;
bit7 @34: Bool;
# Interleave two unions to be really annoying.
union2 @2 union {
f1p @35 :Inline(TestInline1p);
f8p @37 :Inline(TestInline8p);
f16p @40 :Inline(TestInline16p);
f32p @42 :Inline(TestInline32p);
f64p @44 :Inline(TestInline64p);
f128p @46 :Inline(TestInline128p);
f192p @48 :Inline(TestInline192p);
}
union3 @3 union {
f1p @36 :Inline(TestInline1p);
f8p @38 :Inline(TestInline8p);
f16p @41 :Inline(TestInline16p);
f32p @43 :Inline(TestInline32p);
f64p @45 :Inline(TestInline64p);
f128p @47 :Inline(TestInline128p);
f192p @49 :Inline(TestInline192p);
}
byte0 @39: UInt8;
}
struct TestInlineDefaults {
normal @0 :TestInlineLayout = (
f0 = (),
f1 = (f = true),
f8 = (f0 = true, f1 = false, f2 = true),
f16 = (f0 = 123, f1 = 45),
f32 = (f0 = 67, f1 = 8901),
f64 = (f0 = 234, f1 = 567890123),
f128 = (f0 = 1234567890123, f1 = 4567890123456),
f192 = (f0 = 7890123456789, f1 = 2345678901234, f2 = 5678901234567),
f0p = (p0 = "foo"),
f1p = (f = (f = false), p0 = "bar"),
f8p = (f = (f0 = true, f1 = true, f2 = false), p0 = "baz"),
f16p = (f = (f0 = 98, f1 = 76), p0 = "qux", p1 = "quux"),
f32p = (f = (f0 = 54, f1 = 32109), p0 = "corge", p1 = "grault"),
f64p = (f = (f0 = 87, f1 = 654321098), p0 = "garply", p1 = "waldo"),
f128p = (f = (f0 = 7654321098765, f1 = 4321098765432),
p0 = "fred", p1 = "plugh", p2 = "xyzzy"),
f192p = (f = (f0 = 1098765432109, f1 = 8765432109876, f2 = 5432109876543),
p0 = "thud", p1 = "foobar", p2 = "barbaz"));
unions @1 :TestInlineUnions = (
union0 = f32(f0 = 67, f1 = 8901),
union1 = f128(f0 = 1234567890123, f1 = 4567890123456),
union2 = f1p(p0 = "foo"),
union3 = f16p(f = (f0 = 98, f1 = 76), p0 = "qux", p1 = "quux"));
}
c++/src/capnproto/type-safety.h
View file @
7f20d533
...
@@ -651,6 +651,11 @@ inline constexpr decltype(BYTES / ELEMENTS) bytesPerElement() {
...
@@ -651,6 +651,11 @@ inline constexpr decltype(BYTES / ELEMENTS) bytesPerElement() {
return
sizeof
(
T
)
*
BYTES
/
ELEMENTS
;
return
sizeof
(
T
)
*
BYTES
/
ELEMENTS
;
}
}
template
<
typename
T
>
inline
constexpr
decltype
(
BITS
/
ELEMENTS
)
bitsPerElement
()
{
return
sizeof
(
T
)
*
8
*
BITS
/
ELEMENTS
;
}
#ifndef __CDT_PARSER__
#ifndef __CDT_PARSER__
template
<
typename
T
,
typename
U
>
template
<
typename
T
,
typename
U
>
...
...
compiler/capnproto-compiler.cabal
View file @
7f20d533
...
@@ -4,6 +4,13 @@ cabal-version: >=1.2
...
@@ -4,6 +4,13 @@ cabal-version: >=1.2
build-type: Simple
build-type: Simple
author: kenton
author: kenton
-- How to get stack traces:
-- 1. Compile normally and do not clean.
-- 2. Add "-prof -fprof-auto -osuf .prof.o" to ghc-options and compile again.
-- (TODO: Figure out how to add these through "cabal configure" instead of by editing
-- this file. --enable-executable-profiling alone doesn't appear to get the job done.)
-- 3. Run with +RTS -xc -RTS on the command line.
executable capnpc
executable capnpc
hs-source-dirs: src
hs-source-dirs: src
main-is: Main.hs
main-is: Main.hs
...
...
compiler/src/Compiler.hs
View file @
7f20d533
...
@@ -27,12 +27,12 @@ import Grammar
...
@@ -27,12 +27,12 @@ import Grammar
import
Semantics
import
Semantics
import
Token
(
Located
(
Located
),
locatedPos
,
locatedValue
)
import
Token
(
Located
(
Located
),
locatedPos
,
locatedValue
)
import
Parser
(
parseFile
)
import
Parser
(
parseFile
)
import
Control.Monad
(
unless
)
import
Control.Monad
(
when
,
unless
)
import
qualified
Data.Map
as
Map
import
qualified
Data.Map
as
Map
import
Data.Map
((
!
))
import
Data.Map
((
!
))
import
qualified
Data.Set
as
Set
import
qualified
Data.Set
as
Set
import
qualified
Data.List
as
List
import
qualified
Data.List
as
List
import
Data.Maybe
(
mapMaybe
,
fromMaybe
,
listToMaybe
,
catMaybes
)
import
Data.Maybe
(
mapMaybe
,
fromMaybe
,
listToMaybe
,
catMaybes
,
isJust
)
import
Text.Parsec.Pos
(
SourcePos
,
newPos
)
import
Text.Parsec.Pos
(
SourcePos
,
newPos
)
import
Text.Parsec.Error
(
ParseError
,
newErrorMessage
,
Message
(
Message
,
Expect
))
import
Text.Parsec.Error
(
ParseError
,
newErrorMessage
,
Message
(
Message
,
Expect
))
import
Text.Printf
(
printf
)
import
Text.Printf
(
printf
)
...
@@ -67,9 +67,16 @@ instance Monad Status where
...
@@ -67,9 +67,16 @@ instance Monad Status where
return
x
=
Active
x
[]
return
x
=
Active
x
[]
fail
=
makeError
(
newPos
"?"
0
0
)
fail
=
makeError
(
newPos
"?"
0
0
)
-- Recovers from Failed status by using a fallback result, but keeps the errors.
--
-- This function is carefully written such that the runtime can see that it returns Active without
-- actually evaluating the parameters. The parameters are only evaluated when the returned value
-- or errors are examined.
recover
::
a
->
Status
a
->
Status
a
recover
::
a
->
Status
a
->
Status
a
recover
_
(
Active
x
e
)
=
Active
x
e
recover
fallback
status
=
Active
value
errs
where
recover
x
(
Failed
e
)
=
Active
x
e
(
value
,
errs
)
=
case
status
of
Active
v
e
->
(
v
,
e
)
Failed
e
->
(
fallback
,
e
)
succeed
::
a
->
Status
a
succeed
::
a
->
Status
a
succeed
x
=
Active
x
[]
succeed
x
=
Active
x
[]
...
@@ -154,7 +161,7 @@ lookupDesc scope name = lookupDesc (descParent scope) name
...
@@ -154,7 +161,7 @@ lookupDesc scope name = lookupDesc (descParent scope) name
builtinTypeMap
::
Map
.
Map
String
Desc
builtinTypeMap
::
Map
.
Map
String
Desc
builtinTypeMap
=
Map
.
fromList
builtinTypeMap
=
Map
.
fromList
([(
builtinTypeName
t
,
DescBuiltinType
t
)
|
t
<-
builtinTypes
]
++
([(
builtinTypeName
t
,
DescBuiltinType
t
)
|
t
<-
builtinTypes
]
++
[(
"List"
,
DescBuiltinList
),
(
"id"
,
DescBuiltinId
)])
[(
"List"
,
DescBuiltinList
),
(
"
Inline"
,
DescBuiltinInline
),
(
"
id"
,
DescBuiltinId
)])
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
...
@@ -234,6 +241,8 @@ compileValue pos (StructType desc) (RecordFieldValue fields) = do
...
@@ -234,6 +241,8 @@ compileValue pos (StructType desc) (RecordFieldValue fields) = do
return
(
StructValueDesc
assignments
)
return
(
StructValueDesc
assignments
)
compileValue
pos
(
InlineStructType
desc
)
v
=
compileValue
pos
(
StructType
desc
)
v
compileValue
_
(
ListType
t
)
(
ListFieldValue
l
)
=
compileValue
_
(
ListType
t
)
(
ListFieldValue
l
)
=
fmap
ListDesc
(
doAll
[
compileValue
vpos
t
v
|
Located
vpos
v
<-
l
])
fmap
ListDesc
(
doAll
[
compileValue
vpos
t
v
|
Located
vpos
v
<-
l
])
...
@@ -254,6 +263,7 @@ compileValue pos (BuiltinType BuiltinData) _ = makeExpectError pos "string"
...
@@ -254,6 +263,7 @@ compileValue pos (BuiltinType BuiltinData) _ = makeExpectError pos "string"
compileValue
pos
(
EnumType
_
)
_
=
makeExpectError
pos
"enumerant name"
compileValue
pos
(
EnumType
_
)
_
=
makeExpectError
pos
"enumerant name"
compileValue
pos
(
StructType
_
)
_
=
makeExpectError
pos
"parenthesized list of field assignments"
compileValue
pos
(
StructType
_
)
_
=
makeExpectError
pos
"parenthesized list of field assignments"
compileValue
pos
(
InlineStructType
_
)
_
=
makeExpectError
pos
"parenthesized list of field assignments"
compileValue
pos
(
InterfaceType
_
)
_
=
makeError
pos
"Interfaces can't have default values."
compileValue
pos
(
InterfaceType
_
)
_
=
makeError
pos
"Interfaces can't have default values."
compileValue
pos
(
ListType
_
)
_
=
makeExpectError
pos
"list"
compileValue
pos
(
ListType
_
)
_
=
makeExpectError
pos
"list"
...
@@ -264,6 +274,8 @@ descAsType _ (DescBuiltinType desc) = succeed (BuiltinType desc)
...
@@ -264,6 +274,8 @@ descAsType _ (DescBuiltinType desc) = succeed (BuiltinType desc)
descAsType
name
(
DescUsing
desc
)
=
descAsType
name
(
usingTarget
desc
)
descAsType
name
(
DescUsing
desc
)
=
descAsType
name
(
usingTarget
desc
)
descAsType
name
DescBuiltinList
=
makeError
(
declNamePos
name
)
message
where
descAsType
name
DescBuiltinList
=
makeError
(
declNamePos
name
)
message
where
message
=
printf
"'List' requires exactly one type parameter."
(
declNameString
name
)
message
=
printf
"'List' requires exactly one type parameter."
(
declNameString
name
)
descAsType
name
DescBuiltinInline
=
makeError
(
declNamePos
name
)
message
where
message
=
printf
"'Inline' requires exactly one type parameter."
(
declNameString
name
)
descAsType
name
_
=
makeError
(
declNamePos
name
)
message
where
descAsType
name
_
=
makeError
(
declNamePos
name
)
message
where
message
=
printf
"'%s' is not a type."
(
declNameString
name
)
message
=
printf
"'%s' is not a type."
(
declNameString
name
)
...
@@ -278,6 +290,18 @@ compileType scope (TypeExpression n (param:moreParams)) = do
...
@@ -278,6 +290,18 @@ compileType scope (TypeExpression n (param:moreParams)) = do
if
null
moreParams
if
null
moreParams
then
fmap
ListType
(
compileType
scope
param
)
then
fmap
ListType
(
compileType
scope
param
)
else
makeError
(
declNamePos
n
)
"'List' requires exactly one type parameter."
else
makeError
(
declNamePos
n
)
"'List' requires exactly one type parameter."
DescBuiltinInline
->
if
null
moreParams
then
do
inner
<-
compileType
scope
param
case
inner
of
StructType
s
->
if
structIsFixedWidth
s
then
return
(
InlineStructType
s
)
else
makeError
(
declNamePos
n
)
$
printf
"'%s' cannot be inlined because it is not fixed-width."
(
structName
s
)
_
->
makeError
(
declNamePos
n
)
"'Inline' parameter must be a struct type."
else
makeError
(
declNamePos
n
)
"'Inline' requires exactly one type parameter."
_
->
makeError
(
declNamePos
n
)
"Only the type 'List' can have type parameters."
_
->
makeError
(
declNamePos
n
)
"Only the type 'List' can have type parameters."
compileAnnotation
::
Desc
->
AnnotationTarget
->
Annotation
compileAnnotation
::
Desc
->
AnnotationTarget
->
Annotation
...
@@ -378,10 +402,6 @@ requireNoDuplicateNames decls = Active () (loop (List.sort locatedNames)) where
...
@@ -378,10 +402,6 @@ requireNoDuplicateNames decls = Active () (loop (List.sort locatedNames)) where
dupError
val
=
newErrorMessage
(
Message
message
)
where
dupError
val
=
newErrorMessage
(
Message
message
)
where
message
=
printf
"Duplicate declaration
\"
%s
\"
."
val
message
=
printf
"Duplicate declaration
\"
%s
\"
."
val
fieldInUnion
name
f
=
case
fieldUnion
f
of
Nothing
->
False
Just
(
x
,
_
)
->
unionName
x
==
name
requireNoMoreThanOneFieldNumberLessThan
name
pos
num
fields
=
Active
()
errors
where
requireNoMoreThanOneFieldNumberLessThan
name
pos
num
fields
=
Active
()
errors
where
retroFields
=
[
fieldName
f
|
f
<-
fields
,
fieldNumber
f
<
num
]
retroFields
=
[
fieldName
f
|
f
<-
fields
,
fieldNumber
f
<
num
]
message
=
printf
"No more than one field in a union may have a number less than the
\
message
=
printf
"No more than one field in a union may have a number less than the
\
...
@@ -399,102 +419,217 @@ extractFieldNumbers decls = concat
...
@@ -399,102 +419,217 @@ extractFieldNumbers decls = concat
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
initialPackingState
=
PackingState
0
0
0
0
0
0
data
PackingState
=
PackingState
{
packingHoles
::
Map
.
Map
DataSize
Integer
,
packingDataSize
::
Integer
,
packingReferenceCount
::
Integer
}
packValue
::
FieldSize
->
PackingState
->
(
Integer
,
PackingState
)
initialPackingState
=
PackingState
Map
.
empty
0
0
packValue
Size64
s
@
(
PackingState
{
packingDataSize
=
ds
})
=
(
ds
,
s
{
packingDataSize
=
ds
+
1
})
packValue
::
FieldSize
->
PackingState
->
(
FieldOffset
,
PackingState
)
packValue
SizeVoid
s
=
(
VoidOffset
,
s
)
packValue
SizeReference
s
@
(
PackingState
{
packingReferenceCount
=
rc
})
=
packValue
SizeReference
s
@
(
PackingState
{
packingReferenceCount
=
rc
})
=
(
rc
,
s
{
packingReferenceCount
=
rc
+
1
})
(
PointerOffset
rc
,
s
{
packingReferenceCount
=
rc
+
1
})
packValue
(
SizeInlineComposite
_
_
)
_
=
error
"Inline fields not yet supported."
packValue
(
SizeInlineComposite
(
DataSectionWords
inlineDs
)
inlineRc
)
packValue
Size32
s
@
(
PackingState
{
packingHole32
=
0
})
=
s
@
(
PackingState
{
packingDataSize
=
ds
,
packingReferenceCount
=
rc
})
=
case
packValue
Size64
s
of
(
InlineCompositeOffset
ds
rc
(
DataSectionWords
inlineDs
)
inlineRc
,
(
o64
,
s2
)
->
(
o64
*
2
,
s2
{
packingHole32
=
o64
*
2
+
1
})
s
{
packingDataSize
=
ds
+
inlineDs
packValue
Size32
s
@
(
PackingState
{
packingHole32
=
h32
})
=
,
packingReferenceCount
=
rc
+
inlineRc
})
(
h32
,
s
{
packingHole32
=
0
})
packValue
(
SizeInlineComposite
inlineDs
inlineRc
)
packValue
Size16
s
@
(
PackingState
{
packingHole16
=
0
})
=
s
@
(
PackingState
{
packingReferenceCount
=
rc
})
=
let
case
packValue
Size32
s
of
size
=
(
dataSectionAlignment
inlineDs
)
(
o32
,
s2
)
->
(
o32
*
2
,
s2
{
packingHole16
=
o32
*
2
+
1
})
(
offset
,
s2
)
=
packData
size
s
packValue
Size16
s
@
(
PackingState
{
packingHole16
=
h16
})
=
in
(
InlineCompositeOffset
offset
rc
inlineDs
inlineRc
,
(
h16
,
s
{
packingHole16
=
0
})
s2
{
packingReferenceCount
=
rc
+
inlineRc
})
packValue
Size8
s
@
(
PackingState
{
packingHole8
=
0
})
=
packValue
(
SizeData
size
)
s
=
let
(
o
,
s2
)
=
packData
size
s
in
(
DataOffset
size
o
,
s2
)
case
packValue
Size16
s
of
(
o16
,
s2
)
->
(
o16
*
2
,
s2
{
packingHole8
=
o16
*
2
+
1
})
packData
::
DataSize
->
PackingState
->
(
Integer
,
PackingState
)
packValue
Size8
s
@
(
PackingState
{
packingHole8
=
h8
})
=
packData
Size64
s
@
(
PackingState
{
packingDataSize
=
ds
})
=
(
h8
,
s
{
packingHole8
=
0
})
(
ds
,
s
{
packingDataSize
=
ds
+
1
})
packValue
Size1
s
@
(
PackingState
{
packingHole1
=
0
})
=
case
packValue
Size8
s
of
packData
size
s
=
let
(
o8
,
s2
)
->
(
o8
*
8
,
s2
{
packingHole1
=
o8
*
8
+
1
})
-- updateLookupWithKey doesn't quite work here because it returns the new value if updated, or
packValue
Size1
s
@
(
PackingState
{
packingHole1
=
h1
})
=
-- the old value if not. We really always want the old value and have no way to distinguish.
(
h1
,
s
{
packingHole1
=
if
mod
(
h1
+
1
)
8
==
0
then
0
else
h1
+
1
})
-- There appears to be no function that does this, AFAICT.
packValue
Size0
s
=
(
0
,
s
)
hole
=
Map
.
lookup
size
$
packingHoles
s
newHoles
=
Map
.
update
splitHole
size
$
packingHoles
s
initialUnionPackingState
=
UnionPackingState
Nothing
Nothing
splitHole
off
=
case
size
of
Size1
->
if
mod
off
8
==
7
then
Nothing
else
Just
(
off
+
1
)
_
->
Nothing
in
case
hole
of
-- If there was a hole of the correct size, use it.
Just
off
->
(
off
,
s
{
packingHoles
=
newHoles
})
-- Otherwise, try to pack a value of the next size up, and then split it.
Nothing
->
let
nextSize
=
succ
size
(
nextOff
,
s2
)
=
packData
nextSize
s
off
=
demoteOffset
nextSize
nextOff
newHoles2
=
Map
.
insert
size
(
off
+
1
)
$
packingHoles
s2
in
(
off
,
s2
{
packingHoles
=
newHoles2
})
-- Convert an offset of one data size to an offset of the next smaller size.
demoteOffset
::
DataSize
->
Integer
->
Integer
demoteOffset
Size1
_
=
error
"can't split bit"
demoteOffset
Size8
i
=
i
*
8
demoteOffset
_
i
=
i
*
2
data
UnionSlot
sizeType
=
UnionSlot
{
unionSlotSize
::
sizeType
,
unionSlotOffset
::
Integer
}
data
UnionPackingState
=
UnionPackingState
{
unionDataSlot
::
UnionSlot
DataSectionSize
,
unionPointerSlot
::
UnionSlot
Integer
}
initialUnionPackingState
=
UnionPackingState
(
UnionSlot
(
DataSectionWords
0
)
0
)
(
UnionSlot
0
0
)
packUnionizedValue
::
FieldSize
-- Size of field to pack.
packUnionizedValue
::
FieldSize
-- Size of field to pack.
->
UnionPackingState
-- Current layout of the union
->
UnionPackingState
-- Current layout of the union
->
PackingState
-- Current layout of the struct.
->
PackingState
-- Current layout of the struct.
->
(
Integer
,
UnionPackingState
,
PackingState
)
->
(
FieldOffset
,
UnionPackingState
,
PackingState
)
packUnionizedValue
(
SizeInlineComposite
_
_
)
_
_
=
error
"Can't put inline composite into union."
packUnionizedValue
Size0
u
s
=
(
0
,
u
,
s
)
packUnionizedValue
SizeVoid
u
s
=
(
VoidOffset
,
u
,
s
)
-- Pack reference when we already have a reference slot allocated.
-- Pack data when there is no existing slot.
packUnionizedValue
SizeReference
u
@
(
UnionPackingState
_
(
Just
offset
))
s
=
(
offset
,
u
,
s
)
packUnionizedValue
(
SizeData
size
)
(
UnionPackingState
(
UnionSlot
(
DataSectionWords
0
)
_
)
p
)
s
=
let
(
offset
,
s2
)
=
packData
size
s
in
(
DataOffset
size
offset
,
UnionPackingState
(
UnionSlot
(
dataSizeToSectionSize
size
)
offset
)
p
,
s2
)
-- Pack data when there is a word-sized slot. All data fits in a word.
packUnionizedValue
(
SizeData
size
)
ups
@
(
UnionPackingState
(
UnionSlot
(
DataSectionWords
_
)
offset
)
_
)
s
=
(
DataOffset
size
(
offset
*
div
64
(
dataSizeInBits
size
)),
ups
,
s
)
-- Pack data when there is a non-word-sized slot.
packUnionizedValue
(
SizeData
size
)
(
UnionPackingState
(
UnionSlot
slotSize
slotOffset
)
p
)
s
=
case
tryExpandSubWordDataSlot
(
dataSectionAlignment
slotSize
,
slotOffset
)
s
size
of
Just
(
offset
,
(
newSlotSize
,
newSlotOffset
),
s2
)
->
(
DataOffset
size
offset
,
UnionPackingState
(
UnionSlot
(
dataSizeToSectionSize
newSlotSize
)
newSlotOffset
)
p
,
s2
)
-- If the slot wasn't big enough, pack as if there were no slot.
Nothing
->
packUnionizedValue
(
SizeData
size
)
(
UnionPackingState
(
UnionSlot
(
DataSectionWords
0
)
0
)
p
)
s
-- Pack reference when we don't have a reference slot.
-- Pack reference when we don't have a reference slot.
packUnionizedValue
SizeReference
(
UnionPackingState
d
Nothing
)
s
=
(
offset
,
u2
,
s2
)
where
packUnionizedValue
SizeReference
u
@
(
UnionPackingState
_
(
UnionSlot
0
_
))
s
=
let
(
offset
,
s2
)
=
packValue
SizeReference
s
(
PointerOffset
offset
,
s2
)
=
packValue
SizeReference
s
u2
=
UnionPackingState
d
(
Just
offset
)
u2
=
u
{
unionPointerSlot
=
UnionSlot
1
offset
}
in
(
PointerOffset
offset
,
u2
,
s2
)
-- Pack data.
packUnionizedValue
size
(
UnionPackingState
d
r
)
s
=
-- Pack reference when we already have a reference slot allocated.
case
packUnionizedData
(
fromMaybe
(
0
,
Size0
)
d
)
s
size
of
packUnionizedValue
SizeReference
u
@
(
UnionPackingState
_
(
UnionSlot
_
offset
))
s
=
Just
(
offset
,
slotOffset
,
slotSize
,
s2
)
->
(
PointerOffset
offset
,
u
,
s
)
(
offset
,
UnionPackingState
(
Just
(
slotOffset
,
slotSize
))
r
,
s2
)
Nothing
->
let
-- Pack inline composite.
(
offset
,
s2
)
=
packValue
size
s
packUnionizedValue
(
SizeInlineComposite
dataSize
pointerCount
)
in
(
offset
,
UnionPackingState
(
Just
(
offset
,
size
))
r
,
s2
)
u
@
(
UnionPackingState
{
unionDataSlot
=
UnionSlot
dataSlotSize
dataSlotOffset
,
unionPointerSlot
=
UnionSlot
pointerSlotSize
pointerSlotOffset
})
s
=
let
-- Pack the data section.
(
dataOffset
,
u2
,
s2
)
=
case
dataSize
of
DataSectionWords
0
->
(
0
,
u
,
s
)
DataSectionWords
requestedWordSize
->
let
maybeExpanded
=
case
dataSlotSize
of
-- Try to expand existing n-word slot to fit.
DataSectionWords
existingWordSize
->
tryExpandUnionizedDataWords
u
s
dataSlotOffset
existingWordSize
requestedWordSize
-- Try to expand the existing sub-word slot into a word, then from there to a slot
-- of the size we need.
_
->
do
(
expandedSlotOffset
,
_
,
expandedPackingState
)
<-
tryExpandSubWordDataSlot
(
dataSectionAlignment
dataSlotSize
,
dataSlotOffset
)
s
Size64
let
newU
=
u
{
unionDataSlot
=
UnionSlot
(
DataSectionWords
1
)
expandedSlotOffset
}
tryExpandUnionizedDataWords
newU
expandedPackingState
expandedSlotOffset
1
requestedWordSize
-- If expanding fails, fall back to appending the new words to the end of the struct.
atEnd
=
(
packingDataSize
s
,
u
{
unionDataSlot
=
UnionSlot
(
DataSectionWords
requestedWordSize
)
(
packingDataSize
s
)
},
s
{
packingDataSize
=
packingDataSize
s
+
requestedWordSize
})
in
fromMaybe
atEnd
maybeExpanded
_
->
let
(
DataOffset
_
result
,
newU
,
newS
)
=
packUnionizedValue
(
SizeData
(
dataSectionAlignment
dataSize
))
u
s
in
(
result
,
newU
,
newS
)
-- Pack the pointer section.
(
pointerOffset
,
u3
,
s3
)
|
pointerCount
<=
pointerSlotSize
=
(
pointerSlotOffset
,
u2
,
s2
)
|
pointerSlotOffset
+
pointerSlotSize
==
packingReferenceCount
s2
=
(
pointerSlotOffset
,
u2
{
unionPointerSlot
=
UnionSlot
pointerCount
pointerSlotOffset
},
s2
{
packingReferenceCount
=
pointerSlotOffset
+
pointerCount
})
|
otherwise
=
(
packingReferenceCount
s2
,
u2
{
unionPointerSlot
=
UnionSlot
pointerCount
(
packingReferenceCount
s2
)
},
s2
{
packingReferenceCount
=
packingReferenceCount
s2
+
pointerCount
})
combinedOffset
=
InlineCompositeOffset
{
inlineCompositeDataOffset
=
dataOffset
,
inlineCompositePointerOffset
=
pointerOffset
,
inlineCompositeDataSize
=
dataSize
,
inlineCompositePointerSize
=
pointerCount
}
packUnionizedData
::
(
Integer
,
FieldSize
)
-- existing slot to expand
in
(
combinedOffset
,
u3
,
s3
)
tryExpandUnionizedDataWords
unionState
packingState
existingOffset
existingSize
requestedSize
-- Is the existing multi-word slot big enough?
|
requestedSize
<=
existingSize
=
-- Yes, use it.
Just
(
existingOffset
,
unionState
,
packingState
)
-- Is the slot at the end of the struct?
|
existingOffset
+
existingSize
==
packingDataSize
packingState
=
-- Yes, expand it.
Just
(
existingOffset
,
unionState
{
unionDataSlot
=
UnionSlot
(
DataSectionWords
requestedSize
)
existingOffset
},
packingState
{
packingDataSize
=
packingDataSize
packingState
+
requestedSize
-
existingSize
})
|
otherwise
=
Nothing
-- Try to expand an existing data slot to be big enough for a data field.
tryExpandSubWordDataSlot
::
(
DataSize
,
Integer
)
-- existing slot to expand
->
PackingState
-- existing packing state
->
PackingState
-- existing packing state
->
FieldSize
-- desired field size
->
DataSize
-- desired field size
->
Maybe
(
Integer
,
-- Offset of the new field (in multiples of field size).
->
Maybe
(
Integer
,
-- Offset of the new field.
Integer
,
-- New offset of the slot (in multiples of slot size).
(
DataSize
,
Integer
),
-- New offset of the slot.
FieldSize
,
-- New size of the slot.
PackingState
)
-- New struct packing state.
PackingState
)
-- New struct packing state.
-- Don't try to allocate space for voids.
packUnionizedData
(
slotOffset
,
slotSize
)
state
Size0
=
Just
(
0
,
slotOffset
,
slotSize
,
state
)
-- If slot is bigger than desired size, no expansion is needed.
-- If slot is bigger than desired size, no expansion is needed.
packUnionizedData
(
slotOffset
,
slotSize
)
state
desiredSize
tryExpandSubWordDataSlot
(
slotSize
,
slotOffset
)
state
desiredSize
|
sizeInBits
slotSize
>=
sizeInBits
desiredSize
=
|
dataSizeInBits
slotSize
>=
dataSizeInBits
desiredSize
=
Just
(
div
(
sizeInBits
slotSize
)
(
sizeInBits
desiredSize
)
*
slotOffset
,
Just
(
div
(
dataSizeInBits
slotSize
)
(
dataSizeInBits
desiredSize
)
*
slotOffset
,
slotOffset
,
slotSize
,
state
)
(
slotSize
,
slotOffset
),
state
)
-- If slot is a bit, and it is the first bit in its byte, and the bit hole immediately follows
-- Try expanding the slot by combining it with subsequent padding.
-- expand it to a byte.
tryExpandSubWordDataSlot
(
slotSize
,
slotOffset
)
state
desiredSize
=
let
packUnionizedData
(
slotOffset
,
Size1
)
p
@
(
PackingState
{
packingHole1
=
hole
})
desiredSize
nextSize
=
succ
slotSize
|
mod
slotOffset
8
==
0
&&
hole
==
slotOffset
+
1
=
ratio
=
div
(
dataSizeInBits
nextSize
)
(
dataSizeInBits
slotSize
)
packUnionizedData
(
div
slotOffset
8
,
Size8
)
(
p
{
packingHole1
=
0
})
desiredSize
isAligned
=
mod
slotOffset
ratio
==
0
nextOffset
=
div
slotOffset
ratio
-- If slot is size N, and the next N bits are padding, expand.
packUnionizedData
(
slotOffset
,
Size8
)
p
@
(
PackingState
{
packingHole8
=
hole
})
desiredSize
deleteHole
_
_
=
Nothing
|
hole
==
slotOffset
+
1
=
(
maybeHole
,
newHoles
)
=
Map
.
updateLookupWithKey
deleteHole
slotSize
$
packingHoles
state
packUnionizedData
(
div
slotOffset
2
,
Size16
)
(
p
{
packingHole8
=
0
})
desiredSize
newState
=
state
{
packingHoles
=
newHoles
}
packUnionizedData
(
slotOffset
,
Size16
)
p
@
(
PackingState
{
packingHole16
=
hole
})
desiredSize
|
hole
==
slotOffset
+
1
=
in
if
not
isAligned
packUnionizedData
(
div
slotOffset
2
,
Size32
)
(
p
{
packingHole16
=
0
})
desiredSize
then
Nothing
-- Existing slot is not aligned properly.
packUnionizedData
(
slotOffset
,
Size32
)
p
@
(
PackingState
{
packingHole32
=
hole
})
desiredSize
else
case
maybeHole
of
|
hole
==
slotOffset
+
1
=
Just
holeOffset
|
holeOffset
==
slotOffset
+
1
->
packUnionizedData
(
div
slotOffset
2
,
Size64
)
(
p
{
packingHole32
=
0
})
desiredSize
tryExpandSubWordDataSlot
(
nextSize
,
nextOffset
)
newState
desiredSize
_
->
Nothing
-- Otherwise, we fail.
packUnionizedData
_
_
_
=
Nothing
-- Determine the offset for the given field, and update the packing states to include the field.
-- Determine the offset for the given field, and update the packing states to include the field.
packField
::
FieldDesc
->
PackingState
->
Map
.
Map
Integer
UnionPackingState
packField
::
FieldDesc
->
PackingState
->
Map
.
Map
Integer
UnionPackingState
->
(
Integer
,
PackingState
,
Map
.
Map
Integer
UnionPackingState
)
->
(
FieldOffset
,
PackingState
,
Map
.
Map
Integer
UnionPackingState
)
packField
fieldDesc
state
unionState
=
packField
fieldDesc
state
unionState
=
case
fieldUnion
fieldDesc
of
case
fieldUnion
fieldDesc
of
Nothing
->
let
Nothing
->
let
...
@@ -511,13 +646,19 @@ packField fieldDesc state unionState =
...
@@ -511,13 +646,19 @@ packField fieldDesc state unionState =
-- Determine the offset for the given union, and update the packing states to include the union.
-- Determine the offset for the given union, and update the packing states to include the union.
-- Specifically, this packs the union tag, *not* the fields of the union.
-- Specifically, this packs the union tag, *not* the fields of the union.
packUnion
::
UnionDesc
->
PackingState
->
Map
.
Map
Integer
UnionPackingState
packUnion
::
UnionDesc
->
PackingState
->
Map
.
Map
Integer
UnionPackingState
->
(
Integer
,
PackingState
,
Map
.
Map
Integer
UnionPackingState
)
->
(
FieldOffset
,
PackingState
,
Map
.
Map
Integer
UnionPackingState
)
packUnion
_
state
unionState
=
(
offset
,
newState
,
unionState
)
where
packUnion
_
state
unionState
=
(
DataOffset
Size16
offset
,
newState
,
unionState
)
where
(
offset
,
newState
)
=
packValue
Size16
state
(
offset
,
newState
)
=
packData
Size16
state
packFields
::
[
FieldDesc
]
->
[
UnionDesc
]
stripHolesFromFirstWord
Size1
_
=
Size1
-- Nothing left to strip.
->
(
PackingState
,
Map
.
Map
Integer
UnionPackingState
,
Map
.
Map
Integer
(
Integer
,
PackingState
))
stripHolesFromFirstWord
size
holes
=
let
packFields
fields
unions
=
(
finalState
,
finalUnionState
,
Map
.
fromList
packedItems
)
where
nextSize
=
pred
size
in
case
Map
.
lookup
nextSize
holes
of
Just
1
->
stripHolesFromFirstWord
nextSize
holes
_
->
size
packFields
::
[
FieldDesc
]
->
[
UnionDesc
]
->
(
DataSectionSize
,
Integer
,
Map
.
Map
Integer
FieldOffset
)
packFields
fields
unions
=
let
items
=
concat
(
items
=
concat
(
[(
fieldNumber
d
,
packField
d
)
|
d
<-
fields
]
:
[(
fieldNumber
d
,
packField
d
)
|
d
<-
fields
]
:
[(
unionNumber
d
,
packUnion
d
)
:
[(
fieldNumber
d2
,
packField
d2
)
|
d2
<-
unionFields
d
]
[(
unionNumber
d
,
packUnion
d
)
:
[(
fieldNumber
d2
,
packField
d2
)
|
d2
<-
unionFields
d
]
...
@@ -526,13 +667,45 @@ packFields fields unions = (finalState, finalUnionState, Map.fromList packedItem
...
@@ -526,13 +667,45 @@ packFields fields unions = (finalState, finalUnionState, Map.fromList packedItem
itemsByNumber
=
List
.
sortBy
compareNumbers
items
itemsByNumber
=
List
.
sortBy
compareNumbers
items
compareNumbers
(
a
,
_
)
(
b
,
_
)
=
compare
a
b
compareNumbers
(
a
,
_
)
(
b
,
_
)
=
compare
a
b
(
finalState
,
finalUnionState
,
packedItems
)
=
(
finalState
,
_
,
packedItems
)
=
foldl
packItem
(
initialPackingState
,
Map
.
empty
,
[]
)
itemsByNumber
foldl
packItem
(
initialPackingState
,
Map
.
empty
,
[]
)
itemsByNumber
packItem
(
state
,
unionState
,
packed
)
(
n
,
item
)
=
packItem
(
state
,
unionState
,
packed
)
(
n
,
item
)
=
(
newState
,
newUnionState
,
(
n
,
(
offset
,
newState
)
)
:
packed
)
where
(
newState
,
newUnionState
,
(
n
,
offset
)
:
packed
)
where
(
offset
,
newState
,
newUnionState
)
=
item
state
unionState
(
offset
,
newState
,
newUnionState
)
=
item
state
unionState
dataSectionSize
=
if
packingDataSize
finalState
==
1
then
dataSizeToSectionSize
$
stripHolesFromFirstWord
Size64
$
packingHoles
finalState
else
DataSectionWords
$
packingDataSize
finalState
in
(
dataSectionSize
,
packingReferenceCount
finalState
,
Map
.
fromList
packedItems
)
enforceFixed
Nothing
sizes
=
return
sizes
enforceFixed
(
Just
(
Located
pos
(
requestedDataSize
,
requestedPointerCount
)))
(
actualDataSize
,
actualPointerCount
)
=
do
validatedRequestedDataSize
<-
case
requestedDataSize
of
1
->
return
DataSection1
8
->
return
DataSection8
16
->
return
DataSection16
32
->
return
DataSection32
s
|
mod
s
64
==
0
->
return
$
DataSectionWords
$
div
s
64
_
->
makeError
pos
$
printf
"Struct data section size must be a whole number of words
\
\
or 0, 1, 8, 16, or 32 bits."
recover
()
$
when
(
dataSectionBits
actualDataSize
>
dataSectionBits
validatedRequestedDataSize
)
$
makeError
pos
$
printf
"Struct data section size is %s which exceeds specified maximum of
\
\
%s. WARNING: Increasing the maximum will break backwards-compatibility."
(
dataSectionSizeString
actualDataSize
)
(
dataSectionSizeString
validatedRequestedDataSize
)
recover
()
$
when
(
actualPointerCount
>
requestedPointerCount
)
$
makeError
pos
$
printf
"Struct pointer section size is %d pointers which exceeds specified
\
\
maximum of %d pointers. WARNING: Increasing the maximum will break
\
\
backwards-compatibility."
actualPointerCount
requestedPointerCount
return
(
validatedRequestedDataSize
,
requestedPointerCount
)
------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------
data
CompiledStatementStatus
=
CompiledStatementStatus
String
(
Status
Desc
)
data
CompiledStatementStatus
=
CompiledStatementStatus
String
(
Status
Desc
)
...
@@ -604,7 +777,7 @@ compileDecl scope@(DescEnum parent)
...
@@ -604,7 +777,7 @@ compileDecl scope@(DescEnum parent)
compileDecl
_
(
EnumerantDecl
(
Located
pos
name
)
_
_
)
=
compileDecl
_
(
EnumerantDecl
(
Located
pos
name
)
_
_
)
=
CompiledStatementStatus
name
(
makeError
pos
"Enumerants can only appear inside enums."
)
CompiledStatementStatus
name
(
makeError
pos
"Enumerants can only appear inside enums."
)
compileDecl
scope
(
StructDecl
(
Located
_
name
)
annotations
decls
)
=
compileDecl
scope
(
StructDecl
(
Located
_
name
)
isFixed
annotations
decls
)
=
CompiledStatementStatus
name
(
feedback
(
\
desc
->
do
CompiledStatementStatus
name
(
feedback
(
\
desc
->
do
(
members
,
memberMap
)
<-
compileChildDecls
desc
decls
(
members
,
memberMap
)
<-
compileChildDecls
desc
decls
requireNoDuplicateNames
decls
requireNoDuplicateNames
decls
...
@@ -612,15 +785,19 @@ compileDecl scope (StructDecl (Located _ name) annotations decls) =
...
@@ -612,15 +785,19 @@ compileDecl scope (StructDecl (Located _ name) annotations decls) =
requireSequentialNumbering
"Fields"
fieldNums
requireSequentialNumbering
"Fields"
fieldNums
requireOrdinalsInRange
fieldNums
requireOrdinalsInRange
fieldNums
(
theId
,
compiledAnnotations
)
<-
compileAnnotations
scope
StructAnnotation
annotations
(
theId
,
compiledAnnotations
)
<-
compileAnnotations
scope
StructAnnotation
annotations
return
(
let
let
(
dataSize
,
pointerCount
,
fieldPackingMap
)
=
packFields
fields
unions
fields
=
[
d
|
DescField
d
<-
members
]
fields
=
[
d
|
DescField
d
<-
members
]
unions
=
[
d
|
DescUnion
d
<-
members
]
unions
=
[
d
|
DescUnion
d
<-
members
]
(
packing
,
_
,
fieldPackingMap
)
=
packFields
fields
unions
(
finalDataSize
,
finalPointerCount
)
<-
recover
(
dataSize
,
pointerCount
)
$
enforceFixed
isFixed
(
dataSize
,
pointerCount
)
return
(
let
in
DescStruct
StructDesc
in
DescStruct
StructDesc
{
structName
=
name
{
structName
=
name
,
structId
=
theId
,
structId
=
theId
,
structParent
=
scope
,
structParent
=
scope
,
structPacking
=
packing
,
structDataSize
=
finalDataSize
,
structPointerCount
=
finalPointerCount
,
structIsFixedWidth
=
isJust
isFixed
,
structFields
=
fields
,
structFields
=
fields
,
structUnions
=
unions
,
structUnions
=
unions
,
structAnnotations
=
compiledAnnotations
,
structAnnotations
=
compiledAnnotations
...
@@ -639,14 +816,13 @@ compileDecl scope@(DescStruct parent)
...
@@ -639,14 +816,13 @@ compileDecl scope@(DescStruct parent)
requireNoMoreThanOneFieldNumberLessThan
name
numPos
number
fields
requireNoMoreThanOneFieldNumberLessThan
name
numPos
number
fields
(
theId
,
compiledAnnotations
)
<-
compileAnnotations
scope
UnionAnnotation
annotations
(
theId
,
compiledAnnotations
)
<-
compileAnnotations
scope
UnionAnnotation
annotations
return
(
let
return
(
let
(
tagOffset
,
tagPacking
)
=
structFieldPackingMap
parent
!
number
DataOffset
Size16
tagOffset
=
structFieldPackingMap
parent
!
number
in
DescUnion
UnionDesc
in
DescUnion
UnionDesc
{
unionName
=
name
{
unionName
=
name
,
unionId
=
theId
,
unionId
=
theId
,
unionParent
=
parent
,
unionParent
=
parent
,
unionNumber
=
number
,
unionNumber
=
number
,
unionTagOffset
=
tagOffset
,
unionTagOffset
=
tagOffset
,
unionTagPacking
=
tagPacking
,
unionFields
=
fields
,
unionFields
=
fields
,
unionAnnotations
=
compiledAnnotations
,
unionAnnotations
=
compiledAnnotations
,
unionMemberMap
=
memberMap
,
unionMemberMap
=
memberMap
...
@@ -668,18 +844,22 @@ compileDecl scope
...
@@ -668,18 +844,22 @@ compileDecl scope
_
->
Nothing
_
->
Nothing
typeDesc
<-
compileType
scope
typeExp
typeDesc
<-
compileType
scope
typeExp
defaultDesc
<-
case
defaultValue
of
defaultDesc
<-
case
defaultValue
of
Just
(
Located
defaultPos
value
)
->
fmap
Just
(
compileValue
defaultPos
typeDesc
value
)
Just
(
Located
defaultPos
value
)
->
do
result
<-
fmap
Just
(
compileValue
defaultPos
typeDesc
value
)
recover
()
(
case
typeDesc
of
InlineStructType
_
->
makeError
defaultPos
"Inline fields cannot have default values."
_
->
return
()
)
return
result
Nothing
->
return
Nothing
Nothing
->
return
Nothing
(
theId
,
compiledAnnotations
)
<-
compileAnnotations
scope
FieldAnnotation
annotations
(
theId
,
compiledAnnotations
)
<-
compileAnnotations
scope
FieldAnnotation
annotations
return
(
let
return
(
let
(
offset
,
packing
)
=
structFieldPackingMap
parent
!
number
in
DescField
FieldDesc
in
DescField
FieldDesc
{
fieldName
=
name
{
fieldName
=
name
,
fieldId
=
theId
,
fieldId
=
theId
,
fieldParent
=
parent
,
fieldParent
=
parent
,
fieldNumber
=
number
,
fieldNumber
=
number
,
fieldOffset
=
offset
,
fieldOffset
=
structFieldPackingMap
parent
!
number
,
fieldPacking
=
packing
,
fieldUnion
=
unionDesc
,
fieldUnion
=
unionDesc
,
fieldType
=
typeDesc
,
fieldType
=
typeDesc
,
fieldDefaultValue
=
defaultDesc
,
fieldDefaultValue
=
defaultDesc
...
...
compiler/src/CxxGenerator.hs
View file @
7f20d533
...
@@ -88,6 +88,7 @@ hashString str =
...
@@ -88,6 +88,7 @@ hashString str =
isPrimitive
t
@
(
BuiltinType
_
)
=
not
$
isBlob
t
isPrimitive
t
@
(
BuiltinType
_
)
=
not
$
isBlob
t
isPrimitive
(
EnumType
_
)
=
True
isPrimitive
(
EnumType
_
)
=
True
isPrimitive
(
StructType
_
)
=
False
isPrimitive
(
StructType
_
)
=
False
isPrimitive
(
InlineStructType
_
)
=
False
isPrimitive
(
InterfaceType
_
)
=
False
isPrimitive
(
InterfaceType
_
)
=
False
isPrimitive
(
ListType
_
)
=
False
isPrimitive
(
ListType
_
)
=
False
...
@@ -96,8 +97,12 @@ isBlob (BuiltinType BuiltinData) = True
...
@@ -96,8 +97,12 @@ isBlob (BuiltinType BuiltinData) = True
isBlob
_
=
False
isBlob
_
=
False
isStruct
(
StructType
_
)
=
True
isStruct
(
StructType
_
)
=
True
isStruct
(
InlineStructType
_
)
=
True
isStruct
_
=
False
isStruct
_
=
False
isInlineStruct
(
InlineStructType
_
)
=
True
isInlineStruct
_
=
False
isList
(
ListType
_
)
=
True
isList
(
ListType
_
)
=
True
isList
_
=
False
isList
_
=
False
...
@@ -130,18 +135,30 @@ cxxTypeString (BuiltinType BuiltinText) = " ::capnproto::Text"
...
@@ -130,18 +135,30 @@ cxxTypeString (BuiltinType BuiltinText) = " ::capnproto::Text"
cxxTypeString
(
BuiltinType
BuiltinData
)
=
" ::capnproto::Data"
cxxTypeString
(
BuiltinType
BuiltinData
)
=
" ::capnproto::Data"
cxxTypeString
(
EnumType
desc
)
=
globalName
$
DescEnum
desc
cxxTypeString
(
EnumType
desc
)
=
globalName
$
DescEnum
desc
cxxTypeString
(
StructType
desc
)
=
globalName
$
DescStruct
desc
cxxTypeString
(
StructType
desc
)
=
globalName
$
DescStruct
desc
cxxTypeString
(
InlineStructType
desc
)
=
globalName
$
DescStruct
desc
cxxTypeString
(
InterfaceType
desc
)
=
globalName
$
DescInterface
desc
cxxTypeString
(
InterfaceType
desc
)
=
globalName
$
DescInterface
desc
cxxTypeString
(
ListType
t
)
=
concat
[
" ::capnproto::List<"
,
cxxTypeString
t
,
">"
]
cxxTypeString
(
ListType
t
)
=
concat
[
" ::capnproto::List<"
,
cxxTypeString
t
,
">"
]
cxxFieldSizeString
Size
0
=
"VOID"
;
cxxFieldSizeString
Size
Void
=
"VOID"
;
cxxFieldSizeString
Size1
=
"BIT"
;
cxxFieldSizeString
(
SizeData
Size1
)
=
"BIT"
;
cxxFieldSizeString
Size8
=
"BYTE"
;
cxxFieldSizeString
(
SizeData
Size8
)
=
"BYTE"
;
cxxFieldSizeString
Size16
=
"TWO_BYTES"
;
cxxFieldSizeString
(
SizeData
Size16
)
=
"TWO_BYTES"
;
cxxFieldSizeString
Size32
=
"FOUR_BYTES"
;
cxxFieldSizeString
(
SizeData
Size32
)
=
"FOUR_BYTES"
;
cxxFieldSizeString
Size64
=
"EIGHT_BYTES"
;
cxxFieldSizeString
(
SizeData
Size64
)
=
"EIGHT_BYTES"
;
cxxFieldSizeString
SizeReference
=
"REFERENCE"
;
cxxFieldSizeString
SizeReference
=
"REFERENCE"
;
cxxFieldSizeString
(
SizeInlineComposite
_
_
)
=
"INLINE_COMPOSITE"
;
cxxFieldSizeString
(
SizeInlineComposite
_
_
)
=
"INLINE_COMPOSITE"
;
fieldOffsetInteger
VoidOffset
=
"0"
fieldOffsetInteger
(
DataOffset
_
o
)
=
show
o
fieldOffsetInteger
(
PointerOffset
o
)
=
show
o
fieldOffsetInteger
(
InlineCompositeOffset
d
p
ds
ps
)
=
let
bitSize
=
dataSectionBits
ds
bitOffset
=
case
ds
of
DataSectionWords
_
->
d
*
64
_
->
d
*
bitSize
in
printf
"%d * ::capnproto::BITS, %d * ::capnproto::BITS,
\
\
%d * ::capnproto::REFERENCES, %d * ::capnproto::REFERENCES"
bitOffset
bitSize
p
ps
isDefaultZero
VoidDesc
=
True
isDefaultZero
VoidDesc
=
True
isDefaultZero
(
BoolDesc
b
)
=
not
b
isDefaultZero
(
BoolDesc
b
)
=
not
b
isDefaultZero
(
Int8Desc
i
)
=
i
==
0
isDefaultZero
(
Int8Desc
i
)
=
i
==
0
...
@@ -221,6 +238,7 @@ fieldContext parent desc = mkStrContext context where
...
@@ -221,6 +238,7 @@ fieldContext parent desc = mkStrContext context where
context
"fieldIsPrimitive"
=
MuBool
$
isPrimitive
$
fieldType
desc
context
"fieldIsPrimitive"
=
MuBool
$
isPrimitive
$
fieldType
desc
context
"fieldIsBlob"
=
MuBool
$
isBlob
$
fieldType
desc
context
"fieldIsBlob"
=
MuBool
$
isBlob
$
fieldType
desc
context
"fieldIsStruct"
=
MuBool
$
isStruct
$
fieldType
desc
context
"fieldIsStruct"
=
MuBool
$
isStruct
$
fieldType
desc
context
"fieldIsInlineStruct"
=
MuBool
$
isInlineStruct
$
fieldType
desc
context
"fieldIsList"
=
MuBool
$
isList
$
fieldType
desc
context
"fieldIsList"
=
MuBool
$
isList
$
fieldType
desc
context
"fieldIsNonStructList"
=
MuBool
$
isNonStructList
$
fieldType
desc
context
"fieldIsNonStructList"
=
MuBool
$
isNonStructList
$
fieldType
desc
context
"fieldIsPrimitiveList"
=
MuBool
$
isPrimitiveList
$
fieldType
desc
context
"fieldIsPrimitiveList"
=
MuBool
$
isPrimitiveList
$
fieldType
desc
...
@@ -231,7 +249,7 @@ fieldContext parent desc = mkStrContext context where
...
@@ -231,7 +249,7 @@ fieldContext parent desc = mkStrContext context where
Nothing
->
muNull
Nothing
->
muNull
context
"fieldType"
=
MuVariable
$
cxxTypeString
$
fieldType
desc
context
"fieldType"
=
MuVariable
$
cxxTypeString
$
fieldType
desc
context
"fieldBlobType"
=
MuVariable
$
blobTypeString
$
fieldType
desc
context
"fieldBlobType"
=
MuVariable
$
blobTypeString
$
fieldType
desc
context
"fieldOffset"
=
MuVariable
$
fieldOffset
desc
context
"fieldOffset"
=
MuVariable
$
fieldOffset
Integer
$
fieldOffset
desc
context
"fieldDefaultMask"
=
case
fieldDefaultValue
desc
of
context
"fieldDefaultMask"
=
case
fieldDefaultValue
desc
of
Nothing
->
MuVariable
""
Nothing
->
MuVariable
""
Just
v
->
MuVariable
(
if
isDefaultZero
v
then
""
else
", "
++
defaultMask
v
)
Just
v
->
MuVariable
(
if
isDefaultZero
v
then
""
else
", "
++
defaultMask
v
)
...
@@ -283,8 +301,8 @@ structContext parent desc = mkStrContext context where
...
@@ -283,8 +301,8 @@ structContext parent desc = mkStrContext context where
context
"structFullName"
=
MuVariable
$
fullName
(
DescStruct
desc
)
context
"structFullName"
=
MuVariable
$
fullName
(
DescStruct
desc
)
context
"structFields"
=
MuList
$
map
(
fieldContext
context
)
$
structFields
desc
context
"structFields"
=
MuList
$
map
(
fieldContext
context
)
$
structFields
desc
context
"structUnions"
=
MuList
$
map
(
unionContext
context
)
$
structUnions
desc
context
"structUnions"
=
MuList
$
map
(
unionContext
context
)
$
structUnions
desc
context
"structDataSize"
=
MuVariable
$
packingDataSize
$
structPacking
desc
context
"structDataSize"
=
MuVariable
$
dataSectionWordSize
$
structDataSize
desc
context
"structReferenceCount"
=
MuVariable
$
packingReferenceCount
$
structPacking
desc
context
"structReferenceCount"
=
MuVariable
$
structPointerCount
desc
context
"structNestedEnums"
=
context
"structNestedEnums"
=
MuList
$
map
(
enumContext
context
)
[
m
|
DescEnum
m
<-
structMembers
desc
]
MuList
$
map
(
enumContext
context
)
[
m
|
DescEnum
m
<-
structMembers
desc
]
context
"structNestedStructs"
=
context
"structNestedStructs"
=
...
...
compiler/src/Grammar.hs
View file @
7f20d533
...
@@ -95,7 +95,8 @@ data Declaration = UsingDecl (Located String) DeclName
...
@@ -95,7 +95,8 @@ data Declaration = UsingDecl (Located String) DeclName
|
ConstantDecl
(
Located
String
)
TypeExpression
[
Annotation
]
(
Located
FieldValue
)
|
ConstantDecl
(
Located
String
)
TypeExpression
[
Annotation
]
(
Located
FieldValue
)
|
EnumDecl
(
Located
String
)
[
Annotation
]
[
Declaration
]
|
EnumDecl
(
Located
String
)
[
Annotation
]
[
Declaration
]
|
EnumerantDecl
(
Located
String
)
(
Located
Integer
)
[
Annotation
]
|
EnumerantDecl
(
Located
String
)
(
Located
Integer
)
[
Annotation
]
|
StructDecl
(
Located
String
)
[
Annotation
]
[
Declaration
]
|
StructDecl
(
Located
String
)
(
Maybe
(
Located
(
Integer
,
Integer
)))
[
Annotation
]
[
Declaration
]
|
FieldDecl
(
Located
String
)
(
Located
Integer
)
|
FieldDecl
(
Located
String
)
(
Located
Integer
)
TypeExpression
[
Annotation
]
(
Maybe
(
Located
FieldValue
))
TypeExpression
[
Annotation
]
(
Maybe
(
Located
FieldValue
))
|
UnionDecl
(
Located
String
)
(
Located
Integer
)
[
Annotation
]
[
Declaration
]
|
UnionDecl
(
Located
String
)
(
Located
Integer
)
[
Annotation
]
[
Declaration
]
...
@@ -110,7 +111,7 @@ declarationName (UsingDecl n _) = Just n
...
@@ -110,7 +111,7 @@ declarationName (UsingDecl n _) = Just n
declarationName
(
ConstantDecl
n
_
_
_
)
=
Just
n
declarationName
(
ConstantDecl
n
_
_
_
)
=
Just
n
declarationName
(
EnumDecl
n
_
_
)
=
Just
n
declarationName
(
EnumDecl
n
_
_
)
=
Just
n
declarationName
(
EnumerantDecl
n
_
_
)
=
Just
n
declarationName
(
EnumerantDecl
n
_
_
)
=
Just
n
declarationName
(
StructDecl
n
_
_
)
=
Just
n
declarationName
(
StructDecl
n
_
_
_
)
=
Just
n
declarationName
(
FieldDecl
n
_
_
_
_
)
=
Just
n
declarationName
(
FieldDecl
n
_
_
_
_
)
=
Just
n
declarationName
(
UnionDecl
n
_
_
_
)
=
Just
n
declarationName
(
UnionDecl
n
_
_
_
)
=
Just
n
declarationName
(
InterfaceDecl
n
_
_
)
=
Just
n
declarationName
(
InterfaceDecl
n
_
_
)
=
Just
n
...
@@ -122,7 +123,7 @@ declImports (UsingDecl _ name) = maybeToList (declNameImport name)
...
@@ -122,7 +123,7 @@ declImports (UsingDecl _ name) = maybeToList (declNameImport name)
declImports
(
ConstantDecl
_
t
ann
_
)
=
typeImports
t
++
concatMap
annotationImports
ann
declImports
(
ConstantDecl
_
t
ann
_
)
=
typeImports
t
++
concatMap
annotationImports
ann
declImports
(
EnumDecl
_
ann
decls
)
=
concatMap
annotationImports
ann
++
concatMap
declImports
decls
declImports
(
EnumDecl
_
ann
decls
)
=
concatMap
annotationImports
ann
++
concatMap
declImports
decls
declImports
(
EnumerantDecl
_
_
ann
)
=
concatMap
annotationImports
ann
declImports
(
EnumerantDecl
_
_
ann
)
=
concatMap
annotationImports
ann
declImports
(
StructDecl
_
ann
decls
)
=
concatMap
annotationImports
ann
++
declImports
(
StructDecl
_
_
ann
decls
)
=
concatMap
annotationImports
ann
++
concatMap
declImports
decls
concatMap
declImports
decls
declImports
(
FieldDecl
_
_
t
ann
_
)
=
typeImports
t
++
concatMap
annotationImports
ann
declImports
(
FieldDecl
_
_
t
ann
_
)
=
typeImports
t
++
concatMap
annotationImports
ann
declImports
(
UnionDecl
_
_
ann
decls
)
=
concatMap
annotationImports
ann
++
declImports
(
UnionDecl
_
_
ann
decls
)
=
concatMap
annotationImports
ann
++
...
...
compiler/src/Lexer.hs
View file @
7f20d533
...
@@ -49,6 +49,7 @@ keywords =
...
@@ -49,6 +49,7 @@ keywords =
,
(
UnionKeyword
,
"union"
)
,
(
UnionKeyword
,
"union"
)
,
(
InterfaceKeyword
,
"interface"
)
,
(
InterfaceKeyword
,
"interface"
)
,
(
AnnotationKeyword
,
"annotation"
)
,
(
AnnotationKeyword
,
"annotation"
)
,
(
FixedKeyword
,
"fixed"
)
]
]
languageDef
::
T
.
LanguageDef
st
languageDef
::
T
.
LanguageDef
st
...
...
compiler/src/Parser.hs
View file @
7f20d533
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
module
Parser
(
parseFile
)
where
module
Parser
(
parseFile
)
where
import
Data.Generics
import
Data.Generics
import
Data.Maybe
(
fromMaybe
)
import
Text.Parsec
hiding
(
tokens
)
import
Text.Parsec
hiding
(
tokens
)
import
Token
import
Token
import
Grammar
import
Grammar
...
@@ -65,6 +66,7 @@ tokenErrorString StructKeyword = "keyword \"struct\""
...
@@ -65,6 +66,7 @@ tokenErrorString StructKeyword = "keyword \"struct\""
tokenErrorString
UnionKeyword
=
"keyword
\"
union
\"
"
tokenErrorString
UnionKeyword
=
"keyword
\"
union
\"
"
tokenErrorString
InterfaceKeyword
=
"keyword
\"
interface
\"
"
tokenErrorString
InterfaceKeyword
=
"keyword
\"
interface
\"
"
tokenErrorString
AnnotationKeyword
=
"keyword
\"
annotation
\"
"
tokenErrorString
AnnotationKeyword
=
"keyword
\"
annotation
\"
"
tokenErrorString
FixedKeyword
=
"keyword
\"
fixed
\"
"
type
TokenParser
=
Parsec
[
Located
Token
]
[
ParseError
]
type
TokenParser
=
Parsec
[
Located
Token
]
[
ParseError
]
...
@@ -120,6 +122,7 @@ structKeyword = tokenParser (matchSimpleToken StructKeyword) <?> "\"struct\""
...
@@ -120,6 +122,7 @@ structKeyword = tokenParser (matchSimpleToken StructKeyword) <?> "\"struct\""
unionKeyword
=
tokenParser
(
matchSimpleToken
UnionKeyword
)
<?>
"
\"
union
\"
"
unionKeyword
=
tokenParser
(
matchSimpleToken
UnionKeyword
)
<?>
"
\"
union
\"
"
interfaceKeyword
=
tokenParser
(
matchSimpleToken
InterfaceKeyword
)
<?>
"
\"
interface
\"
"
interfaceKeyword
=
tokenParser
(
matchSimpleToken
InterfaceKeyword
)
<?>
"
\"
interface
\"
"
annotationKeyword
=
tokenParser
(
matchSimpleToken
AnnotationKeyword
)
<?>
"
\"
annotation
\"
"
annotationKeyword
=
tokenParser
(
matchSimpleToken
AnnotationKeyword
)
<?>
"
\"
annotation
\"
"
fixedKeyword
=
tokenParser
(
matchSimpleToken
FixedKeyword
)
<?>
"
\"
fixed
\"
"
exactIdentifier
s
=
tokenParser
(
matchSimpleToken
$
Identifier
s
)
<?>
"
\"
"
++
s
++
"
\"
"
exactIdentifier
s
=
tokenParser
(
matchSimpleToken
$
Identifier
s
)
<?>
"
\"
"
++
s
++
"
\"
"
...
@@ -223,9 +226,39 @@ enumerantDecl = do
...
@@ -223,9 +226,39 @@ enumerantDecl = do
structDecl
statements
=
do
structDecl
statements
=
do
structKeyword
structKeyword
name
<-
located
typeIdentifier
name
<-
located
typeIdentifier
fixed
<-
optionMaybe
fixedSpec
annotations
<-
many
annotation
annotations
<-
many
annotation
children
<-
parseBlock
structLine
statements
children
<-
parseBlock
structLine
statements
return
(
StructDecl
name
annotations
children
)
return
(
StructDecl
name
fixed
annotations
children
)
fixedSpec
=
do
fixedKeyword
Located
pos
sizes
<-
located
$
parenthesizedList
fixedSize
(
dataSize
,
pointerSize
)
<-
foldM
combineFixedSizes
(
Nothing
,
Nothing
)
sizes
return
$
Located
pos
(
fromMaybe
0
dataSize
,
fromMaybe
0
pointerSize
)
data
FixedSize
=
FixedData
Integer
|
FixedPointers
Integer
combineFixedSizes
::
(
Maybe
Integer
,
Maybe
Integer
)
->
FixedSize
->
TokenParser
(
Maybe
Integer
,
Maybe
Integer
)
combineFixedSizes
(
Nothing
,
p
)
(
FixedData
d
)
=
return
(
Just
d
,
p
)
combineFixedSizes
(
Just
_
,
_
)
(
FixedData
_
)
=
fail
"Multiple data section size specifications."
combineFixedSizes
(
d
,
Nothing
)
(
FixedPointers
p
)
=
return
(
d
,
Just
p
)
combineFixedSizes
(
_
,
Just
_
)
(
FixedPointers
_
)
=
fail
"Multiple pointer section size specifications."
fixedSize
=
do
size
<-
literalInt
(
exactIdentifier
"bit"
>>
return
(
FixedData
size
))
<|>
(
exactIdentifier
"bits"
>>
return
(
FixedData
size
))
<|>
(
exactIdentifier
"byte"
>>
return
(
FixedData
(
8
*
size
)))
<|>
(
exactIdentifier
"bytes"
>>
return
(
FixedData
(
8
*
size
)))
<|>
(
exactIdentifier
"word"
>>
return
(
FixedData
(
64
*
size
)))
<|>
(
exactIdentifier
"words"
>>
return
(
FixedData
(
64
*
size
)))
<|>
(
exactIdentifier
"pointer"
>>
return
(
FixedPointers
size
))
<|>
(
exactIdentifier
"pointers"
>>
return
(
FixedPointers
size
))
<?>
"
\"
bits
\"
,
\"
bytes
\"
,
\"
words
\"
, or
\"
pointers
\"
"
structLine
::
Maybe
[
Located
Statement
]
->
TokenParser
Declaration
structLine
::
Maybe
[
Located
Statement
]
->
TokenParser
Declaration
structLine
Nothing
=
usingDecl
<|>
constantDecl
<|>
fieldDecl
<|>
annotationDecl
structLine
Nothing
=
usingDecl
<|>
constantDecl
<|>
fieldDecl
<|>
annotationDecl
...
...
compiler/src/Semantics.hs
View file @
7f20d533
...
@@ -55,6 +55,7 @@ data Desc = DescFile FileDesc
...
@@ -55,6 +55,7 @@ data Desc = DescFile FileDesc
|
DescAnnotation
AnnotationDesc
|
DescAnnotation
AnnotationDesc
|
DescBuiltinType
BuiltinType
|
DescBuiltinType
BuiltinType
|
DescBuiltinList
|
DescBuiltinList
|
DescBuiltinInline
|
DescBuiltinId
|
DescBuiltinId
descName
(
DescFile
_
)
=
"(top-level)"
descName
(
DescFile
_
)
=
"(top-level)"
...
@@ -71,6 +72,7 @@ descName (DescParam d) = paramName d
...
@@ -71,6 +72,7 @@ descName (DescParam d) = paramName d
descName
(
DescAnnotation
d
)
=
annotationName
d
descName
(
DescAnnotation
d
)
=
annotationName
d
descName
(
DescBuiltinType
d
)
=
builtinTypeName
d
descName
(
DescBuiltinType
d
)
=
builtinTypeName
d
descName
DescBuiltinList
=
"List"
descName
DescBuiltinList
=
"List"
descName
DescBuiltinInline
=
"Inline"
descName
DescBuiltinId
=
"id"
descName
DescBuiltinId
=
"id"
descId
(
DescFile
d
)
=
fileId
d
descId
(
DescFile
d
)
=
fileId
d
...
@@ -87,6 +89,7 @@ descId (DescParam d) = paramId d
...
@@ -87,6 +89,7 @@ descId (DescParam d) = paramId d
descId
(
DescAnnotation
d
)
=
annotationId
d
descId
(
DescAnnotation
d
)
=
annotationId
d
descId
(
DescBuiltinType
_
)
=
Nothing
descId
(
DescBuiltinType
_
)
=
Nothing
descId
DescBuiltinList
=
Nothing
descId
DescBuiltinList
=
Nothing
descId
DescBuiltinInline
=
Nothing
descId
DescBuiltinId
=
Just
"0U0T3e_SnatEfk6UcH2tcjTt1E0"
descId
DescBuiltinId
=
Just
"0U0T3e_SnatEfk6UcH2tcjTt1E0"
-- Gets the ID if explicitly defined, or generates it by appending ".name" to the parent's ID.
-- Gets the ID if explicitly defined, or generates it by appending ".name" to the parent's ID.
...
@@ -111,6 +114,7 @@ descParent (DescParam d) = DescMethod (paramParent d)
...
@@ -111,6 +114,7 @@ descParent (DescParam d) = DescMethod (paramParent d)
descParent
(
DescAnnotation
d
)
=
annotationParent
d
descParent
(
DescAnnotation
d
)
=
annotationParent
d
descParent
(
DescBuiltinType
_
)
=
error
"Builtin type has no parent."
descParent
(
DescBuiltinType
_
)
=
error
"Builtin type has no parent."
descParent
DescBuiltinList
=
error
"Builtin type has no parent."
descParent
DescBuiltinList
=
error
"Builtin type has no parent."
descParent
DescBuiltinInline
=
error
"Builtin type has no parent."
descParent
DescBuiltinId
=
error
"Builtin annotation has no parent."
descParent
DescBuiltinId
=
error
"Builtin annotation has no parent."
descFile
(
DescFile
d
)
=
d
descFile
(
DescFile
d
)
=
d
...
@@ -130,9 +134,10 @@ descAnnotations (DescParam d) = paramAnnotations d
...
@@ -130,9 +134,10 @@ descAnnotations (DescParam d) = paramAnnotations d
descAnnotations
(
DescAnnotation
d
)
=
annotationAnnotations
d
descAnnotations
(
DescAnnotation
d
)
=
annotationAnnotations
d
descAnnotations
(
DescBuiltinType
_
)
=
Map
.
empty
descAnnotations
(
DescBuiltinType
_
)
=
Map
.
empty
descAnnotations
DescBuiltinList
=
Map
.
empty
descAnnotations
DescBuiltinList
=
Map
.
empty
descAnnotations
DescBuiltinInline
=
Map
.
empty
descAnnotations
DescBuiltinId
=
Map
.
empty
descAnnotations
DescBuiltinId
=
Map
.
empty
descRuntimeImports
(
DescFile
d
)
=
error
"Not to be called on files."
descRuntimeImports
(
DescFile
_
)
=
error
"Not to be called on files."
descRuntimeImports
(
DescUsing
d
)
=
usingRuntimeImports
d
descRuntimeImports
(
DescUsing
d
)
=
usingRuntimeImports
d
descRuntimeImports
(
DescConstant
d
)
=
constantRuntimeImports
d
descRuntimeImports
(
DescConstant
d
)
=
constantRuntimeImports
d
descRuntimeImports
(
DescEnum
d
)
=
enumRuntimeImports
d
descRuntimeImports
(
DescEnum
d
)
=
enumRuntimeImports
d
...
@@ -146,6 +151,7 @@ descRuntimeImports (DescParam d) = paramRuntimeImports d
...
@@ -146,6 +151,7 @@ descRuntimeImports (DescParam d) = paramRuntimeImports d
descRuntimeImports
(
DescAnnotation
d
)
=
annotationRuntimeImports
d
descRuntimeImports
(
DescAnnotation
d
)
=
annotationRuntimeImports
d
descRuntimeImports
(
DescBuiltinType
_
)
=
[]
descRuntimeImports
(
DescBuiltinType
_
)
=
[]
descRuntimeImports
DescBuiltinList
=
[]
descRuntimeImports
DescBuiltinList
=
[]
descRuntimeImports
DescBuiltinInline
=
[]
descRuntimeImports
DescBuiltinId
=
[]
descRuntimeImports
DescBuiltinId
=
[]
type
MemberMap
=
Map
.
Map
String
(
Maybe
Desc
)
type
MemberMap
=
Map
.
Map
String
(
Maybe
Desc
)
...
@@ -212,101 +218,118 @@ valueString (ListDesc l) = "[" ++ delimit ", " (map valueString l) ++ "]" where
...
@@ -212,101 +218,118 @@ valueString (ListDesc l) = "[" ++ delimit ", " (map valueString l) ++ "]" where
data
TypeDesc
=
BuiltinType
BuiltinType
data
TypeDesc
=
BuiltinType
BuiltinType
|
EnumType
EnumDesc
|
EnumType
EnumDesc
|
StructType
StructDesc
|
StructType
StructDesc
|
InlineStructType
StructDesc
|
InterfaceType
InterfaceDesc
|
InterfaceType
InterfaceDesc
|
ListType
TypeDesc
|
ListType
TypeDesc
typeRuntimeImports
(
BuiltinType
_
)
=
[]
typeRuntimeImports
(
BuiltinType
_
)
=
[]
typeRuntimeImports
(
EnumType
d
)
=
[
descFile
(
DescEnum
d
)]
typeRuntimeImports
(
EnumType
d
)
=
[
descFile
(
DescEnum
d
)]
typeRuntimeImports
(
StructType
d
)
=
[
descFile
(
DescStruct
d
)]
typeRuntimeImports
(
StructType
d
)
=
[
descFile
(
DescStruct
d
)]
typeRuntimeImports
(
InlineStructType
d
)
=
[
descFile
(
DescStruct
d
)]
typeRuntimeImports
(
InterfaceType
d
)
=
[
descFile
(
DescInterface
d
)]
typeRuntimeImports
(
InterfaceType
d
)
=
[
descFile
(
DescInterface
d
)]
typeRuntimeImports
(
ListType
d
)
=
typeRuntimeImports
d
typeRuntimeImports
(
ListType
d
)
=
typeRuntimeImports
d
data
PackingState
=
PackingState
data
DataSectionSize
=
DataSection1
|
DataSection8
|
DataSection16
|
DataSection32
{
packingHole1
::
Integer
|
DataSectionWords
Integer
,
packingHole8
::
Integer
,
packingHole16
::
Integer
dataSectionWordSize
ds
=
case
ds
of
,
packingHole32
::
Integer
DataSectionWords
w
->
w
,
packingDataSize
::
Integer
_
->
1
,
packingReferenceCount
::
Integer
dataSectionAlignment
DataSection1
=
Size1
dataSectionAlignment
DataSection8
=
Size8
dataSectionAlignment
DataSection16
=
Size16
dataSectionAlignment
DataSection32
=
Size32
dataSectionAlignment
(
DataSectionWords
_
)
=
Size64
dataSectionBits
DataSection1
=
1
dataSectionBits
DataSection8
=
8
dataSectionBits
DataSection16
=
16
dataSectionBits
DataSection32
=
32
dataSectionBits
(
DataSectionWords
w
)
=
w
*
64
dataSizeToSectionSize
Size1
=
DataSection1
dataSizeToSectionSize
Size8
=
DataSection8
dataSizeToSectionSize
Size16
=
DataSection16
dataSizeToSectionSize
Size32
=
DataSection32
dataSizeToSectionSize
Size64
=
DataSectionWords
1
dataSectionSizeString
DataSection1
=
"1 bits"
dataSectionSizeString
DataSection8
=
"8 bits"
dataSectionSizeString
DataSection16
=
"16 bits"
dataSectionSizeString
DataSection32
=
"32 bits"
dataSectionSizeString
(
DataSectionWords
n
)
=
show
n
++
" words"
data
DataSize
=
Size1
|
Size8
|
Size16
|
Size32
|
Size64
deriving
(
Eq
,
Ord
,
Enum
)
dataSizeInBits
::
DataSize
->
Integer
dataSizeInBits
Size1
=
1
dataSizeInBits
Size8
=
8
dataSizeInBits
Size16
=
16
dataSizeInBits
Size32
=
32
dataSizeInBits
Size64
=
64
data
FieldSize
=
SizeVoid
|
SizeData
DataSize
|
SizeReference
|
SizeInlineComposite
DataSectionSize
Integer
data
FieldOffset
=
VoidOffset
|
DataOffset
DataSize
Integer
|
PointerOffset
Integer
|
InlineCompositeOffset
{
inlineCompositeDataOffset
::
Integer
,
inlineCompositePointerOffset
::
Integer
,
inlineCompositeDataSize
::
DataSectionSize
,
inlineCompositePointerSize
::
Integer
}
}
packingSize
PackingState
{
packingDataSize
=
ds
,
packingReferenceCount
=
rc
}
=
ds
+
rc
offsetToSize
::
FieldOffset
->
FieldSize
offsetToSize
VoidOffset
=
SizeVoid
-- Represents the current packing state of a union. The parameters are:
offsetToSize
(
DataOffset
s
_
)
=
SizeData
s
-- - The offset of a 64-bit word in the data segment allocated to the union.
offsetToSize
(
PointerOffset
_
)
=
SizeReference
-- - The offset of a reference allocated to the union.
offsetToSize
(
InlineCompositeOffset
_
_
d
p
)
=
SizeInlineComposite
d
p
-- - The offset of a smaller piece of the data segment allocated to the union. Such a smaller
-- piece exists if one field in the union has lower number than the union itself -- in this case,
fieldSize
(
BuiltinType
BuiltinVoid
)
=
SizeVoid
-- this is the piece that had been allocated to that field, and is now retroactively part of the
fieldSize
(
BuiltinType
BuiltinBool
)
=
SizeData
Size1
-- union.
fieldSize
(
BuiltinType
BuiltinInt8
)
=
SizeData
Size8
data
UnionPackingState
=
UnionPackingState
fieldSize
(
BuiltinType
BuiltinInt16
)
=
SizeData
Size16
{
unionPackDataOffset
::
Maybe
(
Integer
,
FieldSize
)
fieldSize
(
BuiltinType
BuiltinInt32
)
=
SizeData
Size32
,
unionPackReferenceOffset
::
Maybe
Integer
fieldSize
(
BuiltinType
BuiltinInt64
)
=
SizeData
Size64
}
fieldSize
(
BuiltinType
BuiltinUInt8
)
=
SizeData
Size8
fieldSize
(
BuiltinType
BuiltinUInt16
)
=
SizeData
Size16
data
FieldSize
=
Size0
|
Size1
|
Size8
|
Size16
|
Size32
|
Size64
|
SizeReference
fieldSize
(
BuiltinType
BuiltinUInt32
)
=
SizeData
Size32
|
SizeInlineComposite
Integer
Integer
fieldSize
(
BuiltinType
BuiltinUInt64
)
=
SizeData
Size64
fieldSize
(
BuiltinType
BuiltinFloat32
)
=
SizeData
Size32
isDataFieldSize
SizeReference
=
False
fieldSize
(
BuiltinType
BuiltinFloat64
)
=
SizeData
Size64
isDataFieldSize
(
SizeInlineComposite
_
_
)
=
False
isDataFieldSize
_
=
True
fieldSize
(
BuiltinType
BuiltinVoid
)
=
Size0
fieldSize
(
BuiltinType
BuiltinBool
)
=
Size1
fieldSize
(
BuiltinType
BuiltinInt8
)
=
Size8
fieldSize
(
BuiltinType
BuiltinInt16
)
=
Size16
fieldSize
(
BuiltinType
BuiltinInt32
)
=
Size32
fieldSize
(
BuiltinType
BuiltinInt64
)
=
Size64
fieldSize
(
BuiltinType
BuiltinUInt8
)
=
Size8
fieldSize
(
BuiltinType
BuiltinUInt16
)
=
Size16
fieldSize
(
BuiltinType
BuiltinUInt32
)
=
Size32
fieldSize
(
BuiltinType
BuiltinUInt64
)
=
Size64
fieldSize
(
BuiltinType
BuiltinFloat32
)
=
Size32
fieldSize
(
BuiltinType
BuiltinFloat64
)
=
Size64
fieldSize
(
BuiltinType
BuiltinText
)
=
SizeReference
fieldSize
(
BuiltinType
BuiltinText
)
=
SizeReference
fieldSize
(
BuiltinType
BuiltinData
)
=
SizeReference
fieldSize
(
BuiltinType
BuiltinData
)
=
SizeReference
fieldSize
(
EnumType
_
)
=
Size
16
-- TODO: ??
fieldSize
(
EnumType
_
)
=
Size
Data
Size16
fieldSize
(
StructType
_
)
=
SizeReference
fieldSize
(
StructType
_
)
=
SizeReference
fieldSize
(
InlineStructType
StructDesc
{
structDataSize
=
ds
,
structPointerCount
=
ps
})
=
SizeInlineComposite
ds
ps
fieldSize
(
InterfaceType
_
)
=
SizeReference
fieldSize
(
InterfaceType
_
)
=
SizeReference
fieldSize
(
ListType
_
)
=
SizeReference
fieldSize
(
ListType
_
)
=
SizeReference
fieldValueSize
VoidDesc
=
Size0
elementSize
(
StructType
StructDesc
{
structDataSize
=
DataSection1
,
structPointerCount
=
0
})
=
fieldValueSize
(
BoolDesc
_
)
=
Size1
SizeData
Size1
fieldValueSize
(
Int8Desc
_
)
=
Size8
elementSize
(
StructType
StructDesc
{
structDataSize
=
DataSection8
,
structPointerCount
=
0
})
=
fieldValueSize
(
Int16Desc
_
)
=
Size16
SizeData
Size8
fieldValueSize
(
Int32Desc
_
)
=
Size32
elementSize
(
StructType
StructDesc
{
structDataSize
=
DataSection16
,
structPointerCount
=
0
})
=
fieldValueSize
(
Int64Desc
_
)
=
Size64
SizeData
Size16
fieldValueSize
(
UInt8Desc
_
)
=
Size8
elementSize
(
StructType
StructDesc
{
structDataSize
=
DataSection32
,
structPointerCount
=
0
})
=
fieldValueSize
(
UInt16Desc
_
)
=
Size16
SizeData
Size32
fieldValueSize
(
UInt32Desc
_
)
=
Size32
elementSize
(
StructType
StructDesc
{
structDataSize
=
ds
,
structPointerCount
=
pc
})
=
fieldValueSize
(
UInt64Desc
_
)
=
Size64
SizeInlineComposite
ds
pc
fieldValueSize
(
Float32Desc
_
)
=
Size32
elementSize
(
InlineStructType
s
)
=
elementSize
(
StructType
s
)
fieldValueSize
(
Float64Desc
_
)
=
Size64
fieldValueSize
(
TextDesc
_
)
=
SizeReference
fieldValueSize
(
DataDesc
_
)
=
SizeReference
fieldValueSize
(
EnumerantValueDesc
_
)
=
Size16
fieldValueSize
(
StructValueDesc
_
)
=
SizeReference
fieldValueSize
(
ListDesc
_
)
=
SizeReference
elementSize
(
StructType
StructDesc
{
structPacking
=
PackingState
{
packingDataSize
=
ds
,
packingReferenceCount
=
rc
}
})
=
SizeInlineComposite
ds
rc
elementSize
t
=
fieldSize
t
elementSize
t
=
fieldSize
t
sizeInBits
Size0
=
0
sizeInBits
Size1
=
1
sizeInBits
Size8
=
8
sizeInBits
Size16
=
16
sizeInBits
Size32
=
32
sizeInBits
Size64
=
64
sizeInBits
SizeReference
=
64
sizeInBits
(
SizeInlineComposite
d
r
)
=
(
d
+
r
)
*
64
-- Render the type descriptor's name as a string, appropriate for use in the given scope.
-- Render the type descriptor's name as a string, appropriate for use in the given scope.
typeName
::
Desc
->
TypeDesc
->
String
typeName
::
Desc
->
TypeDesc
->
String
typeName
_
(
BuiltinType
t
)
=
builtinTypeName
t
-- TODO: Check for shadowing.
typeName
_
(
BuiltinType
t
)
=
builtinTypeName
t
-- TODO: Check for shadowing.
typeName
scope
(
EnumType
desc
)
=
descQualifiedName
scope
(
DescEnum
desc
)
typeName
scope
(
EnumType
desc
)
=
descQualifiedName
scope
(
DescEnum
desc
)
typeName
scope
(
StructType
desc
)
=
descQualifiedName
scope
(
DescStruct
desc
)
typeName
scope
(
StructType
desc
)
=
descQualifiedName
scope
(
DescStruct
desc
)
typeName
scope
(
InlineStructType
desc
)
=
descQualifiedName
scope
(
DescStruct
desc
)
typeName
scope
(
InterfaceType
desc
)
=
descQualifiedName
scope
(
DescInterface
desc
)
typeName
scope
(
InterfaceType
desc
)
=
descQualifiedName
scope
(
DescInterface
desc
)
typeName
scope
(
ListType
t
)
=
"List("
++
typeName
scope
t
++
")"
typeName
scope
(
ListType
t
)
=
"List("
++
typeName
scope
t
++
")"
...
@@ -386,7 +409,9 @@ data StructDesc = StructDesc
...
@@ -386,7 +409,9 @@ data StructDesc = StructDesc
{
structName
::
String
{
structName
::
String
,
structId
::
Maybe
String
,
structId
::
Maybe
String
,
structParent
::
Desc
,
structParent
::
Desc
,
structPacking
::
PackingState
,
structDataSize
::
DataSectionSize
,
structPointerCount
::
Integer
,
structIsFixedWidth
::
Bool
,
structFields
::
[
FieldDesc
]
,
structFields
::
[
FieldDesc
]
,
structUnions
::
[
UnionDesc
]
,
structUnions
::
[
UnionDesc
]
,
structAnnotations
::
AnnotationMap
,
structAnnotations
::
AnnotationMap
...
@@ -396,7 +421,7 @@ data StructDesc = StructDesc
...
@@ -396,7 +421,7 @@ data StructDesc = StructDesc
-- Don't use this directly, use the members of FieldDesc and UnionDesc.
-- Don't use this directly, use the members of FieldDesc and UnionDesc.
-- This field is exposed here only because I was too lazy to create a way to pass it on
-- This field is exposed here only because I was too lazy to create a way to pass it on
-- the side when compiling members of a struct.
-- the side when compiling members of a struct.
,
structFieldPackingMap
::
Map
.
Map
Integer
(
Integer
,
PackingState
)
,
structFieldPackingMap
::
Map
.
Map
Integer
FieldOffset
}
}
structRuntimeImports
desc
=
concatMap
descRuntimeImports
$
structMembers
desc
structRuntimeImports
desc
=
concatMap
descRuntimeImports
$
structMembers
desc
...
@@ -407,7 +432,6 @@ data UnionDesc = UnionDesc
...
@@ -407,7 +432,6 @@ data UnionDesc = UnionDesc
,
unionParent
::
StructDesc
,
unionParent
::
StructDesc
,
unionNumber
::
Integer
,
unionNumber
::
Integer
,
unionTagOffset
::
Integer
,
unionTagOffset
::
Integer
,
unionTagPacking
::
PackingState
,
unionFields
::
[
FieldDesc
]
,
unionFields
::
[
FieldDesc
]
,
unionAnnotations
::
AnnotationMap
,
unionAnnotations
::
AnnotationMap
,
unionMemberMap
::
MemberMap
,
unionMemberMap
::
MemberMap
...
@@ -424,8 +448,7 @@ data FieldDesc = FieldDesc
...
@@ -424,8 +448,7 @@ data FieldDesc = FieldDesc
,
fieldId
::
Maybe
String
,
fieldId
::
Maybe
String
,
fieldParent
::
StructDesc
,
fieldParent
::
StructDesc
,
fieldNumber
::
Integer
,
fieldNumber
::
Integer
,
fieldOffset
::
Integer
,
fieldOffset
::
FieldOffset
,
fieldPacking
::
PackingState
-- PackingState for the struct *if* this were the final field.
,
fieldUnion
::
Maybe
(
UnionDesc
,
Integer
)
-- Integer is value of union discriminant.
,
fieldUnion
::
Maybe
(
UnionDesc
,
Integer
)
-- Integer is value of union discriminant.
,
fieldType
::
TypeDesc
,
fieldType
::
TypeDesc
,
fieldDefaultValue
::
Maybe
ValueDesc
,
fieldDefaultValue
::
Maybe
ValueDesc
...
@@ -508,8 +531,13 @@ descToCode indent self@(DescEnum desc) = printf "%senum %s%s {\n%s%s}\n" indent
...
@@ -508,8 +531,13 @@ descToCode indent self@(DescEnum desc) = printf "%senum %s%s {\n%s%s}\n" indent
descToCode
indent
self
@
(
DescEnumerant
desc
)
=
printf
"%s%s @%d%s;
\n
"
indent
descToCode
indent
self
@
(
DescEnumerant
desc
)
=
printf
"%s%s @%d%s;
\n
"
indent
(
enumerantName
desc
)
(
enumerantNumber
desc
)
(
enumerantName
desc
)
(
enumerantNumber
desc
)
(
annotationsCode
self
)
(
annotationsCode
self
)
descToCode
indent
self
@
(
DescStruct
desc
)
=
printf
"%sstruct %s%s {
\n
%s%s}
\n
"
indent
descToCode
indent
self
@
(
DescStruct
desc
)
=
printf
"%sstruct %s%s
%s
{
\n
%s%s}
\n
"
indent
(
structName
desc
)
(
structName
desc
)
(
if
structIsFixedWidth
desc
then
printf
" fixed(%s, %d pointers) "
(
dataSectionSizeString
$
structDataSize
desc
)
(
structPointerCount
desc
)
else
""
)
(
annotationsCode
self
)
(
annotationsCode
self
)
(
blockCode
indent
(
structMembers
desc
))
(
blockCode
indent
(
structMembers
desc
))
indent
indent
...
@@ -519,12 +547,16 @@ descToCode indent self@(DescField desc) = printf "%s%s@%d%s: %s%s%s; # %s\n" in
...
@@ -519,12 +547,16 @@ descToCode indent self@(DescField desc) = printf "%s%s@%d%s: %s%s%s; # %s\n" in
(
typeName
(
descParent
self
)
(
fieldType
desc
))
(
typeName
(
descParent
self
)
(
fieldType
desc
))
(
case
fieldDefaultValue
desc
of
{
Nothing
->
""
;
Just
v
->
" = "
++
valueString
v
;
})
(
case
fieldDefaultValue
desc
of
{
Nothing
->
""
;
Just
v
->
" = "
++
valueString
v
;
})
(
annotationsCode
self
)
(
annotationsCode
self
)
(
case
fieldSize
$
fieldType
desc
of
(
case
fieldOffset
desc
of
SizeReference
->
printf
"ref[%d]"
$
fieldOffset
desc
PointerOffset
o
->
printf
"ptr[%d]"
o
SizeInlineComposite
_
_
->
"??"
InlineCompositeOffset
dataOffset
pointerOffset
dataSize
pointerSize
->
s
->
let
let
dataBitOffset
=
dataOffset
*
dataSizeInBits
(
dataSectionAlignment
dataSize
)
bits
=
sizeInBits
s
in
printf
"bits[%d, %d), ptrs[%d, %d)"
offset
=
fieldOffset
desc
dataBitOffset
(
dataBitOffset
+
dataSectionBits
dataSize
)
pointerOffset
(
pointerOffset
+
pointerSize
)
VoidOffset
->
"(none)"
DataOffset
dataSize
offset
->
let
bits
=
dataSizeInBits
dataSize
in
printf
"bits[%d, %d)"
(
offset
*
bits
)
((
offset
+
1
)
*
bits
))
in
printf
"bits[%d, %d)"
(
offset
*
bits
)
((
offset
+
1
)
*
bits
))
descToCode
indent
self
@
(
DescUnion
desc
)
=
printf
"%sunion %s@%d%s { # [%d, %d)
\n
%s%s}
\n
"
indent
descToCode
indent
self
@
(
DescUnion
desc
)
=
printf
"%sunion %s@%d%s { # [%d, %d)
\n
%s%s}
\n
"
indent
(
unionName
desc
)
(
unionNumber
desc
)
(
unionName
desc
)
(
unionNumber
desc
)
...
@@ -556,6 +588,7 @@ descToCode indent self@(DescAnnotation desc) = printf "%sannotation %s: %s on(%s
...
@@ -556,6 +588,7 @@ descToCode indent self@(DescAnnotation desc) = printf "%sannotation %s: %s on(%s
(
annotationsCode
self
)
(
annotationsCode
self
)
descToCode
_
(
DescBuiltinType
_
)
=
error
"Can't print code for builtin type."
descToCode
_
(
DescBuiltinType
_
)
=
error
"Can't print code for builtin type."
descToCode
_
DescBuiltinList
=
error
"Can't print code for builtin type."
descToCode
_
DescBuiltinList
=
error
"Can't print code for builtin type."
descToCode
_
DescBuiltinInline
=
error
"Can't print code for builtin type."
descToCode
_
DescBuiltinId
=
error
"Can't print code for builtin annotation."
descToCode
_
DescBuiltinId
=
error
"Can't print code for builtin annotation."
maybeBlockCode
::
String
->
[
Desc
]
->
String
maybeBlockCode
::
String
->
[
Desc
]
->
String
...
...
compiler/src/Token.hs
View file @
7f20d533
...
@@ -74,6 +74,7 @@ data Token = Identifier String
...
@@ -74,6 +74,7 @@ data Token = Identifier String
|
UnionKeyword
|
UnionKeyword
|
InterfaceKeyword
|
InterfaceKeyword
|
AnnotationKeyword
|
AnnotationKeyword
|
FixedKeyword
deriving
(
Data
,
Typeable
,
Show
,
Eq
)
deriving
(
Data
,
Typeable
,
Show
,
Eq
)
data
Statement
=
Line
TokenSequence
data
Statement
=
Line
TokenSequence
...
...
compiler/src/WireFormat.hs
View file @
7f20d533
...
@@ -26,11 +26,11 @@ module WireFormat(encodeMessage) where
...
@@ -26,11 +26,11 @@ module WireFormat(encodeMessage) where
import
Data.List
(
sortBy
,
genericLength
,
genericReplicate
)
import
Data.List
(
sortBy
,
genericLength
,
genericReplicate
)
import
Data.Word
import
Data.Word
import
Data.Bits
(
shiftL
,
shiftR
,
Bits
,
setBit
,
xor
)
import
Data.Bits
(
shiftL
,
shiftR
,
Bits
,
setBit
,
xor
)
import
Data.Function
(
on
)
import
Semantics
import
Semantics
import
Data.Binary.IEEE754
(
floatToWord
,
doubleToWord
)
import
Data.Binary.IEEE754
(
floatToWord
,
doubleToWord
)
import
qualified
Codec.Binary.UTF8.String
as
UTF8
import
qualified
Codec.Binary.UTF8.String
as
UTF8
--
byte
::
(
Integral
a
,
Bits
a
)
=>
a
->
Int
->
Word8
byte
::
(
Integral
a
,
Bits
a
)
=>
a
->
Int
->
Word8
byte
i
amount
=
fromIntegral
(
shiftR
i
(
amount
*
8
))
byte
i
amount
=
fromIntegral
(
shiftR
i
(
amount
*
8
))
...
@@ -43,119 +43,112 @@ padToWord b = let
...
@@ -43,119 +43,112 @@ padToWord b = let
then
b
then
b
else
b
++
replicate
(
8
-
trailing
)
0
else
b
++
replicate
(
8
-
trailing
)
0
roundUpToMultiple
factor
n
=
let
data
EncodedData
=
EncodedBit
Bool
remainder
=
mod
n
factor
|
EncodedBytes
[
Word8
]
in
if
remainder
==
0
then
n
xorData
(
EncodedBit
a
)
(
EncodedBit
b
)
=
EncodedBit
(
a
/=
b
)
else
n
+
(
factor
-
remainder
)
xorData
(
EncodedBytes
a
)
(
EncodedBytes
b
)
=
EncodedBytes
(
zipWith
xor
a
b
)
xorData
_
_
=
error
"Value type mismatch when xor'ing."
encodeDataValue
::
ValueDesc
->
[
Word8
]
encodeDataValue
VoidDesc
=
[]
encodeDataValue
::
TypeDesc
->
ValueDesc
->
EncodedData
encodeDataValue
(
BoolDesc
_
)
=
error
"Bools must be handled specially."
encodeDataValue
_
VoidDesc
=
EncodedBytes
[]
encodeDataValue
(
Int8Desc
v
)
=
bytes
v
1
encodeDataValue
_
(
BoolDesc
v
)
=
EncodedBit
v
encodeDataValue
(
Int16Desc
v
)
=
bytes
v
2
encodeDataValue
_
(
Int8Desc
v
)
=
EncodedBytes
$
bytes
v
1
encodeDataValue
(
Int32Desc
v
)
=
bytes
v
4
encodeDataValue
_
(
Int16Desc
v
)
=
EncodedBytes
$
bytes
v
2
encodeDataValue
(
Int64Desc
v
)
=
bytes
v
8
encodeDataValue
_
(
Int32Desc
v
)
=
EncodedBytes
$
bytes
v
4
encodeDataValue
(
UInt8Desc
v
)
=
bytes
v
1
encodeDataValue
_
(
Int64Desc
v
)
=
EncodedBytes
$
bytes
v
8
encodeDataValue
(
UInt16Desc
v
)
=
bytes
v
2
encodeDataValue
_
(
UInt8Desc
v
)
=
EncodedBytes
$
bytes
v
1
encodeDataValue
(
UInt32Desc
v
)
=
bytes
v
4
encodeDataValue
_
(
UInt16Desc
v
)
=
EncodedBytes
$
bytes
v
2
encodeDataValue
(
UInt64Desc
v
)
=
bytes
v
8
encodeDataValue
_
(
UInt32Desc
v
)
=
EncodedBytes
$
bytes
v
4
encodeDataValue
(
Float32Desc
v
)
=
bytes
(
floatToWord
v
)
4
encodeDataValue
_
(
UInt64Desc
v
)
=
EncodedBytes
$
bytes
v
8
encodeDataValue
(
Float64Desc
v
)
=
bytes
(
doubleToWord
v
)
8
encodeDataValue
_
(
Float32Desc
v
)
=
EncodedBytes
$
bytes
(
floatToWord
v
)
4
encodeDataValue
(
TextDesc
_
)
=
error
"Not fixed-width data."
encodeDataValue
_
(
Float64Desc
v
)
=
EncodedBytes
$
bytes
(
doubleToWord
v
)
8
encodeDataValue
(
DataDesc
_
)
=
error
"Not fixed-width data."
encodeDataValue
_
(
TextDesc
_
)
=
error
"Not fixed-width data."
encodeDataValue
(
EnumerantValueDesc
v
)
=
bytes
(
enumerantNumber
v
)
2
encodeDataValue
_
(
DataDesc
_
)
=
error
"Not fixed-width data."
encodeDataValue
(
StructValueDesc
_
)
=
error
"Not fixed-width data."
encodeDataValue
_
(
EnumerantValueDesc
v
)
=
EncodedBytes
$
bytes
(
enumerantNumber
v
)
2
encodeDataValue
(
ListDesc
_
)
=
error
"Not fixed-width data."
encodeDataValue
(
StructType
desc
)
(
StructValueDesc
assignments
)
=
let
encodeMaskedDataValue
v
Nothing
=
encodeDataValue
v
encodeMaskedDataValue
v
(
Just
d
)
=
zipWith
xor
(
encodeDataValue
v
)
(
encodeDataValue
d
)
packBits
::
Bits
a
=>
Int
->
[(
Bool
,
Maybe
Bool
)]
->
a
packBits
_
[]
=
0
packBits
offset
((
True
,
Nothing
)
:
bits
)
=
setBit
(
packBits
(
offset
+
1
)
bits
)
offset
packBits
offset
((
False
,
Nothing
)
:
bits
)
=
packBits
(
offset
+
1
)
bits
packBits
offset
((
b
,
Just
d
)
:
bits
)
=
packBits
offset
((
b
/=
d
,
Nothing
)
:
bits
)
-- The tuples are (offsetInBits, type, value, defaultValue) for each field to encode.
encodeData
::
Integer
->
[(
Integer
,
TypeDesc
,
ValueDesc
,
Maybe
ValueDesc
)]
->
[
Word8
]
encodeData
size
=
loop
0
where
loop
bit
[]
|
bit
==
size
=
[]
loop
bit
[]
|
bit
>
size
=
error
"Data values overran size."
loop
bit
[]
=
0
:
loop
(
bit
+
8
)
[]
loop
bit
rest
@
((
valuePos
,
_
,
BoolDesc
_
,
_
)
:
_
)
|
valuePos
==
bit
=
let
(
bits
,
rest2
)
=
popBits
(
bit
+
8
)
rest
in
packBits
0
bits
:
loop
(
bit
+
8
)
rest2
loop
bit
((
valuePos
,
_
,
value
,
defaultValue
)
:
rest
)
|
valuePos
==
bit
=
encodeMaskedDataValue
value
defaultValue
++
loop
(
bit
+
sizeInBits
(
fieldValueSize
value
))
rest
loop
bit
rest
@
((
valuePos
,
_
,
_
,
_
)
:
_
)
|
valuePos
>
bit
=
0
:
loop
(
bit
+
8
)
rest
loop
_
_
=
error
"Data values were out-of-order."
popBits
limit
((
valuePos
,
_
,
BoolDesc
b
,
d
)
:
rest
)
|
valuePos
<
limit
=
let
(
restBits
,
rest2
)
=
popBits
limit
rest
defaultB
=
fmap
(
\
(
BoolDesc
b2
)
->
b2
)
d
in
((
b
,
defaultB
)
:
restBits
,
rest2
)
popBits
_
rest
=
(
[]
,
rest
)
encodeReferences
::
Integer
->
Integer
->
[(
Integer
,
TypeDesc
,
ValueDesc
)]
->
([
Word8
],
[
Word8
])
encodeReferences
o
size
=
loop
0
(
o
+
size
-
1
)
where
loop
idx
offset
((
pos
,
t
,
v
)
:
rest
)
|
idx
==
pos
=
let
(
ref
,
obj
)
=
case
(
t
,
v
)
of
(
StructType
desc
,
StructValueDesc
assignments
)
->
let
(
dataBytes
,
refBytes
,
childBytes
)
=
encodeStruct
desc
assignments
0
(
dataBytes
,
refBytes
,
childBytes
)
=
encodeStruct
desc
assignments
0
in
(
encodeStructReference
desc
offset
,
concat
[
dataBytes
,
refBytes
,
childBytes
])
in
if
null
refBytes
&&
null
childBytes
(
ListType
elementType
,
ListDesc
items
)
->
then
EncodedBytes
dataBytes
(
encodeListReference
(
elementSize
elementType
)
(
genericLength
items
)
offset
,
else
error
"encodeDataValue called on struct that wasn't plain data."
encodeDataValue
(
InlineStructType
desc
)
v
=
encodeDataValue
(
StructType
desc
)
v
encodeDataValue
_
(
StructValueDesc
_
)
=
error
"Type/value mismatch."
encodeDataValue
_
(
ListDesc
_
)
=
error
"Not fixed-width data."
encodeMaskedDataValue
t
v
Nothing
=
encodeDataValue
t
v
encodeMaskedDataValue
t
v
(
Just
d
)
=
xorData
(
encodeDataValue
t
v
)
(
encodeDataValue
t
d
)
encodePointerValue
::
TypeDesc
->
ValueDesc
->
(
Integer
->
[
Word8
],
[
Word8
])
encodePointerValue
_
(
TextDesc
text
)
=
let
encoded
=
UTF8
.
encode
text
++
[
0
]
in
(
encodeListReference
(
SizeData
Size8
)
(
genericLength
encoded
),
padToWord
encoded
)
encodePointerValue
_
(
DataDesc
d
)
=
(
encodeListReference
(
SizeData
Size8
)
(
genericLength
d
),
padToWord
d
)
encodePointerValue
(
StructType
desc
)
(
StructValueDesc
assignments
)
=
let
(
dataBytes
,
refBytes
,
childBytes
)
=
encodeStruct
desc
assignments
0
in
(
encodeStructReference
desc
,
concat
[
padToWord
dataBytes
,
refBytes
,
childBytes
])
encodePointerValue
(
InlineStructType
desc
)
v
=
encodePointerValue
(
StructType
desc
)
v
encodePointerValue
(
ListType
elementType
)
(
ListDesc
items
)
=
(
encodeListReference
(
elementSize
elementType
)
(
genericLength
items
),
encodeList
elementType
items
)
encodeList
elementType
items
)
(
BuiltinType
BuiltinText
,
TextDesc
text
)
->
let
encodePointerValue
_
_
=
error
"Unknown pointer type."
encoded
=
(
UTF8
.
encode
text
++
[
0
])
in
(
encodeListReference
Size8
(
genericLength
encoded
)
offset
,
padToWord
encoded
)
-- Given a sorted list of (bitOffset, data), pack into a byte array.
(
BuiltinType
BuiltinData
,
DataDesc
d
)
->
let
packBytes
::
Integer
-- Total size of array to pack, in bits.
in
(
encodeListReference
Size8
(
genericLength
d
)
offset
,
padToWord
d
)
->
[(
Integer
,
EncodedData
)]
-- (offset, data) pairs to pack. Must be in order.
_
->
error
"Unknown reference type."
->
[
Word8
]
len
=
genericLength
obj
packBytes
size
=
loop
0
where
wordLen
=
if
mod
len
8
==
0
then
div
len
8
else
error
"Child not word-aligned."
loop
::
Integer
->
[(
Integer
,
EncodedData
)]
->
[
Word8
]
(
refs
,
objects
)
=
loop
(
idx
+
1
)
(
offset
+
wordLen
-
1
)
rest
loop
bit
[]
|
bit
<=
size
=
genericReplicate
(
div
(
size
-
bit
+
7
)
8
)
0
in
(
ref
++
refs
,
obj
++
objects
)
loop
bit
[]
|
bit
>
size
=
error
"Data values overran size."
loop
idx
offset
rest
@
((
pos
,
_
,
_
)
:
_
)
=
let
loop
bit
values
@
((
offset
,
_
)
:
_
)
|
offset
>=
bit
+
8
=
0
:
loop
(
bit
+
8
)
values
loop
bit
((
offset
,
EncodedBit
True
)
:
rest
)
=
let
firstByte
:
restBytes
=
loop
bit
rest
in
setBit
firstByte
(
fromIntegral
(
offset
-
bit
))
:
restBytes
loop
bit
((
_
,
EncodedBit
False
)
:
rest
)
=
loop
bit
rest
loop
bit
((
offset
,
EncodedBytes
encoded
)
:
rest
)
|
offset
==
bit
=
encoded
++
loop
(
bit
+
genericLength
encoded
*
8
)
rest
loop
_
_
=
error
"Data values overlapped."
bytesToWords
i
=
if
mod
i
8
==
0
then
div
i
8
else
error
"Byte count did not divide evenly into words."
packPointers
::
Integer
-- Total number of pointers to pack.
->
[(
Integer
,
(
Integer
->
[
Word8
],
[
Word8
]))]
->
Integer
-- Word offset from end of pointer array to child area.
->
([
Word8
],
[
Word8
])
packPointers
size
items
o
=
loop
0
items
(
o
+
size
-
1
)
where
loop
::
Integer
->
[(
Integer
,
(
Integer
->
[
Word8
],
[
Word8
]))]
->
Integer
->
([
Word8
],
[
Word8
])
loop
idx
((
pos
,
(
mkptrs
,
child
))
:
rest
)
childOff
|
idx
==
pos
=
let
ptrs
=
mkptrs
childOff
ptrCount
=
bytesToWords
(
genericLength
ptrs
)
newChildOff
=
childOff
-
ptrCount
+
bytesToWords
(
genericLength
child
)
(
restPtrs
,
restChildren
)
=
loop
(
idx
+
ptrCount
)
rest
newChildOff
in
(
ptrs
++
restPtrs
,
child
++
restChildren
)
loop
idx
rest
@
((
pos
,
_
)
:
_
)
childOff
=
let
padCount
=
pos
-
idx
padCount
=
pos
-
idx
(
refs
,
objects
)
=
loop
pos
(
offset
-
padCount
)
rest
(
restPtrs
,
restChildren
)
=
loop
pos
rest
(
childOff
-
padCount
)
in
(
genericReplicate
(
padCount
*
8
)
0
++
refs
,
objects
)
in
(
genericReplicate
(
padCount
*
8
)
0
++
restPtrs
,
restChildren
)
loop
idx
_
[]
=
(
genericReplicate
((
size
-
idx
)
*
8
)
0
,
[]
)
loop
idx
[]
_
=
(
genericReplicate
((
size
-
idx
)
*
8
)
0
,
[]
)
encodeStructList
::
Integer
->
StructDesc
->
[[(
FieldDesc
,
ValueDesc
)]]
->
([
Word8
],
[
Word8
])
encodeStructList
o
desc
elements
=
loop
(
o
+
eSize
*
genericLength
elements
)
elements
where
eSize
=
packingSize
$
structPacking
desc
loop
_
[]
=
(
[]
,
[]
)
loop
offset
(
element
:
rest
)
=
let
offsetFromElementEnd
=
offset
-
eSize
(
dataBytes
,
refBytes
,
childBytes
)
=
encodeStruct
desc
element
offsetFromElementEnd
childLen
=
genericLength
childBytes
childWordLen
=
if
mod
childLen
8
==
0
then
div
childLen
8
else
error
"Child not word-aligned."
(
restBytes
,
restChildren
)
=
loop
(
offsetFromElementEnd
+
childWordLen
)
rest
in
(
dataBytes
++
refBytes
++
restBytes
,
childBytes
++
restChildren
)
encodeStructReference
desc
offset
=
encodeStructReference
desc
offset
=
bytes
(
offset
*
4
+
structTag
)
4
++
bytes
(
offset
*
4
+
structTag
)
4
++
bytes
(
packingDataSize
$
structPacking
desc
)
2
++
bytes
(
dataSectionWordSize
$
structDataSize
desc
)
2
++
bytes
(
packingReferenceCount
$
structPacking
desc
)
2
bytes
(
structPointerCount
desc
)
2
encodeListReference
elemSize
@
(
SizeInlineComposite
ds
rc
)
elementCount
offset
=
encodeListReference
elemSize
@
(
SizeInlineComposite
ds
rc
)
elementCount
offset
=
bytes
(
offset
*
4
+
listTag
)
4
++
bytes
(
offset
*
4
+
listTag
)
4
++
bytes
(
fieldSizeEnum
elemSize
+
shiftL
(
elementCount
*
(
ds
+
rc
))
3
)
4
bytes
(
fieldSizeEnum
elemSize
+
shiftL
(
elementCount
*
(
d
ataSectionWordSize
d
s
+
rc
))
3
)
4
encodeListReference
elemSize
elementCount
offset
=
encodeListReference
elemSize
elementCount
offset
=
bytes
(
offset
*
4
+
listTag
)
4
++
bytes
(
offset
*
4
+
listTag
)
4
++
bytes
(
fieldSizeEnum
elemSize
+
shiftL
elementCount
3
)
4
bytes
(
fieldSizeEnum
elemSize
+
shiftL
elementCount
3
)
4
fieldSizeEnum
Size
0
=
0
fieldSizeEnum
Size
Void
=
0
fieldSizeEnum
Size1
=
1
fieldSizeEnum
(
SizeData
Size1
)
=
1
fieldSizeEnum
Size8
=
2
fieldSizeEnum
(
SizeData
Size8
)
=
2
fieldSizeEnum
Size16
=
3
fieldSizeEnum
(
SizeData
Size16
)
=
3
fieldSizeEnum
Size32
=
4
fieldSizeEnum
(
SizeData
Size32
)
=
4
fieldSizeEnum
Size64
=
5
fieldSizeEnum
(
SizeData
Size64
)
=
5
fieldSizeEnum
SizeReference
=
6
fieldSizeEnum
SizeReference
=
6
fieldSizeEnum
(
SizeInlineComposite
_
_
)
=
7
fieldSizeEnum
(
SizeInlineComposite
_
_
)
=
7
...
@@ -164,47 +157,94 @@ listTag = 1
...
@@ -164,47 +157,94 @@ listTag = 1
-- childOffset = number of words between the last reference and the location where children will
-- childOffset = number of words between the last reference and the location where children will
-- be allocated.
-- be allocated.
encodeStruct
desc
assignments
childOffset
=
(
dataBytes
,
referenceBytes
,
children
)
where
encodeStruct
desc
assignments
childOffset
=
let
-- Values explicitly assigned.
dataSize
=
dataSectionBits
$
structDataSize
desc
explicitValues
=
[(
fieldOffset
f
,
fieldType
f
,
v
,
fieldDefaultValue
f
)
|
(
f
,
v
)
<-
assignments
]
dataSection
=
packBytes
dataSize
$
sortBy
(
compare
`
on
`
fst
)
$
structDataSectionValues
assignments
-- Values of union tags.
unionValues
=
[(
unionTagOffset
u
,
BuiltinType
BuiltinUInt16
,
UInt16Desc
$
fromIntegral
n
,
pointerCount
=
structPointerCount
desc
Nothing
)
(
pointerSection
,
children
)
=
packPointers
pointerCount
(
sortBy
(
compare
`
on
`
fst
)
$
structPointerSectionValues
assignments
)
childOffset
in
(
dataSection
,
pointerSection
,
children
)
dataBitOffset
(
DataOffset
size
off
)
=
dataSizeInBits
size
*
off
dataBitOffset
(
InlineCompositeOffset
off
_
dataSectionSize
_
)
=
off
*
dataSizeInBits
(
dataSectionAlignment
dataSectionSize
)
dataBitOffset
_
=
error
"Not a data field."
structDataSectionValues
assignments
=
let
simpleValues
=
[(
dataBitOffset
$
fieldOffset
f
,
encodeMaskedDataValue
(
fieldType
f
)
v
(
fieldDefaultValue
f
))
|
(
f
@
FieldDesc
{
fieldOffset
=
DataOffset
_
_
},
v
)
<-
assignments
]
inlineStructValues
=
do
-- List monad!
(
FieldDesc
{
fieldOffset
=
InlineCompositeOffset
off
_
sectionSize
_
},
StructValueDesc
v
)
<-
assignments
let
bitOffset
=
off
*
dataSizeInBits
(
dataSectionAlignment
sectionSize
)
(
pos
,
v2
)
<-
structDataSectionValues
v
return
(
pos
+
bitOffset
,
v2
)
unionTags
=
[(
unionTagOffset
u
*
16
,
encodeDataValue
(
BuiltinType
BuiltinUInt16
)
(
UInt16Desc
$
fromIntegral
n
))
|
(
FieldDesc
{
fieldUnion
=
Just
(
u
,
n
)},
_
)
<-
assignments
]
|
(
FieldDesc
{
fieldUnion
=
Just
(
u
,
n
)},
_
)
<-
assignments
]
allValues
=
explicitValues
++
unionValues
in
simpleValues
++
inlineStructValues
++
unionTags
allData
=
[
(
o
*
sizeInBits
(
fieldValueSize
v
),
t
,
v
,
d
)
|
(
o
,
t
,
v
,
d
)
<-
allValues
,
isDataFieldSize
$
fieldValueSize
v
]
allReferences
=
[
(
o
,
t
,
v
)
|
(
o
,
t
,
v
,
_
)
<-
allValues
,
not
$
isDataFieldSize
$
fieldValueSize
v
]
sortedData
=
sortBy
compareDataValues
allData
structPointerSectionValues
::
[(
FieldDesc
,
ValueDesc
)]
->
[(
Integer
,
(
Integer
->
[
Word8
],
[
Word8
]))]
compareDataValues
(
o1
,
_
,
_
,
_
)
(
o2
,
_
,
_
,
_
)
=
compare
o1
o2
structPointerSectionValues
assignments
=
let
s
ortedReferences
=
sortBy
compareReferenceValues
allReferences
s
impleValues
=
[(
off
,
encodePointerValue
(
fieldType
f
)
v
)
compareReferenceValues
(
o1
,
_
,
_
)
(
o2
,
_
,
_
)
=
compare
o1
o2
|
(
f
@
FieldDesc
{
fieldOffset
=
PointerOffset
off
},
v
)
<-
assignments
]
dataBytes
=
encodeData
(
packingDataSize
(
structPacking
desc
)
*
64
)
sortedData
inlineStructValues
=
do
-- List monad!
(
referenceBytes
,
children
)
=
encodeReferences
childOffset
(
FieldDesc
{
fieldOffset
=
InlineCompositeOffset
_
off
_
_
},
(
packingReferenceCount
$
structPacking
desc
)
sortedReferences
StructValueDesc
v
)
<-
assignments
(
pos
,
v2
)
<-
structPointerSectionValues
v
return
(
pos
+
off
,
v2
)
in
simpleValues
++
inlineStructValues
encodeList
elementType
elements
=
case
elementSize
elementType
of
encodeList
elementType
elements
=
case
elementSize
elementType
of
SizeInlineComposite
_
_
->
case
elementType
of
SizeVoid
->
[]
StructType
desc
->
let
SizeInlineComposite
_
_
->
let
handleStructType
desc
=
let
count
=
genericLength
elements
count
=
genericLength
elements
tag
=
encodeStructReference
desc
count
tag
=
encodeStructReference
desc
count
(
elemBytes
,
childBytes
)
=
encodeStructList
0
desc
[
v
|
StructValueDesc
v
<-
elements
]
(
elemBytes
,
childBytes
)
=
encodeStructList
0
desc
[
v
|
StructValueDesc
v
<-
elements
]
in
concat
[
tag
,
elemBytes
,
childBytes
]
in
concat
[
tag
,
elemBytes
,
childBytes
]
in
case
elementType
of
StructType
desc
->
handleStructType
desc
InlineStructType
desc
->
handleStructType
desc
_
->
error
"Only structs can be inline composites."
_
->
error
"Only structs can be inline composites."
SizeReference
->
refBytes
++
childBytes
where
SizeReference
->
refBytes
++
childBytes
where
(
refBytes
,
childBytes
)
=
encodeReferences
0
(
genericLength
elements
)
encodedElements
=
zip
[
0
..
]
$
map
(
encodePointerValue
elementType
)
elements
$
zipWith
(
\
i
v
->
(
i
,
elementType
,
v
))
[
0
..
]
elements
(
refBytes
,
childBytes
)
=
packPointers
(
genericLength
elements
)
encodedElements
0
size
->
encodeData
(
roundUpToMultiple
64
(
genericLength
elements
*
sizeInBits
size
))
SizeData
size
->
let
$
zipWith
(
\
i
v
->
(
i
*
sizeInBits
size
,
elementType
,
v
,
Nothing
))
[
0
..
]
elements
bits
=
dataSizeInBits
size
encodedElements
=
zip
[
0
,
bits
..
]
$
map
(
encodeDataValue
elementType
)
elements
in
padToWord
$
packBytes
(
genericLength
elements
*
bits
)
encodedElements
-- Encode an inline-composite struct list. Not used in cases where the struct is data-only and
-- fits into 32 bits or less.
encodeStructList
::
Integer
->
StructDesc
->
[[(
FieldDesc
,
ValueDesc
)]]
->
([
Word8
],
[
Word8
])
encodeStructList
o
desc
elements
=
loop
(
o
+
eSize
*
genericLength
elements
)
elements
where
eSize
=
dataSectionWordSize
(
structDataSize
desc
)
+
structPointerCount
desc
loop
_
[]
=
(
[]
,
[]
)
loop
offset
(
element
:
rest
)
=
let
offsetFromElementEnd
=
offset
-
eSize
(
dataBytes
,
refBytes
,
childBytes
)
=
encodeStruct
desc
element
offsetFromElementEnd
childLen
=
genericLength
childBytes
childWordLen
=
if
mod
childLen
8
==
0
then
div
childLen
8
else
error
"Child not word-aligned."
(
restBytes
,
restChildren
)
=
loop
(
offsetFromElementEnd
+
childWordLen
)
rest
in
(
padToWord
dataBytes
++
refBytes
++
restBytes
,
childBytes
++
restChildren
)
encodeMessage
(
StructType
desc
)
(
StructValueDesc
assignments
)
=
let
encodeMessage
(
StructType
desc
)
(
StructValueDesc
assignments
)
=
let
(
dataBytes
,
refBytes
,
childBytes
)
=
encodeStruct
desc
assignments
0
(
dataBytes
,
refBytes
,
childBytes
)
=
encodeStruct
desc
assignments
0
in
concat
[
encodeStructReference
desc
(
0
::
Integer
),
dataBytes
,
refBytes
,
childBytes
]
in
concat
[
encodeStructReference
desc
(
0
::
Integer
),
padToWord
dataBytes
,
refBytes
,
childBytes
]
encodeMessage
(
InlineStructType
desc
)
val
=
encodeMessage
(
StructType
desc
)
val
encodeMessage
(
ListType
elementType
)
(
ListDesc
elements
)
=
encodeMessage
(
ListType
elementType
)
(
ListDesc
elements
)
=
encodeListReference
(
elementSize
elementType
)
(
genericLength
elements
)
(
0
::
Integer
)
++
encodeListReference
(
elementSize
elementType
)
(
genericLength
elements
)
(
0
::
Integer
)
++
encodeList
elementType
elements
encodeList
elementType
elements
...
...
compiler/src/c++-header.mustache
View file @
7f20d533
...
@@ -295,6 +295,7 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(
...
@@ -295,6 +295,7 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(
{{/
fieldIsBlob
}}
{{/
fieldIsBlob
}}
{{! ------------------------------------------------------------------------------------------- }}
{{! ------------------------------------------------------------------------------------------- }}
{{#
fieldIsStruct
}}
{{#
fieldIsStruct
}}
{{^
fieldIsInlineStruct
}}
inline
{{
fieldType
}}
::Reader
{{
typeFullName
}}
::Reader::get
{{
fieldTitleCase
}}
() {
inline
{{
fieldType
}}
::Reader
{{
typeFullName
}}
::Reader::get
{{
fieldTitleCase
}}
() {
{{#
fieldUnion
}}
{{#
fieldUnion
}}
CAPNPROTO_INLINE_DPRECOND(which() ==
{{
unionTitleCase
}}
::
{{
fieldUpperCase
}}
,
CAPNPROTO_INLINE_DPRECOND(which() ==
{{
unionTitleCase
}}
::
{{
fieldUpperCase
}}
,
...
@@ -324,6 +325,34 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}()
...
@@ -324,6 +325,34 @@ inline {{fieldType}}::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}()
{{#
fieldDefaultBytes
}}
DEFAULT_
{{
fieldUpperCase
}}
.words
{{/
fieldDefaultBytes
}}
{{#
fieldDefaultBytes
}}
DEFAULT_
{{
fieldUpperCase
}}
.words
{{/
fieldDefaultBytes
}}
{{^
fieldDefaultBytes
}}
nullptr
{{/
fieldDefaultBytes
}}
));
{{^
fieldDefaultBytes
}}
nullptr
{{/
fieldDefaultBytes
}}
));
}
}
{{/
fieldIsInlineStruct
}}
{{#
fieldIsInlineStruct
}}
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.getInlineStructField(
{{
fieldOffset
}}
));
}
inline
{{
fieldType
}}
::Builder
{{
typeFullName
}}
::Builder::init
{{
fieldTitleCase
}}
() {
{{#
fieldUnion
}}
_builder.setDataField
<
{{
unionTitleCase
}}
::Which>
(
{{
unionTagOffset
}}
* ::capnproto::ELEMENTS,
{{
unionTitleCase
}}
::
{{
fieldUpperCase
}}
);
{{/
fieldUnion
}}
return
{{
fieldType
}}
::Builder(_builder.initInlineStructField(
{{
fieldOffset
}}
));
}
inline
{{
fieldType
}}
::Builder
{{
typeFullName
}}
::Builder::get
{{
fieldTitleCase
}}
() {
{{#
fieldUnion
}}
CAPNPROTO_INLINE_DPRECOND(which() ==
{{
unionTitleCase
}}
::
{{
fieldUpperCase
}}
,
"Must check which() before get()ing a union member.");
{{/
fieldUnion
}}
return
{{
fieldType
}}
::Builder(_builder.getInlineStructField(
{{
fieldOffset
}}
));
}
{{/
fieldIsInlineStruct
}}
{{/
fieldIsStruct
}}
{{/
fieldIsStruct
}}
{{! ------------------------------------------------------------------------------------------- }}
{{! ------------------------------------------------------------------------------------------- }}
{{#
fieldIsList
}}
{{#
fieldIsList
}}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment