1 /* valalambdaexpression.vala
3 * Copyright (C) 2006-2009 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Jürg Billeter <j@bitron.ch>
27 * Represents a lambda expression in the source code. Lambda expressions are
28 * anonymous methods with implicitly typed parameters.
30 public class Vala
.LambdaExpression
: Expression
{
32 * The expression body of this lambda expression. Only one of
33 * expression_body or statement_body may be set.
35 public Expression expression_body
{ get; set; }
38 * The statement body of this lambda expression. Only one of
39 * expression_body or statement_body may be set.
41 public Block statement_body
{ get; set; }
44 * The generated method.
46 public Method method
{ get; set; }
48 private Gee
.List
<string> parameters
= new ArrayList
<string> ();
51 * Creates a new lambda expression.
53 * @param expression_body expression body
54 * @param source_reference reference to source code
55 * @return newly created lambda expression
57 public LambdaExpression (Expression expression_body
, SourceReference source_reference
) {
58 this
.source_reference
= source_reference
;
59 this
.expression_body
= expression_body
;
63 * Creates a new lambda expression with statement body.
65 * @param statement_body statement body
66 * @param source_reference reference to source code
67 * @return newly created lambda expression
69 public LambdaExpression
.with_statement_body (Block statement_body
, SourceReference source_reference
) {
70 this
.statement_body
= statement_body
;
71 this
.source_reference
= source_reference
;
75 * Appends implicitly typed parameter.
77 * @param param parameter name
79 public void add_parameter (string param
) {
80 parameters
.add (param
);
84 * Returns copy of parameter list.
86 * @return parameter list
88 public Gee
.List
<string> get_parameters () {
89 return new ReadOnlyList
<string> (parameters
);
92 public override void accept (CodeVisitor visitor
) {
93 visitor
.visit_lambda_expression (this
);
95 visitor
.visit_expression (this
);
98 public override void accept_children (CodeVisitor visitor
) {
100 if (expression_body
!= null) {
101 expression_body
.accept (visitor
);
102 visitor
.visit_end_full_expression (expression_body
);
103 } else if (statement_body
!= null) {
104 statement_body
.accept (visitor
);
107 method
.accept (visitor
);
111 public override bool is_pure () {
115 string get_lambda_name (SemanticAnalyzer analyzer
) {
116 var result
= "__lambda%d".printf (analyzer
.next_lambda_id
);
118 analyzer
.next_lambda_id
++;
123 public override bool check (SemanticAnalyzer analyzer
) {
130 if (!(target_type is DelegateType
)) {
132 Report
.error (source_reference
, "lambda expression not allowed in this context");
136 var cb
= (Delegate
) ((DelegateType
) target_type
).delegate_symbol
;
137 method
= new
Method (get_lambda_name (analyzer
), cb
.return_type
);
138 if (!cb
.has_target
|| !analyzer
.is_in_instance_method ()) {
139 method
.binding
= MemberBinding
.STATIC
;
141 method
.owner
= analyzer
.current_symbol
.scope
;
143 var lambda_params
= get_parameters ();
144 Iterator
<string> lambda_param_it
= lambda_params
.iterator ();
145 foreach (FormalParameter cb_param
in cb
.get_parameters ()) {
146 if (!lambda_param_it
.next ()) {
147 /* lambda expressions are allowed to have less parameters */
151 string lambda_param
= lambda_param_it
.get ();
153 var param
= new
FormalParameter (lambda_param
, cb_param
.parameter_type
);
155 method
.add_parameter (param
);
158 if (lambda_param_it
.next ()) {
159 /* lambda expressions may not expect more parameters */
161 Report
.error (source_reference
, "lambda expression: too many parameters");
165 foreach (var error_type
in cb
.get_error_types ()) {
166 method
.add_error_type (error_type
.copy ());
169 if (expression_body
!= null) {
170 var block
= new
Block (source_reference
);
171 block
.scope
.parent_scope
= method
.scope
;
173 if (method
.return_type
.data_type
!= null) {
174 block
.add_statement (new
ReturnStatement (expression_body
, source_reference
));
176 block
.add_statement (new
ExpressionStatement (expression_body
, source_reference
));
181 method
.body
= statement_body
;
183 method
.body
.owner
= method
.scope
;
185 /* lambda expressions should be usable like MemberAccess of a method */
186 symbol_reference
= method
;
188 if (method
== null) {
189 if (expression_body
!= null) {
190 expression_body
.check (analyzer
);
191 } else if (statement_body
!= null) {
192 statement_body
.check (analyzer
);
195 method
.check (analyzer
);
198 value_type
= new
MethodType (method
);