[vala/switch-to-gir: 23/34] girparser: Support symbol reparenting
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/switch-to-gir: 23/34] girparser: Support symbol reparenting
- Date: Sun, 29 Aug 2010 16:21:39 +0000 (UTC)
commit bf84ac731cf809ac64c5d8e0b5bded28f741be27
Author: Luca Bruno <lucabru src gnome org>
Date: Sun Aug 29 15:07:49 2010 +0200
girparser: Support symbol reparenting
vala/valagirparser.vala | 82 ++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 81 insertions(+), 1 deletions(-)
---
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index 853cc33..e78f169 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -24,6 +24,21 @@ using GLib;
/**
* Code visitor parsing all Vala source files.
+ *
+ * Pipeline:
+ * 1) Parse metadata
+ * 2) Parse GIR with metadata, track unresolved GIR symbols, create symbol mappings
+ * 3) Reconciliate the tree by mapping tracked symbols
+ * 4) Reparent nodes
+ * 5) Process callbacks/virtual
+ * 6) Process aliases
+ *
+ * Best hacking practices:
+ * - Keep GIR parsing bloat-free, it must contain the logic
+ * - Prefer being clean / short over performance
+ * - Try to make things common as much as possible
+ * - Prefer replace/merge after parse rather than a bunch of if-then-else and hardcoding
+ * - Prefer postprocessing over hardcoding the parser
*/
public class Vala.GirParser : CodeVisitor {
enum MetadataType {
@@ -505,6 +520,7 @@ public class Vala.GirParser : CodeVisitor {
HashMap<Symbol,Symbol> concrete_symbols_map = new HashMap<Symbol,Symbol> ();
ArrayList<UnresolvedSymbol> unresolved_gir_symbols = new ArrayList<UnresolvedSymbol> ();
+ HashMap<UnresolvedSymbol,ArrayList<Symbol>> symbol_reparent_map = new HashMap<UnresolvedSymbol,ArrayList<Symbol>> (unresolved_symbol_hash, unresolved_symbol_equal);
HashMap<Namespace,ArrayList<Method>> namespace_methods = new HashMap<Namespace,ArrayList<Method>> ();
HashMap<CallbackScope,ArrayList<Delegate>> gtype_callbacks = new HashMap<CallbackScope,ArrayList<Delegate>> (callback_scope_hash, callback_scope_equal);
ArrayList<Alias> aliases = new ArrayList<Alias> ();
@@ -522,6 +538,7 @@ public class Vala.GirParser : CodeVisitor {
resolve_gir_symbols ();
+ postprocess_reparenting ();
postprocess_gtype_callbacks ();
postprocess_aliases ();
postprocess_namespace_methods ();
@@ -852,6 +869,24 @@ public class Vala.GirParser : CodeVisitor {
return false;
}
+ void postprocess_symbol (Symbol symbol, Metadata metadata) {
+ // mark to be reparented
+ if (metadata.has_argument (ArgumentType.PARENT)) {
+ var target_symbol = parse_symbol_from_string (metadata.get_string (ArgumentType.PARENT), metadata.get_source_reference (ArgumentType.PARENT));
+ var reparent_list = symbol_reparent_map[target_symbol];
+ if (reparent_list == null) {
+ reparent_list = new ArrayList<Symbol>();
+ symbol_reparent_map[target_symbol] = reparent_list;
+ }
+ reparent_list.add (symbol);
+
+ // if referenceable, map unresolved references to point to the new place
+ if (symbol is Namespace || symbol is TypeSymbol) {
+ set_symbol_mapping (symbol, new UnresolvedSymbol (target_symbol, symbol.name));
+ }
+ }
+ }
+
void merge_add_process (Symbol container) {
var add_list = new ArrayList<SymbolInfo> ();
foreach (var name in current_symbols_info.get_keys ()) {
@@ -864,7 +899,10 @@ public class Vala.GirParser : CodeVisitor {
}
foreach (var info in add_list) {
- add_symbol_to_container (container, info.symbol);
+ if (!(info.metadata.has_argument (ArgumentType.PARENT))) {
+ add_symbol_to_container (container, info.symbol);
+ }
+ postprocess_symbol (info.symbol, info.metadata);
}
}
@@ -2336,6 +2374,48 @@ public class Vala.GirParser : CodeVisitor {
return null;
}
+ void postprocess_reparenting () {
+ foreach (UnresolvedSymbol target_unresolved_symbol in symbol_reparent_map.get_keys ()) {
+ var target_symbol = resolve_symbol (context.root.scope, target_unresolved_symbol);
+ if (target_symbol == null) {
+ // create namespaces backward
+ var sym = target_unresolved_symbol;
+ var ns = new Namespace (sym.name, sym.source_reference);
+ var result = ns;
+ sym = sym.inner;
+ while (sym != null) {
+ var res = resolve_symbol (context.root.scope, sym);
+ if (res != null && !(res is Namespace)) {
+ result = null;
+ break;
+ }
+ var parent = res as Namespace;
+ if (res == null) {
+ parent = new Namespace (sym.name, sym.source_reference);
+ }
+ if (parent.scope.lookup (ns.name) == null) {
+ parent.add_namespace (ns);
+ }
+ ns = parent;
+ sym = sym.inner;
+ }
+ if (result != null && sym == null && context.root.scope.lookup (ns.name) == null) {
+ // a new root namespace, helpful for a possible non-gobject gir?
+ context.root.add_namespace (ns);
+ }
+ target_symbol = result;
+ }
+ if (target_symbol == null) {
+ Report.error (null, "unable to reparent into `%s'".printf (target_unresolved_symbol.to_string ()));
+ continue;
+ }
+ var symbols = symbol_reparent_map[target_unresolved_symbol];
+ foreach (var symbol in symbols) {
+ add_symbol_to_container (target_symbol, symbol);
+ }
+ }
+ }
+
void postprocess_gtype_callbacks () {
foreach (CallbackScope callback_scope in gtype_callbacks.get_keys ()) {
var gtype = resolve_symbol (callback_scope.parent_namespace.scope, callback_scope.gtype_struct_for) as ObjectTypeSymbol;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]