schema.capnp 16.1 KB
Newer Older
Kenton Varda's avatar
Kenton Varda committed
1 2
# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
# Licensed under the MIT License:
3
#
Kenton Varda's avatar
Kenton Varda committed
4 5 6 7 8 9
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
10
#
Kenton Varda's avatar
Kenton Varda committed
11 12
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
13
#
Kenton Varda's avatar
Kenton Varda committed
14 15 16 17 18 19 20
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
21

22
using Cxx = import "/capnp/c++.capnp";
23

Kenton Varda's avatar
Kenton Varda committed
24
@0xa93fc509624c72d9;
25
$Cxx.namespace("capnp::schema");
26 27 28 29 30 31 32 33 34 35 36 37 38

using Id = UInt64;
# The globally-unique ID of a file, type, or annotation.

struct Node {
  id @0 :Id;

  displayName @1 :Text;
  # Name to present to humans to identify this Node.  You should not attempt to parse this.  Its
  # format could change.  It is not guaranteed to be unique.
  #
  # (On Zooko's triangle, this is the node's nickname.)

Kenton Varda's avatar
Kenton Varda committed
39
  displayNamePrefixLength @2 :UInt32;
Kenton Varda's avatar
Kenton Varda committed
40 41 42
  # If you want a shorter version of `displayName` (just naming this node, without its surrounding
  # scope), chop off this many characters from the beginning of `displayName`.

Kenton Varda's avatar
Kenton Varda committed
43
  scopeId @3 :Id;
44
  # ID of the lexical parent node.  Typically, the scope node will have a NestedNode pointing back
Kenton Varda's avatar
Kenton Varda committed
45 46 47 48
  # at this node, but robust code should avoid relying on this (and, in fact, group nodes are not
  # listed in the outer struct's nestedNodes, since they are listed in the fields).  `scopeId` is
  # zero if the node has no parent, which is normally only the case with files, but should be
  # allowed for any kind of node (in order to make runtime type generation easier).
49

Kenton Varda's avatar
Kenton Varda committed
50 51 52
  parameters @32 :List(Parameter);
  # If this node is parameterized (generic), the list of parameters. Empty for non-generic types.

53 54 55 56
  isGeneric @33 :Bool;
  # True if this node is generic, meaning that it or one of its parent scopes has a non-empty
  # `parameters`.

Kenton Varda's avatar
Kenton Varda committed
57 58 59 60 61 62
  struct Parameter {
    # Information about one of the node's parameters.

    name @0 :Text;
  }

Kenton Varda's avatar
Kenton Varda committed
63
  nestedNodes @4 :List(NestedNode);
64 65 66 67
  # List of nodes nested within this node, along with the names under which they were declared.

  struct NestedNode {
    name @0 :Text;
David Renshaw's avatar
David Renshaw committed
68
    # Unqualified symbol name.  Unlike Node.displayName, this *can* be used programmatically.
69 70 71 72 73 74 75 76
    #
    # (On Zooko's triangle, this is the node's petname according to its parent scope.)

    id @1 :Id;
    # ID of the nested node.  Typically, the target node's scopeId points back to this node, but
    # robust code should avoid relying on this.
  }

Kenton Varda's avatar
Kenton Varda committed
77
  annotations @5 :List(Annotation);
78 79
  # Annotations applied to this node.

Kenton Varda's avatar
Kenton Varda committed
80
  union {
81 82
    # Info specific to each kind of node.

Kenton Varda's avatar
Kenton Varda committed
83 84 85
    file @6 :Void;

    struct :group {
86 87 88 89 90
      dataWordCount @7 :UInt16;
      # Size of the data section, in words.

      pointerCount @8 :UInt16;
      # Size of the pointer section, in pointers (which are one word each).
Kenton Varda's avatar
Kenton Varda committed
91 92 93 94 95 96 97 98 99 100 101

