[vala/switch-to-gir] girparser: Generalize symbols merging
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/switch-to-gir] girparser: Generalize symbols merging
- Date: Fri, 27 Aug 2010 14:46:44 +0000 (UTC)
commit 757f028f600e77f2f413a3e30990e2d6d5c002b0
Author: Luca Bruno <lethalman88 gmail com>
Date: Fri Aug 27 16:46:17 2010 +0200
girparser: Generalize symbols merging
vala/valagirparser.vala | 215 +++++++++++++++++++++++++----------------------
1 files changed, 116 insertions(+), 99 deletions(-)
---
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index 99bf95e..de2e54c 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -37,7 +37,7 @@ using GLib;
* - 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 parse+replace rather than a bunch of if-then-else
+ * - 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 {
@@ -455,6 +455,11 @@ public class Vala.GirParser : CodeVisitor {
public UnresolvedSymbol gtype_struct_for;
}
+ class SymbolInfo {
+ public Symbol symbol;
+ public Metadata metadata;
+ }
+
static GLib.Regex type_from_string_regex;
MarkupReader reader;
@@ -474,6 +479,8 @@ public class Vala.GirParser : CodeVisitor {
ArrayList<Metadata> metadata_stack;
Metadata metadata;
+ HashMap<string,ArrayList<SymbolInfo>> current_symbols_info;
+
HashMap<UnresolvedSymbol,Symbol> symbols_map = new HashMap<UnresolvedSymbol,Symbol> (unresolved_symbol_hash, unresolved_symbol_equal);
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);
@@ -849,6 +856,91 @@ public class Vala.GirParser : CodeVisitor {
}
}
+ SymbolInfo? add_symbol_info (Symbol symbol) {
+ var name = symbol.name;
+ if (symbol is CreationMethod && name == null) {
+ name = ".new";
+ }
+
+ var info = new SymbolInfo ();
+ info.symbol = symbol;
+ info.metadata = metadata;
+ var colliding = current_symbols_info[name];
+ if (colliding == null) {
+ colliding = new ArrayList<SymbolInfo> ();
+ current_symbols_info[name] = colliding;
+ }
+ colliding.add (info);
+ return info;
+ }
+
+ bool merge (Symbol container, SymbolInfo info, ArrayList<SymbolInfo> colliding) {
+ bool merged = false;
+
+ if (info.symbol is Signal) {
+ foreach (var cinfo in colliding) {
+ var sym = cinfo.symbol;
+ if (sym is Property) {
+ // properties take precedence
+ merged = true;
+ }
+ }
+ } else if (info.symbol is Method) {
+ var method = (Method) info.symbol;
+ if (method.is_virtual) {
+ // virtual-method
+ foreach (var cinfo in colliding) {
+ var sym = cinfo.symbol;
+ if (sym is Signal) {
+ ((Signal) sym).is_virtual = true;
+ merged = true;
+ } else if (sym is Property || sym is Field) {
+ // assume method is getter for property/field ignore method
+ merged = true;
+ }
+ }
+ } else {
+ // method
+ foreach (var cinfo in colliding) {
+ var sym = cinfo.symbol;
+ if (sym is Signal) {
+ ((Signal) sym).has_emitter = true;
+ merged = true;
+ } else if (sym is Property || sym is Field) {
+ // assume method is getter for property/field ignore method
+ merged = true;
+ } else if (sym is Method && ((Method) sym).is_virtual) {
+ // assume method is wrapper for virtual method
+ merged = true;
+ }
+ }
+ }
+ } else if (info.symbol is Field) {
+ // fields have lowest priority
+ if (colliding.size > 1) {
+ merged = true;
+ }
+ }
+
+ return merged;
+ }
+
+ void merge_and_add (Symbol container) {
+ var add_list = new ArrayList<Symbol> ();
+ foreach (var name in current_symbols_info.get_keys ()) {
+ var colliding = current_symbols_info[name];
+ foreach (var info in colliding) {
+ if (!merge (container, info, colliding)) {
+ add_list.add (info.symbol);
+ }
+ }
+ }
+
+ foreach (var sym in add_list) {
+ add_symbol_to_container (container, sym);
+ }
+ }
+
void parse_repository () {
start_element ("repository");
next ();
@@ -1471,45 +1563,44 @@ public class Vala.GirParser : CodeVisitor {
}
next ();
- var signals = new ArrayList<Signal> ();
- var methods = new ArrayList<Method> ();
- var vmethods = new ArrayList<Method> ();
- var fields = new ArrayList<Field> ();
+ var old_symbols_info = current_symbols_info;
+ current_symbols_info = new HashMap<string,ArrayList<SymbolInfo>> (str_hash, str_equal);
while (current_token == MarkupTokenType.START_ELEMENT) {
if (!push_metadata ()) {
skip_element ();
continue;
}
+ Symbol sym = null;
if (reader.name == "implements") {
start_element ("implements");
cl.add_base_type (parse_type_from_gir_name (reader.get_attribute ("name")));
next ();
end_element ("implements");
} else if (reader.name == "constant") {
- cl.add_constant (parse_constant ());
+ add_symbol_info (parse_constant ());
} else if (reader.name == "field") {
- fields.add (parse_field ());
+ add_symbol_info (parse_field ());
} else if (reader.name == "property") {
- cl.add_property (parse_property ());
+ add_symbol_info (parse_property ());
} else if (reader.name == "constructor") {
- cl.add_method (parse_constructor (cname));
+ add_symbol_info (parse_constructor (cname));
} else if (reader.name == "function") {
- methods.add (parse_method ("function"));
+ add_symbol_info (parse_method ("function"));
} else if (reader.name == "method") {
- methods.add (parse_method ("method"));
+ add_symbol_info (parse_method ("method"));
} else if (reader.name == "virtual-method") {
- vmethods.add (parse_method ("virtual-method"));
+ add_symbol_info (parse_method ("virtual-method"));
} else if (reader.name == "union") {
Struct s = parse_union ();
var s_fields = s.get_fields ();
foreach (var f in s_fields) {
f.set_cname (s.get_cname () + "." + f.get_cname ());
f.name = s.name + "_" + f.name;
- fields.add (f);
+ add_symbol_info (f);
}
} else if (reader.name == "glib:signal") {
- signals.add (parse_signal ());
+ add_symbol_info (parse_signal ());
} else {
// error
Report.error (get_current_src (), "unknown child element `%s' in `class'".printf (reader.name));
@@ -1519,57 +1610,8 @@ public class Vala.GirParser : CodeVisitor {
pop_metadata ();
}
- // signal merging
- foreach (Signal sig in signals) {
- var symbol = cl.scope.lookup (sig.name);
- if (symbol == null) {
- cl.add_signal (sig);
- } else if (symbol is Property) {
- // properties take precedence
- } else {
- Report.error (get_current_src (), "duplicate member `%s' in `%s'".printf (sig.name, cl.name));
- }
- }
-
- // virtual method merging
- foreach (Method m in vmethods) {
- var symbol = cl.scope.lookup (m.name);
- if (symbol == null) {
- cl.add_method (m);
- } else if (symbol is Signal) {
- var sig = (Signal) symbol;
- sig.is_virtual = true;
- } else if (symbol is Property || symbol is Field) {
- // assume method is getter for property/field ignore method
- } else {
- Report.error (get_current_src (), "duplicate member `%s' in `%s'".printf (m.name, cl.name));
- }
- }
-
- // method merging
- foreach (Method m in methods) {
- var symbol = cl.scope.lookup (m.name);
- if (symbol == null) {
- cl.add_method (m);
- } else if (symbol is Signal) {
- var sig = (Signal) symbol;
- sig.has_emitter = true;
- } else if (symbol is Property || symbol is Field) {
- // assume method is getter for property/field ignore method
- } else if (symbol is Method) {
- // assume method is wrapper for virtual method
- } else {
- Report.error (get_current_src (), "duplicate member `%s' in `%s'".printf (m.name, cl.name));
- }
- }
-
- // fields have lowest priority
- foreach (Field f in fields) {
- var symbol = cl.scope.lookup (f.name);
- if (symbol == null) {
- cl.add_field (f);
- }
- }
+ merge_and_add (cl);
+ current_symbols_info = old_symbols_info;
handle_async_methods (cl);
@@ -1589,8 +1631,8 @@ public class Vala.GirParser : CodeVisitor {
}
next ();
- var methods = new ArrayList<Method> ();
- var vmethods = new ArrayList<Method> ();
+ var old_symbols_info = current_symbols_info;
+ current_symbols_info = new HashMap<string,ArrayList<SymbolInfo>> (str_hash, str_equal);
while (current_token == MarkupTokenType.START_ELEMENT) {
if (!push_metadata ()) {
skip_element ();
@@ -1605,15 +1647,15 @@ public class Vala.GirParser : CodeVisitor {
} else if (reader.name == "field") {
parse_field ();
} else if (reader.name == "property") {
- iface.add_property (parse_property ());
+ add_symbol_info (parse_property ());
} else if (reader.name == "virtual-method") {
- vmethods.add (parse_method ("virtual-method"));
+ add_symbol_info (parse_method ("virtual-method"));
} else if (reader.name == "function") {
- methods.add (parse_method ("function"));
+ add_symbol_info (parse_method ("function"));
} else if (reader.name == "method") {
- methods.add (parse_method ("method"));
+ add_symbol_info (parse_method ("method"));
} else if (reader.name == "glib:signal") {
- iface.add_signal (parse_signal ());
+ add_symbol_info (parse_signal ());
} else {
// error
Report.error (get_current_src (), "unknown child element `%s' in `interface'".printf (reader.name));
@@ -1623,33 +1665,8 @@ public class Vala.GirParser : CodeVisitor {
pop_metadata ();
}
- // virtual method merging
- foreach (Method m in vmethods) {
- var symbol = iface.scope.lookup (m.name);
- if (symbol == null) {
- iface.add_method (m);
- } else if (symbol is Signal) {
- var sig = (Signal) symbol;
- sig.is_virtual = true;
- } else {
- Report.error (get_current_src (), "duplicate member `%s' in `%s'".printf (m.name, iface.name));
- }
- }
-
- // method merging
- foreach (Method m in methods) {
- var symbol = iface.scope.lookup (m.name);
- if (symbol == null) {
- iface.add_method (m);
- } else if (symbol is Signal) {
- var sig = (Signal) symbol;
- sig.has_emitter = true;
- } else if (symbol is Method) {
- // assume method is wrapper for virtual method
- } else {
- Report.error (get_current_src (), "duplicate member `%s' in `%s'".printf (m.name, iface.name));
- }
- }
+ merge_and_add (iface);
+ current_symbols_info = old_symbols_info;
handle_async_methods (iface);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]