[vala/wip/attributes: 1/8] Introduce a cache in code nodes to be used by code generators



commit 29ebbff4ead85a0b2e943e437a5f7b73c705a89d
Author: Luca Bruno <lucabru src gnome org>
Date:   Sat Jun 25 16:25:23 2011 +0200

    Introduce a cache in code nodes to be used by code generators

 codegen/valaccodebasemodule.vala |  184 ++++++++++++++++++++++++++++++++++++++
 vala/valacodenode.vala           |   44 +++++++++
 2 files changed, 228 insertions(+), 0 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 9f4a13a..cac0f59 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -305,6 +305,8 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 
 	public Map<string,string> variable_name_map { get { return emit_context.variable_name_map; } }
 
+	public static int ccode_attribute_hash = CodeNode.get_attribute_hash ();
+
 	public CCodeBaseModule () {
 		predefined_marshal_set = new HashSet<string> (str_hash, str_equal);
 		predefined_marshal_set.add ("VOID:VOID");
@@ -5551,6 +5553,27 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 		return get_cvalue (node);
 	}
 
+	public static CCodeAttribute get_ccode_attribute (CodeNode node) {
+		var attr = node.get_attribute_cache (ccode_attribute_hash);
+		if (attr == null) {
+			attr = new CCodeAttribute (node);
+			node.set_attribute_cache (ccode_attribute_hash, attr);
+		}
+		return (CCodeAttribute) attr;
+	}
+
+	public static string get_ccode_name (CodeNode node) {
+		return get_ccode_attribute(node).name;
+	}
+
+	public static string get_ccode_const_name (CodeNode node) {
+		return get_ccode_attribute(node).const_name;
+	}
+
+	public static string get_ccode_type_name (Interface iface) {
+		return get_ccode_attribute(iface).type_name;
+	}
+
 	public override void visit_class (Class cl) {
 	}
 
@@ -5878,3 +5901,164 @@ public class Vala.GLibValue : TargetValue {
 		return result;
 	}
 }
