486
public override CCodeIdentifier get_value_taker_function (DataType type_reference) {
487
var array_type = type_reference as ArrayType;
488
if (type_reference.data_type != null) {
489
return new CCodeIdentifier (type_reference.data_type.get_take_value_function ());
490
} else if (array_type != null && array_type.element_type.data_type == string_type.data_type) {
492
return new CCodeIdentifier ("g_value_take_boxed");
494
return new CCodeIdentifier ("g_value_set_pointer");
475
498
CCodeIdentifier get_value_getter_function (DataType type_reference) {
476
499
var array_type = type_reference as ArrayType;
477
500
if (type_reference.data_type != null) {
784
809
if (!en.is_private_symbol ()) {
785
810
generate_enum_declaration (en, internal_header_declarations);
788
if (!en.has_type_id) {
792
var clist = new CCodeInitializerList (); /* or during visit time? */
793
CCodeInitializerList clist_ev = null;
794
foreach (EnumValue ev in en.get_values ()) {
795
clist_ev = new CCodeInitializerList ();
796
clist_ev.append (new CCodeConstant (ev.get_cname ()));
797
clist_ev.append (new CCodeIdentifier ("\"%s\"".printf (ev.get_cname ())));
798
clist_ev.append (ev.get_canonical_cconstant ());
799
clist.append (clist_ev);
802
clist_ev = new CCodeInitializerList ();
803
clist_ev.append (new CCodeConstant ("0"));
804
clist_ev.append (new CCodeConstant ("NULL"));
805
clist_ev.append (new CCodeConstant ("NULL"));
806
clist.append (clist_ev);
808
var enum_decl = new CCodeVariableDeclarator ("values[]", clist);
810
CCodeDeclaration cdecl = null;
812
cdecl = new CCodeDeclaration ("const GFlagsValue");
814
cdecl = new CCodeDeclaration ("const GEnumValue");
817
cdecl.add_declarator (enum_decl);
818
cdecl.modifiers = CCodeModifiers.STATIC;
820
var type_init = new CCodeBlock ();
822
type_init.add_statement (cdecl);
824
var fun_name = "%s_get_type".printf (en.get_lower_case_cname (null));
825
var regfun = new CCodeFunction (fun_name, "GType");
826
var regblock = new CCodeBlock ();
828
cdecl = new CCodeDeclaration ("GType");
829
string type_id_name = "%s_type_id".printf (en.get_lower_case_cname (null));
830
cdecl.add_declarator (new CCodeVariableDeclarator (type_id_name, new CCodeConstant ("0")));
831
cdecl.modifiers = CCodeModifiers.STATIC;
832
regblock.add_statement (cdecl);
834
CCodeFunctionCall reg_call;
836
reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_flags_register_static"));
838
reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_enum_register_static"));
841
reg_call.add_argument (new CCodeConstant ("\"%s\"".printf (en.get_cname())));
842
reg_call.add_argument (new CCodeIdentifier ("values"));
844
type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (type_id_name), reg_call)));
846
var cond = new CCodeFunctionCall (new CCodeIdentifier ("G_UNLIKELY"));
847
cond.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (type_id_name), new CCodeConstant ("0")));
848
var cif = new CCodeIfStatement (cond, type_init);
849
regblock.add_statement (cif);
851
regblock.add_statement (new CCodeReturnStatement (new CCodeConstant (type_id_name)));
853
if (en.access == SymbolAccessibility.PRIVATE) {
854
regfun.modifiers = CCodeModifiers.STATIC;
856
regfun.block = regblock;
858
source_type_member_definition.append (new CCodeNewline ());
859
source_type_member_definition.append (regfun);
862
814
public override void visit_member (Member m) {
872
824
finalize_fragment = instance_finalize_fragment;
873
825
} else if (m.is_class_member ()) {
874
826
TypeSymbol parent = (TypeSymbol)m.parent_symbol;
875
l = new CCodeIdentifier ("%s_GET_CLASS_PRIVATE(%s)".printf(parent.get_upper_case_cname (), parent.get_type_id ()));
876
l = new CCodeMemberAccess.pointer (l, get_symbol_lock_name (m.name));
828
var get_class_private_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf(parent.get_upper_case_cname ())));
829
get_class_private_call.add_argument (new CCodeIdentifier ("klass"));
830
l = new CCodeMemberAccess.pointer (get_class_private_call, get_symbol_lock_name (m.name));
878
832
l = new CCodeIdentifier (get_symbol_lock_name ("%s_%s".printf(m.parent_symbol.get_lower_case_cname (), m.name)));
900
854
if (!c.external) {
901
855
generate_type_declaration (c.type_reference, decl_space);
903
if (c.initializer is InitializerList) {
857
var initializer_list = c.initializer as InitializerList;
858
if (initializer_list != null) {
904
859
var cdecl = new CCodeDeclaration (c.type_reference.get_const_cname ());
906
861
if (c.type_reference is ArrayType) {
909
cdecl.add_declarator (new CCodeVariableDeclarator ("%s%s".printf (c.get_cname (), arr), (CCodeExpression) c.initializer.ccodenode));
910
cdecl.modifiers = CCodeModifiers.STATIC;
862
arr = "[%d]".printf (initializer_list.size);
865
var cinitializer = (CCodeExpression) c.initializer.ccodenode;
867
// never output value in header
868
// special case needed as this method combines declaration and definition
872
cdecl.add_declarator (new CCodeVariableDeclarator ("%s%s".printf (c.get_cname (), arr), cinitializer));
873
if (c.is_private_symbol ()) {
874
cdecl.modifiers = CCodeModifiers.STATIC;
876
cdecl.modifiers = CCodeModifiers.EXTERN;
912
879
decl_space.add_constant_declaration (cdecl);
966
933
if (f.field_type is ArrayType && !f.no_array_length) {
967
934
var array_type = (ArrayType) f.field_type;
969
for (int dim = 1; dim <= array_type.rank; dim++) {
970
var len_type = int_type.copy ();
936
if (!array_type.fixed_length) {
937
for (int dim = 1; dim <= array_type.rank; dim++) {
938
var len_type = int_type.copy ();
972
cdecl = new CCodeDeclaration (len_type.get_cname ());
973
cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname (f.get_cname (), dim)));
974
if (f.is_private_symbol ()) {
975
cdecl.modifiers = CCodeModifiers.STATIC;
977
cdecl.modifiers = CCodeModifiers.EXTERN;
940
cdecl = new CCodeDeclaration (len_type.get_cname ());
941
cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname (f.get_cname (), dim)));
942
if (f.is_private_symbol ()) {
943
cdecl.modifiers = CCodeModifiers.STATIC;
945
cdecl.modifiers = CCodeModifiers.EXTERN;
947
decl_space.add_type_member_declaration (cdecl);
979
decl_space.add_type_member_declaration (cdecl);
981
950
} else if (f.field_type is DelegateType) {
982
951
var delegate_type = (DelegateType) f.field_type;
1091
1060
f.error = true;
1064
if (f.access == SymbolAccessibility.PRIVATE) {
1065
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname ())));
1066
ccall.add_argument (new CCodeIdentifier ("klass"));
1067
lhs = new CCodeMemberAccess (ccall, f.get_cname (), true);
1069
lhs = new CCodeMemberAccess (new CCodeIdentifier ("klass"), f.get_cname (), true);
1072
if (f.initializer != null) {
1073
var rhs = (CCodeExpression) f.initializer.ccodenode;
1075
class_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
1077
append_temp_decl (class_init_fragment, temp_vars);
1079
foreach (LocalVariable local in temp_ref_vars) {
1080
var ma = new MemberAccess.simple (local.name);
1081
ma.symbol_reference = local;
1082
ma.value_type = local.variable_type.copy ();
1083
class_init_fragment.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
1087
temp_ref_vars.clear ();
1095
1090
generate_field_declaration (f, source_declarations);
1126
1121
if (f.field_type is ArrayType && !f.no_array_length) {
1127
1122
var array_type = (ArrayType) f.field_type;
1129
for (int dim = 1; dim <= array_type.rank; dim++) {
1130
var len_type = int_type.copy ();
1132
var len_def = new CCodeDeclaration (len_type.get_cname ());
1133
len_def.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname (f.get_cname (), dim), new CCodeConstant ("0")));
1134
if (!f.is_private_symbol ()) {
1135
len_def.modifiers = CCodeModifiers.EXTERN;
1137
len_def.modifiers = CCodeModifiers.STATIC;
1139
source_declarations.add_type_member_declaration (len_def);
1142
if (array_type.rank == 1 && f.is_internal_symbol ()) {
1143
var len_type = int_type.copy ();
1145
var cdecl = new CCodeDeclaration (len_type.get_cname ());
1146
cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_size_cname (f.get_cname ()), new CCodeConstant ("0")));
1147
cdecl.modifiers = CCodeModifiers.STATIC;
1148
source_declarations.add_type_member_declaration (cdecl);
1124
if (!array_type.fixed_length) {
1125
for (int dim = 1; dim <= array_type.rank; dim++) {
1126
var len_type = int_type.copy ();
1128
var len_def = new CCodeDeclaration (len_type.get_cname ());
1129
len_def.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname (f.get_cname (), dim), new CCodeConstant ("0")));
1130
if (!f.is_private_symbol ()) {
1131
len_def.modifiers = CCodeModifiers.EXTERN;
1133
len_def.modifiers = CCodeModifiers.STATIC;
1135
source_declarations.add_type_member_declaration (len_def);
1138
if (array_type.rank == 1 && f.is_internal_symbol ()) {
1139
var len_type = int_type.copy ();
1141
var cdecl = new CCodeDeclaration (len_type.get_cname ());
1142
cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_size_cname (f.get_cname ()), new CCodeConstant ("0")));
1143
cdecl.modifiers = CCodeModifiers.STATIC;
1144
source_declarations.add_type_member_declaration (cdecl);
1150
1147
} else if (f.field_type is DelegateType) {
1151
1148
var delegate_type = (DelegateType) f.field_type;
1703
void capture_parameter (FormalParameter param, CCodeStruct data, CCodeBlock cblock, int block_id, CCodeBlock free_block) {
1704
var param_type = param.parameter_type.copy ();
1705
param_type.value_owned = true;
1706
data.add_field (param_type.get_cname (), get_variable_cname (param.name));
1708
bool is_unowned_delegate = param.parameter_type is DelegateType && !param.parameter_type.value_owned;
1710
// create copy if necessary as captured variables may need to be kept alive
1711
CCodeExpression cparam = get_variable_cexpression (param.name);
1712
if (requires_copy (param_type) && !param.parameter_type.value_owned && !is_unowned_delegate) {
1713
var ma = new MemberAccess.simple (param.name);
1714
ma.symbol_reference = param;
1715
ma.value_type = param.parameter_type.copy ();
1716
// directly access parameters in ref expressions
1717
param.captured = false;
1718
cparam = get_ref_cexpression (param.parameter_type, cparam, ma, param);
1719
param.captured = true;
1722
cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_variable_cname (param.name)), cparam)));
1724
if (param.parameter_type is ArrayType) {
1725
var array_type = (ArrayType) param.parameter_type;
1726
for (int dim = 1; dim <= array_type.rank; dim++) {
1727
data.add_field ("gint", get_array_length_cname (get_variable_cname (param.name), dim));
1728
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)))));
1730
} else if (param.parameter_type is DelegateType) {
1731
data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (param.name)));
1732
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))))));
1733
if (param.parameter_type.value_owned) {
1734
data.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)));
1735
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))))));
1739
if (requires_destroy (param_type) && !is_unowned_delegate) {
1740
bool old_coroutine = false;
1741
if (current_method != null) {
1742
old_coroutine = current_method.coroutine;
1743
current_method.coroutine = false;
1746
var ma = new MemberAccess.simple (param.name);
1747
ma.symbol_reference = param;
1748
ma.value_type = param_type.copy ();
1749
free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), get_variable_cname (param.name)), param.parameter_type, ma)));
1751
if (old_coroutine) {
1752
current_method.coroutine = true;
1700
1757
public override void visit_block (Block b) {
1701
1758
var old_symbol = current_symbol;
1702
1759
current_symbol = b;
1728
1785
var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (parent_block_id)));
1729
1786
unref_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)));
1730
1787
free_block.add_statement (new CCodeExpressionStatement (unref_call));
1731
} else if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE)) {
1788
} else if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE) ||
1789
(current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE)) {
1732
1790
data.add_field ("%s *".printf (current_class.get_cname ()), "self");
1734
1792
var ma = new MemberAccess.simple ("this");
1796
1855
ref_call.add_argument (get_variable_cexpression ("_data%d_".printf (parent_block_id)));
1798
1857
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)));
1799
} else if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE)) {
1858
} else if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE &&
1859
(!(current_method is CreationMethod) || current_method.body != b)) ||
1860
(current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE)) {
1800
1861
var ref_call = new CCodeFunctionCall (get_dup_func_expression (new ObjectType (current_class), b.source_reference));
1801
1862
ref_call.add_argument (get_result_cexpression ("self"));
1809
1870
// parameters are captured with the top-level block of the method
1810
1871
foreach (var param in m.get_parameters ()) {
1811
1872
if (param.captured) {
1812
var param_type = param.parameter_type.copy ();
1813
param_type.value_owned = true;
1814
data.add_field (param_type.get_cname (), get_variable_cname (param.name));
1816
bool is_unowned_delegate = param.parameter_type is DelegateType && !param.parameter_type.value_owned;
1818
// create copy if necessary as captured variables may need to be kept alive
1819
CCodeExpression cparam = get_variable_cexpression (param.name);
1820
if (requires_copy (param_type) && !param.parameter_type.value_owned && !is_unowned_delegate) {
1821
var ma = new MemberAccess.simple (param.name);
1822
ma.symbol_reference = param;
1823
ma.value_type = param.parameter_type.copy ();
1824
// directly access parameters in ref expressions
1825
param.captured = false;
1826
cparam = get_ref_cexpression (param.parameter_type, cparam, ma, param);
1827
param.captured = true;
1830
cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_variable_cname (param.name)), cparam)));
1832
if (param.parameter_type is ArrayType) {
1833
var array_type = (ArrayType) param.parameter_type;
1834
for (int dim = 1; dim <= array_type.rank; dim++) {
1835
data.add_field ("gint", get_array_length_cname (get_variable_cname (param.name), dim));
1836
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)))));
1838
} else if (param.parameter_type is DelegateType) {
1839
data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (param.name)));
1840
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))))));
1841
if (param.parameter_type.value_owned) {
1842
data.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)));
1843
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))))));
1847
if (requires_destroy (param_type) && !is_unowned_delegate) {
1848
bool old_coroutine = false;
1849
if (current_method != null) {
1850
old_coroutine = current_method.coroutine;
1851
current_method.coroutine = false;
1854
var ma = new MemberAccess.simple (param.name);
1855
ma.symbol_reference = param;
1856
ma.value_type = param_type.copy ();
1857
free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), get_variable_cname (param.name)), param.parameter_type, ma)));
1859
if (old_coroutine) {
1860
current_method.coroutine = true;
1873
capture_parameter (param, data, cblock, block_id, free_block);
1876
1887
append_temp_decl (cfrag, temp_vars);
1877
1888
temp_vars.clear ();
1878
1889
cblock.add_statement (cfrag);
1890
} else if (b.parent_symbol is PropertyAccessor) {
1891
var acc = (PropertyAccessor) b.parent_symbol;
1893
if (!acc.readable && acc.value_parameter.captured) {
1894
capture_parameter (acc.value_parameter, data, cblock, block_id, free_block);
1897
var cfrag = new CCodeFragment ();
1898
append_temp_decl (cfrag, temp_vars);
1900
cblock.add_statement (cfrag);
1881
1903
var data_free = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
2147
2180
closure_struct.add_field (local.variable_type.get_cname (), get_variable_cname (local.name) + local.variable_type.get_cdeclarator_suffix ());
2149
2182
if (local.initializer != null) {
2150
cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (local.name)), rhs)));
2183
if (has_simple_struct_initializer (local)) {
2184
cfrag.append (new CCodeExpressionStatement (rhs));
2186
cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (local.name)), rhs)));
2190
CCodeStatement post_stmt = null;
2191
if (has_simple_struct_initializer (local)) {
2192
post_stmt = new CCodeExpressionStatement (rhs);
2153
2196
var cvar = new CCodeVariableDeclarator (get_variable_cname (local.name), rhs, local.variable_type.get_cdeclarator_suffix ());
2154
2197
if (rhs != null) {
2155
2198
cvar.line = rhs.line;
2819
2867
if (type is ValueType && !type.nullable) {
2820
2868
// normal value type, no null check
2821
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cvar));
2869
var st = type.data_type as Struct;
2870
if (st != null && st.is_simple_type ()) {
2872
ccall.add_argument (cvar);
2874
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cvar));
2823
2877
if (gvalue_type != null && type.data_type == gvalue_type) {
2824
2878
// g_value_unset must not be called for already unset values
2955
var expr_type = expr.value_type;
2956
if (expr.target_type != null) {
2957
expr_type = expr.target_type;
2960
var full_expr_var = get_temp_variable (expr_type, true, expr, false);
2961
expr.temp_vars.add (full_expr_var);
2963
3009
var expr_list = new CCodeCommaExpression ();
2964
expr_list.append_expression (new CCodeAssignment (get_variable_cexpression (full_expr_var.name), (CCodeExpression) expr.ccodenode));
3011
LocalVariable full_expr_var = null;
3013
var local_decl = expr.parent_node as LocalVariable;
3014
if (local_decl != null && has_simple_struct_initializer (local_decl)) {
3015
expr_list.append_expression ((CCodeExpression) expr.ccodenode);
3017
var expr_type = expr.value_type;
3018
if (expr.target_type != null) {
3019
expr_type = expr.target_type;
3022
full_expr_var = get_temp_variable (expr_type, true, expr, false);
3023
expr.temp_vars.add (full_expr_var);
3025
expr_list.append_expression (new CCodeAssignment (get_variable_cexpression (full_expr_var.name), (CCodeExpression) expr.ccodenode));
2966
3028
foreach (LocalVariable local in temp_ref_vars) {
2967
3029
var ma = new MemberAccess.simple (local.name);
3047
3111
stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.expression.ccodenode);
3113
/* free temporary objects and handle errors */
3115
if (((List<LocalVariable>) temp_vars).size == 0
3116
&& pre_statement_fragment == null
3117
&& (!stmt.tree_can_fail || !stmt.expression.tree_can_fail)) {
3118
/* nothing to do without temporary variables and errors */
3122
var cfrag = new CCodeFragment ();
3123
append_temp_decl (cfrag, temp_vars);
3125
if (pre_statement_fragment != null) {
3126
cfrag.append (pre_statement_fragment);
3127
pre_statement_fragment = null;
3130
cfrag.append (stmt.ccodenode);
3132
foreach (LocalVariable local in temp_ref_vars) {
3133
var ma = new MemberAccess.simple (local.name);
3134
ma.symbol_reference = local;
3135
ma.value_type = local.variable_type.copy ();
3136
cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
3049
3139
if (stmt.tree_can_fail && stmt.expression.tree_can_fail) {
3050
3140
// simple case, no node breakdown necessary
3052
var cfrag = new CCodeFragment ();
3054
cfrag.append (stmt.ccodenode);
3056
3141
head.add_simple_check (stmt.expression, cfrag);
3058
stmt.ccodenode = cfrag;
3061
/* free temporary objects */
3063
if (((List<LocalVariable>) temp_vars).size == 0
3064
&& pre_statement_fragment == null) {
3065
/* nothing to do without temporary variables */
3069
var cfrag = new CCodeFragment ();
3070
append_temp_decl (cfrag, temp_vars);
3072
if (pre_statement_fragment != null) {
3073
cfrag.append (pre_statement_fragment);
3074
pre_statement_fragment = null;
3077
cfrag.append (stmt.ccodenode);
3079
foreach (LocalVariable local in temp_ref_vars) {
3080
var ma = new MemberAccess.simple (local.name);
3081
ma.symbol_reference = local;
3082
ma.value_type = local.variable_type.copy ();
3083
cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
3086
3144
stmt.ccodenode = cfrag;
3088
3146
temp_vars.clear ();
3089
3147
temp_ref_vars.clear ();
3147
3205
var local_vars = b.get_local_variables ();
3148
3206
foreach (LocalVariable local in local_vars) {
3149
if (local.active && !local.floating && requires_destroy (local.variable_type)) {
3207
if (!local.unreachable && local.active && !local.floating && !local.captured && requires_destroy (local.variable_type)) {
3150
3208
var ma = new MemberAccess.simple (local.name);
3151
3209
ma.symbol_reference = local;
3152
3210
cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
3215
int block_id = get_block_id (b);
3217
var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (block_id)));
3218
data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id)));
3219
cfrag.append (new CCodeExpressionStatement (data_unref));
3156
3222
if (sym == current_try.body) {
3345
3411
return "__lock_%s".printf (symname);
3348
public override void visit_lock_statement (LockStatement stmt) {
3349
var cn = new CCodeFragment ();
3414
private CCodeExpression get_lock_expression (Statement stmt, Expression resource) {
3350
3415
CCodeExpression l = null;
3351
CCodeFunctionCall fc;
3352
var inner_node = ((MemberAccess)stmt.resource).inner;
3353
var member = (Member)stmt.resource.symbol_reference;
3354
var parent = (TypeSymbol) stmt.resource.symbol_reference.parent_symbol;
3416
var inner_node = ((MemberAccess)resource).inner;
3417
var member = (Member)resource.symbol_reference;
3418
var parent = (TypeSymbol)resource.symbol_reference.parent_symbol;
3356
3420
if (member.is_instance_member ()) {
3357
3421
if (inner_node == null) {
3358
3422
l = new CCodeIdentifier ("self");
3359
} else if (stmt.resource.symbol_reference.parent_symbol != current_type_symbol) {
3360
l = generate_instance_cast ((CCodeExpression) inner_node.ccodenode, parent);
3423
} else if (resource.symbol_reference.parent_symbol != current_type_symbol) {
3424
l = generate_instance_cast ((CCodeExpression) inner_node.ccodenode, parent);
3362
3426
l = (CCodeExpression) inner_node.ccodenode;
3365
l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (stmt.resource.symbol_reference.name));
3429
l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (resource.symbol_reference.name));
3366
3430
} else if (member.is_class_member ()) {
3367
l = new CCodeIdentifier ("%s_GET_CLASS_PRIVATE(%s)".printf(parent.get_upper_case_cname (), parent.get_type_id ()));
3368
l = new CCodeMemberAccess.pointer (l, get_symbol_lock_name (stmt.resource.symbol_reference.name));
3431
CCodeExpression klass;
3433
if (current_method != null && current_method.binding == MemberBinding.INSTANCE ||
3434
current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE ||
3435
(in_constructor && !in_static_or_class_context)) {
3436
var k = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_GET_CLASS"));
3437
k.add_argument (new CCodeIdentifier ("self"));
3440
klass = new CCodeIdentifier ("klass");
3443
var get_class_private_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf(parent.get_upper_case_cname ())));
3444
get_class_private_call.add_argument (klass);
3445
l = new CCodeMemberAccess.pointer (get_class_private_call, get_symbol_lock_name (resource.symbol_reference.name));
3370
string lock_name = "%s_%s".printf(parent.get_lower_case_cname (), stmt.resource.symbol_reference.name);
3447
string lock_name = "%s_%s".printf(parent.get_lower_case_cname (), resource.symbol_reference.name);
3371
3448
l = new CCodeIdentifier (get_symbol_lock_name (lock_name));
3374
fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("lock")).get_cname ()));
3375
fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
3377
cn.append (new CCodeExpressionStatement (fc));
3379
cn.append (stmt.body.ccodenode);
3381
fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("unlock")).get_cname ()));
3382
fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
3383
cn.append (new CCodeExpressionStatement (fc));
3453
public override void visit_lock_statement (LockStatement stmt) {
3454
var l = get_lock_expression (stmt, stmt.resource);
3456
var fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("lock")).get_cname ()));
3457
fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
3459
var cn = new CCodeFragment ();
3460
cn.append (new CCodeExpressionStatement (fc));
3461
stmt.ccodenode = cn;
3464
public override void visit_unlock_statement (UnlockStatement stmt) {
3465
var l = get_lock_expression (stmt, stmt.resource);
3467
var fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("unlock")).get_cname ()));
3468
fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
3470
var cn = new CCodeFragment ();
3471
cn.append (new CCodeExpressionStatement (fc));
3385
3472
stmt.ccodenode = cn;
3402
3489
public override void visit_expression (Expression expr) {
3403
3490
if (expr.ccodenode != null && !expr.lvalue) {
3404
3491
if (expr.formal_value_type is GenericType && !(expr.value_type is GenericType)) {
3405
if (expr.formal_value_type.type_parameter.parent_symbol != garray_type) {
3406
// GArray doesn't use pointer-based generics
3492
var st = expr.formal_value_type.type_parameter.parent_symbol.parent_symbol as Struct;
3493
if (expr.formal_value_type.type_parameter.parent_symbol != garray_type &&
3494
(st == null || st.get_cname () != "va_list")) {
3495
// GArray and va_list don't use pointer-based generics
3407
3496
expr.ccodenode = convert_from_generic_pointer ((CCodeExpression) expr.ccodenode, expr.value_type);
3461
3550
public override void visit_string_literal (StringLiteral expr) {
3462
expr.ccodenode = new CCodeConstant (expr.value);
3551
expr.ccodenode = new CCodeConstant.string (expr.value);
3554
public override void visit_regex_literal (RegexLiteral expr) {
3555
string[] parts = expr.value.split ("/", 3);
3556
string re = parts[2].escape ("");
3559
if (parts[1].contains ("i")) {
3560
flags += " | G_REGEX_CASELESS";
3562
if (parts[1].contains ("m")) {
3563
flags += " | G_REGEX_MULTILINE";
3565
if (parts[1].contains ("s")) {
3566
flags += " | G_REGEX_DOTALL";
3568
if (parts[1].contains ("x")) {
3569
flags += " | G_REGEX_EXTENDED";
3572
var regex_var = get_temp_variable (regex_type, true, expr, false);
3573
expr.temp_vars.add (regex_var);
3575
var cdecl = new CCodeDeclaration ("GRegex*");
3577
var cname = regex_var.name + "regex_" + next_regex_id.to_string ();
3578
if (this.next_regex_id == 0) {
3579
var fun = new CCodeFunction ("_thread_safe_regex_init", "GRegex*");
3580
fun.modifiers = CCodeModifiers.STATIC | CCodeModifiers.INLINE;
3581
fun.add_parameter (new CCodeFormalParameter ("re", "GRegex**"));
3582
fun.add_parameter (new CCodeFormalParameter ("pattern", "const gchar *"));
3583
fun.add_parameter (new CCodeFormalParameter ("match_options", "GRegexMatchFlags"));
3584
fun.block = new CCodeBlock ();
3586
var once_enter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_enter"));
3587
once_enter_call.add_argument (new CCodeConstant ("(volatile gsize*) re"));
3589
var if_block = new CCodeBlock ();
3591
var regex_new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_regex_new"));
3592
regex_new_call.add_argument (new CCodeConstant ("pattern"));
3593
regex_new_call.add_argument (new CCodeConstant ("match_options"));
3594
regex_new_call.add_argument (new CCodeConstant ("0"));
3595
regex_new_call.add_argument (new CCodeConstant ("NULL"));
3596
if_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("GRegex* val"), regex_new_call)));
3598
var once_leave_call = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_leave"));
3599
once_leave_call.add_argument (new CCodeConstant ("(volatile gsize*) re"));
3600
once_leave_call.add_argument (new CCodeConstant ("(gsize) val"));
3601
if_block.add_statement (new CCodeExpressionStatement (once_leave_call));
3603
var if_stat = new CCodeIfStatement (once_enter_call, if_block);
3604
fun.block.add_statement (if_stat);
3605
fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("*re")));
3607
source_type_member_definition.append (fun);
3609
this.next_regex_id++;
3611
cdecl.add_declarator (new CCodeVariableDeclarator (cname + " = NULL"));
3612
cdecl.modifiers = CCodeModifiers.STATIC;
3614
var regex_const = new CCodeConstant ("_thread_safe_regex_init (&%s, \"%s\", %s)".printf (cname, re, flags));
3616
source_declarations.add_constant_declaration (cdecl);
3617
expr.ccodenode = regex_const;
3465
3620
public override void visit_null_literal (NullLiteral expr) {
3918
4081
check_type (expr.type_reference);
3920
4083
var st = expr.type_reference.data_type as Struct;
3921
if ((st != null && !st.is_simple_type ()) || expr.get_object_initializer ().size > 0) {
4084
if ((st != null && (!st.is_simple_type () || st.get_cname () == "va_list")) || expr.get_object_initializer ().size > 0) {
3922
4085
// value-type initialization or object creation expression with object initializer
3923
var temp_decl = get_temp_variable (expr.type_reference, false, expr);
3924
temp_vars.add (temp_decl);
3926
instance = get_variable_cexpression (get_variable_cname (temp_decl.name));
4087
var local = expr.parent_node as LocalVariable;
4088
if (local != null && has_simple_struct_initializer (local)) {
4089
instance = get_variable_cexpression (get_variable_cname (local.name));
4091
var temp_decl = get_temp_variable (expr.type_reference, false, expr);
4092
temp_vars.add (temp_decl);
4094
instance = get_variable_cexpression (get_variable_cname (temp_decl.name));
3929
4098
if (expr.symbol_reference == null) {
3963
4132
if ((st != null && !st.is_simple_type ()) && !(m.cinstance_parameter_position < 0)) {
3964
4133
creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance));
4134
} else if (st != null && st.get_cname () == "va_list") {
4135
creation_call.add_argument (instance);
4136
if (m.get_cname () == "va_start") {
4137
FormalParameter last_param = null;
4138
foreach (var param in current_method.get_parameters ()) {
4139
if (param.ellipsis) {
4144
creation_call.add_argument (new CCodeIdentifier (get_variable_cname (last_param.name)));
3967
4148
generate_type_declaration (expr.type_reference, source_declarations);
4360
4539
public override void visit_addressof_expression (AddressofExpression expr) {
4361
expr.ccodenode = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) expr.inner.ccodenode);
4540
if (expr.inner.ccodenode is CCodeCommaExpression) {
4541
var ccomma = expr.inner.ccodenode as CCodeCommaExpression;
4542
var inner = ccomma.get_inner ();
4543
var last = inner.get (inner.size - 1);
4544
ccomma.set_expression (inner.size - 1, new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) last));
4545
expr.ccodenode = ccomma;
4547
expr.ccodenode = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) expr.inner.ccodenode);
4364
4551
public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
4382
4569
var cleft = (CCodeExpression) expr.left.ccodenode;
4383
4570
var cright = (CCodeExpression) expr.right.ccodenode;
4572
CCodeExpression? left_chain = null;
4574
var lbe = (BinaryExpression) expr.left;
4576
var temp_decl = get_temp_variable (lbe.right.value_type, true, null, false);
4577
temp_vars.insert (0, temp_decl);
4578
var cvar = get_variable_cexpression (temp_decl.name);
4579
var ccomma = new CCodeCommaExpression ();
4580
var clbe = (CCodeBinaryExpression) lbe.ccodenode;
4582
clbe = (CCodeBinaryExpression) clbe.right;
4584
ccomma.append_expression (new CCodeAssignment (cvar, (CCodeExpression)lbe.right.ccodenode));
4585
clbe.right = get_variable_cexpression (temp_decl.name);
4586
ccomma.append_expression (cleft);
4588
left_chain = ccomma;
4385
4591
CCodeBinaryOperator op;
4386
4592
if (expr.operator == BinaryOperator.PLUS) {
4387
4593
op = CCodeBinaryOperator.PLUS;
4392
4598
} else if (expr.operator == BinaryOperator.DIV) {
4393
4599
op = CCodeBinaryOperator.DIV;
4394
4600
} else if (expr.operator == BinaryOperator.MOD) {
4395
op = CCodeBinaryOperator.MOD;
4601
if (expr.value_type.equals (double_type)) {
4602
source_declarations.add_include ("math.h");
4603
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("fmod"));
4604
ccall.add_argument (cleft);
4605
ccall.add_argument (cright);
4606
expr.ccodenode = ccall;
4608
} else if (expr.value_type.equals (float_type)) {
4609
source_declarations.add_include ("math.h");
4610
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("fmodf"));
4611
ccall.add_argument (cleft);
4612
ccall.add_argument (cright);
4613
expr.ccodenode = ccall;
4616
op = CCodeBinaryOperator.MOD;
4396
4618
} else if (expr.operator == BinaryOperator.SHIFT_LEFT) {
4397
4619
op = CCodeBinaryOperator.SHIFT_LEFT;
4398
4620
} else if (expr.operator == BinaryOperator.SHIFT_RIGHT) {
4420
4642
} else if (expr.operator == BinaryOperator.OR) {
4421
4643
op = CCodeBinaryOperator.OR;
4422
4644
} else if (expr.operator == BinaryOperator.IN) {
4423
expr.ccodenode = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, cright, cleft), cleft);
4645
if (expr.right.value_type is ArrayType) {
4646
var array_type = (ArrayType) expr.right.value_type;
4647
var node = new CCodeFunctionCall (new CCodeIdentifier (generate_array_contains_wrapper (array_type)));
4648
node.add_argument (cright);
4649
node.add_argument (get_array_length_cexpression (expr.right));
4650
if (array_type.element_type is StructValueType) {
4651
node.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cleft));
4653
node.add_argument (cleft);
4655
expr.ccodenode = node;
4657
expr.ccodenode = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, cright, cleft), cleft);
4426
4661
assert_not_reached ();
4800
string generate_array_contains_wrapper (ArrayType array_type) {
4801
string array_contains_func = "_vala_%s_array_contains".printf (array_type.element_type.get_lower_case_cname ());
4803
if (!add_wrapper (array_contains_func)) {
4804
return array_contains_func;
4807
var function = new CCodeFunction (array_contains_func, "gboolean");
4808
function.modifiers = CCodeModifiers.STATIC;
4810
function.add_parameter (new CCodeFormalParameter ("stack", array_type.get_cname ()));
4811
function.add_parameter (new CCodeFormalParameter ("stack_length", "int"));
4812
if (array_type.element_type is StructValueType) {
4813
function.add_parameter (new CCodeFormalParameter ("needle", array_type.element_type.get_cname () + "*"));
4815
function.add_parameter (new CCodeFormalParameter ("needle", array_type.element_type.get_cname ()));
4817
var block = new CCodeBlock ();
4819
var idx_decl = new CCodeDeclaration ("int");
4820
idx_decl.add_declarator (new CCodeVariableDeclarator ("i"));
4821
block.add_statement (idx_decl);
4823
var celement = new CCodeElementAccess (new CCodeIdentifier ("stack"), new CCodeIdentifier ("i"));
4824
var cneedle = new CCodeIdentifier ("needle");
4825
CCodeBinaryExpression cif_condition;
4826
if (array_type.element_type.compatible (string_type)) {
4827
requires_strcmp0 = true;
4828
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_strcmp0"));
4829
ccall.add_argument (celement);
4830
ccall.add_argument (cneedle);
4831
cif_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccall, new CCodeConstant ("0"));
4832
} else if (array_type.element_type is StructValueType) {
4833
var equalfunc = generate_struct_equal_function ((Struct) array_type.element_type.data_type as Struct);
4834
var ccall = new CCodeFunctionCall (new CCodeIdentifier (equalfunc));
4835
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, celement));
4836
ccall.add_argument (cneedle);
4837
cif_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccall, new CCodeConstant ("TRUE"));
4839
cif_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cneedle, celement);
4841
var cif_found = new CCodeBlock ();
4842
cif_found.add_statement (new CCodeReturnStatement (new CCodeConstant ("TRUE")));
4843
var cloop_body = new CCodeBlock ();
4844
cloop_body.add_statement (new CCodeIfStatement (cif_condition, cif_found));
4846
var cloop_condition = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("stack_length"));
4847
var cloop = new CCodeForStatement (cloop_condition, cloop_body);
4848
cloop.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
4849
cloop.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
4851
block.add_statement (cloop);
4852
block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
4853
source_declarations.add_type_member_declaration (function.copy ());
4854
function.block = block;
4855
source_type_member_definition.append (function);
4857
return array_contains_func;
4562
4860
public override void visit_type_check (TypeCheck expr) {
4563
4861
generate_type_declaration (expr.type_reference, source_declarations);
4890
5192
ccall.add_argument (prop.get_canonical_cconstant ());
4893
ccall.add_argument (cexpr);
4895
5195
var array_type = prop.property_type as ArrayType;
5198
if (array_type != null && !prop.no_array_length) {
5199
var temp_var = get_temp_variable (prop.property_type, true, null, false);
5200
temp_vars.insert (0, temp_var);
5201
var ccomma = new CCodeCommaExpression ();
5202
ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), cexpr));
5203
ccall.add_argument (get_variable_cexpression (temp_var.name));
5204
ccomma.append_expression (ccall);
5207
ccall.add_argument (cexpr);
4896
5211
if (array_type != null && !prop.no_array_length && rhs != null) {
4897
5212
for (int dim = 1; dim <= array_type.rank; dim++) {
4898
5213
ccall.add_argument (head.get_array_length_cexpression (rhs, dim));