[vala/wip/attributes: 2/3] Refactor attributes to use hashmaps, GValue and default values



commit 41d8ce383a116d851dc05ca1ae4abc0c98e1ba76
Author: Luca Bruno <lucabru src gnome org>
Date:   Tue Jun 21 23:25:05 2011 +0200

    Refactor attributes to use hashmaps, GValue and default values

 codegen/valagirwriter.vala     |   13 ++--
 vala/valaattribute.vala        |   92 ++++++++++++++++++++------
 vala/valaclass.vala            |    2 +-
 vala/valacodenode.vala         |  144 +++++++++++++++++++++++++++++++++++++--
 vala/valacodewriter.vala       |   25 +++++--
 vala/valaconstant.vala         |    2 +-
 vala/valadelegate.vala         |    2 +-
 vala/valaenum.vala             |    2 +-
 vala/valaerrorcode.vala        |    7 +-
 vala/valaerrordomain.vala      |    2 +-
 vala/valafield.vala            |    9 +--
 vala/valagenieparser.vala      |   49 +++++++-------
 vala/valagirparser.vala        |   31 +++++----
 vala/valainterface.vala        |    2 +-
 vala/valamethod.vala           |    2 +-
 vala/valanamespace.vala        |    7 +-
 vala/valaparameter.vala        |    7 +-
 vala/valaparser.vala           |   62 ++++++++++-------
 vala/valaproperty.vala         |    2 +-
 vala/valapropertyaccessor.vala |    9 +--
 vala/valasignal.vala           |    2 +-
 vala/valastruct.vala           |    4 +-
 vala/valavariable.vala         |    7 +-
 23 files changed, 340 insertions(+), 144 deletions(-)
