Index ¦ Archives ¦ RSS

Cara generation method changed; delayed

Up until this week, cara had been outputting its schema files something like this:

import cara
ann = cara.Annotation(name='ann', type=cara.Text)
class MyStruct(cara.Struct):
    field1 = cara.Field(name='field1', type=cara.Int32)

However, this causes various problems due to capnp allowing use of types declared later, or even partially defined types (parent of a nested type), such as these:

struct Type1 {
  field1 @0 :Type2;
  struct Type1Inner {
    field3 @0 :Type1;

struct Type2 {
  field2 @0 :Type1;

Here, the outputted code for Type1's field1 would fail to load since it is referring to a Type2 that doesn't exist (yet). As well, Type1Inner's field3 refers to Type1 which isn't fully defined yet (and therefore not in Python's namespace yet).

By switching to the following output, C++'s forward declaration will be mimicked, and there won't be any missing names:

import cara
ann = cara.Annotation(name='ann')
const = cara.Const(name='const')
Type1 = cara.Struct(name='Type1')
Type1.Type1Inner = cara.Struct(name='Type1Inner')
Type2 = cara.Struct(name='Type2')

const.FinishDeclaration(type=cara.Float32, value=3.0e8, annotations=[ann("const before annotation declaration")])
Type1.FinishDeclaration(fields=[cara.Field(name='field1', id=0, type=Type2)])
Type1.Type1Inner.FinishDeclaration(fields=[cara.Field(name='field3', id=0, type=Type1])
Type2.FinishDeclaration(fields=[cara.Field(name='field2', id=0, type=Type1)])

This outputs essentially two lines for every schema declaration, a forward declaration and a completion line. The nested types will use a metaclass on structs, enums and interfaces that catches setattrs on the class to put them into a nested attribute, and the classes will have slots limited to what each schema type is allowed to have.

However, due to the generation needing to be reworked, it won't be available as early as I hoped. There is one upside, though, and that is the generic generation framework I wrote for this will have a better use-case. I mentioned in the capnproto mailing list that for forward declarations and such, using multiple visitor classes that do different things would be simpler than keeping state in one class. The cara output will use multiple visitor classes, one for the forward declaration, and one for finishing each declaration.

© Fahrzin Hemmati. Built using Pelican. Theme by Giulio Fidente on github.