      preferredListEncoding @9 :ElementSize;
      # The preferred element size to use when encoding a list of this struct.  If this is anything
      # other than `inlineComposite` then the struct is one word or less in size and is a candidate
      # for list packing optimization.

      isGroup @10 :Bool;
      # If true, then this "struct" node is actually not an independent node, but merely represents
      # some named union or group within a particular parent struct.  This node's scopeId refers
      # to the parent struct, which may itself be a union/group in yet another struct.
      #
102
      # All group nodes share the same dataWordCount and pointerCount as the top-level
Kenton Varda's avatar
Kenton Varda committed
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
      # struct, and their fields live in the same ordinal and offset spaces as all other fields in
      # the struct.
      #
      # Note that a named union is considered a special kind of group -- in fact, a named union
      # is exactly equivalent to a group that contains nothing but an unnamed union.

      discriminantCount @11 :UInt16;
      # Number of fields in this struct which are members of an anonymous union, and thus may
      # overlap.  If this is non-zero, then a 16-bit discriminant is present indicating which
      # of the overlapping fields is active.  This can never be 1 -- if it is non-zero, it must be
      # two or more.
      #
      # Note that the fields of an unnamed union are considered fields of the scope containing the
      # union -- an unnamed union is not its own group.  So, a top-level struct may contain a
      # non-zero discriminant count.  Named unions, on the other hand, are equivalent to groups
      # containing unnamed unions.  So, a named union has its own independent schema node, with
      # `isGroup` = true.

      discriminantOffset @12 :UInt32;
      # If `discriminantCount` is non-zero, this is the offset of the union discriminant, in
      # multiples of 16 bits.

      fields @13 :List(Field);
      # Fields defined within this scope (either the struct's top-level fields, or the fields of
      # a particular group; see `isGroup`).
      #
      # The fields are sorted by ordinal number, but note that because groups share the same
      # ordinal space, the field's index in this list is not necessarily exactly its ordinal.
      # On the other hand, the field's position in this list does remain the same even as the
      # protocol evolves, since it is not possible to insert or remove an earlier ordinal.
      # Therefore, for most use cases, if you want to identify a field by number, it may make the
      # most sense to use the field's index in this list rather than its ordinal.
    }
136

137 138 139 140
    enum :group {
      enumerants@14 :List(Enumerant);
      # Enumerants ordered by numeric value (ordinal).
    }
141

142 143 144
    interface :group {
      methods @15 :List(Method);
      # Methods ordered by ordinal.
145

146
      superclasses @31 :List(Superclass);
147
      # Superclasses of this interface.
148
    }
149

Kenton Varda's avatar
Kenton Varda committed
150 151 152 153
    const :group {
      type @16 :Type;
      value @17 :Value;
    }
154

Kenton Varda's avatar
Kenton Varda committed
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
    annotation :group {
      type @18 :Type;

      targetsFile @19 :Bool;
      targetsConst @20 :Bool;
      targetsEnum @21 :Bool;
      targetsEnumerant @22 :Bool;
      targetsStruct @23 :Bool;
      targetsField @24 :Bool;
      targetsUnion @25 :Bool;
      targetsGroup @26 :Bool;
      targetsInterface @27 :Bool;
      targetsMethod @28 :Bool;
      targetsParam @29 :Bool;
      targetsAnnotation @30 :Bool;
    }
171 172 173
  }
}

Kenton Varda's avatar
Kenton Varda committed
174 175
struct Field {
  # Schema for a field of a struct.
176

Kenton Varda's avatar
Kenton Varda committed
177
  name @0 :Text;
178

Kenton Varda's avatar
Kenton Varda committed
179 180 181 182 183 184 185
  codeOrder @1 :UInt16;
  # Indicates where this member appeared in the code, relative to other members.
  # Code ordering may have semantic relevance -- programmers tend to place related fields
  # together.  So, using code ordering makes sense in human-readable formats where ordering is
  # otherwise irrelevant, like JSON.  The values of codeOrder are tightly-packed, so the maximum
  # value is count(members) - 1.  Fields that are members of a union are only ordered relative to
  # the other members of that union, so the maximum value there is count(union.members).
186

Kenton Varda's avatar
Kenton Varda committed
187
  annotations @2 :List(Annotation);
188

189 190 191
  const noDiscriminant :UInt16 = 0xffff;

