[vala/wip/defines: 2/2] Support `define' expressions in global scope of source files



commit af6a2cf8e7f736e14a1b0a4a9c01df8d5ac2fd4e
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Wed Mar 13 08:40:04 2019 +0100

    Support `define' expressions in global scope of source files
    
    Fixes https://gitlab.gnome.org/GNOME/vala/issues/765

 ccode/valaccodefile.vala         | 10 +++++--
 codegen/valaccodeattribute.vala  |  4 ++-
 codegen/valaccodebasemodule.vala | 16 ++++++++++
 tests/Makefile.am                |  1 +
 tests/parser/define.vala         |  5 ++++
 vala/Makefile.am                 |  1 +
 vala/valacodevisitor.vala        |  8 +++++
 vala/valadefine.vala             | 63 ++++++++++++++++++++++++++++++++++++++++
 vala/valaparser.vala             | 17 +++++++++++
 vala/valascanner.vala            |  9 +++++-
 vala/valasourcefile.vala         | 22 ++++++++++++++
 vala/valasymbolresolver.vala     | 12 ++++++++
 vala/valatokentype.vala          |  2 ++
 13 files changed, 165 insertions(+), 5 deletions(-)
---
diff --git a/ccode/valaccodefile.vala b/ccode/valaccodefile.vala
index adbdb1880..5321e1868 100644
--- a/ccode/valaccodefile.vala
+++ b/ccode/valaccodefile.vala
@@ -30,7 +30,7 @@ public class Vala.CCodeFile {
        Set<string> declarations = new HashSet<string> (str_hash, str_equal);
        Set<string> includes = new HashSet<string> (str_hash, str_equal);
        CCodeFragment comments = new CCodeFragment ();
-       CCodeFragment feature_test_macros = new CCodeFragment ();
+       CCodeFragment defines = new CCodeFragment ();
        CCodeFragment include_directives = new CCodeFragment ();
        CCodeFragment type_declaration = new CCodeFragment ();
        CCodeFragment type_definition = new CCodeFragment ();
@@ -54,9 +54,13 @@ public class Vala.CCodeFile {
                comments.append (comment);
        }
 
+       public void add_define (CCodeNode node) {
+               defines.append (node);
+       }
+
        public void add_feature_test_macro (string feature_test_macro) {
                if (!(feature_test_macro in features)) {
-                       feature_test_macros.append (new CCodeDefine (feature_test_macro));
+                       defines.append (new CCodeDefine (feature_test_macro));
                        features.add (feature_test_macro);
                }
        }
@@ -148,7 +152,7 @@ public class Vala.CCodeFile {
 
                        comments.write (writer);
                        writer.write_newline ();
-                       feature_test_macros.write (writer);
+                       defines.write (writer);
                        writer.write_newline ();
                        include_directives.write (writer);
                        writer.write_newline ();
diff --git a/codegen/valaccodeattribute.vala b/codegen/valaccodeattribute.vala
index 5615eb618..c0865cfd3 100644
--- a/codegen/valaccodeattribute.vala
+++ b/codegen/valaccodeattribute.vala
@@ -682,7 +682,9 @@ public class Vala.CCodeAttribute : AttributeCache {
 
        private string get_default_name () {
                if (sym != null) {
-                       if (sym is Constant && !(sym is EnumValue)) {
+                       if (sym is Define) {
+                               return sym.name;
+                       } else if (sym is Constant && !(sym is EnumValue)) {
                                if (sym.parent_symbol is Block) {
                                        // local constant
                                        return sym.name;
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index cc3a03f7a..5b03b3643 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -1047,6 +1047,22 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                pop_line ();
        }
 
+       public override void visit_define (Define d) {
+               push_line (d.source_reference);
+
+               d.accept_children (this);
+
+               CCodeDefine cdefine;
+               if (d.value == null) {
+                       cdefine = new CCodeDefine (get_ccode_name (d));
+               } else {
+                       cdefine = new CCodeDefine.with_expression (get_ccode_name (d), get_cvalue (d.value));
+               }
+               cfile.add_define (cdefine);
+
+               pop_line ();
+       }
+
        public void generate_field_declaration (Field f, CCodeFile decl_space) {
                if (add_symbol_declaration (decl_space, f, get_ccode_name (f))) {
                        return;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6c1653bda..6d312578f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -500,6 +500,7 @@ TESTS = \
        parser/creation-no-abstract.test \
        parser/creation-no-override.test \
        parser/creation-no-virtual.test \
+       parser/define.vala \
        parser/delegate-no-new.test \
        parser/destructor-class-exists.test \
        parser/destructor-exists.test \
diff --git a/tests/parser/define.vala b/tests/parser/define.vala
new file mode 100644
index 000000000..2bbf8c126
--- /dev/null
+++ b/tests/parser/define.vala
@@ -0,0 +1,5 @@
+define G_LOG_DOMAIN = "vala", VALA_PI = 3.1415;
+define ENABLE_SOMETHING;
+
+void main () {
+}
diff --git a/vala/Makefile.am b/vala/Makefile.am
index 6be70557d..6308b1634 100644
--- a/vala/Makefile.am
+++ b/vala/Makefile.am
@@ -62,6 +62,7 @@ libvala_la_VALASOURCES = \
        valacreationmethod.vala \
        valadatatype.vala \
        valadeclarationstatement.vala \
+       valadefine.vala \
        valadelegate.vala \
        valadelegatetype.vala \
        valadeletestatement.vala \
diff --git a/vala/valacodevisitor.vala b/vala/valacodevisitor.vala
index d961f85e9..59d825b0d 100644
--- a/vala/valacodevisitor.vala
+++ b/vala/valacodevisitor.vala
@@ -204,6 +204,14 @@ public abstract class Vala.CodeVisitor {
        public virtual void visit_using_directive (UsingDirective ns) {
        }
 
+       /**
+        * Visit operation called for defines.
+        *
+        * @param ns a define
+        */
+       public virtual void visit_define (Define d) {
+       }
+
        /**
         * Visit operation called for type references.
         *
diff --git a/vala/valadefine.vala b/vala/valadefine.vala
new file mode 100644
index 000000000..07807d88a
--- /dev/null
+++ b/vala/valadefine.vala
@@ -0,0 +1,63 @@
+/* valadefine.vala
+ *
+ * Copyright (C) 2019  Rico Tzschichholz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Rico Tzschichholz <ricotz ubuntu com>
+ */
+
+using GLib;
+
+/**
+ * Represents a define in the source code.
+ */
+public class Vala.Define : Constant {
+       /**
+        * Creates a new define.
+        *
+        * @param name  define name
+        * @param value define value
+        * @return      newly created define
+        */
+       public Define (string name, Expression? value, SourceReference? source_reference = null, Comment? 
comment = null) {
+               base (name, null, value, source_reference, comment);
+       }
+
+       public override void accept (CodeVisitor visitor) {
+               visitor.visit_define (this);
+       }
+
+       public override void accept_children (CodeVisitor visitor) {
+               if (value != null) {
+                       value.accept (visitor);
+               }
+       }
+
+       public override bool check (CodeContext context) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               if (value != null) {
+                       value.check (context);
+               }
+
+               return !error;
+       }
+}
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 2614dad72..5d98c8d91 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -338,6 +338,7 @@ public class Vala.Parser : CodeVisitor {
 
 
                try {
+                       parse_defines ();
                        parse_using_directives (context.root);
                        parse_declarations (context.root, true);
                        if (accept (TokenType.CLOSE_BRACE)) {
@@ -2535,6 +2536,22 @@ public class Vala.Parser : CodeVisitor {
                }
        }
 
+       void parse_defines () throws ParseError {
+               while (accept (TokenType.DEFINE)) {
+                       do {
+                               var begin = get_location ();
+                               var name = parse_identifier ();
+                               Expression? val = null;
+                               if (accept (TokenType.ASSIGN)) {
+                                       val = parse_literal ();
+                               }
+                               var def = new Define (name, val, get_src (begin), comment);
+                               scanner.source_file.add_define (def);
+                       } while (accept (TokenType.COMMA));
+                       expect (TokenType.SEMICOLON);
+               }
+       }
+
        void parse_class_declaration (Symbol parent, List<Attribute>? attrs) throws ParseError {
                var begin = get_location ();
                var access = parse_access_modifier ();
diff --git a/vala/valascanner.vala b/vala/valascanner.vala
index 718b65471..293cf6efd 100644
--- a/vala/valascanner.vala
+++ b/vala/valascanner.vala
@@ -424,7 +424,14 @@ public class Vala.Scanner {
                case 6:
                        switch (begin[0]) {
                        case 'd':
-                               if (matches (begin, "delete")) return TokenType.DELETE;
+                               switch (begin[2]) {
+                               case 'f':
+                                       if (matches (begin, "define")) return TokenType.DEFINE;
+                                       break;
+                               case 'l':
+                                       if (matches (begin, "delete")) return TokenType.DELETE;
+                                       break;
+                               }
                                break;
                        case 'e':
                                if (matches (begin, "extern")) return TokenType.EXTERN;
diff --git a/vala/valasourcefile.vala b/vala/valasourcefile.vala
index 35eaf5f26..6e5c12d17 100644
--- a/vala/valasourcefile.vala
+++ b/vala/valasourcefile.vala
@@ -129,6 +129,7 @@ public class Vala.SourceFile {
        public List<UsingDirective> current_using_directives { get; set; default = new 
ArrayList<UsingDirective> (); }
 
        private List<CodeNode> nodes = new ArrayList<CodeNode> ();
+       private List<Define> defines = new ArrayList<Define> ();
 
        string? _relative_filename;
 
@@ -187,6 +188,24 @@ public class Vala.SourceFile {
                current_using_directives.add (ns);
        }
 
+       /**
+        * Adds the specified define to this source file.
+        *
+        * @param define a define
+        */
+       public void add_define (Define define) {
+               defines.add (define);
+       }
+
+       /**
+        * Returns the list of defines.
+        *
+        * @return define list
+        */
+       public List<Define> get_defines () {
+               return defines;
+       }
+
        /**
         * Adds the specified code node to this source file.
         *
@@ -214,6 +233,9 @@ public class Vala.SourceFile {
        }
 
        public void accept_children (CodeVisitor visitor) {
+               foreach (Define define in defines) {
+                       define.accept (visitor);
+               }
                foreach (CodeNode node in nodes) {
                        node.accept (visitor);
                }
diff --git a/vala/valasymbolresolver.vala b/vala/valasymbolresolver.vala
index 1c0da5bcf..2206eee77 100644
--- a/vala/valasymbolresolver.vala
+++ b/vala/valasymbolresolver.vala
@@ -177,6 +177,18 @@ public class Vala.SymbolResolver : CodeVisitor {
                current_scope = old_scope;
        }
 
+       public override void visit_define (Define d) {
+               if (d.checked) {
+                       return;
+               }
+
+               var old_scope = current_scope;
+
+               d.accept_children (this);
+
+               current_scope = old_scope;
+       }
+
        public override void visit_field (Field f) {
                if (f.checked) {
                        return;
diff --git a/vala/valatokentype.vala b/vala/valatokentype.vala
index 75cf92e6c..aee2cc93a 100644
--- a/vala/valatokentype.vala
+++ b/vala/valatokentype.vala
@@ -57,6 +57,7 @@ public enum Vala.TokenType {
        CONSTRUCT,
        CONTINUE,
        DEFAULT,
+       DEFINE,
        DELEGATE,
        DELETE,
        DIV,
@@ -190,6 +191,7 @@ public enum Vala.TokenType {
                case CONSTRUCT: return "`construct'";
                case CONTINUE: return "`continue'";
                case DEFAULT: return "`default'";
+               case DEFINE: return "`define'";
                case DELEGATE: return "`delegate'";
                case DELETE: return "`delete'";
                case DIV: return "`/'";


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