]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
WIP vala: Use Vala.Expression as Vala.Attribute values wip/attribute-expression
authorRico Tzschichholz <ricotz@ubuntu.com>
Mon, 30 Jan 2023 19:19:50 +0000 (20:19 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 2 Aug 2023 13:50:42 +0000 (15:50 +0200)
21 files changed:
codegen/valagdbusclientmodule.vala
codegen/valagdbusmodule.vala
libvaladoc/api/attribute.vala
vala/valaattribute.vala
vala/valaclass.vala
vala/valacodenode.vala
vala/valacodewriter.vala
vala/valaconstant.vala
vala/valadelegate.vala
vala/valaenum.vala
vala/valaenumvalue.vala
vala/valaerrorcode.vala
vala/valaerrordomain.vala
vala/valafield.vala
vala/valagenieparser.vala
vala/valamethod.vala
vala/valanamespace.vala
vala/valaparameter.vala
vala/valaparser.vala
vala/valasignal.vala
vala/valastruct.vala

index 697b0875875f298bbc251b9af5c643a43c4a7d3e..da715d2a5a352f1cd2c8c5228c9b33af2f4b0be4 100644 (file)
@@ -29,17 +29,15 @@ public class Vala.GDBusClientModule : GDBusModule {
                NO_REPLY
        }
 
-       public CCodeConstant get_dbus_timeout (Symbol symbol) {
-               int timeout = -1;
-
+       public CCodeExpression get_dbus_timeout (Symbol symbol) {
                var dbus = symbol.get_attribute ("DBus");
                if (dbus != null && dbus.has_argument ("timeout")) {
-                       timeout = dbus.get_integer ("timeout");
+                       return get_ccodenode (dbus.get_expression ("timeout"));
                } else if (symbol.parent_symbol != null) {
                        return get_dbus_timeout (symbol.parent_symbol);
                }
 
-               return new CCodeConstant (timeout.to_string ());
+               return new CCodeConstant ("-1");
        }
 
        public override void generate_dynamic_method_wrapper (DynamicMethod method) {
@@ -53,7 +51,7 @@ public class Vala.GDBusClientModule : GDBusModule {
                push_function (func);
 
                if (method.dynamic_type.type_symbol == dbus_proxy_type) {
-                       generate_marshalling (method, CallType.SYNC, null, method.name, -1);
+                       generate_marshalling (method, CallType.SYNC, null, method.name, null);
                } else {
                        Report.error (method.source_reference, "dynamic methods are not supported for `%s'", method.dynamic_type.to_string ());
                }
@@ -555,7 +553,7 @@ public class Vala.GDBusClientModule : GDBusModule {
                cfile.add_function (cfunc);
        }
 
-       void generate_marshalling (Method m, CallType call_type, string? iface_name, string? method_name, int method_timeout) {
+       void generate_marshalling (Method m, CallType call_type, string? iface_name, string? method_name, CCodeExpression? method_timeout) {
                var gdbusproxy = new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *");
 
                var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_connection"));
@@ -586,11 +584,11 @@ public class Vala.GDBusClientModule : GDBusModule {
                        object_path.add_argument (gdbusproxy);
 
                        CCodeExpression timeout;
-                       if (method_timeout <= 0) {
+                       if (method_timeout == null) {
                                timeout = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_default_timeout"));
                                ((CCodeFunctionCall) timeout).add_argument (gdbusproxy);
                        } else {
-                               timeout = new CCodeConstant ("%d".printf (method_timeout));
+                               timeout = method_timeout;
                        }
 
                        // register errors
@@ -962,7 +960,7 @@ public class Vala.GDBusClientModule : GDBusModule {
 
                push_function (function);
 
-               generate_marshalling (m, CallType.FINISH, null, null, -1);
+               generate_marshalling (m, CallType.FINISH, null, null, null);
 
                pop_function ();
 
index 59ab1de8b76af8591176c8a4fb1ae68c6e783483..5e59b2369e69fcf015abb0063eadcc6fa97c8649 100644 (file)
@@ -34,8 +34,13 @@ public class Vala.GDBusModule : GVariantModule {
                return Symbol.lower_case_to_camel_case (symbol.name);
        }
 
-       public static int get_dbus_timeout_for_member (Symbol symbol) {
-               return symbol.get_attribute_integer ("DBus", "timeout", -1);
+       public CCodeExpression get_dbus_timeout_for_member (Symbol symbol) {
+               var dbus = symbol.get_attribute ("DBus");
+               if (dbus != null && dbus.has_argument ("timeout")) {
+                       return get_ccodenode (dbus.get_expression ("timeout"));
+               }
+
+               return null; //new CCodeConstant ("-1");
        }
 
        public static bool is_dbus_visible (CodeNode node) {
index befdfe95d568c9a8977587528fd67bb805a1c5b3..1a0e7312604176123b9ad0be82048bc02ec6ef59 100644 (file)
@@ -78,7 +78,7 @@ public class Valadoc.Api.Attribute : Item {
                                if (arg_name != "cheader_filename") {
                                        builder.append_attribute (arg_name);
                                        builder.append_attribute ("=");
-                                       builder.append_literal (attr.args.get (arg_name));
+                                       builder.append_literal (attr.args.get (arg_name).to_string ());
                                }
                                separator = ", ";
                        }
index 58a56ca5d7b2da8d4343a3713c745137b0699d61..21afe3c7262ba19ae54651b82734e733b458b10a 100644 (file)
@@ -34,7 +34,7 @@ public class Vala.Attribute : CodeNode {
        /**
         * Contains all specified attribute arguments.
         */
-       public Vala.Map<string,string> args { get; private set; }
+       public Vala.Map<string,Expression> args { get; private set; }
 
        /**
         * Creates a new attribute.
@@ -46,7 +46,7 @@ public class Vala.Attribute : CodeNode {
        public Attribute (string name, SourceReference? source_reference = null) {
                this.name = name;
                this.source_reference = source_reference;
-               this.args = new HashMap<string,string> (str_hash, str_equal);
+               this.args = new HashMap<string,Expression> (str_hash, str_equal);
 
                if (!CodeContext.get ().deprecated) {
                        if (name == "Deprecated") {
@@ -63,7 +63,7 @@ public class Vala.Attribute : CodeNode {
         * @param key    argument name
         * @param value  argument value
         */
-       public void add_argument (string key, string value) {
+       public void add_argument (string key, Expression value) {
                args.set (key, value);
        }
 
@@ -77,6 +77,22 @@ public class Vala.Attribute : CodeNode {
                return args.contains (name);
        }
 
+       /**
+        * Returns the expression of the specified named argument.
+        *
+        * @param name argument name
+        * @return     expression value
+        */
+       public Expression? get_expression (string name, Expression? default_value = null) {
+               Expression? value = args.get (name);
+
+               if (value == null) {
+                       return default_value;
+               }
+
+               return value;
+       }
+
        /**
         * Returns the string value of the specified named argument.
         *
@@ -84,16 +100,15 @@ public class Vala.Attribute : CodeNode {
         * @return     string value
         */
        public string? get_string (string name, string? default_value = null) {
-               string value = args.get (name);
+               Expression? value = args.get (name);
 
                if (value == null) {
                        return default_value;
                }
 
-               /* remove quotes */
-               var noquotes = value.substring (1, (uint) (value.length - 2));
-               /* unescape string */
-               return noquotes.compress ();
+               assert (value is StringLiteral);
+
+               return ((StringLiteral) value).eval ();
        }
 
        /**
@@ -103,13 +118,15 @@ public class Vala.Attribute : CodeNode {
         * @return     integer value
         */
        public int get_integer (string name, int default_value = 0) {
-               string value = args.get (name);
+               Expression? value = args.get (name);
 
                if (value == null) {
                        return default_value;
                }
 
-               return int.parse (value);
+               assert (value is IntegerLiteral);
+
+               return int.parse (((IntegerLiteral) value).value);
        }
 
        /**
@@ -119,13 +136,19 @@ public class Vala.Attribute : CodeNode {
         * @return     double value
         */
        public double get_double (string name, double default_value = 0) {
-               string value = args.get (name);
+               Expression? value = args.get (name);
 
                if (value == null) {
                        return default_value;
                }
 
-               return double.parse (value);
+               assert (value is RealLiteral || value is IntegerLiteral);
+
+               if (value is IntegerLiteral) {
+                       return int.parse (((IntegerLiteral) value).value);
+               } else {
+                       return double.parse (((RealLiteral) value).value);
+               }
        }
 
        /**
@@ -135,12 +158,28 @@ public class Vala.Attribute : CodeNode {
         * @return     boolean value
         */
        public bool get_bool (string name, bool default_value = false) {
-               string value = args.get (name);
+               Expression? value = args.get (name);
 
                if (value == null) {
                        return default_value;
                }
 
-               return bool.parse (value);
+               assert (value is BooleanLiteral);
+
+               return ((BooleanLiteral) value).value;
+       }
+
+       public override bool check (CodeContext context) {
+               foreach (var attr in args.get_values ()) {
+                       if (!attr.check (context)) {
+                               return false;
+                       }
+                       if (!attr.is_constant ()) {
+                               Report.error (attr.source_reference, "attribute values must be constant");
+                               return false;
+                       }
+               }
+
+               return true;
        }
 }
index cf2943e4de15a4bd6455b8580f003833671c769c..769de3ba7e2037150fd27159cc18740244bd97f2 100644 (file)
@@ -540,6 +540,8 @@ public class Vala.Class : ObjectTypeSymbol {
                }
                context.analyzer.current_symbol = this;
 
+               base.check (context);
+
                foreach (DataType base_type_reference in get_base_types ()) {
                        if (!base_type_reference.check (context)) {
                                error = true;
index 3ff39dbc8e7c9b9a862d302c58d49e4f7109d534..d22ecb92a4e186184d0b3e26e65ed4ccb7898b09 100644 (file)
@@ -91,6 +91,10 @@ public abstract class Vala.CodeNode {
        }
 
        public virtual bool check (CodeContext context) {
+               foreach (unowned Attribute a in attributes) {
+                       a.check (context);
+               }
+
                return true;
        }
 
@@ -283,7 +287,7 @@ public abstract class Vala.CodeNode {
                }
 
                unowned Attribute a = get_or_create_attribute (attribute);
-               a.add_argument (argument, "\"%s\"".printf (value));
+               a.add_argument (argument, new StringLiteral ("\"%s\"".printf (value)));
        }
 
        /**
@@ -295,7 +299,7 @@ public abstract class Vala.CodeNode {
         */
        public void set_attribute_integer (string attribute, string argument, int value, SourceReference? source_reference = null) {
                unowned Attribute a = get_or_create_attribute (attribute);
-               a.add_argument (argument, value.to_string ());
+               a.add_argument (argument, new IntegerLiteral (value.to_string (), source_reference));
        }
 
        /**
@@ -307,7 +311,7 @@ public abstract class Vala.CodeNode {
         */
        public void set_attribute_double (string attribute, string argument, double value, SourceReference? source_reference = null) {
                unowned Attribute a = get_or_create_attribute (attribute);
-               a.add_argument (argument, value.format (new char[double.DTOSTR_BUF_SIZE]));
+               a.add_argument (argument, new RealLiteral (value.format (new char[double.DTOSTR_BUF_SIZE]), source_reference));
        }
 
        /**
@@ -319,7 +323,7 @@ public abstract class Vala.CodeNode {
         */
        public void set_attribute_bool (string attribute, string argument, bool value, SourceReference? source_reference = null) {
                unowned Attribute a = get_or_create_attribute (attribute);
-               a.add_argument (argument, value.to_string ());
+               a.add_argument (argument, new BooleanLiteral (value, source_reference));
        }
 
        /**
index c016497b5d2f6c78ba189db26a7f913ec39fc671..cf9028b84f6760de09dcd470fbbbebbd0f3ddb9b 100644 (file)
@@ -1713,7 +1713,8 @@ public class Vala.CodeWriter : CodeVisitor {
                                        if (arg_name == "cheader_filename") {
                                                stream.printf ("%scheader_filename = \"%s\"", separator, get_cheaders (sym));
                                        } else {
-                                               stream.printf ("%s%s = %s", separator, arg_name, attr.args.get (arg_name));
+                                               stream.printf ("%s%s = ", separator, arg_name);
+                                               attr.args.get (arg_name).accept (this);
                                        }
                                        separator = ", ";
                                }
index 9ada91cb3561a91265d091d08d33263ffe98f098..de1da25756c72be45b6ab83f81f25310ac9a9aa3 100644 (file)
@@ -113,6 +113,8 @@ public class Vala.Constant : Symbol {
                        context.analyzer.current_symbol = this;
                }
 
+               base.check (context);
+
                type_reference.check (context);
 
                if (!check_const_type (type_reference, context)) {
index e7ec720a25aab4c87b3cc5bff42d1803f4385c72..c6ca6968a7357e0d6c9ab1e39027dba08c3612f0 100644 (file)
@@ -314,6 +314,8 @@ public class Vala.Delegate : TypeSymbol, Callable, GenericSymbol {
                        context.analyzer.current_source_file = source_reference.file;
                }
 
+               base.check (context);
+
                foreach (TypeParameter p in type_parameters) {
                        p.check (context);
                }
index b2b40285c2a8ce4d4e9fca23fb5d6212c000339e..699c9782608d51da7738a2ce673b17b54094de41 100644 (file)
@@ -166,6 +166,8 @@ public class Vala.Enum : TypeSymbol {
                }
                context.analyzer.current_symbol = this;
 
+               base.check (context);
+
                if (values.size <= 0) {
                        Report.error (source_reference, "Enum `%s' requires at least one value", get_full_name ());
                        error = true;
index be3fcc52ea65c98bd087888a2eb24f123d14dd00..a02ce178fac368043c7030bdf7c504f7f6fbe1a9 100644 (file)
@@ -71,6 +71,8 @@ public class Vala.EnumValue : Constant {
 
                checked = true;
 
+               base.check (context);
+
                if (value != null) {
                        value.check (context);
 
index 5fcff75858867c3c488059ed5cd538a8524efc31..7c912c5c5a5c7999579d17a923bc22f2f11029fa 100644 (file)
@@ -112,6 +112,8 @@ public class Vala.ErrorCode : TypeSymbol {
 
                checked = true;
 
+               base.check (context);
+
                if (value != null) {
                        value.check (context);
                }
index 889d0b8abfecc067cb17b7fdb6bf0673a78ddace..8bf5f4e34a3c8fd981cd655f429c8e8e9aa1bd39 100644 (file)
@@ -114,6 +114,8 @@ public class Vala.ErrorDomain : TypeSymbol {
 
                checked = true;
 
+               base.check (context);
+
                if (codes.size <= 0) {
                        Report.error (source_reference, "Error domain `%s' requires at least one code", get_full_name ());
                        error = true;
index 2f675a96f6183280969dbd07ece95efc430bc38d..a57e5eecac21b008160c04b33383fc1aced7678e 100644 (file)
@@ -92,6 +92,8 @@ public class Vala.Field : Variable, Lockable {
                }
                context.analyzer.current_symbol = this;
 
+               base.check (context);
+
                if (variable_type is VoidType) {
                        error = true;
                        Report.error (source_reference, "'void' not supported as field type");
index 4134b21c8ac6d2086a17404fa910a44878b24e1c..81e7ca505e433eeacca1244c9fb05e6536084e7c 100644 (file)
@@ -2358,31 +2358,6 @@ public class Vala.Genie.Parser : CodeVisitor {
                return new DeleteStatement (expr, get_src (begin));
        }
 
-       string parse_attribute_value () throws ParseError {
-               switch (current ()) {
-               case TokenType.NULL:
-               case TokenType.TRUE:
-               case TokenType.FALSE:
-               case TokenType.INTEGER_LITERAL:
-               case TokenType.REAL_LITERAL:
-               case TokenType.STRING_LITERAL:
-                       next ();
-                       return get_last_string ();
-               case TokenType.MINUS:
-                       next ();
-                       switch (current ()) {
-                       case TokenType.INTEGER_LITERAL:
-                       case TokenType.REAL_LITERAL:
-                               next ();
-                               return "-" + get_last_string ();
-                       default:
-                               throw new ParseError.SYNTAX ("expected number");
-                       }
-               default:
-                       throw new ParseError.SYNTAX ("expected literal");
-               }
-       }
-
        List<Attribute>? parse_attributes (bool parameter) throws ParseError {
                if (current () != TokenType.OPEN_BRACKET) {
                        return null;
@@ -2398,7 +2373,7 @@ public class Vala.Genie.Parser : CodeVisitor {
                                                do {
                                                        id = parse_identifier ();
                                                        expect (TokenType.ASSIGN);
-                                                       attr.add_argument (id, parse_attribute_value ());
+                                                       attr.add_argument (id, parse_unary_expression ());
                                                } while (accept (TokenType.COMMA));
                                        }
                                        expect (TokenType.CLOSE_PARENS);
index 6a1d686cf33b2bfc4ec959d1093706f86ec38e55..c19291119d09b33e468bd34f8288f0e11d88bdf2 100644 (file)
@@ -748,6 +748,8 @@ public class Vala.Method : Subroutine, Callable, GenericSymbol {
 
                checked = true;
 
+               base.check (context);
+
                if (this_parameter != null) {
                        this_parameter.check (context);
                }
index 1e763f32e4967379a879464bf48e91db39670d9b..6c2b6d910cbf17da152cb4a9311ef295cb94339a 100644 (file)
@@ -465,6 +465,8 @@ public class Vala.Namespace : Symbol {
 
                checked = true;
 
+               base.check (context);
+
                var a = get_attribute ("CCode");
                if (a != null && a.has_argument ("gir_namespace")) {
                        var new_gir = a.get_string ("gir_namespace");
index eaf08746d889f42aa2f35d60338e4f4e16195a92..0882092498ce762c853eb2036dd997e7e6f71ace 100644 (file)
@@ -140,6 +140,8 @@ public class Vala.Parameter : Variable {
                }
                context.analyzer.current_symbol = parent_symbol;
 
+               base.check (context);
+
                if (variable_type != null) {
                        if (variable_type is VoidType) {
                                error = true;
index 33cb4843ee2dfab378c2f66444a84bf97032095f..5dc25b7925bb6b20eb289ba85e3a2748d60a58ae 100644 (file)
@@ -2578,31 +2578,6 @@ public class Vala.Parser : CodeVisitor {
                return new WithStatement (local, expr, body, src);
        }
 
-       string parse_attribute_value () throws ParseError {
-               switch (current ()) {
-               case TokenType.NULL:
-               case TokenType.TRUE:
-               case TokenType.FALSE:
-               case TokenType.INTEGER_LITERAL:
-               case TokenType.REAL_LITERAL:
-               case TokenType.STRING_LITERAL:
-                       next ();
-                       return get_last_string ();
-               case TokenType.MINUS:
-                       next ();
-                       switch (current ()) {
-                       case TokenType.INTEGER_LITERAL:
-                       case TokenType.REAL_LITERAL:
-                               next ();
-                               return "-" + get_last_string ();
-                       default:
-                               throw new ParseError.SYNTAX ("expected number");
-                       }
-               default:
-                       throw new ParseError.SYNTAX ("expected literal");
-               }
-       }
-
        List<Attribute>? parse_attributes () throws ParseError {
                if (current () != TokenType.OPEN_BRACKET) {
                        return null;
@@ -2618,7 +2593,7 @@ public class Vala.Parser : CodeVisitor {
                                                do {
                                                        id = parse_identifier ();
                                                        expect (TokenType.ASSIGN);
-                                                       attr.add_argument (id, parse_attribute_value ());
+                                                       attr.add_argument (id, parse_unary_expression ());
                                                } while (accept (TokenType.COMMA));
                                        }
                                        expect (TokenType.CLOSE_PARENS);
index 1da87cff06e8f19b640450d0234945fa87555e59..e8630c054e119055c0aaa79ee453e0e4201b8875 100644 (file)
@@ -183,6 +183,8 @@ public class Vala.Signal : Symbol, Callable {
 
                checked = true;
 
+               base.check (context);
+
                // parent_symbol may be null for dynamic signals
                unowned Class? parent_cl = parent_symbol as Class;
                if (parent_cl != null && parent_cl.is_compact) {
index 52c85dac725a71e000b5f7a3e48e1215f46b87c6..6e24e551b5ac00be5121ca26f524a3f8e5889312 100644 (file)
@@ -506,6 +506,8 @@ public class Vala.Struct : TypeSymbol, GenericSymbol {
                }
                context.analyzer.current_symbol = this;
 
+               base.check (context);
+
                if (base_type != null) {
                        base_type.check (context);