+
+
+public class Vala.CCodeAttribute : AttributeCache {
+	public weak CodeNode node;
+
+	public string name {
+		get {
+			if (_name == null) {
+				_name = get_default_name ();
+			}
+			return _name;
+		}
+	}
+
+	public string const_name {
+		get {
+			if (_const_name == null) {
+				_const_name = CCodeBaseModule.get_ccode_name (node);
+				if (node is Class && ((Class) node).is_immutable) {
+					_const_name = "const %s".printf (_const_name);
+				}
+			}
+			return _const_name;
+		}
+	}
+
+	public string type_name {
+		get {
+			if (_type_name == null) {
+				_type_name = "%sIface".printf (((Interface) node).name);
+			}
+			return _type_name;
+		}
+	}
+
+	private string _name;
+	private string _const_name;
+	private string _type_name;
+
+	private string get_default_name () {
+		var sym = node as Symbol;
+		if (sym != null) {
+			if (sym is Constant && !(sym is EnumValue)) {
+				return "%s%s".printf (sym.parent_symbol.get_lower_case_cprefix ().up (), sym.name);
+			} else if (sym is Field) {
+				if (((Field) sym).binding == MemberBinding.STATIC) {
+					return "%s%s".printf (sym.parent_symbol.get_lower_case_cprefix (), sym.name);
+				} else {
+					return sym.name;
+				}
+			} else if (sym is CreationMethod) {
+				var m = (CreationMethod) sym;
+				string infix;
+				if (m.parent_symbol is Struct) {
+					infix = "init";
+				} else {
+					infix = "new";
+				}
+				if (m.name == ".new") {
+					return "%s%s".printf (m.parent_symbol.get_lower_case_cprefix (), infix);
+				} else {
+					return "%s%s_%s".printf (m.parent_symbol.get_lower_case_cprefix (), infix, m.name);
+				}
+			} else if (sym is Method) {
+				var m = (Method) sym;
+				if (m.is_async_callback) {
+					return "%s_co".printf (((Method) m.parent_symbol).get_real_cname ());
+				}
+				if (sym.name == "main" && sym.parent_symbol.name == null) {
+					// avoid conflict with generated main function
+					return "_vala_main";
+				} else if (sym.name.has_prefix ("_")) {
+					return "_%s%s".printf (sym.parent_symbol.get_lower_case_cprefix (), sym.name.substring (1));
+				} else {
+					return "%s%s".printf (sym.parent_symbol.get_lower_case_cprefix (), sym.name);
+				}
+			} else if (sym is PropertyAccessor) {
+				var acc = (PropertyAccessor) sym;
+				var t = (TypeSymbol) acc.prop.parent_symbol;
+
+				if (acc.readable) {
+					return "%sget_%s".printf (t.get_lower_case_cprefix (), acc.prop.name);
+				} else {
+					return "%sset_%s".printf (t.get_lower_case_cprefix (), acc.prop.name);
+				}
+			} else if (sym is Signal) {
+				return Symbol.camel_case_to_lower_case (sym.name);
+			} else {
+				return "%s%s".printf (sym.parent_symbol.get_cprefix (), sym.name);
+			}
+		} else if (node is ObjectType) {
+			var type = (ObjectType) node;
+			string cname;
+			if (!type.value_owned) {
+				cname = CCodeBaseModule.get_ccode_const_name (type.type_symbol);
+			} else {
+				cname = CCodeBaseModule.get_ccode_name (type.type_symbol);
+			}
+			return "%s*".printf (cname);
+		} else if (node is ArrayType) {
+			var type = (ArrayType) node;
+			var cname = CCodeBaseModule.get_ccode_name (type.element_type);
+			if (type.inline_allocated) {
+				return cname;
+			} else {
+				return "%s*".printf (cname);
+			}
+		} else if (node is DelegateType) {
+			var type = (DelegateType) node;
+			return CCodeBaseModule.get_ccode_name (type.delegate_symbol);
+		} else if (node is ErrorType) {
+			return "GError*";
+		} else if (node is GenericType) {
+			var type = (GenericType) node;
+			if (type.value_owned) {
+				return "gpointer";
+			} else {
+				return "gconstpointer";
+			}
+		} else if (node is MethodType || node is NullType) {
+			return "gpointer";
+		} else if (node is PointerType) {
+			var type = (PointerType) node;
+			if (type.base_type.data_type != null && type.base_type.data_type.is_reference_type ()) {
+				return CCodeBaseModule.get_ccode_name (type.base_type);
+			} else {
+				return "%s*".printf (CCodeBaseModule.get_ccode_name (type.base_type));
+			}
+		} else if (node is VoidType) {
+			return "void";
+		} else if (node is ClassType) {
+			var type = (ClassType) node;
+			return "%sClass*".printf (CCodeBaseModule.get_ccode_name (type.class_symbol));
+		} else if (node is InterfaceType) {
+			var type = (InterfaceType) node;
+			return "%s*".printf (CCodeBaseModule.get_ccode_type_name (type.interface_symbol));
+		} else if (node is ValueType) {
+			var type = (ValueType) node;
+			var cname = CCodeBaseModule.get_ccode_name (type.type_symbol);
+			if (type.nullable) {
+				return "%s*".printf (cname);
+			} else {
+				return cname;
+			}
+		} else {
+			Report.error (node.source_reference, "Unresolved type reference");
+			return "";
+		}
+	}
+
+	public CCodeAttribute (CodeNode node) {
+		this.node = node;
+
+		var attr = node.get_attribute ("CCode");
+		if (attr != null) {
+			_name = attr.get_string ("cname");
+			_const_name = attr.get_string ("const_cname");
+			_type_name = attr.get_string ("type_cname");
+		}
+	}
+}
diff --git a/vala/valacodenode.vala b/vala/valacodenode.vala
index b1fc30e..7badfa9 100644
--- a/vala/valacodenode.vala
+++ b/vala/valacodenode.vala
@@ -47,6 +47,11 @@ public abstract class Vala.CodeNode {
 	 */
 	public GLib.List<Attribute> attributes;
 
+	/**
+	 * Contains objects for handling attributes in the codegen
+	 */
+	public AttributeCache[] attribute_caches;
+
 	public string type_name {
 		get { return Type.from_instance (this).name (); }
 	}
@@ -69,6 +74,7 @@ public abstract class Vala.CodeNode {
 	private static List<DataType> _empty_type_list;
 
 	static int last_temp_nr = 0;
+	static int next_attribute_hash = 0;
 
 	/**
 	 * Specifies the exceptions that can be thrown by this node or a child node
@@ -152,6 +158,32 @@ public abstract class Vala.CodeNode {
 	}
 
 	/**
+	 * Returns the specified attribute cache.
+	 *
+	 * @param hash hash number
+	 * @return     attribute manager
+	 */
+	public AttributeCache? get_attribute_cache (int hash) {
+		if (hash >= attribute_caches.length) {
+			return null;
+		}
+		return attribute_caches[hash];
+	}
+
+	/**
+	 * Sets the specified attribute cache to this code node.
+	 *
+	 * @param hash    hash number
+	 * @param cache attribute cache
+	 */
+	public void set_attribute_cache (int hash, AttributeCache cache) {
+		if (hash >= attribute_caches.length) {
+			attribute_caches.resize (hash * 2 + 1);
+		}
+		attribute_caches[hash] = cache;
+	}
+
+	/**
 	 * Returns a string that represents this code node.
 	 *
 	 * @return a string representation
@@ -177,4 +209,16 @@ public abstract class Vala.CodeNode {
 	public static string get_temp_name () {
 		return "." + (++last_temp_nr).to_string ();
 	}
+
+	/**
+	 * Returns a new hash number for accessing the attribute caches of code nodes
+	 *
+	 * @return a new hash number
+	 */
+	public static int get_attribute_hash () {
+		return next_attribute_hash++;
+	}
+}
+
+public class Vala.AttributeCache {
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]