---
diff --git a/codegen/valagirwriter.vala b/codegen/valagirwriter.vala
index a29b654..b911b96 100644
--- a/codegen/valagirwriter.vala
+++ b/codegen/valagirwriter.vala
@@ -1118,18 +1118,21 @@ public class Vala.GIRWriter : CodeVisitor {
 	}
 
 	private void write_annotations (CodeNode node) {
-		foreach (Attribute attr in node.attributes) {
+		foreach (Attribute attr in node.attributes.get_values ()) {
 			string name = camel_case_to_canonical (attr.name);
-			foreach (string arg_name in attr.args.get_keys ()) {
-				string value = attr.args.get (arg_name);
+			foreach (var arg in attr.args.get_values ()) {
+				if (arg.is_default) {
+					continue;
+				}
+				string value = arg.to_string ();
 				if (value.has_prefix ("\"")) {
 					// eval string
-					value = attr.get_string (arg_name);
+					value = (string) arg.value;
 				}
 
 				write_indent ();
 				buffer.append_printf ("<annotation key=\"%s.%s\" value=\"%s\"/>\n",
-					name, camel_case_to_canonical (arg_name), value);
+					name, camel_case_to_canonical (arg.name), value);
 			}
 		}
 	}
diff --git a/vala/valaattribute.vala b/vala/valaattribute.vala
index 68d7539..b720e80 100644
--- a/vala/valaattribute.vala
+++ b/vala/valaattribute.vala
@@ -27,6 +27,43 @@ using GLib;
  */
 public class Vala.Attribute : CodeNode {
 	/**
+	 * Represents an attribute argument specified in the source code.
+	 */
+	public class Argument {
+		public string name;
+		public Value value;
+		public bool is_default;
+
+		public Argument (string name, Value value, bool is_default) {
+			this.name = name;
+			this.value = value;
+			this.is_default = is_default;
+		}
+
+		/**
+		 * Returns the value of the argument as a string.
+		 *
+		 * @return the value as a string
+		 */
+		public string to_string () {
+			string strval;
+			var type = value.type ();
+			if (type == typeof (string)) {
+				strval = (string) value;
+			} else if (type == typeof (int)) {
+				strval = ((int) value).to_string ();
+			} else if (type == typeof (double)) {
+				strval = ((double) value).to_string ();
+			} else if (type == typeof (bool)) {
+				strval = ((bool) value).to_string ();
+			} else {
+				assert_not_reached ();
+			}
+			return strval;
+		}
+	}
+
+	/**
 	 * The name of the attribute type.
 	 */
 	public string name { get; set; }
@@ -34,7 +71,7 @@ public class Vala.Attribute : CodeNode {
 	/**
 	 * Contains all specified attribute arguments.
 	 */
-	public Vala.Map<string,string> args = new HashMap<string,string> (str_hash, str_equal);
+	public Vala.Map<string,Argument> args = new HashMap<string,Argument> (str_hash, str_equal);
 
 	/**
 	 * Creates a new attribute.
@@ -49,12 +86,14 @@ public class Vala.Attribute : CodeNode {
 	}
 
 	/**
-	 * Adds an attribute argument.
+	 * Sets an attribute argument.
 	 *
-	 * @param arg named argument
+	 * @param name       named argument
+	 * @param value      argument value
+	 * @param is_default true whether the value is the default value, false otherwise
 	 */
-	public void add_argument (string key, string value) {
-		args.set (key, value);
+	public void add_argument (string name, Value value, bool is_default = false) {
+		args.set (name, new Argument (name, value, is_default));
 	}
 	
 	/**
@@ -66,7 +105,17 @@ public class Vala.Attribute : CodeNode {
 	public bool has_argument (string name) {
 		return args.contains (name);
 	}
-	
+
+	/**
+	 * Returns the value of the specified named argument.
+	 *
+	 * @param name argument name
+	 * @return     argument value
+	 */
+	public Value? get_argument (string name) {
+		return args.get (name);
+	}
+
 	/**
 	 * Returns the string value of the specified named argument.
 	 *
@@ -74,18 +123,15 @@ public class Vala.Attribute : CodeNode {
 	 * @return     string value
 	 */
 	public string? get_string (string name) {
-		string value = args.get (name);
+		var arg = args.get (name);
 
-		if (value == null) {
+		if (arg == null) {
 			return null;
 		}
 
-		/* remove quotes */
-		var noquotes = value.substring (1, (uint) (value.length - 2));
-		/* unescape string */
-		return noquotes.compress ();
+		return (string) arg.value;
 	}
-	
+
 	/**
 	 * Returns the integer value of the specified named argument.
 	 *
@@ -93,13 +139,13 @@ public class Vala.Attribute : CodeNode {
 	 * @return     integer value
 	 */
 	public int get_integer (string name) {
-		string value = args.get (name);
+		var arg = args.get (name);
 
-		if (value == null) {
+		if (arg == null) {
 			return 0;
 		}
 
-		return int.parse (value);
+		return (int) arg.value;
 	}
 
 	/**
@@ -109,13 +155,13 @@ public class Vala.Attribute : CodeNode {
 	 * @return     double value
 	 */
 	public double get_double (string name) {
-		string value = args.get (name);
+		var arg = args.get (name);
 
-		if (value == null) {
+		if (arg == null) {
 			return 0;
 		}
 
-		return double.parse (value);
+		return (double) arg.value;
 	}
 
 	/**
@@ -125,6 +171,12 @@ public class Vala.Attribute : CodeNode {
 	 * @return     boolean value
 	 */
 	public bool get_bool (string name) {
-		return bool.parse (args.get (name));
+		var arg = args.get (name);
+
+		if (arg == null) {
+			return false;
+		}
+
+		return (bool) arg.value;
 	}
 }
diff --git a/vala/valaclass.vala b/vala/valaclass.vala
index 2550058..cdefcf2 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -736,7 +736,7 @@ public class Vala.Class : ObjectTypeSymbol {
 	 * Process all associated attributes.
 	 */
 	public void process_attributes () {
-		foreach (Attribute a in attributes) {
+		foreach (Attribute a in attributes.get_values ()) {
 			if (a.name == "CCode") {
 				process_ccode_attribute (a);
 			} else if (a.name == "Compact") {
diff --git a/vala/valacodenode.vala b/vala/valacodenode.vala
index b1fc30e..b677c09 100644
--- a/vala/valacodenode.vala
+++ b/vala/valacodenode.vala
@@ -45,7 +45,7 @@ public abstract class Vala.CodeNode {
 	/**
 	 * Contains all attributes that have been specified for this code node.
 	 */
-	public GLib.List<Attribute> attributes;
+	public Vala.Map<string,Attribute> attributes = new HashMap<string,Attribute> (str_hash, str_equal);
 
 	public string type_name {
 		get { return Type.from_instance (this).name (); }
@@ -141,14 +141,142 @@ public abstract class Vala.CodeNode {
 	 * @return     attribute
 	 */
 	public Attribute? get_attribute (string name) {
-		// FIXME: use hash table
-		foreach (Attribute a in attributes) {
-			if (a.name == name) {
-				return a;
-			}
+		return attributes.get (name);
+	}
+
+	/**
+	 * Returns the value of the specified attribute argument.
+	 *
+	 * @param attribute attribute name
+	 * @param argument  argument name
+	 * @return          argument value
+	 */
+	public Value? get_attribute_argument (string attribute, string argument) {
+		var attr = get_attribute (attribute);
+
+		if (attr == null) {
+			return null;
+		}
+
+		return attr.get_argument (argument);
+	}
+
+	/**
+	 * Returns the string value of the specified attribute argument.
+	 *
+	 * @param attribute attribute name
+	 * @param argument  argument name
+	 * @return          string value
+	 */
+	public string? get_attribute_string (string attribute, string argument) {
+		var attr = get_attribute (attribute);
+
+		if (attr == null) {
+			return null;
+		}
+
+		return attr.get_string (argument);
+	}
+
+	/**
+	 * Returns the integer value of the specified attribute argument.
+	 *
+	 * @param attribute attribute name
+	 * @param argument  argument name
+	 * @return          integer value
+	 */
+	public int get_attribute_integer (string attribute, string argument) {
+		var attr = get_attribute (attribute);
+
+		if (attr == null) {
+			return 0;
+		}
+
+		return attr.get_integer (argument);
+	}
+
+	/**
+	 * Returns the double value of the specified attribute argument.
+	 *
+	 * @param attribute attribute name
+	 * @param argument  argument name
+	 * @return          double value
+	 */
+	public double get_attribute_double (string attribute, string argument) {
+		var attr = get_attribute (attribute);
+
+		if (attr == null) {
+			return 0;
+		}
+
+		return attr.get_double (argument);
+	}
+
+	/**
+	 * Returns the boolean value of the specified attribute argument.
+	 *
+	 * @param attribute attribute name
+	 * @param argument  argument name
+	 * @return          boolean value
+	 */
+	public bool get_attribute_bool (string attribute, string argument) {
+		var attr = get_attribute (attribute);
+
+		if (attr == null) {
+			return false;
+		}
+
+		return attr.get_bool (argument);
+	}
+
+	/**
+	 * Adds the specified named attribute to this code node.
+	 *
+	 * @param attribute attribute name
+	 */
+	public void add_attribute (string attribute, SourceReference? source_reference = null) {
+		var attr = get_attribute (attribute);
+
+		if (attr == null) {
+			attr = new Attribute (attribute, source_reference);
+			attributes.set (attribute, attr);
 		}
-		
-		return null;
+	}
+
+	/**
+	 * Sets the value of the specified attribute argument.
+	 *
+	 * @param attribute attribute name
+	 * @param argument  argument name
+	 * @param value     argument value
+	 */
+	public void set_attribute_argument (string attribute, string argument, Value value, SourceReference? source_reference = null) {
+		var attr = get_attribute (attribute);
+
+		if (attr == null) {
+			attr = new Attribute (attribute, source_reference);
+			attributes.set (attribute, attr);
+		}
+
+		attr.add_argument (argument, value);
+	}
+
+	/**
+	 * Sets the default value of the specified attribute argument.
+	 *
+	 * @param attribute attribute name
+	 * @param argument  argument name
+	 * @param value     default value
+	 */
+	public void set_attribute_default (string attribute, string argument, Value value) {
+		var attr = get_attribute (attribute);
+
+		if (attr == null) {
+			attr = new Attribute (attribute);
+			attributes.set (attribute, attr);
+		}
+
+		attr.add_argument (argument, value, true);
 	}
 
 	/**
diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala
index ee5daf1..60710dd 100644
--- a/vala/valacodewriter.vala
+++ b/vala/valacodewriter.vala
@@ -2048,19 +2048,20 @@ public class Vala.CodeWriter : CodeVisitor {
 	}
 
 	private void write_attributes (CodeNode node) {
-		foreach (Attribute attr in node.attributes) {
+		foreach (Attribute attr in node.attributes.get_values ()) {
 			if (!filter_attribute (attr)) {
 				write_indent ();
 				stream.printf ("[%s", attr.name);
 
-				var keys = attr.args.get_keys ();
-				if (keys.size != 0) {
+				if (attr.args.size > 0) {
 					stream.printf (" (");
 
 					string separator = "";
-					foreach (string arg_name in keys) {
-						stream.printf ("%s%s = %s", separator, arg_name, attr.args.get (arg_name));
-						separator = ", ";
+					foreach (var arg in attr.args.get_values ()) {
+						if (!arg.is_default) {
+							stream.printf ("%s%s = %s", arg.name, separator, arg.to_string ());
+							separator = ", ";
+						}
 					}
 
 					stream.printf (")");
@@ -2078,7 +2079,17 @@ public class Vala.CodeWriter : CodeVisitor {
 		    || attr.name == "Flags") {
 			return true;
 		}
-		return false;
+
+		if (attr.args.size == 0) {
+			return false;
+		} else {
+			foreach (var arg in attr.args.get_values ()) {
+				if (!arg.is_default) {
+					return false;
+				}
+			}
+		}
+		return true;
 	}
 
 	private void write_accessibility (Symbol sym) {
diff --git a/vala/valaconstant.vala b/vala/valaconstant.vala
index 0c77d07..2022d38 100644
--- a/vala/valaconstant.vala
+++ b/vala/valaconstant.vala
@@ -154,7 +154,7 @@ public class Vala.Constant : Symbol, Lockable {
 	 * Process all associated attributes.
 	 */
 	public void process_attributes () {
-		foreach (Attribute a in attributes) {
+		foreach (Attribute a in attributes.get_values ()) {
 			if (a.name == "CCode") {
 				process_ccode_attribute (a);
 			} else if (a.name == "Deprecated") {
diff --git a/vala/valadelegate.vala b/vala/valadelegate.vala
index ddaba92..4684486 100644
--- a/vala/valadelegate.vala
+++ b/vala/valadelegate.vala
@@ -316,7 +316,7 @@ public class Vala.Delegate : TypeSymbol {
 	 * Process all associated attributes.
 	 */
 	public void process_attributes () {
-		foreach (Attribute a in attributes) {
+		foreach (Attribute a in attributes.get_values ()) {
 			if (a.name == "CCode") {
 				process_ccode_attribute (a);
 			} else if (a.name == "Deprecated") {
diff --git a/vala/valaenum.vala b/vala/valaenum.vala
index fed3286..ffcf55a 100644
--- a/vala/valaenum.vala
+++ b/vala/valaenum.vala
@@ -250,7 +250,7 @@ public class Vala.Enum : TypeSymbol {
 	 * Process all associated attributes.
 	 */
 	public void process_attributes () {
-		foreach (Attribute a in attributes) {
+		foreach (Attribute a in attributes.get_values ()) {
 			if (a.name == "CCode") {
 				process_ccode_attribute (a);
 			} else if (a.name == "Flags") {
diff --git a/vala/valaerrorcode.vala b/vala/valaerrorcode.vala
index eace48c..5f853c1 100644
--- a/vala/valaerrorcode.vala
+++ b/vala/valaerrorcode.vala
@@ -95,10 +95,9 @@ public class Vala.ErrorCode : TypeSymbol {
 	 * Process all associated attributes.
 	 */
 	public void process_attributes () {
-		foreach (Attribute a in attributes) {
-			if (a.name == "CCode") {
-				process_ccode_attribute (a);
-			}
+		var a = get_attribute ("CCode");
+		if (a != null) {
+			process_ccode_attribute (a);
 		}
 	}
 
diff --git a/vala/valaerrordomain.vala b/vala/valaerrordomain.vala
index 40dd9b1..785a095 100644
--- a/vala/valaerrordomain.vala
+++ b/vala/valaerrordomain.vala
@@ -192,7 +192,7 @@ public class Vala.ErrorDomain : TypeSymbol {
 	 * Process all associated attributes.
 	 */
 	public void process_attributes () {
-		foreach (Attribute a in attributes) {
+		foreach (Attribute a in attributes.get_values ()) {
 			if (a.name == "CCode") {
 				process_ccode_attribute (a);
 			} else if (a.name == "Deprecated") {
diff --git a/vala/valafield.vala b/vala/valafield.vala
index 4d260d1..7563f53 100644
--- a/vala/valafield.vala
+++ b/vala/valafield.vala
@@ -119,7 +119,7 @@ public class Vala.Field : Variable, Lockable {
 	public override void process_attributes () {
 		base.process_attributes ();
 
-		foreach (Attribute a in attributes) {
+		foreach (Attribute a in attributes.get_values ()) {
 			if (a.name == "CCode") {
 				process_ccode_attribute (a);
 			} else if (a.name == "Deprecated") {
@@ -159,12 +159,7 @@ public class Vala.Field : Variable, Lockable {
 	}
 
 	public void set_ctype (string ctype) {
-		var attr = get_attribute ("CCode");
-		if (attr == null) {
-			attr = new Attribute ("CCode");
-			attributes.append (attr);
-		}
-		attr.add_argument ("type", "\"%s\"".printf (ctype));
+		set_attribute_argument ("CCode", "type", ctype);
 	}
 
 	public override bool check (CodeContext context) {
diff --git a/vala/valagenieparser.vala b/vala/valagenieparser.vala
index 0de741c..393c1fc 100644
--- a/vala/valagenieparser.vala
+++ b/vala/valagenieparser.vala
@@ -2289,16 +2289,20 @@ public class Vala.Genie.Parser : CodeVisitor {
 		}
 	}
 
-	List<Attribute>? parse_attributes (bool parameter) throws ParseError {
+	Map<string, Attribute>? parse_attributes (bool parameter) throws ParseError {
 		if (current () != TokenType.OPEN_BRACKET) {
 			return null;
 		}
-		var attrs = new ArrayList<Attribute> ();
+		var attrs = new HashMap<string, Attribute> (str_hash, str_equal);
 		while (accept (TokenType.OPEN_BRACKET)) {
 			do {
 				var begin = get_location ();
 				string id = parse_identifier ();
-				var attr = new Attribute (id, get_src (begin));
+				var attr = attrs.get (id);
+				if (attr == null) {
+					attr = new Attribute (id, get_src (begin));
+					attrs.set (id, attr);
+				}
 				if (accept (TokenType.OPEN_PARENS)) {
 					if (current () != TokenType.CLOSE_PARENS) {
 						do {
@@ -2309,7 +2313,6 @@ public class Vala.Genie.Parser : CodeVisitor {
 					}
 					expect (TokenType.CLOSE_PARENS);
 				}
-				attrs.add (attr);
 			} while (accept (TokenType.COMMA));
 			expect (TokenType.CLOSE_BRACKET);
 		}
@@ -2318,11 +2321,9 @@ public class Vala.Genie.Parser : CodeVisitor {
 		return attrs;
 	}
 
-	void set_attributes (CodeNode node, List<Attribute>? attributes) {
+	void set_attributes (CodeNode node, Map<string, Attribute>? attributes) {
 		if (attributes != null) {
-			foreach (Attribute attr in (List<Attribute>) attributes) {
-				node.attributes.append (attr);
-			}
+			node.attributes = attributes;
 		}
 	}
 
@@ -2475,7 +2476,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		return RecoveryState.EOF;
 	}
 
-	Namespace parse_namespace_declaration (List<Attribute>? attrs) throws ParseError {
+	Namespace parse_namespace_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		expect (TokenType.NAMESPACE);
 		var sym = parse_symbol_name ();
@@ -2566,7 +2567,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		
 	}
 
-	Symbol parse_class_declaration (List<Attribute>? attrs) throws ParseError {
+	Symbol parse_class_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		expect (TokenType.CLASS);
 
@@ -2703,7 +2704,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		}
 	}
 
-	Constant parse_constant_declaration (List<Attribute>? attrs) throws ParseError {
+	Constant parse_constant_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 
 		expect (TokenType.CONST);
@@ -2742,7 +2743,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		return c;
 	}
 
-	Field parse_field_declaration (List<Attribute>? attrs) throws ParseError {
+	Field parse_field_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		string id = parse_identifier ();
 		expect (TokenType.COLON);
@@ -2810,7 +2811,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 	
 	
 
-	Method parse_main_method_declaration (List<Attribute>? attrs) throws ParseError {
+	Method parse_main_method_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var id = "main";
 		var begin = get_location ();
 		DataType type = new VoidType ();
@@ -2842,7 +2843,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		return method;
 	}
 
-	Method parse_method_declaration (List<Attribute>? attrs) throws ParseError {
+	Method parse_method_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		DataType type = new VoidType ();
 		expect (TokenType.DEF);
@@ -2992,7 +2993,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		return method;
 	}
 
-	Property parse_property_declaration (List<Attribute>? attrs) throws ParseError {
+	Property parse_property_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var readonly = false;
 
@@ -3135,7 +3136,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		return prop;
 	}
 
-	Vala.Signal parse_signal_declaration (List<Attribute>? attrs) throws ParseError {
+	Vala.Signal parse_signal_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		DataType type;
 
@@ -3193,7 +3194,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		return sig;
 	}
 
-	Constructor parse_constructor_declaration (List<Attribute>? attrs) throws ParseError {
+	Constructor parse_constructor_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 
 		expect (TokenType.INIT);
@@ -3211,7 +3212,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		return c;
 	}
 
-	Destructor parse_destructor_declaration (List<Attribute>? attrs) throws ParseError {
+	Destructor parse_destructor_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		expect (TokenType.FINAL);
 		var d = new Destructor (get_src (begin));
@@ -3220,7 +3221,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		return d;
 	}
 
-	Symbol parse_struct_declaration (List<Attribute>? attrs) throws ParseError {
+	Symbol parse_struct_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 
 		expect (TokenType.STRUCT);
@@ -3277,7 +3278,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		}
 	}
 
-	Symbol parse_interface_declaration (List<Attribute>? attrs) throws ParseError {
+	Symbol parse_interface_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 
 		expect (TokenType.INTERFACE);
@@ -3354,7 +3355,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		}
 	}
 
-	Symbol parse_enum_declaration (List<Attribute>? attrs) throws ParseError {
+	Symbol parse_enum_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		expect (TokenType.ENUM);
 		var flags = parse_type_declaration_modifiers ();
@@ -3412,7 +3413,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		return result;
 	}
 
-	Symbol parse_errordomain_declaration (List<Attribute>? attrs) throws ParseError {
+	Symbol parse_errordomain_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		expect (TokenType.ERRORDOMAIN);
 		var flags = parse_type_declaration_modifiers ();
@@ -3582,7 +3583,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		return param;
 	}
 
-	CreationMethod parse_creation_method_declaration (List<Attribute>? attrs) throws ParseError {
+	CreationMethod parse_creation_method_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		CreationMethod method;
 
@@ -3632,7 +3633,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		return method;
 	}
 
-	Symbol parse_delegate_declaration (List<Attribute>? attrs) throws ParseError {
+	Symbol parse_delegate_declaration (Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		DataType type;
 
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index 567d9be..73cfb13 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -673,19 +673,18 @@ public class Vala.GirParser : CodeVisitor {
 						} else if (sym is Method && !(sym is CreationMethod) && node != this) {
 							if (m.is_virtual || m.is_abstract) {
 								bool different_invoker = false;
-								foreach (var attr in m.attributes) {
-									if (attr.name == "NoWrapper") {
-										/* no invoker but this method has the same name,
-										   most probably the invoker has a different name
-										   and g-ir-scanner missed it */
-										var invoker = parser.find_invoker (this);
-										if (invoker != null) {
-											m.vfunc_name = m.name;
-											m.name = invoker.symbol.name;
-											m.attributes.remove (attr);
-											invoker.merged = true;
-											different_invoker = true;
-										}
+								var a = m.get_attribute ("NoWrapper");
+								if (a != null) {
+									/* no invoker but this method has the same name,
+									   most probably the invoker has a different name
+									   and g-ir-scanner missed it */
+									var invoker = parser.find_invoker (this);
+									if (invoker != null) {
+										m.vfunc_name = m.name;
+										m.name = invoker.symbol.name;
+										m.attributes.remove ("NoWrapper");
+										invoker.merged = true;
+										different_invoker = true;
 									}
 								}
 								if (!different_invoker) {
@@ -2473,7 +2472,7 @@ public class Vala.GirParser : CodeVisitor {
 					m.is_virtual = true;
 				}
 				if (invoker == null && !metadata.has_argument (ArgumentType.VFUNC_NAME)) {
-					s.attributes.append (new Attribute ("NoWrapper", s.source_reference));
+					s.add_attribute ("NoWrapper", s.source_reference);
 				} else {
 					if (current.girdata["name"] != name) {
 						m.vfunc_name = current.girdata["name"];
@@ -3137,7 +3136,9 @@ public class Vala.GirParser : CodeVisitor {
 				method.external = true;
 				method.coroutine = true;
 				method.has_construct_function = finish_method.has_construct_function;
-				method.attributes = m.attributes.copy ();
+				foreach (var attr in m.attributes.get_values ()) {
+					method.attributes.set (attr.name, attr);
+				}
 				method.set_cname (node.get_cname ());
 				if (finish_method_base == "new") {
 					method.name = null;
diff --git a/vala/valainterface.vala b/vala/valainterface.vala
index d189323..d63a799 100644
--- a/vala/valainterface.vala
+++ b/vala/valainterface.vala
@@ -488,7 +488,7 @@ public class Vala.Interface : ObjectTypeSymbol {
 	 * Process all associated attributes.
 	 */
 	public void process_attributes () {
-		foreach (Attribute a in attributes) {
+		foreach (Attribute a in attributes.get_values ()) {
 			if (a.name == "CCode") {
 				process_ccode_attribute (a);
 			} else if (a.name == "Deprecated") {
diff --git a/vala/valamethod.vala b/vala/valamethod.vala
index 9664072..32f8de4 100644
--- a/vala/valamethod.vala
+++ b/vala/valamethod.vala
@@ -485,7 +485,7 @@ public class Vala.Method : Subroutine {
 	 * Process all associated attributes.
 	 */
 	public void process_attributes () {
-		foreach (Attribute a in attributes) {
+		foreach (Attribute a in attributes.get_values ()) {
 			if (a.name == "CCode") {
 				process_ccode_attribute (a);
 			} else if (a.name == "ReturnsModifiedPointer") {
diff --git a/vala/valanamespace.vala b/vala/valanamespace.vala
index 45abd68..daa7f5d 100644
--- a/vala/valanamespace.vala
+++ b/vala/valanamespace.vala
@@ -599,10 +599,9 @@ public class Vala.Namespace : Symbol {
 	 * Process all associated attributes.
 	 */
 	public void process_attributes () {
-		foreach (Attribute a in attributes) {
-			if (a.name == "CCode") {
-				process_ccode_attribute (a);
-			}
+		var a = get_attribute ("CCode");
+		if (a != null) {
+			process_ccode_attribute (a);
 		}
 	}
 
diff --git a/vala/valaparameter.vala b/vala/valaparameter.vala
index ab4d4a3..81b6db8 100644
--- a/vala/valaparameter.vala
+++ b/vala/valaparameter.vala
@@ -143,10 +143,9 @@ public class Vala.Parameter : Variable {
 	public override void process_attributes () {
 		base.process_attributes ();
 
-		foreach (Attribute a in attributes) {
-			if (a.name == "CCode") {
-				process_ccode_attribute (a);
-			}
+		var a = get_attribute ("CCode");
+		if (a != null) {
+			process_ccode_attribute (a);
 		}
 	}
 
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 60c7a60..44bb682 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -2081,13 +2081,20 @@ public class Vala.Parser : CodeVisitor {
 		return new DeleteStatement (expr, get_src (begin));
 	}
 
-	string parse_attribute_value () throws ParseError {
+	Value parse_attribute_value () throws ParseError {
 		switch (current ()) {
-		case TokenType.NULL:
 		case TokenType.TRUE:
+			next ();
+			return true;
 		case TokenType.FALSE:
+			next ();
+			return false;
 		case TokenType.INTEGER_LITERAL:
+			next ();
+			return int.parse (get_last_string ());
 		case TokenType.REAL_LITERAL:
+			next ();
+			return double.parse (get_last_string ());
 		case TokenType.STRING_LITERAL:
 			next ();
 			return get_last_string ();
@@ -2095,9 +2102,11 @@ public class Vala.Parser : CodeVisitor {
 			next ();
 			switch (current ()) {
 			case TokenType.INTEGER_LITERAL:
+				next ();
+				return -int.parse (get_last_string ());
 			case TokenType.REAL_LITERAL:
 				next ();
-				return "-" + get_last_string ();
+				return -double.parse (get_last_string ());
 			default:
 				throw new ParseError.SYNTAX (get_error ("expected number"));
 			}
@@ -2106,16 +2115,20 @@ public class Vala.Parser : CodeVisitor {
 		}
 	}
 
-	List<Attribute>? parse_attributes () throws ParseError {
+	Map<string,Attribute>? parse_attributes () throws ParseError {
 		if (current () != TokenType.OPEN_BRACKET) {
 			return null;
 		}
-		var attrs = new ArrayList<Attribute> ();
+		var attrs = new HashMap<string,Attribute> (str_hash, str_equal);
 		while (accept (TokenType.OPEN_BRACKET)) {
 			do {
 				var begin = get_location ();
 				string id = parse_identifier ();
-				var attr = new Attribute (id, get_src (begin));
+				var attr = attrs.get (id);
+				if (attr == null) {
+					attr = new Attribute (id, get_src (begin));
+					attrs.set (id, attr);
+				}
 				if (accept (TokenType.OPEN_PARENS)) {
 					if (current () != TokenType.CLOSE_PARENS) {
 						do {
@@ -2126,18 +2139,15 @@ public class Vala.Parser : CodeVisitor {
 					}
 					expect (TokenType.CLOSE_PARENS);
 				}
-				attrs.add (attr);
 			} while (accept (TokenType.COMMA));
 			expect (TokenType.CLOSE_BRACKET);
 		}
 		return attrs;
 	}
 
-	void set_attributes (CodeNode node, List<Attribute>? attributes) {
+	void set_attributes (CodeNode node, Map<string,Attribute>? attributes) {
 		if (attributes != null) {
-			foreach (Attribute attr in (List<Attribute>) attributes) {
-				node.attributes.append (attr);
-			}
+			node.attributes = attributes;
 		}
 	}
 
@@ -2398,7 +2408,7 @@ public class Vala.Parser : CodeVisitor {
 		return RecoveryState.EOF;
 	}
 
-	void parse_namespace_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_namespace_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		expect (TokenType.NAMESPACE);
 		var sym = parse_symbol_name ();
@@ -2449,7 +2459,7 @@ public class Vala.Parser : CodeVisitor {
 		}
 	}
 
-	void parse_class_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_class_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var access = parse_access_modifier ();
 		var flags = parse_type_declaration_modifiers ();
@@ -2504,7 +2514,7 @@ public class Vala.Parser : CodeVisitor {
 		}
 	}
 
-	void parse_constant_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_constant_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var access = parse_access_modifier ();
 		var flags = parse_member_declaration_modifiers ();
@@ -2539,7 +2549,7 @@ public class Vala.Parser : CodeVisitor {
 		parent.add_constant (c);
 	}
 
-	void parse_field_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_field_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var access = parse_access_modifier ();
 		var flags = parse_member_declaration_modifiers ();
@@ -2644,7 +2654,7 @@ public class Vala.Parser : CodeVisitor {
 		return map;
 	}
 
-	void parse_method_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_method_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var access = parse_access_modifier ();
 		var flags = parse_member_declaration_modifiers ();
@@ -2741,7 +2751,7 @@ public class Vala.Parser : CodeVisitor {
 		parent.add_method (method);
 	}
 
-	void parse_property_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_property_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var access = parse_access_modifier ();
 		var flags = parse_member_declaration_modifiers ();
@@ -2883,7 +2893,7 @@ public class Vala.Parser : CodeVisitor {
 		parent.add_property (prop);
 	}
 
-	void parse_signal_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_signal_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var access = parse_access_modifier ();
 		var flags = parse_member_declaration_modifiers ();
@@ -2919,7 +2929,7 @@ public class Vala.Parser : CodeVisitor {
 		parent.add_signal (sig);
 	}
 
-	void parse_constructor_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_constructor_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var flags = parse_member_declaration_modifiers ();
 		expect (TokenType.CONSTRUCT);
@@ -2937,7 +2947,7 @@ public class Vala.Parser : CodeVisitor {
 		parent.add_constructor (c);
 	}
 
-	void parse_destructor_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_destructor_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var flags = parse_member_declaration_modifiers ();
 		expect (TokenType.TILDE);
@@ -2958,7 +2968,7 @@ public class Vala.Parser : CodeVisitor {
 		parent.add_destructor (d);
 	}
 
-	void parse_struct_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_struct_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var access = parse_access_modifier ();
 		var flags = parse_type_declaration_modifiers ();
@@ -2998,7 +3008,7 @@ public class Vala.Parser : CodeVisitor {
 		}
 	}
 
-	void parse_interface_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_interface_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var access = parse_access_modifier ();
 		var flags = parse_type_declaration_modifiers ();
@@ -3041,7 +3051,7 @@ public class Vala.Parser : CodeVisitor {
 		}
 	}
 
-	void parse_enum_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_enum_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var access = parse_access_modifier ();
 		var flags = parse_type_declaration_modifiers ();
@@ -3098,7 +3108,7 @@ public class Vala.Parser : CodeVisitor {
 		}
 	}
 
-	void parse_errordomain_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_errordomain_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var access = parse_access_modifier ();
 		var flags = parse_type_declaration_modifiers ();
@@ -3285,7 +3295,7 @@ public class Vala.Parser : CodeVisitor {
 		return param;
 	}
 
-	void parse_creation_method_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_creation_method_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var access = parse_access_modifier ();
 		var flags = parse_member_declaration_modifiers ();
@@ -3355,7 +3365,7 @@ public class Vala.Parser : CodeVisitor {
 		parent.add_method (method);
 	}
 
-	void parse_delegate_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
+	void parse_delegate_declaration (Symbol parent, Map<string, Attribute>? attrs) throws ParseError {
 		var begin = get_location ();
 		var access = parse_access_modifier ();
 		var flags = parse_member_declaration_modifiers ();
diff --git a/vala/valaproperty.vala b/vala/valaproperty.vala
index 467cdf8..27ef0fa 100644
--- a/vala/valaproperty.vala
+++ b/vala/valaproperty.vala
@@ -280,7 +280,7 @@ public class Vala.Property : Symbol, Lockable {
 	 * Process all associated attributes.
 	 */
 	public void process_attributes () {
-		foreach (Attribute a in attributes) {
+		foreach (Attribute a in attributes.get_values ()) {
 			if (a.name == "CCode") {
 				process_ccode_attribute (a);
 			} else if (a.name == "NoAccessorMethod") {
diff --git a/vala/valapropertyaccessor.vala b/vala/valapropertyaccessor.vala
index dc4a8b3..c86e46a 100644
--- a/vala/valapropertyaccessor.vala
+++ b/vala/valapropertyaccessor.vala
@@ -140,11 +140,10 @@ public class Vala.PropertyAccessor : Subroutine {
 	 * Process all associated attributes.
 	 */
 	public void process_attributes () {
-		foreach (Attribute a in attributes) {
-			if (a.name == "CCode") {
-				if (a.has_argument ("cname")) {
-					_cname = a.get_string ("cname");
-				}
+		var a = get_attribute ("CCode");
+		if (a != null) {
+			if (a.has_argument ("cname")) {
+				_cname = a.get_string ("cname");
 			}
 		}
 	}
diff --git a/vala/valasignal.vala b/vala/valasignal.vala
index ea4b767..5b7e000 100644
--- a/vala/valasignal.vala
+++ b/vala/valasignal.vala
@@ -264,7 +264,7 @@ public class Vala.Signal : Symbol, Lockable {
 	 * Process all associated attributes.
 	 */
 	public void process_attributes () {
-		foreach (Attribute a in attributes) {
+		foreach (Attribute a in attributes.get_values ()) {
 			if (a.name == "HasEmitter") {
 				has_emitter = true;
 			} else if (a.name == "Signal") {
diff --git a/vala/valastruct.vala b/vala/valastruct.vala
index a492233..4166311 100644
--- a/vala/valastruct.vala
+++ b/vala/valastruct.vala
@@ -496,7 +496,7 @@ public class Vala.Struct : TypeSymbol {
 	 * Process all associated attributes.
 	 */
 	public void process_attributes () {
-		foreach (Attribute a in attributes) {
+		foreach (Attribute a in attributes.get_values ()) {
 			if (a.name == "CCode") {
 				process_ccode_attribute (a);
 			} else if (a.name == "BooleanType") {
@@ -713,7 +713,7 @@ public class Vala.Struct : TypeSymbol {
 	 * value.
 	 */
 	public void set_simple_type (bool simple_type) {
-		attributes.append (new Attribute ("SimpleType"));
+		add_attribute ("SimpleType");
 	}
 
 	public override void replace_type (DataType old_type, DataType new_type) {
diff --git a/vala/valavariable.vala b/vala/valavariable.vala
index 56cb1ae..d07006e 100644
--- a/vala/valavariable.vala
+++ b/vala/valavariable.vala
@@ -162,10 +162,9 @@ public class Vala.Variable : Symbol {
 	 * Process all associated attributes.
 	 */
 	public virtual void process_attributes () {
-		foreach (Attribute a in attributes) {
-			if (a.name == "CCode") {
-				process_ccode_attribute (a);
-			}
+		var a = get_attribute ("CCode");
+		if (a != null) {
+			process_ccode_attribute (a);
 		}
 	}
 }



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