From 7a429688cdf0fd16cc1503a7666681792e309da8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=BCrg=20Billeter?= Date: Sat, 14 Aug 2010 15:24:18 +0200 Subject: [PATCH] codegen: Use builder API --- codegen/valaccodearraymodule.vala | 84 ++- codegen/valaccodeassignmentmodule.vala | 4 +- codegen/valaccodebasemodule.vala | 634 +++++++++-------------- codegen/valaccodecontrolflowmodule.vala | 295 ++++------- codegen/valaccodememberaccessmodule.vala | 12 +- codegen/valaccodemethodcallmodule.vala | 47 +- codegen/valaccodemethodmodule.vala | 345 ++++++------ codegen/valaccodestructmodule.vala | 25 +- codegen/valadovaarraymodule.vala | 2 +- codegen/valadovaassignmentmodule.vala | 4 +- codegen/valadovabasemodule.vala | 409 ++++----------- codegen/valadovacontrolflowmodule.vala | 54 +- codegen/valadovaerrormodule.vala | 153 ++---- codegen/valadovamemberaccessmodule.vala | 2 +- codegen/valadovamethodcallmodule.vala | 10 +- codegen/valadovaobjectmodule.vala | 142 ++--- codegen/valadovastructmodule.vala | 5 - codegen/valadovavaluemodule.vala | 17 +- codegen/valagasyncmodule.vala | 221 ++++---- codegen/valagerrormodule.vala | 187 +++---- codegen/valagobjectmodule.vala | 94 ++-- codegen/valagsignalmodule.vala | 6 +- codegen/valagtypemodule.vala | 372 +++++++------ vala/valablock.vala | 4 + vala/valaexpression.vala | 17 +- vala/valamethod.vala | 2 + vala/valamethodcall.vala | 1 + vala/valayieldstatement.vala | 2 + 28 files changed, 1268 insertions(+), 1882 deletions(-) diff --git a/codegen/valaccodearraymodule.vala b/codegen/valaccodearraymodule.vala index 1a5f239e2..6db8f301f 100644 --- a/codegen/valaccodearraymodule.vala +++ b/codegen/valaccodearraymodule.vala @@ -48,7 +48,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { var name_cnode = get_variable_cexpression (temp_var.name); int i = 0; - temp_vars.add (temp_var); + emit_temp_var (temp_var); append_initializer_list (ce, name_cnode, expr.initializer_list, expr.rank, ref i); @@ -80,7 +80,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { var name_cnode = get_variable_cexpression (temp_var.name); size.ccodenode = name_cnode; - temp_vars.add (temp_var); + emit_temp_var (temp_var); csize = new CCodeAssignment (name_cnode, csize); } @@ -112,7 +112,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { var name_cnode = get_variable_cexpression (temp_var.name); int i = 0; - temp_vars.add (temp_var); + emit_temp_var (temp_var); ce.append_expression (new CCodeAssignment (name_cnode, gnew)); @@ -428,15 +428,15 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { var len_var = get_temp_variable (int_type); len_var.source_reference = expr.source_reference; - temp_vars.add (len_var); + emit_temp_var (len_var); var slice_var = get_temp_variable (expr.value_type, true, expr); - temp_vars.add (slice_var); + emit_temp_var (slice_var); if (!is_pure_ccode_expression (cstart)) { // avoid double evaluation of start var start_var = get_temp_variable (int_type); - temp_vars.add (start_var); + emit_temp_var (start_var); var start_assignment = new CCodeAssignment (get_variable_cexpression (start_var.name), cstart); ccomma.append_expression (start_assignment); @@ -674,7 +674,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { } var decl = get_temp_variable (expression_type, false, node); - temp_vars.add (decl); + emit_temp_var (decl); var ctemp = get_variable_cexpression (decl.name); @@ -752,14 +752,11 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { // definition - var block = new CCodeBlock (); + push_context (new EmitContext ()); + push_function (function); if (requires_copy (array_type.element_type)) { - push_context (new EmitContext ()); - - var cdecl = new CCodeDeclaration (array_type.get_cname ()); var cvardecl = new CCodeVariableDeclarator ("result"); - cdecl.add_declarator (cvardecl); var gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0")); gnew.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ())); @@ -770,28 +767,19 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { } gnew.add_argument (length_expr); - cvardecl.initializer = gnew; - block.add_statement (cdecl); - - var idx_decl = new CCodeDeclaration ("int"); - idx_decl.add_declarator (new CCodeVariableDeclarator ("i")); - block.add_statement (idx_decl); - - var loop_body = new CCodeBlock (); - loop_body.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("result"), new CCodeIdentifier ("i")), get_ref_cexpression (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), null, array_type)))); + ccode.add_declaration (array_type.get_cname (), cvardecl); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("result"), gnew)); - var cfor = new CCodeForStatement (new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("length")), loop_body); - cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0"))); - cfor.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i"))); - block.add_statement (cfor); + ccode.add_declaration ("int", new CCodeVariableDeclarator ("i")); - block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result"))); + ccode.open_for (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")), + new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("length")), + new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i"))); - var cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - block.add_statement (cfrag); + ccode.add_expression (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("result"), new CCodeIdentifier ("i")), get_ref_cexpression (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), null, array_type))); + ccode.close (); - pop_context (); + ccode.add_return (new CCodeIdentifier ("result")); } else { var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup")); dup_call.add_argument (new CCodeIdentifier ("self")); @@ -800,16 +788,16 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ())); dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeIdentifier ("length"), sizeof_call)); - block.add_statement (new CCodeReturnStatement (dup_call)); + ccode.add_return (dup_call); } // append to file cfile.add_function_declaration (function); - - function.block = block; cfile.add_function (function); + pop_context (); + return dup_func; } @@ -831,28 +819,18 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { // definition - var block = new CCodeBlock (); + push_context (new EmitContext ()); + push_function (function); if (requires_copy (array_type.element_type)) { - push_context (new EmitContext ()); - - var idx_decl = new CCodeDeclaration ("int"); - idx_decl.add_declarator (new CCodeVariableDeclarator ("i")); - block.add_statement (idx_decl); - - var loop_body = new CCodeBlock (); - loop_body.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("dest"), new CCodeIdentifier ("i")), get_ref_cexpression (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), null, array_type)))); + ccode.add_declaration ("int", new CCodeVariableDeclarator ("i")); - var cfor = new CCodeForStatement (new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeConstant ("%d".printf (array_type.length))), loop_body); - cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0"))); - cfor.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i"))); - block.add_statement (cfor); + ccode.open_for (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")), + new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeConstant ("%d".printf (array_type.length))), + new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i"))); - var cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - block.add_statement (cfrag); - pop_context (); + ccode.add_expression (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("dest"), new CCodeIdentifier ("i")), get_ref_cexpression (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), null, array_type))); } else { cfile.add_include ("string.h"); @@ -864,16 +842,16 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule { sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ())); dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("%d".printf (array_type.length)), sizeof_call)); - block.add_statement (new CCodeExpressionStatement (dup_call)); + ccode.add_expression (dup_call); } // append to file cfile.add_function_declaration (function); - - function.block = block; cfile.add_function (function); + pop_context (); + return dup_func; } diff --git a/codegen/valaccodeassignmentmodule.vala b/codegen/valaccodeassignmentmodule.vala index 20ed40923..a403ada79 100644 --- a/codegen/valaccodeassignmentmodule.vala +++ b/codegen/valaccodeassignmentmodule.vala @@ -126,13 +126,13 @@ public class Vala.CCodeAssignmentModule : CCodeMemberAccessModule { var lhs_value_type = assignment.left.value_type.copy (); string lhs_temp_name = "_tmp%d_".printf (next_temp_var_id++); var lhs_temp = new LocalVariable (lhs_value_type, "*" + lhs_temp_name); - temp_vars.add (lhs_temp); + emit_temp_var (lhs_temp); outer_ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (lhs_temp_name), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, lhs))); lhs = new CCodeParenthesizedExpression (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (lhs_temp_name))); } var temp_decl = get_temp_variable (assignment.left.value_type, true, null, false); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_decl.name), rhs)); if (unref_old) { /* unref old value */ diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index c23ebe29f..4015c00e3 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -31,8 +31,8 @@ public class Vala.CCodeBaseModule : CodeGenerator { public Symbol? current_symbol; public ArrayList symbol_stack = new ArrayList (); public TryStatement current_try; - public CCodeSwitchStatement state_switch_statement; - public ArrayList temp_vars = new ArrayList (); + public CCodeFunction ccode; + public ArrayList ccode_stack = new ArrayList (); public ArrayList temp_ref_vars = new ArrayList (); public int next_temp_var_id; public bool current_method_inner_error; @@ -152,30 +152,19 @@ public class Vala.CCodeBaseModule : CodeGenerator { public CCodeFile internal_header_file; public CCodeFile cfile; - public CCodeFragment class_init_fragment; - public CCodeFragment base_init_fragment; - public CCodeFragment class_finalize_fragment; - public CCodeFragment base_finalize_fragment; - public CCodeFragment instance_init_fragment; - public CCodeFragment instance_finalize_fragment; + public EmitContext class_init_context; + public EmitContext base_init_context; + public EmitContext class_finalize_context; + public EmitContext base_finalize_context; + public EmitContext instance_init_context; + public EmitContext instance_finalize_context; public CCodeStruct param_spec_struct; public CCodeStruct closure_struct; public CCodeEnum prop_enum; - public CCodeFunction function; - // code nodes to be inserted before the current statement - // used by async method calls in coroutines - public CCodeFragment pre_statement_fragment; + public CCodeFunction ccode { get { return emit_context.ccode; } } - // case statements to be inserted for the couroutine state - public CCodeSwitchStatement state_switch_statement { - get { return emit_context.state_switch_statement; } - set { emit_context.state_switch_statement = value; } - } - - /* all temporary variables */ - public ArrayList temp_vars { get { return emit_context.temp_vars; } } /* temporary variables that own their content */ public ArrayList temp_ref_vars { get { return emit_context.temp_ref_vars; } } /* cache to check whether a certain marshaller has been created yet */ @@ -483,6 +472,16 @@ public class Vala.CCodeBaseModule : CodeGenerator { } } + public void push_function (CCodeFunction func) { + emit_context.ccode_stack.add (ccode); + emit_context.ccode = func; + } + + public void pop_function () { + emit_context.ccode = emit_context.ccode_stack[emit_context.ccode_stack.size - 1]; + emit_context.ccode_stack.remove_at (emit_context.ccode_stack.size - 1); + } + public bool add_symbol_declaration (CCodeFile decl_space, Symbol sym, string name) { if (decl_space.add_declaration (name)) { return true; @@ -726,13 +725,13 @@ public class Vala.CCodeBaseModule : CodeGenerator { /* stuff meant for all lockable members */ if (m is Lockable && ((Lockable) m).get_lock_used ()) { CCodeExpression l = new CCodeIdentifier ("self"); - CCodeFragment init_fragment = class_init_fragment; - CCodeFragment finalize_fragment = class_finalize_fragment; + var init_context = class_init_context; + var finalize_context = class_finalize_context; if (m.is_instance_member ()) { l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (m.name)); - init_fragment = instance_init_fragment; - finalize_fragment = instance_finalize_fragment; + init_context = instance_init_context; + finalize_context = instance_finalize_context; } else if (m.is_class_member ()) { TypeSymbol parent = (TypeSymbol)m.parent_symbol; @@ -743,14 +742,18 @@ public class Vala.CCodeBaseModule : CodeGenerator { l = new CCodeIdentifier (get_symbol_lock_name ("%s_%s".printf(m.parent_symbol.get_lower_case_cname (), m.name))); } + push_context (init_context); var initf = new CCodeFunctionCall (new CCodeIdentifier (mutex_type.default_construction_method.get_cname ())); initf.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l)); - init_fragment.append (new CCodeExpressionStatement (initf)); + ccode.add_expression (initf); + pop_context (); - if (finalize_fragment != null) { + if (finalize_context != null) { + push_context (finalize_context); var fc = new CCodeFunctionCall (new CCodeIdentifier ("g_static_rec_mutex_free")); fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l)); - finalize_fragment.append (new CCodeExpressionStatement (fc)); + ccode.add_expression (fc); + pop_context (); } } } @@ -894,10 +897,6 @@ public class Vala.CCodeBaseModule : CodeGenerator { check_type (f.variable_type); - if (f.initializer != null) { - f.initializer.emit (this); - } - var cl = f.parent_symbol as Class; bool is_gtypeinstance = (cl != null && !cl.is_compact); @@ -916,9 +915,13 @@ public class Vala.CCodeBaseModule : CodeGenerator { } if (f.initializer != null) { + push_context (instance_init_context); + + f.initializer.emit (this); + var rhs = (CCodeExpression) f.initializer.ccodenode; - instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs))); + ccode.add_expression (new CCodeAssignment (lhs, rhs)); if (f.variable_type is ArrayType && !f.no_array_length && f.initializer is ArrayCreationExpression) { @@ -933,30 +936,31 @@ public class Vala.CCodeBaseModule : CodeGenerator { for (int dim = 1; dim <= array_type.rank; dim++) { var array_len_lhs = get_array_length_cexpression (ma, dim); var size = sizes[dim - 1]; - instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (array_len_lhs, (CCodeExpression) size.ccodenode))); + ccode.add_expression (new CCodeAssignment (array_len_lhs, (CCodeExpression) size.ccodenode)); } if (array_type.rank == 1 && f.is_internal_symbol ()) { var lhs_array_size = get_array_size_cexpression (ma); var rhs_array_len = get_array_length_cexpression (ma, 1); - instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs_array_size, rhs_array_len))); + ccode.add_expression (new CCodeAssignment (lhs_array_size, rhs_array_len)); } } - append_temp_decl (instance_init_fragment, temp_vars); - foreach (LocalVariable local in temp_ref_vars) { var ma = new MemberAccess.simple (local.name); ma.symbol_reference = local; ma.value_type = local.variable_type.copy (); - instance_init_fragment.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma))); + ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)); } - temp_vars.clear (); temp_ref_vars.clear (); + + pop_context (); } - if (requires_destroy (f.variable_type) && instance_finalize_fragment != null) { + if (requires_destroy (f.variable_type) && instance_finalize_context != null) { + push_context (instance_finalize_context); + var this_access = new MemberAccess.simple ("this"); this_access.value_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol); @@ -970,7 +974,9 @@ public class Vala.CCodeBaseModule : CodeGenerator { var ma = new MemberAccess (this_access, f.name); ma.symbol_reference = f; ma.value_type = f.variable_type.copy (); - instance_finalize_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.variable_type, ma))); + ccode.add_expression (get_unref_expression (lhs, f.variable_type, ma)); + + pop_context (); } } else if (f.binding == MemberBinding.CLASS) { if (!is_gtypeinstance) { @@ -988,21 +994,24 @@ public class Vala.CCodeBaseModule : CodeGenerator { } if (f.initializer != null) { - var rhs = (CCodeExpression) f.initializer.ccodenode; + push_context (class_init_context); + + f.initializer.emit (this); - class_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs))); + var rhs = (CCodeExpression) f.initializer.ccodenode; - append_temp_decl (class_init_fragment, temp_vars); + ccode.add_expression (new CCodeAssignment (lhs, rhs)); foreach (LocalVariable local in temp_ref_vars) { var ma = new MemberAccess.simple (local.name); ma.symbol_reference = local; ma.value_type = local.variable_type.copy (); - class_init_fragment.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma))); + ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)); } - temp_vars.clear (); temp_ref_vars.clear (); + + pop_context (); } } else { generate_field_declaration (f, cfile); @@ -1019,7 +1028,15 @@ public class Vala.CCodeBaseModule : CodeGenerator { var var_decl = new CCodeVariableDeclarator (f.get_cname (), null, f.variable_type.get_cdeclarator_suffix ()); var_decl.initializer = default_value_for_type (f.variable_type, true); + if (class_init_context != null) { + push_context (class_init_context); + } else { + push_context (new EmitContext ()); + } + if (f.initializer != null) { + f.initializer.emit (this); + var init = (CCodeExpression) f.initializer.ccodenode; if (is_constant_ccode_expression (init)) { var_decl.initializer = init; @@ -1095,23 +1112,18 @@ public class Vala.CCodeBaseModule : CodeGenerator { if (!is_constant_ccode_expression (rhs)) { if (f.parent_symbol is Class) { if (f.initializer is InitializerList) { - var block = new CCodeBlock (); - var frag = new CCodeFragment (); + ccode.open_block (); var temp_decl = get_temp_variable (f.variable_type); - var cdecl = new CCodeDeclaration (temp_decl.variable_type.get_cname ()); - var vardecl = new CCodeVariableDeclarator (temp_decl.name, rhs); - cdecl.add_declarator (vardecl); - vardecl.init0 = true; - frag.append (cdecl); + var vardecl = new CCodeVariableDeclarator.zero (temp_decl.name, rhs); + ccode.add_declaration (temp_decl.variable_type.get_cname (), vardecl); var tmp = get_variable_cexpression (get_variable_cname (temp_decl.name)); - frag.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, tmp))); + ccode.add_expression (new CCodeAssignment (lhs, tmp)); - block.add_statement (frag); - class_init_fragment.append (block); + ccode.close (); } else { - class_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs))); + ccode.add_expression (new CCodeAssignment (lhs, rhs)); } if (f.variable_type is ArrayType && !f.no_array_length && @@ -1124,12 +1136,9 @@ public class Vala.CCodeBaseModule : CodeGenerator { for (int dim = 1; dim <= array_type.rank; dim++) { var array_len_lhs = get_array_length_cexpression (ma, dim); var size = sizes[dim - 1]; - class_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (array_len_lhs, (CCodeExpression) size.ccodenode))); + ccode.add_expression (new CCodeAssignment (array_len_lhs, (CCodeExpression) size.ccodenode)); } } - - append_temp_decl (class_init_fragment, temp_vars); - temp_vars.clear (); } else { f.error = true; Report.error (f.source_reference, "Non-constant field initializers not supported in this context"); @@ -1137,6 +1146,8 @@ public class Vala.CCodeBaseModule : CodeGenerator { } } } + + pop_context (); } } @@ -1275,6 +1286,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { } generate_type_declaration (acc.value_type, decl_space); + CCodeFunction function; if (acc.readable && !returns_real_struct) { function = new CCodeFunction (acc.get_cname (), acc.value_type.get_cname ()); } else { @@ -1531,46 +1543,34 @@ public class Vala.CCodeBaseModule : CodeGenerator { } } - var init_fragment = new CCodeFragment (); + push_function (function); if (prop.binding == MemberBinding.INSTANCE && !is_virtual) { - CCodeStatement check_stmt; if (!acc.readable || returns_real_struct) { - check_stmt = create_property_type_check_statement (prop, false, t, true, "self"); + create_property_type_check_statement (prop, false, t, true, "self"); } else { - check_stmt = create_property_type_check_statement (prop, true, t, true, "self"); - } - if (check_stmt != null) { - init_fragment.append (check_stmt); + create_property_type_check_statement (prop, true, t, true, "self"); } } + if (current_method_inner_error) { + ccode.add_declaration ("GError *", new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL"))); + } + if (acc.readable && !returns_real_struct) { // do not declare result variable if exit block is known to be unreachable if (acc.return_block == null || acc.return_block.get_predecessors ().size > 0) { - var cdecl = new CCodeDeclaration (acc.value_type.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator ("result")); - init_fragment.append (cdecl); + ccode.add_declaration (acc.value_type.get_cname (), new CCodeVariableDeclarator ("result")); } } if (is_virtual) { - var cdecl = new CCodeDeclaration (this_type.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator ("self", transform_expression (new CCodeIdentifier ("base"), base_type, this_type))); - init_fragment.append (cdecl); + ccode.add_declaration (this_type.get_cname (), new CCodeVariableDeclarator ("self")); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), transform_expression (new CCodeIdentifier ("base"), base_type, this_type))); } acc.body.emit (this); - function.block = (CCodeBlock) acc.body.ccodenode; - function.block.prepend_statement (init_fragment); - - if (current_method_inner_error) { - var cdecl = new CCodeDeclaration ("GError *"); - cdecl.add_declarator (new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL"))); - function.block.add_statement (cdecl); - } - // notify on property changes if (is_gobject_property (prop) && prop.notify && @@ -1578,7 +1578,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var notify_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_notify")); notify_call.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *")); notify_call.add_argument (prop.get_canonical_cconstant ()); - function.block.add_statement (new CCodeExpressionStatement (notify_call)); + ccode.add_expression (notify_call); } cfile.add_function (function); @@ -1588,30 +1588,11 @@ public class Vala.CCodeBaseModule : CodeGenerator { } public override void visit_destructor (Destructor d) { - bool old_method_inner_error = current_method_inner_error; - current_method_inner_error = false; - - d.body.emit (this); - if (d.binding == MemberBinding.STATIC && !in_plugin) { Report.error (d.source_reference, "static destructors are only supported for dynamic types"); d.error = true; return; } - - CCodeFragment cfrag = new CCodeFragment (); - - if (current_method_inner_error) { - var cdecl = new CCodeDeclaration ("GError *"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_inner_error_", new CCodeConstant ("NULL"))); - cfrag.append (cdecl); - } - - cfrag.append (d.body.ccodenode); - - d.ccodenode = cfrag; - - current_method_inner_error = old_method_inner_error; } public int get_block_id (Block b) { @@ -1623,7 +1604,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { return result; } - void capture_parameter (FormalParameter param, CCodeStruct data, CCodeBlock cblock, int block_id, CCodeBlock free_block) { + void capture_parameter (FormalParameter param, CCodeStruct data, int block_id, CCodeBlock free_block) { generate_type_declaration (param.variable_type, cfile); var param_type = param.variable_type.copy (); @@ -1647,20 +1628,20 @@ public class Vala.CCodeBaseModule : CodeGenerator { 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))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_variable_cname (param.name)), cparam)); if (param.variable_type is ArrayType) { var array_type = (ArrayType) param.variable_type; for (int dim = 1; dim <= array_type.rank; dim++) { data.add_field ("gint", get_array_length_cname (get_variable_cname (param.name), dim)); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_array_length_cname (get_variable_cname (param.name), dim)), new CCodeIdentifier (get_array_length_cname (get_variable_cname (param.name), dim))))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_array_length_cname (get_variable_cname (param.name), dim)), new CCodeIdentifier (get_array_length_cname (get_variable_cname (param.name), dim)))); } } else if (param.variable_type is DelegateType) { data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (param.name))); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name)))))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name))))); if (param.variable_type.value_owned) { data.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)))))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))))); } } @@ -1685,16 +1666,11 @@ public class Vala.CCodeBaseModule : CodeGenerator { public override void visit_block (Block b) { emit_context.push_symbol (b); - foreach (Statement stmt in b.get_statements ()) { - stmt.emit (this); - } - var local_vars = b.get_local_variables (); - foreach (LocalVariable local in local_vars) { - local.active = false; + + if (b.parent_node is Block || b.parent_node is SwitchStatement) { + ccode.open_block (); } - - var cblock = new CCodeBlock (); if (b.captured) { var parent_block = next_closure_block (b.parent_symbol); @@ -1770,15 +1746,13 @@ public class Vala.CCodeBaseModule : CodeGenerator { if (current_method != null && current_method.coroutine) { closure_struct.add_field (struct_name + "*", "_data%d_".printf (block_id)); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression ("_data%d_".printf (block_id)), data_alloc))); } else { - 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); + ccode.add_declaration (struct_name + "*", new CCodeVariableDeclarator ("_data%d_".printf (block_id))); } + ccode.add_expression (new CCodeAssignment (get_variable_cexpression ("_data%d_".printf (block_id)), data_alloc)); // initialize ref_count - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_ref_count_"), new CCodeIdentifier ("1")))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_ref_count_"), new CCodeIdentifier ("1"))); if (parent_block != null) { int parent_block_id = get_block_id (parent_block); @@ -1786,14 +1760,14 @@ public class Vala.CCodeBaseModule : CodeGenerator { var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_ref".printf (parent_block_id))); 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))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)), ref_call)); } else if (in_constructor || (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 (get_result_cexpression ("self")); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "self"), ref_call))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "self"), ref_call)); } if (b.parent_symbol is Method) { @@ -1802,7 +1776,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { // 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); + capture_parameter (param, data, block_id, free_block); } } @@ -1812,24 +1786,14 @@ public class Vala.CCodeBaseModule : CodeGenerator { // async method is suspended while waiting for callback, // so we never need to care about memory management of async data - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_async_data_"), new CCodeIdentifier ("data")))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_async_data_"), new CCodeIdentifier ("data"))); } - - 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); + capture_parameter (acc.value_parameter, data, 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)); @@ -1867,28 +1831,19 @@ public class Vala.CCodeBaseModule : CodeGenerator { cfile.add_function (unref_fun); } - foreach (CodeNode stmt in b.get_statements ()) { - if (stmt.error || stmt.unreachable) { - continue; - } - - if (stmt.ccodenode is CCodeFragment) { - foreach (CCodeNode cstmt in ((CCodeFragment) stmt.ccodenode).get_children ()) { - cblock.add_statement (cstmt); - } - } else { - cblock.add_statement (stmt.ccodenode); - } + foreach (Statement stmt in b.get_statements ()) { + stmt.emit (this); } // free in reverse order for (int i = local_vars.size - 1; i >= 0; i--) { var local = local_vars[i]; + local.active = false; if (!local.unreachable && !local.floating && !local.captured && requires_destroy (local.variable_type)) { var ma = new MemberAccess.simple (local.name); ma.symbol_reference = local; ma.value_type = local.variable_type.copy (); - cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma))); + ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)); } } @@ -1899,7 +1854,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var ma = new MemberAccess.simple (param.name); ma.symbol_reference = param; ma.value_type = param.variable_type.copy (); - cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma))); + ccode.add_expression (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma)); } } } @@ -1909,30 +1864,18 @@ public class Vala.CCodeBaseModule : CodeGenerator { var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (block_id))); data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id))); - cblock.add_statement (new CCodeExpressionStatement (data_unref)); + ccode.add_expression (data_unref); } - b.ccodenode = cblock; + if (b.parent_node is Block || b.parent_node is SwitchStatement) { + ccode.close (); + } emit_context.pop_symbol (); } - public override void visit_empty_statement (EmptyStatement stmt) { - stmt.ccodenode = new CCodeEmptyStatement (); - } - public override void visit_declaration_statement (DeclarationStatement stmt) { stmt.declaration.accept (this); - - stmt.ccodenode = stmt.declaration.ccodenode; - - var local = stmt.declaration as LocalVariable; - if (local != null && local.initializer != null) { - create_temp_decl (stmt, local.initializer.temp_vars); - } - - create_temp_decl (stmt, temp_vars); - temp_vars.clear (); } public CCodeExpression get_variable_cexpression (string name) { @@ -1999,12 +1942,12 @@ public class Vala.CCodeBaseModule : CodeGenerator { if (!array_type.fixed_length) { for (int dim = 1; dim <= array_type.rank; dim++) { var len_var = new LocalVariable (int_type.copy (), get_array_length_cname (get_variable_cname (local.name), dim)); - temp_vars.add (len_var); + emit_temp_var (len_var); } if (array_type.rank == 1) { var size_var = new LocalVariable (int_type.copy (), get_array_size_cname (get_variable_cname (local.name))); - temp_vars.add (size_var); + emit_temp_var (size_var); } } } else if (local.variable_type is DelegateType) { @@ -2013,10 +1956,10 @@ public class Vala.CCodeBaseModule : CodeGenerator { if (d.has_target) { // create variable to store delegate target var target_var = new LocalVariable (new PointerType (new VoidType ()), get_delegate_target_cname (get_variable_cname (local.name))); - temp_vars.add (target_var); + emit_temp_var (target_var); if (deleg_type.value_owned) { var target_destroy_notify_var = new LocalVariable (new DelegateType ((Delegate) context.root.scope.lookup ("GLib").scope.lookup ("DestroyNotify")), get_delegate_target_destroy_notify_cname (get_variable_cname (local.name))); - temp_vars.add (target_destroy_notify_var); + emit_temp_var (target_destroy_notify_var); } } } @@ -2039,7 +1982,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (local.variable_type, true, local, false); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), rhs)); for (int dim = 1; dim <= array_type.rank; dim++) { @@ -2064,7 +2007,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (local.variable_type, true, local, false); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), rhs)); CCodeExpression lhs_delegate_target_destroy_notify; @@ -2113,19 +2056,12 @@ public class Vala.CCodeBaseModule : CodeGenerator { } } - var cfrag = new CCodeFragment (); - - if (pre_statement_fragment != null) { - cfrag.append (pre_statement_fragment); - pre_statement_fragment = null; - } - if (local.captured) { if (local.initializer != null) { if (has_simple_struct_initializer (local)) { - cfrag.append (new CCodeExpressionStatement (rhs)); + ccode.add_expression (rhs); } else { - 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))); + ccode.add_expression (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 if (current_method != null && current_method.coroutine) { @@ -2133,15 +2069,15 @@ public class Vala.CCodeBaseModule : CodeGenerator { if (local.initializer != null) { if (has_simple_struct_initializer (local)) { - cfrag.append (new CCodeExpressionStatement (rhs)); + ccode.add_expression (rhs); } else { - cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (local.name)), rhs))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (local.name)), rhs)); } } } else { - CCodeStatement post_stmt = null; + CCodeExpression post_rhs = null; if (has_simple_struct_initializer (local)) { - post_stmt = new CCodeExpressionStatement (rhs); + post_rhs = rhs; rhs = null; } @@ -2150,10 +2086,6 @@ public class Vala.CCodeBaseModule : CodeGenerator { cvar.line = rhs.line; } - 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) { @@ -2161,8 +2093,15 @@ public class Vala.CCodeBaseModule : CodeGenerator { cvar.init0 = true; } - if (post_stmt != null) { - cfrag.append (post_stmt); + ccode.add_declaration (local.variable_type.get_cname (), cvar); + + if (cvar.initializer != null && !cvar.init0) { + cvar.initializer = null; + ccode.add_expression (new CCodeAssignment (get_variable_cexpression (local.name), rhs)); + } + + if (post_rhs != null) { + ccode.add_expression (post_rhs); } } @@ -2182,16 +2121,14 @@ public class Vala.CCodeBaseModule : CodeGenerator { ccopy.add_argument (get_variable_cexpression (local.name)); ccopy.add_argument ((CCodeExpression) local.initializer.ccodenode); ccopy.add_argument (size); - cfrag.append (new CCodeExpressionStatement (ccopy)); + ccode.add_expression (ccopy); } } if (local.initializer != null && local.initializer.tree_can_fail) { - add_simple_check (local.initializer, cfrag); + add_simple_check (local.initializer); } - local.ccodenode = cfrag; - local.active = true; } @@ -2229,7 +2166,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { } else { // used as expression var temp_decl = get_temp_variable (list.target_type, false, list); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); var instance = get_variable_cexpression (get_variable_cname (temp_decl.name)); @@ -3055,25 +2992,6 @@ public class Vala.CCodeBaseModule : CodeGenerator { * we unref temporary variables at the end of a full * expression */ - - /* can't automatically deep copy lists yet, so do it - * manually for now - * replace with - * expr.temp_vars = temp_vars; - * when deep list copying works - */ - if (temp_vars.size > 0) { - if (expr.temp_vars == null) { - expr.temp_vars = new ArrayList (); - } else { - expr.temp_vars.clear (); - } - foreach (LocalVariable local in temp_vars) { - expr.add_temp_var (local); - } - temp_vars.clear (); - } - if (((List) temp_ref_vars).size == 0) { /* nothing to do without temporary variables */ return; @@ -3093,7 +3011,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { } full_expr_var = get_temp_variable (expr_type, true, expr, false); - expr.add_temp_var (full_expr_var); + emit_temp_var (full_expr_var); expr_list.append_expression (new CCodeAssignment (get_variable_cexpression (full_expr_var.name), (CCodeExpression) expr.ccodenode)); } @@ -3114,65 +3032,57 @@ public class Vala.CCodeBaseModule : CodeGenerator { temp_ref_vars.clear (); } - public void append_temp_decl (CCodeFragment cfrag, List? temp_vars) { - if (temp_vars == null) { - return; - } - foreach (LocalVariable local in temp_vars) { - var cdecl = new CCodeDeclaration (local.variable_type.get_cname ()); - - var vardecl = new CCodeVariableDeclarator (local.name, null, local.variable_type.get_cdeclarator_suffix ()); - // sets #line - local.ccodenode = vardecl; - cdecl.add_declarator (vardecl); - - var st = local.variable_type.data_type as Struct; - var array_type = local.variable_type as ArrayType; - - if (local.name.has_prefix ("*")) { - // do not dereference unintialized variable - // initialization is not needed for these special - // pointer temp variables - // used to avoid side-effects in assignments - } else if (local.no_init) { - // no initialization necessary for this temp var - } else if (!local.variable_type.nullable && - (st != null && !st.is_simple_type ()) || - (array_type != null && array_type.fixed_length)) { - // 0-initialize struct with struct initializer { 0 } - // necessary as they will be passed by reference - var clist = new CCodeInitializerList (); - clist.append (new CCodeConstant ("0")); + public void emit_temp_var (LocalVariable local) { + var vardecl = new CCodeVariableDeclarator (local.name, null, local.variable_type.get_cdeclarator_suffix ()); + // sets #line + local.ccodenode = vardecl; - vardecl.initializer = clist; - vardecl.init0 = true; - } else if (local.variable_type.is_reference_type_or_type_parameter () || - local.variable_type.nullable || - local.variable_type is DelegateType) { - vardecl.initializer = new CCodeConstant ("NULL"); - vardecl.init0 = true; - } + var st = local.variable_type.data_type as Struct; + var array_type = local.variable_type as ArrayType; + + if (local.name.has_prefix ("*")) { + // do not dereference unintialized variable + // initialization is not needed for these special + // pointer temp variables + // used to avoid side-effects in assignments + } else if (local.no_init) { + // no initialization necessary for this temp var + } else if (!local.variable_type.nullable && + (st != null && !st.is_simple_type ()) || + (array_type != null && array_type.fixed_length)) { + // 0-initialize struct with struct initializer { 0 } + // necessary as they will be passed by reference + var clist = new CCodeInitializerList (); + clist.append (new CCodeConstant ("0")); - if (current_method != null && current_method.coroutine) { - closure_struct.add_field (local.variable_type.get_cname (), local.name); + vardecl.initializer = clist; + vardecl.init0 = true; + } else if (local.variable_type.is_reference_type_or_type_parameter () || + local.variable_type.nullable || + local.variable_type is DelegateType) { + vardecl.initializer = new CCodeConstant ("NULL"); + vardecl.init0 = true; + } - // even though closure struct is zerod, we need to initialize temporary variables - // as they might be used multiple times when declared in a loop + if (current_method != null && current_method.coroutine) { + closure_struct.add_field (local.variable_type.get_cname (), local.name); - if (vardecl.initializer is CCodeInitializerList) { - // C does not support initializer lists in assignments, use memset instead - cfile.add_include ("string.h"); - var memset_call = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - memset_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (local.name))); - memset_call.add_argument (new CCodeConstant ("0")); - memset_call.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (local.variable_type.get_cname ()))); - cfrag.append (new CCodeExpressionStatement (memset_call)); - } else if (vardecl.initializer != null) { - cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (local.name), vardecl.initializer))); - } - } else { - cfrag.append (cdecl); + // even though closure struct is zerod, we need to initialize temporary variables + // as they might be used multiple times when declared in a loop + + if (vardecl.initializer is CCodeInitializerList) { + // C does not support initializer lists in assignments, use memset instead + cfile.add_include ("string.h"); + var memset_call = new CCodeFunctionCall (new CCodeIdentifier ("memset")); + memset_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (local.name))); + memset_call.add_argument (new CCodeConstant ("0")); + memset_call.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (local.variable_type.get_cname ()))); + ccode.add_expression (memset_call); + } else if (vardecl.initializer != null) { + ccode.add_expression (new CCodeAssignment (get_variable_cexpression (local.name), vardecl.initializer)); } + } else { + ccode.add_declaration (local.variable_type.get_cname (), vardecl); } } @@ -3182,62 +3092,26 @@ public class Vala.CCodeBaseModule : CodeGenerator { return; } - stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.expression.ccodenode); + ccode.add_expression ((CCodeExpression) stmt.expression.ccodenode); /* free temporary objects and handle errors */ - if (((List) temp_vars).size == 0 - && pre_statement_fragment == null - && (!stmt.tree_can_fail || !stmt.expression.tree_can_fail)) { - /* nothing to do without temporary variables and errors */ - return; - } - - var cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - - if (pre_statement_fragment != null) { - cfrag.append (pre_statement_fragment); - pre_statement_fragment = null; - } - - cfrag.append (stmt.ccodenode); - foreach (LocalVariable local in temp_ref_vars) { var ma = new MemberAccess.simple (local.name); ma.symbol_reference = local; ma.value_type = local.variable_type.copy (); - cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma))); + ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)); } if (stmt.tree_can_fail && stmt.expression.tree_can_fail) { // simple case, no node breakdown necessary - add_simple_check (stmt.expression, cfrag); + add_simple_check (stmt.expression); } - stmt.ccodenode = cfrag; - - temp_vars.clear (); temp_ref_vars.clear (); } - - public void create_temp_decl (Statement stmt, List? temp_vars) { - /* declare temporary variables */ - - if (temp_vars == null || temp_vars.size == 0) { - /* nothing to do without temporary variables */ - return; - } - - var cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - - cfrag.append (stmt.ccodenode); - - stmt.ccodenode = cfrag; - } - public virtual void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop = false) { + public virtual void append_local_free (Symbol sym, bool stop_at_loop = false) { var b = (Block) sym; var local_vars = b.get_local_variables (); @@ -3248,7 +3122,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var ma = new MemberAccess.simple (local.name); ma.symbol_reference = local; ma.value_type = local.variable_type.copy (); - cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma))); + ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)); } } @@ -3257,7 +3131,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (block_id))); data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id))); - cfrag.append (new CCodeExpressionStatement (data_unref)); + ccode.add_expression (data_unref); } if (stop_at_loop) { @@ -3269,13 +3143,13 @@ public class Vala.CCodeBaseModule : CodeGenerator { } if (sym.parent_symbol is Block) { - append_local_free (sym.parent_symbol, cfrag, stop_at_loop); + append_local_free (sym.parent_symbol, stop_at_loop); } else if (sym.parent_symbol is Method) { - append_param_free ((Method) sym.parent_symbol, cfrag); + append_param_free ((Method) sym.parent_symbol); } } - public void append_error_free (Symbol sym, CCodeFragment cfrag, TryStatement current_try) { + public void append_error_free (Symbol sym, TryStatement current_try) { var b = (Block) sym; var local_vars = b.get_local_variables (); @@ -3285,7 +3159,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { if (!local.unreachable && 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))); + ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)); } } @@ -3294,7 +3168,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (block_id))); data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id))); - cfrag.append (new CCodeExpressionStatement (data_unref)); + ccode.add_expression (data_unref); } if (sym == current_try.body) { @@ -3302,32 +3176,23 @@ public class Vala.CCodeBaseModule : CodeGenerator { } if (sym.parent_symbol is Block) { - append_error_free (sym.parent_symbol, cfrag, current_try); + append_error_free (sym.parent_symbol, current_try); } else if (sym.parent_symbol is Method) { - append_param_free ((Method) sym.parent_symbol, cfrag); + append_param_free ((Method) sym.parent_symbol); } } - private void append_param_free (Method m, CCodeFragment cfrag) { + private void append_param_free (Method m) { foreach (FormalParameter param in m.get_parameters ()) { if (!param.ellipsis && requires_destroy (param.variable_type) && param.direction == ParameterDirection.IN) { var ma = new MemberAccess.simple (param.name); ma.symbol_reference = param; ma.value_type = param.variable_type.copy (); - cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma))); + ccode.add_expression (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma)); } } } - public void create_local_free (CodeNode stmt, bool stop_at_loop = false) { - var cfrag = new CCodeFragment (); - - append_local_free (current_symbol, cfrag, stop_at_loop); - - cfrag.append (stmt.ccodenode); - stmt.ccodenode = cfrag; - } - public bool variable_accessible_in_finally (LocalVariable local) { if (current_try == null) { return false; @@ -3386,7 +3251,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { ccomma.append_expression (get_variable_cexpression (return_expr_decl.name)); stmt.return_expression.ccodenode = ccomma; - stmt.return_expression.add_temp_var (return_expr_decl); + emit_temp_var (return_expr_decl); } else if ((current_method != null || current_property_accessor != null) && current_return_type is DelegateType) { var delegate_type = (DelegateType) current_return_type; if (delegate_type.delegate_symbol.has_target) { @@ -3413,52 +3278,37 @@ public class Vala.CCodeBaseModule : CodeGenerator { ccomma.append_expression (get_variable_cexpression (return_expr_decl.name)); stmt.return_expression.ccodenode = ccomma; - stmt.return_expression.add_temp_var (return_expr_decl); + emit_temp_var (return_expr_decl); } } - var cfrag = new CCodeFragment (); - if (stmt.return_expression != null) { // assign method result to `result' CCodeExpression result_lhs = get_result_cexpression (); if (current_return_type.is_real_non_null_struct_type () && (current_method == null || !current_method.coroutine)) { result_lhs = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, result_lhs); } - cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (result_lhs, (CCodeExpression) stmt.return_expression.ccodenode))); + ccode.add_expression (new CCodeAssignment (result_lhs, (CCodeExpression) stmt.return_expression.ccodenode)); } // free local variables - append_local_free (current_symbol, cfrag); + append_local_free (current_symbol); if (current_method != null) { // check postconditions foreach (Expression postcondition in current_method.get_postconditions ()) { - cfrag.append (create_postcondition_statement (postcondition)); + create_postcondition_statement (postcondition); } } - CCodeReturnStatement creturn = null; if (current_method is CreationMethod) { - creturn = new CCodeReturnStatement (new CCodeIdentifier ("self")); - cfrag.append (creturn); + ccode.add_return (new CCodeIdentifier ("self")); } else if (current_method != null && current_method.coroutine) { } else if (current_return_type is VoidType || current_return_type.is_real_non_null_struct_type ()) { // structs are returned via out parameter - creturn = new CCodeReturnStatement (); - cfrag.append (creturn); + ccode.add_return (); } else { - creturn = new CCodeReturnStatement (new CCodeIdentifier ("result")); - cfrag.append (creturn); - } - - stmt.ccodenode = cfrag; - if (creturn != null) { - creturn.line = stmt.ccodenode.line; - } - - if (stmt.return_expression != null) { - create_temp_decl (stmt, stmt.return_expression.temp_vars); + ccode.add_return (new CCodeIdentifier ("result")); } if (return_expression_symbol != null) { @@ -3515,9 +3365,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("lock")).get_cname ())); fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l)); - var cn = new CCodeFragment (); - cn.append (new CCodeExpressionStatement (fc)); - stmt.ccodenode = cn; + ccode.add_expression (fc); } public override void visit_unlock_statement (UnlockStatement stmt) { @@ -3526,9 +3374,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("unlock")).get_cname ())); fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l)); - var cn = new CCodeFragment (); - cn.append (new CCodeExpressionStatement (fc)); - stmt.ccodenode = cn; + ccode.add_expression (fc); } public override void visit_delete_statement (DeleteStatement stmt) { @@ -3540,7 +3386,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var ccall = new CCodeFunctionCall (get_destroy_func_expression (type)); ccall.add_argument ((CCodeExpression) stmt.expression.ccodenode); - stmt.ccodenode = new CCodeExpressionStatement (ccall); + ccode.add_expression (ccall); } public override void visit_expression (Expression expr) { @@ -3627,7 +3473,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { } var regex_var = get_temp_variable (regex_type, true, expr, false); - expr.add_temp_var (regex_var); + emit_temp_var (regex_var); var cdecl = new CCodeDeclaration ("GRegex*"); @@ -3715,7 +3561,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { // assign current value to temp variable var temp_decl = get_temp_variable (prop.property_type, true, expr, false); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_decl.name), (CCodeExpression) expr.inner.ccodenode)); // increment/decrement property @@ -3826,7 +3672,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { // (copy (&expr, &temp), temp) var decl = get_temp_variable (expression_type, false, node); - temp_vars.add (decl); + emit_temp_var (decl); var ctemp = get_variable_cexpression (decl.name); @@ -3926,7 +3772,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { return ccall; } else { var decl = get_temp_variable (expression_type, false, node, false); - temp_vars.add (decl); + emit_temp_var (decl); var ctemp = get_variable_cexpression (decl.name); @@ -4149,7 +3995,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { } } else { var temp_decl = get_temp_variable (expr.type_reference, false, expr); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); instance = get_variable_cexpression (get_variable_cname (temp_decl.name)); } @@ -4457,7 +4303,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (type, true, null, false); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), cexpr)); ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name))); @@ -4529,7 +4375,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { expr.append_array_size (len_call); } else if (to is StructValueType) { var temp_decl = get_temp_variable (to, true, null, true); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); var ctemp = get_variable_cexpression (temp_decl.name); rv = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeCastExpression (rv, (new PointerType(to)).get_cname ())); @@ -4577,7 +4423,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { for (int dim = 1; dim <= array_type.rank; dim++) { var temp_decl = get_temp_variable (int_type, false, expr); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name))); cfunc.add_parameter (new CCodeFormalParameter (get_array_length_cname ("result", dim), "int*")); @@ -4631,7 +4477,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var ccomma = new CCodeCommaExpression (); var temp_decl = get_temp_variable (expr.inner.value_type, true, expr, false); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); var ctemp = get_variable_cexpression (temp_decl.name); var cinit = new CCodeAssignment (ctemp, (CCodeExpression) expr.inner.ccodenode); @@ -4695,7 +4541,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { /* (tmp = var, var = null, tmp) */ var ccomma = new CCodeCommaExpression (); var temp_decl = get_temp_variable (expr.value_type, true, expr, false); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); var cvar = get_variable_cexpression (temp_decl.name); ccomma.append_expression (new CCodeAssignment (cvar, (CCodeExpression) expr.inner.ccodenode)); @@ -4713,7 +4559,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var lbe = (BinaryExpression) expr.left; var temp_decl = get_temp_variable (lbe.right.value_type, true, null, false); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); var cvar = get_variable_cexpression (temp_decl.name); var ccomma = new CCodeCommaExpression (); var clbe = (CCodeBinaryExpression) lbe.ccodenode; @@ -5095,7 +4941,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { // treat void* special to not leak memory with void* method parameters } else if (requires_destroy (expression_type)) { var decl = get_temp_variable (expression_type, true, expression_type, false); - temp_vars.add (decl); + emit_temp_var (decl); temp_ref_vars.insert (0, decl); cexpr = new CCodeAssignment (get_variable_cexpression (decl.name), cexpr); @@ -5105,7 +4951,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { ccomma.append_expression (cexpr); for (int dim = 1; dim <= array_type.rank; dim++) { var len_decl = new LocalVariable (int_type.copy (), get_array_length_cname (decl.name, dim)); - temp_vars.add (len_decl); + emit_temp_var (len_decl); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (len_decl.name), get_array_length_cexpression (expr, dim))); } ccomma.append_expression (get_variable_cexpression (decl.name)); @@ -5115,9 +4961,9 @@ public class Vala.CCodeBaseModule : CodeGenerator { ccomma.append_expression (cexpr); var target_decl = new LocalVariable (new PointerType (new VoidType ()), get_delegate_target_cname (decl.name)); - temp_vars.add (target_decl); + emit_temp_var (target_decl); var target_destroy_notify_decl = new LocalVariable (new DelegateType ((Delegate) context.root.scope.lookup ("GLib").scope.lookup ("DestroyNotify")), get_delegate_target_destroy_notify_cname (decl.name)); - temp_vars.add (target_destroy_notify_decl); + emit_temp_var (target_destroy_notify_decl); CCodeExpression target_destroy_notify; ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (target_decl.name), get_delegate_target_cexpression (expr, out target_destroy_notify))); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (target_destroy_notify_decl.name), target_destroy_notify)); @@ -5136,7 +4982,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { if (gvalue_boxing) { // implicit conversion to GValue var decl = get_temp_variable (target_type, true, target_type); - temp_vars.add (decl); + emit_temp_var (decl); var ccomma = new CCodeCommaExpression (); @@ -5228,7 +5074,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr); } else { var decl = get_temp_variable (expression_type, expression_type.value_owned, expression_type, false); - temp_vars.add (decl); + emit_temp_var (decl); var ccomma = new CCodeCommaExpression (); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (decl.name), cexpr)); @@ -5350,7 +5196,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (ma.inner.target_type, true, null, false); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), instance)); ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name))); @@ -5371,7 +5217,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { CCodeExpression rv; if (array_type != null && !prop.no_array_length) { var temp_var = get_temp_variable (prop.property_type, true, null, false); - temp_vars.add (temp_var); + emit_temp_var (temp_var); var ccomma = new CCodeCommaExpression (); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), cexpr)); ccall.add_argument (get_variable_cexpression (temp_var.name)); @@ -5437,7 +5283,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { } var temp_decl = get_temp_variable (address_of_type, true, null, false); var ctemp = get_variable_cexpression (temp_decl.name); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); ccomma.append_expression (new CCodeAssignment (ctemp, ce)); ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp)); return ccomma; @@ -5509,19 +5355,19 @@ public class Vala.CCodeBaseModule : CodeGenerator { return null; } - private CCodeStatement? create_property_type_check_statement (Property prop, bool check_return_type, TypeSymbol t, bool non_null, string var_name) { + private void create_property_type_check_statement (Property prop, bool check_return_type, TypeSymbol t, bool non_null, string var_name) { if (check_return_type) { - return create_type_check_statement (prop, prop.property_type, t, non_null, var_name); + create_type_check_statement (prop, prop.property_type, t, non_null, var_name); } else { - return create_type_check_statement (prop, new VoidType (), t, non_null, var_name); + create_type_check_statement (prop, new VoidType (), t, non_null, var_name); } } - public CCodeStatement? create_type_check_statement (CodeNode method_node, DataType ret_type, TypeSymbol t, bool non_null, string var_name) { + public void create_type_check_statement (CodeNode method_node, DataType ret_type, TypeSymbol t, bool non_null, string var_name) { var ccheck = new CCodeFunctionCall (); if (!context.assert) { - return null; + return; } else if (context.checking && ((t is Class && !((Class) t).is_compact) || t is Interface)) { var ctype_check = new CCodeFunctionCall (new CCodeIdentifier (get_type_check_function (t))); ctype_check.add_argument (new CCodeIdentifier (var_name)); @@ -5534,10 +5380,10 @@ public class Vala.CCodeBaseModule : CodeGenerator { } ccheck.add_argument (cexpr); } else if (!non_null) { - return null; + return; } else if (t == glist_type || t == gslist_type) { // NULL is empty list - return null; + return; } else { var cnonnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL")); ccheck.add_argument (cnonnull); @@ -5557,11 +5403,11 @@ public class Vala.CCodeBaseModule : CodeGenerator { if (cdefault != null) { ccheck.add_argument (cdefault); } else { - return null; + return; } } - return new CCodeExpressionStatement (ccheck); + ccode.add_expression (ccheck); } public int get_param_pos (double param_pos, bool ellipsis = false) { @@ -5590,12 +5436,12 @@ public class Vala.CCodeBaseModule : CodeGenerator { public override void visit_class (Class cl) { } - public CCodeStatement create_postcondition_statement (Expression postcondition) { + public void create_postcondition_statement (Expression postcondition) { var cassert = new CCodeFunctionCall (new CCodeIdentifier ("g_warn_if_fail")); cassert.add_argument ((CCodeExpression) postcondition.ccodenode); - return new CCodeExpressionStatement (cassert); + ccode.add_expression (cassert); } public virtual bool is_gobject_property (Property prop) { @@ -5707,13 +5553,11 @@ public class Vala.CCodeBaseModule : CodeGenerator { } } - append_temp_decl (cfrag, temp_vars); - temp_vars.clear (); - pop_context (); - cfile.add_function_declaration (function); function.block = cblock; + + cfile.add_function_declaration (function); cfile.add_function (function); } @@ -5789,7 +5633,7 @@ public class Vala.CCodeBaseModule : CodeGenerator { return new CCodeConstant (""); } - public virtual void add_simple_check (CodeNode node, CCodeFragment cfrag, bool always_fails = false) { + public virtual void add_simple_check (CodeNode node, bool always_fails = false) { } } diff --git a/codegen/valaccodecontrolflowmodule.vala b/codegen/valaccodecontrolflowmodule.vala index 49d868b5c..0793d3374 100644 --- a/codegen/valaccodecontrolflowmodule.vala +++ b/codegen/valaccodecontrolflowmodule.vala @@ -26,24 +26,22 @@ using GLib; public class Vala.CCodeControlFlowModule : CCodeMethodModule { public override void visit_if_statement (IfStatement stmt) { + ccode.open_if ((CCodeExpression) stmt.condition.ccodenode); + stmt.true_statement.emit (this); + if (stmt.false_statement != null) { + ccode.add_else (); stmt.false_statement.emit (this); } - if (stmt.false_statement != null) { - stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode, (CCodeStatement) stmt.false_statement.ccodenode); - } else { - stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode); - } - - create_temp_decl (stmt, stmt.condition.temp_vars); + ccode.close (); } void visit_string_switch_statement (SwitchStatement stmt) { // we need a temporary variable to save the property value var temp_var = get_temp_variable (stmt.expression.value_type, stmt.expression.value_type.value_owned, stmt, false); - stmt.expression.add_temp_var (temp_var); + emit_temp_var (temp_var); var ctemp = get_variable_cexpression (temp_var.name); var cinit = new CCodeAssignment (ctemp, (CCodeExpression) stmt.expression.ccodenode); @@ -52,9 +50,6 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free")); free_call.add_argument (ctemp); - var cswitchblock = new CCodeFragment (); - stmt.ccodenode = cswitchblock; - var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), ctemp); var cquark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string")); cquark.add_argument (ctemp); @@ -62,7 +57,7 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cquark); temp_var = get_temp_variable (gquark_type); - stmt.expression.add_temp_var (temp_var); + emit_temp_var (temp_var); int label_count = 0; @@ -72,48 +67,43 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { } foreach (SwitchLabel label in section.get_labels ()) { + label.expression.emit (this); var cexpr = (CCodeExpression) label.expression.ccodenode; if (is_constant_ccode_expression (cexpr)) { var cname = "%s_label%d".printf (temp_var.name, label_count++); - var cdecl = new CCodeDeclaration (gquark_type.get_cname ()); - cdecl.modifiers = CCodeModifiers.STATIC; - cdecl.add_declarator (new CCodeVariableDeclarator (cname, czero)); - - cswitchblock.append (cdecl); + ccode.add_declaration (gquark_type.get_cname (), new CCodeVariableDeclarator (cname, czero), CCodeModifiers.STATIC); } } } - cswitchblock.append (new CCodeExpressionStatement (cinit)); + ccode.add_expression (cinit); ctemp = get_variable_cexpression (temp_var.name); cinit = new CCodeAssignment (ctemp, ccond); - cswitchblock.append (new CCodeExpressionStatement (cinit)); - create_temp_decl (stmt, stmt.expression.temp_vars); + ccode.add_expression (cinit); if (stmt.expression.value_type.value_owned) { // free owned string - cswitchblock.append (new CCodeExpressionStatement (free_call)); + ccode.add_expression (free_call); } - List default_statements = null; + SwitchSection default_section = null; label_count = 0; - // generate nested if statements - CCodeStatement ctopstmt = null; - CCodeIfStatement coldif = null; + int n = 0; foreach (SwitchSection section in stmt.get_sections ()) { if (section.has_default_label ()) { - default_statements = section.get_statements (); + default_section = section; continue; } CCodeBinaryExpression cor = null; foreach (SwitchLabel label in section.get_labels ()) { + label.expression.emit (this); var cexpr = (CCodeExpression) label.expression.ccodenode; if (is_constant_ccode_expression (cexpr)) { @@ -140,119 +130,86 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { } } - var cblock = new CCodeBlock (); - foreach (CodeNode body_stmt in section.get_statements ()) { - if (body_stmt.ccodenode is CCodeFragment) { - foreach (CCodeNode cstmt in ((CCodeFragment) body_stmt.ccodenode).get_children ()) { - cblock.add_statement (cstmt); - } - } else { - cblock.add_statement (body_stmt.ccodenode); - } + if (n > 0) { + ccode.else_if (cor); + } else { + ccode.open_if (cor); } - var cswitch = new CCodeSwitchStatement (new CCodeConstant ("0")); - cswitch.add_statement (new CCodeLabel ("default")); - cswitch.add_statement (cblock); - var cif = new CCodeIfStatement (cor, cswitch); + ccode.open_switch (new CCodeConstant ("0")); + ccode.add_default (); - if (coldif != null) { - coldif.false_statement = cif; - } else { - ctopstmt = cif; - } + section.emit (this); + + ccode.close (); - coldif = cif; + n++; } - if (default_statements != null) { - var cblock = new CCodeBlock (); - foreach (CodeNode body_stmt in default_statements) { - cblock.add_statement (body_stmt.ccodenode); + if (default_section != null) { + if (n > 0) { + ccode.add_else (); } - var cswitch = new CCodeSwitchStatement (new CCodeConstant ("0")); - cswitch.add_statement (new CCodeLabel ("default")); - cswitch.add_statement (cblock); + ccode.open_switch (new CCodeConstant ("0")); + ccode.add_default (); - if (coldif == null) { - // there is only one section and that section - // contains a default label - ctopstmt = cswitch; - } else { - coldif.false_statement = cswitch; - } + default_section.emit (this); + + ccode.close (); } - - cswitchblock.append (ctopstmt); + + ccode.close (); } public override void visit_switch_statement (SwitchStatement stmt) { - foreach (SwitchSection section in stmt.get_sections ()) { - section.emit (this); - } - if (stmt.expression.value_type.compatible (string_type)) { visit_string_switch_statement (stmt); return; } - var cswitch = new CCodeSwitchStatement ((CCodeExpression) stmt.expression.ccodenode); - stmt.ccodenode = cswitch; + ccode.open_switch ((CCodeExpression) stmt.expression.ccodenode); foreach (SwitchSection section in stmt.get_sections ()) { if (section.has_default_label ()) { - cswitch.add_statement (new CCodeLabel ("default")); - var cdefaultblock = new CCodeBlock (); - cswitch.add_statement (cdefaultblock); - foreach (CodeNode default_stmt in section.get_statements ()) { - cdefaultblock.add_statement (default_stmt.ccodenode); - } - continue; + ccode.add_default (); } - - foreach (SwitchLabel label in section.get_labels ()) { - cswitch.add_statement (new CCodeCaseStatement ((CCodeExpression) label.expression.ccodenode)); - } - - cswitch.add_statement (section.ccodenode); + section.emit (this); } - - create_temp_decl (stmt, stmt.expression.temp_vars); + + ccode.close (); } public override void visit_switch_label (SwitchLabel label) { + if (((SwitchStatement) label.section.parent_node).expression.value_type.compatible (string_type)) { + return; + } + if (label.expression != null) { label.expression.emit (this); visit_end_full_expression (label.expression); + + ccode.add_case ((CCodeExpression) label.expression.ccodenode); } } public override void visit_loop (Loop stmt) { - stmt.body.emit (this); - if (context.profile == Profile.GOBJECT) { - stmt.ccodenode = new CCodeWhileStatement (new CCodeConstant ("TRUE"), (CCodeStatement) stmt.body.ccodenode); + ccode.open_while (new CCodeConstant ("TRUE")); } else { cfile.add_include ("stdbool.h"); - stmt.ccodenode = new CCodeWhileStatement (new CCodeConstant ("true"), (CCodeStatement) stmt.body.ccodenode); + ccode.open_while (new CCodeConstant ("true")); } - } - public override void visit_foreach_statement (ForeachStatement stmt) { stmt.body.emit (this); - visit_block (stmt); + ccode.close (); + } - var cblock = new CCodeBlock (); - // sets #line - stmt.ccodenode = cblock; + public override void visit_foreach_statement (ForeachStatement stmt) { + ccode.open_block (); - var cfrag = new CCodeFragment (); - append_temp_decl (cfrag, stmt.collection.temp_vars); - cblock.add_statement (cfrag); - var collection_backup = stmt.collection_variable; var collection_type = collection_backup.variable_type.copy (); @@ -264,20 +221,15 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { if (current_method != null && current_method.coroutine) { closure_struct.add_field (collection_type.get_cname (), collection_backup.name); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (collection_backup.name), (CCodeExpression) stmt.collection.ccodenode))); } else { - var ccoldecl = new CCodeDeclaration (collection_type.get_cname ()); - var ccolvardecl = new CCodeVariableDeclarator (collection_backup.name, (CCodeExpression) stmt.collection.ccodenode); - ccolvardecl.line = cblock.line; - ccoldecl.add_declarator (ccolvardecl); - cblock.add_statement (ccoldecl); + var ccolvardecl = new CCodeVariableDeclarator (collection_backup.name); + ccode.add_declaration (collection_type.get_cname (), ccolvardecl); } + ccode.add_expression (new CCodeAssignment (get_variable_cexpression (collection_backup.name), (CCodeExpression) stmt.collection.ccodenode)); if (stmt.tree_can_fail && stmt.collection.tree_can_fail) { // exception handling - cfrag = new CCodeFragment (); - add_simple_check (stmt.collection, cfrag); - cblock.add_statement (cfrag); + add_simple_check (stmt.collection); } if (stmt.collection.value_type is ArrayType) { @@ -288,24 +240,24 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { // store array length for use by _vala_array_free if (current_method != null && current_method.coroutine) { closure_struct.add_field ("int", get_array_length_cname (collection_backup.name, 1)); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (get_array_length_cname (collection_backup.name, 1)), array_len))); } else { - var clendecl = new CCodeDeclaration ("int"); - clendecl.add_declarator (new CCodeVariableDeclarator (get_array_length_cname (collection_backup.name, 1), array_len)); - cblock.add_statement (clendecl); + ccode.add_declaration ("int", new CCodeVariableDeclarator (get_array_length_cname (collection_backup.name, 1))); } + ccode.add_expression (new CCodeAssignment (get_variable_cexpression (get_array_length_cname (collection_backup.name, 1)), array_len)); var it_name = (stmt.variable_name + "_it"); if (current_method != null && current_method.coroutine) { closure_struct.add_field ("int", it_name); } else { - var citdecl = new CCodeDeclaration ("int"); - citdecl.add_declarator (new CCodeVariableDeclarator (it_name)); - cblock.add_statement (citdecl); + ccode.add_declaration ("int", new CCodeVariableDeclarator (it_name)); } - - var cbody = new CCodeBlock (); + + var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (it_name), array_len); + + ccode.open_for (new CCodeAssignment (get_variable_cexpression (it_name), new CCodeConstant ("0")), + ccond, + new CCodeAssignment (get_variable_cexpression (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (it_name), new CCodeConstant ("1")))); CCodeExpression element_expr = new CCodeElementAccess (get_variable_cexpression (collection_backup.name), get_variable_cexpression (it_name)); @@ -313,19 +265,12 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { element_type.value_owned = false; element_expr = transform_expression (element_expr, element_type, stmt.type_reference); - cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - cbody.add_statement (cfrag); - temp_vars.clear (); - if (current_method != null && current_method.coroutine) { closure_struct.add_field (stmt.type_reference.get_cname (), stmt.variable_name); - cbody.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr))); } else { - var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator (stmt.variable_name, element_expr)); - cbody.add_statement (cdecl); + ccode.add_declaration (stmt.type_reference.get_cname (), new CCodeVariableDeclarator (stmt.variable_name)); } + ccode.add_expression (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr)); // add array length variable for stacked arrays if (stmt.type_reference is ArrayType) { @@ -333,23 +278,16 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { for (int dim = 1; dim <= inner_array_type.rank; dim++) { if (current_method != null && current_method.coroutine) { closure_struct.add_field ("int", get_array_length_cname (stmt.variable_name, dim)); - cbody.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (get_array_length_cname (stmt.variable_name, dim)), new CCodeConstant ("-1")))); + ccode.add_expression (new CCodeAssignment (get_variable_cexpression (get_array_length_cname (stmt.variable_name, dim)), new CCodeConstant ("-1"))); } else { - var cdecl = new CCodeDeclaration ("int"); - cdecl.add_declarator (new CCodeVariableDeclarator (get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1"))); - cbody.add_statement (cdecl); + ccode.add_declaration ("int", new CCodeVariableDeclarator (get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1"))); } } } - cbody.add_statement (stmt.body.ccodenode); - - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (it_name), array_len); + stmt.body.emit (this); - var cfor = new CCodeForStatement (ccond, cbody); - cfor.add_initializer (new CCodeAssignment (get_variable_cexpression (it_name), new CCodeConstant ("0"))); - cfor.add_iterator (new CCodeAssignment (get_variable_cexpression (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (it_name), new CCodeConstant ("1")))); - cblock.add_statement (cfor); + ccode.close (); } else if (stmt.collection.value_type.compatible (new ObjectType (glist_type)) || stmt.collection.value_type.compatible (new ObjectType (gslist_type))) { // iterating over a GList or GSList @@ -358,14 +296,14 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { if (current_method != null && current_method.coroutine) { closure_struct.add_field (collection_type.get_cname (), it_name); } else { - var citdecl = new CCodeDeclaration (collection_type.get_cname ()); - var citvardecl = new CCodeVariableDeclarator (it_name); - citvardecl.line = cblock.line; - citdecl.add_declarator (citvardecl); - cblock.add_statement (citdecl); + ccode.add_declaration (collection_type.get_cname (), new CCodeVariableDeclarator (it_name)); } - var cbody = new CCodeBlock (); + var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (it_name), new CCodeConstant ("NULL")); + + ccode.open_for (new CCodeAssignment (get_variable_cexpression (it_name), get_variable_cexpression (collection_backup.name)), + ccond, + new CCodeAssignment (get_variable_cexpression (it_name), new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "next"))); CCodeExpression element_expr = new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "data"); @@ -380,32 +318,16 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { element_expr = convert_from_generic_pointer (element_expr, element_data_type); element_expr = transform_expression (element_expr, element_data_type, stmt.type_reference); - cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - cbody.add_statement (cfrag); - temp_vars.clear (); - if (current_method != null && current_method.coroutine) { closure_struct.add_field (stmt.type_reference.get_cname (), stmt.variable_name); - cbody.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr))); } else { - var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ()); - var cvardecl = new CCodeVariableDeclarator (stmt.variable_name, element_expr); - cvardecl.line = cblock.line; - cdecl.add_declarator (cvardecl); - cbody.add_statement (cdecl); + ccode.add_declaration (stmt.type_reference.get_cname (), new CCodeVariableDeclarator (stmt.variable_name)); } - - cbody.add_statement (stmt.body.ccodenode); - - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (it_name), new CCodeConstant ("NULL")); - - var cfor = new CCodeForStatement (ccond, cbody); - - cfor.add_initializer (new CCodeAssignment (get_variable_cexpression (it_name), get_variable_cexpression (collection_backup.name))); + ccode.add_expression (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr)); - cfor.add_iterator (new CCodeAssignment (get_variable_cexpression (it_name), new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "next"))); - cblock.add_statement (cfor); + stmt.body.emit (this); + + ccode.close (); } else if (stmt.collection.value_type.compatible (new ObjectType (gvaluearray_type))) { // iterating over a GValueArray @@ -414,14 +336,14 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { if (current_method != null && current_method.coroutine) { closure_struct.add_field (uint_type.get_cname (), arr_index); } else { - var citdecl = new CCodeDeclaration (uint_type.get_cname ()); - var citvardecl = new CCodeVariableDeclarator (arr_index); - citvardecl.line = cblock.line; - citdecl.add_declarator (citvardecl); - cblock.add_statement (citdecl); + ccode.add_declaration (uint_type.get_cname (), new CCodeVariableDeclarator (arr_index)); } - var cbody = new CCodeBlock (); + var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (arr_index), new CCodeMemberAccess.pointer (get_variable_cexpression (collection_backup.name), "n_values")); + + ccode.open_for (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeConstant ("0")), + ccond, + new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (arr_index), new CCodeConstant ("1")))); var get_item = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_get_nth")); get_item.add_argument (get_variable_cexpression (collection_backup.name)); @@ -433,56 +355,39 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule { element_expr = get_ref_cexpression (stmt.type_reference, element_expr, null, new StructValueType (gvalue_type)); } - cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - cbody.add_statement (cfrag); - temp_vars.clear (); - if (current_method != null && current_method.coroutine) { closure_struct.add_field (stmt.type_reference.get_cname (), stmt.variable_name); - cbody.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr))); } else { - var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ()); - var cvardecl = new CCodeVariableDeclarator (stmt.variable_name, element_expr); - cvardecl.line = cblock.line; - cdecl.add_declarator (cvardecl); - cbody.add_statement (cdecl); + ccode.add_declaration (stmt.type_reference.get_cname (), new CCodeVariableDeclarator (stmt.variable_name)); } + ccode.add_expression (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr)); - cbody.add_statement (stmt.body.ccodenode); - - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (arr_index), new CCodeMemberAccess.pointer (get_variable_cexpression (collection_backup.name), "n_values")); - - var cfor = new CCodeForStatement (ccond, cbody); - - cfor.add_initializer (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeConstant ("0"))); + stmt.body.emit (this); - cfor.add_iterator (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (arr_index), new CCodeConstant ("1")))); - - cblock.add_statement (cfor); + ccode.close (); } foreach (LocalVariable local in stmt.get_local_variables ()) { if (requires_destroy (local.variable_type)) { var ma = new MemberAccess.simple (local.name); ma.symbol_reference = local; - var cunref = new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)); - cunref.line = cblock.line; - cblock.add_statement (cunref); + ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)); } } + + ccode.close (); } public override void visit_break_statement (BreakStatement stmt) { - stmt.ccodenode = new CCodeBreakStatement (); + append_local_free (current_symbol, true); - create_local_free (stmt, true); + ccode.add_break (); } public override void visit_continue_statement (ContinueStatement stmt) { - stmt.ccodenode = new CCodeContinueStatement (); + append_local_free (current_symbol, true); - create_local_free (stmt, true); + ccode.add_continue (); } } diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala index bbe085f88..fbdbbe5a9 100644 --- a/codegen/valaccodememberaccessmodule.vala +++ b/codegen/valaccodememberaccessmodule.vala @@ -69,7 +69,7 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { // instance expression has side-effects // store in temp. variable var temp_var = get_temp_variable (expr.inner.value_type, true, null, false); - temp_vars.add (temp_var); + emit_temp_var (temp_var); var ctemp = get_variable_cexpression (temp_var.name); inst = new CCodeAssignment (ctemp, pub_inst); expr.inner.ccodenode = ctemp; @@ -264,7 +264,7 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (expr.inner.target_type, true, null, false); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), pub_inst)); ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name))); @@ -281,7 +281,7 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (base_property.get_accessor.value_type); var ctemp = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp)); ccomma.append_expression (ccall); ccomma.append_expression (ctemp); @@ -292,7 +292,7 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { for (int dim = 1; dim <= array_type.rank; dim++) { var temp_var = get_temp_variable (int_type); var ctemp = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp)); expr.append_array_size (ctemp); } @@ -301,7 +301,7 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { if (delegate_type != null && delegate_type.delegate_symbol.has_target) { var temp_var = get_temp_variable (new PointerType (new VoidType ())); var ctemp = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp)); expr.delegate_target = ctemp; } @@ -332,7 +332,7 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (expr.value_type); var ctemp = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp)); ccall.add_argument (new CCodeConstant ("NULL")); ccomma.append_expression (ccall); diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala index 5a01c9183..f1dd34212 100644 --- a/codegen/valaccodemethodcallmodule.vala +++ b/codegen/valaccodemethodcallmodule.vala @@ -200,7 +200,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (ma.inner.target_type, true, null, false); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), instance)); ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name))); @@ -353,14 +353,14 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { if (param.array_length_type != null) { if (param.direction == ParameterDirection.OUT) { var temp_array_length = get_temp_variable (new CType (param.array_length_type)); - temp_vars.add (temp_array_length); + emit_temp_var (temp_array_length); array_length_expr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_array_length.name)); var comma = new CCodeCommaExpression (); LocalVariable? temp_result = null; if (!(m.return_type is VoidType)) { temp_result = get_temp_variable (m.return_type); - temp_vars.add (temp_result); + emit_temp_var (temp_result); ccall_expr = new CCodeAssignment (get_variable_cexpression (temp_result.name), ccall_expr); } @@ -430,7 +430,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { var ccomma = new CCodeCommaExpression (); var temp_decl = get_temp_variable (arg.value_type, true, null, false); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_decl.name), cexpr)); cexpr = get_variable_cexpression (temp_decl.name); @@ -451,7 +451,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (param.variable_type, param.variable_type.value_owned); - temp_vars.add (temp_var); + emit_temp_var (temp_var); cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name)); if (param.direction == ParameterDirection.REF) { @@ -468,14 +468,14 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { ccomma.append_expression (ccall_expr); } else { ret_temp_var = get_temp_variable (itype.get_return_type (), true, null, false); - temp_vars.add (ret_temp_var); + emit_temp_var (ret_temp_var); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (ret_temp_var.name), ccall_expr)); } var cassign_comma = new CCodeCommaExpression (); var assign_temp_var = get_temp_variable (unary.inner.value_type, unary.inner.value_type.value_owned, null, false); - temp_vars.add (assign_temp_var); + emit_temp_var (assign_temp_var); cassign_comma.append_expression (new CCodeAssignment (get_variable_cexpression (assign_temp_var.name), transform_expression (get_variable_cexpression (temp_var.name), param.variable_type, unary.inner.value_type, arg))); @@ -538,7 +538,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { var temp_var = get_temp_variable (itype.get_return_type (), true, null, false); var temp_ref = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccall_expr = new CCodeAssignment (temp_ref, ccall_expr); @@ -557,7 +557,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { } var temp_ref = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); out_arg_map.set (get_param_pos (m.carray_length_parameter_position + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref)); @@ -573,7 +573,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { var temp_var = get_temp_variable (new PointerType (new VoidType ())); var temp_ref = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); out_arg_map.set (get_param_pos (m.cdelegate_target_parameter_position), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref)); @@ -583,7 +583,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { temp_var = get_temp_variable (new DelegateType ((Delegate) context.root.scope.lookup ("GLib").scope.lookup ("DestroyNotify"))); temp_ref = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); out_arg_map.set (get_param_pos (m.cdelegate_target_parameter_position + 0.01), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref)); @@ -602,7 +602,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { var temp_var = get_temp_variable (itype.get_return_type (), true, null, false); var temp_ref = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccall_expr = new CCodeAssignment (temp_ref, ccall_expr); @@ -615,7 +615,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { var temp_var = get_temp_variable (int_type); var temp_ref = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); out_arg_map.set (get_param_pos (deleg.carray_length_parameter_position + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref)); @@ -631,7 +631,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { var temp_var = get_temp_variable (new PointerType (new VoidType ())); var temp_ref = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); out_arg_map.set (get_param_pos (deleg.cdelegate_target_parameter_position), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref)); @@ -688,7 +688,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { var temp_var = get_temp_variable (itype.get_return_type ()); var temp_ref = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); out_arg_map.set (get_param_pos (-3), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref)); @@ -746,20 +746,13 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { } if (expr.is_yield_expression) { - if (pre_statement_fragment == null) { - pre_statement_fragment = new CCodeFragment (); - } - // set state before calling async function to support immediate callbacks int state = next_coroutine_state++; - state_switch_statement.add_statement (new CCodeCaseStatement (new CCodeConstant (state.to_string ()))); - state_switch_statement.add_statement (new CCodeGotoStatement ("_state_%d".printf (state))); - - pre_statement_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ())))); - pre_statement_fragment.append (new CCodeExpressionStatement (async_call)); - pre_statement_fragment.append (new CCodeReturnStatement (new CCodeConstant ("FALSE"))); - pre_statement_fragment.append (new CCodeLabel ("_state_%d".printf (state))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ()))); + ccode.add_expression (async_call); + ccode.add_return (new CCodeConstant ("FALSE")); + ccode.add_label ("_state_%d".printf (state)); } if (m is ArrayResizeMethod) { @@ -771,7 +764,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { var temp_decl = get_temp_variable (int_type); var temp_ref = get_variable_cexpression (temp_decl.name); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); /* memset needs string.h */ cfile.add_include ("string.h"); diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala index 4a6e805e9..89d216f2b 100644 --- a/codegen/valaccodemethodmodule.vala +++ b/codegen/valaccodemethodmodule.vala @@ -129,33 +129,31 @@ public class Vala.CCodeMethodModule : CCodeStructModule { } } - public CCodeStatement complete_async () { - var complete_block = new CCodeBlock (); + public void complete_async () { + var state = new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"); + var zero = new CCodeConstant ("0"); + var state_is_zero = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, state, zero); + ccode.open_if (state_is_zero); - var direct_block = new CCodeBlock (); - var direct_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete")); var async_result_expr = new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_async_result"); - direct_call.add_argument (async_result_expr); - direct_block.add_statement (new CCodeExpressionStatement (direct_call)); - var idle_block = new CCodeBlock (); var idle_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete_in_idle")); idle_call.add_argument (async_result_expr); - idle_block.add_statement (new CCodeExpressionStatement (idle_call)); + ccode.add_expression (idle_call); - var state = new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"); - var zero = new CCodeConstant ("0"); - var state_is_zero = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, state, zero); - var dispatch = new CCodeIfStatement (state_is_zero, idle_block, direct_block); - complete_block.add_statement (dispatch); + ccode.add_else (); + + var direct_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete")); + direct_call.add_argument (async_result_expr); + ccode.add_expression (direct_call); + + ccode.close (); var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); unref.add_argument (async_result_expr); - complete_block.add_statement (new CCodeExpressionStatement (unref)); - - complete_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE"))); + ccode.add_expression (unref); - return complete_block; + ccode.add_return (new CCodeConstant ("FALSE")); } public override void generate_method_declaration (Method m, CCodeFile decl_space) { @@ -206,34 +204,34 @@ public class Vala.CCodeMethodModule : CCodeStructModule { } } - void register_plugin_types (CCodeFragment module_init_fragment, Symbol sym, Set registered_types) { + void register_plugin_types (Symbol sym, Set registered_types) { var ns = sym as Namespace; var cl = sym as Class; var iface = sym as Interface; if (ns != null) { foreach (var ns_ns in ns.get_namespaces ()) { - register_plugin_types (module_init_fragment, ns_ns, registered_types); + register_plugin_types (ns_ns, registered_types); } foreach (var ns_cl in ns.get_classes ()) { - register_plugin_types (module_init_fragment, ns_cl, registered_types); + register_plugin_types (ns_cl, registered_types); } foreach (var ns_iface in ns.get_interfaces ()) { - register_plugin_types (module_init_fragment, ns_iface, registered_types); + register_plugin_types (ns_iface, registered_types); } } else if (cl != null) { - register_plugin_type (module_init_fragment, cl, registered_types); + register_plugin_type (cl, registered_types); foreach (var cl_cl in cl.get_classes ()) { - register_plugin_types (module_init_fragment, cl_cl, registered_types); + register_plugin_types (cl_cl, registered_types); } } else if (iface != null) { - register_plugin_type (module_init_fragment, iface, registered_types); + register_plugin_type (iface, registered_types); foreach (var iface_cl in iface.get_classes ()) { - register_plugin_types (module_init_fragment, iface_cl, registered_types); + register_plugin_types (iface_cl, registered_types); } } } - void register_plugin_type (CCodeFragment module_init_fragment, ObjectTypeSymbol type_symbol, Set registered_types) { + void register_plugin_type (ObjectTypeSymbol type_symbol, Set registered_types) { if (type_symbol.external_package) { return; } @@ -251,13 +249,13 @@ public class Vala.CCodeMethodModule : CCodeStructModule { // register base types first foreach (var base_type in cl.get_base_types ()) { - register_plugin_type (module_init_fragment, (ObjectTypeSymbol) base_type.data_type, registered_types); + register_plugin_type ((ObjectTypeSymbol) base_type.data_type, registered_types); } } var register_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_register_type".printf (type_symbol.get_lower_case_cname (null)))); register_call.add_argument (new CCodeIdentifier (module_init_param_name)); - module_init_fragment.append (new CCodeExpressionStatement (register_call)); + ccode.add_expression (register_call); } public override void visit_method (Method m) { @@ -280,13 +278,8 @@ public class Vala.CCodeMethodModule : CCodeStructModule { } if (m.coroutine) { - state_switch_statement = new CCodeSwitchStatement (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_")); - - // initial coroutine state - state_switch_statement.add_statement (new CCodeCaseStatement (new CCodeConstant ("0"))); - state_switch_statement.add_statement (new CCodeGotoStatement ("_state_0")); + next_coroutine_state = 1; } - var current_state_switch = state_switch_statement; var creturn_type = m.return_type; if (m.return_type.is_real_non_null_struct_type ()) { @@ -328,13 +321,8 @@ public class Vala.CCodeMethodModule : CCodeStructModule { } } - if (m.comment != null) { - cfile.add_type_member_definition (new CCodeComment (m.comment.content)); - } - CCodeFunction function; function = new CCodeFunction (m.get_real_cname ()); - m.ccodenode = function; if (m.is_inline) { function.modifiers |= CCodeModifiers.INLINE; @@ -361,8 +349,6 @@ public class Vala.CCodeMethodModule : CCodeStructModule { // generate *_real_* functions for virtual methods // also generate them for abstract methods of classes to prevent faulty subclassing if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) { - /* Methods imported from a plain C file don't - * have a body, e.g. Vala.Parser.parse_file () */ if (m.body != null) { if (m.coroutine) { function = new CCodeFunction (m.get_real_cname () + "_co", "gboolean"); @@ -376,22 +362,37 @@ public class Vala.CCodeMethodModule : CCodeStructModule { } } - var cinit = new CCodeFragment (); + if (m.comment != null) { + cfile.add_type_member_definition (new CCodeComment (m.comment.content)); + } + + push_function (function); // generate *_real_* functions for virtual methods // also generate them for abstract methods of classes to prevent faulty subclassing if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) { - /* Methods imported from a plain C file don't - * have a body, e.g. Vala.Parser.parse_file () */ if (m.body != null) { if (m.coroutine) { + ccode.open_switch (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_")); + + // initial coroutine state + ccode.add_case (new CCodeConstant ("0")); + ccode.add_goto ("_state_0"); + + for (int state = 1; state <= m.yield_count; state++) { + ccode.add_case (new CCodeConstant (state.to_string ())); + ccode.add_goto ("_state_%d".printf (state)); + } + + // let gcc know that this can't happen - current_state_switch.add_statement (new CCodeLabel ("default")); - current_state_switch.add_statement (new CCodeExpressionStatement (new CCodeFunctionCall (new CCodeIdentifier ("g_assert_not_reached")))); + ccode.add_default (); + ccode.add_expression (new CCodeFunctionCall (new CCodeIdentifier ("g_assert_not_reached"))); - cinit.append (current_state_switch); + ccode.close (); - cinit.append (new CCodeLabel ("_state_0")); + // coroutine body + ccode.add_label ("_state_0"); } if (m.closure) { @@ -407,10 +408,8 @@ public class Vala.CCodeMethodModule : CCodeStructModule { 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); + ccode.add_declaration ("Block%dData*".printf (parent_block_id), new CCodeVariableDeclarator ("_data%d_".printf (parent_block_id))); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("_data%d_".printf (parent_block_id)), parent_data)); closure_block = parent_closure_block; block_id = parent_block_id; @@ -420,10 +419,8 @@ public class Vala.CCodeMethodModule : CCodeStructModule { // as closures have block data parameter if (m.binding == MemberBinding.INSTANCE) { var cself = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "self"); - var cdecl = new CCodeDeclaration ("%s *".printf (current_class.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator ("self", cself)); - - cinit.append (cdecl); + ccode.add_declaration ("%s *".printf (current_class.get_cname ()), new CCodeVariableDeclarator ("self")); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), cself)); } } else if (m.parent_symbol is Class && !m.coroutine) { var cl = (Class) m.parent_symbol; @@ -440,19 +437,14 @@ public class Vala.CCodeMethodModule : CCodeStructModule { var self_target_type = new ObjectType (cl); CCodeExpression cself = transform_expression (new CCodeIdentifier ("base"), base_expression_type, self_target_type); - var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator ("self", cself)); - - cinit.append (cdecl); + ccode.add_declaration ("%s *".printf (cl.get_cname ()), new CCodeVariableDeclarator ("self")); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), cself)); } else if (m.binding == MemberBinding.INSTANCE - && !(m is CreationMethod)) { - var ccheckstmt = create_method_type_check_statement (m, creturn_type, cl, true, "self"); - if (ccheckstmt != null) { - ccheckstmt.line = function.line; - cinit.append (ccheckstmt); - } + && !(m is CreationMethod)) { + create_method_type_check_statement (m, creturn_type, cl, true, "self"); } } + foreach (FormalParameter param in m.get_parameters ()) { if (param.ellipsis) { break; @@ -461,11 +453,7 @@ public class Vala.CCodeMethodModule : CCodeStructModule { if (param.direction != ParameterDirection.OUT) { var t = param.variable_type.data_type; if (t != null && t.is_reference_type ()) { - var type_check = create_method_type_check_statement (m, creturn_type, t, !param.variable_type.nullable, get_variable_cname (param.name)); - if (type_check != null) { - type_check.line = function.line; - cinit.append (type_check); - } + create_method_type_check_statement (m, creturn_type, t, !param.variable_type.nullable, get_variable_cname (param.name)); } } else if (!m.coroutine) { var t = param.variable_type.data_type; @@ -477,36 +465,28 @@ public class Vala.CCodeMethodModule : CCodeStructModule { var condition = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (param.name), new CCodeConstant ("NULL")); var if_statement = new CCodeIfStatement (condition, cblock); - cinit.append (if_statement); + ccode.add_statement (if_statement); } } } if (!(m.return_type is VoidType) && !m.return_type.is_real_non_null_struct_type () && !m.coroutine) { - var cdecl = new CCodeDeclaration (m.return_type.get_cname ()); var vardecl = new CCodeVariableDeclarator ("result", default_value_for_type (m.return_type, true)); vardecl.init0 = true; - cdecl.add_declarator (vardecl); - cinit.append (cdecl); + ccode.add_declaration (m.return_type.get_cname (), vardecl); } if (m is CreationMethod) { if (in_gobject_creation_method) { - var cdeclaration = new CCodeDeclaration ("%s *".printf (((Class) current_type_symbol).get_cname ())); - cdeclaration.add_declarator (new CCodeVariableDeclarator ("self")); - - cinit.append (cdeclaration); + ccode.add_declaration ("%s *".printf (((Class) current_type_symbol).get_cname ()), new CCodeVariableDeclarator ("self")); } else if (is_gtypeinstance_creation_method (m)) { var cl = (Class) m.parent_symbol; - var cdeclaration = new CCodeDeclaration (cl.get_cname () + "*"); - var cdecl = new CCodeVariableDeclarator ("self"); - cdeclaration.add_declarator (cdecl); - cinit.append (cdeclaration); + ccode.add_declaration (cl.get_cname () + "*", new CCodeVariableDeclarator ("self")); if (cl.is_fundamental ()) { var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_create_instance")); ccall.add_argument (new CCodeIdentifier ("object_type")); - cdecl.initializer = new CCodeCastExpression (ccall, cl.get_cname () + "*"); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), new CCodeCastExpression (ccall, cl.get_cname () + "*"))); /* type, dup func, and destroy func fields for generic types */ foreach (TypeParameter type_param in current_class.get_type_parameters ()) { @@ -517,36 +497,33 @@ public class Vala.CCodeMethodModule : CCodeStructModule { param_name = new CCodeIdentifier ("%s_type".printf (type_param.name.down ())); assign = new CCodeAssignment (new CCodeMemberAccess.pointer (priv_access, param_name.name), param_name); - cinit.append (new CCodeExpressionStatement (assign)); + ccode.add_expression (assign); param_name = new CCodeIdentifier ("%s_dup_func".printf (type_param.name.down ())); assign = new CCodeAssignment (new CCodeMemberAccess.pointer (priv_access, param_name.name), param_name); - cinit.append (new CCodeExpressionStatement (assign)); + ccode.add_expression (assign); param_name = new CCodeIdentifier ("%s_destroy_func".printf (type_param.name.down ())); assign = new CCodeAssignment (new CCodeMemberAccess.pointer (priv_access, param_name.name), param_name); - cinit.append (new CCodeExpressionStatement (assign)); + ccode.add_expression (assign); } } } else if (current_type_symbol is Class) { var cl = (Class) m.parent_symbol; - var cdeclaration = new CCodeDeclaration (cl.get_cname () + "*"); - var cdecl = new CCodeVariableDeclarator ("self"); - cdeclaration.add_declarator (cdecl); - cinit.append (cdeclaration); + ccode.add_declaration (cl.get_cname () + "*", new CCodeVariableDeclarator ("self")); if (!((CreationMethod) m).chain_up) { // TODO implicitly chain up to base class as in add_object_creation var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0")); ccall.add_argument (new CCodeIdentifier (cl.get_cname ())); - cdecl.initializer = ccall; + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), ccall)); } if (cl.base_class == null) { // derived compact classes do not have fields var cinitcall = new CCodeFunctionCall (new CCodeIdentifier ("%s_instance_init".printf (cl.get_lower_case_cname (null)))); cinitcall.add_argument (new CCodeIdentifier ("self")); - cinit.append (new CCodeExpressionStatement (cinitcall)); + ccode.add_expression (cinitcall); } } else { var st = (Struct) m.parent_symbol; @@ -557,20 +534,17 @@ public class Vala.CCodeMethodModule : CCodeStructModule { czero.add_argument (new CCodeIdentifier ("self")); czero.add_argument (new CCodeConstant ("0")); czero.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (st.get_cname ()))); - cinit.append (new CCodeExpressionStatement (czero)); + ccode.add_expression (czero); } } if (context.module_init_method == m && in_plugin) { // GTypeModule-based plug-in, register types - register_plugin_types (cinit, context.root, new HashSet ()); + register_plugin_types (context.root, new HashSet ()); } foreach (Expression precondition in m.get_preconditions ()) { - var check_stmt = create_precondition_statement (m, creturn_type, precondition); - if (check_stmt != null) { - cinit.append (check_stmt); - } + create_precondition_statement (m, creturn_type, precondition); } } } @@ -585,11 +559,6 @@ public class Vala.CCodeMethodModule : CCodeStructModule { /* Methods imported from a plain C file don't * have a body, e.g. Vala.Parser.parse_file () */ if (m.body != null) { - function.block = (CCodeBlock) m.body.ccodenode; - function.block.line = function.line; - - function.block.prepend_statement (cinit); - if (current_method_inner_error) { /* always separate error parameter and inner_error local variable * as error may be set to NULL but we're always interested in inner errors @@ -599,61 +568,90 @@ public class Vala.CCodeMethodModule : CCodeStructModule { // no initialization necessary, closure struct is zeroed } else { - var cdecl = new CCodeDeclaration ("GError *"); - cdecl.add_declarator (new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL"))); - function.block.add_statement (cdecl); + ccode.add_declaration ("GError *", new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL"))); } } if (m.coroutine) { // epilogue - function.block.add_statement (complete_async ()); + complete_async (); } if (!(m.return_type is VoidType) && !m.return_type.is_real_non_null_struct_type () && !m.coroutine) { // add dummy return if exit block is known to be unreachable to silence C compiler if (m.return_block != null && m.return_block.get_predecessors ().size == 0) { - function.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result"))); + ccode.add_return (new CCodeIdentifier ("result")); } } - cfile.add_function (function); - } else if (m.is_abstract) { - // generate helpful error message if a sublcass does not implement an abstract method. - // This is only meaningful for subclasses implemented in C since the vala compiler would - // complain during compile time of such en error. + if (m is CreationMethod) { + if (current_type_symbol is Class) { + creturn_type = new ObjectType (current_class); + } else { + creturn_type = new VoidType (); + } + - var cblock = new CCodeBlock (); + if (current_type_symbol is Class && gobject_type != null && current_class.is_subtype_of (gobject_type) + && current_class.get_type_parameters ().size > 0 + && !((CreationMethod) m).chain_up) { + var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN, new CCodeIdentifier ("__params_it"), new CCodeIdentifier ("__params")); + var cdofreeparam = new CCodeBlock (); + cdofreeparam.add_statement (new CCodeExpressionStatement (new CCodeUnaryExpression (CCodeUnaryOperator.PREFIX_DECREMENT, new CCodeIdentifier ("__params_it")))); + var cunsetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_unset")); + cunsetcall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (new CCodeIdentifier ("__params_it"), "value"))); + cdofreeparam.add_statement (new CCodeExpressionStatement (cunsetcall)); + ccode.add_statement (new CCodeWhileStatement (ccond, cdofreeparam)); + + var cfreeparams = new CCodeFunctionCall (new CCodeIdentifier ("g_free")); + cfreeparams.add_argument (new CCodeIdentifier ("__params")); + ccode.add_expression (cfreeparams); + } + + if (current_type_symbol is Class) { + CCodeExpression cresult = new CCodeIdentifier ("self"); + if (get_custom_creturn_type (m) != null) { + cresult = new CCodeCastExpression (cresult, get_custom_creturn_type (m)); + } - // add a typecheck statement for "self" - var check_stmt = create_method_type_check_statement (m, creturn_type, current_type_symbol, true, "self"); - if (check_stmt != null) { - cblock.add_statement (check_stmt); + ccode.add_return (cresult); + } } - // add critical warning that this method should not have been called - var type_from_instance_call = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE")); - type_from_instance_call.add_argument (new CCodeIdentifier ("self")); - - var type_name_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name")); - type_name_call.add_argument (type_from_instance_call); + cfile.add_function (ccode); + } + } - var error_string = "\"Type `%%s' does not implement abstract method `%s'\"".printf (m.get_cname ()); + if (m.is_abstract) { + // generate helpful error message if a sublcass does not implement an abstract method. + // This is only meaningful for subclasses implemented in C since the vala compiler would + // complain during compile time of such en error. - var cerrorcall = new CCodeFunctionCall (new CCodeIdentifier ("g_critical")); - cerrorcall.add_argument (new CCodeConstant (error_string)); - cerrorcall.add_argument (type_name_call); + // add a typecheck statement for "self" + create_method_type_check_statement (m, creturn_type, current_type_symbol, true, "self"); - cblock.add_statement (new CCodeExpressionStatement (cerrorcall)); + // add critical warning that this method should not have been called + var type_from_instance_call = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE")); + type_from_instance_call.add_argument (new CCodeIdentifier ("self")); - // add return statement - cblock.add_statement (new CCodeReturnStatement (default_value_for_type (creturn_type, false))); + var type_name_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name")); + type_name_call.add_argument (type_from_instance_call); - function.block = cblock; - cfile.add_function (function); - } + var error_string = "\"Type `%%s' does not implement abstract method `%s'\"".printf (m.get_cname ()); + + var cerrorcall = new CCodeFunctionCall (new CCodeIdentifier ("g_critical")); + cerrorcall.add_argument (new CCodeConstant (error_string)); + cerrorcall.add_argument (type_name_call); + + ccode.add_expression (cerrorcall); + + // add return statement + ccode.add_return (default_value_for_type (creturn_type, false)); + + cfile.add_function (ccode); } + in_static_or_class_context = false; pop_context (); @@ -885,23 +883,13 @@ public class Vala.CCodeMethodModule : CCodeStructModule { } public void generate_vfunc (Method m, DataType return_type, Map cparam_map, Map carg_map, string suffix = "", int direction = 3) { + push_context (new EmitContext ()); + string cname = m.get_cname (); if (suffix == "_finish" && cname.has_suffix ("_async")) { cname = cname.substring (0, cname.length - "_async".length); } var vfunc = new CCodeFunction (cname + suffix); - if (function != null) { - vfunc.line = function.line; - } - - var vblock = new CCodeBlock (); - - foreach (Expression precondition in m.get_preconditions ()) { - var check_stmt = create_precondition_statement (m, return_type, precondition); - if (check_stmt != null) { - vblock.add_statement (check_stmt); - } - } CCodeFunctionCall vcast = null; if (m.parent_symbol is Interface) { @@ -924,47 +912,45 @@ public class Vala.CCodeMethodModule : CCodeStructModule { generate_cparameters (m, cfile, cparam_map, vfunc, null, carg_map, vcall, direction); - CCodeStatement cstmt; + push_function (vfunc); + + foreach (Expression precondition in m.get_preconditions ()) { + create_precondition_statement (m, return_type, precondition); + } + if (return_type is VoidType || return_type.is_real_non_null_struct_type ()) { - cstmt = new CCodeExpressionStatement (vcall); + ccode.add_expression (vcall); } else if (m.get_postconditions ().size == 0) { /* pass method return value */ - cstmt = new CCodeReturnStatement (vcall); + ccode.add_return (vcall); } else { /* store method return value for postconditions */ - var cdecl = new CCodeDeclaration (get_creturn_type (m, return_type.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator ("result", vcall)); - cstmt = cdecl; + ccode.add_declaration (get_creturn_type (m, return_type.get_cname ()), new CCodeVariableDeclarator ("result")); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("result"), vcall)); } - cstmt.line = vfunc.line; - vblock.add_statement (cstmt); if (m.get_postconditions ().size > 0) { foreach (Expression postcondition in m.get_postconditions ()) { - vblock.add_statement (create_postcondition_statement (postcondition)); + create_postcondition_statement (postcondition); } if (!(return_type is VoidType)) { - var cret_stmt = new CCodeReturnStatement (new CCodeIdentifier ("result")); - cret_stmt.line = vfunc.line; - vblock.add_statement (cret_stmt); + ccode.add_return (new CCodeIdentifier ("result")); } } - vfunc.block = vblock; - cfile.add_function (vfunc); + + pop_context (); } - private CCodeStatement? create_method_type_check_statement (Method m, DataType return_type, TypeSymbol t, bool non_null, string var_name) { - if (m.coroutine) { - return null; - } else { - return create_type_check_statement (m, return_type, t, non_null, var_name); + private void create_method_type_check_statement (Method m, DataType return_type, TypeSymbol t, bool non_null, string var_name) { + if (!m.coroutine) { + create_type_check_statement (m, return_type, t, non_null, var_name); } } - private CCodeStatement? create_precondition_statement (CodeNode method_node, DataType ret_type, Expression precondition) { + private void create_precondition_statement (CodeNode method_node, DataType ret_type, Expression precondition) { var ccheck = new CCodeFunctionCall (); ccheck.add_argument ((CCodeExpression) precondition.ccodenode); @@ -986,11 +972,11 @@ public class Vala.CCodeMethodModule : CCodeStructModule { if (cdefault != null) { ccheck.add_argument (cdefault); } else { - return null; + return; } } - return new CCodeExpressionStatement (ccheck); + ccode.add_expression (ccheck); } private TypeSymbol? find_parent_type (Symbol sym) { @@ -1012,19 +998,9 @@ public class Vala.CCodeMethodModule : CCodeStructModule { return; } - function = (CCodeFunction) m.ccodenode; - - DataType creturn_type; - if (current_type_symbol is Class) { - creturn_type = new ObjectType (current_class); - } else { - creturn_type = new VoidType (); - } - // do not generate _new functions for creation methods of abstract classes if (current_type_symbol is Class && !current_class.is_compact && !current_class.is_abstract) { var vfunc = new CCodeFunction (m.get_cname ()); - vfunc.line = function.line; var cparam_map = new HashMap (direct_hash, direct_equal); var carg_map = new HashMap (direct_hash, direct_equal); @@ -1047,17 +1023,6 @@ public class Vala.CCodeMethodModule : CCodeStructModule { cfile.add_function (vfunc); } - - if (current_type_symbol is Class) { - CCodeExpression cresult = new CCodeIdentifier ("self"); - if (get_custom_creturn_type (m) != null) { - cresult = new CCodeCastExpression (cresult, get_custom_creturn_type (m)); - } - - var creturn = new CCodeReturnStatement (); - creturn.return_expression = cresult; - function.block.add_statement (creturn); - } } } diff --git a/codegen/valaccodestructmodule.vala b/codegen/valaccodestructmodule.vala index 04b831c0b..51e5d7f81 100644 --- a/codegen/valaccodestructmodule.vala +++ b/codegen/valaccodestructmodule.vala @@ -142,8 +142,8 @@ public class Vala.CCodeStructModule : CCodeBaseModule { public override void visit_struct (Struct st) { push_context (new EmitContext (st)); - var old_instance_finalize_fragment = instance_finalize_fragment; - instance_finalize_fragment = new CCodeFragment (); + var old_instance_finalize_context = instance_finalize_context; + instance_finalize_context = new EmitContext (); generate_struct_declaration (st, cfile); @@ -154,6 +154,8 @@ public class Vala.CCodeStructModule : CCodeBaseModule { generate_struct_declaration (st, internal_header_file); } + begin_struct_destroy_function (st); + st.accept_children (this); if (context.profile == Profile.GOBJECT && !st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) { @@ -166,7 +168,7 @@ public class Vala.CCodeStructModule : CCodeBaseModule { add_struct_free_function (st); } - instance_finalize_fragment = old_instance_finalize_fragment; + instance_finalize_context = old_instance_finalize_context; pop_context (); } @@ -294,15 +296,14 @@ public class Vala.CCodeStructModule : CCodeBaseModule { } } - append_temp_decl (cfrag, temp_vars); - temp_vars.clear (); - function.block = cblock; cfile.add_function (function); } - void add_struct_destroy_function (Struct st) { + void begin_struct_destroy_function (Struct st) { + push_context (instance_finalize_context); + var function = new CCodeFunction (st.get_destroy_function (), "void"); if (st.access == SymbolAccessibility.PRIVATE) { function.modifiers = CCodeModifiers.STATIC; @@ -310,13 +311,13 @@ public class Vala.CCodeStructModule : CCodeBaseModule { function.add_parameter (new CCodeFormalParameter ("self", st.get_cname () + "*")); - var cblock = new CCodeBlock (); - - cblock.add_statement (instance_finalize_fragment); + push_function (function); - function.block = cblock; + pop_context (); + } - cfile.add_function (function); + void add_struct_destroy_function (Struct st) { + cfile.add_function (instance_finalize_context.ccode); } } diff --git a/codegen/valadovaarraymodule.vala b/codegen/valadovaarraymodule.vala index 93978f1b7..182ffce34 100644 --- a/codegen/valadovaarraymodule.vala +++ b/codegen/valadovaarraymodule.vala @@ -38,7 +38,7 @@ public class Vala.DovaArrayModule : DovaMethodCallModule { var name_cnode = new CCodeIdentifier (temp_var.name); int i = 0; - temp_vars.add (temp_var); + emit_temp_var (temp_var); append_initializer_list (ce, name_cnode, expr.initializer_list, ref i); diff --git a/codegen/valadovaassignmentmodule.vala b/codegen/valadovaassignmentmodule.vala index 3d21f33e9..1219a44e6 100644 --- a/codegen/valadovaassignmentmodule.vala +++ b/codegen/valadovaassignmentmodule.vala @@ -102,13 +102,13 @@ public class Vala.DovaAssignmentModule : DovaMemberAccessModule { var lhs_value_type = assignment.left.value_type.copy (); string lhs_temp_name = "_tmp%d_".printf (next_temp_var_id++); var lhs_temp = new LocalVariable (lhs_value_type, "*" + lhs_temp_name); - temp_vars.add (lhs_temp); + emit_temp_var (lhs_temp); outer_ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (lhs_temp_name), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, lhs))); lhs = new CCodeParenthesizedExpression (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (lhs_temp_name))); } var temp_decl = get_temp_variable (assignment.left.value_type); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_decl.name), rhs)); if (unref_old) { /* unref old value */ diff --git a/codegen/valadovabasemodule.vala b/codegen/valadovabasemodule.vala index 28aaefffc..8c5fe91ff 100644 --- a/codegen/valadovabasemodule.vala +++ b/codegen/valadovabasemodule.vala @@ -30,7 +30,8 @@ public class Vala.DovaBaseModule : CodeGenerator { public Symbol? current_symbol; public ArrayList symbol_stack = new ArrayList (); public TryStatement current_try; - public ArrayList temp_vars = new ArrayList (); + public CCodeFunction ccode; + public ArrayList ccode_stack = new ArrayList (); public ArrayList temp_ref_vars = new ArrayList (); public int next_temp_var_id; public Map variable_name_map = new HashMap (str_hash, str_equal); @@ -150,21 +151,15 @@ public class Vala.DovaBaseModule : CodeGenerator { string? csource_filename; - public CCodeFragment module_init_fragment; - public CCodeFragment instance_init_fragment; - public CCodeFragment instance_finalize_fragment; + public CCodeFunction ccode { get { return emit_context.ccode; } } - // code nodes to be inserted before the current statement - // used by async method calls in coroutines - public CCodeFragment pre_statement_fragment; - - /* all temporary variables */ - public ArrayList temp_vars { get { return emit_context.temp_vars; } } /* temporary variables that own their content */ public ArrayList temp_ref_vars { get { return emit_context.temp_ref_vars; } } /* (constant) hash table with all reserved identifiers in the generated code */ Set reserved_identifiers; + public List static_fields = new ArrayList (); + public int next_temp_var_id { get { return emit_context.next_temp_var_id; } set { emit_context.next_temp_var_id = value; } @@ -276,7 +271,6 @@ public class Vala.DovaBaseModule : CodeGenerator { header_file.is_header = true; cfile = new CCodeFile (); - module_init_fragment = new CCodeFragment (); if (context.nostdpkg) { header_file.add_include ("dova-types.h"); @@ -331,6 +325,16 @@ public class Vala.DovaBaseModule : CodeGenerator { } } + public void push_function (CCodeFunction func) { + emit_context.ccode_stack.add (ccode); + emit_context.ccode = func; + } + + public void pop_function () { + emit_context.ccode = emit_context.ccode_stack[emit_context.ccode_stack.size - 1]; + emit_context.ccode_stack.remove_at (emit_context.ccode_stack.size - 1); + } + public bool add_symbol_declaration (CCodeFile decl_space, Symbol sym, string name) { if (decl_space.add_declaration (name)) { return true; @@ -458,71 +462,23 @@ public class Vala.DovaBaseModule : CodeGenerator { } public override void visit_field (Field f) { - if (f.initializer != null) { - f.initializer.emit (this); - } - - var cl = f.parent_symbol as Class; - - CCodeExpression lhs = null; - - string field_ctype = f.variable_type.get_cname (); - if (f.is_volatile) { - field_ctype = "volatile " + field_ctype; - } - - if (f.binding == MemberBinding.INSTANCE) { - if (cl != null && f.is_internal_symbol ()) { - var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null)))); - priv_call.add_argument (new CCodeIdentifier ("this")); - lhs = new CCodeMemberAccess.pointer (priv_call, f.get_cname ()); - } else { - lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("this"), f.get_cname ()); - } - - if (f.initializer != null) { - var rhs = (CCodeExpression) f.initializer.ccodenode; - - instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs))); - - append_temp_decl (instance_init_fragment, temp_vars); - temp_vars.clear (); - } - - if (requires_destroy (f.variable_type) && instance_finalize_fragment != null) { - var this_access = new MemberAccess.simple ("this"); - this_access.value_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol); - - var field_st = f.parent_symbol as Struct; - if (field_st != null && !field_st.is_simple_type ()) { - this_access.ccodenode = new CCodeIdentifier ("(*this)"); - } else { - this_access.ccodenode = new CCodeIdentifier ("this"); - } - - var ma = new MemberAccess (this_access, f.name); - ma.symbol_reference = f; - instance_finalize_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.variable_type, ma))); - } - } else { + if (f.binding == MemberBinding.STATIC) { generate_field_declaration (f, cfile); if (!f.is_internal_symbol ()) { generate_field_declaration (f, header_file); } - lhs = new CCodeIdentifier (f.get_cname ()); - var var_decl = new CCodeVariableDeclarator (f.get_cname ()); var_decl.initializer = default_value_for_type (f.variable_type, true); if (f.initializer != null) { - var rhs = (CCodeExpression) f.initializer.ccodenode; - - module_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs))); + static_fields.add (f); + } - append_temp_decl (module_init_fragment, temp_vars); - temp_vars.clear (); + string field_ctype = f.variable_type.get_cname (); + if (f.is_volatile) { + field_ctype = "volatile " + field_ctype; } var var_def = new CCodeDeclaration (field_ctype); @@ -644,16 +600,6 @@ public class Vala.DovaBaseModule : CodeGenerator { public virtual void generate_property_accessor_declaration (PropertyAccessor acc, CCodeFile decl_space) { } - public override void visit_destructor (Destructor d) { - d.body.emit (this); - - CCodeFragment cfrag = new CCodeFragment (); - - cfrag.append (d.body.ccodenode); - - d.ccodenode = cfrag; - } - public int get_block_id (Block b) { int result = block_map[b]; if (result == 0) { @@ -663,7 +609,7 @@ public class Vala.DovaBaseModule : CodeGenerator { return result; } - void capture_parameter (FormalParameter param, CCodeStruct data, CCodeBlock cblock, int block_id, CCodeBlock free_block) { + void capture_parameter (FormalParameter param, CCodeStruct data, int block_id, CCodeBlock free_block) { generate_type_declaration (param.variable_type, cfile); var param_type = param.variable_type.copy (); @@ -682,7 +628,7 @@ public class Vala.DovaBaseModule : CodeGenerator { 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))); + ccode.add_expression (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); @@ -695,17 +641,11 @@ public class Vala.DovaBaseModule : CodeGenerator { public override void visit_block (Block b) { emit_context.push_symbol (b); - foreach (Statement stmt in b.get_statements ()) { - stmt.emit (this); - } - var local_vars = b.get_local_variables (); - foreach (LocalVariable local in local_vars) { - local.active = false; - } - - var cblock = new CCodeBlock (); + if (b.parent_node is Block || b.parent_node is SwitchStatement) { + ccode.open_block (); + } if (b.captured) { var parent_block = next_closure_block (b.parent_symbol); @@ -759,7 +699,7 @@ public class Vala.DovaBaseModule : CodeGenerator { 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); + ccode.add_statement (data_decl); if (parent_block != null) { int parent_block_id = get_block_id (parent_block); @@ -767,13 +707,13 @@ public class Vala.DovaBaseModule : CodeGenerator { 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))); + ccode.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_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))); + ccode.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) { @@ -782,25 +722,15 @@ public class Vala.DovaBaseModule : CodeGenerator { // 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); + capture_parameter (param, data, 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); + capture_parameter (acc.value_parameter, data, 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)); @@ -858,18 +788,8 @@ public class Vala.DovaBaseModule : CodeGenerator { cfile.add_function (unref_fun); } - foreach (CodeNode stmt in b.get_statements ()) { - if (stmt.error) { - continue; - } - - if (stmt.ccodenode is CCodeFragment) { - foreach (CCodeNode cstmt in ((CCodeFragment) stmt.ccodenode).get_children ()) { - cblock.add_statement (cstmt); - } - } else { - cblock.add_statement (stmt.ccodenode); - } + foreach (Statement stmt in b.get_statements ()) { + stmt.emit (this); } // free in reverse order @@ -878,7 +798,7 @@ public class Vala.DovaBaseModule : CodeGenerator { 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))); + ccode.add_statement (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma))); } } @@ -888,7 +808,7 @@ public class Vala.DovaBaseModule : CodeGenerator { if (!param.captured && requires_destroy (param.variable_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.variable_type, ma))); + ccode.add_statement (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma))); } } } @@ -898,30 +818,18 @@ public class Vala.DovaBaseModule : CodeGenerator { 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)); + ccode.add_statement (new CCodeExpressionStatement (data_unref)); } - b.ccodenode = cblock; + if (b.parent_node is Block || b.parent_node is SwitchStatement) { + ccode.close (); + } emit_context.pop_symbol (); } - public override void visit_empty_statement (EmptyStatement stmt) { - stmt.ccodenode = new CCodeEmptyStatement (); - } - public override void visit_declaration_statement (DeclarationStatement stmt) { stmt.declaration.accept (this); - - stmt.ccodenode = stmt.declaration.ccodenode; - - var local = stmt.declaration as LocalVariable; - if (local != null && local.initializer != null) { - create_temp_decl (stmt, local.initializer.temp_vars); - } - - create_temp_decl (stmt, temp_vars); - temp_vars.clear (); } public CCodeExpression get_variable_cexpression (string name) { @@ -957,23 +865,16 @@ public class Vala.DovaBaseModule : CodeGenerator { rhs = (CCodeExpression) local.initializer.ccodenode; } - var cfrag = new CCodeFragment (); - - if (pre_statement_fragment != null) { - cfrag.append (pre_statement_fragment); - pre_statement_fragment = null; - } - 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))); + ccode.add_expression (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); + ccode.add_statement (cdecl); // try to initialize uninitialized variables // initialization not necessary for variables stored in closure @@ -984,11 +885,9 @@ public class Vala.DovaBaseModule : CodeGenerator { } if (local.initializer != null && local.initializer.tree_can_fail) { - add_simple_check (local.initializer, cfrag); + add_simple_check (local.initializer); } - local.ccodenode = cfrag; - local.active = true; } @@ -1209,24 +1108,6 @@ public class Vala.DovaBaseModule : CodeGenerator { * expression */ - /* can't automatically deep copy lists yet, so do it - * manually for now - * replace with - * expr.temp_vars = temp_vars; - * when deep list copying works - */ - if (temp_vars.size > 0) { - if (expr.temp_vars == null) { - expr.temp_vars = new ArrayList (); - } else { - expr.temp_vars.clear (); - } - foreach (LocalVariable local in temp_vars) { - expr.temp_vars.add (local); - } - temp_vars.clear (); - } - if (((List) temp_ref_vars).size == 0) { /* nothing to do without temporary variables */ return; @@ -1238,7 +1119,7 @@ public class Vala.DovaBaseModule : CodeGenerator { } var full_expr_var = get_temp_variable (expr_type, true, expr); - expr.add_temp_var (full_expr_var); + emit_temp_var (full_expr_var); var expr_list = new CCodeCommaExpression (); expr_list.append_expression (new CCodeAssignment (get_variable_cexpression (full_expr_var.name), (CCodeExpression) expr.ccodenode)); @@ -1256,58 +1137,53 @@ public class Vala.DovaBaseModule : CodeGenerator { temp_ref_vars.clear (); } - public void append_temp_decl (CCodeFragment cfrag, List? temp_vars) { - if (temp_vars == null) { - return; - } - foreach (LocalVariable local in temp_vars) { - var cdecl = new CCodeDeclaration (local.variable_type.get_cname ()); + public void emit_temp_var (LocalVariable local) { + var cdecl = new CCodeDeclaration (local.variable_type.get_cname ()); - var vardecl = new CCodeVariableDeclarator (local.name, null, local.variable_type.get_cdeclarator_suffix ()); - // sets #line - local.ccodenode = vardecl; - cdecl.add_declarator (vardecl); + var vardecl = new CCodeVariableDeclarator (local.name, null, local.variable_type.get_cdeclarator_suffix ()); + // sets #line + local.ccodenode = vardecl; + cdecl.add_declarator (vardecl); - var st = local.variable_type.data_type as Struct; - var array_type = local.variable_type as ArrayType; + var st = local.variable_type.data_type as Struct; + var array_type = local.variable_type as ArrayType; - if (local.name.has_prefix ("*")) { - // do not dereference unintialized variable - // initialization is not needed for these special - // pointer temp variables - // used to avoid side-effects in assignments - } else if (local.variable_type is GenericType) { - var value_size = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_get_value_size")); - value_size.add_argument (get_type_id_expression (local.variable_type)); - - var alloca_call = new CCodeFunctionCall (new CCodeIdentifier ("alloca")); - alloca_call.add_argument (value_size); + if (local.name.has_prefix ("*")) { + // do not dereference unintialized variable + // initialization is not needed for these special + // pointer temp variables + // used to avoid side-effects in assignments + } else if (local.variable_type is GenericType) { + var value_size = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_get_value_size")); + value_size.add_argument (get_type_id_expression (local.variable_type)); - var memset_call = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - memset_call.add_argument (alloca_call); - memset_call.add_argument (new CCodeConstant ("0")); - memset_call.add_argument (value_size); + var alloca_call = new CCodeFunctionCall (new CCodeIdentifier ("alloca")); + alloca_call.add_argument (value_size); - vardecl.initializer = memset_call; - vardecl.init0 = true; - } else if (!local.variable_type.nullable && - (st != null && st.get_fields ().size > 0) || - (array_type != null && array_type.fixed_length)) { - // 0-initialize struct with struct initializer { 0 } - // necessary as they will be passed by reference - var clist = new CCodeInitializerList (); - clist.append (new CCodeConstant ("0")); + var memset_call = new CCodeFunctionCall (new CCodeIdentifier ("memset")); + memset_call.add_argument (alloca_call); + memset_call.add_argument (new CCodeConstant ("0")); + memset_call.add_argument (value_size); - vardecl.initializer = clist; - vardecl.init0 = true; - } else if (local.variable_type.is_reference_type_or_type_parameter () || - local.variable_type.nullable) { - vardecl.initializer = new CCodeConstant ("NULL"); - vardecl.init0 = true; - } + vardecl.initializer = memset_call; + vardecl.init0 = true; + } else if (!local.variable_type.nullable && + (st != null && st.get_fields ().size > 0) || + (array_type != null && array_type.fixed_length)) { + // 0-initialize struct with struct initializer { 0 } + // necessary as they will be passed by reference + var clist = new CCodeInitializerList (); + clist.append (new CCodeConstant ("0")); - cfrag.append (cdecl); + vardecl.initializer = clist; + vardecl.init0 = true; + } else if (local.variable_type.is_reference_type_or_type_parameter () || + local.variable_type.nullable) { + vardecl.initializer = new CCodeConstant ("NULL"); + vardecl.init0 = true; } + + ccode.add_statement (cdecl); } public override void visit_expression_statement (ExpressionStatement stmt) { @@ -1316,67 +1192,25 @@ public class Vala.DovaBaseModule : CodeGenerator { return; } - stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.expression.ccodenode); - - if (stmt.tree_can_fail && stmt.expression.tree_can_fail) { - // simple case, no node breakdown necessary - - var cfrag = new CCodeFragment (); - - cfrag.append (stmt.ccodenode); - - add_simple_check (stmt.expression, cfrag); - - stmt.ccodenode = cfrag; - } - - /* free temporary objects */ - - if (((List) temp_vars).size == 0 - && pre_statement_fragment == null) { - /* nothing to do without temporary variables */ - return; - } - - var cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - - if (pre_statement_fragment != null) { - cfrag.append (pre_statement_fragment); - pre_statement_fragment = null; - } - - cfrag.append (stmt.ccodenode); + ccode.add_expression ((CCodeExpression) stmt.expression.ccodenode); + /* free temporary objects and handle errors */ foreach (LocalVariable local in temp_ref_vars) { var ma = new MemberAccess.simple (local.name); ma.symbol_reference = local; - cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (local.name), local.variable_type, ma))); + ma.value_type = local.variable_type.copy (); + ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)); } - stmt.ccodenode = cfrag; - - temp_vars.clear (); - temp_ref_vars.clear (); - } - - public void create_temp_decl (Statement stmt, List? temp_vars) { - /* declare temporary variables */ - - if (temp_vars == null || temp_vars.size == 0) { - /* nothing to do without temporary variables */ - return; + if (stmt.tree_can_fail && stmt.expression.tree_can_fail) { + // simple case, no node breakdown necessary + add_simple_check (stmt.expression); } - var cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - - cfrag.append (stmt.ccodenode); - - stmt.ccodenode = cfrag; + temp_ref_vars.clear (); } - public virtual void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop = false) { + public virtual void append_local_free (Symbol sym, bool stop_at_loop = false) { var b = (Block) sym; var local_vars = b.get_local_variables (); @@ -1386,7 +1220,7 @@ public class Vala.DovaBaseModule : CodeGenerator { 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))); + ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)); } } @@ -1395,7 +1229,7 @@ public class Vala.DovaBaseModule : CodeGenerator { 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)); + ccode.add_expression (data_unref); } if (stop_at_loop) { @@ -1407,13 +1241,13 @@ public class Vala.DovaBaseModule : CodeGenerator { } if (sym.parent_symbol is Block) { - append_local_free (sym.parent_symbol, cfrag, stop_at_loop); + append_local_free (sym.parent_symbol, stop_at_loop); } else if (sym.parent_symbol is Method) { - append_param_free ((Method) sym.parent_symbol, cfrag); + append_param_free ((Method) sym.parent_symbol); } } - public void append_error_free (Symbol sym, CCodeFragment cfrag, TryStatement current_try) { + public void append_error_free (Symbol sym, TryStatement current_try) { var b = (Block) sym; var local_vars = b.get_local_variables (); @@ -1423,7 +1257,7 @@ public class Vala.DovaBaseModule : CodeGenerator { 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))); + ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)); } } @@ -1432,7 +1266,7 @@ public class Vala.DovaBaseModule : CodeGenerator { 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)); + ccode.add_expression (data_unref); } if (sym == current_try.body) { @@ -1440,40 +1274,27 @@ public class Vala.DovaBaseModule : CodeGenerator { } if (sym.parent_symbol is Block) { - append_error_free (sym.parent_symbol, cfrag, current_try); + append_error_free (sym.parent_symbol, current_try); } else if (sym.parent_symbol is Method) { - append_param_free ((Method) sym.parent_symbol, cfrag); + append_param_free ((Method) sym.parent_symbol); } } - private void append_param_free (Method m, CCodeFragment cfrag) { + private void append_param_free (Method m) { foreach (FormalParameter param in m.get_parameters ()) { if (requires_destroy (param.variable_type) && param.direction == ParameterDirection.IN) { var ma = new MemberAccess.simple (param.name); ma.symbol_reference = param; - cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma))); + ccode.add_expression (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma)); } } } - public void create_local_free (CodeNode stmt, bool stop_at_loop = false) { - var cfrag = new CCodeFragment (); - - append_local_free (current_symbol, cfrag, stop_at_loop); - - cfrag.append (stmt.ccodenode); - stmt.ccodenode = cfrag; - } - public override void visit_return_statement (ReturnStatement stmt) { - var cfrag = new CCodeFragment (); - // free local variables - append_local_free (current_symbol, cfrag); - - cfrag.append (new CCodeReturnStatement ((current_return_type is VoidType) ? null : new CCodeIdentifier ("result"))); + append_local_free (current_symbol); - stmt.ccodenode = cfrag; + ccode.add_return ((current_return_type is VoidType) ? null : new CCodeIdentifier ("result")); } public override void visit_delete_statement (DeleteStatement stmt) { @@ -1485,7 +1306,7 @@ public class Vala.DovaBaseModule : CodeGenerator { var ccall = new CCodeFunctionCall (get_destroy_func_expression (type)); ccall.add_argument ((CCodeExpression) stmt.expression.ccodenode); - stmt.ccodenode = new CCodeExpressionStatement (ccall); + ccode.add_expression (ccall); } public override void visit_expression (Expression expr) { @@ -1555,7 +1376,7 @@ public class Vala.DovaBaseModule : CodeGenerator { // assign current value to temp variable var temp_decl = get_temp_variable (prop.property_type, true, expr); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_decl.name), (CCodeExpression) expr.inner.ccodenode)); // increment/decrement property @@ -1647,7 +1468,7 @@ public class Vala.DovaBaseModule : CodeGenerator { // (copy (&temp, 0, &expr, 0), temp) var decl = get_temp_variable (expression_type, false, node); - temp_vars.add (decl); + emit_temp_var (decl); var ctemp = get_variable_cexpression (decl.name); @@ -1691,7 +1512,7 @@ public class Vala.DovaBaseModule : CodeGenerator { return ccall; } else { var decl = get_temp_variable (expression_type, false, node); - temp_vars.add (decl); + emit_temp_var (decl); var ctemp = get_variable_cexpression (decl.name); @@ -1752,7 +1573,7 @@ public class Vala.DovaBaseModule : CodeGenerator { if (struct_by_ref || expr.get_object_initializer ().size > 0) { // value-type initialization or object creation expression with object initializer var temp_decl = get_temp_variable (expr.type_reference, false, expr); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); instance = get_variable_cexpression (get_variable_cname (temp_decl.name)); } @@ -1914,7 +1735,7 @@ public class Vala.DovaBaseModule : CodeGenerator { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (arg.target_type); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), cexpr)); ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_var.name))); @@ -1970,7 +1791,7 @@ public class Vala.DovaBaseModule : CodeGenerator { if (expr.type_reference.data_type != null && expr.type_reference.data_type.get_full_name () == "Dova.Value") { // box value var temp_decl = get_temp_variable (expr.inner.value_type, true, expr); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); var cvar = get_variable_cexpression (temp_decl.name); var ccomma = new CCodeCommaExpression (); @@ -1987,7 +1808,7 @@ public class Vala.DovaBaseModule : CodeGenerator { } else if (expr.inner.value_type.data_type != null && expr.inner.value_type.data_type.get_full_name () == "Dova.Value") { // unbox value var temp_decl = get_temp_variable (expr.type_reference, true, expr); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); var cvar = get_variable_cexpression (temp_decl.name); var ccomma = new CCodeCommaExpression (); @@ -2030,7 +1851,7 @@ public class Vala.DovaBaseModule : CodeGenerator { /* (tmp = var, var = null, tmp) */ var ccomma = new CCodeCommaExpression (); var temp_decl = get_temp_variable (expr.value_type, true, expr); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); var cvar = get_variable_cexpression (temp_decl.name); ccomma.append_expression (new CCodeAssignment (cvar, (CCodeExpression) expr.inner.ccodenode)); @@ -2178,7 +1999,7 @@ public class Vala.DovaBaseModule : CodeGenerator { // treat void* special to not leak memory with void* method parameters } else if (requires_destroy (expression_type)) { var decl = get_temp_variable (expression_type, true, expression_type); - temp_vars.add (decl); + emit_temp_var (decl); temp_ref_vars.insert (0, decl); cexpr = new CCodeAssignment (get_variable_cexpression (decl.name), cexpr); } @@ -2442,6 +2263,6 @@ public class Vala.DovaBaseModule : CodeGenerator { return false; } - public virtual void add_simple_check (CodeNode node, CCodeFragment cfrag, bool always_fails = false) { + public virtual void add_simple_check (CodeNode node, bool always_fails = false) { } } diff --git a/codegen/valadovacontrolflowmodule.vala b/codegen/valadovacontrolflowmodule.vala index 0fddf3f97..93894ed46 100644 --- a/codegen/valadovacontrolflowmodule.vala +++ b/codegen/valadovacontrolflowmodule.vala @@ -22,51 +22,29 @@ public class Vala.DovaControlFlowModule : DovaMethodModule { public override void visit_if_statement (IfStatement stmt) { + ccode.open_if ((CCodeExpression) stmt.condition.ccodenode); + stmt.true_statement.emit (this); - if (stmt.false_statement != null) { - stmt.false_statement.emit (this); - } if (stmt.false_statement != null) { - stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode, (CCodeStatement) stmt.false_statement.ccodenode); - } else { - stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode); + ccode.add_else (); + stmt.false_statement.emit (this); } - create_temp_decl (stmt, stmt.condition.temp_vars); + ccode.close (); } public override void visit_switch_statement (SwitchStatement stmt) { - foreach (SwitchSection section in stmt.get_sections ()) { - section.emit (this); - } - - var cswitch = new CCodeSwitchStatement ((CCodeExpression) stmt.expression.ccodenode); - stmt.ccodenode = cswitch; + ccode.open_switch ((CCodeExpression) stmt.expression.ccodenode); foreach (SwitchSection section in stmt.get_sections ()) { if (section.has_default_label ()) { - cswitch.add_statement (new CCodeLabel ("default")); - var cdefaultblock = new CCodeBlock (); - cswitch.add_statement (cdefaultblock); - foreach (CodeNode default_stmt in section.get_statements ()) { - cdefaultblock.add_statement (default_stmt.ccodenode); - } - continue; - } - - foreach (SwitchLabel label in section.get_labels ()) { - cswitch.add_statement (new CCodeCaseStatement ((CCodeExpression) label.expression.ccodenode)); - } - - var cblock = new CCodeBlock (); - cswitch.add_statement (cblock); - foreach (CodeNode body_stmt in section.get_statements ()) { - cblock.add_statement (body_stmt.ccodenode); + ccode.add_default (); } + section.emit (this); } - create_temp_decl (stmt, stmt.expression.temp_vars); + ccode.close (); } public override void visit_switch_label (SwitchLabel label) { @@ -74,25 +52,29 @@ public class Vala.DovaControlFlowModule : DovaMethodModule { label.expression.emit (this); visit_end_full_expression (label.expression); + + ccode.add_case ((CCodeExpression) label.expression.ccodenode); } } public override void visit_loop (Loop stmt) { + ccode.open_while (new CCodeConstant ("true")); + stmt.body.emit (this); - stmt.ccodenode = new CCodeWhileStatement (new CCodeConstant ("true"), (CCodeStatement) stmt.body.ccodenode); + ccode.close (); } public override void visit_break_statement (BreakStatement stmt) { - stmt.ccodenode = new CCodeBreakStatement (); + append_local_free (current_symbol, true); - create_local_free (stmt, true); + ccode.add_break (); } public override void visit_continue_statement (ContinueStatement stmt) { - stmt.ccodenode = new CCodeContinueStatement (); + append_local_free (current_symbol, true); - create_local_free (stmt, true); + ccode.add_continue (); } } diff --git a/codegen/valadovaerrormodule.vala b/codegen/valadovaerrormodule.vala index f38bafde1..be2fcafd2 100644 --- a/codegen/valadovaerrormodule.vala +++ b/codegen/valadovaerrormodule.vala @@ -27,67 +27,44 @@ public class Vala.DovaErrorModule : DovaDelegateModule { private bool is_in_catch = false; public override void visit_throw_statement (ThrowStatement stmt) { - var cfrag = new CCodeFragment (); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("dova_error"), (CCodeExpression) stmt.error_expression.ccodenode)); - // method will fail - var cassign = new CCodeAssignment (new CCodeIdentifier ("dova_error"), (CCodeExpression) stmt.error_expression.ccodenode); - cfrag.append (new CCodeExpressionStatement (cassign)); - - add_simple_check (stmt, cfrag, true); - - stmt.ccodenode = cfrag; - - create_temp_decl (stmt, stmt.error_expression.temp_vars); + add_simple_check (stmt, true); } - public virtual CCodeStatement return_with_exception () { - var cerror_block = new CCodeBlock (); - + public void return_with_exception () { // propagate error // nothing to do // free local variables - var free_frag = new CCodeFragment (); - append_local_free (current_symbol, free_frag, false); - cerror_block.add_statement (free_frag); + append_local_free (current_symbol, false); if (current_method is CreationMethod && current_method.parent_symbol is Class) { var cl = current_method.parent_symbol as Class; var unref_call = new CCodeFunctionCall (new CCodeIdentifier (cl.get_unref_function ())); unref_call.add_argument (new CCodeIdentifier ("this")); - cerror_block.add_statement (new CCodeExpressionStatement (unref_call)); - cerror_block.add_statement (new CCodeReturnStatement ()); + ccode.add_expression (unref_call); + ccode.add_return (); } else if (current_return_type is VoidType) { - cerror_block.add_statement (new CCodeReturnStatement ()); + ccode.add_return (); } else { - cerror_block.add_statement (new CCodeReturnStatement (default_value_for_type (current_return_type, false))); + ccode.add_return (default_value_for_type (current_return_type, false)); } - - return cerror_block; } - CCodeStatement uncaught_error_statement (CCodeBlock? block = null, bool unexpected = false) { - var cerror_block = block; - if (cerror_block == null) { - cerror_block = new CCodeBlock (); - } - + void uncaught_error_statement () { // free local variables - var free_frag = new CCodeFragment (); - append_local_free (current_symbol, free_frag, false); - cerror_block.add_statement (free_frag); + append_local_free (current_symbol, false); // TODO log uncaught error as critical warning if (current_method is CreationMethod) { - cerror_block.add_statement (new CCodeReturnStatement ()); + ccode.add_return (); } else if (current_return_type is VoidType) { - cerror_block.add_statement (new CCodeReturnStatement ()); + ccode.add_return (); } else if (current_return_type != null) { - cerror_block.add_statement (new CCodeReturnStatement (default_value_for_type (current_return_type, false))); + ccode.add_return (default_value_for_type (current_return_type, false)); } - - return cerror_block; } bool in_finally_block (CodeNode node) { @@ -102,17 +79,20 @@ public class Vala.DovaErrorModule : DovaDelegateModule { return false; } - public override void add_simple_check (CodeNode node, CCodeFragment cfrag, bool always_fails = false) { - CCodeStatement cerror_handler = null; + public override void add_simple_check (CodeNode node, bool always_fails = false) { + if (always_fails) { + // inner_error is always set, avoid unnecessary if statement + // eliminates C warnings + } else { + var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("dova_error"), new CCodeConstant ("NULL")); + ccode.open_if (ccond); + } if (current_try != null) { // surrounding try found - var cerror_block = new CCodeBlock (); // free local variables - var free_frag = new CCodeFragment (); - append_error_free (current_symbol, free_frag, current_try); - cerror_block.add_statement (free_frag); + append_error_free (current_symbol, current_try); var error_types = new ArrayList (); foreach (DataType node_error_type in node.get_error_types ()) { @@ -135,24 +115,23 @@ public class Vala.DovaErrorModule : DovaDelegateModule { } handled_error_types.clear (); - // go to catch clause if error domain matches - var cgoto_stmt = new CCodeGotoStatement (clause.clabel_name); - if (clause.error_type.equals (new ObjectType (error_class))) { // general catch clause, this should be the last one has_general_catch_clause = true; - cerror_block.add_statement (cgoto_stmt); + ccode.add_goto (clause.clabel_name); break; } else { var catch_type = clause.error_type as ObjectType; - var cgoto_block = new CCodeBlock (); - cgoto_block.add_statement (cgoto_stmt); var type_check = new CCodeFunctionCall (new CCodeIdentifier ("any_is_a")); type_check.add_argument (new CCodeIdentifier ("dova_error")); type_check.add_argument (new CCodeFunctionCall (new CCodeIdentifier ("%s_type_get".printf (catch_type.type_symbol.get_lower_case_cname ())))); - cerror_block.add_statement (new CCodeIfStatement (type_check, cgoto_block)); + ccode.open_if (type_check); + + // go to catch clause if error domain matches + ccode.add_goto (clause.clabel_name); + ccode.close (); } } } @@ -164,16 +143,13 @@ public class Vala.DovaErrorModule : DovaDelegateModule { } else if (error_types.size > 0) { // go to finally clause if no catch clause matches // and there are still unhandled error types - cerror_block.add_statement (new CCodeGotoStatement ("__finally%d".printf (current_try_id))); + ccode.add_goto ("__finally%d".printf (current_try_id)); } else if (in_finally_block (node)) { // do not check unexpected errors happening within finally blocks // as jump out of finally block is not supported } else { - // should never happen with correct bindings - uncaught_error_statement (cerror_block, true); + assert_not_reached (); } - - cerror_handler = cerror_block; } else if (current_method != null && current_method.get_error_types ().size > 0) { // current method can fail, propagate error CCodeExpression ccond = null; @@ -197,25 +173,20 @@ public class Vala.DovaErrorModule : DovaDelegateModule { } if (ccond == null) { - cerror_handler = return_with_exception (); + return_with_exception (); } else { - var cerror_block = new CCodeBlock (); - cerror_block.add_statement (new CCodeIfStatement (ccond, - return_with_exception (), - uncaught_error_statement ())); - cerror_handler = cerror_block; + ccode.open_if (ccond); + return_with_exception (); + ccode.add_else (); + uncaught_error_statement (); + ccode.close (); } } else { - cerror_handler = uncaught_error_statement (); + uncaught_error_statement (); } - if (always_fails) { - // inner_error is always set, avoid unnecessary if statement - // eliminates C warnings - cfrag.append (cerror_handler); - } else { - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("dova_error"), new CCodeConstant ("NULL")); - cfrag.append (new CCodeIfStatement (ccond, cerror_handler)); + if (!always_fails) { + ccode.close (); } } @@ -233,15 +204,12 @@ public class Vala.DovaErrorModule : DovaDelegateModule { clause.clabel_name = "__catch%d_%s".printf (this_try_id, clause.error_type.get_lower_case_cname ()); } - if (stmt.finally_body != null) { - stmt.finally_body.emit (this); - } - is_in_catch = false; stmt.body.emit (this); is_in_catch = true; foreach (CatchClause clause in stmt.get_catch_clauses ()) { + ccode.add_goto ("__finally%d".printf (this_try_id)); clause.emit (this); } @@ -249,35 +217,22 @@ public class Vala.DovaErrorModule : DovaDelegateModule { current_try_id = old_try_id; is_in_catch = old_is_in_catch; - var cfrag = new CCodeFragment (); - cfrag.append (stmt.body.ccodenode); - - foreach (CatchClause clause in stmt.get_catch_clauses ()) { - cfrag.append (new CCodeGotoStatement ("__finally%d".printf (this_try_id))); - cfrag.append (clause.ccodenode); - } - - cfrag.append (new CCodeLabel ("__finally%d".printf (this_try_id))); + ccode.add_label ("__finally%d".printf (this_try_id)); if (stmt.finally_body != null) { - cfrag.append (stmt.finally_body.ccodenode); + stmt.finally_body.emit (this); } // check for errors not handled by this try statement // may be handled by outer try statements or propagated - add_simple_check (stmt, cfrag, !stmt.after_try_block_reachable); - - stmt.ccodenode = cfrag; + add_simple_check (stmt, !stmt.after_try_block_reachable); } public override void visit_catch_clause (CatchClause clause) { generate_type_declaration (clause.error_type, cfile); - clause.body.emit (this); - - var cfrag = new CCodeFragment (); - cfrag.append (new CCodeLabel (clause.clabel_name)); + ccode.add_label (clause.clabel_name); - var cblock = new CCodeBlock (); + ccode.open_block (); string variable_name; if (clause.variable_name != null) { @@ -289,23 +244,21 @@ public class Vala.DovaErrorModule : DovaDelegateModule { if (clause.variable_name != null) { var cdecl = new CCodeDeclaration (clause.error_type.get_cname ()); cdecl.add_declarator (new CCodeVariableDeclarator (variable_name, new CCodeIdentifier ("dova_error"))); - cblock.add_statement (cdecl); + ccode.add_statement (cdecl); } else { // error object is not used within catch statement, clear it var cclear = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_unref")); cclear.add_argument (new CCodeIdentifier ("dova_error")); - cblock.add_statement (new CCodeExpressionStatement (cclear)); + ccode.add_statement (new CCodeExpressionStatement (cclear)); } - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("dova_error"), new CCodeConstant ("NULL")))); + ccode.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("dova_error"), new CCodeConstant ("NULL")))); - cblock.add_statement (clause.body.ccodenode); - - cfrag.append (cblock); + clause.body.emit (this); - clause.ccodenode = cfrag; + ccode.close (); } - public override void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop = false) { + public override void append_local_free (Symbol sym, bool stop_at_loop = false) { var finally_block = (Block) null; if (sym.parent_node is TryStatement) { finally_block = (sym.parent_node as TryStatement).finally_body; @@ -314,10 +267,10 @@ public class Vala.DovaErrorModule : DovaDelegateModule { } if (finally_block != null) { - cfrag.append (finally_block.ccodenode); + finally_block.emit (this); } - base.append_local_free (sym, cfrag, stop_at_loop); + base.append_local_free (sym, stop_at_loop); } } diff --git a/codegen/valadovamemberaccessmodule.vala b/codegen/valadovamemberaccessmodule.vala index 3e7b10252..3e87b0514 100644 --- a/codegen/valadovamemberaccessmodule.vala +++ b/codegen/valadovamemberaccessmodule.vala @@ -71,7 +71,7 @@ public class Vala.DovaMemberAccessModule : DovaControlFlowModule { // instance expression has side-effects // store in temp. variable var temp_var = get_temp_variable (expr.inner.value_type); - temp_vars.add (temp_var); + emit_temp_var (temp_var); var ctemp = new CCodeIdentifier (temp_var.name); inst = new CCodeAssignment (ctemp, pub_inst); expr.inner.ccodenode = ctemp; diff --git a/codegen/valadovamethodcallmodule.vala b/codegen/valadovamethodcallmodule.vala index 7a245b0bc..958aa2635 100644 --- a/codegen/valadovamethodcallmodule.vala +++ b/codegen/valadovamethodcallmodule.vala @@ -81,7 +81,7 @@ public class Vala.DovaMethodCallModule : DovaAssignmentModule { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (ma.inner.target_type); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), instance)); ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name))); @@ -135,7 +135,7 @@ public class Vala.DovaMethodCallModule : DovaAssignmentModule { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (param.variable_type, param.variable_type.value_owned); - temp_vars.add (temp_var); + emit_temp_var (temp_var); cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name)); if (param.direction == ParameterDirection.REF) { @@ -151,14 +151,14 @@ public class Vala.DovaMethodCallModule : DovaAssignmentModule { ccomma.append_expression (ccall_expr); } else { ret_temp_var = get_temp_variable (itype.get_return_type ()); - temp_vars.add (ret_temp_var); + emit_temp_var (ret_temp_var); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (ret_temp_var.name), ccall_expr)); } var cassign_comma = new CCodeCommaExpression (); var assign_temp_var = get_temp_variable (unary.inner.value_type, unary.inner.value_type.value_owned); - temp_vars.add (assign_temp_var); + emit_temp_var (assign_temp_var); cassign_comma.append_expression (new CCodeAssignment (get_variable_cexpression (assign_temp_var.name), transform_expression (get_variable_cexpression (temp_var.name), param.variable_type, unary.inner.value_type, arg))); @@ -203,7 +203,7 @@ public class Vala.DovaMethodCallModule : DovaAssignmentModule { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (expr.value_type); - temp_vars.add (temp_var); + emit_temp_var (temp_var); if (expr.value_type is GenericType) { ccall.add_argument (get_variable_cexpression (temp_var.name)); } else { diff --git a/codegen/valadovaobjectmodule.vala b/codegen/valadovaobjectmodule.vala index fca759d39..4d65c26a5 100644 --- a/codegen/valadovaobjectmodule.vala +++ b/codegen/valadovaobjectmodule.vala @@ -758,16 +758,42 @@ public class Vala.DovaObjectModule : DovaArrayModule { function.add_parameter (new CCodeFormalParameter ("this", cl.get_cname () + "*")); - cfile.add_function_declaration (function); - + push_function (function); - var cblock = new CCodeBlock (); + cfile.add_function_declaration (function); if (cl.destructor != null) { - cblock.add_statement (cl.destructor.ccodenode); + cl.destructor.body.emit (this); } - cblock.add_statement (instance_finalize_fragment); + foreach (var f in cl.get_fields ()) { + if (f.binding == MemberBinding.INSTANCE) { + CCodeExpression lhs = null; + if (f.is_internal_symbol ()) { + var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null)))); + priv_call.add_argument (new CCodeIdentifier ("this")); + lhs = new CCodeMemberAccess.pointer (priv_call, f.get_cname ()); + } else { + lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("this"), f.get_cname ()); + } + + if (requires_destroy (f.variable_type)) { + var this_access = new MemberAccess.simple ("this"); + this_access.value_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol); + + var field_st = f.parent_symbol as Struct; + if (field_st != null && !field_st.is_simple_type ()) { + this_access.ccodenode = new CCodeIdentifier ("(*this)"); + } else { + this_access.ccodenode = new CCodeIdentifier ("this"); + } + + var ma = new MemberAccess (this_access, f.name); + ma.symbol_reference = f; + ccode.add_expression (get_unref_expression (lhs, f.variable_type, ma)); + } + } + } // chain up to finalize function of the base class foreach (DataType base_type in cl.get_base_types ()) { @@ -780,12 +806,11 @@ public class Vala.DovaObjectModule : DovaArrayModule { } ccall.add_argument (type_get_call); ccall.add_argument (new CCodeIdentifier ("this")); - cblock.add_statement (new CCodeExpressionStatement (ccall)); + ccode.add_statement (new CCodeExpressionStatement (ccall)); } } - - function.block = cblock; + pop_function (); cfile.add_function (function); } @@ -793,9 +818,6 @@ public class Vala.DovaObjectModule : DovaArrayModule { public override void visit_class (Class cl) { push_context (new EmitContext (cl)); - var old_instance_finalize_fragment = instance_finalize_fragment; - instance_finalize_fragment = new CCodeFragment (); - generate_class_declaration (cl, cfile); generate_class_private_declaration (cl, cfile); @@ -969,8 +991,6 @@ public class Vala.DovaObjectModule : DovaArrayModule { cfile.add_function (create_set_value_from_any_function ()); } - instance_finalize_fragment = old_instance_finalize_fragment; - pop_context (); } @@ -1148,14 +1168,6 @@ public class Vala.DovaObjectModule : DovaArrayModule { var prop = (Property) acc.prop; - if (acc.result_var != null) { - acc.result_var.accept (this); - } - - if (acc.body != null) { - acc.body.emit (this); - } - // do not declare overriding properties and interface implementations if (prop.is_abstract || prop.is_virtual || (prop.base_property == null && prop.base_interface_property == null)) { @@ -1256,7 +1268,13 @@ public class Vala.DovaObjectModule : DovaArrayModule { function.modifiers |= CCodeModifiers.STATIC; } - function.block = (CCodeBlock) acc.body.ccodenode; + push_function (function); + + if (acc.result_var != null) { + acc.result_var.accept (this); + } + + acc.body.emit (this); if (acc.readable) { var cdecl = new CCodeDeclaration (acc.value_type.get_cname ()); @@ -1386,10 +1404,6 @@ public class Vala.DovaObjectModule : DovaArrayModule { param.accept (this); } - if (m.result_var != null) { - m.result_var.accept (this); - } - foreach (Expression precondition in m.get_preconditions ()) { precondition.emit (this); } @@ -1398,12 +1412,6 @@ public class Vala.DovaObjectModule : DovaArrayModule { postcondition.emit (this); } - if (m.body != null) { - m.body.emit (this); - } - - - pop_context (); generate_method_declaration (m, cfile); @@ -1412,7 +1420,6 @@ public class Vala.DovaObjectModule : DovaArrayModule { } var function = new CCodeFunction (m.get_real_cname ()); - m.ccodenode = function; generate_cparameters (m, cfile, function); @@ -1427,14 +1434,10 @@ public class Vala.DovaObjectModule : DovaArrayModule { } if (m.body != null) { - function.block = (CCodeBlock) m.body.ccodenode; - function.block.line = function.line; - - var cinit = new CCodeFragment (); - function.block.prepend_statement (cinit); + push_function (function); if (context.module_init_method == m) { - cinit.append (module_init_fragment); + add_module_init (); } if (m.closure) { @@ -1453,7 +1456,7 @@ public class Vala.DovaObjectModule : DovaArrayModule { 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); + ccode.add_statement (cdecl); closure_block = parent_closure_block; block_id = parent_block_id; @@ -1466,7 +1469,7 @@ public class Vala.DovaObjectModule : DovaArrayModule { var cdecl = new CCodeDeclaration ("%s *".printf (current_class.get_cname ())); cdecl.add_declarator (new CCodeVariableDeclarator ("this", cself)); - cinit.append (cdecl); + ccode.add_statement (cdecl); } } foreach (FormalParameter param in m.get_parameters ()) { @@ -1484,26 +1487,32 @@ public class Vala.DovaObjectModule : DovaArrayModule { var condition = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (param.name), new CCodeConstant ("NULL")); var if_statement = new CCodeIfStatement (condition, cblock); - cinit.append (if_statement); + ccode.add_statement (if_statement); } } } + if (m.result_var != null) { + m.result_var.accept (this); + } + + m.body.emit (this); + if (!(m.return_type is VoidType) && !(m.return_type is GenericType)) { var cdecl = new CCodeDeclaration (m.return_type.get_cname ()); cdecl.add_declarator (new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true))); - cinit.append (cdecl); + ccode.add_statement (cdecl); - function.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result"))); + ccode.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result"))); } var st = m.parent_symbol as Struct; if (m is CreationMethod && st != null && (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ())) { var cdecl = new CCodeDeclaration (st.get_cname ()); cdecl.add_declarator (new CCodeVariableDeclarator ("this", new CCodeConstant ("0"))); - cinit.append (cdecl); + ccode.add_statement (cdecl); - function.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("this"))); + ccode.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("this"))); } cfile.add_function (function); @@ -1639,6 +1648,8 @@ public class Vala.DovaObjectModule : DovaArrayModule { cfile.add_function (override_func); } + pop_context (); + if (m.entry_point) { generate_type_declaration (new ObjectType (array_class), cfile); @@ -1647,18 +1658,19 @@ public class Vala.DovaObjectModule : DovaArrayModule { cmain.line = function.line; cmain.add_parameter (new CCodeFormalParameter ("argc", "int")); cmain.add_parameter (new CCodeFormalParameter ("argv", "char **")); - var main_block = new CCodeBlock (); + + push_function (cmain); var dova_init_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_init")); dova_init_call.add_argument (new CCodeIdentifier ("argc")); dova_init_call.add_argument (new CCodeIdentifier ("argv")); - main_block.add_statement (new CCodeExpressionStatement (dova_init_call)); + ccode.add_statement (new CCodeExpressionStatement (dova_init_call)); - main_block.add_statement (module_init_fragment); + add_module_init (); var cdecl = new CCodeDeclaration ("int"); cdecl.add_declarator (new CCodeVariableDeclarator ("result", new CCodeConstant ("0"))); - main_block.add_statement (cdecl); + ccode.add_statement (cdecl); var main_call = new CCodeFunctionCall (new CCodeIdentifier (function.name)); @@ -1671,18 +1683,18 @@ public class Vala.DovaObjectModule : DovaArrayModule { cdecl = new CCodeDeclaration ("DovaArray*"); cdecl.add_declarator (new CCodeVariableDeclarator ("args", array_creation)); - main_block.add_statement (cdecl); + ccode.add_statement (cdecl); var array_data = new CCodeFunctionCall (new CCodeIdentifier ("dova_array_get_data")); array_data.add_argument (new CCodeIdentifier ("args")); cdecl = new CCodeDeclaration ("string_t*"); cdecl.add_declarator (new CCodeVariableDeclarator ("args_data", array_data)); - main_block.add_statement (cdecl); + ccode.add_statement (cdecl); cdecl = new CCodeDeclaration ("int"); cdecl.add_declarator (new CCodeVariableDeclarator ("argi")); - main_block.add_statement (cdecl); + ccode.add_statement (cdecl); var string_creation = new CCodeFunctionCall (new CCodeIdentifier ("string_create_from_cstring")); string_creation.add_argument (new CCodeElementAccess (new CCodeIdentifier ("argv"), new CCodeIdentifier ("argi"))); @@ -1693,7 +1705,7 @@ public class Vala.DovaObjectModule : DovaArrayModule { var for_stmt = new CCodeForStatement (new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("argi"), new CCodeIdentifier ("argc")), loop_block); for_stmt.add_initializer (new CCodeAssignment (new CCodeIdentifier ("argi"), new CCodeConstant ("0"))); for_stmt.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("argi"))); - main_block.add_statement (for_stmt); + ccode.add_statement (for_stmt); main_call.add_argument (new CCodeIdentifier ("args")); } @@ -1702,25 +1714,26 @@ public class Vala.DovaObjectModule : DovaArrayModule { // method returns void, always use 0 as exit code var main_stmt = new CCodeExpressionStatement (main_call); main_stmt.line = cmain.line; - main_block.add_statement (main_stmt); + ccode.add_statement (main_stmt); } else { var main_stmt = new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), main_call)); main_stmt.line = cmain.line; - main_block.add_statement (main_stmt); + ccode.add_statement (main_stmt); } if (m.get_parameters ().size == 1) { // destroy Dova array var unref = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_unref")); unref.add_argument (new CCodeIdentifier ("args")); - main_block.add_statement (new CCodeExpressionStatement (unref)); + ccode.add_statement (new CCodeExpressionStatement (unref)); } var ret_stmt = new CCodeReturnStatement (new CCodeIdentifier ("result")); ret_stmt.line = cmain.line; - main_block.add_statement (ret_stmt); + ccode.add_statement (ret_stmt); + + pop_function (); - cmain.block = main_block; cfile.add_function (cmain); } } @@ -1955,4 +1968,15 @@ public class Vala.DovaObjectModule : DovaArrayModule { base.visit_element_access (expr); } } + + void add_module_init () { + foreach (var field in static_fields) { + field.initializer.emit (this); + + var lhs = new CCodeIdentifier (field.get_cname ()); + var rhs = (CCodeExpression) field.initializer.ccodenode; + + ccode.add_expression (new CCodeAssignment (lhs, rhs)); + } + } } diff --git a/codegen/valadovastructmodule.vala b/codegen/valadovastructmodule.vala index b7a99cd3a..2c6cdf2c7 100644 --- a/codegen/valadovastructmodule.vala +++ b/codegen/valadovastructmodule.vala @@ -72,9 +72,6 @@ public class Vala.DovaStructModule : DovaBaseModule { public override void visit_struct (Struct st) { push_context (new EmitContext (st)); - var old_instance_finalize_fragment = instance_finalize_fragment; - instance_finalize_fragment = new CCodeFragment (); - generate_struct_declaration (st, cfile); if (!st.is_internal_symbol ()) { @@ -83,8 +80,6 @@ public class Vala.DovaStructModule : DovaBaseModule { st.accept_children (this); - instance_finalize_fragment = old_instance_finalize_fragment; - pop_context (); } } diff --git a/codegen/valadovavaluemodule.vala b/codegen/valadovavaluemodule.vala index e87686982..94369253b 100644 --- a/codegen/valadovavaluemodule.vala +++ b/codegen/valadovavaluemodule.vala @@ -362,9 +362,6 @@ public class Vala.DovaValueModule : DovaObjectModule { cblock.add_statement (new CCodeIfStatement (new CCodeIdentifier ("src"), copy_block)); - append_temp_decl (cfrag, temp_vars); - temp_vars.clear (); - function.block = cblock; cfile.add_function (function); @@ -549,7 +546,7 @@ public class Vala.DovaValueModule : DovaObjectModule { var temp_var = get_temp_variable (array_type, true, expr); var name_cnode = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); int i = 0; foreach (Expression e in expr.get_expressions ()) { @@ -583,7 +580,7 @@ public class Vala.DovaValueModule : DovaObjectModule { var temp_var = get_temp_variable (array_type, true, expr); var name_cnode = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); int i = 0; foreach (Expression e in expr.get_expressions ()) { @@ -619,7 +616,7 @@ public class Vala.DovaValueModule : DovaObjectModule { var key_temp_var = get_temp_variable (key_array_type, true, expr); var key_name_cnode = get_variable_cexpression (key_temp_var.name); - temp_vars.add (key_temp_var); + emit_temp_var (key_temp_var); var value_array_type = new ArrayType (expr.map_value_type, 1, expr.source_reference); value_array_type.inline_allocated = true; @@ -629,7 +626,7 @@ public class Vala.DovaValueModule : DovaObjectModule { var value_temp_var = get_temp_variable (value_array_type, true, expr); var value_name_cnode = get_variable_cexpression (value_temp_var.name); - temp_vars.add (value_temp_var); + emit_temp_var (value_temp_var); for (int i = 0; i < length; i++) { key_ce.append_expression (new CCodeAssignment (new CCodeElementAccess (key_name_cnode, new CCodeConstant (i.to_string ())), (CCodeExpression) expr.get_keys ().get (i).ccodenode)); @@ -658,7 +655,7 @@ public class Vala.DovaValueModule : DovaObjectModule { var type_temp_var = get_temp_variable (type_array_type, true, tuple); var type_name_cnode = get_variable_cexpression (type_temp_var.name); - temp_vars.add (type_temp_var); + emit_temp_var (type_temp_var); var array_type = new ArrayType (new PointerType (new VoidType ()), 1, tuple.source_reference); array_type.inline_allocated = true; @@ -667,7 +664,7 @@ public class Vala.DovaValueModule : DovaObjectModule { var temp_var = get_temp_variable (array_type, true, tuple); var name_cnode = get_variable_cexpression (temp_var.name); - temp_vars.add (temp_var); + emit_temp_var (temp_var); var type_ce = new CCodeCommaExpression (); var ce = new CCodeCommaExpression (); @@ -691,7 +688,7 @@ public class Vala.DovaValueModule : DovaObjectModule { // tmp = expr, &tmp var element_temp_var = get_temp_variable (element_type); - temp_vars.add (element_temp_var); + emit_temp_var (element_temp_var); ce.append_expression (new CCodeAssignment (get_variable_cexpression (element_temp_var.name), cexpr)); cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (element_temp_var.name)); } diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala index a62167dcf..02846d250 100644 --- a/codegen/valagasyncmodule.vala +++ b/codegen/valagasyncmodule.vala @@ -138,8 +138,27 @@ public class Vala.GAsyncModule : GSignalModule { return freefunc; } - CCodeFunction generate_async_function (Method m) { - var asyncblock = new CCodeBlock (); + void generate_async_function (Method m) { + push_context (new EmitContext ()); + + var dataname = Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data"; + var asyncfunc = new CCodeFunction (m.get_real_cname (), "void"); + var cparam_map = new HashMap (direct_hash, direct_equal); + + cparam_map.set (get_param_pos (-1), new CCodeFormalParameter ("_callback_", "GAsyncReadyCallback")); + cparam_map.set (get_param_pos (-0.9), new CCodeFormalParameter ("_user_data_", "gpointer")); + + generate_cparameters (m, cfile, cparam_map, asyncfunc, null, null, null, 1); + + if (m.base_method != null || m.base_interface_method != null) { + // declare *_real_* function + asyncfunc.modifiers |= CCodeModifiers.STATIC; + cfile.add_function_declaration (asyncfunc); + } else if (m.is_private_symbol ()) { + asyncfunc.modifiers |= CCodeModifiers.STATIC; + } + + push_function (asyncfunc); // logic copied from valaccodemethodmodule if (m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) { @@ -156,24 +175,17 @@ public class Vala.GAsyncModule : GSignalModule { var self_target_type = new ObjectType (type_symbol); var cself = transform_expression (new CCodeIdentifier ("base"), base_expression_type, self_target_type); - var cdecl = new CCodeDeclaration ("%s *".printf (type_symbol.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator ("self", cself)); - asyncblock.add_statement (cdecl); + ccode.add_declaration ("%s *".printf (type_symbol.get_cname ()), new CCodeVariableDeclarator ("self")); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), cself)); } - var dataname = Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data"; - var asyncfunc = new CCodeFunction (m.get_real_cname (), "void"); - var cparam_map = new HashMap (direct_hash, direct_equal); - var dataalloc = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0")); dataalloc.add_argument (new CCodeIdentifier (dataname)); var data_var = new CCodeIdentifier ("_data_"); - var datadecl = new CCodeDeclaration (dataname + "*"); - datadecl.add_declarator (new CCodeVariableDeclarator ("_data_")); - asyncblock.add_statement (datadecl); - asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (data_var, dataalloc))); + ccode.add_declaration (dataname + "*", new CCodeVariableDeclarator ("_data_")); + ccode.add_expression (new CCodeAssignment (data_var, dataalloc)); var create_result = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_new")); @@ -201,13 +213,13 @@ public class Vala.GAsyncModule : GSignalModule { create_result.add_argument (new CCodeIdentifier ("_user_data_")); create_result.add_argument (new CCodeIdentifier (m.get_real_cname ())); - asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "_async_result"), create_result))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "_async_result"), create_result)); var set_op_res_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_set_op_res_gpointer")); set_op_res_call.add_argument (new CCodeMemberAccess.pointer (data_var, "_async_result")); set_op_res_call.add_argument (data_var); set_op_res_call.add_argument (new CCodeIdentifier (m.get_real_cname () + "_data_free")); - asyncblock.add_statement (new CCodeExpressionStatement (set_op_res_call)); + ccode.add_expression (set_op_res_call); if (m.binding == MemberBinding.INSTANCE) { CCodeExpression self_expr = new CCodeIdentifier ("self"); @@ -219,7 +231,7 @@ public class Vala.GAsyncModule : GSignalModule { self_expr = refcall; } - asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "self"), self_expr))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "self"), self_expr)); } foreach (FormalParameter param in m.get_parameters ()) { @@ -228,7 +240,7 @@ public class Vala.GAsyncModule : GSignalModule { param_type.value_owned = true; // create copy if necessary as variables in async methods may need to be kept alive - CCodeExpression cparam = get_variable_cexpression (param.name); + CCodeExpression cparam = new CCodeIdentifier (get_variable_cname (param.name)); if (param.variable_type.is_real_non_null_struct_type ()) { cparam = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cparam); } @@ -238,51 +250,33 @@ public class Vala.GAsyncModule : GSignalModule { cparam = get_ref_cexpression (param.variable_type, cparam, ma, param); } - asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), cparam))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), cparam)); if (param.variable_type is ArrayType) { var array_type = (ArrayType) param.variable_type; if (!param.no_array_length) { for (int dim = 1; dim <= array_type.rank; dim++) { - asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_array_length_cname (get_variable_cname (param.name), dim)), new CCodeIdentifier (get_array_length_cname (get_variable_cname (param.name), dim))))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_array_length_cname (get_variable_cname (param.name), dim)), new CCodeIdentifier (get_array_length_cname (get_variable_cname (param.name), dim)))); } } } else if (param.variable_type is DelegateType) { var deleg_type = (DelegateType) param.variable_type; if (deleg_type.delegate_symbol.has_target) { - asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name)))))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name))))); if (deleg_type.value_owned) { - asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)))))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))))); } } } } } - var cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - temp_vars.clear (); - asyncblock.add_statement (cfrag); - var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_real_cname () + "_co")); ccall.add_argument (data_var); - asyncblock.add_statement (new CCodeExpressionStatement (ccall)); - - cparam_map.set (get_param_pos (-1), new CCodeFormalParameter ("_callback_", "GAsyncReadyCallback")); - cparam_map.set (get_param_pos (-0.9), new CCodeFormalParameter ("_user_data_", "gpointer")); - - generate_cparameters (m, cfile, cparam_map, asyncfunc, null, null, null, 1); - - if (m.base_method != null || m.base_interface_method != null) { - // declare *_real_* function - asyncfunc.modifiers |= CCodeModifiers.STATIC; - cfile.add_function_declaration (asyncfunc); - } else if (m.is_private_symbol ()) { - asyncfunc.modifiers |= CCodeModifiers.STATIC; - } + ccode.add_expression (ccall); - asyncfunc.block = asyncblock; + cfile.add_function (asyncfunc); - return asyncfunc; + pop_context (); } void append_struct (CCodeStruct structure) { @@ -293,12 +287,7 @@ public class Vala.GAsyncModule : GSignalModule { } void append_function (CCodeFunction function) { - var block = function.block; - function.block = null; - cfile.add_function_declaration (function); - - function.block = block; cfile.add_function (function); } @@ -347,13 +336,14 @@ public class Vala.GAsyncModule : GSignalModule { if (!m.is_abstract && m.body != null) { var data = generate_data_struct (m); + closure_struct = data; + append_function (generate_free_function (m)); - cfile.add_function (generate_async_function (m)); - cfile.add_function (generate_finish_function (m)); + generate_async_function (m); + generate_finish_function (m); append_function (generate_ready_function (m)); // append the _co function - closure_struct = data; base.visit_method (m); closure_struct = null; @@ -387,27 +377,33 @@ public class Vala.GAsyncModule : GSignalModule { } - CCodeFunction generate_finish_function (Method m) { + void generate_finish_function (Method m) { + push_context (new EmitContext ()); + string dataname = Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data"; var finishfunc = new CCodeFunction (m.get_finish_real_cname ()); var cparam_map = new HashMap (direct_hash, direct_equal); - var finishblock = new CCodeBlock (); + cparam_map.set (get_param_pos (0.1), new CCodeFormalParameter ("_res_", "GAsyncResult*")); + + generate_cparameters (m, cfile, cparam_map, finishfunc, null, null, null, 2); + + if (m.is_private_symbol () || m.base_method != null || m.base_interface_method != null) { + finishfunc.modifiers |= CCodeModifiers.STATIC; + } + + push_function (finishfunc); var return_type = m.return_type; if (!(return_type is VoidType) && !return_type.is_real_non_null_struct_type ()) { - var cdecl = new CCodeDeclaration (m.return_type.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator ("result")); - finishblock.add_statement (cdecl); + ccode.add_declaration (m.return_type.get_cname (), new CCodeVariableDeclarator ("result")); } var data_var = new CCodeIdentifier ("_data_"); - var datadecl = new CCodeDeclaration (dataname + "*"); - datadecl.add_declarator (new CCodeVariableDeclarator ("_data_")); - finishblock.add_statement (datadecl); + ccode.add_declaration (dataname + "*", new CCodeVariableDeclarator ("_data_")); var simple_async_result_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_SIMPLE_ASYNC_RESULT")); simple_async_result_cast.add_argument (new CCodeIdentifier ("_res_")); @@ -417,24 +413,25 @@ public class Vala.GAsyncModule : GSignalModule { var propagate_error = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_propagate_error")); propagate_error.add_argument (simple_async_result_cast); propagate_error.add_argument (new CCodeIdentifier ("error")); - var errorblock = new CCodeBlock (); + + ccode.open_if (propagate_error); if (return_type is VoidType || return_type.is_real_non_null_struct_type ()) { - errorblock.add_statement (new CCodeReturnStatement ()); + ccode.add_return (); } else { - errorblock.add_statement (new CCodeReturnStatement (default_value_for_type (return_type, false))); + ccode.add_return (default_value_for_type (return_type, false)); } - finishblock.add_statement (new CCodeIfStatement (propagate_error, errorblock)); + ccode.close (); } var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_get_op_res_gpointer")); ccall.add_argument (simple_async_result_cast); - finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (data_var, ccall))); + ccode.add_expression (new CCodeAssignment (data_var, ccall)); foreach (FormalParameter param in m.get_parameters ()) { if (param.direction != ParameterDirection.IN) { - finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (param.name)), new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name))))); + ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (param.name)), new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)))); if (!(param.variable_type is ValueType) || param.variable_type.nullable) { - finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), new CCodeConstant ("NULL")))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), new CCodeConstant ("NULL"))); } } } @@ -445,41 +442,30 @@ public class Vala.GAsyncModule : GSignalModule { if (requires_copy (return_type)) { cexpr = get_ref_cexpression (return_type, cexpr, null, return_type); } - finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result")), cexpr))); + ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result")), cexpr)); } else if (!(return_type is VoidType)) { - finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), new CCodeMemberAccess.pointer (data_var, "result")))); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("result"), new CCodeMemberAccess.pointer (data_var, "result"))); if (return_type is ArrayType) { var array_type = (ArrayType) return_type; if (!m.no_array_length) { for (int dim = 1; dim <= array_type.rank; dim++) { - finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_array_length_cname ("result", dim))), new CCodeMemberAccess.pointer (data_var, get_array_length_cname ("result", dim))))); + ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_array_length_cname ("result", dim))), new CCodeMemberAccess.pointer (data_var, get_array_length_cname ("result", dim)))); } } } else if (return_type is DelegateType && ((DelegateType) return_type).delegate_symbol.has_target) { - finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_delegate_target_cname ("result"))), new CCodeMemberAccess.pointer (data_var, get_delegate_target_cname ("result"))))); + ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_delegate_target_cname ("result"))), new CCodeMemberAccess.pointer (data_var, get_delegate_target_cname ("result")))); } if (!(return_type is ValueType) || return_type.nullable) { - finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "result"), new CCodeConstant ("NULL")))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "result"), new CCodeConstant ("NULL"))); } - finishblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result"))); + ccode.add_return (new CCodeIdentifier ("result")); } - var cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - temp_vars.clear (); - finishblock.add_statement (cfrag); - - cparam_map.set (get_param_pos (0.1), new CCodeFormalParameter ("_res_", "GAsyncResult*")); + pop_function (); - generate_cparameters (m, cfile, cparam_map, finishfunc, null, null, null, 2); + cfile.add_function (finishfunc); - if (m.is_private_symbol () || m.base_method != null || m.base_interface_method != null) { - finishfunc.modifiers |= CCodeModifiers.STATIC; - } - - finishfunc.block = finishblock; - - return finishfunc; + pop_context (); } CCodeFunction generate_ready_function (Method m) { @@ -550,23 +536,16 @@ public class Vala.GAsyncModule : GSignalModule { public override void visit_yield_statement (YieldStatement stmt) { if (current_method == null || !current_method.coroutine) { - stmt.ccodenode = new CCodeEmptyStatement (); return; } if (stmt.yield_expression == null) { - var cfrag = new CCodeFragment (); - stmt.ccodenode = cfrag; - int state = next_coroutine_state++; - state_switch_statement.add_statement (new CCodeCaseStatement (new CCodeConstant (state.to_string ()))); - state_switch_statement.add_statement (new CCodeGotoStatement ("_state_%d".printf (state))); - - cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ())))); - cfrag.append (new CCodeReturnStatement (new CCodeConstant ("FALSE"))); - cfrag.append (new CCodeLabel ("_state_%d".printf (state))); - cfrag.append (new CCodeEmptyStatement ()); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ()))); + ccode.add_return (new CCodeConstant ("FALSE")); + ccode.add_label ("_state_%d".printf (state)); + ccode.add_statement (new CCodeEmptyStatement ()); return; } @@ -576,68 +555,44 @@ public class Vala.GAsyncModule : GSignalModule { return; } - stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.yield_expression.ccodenode); + ccode.add_expression ((CCodeExpression) stmt.yield_expression.ccodenode); if (stmt.tree_can_fail && stmt.yield_expression.tree_can_fail) { // simple case, no node breakdown necessary - var cfrag = new CCodeFragment (); - - cfrag.append (stmt.ccodenode); - - add_simple_check (stmt.yield_expression, cfrag); - - stmt.ccodenode = cfrag; + add_simple_check (stmt.yield_expression); } /* free temporary objects */ - if (((List) temp_vars).size == 0) { - /* nothing to do without temporary variables */ - return; - } - - var cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - - cfrag.append (stmt.ccodenode); - foreach (LocalVariable local in temp_ref_vars) { var ma = new MemberAccess.simple (local.name); ma.symbol_reference = local; - cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (local.name), local.variable_type, ma))); + ccode.add_expression (get_unref_expression (new CCodeIdentifier (local.name), local.variable_type, ma)); } - - stmt.ccodenode = cfrag; - - temp_vars.clear (); + temp_ref_vars.clear (); } - public override CCodeStatement return_with_exception (CCodeExpression error_expr) + public override void return_with_exception (CCodeExpression error_expr) { if (!current_method.coroutine) { - return base.return_with_exception (error_expr); + base.return_with_exception (error_expr); + return; } - var block = new CCodeBlock (); - var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_set_from_error")); set_error.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_async_result")); set_error.add_argument (error_expr); - block.add_statement (new CCodeExpressionStatement (set_error)); + ccode.add_expression (set_error); var free_error = new CCodeFunctionCall (new CCodeIdentifier ("g_error_free")); free_error.add_argument (error_expr); - block.add_statement (new CCodeExpressionStatement (free_error)); + ccode.add_expression (free_error); - var free_locals = new CCodeFragment (); - append_local_free (current_symbol, free_locals, false); - block.add_statement (free_locals); + append_local_free (current_symbol, false); - block.add_statement (complete_async ()); - - return block; + complete_async (); } public override void visit_return_statement (ReturnStatement stmt) { @@ -647,9 +602,7 @@ public class Vala.GAsyncModule : GSignalModule { return; } - var cfrag = (CCodeFragment) stmt.ccodenode; - - cfrag.append (complete_async ()); + complete_async (); } public override void generate_cparameters (Method m, CCodeFile decl_space, Map cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, Map? carg_map = null, CCodeFunctionCall? vcall = null, int direction = 3) { diff --git a/codegen/valagerrormodule.vala b/codegen/valagerrormodule.vala index 19db146a9..ae406e13f 100644 --- a/codegen/valagerrormodule.vala +++ b/codegen/valagerrormodule.vala @@ -81,60 +81,40 @@ public class Vala.GErrorModule : CCodeDelegateModule { } public override void visit_throw_statement (ThrowStatement stmt) { - var cfrag = new CCodeFragment (); - // method will fail current_method_inner_error = true; - var cassign = new CCodeAssignment (get_variable_cexpression ("_inner_error_"), (CCodeExpression) stmt.error_expression.ccodenode); - cfrag.append (new CCodeExpressionStatement (cassign)); - - add_simple_check (stmt, cfrag, true); - - stmt.ccodenode = cfrag; + ccode.add_expression (new CCodeAssignment (get_variable_cexpression ("_inner_error_"), (CCodeExpression) stmt.error_expression.ccodenode)); - create_temp_decl (stmt, stmt.error_expression.temp_vars); + add_simple_check (stmt, true); } - public virtual CCodeStatement return_with_exception (CCodeExpression error_expr) - { + public virtual void return_with_exception (CCodeExpression error_expr) { var cpropagate = new CCodeFunctionCall (new CCodeIdentifier ("g_propagate_error")); cpropagate.add_argument (new CCodeIdentifier ("error")); cpropagate.add_argument (error_expr); - var cerror_block = new CCodeBlock (); - cerror_block.add_statement (new CCodeExpressionStatement (cpropagate)); + ccode.add_expression (cpropagate); // free local variables - var free_frag = new CCodeFragment (); - append_local_free (current_symbol, free_frag, false); - cerror_block.add_statement (free_frag); + append_local_free (current_symbol, false); if (current_method is CreationMethod) { var cl = current_method.parent_symbol as Class; var unref_call = get_unref_expression (new CCodeIdentifier ("self"), new ObjectType (cl), null); - cerror_block.add_statement (new CCodeExpressionStatement (unref_call)); - cerror_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL"))); + ccode.add_expression (unref_call); + ccode.add_return (new CCodeConstant ("NULL")); } else if (current_method != null && current_method.coroutine) { - cerror_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE"))); + ccode.add_return (new CCodeConstant ("FALSE")); } else if (current_return_type is VoidType) { - cerror_block.add_statement (new CCodeReturnStatement ()); + ccode.add_return (); } else { - cerror_block.add_statement (new CCodeReturnStatement (default_value_for_type (current_return_type, false))); + ccode.add_return (default_value_for_type (current_return_type, false)); } - - return cerror_block; } - CCodeStatement uncaught_error_statement (CCodeExpression inner_error, CCodeBlock? block = null, bool unexpected = false) { - var cerror_block = block; - if (cerror_block == null) { - cerror_block = new CCodeBlock (); - } - + void uncaught_error_statement (CCodeExpression inner_error, bool unexpected = false) { // free local variables - var free_frag = new CCodeFragment (); - append_local_free (current_symbol, free_frag, false); - cerror_block.add_statement (free_frag); + append_local_free (current_symbol, false); var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical")); ccritical.add_argument (new CCodeConstant (unexpected ? "\"file %s: line %d: unexpected error: %s (%s, %d)\"" : "\"file %s: line %d: uncaught error: %s (%s, %d)\"")); @@ -149,24 +129,19 @@ public class Vala.GErrorModule : CCodeDelegateModule { var cclear = new CCodeFunctionCall (new CCodeIdentifier ("g_clear_error")); cclear.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, inner_error)); - var cprint_frag = new CCodeFragment (); - cprint_frag.append (new CCodeExpressionStatement (ccritical)); - cprint_frag.append (new CCodeExpressionStatement (cclear)); - // print critical message - cerror_block.add_statement (cprint_frag); + ccode.add_expression (ccritical); + ccode.add_expression (cclear); if (current_method is CreationMethod) { - cerror_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL"))); + ccode.add_return (new CCodeConstant ("NULL")); } else if (current_method != null && current_method.coroutine) { - cerror_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE"))); + ccode.add_return (new CCodeConstant ("FALSE")); } else if (current_return_type is VoidType) { - cerror_block.add_statement (new CCodeReturnStatement ()); + ccode.add_return (); } else if (current_return_type != null) { - cerror_block.add_statement (new CCodeReturnStatement (default_value_for_type (current_return_type, false))); + ccode.add_return (default_value_for_type (current_return_type, false)); } - - return cerror_block; } bool in_finally_block (CodeNode node) { @@ -181,21 +156,24 @@ public class Vala.GErrorModule : CCodeDelegateModule { return false; } - public override void add_simple_check (CodeNode node, CCodeFragment cfrag, bool always_fails = false) { + public override void add_simple_check (CodeNode node, bool always_fails = false) { current_method_inner_error = true; var inner_error = get_variable_cexpression ("_inner_error_"); - CCodeStatement cerror_handler = null; + if (always_fails) { + // inner_error is always set, avoid unnecessary if statement + // eliminates C warnings + } else { + var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, inner_error, new CCodeConstant ("NULL")); + ccode.open_if (ccond); + } if (current_try != null) { // surrounding try found - var cerror_block = new CCodeBlock (); // free local variables - var free_frag = new CCodeFragment (); - append_error_free (current_symbol, free_frag, current_try); - cerror_block.add_statement (free_frag); + append_error_free (current_symbol, current_try); var error_types = new ArrayList (); foreach (DataType node_error_type in node.get_error_types ()) { @@ -218,18 +196,13 @@ public class Vala.GErrorModule : CCodeDelegateModule { } handled_error_types.clear (); - // go to catch clause if error domain matches - var cgoto_stmt = new CCodeGotoStatement (clause.clabel_name); - if (clause.error_type.equals (gerror_type)) { // general catch clause, this should be the last one has_general_catch_clause = true; - cerror_block.add_statement (cgoto_stmt); + ccode.add_goto (clause.clabel_name); break; } else { var catch_type = clause.error_type as ErrorType; - var cgoto_block = new CCodeBlock (); - cgoto_block.add_statement (cgoto_stmt); if (catch_type.error_code != null) { /* catch clause specifies a specific error code */ @@ -238,15 +211,19 @@ public class Vala.GErrorModule : CCodeDelegateModule { error_match.add_argument (new CCodeIdentifier (catch_type.data_type.get_upper_case_cname ())); error_match.add_argument (new CCodeIdentifier (catch_type.error_code.get_cname ())); - cerror_block.add_statement (new CCodeIfStatement (error_match, cgoto_block)); + ccode.open_if (error_match); } else { /* catch clause specifies a full error domain */ var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeMemberAccess.pointer (inner_error, "domain"), new CCodeIdentifier (clause.error_type.data_type.get_upper_case_cname ())); - cerror_block.add_statement (new CCodeIfStatement (ccond, cgoto_block)); + ccode.open_if (ccond); } + + // go to catch clause if error domain matches + ccode.add_goto (clause.clabel_name); + ccode.close (); } } } @@ -258,16 +235,14 @@ public class Vala.GErrorModule : CCodeDelegateModule { } else if (error_types.size > 0) { // go to finally clause if no catch clause matches // and there are still unhandled error types - cerror_block.add_statement (new CCodeGotoStatement ("__finally%d".printf (current_try_id))); + ccode.add_goto ("__finally%d".printf (current_try_id)); } else if (in_finally_block (node)) { // do not check unexpected errors happening within finally blocks // as jump out of finally block is not supported } else { // should never happen with correct bindings - uncaught_error_statement (inner_error, cerror_block, true); + uncaught_error_statement (inner_error, true); } - - cerror_handler = cerror_block; } else if (current_method != null && current_method.get_error_types ().size > 0) { // current method can fail, propagate error CCodeBinaryExpression ccond = null; @@ -289,26 +264,22 @@ public class Vala.GErrorModule : CCodeDelegateModule { } } - if (ccond == null) { - cerror_handler = return_with_exception (inner_error); + if (ccond != null) { + ccode.open_if (ccond); + return_with_exception (inner_error); + + ccode.add_else (); + uncaught_error_statement (inner_error); + ccode.close (); } else { - var cerror_block = new CCodeBlock (); - cerror_block.add_statement (new CCodeIfStatement (ccond, - return_with_exception (inner_error), - uncaught_error_statement (inner_error))); - cerror_handler = cerror_block; + return_with_exception (inner_error); } } else { - cerror_handler = uncaught_error_statement (inner_error); + uncaught_error_statement (inner_error); } - if (always_fails) { - // inner_error is always set, avoid unnecessary if statement - // eliminates C warnings - cfrag.append (cerror_handler); - } else { - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, inner_error, new CCodeConstant ("NULL")); - cfrag.append (new CCodeIfStatement (ccond, cerror_handler)); + if (!always_fails) { + ccode.close (); } } @@ -326,15 +297,12 @@ public class Vala.GErrorModule : CCodeDelegateModule { clause.clabel_name = "__catch%d_%s".printf (this_try_id, clause.error_type.get_lower_case_cname ()); } - if (stmt.finally_body != null) { - stmt.finally_body.emit (this); - } - is_in_catch = false; stmt.body.emit (this); is_in_catch = true; foreach (CatchClause clause in stmt.get_catch_clauses ()) { + ccode.add_goto ("__finally%d".printf (this_try_id)); clause.emit (this); } @@ -342,24 +310,14 @@ public class Vala.GErrorModule : CCodeDelegateModule { current_try_id = old_try_id; is_in_catch = old_is_in_catch; - var cfrag = new CCodeFragment (); - cfrag.append (stmt.body.ccodenode); - - foreach (CatchClause clause in stmt.get_catch_clauses ()) { - cfrag.append (new CCodeGotoStatement ("__finally%d".printf (this_try_id))); - cfrag.append (clause.ccodenode); - } - - cfrag.append (new CCodeLabel ("__finally%d".printf (this_try_id))); + ccode.add_label ("__finally%d".printf (this_try_id)); if (stmt.finally_body != null) { - cfrag.append (stmt.finally_body.ccodenode); + stmt.finally_body.emit (this); } // check for errors not handled by this try statement // may be handled by outer try statements or propagated - add_simple_check (stmt, cfrag, !stmt.after_try_block_reachable); - - stmt.ccodenode = cfrag; + add_simple_check (stmt, !stmt.after_try_block_reachable); } public override void visit_catch_clause (CatchClause clause) { @@ -370,12 +328,9 @@ public class Vala.GErrorModule : CCodeDelegateModule { generate_error_domain_declaration (error_type.error_domain, cfile); } - clause.body.emit (this); - - var cfrag = new CCodeFragment (); - cfrag.append (new CCodeLabel (clause.clabel_name)); + ccode.add_label (clause.clabel_name); - var cblock = new CCodeBlock (); + ccode.open_block (); string variable_name; if (clause.variable_name != null) { @@ -384,31 +339,27 @@ public class Vala.GErrorModule : CCodeDelegateModule { variable_name = "__err"; } - if (current_method != null && current_method.coroutine) { - closure_struct.add_field ("GError *", variable_name); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (variable_name), get_variable_cexpression ("_inner_error_")))); - } else { - if (clause.variable_name != null) { - var cdecl = new CCodeDeclaration ("GError *"); - cdecl.add_declarator (new CCodeVariableDeclarator (variable_name, get_variable_cexpression ("_inner_error_"))); - cblock.add_statement (cdecl); + if (clause.variable_name != null) { + if (current_method != null && current_method.coroutine) { + closure_struct.add_field ("GError *", variable_name); } else { - // error object is not used within catch statement, clear it - var cclear = new CCodeFunctionCall (new CCodeIdentifier ("g_clear_error")); - cclear.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_"))); - cblock.add_statement (new CCodeExpressionStatement (cclear)); + ccode.add_declaration ("GError *", new CCodeVariableDeclarator (variable_name)); } + ccode.add_expression (new CCodeAssignment (get_variable_cexpression (variable_name), get_variable_cexpression ("_inner_error_"))); + } else { + // error object is not used within catch statement, clear it + var cclear = new CCodeFunctionCall (new CCodeIdentifier ("g_clear_error")); + cclear.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_"))); + ccode.add_expression (cclear); } - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression ("_inner_error_"), new CCodeConstant ("NULL")))); + ccode.add_expression (new CCodeAssignment (get_variable_cexpression ("_inner_error_"), new CCodeConstant ("NULL"))); - cblock.add_statement (clause.body.ccodenode); - - cfrag.append (cblock); + clause.body.emit (this); - clause.ccodenode = cfrag; + ccode.close (); } - public override void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop = false) { + public override void append_local_free (Symbol sym, bool stop_at_loop = false) { var finally_block = (Block) null; if (sym.parent_node is TryStatement) { finally_block = (sym.parent_node as TryStatement).finally_body; @@ -417,10 +368,10 @@ public class Vala.GErrorModule : CCodeDelegateModule { } if (finally_block != null) { - cfrag.append (finally_block.ccodenode); + finally_block.emit (this); } - base.append_local_free (sym, cfrag, stop_at_loop); + base.append_local_free (sym, stop_at_loop); } } diff --git a/codegen/valagobjectmodule.vala b/codegen/valagobjectmodule.vala index ef7e11fe7..d18110811 100644 --- a/codegen/valagobjectmodule.vala +++ b/codegen/valagobjectmodule.vala @@ -42,7 +42,7 @@ public class Vala.GObjectModule : GTypeModule { } } - public override void generate_class_init (Class cl, CCodeBlock init_block) { + public override void generate_class_init (Class cl) { if (!cl.is_subtype_of (gobject_type)) { return; } @@ -51,24 +51,24 @@ public class Vala.GObjectModule : GTypeModule { var ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); ccall.add_argument (new CCodeIdentifier ("klass")); if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) { - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "get_property"), new CCodeIdentifier ("_vala_%s_get_property".printf (cl.get_lower_case_cname (null)))))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "get_property"), new CCodeIdentifier ("_vala_%s_get_property".printf (cl.get_lower_case_cname (null))))); } if (class_has_writable_properties (cl) || cl.get_type_parameters ().size > 0) { - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "set_property"), new CCodeIdentifier ("_vala_%s_set_property".printf (cl.get_lower_case_cname (null)))))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "set_property"), new CCodeIdentifier ("_vala_%s_set_property".printf (cl.get_lower_case_cname (null))))); } /* set constructor */ if (cl.constructor != null) { var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); ccast.add_argument (new CCodeIdentifier ("klass")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "constructor"), new CCodeIdentifier ("%s_constructor".printf (cl.get_lower_case_cname (null)))))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "constructor"), new CCodeIdentifier ("%s_constructor".printf (cl.get_lower_case_cname (null))))); } /* set finalize function */ if (cl.get_fields ().size > 0 || cl.destructor != null) { var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); ccast.add_argument (new CCodeIdentifier ("klass")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%s_finalize".printf (cl.get_lower_case_cname (null)))))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%s_finalize".printf (cl.get_lower_case_cname (null))))); } /* create type, dup_func, and destroy_func properties for generic types */ @@ -90,7 +90,7 @@ public class Vala.GObjectModule : GTypeModule { cspec.add_argument (new CCodeIdentifier ("G_TYPE_NONE")); cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY")); cinst.add_argument (cspec); - init_block.add_statement (new CCodeExpressionStatement (cinst)); + ccode.add_expression (cinst); prop_enum.add_value (new CCodeEnumValue (enum_value)); @@ -106,7 +106,7 @@ public class Vala.GObjectModule : GTypeModule { cspec.add_argument (new CCodeConstant ("\"dup func\"")); cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY")); cinst.add_argument (cspec); - init_block.add_statement (new CCodeExpressionStatement (cinst)); + ccode.add_expression (cinst); prop_enum.add_value (new CCodeEnumValue (enum_value)); @@ -122,7 +122,7 @@ public class Vala.GObjectModule : GTypeModule { cspec.add_argument (new CCodeConstant ("\"destroy func\"")); cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY")); cinst.add_argument (cspec); - init_block.add_statement (new CCodeExpressionStatement (cinst)); + ccode.add_expression (cinst); prop_enum.add_value (new CCodeEnumValue (enum_value)); } @@ -134,7 +134,7 @@ public class Vala.GObjectModule : GTypeModule { } if (prop.comment != null) { - init_block.add_statement (new CCodeComment (prop.comment.content)); + ccode.add_statement (new CCodeComment (prop.comment.content)); } if (prop.overrides || prop.base_interface_property != null) { @@ -143,14 +143,14 @@ public class Vala.GObjectModule : GTypeModule { cinst.add_argument (new CCodeConstant (prop.get_upper_case_cname ())); cinst.add_argument (prop.get_canonical_cconstant ()); - init_block.add_statement (new CCodeExpressionStatement (cinst)); + ccode.add_expression (cinst); } else { var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); cinst.add_argument (ccall); cinst.add_argument (new CCodeConstant (prop.get_upper_case_cname ())); cinst.add_argument (get_param_spec (prop)); - init_block.add_statement (new CCodeExpressionStatement (cinst)); + ccode.add_expression (cinst); } } } @@ -412,18 +412,11 @@ public class Vala.GObjectModule : GTypeModule { } public override void visit_constructor (Constructor c) { - bool old_method_inner_error = current_method_inner_error; - current_method_inner_error = false; - if (c.binding == MemberBinding.CLASS || c.binding == MemberBinding.STATIC) { in_static_or_class_context = true; } else { in_constructor = true; } - c.body.emit (this); - in_static_or_class_context = false; - - in_constructor = false; var cl = (Class) c.parent_symbol; @@ -434,7 +427,9 @@ public class Vala.GObjectModule : GTypeModule { return; } - function = new CCodeFunction ("%s_constructor".printf (cl.get_lower_case_cname (null)), "GObject *"); + push_context (new EmitContext (c)); + + var function = new CCodeFunction ("%s_constructor".printf (cl.get_lower_case_cname (null)), "GObject *"); function.modifiers = CCodeModifiers.STATIC; function.add_parameter (new CCodeFormalParameter ("type", "GType")); @@ -443,52 +438,43 @@ public class Vala.GObjectModule : GTypeModule { cfile.add_function_declaration (function); + push_function (function); - var cblock = new CCodeBlock (); - var cdecl = new CCodeDeclaration ("GObject *"); - cdecl.add_declarator (new CCodeVariableDeclarator ("obj")); - cblock.add_statement (cdecl); - - cdecl = new CCodeDeclaration ("GObjectClass *"); - cdecl.add_declarator (new CCodeVariableDeclarator ("parent_class")); - cblock.add_statement (cdecl); - + ccode.add_declaration ("GObject *", new CCodeVariableDeclarator ("obj")); + ccode.add_declaration ("GObjectClass *", new CCodeVariableDeclarator ("parent_class")); var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null)))); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_class"), ccast))); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("parent_class"), ccast)); - var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier ("parent_class"), "constructor")); ccall.add_argument (new CCodeIdentifier ("type")); ccall.add_argument (new CCodeIdentifier ("n_construct_properties")); ccall.add_argument (new CCodeIdentifier ("construct_properties")); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("obj"), ccall))); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("obj"), ccall)); ccall = generate_instance_cast (new CCodeIdentifier ("obj"), cl); - cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator ("self", ccall)); - cblock.add_statement (cdecl); + ccode.add_declaration ("%s *".printf (cl.get_cname ()), new CCodeVariableDeclarator ("self")); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), ccall)); if (current_method_inner_error) { /* always separate error parameter and inner_error local variable * as error may be set to NULL but we're always interested in inner errors */ - cdecl = new CCodeDeclaration ("GError *"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_inner_error_", new CCodeConstant ("NULL"))); - cblock.add_statement (cdecl); + ccode.add_declaration ("GError *", new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL"))); } - cblock.add_statement (c.body.ccodenode); - - cblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("obj"))); + c.body.emit (this); - function.block = cblock; + ccode.add_return (new CCodeIdentifier ("obj")); + pop_function (); cfile.add_function (function); + + pop_context (); } else if (c.binding == MemberBinding.CLASS) { // class constructor @@ -498,16 +484,18 @@ public class Vala.GObjectModule : GTypeModule { return; } + push_context (base_init_context); + + c.body.emit (this); + if (current_method_inner_error) { /* always separate error parameter and inner_error local variable * as error may be set to NULL but we're always interested in inner errors */ - var cdecl = new CCodeDeclaration ("GError *"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_inner_error_", new CCodeConstant ("NULL"))); - base_init_fragment.append (cdecl); + ccode.add_declaration ("GError *", new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL"))); } - base_init_fragment.append (c.body.ccodenode); + pop_context (); } else if (c.binding == MemberBinding.STATIC) { // static class constructor // add to class_init @@ -518,21 +506,25 @@ public class Vala.GObjectModule : GTypeModule { return; } + push_context (class_init_context); + + c.body.emit (this); + if (current_method_inner_error) { /* always separate error parameter and inner_error local variable * as error may be set to NULL but we're always interested in inner errors */ - var cdecl = new CCodeDeclaration ("GError *"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_inner_error_", new CCodeConstant ("NULL"))); - class_init_fragment.append (cdecl); + ccode.add_declaration ("GError *", new CCodeVariableDeclarator ("_inner_error_", new CCodeConstant ("NULL"))); } - class_init_fragment.append (c.body.ccodenode); + pop_context (); } else { Report.error (c.source_reference, "internal error: constructors must have instance, class, or static binding"); } - current_method_inner_error = old_method_inner_error; + in_static_or_class_context = false; + + in_constructor = false; } public override string get_dynamic_property_getter_cname (DynamicProperty prop) { @@ -756,7 +748,7 @@ public class Vala.GObjectModule : GTypeModule { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (expr.value_type, false, expr, false); - temp_vars.add (temp_var); + emit_temp_var (temp_var); ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), (CCodeExpression) expr.ccodenode)); var initiallyunowned_ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_IS_INITIALLY_UNOWNED")); diff --git a/codegen/valagsignalmodule.vala b/codegen/valagsignalmodule.vala index e2b0de89a..8b90ef4c0 100644 --- a/codegen/valagsignalmodule.vala +++ b/codegen/valagsignalmodule.vala @@ -164,7 +164,7 @@ public class Vala.GSignalModule : GObjectModule { } var detail_decl = get_temp_variable (detail_expr.value_type, true, node); - temp_vars.insert (0, detail_decl); + emit_temp_var (detail_decl); temp_ref_vars.insert (0, detail_decl); var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat")); @@ -679,7 +679,7 @@ public class Vala.GSignalModule : GObjectModule { // get signal id ccomma = new CCodeCommaExpression (); var temp_decl = get_temp_variable (uint_type); - temp_vars.add (temp_decl); + emit_temp_var (temp_decl); var parse_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_parse_name")); parse_call.add_argument (signal_name_cexpr); var decl_type = (TypeSymbol) sig.parent_symbol; @@ -691,7 +691,7 @@ public class Vala.GSignalModule : GObjectModule { parse_call.add_argument (new CCodeConstant ("FALSE")); } else { detail_temp_decl = get_temp_variable (gquark_type); - temp_vars.add (detail_temp_decl); + emit_temp_var (detail_temp_decl); parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (detail_temp_decl.name))); parse_call.add_argument (new CCodeConstant ("TRUE")); } diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala index a6c1ebd4a..d6da08618 100644 --- a/codegen/valagtypemodule.vala +++ b/codegen/valagtypemodule.vala @@ -516,12 +516,12 @@ public class Vala.GTypeModule : GErrorModule { var old_param_spec_struct = param_spec_struct; var old_prop_enum = prop_enum; - var old_class_init_fragment = class_init_fragment; - var old_base_init_fragment = base_init_fragment; - var old_class_finalize_fragment = class_finalize_fragment; - var old_base_finalize_fragment = base_finalize_fragment; - var old_instance_init_fragment = instance_init_fragment; - var old_instance_finalize_fragment = instance_finalize_fragment; + var old_class_init_context = class_init_context; + var old_base_init_context = base_init_context; + var old_class_finalize_context = class_finalize_context; + var old_base_finalize_context = base_finalize_context; + var old_instance_init_context = instance_init_context; + var old_instance_finalize_context = instance_finalize_context; bool is_gtypeinstance = !cl.is_compact; bool is_fundamental = is_gtypeinstance && cl.base_class == null; @@ -534,12 +534,12 @@ public class Vala.GTypeModule : GErrorModule { prop_enum = new CCodeEnum (); prop_enum.add_value (new CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null)))); - class_init_fragment = new CCodeFragment (); - base_init_fragment = new CCodeFragment (); - class_finalize_fragment = new CCodeFragment (); - base_finalize_fragment = new CCodeFragment (); - instance_init_fragment = new CCodeFragment (); - instance_finalize_fragment = new CCodeFragment (); + class_init_context = new EmitContext (cl); + base_init_context = new EmitContext (cl); + class_finalize_context = new EmitContext (cl); + base_finalize_context = new EmitContext (cl); + instance_init_context = new EmitContext (cl); + instance_finalize_context = new EmitContext (cl); generate_class_struct_declaration (cl, cfile); @@ -552,6 +552,21 @@ public class Vala.GTypeModule : GErrorModule { generate_class_struct_declaration (cl, internal_header_file); } + if (is_gtypeinstance) { + begin_base_init_function (cl); + begin_class_init_function (cl); + begin_instance_init_function (cl); + + begin_base_finalize_function (cl); + begin_class_finalize_function (cl); + begin_finalize_function (cl); + } else { + if (cl.base_class == null) { + begin_instance_init_function (cl); + begin_finalize_function (cl); + } + } + cl.accept_children (this); if (is_gtypeinstance) { @@ -577,7 +592,7 @@ public class Vala.GTypeModule : GErrorModule { add_g_value_take_function (cl); var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1")); - instance_init_fragment.append (new CCodeExpressionStatement (ref_count)); + instance_init_context.ccode.add_expression (ref_count); } @@ -672,41 +687,18 @@ public class Vala.GTypeModule : GErrorModule { if (cl.base_class == null) { // derived compact classes do not have fields add_instance_init_function (cl); - - var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void"); - if (cl.access == SymbolAccessibility.PRIVATE) { - function.modifiers = CCodeModifiers.STATIC; - } - - function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*")); - - var cblock = new CCodeBlock (); - - if (cl.destructor != null) { - cblock.add_statement (cl.destructor.ccodenode); - } - - cblock.add_statement (instance_finalize_fragment); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); - ccall.add_argument (new CCodeIdentifier (cl.get_cname ())); - ccall.add_argument (new CCodeIdentifier ("self")); - cblock.add_statement (new CCodeExpressionStatement (ccall)); - - function.block = cblock; - - cfile.add_function (function); + add_finalize_function (cl); } } param_spec_struct = old_param_spec_struct; prop_enum = old_prop_enum; - class_init_fragment = old_class_init_fragment; - base_init_fragment = old_base_init_fragment; - class_finalize_fragment = old_class_finalize_fragment; - base_finalize_fragment = old_base_finalize_fragment; - instance_init_fragment = old_instance_init_fragment; - instance_finalize_fragment = old_instance_finalize_fragment; + class_init_context = old_class_init_context; + base_init_context = old_base_init_context; + class_finalize_context = old_class_finalize_context; + base_finalize_context = old_base_finalize_context; + instance_init_context = old_instance_init_context; + instance_finalize_context = old_instance_finalize_context; pop_context (); } @@ -1133,31 +1125,31 @@ public class Vala.GTypeModule : GErrorModule { cfile.add_function (function); } - private void add_base_init_function (Class cl) { + private void begin_base_init_function (Class cl) { + push_context (base_init_context); + var base_init = new CCodeFunction ("%s_base_init".printf (cl.get_lower_case_cname (null)), "void"); base_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ()))); base_init.modifiers = CCodeModifiers.STATIC; - var init_block = new CCodeBlock (); - base_init.block = init_block; + push_function (base_init); if (!context.require_glib_version (2, 24) && cl.has_class_private_fields) { - var block = new CCodeBlock (); var cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ())); cdecl.add_declarator (new CCodeVariableDeclarator ("priv")); - block.add_statement (cdecl); + ccode.add_statement (cdecl); cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ())); cdecl.add_declarator (new CCodeVariableDeclarator ("parent_priv", new CCodeConstant ("NULL"))); - block.add_statement (cdecl); + ccode.add_statement (cdecl); cdecl = new CCodeDeclaration ("GType"); cdecl.add_declarator (new CCodeVariableDeclarator ("parent_type")); - block.add_statement (cdecl); + ccode.add_statement (cdecl); var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_parent")); var ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS")); ccall2.add_argument (new CCodeIdentifier ("klass")); ccall.add_argument (ccall2); - block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_type"), ccall))); + ccode.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_type"), ccall))); var iftrue = new CCodeBlock (); ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname (null)))); @@ -1165,12 +1157,12 @@ public class Vala.GTypeModule : GErrorModule { ccall2.add_argument (new CCodeIdentifier ("parent_type")); ccall.add_argument (ccall2); iftrue.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_priv"), ccall))); - block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_type"), iftrue)); + ccode.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_type"), iftrue)); ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0")); ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf(cl.get_cname()))); - block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall))); + ccode.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall))); cfile.add_include ("string.h"); @@ -1181,7 +1173,7 @@ public class Vala.GTypeModule : GErrorModule { ccall.add_argument (new CCodeIdentifier ("sizeof (%sClassPrivate)".printf(cl.get_cname()))); iftrue.add_statement (new CCodeExpressionStatement (ccall)); - block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_priv"), iftrue)); + ccode.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_priv"), iftrue)); ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata")); ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS")); @@ -1189,42 +1181,26 @@ public class Vala.GTypeModule : GErrorModule { ccall.add_argument (ccall2); ccall.add_argument (new CCodeIdentifier ("_vala_%s_class_private_quark".printf (cl.get_lower_case_cname ()))); ccall.add_argument (new CCodeIdentifier ("priv")); - block.add_statement (new CCodeExpressionStatement (ccall)); - - init_block.add_statement (block); - - block = new CCodeBlock (); - cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator ("priv")); - block.add_statement (cdecl); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname (null)))); - ccall.add_argument (new CCodeConstant ("klass")); - block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall))); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); - ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf (cl.get_cname ()))); - ccall.add_argument (new CCodeIdentifier ("priv")); - block.add_statement (new CCodeExpressionStatement (ccall)); - base_finalize_fragment.append (block); + ccode.add_statement (new CCodeExpressionStatement (ccall)); } - init_block.add_statement (base_init_fragment); + pop_context (); + } - cfile.add_function (base_init); + private void add_base_init_function (Class cl) { + cfile.add_function (base_init_context.ccode); } - public virtual void generate_class_init (Class cl, CCodeBlock init_block) { + public virtual void generate_class_init (Class cl) { } - private void add_class_init_function (Class cl) { - var class_init = new CCodeFunction ("%s_class_init".printf (cl.get_lower_case_cname (null)), "void"); - class_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ()))); - class_init.modifiers = CCodeModifiers.STATIC; + private void begin_class_init_function (Class cl) { + push_context (class_init_context); + + var func = new CCodeFunction ("%s_class_init".printf (cl.get_lower_case_cname (null))); + func.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ()))); + func.modifiers = CCodeModifiers.STATIC; - var init_block = new CCodeBlock (); - class_init.block = init_block; - CCodeFunctionCall ccall; /* save pointer to parent class */ @@ -1234,10 +1210,13 @@ public class Vala.GTypeModule : GErrorModule { parent_decl.add_declarator (parent_var_decl); parent_decl.modifiers = CCodeModifiers.STATIC; cfile.add_type_member_declaration (parent_decl); + + push_function (func); + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent")); ccall.add_argument (new CCodeIdentifier ("klass")); var parent_assignment = new CCodeAssignment (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null))), ccall); - init_block.add_statement (new CCodeExpressionStatement (parent_assignment)); + ccode.add_expression (parent_assignment); if (!cl.is_compact && !cl.is_subtype_of (gobject_type) && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) { @@ -1250,7 +1229,7 @@ public class Vala.GTypeModule : GErrorModule { ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname (null)))); ccall.add_argument (new CCodeIdentifier ("klass")); var finalize_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "finalize"), new CCodeIdentifier (cl.get_lower_case_cprefix () + "finalize")); - init_block.add_statement (new CCodeExpressionStatement (finalize_assignment)); + ccode.add_expression (finalize_assignment); } /* add struct for private fields */ @@ -1258,7 +1237,7 @@ public class Vala.GTypeModule : GErrorModule { ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_add_private")); ccall.add_argument (new CCodeIdentifier ("klass")); ccall.add_argument (new CCodeConstant ("sizeof (%sPrivate)".printf (cl.get_cname ()))); - init_block.add_statement (new CCodeExpressionStatement (ccall)); + ccode.add_expression (ccall); } /* connect overridden methods */ @@ -1273,10 +1252,10 @@ public class Vala.GTypeModule : GErrorModule { var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null)))); ccast.add_argument (new CCodeIdentifier ("klass")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.vfunc_name), new CCodeIdentifier (m.get_real_cname ())))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.vfunc_name), new CCodeIdentifier (m.get_real_cname ()))); if (m.coroutine) { - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.get_finish_vfunc_name ()), new CCodeIdentifier (m.get_finish_real_cname ())))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.get_finish_vfunc_name ()), new CCodeIdentifier (m.get_finish_real_cname ()))); } } } @@ -1288,7 +1267,7 @@ public class Vala.GTypeModule : GErrorModule { } var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (cl.get_upper_case_cname (null)))); ccast.add_argument (new CCodeIdentifier ("klass")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, sig.default_handler.vfunc_name), new CCodeIdentifier (sig.default_handler.get_real_cname ())))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, sig.default_handler.vfunc_name), new CCodeIdentifier (sig.default_handler.get_real_cname ()))); } /* connect overridden properties */ @@ -1303,30 +1282,33 @@ public class Vala.GTypeModule : GErrorModule { if (prop.get_accessor != null) { string cname = "%s_real_get_%s".printf (cl.get_lower_case_cname (null), prop.name); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname)))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname))); } if (prop.set_accessor != null) { string cname = "%s_real_set_%s".printf (cl.get_lower_case_cname (null), prop.name); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname)))); + ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname))); } } - generate_class_init (cl, init_block); + generate_class_init (cl); if (!cl.is_compact) { /* create signals */ foreach (Signal sig in cl.get_signals ()) { if (sig.comment != null) { - init_block.add_statement (new CCodeComment (sig.comment.content)); + ccode.add_statement (new CCodeComment (sig.comment.content)); } - init_block.add_statement (new CCodeExpressionStatement (get_signal_creation (sig, cl))); + ccode.add_expression (get_signal_creation (sig, cl)); } } - init_block.add_statement (register_dbus_info (cl)); - init_block.add_statement (class_init_fragment); + register_dbus_info (cl); - cfile.add_function (class_init); + pop_context (); + } + + private void add_class_init_function (Class cl) { + cfile.add_function (class_init_context.ccode); } private void add_interface_init_function (Class cl, Interface iface) { @@ -1540,111 +1522,167 @@ public class Vala.GTypeModule : GErrorModule { return new CCodeCastExpression (cfunc, cast); } - private void add_instance_init_function (Class cl) { - var instance_init = new CCodeFunction ("%s_instance_init".printf (cl.get_lower_case_cname (null)), "void"); - instance_init.add_parameter (new CCodeFormalParameter ("self", "%s *".printf (cl.get_cname ()))); - instance_init.modifiers = CCodeModifiers.STATIC; - + private void begin_instance_init_function (Class cl) { + push_context (instance_init_context); + + var func = new CCodeFunction ("%s_instance_init".printf (cl.get_lower_case_cname (null))); + func.add_parameter (new CCodeFormalParameter ("self", "%s *".printf (cl.get_cname ()))); + func.modifiers = CCodeModifiers.STATIC; + + push_function (func); + if (cl.is_compact) { // Add declaration, since the instance_init function is explicitly called // by the creation methods - cfile.add_function_declaration (instance_init); + cfile.add_function_declaration (func); } - var init_block = new CCodeBlock (); - instance_init.block = init_block; - if (!cl.is_compact && (cl.has_private_fields || cl.get_type_parameters ().size > 0)) { var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null)))); ccall.add_argument (new CCodeIdentifier ("self")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall))); + func.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall)); } - - init_block.add_statement (instance_init_fragment); - cfile.add_function (instance_init); + pop_context (); } - private void add_class_finalize_function (Class cl) { + private void add_instance_init_function (Class cl) { + cfile.add_function (instance_init_context.ccode); + } + + private void begin_class_finalize_function (Class cl) { + push_context (class_finalize_context); + var function = new CCodeFunction ("%s_class_finalize".printf (cl.get_lower_case_cname (null)), "void"); function.modifiers = CCodeModifiers.STATIC; function.add_parameter (new CCodeFormalParameter ("klass", cl.get_cname () + "Class *")); - cfile.add_function_declaration (function); - - var cblock = new CCodeBlock (); + + push_function (function); if (cl.class_destructor != null) { - cblock.add_statement (cl.class_destructor.ccodenode); + cl.class_destructor.body.emit (this); } - cblock.add_statement (class_finalize_fragment); + pop_context (); + } - function.block = cblock; - cfile.add_function (function); + private void add_class_finalize_function (Class cl) { + cfile.add_function_declaration (class_finalize_context.ccode); + cfile.add_function (class_finalize_context.ccode); } - private void add_base_finalize_function (Class cl) { + private void begin_base_finalize_function (Class cl) { + push_context (base_finalize_context); + var function = new CCodeFunction ("%s_base_finalize".printf (cl.get_lower_case_cname (null)), "void"); function.modifiers = CCodeModifiers.STATIC; function.add_parameter (new CCodeFormalParameter ("klass", cl.get_cname () + "Class *")); - cfile.add_function_declaration (function); - - var cblock = new CCodeBlock (); + + push_function (function); if (cl.class_destructor != null) { - cblock.add_statement (cl.class_destructor.ccodenode); + cl.class_destructor.body.emit (this); } - cblock.add_statement (base_finalize_fragment); - - function.block = cblock; - cfile.add_function (function); + pop_context (); } - private void add_finalize_function (Class cl) { - var function = new CCodeFunction ("%s_finalize".printf (cl.get_lower_case_cname (null)), "void"); - function.modifiers = CCodeModifiers.STATIC; + private void add_base_finalize_function (Class cl) { + push_context (base_finalize_context); + + if (!context.require_glib_version (2, 24) && cl.has_class_private_fields) { + ccode.open_block (); + + var cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator ("priv")); + ccode.add_statement (cdecl); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname (null)))); + ccall.add_argument (new CCodeConstant ("klass")); + ccode.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall))); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); + ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf (cl.get_cname ()))); + ccall.add_argument (new CCodeIdentifier ("priv")); + ccode.add_statement (new CCodeExpressionStatement (ccall)); - var fundamental_class = cl; - while (fundamental_class.base_class != null) { - fundamental_class = fundamental_class.base_class; + ccode.close (); } - function.add_parameter (new CCodeFormalParameter ("obj", fundamental_class.get_cname () + "*")); + cfile.add_function_declaration (ccode); + cfile.add_function (ccode); - cfile.add_function_declaration (function); + pop_context (); + } + private void begin_finalize_function (Class cl) { + push_context (instance_finalize_context); - var cblock = new CCodeBlock (); + if (!cl.is_compact) { + var fundamental_class = cl; + while (fundamental_class.base_class != null) { + fundamental_class = fundamental_class.base_class; + } - CCodeFunctionCall ccall = generate_instance_cast (new CCodeIdentifier ("obj"), cl); + var func = new CCodeFunction ("%s_finalize".printf (cl.get_lower_case_cname (null))); + func.add_parameter (new CCodeFormalParameter ("obj", fundamental_class.get_cname () + "*")); + func.modifiers = CCodeModifiers.STATIC; - var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator ("self", ccall)); - - cblock.add_statement (cdecl); + push_function (func); - if (cl.destructor != null) { - cblock.add_statement (cl.destructor.ccodenode); - } + CCodeFunctionCall ccall = generate_instance_cast (new CCodeIdentifier ("obj"), cl); - cblock.add_statement (instance_finalize_fragment); + ccode.add_declaration ("%s *".printf (cl.get_cname ()), new CCodeVariableDeclarator ("self")); + ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), ccall)); - // chain up to finalize function of the base class - if (cl.base_class != null) { - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname ()))); - ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null)))); - ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize")); - ccall.add_argument (new CCodeIdentifier ("obj")); - cblock.add_statement (new CCodeExpressionStatement (ccall)); + if (cl.destructor != null) { + cl.destructor.body.emit (this); + } + } else { + var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void"); + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + } + + function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*")); + + push_function (function); + + if (cl.destructor != null) { + cl.destructor.body.emit (this); + } } + pop_context (); + } - function.block = cblock; + private void add_finalize_function (Class cl) { + if (!cl.is_compact) { + var fundamental_class = cl; + while (fundamental_class.base_class != null) { + fundamental_class = fundamental_class.base_class; + } - cfile.add_function (function); + // chain up to finalize function of the base class + if (cl.base_class != null) { + var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname ()))); + ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null)))); + var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize")); + ccall.add_argument (new CCodeIdentifier ("obj")); + instance_finalize_context.ccode.add_expression (ccall); + } + + cfile.add_function_declaration (instance_finalize_context.ccode); + } else { + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); + ccall.add_argument (new CCodeIdentifier (cl.get_cname ())); + ccall.add_argument (new CCodeIdentifier ("self")); + instance_finalize_context.ccode.add_expression (ccall); + } + + cfile.add_function (instance_finalize_context.ccode); } public override CCodeFunctionCall get_param_spec (Property prop) { @@ -1687,7 +1725,7 @@ public class Vala.GTypeModule : GErrorModule { } if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode); + cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); } else { cspec.add_argument (new CCodeConstant (prop.property_type.data_type.get_default_value ())); } @@ -1698,7 +1736,7 @@ public class Vala.GTypeModule : GErrorModule { cspec.add_argument (new CCodeConstant ("G_MININT")); cspec.add_argument (new CCodeConstant ("G_MAXINT")); if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode); + cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); } else { cspec.add_argument (new CCodeConstant ("0")); } @@ -1707,7 +1745,7 @@ public class Vala.GTypeModule : GErrorModule { cspec.add_argument (new CCodeConstant ("0")); cspec.add_argument (new CCodeConstant ("G_MAXUINT")); if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode); + cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); } else { cspec.add_argument (new CCodeConstant ("0U")); } @@ -1716,7 +1754,7 @@ public class Vala.GTypeModule : GErrorModule { cspec.add_argument (new CCodeConstant ("G_MININT64")); cspec.add_argument (new CCodeConstant ("G_MAXINT64")); if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode); + cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); } else { cspec.add_argument (new CCodeConstant ("0")); } @@ -1725,7 +1763,7 @@ public class Vala.GTypeModule : GErrorModule { cspec.add_argument (new CCodeConstant ("0")); cspec.add_argument (new CCodeConstant ("G_MAXUINT64")); if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode); + cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); } else { cspec.add_argument (new CCodeConstant ("0U")); } @@ -1734,7 +1772,7 @@ public class Vala.GTypeModule : GErrorModule { cspec.add_argument (new CCodeConstant ("G_MINLONG")); cspec.add_argument (new CCodeConstant ("G_MAXLONG")); if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode); + cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); } else { cspec.add_argument (new CCodeConstant ("0L")); } @@ -1743,14 +1781,14 @@ public class Vala.GTypeModule : GErrorModule { cspec.add_argument (new CCodeConstant ("0")); cspec.add_argument (new CCodeConstant ("G_MAXULONG")); if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode); + cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); } else { cspec.add_argument (new CCodeConstant ("0UL")); } } else if (st.get_type_id () == "G_TYPE_BOOLEAN") { cspec.call = new CCodeIdentifier ("g_param_spec_boolean"); if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode); + cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); } else { cspec.add_argument (new CCodeConstant ("FALSE")); } @@ -1759,7 +1797,7 @@ public class Vala.GTypeModule : GErrorModule { cspec.add_argument (new CCodeConstant ("G_MININT8")); cspec.add_argument (new CCodeConstant ("G_MAXINT8")); if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode); + cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); } else { cspec.add_argument (new CCodeConstant ("0")); } @@ -1768,7 +1806,7 @@ public class Vala.GTypeModule : GErrorModule { cspec.add_argument (new CCodeConstant ("0")); cspec.add_argument (new CCodeConstant ("G_MAXUINT8")); if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode); + cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); } else { cspec.add_argument (new CCodeConstant ("0")); } @@ -1777,7 +1815,7 @@ public class Vala.GTypeModule : GErrorModule { cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT")); cspec.add_argument (new CCodeConstant ("G_MAXFLOAT")); if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode); + cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); } else { cspec.add_argument (new CCodeConstant ("0.0F")); } @@ -1786,14 +1824,14 @@ public class Vala.GTypeModule : GErrorModule { cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE")); cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE")); if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode); + cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); } else { cspec.add_argument (new CCodeConstant ("0.0")); } } else if (st.get_type_id () == "G_TYPE_GTYPE") { cspec.call = new CCodeIdentifier ("g_param_spec_gtype"); if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode); + cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); } else { cspec.add_argument (new CCodeConstant ("G_TYPE_NONE")); } @@ -2065,7 +2103,7 @@ public class Vala.GTypeModule : GErrorModule { var ccomma = new CCodeCommaExpression (); var temp_var = get_temp_variable (new CType ("GEnumValue*"), false, expr, false); - temp_vars.add (temp_var); + emit_temp_var (temp_var); var class_ref = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_ref")); class_ref.add_argument (new CCodeIdentifier (ma.inner.value_type.get_type_id ())); diff --git a/vala/valablock.vala b/vala/valablock.vala index 64cbfaab7..d7b35f28f 100644 --- a/vala/valablock.vala +++ b/vala/valablock.vala @@ -165,6 +165,7 @@ public class Vala.Block : Symbol, Statement { for (int j = 0; j < stmt_list.length; j++) { if (stmt_list.get (j) == stmt) { stmt_list.insert (j, new_stmt); + new_stmt.parent_node = this; break; } } @@ -173,6 +174,7 @@ public class Vala.Block : Symbol, Statement { stmt_list.add (new_stmt); stmt_list.add (stmt); statement_list[i] = stmt_list; + new_stmt.parent_node = this; } } } @@ -184,11 +186,13 @@ public class Vala.Block : Symbol, Statement { for (int j = 0; j < stmt_list.length; j++) { if (stmt_list.get (j) == old_stmt) { stmt_list.set (j, new_stmt); + new_stmt.parent_node = this; break; } } } else if (statement_list[i] == old_stmt) { statement_list[i] = new_stmt; + new_stmt.parent_node = this; break; } } diff --git a/vala/valaexpression.vala b/vala/valaexpression.vala index 23c01e291..eafb202d8 100644 --- a/vala/valaexpression.vala +++ b/vala/valaexpression.vala @@ -1,6 +1,6 @@ /* valaexpression.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 @@ -55,14 +55,6 @@ public abstract class Vala.Expression : CodeNode { */ public bool lvalue { get; set; } - /** - * Contains all temporary variables this expression requires for - * execution. - * - * The code generator sets and uses them for memory management. - */ - public ArrayList temp_vars; - private List array_sizes; public CCodeExpression? delegate_target { get; set; } @@ -89,13 +81,6 @@ public abstract class Vala.Expression : CodeNode { return false; } - public void add_temp_var (LocalVariable local) { - if (temp_vars == null) { - temp_vars = new ArrayList (); - } - temp_vars.add (local); - } - /** * Add an array size C code expression. */ diff --git a/vala/valamethod.vala b/vala/valamethod.vala index a29ab0592..bc6510e23 100644 --- a/vala/valamethod.vala +++ b/vala/valamethod.vala @@ -233,6 +233,8 @@ public class Vala.Method : Symbol { public bool is_async_callback { get; set; } + public int yield_count { get; set; } + private List parameters = new ArrayList (); private string cname; private string finish_name; diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala index a493c56cd..23a109a49 100644 --- a/vala/valamethodcall.vala +++ b/vala/valamethodcall.vala @@ -538,6 +538,7 @@ public class Vala.MethodCall : Expression { error = true; Report.error (source_reference, "yield expression not available outside async method"); } + analyzer.current_method.yield_count++; } if (m != null && m.coroutine && !is_yield_expression && ((MemberAccess) call).member_name != "end") { // .begin call of async method, no error can happen here diff --git a/vala/valayieldstatement.vala b/vala/valayieldstatement.vala index be526a1de..0fd6e3454 100644 --- a/vala/valayieldstatement.vala +++ b/vala/valayieldstatement.vala @@ -75,6 +75,8 @@ public class Vala.YieldStatement : CodeNode, Statement { error = yield_expression.error; } + analyzer.current_method.yield_count++; + return !error; } -- 2.47.2