+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
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) {
MINUS,
LOGICAL_NEGATION,
BITWISE_COMPLEMENT,
+ POINTER_INDIRECTION,
ADDRESS_OF,
PREFIX_INCREMENT,
PREFIX_DECREMENT,
scanner.l \
vala.h \
vala.vala.stamp \
+ valaaddressofexpression.c \
+ valaaddressofexpression.h \
+ valaaddressofexpression.vala \
valaarray.c \
valaarray.h \
valaarray.vala \
valaparser.c \
valaparser.h \
valaparser.vala \
+ valapointer.c \
+ valapointer.h \
+ valapointer.vala \
+ valapointerindirection.c \
+ valapointerindirection.h \
+ valapointerindirection.vala \
valapostfixexpression.c \
valapostfixexpression.h \
valapostfixexpression.vala \
valainclude_HEADERS = \
vala.h \
+ valaaddressofexpression.h \
valaarray.h \
valaarraycreationexpression.h \
valaassignment.h \
valaobjectcreationexpression.h \
valaparenthesizedexpression.h \
valaparser.h \
+ valapointer.h \
+ valapointerindirection.h \
valapostfixexpression.h \
valapropertyaccessor.h \
valaproperty.h \
%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
%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
}
;
+stars
+ : STAR
+ {
+ $$ = 1;
+ }
+ | stars STAR
+ {
+ $$ = $1 + 1;
+ }
+ ;
+
type
: type_name opt_rank_specifier opt_op_neg
{
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
g_object_unref ($2);
}
| cast_expression
+ | pointer_indirection_expression
+ | addressof_expression
;
pre_increment_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
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);
+#include <vala/valaaddressofexpression.h>
#include <vala/valaarraycreationexpression.h>
#include <vala/valaassignment.h>
#include <vala/valaattribute.h>
#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>
--- /dev/null
+/* 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;
+ }
+ }
+}
-/* valatype.vala
+/* valaarray.vala
*
* Copyright (C) 2006-2007 Raffaele Sandrini, Jürg Billeter
*
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;
}
/**
+ * 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
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);
}
/**
+ * 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
}
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);
--- /dev/null
+/* 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";
+ }
+}
--- /dev/null
+/* 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;
+ }
+ }
+}
}
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) {
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 ()));
}
} 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");
}
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 ();
* 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.