TheToolsmiths / ddl

Data Definition Language for Game Development Tools
MIT License
4 stars 3 forks source link

Support attributes #4

Open flaxed opened 5 years ago

flaxed commented 5 years ago

Support attributes that can be used to tag types, fields, or other elements present in the DDL

Example (with placeholder syntax):

struct Foo @(zorg_npc) {
    bar: int @(item_id)
}

In this example the struct Foo is tagged with a zorg_npc attribute, and the field bar is tagged with item_id attribute, that can be used by the codegen tools, or other tools in the game's pipeline, to execute custom code based on this attribute.

flaxed commented 5 years ago

I've been thinking more about this topic lately, and there is a detail I'm unsure about, and that is if attributes should be typed before usage, even if they're just primitive types. Of course this is only an issue if #5 is also implemented.

Usually simple attribute systems will support either a tag, or a key=value, where the value is a primitive type. If feature #5 goes ahead, it will probably work something like:

def attr TypedAttrib
{
    prop1: float,
    prop2: bool,
}

def struct SomeStruct
[
    TypedAttrib
    {
        prop1 = 1.0,
        prop2 = false
    }
]
{
  [...]
}

where typeless attributes would be used like:

def struct SomeOtherStruct
[
    prop3 = 10,
    prop4 = true
]
{
  [...]
}

This mix of key=value and, let's call it C#-like attributes for lack of better wording atm, doesn't look productive to me. Nor will it make the work easy when implementing the parser libraries that will have to expose both functionalities.

An alternative would be:

def struct SomeStruct
[
    main_prop = TypedAttrib
    {
        prop1 = 1.0,
        prop2 = false
    }
]
{
  [...]
}

but having a key for the typed attribute seems redundant to me, the intention of the attribute usually is encoded already in the type.

At the moment I'm unsure how to solve this, but seemed relevant enough to put it out there for consideration.

leiradel commented 5 years ago

Any previously defined structure could be an attribute:

struct serialization::id {
    string id;
};

struct serialization::maxSize {
    unsigned maxSize;
};

struct Object [[serialization::id("object")]] {
    string type [[serialization::maxSize(32)]];
};
flaxed commented 5 years ago

Just using any structure as attribute would probably be the simplest, but I'm wary of the impact on tooling. Say you have a structure database, and some part of a workflow lets you create and edit any structure. The database would feed it all types, even if they were just created to be used as attributes. Might not be an actual issue, but worth to consider.

flaxed commented 5 years ago

Re. the syntax you've used, thats similar to tuple syntax. Think its worth implementing? Or is it more in the way of C++ aggregate initialization, where it will initialize the fields per order?

leiradel commented 5 years ago

The database would feed it all types, even if they were just created to be used as attributes.

I'd rather have attributes as structures and use them to drive the tooling, i.e.:

struct db::table {};
struct db::pk {};

struct Table [[db::table]] {};

struct Person : Table {
    long fiscalNumber [[db::pk]];
};
leiradel commented 5 years ago

the syntax you've used, thats similar to tuple syntax

It's initialization by order of declaration. It's easy to allow key = value initialization in addition to that.

flaxed commented 5 years ago

The database would feed it all types, even if they were just created to be used as attributes.

I'd rather have attributes as structures and use them to drive the tooling, i.e.:

struct db::table {};
struct db::pk {};

struct Table [[db::table]] {};

struct Person : Table {
    long fiscalNumber [[db::pk]];
};

Not arguing about the way we define the attributes. I agree we should just declare it the same way as structs. My question is if we should somehow mark them as only usable as attributes? Or is that in the scope of the project using this?

leiradel commented 5 years ago

Why limit them that way? I like to think people know what they're doing.

flaxed commented 5 years ago

Because it’s more powerful to have tools that guide you into using things the right way, than having the burden of using it the right way just on the user. That’s why you have a myriad of linters and similar tools for all sorts of frameworks.

It can be configurable, but it’s in our scope to provide a common way to achieve this scenario, before everyone implements it their own way.