support pointer indirections support pointer-types, pointer indirections,
authorJürg Billeter <j@bitron.ch>
Sat, 17 Mar 2007 09:52:20 +0000 (09:52 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Sat, 17 Mar 2007 09:52:20 +0000 (09:52 +0000)
2007-03-17  Jürg Billeter  <j@bitron.ch>

* ccode/valaccodeunaryexpression.vala: support pointer indirections
* vala/parser.y, vala/valacodevisitor.vala,
  vala/valasymbolresolver.vala, vala/valasemanticanalyzer.vala,
  vala/valamemorymanager.vala, vala/valacodegenerator.vala,
  vala/valaaddressofexpression.vala, vala/valadatatype.vala,
  vala/valapointer.vala, vala/valapointerindirection.vala,
  vala/valatypereference.vala: support pointer-types, pointer
  indirections, and address-of expressions
* vala/vala.h, vala/Makefile.am: update

svn path=/trunk/; revision=239

16 files changed:
vala/ChangeLog
vala/ccode/valaccodeunaryexpression.vala
vala/vala/Makefile.am
vala/vala/parser.y
vala/vala/vala.h
vala/vala/valaaddressofexpression.vala [new file with mode: 0644]
vala/vala/valaarray.vala
vala/vala/valacodegenerator.vala
vala/vala/valacodevisitor.vala
vala/vala/valadatatype.vala
vala/vala/valamemorymanager.vala
vala/vala/valapointer.vala [new file with mode: 0644]
vala/vala/valapointerindirection.vala [new file with mode: 0644]
vala/vala/valasemanticanalyzer.vala
vala/vala/valasymbolresolver.vala
vala/vala/valatypereference.vala

index fff79bc..add69a0 100644 (file)
@@ -1,3 +1,15 @@
+2007-03-17  Jürg Billeter  <j@bitron.ch>
+
+       * ccode/valaccodeunaryexpression.vala: support pointer indirections
+       * vala/parser.y, vala/valacodevisitor.vala,
+         vala/valasymbolresolver.vala, vala/valasemanticanalyzer.vala,
+         vala/valamemorymanager.vala, vala/valacodegenerator.vala,
+         vala/valaaddressofexpression.vala, vala/valadatatype.vala,
+         vala/valapointer.vala, vala/valapointerindirection.vala,
+         vala/valatypereference.vala: support pointer-types, pointer
+         indirections, and address-of expressions
+       * vala/vala.h, vala/Makefile.am: update
+
 2007-03-16  Jürg Billeter  <j@bitron.ch>
 
        * vala/parser.y: support weak keyword in local variable declarations
index 8e139e3..b41f60f 100644 (file)
@@ -50,6 +50,8 @@ public class Vala.CCodeUnaryExpression : CCodeExpression {
                        writer.write_string ("!");
                } else if (operator == CCodeUnaryOperator.BITWISE_COMPLEMENT) {
                        writer.write_string ("~");
+               } else if (operator == CCodeUnaryOperator.POINTER_INDIRECTION) {
+                       writer.write_string ("*");
                } else if (operator == CCodeUnaryOperator.ADDRESS_OF) {
                        writer.write_string ("&");
                } else if (operator == CCodeUnaryOperator.PREFIX_INCREMENT) {
@@ -73,6 +75,7 @@ public enum Vala.CCodeUnaryOperator {
        MINUS,
        LOGICAL_NEGATION,
        BITWISE_COMPLEMENT,
+       POINTER_INDIRECTION,
        ADDRESS_OF,
        PREFIX_INCREMENT,
        PREFIX_DECREMENT,
index e44686c..7ff4eaa 100644 (file)
@@ -16,6 +16,9 @@ libvala_la_SOURCES = \
        scanner.l \
        vala.h \
        vala.vala.stamp \
+       valaaddressofexpression.c \
+       valaaddressofexpression.h \
+       valaaddressofexpression.vala \
        valaarray.c \
        valaarray.h \
        valaarray.vala \
@@ -226,6 +229,12 @@ libvala_la_SOURCES = \
        valaparser.c \
        valaparser.h \
        valaparser.vala \
+       valapointer.c \
+       valapointer.h \
+       valapointer.vala \
+       valapointerindirection.c \
+       valapointerindirection.h \
+       valapointerindirection.vala \
        valapostfixexpression.c \
        valapostfixexpression.h \
        valapostfixexpression.vala \
@@ -322,6 +331,7 @@ valaincludedir = $(includedir)/vala-1.0/vala
 
 valainclude_HEADERS = \
        vala.h \
+       valaaddressofexpression.h \
        valaarray.h \
        valaarraycreationexpression.h \
        valaassignment.h \
@@ -390,6 +400,8 @@ valainclude_HEADERS = \
        valaobjectcreationexpression.h \
        valaparenthesizedexpression.h \
        valaparser.h \
+       valapointer.h \
+       valapointerindirection.h \
        valapostfixexpression.h \
        valapropertyaccessor.h \
        valaproperty.h \
index 785c49c..3290c36 100644 (file)
@@ -211,6 +211,7 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg);
 %type <str> identifier
 %type <literal> literal
 %type <literal> boolean_literal
+%type <num> stars
 %type <type_reference> type_name
 %type <type_reference> type
 %type <list> opt_argument_list
@@ -241,6 +242,8 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg);
 %type <expression> pre_increment_expression
 %type <expression> pre_decrement_expression
 %type <expression> cast_expression
+%type <expression> pointer_indirection_expression
+%type <expression> addressof_expression
 %type <expression> multiplicative_expression
 %type <expression> additive_expression
 %type <expression> shift_expression
@@ -480,6 +483,17 @@ type_name
          }
        ;
 
