Fix gtk_text_iter_forward_find_char binding, patch by Nicolas Joseph,
[vala-lang.git] / vala / valalambdaexpression.vala
blob042df585ca35fc9faf827707d2daf3dfdfaeb5b7
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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
24 using Gee;
26 /**
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 {
31 /**
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; }
37 /**
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; }
43 /**
44 * The generated method.
46 public Method method { get; set; }
48 private Gee.List<string> parameters = new ArrayList<string> ();
50 /**
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;
62 /**
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;
74 /**
75 * Appends implicitly typed parameter.
77 * @param param parameter name
79 public void add_parameter (string param) {
80 parameters.add (param);
83 /**
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) {
99 if (method == null) {
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);
106 } else {
107 method.accept (visitor);
111 public override bool is_pure () {
112 return false;
115 string get_lambda_name (SemanticAnalyzer analyzer) {
116 var result = "__lambda%d".printf (analyzer.next_lambda_id);
118 analyzer.next_lambda_id++;
120 return result;
123 public override bool check (SemanticAnalyzer analyzer) {
124 if (checked) {
125 return !error;
128 checked = true;
130 if (!(target_type is DelegateType)) {
131 error = true;
132 Report.error (source_reference, "lambda expression not allowed in this context");
133 return false;
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 */
148 break;
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 */
160 error = true;
161 Report.error (source_reference, "lambda expression: too many parameters");
162 return false;
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));
175 } else {
176 block.add_statement (new ExpressionStatement (expression_body, source_reference));
179 method.body = block;
180 } else {
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);
194 } else {
195 method.check (analyzer);
198 value_type = new MethodType (method);
200 return !error;