diff options
author | Alexey Yerin <yyp@disroot.org> | 2023-05-28 14:10:05 +0300 |
---|---|---|
committer | Alexey Yerin <yyp@disroot.org> | 2023-05-28 14:15:22 +0300 |
commit | 16e730f540acfe6a0015464c81831cdfacaf107b (patch) | |
tree | a2aa04bf788dc16977fc6cda2ed874938c3c13c5 /gir |
Initial commit
Diffstat (limited to 'gir')
-rw-r--r-- | gir/parse.ha | 742 | ||||
-rw-r--r-- | gir/types.ha | 363 |
2 files changed, 1105 insertions, 0 deletions
diff --git a/gir/parse.ha b/gir/parse.ha new file mode 100644 index 0000000..f844cd9 --- /dev/null +++ b/gir/parse.ha @@ -0,0 +1,742 @@ +use fmt; +use io; +use strconv; +use strings; +use xml = format::fastxml; + +// The provided GIR file is invalid. +export type invalid = !void; + +// Any error which can occur during GIR parsing. +export type error = !(invalid | xml::error); + +// Returns a human-friendly representation of an [[error]]. +export fn strerror(err: error) const str = { + match (err) { + case invalid => + return "File does not follow GIR structure"; + case let err: xml::error => + return xml::strerror(err); + }; +}; + +// Parses a file into a [[repository]]. +export fn parse(in: io::file) (repository | error) = { + const parser = xml::parse(in)?; + defer xml::parser_free(parser); + + let repo = repository { ... }; + parse_element(parser, "", + ("repository", &parse_repository, &repo), + )?; + return repo; +}; + +fn parse_repository(parser: *xml::parser, repo: *void) (void | error) = { + const repo = repo: *repository; + return parse_element(parser, "repository", + ("xmlns", null), + ("xmlns:c", null), + ("xmlns:glib", null), + ("version", &repo.version), + ("c:identifier-prefixes", null), + ("c:symbol-prefixes", null), + ("include", &parse_include, &repo.includes), + ("c:include", null, null), + ("package", null, null), + ("namespace", &parse_namespace, &repo.namespaces), + ); +}; + +fn parse_include(parser: *xml::parser, includes: *void) (void | error) = { + const includes = includes: *[]include; + let new = include { ... }; + parse_element(parser, "include", + ("name", &new.name), + ("version", &new.version), + )?; + append(includes, new); +}; + +fn parse_namespace(parser: *xml::parser, namespaces: *void) (void | error) = { + const namespaces = namespaces: *[]namespace; + let new = namespace { ... }; + parse_element(parser, "namespace", + ("name", &new.name), + ("version", &new.version), + ("c:identifier-prefixes", null), + ("c:symbol-prefixes", null), + ("shared-library", null), + + ("alias", &parse_alias, &new.aliases), + ("class", &parse_class, &new.classes), + ("interface", &parse_interface, &new.interfaces), + ("record", &parse_record, &new.records), + ("enumeration", &parse_enumeration, &new.enums), + ("function", &parse_function, &new.functions), + ("union", &parse_union, &new.unions), + ("bitfield", &parse_bitfield, &new.bitfields), + ("callback", &parse_callback, &new.callbacks), + ("constant", &parse_constant, &new.constants), + ("annotation", null, null), + ("glib:boxed", null, null), + + // Undocumented and unsupported + ("docsection", null, null), + ("function-macro", null, null), + )?; + append(namespaces, new); +}; + +fn parse_alias(parser: *xml::parser, aliases: *void) (void | error) = { + const aliases = aliases: *[]alias; + let new = alias { ... }; + parse_element(parser, "alias", + parse_info(&new), + ("name", &new.name), + ("c:type", &new.c_type), + ("type", &parse_simple_type, &new.inner), + )?; + append(aliases, new); +}; + +fn parse_class(parser: *xml::parser, classes: *void) (void | error) = { + const classes = classes: *[]class; + let new = class { ... }; + parse_element(parser, "class", + parse_info(&new), + ("name", &new.name), + ("glib:type-name", &new.glib_type_name), + ("glib:get-type", &new.glib_get_type), + ("parent", &new.parent), + ("glib:type-struct", null), + ("glib:ref-func", &new.glib_ref_func), + ("glib:unref-func", &new.glib_unref_func), + ("glib:set-value-func", &new.glib_set_value_func), + ("glib:get-value-func", &new.glib_get_value_func), + ("c:type", &new.c_type), + ("c:symbol-prefix", &new.symbol_prefix), + ("abstract", &new.abstract), + ("glib:fundamental", &new.fundamental), + ("final", &new.final), + + ("implements", &parse_implements, &new.implements), + ("constructor", &parse_constructor, &new.constructors), + ("method", &parse_method, &new.methods), + ("function", &parse_function, &new.functions), + ("virtual-method", &parse_virtual_method, &new.virtual_methods), + ("field", &parse_field, &new.entries), + ("property", &parse_property, &new.properties), + ("glib:signal", &parse_signal, &new.signals), + ("union", &parse_union_entry, &new.entries), + ("constant", &parse_constant, &new.constants), + ("record", &parse_record_entry, &new.entries), + ("callback", &parse_callback, &new.callbacks), + )?; + append(classes, new); +}; +fn parse_implements(parser: *xml::parser, implements: *void) (void | error) = { + const implements = implements: *[]str; + let name = ""; + parse_element(parser, "implements", + ("name", &name), + )?; + append(implements, name); +}; +fn parse_interface(parser: *xml::parser, interfaces: *void) (void | error) = { + const interfaces = interfaces: *[]interface; + let new = interface { ... }; + parse_element(parser, "interface", + parse_info(&new), + ("name", &new.name), + ("glib:type-name", &new.glib_type_name), + ("glib:get-type", &new.glib_get_type), + ("c:symbol-prefix", null), + ("c:type", &new.c_type), + ("glib:type-struct", null), + + ("prerequisite", &parse_prerequisite, &new.prerequisites), + ("implements", &parse_implements, &new.implements), + ("function", &parse_function, &new.functions), + ("constructor", &parse_constructor, &new.constructors), + ("method", &parse_method, &new.methods), + ("virtual-method", &parse_virtual_method, &new.virtual_methods), + ("field", &parse_field, &new.entries), + ("property", &parse_property, &new.properties), + ("glib:signal", &parse_signal, &new.signals), + ("callback", &parse_callback, &new.callbacks), + ("constant", &parse_constant, &new.constants), + )?; + append(interfaces, new); +}; +fn parse_prerequisite(parser: *xml::parser, prerequisites: *void) (void | error) = { + const prerequisites = prerequisites: *[]str; + let name = ""; + parse_element(parser, "prerequisite", + ("name", &name), + )?; + append(prerequisites, name); +}; + +fn parse_record(parser: *xml::parser, records: *void) (void | error) = { + const records = records: *[]record; + let new = record { ... }; + parse_element(parser, "record", + parse_info(&new), + ("name", &new.name), + ("c:type", &new.c_type), + ("disguised", &new.disguised), + ("opaque", &new.opaque), + ("pointer", &new.pointer), + ("glib:type-name", &new.glib_type_name), + ("glib:get-type", &new.glib_get_type), + ("c:symbol-prefix", null), + ("foreign", &new.foreign), + ("glib:is-gtype-struct-for", null), + ("copy-function", &new.copy_function), + ("free-function", &new.free_function), + + ("field", &parse_field, &new.entries), + ("function", &parse_function, &new.functions), + ("union", &parse_union_entry, &new.entries), + ("method", &parse_method, &new.methods), + ("constructor", &parse_constructor, &new.constructors), + )?; + append(records, new); +}; + +fn parse_record_entry(parser: *xml::parser, entries: *void) (void | error) = { + const entries = entries: *[]entry; + let records: []record = []; + defer free(records); + parse_record(parser, &records)?; + append(entries, records[0]); +}; + +fn parse_constructor(parser: *xml::parser, constructors: *void) (void | error) = { + const constructors = constructors: *[]constructor; + let new = constructor { ... }; + parse_element(parser, "constructor", + parse_callable(&new), + ("parameters", &parse_parameters, &new.params), + ("return-value", &parse_return_value, &new.return_value), + )?; + append(constructors, new); +}; +fn parse_method(parser: *xml::parser, methods: *void) (void | error) = { + const methods = methods: *[]method; + let new = method { ... }; + parse_element(parser, "method", + parse_callable(&new), + ("glib:set-property", &new.glib_set_property), + ("glib:get-property", &new.glib_get_property), + ("parameters", &parse_method_parameters, + &(&new.instance, &new.params)), + ("return-value", &parse_return_value, &new.return_value), + )?; + append(methods, new); +}; +fn parse_virtual_method(parser: *xml::parser, vmethods: *void) (void | error) = { + const vmethods = vmethods: *[]virtual_method; + let new = virtual_method { ... }; + parse_element(parser, "virtual-method", + parse_callable(&new), + ("invoker", &new.invoker), + ("parameters", &parse_method_parameters, + &(&new.instance, &new.params)), + ("return-value", &parse_return_value, &new.return_value), + )?; + append(vmethods, new); +}; +fn parse_field(parser: *xml::parser, entries: *void) (void | error) = { + const entries = entries: *[]entry; + let new = field { ... }; + let type_: any_type = simple_type { ... }; + let cb = callback { ... }; + parse_element(parser, "field", + parse_info(&new), + ("name", &new.name), + ("writable", &new.writable), + ("readable", &new.readable), + ("private", &new.private), + ("bits", &new.bits), + + ("callback", &parse_one_callback, &cb), + parse_any_type(&type_), + )?; + if (len(cb.name) > 0) { + new.type_ = cb; + } else { + new.type_ = type_; + }; + append(entries, new); +}; +fn parse_property(parser: *xml::parser, properties: *void) (void | error) = { + const properties = properties: *[]property; + let new = property { ... }; + parse_element(parser, "property", + parse_info(&new), + ("name", &new.name), + ("writable", &new.writable), + ("readable", &new.readable), + ("construct", &new.construct), + ("construct-only", &new.construct_only), + ("setter", &new.setter), + ("getter", &new.getter), + ("default-value", &new.default_value), + ("transfer-ownership", &new.transfer_ownership), + + parse_any_type(&new.type_), + )?; + append(properties, new); +}; + +fn parse_enumeration(parser: *xml::parser, enums: *void) (void | error) = { + const enums = enums: *[]enumeration; + let new = enumeration { ... }; + parse_element(parser, "enumeration", + parse_info(&new), + ("name", &new.name), + ("c:type", &new.c_type), + ("glib:type-name", &new.glib_type_name), + ("glib:get-type", &new.glib_get_type), + ("glib:error-domain", &new.glib_error_domain), + + ("member", &parse_member, &new.members), + ("function", &parse_function, &new.functions), + )?; + append(enums, new); +}; + +fn parse_function(parser: *xml::parser, functions: *void) (void | error) = { + const functions = functions: *[]function; + let new = function { ... }; + parse_element(parser, "function", + parse_callable(&new), + ("parameters", &parse_parameters, &new.params), + ("return-value", &parse_return_value, &new.return_value), + )?; + append(functions, new); +}; + +fn parse_union(parser: *xml::parser, unions: *void) (void | error) = { + const unions = unions: *[]union_; + let new = union_ { ... }; + parse_element(parser, "union", + parse_info(&new), + ("name", &new.name), + ("c:type", &new.c_type), + ("c:symbol-prefix", null), + ("glib:type-name", &new.glib_type_name), + ("glib:get-type", &new.glib_get_type), + ("copy-function", &new.copy_function), + ("free-function", &new.free_function), + + ("field", &parse_field, &new.entries), + ("constructor", &parse_constructor, &new.constructors), + ("method", &parse_method, &new.methods), + ("function", &parse_function, &new.functions), + ("record", &parse_record_entry, &new.entries), + )?; + append(unions, new); +}; + +fn parse_union_entry(parser: *xml::parser, entries: *void) (void | error) = { + const entries = entries: *[]entry; + let unions: []union_ = []; + defer free(unions); + parse_union(parser, &unions)?; + append(entries, unions[0]); +}; + +fn parse_bitfield(parser: *xml::parser, bitfields: *void) (void | error) = { + const bitfields = bitfields: *[]bitfield; + let new = bitfield { ... }; + parse_element(parser, "bitfield", + parse_info(&new), + ("name", &new.name), + ("c:type", &new.c_type), + ("glib:type-name", &new.glib_type_name), + ("glib:get-type", &new.glib_get_type), + + ("member", &parse_member, &new.members), + ("function", &parse_function, &new.functions), + )?; + append(bitfields, new); +}; + +fn parse_callback(parser: *xml::parser, callbacks: *void) (void | error) = { + const callbacks = callbacks: *[]callback; + let new = callback { ... }; + parse_one_callback(parser, &new)?; + append(callbacks, new); +}; +fn parse_one_callback(parser: *xml::parser, cb: *void) (void | error) = { + const cb = cb: *callback; + return parse_element(parser, "callback", + parse_info(cb), + ("name", &cb.name), + ("c:type", &cb.c_type), + ("throws", &cb.throws), + + ("parameters", &parse_parameters, &cb.params), + ("return-value", &parse_return_value, &cb.return_value), + ); +}; + +fn parse_constant(parser: *xml::parser, constants: *void) (void | error) = { + const constants = constants: *[]constant; + let new = constant { ... }; + let type_: any_type = simple_type { ... }; + parse_element(parser, "constant", + parse_info(&new), + ("name", &new.name), + ("value", &new.value), + ("c:type", &new.c_type), + ("c:identifier", &new.c_identifier), + parse_any_type(&type_), + )?; + if (type_ is array_type || len((type_ as simple_type).name) > 0) { + new.type_ = type_; + } else { + new.type_ = void; + }; + append(constants, new); +}; + +fn parse_signal(parser: *xml::parser, signals: *void) (void | error) = { + const signals = signals: *[]signal; + let new = signal { ... }; + parse_element(parser, "glib:signal", + parse_info(&new), + ("name", &new.name), + ("detailed", &new.detailed), + ("when", &new.when), + ("action", &new.action), + ("no-hooks", &new.no_hooks), + ("no-recurse", &new.no_recurse), + ("emitter", &new.emitter), + + ("parameters", &parse_parameters, &new.params), + ("return-value", &parse_return_value, &new.return_value), + )?; + append(signals, new); +}; + +// enum + bitfield +fn parse_member(parser: *xml::parser, members: *void) (void | error) = { + const members = members: *[]member; + let new = member { ... }; + parse_element(parser, "member", + parse_info(&new), + ("name", &new.name), + ("value", &new.value), + ("c:identifier", &new.c_identifier), + ("glib:nick", &new.glib_nick), + ("glib:name", &new.glib_name), + )?; + append(members, new); +}; + +// callable +fn parse_callable(callable: *callable) [17]scan = [ + ("introspectable", null), + ("deprecated", null), + ("deprecated-version", null), + ("version", null), + ("stability", null), + ("doc", &parse_doc, &callable.doc), + ("doc-version", null, null), + ("doc-stability", null, null), + ("doc-deprecated", null, null), + ("source-position", null, null), + ("attribute", null, null), + ("name", &callable.name), + ("c:identifier", &callable.c_identifier), + ("shadowed-by", &callable.shadowed_by), + ("shadows", &callable.shadows), + ("throws", &callable.throws), + ("moved-to", null), +]; +fn parse_parameters(parser: *xml::parser, parameters: *void) (void | error) = { + return parse_element(parser, "parameters", + ("parameter", &parse_parameter, parameters), + ("varargs", &parse_varargs, parameters), + ); +}; +fn parse_method_parameters(parser: *xml::parser, parameters: *void) (void | error) = { + const parameters = parameters: *(*instance_parameter, *[]callable_param); + return parse_element(parser, "parameters", + ("instance-parameter", &parse_instance_parameter, parameters.0), + ("parameter", &parse_parameter, parameters.1), + ("varargs", &parse_varargs, parameters.1), + ); +}; +fn parse_instance_parameter(parser: *xml::parser, param: *void) (void | error) = { + const param = param: *instance_parameter; + return parse_element(parser, "instance-parameter", + parse_info(param), + ("name", ¶m.name), + ("nullable", ¶m.is_nullable), + ("allow-none", ¶m.allow_none), + ("direction", ¶m.direction), + ("caller-allocates", ¶m.caller_allocates), + ("transfer-ownership", ¶m.transfer_ownership), + + ("type", &parse_simple_type, ¶m.type_), + ); +}; +fn parse_parameter(parser: *xml::parser, parameters: *void) (void | error) = { + const parameters = parameters: *[]callable_param; + let new = callable_param { ... }; + let type_: any_type = simple_type { ... }; + let has_varargs = false; + parse_element(parser, "parameter", + parse_info(&new), + ("name", &new.name), + ("nullable", &new.is_nullable), + ("allow-none", &new.allow_none), + ("introspectable", &new.introspectable), + ("closure", &new.closure), + ("destroy", &new.destroy), + ("scope", &new.scope), + ("direction", &new.direction), + ("caller-allocates", &new.caller_allocates), + ("optional", &new.optional), + ("skip", &new.skip), + ("transfer-ownership", &new.transfer_ownership), + ("varargs", &parse_varargs, &has_varargs), + parse_any_type(&type_), + )?; + if (has_varargs) { + new.parameter = varargs; + } else { + new.parameter = type_; + }; + append(parameters, new); +}; +fn parse_varargs(parser: *xml::parser, has_varargs: *void) (void | error) = { + *(has_varargs: *bool) = true; + return parse_element(parser, "varargs"); +}; +fn parse_return_value(parser: *xml::parser, return_value: *void) (void | error) = { + const return_value = return_value: *(callable_return | void); + let new = callable_return { ... }; + parse_element(parser, "return-value", + parse_info(&new), + ("introspectable", &new.introspectable), + ("nullable", &new.is_nullable), + ("closure", &new.closure), + ("destroy", &new.destroy), + ("skip", &new.skip), + ("allow-none", &new.allow_none), + ("transfer-ownership", &new.transfer_ownership), + parse_any_type(&new.type_), + )?; + *return_value = new; +}; + +// documentation +fn parse_info(doc: *documentation) [11]scan = [ + ("introspectable", null), + ("deprecated", null), + ("deprecated-version", null), + ("version", null), + ("stability", null), + ("doc", &parse_doc, &doc.doc), + ("doc-version", null, null), + ("doc-stability", null, null), + ("doc-deprecated", null, null), + ("source-position", null, null), + ("attribute", null, null), +]; +fn parse_doc(parser: *xml::parser, text: *void) (void | error) = { + const text = text: *str; + return parse_element(parser, "doc", + ("xml:space", null), + ("xml:whitespace", null), + ("filename", null), + ("line", null), + ("column", null), + text, + ); +}; + +// types +fn parse_simple_type(parser: *xml::parser, out: *void) (void | error) = { + const out = out: *simple_type; + return parse_element(parser, "type", + parse_info(out), + ("name", &out.name), + ("c:type", &out.c_type), + ("introspectable", &out.introspectable), + ("type", null, null), + ("array", null, null), + ); +}; + +fn parse_array_type(parser: *xml::parser, out: *void) (void | error) = { + const out = out: *array_type; + let inner: any_type = simple_type { ... }; + parse_element(parser, "array", + parse_info(out), + ("name", &out.name), + ("zero-terminated", &out.zero_terminated), + ("fixed-size", &out.fixed_size), + ("introspectable", &out.introspectable), + ("length", &out.length), + ("c:type", &out.c_type), + parse_any_type(&inner), + )?; + out.inner = alloc(inner); +}; + +fn parse_any_type(out: *any_type) [2]scan = [ + ("type", &parse_simple_type_union, out), + ("array", &parse_array_type_union, out), +]; +fn parse_simple_type_union(parser: *xml::parser, out: *void) (void | error) = { + const out = out: *any_type; + let simple = simple_type { ... }; + parse_simple_type(parser, &simple)?; + *out = simple; +}; +fn parse_array_type_union(parser: *xml::parser, out: *void) (void | error) = { + const out = out: *any_type; + let array = array_type { ... }; + parse_array_type(parser, &array)?; + *out = array; +}; + +type parse_func = fn(parser: *xml::parser, data: *void) (void | error); +type scan_element = ( + str, + nullable *parse_func, + nullable *void, +); +type scan_attribute = ( + str, + (nullable *str | *uint | *bool), +); +type scan_text = *str; +type scan = (scan_element | scan_attribute | scan_text | []scan); + +fn parse_element( + parser: *xml::parser, + current: str, + scans: scan... +) (void | error) = { + let elements: []scan_element = []; + defer free(elements); + let attrs: []scan_attribute = []; + defer free(attrs); + let text_out: nullable *str = null; + + for (let i = 0z; i < len(scans); i += 1) { + match (scans[i]) { + case let s: []scan => + for (let j = 0z; j < len(s); j += 1) match (s[j]) { + case let s: scan_element => + append(elements, s); + case let s: scan_attribute => + append(attrs, s); + case let s: scan_text => + assert(text_out is null, "only one scan_text is allowed"); + text_out = s; + case => abort("too deep"); + }; + case let s: scan_element => + append(elements, s); + case let s: scan_attribute => + append(attrs, s); + case let s: scan_text => + assert(text_out is null, "only one scan_text is allowed"); + text_out = s; + }; + }; + + for (true) match (xml::scan(parser)?) { + case let start: xml::elementstart => + let found = false; + for (let i = 0z; i < len(elements); i += 1) { + const (name, func, data) = elements[i]; + if (start == name) { + match (func) { + case let func: *parse_func => + func(parser, data: *void)?; + case null => + ignore(parser, name)?; + }; + found = true; + break; + }; + }; + if (!found) { + fmt::fatalf("Unhandled element {}->{}", current, start); + //return invalid; + }; + case let end: xml::elementend => + assert(len(end) == 0 || end == current); + break; + case let attr: xml::attribute => + let found = false; + for (let i = 0z; i < len(attrs); i += 1) { + const (name, out) = attrs[i]; + if (attr.0 == name) { + match (out) { + case let s: nullable *str => + match(s) { + case let s: *str => + *s = strings::dup(attr.1); + case null => yield; + }; + case let b: *bool => + *b = (attr.1 == "1"); + case let u: *uint => + match (strconv::stou(attr.1)) { + case let parsed: uint => + *u = parsed; + case => + return invalid; + }; + }; + found = true; + break; + }; + }; + if (!found) { + fmt::fatalf("Unhandled attribute {}->{}", current, attr.0); + //return invalid; + }; + case let text: xml::text => + if (len(strings::trim(text)) > 0) { + match (text_out) { + case let s: *str => + *s = strings::dup(text); + case null => + yield; + }; + }; + case void => + if (len(current) == 0) { + break; + }; + return invalid; + }; +}; + +fn ignore(parser: *xml::parser, name: str) (void | error) = { + const name = strings::dup(name); + defer free(name); + + for (true) match (xml::scan(parser)?) { + case let start: xml::elementstart => + ignore(parser, start)?; + case let end: xml::elementend => + assert(end == name || end == ""); + break; + case void => + return invalid; + case => yield; + }; +}; diff --git a/gir/types.ha b/gir/types.ha new file mode 100644 index 0000000..6616d69 --- /dev/null +++ b/gir/types.ha @@ -0,0 +1,363 @@ +export type repository = struct { + version: str, + + includes: []include, + namespaces: []namespace, +}; +export fn repository_finish(repo: *repository) void = { + free(repo.version); + for (let i = 0z; i < len(repo.includes); i += 1) { + include_finish(&repo.includes[i]); + }; + for (let i = 0z; i < len(repo.namespaces); i += 1) { + namespace_finish(&repo.namespaces[i]); + }; +}; + +export type include = struct { + name: str, + version: str, +}; +export fn include_finish(incl: *include) void = { + free(incl.name); + free(incl.version); +}; + +export type namespace = struct { + name: str, + version: str, + + aliases: []alias, + classes: []class, + interfaces: []interface, + records: []record, + enums: []enumeration, + functions: []function, + unions: []union_, + bitfields: []bitfield, + callbacks: []callback, + constants: []constant, +}; +export fn namespace_finish(ns: *namespace) void = { + free(ns.name); + free(ns.version); + // TODO +}; + +export type alias = struct { + documentation, + + name: str, + c_type: str, + + inner: simple_type, +}; + +export type class = struct { + documentation, + + name: str, + glib_type_name: str, + glib_get_type: str, + parent: str, + glib_ref_func: str, + glib_unref_func: str, + glib_set_value_func: str, + glib_get_value_func: str, + c_type: str, + symbol_prefix: str, + abstract: bool, + fundamental: bool, + final: bool, + + entries: []entry, + implements: []str, + constructors: []constructor, + methods: []method, + functions: []function, + virtual_methods: []virtual_method, + properties: []property, + signals: []signal, + constants: []constant, + callbacks: []callback, +}; +export type interface = struct { + documentation, + + name: str, + glib_type_name: str, + glib_get_type: str, + symbol_prefix: str, + c_type: str, + + entries: []entry, + prerequisites: []str, + implements: []str, + functions: []function, + constructors: []constructor, + methods: []method, + virtual_methods: []virtual_method, + properties: []property, + signals: []signal, + callbacks: []callback, + constants: []constant, +}; +export type record = struct { + documentation, + + name: str, + c_type: str, + disguised: bool, + opaque: bool, + pointer: bool, + glib_type_name: str, + glib_get_type: str, + symbol_prefix: str, + foreign: bool, + copy_function: str, + free_function: str, + + entries: []entry, + functions: []function, + methods: []method, + constructors: []constructor, +}; + +// FIXME: find a better name for this +export type entry = (field | union_ | record); + +export type constructor = struct { + callable, + + params: []callable_param, + return_value: (callable_return | void), +}; +export type method = struct { + callable, + + glib_set_property: str, + glib_get_property: str, + + instance: instance_parameter, + params: []callable_param, + return_value: (callable_return | void), +}; +export type virtual_method = struct { + callable, + + invoker: str, + + instance: instance_parameter, + params: []callable_param, + return_value: (callable_return | void), +}; +export type field = struct { + documentation, + + name: str, + writable: bool, + readable: bool, + private: bool, + bits: uint, + + type_: (callback | any_type), +}; +export type property = struct { + documentation, + + name: str, + writable: bool, + readable: bool, + construct: bool, + construct_only: bool, + setter: str, + getter: str, + default_value: str, + transfer_ownership: str, + + type_: any_type, +}; + +export type enumeration = struct { + documentation, + + name: str, + c_type: str, + glib_type_name: str, + glib_get_type: str, + glib_error_domain: str, + + members: []member, + functions: []function, +}; + +export type function = struct { + callable, + + params: []callable_param, + return_value: (callable_return | void), +}; + +export type union_ = struct { + documentation, + + name: str, + c_type: str, + symbol_prefix: str, + glib_type_name: str, + glib_get_type: str, + copy_function: str, + free_function: str, + + entries: []entry, + constructors: []constructor, + methods: []method, + functions: []function, +}; + +export type bitfield = struct { + documentation, + + name: str, + c_type: str, + glib_type_name: str, + glib_get_type: str, + + members: []member, + functions: []function, +}; + +export type callback = struct { + documentation, + + name: str, + c_type: str, + throws: bool, + + params: []callable_param, + return_value: (callable_return | void), +}; + +export type constant = struct { + documentation, + + name: str, + value: str, + c_type: str, + c_identifier: str, + + type_: (any_type | void), +}; + +export type signal = struct { + documentation, + + name: str, + detailed: bool, + when: str, + action: bool, + no_hooks: bool, + no_recurse: bool, + emitter: str, + + params: []callable_param, + return_value: (callable_return | void), +}; + +export type member = struct { + documentation, + + name: str, + value: str, + c_identifier: str, + glib_nick: str, + glib_name: str, +}; + +export type callable = struct { + documentation, + + name: str, + c_identifier: str, + shadowed_by: str, + shadows: str, + throws: bool, +}; + +export type callable_param = struct { + documentation, + + name: str, + is_nullable: bool, + allow_none: bool, + introspectable: bool, + closure: uint, + destroy: uint, + scope: str, + direction: str, + caller_allocates: bool, + optional: bool, + skip: bool, + transfer_ownership: str, + + parameter: (any_type | varargs), +}; + +export type instance_parameter = struct { + documentation, + + name: str, + is_nullable: bool, + allow_none: bool, + direction: str, + caller_allocates: str, + transfer_ownership: str, + + type_: simple_type, +}; + +export type varargs = void; + +export type callable_return = struct { + documentation, + + introspectable: bool, + is_nullable: bool, + closure: uint, + scope: str, + destroy: uint, + skip: bool, + allow_none: bool, + transfer_ownership: str, + + type_: any_type, +}; + +export type documentation = struct { + doc: str, +}; + +export type simple_type = struct { + documentation, + + name: str, + c_type: str, + introspectable: bool, + + inner: []any_type, +}; + +export type array_type = struct { + documentation, + + name: str, + zero_terminated: bool, + fixed_size: uint, + introspectable: bool, + length: uint, + c_type: str, + + inner: *any_type, +}; + +export type any_type = (simple_type | array_type); |