Skip to content

Instantly share code, notes, and snippets.

@thebirk
Last active February 7, 2019 16:44
Show Gist options
  • Save thebirk/fb27fa07a816c311a9ec700f210041a3 to your computer and use it in GitHub Desktop.
Save thebirk/fb27fa07a816c311a9ec700f210041a3 to your computer and use it in GitHub Desktop.
Odin annotations proposal
// This example has some faults, the most important one is how are you gonna know what data
// the annotation actually annotates. The best way would probably be to tag it with
// {entity_id: typeid, entity_ptr: rawptr}, this would allow you to switch on the type
// and cast the ptr. That way you can ensure the annotation was added to the correct type
// and not some random entity
package main
// Proposed change for existing compiler attributes
#(link_name="__func_println")
//
// Another alternative would be to forbid the attribute shortand "@builtin = @(builtin)"
// And have all '@'s followed by an identifier be annotations and those without be compiler attributes
@(link_name="__func_println")
// Could give a compiler attribute, which inserts a function call inside the runtime initialization.
@(annotation_init=register_func_from_annotation)
// This would insert register_func_from_annotation(some_funcdecl) into the initalization.
//
// Declares an annotation called "FuncDecl"
// that takes atleast one argument called 'name'
// and optionally 'is_vararg' or 'desc'.
// Should user defined types be allowed?
FuncDecl :: /*distinct*/ annotation {
name: string,
is_vargarg := false,
desc := "",
}
// Very basic usage
@FuncDecl(name="add")
func_add :: proc(a, b: int) -> int {
return a + b;
}
// Q: Should they all be literals or should you be able to reference globals?
//
// These all have to be constants
@FuncDecl(name = "println", is_vararg = true, desc="Print all arguments followed by a newline")
func_println :: proc(args: []^Value) {
for v in args {
print_value(v);
}
fmt.printf("\n");
}
main :: proc() {
func_decls := runtime.get_annotations_from_type(FuncDecl);
for d in func_decls {
// d is FuncDecl, which acts like a struct, perhaps read-only
register_func_from_annotation(d);
}
}
// This is the stuff that the compiler generates and
// the types that it exposes
runtime.Annotation :: struct {
id: typeid,
data: rawptr,
len: int, // Do we really need 64bits, 32 should be more than enough, even 16 would suffice
}
FuncDecl :: struct /* stored in read-only memory*/ {
field_id: typeid,
field_ptr: rawptr,
name: string,
is_vararg: bool,
desc: string,
}
FuncDecl_annotations := [?]FuncDecl {
{type_of(func_add) , rawptr(func_add) , "add" , false, ""},
{type_of(func_println), rawptr(func_println), "println", true , "Print all arguments followed by a newline"},
};
runtime.annotations := [?]Annotation{
{type_of(FuncDecl), &FuncDecl_annotations[0], len(FuncDecl_annotations)},
};
runtime.get_annotations_from_type :: proc($T: typeid) -> []T {
for a, i in annotations {
if a.id = T {
sl := mem.Raw_Slice{a.data, a.len};
return sl;
}
}
return nil;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment