[vala/wip/explicit-class-access: 3/3] WIP vala: Allow explicit access to class members




commit c23e947e4e4f0b12e72eacfba160ba6062d18746
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Wed Sep 30 08:41:05 2020 +0200

    WIP vala: Allow explicit access to class members

 codegen/valaccodebasemodule.vala         | 14 ++++++
 codegen/valaccodememberaccessmodule.vala | 22 ++-------
 codegen/valaccodemethodcallmodule.vala   | 25 ++--------
 vala/Makefile.am                         |  1 +
 vala/valaclassaccess.vala                | 82 ++++++++++++++++++++++++++++++++
 vala/valacodevisitor.vala                |  8 ++++
 vala/valamemberaccess.vala               | 21 +++++++-
 vala/valaparser.vala                     |  9 ++++
 8 files changed, 142 insertions(+), 40 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index e782a4a58..05318e2a9 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -4450,6 +4450,20 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                }
        }
 
+       public override void visit_class_access (ClassAccess expr) {
+               CCodeExpression klass;
+               if (get_this_type () == null) {
+                       // Accessing the method from a static or class constructor
+                       klass = new CCodeIdentifier ("klass");
+               } else {
+                       // Accessing the method from within an instance method
+                       var k = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_GET_CLASS"));
+                       k.add_argument (get_this_cexpression ());
+                       klass = k;
+               }
+               set_cvalue (expr, klass);
+       }
+
        public override void visit_postfix_expression (PostfixExpression expr) {
                MemberAccess ma = find_property_access (expr.inner);
                if (ma != null) {
diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala
index f46ea9dfd..84371bcd8 100644
--- a/codegen/valaccodememberaccessmodule.vala
+++ b/codegen/valaccodememberaccessmodule.vala
@@ -678,26 +678,10 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                }
                        }
                } else if (field.binding == MemberBinding.CLASS) {
-                       var cl = (Class) field.parent_symbol;
-                       var cast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function 
(cl)));
+                       var klass = get_cvalue_ (instance);
 
-                       CCodeExpression klass;
-                       if (instance == null) {
-                               if (get_this_type () == null) {
-                                       // Accessing the field from a static or class constructor
-                                       klass = new CCodeIdentifier ("klass");
-                               } else {
-                                       // Accessing the field from within an instance method
-                                       var k = new CCodeFunctionCall (new CCodeIdentifier 
("G_OBJECT_GET_CLASS"));
-                                       k.add_argument (new CCodeIdentifier ("self"));
-                                       klass = k;
-                               }
-                       } else {
-                               // Accessing the field of an instance
-                               var k = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_GET_CLASS"));
-                               k.add_argument (get_cvalue_ (instance));
-                               klass = k;
-                       }
+                       unowned Class cl = (Class) field.parent_symbol;
+                       var cast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function 
(cl)));
                        cast.add_argument (klass);
 
                        if (field.access == SymbolAccessibility.PRIVATE) {
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index e3293feb4..b6f985f06 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -243,28 +243,13 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance);
                        }
                } else if (m != null && m.binding == MemberBinding.CLASS) {
-                       var cl = (Class) m.parent_symbol;
-                       var cast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function 
(cl)));
-
-                       CCodeExpression klass;
-                       if (ma.inner == null) {
-                               if (get_this_type () == null) {
-                                       // Accessing the method from a static or class constructor
-                                       klass = new CCodeIdentifier ("klass");
-                               } else {
-                                       // Accessing the method from within an instance method
-                                       var k = new CCodeFunctionCall (new CCodeIdentifier 
("G_OBJECT_GET_CLASS"));
-                                       k.add_argument (get_this_cexpression ());
-                                       klass = k;
-                               }
-                       } else {
-                               // Accessing the method of an instance
-                               var k = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_GET_CLASS"));
-                               k.add_argument (get_cvalue (ma.inner));
-                               klass = k;
-                       }
+                       assert (ma.inner is ClassAccess);
+                       var klass = get_cvalue (ma.inner);
 
+                       unowned Class cl = (Class) m.parent_symbol;
+                       var cast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function 
(cl)));
                        cast.add_argument (klass);
+
                        in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), cast);
                        out_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), cast);
                }
diff --git a/vala/Makefile.am b/vala/Makefile.am
index 8a9badd4c..5dcc2766d 100644
--- a/vala/Makefile.am
+++ b/vala/Makefile.am
@@ -48,6 +48,7 @@ libvala_la_VALASOURCES = \
        valacatchclause.vala \
        valacharacterliteral.vala \
        valaclass.vala \
+       valaclassaccess.vala \
        valaclasstype.vala \
        valacodecontext.vala \
        valacodegenerator.vala \
