]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Support ref and out parameters in lambda expressions
authorLuca Bruno <lucabru@src.gnome.org>
Sat, 16 Apr 2011 10:55:35 +0000 (12:55 +0200)
committerLuca Bruno <lucabru@src.gnome.org>
Fri, 17 Jun 2011 20:13:02 +0000 (22:13 +0200)
Fixes bug 622570.

tests/Makefile.am
tests/methods/bug622570.vala [new file with mode: 0644]
vala/valacodewriter.vala
vala/valagenieparser.vala
vala/valalambdaexpression.vala
vala/valaparameter.vala
vala/valaparser.vala

index 693551d8521b5d897280658ad0e7b1ccdd438c24..a4b1beddd80a091b3f00b98b99988999bc102732 100644 (file)
@@ -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 (file)
index 0000000..f8b4e91
--- /dev/null
@@ -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);
+}
index ff5b413a8b3f3d428c89af9b82271f09351baa5d..ee5daf1118acfd68f9f2909e76bd5f17c4edaada 100644 (file)
@@ -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) {
index 89e5ea732076bf4781161fb29ba2c454adb135df..0de741cc5cb8614dae58d772b28b87b017b5c27a 100644 (file)
@@ -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;
index c09aea82ba8fcee625dec4f7851760d659e9f18b..ecfe25106509a49495d331601a96138dc7cebaf5 100644 (file)
@@ -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 ()) {
index faab5afe621742ccc2a861aaa37918de09feefa4..ab4d4a3b09fa32675e298a47702f5f9967c02c53 100644 (file)
@@ -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;
index ad97da8790b0a39abd5995cff287b4c20100f69c..60c7a6039663c616937ab065604c0bca00ce2205 100644 (file)
@@ -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 ();