[vala/switch-to-gir] girparser: Reorder the pipeline and generalize the symbol mapping process



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]