[vala] dova: Add support for closures
- From: Jürg Billeter <juergbi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala] dova: Add support for closures
- Date: Sat, 26 Jun 2010 16:03:27 +0000 (UTC)
commit 9d89bd50cff087c209b003cd7dff668bf973f137
Author: Jürg Billeter <j bitron ch>
Date: Sat Jun 26 18:02:37 2010 +0200
dova: Add support for closures
codegen/valadovabasemodule.vala | 292 +++++++++++++++++++++++++++++--
codegen/valadovamemberaccessmodule.vala | 55 ++++---
codegen/valadovaobjectmodule.vala | 38 ++++-
3 files changed, 348 insertions(+), 37 deletions(-)
---
diff --git a/codegen/valadovabasemodule.vala b/codegen/valadovabasemodule.vala
index a0b2641..77befcc 100644
--- a/codegen/valadovabasemodule.vala
+++ b/codegen/valadovabasemodule.vala
@@ -89,6 +89,29 @@ internal class Vala.DovaBaseModule : CCodeModule {
}
}
+ public Block? current_closure_block {
+ get {
+ return next_closure_block (current_symbol);
+ }
+ }
+
+ public unowned Block? next_closure_block (Symbol sym) {
+ unowned Block block = null;
+ while (true) {
+ block = sym as Block;
+ if (!(sym is Block || sym is Method)) {
+ // no closure block
+ break;
+ }
+ if (block != null && block.captured) {
+ // closure block found
+ break;
+ }
+ sym = sym.parent_symbol;
+ }
+ return block;
+ }
+
public CCodeDeclarationSpace header_declarations;
public CCodeDeclarationSpace internal_header_declarations;
public CCodeDeclarationSpace source_declarations;
@@ -112,6 +135,8 @@ internal class Vala.DovaBaseModule : CCodeModule {
public int next_string_const_id = 0;
public bool in_creation_method { get { return current_method is CreationMethod; } }
public bool current_method_inner_error = false;
+ int next_block_id = 0;
+ Map<Block,int> block_map = new HashMap<Block,int> ();
public DataType void_type = new VoidType ();
public DataType bool_type;
@@ -643,6 +668,44 @@ internal class Vala.DovaBaseModule : CCodeModule {
current_method_inner_error = old_method_inner_error;
}
+ public int get_block_id (Block b) {
+ int result = block_map[b];
+ if (result == 0) {
+ result = ++next_block_id;
+ block_map[b] = result;
+ }
+ return result;
+ }
+
+ void capture_parameter (FormalParameter param, CCodeStruct data, CCodeBlock cblock, int block_id, CCodeBlock free_block) {
+ generate_type_declaration (param.parameter_type, source_declarations);
+
+ var param_type = param.parameter_type.copy ();
+ param_type.value_owned = true;
+ data.add_field (param_type.get_cname (), get_variable_cname (param.name));
+
+ // create copy if necessary as captured variables may need to be kept alive
+ CCodeExpression cparam = get_variable_cexpression (param.name);
+ if (requires_copy (param_type) && !param.parameter_type.value_owned) {
+ var ma = new MemberAccess.simple (param.name);
+ ma.symbol_reference = param;
+ ma.value_type = param.parameter_type.copy ();
+ // directly access parameters in ref expressions
+ param.captured = false;
+ cparam = get_ref_cexpression (param.parameter_type, cparam, ma, param);
+ param.captured = true;
+ }
+
+ cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_variable_cname (param.name)), cparam)));
+
+ if (requires_destroy (param_type)) {
+ var ma = new MemberAccess.simple (param.name);
+ ma.symbol_reference = param;
+ ma.value_type = param_type.copy ();
+ free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), get_variable_cname (param.name)), param.parameter_type, ma)));
+ }
+ }
+
public override void visit_block (Block b) {
var old_symbol = current_symbol;
current_symbol = b;
@@ -656,6 +719,154 @@ internal class Vala.DovaBaseModule : CCodeModule {
var cblock = new CCodeBlock ();
+
+ if (b.captured) {
+ var parent_block = next_closure_block (b.parent_symbol);
+
+ int block_id = get_block_id (b);
+ string struct_name = "Block%dData".printf (block_id);
+
+ var free_block = new CCodeBlock ();
+
+ var data = new CCodeStruct ("_" + struct_name);
+ data.add_field ("DovaType*", "type");
+ data.add_field ("int", "_ref_count_");
+ if (parent_block != null) {
+ int parent_block_id = get_block_id (parent_block);
+
+ data.add_field ("Block%dData *".printf (parent_block_id), "_data%d_".printf (parent_block_id));
+
+ var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_unref"));
+ unref_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)));
+ free_block.add_statement (new CCodeExpressionStatement (unref_call));
+ } else if ((current_method != null && current_method.binding == MemberBinding.INSTANCE) ||
+ (current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE)) {
+ data.add_field ("%s *".printf (current_class.get_cname ()), "this");
+
+ var ma = new MemberAccess.simple ("this");
+ ma.symbol_reference = current_class;
+ free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "this"), new ObjectType (current_class), ma)));
+ }
+ foreach (var local in local_vars) {
+ if (local.captured) {
+ generate_type_declaration (local.variable_type, source_declarations);
+
+ data.add_field (local.variable_type.get_cname (), get_variable_cname (local.name) + local.variable_type.get_cdeclarator_suffix ());
+
+ if (requires_destroy (local.variable_type)) {
+ var ma = new MemberAccess.simple (local.name);
+ ma.symbol_reference = local;
+ ma.value_type = local.variable_type.copy ();
+ free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), get_variable_cname (local.name)), local.variable_type, ma)));
+ }
+ }
+ }
+
+ var data_alloc = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_alloc"));
+ data_alloc.add_argument (new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_type_get".printf (block_id))));
+
+ var data_decl = new CCodeDeclaration (struct_name + "*");
+ data_decl.add_declarator (new CCodeVariableDeclarator ("_data%d_".printf (block_id), data_alloc));
+ cblock.add_statement (data_decl);
+
+ if (parent_block != null) {
+ int parent_block_id = get_block_id (parent_block);
+
+ var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_ref"));
+ ref_call.add_argument (get_variable_cexpression ("_data%d_".printf (parent_block_id)));
+
+ cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)), ref_call)));
+ } else if ((current_method != null && current_method.binding == MemberBinding.INSTANCE &&
+ (!(current_method is CreationMethod) || current_method.body != b)) ||
+ (current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE)) {
+ var ref_call = new CCodeFunctionCall (get_dup_func_expression (new ObjectType (current_class), b.source_reference));
+ ref_call.add_argument (new CCodeIdentifier ("this"));
+
+ cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "this"), ref_call)));
+ }
+
+ if (b.parent_symbol is Method) {
+ var m = (Method) b.parent_symbol;
+
+ // parameters are captured with the top-level block of the method
+ foreach (var param in m.get_parameters ()) {
+ if (param.captured) {
+ capture_parameter (param, data, cblock, block_id, free_block);
+ }
+ }
+
+ var cfrag = new CCodeFragment ();
+ append_temp_decl (cfrag, temp_vars);
+ temp_vars.clear ();
+ cblock.add_statement (cfrag);
+ } else if (b.parent_symbol is PropertyAccessor) {
+ var acc = (PropertyAccessor) b.parent_symbol;
+
+ if (!acc.readable && acc.value_parameter.captured) {
+ capture_parameter (acc.value_parameter, data, cblock, block_id, free_block);
+ }
+
+ var cfrag = new CCodeFragment ();
+ append_temp_decl (cfrag, temp_vars);
+ temp_vars.clear ();
+ cblock.add_statement (cfrag);
+ }
+
+ var typedef = new CCodeTypeDefinition ("struct _" + struct_name, new CCodeVariableDeclarator (struct_name));
+ source_declarations.add_type_declaration (typedef);
+ source_declarations.add_type_definition (data);
+
+ var data_free = new CCodeFunctionCall (new CCodeIdentifier ("free"));
+ data_free.add_argument (new CCodeIdentifier ("_data%d_".printf (block_id)));
+ free_block.add_statement (new CCodeExpressionStatement (data_free));
+
+ // create type_get/finalize functions
+ var type_get_fun = new CCodeFunction ("block%d_data_type_get".printf (block_id), "DovaType*");
+ type_get_fun.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_type_member_declaration (type_get_fun.copy ());
+ type_get_fun.block = new CCodeBlock ();
+
+ var cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_block%d_data_object_offset".printf (block_id), new CCodeConstant ("0")));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_type_member_declaration (cdecl);
+
+ cdecl = new CCodeDeclaration ("int");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_block%d_data_type_offset".printf (block_id), new CCodeConstant ("0")));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_type_member_declaration (cdecl);
+
+ cdecl = new CCodeDeclaration ("DovaType *");
+ cdecl.add_declarator (new CCodeVariableDeclarator ("block%d_data_type".printf (block_id), new CCodeConstant ("NULL")));
+ cdecl.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_type_member_declaration (cdecl);
+
+ var type_init_block = new CCodeBlock ();
+ var alloc_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_alloc"));
+ alloc_call.add_argument (new CCodeFunctionCall (new CCodeIdentifier ("dova_object_type_get")));
+ alloc_call.add_argument (new CCodeConstant ("sizeof (%s)".printf (struct_name)));
+ alloc_call.add_argument (new CCodeConstant ("0"));
+ alloc_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("block%d_data_type".printf (block_id))));
+ alloc_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_block%d_data_object_offset".printf (block_id))));
+ alloc_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_block%d_data_type_offset".printf (block_id))));
+ type_init_block.add_statement (new CCodeExpressionStatement (alloc_call));
+ var type_init_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_type_init"));
+ type_init_call.add_argument (new CCodeIdentifier ("block%d_data_type".printf (block_id)));
+ type_init_block.add_statement (new CCodeExpressionStatement (type_init_call));
+ type_get_fun.block.add_statement (new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("block%d_data_type".printf (block_id))), type_init_block));
+ type_get_fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("block%d_data_type".printf (block_id))));
+
+ source_type_member_definition.append (type_get_fun);
+
+ var unref_fun = new CCodeFunction ("block%d_data_finalize".printf (block_id), "void");
+ unref_fun.add_parameter (new CCodeFormalParameter ("_data%d_".printf (block_id), struct_name + "*"));
+ unref_fun.modifiers = CCodeModifiers.STATIC;
+ source_declarations.add_type_member_declaration (unref_fun.copy ());
+ unref_fun.block = free_block;
+
+ source_type_member_definition.append (unref_fun);
+ }
+
foreach (CodeNode stmt in b.get_statements ()) {
if (stmt.error) {
continue;
@@ -671,7 +882,7 @@ internal class Vala.DovaBaseModule : CCodeModule {
}
foreach (LocalVariable local in local_vars) {
- if (!local.floating && requires_destroy (local.variable_type)) {
+ if (!local.floating && !local.captured && requires_destroy (local.variable_type)) {
var ma = new MemberAccess.simple (local.name);
ma.symbol_reference = local;
cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
@@ -681,7 +892,7 @@ internal class Vala.DovaBaseModule : CCodeModule {
if (b.parent_symbol is Method) {
var m = (Method) b.parent_symbol;
foreach (FormalParameter param in m.get_parameters ()) {
- if (requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
+ if (!param.captured && requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
var ma = new MemberAccess.simple (param.name);
ma.symbol_reference = param;
cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (param.name), param.parameter_type, ma)));
@@ -689,6 +900,14 @@ internal class Vala.DovaBaseModule : CCodeModule {
}
}
+ if (b.captured) {
+ int block_id = get_block_id (b);
+
+ var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_unref"));
+ data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id)));
+ cblock.add_statement (new CCodeExpressionStatement (data_unref));
+ }
+
b.ccodenode = cblock;
current_symbol = old_symbol;
@@ -748,17 +967,23 @@ internal class Vala.DovaBaseModule : CCodeModule {
pre_statement_fragment = null;
}
- var cvar = new CCodeVariableDeclarator (get_variable_cname (local.name), rhs, local.variable_type.get_cdeclarator_suffix ());
+ if (local.captured) {
+ if (local.initializer != null) {
+ cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id ((Block) local.parent_symbol))), get_variable_cname (local.name)), rhs)));
+ }
+ } else {
+ var cvar = new CCodeVariableDeclarator (get_variable_cname (local.name), rhs, local.variable_type.get_cdeclarator_suffix ());
- var cdecl = new CCodeDeclaration (local.variable_type.get_cname ());
- cdecl.add_declarator (cvar);
- cfrag.append (cdecl);
+ var cdecl = new CCodeDeclaration (local.variable_type.get_cname ());
+ cdecl.add_declarator (cvar);
+ cfrag.append (cdecl);
- // try to initialize uninitialized variables
- // initialization not necessary for variables stored in closure
- if (cvar.initializer == null) {
- cvar.initializer = default_value_for_type (local.variable_type, true);
- cvar.init0 = true;
+ // try to initialize uninitialized variables
+ // initialization not necessary for variables stored in closure
+ if (cvar.initializer == null) {
+ cvar.initializer = default_value_for_type (local.variable_type, true);
+ cvar.init0 = true;
+ }
}
if (local.initializer != null && local.initializer.tree_can_fail) {
@@ -1162,13 +1387,21 @@ internal class Vala.DovaBaseModule : CCodeModule {
var local_vars = b.get_local_variables ();
foreach (LocalVariable local in local_vars) {
- if (local.active && !local.floating && requires_destroy (local.variable_type)) {
+ if (local.active && !local.floating && !local.captured && requires_destroy (local.variable_type)) {
var ma = new MemberAccess.simple (local.name);
ma.symbol_reference = local;
cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
}
}
+ if (b.captured) {
+ int block_id = get_block_id (b);
+
+ var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_unref"));
+ data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id)));
+ cfrag.append (new CCodeExpressionStatement (data_unref));
+ }
+
if (stop_at_loop) {
if (b.parent_node is Loop ||
b.parent_node is ForeachStatement ||
@@ -1189,13 +1422,21 @@ internal class Vala.DovaBaseModule : CCodeModule {
var local_vars = b.get_local_variables ();
foreach (LocalVariable local in local_vars) {
- if (local.active && !local.floating && requires_destroy (local.variable_type)) {
+ if (local.active && !local.floating && !local.captured && requires_destroy (local.variable_type)) {
var ma = new MemberAccess.simple (local.name);
ma.symbol_reference = local;
cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
}
}
+ if (b.captured) {
+ int block_id = get_block_id (b);
+
+ var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_unref"));
+ data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id)));
+ cfrag.append (new CCodeExpressionStatement (data_unref));
+ }
+
if (sym == current_try.body) {
return;
}
@@ -1995,8 +2236,20 @@ internal class Vala.DovaBaseModule : CCodeModule {
var method_type = (MethodType) expression_type;
CCodeExpression delegate_target = new CCodeConstant ("NULL");
if (method_type.method_symbol.binding == MemberBinding.INSTANCE) {
- var ma = (MemberAccess) expr;
- delegate_target = (CCodeExpression) get_ccodenode (ma.inner);
+ if (expr is LambdaExpression) {
+ var lambda = (LambdaExpression) expr;
+ if (lambda.method.closure) {
+ int block_id = get_block_id (current_closure_block);
+ delegate_target = get_variable_cexpression ("_data%d_".printf (block_id));
+ } else if (get_this_type () != null) {
+ delegate_target = new CCodeIdentifier ("this");
+ } else {
+ delegate_target = new CCodeConstant ("NULL");
+ }
+ } else {
+ var ma = (MemberAccess) expr;
+ delegate_target = (CCodeExpression) get_ccodenode (ma.inner);
+ }
}
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_new".printf (deleg_type.delegate_symbol.get_lower_case_cname ())));
ccall.add_argument (delegate_target);
@@ -2132,6 +2385,15 @@ internal class Vala.DovaBaseModule : CCodeModule {
public override void visit_class (Class cl) {
}
+ public DataType? get_this_type () {
+ if (current_method != null && current_method.binding == MemberBinding.INSTANCE) {
+ return current_method.this_parameter.parameter_type;
+ } else if (current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE) {
+ return current_property_accessor.prop.this_parameter.parameter_type;
+ }
+ return null;
+ }
+
public CCodeFunctionCall generate_instance_cast (CCodeExpression expr, TypeSymbol type) {
var result = new CCodeFunctionCall (new CCodeIdentifier (type.get_upper_case_cname (null)));
result.add_argument (expr);
diff --git a/codegen/valadovamemberaccessmodule.vala b/codegen/valadovamemberaccessmodule.vala
index 8bc36c7..8a3ade7 100644
--- a/codegen/valadovamemberaccessmodule.vala
+++ b/codegen/valadovamemberaccessmodule.vala
@@ -1,6 +1,6 @@
/* valadovamemberaccessmodule.vala
*
- * Copyright (C) 2006-2009 Jürg Billeter
+ * Copyright (C) 2006-2010 Jürg Billeter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -204,6 +204,10 @@ internal class Vala.DovaMemberAccessModule : DovaControlFlowModule {
if (local.is_result) {
// used in postconditions
expr.ccodenode = new CCodeIdentifier ("result");
+ } else if (local.captured) {
+ // captured variables are stored on the heap
+ var block = (Block) local.parent_symbol;
+ expr.ccodenode = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_variable_cname (local.name));
} else {
expr.ccodenode = get_variable_cexpression (local.name);
}
@@ -222,29 +226,38 @@ internal class Vala.DovaMemberAccessModule : DovaControlFlowModule {
}
}
} else {
- if (current_method != null && current_method.coroutine) {
- // use closure
- expr.ccodenode = get_variable_cexpression (p.name);
+ if (p.captured) {
+ // captured variables are stored on the heap
+ var block = p.parent_symbol as Block;
+ if (block == null) {
+ block = ((Method) p.parent_symbol).body;
+ }
+ expr.ccodenode = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_variable_cname (p.name));
} else {
- var type_as_struct = p.parameter_type.data_type as Struct;
- if (p.direction != ParameterDirection.IN
- || (type_as_struct != null && !type_as_struct.is_simple_type () && !p.parameter_type.nullable)) {
- if (p.parameter_type is GenericType) {
- expr.ccodenode = get_variable_cexpression (p.name);
- } else {
- expr.ccodenode = new CCodeIdentifier ("(*%s)".printf (get_variable_cname (p.name)));
- }
+ if (current_method != null && current_method.coroutine) {
+ // use closure
+ expr.ccodenode = get_variable_cexpression (p.name);
} else {
- // Property setters of non simple structs shall replace all occurences
- // of the "value" formal parameter with a dereferencing version of that
- // parameter.
- if (current_property_accessor != null &&
- current_property_accessor.writable &&
- current_property_accessor.value_parameter == p &&
- current_property_accessor.prop.property_type.is_real_struct_type ()) {
- expr.ccodenode = new CCodeIdentifier ("(*value)");
+ var type_as_struct = p.parameter_type.data_type as Struct;
+ if (p.direction != ParameterDirection.IN
+ || (type_as_struct != null && !type_as_struct.is_simple_type () && !p.parameter_type.nullable)) {
+ if (p.parameter_type is GenericType) {
+ expr.ccodenode = get_variable_cexpression (p.name);
+ } else {
+ expr.ccodenode = new CCodeIdentifier ("(*%s)".printf (get_variable_cname (p.name)));
+ }
} else {
- expr.ccodenode = get_variable_cexpression (p.name);
+ // Property setters of non simple structs shall replace all occurences
+ // of the "value" formal parameter with a dereferencing version of that
+ // parameter.
+ if (current_property_accessor != null &&
+ current_property_accessor.writable &&
+ current_property_accessor.value_parameter == p &&
+ current_property_accessor.prop.property_type.is_real_struct_type ()) {
+ expr.ccodenode = new CCodeIdentifier ("(*value)");
+ } else {
+ expr.ccodenode = get_variable_cexpression (p.name);
+ }
}
}
}
diff --git a/codegen/valadovaobjectmodule.vala b/codegen/valadovaobjectmodule.vala
index f6bf313..8c8edfe 100644
--- a/codegen/valadovaobjectmodule.vala
+++ b/codegen/valadovaobjectmodule.vala
@@ -1153,6 +1153,38 @@ internal class Vala.DovaObjectModule : DovaArrayModule {
var cinit = new CCodeFragment ();
function.block.prepend_statement (cinit);
+ if (m.closure) {
+ // add variables for parent closure blocks
+ // as closures only have one parameter for the innermost closure block
+ var closure_block = current_closure_block;
+ int block_id = get_block_id (closure_block);
+ while (true) {
+ var parent_closure_block = next_closure_block (closure_block.parent_symbol);
+ if (parent_closure_block == null) {
+ break;
+ }
+ int parent_block_id = get_block_id (parent_closure_block);
+
+ var parent_data = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id));
+ var cdecl = new CCodeDeclaration ("Block%dData*".printf (parent_block_id));
+ cdecl.add_declarator (new CCodeVariableDeclarator ("_data%d_".printf (parent_block_id), parent_data));
+
+ cinit.append (cdecl);
+
+ closure_block = parent_closure_block;
+ block_id = parent_block_id;
+ }
+
+ // add self variable for closures
+ // as closures have block data parameter
+ if (m.binding == MemberBinding.INSTANCE) {
+ var cself = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "this");
+ var cdecl = new CCodeDeclaration ("%s *".printf (current_class.get_cname ()));
+ cdecl.add_declarator (new CCodeVariableDeclarator ("this", cself));
+
+ cinit.append (cdecl);
+ }
+ }
foreach (FormalParameter param in m.get_parameters ()) {
if (param.ellipsis) {
break;
@@ -1462,7 +1494,11 @@ internal class Vala.DovaObjectModule : DovaArrayModule {
public override void generate_cparameters (Method m, CCodeDeclarationSpace decl_space, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, CCodeFunctionCall? vcall = null) {
CCodeFormalParameter instance_param = null;
- if (m.parent_symbol is Class && m is CreationMethod) {
+ if (m.closure) {
+ var closure_block = current_closure_block;
+ int block_id = get_block_id (closure_block);
+ instance_param = new CCodeFormalParameter ("_data%d_".printf (block_id), "Block%dData*".printf (block_id));
+ } else if (m.parent_symbol is Class && m is CreationMethod) {
if (vcall == null) {
instance_param = new CCodeFormalParameter ("this", ((Class) m.parent_symbol).get_cname () + "*");
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]