+stars
+       : STAR
+         {
+               $$ = 1;
+         }
+       | stars STAR
+         {
+               $$ = $1 + 1;
+         }
+       ;
+
 type
        : type_name opt_rank_specifier opt_op_neg
          {
@@ -526,6 +540,15 @@ type
                        vala_type_reference_set_non_null ($$, TRUE);
                }
          }
+       | type_name stars opt_rank_specifier opt_op_neg
+         {
+               $$ = $1;
+               vala_type_reference_set_pointer_level ($$, $2);
+               vala_type_reference_set_array_rank ($$, $3);
+               if ($4) {
+                       vala_type_reference_set_non_null ($$, TRUE);
+               }
+         }
        ;
 
 opt_argument_list
@@ -867,6 +890,8 @@ unary_expression
                g_object_unref ($2);
          }
        | cast_expression
+       | pointer_indirection_expression
+       | addressof_expression
        ;
 
 pre_increment_expression
@@ -900,6 +925,26 @@ cast_expression
          }
        ;
 
+pointer_indirection_expression
+       : STAR unary_expression
+         {
+               ValaSourceReference *src = src(@1);
+               $$ = VALA_EXPRESSION (vala_pointer_indirection_new ($2, src));
+               g_object_unref (src);
+               g_object_unref ($2);
+         }
+       ;
+
+addressof_expression
+       : BITWISE_AND unary_expression
+         {
+               ValaSourceReference *src = src(@1);
+               $$ = VALA_EXPRESSION (vala_addressof_expression_new ($2, src));
+               g_object_unref (src);
+               g_object_unref ($2);
+         }
+       ;
+
 multiplicative_expression
        : unary_expression
        | multiplicative_expression STAR unary_expression
@@ -1423,6 +1468,14 @@ local_variable_type
                        vala_type_reference_set_non_null ($$, TRUE);
                }
          }
