Feature chat: Type/member annotations

Started by
6 comments, last by lubby 10 years, 5 months ago

While the compiler metadata feature has been around for some time, I've really been impressed by how powerful and elegant C#'s type/member annotation feature is. I feel we could cook up something pretty similar for AS using mostly pre-existing features (namely initializer lists and built-in arrays of interfaces) but for best results I really think this needs a solid, 'standards-compliant' official integration.

Brainstorming:

The actual creation/retrieval of metadata is pretty trivial. You'd probably want to have a basic (application-defined?) metadata interface stored in a built-in array. At a low level, the compiler could stow away anything in the square brackets, then parse the contents as an initializer list for your array. What is interesting is how the process would interact with bytecode precompilation, and specifically serialization. As of right now, there's no official AS object serialization framework, which means we can either A) develop something from scratch, B) create some sort of application interface (promising but obviously fragmenting/error-prone) or C) keep type metadata in plaintext, then parse it on bytecode deserialization.

As of right now, my vote goes for B; the differences between application interfaces mean that the loss of direct bytecode portability between AS implementations is essentially a non-issue. This also means that work/code could in theory be shared between the metadata engine and actual game functionalities like networking and/or game saves and thus be tailored to suit the needs of the specific use case(s).

Storing the metadata with the property/type is also going to be kind of interesting. I think keeping this as a script object makes the most sense, and I also think keeping the user data as a separate field is valuable. Therefore, I propose adding an extra void* member to store a pointer to the array. The pointer could then be cast as appropriate for use

The type would be fixed, and specifically the built-in array type with the subtype set to be references to the application metadata type.

Example application metadata type:


interface Annotation {};

Example AS storage type:


Annotation@[]

or alternately


Array<Annotation@>

For convenience, I also propose adding additional methods to asIScriptEngine with the following signatures


asIObjectType* GetMetadataBaseType() const;
asIObjectType* GetMetadataContainerType() const;

It may also be valuable to have different types of annotations for functions, fields and types, but that's what I'd like to interact with the library community on.

clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.
Advertisement

I don't have experience with C# so haven't seen how the C# annotations feature is used in real-world examples. Can you perhaps give me some examples of what they are good for? And why the current metadata implementation in the CScriptBuilder isn't good enough to do the same thing?

I'll need to be convinced of the benefits before I consider adding this to the core engine. :)

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

That would be helpful! They're essentially a more structured version of what you see in the metadata example, a formal way of associating arbitrary extra markup to types, fields, functions, etc. (It's a fairly broad topic and I would encourage you to check out the official examples!) Like I mention, the annotations/attributes actually exist within and can be manipulated by the language where appropriate, though it's not possible to directly associate or remove items from the list at runtime.

Re: their practicality for game scripting-- Unity makes extensive use of these for serialization and editing.

clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.

I'm still not convinced :)

All of this can already be done with the metadata that is in the CScriptBuilder add-on (albeit with a little bit of work from the application developer). It's easy for the application to register functions to allow the script to access the metadata. It is also quite easy for the application to serialize the metadata together with the saved bytecode if so is desired.

Making the metadata part of the core engine would just impose rules to this metadata that may not fit everyone. By keeping it apart from the core engine the applications that wishes to use it can do so, and implement it the way they want, with their own restrictions and so on.

Despite not being convinced this is something that should be part of the core engine, I can certainly see how the add-on can be improved further. For example, rather than keeping the metadata in the CScriptBuilder, it could instead be stored as user-data in the script module (or even as user data of each class, function, or property).

The user data in the various entities of the script engine should then be improved to allow multiple types of user data (as has already been done with asIScriptEngine).

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

That's perfectly all right, as I've actually been able to knock out a good amount of this just as-is. Really, all I needed was the ability to associate the metadata with the respective fields, types, and functions anyway.

tl;dr go for it, and I can probably just release an annotation metadata add-on.

EDIT: And have this work with precompilation, of course.

clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.

I'm still not convinced smile.png

All of this can already be done with the metadata that is in the CScriptBuilder add-on (albeit with a little bit of work from the application developer). It's easy for the application to register functions to allow the script to access the metadata. It is also quite easy for the application to serialize the metadata together with the saved bytecode if so is desired.

Making the metadata part of the core engine would just impose rules to this metadata that may not fit everyone. By keeping it apart from the core engine the applications that wishes to use it can do so, and implement it the way they want, with their own restrictions and so on.

Despite not being convinced this is something that should be part of the core engine, I can certainly see how the add-on can be improved further. For example, rather than keeping the metadata in the CScriptBuilder, it could instead be stored as user-data in the script module (or even as user data of each class, function, or property).

The user data in the various entities of the script engine should then be improved to allow multiple types of user data (as has already been done with asIScriptEngine).

Fortunately this thread is active today, I just came looking for a solution to flagging user editable class variables with metadata.


const char *CScriptBuilder::GetMetadataStringForTypeProperty(int typeId, int varIdx); // Expects the type and index for that type

Though when I need to peek at my user editable values CScriptBuilder is long gone out of scope. Additionally, I am using


int count = asIScriptObject::GetPropertyCount() 
aslScriptObject::GetAddressOfProperty(i); // Traversing all properties

These two functions don't actually pair up without some work. What would be great is aslScriptObject::GetPropertyMetadata(i) and friends!



Currently you would need to keep the CScriptBuilder around. Or extract the metadata to store it in some other form. With the change I proposed, the metadata could for example be stored as user data in the script code (actually, it can already be done that way, unless you're already using the user data for something else).

The metadata for classes should preferably be stored with the asIObjectType, and not the asIScriptObject. After all, the metadata is part of the code, and not the instances.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Currently you would need to keep the CScriptBuilder around. Or extract the metadata to store it in some other form. With the change I proposed, the metadata could for example be stored as user data in the script code (actually, it can already be done that way, unless you're already using the user data for something else).

The metadata for classes should preferably be stored with the asIObjectType, and not the asIScriptObject. After all, the metadata is part of the code, and not the instances.

I did not want to re-architect the code flow, so ended up using the private types to enable exposed variables, this is simple enough as I have the asIObjectType pointer available from each instance. This is sufficient enough for my current use case but won't hold up for more advanced techniques. So if you do decide to expose the metadata via the asIObjectType that would be great.

This topic is closed to new replies.

Advertisement