From 33cb1ce35b493a59e0c5037c198bab58894651a8 Mon Sep 17 00:00:00 2001 From: Juerg Billeter Date: Fri, 30 May 2008 22:48:14 +0000 Subject: [PATCH] Add basic support for nullable structs 2008-05-31 Juerg Billeter * gobject/valaccodegenerator.vala: * gobject/valaccodeinvocationexpressionbinding.vala: * gobject/valaccodememberaccessbinding.vala: Add basic support for nullable structs * tests/structs.vala: Test nullable struct parameters svn path=/trunk/; revision=1502 --- ChangeLog | 12 ++++++ gobject/valaccodegenerator.vala | 51 ++++++++++++++++++++++- gobject/valaccodeinvocationexpressionbinding.vala | 4 +- gobject/valaccodememberaccessbinding.vala | 2 +- tests/structs.vala | 5 +++ 5 files changed, 69 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 99b4f96..6796a19 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2008-05-31 Jürg Billeter + + * gobject/valaccodegenerator.vala: + * gobject/valaccodeinvocationexpressionbinding.vala: + * gobject/valaccodememberaccessbinding.vala: + + Add basic support for nullable structs + + * tests/structs.vala: + + Test nullable struct parameters + 2008-05-30 Jürg Billeter * vala/valadatatype.vala: remove obsolete code diff --git a/gobject/valaccodegenerator.vala b/gobject/valaccodegenerator.vala index abaaf21..8b5542a 100644 --- a/gobject/valaccodegenerator.vala +++ b/gobject/valaccodegenerator.vala @@ -3385,8 +3385,13 @@ public class Vala.CCodeGenerator : CodeGenerator { cexpr = csink; } + bool boxing = (expression_type is ValueType && !expression_type.nullable + && target_type is ValueType && target_type.nullable); + bool unboxing = (expression_type is ValueType && expression_type.nullable + && target_type is ValueType && !target_type.nullable); + if (expression_type.value_owned - && (target_type == null || !target_type.value_owned)) { + && (target_type == null || !target_type.value_owned || boxing)) { // value leaked, destroy it var pointer_type = target_type as PointerType; if (pointer_type != null && !(pointer_type.base_type is VoidType)) { @@ -3418,7 +3423,49 @@ public class Vala.CCodeGenerator : CodeGenerator { return cexpr; } - cexpr = get_implicit_cast_expression (cexpr, expression_type, target_type, expr); + if (boxing) { + // value needs to be boxed + + if (cexpr is CCodeIdentifier) { + cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr); + } else { + var decl = get_temp_variable (expression_type, expression_type.value_owned, expression_type); + temp_vars.insert (0, decl); + + var ccomma = new CCodeCommaExpression (); + ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (get_variable_cname (decl.name)), cexpr)); + ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (get_variable_cname (decl.name)))); + cexpr = ccomma; + } + + if (!target_type.value_owned) { + // reference to stack value + } else { + // heap-allocated + string dup_func = expression_type.data_type.get_dup_function (); + if (dup_func == null) { + // default to g_memdup + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup")); + ccall.add_argument (cexpr); + var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); + csizeof.add_argument (new CCodeIdentifier (expression_type.data_type.get_cname ())); + ccall.add_argument (csizeof); + + cexpr = ccall; + } else { + var ccall = new CCodeFunctionCall (new CCodeIdentifier (dup_func)); + ccall.add_argument (cexpr); + + cexpr = ccall; + } + } + } else if (unboxing) { + // unbox value + + cexpr = new CCodeParenthesizedExpression (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cexpr)); + } else { + cexpr = get_implicit_cast_expression (cexpr, expression_type, target_type, expr); + } if (expression_type.is_type_argument) { cexpr = convert_from_generic_pointer (cexpr, target_type); diff --git a/gobject/valaccodeinvocationexpressionbinding.vala b/gobject/valaccodeinvocationexpressionbinding.vala index 14bcd70..5947ef2 100644 --- a/gobject/valaccodeinvocationexpressionbinding.vala +++ b/gobject/valaccodeinvocationexpressionbinding.vala @@ -176,8 +176,8 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding { // pass non-simple struct instances always by reference if (!(arg.value_type is NullType) && param.parameter_type.data_type is Struct && !((Struct) param.parameter_type.data_type).is_simple_type ()) { - // we already use a reference for arguments of ref and out parameters - if (param.direction == ParameterDirection.IN) { + // we already use a reference for arguments of ref, out, and nullable parameters + if (param.direction == ParameterDirection.IN && !param.parameter_type.nullable) { if (cexpr is CCodeIdentifier) { cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr); } else { diff --git a/gobject/valaccodememberaccessbinding.vala b/gobject/valaccodememberaccessbinding.vala index cb881a4..a67228c 100644 --- a/gobject/valaccodememberaccessbinding.vala +++ b/gobject/valaccodememberaccessbinding.vala @@ -199,7 +199,7 @@ public class Vala.CCodeMemberAccessBinding : CCodeExpressionBinding { } else { var type_as_struct = p.parameter_type.data_type as Struct; if (p.direction != ParameterDirection.IN - || (type_as_struct != null && !type_as_struct.is_simple_type ())) { + || (type_as_struct != null && !type_as_struct.is_simple_type () && !p.parameter_type.nullable)) { expr.ccodenode = new CCodeIdentifier ("(*%s)".printf (p.name)); } else { // Property setters of non simple structs shall replace all occurences diff --git a/tests/structs.vala b/tests/structs.vala index 5656511..f5c2621 100644 --- a/tests/structs.vala +++ b/tests/structs.vala @@ -28,6 +28,10 @@ void test_in_parameter (SimpleStruct st) { stdout.printf ("test_in_parameter: st.field = %d\n", st.field); } +void test_in_nullable_parameter (SimpleStruct? st) { + assert (st.field == 1); +} + void test_ref_parameter (ref SimpleStruct st) { stdout.printf ("test_ref_parameter: st.field = %d\n", st.field); st.field++; @@ -55,6 +59,7 @@ void main () { stdout.printf ("simple_struct.field = %d\n", simple_struct.field); test_in_parameter (simple_struct); + test_in_nullable_parameter (simple_struct); test_ref_parameter (ref simple_struct); stdout.printf ("after test_ref_parameter: st.field = %d\n", simple_struct.field); test_out_parameter (out simple_struct); -- 2.7.4