  discriminantValue @3 :UInt16 = Field.noDiscriminant;
Kenton Varda's avatar
Kenton Varda committed
192
  # If the field is in a union, this is the value which the union's discriminant should take when
193
  # the field is active.  If the field is not in a union, this is 0xffff.
194

Kenton Varda's avatar
Kenton Varda committed
195
  union {
196 197
    slot :group {
      # A regular, non-group, non-fixed-list field.
198

Kenton Varda's avatar
Kenton Varda committed
199 200 201 202
      offset @4 :UInt32;
      # Offset, in units of the field's size, from the beginning of the section in which the field
      # resides.  E.g. for a UInt32 field, multiply this by 4 to get the byte offset from the
      # beginning of the data section.
203

Kenton Varda's avatar
Kenton Varda committed
204 205
      type @5 :Type;
      defaultValue @6 :Value;
206 207 208 209 210 211

      hadExplicitDefault @10 :Bool;
      # Whether the default value was specified explicitly.  Non-explicit default values are always
      # zero or empty values.  Usually, whether the default value was explicit shouldn't matter.
      # The main use case for this flag is for structs representing method parameters:
      # explicitly-defaulted parameters may be allowed to be omitted when calling the method.
Kenton Varda's avatar
Kenton Varda committed
212
    }
213

214 215 216 217 218 219
    group :group {
      # A group.

      typeId @7 :Id;
      # The ID of the group's node.
    }
Kenton Varda's avatar
Kenton Varda committed
220
  }
221

Kenton Varda's avatar
Kenton Varda committed
222 223 224 225 226 227 228 229 230
  ordinal :union {
    implicit @8 :Void;
    explicit @9 :UInt16;
    # The original ordinal number given to the field.  You probably should NOT use this; if you need
    # a numeric identifier for a field, use its position within the field array for its scope.
    # The ordinal is given here mainly just so that the original schema text can be reproduced given
    # the compiled version -- i.e. so that `capnp compile -ocapnp` can do its job.
  }
}
231

Kenton Varda's avatar
Kenton Varda committed
232 233
struct Enumerant {
  # Schema for member of an enum.
234

Kenton Varda's avatar
Kenton Varda committed
235
  name @0 :Text;
236

Kenton Varda's avatar
Kenton Varda committed
237 238 239
  codeOrder @1 :UInt16;
  # Specifies order in which the enumerants were declared in the code.
  # Like Struct.Field.codeOrder.
240

Kenton Varda's avatar
Kenton Varda committed
241 242
  annotations @2 :List(Annotation);
}
243

244 245 246 247 248
struct Superclass {
  id @0 :Id;
  brand @1 :Brand;
}

Kenton Varda's avatar
Kenton Varda committed
249 250
struct Method {
  # Schema for method of an interface.
251

Kenton Varda's avatar
Kenton Varda committed
252
  name @0 :Text;
253

Kenton Varda's avatar
Kenton Varda committed
254 255 256
  codeOrder @1 :UInt16;
  # Specifies order in which the methods were declared in the code.
  # Like Struct.Field.codeOrder.
257

258 259 260 261
  implicitParameters @7 :List(Node.Parameter);
  # The parameters listed in [] (typically, type / generic parameters), whose bindings are intended
  # to be inferred rather than specified explicitly, although not all languages support this.

262 263 264 265 266
  paramStructType @2 :Id;
  # ID of the parameter struct type.  If a named parameter list was specified in the method
  # declaration (rather than a single struct parameter type) then a corresponding struct type is
  # auto-generated.  Such an auto-generated type will not be listed in the interface's
  # `nestedNodes` and its `scopeId` will be zero -- it is completely detached from the namespace.
Kenton Varda's avatar
Kenton Varda committed
267 268 269 270
  # (Awkwardly, it does of course inherit generic parameters from the method's scope, which makes
  # this a situation where you can't just climb the scope chain to find where a particular
  # generic parameter was introduced. Making the `scopeId` zero was a mistake.)

271 272
  paramBrand @5 :Brand;
  # Brand of param struct type.
273

274 275
  resultStructType @3 :Id;
  # ID of the return struct type; similar to `paramStructType`.
276

277 278
  resultBrand @6 :Brand;
  # Brand of result struct type.
Kenton Varda's avatar
Kenton Varda committed
279

280
  annotations @4 :List(Annotation);
281 282
}

