Commit 4fe37fe2 authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

support pointer indirections support pointer-types, pointer indirections,

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
parent dc8db285
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
......
......@@ -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,
......
......@@ -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 \
......
......@@ -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);
......
#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>
......
/* 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
*
......
......@@ -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;
......
......@@ -748,6 +748,22 @@ public abstract class Vala.CodeVisitor {
public virtual void visit_cast_expression (CastExpression! expr) {
}
/**
* 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.
*
......
......@@ -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);
......@@ -226,6 +228,25 @@ public abstract class Vala.DataType : CodeNode {
cheader_filenames.append (filename);
}
/**
* 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.
*
......
......@@ -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);
......
/* 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";
}
}
/* 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;
}
}
}
......@@ -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");
......
......@@ -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 ();
......
......@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment