node-translator.h 9.08 KB
Newer Older
Kenton Varda's avatar
Kenton Varda committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef CAPNP_COMPILER_NODE_TRANSLATOR_H_
#define CAPNP_COMPILER_NODE_TRANSLATOR_H_

#include <capnp/orphan.h>
#include <capnp/compiler/grammar.capnp.h>
#include <capnp/schema.capnp.h>
#include <capnp/schema-loader.h>
#include <capnp/dynamic.h>
#include <kj/vector.h>
#include "error-reporter.h"

namespace capnp {
namespace compiler {

class NodeTranslator {
  // Translates one node in the schema from AST form to final schema form.  A "node" is anything
  // that has a unique ID, such as structs, enums, constants, and annotations, but not fields,
  // unions, enumerants, or methods (the latter set have 16-bit ordinals but not 64-bit global IDs).

public:
  class Resolver {
    // Callback class used to find other nodes relative to this one.

  public:
    struct ResolvedName {
      uint64_t id;
      Declaration::Body::Which kind;
    };

    virtual kj::Maybe<ResolvedName> resolve(const DeclName::Reader& name) const = 0;
    // Look up the given name, relative to this node, and return basic information about the
    // target.

57 58 59 60 61 62 63
    virtual kj::Maybe<Schema> resolveBootstrapSchema(uint64_t id) const = 0;
    // Get the schema for the given ID.  If a schema is returned, it must be safe to traverse its
    // dependencies using Schema::getDependency().  A schema that is only at the bootstrap stage
    // is acceptable.
    //
    // Throws an exception if the id is not one that was found by calling resolve() or by
    // traversing other schemas.  Returns null if the ID is recognized, but the corresponding
64
    // schema node failed to be built for reasons that were already reported.
Kenton Varda's avatar
Kenton Varda committed
65

66 67 68 69 70
    virtual kj::Maybe<schema::Node::Reader> resolveFinalSchema(uint64_t id) const = 0;
    // Get the final schema for the given ID.  A bootstrap schema is not acceptable.  A raw
    // node reader is returned rather than a Schema object because using a Schema object built
    // by the final schema loader could trigger lazy initialization of dependencies which could
    // lead to a cycle and deadlock.
71 72 73 74
    //
    // Throws an exception if the id is not one that was found by calling resolve() 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.
Kenton Varda's avatar
Kenton Varda committed
75 76 77
  };

  NodeTranslator(const Resolver& resolver, const ErrorReporter& errorReporter,
78 79
                 const Declaration::Reader& decl, Orphan<schema::Node> wipNode,
                 bool compileAnnotations);
Kenton Varda's avatar
Kenton Varda committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
  // Construct a NodeTranslator to translate the given declaration.  The wipNode starts out with
  // `displayName`, `id`, `scopeId`, and `nestedNodes` already initialized.  The `NodeTranslator`
  // fills in the rest.

  schema::Node::Reader getBootstrapNode() { return wipNode.getReader(); }
  // Get an incomplete version of the node in which pointer-typed value expressions have not yet
  // been translated.  Instead, for all `schema.Value` objects representing pointer-type values,
  // the value is set to an appropriate "empty" value.  This version of the schema can be used to
  // bootstrap the dynamic API which can then in turn be used to encode the missing complex values.
  //
  // If the final node has already been built, this will actually return the final node (in fact,
  // it's the same node object).

  schema::Node::Reader finish();
  // Finish translating the node (including filling in all the pieces that are missing from the
  // bootstrap node) and return it.

private:
  const Resolver& resolver;
  const ErrorReporter& errorReporter;
100
  bool compileAnnotations;
Kenton Varda's avatar
Kenton Varda committed
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151

  Orphan<schema::Node> wipNode;
  // The work-in-progress schema node.

  struct UnfinishedValue {
    ValueExpression::Reader source;
    schema::Type::Reader type;
    schema::Value::Builder target;
  };
  kj::Vector<UnfinishedValue> unfinishedValues;
  // List of values in `wipNode` which have not yet been interpreted, because they are structs
  // or lists and as such interpreting them require using the types' schemas (to take advantage
  // of the dynamic API).  Once bootstrap schemas have been built, they can be used to interpret
  // these values.

  void compileNode(Declaration::Reader decl, schema::Node::Builder builder);

  void checkMembers(List<Declaration>::Reader nestedDecls, Declaration::Body::Which parentKind);
  // Check the given member list for errors, including detecting duplicate names and detecting
  // out-of-place declarations.

  void disallowNested(List<Declaration>::Reader nestedDecls);
  // Complain if the nested decl list is non-empty.

  void compileFile(Declaration::Reader decl, schema::FileNode::Builder builder);
  void compileConst(Declaration::Const::Reader decl, schema::ConstNode::Builder builder);
  void compileAnnotation(Declaration::Annotation::Reader decl,
                         schema::AnnotationNode::Builder builder);

  class DuplicateOrdinalDetector;
  class StructLayout;
  class StructTranslator;

  void compileEnum(Declaration::Enum::Reader decl, List<Declaration>::Reader members,
                   schema::EnumNode::Builder builder);
  void compileStruct(Declaration::Struct::Reader decl, List<Declaration>::Reader members,
                     schema::StructNode::Builder builder);
  void compileInterface(Declaration::Interface::Reader decl, List<Declaration>::Reader members,
                        schema::InterfaceNode::Builder builder);
  // The `members` arrays contain only members with ordinal numbers, in code order.  Other members
  // are handled elsewhere.

  bool compileType(TypeExpression::Reader source, schema::Type::Builder target);
  // Returns false if there was a problem, in which case value expressions of this type should
  // not be parsed.

  void compileDefaultDefaultValue(schema::Type::Reader type, schema::Value::Builder target);
  // Initializes `target` to contain the "default default" value for `type`.

  void compileBootstrapValue(ValueExpression::Reader source, schema::Type::Reader type,
                             schema::Value::Builder target);
152 153
  // Calls compileValue() if this value should be interpreted at bootstrap time.  Otheriwse,
  // adds the value to `unfinishedValues` for later evaluation.
Kenton Varda's avatar
Kenton Varda committed
154

155 156 157 158 159 160 161 162 163 164 165 166
  void compileValue(ValueExpression::Reader source, schema::Type::Reader type,
                    schema::Value::Builder target, bool isBootstrap);
  // Interprets the value expression and initializes `target` with the result.

  class DynamicSlot;

  void compileValue(ValueExpression::Reader src, DynamicSlot& dst, bool isBootstrap);
  // Fill in `dst` (which effectively points to a struct field or list element) with the given
  // value.

  void compileValueInner(ValueExpression::Reader src, DynamicSlot& dst, bool isBootstrap);
  // Helper for compileValue().
Kenton Varda's avatar
Kenton Varda committed
167

Kenton Varda's avatar
Kenton Varda committed
168 169 170 171 172 173
  void copyValue(schema::Value::Reader src, schema::Type::Reader srcType,
                 schema::Value::Builder dst, schema::Type::Reader dstType,
                 ValueExpression::Reader errorLocation);
  // Copy a value from one schema to another, possibly coercing the type if compatible, or
  // reporting an error otherwise.

174 175
  kj::Maybe<DynamicValue::Reader> readConstant(DeclName::Reader name, bool isBootstrap,
                                               ValueExpression::Reader errorLocation);
176 177
  // Get the value of the given constant.  May return null if some error occurs, which will already
  // have been reported.
178

179 180 181
  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.
182

Kenton Varda's avatar
Kenton Varda committed
183 184 185 186 187 188 189 190 191
  Orphan<List<schema::Annotation>> compileAnnotationApplications(
      List<Declaration::AnnotationApplication>::Reader annotations,
      kj::StringPtr targetsFlagName);
};

}  // namespace compiler
}  // namespace capnp

#endif  // CAPNP_COMPILER_NODE_TRANSLATOR_H_