From 4fe37fe2ed6e069ffa87411d10ffe819be29eae4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=BCrg=20Billeter?= Date: Sat, 17 Mar 2007 09:52:20 +0000 Subject: [PATCH] support pointer indirections support pointer-types, pointer indirections, MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 2007-03-17 Jürg Billeter * 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 --- vala/ChangeLog | 12 +++++ vala/ccode/valaccodeunaryexpression.vala | 3 ++ vala/vala/Makefile.am | 12 +++++ vala/vala/parser.y | 53 ++++++++++++++++++++ vala/vala/vala.h | 2 + vala/vala/valaaddressofexpression.vala | 64 ++++++++++++++++++++++++ vala/vala/valaarray.vala | 2 +- vala/vala/valacodegenerator.vala | 8 +++ vala/vala/valacodevisitor.vala | 16 ++++++ vala/vala/valadatatype.vala | 21 ++++++++ vala/vala/valamemorymanager.vala | 2 +- vala/vala/valapointer.vala | 86 ++++++++++++++++++++++++++++++++ vala/vala/valapointerindirection.vala | 64 ++++++++++++++++++++++++ vala/vala/valasemanticanalyzer.vala | 47 ++++++++++++++++- vala/vala/valasymbolresolver.vala | 21 +++++++- vala/vala/valatypereference.vala | 8 ++- 16 files changed, 416 insertions(+), 5 deletions(-) create mode 100644 vala/vala/valaaddressofexpression.vala create mode 100644 vala/vala/valapointer.vala create mode 100644 vala/vala/valapointerindirection.vala diff --git a/vala/ChangeLog b/vala/ChangeLog index fff79bc..add69a0 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,3 +1,15 @@ +2007-03-17 Jürg Billeter + + * 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 * vala/parser.y: support weak keyword in local variable declarations diff --git a/vala/ccode/valaccodeunaryexpression.vala b/vala/ccode/valaccodeunaryexpression.vala index 8e139e3..b41f60f 100644 --- a/vala/ccode/valaccodeunaryexpression.vala +++ b/vala/ccode/valaccodeunaryexpression.vala @@ -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, diff --git a/vala/vala/Makefile.am b/vala/vala/Makefile.am index e44686c..7ff4eaa 100644 --- a/vala/vala/Makefile.am +++ b/vala/vala/Makefile.am @@ -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 \ diff --git a/vala/vala/parser.y b/vala/vala/parser.y index 785c49c..3290c36 100644 --- a/vala/vala/parser.y +++ b/vala/vala/parser.y @@ -211,6 +211,7 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %type identifier %type literal %type boolean_literal +%type stars %type type_name %type type %type opt_argument_list @@ -241,6 +242,8 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %type pre_increment_expression %type pre_decrement_expression %type cast_expression +%type pointer_indirection_expression +%type addressof_expression %type multiplicative_expression %type additive_expression %type 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); diff --git a/vala/vala/vala.h b/vala/vala/vala.h index 3909e10..d68c473 100644 --- a/vala/vala/vala.h +++ b/vala/vala/vala.h @@ -1,3 +1,4 @@ +#include #include #include #include @@ -50,6 +51,7 @@ #include #include #include +#include #include #include #include diff --git a/vala/vala/valaaddressofexpression.vala b/vala/vala/valaaddressofexpression.vala new file mode 100644 index 0000000..8cfb825 --- /dev/null +++ b/vala/vala/valaaddressofexpression.vala @@ -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 + */ + +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; + } + } +} diff --git a/vala/vala/valaarray.vala b/vala/vala/valaarray.vala index e318478..d1e5fa1 100644 --- a/vala/vala/valaarray.vala +++ b/vala/vala/valaarray.vala @@ -1,4 +1,4 @@ -/* valatype.vala +/* valaarray.vala * * Copyright (C) 2006-2007 Raffaele Sandrini, Jürg Billeter * diff --git a/vala/vala/valacodegenerator.vala b/vala/vala/valacodegenerator.vala index 253fdf9..ad6be31 100644 --- a/vala/vala/valacodegenerator.vala +++ b/vala/vala/valacodegenerator.vala @@ -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; diff --git a/vala/vala/valacodevisitor.vala b/vala/vala/valacodevisitor.vala index 08110f0..690748a 100644 --- a/vala/vala/valacodevisitor.vala +++ b/vala/vala/valacodevisitor.vala @@ -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 diff --git a/vala/vala/valadatatype.vala b/vala/vala/valadatatype.vala index d9585c1..66be4db 100644 --- a/vala/vala/valadatatype.vala +++ b/vala/vala/valadatatype.vala @@ -48,6 +48,8 @@ public abstract class Vala.DataType : CodeNode { private List 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 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 diff --git a/vala/vala/valamemorymanager.vala b/vala/vala/valamemorymanager.vala index 9691195..ac6103b 100644 --- a/vala/vala/valamemorymanager.vala +++ b/vala/vala/valamemorymanager.vala @@ -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 index 0000000..dceb8c6 --- /dev/null +++ b/vala/vala/valapointer.vala @@ -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 + */ + +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 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 index 0000000..747001e --- /dev/null +++ b/vala/vala/valapointerindirection.vala @@ -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 + */ + +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; + } + } +} diff --git a/vala/vala/valasemanticanalyzer.vala b/vala/vala/valasemanticanalyzer.vala index 993cebe..de18e12 100644 --- a/vala/vala/valasemanticanalyzer.vala +++ b/vala/vala/valasemanticanalyzer.vala @@ -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"); diff --git a/vala/vala/valasymbolresolver.vala b/vala/vala/valasymbolresolver.vala index 0091bee..2ae0102 100644 --- a/vala/vala/valasymbolresolver.vala +++ b/vala/vala/valasymbolresolver.vala @@ -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 (); diff --git a/vala/vala/valatypereference.vala b/vala/vala/valatypereference.vala index 2db60e5..03dbdc9 100644 --- a/vala/vala/valatypereference.vala +++ b/vala/vala/valatypereference.vala @@ -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. -- 2.7.4