[vala] Support ref and out parameters in lambda expressions
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala] Support ref and out parameters in lambda expressions
- Date: Fri, 17 Jun 2011 20:17:16 +0000 (UTC)
commit 3ee508f5fdf332978848d344049bdeeb3fbe741a
Author: Luca Bruno <lucabru src gnome org>
Date: Sat Apr 16 12:55:35 2011 +0200
Support ref and out parameters in lambda expressions
Fixes bug 622570.
tests/Makefile.am | 1 +
tests/methods/bug622570.vala | 13 +++++++
vala/valacodewriter.vala | 17 +++++++--
vala/valagenieparser.vala | 10 +++--
vala/valalambdaexpression.vala | 21 +++++------
vala/valaparameter.vala | 2 +-
vala/valaparser.vala | 78 ++++++++++++++++++++++++++++++++++-----
7 files changed, 112 insertions(+), 30 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 693551d..a4b1bed 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -37,6 +37,7 @@ TESTS = \
methods/bug599892.vala \
methods/bug613483.vala \
methods/bug620673.vala \
+ methods/bug622570.vala \
methods/bug642899.vala \
methods/bug646345.vala \
methods/bug648320.vala \
diff --git a/tests/methods/bug622570.vala b/tests/methods/bug622570.vala
new file mode 100644
index 0000000..f8b4e91
--- /dev/null
+++ b/tests/methods/bug622570.vala
@@ -0,0 +1,13 @@
+delegate int Deleg1 (ref int foo);
+delegate void Deleg2 (out Value foo, ref int bar);
+
+void main () {
+ int a = 3, b = 4;
+ Value c;
+ Deleg1 d1 = ref foo => foo + 5;
+ Deleg2 d2 = (out foo, ref bar) => { foo = 10; bar = 3; };
+ assert (d1 (ref a) == 8);
+ d2 (out c, ref b);
+ assert (c == 10);
+ assert (b == 3);
+}
diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala
index ff5b413..ee5daf1 100644
--- a/vala/valacodewriter.vala
+++ b/vala/valacodewriter.vala
@@ -1924,12 +1924,21 @@ public class Vala.CodeWriter : CodeVisitor {
public override void visit_lambda_expression (LambdaExpression expr) {
write_string ("(");
var params = expr.get_parameters ();
- if (params.size != 0) {
- for (var i = 0; i < params.size - 1; ++ i) {
- write_string (params[i]);
+ int i = 1;
+ foreach (var param in params) {
+ if (i > 1) {
write_string (", ");
}
- write_string (params[params.size - 1]);
+
+ if (param.direction == ParameterDirection.REF) {
+ write_string ("ref ");
+ } else if (param.direction == ParameterDirection.OUT) {
+ write_string ("out ");
+ }
+
+ write_identifier (param.name);
+
+ i++;
}
write_string (") =>");
if (expr.statement_body != null) {
diff --git a/vala/valagenieparser.vala b/vala/valagenieparser.vala
index 89e5ea7..0de741c 100644
--- a/vala/valagenieparser.vala
+++ b/vala/valagenieparser.vala
@@ -1522,19 +1522,21 @@ public class Vala.Genie.Parser : CodeVisitor {
Expression parse_lambda_expression () throws ParseError {
var begin = get_location ();
- List<string> params = new ArrayList<string> ();
+ List<Parameter> params = new ArrayList<Parameter> ();
expect (TokenType.DEF);
if (accept (TokenType.OPEN_PARENS)) {
if (current () != TokenType.CLOSE_PARENS) {
do {
- params.add (parse_identifier ());
+ var param = new Parameter (parse_identifier (), null, get_src (get_location ()));
+ params.add (param);
} while (accept (TokenType.COMMA));
}
expect (TokenType.CLOSE_PARENS);
} else {
- params.add (parse_identifier ());
+ var param = new Parameter (parse_identifier (), null, get_src (get_location ()));
+ params.add (param);
}
@@ -1550,7 +1552,7 @@ public class Vala.Genie.Parser : CodeVisitor {
}
- foreach (string param in params) {
+ foreach (var param in params) {
lambda.add_parameter (param);
}
return lambda;
diff --git a/vala/valalambdaexpression.vala b/vala/valalambdaexpression.vala
index c09aea8..ecfe251 100644
--- a/vala/valalambdaexpression.vala
+++ b/vala/valalambdaexpression.vala
@@ -44,7 +44,7 @@ public class Vala.LambdaExpression : Expression {
*/
public Method method { get; set; }
- private List<string> parameters = new ArrayList<string> ();
+ private List<Parameter> parameters = new ArrayList<Parameter> ();
/**
* Creates a new lambda expression.
@@ -75,7 +75,7 @@ public class Vala.LambdaExpression : Expression {
*
* @param param parameter name
*/
- public void add_parameter (string param) {
+ public void add_parameter (Parameter param) {
parameters.add (param);
}
@@ -84,7 +84,7 @@ public class Vala.LambdaExpression : Expression {
*
* @return parameter list
*/
- public List<string> get_parameters () {
+ public List<Parameter> get_parameters () {
return parameters;
}
@@ -173,15 +173,15 @@ public class Vala.LambdaExpression : Expression {
}
var lambda_params = get_parameters ();
- Iterator<string> lambda_param_it = lambda_params.iterator ();
+ Iterator<Parameter> lambda_param_it = lambda_params.iterator ();
if (cb.sender_type != null && lambda_params.size == cb.get_parameters ().size + 1) {
// lambda expression has sender parameter
lambda_param_it.next ();
- string lambda_param = lambda_param_it.get ();
- var param = new Parameter (lambda_param, cb.sender_type);
- method.add_parameter (param);
+ Parameter lambda_param = lambda_param_it.get ();
+ lambda_param.variable_type = cb.sender_type;
+ method.add_parameter (lambda_param);
}
foreach (Parameter cb_param in cb.get_parameters ()) {
@@ -190,10 +190,9 @@ public class Vala.LambdaExpression : Expression {
break;
}
- string lambda_param = lambda_param_it.get ();
- var param_type = cb_param.variable_type.get_actual_type (target_type, null, this);
- var param = new Parameter (lambda_param, param_type);
- method.add_parameter (param);
+ Parameter lambda_param = lambda_param_it.get ();
+ lambda_param.variable_type = cb_param.variable_type.get_actual_type (target_type, null, this);
+ method.add_parameter (lambda_param);
}
if (lambda_param_it.next ()) {
diff --git a/vala/valaparameter.vala b/vala/valaparameter.vala
index faab5af..ab4d4a3 100644
--- a/vala/valaparameter.vala
+++ b/vala/valaparameter.vala
@@ -76,7 +76,7 @@ public class Vala.Parameter : Variable {
* @param source reference to source code
* @return newly created formal parameter
*/
- public Parameter (string name, DataType variable_type, SourceReference? source_reference = null) {
+ public Parameter (string name, DataType? variable_type, SourceReference? source_reference = null) {
base (variable_type, name, null, source_reference);
access = SymbolAccessibility.PUBLIC;
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index ad97da8..60c7a60 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -1352,18 +1352,34 @@ public class Vala.Parser : CodeVisitor {
}
}
+ Parameter parse_lambda_parameter () throws ParseError {
+ var begin = get_location ();
+ var direction = ParameterDirection.IN;
+ if (accept (TokenType.OUT)) {
+ direction = ParameterDirection.OUT;
+ } else if (accept (TokenType.REF)) {
+ direction = ParameterDirection.REF;
+ }
+
+ string id = parse_identifier ();
+
+ var param = new Parameter (id, null, get_src (begin));
+ param.direction = direction;
+ return param;
+ }
+
Expression parse_lambda_expression () throws ParseError {
var begin = get_location ();
- List<string> params = new ArrayList<string> ();
+ List<Parameter> params = new ArrayList<Parameter> ();
if (accept (TokenType.OPEN_PARENS)) {
if (current () != TokenType.CLOSE_PARENS) {
do {
- params.add (parse_identifier ());
+ params.add (parse_lambda_parameter ());
} while (accept (TokenType.COMMA));
}
expect (TokenType.CLOSE_PARENS);
} else {
- params.add (parse_identifier ());
+ params.add (parse_lambda_parameter ());
}
expect (TokenType.LAMBDA);
@@ -1375,7 +1391,7 @@ public class Vala.Parser : CodeVisitor {
var expr = parse_expression ();
lambda = new LambdaExpression (expr, get_src (begin));
}
- foreach (string param in params) {
+ foreach (var param in params) {
lambda.add_parameter (param);
}
return lambda;
@@ -1398,14 +1414,13 @@ public class Vala.Parser : CodeVisitor {
}
Expression parse_expression () throws ParseError {
+ if (is_lambda_expression ()) {
+ return parse_lambda_expression ();
+ }
+
var begin = get_location ();
- Expression expr = parse_conditional_expression ();
- if (current () == TokenType.LAMBDA) {
- rollback (begin);
- var lambda = parse_lambda_expression ();
- return lambda;
- }
+ Expression expr = parse_conditional_expression ();
while (true) {
var operator = get_assignment_operator (current ());
@@ -1582,6 +1597,49 @@ public class Vala.Parser : CodeVisitor {
}
}
+ bool is_lambda_expression () {
+ var begin = get_location ();
+
+ switch (current ()) {
+ case TokenType.OUT:
+ case TokenType.REF:
+ next ();
+ if (accept (TokenType.IDENTIFIER) && accept (TokenType.LAMBDA)) {
+ rollback (begin);
+ return true;
+ }
+ break;
+ case TokenType.IDENTIFIER:
+ next ();
+ if (accept (TokenType.LAMBDA)) {
+ rollback (begin);
+ return true;
+ }
+ break;
+ case TokenType.OPEN_PARENS:
+ next ();
+ if (current () != TokenType.CLOSE_PARENS) {
+ do {
+ if (current () == TokenType.OUT || current () == TokenType.REF) {
+ next ();
+ }
+ if (!accept (TokenType.IDENTIFIER)) {
+ rollback (begin);
+ return false;
+ }
+ } while (accept (TokenType.COMMA));
+ }
+ if (accept (TokenType.CLOSE_PARENS) && accept (TokenType.LAMBDA)) {
+ rollback (begin);
+ return true;
+ }
+ break;
+ }
+
+ rollback (begin);
+ return false;
+ }
+
Block parse_embedded_statement () throws ParseError {
if (current () == TokenType.OPEN_BRACE) {
var block = parse_block ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]