[vala/switch-to-gir: 11/36] girparser: Postprocess symbols
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/switch-to-gir: 11/36] girparser: Postprocess symbols
- Date: Sat, 6 Nov 2010 11:49:18 +0000 (UTC)
commit 062ce32f98146ac19b059d91e816f749a287f939
Author: Luca Bruno <lucabru src gnome org>
Date: Sun Oct 31 23:01:24 2010 -0700
girparser: Postprocess symbols
vala/valagirparser.vala | 294 ++++++++++++++++++++++++++++++++++++++---------
1 files changed, 241 insertions(+), 53 deletions(-)
---
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index 9c8e371..2c132fd 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -463,19 +463,31 @@ public class Vala.GirParser : CodeVisitor {
}
}
+ class CallbackScope {
+ public Namespace parent_namespace;
+ public UnresolvedSymbol gtype_struct_for;
+ }
+
MarkupReader reader;
CodeContext context;
Namespace glib_ns;
SourceFile current_source_file;
+ Namespace current_namespace;
+ string current_gtype_struct_for;
SourceLocation begin;
SourceLocation end;
MarkupTokenType current_token;
string[] cheader_filenames;
- HashMap<string,ArrayList<Method>> gtype_callbacks = new HashMap<string,ArrayList<Method>> (str_hash, str_equal);
+ HashMap<UnresolvedSymbol,Symbol> unresolved_symbols_map = new HashMap<UnresolvedSymbol,Symbol> (unresolved_symbol_hash, unresolved_symbol_equal);
+ HashMap<Symbol,Symbol> concrete_symbols_map = new HashMap<Symbol,Symbol> ();
+
+ ArrayList<UnresolvedSymbol> unresolved_gir_symbols = new ArrayList<UnresolvedSymbol> ();
+
+ HashMap<CallbackScope,ArrayList<Delegate>> gtype_callbacks = new HashMap<CallbackScope,ArrayList<Delegate>> (callback_scope_hash, callback_scope_equal);
/**
* Parses all .gir source files in the specified code
@@ -487,9 +499,32 @@ public class Vala.GirParser : CodeVisitor {
this.context = context;
glib_ns = context.root.scope.lookup ("GLib") as Namespace;
context.accept (this);
+
+ resolve_gir_symbols ();
+
+ postprocess_gtype_callbacks ();
}
public override void visit_source_file (SourceFile source_file) {
+ // collect gir namespaces
+ foreach (var node in source_file.get_nodes ()) {
+ if (node is Namespace) {
+ var ns = (Namespace) node;
+ 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_namespace = a.get_string ("gir_namespace");
+ }
+ }
+ if (gir_namespace != null && gir_namespace != ns.name) {
+ var map_from = new UnresolvedSymbol (null, gir_namespace);
+ set_symbol_mapping (map_from, ns);
+ break;
+ }
+ }
+ }
+
if (source_file.filename.has_suffix (".gir")) {
parse_file (source_file);
}
@@ -578,6 +613,45 @@ public class Vala.GirParser : CodeVisitor {
return sym;
}
+ UnresolvedSymbol get_unresolved_symbol (Symbol symbol) {
+ if (symbol is UnresolvedSymbol) {
+ return (UnresolvedSymbol) symbol;
+ }
+ var sym = new UnresolvedSymbol (null, symbol.name);
+ var result = sym;
+ var cur = symbol.parent_node as Symbol;
+ while (cur != null && cur.name != null) {
+ sym = new UnresolvedSymbol (sym, cur.name);
+ cur = cur.parent_node as Symbol;
+ }
+ return result;
+ }
+
+ void set_symbol_mapping (Symbol map_from, Symbol map_to) {
+ // last mapping is the most up-to-date
+ if (map_from is UnresolvedSymbol) {
+ unresolved_symbols_map[(UnresolvedSymbol) map_from] = map_to;
+ } else {
+ concrete_symbols_map[map_from] = map_to;
+ }
+ }
+
+ void assume_parameter_names (Signal sig, Symbol sym) {
+ Iterator<Parameter> iter;
+ if (sym is Method) {
+ iter = ((Method) sym).get_parameters ().iterator ();
+ } else {
+ iter = ((Delegate) sym).get_parameters ().iterator ();
+ }
+ foreach (var param in sig.get_parameters ()) {
+ if (!iter.next ()) {
+ // unreachable for valid GIR
+ break;
+ }
+ param.name = iter.get ().name;
+ }
+ }
+
void parse_repository () {
start_element ("repository");
if (reader.get_attribute ("version") != GIR_VERSION) {
@@ -661,7 +735,16 @@ public class Vala.GirParser : CodeVisitor {
start_element ("namespace");
bool new_namespace = false;
- string namespace_name = transform_namespace_name (reader.get_attribute ("name"));
+ string? cprefix = reader.get_attribute ("c:identifier-prefixes");
+ string namespace_name = cprefix;
+ string gir_namespace = reader.get_attribute ("name");
+ string gir_version = reader.get_attribute ("version");
+ if (namespace_name == null) {
+ namespace_name = gir_namespace;
+ }
+ current_source_file.gir_namespace = gir_namespace;
+ current_source_file.gir_version = gir_version;
+
var ns = context.root.scope.lookup (namespace_name) as Namespace;
if (ns == null) {
ns = new Namespace (namespace_name, get_current_src ());
@@ -673,7 +756,13 @@ public class Vala.GirParser : CodeVisitor {
}
}
- string? cprefix = reader.get_attribute ("c:identifier-prefixes");
+ if (gir_namespace != ns.name) {
+ set_symbol_mapping (new UnresolvedSymbol (null, gir_namespace), ns);
+ }
+
+ var old_namespace = current_namespace;
+ current_namespace = ns;
+
if (cprefix != null) {
ns.add_cprefix (cprefix);
ns.set_lower_case_cprefix (Symbol.camel_case_to_lower_case (cprefix) + "_");
@@ -748,7 +837,7 @@ public class Vala.GirParser : CodeVisitor {
}
end_element ("namespace");
- postprocess_gtype_callbacks (ns);
+ current_namespace = old_namespace;
if (!new_namespace) {
ns = null;
@@ -1045,6 +1134,7 @@ public class Vala.GirParser : CodeVisitor {
} else if (type_name == "GObject.Strv") {
type = new ArrayType (new UnresolvedType.from_symbol (new UnresolvedSymbol (null, "string")), 1, get_current_src ());
} else {
+ bool known_type = true;
if (type_name == "utf8") {
type_name = "string";
} else if (type_name == "gboolean") {
@@ -1103,31 +1193,25 @@ public class Vala.GirParser : CodeVisitor {
type_name = "GLib.Datalist";
} else if (type_name == "Atk.ImplementorIface") {
type_name = "Atk.Implementor";
+ } else {
+ 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);
+ }
}
return type;
}
- string transform_namespace_name (string gir_module_name) {
- if (gir_module_name == "GObject") {
- return "GLib";
- } else if (gir_module_name == "Gio") {
- return "GLib";
- } else if (gir_module_name == "GModule") {
- return "GLib";
- }
- return gir_module_name;
- }
-
Struct parse_record () {
start_element ("record");
var st = new Struct (reader.get_attribute ("name"), get_current_src ());
st.external = true;
- string glib_is_gtype_struct_for = reader.get_attribute ("glib:is-gtype-struct-for");
+ current_gtype_struct_for = reader.get_attribute ("glib:is-gtype-struct-for");
st.access = SymbolAccessibility.PUBLIC;
next ();
@@ -1139,17 +1223,6 @@ public class Vala.GirParser : CodeVisitor {
if (reader.name == "field") {
st.add_field (parse_field ());
- } else if (reader.name == "callback") {
- if (glib_is_gtype_struct_for != null) {
- ArrayList<Method> callbacks = gtype_callbacks.get (glib_is_gtype_struct_for);
- if (callbacks == null) {
- callbacks = new ArrayList<Method> ();
- gtype_callbacks.set (glib_is_gtype_struct_for, callbacks);
- }
- callbacks.add (parse_method ("callback"));
- } else {
- parse_callback ();
- }
} else if (reader.name == "constructor") {
parse_constructor ();
} else if (reader.name == "method") {
@@ -1172,31 +1245,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;
- ArrayList<Method> callbacks = gtype_callbacks.get (gtype_name);
- foreach (Method m in callbacks) {
- var symbol = gtype.scope.lookup (m.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 {
- Report.error (get_current_src (), "unknown member type `%s' in `%s'".printf (m.name, gtype.name));
- }
- }
- }
- }
-
Class parse_class () {
start_element ("class");
var cl = new Class (reader.get_attribute ("name"), get_current_src ());
@@ -1466,6 +1514,18 @@ public class Vala.GirParser : CodeVisitor {
string allow_none = reader.get_attribute ("allow-none");
next ();
var type = parse_type ();
+ if (type is DelegateType && current_gtype_struct_for != null) {
+ // virtual
+ var callback_scope = new CallbackScope ();
+ callback_scope.parent_namespace = current_namespace;
+ callback_scope.gtype_struct_for = parse_symbol_from_string (current_gtype_struct_for);
+ ArrayList<Delegate> callbacks = gtype_callbacks.get (callback_scope);
+ if (callbacks == null) {
+ callbacks = new ArrayList<Delegate> ();
+ gtype_callbacks.set (callback_scope, callbacks);
+ }
+ callbacks.add (((DelegateType) type).delegate_symbol);
+ }
var field = new Field (name, type, null, get_current_src ());
field.access = SymbolAccessibility.PUBLIC;
if (allow_none == "1") {
@@ -1851,5 +1911,133 @@ public class Vala.GirParser : CodeVisitor {
end_element ("constant");
return c;
}
-}
+ /* Post-parsing */
+
+ void resolve_gir_symbols () {
+ // we are remapping unresolved symbols, so create them from concrete symbols
+ foreach (var map_from in concrete_symbols_map.get_keys ()) {
+ unresolved_symbols_map[get_unresolved_symbol(map_from)] = concrete_symbols_map[map_from];
+ }
+
+ // gir has simple namespaces, we won't get deeper than 2 levels here, except reparenting
+ foreach (var map_from in unresolved_gir_symbols) {
+ while (map_from != null) {
+ var map_to = unresolved_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_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;
+ if (gtype == null) {
+ Report.error (null, "unknown symbol `%s'".printf (callback_scope.gtype_struct_for.to_string ()));
+ continue;
+ }
+ ArrayList<Delegate> callbacks = gtype_callbacks.get (callback_scope);
+ 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;
+ assume_parameter_names (sig, d);
+ } 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));
+ }
+ }
+ }
+ }
+
+ /* Hash and equal functions */
+
+ 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;
+ }
+
+ static uint callback_scope_hash (void *ptr) {
+ var cs = (CallbackScope) ptr;
+ return unresolved_symbol_hash (cs.gtype_struct_for);
+ }
+
+ static bool callback_scope_equal (void *ptr1, void *ptr2) {
+ var cs1 = (CallbackScope) ptr1;
+ var cs2 = (CallbackScope) ptr2;
+ return cs1.parent_namespace == cs2.parent_namespace && unresolved_symbol_equal (cs1.gtype_struct_for, cs2.gtype_struct_for);
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]