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
b92a28a6
Commit
b92a28a6
authored
Jul 30, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Compiler nearing completion. Mostly just needs a driver.
parent
34e70d5a
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
390 additions
and
207 deletions
+390
-207
capnpc2.c++
c++/src/capnp/compiler/capnpc2.c++
+47
-14
compiler.c++
c++/src/capnp/compiler/compiler.c++
+100
-29
compiler.h
c++/src/capnp/compiler/compiler.h
+6
-3
node-translator.c++
c++/src/capnp/compiler/node-translator.c++
+224
-152
node-translator.h
c++/src/capnp/compiler/node-translator.h
+11
-7
layout.c++
c++/src/capnp/layout.c++
+1
-1
common.h
c++/src/kj/common.h
+1
-1
No files found.
c++/src/capnp/compiler/capnpc2.c++
View file @
b92a28a6
...
...
@@ -23,6 +23,7 @@
#include "lexer.h"
#include "parser.h"
#include "compiler.h"
#include <capnp/pretty-print.h>
#include <kj/vector.h>
#include <kj/io.h>
...
...
@@ -31,8 +32,22 @@
#include "../message.h"
#include <iostream>
class
CerrErrorReporter
:
public
capnp
::
compiler
::
ErrorReporter
{
class
DummyModule
:
public
capnp
::
compiler
::
Module
{
public
:
capnp
::
compiler
::
ParsedFile
::
Reader
content
;
kj
::
StringPtr
getLocalName
()
const
{
return
"(stdin)"
;
}
kj
::
StringPtr
getSourceName
()
const
{
return
"(stdin)"
;
}
capnp
::
Orphan
<
capnp
::
compiler
::
ParsedFile
>
loadContent
(
capnp
::
Orphanage
orphanage
)
const
{
return
orphanage
.
newOrphanCopy
(
content
);
}
kj
::
Maybe
<
const
Module
&>
importRelative
(
kj
::
StringPtr
importPath
)
const
{
return
nullptr
;
}
void
addError
(
uint32_t
startByte
,
uint32_t
endByte
,
kj
::
StringPtr
message
)
const
override
{
std
::
cerr
<<
"input:"
<<
startByte
<<
"-"
<<
endByte
<<
": "
<<
message
.
cStr
()
<<
std
::
endl
;
}
...
...
@@ -41,18 +56,23 @@ public:
int
main
(
int
argc
,
char
*
argv
[])
{
// Eventually this will be capnpc. For now it's just a dummy program that tests parsing.
kj
::
Vector
<
char
>
input
;
char
buffer
[
4096
];
for
(;;)
{
ssize_t
n
;
KJ_SYSCALL
(
n
=
read
(
STDIN_FILENO
,
buffer
,
sizeof
(
buffer
)));
if
(
n
==
0
)
{
break
;
}
input
.
addAll
(
buffer
,
buffer
+
n
);
}
// kj::Vector<char> input;
// char buffer[4096];
// for (;;) {
// ssize_t n;
// KJ_SYSCALL(n = read(STDIN_FILENO, buffer, sizeof(buffer)));
// if (n == 0) {
// break;
// }
// input.addAll(buffer, buffer + n);
// }
kj
::
StringPtr
input
=
"@0x8e001c75f6ff54c8;
\n
"
"struct Foo { bar @0 :Int32 = 123; baz @1 :Text; }
\n
"
"struct Qux { foo @0 :List(Int32) = [12, 34]; }"
;
CerrErrorReporter
errorReporter
;
DummyModule
module
;
std
::
cout
<<
"=========================================================================
\n
"
<<
"lex
\n
"
...
...
@@ -61,7 +81,7 @@ int main(int argc, char* argv[]) {
capnp
::
MallocMessageBuilder
lexerArena
;
auto
lexedFile
=
lexerArena
.
initRoot
<
capnp
::
compiler
::
LexedStatements
>
();
capnp
::
compiler
::
lex
(
input
,
lexedFile
,
errorReporter
);
capnp
::
compiler
::
lex
(
input
,
lexedFile
,
module
);
std
::
cout
<<
capnp
::
prettyPrint
(
lexedFile
).
cStr
()
<<
std
::
endl
;
std
::
cout
<<
"=========================================================================
\n
"
...
...
@@ -71,8 +91,21 @@ int main(int argc, char* argv[]) {
capnp
::
MallocMessageBuilder
parserArena
;
auto
parsedFile
=
parserArena
.
initRoot
<
capnp
::
compiler
::
ParsedFile
>
();
capnp
::
compiler
::
parseFile
(
lexedFile
.
getStatements
(),
parsedFile
,
errorReporter
);
capnp
::
compiler
::
parseFile
(
lexedFile
.
getStatements
(),
parsedFile
,
module
);
std
::
cout
<<
capnp
::
prettyPrint
(
parsedFile
).
cStr
()
<<
std
::
endl
;
std
::
cout
<<
"=========================================================================
\n
"
<<
"compile
\n
"
<<
"========================================================================="
<<
std
::
endl
;
module
.
content
=
parsedFile
.
asReader
();
capnp
::
compiler
::
Compiler
compiler
;
compiler
.
add
(
module
,
capnp
::
compiler
::
Compiler
::
EAGER
);
for
(
auto
schema
:
compiler
.
getLoader
().
getAllLoaded
())
{
std
::
cout
<<
capnp
::
prettyPrint
(
schema
.
getProto
()).
cStr
()
<<
std
::
endl
;
}
return
0
;
}
c++/src/capnp/compiler/compiler.c++
View file @
b92a28a6
...
...
@@ -68,8 +68,8 @@ public:
Node
(
kj
::
StringPtr
name
,
Declaration
::
Body
::
Which
kind
);
// Create a dummy node representing a built-in declaration, like "Int32" or "true".
uint64_t
getId
()
{
return
id
;
}
Declaration
::
Body
::
Which
getKind
()
{
return
kind
;
}
uint64_t
getId
()
const
{
return
id
;
}
Declaration
::
Body
::
Which
getKind
()
const
{
return
kind
;
}
kj
::
Maybe
<
const
Node
&>
lookupMember
(
kj
::
StringPtr
name
)
const
;
// Find a direct member of this node with the given name.
...
...
@@ -81,16 +81,20 @@ public:
kj
::
Maybe
<
const
Node
&>
lookup
(
const
DeclName
::
Reader
&
name
)
const
;
// Resolve an arbitrary DeclName to a Node.
Schema
getBootstrapOrFinalSchema
()
const
;
Schema
getFinalSchema
()
const
;
kj
::
Maybe
<
Schema
>
getBootstrapOrFinalSchema
()
const
;
kj
::
Maybe
<
Schema
>
getFinalSchema
()
const
;
void
traverse
(
Compiler
::
Mode
mode
)
const
;
// Get the final schema for this node, and also possibly traverse the node's children and
// dependencies to ensure that they are loaded, depending on the mode.
void
addError
(
kj
::
StringPtr
error
)
const
;
// Report an error on this Node.
// implements NodeTranslator::Resolver -----------------------------
kj
::
Maybe
<
ResolvedName
>
resolve
(
const
DeclName
::
Reader
&
name
)
const
override
;
Schema
resolveMaybeBootstrapSchema
(
uint64_t
id
)
const
override
;
Schema
resolveFinalSchema
(
uint64_t
id
)
const
override
;
kj
::
Maybe
<
Schema
>
resolveMaybeBootstrapSchema
(
uint64_t
id
)
const
override
;
kj
::
Maybe
<
Schema
>
resolveFinalSchema
(
uint64_t
id
)
const
override
;
private
:
const
CompiledModule
*
module
;
// null iff isBuiltin is true
...
...
@@ -153,13 +157,14 @@ private:
NodeTranslator
*
translator
;
// Node translator, allocated in the bootstrap arena.
Schema
bootstrapSchema
;
// The schema built in the bootstrap loader.
kj
::
Maybe
<
Schema
>
bootstrapSchema
;
// The schema built in the bootstrap loader.
Null if the bootstrap loader threw an exception.
// FINISHED ------------------------------------
Schema
finalSchema
;
// The complete schema as loaded by the compiler's main SchemaLoader.
kj
::
Maybe
<
Schema
>
finalSchema
;
// The complete schema as loaded by the compiler's main SchemaLoader. Null if the final
// loader threw an exception.
};
kj
::
MutexGuarded
<
Content
>
content
;
...
...
@@ -188,7 +193,7 @@ public:
const
Compiler
::
Impl
&
getCompiler
()
const
{
return
compiler
;
}
const
ErrorReporter
&
getErrorReporter
()
const
{
return
parserModule
;
}
const
ParsedFile
::
Reader
&
getParsedFile
()
const
{
return
content
;
}
ParsedFile
::
Reader
getParsedFile
()
const
{
return
content
.
getReader
()
;
}
const
Node
&
getRootNode
()
const
{
return
rootNode
;
}
kj
::
StringPtr
getSourceName
()
const
{
return
parserModule
.
getSourceName
();
}
...
...
@@ -198,14 +203,16 @@ private:
const
Compiler
::
Impl
&
compiler
;
const
Module
&
parserModule
;
MallocMessageBuilder
contentArena
;
ParsedFile
::
Reader
content
;
Orphan
<
ParsedFile
>
content
;
Node
rootNode
;
};
class
Compiler
::
Impl
:
public
SchemaLoader
::
LazyLoadCallback
{
public
:
Impl
();
virtual
~
Impl
();
uint64_t
add
(
Module
&
module
,
Mode
mode
)
const
;
const
CompiledModule
&
add
(
const
Module
&
parsedModule
)
const
;
struct
Workspace
{
...
...
@@ -214,18 +221,23 @@ public:
// compiler. Note that since nodes are compiled lazily, a new Workspace may have to be
// constructed in order to compile more nodes later.
kj
::
Arena
arena
;
// Arena for allocating temporary native objects.
MallocMessageBuilder
message
;
Orphanage
orphanage
;
// Orphanage for allocating temporary Cap'n Proto objects.
kj
::
Arena
arena
;
// Arena for allocating temporary native objects. Note that objects in `arena` may contain
// pointers into `message` that will be manipulated on destruction, so `arena` must be declared
// after `message`.
SchemaLoader
bootstrapLoader
;
// Loader used to load bootstrap schemas. The bootstrap schema nodes are similar to the final
// versions except that any value expressions which depend on knowledge of other types (e.g.
// default values for struct fields) are left unevaluated (the values in the schema are empty).
// These bootstrap schemas can then be plugged into the dynamic API and used to evaluate these
// remaining values.
inline
Workspace
()
:
orphanage
(
message
.
getOrphanage
())
{}
};
const
kj
::
Arena
&
getNodeArena
()
const
{
return
nodeArena
;
}
...
...
@@ -261,10 +273,7 @@ private:
// the pointer to point at said stack workspace. The rest of the compiler can assume that this
// Workspace is active.
uint
workspaceRefcount
=
0
;
// Count of threads that have entered the compiler.
typedef
std
::
unordered_map
<
Module
*
,
kj
::
Own
<
CompiledModule
>>
ModuleMap
;
typedef
std
::
unordered_map
<
const
Module
*
,
kj
::
Own
<
CompiledModule
>>
ModuleMap
;
kj
::
MutexGuarded
<
ModuleMap
>
modules
;
// Map of parser modules to compiler modules.
...
...
@@ -377,7 +386,7 @@ kj::StringPtr Compiler::Node::joinDisplayName(
result
[
separatorPos
]
=
parent
.
parent
==
nullptr
?
':'
:
'.'
;
memcpy
(
result
.
begin
()
+
separatorPos
+
1
,
declName
.
begin
(),
declName
.
size
());
result
[
result
.
size
()
-
1
]
=
'\0'
;
return
kj
::
StringPtr
(
declName
.
begin
(),
declName
.
size
()
-
1
);
return
kj
::
StringPtr
(
result
.
begin
(),
result
.
size
()
-
1
);
}
const
Compiler
::
Node
::
Content
&
Compiler
::
Node
::
getContent
(
Content
::
State
minimumState
)
const
{
...
...
@@ -459,8 +468,14 @@ const Compiler::Node::Content& Compiler::Node::getContent(Content::State minimum
locked
->
translator
=
&
workspace
.
arena
.
allocate
<
NodeTranslator
>
(
*
this
,
module
->
getErrorReporter
(),
declaration
,
kj
::
mv
(
schemaNode
));
locked
->
bootstrapSchema
=
workspace
.
bootstrapLoader
.
loadOnce
(
locked
->
translator
->
getBootstrapNode
());
KJ_IF_MAYBE
(
exception
,
kj
::
runCatchingExceptions
([
&
](){
locked
->
bootstrapSchema
=
workspace
.
bootstrapLoader
.
loadOnce
(
locked
->
translator
->
getBootstrapNode
());
}))
{
locked
->
bootstrapSchema
=
nullptr
;
addError
(
kj
::
str
(
"Internal compiler bug: Bootstrap schema failed validation: "
,
exception
->
getDescription
()));
}
// If the Workspace is destroyed while this Node is still in the BOOTSTRAP state,
// revert it to the EXPANDED state, because the NodeTranslator is no longer valid in this
...
...
@@ -480,8 +495,14 @@ const Compiler::Node::Content& Compiler::Node::getContent(Content::State minimum
if
(
minimumState
<=
Content
::
BOOTSTRAP
)
break
;
// Create the final schema.
locked
->
finalSchema
=
module
->
getCompiler
().
getFinalLoader
().
loadOnce
(
locked
->
translator
->
finish
());
KJ_IF_MAYBE
(
exception
,
kj
::
runCatchingExceptions
([
&
](){
locked
->
finalSchema
=
module
->
getCompiler
().
getFinalLoader
().
loadOnce
(
locked
->
translator
->
finish
());
}))
{
locked
->
finalSchema
=
nullptr
;
addError
(
kj
::
str
(
"Internal compiler bug: Schema failed validation: "
,
exception
->
getDescription
()));
}
locked
->
advanceState
(
Content
::
FINISHED
);
// no break
...
...
@@ -584,19 +605,30 @@ kj::Maybe<const Compiler::Node&> Compiler::Node::lookup(const DeclName::Reader&
return
*
node
;
}
Schema
Compiler
::
Node
::
getBootstrapOrFinalSchema
()
const
{
kj
::
Maybe
<
Schema
>
Compiler
::
Node
::
getBootstrapOrFinalSchema
()
const
{
auto
&
content
=
getContent
(
Content
::
BOOTSTRAP
);
if
(
__atomic_load_n
(
&
content
.
state
,
__ATOMIC_ACQUIRE
)
==
Content
::
FINISHED
)
{
if
(
__atomic_load_n
(
&
content
.
state
,
__ATOMIC_ACQUIRE
)
==
Content
::
FINISHED
&&
content
.
finalSchema
!=
nullptr
)
{
return
content
.
finalSchema
;
}
else
{
return
content
.
bootstrapSchema
;
}
}
Schema
Compiler
::
Node
::
getFinalSchema
()
const
{
kj
::
Maybe
<
Schema
>
Compiler
::
Node
::
getFinalSchema
()
const
{
return
getContent
(
Content
::
FINISHED
).
finalSchema
;
}
void
Compiler
::
Node
::
traverse
(
Compiler
::
Mode
mode
)
const
{
getFinalSchema
();
if
(
mode
==
EAGER
)
{
for
(
auto
&
child
:
getContent
(
Content
::
EXPANDED
).
nestedNodes
)
{
child
.
second
->
traverse
(
mode
);
}
}
}
void
Compiler
::
Node
::
addError
(
kj
::
StringPtr
error
)
const
{
module
->
getErrorReporter
().
addError
(
startByte
,
endByte
,
error
);
}
...
...
@@ -608,7 +640,7 @@ kj::Maybe<NodeTranslator::Resolver::ResolvedName> Compiler::Node::resolve(
});
}
Schema
Compiler
::
Node
::
resolveMaybeBootstrapSchema
(
uint64_t
id
)
const
{
kj
::
Maybe
<
Schema
>
Compiler
::
Node
::
resolveMaybeBootstrapSchema
(
uint64_t
id
)
const
{
KJ_IF_MAYBE
(
node
,
module
->
getCompiler
().
findNode
(
id
))
{
return
node
->
getBootstrapOrFinalSchema
();
}
else
{
...
...
@@ -616,7 +648,7 @@ Schema Compiler::Node::resolveMaybeBootstrapSchema(uint64_t id) const {
}
}
Schema
Compiler
::
Node
::
resolveFinalSchema
(
uint64_t
id
)
const
{
kj
::
Maybe
<
Schema
>
Compiler
::
Node
::
resolveFinalSchema
(
uint64_t
id
)
const
{
KJ_IF_MAYBE
(
node
,
module
->
getCompiler
().
findNode
(
id
))
{
return
node
->
getFinalSchema
();
}
else
{
...
...
@@ -657,6 +689,19 @@ Compiler::Impl::Impl(): finalLoader(*this), workspace(nullptr) {
}
}
Compiler
::
Impl
::~
Impl
()
{}
const
Compiler
::
CompiledModule
&
Compiler
::
Impl
::
add
(
const
Module
&
parsedModule
)
const
{
auto
locked
=
modules
.
lockExclusive
();
kj
::
Own
<
CompiledModule
>&
slot
=
(
*
locked
)[
&
parsedModule
];
if
(
slot
.
get
()
==
nullptr
)
{
slot
=
kj
::
heap
<
CompiledModule
>
(
*
this
,
parsedModule
);
}
return
*
slot
;
}
uint64_t
Compiler
::
Impl
::
addNode
(
uint64_t
desiredId
,
Node
&
node
)
const
{
auto
lock
=
nodesById
.
lockExclusive
();
for
(;;)
{
...
...
@@ -698,6 +743,19 @@ kj::Maybe<const Compiler::Node&> Compiler::Impl::lookupBuiltin(kj::StringPtr nam
}
}
uint64_t
Compiler
::
Impl
::
add
(
Module
&
module
,
Mode
mode
)
const
{
Impl
::
Workspace
workspace
;
auto
lock
=
this
->
workspace
.
lockExclusive
();
*
lock
=
&
workspace
;
KJ_DEFER
(
*
lock
=
nullptr
);
auto
&
node
=
add
(
module
).
getRootNode
();
if
(
mode
!=
LAZY
)
{
node
.
traverse
(
mode
);
}
return
node
.
getId
();
}
void
Compiler
::
Impl
::
load
(
const
SchemaLoader
&
loader
,
uint64_t
id
)
const
{
KJ_IF_MAYBE
(
node
,
findNode
(
id
))
{
if
(
&
loader
==
&
finalLoader
)
{
...
...
@@ -713,5 +771,18 @@ void Compiler::Impl::load(const SchemaLoader& loader, uint64_t id) const {
}
}
// =======================================================================================
Compiler
::
Compiler
()
:
impl
(
kj
::
heap
<
Impl
>
())
{}
Compiler
::~
Compiler
()
{}
uint64_t
Compiler
::
add
(
Module
&
module
,
Mode
mode
)
const
{
return
impl
->
add
(
module
,
mode
);
}
const
SchemaLoader
&
Compiler
::
getLoader
()
const
{
return
impl
->
getFinalLoader
();
}
}
// namespace compiler
}
// namespace capnp
c++/src/capnp/compiler/compiler.h
View file @
b92a28a6
...
...
@@ -55,7 +55,7 @@ class Compiler {
// Cross-links separate modules (schema files) and translates them into schema nodes.
public
:
explicit
Compiler
();
Compiler
();
~
Compiler
();
KJ_DISALLOW_COPY
(
Compiler
);
...
...
@@ -76,8 +76,11 @@ public:
// use EAGER mode.
};
Schema
add
(
Module
&
module
,
Mode
mode
)
const
;
// Add a module to the Compiler, returning its root Schema object.
uint64_t
add
(
Module
&
module
,
Mode
mode
)
const
;
// Add a module to the Compiler, returning the module's file ID. The ID can then be used to
// look up the schema in the SchemaLoader returned by `getLoader()`. However, if there were any
// errors while compiling (reported via `module.addError()`), then the SchemaLoader may behave as
// if the node doesn't exist, or may return an invalid partial Schema.
const
SchemaLoader
&
getLoader
()
const
;
// Get a SchemaLoader backed by this compiler. Schema nodes will be lazily constructed as you
...
...
c++/src/capnp/compiler/node-translator.c++
View file @
b92a28a6
...
...
@@ -74,7 +74,9 @@ public:
// remove it from the holes, and return its offset (as a multiple of its size). If there
// is no such space, returns zero (no hole can be at offset zero, as explained above).
if
(
holes
[
lgSize
]
!=
0
)
{
if
(
lgSize
>=
KJ_ARRAY_SIZE
(
holes
))
{
return
nullptr
;
}
else
if
(
holes
[
lgSize
]
!=
0
)
{
UIntType
result
=
holes
[
lgSize
];
holes
[
lgSize
]
=
0
;
return
result
;
...
...
@@ -549,7 +551,7 @@ public:
}
};
Top
&
getTop
()
;
Top
&
getTop
()
{
return
top
;
}
private
:
Top
top
;
...
...
@@ -835,7 +837,7 @@ public:
schema
::
StructNode
::
Builder
builder
)
{
// Build the member-info-by-ordinal map.
MemberInfo
root
(
layout
.
getTop
());
traverseGroup
(
members
,
root
);
traverse
TopOr
Group
(
members
,
root
);
// Init the root.
root
.
memberSchemas
=
builder
.
initMembers
(
root
.
childCount
);
...
...
@@ -872,40 +874,42 @@ public:
translator
.
compileDefaultDefaultValue
(
typeBuilder
,
fieldBuilder
.
initDefaultValue
());
break
;
}
}
else
{
translator
.
compileDefaultDefaultValue
(
typeBuilder
,
fieldBuilder
.
initDefaultValue
());
}
int
lgSize
=
-
1
;
switch
(
typeBuilder
.
getBody
().
which
())
{
case
schema
:
:
Type
::
Body
::
VOID_TYPE
:
lgSize
=
-
1
;
break
;
case
schema
:
:
Type
::
Body
::
BOOL_TYPE
:
lgSize
=
0
;
break
;
case
schema
:
:
Type
::
Body
::
INT8_TYPE
:
lgSize
=
3
;
break
;
case
schema
:
:
Type
::
Body
::
INT16_TYPE
:
lgSize
=
4
;
break
;
case
schema
:
:
Type
::
Body
::
INT32_TYPE
:
lgSize
=
5
;
break
;
case
schema
:
:
Type
::
Body
::
INT64_TYPE
:
lgSize
=
6
;
break
;
case
schema
:
:
Type
::
Body
::
UINT8_TYPE
:
lgSize
=
3
;
break
;
case
schema
:
:
Type
::
Body
::
UINT16_TYPE
:
lgSize
=
4
;
break
;
case
schema
:
:
Type
::
Body
::
UINT32_TYPE
:
lgSize
=
5
;
break
;
case
schema
:
:
Type
::
Body
::
UINT64_TYPE
:
lgSize
=
6
;
break
;
case
schema
:
:
Type
::
Body
::
FLOAT32_TYPE
:
lgSize
=
5
;
break
;
case
schema
:
:
Type
::
Body
::
FLOAT64_TYPE
:
lgSize
=
6
;
break
;
case
schema
:
:
Type
::
Body
::
TEXT_TYPE
:
lgSize
=
-
2
;
break
;
case
schema
:
:
Type
::
Body
::
DATA_TYPE
:
lgSize
=
-
2
;
break
;
case
schema
:
:
Type
::
Body
::
LIST_TYPE
:
lgSize
=
-
2
;
break
;
case
schema
:
:
Type
::
Body
::
ENUM_TYPE
:
lgSize
=
4
;
break
;
case
schema
:
:
Type
::
Body
::
STRUCT_TYPE
:
lgSize
=
-
2
;
break
;
case
schema
:
:
Type
::
Body
::
INTERFACE_TYPE
:
lgSize
=
-
2
;
break
;
case
schema
:
:
Type
::
Body
::
OBJECT_TYPE
:
lgSize
=
-
2
;
break
;
}
int
lgSize
=
-
1
;
switch
(
typeBuilder
.
getBody
().
which
())
{
case
schema
:
:
Type
::
Body
::
VOID_TYPE
:
lgSize
=
-
1
;
break
;
case
schema
:
:
Type
::
Body
::
BOOL_TYPE
:
lgSize
=
0
;
break
;
case
schema
:
:
Type
::
Body
::
INT8_TYPE
:
lgSize
=
3
;
break
;
case
schema
:
:
Type
::
Body
::
INT16_TYPE
:
lgSize
=
4
;
break
;
case
schema
:
:
Type
::
Body
::
INT32_TYPE
:
lgSize
=
5
;
break
;
case
schema
:
:
Type
::
Body
::
INT64_TYPE
:
lgSize
=
6
;
break
;
case
schema
:
:
Type
::
Body
::
UINT8_TYPE
:
lgSize
=
3
;
break
;
case
schema
:
:
Type
::
Body
::
UINT16_TYPE
:
lgSize
=
4
;
break
;
case
schema
:
:
Type
::
Body
::
UINT32_TYPE
:
lgSize
=
5
;
break
;
case
schema
:
:
Type
::
Body
::
UINT64_TYPE
:
lgSize
=
6
;
break
;
case
schema
:
:
Type
::
Body
::
FLOAT32_TYPE
:
lgSize
=
5
;
break
;
case
schema
:
:
Type
::
Body
::
FLOAT64_TYPE
:
lgSize
=
6
;
break
;
case
schema
:
:
Type
::
Body
::
TEXT_TYPE
:
lgSize
=
-
2
;
break
;
case
schema
:
:
Type
::
Body
::
DATA_TYPE
:
lgSize
=
-
2
;
break
;
case
schema
:
:
Type
::
Body
::
LIST_TYPE
:
lgSize
=
-
2
;
break
;
case
schema
:
:
Type
::
Body
::
ENUM_TYPE
:
lgSize
=
4
;
break
;
case
schema
:
:
Type
::
Body
::
STRUCT_TYPE
:
lgSize
=
-
2
;
break
;
case
schema
:
:
Type
::
Body
::
INTERFACE_TYPE
:
lgSize
=
-
2
;
break
;
case
schema
:
:
Type
::
Body
::
OBJECT_TYPE
:
lgSize
=
-
2
;
break
;
}
if
(
lgSize
==
-
2
)
{
// pointer
fieldBuilder
.
setOffset
(
member
.
fieldScope
->
addPointer
());
}
else
if
(
lgSize
==
-
1
)
{
// void
fieldBuilder
.
setOffset
(
0
);
}
else
{
fieldBuilder
.
setOffset
(
member
.
fieldScope
->
addData
(
lgSize
));
}
if
(
lgSize
==
-
2
)
{
// pointer
fieldBuilder
.
setOffset
(
member
.
fieldScope
->
addPointer
());
}
else
if
(
lgSize
==
-
1
)
{
// void
fieldBuilder
.
setOffset
(
0
);
}
else
{
fieldBuilder
.
setOffset
(
member
.
fieldScope
->
addData
(
lgSize
));
}
targetsFlagName
=
"targetsField"
;
...
...
@@ -1107,13 +1111,17 @@ private:
}
uint
traverseGroup
(
List
<
Declaration
>::
Reader
members
,
MemberInfo
&
parent
)
{
uint
minOrdinal
=
std
::
numeric_limits
<
uint
>::
max
();
uint
codeOrder
=
0
;
if
(
members
.
size
()
<
2
)
{
errorReporter
.
addErrorOn
(
parent
.
decl
,
"Group must have at least two members."
);
}
return
traverseTopOrGroup
(
members
,
parent
);
}
uint
traverseTopOrGroup
(
List
<
Declaration
>::
Reader
members
,
MemberInfo
&
parent
)
{
uint
minOrdinal
=
std
::
numeric_limits
<
uint
>::
max
();
uint
codeOrder
=
0
;
for
(
auto
member
:
members
)
{
uint
ordinal
=
0
;
MemberInfo
*
memberInfo
=
nullptr
;
...
...
@@ -1122,6 +1130,7 @@ private:
case
Declaration
:
:
Body
::
FIELD_DECL
:
{
memberInfo
=
&
arena
.
allocate
<
MemberInfo
>
(
parent
,
codeOrder
++
,
member
,
*
parent
.
fieldScope
);
ordinal
=
member
.
getId
().
getOrdinal
().
getValue
();
break
;
}
...
...
@@ -1258,13 +1267,14 @@ bool NodeTranslator::compileType(TypeExpression::Reader source, schema::Type::Bu
if
(
source
.
getParams
().
size
()
!=
0
)
{
errorReporter
.
addErrorOn
(
source
,
kj
::
str
(
"'"
,
declNameString
(
name
),
"' does not accept parameters."
));
return
false
;
}
return
false
;
}
return
true
;
}
else
{
target
.
getBody
().
setVoidType
();
return
false
;
}
}
...
...
@@ -1305,63 +1315,59 @@ public:
:
type
(
FIELD
),
structBuilder
(
structBuilder
),
member
(
member
)
{}
DynamicSlot
(
DynamicList
::
Builder
listBuilder
,
uint
index
)
:
type
(
ELEMENT
),
listBuilder
(
listBuilder
),
index
(
index
)
{}
DynamicSlot
(
DynamicStruct
::
Builder
structBuilder
,
StructSchema
::
Member
member
,
DynamicSlot
(
DynamicUnion
::
Builder
unionBuilder
,
StructSchema
::
Member
unionMember
)
:
type
(
UNION_MEMBER
),
unionBuilder
(
unionBuilder
),
unionMember
(
unionMember
)
{}
DynamicSlot
(
DynamicUnion
::
Builder
unionBuilder
,
StructSchema
::
Member
unionMember
,
StructSchema
structMemberSchema
)
:
type
(
STRUCT_OBJECT_
FIELD
),
structBuilder
(
structBuilder
),
member
(
m
ember
),
:
type
(
STRUCT_OBJECT_
UNION_MEMBER
),
unionBuilder
(
unionBuilder
),
unionMember
(
unionM
ember
),
structMemberSchema
(
structMemberSchema
)
{}
DynamicSlot
(
Dynamic
Struct
::
Builder
structBuilder
,
StructSchema
::
Member
m
ember
,
DynamicSlot
(
Dynamic
Union
::
Builder
unionBuilder
,
StructSchema
::
Member
unionM
ember
,
ListSchema
listMemberSchema
)
:
type
(
LIST_OBJECT_
FIELD
),
structBuilder
(
structBuilder
),
member
(
m
ember
),
:
type
(
LIST_OBJECT_
UNION_MEMBER
),
unionBuilder
(
unionBuilder
),
unionMember
(
unionM
ember
),
listMemberSchema
(
listMemberSchema
)
{}
DynamicSlot
(
DynamicUnion
::
Builder
unionBuilder
,
StructSchema
::
Member
unionMember
)
:
type
(
UNION_MEMBER
),
unionBuilder
(
unionBuilder
),
unionMember
(
unionMember
)
{}
bool
wasSet
=
false
;
DynamicStruct
::
Builder
initStruct
()
{
wasSet
=
true
;
switch
(
type
)
{
case
FIELD
:
return
structBuilder
.
init
(
member
).
as
<
DynamicStruct
>
();
case
ELEMENT
:
return
listBuilder
[
index
].
as
<
DynamicStruct
>
();
case
STRUCT_OBJECT_FIELD
:
return
structBuilder
.
initObject
(
member
,
structMemberSchema
);
case
LIST_OBJECT_FIELD
:
KJ_FAIL_REQUIRE
(
"Value type mismatch."
);
case
UNION_MEMBER
:
return
unionBuilder
.
init
(
unionMember
).
as
<
DynamicStruct
>
();
case
STRUCT_OBJECT_UNION_MEMBER
:
return
unionBuilder
.
initObject
(
unionMember
,
structMemberSchema
);
case
LIST_OBJECT_UNION_MEMBER
:
KJ_FAIL_REQUIRE
(
"Type mismatch."
);
}
KJ_FAIL_ASSERT
(
"can't get here"
);
}
DynamicList
::
Builder
initList
(
uint
size
)
{
wasSet
=
true
;
switch
(
type
)
{
case
FIELD
:
return
structBuilder
.
init
(
member
,
size
).
as
<
DynamicList
>
();
case
ELEMENT
:
return
listBuilder
.
init
(
index
,
size
).
as
<
DynamicList
>
();
case
STRUCT_OBJECT_FIELD
:
KJ_FAIL_REQUIRE
(
"Value type mismatch."
);
case
LIST_OBJECT_FIELD
:
return
structBuilder
.
initObject
(
member
,
listMemberSchema
,
size
);
case
UNION_MEMBER
:
return
unionBuilder
.
init
(
unionMember
,
size
).
as
<
DynamicList
>
();
case
STRUCT_OBJECT_UNION_MEMBER
:
KJ_FAIL_REQUIRE
(
"Type mismatch."
);
case
LIST_OBJECT_UNION_MEMBER
:
return
unionBuilder
.
initObject
(
unionMember
,
listMemberSchema
,
size
);
}
KJ_FAIL_ASSERT
(
"can't get here"
);
}
DynamicUnion
::
Builder
getUnion
()
{
wasSet
=
true
;
switch
(
type
)
{
case
FIELD
:
return
structBuilder
.
get
(
member
).
as
<
DynamicUnion
>
();
case
ELEMENT
:
KJ_FAIL_REQUIRE
(
"Value type mismatch."
);
case
STRUCT_OBJECT_FIELD
:
KJ_FAIL_REQUIRE
(
"Value type mismatch."
);
case
LIST_OBJECT_FIELD
:
KJ_FAIL_REQUIRE
(
"Value type mismatch."
);
case
ELEMENT
:
KJ_FAIL_REQUIRE
(
"Type mismatch."
);
case
UNION_MEMBER
:
return
unionBuilder
.
init
(
unionMember
).
as
<
DynamicUnion
>
();
case
STRUCT_OBJECT_UNION_MEMBER
:
KJ_FAIL_REQUIRE
(
"Type mismatch."
);
case
LIST_OBJECT_UNION_MEMBER
:
KJ_FAIL_REQUIRE
(
"Type mismatch."
);
}
KJ_FAIL_ASSERT
(
"can't get here"
);
}
void
set
(
DynamicValue
::
Reader
value
)
{
wasSet
=
true
;
switch
(
type
)
{
case
FIELD
:
return
structBuilder
.
set
(
member
,
value
);
case
ELEMENT
:
return
listBuilder
.
set
(
index
,
value
);
case
STRUCT_OBJECT_FIELD
:
return
structBuilder
.
set
(
member
,
value
);
case
LIST_OBJECT_FIELD
:
return
structBuilder
.
set
(
member
,
value
);
case
UNION_MEMBER
:
return
unionBuilder
.
set
(
unionMember
,
value
);
case
STRUCT_OBJECT_UNION_MEMBER
:
return
unionBuilder
.
set
(
unionMember
,
value
);
case
LIST_OBJECT_UNION_MEMBER
:
return
unionBuilder
.
set
(
unionMember
,
value
);
}
KJ_FAIL_ASSERT
(
"can't get here"
);
}
...
...
@@ -1379,16 +1385,16 @@ public:
}
return
nullptr
;
}
case
STRUCT_OBJECT_FIELD
:
return
nullptr
;
case
LIST_OBJECT_FIELD
:
return
nullptr
;
case
UNION_MEMBER
:
return
enumIdForMember
(
unionMember
);
case
STRUCT_OBJECT_UNION_MEMBER
:
return
nullptr
;
case
LIST_OBJECT_UNION_MEMBER
:
return
nullptr
;
}
KJ_FAIL_ASSERT
(
"can't get here"
);
}
private
:
enum
Type
{
FIELD
,
ELEMENT
,
STRUCT_OBJECT_FIELD
,
LIST_OBJECT_FIELD
,
UNION_MEMBER
FIELD
,
ELEMENT
,
UNION_MEMBER
,
STRUCT_OBJECT_UNION_MEMBER
,
LIST_OBJECT_
UNION_MEMBER
};
Type
type
;
...
...
@@ -1396,10 +1402,6 @@ private:
struct
{
DynamicStruct
::
Builder
structBuilder
;
StructSchema
::
Member
member
;
union
{
StructSchema
structMemberSchema
;
ListSchema
listMemberSchema
;
};
};
struct
{
DynamicList
::
Builder
listBuilder
;
...
...
@@ -1408,6 +1410,10 @@ private:
struct
{
DynamicUnion
::
Builder
unionBuilder
;
StructSchema
::
Member
unionMember
;
union
{
StructSchema
structMemberSchema
;
ListSchema
listMemberSchema
;
};
};
};
...
...
@@ -1451,6 +1457,10 @@ static kj::StringPtr getValueUnionMemberNameFor(schema::Type::Body::Which type)
void
NodeTranslator
::
compileBootstrapValue
(
ValueExpression
::
Reader
source
,
schema
::
Type
::
Reader
type
,
schema
::
Value
::
Builder
target
)
{
// Start by filling in a default default value so that if for whatever reason we don't end up
// initializing the value, this won't cause schema validation to fail.
compileDefaultDefaultValue
(
type
,
target
);
switch
(
type
.
getBody
().
which
())
{
case
schema
:
:
Type
::
Body
::
LIST_TYPE
:
case
schema
:
:
Type
::
Body
::
STRUCT_TYPE
:
...
...
@@ -1471,11 +1481,24 @@ void NodeTranslator::compileValue(ValueExpression::Reader source, schema::Type::
auto
valueUnion
=
toDynamic
(
target
).
get
(
"body"
).
as
<
DynamicUnion
>
();
auto
member
=
valueUnion
.
getSchema
().
getMemberByName
(
getValueUnionMemberNameFor
(
type
.
getBody
().
which
()));
DynamicSlot
slot
(
valueUnion
,
member
);
compileValue
(
source
,
slot
,
isBootstrap
);
if
(
!
slot
.
wasSet
)
{
// An error should have been reported already. Initialize to a reasonable default.
compileDefaultDefaultValue
(
type
,
target
);
switch
(
type
.
getBody
().
which
())
{
case
schema
:
:
Type
::
Body
::
LIST_TYPE
:
KJ_IF_MAYBE
(
listSchema
,
makeListSchemaOf
(
type
.
getBody
().
getListType
()))
{
DynamicSlot
slot
(
valueUnion
,
member
,
*
listSchema
);
compileValue
(
source
,
slot
,
isBootstrap
);
}
break
;
case
schema
:
:
Type
::
Body
::
STRUCT_TYPE
:
KJ_IF_MAYBE
(
structSchema
,
resolver
.
resolveMaybeBootstrapSchema
(
type
.
getBody
().
getStructType
()))
{
DynamicSlot
slot
(
valueUnion
,
member
,
structSchema
->
asStruct
());
compileValue
(
source
,
slot
,
isBootstrap
);
}
break
;
default
:
DynamicSlot
slot
(
valueUnion
,
member
);
compileValue
(
source
,
slot
,
isBootstrap
);
break
;
}
}
...
...
@@ -1487,8 +1510,7 @@ void NodeTranslator::compileValue(ValueExpression::Reader src, DynamicSlot& dst,
// way to test for type compatibility without throwing.
KJ_IF_MAYBE
(
exception
,
kj
::
runCatchingExceptions
(
[
&
]()
{
compileValueInner
(
src
,
dst
,
isBootstrap
);
}))
{
errorReporter
.
addErrorOn
(
src
,
exception
->
getDescription
());
dst
.
wasSet
=
false
;
errorReporter
.
addErrorOn
(
src
,
"Type mismatch."
);
}
}
...
...
@@ -1499,32 +1521,45 @@ void NodeTranslator::compileValueInner(
auto
name
=
src
.
getBody
().
getName
();
bool
isBare
=
name
.
getBase
().
which
()
==
DeclName
::
Base
::
RELATIVE_NAME
&&
name
.
getMemberPath
().
size
()
==
0
;
bool
wasSet
=
false
;
if
(
isBare
)
{
// The name is just a bare identifier. It may be a literal value or an enumerant.
kj
::
StringPtr
id
=
name
.
getBase
().
getRelativeName
().
getValue
();
KJ_IF_MAYBE
(
enumId
,
dst
.
getEnumType
())
{
auto
enumSchema
=
resolver
.
resolveMaybeBootstrapSchema
(
*
enumId
).
asEnum
();
KJ_IF_MAYBE
(
enumerant
,
enumSchema
.
findEnumerantByName
(
id
))
{
dst
.
set
(
DynamicEnum
(
*
enumerant
));
KJ_IF_MAYBE
(
enumSchema
,
resolver
.
resolveMaybeBootstrapSchema
(
*
enumId
))
{
KJ_IF_MAYBE
(
enumerant
,
enumSchema
->
asEnum
().
findEnumerantByName
(
id
))
{
dst
.
set
(
DynamicEnum
(
*
enumerant
));
wasSet
=
true
;
}
}
else
{
// Enum type is broken. We don't want to report a redundant error here, so just assume
// we would have found a matching enumerant.
dst
.
set
(
kj
::
implicitCast
<
uint16_t
>
(
0
));
wasSet
=
true
;
}
}
else
{
// Interpret known constant values.
if
(
id
==
"void"
)
{
dst
.
set
(
Void
::
VOID
);
wasSet
=
true
;
}
else
if
(
id
==
"true"
)
{
dst
.
set
(
true
);
wasSet
=
true
;
}
else
if
(
id
==
"false"
)
{
dst
.
set
(
false
);
wasSet
=
true
;
}
else
if
(
id
==
"nan"
)
{
dst
.
set
(
std
::
numeric_limits
<
double
>::
quiet_NaN
());
wasSet
=
true
;
}
else
if
(
id
==
"inf"
)
{
dst
.
set
(
std
::
numeric_limits
<
double
>::
infinity
());
wasSet
=
true
;
}
}
}
if
(
!
dst
.
wasSet
)
{
if
(
!
wasSet
)
{
// Haven't resolved the name yet. Try looking up a constant.
KJ_IF_MAYBE
(
constValue
,
readConstant
(
src
.
getBody
().
getName
(),
isBootstrap
,
src
))
{
dst
.
set
(
*
constValue
);
...
...
@@ -1618,7 +1653,7 @@ void NodeTranslator::copyValue(schema::Value::Reader src, schema::Type::Reader s
KJ_IF_MAYBE
(
exception
,
kj
::
runCatchingExceptions
(
[
&
]()
{
dstBody
.
set
(
dstFieldName
,
srcBody
.
get
());
}))
{
// Exception caught, therefore the types are not compatible.
errorReporter
.
addErrorOn
(
errorLocation
,
exception
->
getDescription
()
);
errorReporter
.
addErrorOn
(
errorLocation
,
"Type mismatch."
);
}
}
else
{
KJ_FAIL_ASSERT
(
"Didn't recognize schema::Value::Body type?"
);
...
...
@@ -1641,72 +1676,105 @@ kj::Maybe<DynamicValue::Reader> NodeTranslator::readConstant(
//
// We need to be very careful not to query this Schema's dependencies because if it is
// a final schema then this query could trigger a lazy load which would deadlock.
Schema
c
onstSchema
=
isBootstrap
?
kj
::
Maybe
<
Schema
>
maybeC
onstSchema
=
isBootstrap
?
resolver
.
resolveMaybeBootstrapSchema
(
resolved
->
id
)
:
resolver
.
resolveFinalSchema
(
resolved
->
id
);
auto
constReader
=
constSchema
.
getProto
().
getBody
().
getConstNode
();
auto
constValue
=
toDynamic
(
constReader
.
getValue
()).
get
(
"body"
).
as
<
DynamicUnion
>
().
get
();
if
(
constValue
.
getType
()
==
DynamicValue
::
OBJECT
)
{
// We need to assign an appropriate schema to this object.
DynamicObject
objValue
=
constValue
.
as
<
DynamicObject
>
();
auto
constType
=
constReader
.
getType
();
switch
(
constType
.
getBody
().
which
())
{
case
schema
:
:
Type
::
Body
::
STRUCT_TYPE
:
constValue
=
objValue
.
as
(
resolver
.
resolveMaybeBootstrapSchema
(
constType
.
getBody
().
getStructType
()).
asStruct
());
break
;
case
schema
:
:
Type
::
Body
::
LIST_TYPE
:
constValue
=
objValue
.
as
(
makeListSchemaOf
(
constType
.
getBody
().
getListType
()));
break
;
case
schema
:
:
Type
::
Body
::
OBJECT_TYPE
:
// Fine as-is.
break
;
default
:
KJ_FAIL_ASSERT
(
"Unrecognized Object-typed member of schema::Value::body."
);
break
;
KJ_IF_MAYBE
(
constSchema
,
maybeConstSchema
)
{
auto
constReader
=
constSchema
->
getProto
().
getBody
().
getConstNode
();
auto
constValue
=
toDynamic
(
constReader
.
getValue
()).
get
(
"body"
).
as
<
DynamicUnion
>
().
get
();
if
(
constValue
.
getType
()
==
DynamicValue
::
OBJECT
)
{
// We need to assign an appropriate schema to this object.
DynamicObject
objValue
=
constValue
.
as
<
DynamicObject
>
();
auto
constType
=
constReader
.
getType
();
switch
(
constType
.
getBody
().
which
())
{
case
schema
:
:
Type
::
Body
::
STRUCT_TYPE
:
KJ_IF_MAYBE
(
structSchema
,
resolver
.
resolveMaybeBootstrapSchema
(
constType
.
getBody
().
getStructType
()))
{
constValue
=
objValue
.
as
(
structSchema
->
asStruct
());
}
else
{
// The struct's schema is broken for reasons already reported.
return
nullptr
;
}
break
;
case
schema
:
:
Type
::
Body
::
LIST_TYPE
:
KJ_IF_MAYBE
(
listSchema
,
makeListSchemaOf
(
constType
.
getBody
().
getListType
()))
{
constValue
=
objValue
.
as
(
*
listSchema
);
}
else
{
// The list's schema is broken for reasons already reported.
return
nullptr
;
}
break
;
case
schema
:
:
Type
::
Body
::
OBJECT_TYPE
:
// Fine as-is.
break
;
default
:
KJ_FAIL_ASSERT
(
"Unrecognized Object-typed member of schema::Value::body."
);
break
;
}
}
}
if
(
name
.
getBase
().
which
()
==
DeclName
::
Base
::
RELATIVE_NAME
&&
name
.
getMemberPath
().
size
()
==
0
)
{
// A fully unqualified identifier looks like it might refer to a constant visible in the
// current scope, but if that's really what the user wanted, we want them to use a
// qualified name to make it more obvious. Report an error.
Schema
scope
=
resolver
.
resolveMaybeBootstrapSchema
(
constSchema
.
getProto
().
getScopeId
());
auto
scopeReader
=
scope
.
getProto
();
kj
::
StringPtr
parent
;
if
(
scopeReader
.
getBody
().
which
()
==
schema
::
Node
::
Body
::
FILE_NODE
)
{
parent
=
""
;
}
else
{
parent
=
scopeReader
.
getDisplayName
().
slice
(
scopeReader
.
getDisplayNamePrefixLength
());
if
(
name
.
getBase
().
which
()
==
DeclName
::
Base
::
RELATIVE_NAME
&&
name
.
getMemberPath
().
size
()
==
0
)
{
// A fully unqualified identifier looks like it might refer to a constant visible in the
// current scope, but if that's really what the user wanted, we want them to use a
// qualified name to make it more obvious. Report an error.
KJ_IF_MAYBE
(
scope
,
resolver
.
resolveMaybeBootstrapSchema
(
constSchema
->
getProto
().
getScopeId
()))
{
auto
scopeReader
=
scope
->
getProto
();
kj
::
StringPtr
parent
;
if
(
scopeReader
.
getBody
().
which
()
==
schema
::
Node
::
Body
::
FILE_NODE
)
{
parent
=
""
;
}
else
{
parent
=
scopeReader
.
getDisplayName
().
slice
(
scopeReader
.
getDisplayNamePrefixLength
());
}
kj
::
StringPtr
id
=
name
.
getBase
().
getRelativeName
().
getValue
();
errorReporter
.
addErrorOn
(
errorLocation
,
kj
::
str
(
"Constant names must be qualified to avoid confusion. Please replace '"
,
declNameString
(
name
),
"' with '"
,
parent
,
"."
,
id
,
"', if that's what you intended."
));
}
}
kj
::
StringPtr
id
=
name
.
getBase
().
getRelativeName
().
getValue
();
errorReporter
.
addErrorOn
(
errorLocation
,
kj
::
str
(
"Constant names must be qualified to avoid confusion. Please replace '"
,
declNameString
(
name
),
"' with '"
,
parent
,
"."
,
id
,
"', if that's what you intended."
))
;
return
constValue
;
}
else
{
// The target is a constant, but the constant's schema is broken for reasons already reported.
return
nullptr
;
}
return
constValue
;
}
else
{
// Lookup will have reported an error.
return
nullptr
;
}
}
ListSchema
NodeTranslator
::
makeListSchemaOf
(
schema
::
Type
::
Reader
elementType
)
{
kj
::
Maybe
<
ListSchema
>
NodeTranslator
::
makeListSchemaOf
(
schema
::
Type
::
Reader
elementType
)
{
auto
body
=
elementType
.
getBody
();
switch
(
body
.
which
())
{
case
schema
:
:
Type
::
Body
::
ENUM_TYPE
:
return
ListSchema
::
of
(
resolver
.
resolveMaybeBootstrapSchema
(
body
.
getEnumType
()).
asEnum
());
KJ_IF_MAYBE
(
enumSchema
,
resolver
.
resolveMaybeBootstrapSchema
(
body
.
getEnumType
()))
{
return
ListSchema
::
of
(
enumSchema
->
asEnum
());
}
else
{
return
nullptr
;
}
case
schema
:
:
Type
::
Body
::
STRUCT_TYPE
:
return
ListSchema
::
of
(
resolver
.
resolveMaybeBootstrapSchema
(
body
.
getStructType
()).
asStruct
());
KJ_IF_MAYBE
(
structSchema
,
resolver
.
resolveMaybeBootstrapSchema
(
body
.
getStructType
()))
{
return
ListSchema
::
of
(
structSchema
->
asStruct
());
}
else
{
return
nullptr
;
}
case
schema
:
:
Type
::
Body
::
INTERFACE_TYPE
:
return
ListSchema
::
of
(
resolver
.
resolveMaybeBootstrapSchema
(
body
.
getInterfaceType
())
.
asInterface
());
KJ_IF_MAYBE
(
interfaceSchema
,
resolver
.
resolveMaybeBootstrapSchema
(
body
.
getInterfaceType
()))
{
return
ListSchema
::
of
(
interfaceSchema
->
asInterface
());
}
else
{
return
nullptr
;
}
case
schema
:
:
Type
::
Body
::
LIST_TYPE
:
return
ListSchema
::
of
(
makeListSchemaOf
(
body
.
getListType
()));
KJ_IF_MAYBE
(
listSchema
,
makeListSchemaOf
(
body
.
getListType
()))
{
return
ListSchema
::
of
(
*
listSchema
);
}
else
{
return
nullptr
;
}
default
:
return
ListSchema
::
of
(
body
.
which
());
}
...
...
@@ -1727,6 +1795,10 @@ Orphan<List<schema::Annotation>> NodeTranslator::compileAnnotationApplications(
for
(
uint
i
=
0
;
i
<
annotations
.
size
();
i
++
)
{
Declaration
::
AnnotationApplication
::
Reader
annotation
=
annotations
[
i
];
schema
::
Annotation
::
Builder
annotationBuilder
=
builder
[
i
];
// Set the annotation's value to void in case we fail to produce something better below.
annotationBuilder
.
initValue
().
getBody
().
setVoidValue
();
auto
name
=
annotation
.
getName
();
KJ_IF_MAYBE
(
decl
,
resolver
.
resolve
(
name
))
{
if
(
decl
->
kind
!=
Declaration
::
Body
::
ANNOTATION_DECL
)
{
...
...
@@ -1734,33 +1806,33 @@ Orphan<List<schema::Annotation>> NodeTranslator::compileAnnotationApplications(
"'"
,
declNameString
(
name
),
"' is not an annotation."
));
}
else
{
annotationBuilder
.
setId
(
decl
->
id
);
auto
node
=
resolver
.
resolveMaybeBootstrapSchema
(
decl
->
id
).
getProto
()
.
getBody
().
getAnnotationNode
();
if
(
!
toDynamic
(
node
).
get
(
targetsFlagName
).
as
<
bool
>
())
{
errorReporter
.
addErrorOn
(
name
,
kj
::
str
(
"'"
,
declNameString
(
name
),
"' cannot be applied to this kind of declaration."
));
}
// Interpret the value.
auto
value
=
annotation
.
getValue
();
switch
(
value
.
which
())
{
case
Declaration
:
:
AnnotationApplication
::
Value
::
NONE
:
// No value, i.e. void.
if
(
node
.
getType
().
getBody
().
which
()
==
schema
::
Type
::
Body
::
VOID_TYPE
)
{
annotationBuilder
.
initValue
().
getBody
().
setVoidValue
();
}
else
{
errorReporter
.
addErrorOn
(
name
,
kj
::
str
(
"'"
,
declNameString
(
name
),
"' requires a value."
));
compileDefaultDefaultValue
(
node
.
getType
(),
annotationBuilder
.
initValue
());
}
break
;
KJ_IF_MAYBE
(
annotationSchema
,
resolver
.
resolveMaybeBootstrapSchema
(
decl
->
id
))
{
auto
node
=
annotationSchema
->
getProto
().
getBody
().
getAnnotationNode
();
if
(
!
toDynamic
(
node
).
get
(
targetsFlagName
).
as
<
bool
>
())
{
errorReporter
.
addErrorOn
(
name
,
kj
::
str
(
"'"
,
declNameString
(
name
),
"' cannot be applied to this kind of declaration."
));
}
case
Declaration
:
:
AnnotationApplication
::
Value
::
EXPRESSION
:
compileBootstrapValue
(
value
.
getExpression
(),
node
.
getType
(),
annotationBuilder
.
initValue
());
break
;
// Interpret the value.
auto
value
=
annotation
.
getValue
();
switch
(
value
.
which
())
{
case
Declaration
:
:
AnnotationApplication
::
Value
::
NONE
:
// No value, i.e. void.
if
(
node
.
getType
().
getBody
().
which
()
==
schema
::
Type
::
Body
::
VOID_TYPE
)
{
annotationBuilder
.
getValue
().
getBody
().
setVoidValue
();
}
else
{
errorReporter
.
addErrorOn
(
name
,
kj
::
str
(
"'"
,
declNameString
(
name
),
"' requires a value."
));
compileDefaultDefaultValue
(
node
.
getType
(),
annotationBuilder
.
getValue
());
}
break
;
case
Declaration
:
:
AnnotationApplication
::
Value
::
EXPRESSION
:
compileBootstrapValue
(
value
.
getExpression
(),
node
.
getType
(),
annotationBuilder
.
getValue
());
break
;
}
}
}
}
}
...
...
c++/src/capnp/compiler/node-translator.h
View file @
b92a28a6
...
...
@@ -54,15 +54,17 @@ public:
// Look up the given name, relative to this node, and return basic information about the
// target.
virtual
Schema
resolveMaybeBootstrapSchema
(
uint64_t
id
)
const
=
0
;
virtual
kj
::
Maybe
<
Schema
>
resolveMaybeBootstrapSchema
(
uint64_t
id
)
const
=
0
;
// Get the schema for the given ID. Returning either a bootstrap schema or a final schema
// is acceptable. Throws an exception if the id is not one that was found by calling resolve()
// or by traversing other schemas.
// or by traversing other schemas. Returns null if the ID is recognized, but the corresponding
// schema node failed to be built for reasons that were already reported.
virtual
Schema
resolveFinalSchema
(
uint64_t
id
)
const
=
0
;
virtual
kj
::
Maybe
<
Schema
>
resolveFinalSchema
(
uint64_t
id
)
const
=
0
;
// Get the final schema for the given ID. A bootstrap schema is not acceptable. Throws an
// exception if the id is not one that was found by calling resolve() or by traversing other
// schemas.
// schemas. Returns null if the ID is recognized, but the corresponding schema node failed to
// be built for reasons that were already reported.
};
NodeTranslator
(
const
Resolver
&
resolver
,
const
ErrorReporter
&
errorReporter
,
...
...
@@ -162,10 +164,12 @@ private:
kj
::
Maybe
<
DynamicValue
::
Reader
>
readConstant
(
DeclName
::
Reader
name
,
bool
isBootstrap
,
ValueExpression
::
Reader
errorLocation
);
// Get the value of the given constant.
// Get the value of the given constant. May return null if some error occurs, which will already
// have been reported.
ListSchema
makeListSchemaOf
(
schema
::
Type
::
Reader
elementType
);
// Construct a list schema representing a list of elements of the given type.
kj
::
Maybe
<
ListSchema
>
makeListSchemaOf
(
schema
::
Type
::
Reader
elementType
);
// Construct a list schema representing a list of elements of the given type. May return null if
// some error occurs, which will already have been reported.
Orphan
<
List
<
schema
::
Annotation
>>
compileAnnotationApplications
(
List
<
Declaration
::
AnnotationApplication
>::
Reader
annotations
,
...
...
c++/src/capnp/layout.c++
View file @
b92a28a6
...
...
@@ -1585,7 +1585,7 @@ struct WireHelpers {
}
static
void
adopt
(
SegmentBuilder
*
segment
,
WirePointer
*
ref
,
OrphanBuilder
&&
value
)
{
KJ_REQUIRE
(
value
.
segment
->
getArena
()
==
segment
->
getArena
(),
KJ_REQUIRE
(
value
.
segment
==
nullptr
||
value
.
segment
->
getArena
()
==
segment
->
getArena
(),
"Adopted object must live in the same message."
);
if
(
!
ref
->
isNull
())
{
...
...
c++/src/kj/common.h
View file @
b92a28a6
...
...
@@ -733,7 +733,7 @@ public:
KJ_DISALLOW_COPY
(
Deferred
);
// This move constructor is usually optimized away by the compiler.
inline
Deferred
(
Deferred
&&
other
)
:
func
(
kj
::
mv
(
other
.
func
))
{
inline
Deferred
(
Deferred
&&
other
)
:
func
(
kj
::
mv
(
other
.
func
))
,
canceled
(
false
)
{
other
.
canceled
=
true
;
}
private
:
...
...
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