Kenton Varda's avatar
Kenton Varda committed
283 284
struct Type {
  # Represents a type expression.
285

Kenton Varda's avatar
Kenton Varda committed
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
  union {
    # The ordinals intentionally match those of Value.

    void @0 :Void;
    bool @1 :Void;
    int8 @2 :Void;
    int16 @3 :Void;
    int32 @4 :Void;
    int64 @5 :Void;
    uint8 @6 :Void;
    uint16 @7 :Void;
    uint32 @8 :Void;
    uint64 @9 :Void;
    float32 @10 :Void;
    float64 @11 :Void;
    text @12 :Void;
    data @13 :Void;

304 305 306
    list :group {
      elementType @14 :Type;
    }
Kenton Varda's avatar
Kenton Varda committed
307

308 309
    enum :group {
      typeId @15 :Id;
310
      brand @21 :Brand;
311 312 313
    }
    struct :group {
      typeId @16 :Id;
314
      brand @22 :Brand;
315 316 317
    }
    interface :group {
      typeId @17 :Id;
318
      brand @23 :Brand;
Kenton Varda's avatar
Kenton Varda committed
319 320 321
    }

    anyPointer :union {
322 323 324 325 326 327 328 329 330 331 332 333
      unconstrained :union {
        # A regular AnyPointer.
        #
        # The name "unconstained" means as opposed to constraining it to match a type parameter.
        # In retrospect this name is probably a poor choice given that it may still be constrained
        # to be a struct, list, or capability.

        anyKind @18 :Void;       # truly AnyPointer
        struct @25 :Void;        # AnyStruct
        list @26 :Void;          # AnyList
        capability @27 :Void;    # Capability
      }
Kenton Varda's avatar
Kenton Varda committed
334 335 336 337

      parameter :group {
        # This is actually a reference to a type parameter defined within this scope.

338 339 340
        scopeId @19 :Id;
        # ID of the generic type whose parameter we're referencing. This should be a parent of the
        # current scope.
Kenton Varda's avatar
Kenton Varda committed
341 342 343 344

        parameterIndex @20 :UInt16;
        # Index of the parameter within the generic type's parameter list.
      }
345 346 347 348 349 350 351

      implicitMethodParameter :group {
        # This is actually a reference to an implicit (generic) parameter of a method. The only
        # legal context for this type to appear is inside Method.paramBrand or Method.resultBrand.

        parameterIndex @24 :UInt16;
      }
352
    }
Kenton Varda's avatar
Kenton Varda committed
353 354 355
  }
}

356 357 358
struct Brand {
  # Specifies bindings for parameters of generics. Since these bindings turn a generic into a
  # non-generic, we call it the "brand".
Kenton Varda's avatar
Kenton Varda committed
359 360 361 362 363 364 365 366 367

  scopes @0 :List(Scope);
  # For each of the target type and each of its parent scopes, a parameterization may be included
  # in this list. If no parameterization is included for a particular relevant scope, then either
  # that scope has no parameters or all parameters should be considered to be `AnyPointer`.

  struct Scope {
    scopeId @0 :Id;
    # ID of the scope to which these params apply.
Kenton Varda's avatar
Kenton Varda committed
368

369 370 371 372 373
    union {
      bind @1 :List(Binding);
      # List of parameter bindings.

