vala r838 - in trunk: . gobject vala
- From: juergbi svn gnome org
- To: svn-commits-list gnome org
- Subject: vala r838 - in trunk: . gobject vala
- Date: Tue, 15 Jan 2008 21:01:27 +0000 (GMT)
Author: juergbi
Date: Tue Jan 15 21:01:26 2008
New Revision: 838
URL: http://svn.gnome.org/viewvc/vala?rev=838&view=rev
Log:
2008-01-15 Juerg Billeter <j bitron ch>
* vala/parser.y, vala/scanner.l, vala/valaclass.vala,
vala/valainterface.vala, vala/valamethod.vala,
vala/valasemanticanalyzer.vala, vala/valastruct.vala,
gobject/valaccodegeneratormethod.vala: add basic support for
method pre- and postconditions
Modified:
trunk/ChangeLog
trunk/gobject/valaccodegeneratormethod.vala
trunk/vala/parser.y
trunk/vala/scanner.l
trunk/vala/valaclass.vala
trunk/vala/valainterface.vala
trunk/vala/valamethod.vala
trunk/vala/valasemanticanalyzer.vala
trunk/vala/valastruct.vala
Modified: trunk/gobject/valaccodegeneratormethod.vala
==============================================================================
--- trunk/gobject/valaccodegeneratormethod.vala (original)
+++ trunk/gobject/valaccodegeneratormethod.vala Tue Jan 15 21:01:26 2008
@@ -418,6 +418,10 @@
// GTypeModule-based plug-in, register types
cinit.append (module_init_fragment);
}
+
+ foreach (Expression precondition in m.get_preconditions ()) {
+ cinit.append (create_precondition_statement (m, creturn_type, precondition));
+ }
}
}
@@ -436,7 +440,11 @@
vfunc.add_parameter (cparam);
var vblock = new CCodeBlock ();
-
+
+ foreach (Expression precondition in m.get_preconditions ()) {
+ vblock.add_statement (create_precondition_statement (m, creturn_type, precondition));
+ }
+
CCodeFunctionCall vcast = null;
if (m.parent_symbol is Interface) {
var iface = (Interface) m.parent_symbol;
@@ -491,15 +499,27 @@
}
CCodeStatement cstmt;
- if (creturn_type.data_type == null && creturn_type.type_parameter == null) {
+ if (creturn_type is VoidType) {
cstmt = new CCodeExpressionStatement (vcall);
} else {
- /* pass method return value */
- cstmt = new CCodeReturnStatement (vcall);
+ /* store method return value */
+ var cdecl = new CCodeDeclaration (creturn_type.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("result", vcall));
+ cstmt = cdecl;
}
cstmt.line = vfunc.line;
vblock.add_statement (cstmt);
+ foreach (Expression postcondition in m.get_postconditions ()) {
+ vblock.add_statement (create_postcondition_statement (postcondition));
+ }
+
+ if (!(creturn_type is VoidType)) {
+ var cret_stmt = new CCodeReturnStatement (new CCodeIdentifier ("result"));
+ cret_stmt.line = vfunc.line;
+ vblock.add_statement (cret_stmt);
+ }
+
if (visible) {
header_type_member_declaration.append (vfunc.copy ());
} else {
@@ -592,7 +612,7 @@
return create_type_check_statement (prop, new VoidType (), t, non_null, var_name);
}
}
-
+
private CCodeStatement create_type_check_statement (CodeNode! method_node, DataType ret_type, Typesymbol! t, bool non_null, string! var_name) {
var ccheck = new CCodeFunctionCall ();
@@ -632,6 +652,37 @@
return new CCodeExpressionStatement (ccheck);
}
+ private CCodeStatement create_precondition_statement (CodeNode! method_node, DataType ret_type, Expression precondition) {
+ var ccheck = new CCodeFunctionCall ();
+
+ ccheck.add_argument ((CCodeExpression) precondition.ccodenode);
+
+ if (ret_type is VoidType) {
+ /* void function */
+ ccheck.call = new CCodeIdentifier ("g_return_if_fail");
+ } else {
+ ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
+
+ var cdefault = default_value_for_type (ret_type);
+ if (cdefault != null) {
+ ccheck.add_argument (cdefault);
+ } else {
+ Report.warning (method_node.source_reference, "not supported return type for runtime type checks");
+ return new CCodeExpressionStatement (new CCodeConstant ("0"));
+ }
+ }
+
+ return new CCodeExpressionStatement (ccheck);
+ }
+
+ private CCodeStatement create_postcondition_statement (Expression postcondition) {
+ var cassert = new CCodeFunctionCall (new CCodeIdentifier ("g_assert"));
+
+ cassert.add_argument ((CCodeExpression) postcondition.ccodenode);
+
+ return new CCodeExpressionStatement (cassert);
+ }
+
private CCodeExpression default_value_for_type (DataType! type) {
if ((type.data_type != null && type.data_type.is_reference_type ()) || type is PointerType) {
return new CCodeConstant ("NULL");
Modified: trunk/vala/parser.y
==============================================================================
--- trunk/vala/parser.y (original)
+++ trunk/vala/parser.y Tue Jan 15 21:01:26 2008
@@ -169,6 +169,7 @@
%token DELEGATE "delegate"
%token DO "do"
%token ELSE "else"
+%token ENSURES "ensures"
%token ENUM "enum"
%token VALA_FALSE "false"
%token FINALLY "finally"
@@ -190,6 +191,7 @@
%token PROTECTED "protected"
%token PUBLIC "public"
%token REF "ref"
+%token REQUIRES "requires"
%token RETURN "return"
%token SET "set"
%token SIGNAL "signal"
@@ -358,6 +360,12 @@
%type <formal_parameter> fixed_parameter
%type <list> opt_throws_declaration
%type <list> throws_declaration
+%type <list> opt_requires_declarations
+%type <list> requires_declarations
+%type <expression> requires_declaration
+%type <list> opt_ensures_declarations
+%type <list> ensures_declarations
+%type <expression> ensures_declaration
%type <signal> signal_declaration
%type <constructor> constructor_declaration
%type <destructor> destructor_declaration
@@ -393,7 +401,7 @@
| COMMA
;
-/* identifiers never conflict with context-specific keywords get or set */
+/* identifiers never conflict with context-specific keywords get, set, requires, or ensures */
identifier
: IDENTIFIER
| GET
@@ -404,6 +412,14 @@
{
$$ = g_strdup ("set");
}
+ | REQUIRES
+ {
+ $$ = g_strdup ("requires");
+ }
+ | ENSURES
+ {
+ $$ = g_strdup ("ensures");
+ }
;
literal
@@ -3001,7 +3017,7 @@
;
method_header
- : comment opt_attributes opt_access_modifier opt_modifiers type identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_throws_declaration
+ : comment opt_attributes opt_access_modifier opt_modifiers type identifier OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS opt_throws_declaration opt_requires_declarations opt_ensures_declarations
{
GList *l;
ValaSourceReference *src;
@@ -3059,6 +3075,22 @@
g_list_free ($10);
}
+ if ($11 != NULL) {
+ for (l = $11; l != NULL; l = l->next) {
+ vala_method_add_precondition ($$, l->data);
+ g_object_unref (l->data);
+ }
+ g_list_free ($11);
+ }
+
+ if ($12 != NULL) {
+ for (l = $12; l != NULL; l = l->next) {
+ vala_method_add_postcondition ($$, l->data);
+ g_object_unref (l->data);
+ }
+ g_list_free ($12);
+ }
+
g_object_unref ($5);
g_free ($6);
}
@@ -3219,6 +3251,58 @@
}
;
+opt_requires_declarations
+ : /* empty */
+ {
+ $$ = NULL;
+ }
+ | requires_declarations
+ ;
+
+requires_declarations
+ : requires_declaration
+ {
+ $$ = g_list_append (NULL, $1);
+ }
+ | requires_declarations requires_declaration
+ {
+ $$ = g_list_append ($1, $2);
+ }
+ ;
+
+requires_declaration
+ : REQUIRES open_parens expression CLOSE_PARENS
+ {
+ $$ = $3;
+ }
+ ;
+
+opt_ensures_declarations
+ : /* empty */
+ {
+ $$ = NULL;
+ }
+ | ensures_declarations
+ ;
+
+ensures_declarations
+ : ensures_declaration
+ {
+ $$ = g_list_append (NULL, $1);
+ }
+ | ensures_declarations ensures_declaration
+ {
+ $$ = g_list_append ($1, $2);
+ }
+ ;
+
+ensures_declaration
+ : ENSURES open_parens expression CLOSE_PARENS
+ {
+ $$ = $3;
+ }
+ ;
+
property_declaration
: comment opt_attributes opt_access_modifier opt_modifiers type identifier OPEN_BRACE get_accessor_declaration opt_set_accessor_declaration CLOSE_BRACE
{
Modified: trunk/vala/scanner.l
==============================================================================
--- trunk/vala/scanner.l (original)
+++ trunk/vala/scanner.l Tue Jan 15 21:01:26 2008
@@ -146,6 +146,7 @@
"delegate" { uploc; return DELEGATE; }
"do" { uploc; return DO; }
"else" { uploc; return ELSE; }
+"ensures" { uploc; return ENSURES; }
"enum" { uploc; return ENUM; }
"false" { uploc; return VALA_FALSE; }
"finally" { uploc; return FINALLY; }
@@ -167,6 +168,7 @@
"protected" { uploc; return PROTECTED; }
"public" { uploc; return PUBLIC; }
"ref" { uploc; return REF; }
+"requires" { uploc; return REQUIRES; }
"set" { uploc; return SET; }
"signal" { uploc; return SIGNAL; }
"sizeof" { uploc; return SIZEOF; }
Modified: trunk/vala/valaclass.vala
==============================================================================
--- trunk/vala/valaclass.vala (original)
+++ trunk/vala/valaclass.vala Tue Jan 15 21:01:26 2008
@@ -190,6 +190,11 @@
m.this_parameter = new FormalParameter ("this", new ClassType (this));
m.scope.add (m.this_parameter.name, m.this_parameter);
}
+ if (!(m.return_type is VoidType)) {
+ m.result_var = new VariableDeclarator ("result");
+ m.result_var.type_reference = m.return_type.copy ();
+ m.scope.add (m.result_var.name, m.result_var);
+ }
if (m is CreationMethod) {
if (m.name == null) {
default_construction_method = m;
Modified: trunk/vala/valainterface.vala
==============================================================================
--- trunk/vala/valainterface.vala (original)
+++ trunk/vala/valainterface.vala Tue Jan 15 21:01:26 2008
@@ -125,6 +125,11 @@
m.this_parameter = new FormalParameter ("this", new InterfaceType (this));
m.scope.add (m.this_parameter.name, m.this_parameter);
}
+ if (!(m.return_type is VoidType)) {
+ m.result_var = new VariableDeclarator ("result");
+ m.result_var.type_reference = m.return_type.copy ();
+ m.scope.add (m.result_var.name, m.result_var);
+ }
methods.add (m);
scope.add (m.name, m);
Modified: trunk/vala/valamethod.vala
==============================================================================
--- trunk/vala/valamethod.vala (original)
+++ trunk/vala/valamethod.vala Tue Jan 15 21:01:26 2008
@@ -1,6 +1,6 @@
/* valamethod.vala
*
- * Copyright (C) 2006-2007 JÃrg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2008 JÃrg Billeter, Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -141,7 +141,12 @@
* Specifies the generated `this' parameter for instance methods.
*/
public FormalParameter this_parameter { get; set; }
-
+
+ /**
+ * Specifies the generated `result' variable for postconditions.
+ */
+ public VariableDeclarator result_var { get; set; }
+
/**
* Specifies whether the array length should implicitly be passed
* if the parameter type is an array.
@@ -170,6 +175,8 @@
private string _sentinel;
private bool _no_array_length;
private Gee.List<DataType> error_domains = new ArrayList<DataType> ();
+ private Gee.List<Expression> preconditions = new ArrayList<Expression> ();
+ private Gee.List<Expression> postconditions = new ArrayList<Expression> ();
private DataType _return_type;
/**
@@ -220,6 +227,18 @@
error_domain.accept (visitor);
}
+ if (result_var != null) {
+ result_var.type_reference.accept (visitor);
+ }
+
+ foreach (Expression precondition in preconditions) {
+ precondition.accept (visitor);
+ }
+
+ foreach (Expression postcondition in postconditions) {
+ postcondition.accept (visitor);
+ }
+
if (body != null) {
body.accept (visitor);
}
@@ -378,6 +397,44 @@
return new ReadOnlyCollection<DataType> (error_domains);
}
+ /**
+ * Adds a precondition to this method.
+ *
+ * @param precondition a boolean precondition expression
+ */
+ public void add_precondition (Expression! precondition) {
+ preconditions.add (precondition);
+ precondition.parent_node = this;
+ }
+
+ /**
+ * Returns a copy of the list of preconditions of this method.
+ *
+ * @return list of preconditions
+ */
+ public Collection<Expression> get_preconditions () {
+ return new ReadOnlyCollection<Expression> (preconditions);
+ }
+
+ /**
+ * Adds a postcondition to this method.
+ *
+ * @param postcondition a boolean postcondition expression
+ */
+ public void add_postcondition (Expression! postcondition) {
+ postconditions.add (postcondition);
+ postcondition.parent_node = this;
+ }
+
+ /**
+ * Returns a copy of the list of postconditions of this method.
+ *
+ * @return list of postconditions
+ */
+ public Collection<Expression> get_postconditions () {
+ return new ReadOnlyCollection<Expression> (postconditions);
+ }
+
public override void replace_type (DataType! old_type, DataType! new_type) {
if (return_type == old_type) {
return_type = new_type;
Modified: trunk/vala/valasemanticanalyzer.vala
==============================================================================
--- trunk/vala/valasemanticanalyzer.vala (original)
+++ trunk/vala/valasemanticanalyzer.vala Tue Jan 15 21:01:26 2008
@@ -391,6 +391,34 @@
return;
}
}
+
+ /*foreach (Expression precondition in m.get_preconditions ()) {
+ if (precondition.error) {
+ // if there was an error in the precondition, skip this check
+ m.error = true;
+ return;
+ }
+
+ if (!precondition.static_type.compatible (bool_type)) {
+ m.error = true;
+ Report.error (precondition.source_reference, "Precondition must be boolean");
+ return;
+ }
+ }
+
+ foreach (Expression postcondition in m.get_postconditions ()) {
+ if (postcondition.error) {
+ // if there was an error in the postcondition, skip this check
+ m.error = true;
+ return;
+ }
+
+ if (!postcondition.static_type.compatible (bool_type)) {
+ m.error = true;
+ Report.error (postcondition.source_reference, "Postcondition must be boolean");
+ return;
+ }
+ }*/
}
private void find_base_class_method (Method! m, Class! cl) {
Modified: trunk/vala/valastruct.vala
==============================================================================
--- trunk/vala/valastruct.vala (original)
+++ trunk/vala/valastruct.vala Tue Jan 15 21:01:26 2008
@@ -117,6 +117,11 @@
m.this_parameter = new FormalParameter ("this", new ValueType (this));
m.scope.add (m.this_parameter.name, m.this_parameter);
}
+ if (!(m.return_type is VoidType)) {
+ m.result_var = new VariableDeclarator ("result");
+ m.result_var.type_reference = m.return_type.copy ();
+ m.scope.add (m.result_var.name, m.result_var);
+ }
if (m is CreationMethod) {
if (m.name == null) {
default_construction_method = m;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]