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