[vala/switch-to-gir] girparser: Reorder the pipeline and generalize the symbol mapping process
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/switch-to-gir] girparser: Reorder the pipeline and generalize the symbol mapping process
- Date: Thu, 26 Aug 2010 16:41:55 +0000 (UTC)
commit 4b140fc444cd089d814c4f7c5aa679c9ccc87631
Author: Luca Bruno <lethalman88 gmail com>
Date: Thu Aug 26 18:15:33 2010 +0200
girparser: Reorder the pipeline and generalize the symbol mapping process
vala/valagirparser.vala | 274 ++++++++++++++++++++++++++++++-----------------
1 files changed, 174 insertions(+), 100 deletions(-)
---
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index b883c8b..5ef83ef 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -24,6 +24,12 @@ 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) Do post-parsing/symbol-resolving operations on the reconciliated tree
*/
public class Vala.GirParser : CodeVisitor {
enum MetadataType {
@@ -442,12 +448,12 @@ public class Vala.GirParser : CodeVisitor {
string[] cheader_filenames;
ArrayList<Metadata> metadata_stack;
- Metadata metadata = Metadata.empty;
+ Metadata metadata;
HashMap<string,ArrayList<Delegate>> gtype_callbacks;
- HashMap<string,string> gir_namespaces = new HashMap<string,string> (str_hash, str_equal);
- ArrayList<UnresolvedType> unresolved_namespaced_types = new ArrayList<UnresolvedType> ();
+ HashMap<UnresolvedSymbol,Symbol> symbols_map = new HashMap<UnresolvedSymbol,Symbol> (unresolved_symbol_hash, unresolved_symbol_equal);
+ ArrayList<UnresolvedSymbol> unresolved_gir_symbols = new ArrayList<UnresolvedSymbol> ();
ArrayList<Alias> aliases = new ArrayList<Alias> ();
@@ -462,7 +468,7 @@ public class Vala.GirParser : CodeVisitor {
glib_ns = context.root.scope.lookup ("GLib") as Namespace;
context.accept (this);
- resolve_gir_namespaces ();
+ resolve_gir_symbols ();
postprocess_aliases ();
}
@@ -471,14 +477,17 @@ public class Vala.GirParser : CodeVisitor {
// collect gir namespaces
if (node is Namespace) {
var ns = (Namespace) node;
- if (source_file.gir_namespace != null) {
- gir_namespaces[source_file.gir_namespace] = ns.name;
- } else {
+ var gir_namespace = source_file.gir_namespace;
+ if (gir_namespace == null) {
var a = ns.get_attribute ("CCode");
if (a != null && a.has_argument ("gir_namespace")) {
- gir_namespaces[a.get_string ("gir_namespace")] = ns.name;
+ gir_namespace = a.get_string ("gir_namespace");
}
}
+ if (gir_namespace != null && gir_namespace != ns.name) {
+ var map_from = new UnresolvedSymbol (null, gir_namespace);
+ add_symbol_mapping (map_from, ns);
+ }
}
}
@@ -713,6 +722,12 @@ public class Vala.GirParser : CodeVisitor {
return type;
}
+ void add_symbol_mapping (UnresolvedSymbol map_from, Symbol map_to) {
+ if (!(map_from in symbols_map)) {
+ symbols_map[map_from] = map_to;
+ }
+ }
+
DataType? element_get_type (DataType type, bool owned_by_default, out bool changed = null, ArgumentType arg_type = ArgumentType.TYPE) {
if (&changed != null) {
changed = false;
@@ -843,9 +858,6 @@ public class Vala.GirParser : CodeVisitor {
}
current_source_file.gir_namespace = gir_namespace;
current_source_file.gir_version = gir_version;
- if (!(gir_namespace in gir_namespaces)) {
- gir_namespaces[gir_namespace] = namespace_name;
- }
var ns_metadata = metadata.match_child (gir_namespace);
@@ -859,6 +871,10 @@ public class Vala.GirParser : CodeVisitor {
ns.source_reference = get_current_src ();
}
}
+ if (gir_namespace != ns.name) {
+ add_symbol_mapping (new UnresolvedSymbol (null, gir_namespace), ns);
+ }
+
var old_namespace = current_namespace;
current_namespace = ns;
@@ -1274,6 +1290,7 @@ public class Vala.GirParser : CodeVisitor {
array_null_terminated = true;
}
} else {
+ bool known_type = true;
if (type_name == "utf8") {
type_name = "string";
} else if (type_name == "boolean") {
@@ -1294,16 +1311,13 @@ public class Vala.GirParser : CodeVisitor {
type_name = "GLib.Datalist";
} else if (type_name == "Atk.ImplementorIface") {
type_name = "Atk.Implementor";
- }
- string[] type_components = type_name.split (".");
- if (type_components[1] != null) {
- // namespaced name
- string namespace_component = type_components[0];
- string type_component = type_components[1];
- type = new UnresolvedType.from_symbol (new UnresolvedSymbol (new UnresolvedSymbol (null, namespace_component, get_current_src ()), type_component, get_current_src ()), get_current_src ());
- unresolved_namespaced_types.add ((UnresolvedType) type);
} else {
- type = new UnresolvedType.from_symbol (new UnresolvedSymbol (null, type_name, get_current_src ()), get_current_src ());
+ known_type = false;
+ }
+ var sym = parse_symbol_from_string (type_name, get_current_src ());
+ type = new UnresolvedType.from_symbol (sym, get_current_src ());
+ if (!known_type) {
+ unresolved_gir_symbols.add (sym);
}
}
@@ -1358,80 +1372,6 @@ public class Vala.GirParser : CodeVisitor {
return st;
}
- void postprocess_gtype_callbacks (Namespace ns) {
- foreach (string gtype_name in gtype_callbacks.get_keys ()) {
- var gtype = ns.scope.lookup (gtype_name) as ObjectTypeSymbol;
- if (gtype == null) {
- Report.error (null, "unknown type `%s.%s'".printf (ns.name, gtype_name));
- continue;
- }
- ArrayList<Delegate> callbacks = gtype_callbacks.get (gtype_name);
- foreach (Delegate d in callbacks) {
- var symbol = gtype.scope.lookup (d.name);
- if (symbol == null) {
- continue;
- } else if (symbol is Method) {
- var meth = (Method) symbol;
- if (gtype is Class) {
- meth.is_virtual = true;
- } else if (gtype is Interface) {
- meth.is_abstract = true;
- }
- } else if (symbol is Signal) {
- var sig = (Signal) symbol;
- sig.is_virtual = true;
- } else if (symbol is Property) {
- var prop = (Property) symbol;
- prop.is_virtual = true;
- } else {
- Report.error (get_current_src (), "unknown member type `%s' in `%s'".printf (d.name, gtype.name));
- }
- }
- }
- }
-
- void postprocess_aliases () {
- foreach (var alias in aliases) {
- DataType base_type = null;
- Symbol type_sym = null;
- if (alias.base_type is UnresolvedType) {
- Symbol parent = alias.parent_namespace;
- var type = (UnresolvedType) alias.base_type;
- // simulate some basic two-steps of the symbol resolver
- if (type.unresolved_symbol.inner != null) {
- var name = type.unresolved_symbol.inner.name;
- if (name in gir_namespaces) {
- name = gir_namespaces[name];
- }
- parent = context.root.scope.lookup (name);
- }
- base_type = alias.base_type;
- type_sym = parent.scope.lookup (type.unresolved_symbol.name);
- } else if (!(alias.base_type is VoidType)) {
- base_type = alias.base_type;
- type_sym = base_type.data_type;
- }
-
- if (base_type == null || type_sym == null || type_sym is Struct) {
- var st = new Struct (alias.name, alias.source_reference);
- st.access = SymbolAccessibility.PUBLIC;
- if (base_type != null) {
- st.base_type = base_type;
- }
- st.external = true;
- alias.parent_namespace.add_struct (st);
- } else if (type_sym is Class) {
- var cl = new Class (alias.name, alias.source_reference);
- cl.access = SymbolAccessibility.PUBLIC;
- if (base_type != null) {
- cl.add_base_type (base_type);
- }
- cl.external = true;
- alias.parent_namespace.add_class (cl);
- }
- }
- }
-
Class parse_class () {
start_element ("class");
var cl = new Class (reader.get_attribute ("name"), get_current_src ());
@@ -2102,12 +2042,120 @@ public class Vala.GirParser : CodeVisitor {
return c;
}
- void resolve_gir_namespaces () {
- foreach (var type in unresolved_namespaced_types) {
- var name = type.unresolved_symbol.inner.name;
- if (name in gir_namespaces) {
- // map the gir namespace to the vala namespace
- type.unresolved_symbol.inner.name = gir_namespaces[name];
+ void postprocess_gtype_callbacks (Namespace ns) {
+ foreach (string gtype_name in gtype_callbacks.get_keys ()) {
+ var gtype = ns.scope.lookup (gtype_name) as ObjectTypeSymbol;
+ if (gtype == null) {
+ Report.error (null, "unknown type `%s.%s'".printf (ns.name, gtype_name));
+ continue;
+ }
+ ArrayList<Delegate> callbacks = gtype_callbacks.get (gtype_name);
+ foreach (Delegate d in callbacks) {
+ var symbol = gtype.scope.lookup (d.name);
+ if (symbol == null) {
+ continue;
+ } else if (symbol is Method) {
+ var meth = (Method) symbol;
+ if (gtype is Class) {
+ meth.is_virtual = true;
+ } else if (gtype is Interface) {
+ meth.is_abstract = true;
+ }
+ } else if (symbol is Signal) {
+ var sig = (Signal) symbol;
+ sig.is_virtual = true;
+ } else if (symbol is Property) {
+ var prop = (Property) symbol;
+ prop.is_virtual = true;
+ } else {
+ Report.error (get_current_src (), "unknown member type `%s' in `%s'".printf (d.name, gtype.name));
+ }
+ }
+ }
+ }
+
+ void resolve_gir_symbols () {
+ // gir has simple namespaces, we won't get deeper than 2 levels here
+ foreach (var map_from in unresolved_gir_symbols) {
+ while (map_from != null) {
+ var map_to = symbols_map[map_from];
+ if (map_to != null) {
+ // remap the original symbol to match the target
+ map_from.inner = null;
+ map_from.name = map_to.name;
+ if (map_to is UnresolvedSymbol) {
+ var umap_to = (UnresolvedSymbol) map_to;
+ while (umap_to.inner != null) {
+ umap_to = umap_to.inner;
+ map_from.inner = new UnresolvedSymbol (null, umap_to.name);
+ map_from = map_from.inner;
+ }
+ } else {
+ while (map_to.parent_symbol != null && map_to.parent_symbol != context.root) {
+ map_to = map_to.parent_symbol;
+ map_from.inner = new UnresolvedSymbol (null, map_to.name);
+ map_from = map_from.inner;
+ }
+ }
+ break;
+ }
+ map_from = map_from.inner;
+ }
+ }
+ }
+
+ Symbol? resolve_symbol (Scope parent_scope, UnresolvedSymbol unresolved_symbol) {
+ // simple symbol resolver, enough for gir
+ if (unresolved_symbol.inner == null) {
+ var scope = parent_scope;
+ while (scope != null) {
+ var sym = scope.lookup (unresolved_symbol.name);
+ if (sym != null) {
+ return sym;
+ }
+ scope = scope.parent_scope;
+ }
+ } else {
+ var inner = resolve_symbol (parent_scope, unresolved_symbol.inner);
+ if (inner != null) {
+ return inner.scope.lookup (unresolved_symbol.name);
+ }
+ }
+ return null;
+ }
+
+ void postprocess_aliases () {
+ /* this is unfortunate because <alias> tag has no type information, thus we have
+ to guess it from the target */
+ foreach (var alias in aliases) {
+ DataType base_type = null;
+ Symbol type_sym = null;
+ if (alias.base_type is UnresolvedType) {
+ Symbol parent = alias.parent_namespace;
+ base_type = alias.base_type;
+ type_sym = resolve_symbol (alias.parent_namespace.scope, ((UnresolvedType) base_type).unresolved_symbol);
+ } else if (!(alias.base_type is VoidType)) {
+ base_type = alias.base_type;
+ type_sym = base_type.data_type;
+ }
+
+ if (base_type == null || type_sym == null || type_sym is Struct) {
+ var st = new Struct (alias.name, alias.source_reference);
+ st.access = SymbolAccessibility.PUBLIC;
+ if (base_type != null) {
+ // threat target="none" as a new struct
+ st.base_type = base_type;
+ }
+ st.external = true;
+ alias.parent_namespace.add_struct (st);
+ } else if (type_sym is Class) {
+ var cl = new Class (alias.name, alias.source_reference);
+ cl.access = SymbolAccessibility.PUBLIC;
+ if (base_type != null) {
+ cl.add_base_type (base_type);
+ }
+ cl.external = true;
+ alias.parent_namespace.add_class (cl);
}
}
}
@@ -2138,5 +2186,31 @@ public class Vala.GirParser : CodeVisitor {
}
}
}
+
+ static uint unresolved_symbol_hash (void *ptr) {
+ var sym = (UnresolvedSymbol) ptr;
+ var builder = new StringBuilder ();
+ while (sym != null) {
+ builder.append (sym.name);
+ sym = sym.inner;
+ }
+ return builder.str.hash ();
+ }
+
+ static bool unresolved_symbol_equal (void *ptr1, void *ptr2) {
+ var sym1 = (UnresolvedSymbol) ptr1;
+ var sym2 = (UnresolvedSymbol) ptr2;
+ while (sym1 != sym2) {
+ if (sym1 == null || sym2 == null) {
+ return false;
+ }
+ if (sym1.name != sym2.name) {
+ return false;
+ }
+ sym1 = sym1.inner;
+ sym2 = sym2.inner;
+ }
+ return true;
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]