capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

compiler.c++ (53029B)


      1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
      2 // Licensed under the MIT License:
      3 //
      4 // Permission is hereby granted, free of charge, to any person obtaining a copy
      5 // of this software and associated documentation files (the "Software"), to deal
      6 // in the Software without restriction, including without limitation the rights
      7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      8 // copies of the Software, and to permit persons to whom the Software is
      9 // furnished to do so, subject to the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     20 // THE SOFTWARE.
     21 
     22 #include "compiler.h"
     23 #include "parser.h"      // only for generateChildId()
     24 #include <kj/mutex.h>
     25 #include <kj/arena.h>
     26 #include <kj/vector.h>
     27 #include <kj/debug.h>
     28 #include <capnp/message.h>
     29 #include <map>
     30 #include <set>
     31 #include <unordered_map>
     32 #include "node-translator.h"
     33 
     34 namespace capnp {
     35 namespace compiler {
     36 
     37 typedef std::unordered_map<uint64_t, Orphan<schema::Node::SourceInfo::Reader>> SourceInfoMap;
     38 
     39 class Compiler::Alias {
     40 public:
     41   Alias(CompiledModule& module, Node& parent, const Expression::Reader& targetName)
     42       : module(module), parent(parent), targetName(targetName) {}
     43 
     44   kj::Maybe<Resolver::ResolveResult> compile();
     45 
     46 private:
     47   CompiledModule& module;
     48   Node& parent;
     49   Expression::Reader targetName;
     50   kj::Maybe<Resolver::ResolveResult> target;
     51   Orphan<schema::Brand> brandOrphan;
     52   bool initialized = false;
     53 };
     54 
     55 class Compiler::Node final: public Resolver {
     56   // Passes through four states:
     57   // - Stub:  On initial construction, the Node is just a placeholder object.  Its ID has been
     58   //     determined, and it is placed in its parent's member table as well as the compiler's
     59   //     nodes-by-ID table.
     60   // - Expanded:  Nodes have been constructed for all of this Node's nested children.  This happens
     61   //     the first time a lookup is performed for one of those children.
     62   // - Bootstrap:  A NodeTranslator has been built and advanced to the bootstrap phase.
     63   // - Finished:  A final Schema object has been constructed.
     64 
     65 public:
     66   explicit Node(CompiledModule& module);
     67   // Create a root node representing the given file.  May
     68 
     69   Node(Node& parent, const Declaration::Reader& declaration);
     70   // Create a child node.
     71 
     72   Node(kj::StringPtr name, Declaration::Which kind,
     73        List<Declaration::BrandParameter>::Reader genericParams);
     74   // Create a dummy node representing a built-in declaration, like "Int32" or "true".
     75 
     76   uint64_t getId() { return id; }
     77   uint getParameterCount() { return genericParamCount; }
     78   Declaration::Which getKind() { return kind; }
     79 
     80   kj::Maybe<Schema> getBootstrapSchema();
     81   kj::Maybe<schema::Node::Reader> getFinalSchema();
     82   void loadFinalSchema(const SchemaLoader& loader);
     83 
     84   void traverse(uint eagerness, std::unordered_map<Node*, uint>& seen,
     85                 const SchemaLoader& finalLoader,
     86                 kj::Vector<schema::Node::SourceInfo::Reader>& sourceInfo);
     87   // Get the final schema for this node, and also possibly traverse the node's children and
     88   // dependencies to ensure that they are loaded, depending on the mode.
     89 
     90   void addError(kj::StringPtr error);
     91   // Report an error on this Node.
     92 
     93   // implements Resolver ---------------------------------------------
     94   kj::Maybe<ResolveResult> resolve(kj::StringPtr name) override;
     95   kj::Maybe<ResolveResult> resolveMember(kj::StringPtr name) override;
     96   ResolvedDecl resolveBuiltin(Declaration::Which which) override;
     97   ResolvedDecl resolveId(uint64_t id) override;
     98   kj::Maybe<ResolvedDecl> getParent() override;
     99   ResolvedDecl getTopScope() override;
    100   kj::Maybe<Schema> resolveBootstrapSchema(
    101       uint64_t id, schema::Brand::Reader brand) override;
    102   kj::Maybe<schema::Node::Reader> resolveFinalSchema(uint64_t id) override;
    103   kj::Maybe<ResolvedDecl> resolveImport(kj::StringPtr name) override;
    104   kj::Maybe<kj::Array<const byte>> readEmbed(kj::StringPtr name) override;
    105   kj::Maybe<Type> resolveBootstrapType(schema::Type::Reader type, Schema scope) override;
    106 
    107 private:
    108   CompiledModule* module;  // null iff isBuiltin is true
    109   kj::Maybe<Node&> parent;
    110 
    111   Declaration::Reader declaration;
    112   // AST of the declaration parsed from the schema file.  May become invalid once the content
    113   // state has reached FINISHED.
    114 
    115   uint64_t id;
    116   // The ID of this node, either taken from the AST or computed based on the parent.  Or, a dummy
    117   // value, if duplicates were detected.
    118 
    119   kj::StringPtr displayName;
    120   // Fully-qualified display name for this node.  For files, this is just the file name, otherwise
    121   // it is "filename:Path.To.Decl".
    122 
    123   Declaration::Which kind;
    124   // Kind of node.
    125 
    126   uint genericParamCount;
    127   // Number of generic parameters.
    128 
    129   bool isBuiltin;
    130   // Whether this is a bulit-in declaration, like "Int32" or "true".
    131 
    132   uint32_t startByte;
    133   uint32_t endByte;
    134   // Start and end byte for reporting general errors.
    135 
    136   struct Content {
    137     inline Content(): state(STUB) {}
    138 
    139     enum State {
    140       STUB,
    141       EXPANDED,
    142       BOOTSTRAP,
    143       FINISHED
    144     };
    145     State state;
    146     // Indicates which fields below are valid.
    147 
    148     inline bool stateHasReached(State minimumState) {
    149       return state >= minimumState;
    150     }
    151     inline void advanceState(State newState) {
    152       state = newState;
    153     }
    154 
    155     // EXPANDED ------------------------------------
    156 
    157     typedef std::multimap<kj::StringPtr, kj::Own<Node>> NestedNodesMap;
    158     NestedNodesMap nestedNodes;
    159     kj::Vector<Node*> orderedNestedNodes;
    160     // multimap in case of duplicate member names -- we still want to compile them, even if it's an
    161     // error.
    162 
    163     typedef std::multimap<kj::StringPtr, kj::Own<Alias>> AliasMap;
    164     AliasMap aliases;
    165     // The "using" declarations.  These are just links to nodes elsewhere.
    166 
    167     // BOOTSTRAP -----------------------------------
    168 
    169     NodeTranslator* translator;
    170     // Node translator, allocated in the bootstrap arena.
    171 
    172     kj::Maybe<Schema> bootstrapSchema;
    173     // The schema built in the bootstrap loader.  Null if the bootstrap loader threw an exception.
    174 
    175     // FINISHED ------------------------------------
    176 
    177     kj::Maybe<schema::Node::Reader> finalSchema;
    178     // The completed schema, ready to load into the real schema loader.
    179 
    180     kj::Array<schema::Node::Reader> auxSchemas;
    181     // Schemas for all auxiliary nodes built by the NodeTranslator.
    182 
    183     kj::Array<schema::Node::SourceInfo::Reader> sourceInfo;
    184     // All source info structs as built by the NodeTranslator.
    185   };
    186 
    187   Content guardedContent;     // Read using getContent() only!
    188   bool inGetContent = false;  // True while getContent() is running; detects cycles.
    189 
    190   kj::Maybe<schema::Node::Reader> loadedFinalSchema;
    191   // Copy of `finalSchema` as loaded into the final schema loader.  This doesn't go away if the
    192   // workspace is destroyed.
    193 
    194   // ---------------------------------------------
    195 
    196   static uint64_t generateId(uint64_t parentId, kj::StringPtr declName,
    197                              Declaration::Id::Reader declId);
    198   // Extract the ID from the declaration, or if it has none, generate one based on the name and
    199   // parent ID.
    200 
    201   static kj::StringPtr joinDisplayName(kj::Arena& arena, Node& parent, kj::StringPtr declName);
    202   // Join the parent's display name with the child's unqualified name to construct the child's
    203   // display name.
    204 
    205   kj::Maybe<Content&> getContent(Content::State minimumState);
    206   // Advances the content to at least the given state and returns it.  Returns null if getContent()
    207   // is being called recursively and the given state has not yet been reached, as this indicates
    208   // that the declaration recursively depends on itself.
    209 
    210   void traverseNodeDependencies(const schema::Node::Reader& schemaNode, uint eagerness,
    211                                 std::unordered_map<Node*, uint>& seen,
    212                                 const SchemaLoader& finalLoader,
    213                                 kj::Vector<schema::Node::SourceInfo::Reader>& sourceInfo);
    214   void traverseType(const schema::Type::Reader& type, uint eagerness,
    215                     std::unordered_map<Node*, uint>& seen,
    216                     const SchemaLoader& finalLoader,
    217                     kj::Vector<schema::Node::SourceInfo::Reader>& sourceInfo);
    218   void traverseBrand(const schema::Brand::Reader& brand, uint eagerness,
    219                      std::unordered_map<Node*, uint>& seen,
    220                      const SchemaLoader& finalLoader,
    221                      kj::Vector<schema::Node::SourceInfo::Reader>& sourceInfo);
    222   void traverseAnnotations(const List<schema::Annotation>::Reader& annotations, uint eagerness,
    223                            std::unordered_map<Node*, uint>& seen,
    224                            const SchemaLoader& finalLoader,
    225                            kj::Vector<schema::Node::SourceInfo::Reader>& sourceInfo);
    226   void traverseDependency(uint64_t depId, uint eagerness,
    227                           std::unordered_map<Node*, uint>& seen,
    228                           const SchemaLoader& finalLoader,
    229                           kj::Vector<schema::Node::SourceInfo::Reader>& sourceInfo,
    230                           bool ignoreIfNotFound = false);
    231   // Helpers for traverse().
    232 };
    233 
    234 class Compiler::CompiledModule {
    235 public:
    236   CompiledModule(Compiler::Impl& compiler, Module& parserModule);
    237 
    238   Compiler::Impl& getCompiler() { return compiler; }
    239 
    240   ErrorReporter& getErrorReporter() { return parserModule; }
    241   ParsedFile::Reader getParsedFile() { return content.getReader(); }
    242   Node& getRootNode() { return rootNode; }
    243   kj::StringPtr getSourceName() { return parserModule.getSourceName(); }
    244 
    245   kj::Maybe<CompiledModule&> importRelative(kj::StringPtr importPath);
    246   kj::Maybe<kj::Array<const byte>> embedRelative(kj::StringPtr importPath);
    247 
    248   Orphan<List<schema::CodeGeneratorRequest::RequestedFile::Import>>
    249       getFileImportTable(Orphanage orphanage);
    250 
    251 private:
    252   Compiler::Impl& compiler;
    253   Module& parserModule;
    254   MallocMessageBuilder contentArena;
    255   Orphan<ParsedFile> content;
    256   Node rootNode;
    257 };
    258 
    259 class Compiler::Impl: public SchemaLoader::LazyLoadCallback {
    260 public:
    261   explicit Impl(AnnotationFlag annotationFlag);
    262   virtual ~Impl() noexcept(false);
    263 
    264   uint64_t add(Module& module);
    265   kj::Maybe<uint64_t> lookup(uint64_t parent, kj::StringPtr childName);
    266   kj::Maybe<schema::Node::SourceInfo::Reader> getSourceInfo(uint64_t id);
    267   Orphan<List<schema::CodeGeneratorRequest::RequestedFile::Import>>
    268       getFileImportTable(Module& module, Orphanage orphanage);
    269   Orphan<List<schema::Node::SourceInfo>> getAllSourceInfo(Orphanage orphanage);
    270   void eagerlyCompile(uint64_t id, uint eagerness, const SchemaLoader& loader);
    271   CompiledModule& addInternal(Module& parsedModule);
    272 
    273   struct Workspace {
    274     // Scratch space where stuff can be allocated while working.  The Workspace is available
    275     // whenever nodes are actively being compiled, then is destroyed once control exits the
    276     // compiler.  Note that since nodes are compiled lazily, a new Workspace may have to be
    277     // constructed in order to compile more nodes later.
    278 
    279     MallocMessageBuilder message;
    280     Orphanage orphanage;
    281     // Orphanage for allocating temporary Cap'n Proto objects.
    282 
    283     kj::Arena arena;
    284     // Arena for allocating temporary native objects.  Note that objects in `arena` may contain
    285     // pointers into `message` that will be manipulated on destruction, so `arena` must be declared
    286     // after `message`.
    287 
    288     SchemaLoader bootstrapLoader;
    289     // Loader used to load bootstrap schemas.  The bootstrap schema nodes are similar to the final
    290     // versions except that any value expressions which depend on knowledge of other types (e.g.
    291     // default values for struct fields) are left unevaluated (the values in the schema are empty).
    292     // These bootstrap schemas can then be plugged into the dynamic API and used to evaluate these
    293     // remaining values.
    294 
    295     inline explicit Workspace(const SchemaLoader::LazyLoadCallback& loaderCallback)
    296         : orphanage(message.getOrphanage()),
    297           bootstrapLoader(loaderCallback) {}
    298   };
    299 
    300   kj::Arena& getNodeArena() { return nodeArena; }
    301   // Arena where nodes and other permanent objects should be allocated.
    302 
    303   Workspace& getWorkspace() { return workspace; }
    304   // Temporary workspace that can be used to construct bootstrap objects.
    305 
    306   inline bool shouldCompileAnnotations() {
    307     return annotationFlag == AnnotationFlag::COMPILE_ANNOTATIONS;
    308   }
    309 
    310   void clearWorkspace();
    311   // Reset the temporary workspace.
    312 
    313   uint64_t addNode(uint64_t desiredId, Node& node);
    314   // Add the given node to the by-ID map under the given ID.  If another node with the same ID
    315   // already exists, choose a new one arbitrarily and use that instead.  Return the ID that was
    316   // finally used.
    317 
    318   kj::Maybe<Node&> findNode(uint64_t id);
    319 
    320   kj::Maybe<Node&> lookupBuiltin(kj::StringPtr name);
    321   Node& getBuiltin(Declaration::Which which);
    322 
    323   void load(const SchemaLoader& loader, uint64_t id) const override;
    324   // SchemaLoader callback for the bootstrap loader.
    325 
    326   void loadFinal(const SchemaLoader& loader, uint64_t id);
    327   // Called from the SchemaLoader callback for the final loader.
    328 
    329 private:
    330   AnnotationFlag annotationFlag;
    331 
    332   kj::Arena nodeArena;
    333   // Arena used to allocate nodes and other permanent objects.
    334 
    335   std::unordered_map<Module*, kj::Own<CompiledModule>> modules;
    336   // Map of parser modules to compiler modules.
    337 
    338   Workspace workspace;
    339   // The temporary workspace. This field must be declared after `modules` because objects
    340   // allocated in the workspace may hold references to the compiled modules in `modules`.
    341 
    342   std::unordered_map<uint64_t, Node*> nodesById;
    343   // Map of nodes by ID.
    344 
    345   std::unordered_map<uint64_t, schema::Node::SourceInfo::Reader> sourceInfoById;
    346   // Map of SourceInfos by ID, including SourceInfos for groups and param sturcts (which are not
    347   // listed in nodesById).
    348 
    349   std::map<kj::StringPtr, kj::Own<Node>> builtinDecls;
    350   std::map<Declaration::Which, Node*> builtinDeclsByKind;
    351   // Map of built-in declarations, like "Int32" and "List", which make up the global scope.
    352 
    353   uint64_t nextBogusId = 1000;
    354   // Counter for assigning bogus IDs to nodes whose real ID is a duplicate.
    355 };
    356 
    357 // =======================================================================================
    358 
    359 kj::Maybe<Resolver::ResolveResult> Compiler::Alias::compile() {
    360   if (!initialized) {
    361     initialized = true;
    362 
    363     auto& workspace = module.getCompiler().getWorkspace();
    364     brandOrphan = workspace.orphanage.newOrphan<schema::Brand>();
    365 
    366     // If the Workspace is destroyed, revert the alias to the uninitialized state, because the
    367     // orphan we created is no longer valid in this case.
    368     workspace.arena.copy(kj::defer([this]() {
    369       initialized = false;
    370       brandOrphan = Orphan<schema::Brand>();
    371     }));
    372 
    373     target = NodeTranslator::compileDecl(
    374         parent.getId(), parent.getParameterCount(), parent,
    375         module.getErrorReporter(), targetName, brandOrphan.get());
    376   }
    377 
    378   return target;
    379 }
    380 
    381 // =======================================================================================
    382 
    383 Compiler::Node::Node(CompiledModule& module)
    384     : module(&module),
    385       parent(nullptr),
    386       declaration(module.getParsedFile().getRoot()),
    387       id(generateId(0, declaration.getName().getValue(), declaration.getId())),
    388       displayName(module.getSourceName()),
    389       kind(declaration.which()),
    390       genericParamCount(declaration.getParameters().size()),
    391       isBuiltin(false) {
    392   auto name = declaration.getName();
    393   if (name.getValue().size() > 0) {
    394     startByte = name.getStartByte();
    395     endByte = name.getEndByte();
    396   } else {
    397     startByte = declaration.getStartByte();
    398     endByte = declaration.getEndByte();
    399   }
    400 
    401   id = module.getCompiler().addNode(id, *this);
    402 }
    403 
    404 Compiler::Node::Node(Node& parent, const Declaration::Reader& declaration)
    405     : module(parent.module),
    406       parent(parent),
    407       declaration(declaration),
    408       id(generateId(parent.id, declaration.getName().getValue(), declaration.getId())),
    409       displayName(joinDisplayName(parent.module->getCompiler().getNodeArena(),
    410                                   parent, declaration.getName().getValue())),
    411       kind(declaration.which()),
    412       genericParamCount(declaration.getParameters().size()),
    413       isBuiltin(false) {
    414   auto name = declaration.getName();
    415   if (name.getValue().size() > 0) {
    416     startByte = name.getStartByte();
    417     endByte = name.getEndByte();
    418   } else {
    419     startByte = declaration.getStartByte();
    420     endByte = declaration.getEndByte();
    421   }
    422 
    423   id = module->getCompiler().addNode(id, *this);
    424 }
    425 
    426 Compiler::Node::Node(kj::StringPtr name, Declaration::Which kind,
    427                      List<Declaration::BrandParameter>::Reader genericParams)
    428     : module(nullptr),
    429       parent(nullptr),
    430       // It's helpful if these have unique IDs. Real type IDs can't be under 2^31 anyway.
    431       id(1000 + static_cast<uint>(kind)),
    432       displayName(name),
    433       kind(kind),
    434       genericParamCount(genericParams.size()),
    435       isBuiltin(true),
    436       startByte(0),
    437       endByte(0) {}
    438 
    439 uint64_t Compiler::Node::generateId(uint64_t parentId, kj::StringPtr declName,
    440                                     Declaration::Id::Reader declId) {
    441   if (declId.isUid()) {
    442     return declId.getUid().getValue();
    443   }
    444 
    445   return generateChildId(parentId, declName);
    446 }
    447 
    448 kj::StringPtr Compiler::Node::joinDisplayName(
    449     kj::Arena& arena, Node& parent, kj::StringPtr declName) {
    450   kj::ArrayPtr<char> result = arena.allocateArray<char>(
    451       parent.displayName.size() + declName.size() + 2);
    452 
    453   size_t separatorPos = parent.displayName.size();
    454   memcpy(result.begin(), parent.displayName.begin(), separatorPos);
    455   result[separatorPos] = parent.parent == nullptr ? ':' : '.';
    456   memcpy(result.begin() + separatorPos + 1, declName.begin(), declName.size());
    457   result[result.size() - 1] = '\0';
    458   return kj::StringPtr(result.begin(), result.size() - 1);
    459 }
    460 
    461 kj::Maybe<Compiler::Node::Content&> Compiler::Node::getContent(Content::State minimumState) {
    462   KJ_REQUIRE(!isBuiltin, "illegal method call for built-in declaration");
    463 
    464   auto& content = guardedContent;
    465 
    466   if (content.stateHasReached(minimumState)) {
    467     return content;
    468   }
    469 
    470   if (inGetContent) {
    471     addError("Declaration recursively depends on itself.");
    472     return nullptr;
    473   }
    474 
    475   inGetContent = true;
    476   KJ_DEFER(inGetContent = false);
    477 
    478   switch (content.state) {
    479     case Content::STUB: {
    480       if (minimumState <= Content::STUB) break;
    481 
    482       // Expand the child nodes.
    483       auto& arena = module->getCompiler().getNodeArena();
    484 
    485       for (auto nestedDecl: declaration.getNestedDecls()) {
    486         switch (nestedDecl.which()) {
    487           case Declaration::FILE:
    488           case Declaration::CONST:
    489           case Declaration::ANNOTATION:
    490           case Declaration::ENUM:
    491           case Declaration::STRUCT:
    492           case Declaration::INTERFACE: {
    493             kj::Own<Node> subNode = arena.allocateOwn<Node>(*this, nestedDecl);
    494             kj::StringPtr name = nestedDecl.getName().getValue();
    495             content.orderedNestedNodes.add(subNode);
    496             content.nestedNodes.insert(std::make_pair(name, kj::mv(subNode)));
    497             break;
    498           }
    499 
    500           case Declaration::USING: {
    501             kj::Own<Alias> alias = arena.allocateOwn<Alias>(
    502                 *module, *this, nestedDecl.getUsing().getTarget());
    503             kj::StringPtr name = nestedDecl.getName().getValue();
    504             content.aliases.insert(std::make_pair(name, kj::mv(alias)));
    505             break;
    506           }
    507           case Declaration::ENUMERANT:
    508           case Declaration::FIELD:
    509           case Declaration::UNION:
    510           case Declaration::GROUP:
    511           case Declaration::METHOD:
    512           case Declaration::NAKED_ID:
    513           case Declaration::NAKED_ANNOTATION:
    514             // Not a node.  Skip.
    515             break;
    516           default:
    517             KJ_FAIL_ASSERT("unknown declaration type", nestedDecl);
    518             break;
    519         }
    520       }
    521 
    522       content.advanceState(Content::EXPANDED);
    523     } KJ_FALLTHROUGH;
    524 
    525     case Content::EXPANDED: {
    526       if (minimumState <= Content::EXPANDED) break;
    527 
    528       // Construct the NodeTranslator.
    529       auto& workspace = module->getCompiler().getWorkspace();
    530 
    531       auto schemaNode = workspace.orphanage.newOrphan<schema::Node>();
    532       auto builder = schemaNode.get();
    533       builder.setId(id);
    534       builder.setDisplayName(displayName);
    535       // TODO(cleanup):  Would be better if we could remember the prefix length from before we
    536       //   added this decl's name to the end.
    537       KJ_IF_MAYBE(lastDot, displayName.findLast('.')) {
    538         builder.setDisplayNamePrefixLength(*lastDot + 1);
    539       }
    540       KJ_IF_MAYBE(lastColon, displayName.findLast(':')) {
    541         if (*lastColon > builder.getDisplayNamePrefixLength()) {
    542           builder.setDisplayNamePrefixLength(*lastColon + 1);
    543         }
    544       }
    545       KJ_IF_MAYBE(p, parent) {
    546         builder.setScopeId(p->id);
    547       }
    548 
    549       auto nestedNodes = builder.initNestedNodes(content.orderedNestedNodes.size());
    550       auto nestedIter = nestedNodes.begin();
    551       for (auto node: content.orderedNestedNodes) {
    552         nestedIter->setName(node->declaration.getName().getValue());
    553         nestedIter->setId(node->id);
    554         ++nestedIter;
    555       }
    556 
    557       content.translator = &workspace.arena.allocate<NodeTranslator>(
    558           *this, module->getErrorReporter(), declaration, kj::mv(schemaNode),
    559           module->getCompiler().shouldCompileAnnotations());
    560       KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&](){
    561         auto nodeSet = content.translator->getBootstrapNode();
    562         for (auto& auxNode: nodeSet.auxNodes) {
    563           workspace.bootstrapLoader.loadOnce(auxNode);
    564         }
    565         content.bootstrapSchema = workspace.bootstrapLoader.loadOnce(nodeSet.node);
    566       })) {
    567         content.bootstrapSchema = nullptr;
    568         // Only bother to report validation failures if we think we haven't seen any errors.
    569         // Otherwise we assume that the errors caused the validation failure.
    570         if (!module->getErrorReporter().hadErrors()) {
    571           addError(kj::str("Internal compiler bug: Bootstrap schema failed validation:\n",
    572                            *exception));
    573         }
    574       }
    575 
    576       // If the Workspace is destroyed, revert the node to the EXPANDED state, because the
    577       // NodeTranslator is no longer valid in this case.
    578       workspace.arena.copy(kj::defer([&content]() {
    579         content.bootstrapSchema = nullptr;
    580         if (content.state > Content::EXPANDED) {
    581           content.state = Content::EXPANDED;
    582         }
    583       }));
    584 
    585       content.advanceState(Content::BOOTSTRAP);
    586     } KJ_FALLTHROUGH;
    587 
    588     case Content::BOOTSTRAP: {
    589       if (minimumState <= Content::BOOTSTRAP) break;
    590 
    591       // Create the final schema.
    592       NodeTranslator::NodeSet nodeSet;
    593       if (content.bootstrapSchema == nullptr) {
    594         // Must have failed in an earlier stage.
    595         KJ_ASSERT(module->getErrorReporter().hadErrors());
    596         nodeSet = content.translator->getBootstrapNode();
    597       } else {
    598         nodeSet = content.translator->finish(
    599             module->getCompiler().getWorkspace().bootstrapLoader.getUnbound(id));
    600       }
    601 
    602       content.finalSchema = nodeSet.node;
    603       content.auxSchemas = kj::mv(nodeSet.auxNodes);
    604       content.sourceInfo = kj::mv(nodeSet.sourceInfo);
    605 
    606       content.advanceState(Content::FINISHED);
    607     } KJ_FALLTHROUGH;
    608 
    609     case Content::FINISHED:
    610       break;
    611   }
    612 
    613   return content;
    614 }
    615 
    616 kj::Maybe<Schema> Compiler::Node::getBootstrapSchema() {
    617   KJ_IF_MAYBE(schema, loadedFinalSchema) {
    618     // We don't need to rebuild the bootstrap schema if we already have a final schema.
    619     return module->getCompiler().getWorkspace().bootstrapLoader.loadOnce(*schema);
    620   } else KJ_IF_MAYBE(content, getContent(Content::BOOTSTRAP)) {
    621     if (content->state == Content::FINISHED && content->bootstrapSchema == nullptr) {
    622       // The bootstrap schema was discarded.  Copy it from the final schema.
    623       // (We can't just return the final schema because using it could trigger schema loader
    624       // callbacks that would deadlock.)
    625       KJ_IF_MAYBE(finalSchema, content->finalSchema) {
    626         return module->getCompiler().getWorkspace().bootstrapLoader.loadOnce(*finalSchema);
    627       } else {
    628         return nullptr;
    629       }
    630     } else {
    631       return content->bootstrapSchema;
    632     }
    633   } else {
    634     return nullptr;
    635   }
    636 }
    637 kj::Maybe<schema::Node::Reader> Compiler::Node::getFinalSchema() {
    638   KJ_IF_MAYBE(schema, loadedFinalSchema) {
    639     return *schema;
    640   } else KJ_IF_MAYBE(content, getContent(Content::FINISHED)) {
    641     return content->finalSchema;
    642   } else {
    643     return nullptr;
    644   }
    645 }
    646 void Compiler::Node::loadFinalSchema(const SchemaLoader& loader) {
    647   KJ_IF_MAYBE(content, getContent(Content::FINISHED)) {
    648     KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&](){
    649       KJ_IF_MAYBE(finalSchema, content->finalSchema) {
    650         KJ_MAP(auxSchema, content->auxSchemas) {
    651           return loader.loadOnce(auxSchema);
    652         };
    653         loadedFinalSchema = loader.loadOnce(*finalSchema).getProto();
    654       }
    655     })) {
    656       // Schema validation threw an exception.
    657 
    658       // Don't try loading this again.
    659       content->finalSchema = nullptr;
    660 
    661       // Only bother to report validation failures if we think we haven't seen any errors.
    662       // Otherwise we assume that the errors caused the validation failure.
    663       if (!module->getErrorReporter().hadErrors()) {
    664         addError(kj::str("Internal compiler bug: Schema failed validation:\n", *exception));
    665       }
    666     }
    667   }
    668 }
    669 
    670 void Compiler::Node::traverse(uint eagerness, std::unordered_map<Node*, uint>& seen,
    671                               const SchemaLoader& finalLoader,
    672                               kj::Vector<schema::Node::SourceInfo::Reader>& sourceInfo) {
    673   uint& slot = seen[this];
    674   if ((slot & eagerness) == eagerness) {
    675     // We've already covered this node.
    676     return;
    677   }
    678   slot |= eagerness;
    679 
    680   KJ_IF_MAYBE(content, getContent(Content::FINISHED)) {
    681     loadFinalSchema(finalLoader);
    682 
    683     KJ_IF_MAYBE(schema, getFinalSchema()) {
    684       if (eagerness / DEPENDENCIES != 0) {
    685         // For traversing dependencies, discard the bits lower than DEPENDENCIES and replace
    686         // them with the bits above DEPENDENCIES shifted over.
    687         uint newEagerness = (eagerness & ~(DEPENDENCIES - 1)) | (eagerness / DEPENDENCIES);
    688 
    689         traverseNodeDependencies(*schema, newEagerness, seen, finalLoader, sourceInfo);
    690         for (auto& aux: content->auxSchemas) {
    691           traverseNodeDependencies(aux, newEagerness, seen, finalLoader, sourceInfo);
    692         }
    693       }
    694     }
    695 
    696     sourceInfo.addAll(content->sourceInfo);
    697   }
    698 
    699   if (eagerness & PARENTS) {
    700     KJ_IF_MAYBE(p, parent) {
    701       p->traverse(eagerness, seen, finalLoader, sourceInfo);
    702     }
    703   }
    704 
    705   if (eagerness & CHILDREN) {
    706     KJ_IF_MAYBE(content, getContent(Content::EXPANDED)) {
    707       for (auto& child: content->orderedNestedNodes) {
    708         child->traverse(eagerness, seen, finalLoader, sourceInfo);
    709       }
    710 
    711       // Also traverse `using` declarations.
    712       for (auto& child: content->aliases) {
    713         child.second->compile();
    714       }
    715     }
    716   }
    717 }
    718 
    719 void Compiler::Node::traverseNodeDependencies(
    720     const schema::Node::Reader& schemaNode, uint eagerness,
    721     std::unordered_map<Node*, uint>& seen,
    722     const SchemaLoader& finalLoader,
    723     kj::Vector<schema::Node::SourceInfo::Reader>& sourceInfo) {
    724   switch (schemaNode.which()) {
    725     case schema::Node::STRUCT:
    726       for (auto field: schemaNode.getStruct().getFields()) {
    727         switch (field.which()) {
    728           case schema::Field::SLOT:
    729             traverseType(field.getSlot().getType(), eagerness, seen, finalLoader, sourceInfo);
    730             break;
    731           case schema::Field::GROUP:
    732             // Aux node will be scanned later.
    733             break;
    734         }
    735 
    736         traverseAnnotations(field.getAnnotations(), eagerness, seen, finalLoader, sourceInfo);
    737       }
    738       break;
    739 
    740     case schema::Node::ENUM:
    741       for (auto enumerant: schemaNode.getEnum().getEnumerants()) {
    742         traverseAnnotations(enumerant.getAnnotations(), eagerness, seen, finalLoader, sourceInfo);
    743       }
    744       break;
    745 
    746     case schema::Node::INTERFACE: {
    747       auto interface = schemaNode.getInterface();
    748       for (auto superclass: interface.getSuperclasses()) {
    749         uint64_t superclassId = superclass.getId();
    750         if (superclassId != 0) {  // if zero, we reported an error earlier
    751           traverseDependency(superclassId, eagerness, seen, finalLoader, sourceInfo);
    752         }
    753         traverseBrand(superclass.getBrand(), eagerness, seen, finalLoader, sourceInfo);
    754       }
    755       for (auto method: interface.getMethods()) {
    756         traverseDependency(
    757             method.getParamStructType(), eagerness, seen, finalLoader, sourceInfo, true);
    758         traverseBrand(method.getParamBrand(), eagerness, seen, finalLoader, sourceInfo);
    759         traverseDependency(
    760             method.getResultStructType(), eagerness, seen, finalLoader, sourceInfo, true);
    761         traverseBrand(method.getResultBrand(), eagerness, seen, finalLoader, sourceInfo);
    762         traverseAnnotations(method.getAnnotations(), eagerness, seen, finalLoader, sourceInfo);
    763       }
    764       break;
    765     }
    766 
    767     case schema::Node::CONST:
    768       traverseType(schemaNode.getConst().getType(), eagerness, seen, finalLoader, sourceInfo);
    769       break;
    770 
    771     case schema::Node::ANNOTATION:
    772       traverseType(schemaNode.getAnnotation().getType(), eagerness, seen, finalLoader, sourceInfo);
    773       break;
    774 
    775     default:
    776       break;
    777   }
    778 
    779   traverseAnnotations(schemaNode.getAnnotations(), eagerness, seen, finalLoader, sourceInfo);
    780 }
    781 
    782 void Compiler::Node::traverseType(const schema::Type::Reader& type, uint eagerness,
    783                                   std::unordered_map<Node*, uint>& seen,
    784                                   const SchemaLoader& finalLoader,
    785                                   kj::Vector<schema::Node::SourceInfo::Reader>& sourceInfo) {
    786   uint64_t id = 0;
    787   schema::Brand::Reader brand;
    788   switch (type.which()) {
    789     case schema::Type::STRUCT:
    790       id = type.getStruct().getTypeId();
    791       brand = type.getStruct().getBrand();
    792       break;
    793     case schema::Type::ENUM:
    794       id = type.getEnum().getTypeId();
    795       brand = type.getEnum().getBrand();
    796       break;
    797     case schema::Type::INTERFACE:
    798       id = type.getInterface().getTypeId();
    799       brand = type.getInterface().getBrand();
    800       break;
    801     case schema::Type::LIST:
    802       traverseType(type.getList().getElementType(), eagerness, seen, finalLoader, sourceInfo);
    803       return;
    804     default:
    805       return;
    806   }
    807 
    808   traverseDependency(id, eagerness, seen, finalLoader, sourceInfo);
    809   traverseBrand(brand, eagerness, seen, finalLoader, sourceInfo);
    810 }
    811 
    812 void Compiler::Node::traverseBrand(
    813     const schema::Brand::Reader& brand, uint eagerness,
    814     std::unordered_map<Node*, uint>& seen,
    815     const SchemaLoader& finalLoader,
    816     kj::Vector<schema::Node::SourceInfo::Reader>& sourceInfo) {
    817   for (auto scope: brand.getScopes()) {
    818     switch (scope.which()) {
    819       case schema::Brand::Scope::BIND:
    820         for (auto binding: scope.getBind()) {
    821           switch (binding.which()) {
    822             case schema::Brand::Binding::UNBOUND:
    823               break;
    824             case schema::Brand::Binding::TYPE:
    825               traverseType(binding.getType(), eagerness, seen, finalLoader, sourceInfo);
    826               break;
    827           }
    828         }
    829         break;
    830       case schema::Brand::Scope::INHERIT:
    831         break;
    832     }
    833   }
    834 }
    835 
    836 void Compiler::Node::traverseDependency(uint64_t depId, uint eagerness,
    837                                         std::unordered_map<Node*, uint>& seen,
    838                                         const SchemaLoader& finalLoader,
    839                                         kj::Vector<schema::Node::SourceInfo::Reader>& sourceInfo,
    840                                         bool ignoreIfNotFound) {
    841   KJ_IF_MAYBE(node, module->getCompiler().findNode(depId)) {
    842     node->traverse(eagerness, seen, finalLoader, sourceInfo);
    843   } else if (!ignoreIfNotFound) {
    844     KJ_FAIL_ASSERT("Dependency ID not present in compiler?", depId);
    845   }
    846 }
    847 
    848 void Compiler::Node::traverseAnnotations(const List<schema::Annotation>::Reader& annotations,
    849                                          uint eagerness,
    850                                          std::unordered_map<Node*, uint>& seen,
    851                                          const SchemaLoader& finalLoader,
    852                                          kj::Vector<schema::Node::SourceInfo::Reader>& sourceInfo) {
    853   for (auto annotation: annotations) {
    854     KJ_IF_MAYBE(node, module->getCompiler().findNode(annotation.getId())) {
    855       node->traverse(eagerness, seen, finalLoader, sourceInfo);
    856     }
    857   }
    858 }
    859 
    860 
    861 void Compiler::Node::addError(kj::StringPtr error) {
    862   module->getErrorReporter().addError(startByte, endByte, error);
    863 }
    864 
    865 kj::Maybe<Resolver::ResolveResult>
    866 Compiler::Node::resolve(kj::StringPtr name) {
    867   // Check members.
    868   KJ_IF_MAYBE(member, resolveMember(name)) {
    869     return *member;
    870   }
    871 
    872   // Check parameters.
    873   // TODO(perf): Maintain a map?
    874   auto params = declaration.getParameters();
    875   for (uint i: kj::indices(params)) {
    876     if (params[i].getName() == name) {
    877       ResolveResult result;
    878       result.init<ResolvedParameter>(ResolvedParameter {id, i});
    879       return result;
    880     }
    881   }
    882 
    883   // Check parent scope.
    884   KJ_IF_MAYBE(p, parent) {
    885     return p->resolve(name);
    886   } else KJ_IF_MAYBE(b, module->getCompiler().lookupBuiltin(name)) {
    887     ResolveResult result;
    888     result.init<ResolvedDecl>(ResolvedDecl { b->id, b->genericParamCount, 0, b->kind, b, nullptr });
    889     return result;
    890   } else {
    891     return nullptr;
    892   }
    893 }
    894 
    895 kj::Maybe<Resolver::ResolveResult>
    896 Compiler::Node::resolveMember(kj::StringPtr name) {
    897   if (isBuiltin) return nullptr;
    898 
    899   KJ_IF_MAYBE(content, getContent(Content::EXPANDED)) {
    900     {
    901       auto iter = content->nestedNodes.find(name);
    902       if (iter != content->nestedNodes.end()) {
    903         Node* node = iter->second;
    904         ResolveResult result;
    905         result.init<ResolvedDecl>(ResolvedDecl {
    906             node->id, node->genericParamCount, id, node->kind, node, nullptr });
    907         return result;
    908       }
    909     }
    910     {
    911       auto iter = content->aliases.find(name);
    912       if (iter != content->aliases.end()) {
    913         return iter->second->compile();
    914       }
    915     }
    916   }
    917   return nullptr;
    918 }
    919 
    920 Resolver::ResolvedDecl Compiler::Node::resolveBuiltin(Declaration::Which which) {
    921   auto& b = module->getCompiler().getBuiltin(which);
    922   return { b.id, b.genericParamCount, 0, b.kind, &b, nullptr };
    923 }
    924 
    925 Resolver::ResolvedDecl Compiler::Node::resolveId(uint64_t id) {
    926   auto& n = KJ_ASSERT_NONNULL(module->getCompiler().findNode(id));
    927   uint64_t parentId = n.parent.map([](Node& n) { return n.id; }).orDefault(0);
    928   return { n.id, n.genericParamCount, parentId, n.kind, &n, nullptr };
    929 }
    930 
    931 kj::Maybe<Resolver::ResolvedDecl> Compiler::Node::getParent() {
    932   return parent.map([](Node& parent) {
    933     uint64_t scopeId = parent.parent.map([](Node& gp) { return gp.id; }).orDefault(0);
    934     return ResolvedDecl { parent.id, parent.genericParamCount, scopeId, parent.kind, &parent, nullptr };
    935   });
    936 }
    937 
    938 Resolver::ResolvedDecl Compiler::Node::getTopScope() {
    939   Node& node = module->getRootNode();
    940   return ResolvedDecl { node.id, 0, 0, node.kind, &node, nullptr };
    941 }
    942 
    943 kj::Maybe<Schema> Compiler::Node::resolveBootstrapSchema(
    944     uint64_t id, schema::Brand::Reader brand) {
    945   KJ_IF_MAYBE(node, module->getCompiler().findNode(id)) {
    946     // Make sure the bootstrap schema is loaded into the SchemaLoader.
    947     if (node->getBootstrapSchema() == nullptr) {
    948       return nullptr;
    949     }
    950 
    951     // Now we actually invoke get() to evaluate the brand.
    952     return module->getCompiler().getWorkspace().bootstrapLoader.get(id, brand);
    953   } else {
    954     KJ_FAIL_REQUIRE("Tried to get schema for ID we haven't seen before.");
    955   }
    956 }
    957 
    958 kj::Maybe<schema::Node::Reader> Compiler::Node::resolveFinalSchema(uint64_t id) {
    959   KJ_IF_MAYBE(node, module->getCompiler().findNode(id)) {
    960     return node->getFinalSchema();
    961   } else {
    962     KJ_FAIL_REQUIRE("Tried to get schema for ID we haven't seen before.");
    963   }
    964 }
    965 
    966 kj::Maybe<Resolver::ResolvedDecl>
    967 Compiler::Node::resolveImport(kj::StringPtr name) {
    968   KJ_IF_MAYBE(m, module->importRelative(name)) {
    969     Node& root = m->getRootNode();
    970     return ResolvedDecl { root.id, 0, 0, root.kind, &root, nullptr };
    971   } else {
    972     return nullptr;
    973   }
    974 }
    975 
    976 kj::Maybe<kj::Array<const byte>> Compiler::Node::readEmbed(kj::StringPtr name) {
    977   return module->embedRelative(name);
    978 }
    979 
    980 kj::Maybe<Type> Compiler::Node::resolveBootstrapType(schema::Type::Reader type, Schema scope) {
    981   // TODO(someday): Arguably should return null if the type or its dependencies are placeholders.
    982 
    983   kj::Maybe<Type> result;
    984   KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]() {
    985     result = module->getCompiler().getWorkspace().bootstrapLoader.getType(type, scope);
    986   })) {
    987     result = nullptr;
    988     if (!module->getErrorReporter().hadErrors()) {
    989       addError(kj::str("Internal compiler bug: Bootstrap schema failed to load:\n",
    990                        *exception));
    991     }
    992   }
    993   return result;
    994 }
    995 
    996 // =======================================================================================
    997 
    998 Compiler::CompiledModule::CompiledModule(Compiler::Impl& compiler, Module& parserModule)
    999     : compiler(compiler), parserModule(parserModule),
   1000       content(parserModule.loadContent(contentArena.getOrphanage())),
   1001       rootNode(*this) {}
   1002 
   1003 kj::Maybe<Compiler::CompiledModule&> Compiler::CompiledModule::importRelative(
   1004     kj::StringPtr importPath) {
   1005   return parserModule.importRelative(importPath).map(
   1006       [this](Module& module) -> Compiler::CompiledModule& {
   1007         return compiler.addInternal(module);
   1008       });
   1009 }
   1010 
   1011 kj::Maybe<kj::Array<const byte>> Compiler::CompiledModule::embedRelative(kj::StringPtr embedPath) {
   1012   return parserModule.embedRelative(embedPath);
   1013 }
   1014 
   1015 static void findImports(Expression::Reader exp, std::set<kj::StringPtr>& output) {
   1016   switch (exp.which()) {
   1017     case Expression::UNKNOWN:
   1018     case Expression::POSITIVE_INT:
   1019     case Expression::NEGATIVE_INT:
   1020     case Expression::FLOAT:
   1021     case Expression::STRING:
   1022     case Expression::BINARY:
   1023     case Expression::RELATIVE_NAME:
   1024     case Expression::ABSOLUTE_NAME:
   1025     case Expression::EMBED:
   1026       break;
   1027 
   1028     case Expression::IMPORT:
   1029       output.insert(exp.getImport().getValue());
   1030       break;
   1031 
   1032     case Expression::LIST:
   1033       for (auto element: exp.getList()) {
   1034         findImports(element, output);
   1035       }
   1036       break;
   1037 
   1038     case Expression::TUPLE:
   1039       for (auto element: exp.getTuple()) {
   1040         findImports(element.getValue(), output);
   1041       }
   1042       break;
   1043 
   1044     case Expression::APPLICATION: {
   1045       auto app = exp.getApplication();
   1046       findImports(app.getFunction(), output);
   1047       for (auto param: app.getParams()) {
   1048         findImports(param.getValue(), output);
   1049       }
   1050       break;
   1051     }
   1052 
   1053     case Expression::MEMBER: {
   1054       findImports(exp.getMember().getParent(), output);
   1055       break;
   1056     }
   1057   }
   1058 }
   1059 
   1060 static void findImports(Declaration::ParamList::Reader paramList, std::set<kj::StringPtr>& output) {
   1061   switch (paramList.which()) {
   1062     case Declaration::ParamList::NAMED_LIST:
   1063       for (auto param: paramList.getNamedList()) {
   1064         findImports(param.getType(), output);
   1065         for (auto ann: param.getAnnotations()) {
   1066           findImports(ann.getName(), output);
   1067         }
   1068       }
   1069       break;
   1070     case Declaration::ParamList::TYPE:
   1071       findImports(paramList.getType(), output);
   1072       break;
   1073     case Declaration::ParamList::STREAM:
   1074       output.insert("/capnp/stream.capnp");
   1075       break;
   1076   }
   1077 }
   1078 
   1079 static void findImports(Declaration::Reader decl, std::set<kj::StringPtr>& output) {
   1080   switch (decl.which()) {
   1081     case Declaration::USING:
   1082       findImports(decl.getUsing().getTarget(), output);
   1083       break;
   1084     case Declaration::CONST:
   1085       findImports(decl.getConst().getType(), output);
   1086       break;
   1087     case Declaration::FIELD:
   1088       findImports(decl.getField().getType(), output);
   1089       break;
   1090     case Declaration::INTERFACE:
   1091       for (auto superclass: decl.getInterface().getSuperclasses()) {
   1092         findImports(superclass, output);
   1093       }
   1094       break;
   1095     case Declaration::METHOD: {
   1096       auto method = decl.getMethod();
   1097 
   1098       findImports(method.getParams(), output);
   1099       if (method.getResults().isExplicit()) {
   1100         findImports(method.getResults().getExplicit(), output);
   1101       }
   1102       break;
   1103     }
   1104     default:
   1105       break;
   1106   }
   1107 
   1108   for (auto ann: decl.getAnnotations()) {
   1109     findImports(ann.getName(), output);
   1110   }
   1111 
   1112   for (auto nested: decl.getNestedDecls()) {
   1113     findImports(nested, output);
   1114   }
   1115 }
   1116 
   1117 Orphan<List<schema::CodeGeneratorRequest::RequestedFile::Import>>
   1118     Compiler::CompiledModule::getFileImportTable(Orphanage orphanage) {
   1119   // Build a table of imports for CodeGeneratorRequest.RequestedFile.imports. Note that we only
   1120   // care about type imports, not constant value imports, since constant values (including default
   1121   // values) are already embedded in full in the schema. In other words, we only need the imports
   1122   // that would need to be #included in the generated code.
   1123 
   1124   std::set<kj::StringPtr> importNames;
   1125   findImports(content.getReader().getRoot(), importNames);
   1126 
   1127   auto result = orphanage.newOrphan<List<schema::CodeGeneratorRequest::RequestedFile::Import>>(
   1128       importNames.size());
   1129   auto builder = result.get();
   1130 
   1131   uint i = 0;
   1132   for (auto name: importNames) {
   1133     // We presumably ran this import before, so it shouldn't throw now.
   1134     auto entry = builder[i++];
   1135     entry.setId(KJ_ASSERT_NONNULL(importRelative(name)).rootNode.getId());
   1136     entry.setName(name);
   1137   }
   1138 
   1139   return result;
   1140 }
   1141 
   1142 // =======================================================================================
   1143 
   1144 Compiler::Impl::Impl(AnnotationFlag annotationFlag)
   1145     : annotationFlag(annotationFlag), workspace(*this) {
   1146   // Reflectively interpret the members of Declaration.body.  Any member prefixed by "builtin"
   1147   // defines a builtin declaration visible in the global scope.
   1148 
   1149   StructSchema declSchema = Schema::from<Declaration>();
   1150   for (auto field: declSchema.getFields()) {
   1151     auto fieldProto = field.getProto();
   1152     if (fieldProto.getDiscriminantValue() != schema::Field::NO_DISCRIMINANT) {
   1153       auto name = fieldProto.getName();
   1154       if (name.startsWith("builtin")) {
   1155         kj::StringPtr symbolName = name.slice(strlen("builtin"));
   1156 
   1157         List<Declaration::BrandParameter>::Reader params;
   1158         for (auto annotation: fieldProto.getAnnotations()) {
   1159           if (annotation.getId() == 0x94099c3f9eb32d6bull) {
   1160             params = annotation.getValue().getList().getAs<List<Declaration::BrandParameter>>();
   1161             break;
   1162           }
   1163         }
   1164 
   1165         Declaration::Which which =
   1166             static_cast<Declaration::Which>(fieldProto.getDiscriminantValue());
   1167         kj::Own<Node> newNode = nodeArena.allocateOwn<Node>(symbolName, which, params);
   1168         builtinDeclsByKind[which] = newNode;
   1169         builtinDecls[symbolName] = kj::mv(newNode);
   1170       }
   1171     }
   1172   }
   1173 }
   1174 
   1175 Compiler::Impl::~Impl() noexcept(false) {}
   1176 
   1177 void Compiler::Impl::clearWorkspace() {
   1178   // Make sure we reconstruct the workspace even if destroying it throws an exception.
   1179   KJ_DEFER(kj::ctor(workspace, *this));
   1180   kj::dtor(workspace);
   1181 }
   1182 
   1183 Compiler::CompiledModule& Compiler::Impl::addInternal(Module& parsedModule) {
   1184   kj::Own<CompiledModule>& slot = modules[&parsedModule];
   1185   if (slot.get() == nullptr) {
   1186     slot = kj::heap<CompiledModule>(*this, parsedModule);
   1187   }
   1188 
   1189   return *slot;
   1190 }
   1191 
   1192 uint64_t Compiler::Impl::addNode(uint64_t desiredId, Node& node) {
   1193   for (;;) {
   1194     auto insertResult = nodesById.insert(std::make_pair(desiredId, &node));
   1195     if (insertResult.second) {
   1196       return desiredId;
   1197     }
   1198 
   1199     // Only report an error if this ID is not bogus.  Actual IDs specified in the original source
   1200     // code are required to have the upper bit set.  Anything else must have been manufactured
   1201     // at some point to cover up an error.
   1202     if (desiredId & (1ull << 63)) {
   1203       node.addError(kj::str("Duplicate ID @0x", kj::hex(desiredId), "."));
   1204       insertResult.first->second->addError(
   1205           kj::str("ID @0x", kj::hex(desiredId), " originally used here."));
   1206     }
   1207 
   1208     // Assign a new bogus ID.
   1209     desiredId = nextBogusId++;
   1210   }
   1211 }
   1212 
   1213 kj::Maybe<Compiler::Node&> Compiler::Impl::findNode(uint64_t id) {
   1214   auto iter = nodesById.find(id);
   1215   if (iter == nodesById.end()) {
   1216     return nullptr;
   1217   } else {
   1218     return *iter->second;
   1219   }
   1220 }
   1221 
   1222 kj::Maybe<Compiler::Node&> Compiler::Impl::lookupBuiltin(kj::StringPtr name) {
   1223   auto iter = builtinDecls.find(name);
   1224   if (iter == builtinDecls.end()) {
   1225     return nullptr;
   1226   } else {
   1227     return *iter->second;
   1228   }
   1229 }
   1230 
   1231 Compiler::Node& Compiler::Impl::getBuiltin(Declaration::Which which) {
   1232   auto iter = builtinDeclsByKind.find(which);
   1233   KJ_REQUIRE(iter != builtinDeclsByKind.end(), "invalid builtin", (uint)which);
   1234   return *iter->second;
   1235 }
   1236 
   1237 kj::Maybe<uint64_t> Compiler::Impl::lookup(uint64_t parent, kj::StringPtr childName) {
   1238   // Looking up members does not use the workspace, so we don't need to lock it.
   1239   KJ_IF_MAYBE(parentNode, findNode(parent)) {
   1240     KJ_IF_MAYBE(child, parentNode->resolveMember(childName)) {
   1241       if (child->is<Resolver::ResolvedDecl>()) {
   1242         return child->get<Resolver::ResolvedDecl>().id;
   1243       } else {
   1244         // An alias. We don't support looking up aliases with this method.
   1245         return nullptr;
   1246       }
   1247     } else {
   1248       return nullptr;
   1249     }
   1250   } else {
   1251     KJ_FAIL_REQUIRE("lookup()s parameter 'parent' must be a known ID.", parent);
   1252   }
   1253 }
   1254 
   1255 kj::Maybe<schema::Node::SourceInfo::Reader> Compiler::Impl::getSourceInfo(uint64_t id) {
   1256   auto iter = sourceInfoById.find(id);
   1257   if (iter == sourceInfoById.end()) {
   1258     return nullptr;
   1259   } else {
   1260     return iter->second;
   1261   }
   1262 }
   1263 
   1264 Orphan<List<schema::CodeGeneratorRequest::RequestedFile::Import>>
   1265     Compiler::Impl::getFileImportTable(Module& module, Orphanage orphanage) {
   1266   return addInternal(module).getFileImportTable(orphanage);
   1267 }
   1268 
   1269 Orphan<List<schema::Node::SourceInfo>> Compiler::Impl::getAllSourceInfo(Orphanage orphanage) {
   1270   auto result = orphanage.newOrphan<List<schema::Node::SourceInfo>>(sourceInfoById.size());
   1271 
   1272   auto builder = result.get();
   1273   size_t i = 0;
   1274   for (auto& entry: sourceInfoById) {
   1275     builder.setWithCaveats(i++, entry.second);
   1276   }
   1277 
   1278   return result;
   1279 }
   1280 
   1281 void Compiler::Impl::eagerlyCompile(uint64_t id, uint eagerness,
   1282                                     const SchemaLoader& finalLoader) {
   1283   KJ_IF_MAYBE(node, findNode(id)) {
   1284     std::unordered_map<Node*, uint> seen;
   1285     kj::Vector<schema::Node::SourceInfo::Reader> sourceInfos;
   1286     node->traverse(eagerness, seen, finalLoader, sourceInfos);
   1287 
   1288     // Copy the SourceInfo structures into permanent space so that they aren't invalidated when
   1289     // clearWorkspace() is called.
   1290     for (auto& sourceInfo: sourceInfos) {
   1291       auto words = nodeArena.allocateArray<word>(sourceInfo.totalSize().wordCount + 1);
   1292       memset(words.begin(), 0, words.asBytes().size());
   1293       copyToUnchecked(sourceInfo, words);
   1294       sourceInfoById.insert(std::make_pair(sourceInfo.getId(),
   1295           readMessageUnchecked<schema::Node::SourceInfo>(words.begin())));
   1296     }
   1297   } else {
   1298     KJ_FAIL_REQUIRE("id did not come from this Compiler.", id);
   1299   }
   1300 }
   1301 
   1302 void Compiler::Impl::load(const SchemaLoader& loader, uint64_t id) const {
   1303   // We know that this load() is only called from the bootstrap loader which is already protected
   1304   // by our mutex, so we can drop thread-safety.
   1305   auto& self = const_cast<Compiler::Impl&>(*this);
   1306 
   1307   KJ_IF_MAYBE(node, self.findNode(id)) {
   1308     node->getBootstrapSchema();
   1309   }
   1310 }
   1311 
   1312 void Compiler::Impl::loadFinal(const SchemaLoader& loader, uint64_t id) {
   1313   KJ_IF_MAYBE(node, findNode(id)) {
   1314     node->loadFinalSchema(loader);
   1315   }
   1316 }
   1317 
   1318 // =======================================================================================
   1319 
   1320 Compiler::Compiler(AnnotationFlag annotationFlag)
   1321     : impl(kj::heap<Impl>(annotationFlag)),
   1322       loader(*this) {}
   1323 Compiler::~Compiler() noexcept(false) {}
   1324 
   1325 Compiler::ModuleScope Compiler::add(Module& module) const {
   1326   Node& root = impl.lockExclusive()->get()->addInternal(module).getRootNode();
   1327   return ModuleScope(*this, root.getId(), root);
   1328 }
   1329 
   1330 kj::Maybe<uint64_t> Compiler::lookup(uint64_t parent, kj::StringPtr childName) const {
   1331   return impl.lockExclusive()->get()->lookup(parent, childName);
   1332 }
   1333 
   1334 kj::Maybe<schema::Node::SourceInfo::Reader> Compiler::getSourceInfo(uint64_t id) const {
   1335   return impl.lockExclusive()->get()->getSourceInfo(id);
   1336 }
   1337 
   1338 Orphan<List<schema::CodeGeneratorRequest::RequestedFile::Import>>
   1339     Compiler::getFileImportTable(Module& module, Orphanage orphanage) const {
   1340   return impl.lockExclusive()->get()->getFileImportTable(module, orphanage);
   1341 }
   1342 
   1343 Orphan<List<schema::Node::SourceInfo>> Compiler::getAllSourceInfo(Orphanage orphanage) const {
   1344   return impl.lockExclusive()->get()->getAllSourceInfo(orphanage);
   1345 }
   1346 
   1347 void Compiler::eagerlyCompile(uint64_t id, uint eagerness) const {
   1348   impl.lockExclusive()->get()->eagerlyCompile(id, eagerness, loader);
   1349 }
   1350 
   1351 void Compiler::clearWorkspace() const {
   1352   impl.lockExclusive()->get()->clearWorkspace();
   1353 }
   1354 
   1355 void Compiler::load(const SchemaLoader& loader, uint64_t id) const {
   1356   impl.lockExclusive()->get()->loadFinal(loader, id);
   1357 }
   1358 
   1359 // -----------------------------------------------------------------------------
   1360 
   1361 class Compiler::ErrorIgnorer: public ErrorReporter {
   1362 public:
   1363   void addError(uint32_t startByte, uint32_t endByte, kj::StringPtr message) override {}
   1364   bool hadErrors() override { return false; }
   1365 
   1366   static ErrorIgnorer instance;
   1367 };
   1368 Compiler::ErrorIgnorer Compiler::ErrorIgnorer::instance;
   1369 
   1370 kj::Maybe<Type> Compiler::CompiledType::getSchema() {
   1371   capnp::word scratch[32];
   1372   memset(&scratch, 0, sizeof(scratch));
   1373   capnp::MallocMessageBuilder message(scratch);
   1374   auto builder = message.getRoot<schema::Type>();
   1375 
   1376   {
   1377     auto lock = compiler.impl.lockShared();
   1378     decl.get(lock).compileAsType(ErrorIgnorer::instance, builder);
   1379   }
   1380 
   1381   // No need to pass `scope` as second parameter since CompiledType always represents a type
   1382   // expression evaluated free-standing, not in any scope.
   1383   return compiler.loader.getType(builder.asReader());
   1384 }
   1385 
   1386 Compiler::CompiledType Compiler::CompiledType::clone() {
   1387   kj::ExternalMutexGuarded<BrandedDecl> newDecl;
   1388   {
   1389     auto lock = compiler.impl.lockExclusive();
   1390     newDecl.set(lock, kj::cp(decl.get(lock)));
   1391   }
   1392   return CompiledType(compiler, kj::mv(newDecl));
   1393 }
   1394 
   1395 kj::Maybe<Compiler::CompiledType> Compiler::CompiledType::getMember(kj::StringPtr name) {
   1396   kj::ExternalMutexGuarded<BrandedDecl> newDecl;
   1397   bool found = false;
   1398 
   1399   {
   1400     auto lock = compiler.impl.lockShared();
   1401     KJ_IF_MAYBE(member, decl.get(lock).getMember(name, {})) {
   1402       newDecl.set(lock, kj::mv(*member));
   1403       found = true;
   1404     }
   1405   }
   1406 
   1407   if (found) {
   1408     return CompiledType(compiler, kj::mv(newDecl));
   1409   } else {
   1410     return nullptr;
   1411   }
   1412 }
   1413 
   1414 kj::Maybe<Compiler::CompiledType> Compiler::CompiledType::applyBrand(
   1415     kj::Array<CompiledType> arguments) {
   1416   kj::ExternalMutexGuarded<BrandedDecl> newDecl;
   1417   bool found = false;
   1418 
   1419   {
   1420     auto lock = compiler.impl.lockShared();
   1421     auto args = KJ_MAP(arg, arguments) { return kj::mv(arg.decl.get(lock)); };
   1422     KJ_IF_MAYBE(member, decl.get(lock).applyParams(kj::mv(args), {})) {
   1423       newDecl.set(lock, kj::mv(*member));
   1424       found = true;
   1425     }
   1426   }
   1427 
   1428   if (found) {
   1429     return CompiledType(compiler, kj::mv(newDecl));
   1430   } else {
   1431     return nullptr;
   1432   }
   1433 }
   1434 
   1435 Compiler::CompiledType Compiler::ModuleScope::getRoot() {
   1436   kj::ExternalMutexGuarded<BrandedDecl> newDecl;
   1437 
   1438   {
   1439     auto lock = compiler.impl.lockExclusive();
   1440     auto brandScope = kj::refcounted<BrandScope>(ErrorIgnorer::instance, node.getId(), 0, node);
   1441     Resolver::ResolvedDecl decl { node.getId(), 0, 0, node.getKind(), &node, nullptr };
   1442     newDecl.set(lock, BrandedDecl(kj::mv(decl), kj::mv(brandScope), {}));
   1443   }
   1444 
   1445   return CompiledType(compiler, kj::mv(newDecl));
   1446 }
   1447 
   1448 kj::Maybe<Compiler::CompiledType> Compiler::ModuleScope::evalType(
   1449     Expression::Reader expression, ErrorReporter& errorReporter) {
   1450   kj::ExternalMutexGuarded<BrandedDecl> newDecl;
   1451   bool found = false;
   1452 
   1453   {
   1454     auto lock = compiler.impl.lockExclusive();
   1455     auto brandScope = kj::refcounted<BrandScope>(errorReporter, node.getId(), 0, node);
   1456     KJ_IF_MAYBE(result, brandScope->compileDeclExpression(
   1457         expression, node, ImplicitParams::none())) {
   1458       newDecl.set(lock, kj::mv(*result));
   1459       found = true;
   1460     };
   1461   }
   1462 
   1463   if (found) {
   1464     return CompiledType(compiler, kj::mv(newDecl));
   1465   } else {
   1466     return nullptr;
   1467   }
   1468 }
   1469 
   1470 }  // namespace compiler
   1471 }  // namespace capnp