      inherit @2 :Void;
David Renshaw's avatar
David Renshaw committed
374
      # The place where this Brand appears is actually within this scope or a sub-scope,
375 376
      # and the bindings for this scope should be inherited from the reference point.
    }
Kenton Varda's avatar
Kenton Varda committed
377 378 379 380 381 382 383 384 385
  }

  struct Binding {
    union {
      unbound @0 :Void;
      type @1 :Type;

      # TODO(someday): Allow non-type parameters? Unsure if useful.
    }
386 387 388
  }
}

Kenton Varda's avatar
Kenton Varda committed
389 390
struct Value {
  # Represents a value, e.g. a field default value, constant value, or annotation value.
391

Kenton Varda's avatar
Kenton Varda committed
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
  union {
    # The ordinals intentionally match those of Type.

    void @0 :Void;
    bool @1 :Bool;
    int8 @2 :Int8;
    int16 @3 :Int16;
    int32 @4 :Int32;
    int64 @5 :Int64;
    uint8 @6 :UInt8;
    uint16 @7 :UInt16;
    uint32 @8 :UInt32;
    uint64 @9 :UInt64;
    float32 @10 :Float32;
    float64 @11 :Float64;
    text @12 :Text;
    data @13 :Data;

410
    list @14 :AnyPointer;
Kenton Varda's avatar
Kenton Varda committed
411 412

    enum @15 :UInt16;
413
    struct @16 :AnyPointer;
Kenton Varda's avatar
Kenton Varda committed
414 415 416 417

    interface @17 :Void;
    # The only interface value that can be represented statically is "null", whose methods always
    # throw exceptions.
418

419
    anyPointer @18 :AnyPointer;
420 421 422
  }
}

Kenton Varda's avatar
Kenton Varda committed
423 424 425 426 427 428 429
struct Annotation {
  # Describes an annotation applied to a declaration.  Note AnnotationNode describes the
  # annotation's declaration, while this describes a use of the annotation.

  id @0 :Id;
  # ID of the annotation node.

430 431
  brand @2 :Brand;
  # Brand of the annotation.
Kenton Varda's avatar
Kenton Varda committed
432 433 434
  #
  # Note that the annotation itself is not allowed to be parameterized, but its scope might be.

435 436 437
  value @1 :Value;
}

Kenton Varda's avatar
Kenton Varda committed
438 439 440 441 442 443 444 445 446 447 448 449
enum ElementSize {
  # Possible element sizes for encoded lists.  These correspond exactly to the possible values of
  # the 3-bit element size component of a list pointer.

  empty @0;    # aka "void", but that's a keyword.
  bit @1;
  byte @2;
  twoBytes @3;
  fourBytes @4;
  eightBytes @5;
  pointer @6;
  inlineComposite @7;
450 451 452 453 454 455 456
}

struct CodeGeneratorRequest {
  nodes @0 :List(Node);
  # All nodes parsed by the compiler, including for the files on the command line and their
  # imports.

Kenton Varda's avatar
Kenton Varda committed
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
  requestedFiles @1 :List(RequestedFile);
  # Files which were listed on the command line.

  struct RequestedFile {
    id @0 :Id;
    # ID of the file.

    filename @1 :Text;
    # Name of the file as it appeared on the command-line (minus the src-prefix).  You may use
    # this to decide where to write the output.

    imports @2 :List(Import);
    # List of all imported paths seen in this file.

    struct Import {
      id @0 :Id;
      # ID of the imported file.

      name @1 :Text;
      # Name which *this* file used to refer to the foreign file.  This may be a relative name.
      # This information is provided because it might be useful for code generation, e.g. to
      # generate #include directives in C++.  We don't put this in Node.file because this
      # information is only meaningful at compile time anyway.
      #
      # (On Zooko's triangle, this is the import's petname according to the importing file.)
    }
  }
484
}