diff --git a/vala/valaclassaccess.vala b/vala/valaclassaccess.vala
new file mode 100644
index 000000000..2e3bbc51c
--- /dev/null
+++ b/vala/valaclassaccess.vala
@@ -0,0 +1,82 @@
+/* valaclassaccess.vala
+ *
+ * Copyright (C) 2020  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>
+ */
+
+
+/**
+ * Represents an access to class member in the source code.
+ */
+public class Vala.ClassAccess : Expression {
+       /**
+        * Creates a new class access expression.
+        *
+        * @param source reference to source code
+        * @return       newly created class access expression
+        */
+       public ClassAccess (SourceReference? source = null) {
+               source_reference = source;
+       }
+
+       public override void accept (CodeVisitor visitor) {
+               visitor.visit_class_access (this);
+
+               visitor.visit_expression (this);
+       }
+
+       public override string to_string () {
+               return "class";
+       }
+
+       public override bool is_pure () {
+               return true;
+       }
+
+       public override bool check (CodeContext context) {
+               if (checked) {
+                       return !error;
+               }
+
+               checked = true;
+
+               if (context.analyzer.current_class == null) {
+                       error = true;
+                       Report.error (source_reference, "Class access invalid outside of class");
+                       return false;
+               } else if (context.analyzer.current_class.is_compact) {
+                       error = true;
+                       Report.error (source_reference, "Class access invalid in compact class");
+                       return false;
+               } else {
+                       value_type = SemanticAnalyzer.get_data_type_for_symbol 
(context.analyzer.current_class);
+                       value_type.value_owned = false;
+               }
+
+               symbol_reference = value_type.type_symbol;
+
+               return !error;
+       }
+
+       public override void emit (CodeGenerator codegen) {
+               codegen.visit_class_access (this);
+
+               codegen.visit_expression (this);
+       }
+}
diff --git a/vala/valacodevisitor.vala b/vala/valacodevisitor.vala
index f47f96349..fe71d4c4d 100644
--- a/vala/valacodevisitor.vala
+++ b/vala/valacodevisitor.vala
@@ -549,6 +549,14 @@ public abstract class Vala.CodeVisitor {
        public virtual void visit_base_access (BaseAccess expr) {
        }
 
+       /**
+        * Visit operation called for class access expressions.
+        *
+        * @param expr a class access expression
+        */
+       public virtual void visit_class_access (ClassAccess expr) {
+       }
+
        /**
         * Visit operation called for postfix expressions.
         *
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index b1cc20ada..4a6bda128 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -402,6 +402,22 @@ public class Vala.MemberAccess : Expression {
                                                may_access_klass_members = true;
                                        }
                                }
+                       } else if (inner is ClassAccess) {
+                               unowned Class cl = (Class) inner.symbol_reference;
+
+                               while (cl != null) {
+                                       symbol_reference = cl.scope.lookup (member_name);
+                                       if (symbol_reference is Method && ((Method) symbol_reference).binding 
== MemberBinding.CLASS) {
+                                               may_access_klass_members = true;
+                                               break;
+                                       } else if (symbol_reference is Field && ((Field) 
symbol_reference).binding == MemberBinding.CLASS) {
+                                               may_access_klass_members = true;
+                                               break;
+                                       } else {
+                                               symbol_reference = null;
+                                       }
+                                       cl = cl.base_class;
+                               }
                        }
 
                        if (inner is MemberAccess && inner.symbol_reference is TypeParameter) {
@@ -916,12 +932,15 @@ public class Vala.MemberAccess : Expression {
                                value_type.value_owned = target_type.value_owned;
                        }
                } else {
-                       // implicit this access
+                       // implicit this or class access
                        if (instance && inner == null) {
                                inner = new MemberAccess (null, "this", source_reference);
                                inner.value_type = this_parameter.variable_type.copy ();
                                inner.value_type.value_owned = false;
                                inner.symbol_reference = this_parameter;
+                       } else if (klass && inner == null) {
+                               inner = new ClassAccess (source_reference);
+                               inner.check (context);
                        } else {
                                check_lvalue_access ();
                        }
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 74cf0f2f4..55b3afb04 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -690,6 +690,9 @@ public class Vala.Parser : CodeVisitor {
                case TokenType.BASE:
                        expr = parse_base_access ();
                        break;
+               case TokenType.CLASS:
+                       expr = parse_class_access ();
+                       break;
                case TokenType.NEW:
                        expr = parse_object_or_array_creation_expression ();
                        break;
@@ -913,6 +916,12 @@ public class Vala.Parser : CodeVisitor {
                return new BaseAccess (get_src (begin));
        }
 
+       Expression parse_class_access () throws ParseError {
+               var begin = get_location ();
+               expect (TokenType.CLASS);
+               return new ClassAccess (get_src (begin));
+       }
+
        Expression parse_post_increment_expression (SourceLocation begin, Expression inner) throws ParseError 
{
                expect (TokenType.OP_INC);
                return new PostfixExpression (inner, true, get_src (begin));


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