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

node-translator.h (9958B)


      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 #pragma once
     23 
     24 #include <capnp/orphan.h>
     25 #include <capnp/compiler/grammar.capnp.h>
     26 #include <capnp/schema.capnp.h>
     27 #include <capnp/dynamic.h>
     28 #include <kj/vector.h>
     29 #include <kj/one-of.h>
     30 #include "error-reporter.h"
     31 #include "resolver.h"
     32 #include "generics.h"
     33 #include <map>
     34 
     35 CAPNP_BEGIN_HEADER
     36 
     37 namespace capnp {
     38 namespace compiler {
     39 
     40 class NodeTranslator {
     41   // Translates one node in the schema from AST form to final schema form.  A "node" is anything
     42   // that has a unique ID, such as structs, enums, constants, and annotations, but not fields,
     43   // unions, enumerants, or methods (the latter set have 16-bit ordinals but not 64-bit global IDs).
     44 public:
     45   NodeTranslator(Resolver& resolver, ErrorReporter& errorReporter,
     46                  const Declaration::Reader& decl, Orphan<schema::Node> wipNode,
     47                  bool compileAnnotations);
     48   // Construct a NodeTranslator to translate the given declaration.  The wipNode starts out with
     49   // `displayName`, `id`, `scopeId`, and `nestedNodes` already initialized.  The `NodeTranslator`
     50   // fills in the rest.
     51 
     52   ~NodeTranslator() noexcept(false);
     53 
     54   struct NodeSet {
     55     schema::Node::Reader node;
     56     // The main node.
     57 
     58     kj::Array<schema::Node::Reader> auxNodes;
     59     // Auxiliary nodes that were produced when translating this node and should be loaded along
     60     // with it.  In particular, structs that contain groups (or named unions) spawn extra nodes
     61     // representing those, and interfaces spawn struct nodes representing method params/results.
     62 
     63     kj::Array<schema::Node::SourceInfo::Reader> sourceInfo;
     64     // The SourceInfo for the node and all aux nodes.
     65   };
     66 
     67   NodeSet getBootstrapNode();
     68   // Get an incomplete version of the node in which pointer-typed value expressions have not yet
     69   // been translated.  Instead, for all `schema.Value` objects representing pointer-type values,
     70   // the value is set to an appropriate "empty" value.  This version of the schema can be used to
     71   // bootstrap the dynamic API which can then in turn be used to encode the missing complex values.
     72   //
     73   // If the final node has already been built, this will actually return the final node (in fact,
     74   // it's the same node object).
     75 
     76   NodeSet finish(Schema selfUnboundBootstrap);
     77   // Finish translating the node (including filling in all the pieces that are missing from the
     78   // bootstrap node) and return it.
     79   //
     80   // `selfUnboundBootstrap` is a Schema build using the Node returned by getBootstrapNode(), and
     81   // with generic parameters "unbound", i.e. it was returned by SchemaLoader::getUnbound().
     82 
     83   static kj::Maybe<Resolver::ResolveResult> compileDecl(
     84       uint64_t scopeId, uint scopeParameterCount, Resolver& resolver, ErrorReporter& errorReporter,
     85       Expression::Reader expression, schema::Brand::Builder brandBuilder);
     86   // Compile a one-off declaration expression without building a NodeTranslator. Used for
     87   // evaluating aliases.
     88   //
     89   // `brandBuilder` may be used to construct a message which will fill in ResolvedDecl::brand in
     90   // the result.
     91 
     92 private:
     93   class DuplicateNameDetector;
     94   class DuplicateOrdinalDetector;
     95   class StructLayout;
     96   class StructTranslator;
     97 
     98   Resolver& resolver;
     99   ErrorReporter& errorReporter;
    100   Orphanage orphanage;
    101   bool compileAnnotations;
    102   kj::Own<BrandScope> localBrand;
    103 
    104   Orphan<schema::Node> wipNode;
    105   // The work-in-progress schema node.
    106 
    107   Orphan<schema::Node::SourceInfo> sourceInfo;
    108   // Doc comments and other source info for this node.
    109 
    110   struct AuxNode {
    111     Orphan<schema::Node> node;
    112     Orphan<schema::Node::SourceInfo> sourceInfo;
    113   };
    114 
    115   kj::Vector<AuxNode> groups;
    116   // If this is a struct node and it contains groups, these are the nodes for those groups,  which
    117   // must be loaded together with the top-level node.
    118 
    119   kj::Vector<AuxNode> paramStructs;
    120   // If this is an interface, these are the auto-generated structs representing params and results.
    121 
    122   struct UnfinishedValue {
    123     Expression::Reader source;
    124     schema::Type::Reader type;
    125     kj::Maybe<Schema> typeScope;
    126     schema::Value::Builder target;
    127   };
    128   kj::Vector<UnfinishedValue> unfinishedValues;
    129   // List of values in `wipNode` which have not yet been interpreted, because they are structs
    130   // or lists and as such interpreting them require using the types' schemas (to take advantage
    131   // of the dynamic API).  Once bootstrap schemas have been built, they can be used to interpret
    132   // these values.
    133 
    134   void compileNode(Declaration::Reader decl, schema::Node::Builder builder);
    135 
    136   void compileConst(Declaration::Const::Reader decl, schema::Node::Const::Builder builder);
    137   void compileAnnotation(Declaration::Annotation::Reader decl,
    138                          schema::Node::Annotation::Builder builder);
    139 
    140   void compileEnum(Void decl, List<Declaration>::Reader members,
    141                    schema::Node::Builder builder);
    142   void compileStruct(Void decl, List<Declaration>::Reader members,
    143                      schema::Node::Builder builder);
    144   void compileInterface(Declaration::Interface::Reader decl,
    145                         List<Declaration>::Reader members,
    146                         schema::Node::Builder builder);
    147   // The `members` arrays contain only members with ordinal numbers, in code order.  Other members
    148   // are handled elsewhere.
    149 
    150   template <typename InitBrandFunc>
    151   uint64_t compileParamList(kj::StringPtr methodName, uint16_t ordinal, bool isResults,
    152                             Declaration::ParamList::Reader paramList,
    153                             typename List<Declaration::BrandParameter>::Reader implicitParams,
    154                             InitBrandFunc&& initBrand);
    155   // Compile a param (or result) list and return the type ID of the struct type.
    156 
    157   kj::Maybe<BrandedDecl> compileDeclExpression(
    158       Expression::Reader source, ImplicitParams implicitMethodParams);
    159   // Compile an expression which is expected to resolve to a declaration or type expression.
    160 
    161   bool compileType(Expression::Reader source, schema::Type::Builder target,
    162                    ImplicitParams implicitMethodParams);
    163   // Returns false if there was a problem, in which case value expressions of this type should
    164   // not be parsed.
    165 
    166   void compileDefaultDefaultValue(schema::Type::Reader type, schema::Value::Builder target);
    167   // Initializes `target` to contain the "default default" value for `type`.
    168 
    169   void compileBootstrapValue(
    170       Expression::Reader source, schema::Type::Reader type, schema::Value::Builder target,
    171       kj::Maybe<Schema> typeScope = nullptr);
    172   // Calls compileValue() if this value should be interpreted at bootstrap time.  Otheriwse,
    173   // adds the value to `unfinishedValues` for later evaluation.
    174   //
    175   // If `type` comes from some other node, `typeScope` is the schema for that node. Otherwise the
    176   // scope of the type expression is assumed to be this node (meaning, in particular, that no
    177   // generic type parameters are bound).
    178 
    179   void compileValue(Expression::Reader source, schema::Type::Reader type,
    180                     Schema typeScope, schema::Value::Builder target, bool isBootstrap);
    181   // Interprets the value expression and initializes `target` with the result.
    182 
    183   kj::Maybe<DynamicValue::Reader> readConstant(Expression::Reader name, bool isBootstrap);
    184   // Get the value of the given constant.  May return null if some error occurs, which will already
    185   // have been reported.
    186 
    187   kj::Maybe<kj::Array<const byte>> readEmbed(LocatedText::Reader filename);
    188   // Read a raw file for embedding.
    189 
    190   Orphan<List<schema::Annotation>> compileAnnotationApplications(
    191       List<Declaration::AnnotationApplication>::Reader annotations,
    192       kj::StringPtr targetsFlagName);
    193 };
    194 
    195 class ValueTranslator {
    196 public:
    197   class Resolver {
    198   public:
    199     virtual kj::Maybe<DynamicValue::Reader> resolveConstant(Expression::Reader name) = 0;
    200     virtual kj::Maybe<kj::Array<const byte>> readEmbed(LocatedText::Reader filename) = 0;
    201   };
    202 
    203   ValueTranslator(Resolver& resolver, ErrorReporter& errorReporter, Orphanage orphanage)
    204       : resolver(resolver), errorReporter(errorReporter), orphanage(orphanage) {}
    205 
    206   kj::Maybe<Orphan<DynamicValue>> compileValue(Expression::Reader src, Type type);
    207 
    208   void fillStructValue(DynamicStruct::Builder builder,
    209                        List<Expression::Param>::Reader assignments);
    210   // Interprets the given assignments and uses them to fill in the given struct builder.
    211 
    212 private:
    213   Resolver& resolver;
    214   ErrorReporter& errorReporter;
    215   Orphanage orphanage;
    216 
    217   Orphan<DynamicValue> compileValueInner(Expression::Reader src, Type type);
    218   // Helper for compileValue().
    219 
    220   kj::String makeNodeName(Schema node);
    221   kj::String makeTypeName(Type type);
    222 
    223   kj::Maybe<ListSchema> makeListSchemaOf(schema::Type::Reader elementType);
    224 };
    225 
    226 }  // namespace compiler
    227 }  // namespace capnp
    228 
    229 CAPNP_END_HEADER