+       | primary_expression stars
+         {
+               ValaSourceReference *src = src(@1);
+               $$ = vala_type_reference_new_from_expression ($1);
+               g_object_unref ($1);
+               g_object_unref (src);
+               vala_type_reference_set_pointer_level ($$, $2);
+         }
        | REF primary_expression opt_op_neg
          {
                ValaSourceReference *src = src(@2);
index 3909e10..d68c473 100644 (file)
@@ -1,3 +1,4 @@
+#include <vala/valaaddressofexpression.h>
 #include <vala/valaarraycreationexpression.h>
 #include <vala/valaassignment.h>
 #include <vala/valaattribute.h>
@@ -50,6 +51,7 @@
 #include <vala/valaobjectcreationexpression.h>
 #include <vala/valaparenthesizedexpression.h>
 #include <vala/valaparser.h>
+#include <vala/valapointerindirection.h>
 #include <vala/valapostfixexpression.h>
 #include <vala/valaproperty.h>
 #include <vala/valapropertyaccessor.h>
diff --git a/vala/vala/valaaddressofexpression.vala b/vala/vala/valaaddressofexpression.vala
new file mode 100644 (file)
index 0000000..8cfb825
--- /dev/null
@@ -0,0 +1,64 @@
+/* valaaddressofexpression.vala
+ *
+ * Copyright (C) 2007  Jürg Billeter
+ *
+ * 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 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:
+ *     Jürg Billeter <j@bitron.ch>
+ */
+
+using GLib;
+
+/**
+ * Represents an address-of expression in the source code, e.g. `&foo'.
+ */
+public class Vala.AddressofExpression : Expression {
+       /**
+        * The variable whose address is to be computed.
+        */
+       public Expression! inner {
+               get {
+                       return _inner;
+               }
+               set construct {
+                       _inner = value;
+                       _inner.parent_node = this;
+               }
+       }
+       
+       private Expression! _inner;
+
+       /**
+        * Creates a new address-of expression.
+        *
+        * @param inner variable whose address is to be computed
+        * @return      newly created address-of expression
+        */
+       public AddressofExpression (construct Expression! inner, construct SourceReference source_reference = null) {
+       }
+       
+       public override void accept (CodeVisitor! visitor) {
+               inner.accept (visitor);
+
+               visitor.visit_addressof_expression (this);
+       }
+
+       public override void replace (CodeNode! old_node, CodeNode! new_node) {
+               if (inner == old_node) {
+                       inner = (Expression) new_node;
+               }
+       }
+}
index e318478..d1e5fa1 100644 (file)
@@ -1,4 +1,4 @@
-/* valatype.vala
+/* valaarray.vala
  *
  * Copyright (C) 2006-2007  Raffaele Sandrini, Jürg Billeter
  *
index 253fdf9..ad6be31 100644 (file)
@@ -3512,6 +3512,14 @@ public class Vala.CodeGenerator : CodeVisitor {
                
                visit_expression (expr);
        }
+       
+       public override void visit_pointer_indirection (PointerIndirection! expr) {
+               expr.ccodenode = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, (CCodeExpression) expr.inner.ccodenode);
+       }
+
+       public override void visit_addressof_expression (AddressofExpression! expr) {
+               expr.ccodenode = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) expr.inner.ccodenode);
+       }
 
        public override void visit_binary_expression (BinaryExpression! expr) {
                CCodeBinaryOperator op;
index 08110f0..690748a 100644 (file)
@@ -749,6 +749,22 @@ public abstract class Vala.CodeVisitor {
        }
 
        /**
+        * Visit operation called for pointer indirections.
+        *
+        * @param expr a pointer indirection
+        */
+       public virtual void visit_pointer_indirection (PointerIndirection! expr) {
+       }
+
+       /**
+        * Visit operation called for address-of expressions.
+        *
+        * @param expr an address-of expression
+        */
+       public virtual void visit_addressof_expression (AddressofExpression! expr) {
+       }
+
+       /**
         * Visit operation called for binary expressions.
         *
         * @param expr a binary expression
index d9585c1..66be4db 100644 (file)
@@ -48,6 +48,8 @@ public abstract class Vala.DataType : CodeNode {
 
        private List<string> cheader_filenames;
 
+       private Pointer pointer_type;
+
        /* holds the array types of this type; each rank is a separate one */
        /* FIXME: uses string because int does not work as key yet */
        private HashTable<string,Array> array_types = new HashTable.full (str_hash, str_equal, g_free, g_object_unref);
@@ -227,6 +229,25 @@ public abstract class Vala.DataType : CodeNode {
        }
        
        /**
+        * Returns the pointer type of this data type.
+        *
+        * @return pointer-type for this data type
+        */
+       public Pointer! get_pointer () {
+               if (pointer_type == null) {
+                       pointer_type = new Pointer (this, source_reference);
+                       /* create a new Symbol */
+                       pointer_type.symbol = new Symbol (pointer_type);
+                       this.symbol.parent_symbol.add (pointer_type.name, pointer_type.symbol);
+
+                       /* link the namespace */
+                       pointer_type.@namespace = this.@namespace;
+               }
+
+               return pointer_type;
+       }
+       
+       /**
         * Returns the array type for elements of this data type.
         *
         * @param rank the rank the array should be of
index 9691195..ac6103b 100644 (file)
@@ -239,7 +239,7 @@ public class Vala.MemoryManager : CodeVisitor {
        }
 
        public override void visit_end_assignment (Assignment! a) {
-               if (a.left is ElementAccess || a.left.symbol_reference.node is Signal) {
+               if (a.left is PointerIndirection || a.left is ElementAccess || a.left.symbol_reference.node is Signal) {
                } else {
                        if (a.left.static_type.takes_ownership) {
                                visit_possibly_missing_copy_expression (a.right);
diff --git a/vala/vala/valapointer.vala b/vala/vala/valapointer.vala
new file mode 100644 (file)
index 0000000..dceb8c6
--- /dev/null
@@ -0,0 +1,86 @@
+/* valapointer.vala
+ *
+ * Copyright (C) 2007  Jürg Billeter
+ *
+ * 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 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:
+ *     Jürg Billeter <j@bitron.ch>
+ */
+
+using GLib;
+
+/**
+ * Represents a pointer-type.
+ */
+public class Vala.Pointer : DataType {
+       /**
+        * The type to which this pointer type points.
+        */
+       public DataType! referent_type { get; set construct; }
+       
+       private string cname;
+       
+       public Pointer (construct DataType! referent_type, construct SourceReference source_reference = null) {
+       }
+
+       construct {
+               name = referent_type.name + "*";
+       }
+
+       public override string get_cname (bool const_type = false) {
+               if (cname == null) {
+                       if (referent_type.is_reference_type ()) {
+                               cname = "%s**".printf (referent_type.get_cname ());
+                       } else {
+                               cname = "%s*".printf (referent_type.get_cname ());
+                       }
+               }
+
+               return cname;
+       }
+
+       public override bool is_reference_type () {
+               return false;
+       }
+       
+       public override ref string get_upper_case_cname (string infix) {
+               return null;
+       }
+
+       public override ref string get_lower_case_cname (string infix) {
+               return null;
+       }
+
+       public override string get_free_function () {
+               return null;
+       }
+       
+       public override ref List<string> get_cheader_filenames () {
+               return referent_type.get_cheader_filenames ();
+       }
+       
+       public override string get_marshaller_type_name () {
+               return "POINTER";
+       }
+
+       public override string get_get_value_function () {
+               return "g_value_get_pointer";
+       }
+       
+       public override string get_set_value_function () {
+               return "g_value_set_pointer";
+       }
+}
diff --git a/vala/vala/valapointerindirection.vala b/vala/vala/valapointerindirection.vala
new file mode 100644 (file)
index 0000000..747001e
--- /dev/null
@@ -0,0 +1,64 @@
+/* valapointerindirection.vala
+ *
+ * Copyright (C) 2007  Jürg Billeter
+ *
+ * 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 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:
+ *     Jürg Billeter <j@bitron.ch>
+ */
+
+using GLib;
+
+/**
+ * Represents a pointer indirection in the source code, e.g. `*pointer'.
+ */
+public class Vala.PointerIndirection : Expression {
+       /**
+        * The pointer to dereference.
+        */
+       public Expression! inner {
+               get {
+                       return _inner;
+               }
+               set construct {
+                       _inner = value;
+                       _inner.parent_node = this;
+               }
+       }
+       
+       private Expression! _inner;
+
+       /**
+        * Creates a new pointer indirection.
+        *
+        * @param inner pointer to be dereferenced
+        * @return      newly created pointer indirection
+        */
+       public PointerIndirection (construct Expression! inner, construct SourceReference source_reference = null) {
+       }
+       
+       public override void accept (CodeVisitor! visitor) {
+               inner.accept (visitor);
+
+               visitor.visit_pointer_indirection (this);
+       }
+
+       public override void replace (CodeNode! old_node, CodeNode! new_node) {
+               if (inner == old_node) {
+                       inner = (Expression) new_node;
+               }
+       }
+}
index 993cebe..de18e12 100644 (file)
@@ -1092,10 +1092,11 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                }
 
                if (expression_type.data_type == null) {
-                       /* null can be cast to any reference or array type */
+                       /* null can be cast to any reference or array type or pointer type */
                        if (expected_type.type_parameter != null ||
                            expected_type.data_type.is_reference_type () ||
                            expected_type.reference_to_value_type ||
+                           expected_type.data_type is Pointer ||
                            expected_type.data_type is Array ||
                            expected_type.data_type is Callback ||
                            expected_type.data_type == pointer_type) {
@@ -1632,6 +1633,48 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                expr.static_type = expr.type_reference;
        }
        
+       public override void visit_pointer_indirection (PointerIndirection! expr) {
+               if (expr.inner.error) {
+                       return;
+               }
+               if (expr.inner.static_type == null) {
+                       expr.error = true;
+                       Report.error (expr.source_reference, "internal error: unknown type of inner expression");
+                       return;
+               }
+               if (!(expr.inner.static_type.data_type is Pointer)) {
+                       expr.error = true;
+                       Report.error (expr.source_reference, "Pointer indirection not supported for this expression");
+                       return;
+               }
+
+               var pointer = (Pointer) expr.inner.static_type.data_type;
+
+               expr.static_type = new TypeReference ();
+               expr.static_type.data_type = pointer.referent_type;
+               expr.static_type.takes_ownership = expr.inner.static_type.takes_ownership;
+       }
+
+       public override void visit_addressof_expression (AddressofExpression! expr) {
+               if (expr.inner.error) {
+                       return;
+               }
+               if (expr.inner.static_type == null) {
+                       expr.error = true;
+                       Report.error (expr.source_reference, "internal error: unknown type of inner expression");
+                       return;
+               }
+               if (expr.inner.static_type.data_type == null) {
+                       expr.error = true;
+                       Report.error (expr.source_reference, "Address-of operator not supported for this expression");
+                       return;
+               }
+
+               expr.static_type = new TypeReference ();
+               expr.static_type.data_type = expr.inner.static_type.data_type.get_pointer ();
+               expr.static_type.takes_ownership = expr.inner.static_type.takes_ownership;
+       }
+
        private bool check_binary_type (BinaryExpression! expr, string! operation) {
                if (!is_type_compatible (expr.right.static_type, expr.left.static_type)) {
                        Report.error (expr.source_reference, "%s: Cannot convert from `%s' to `%s'".printf (operation, expr.right.static_type.to_string (), expr.left.static_type.to_string ()));
@@ -1926,6 +1969,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        }
                } else if (a.left is ElementAccess) {
                        // do nothing
+               } else if (a.left is PointerIndirection) {
+                       // do nothing
                } else {
                        a.error = true;
                        Report.error (a.source_reference, "unsupported lvalue in assignment");
index 0091bee..2ae0102 100644 (file)
@@ -192,7 +192,26 @@ public class Vala.SymbolResolver : CodeVisitor {
                        }
                        type.data_type = (DataType) sym.node;
                }
-               
+
+               if (type.pointer_level > 0) {
+                       if (type.data_type == null) {
+                               type.error = true;
+                               Report.error (type.source_reference, "Pointer to `%s' not supported".printf (type.type_name));
+                               return;
+                       }
+                       var referent_type = new TypeReference ();
+                       referent_type.data_type = type.data_type;
+                       referent_type.pointer_level = type.pointer_level - 1;
+
+                       if (type.data_type.is_reference_type ()) {
+                               referent_type.takes_ownership = type.takes_ownership;
+                       }
+                       type.data_type = referent_type.data_type.get_pointer ();
+                       type.add_type_argument (referent_type);
+                       
+                       visit_type_reference (referent_type);
+               }
+
                /* check for array */
                if (type.array_rank > 0) {
                        var element_type = new TypeReference ();
index 2db60e5..03dbdc9 100644 (file)
@@ -88,7 +88,13 @@ public class Vala.TypeReference : CodeNode {
         * WARNING: This property may only be set by the parser and only be read by the symbol resolver.
         */
        public int array_rank { get; set; }
-       
+
+       /**
+        * Specifies the level of the pointer if this is a pointer-type. "0" indicates no pointer-type.
+        * WARNING: This property may only be set by the parser and only be read by the symbol resolver.
+        */
+       public int pointer_level { get; set; }
+
        /**
         * The ref modifier has been specified, may only be used with unresolved
         * type references.