From: Jürg Billeter Date: Tue, 13 Jul 2010 05:48:15 +0000 (+0200) Subject: dova: Add initial value boxing and unboxing support X-Git-Tag: 0.9.3~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=730eebc89c2c6875300f14caf4f71d9228f12538;p=thirdparty%2Fvala.git dova: Add initial value boxing and unboxing support --- diff --git a/codegen/valadovabasemodule.vala b/codegen/valadovabasemodule.vala index d5028d63a..572270dd7 100644 --- a/codegen/valadovabasemodule.vala +++ b/codegen/valadovabasemodule.vala @@ -1996,6 +1996,47 @@ internal class Vala.DovaBaseModule : CCodeModule { return; } + 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.insert (0, temp_decl); + var cvar = get_variable_cexpression (temp_decl.name); + + var ccomma = new CCodeCommaExpression (); + ccomma.append_expression (new CCodeAssignment (cvar, (CCodeExpression) expr.inner.ccodenode)); + + var to_any = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_value_to_any")); + to_any.add_argument (get_type_id_expression (expr.inner.value_type)); + to_any.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cvar)); + to_any.add_argument (new CCodeConstant ("0")); + ccomma.append_expression (to_any); + + expr.ccodenode = ccomma; + return; + } 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.insert (0, temp_decl); + var cvar = get_variable_cexpression (temp_decl.name); + + var ccomma = new CCodeCommaExpression (); + + var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); + sizeof_call.add_argument (new CCodeIdentifier (expr.type_reference.get_cname ())); + + var to_any = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_value_from_any")); + to_any.add_argument (get_type_id_expression (expr.type_reference)); + to_any.add_argument ((CCodeExpression) expr.inner.ccodenode); + to_any.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cvar)); + to_any.add_argument (new CCodeConstant ("0")); + ccomma.append_expression (to_any); + + ccomma.append_expression (cvar); + + expr.ccodenode = ccomma; + return; + } + generate_type_declaration (expr.type_reference, source_declarations); if (expr.inner.value_type is GenericType && !(expr.type_reference is GenericType)) { diff --git a/codegen/valadovaobjectmodule.vala b/codegen/valadovaobjectmodule.vala index 15314ac91..c64c7b97a 100644 --- a/codegen/valadovaobjectmodule.vala +++ b/codegen/valadovaobjectmodule.vala @@ -159,6 +159,23 @@ internal class Vala.DovaObjectModule : DovaArrayModule { vdecl = new CCodeDeclaration ("int32_t"); vdecl.add_declarator (vdeclarator); instance_priv_struct.add_declaration (vdecl); + + vdeclarator = new CCodeFunctionDeclarator ("value_to_any"); + vdeclarator.add_parameter (new CCodeFormalParameter ("value", "void *")); + vdeclarator.add_parameter (new CCodeFormalParameter ("value_index", "int32_t")); + + vdecl = new CCodeDeclaration ("DovaObject *"); + vdecl.add_declarator (vdeclarator); + instance_priv_struct.add_declaration (vdecl); + + vdeclarator = new CCodeFunctionDeclarator ("value_from_any"); + vdeclarator.add_parameter (new CCodeFormalParameter ("any", "DovaObject *")); + vdeclarator.add_parameter (new CCodeFormalParameter ("value", "void *")); + vdeclarator.add_parameter (new CCodeFormalParameter ("value_index", "int32_t")); + + vdecl = new CCodeDeclaration ("void"); + vdecl.add_declarator (vdeclarator); + instance_priv_struct.add_declaration (vdecl); } foreach (var type_param in cl.get_type_parameters ()) { @@ -301,6 +318,54 @@ internal class Vala.DovaObjectModule : DovaArrayModule { decl_space.add_type_member_declaration (create_set_value_hash_function (true)); } + CCodeFunction create_set_value_to_any_function (bool decl_only = false) { + var result = new CCodeFunction ("dova_type_set_value_to_any"); + result.add_parameter (new CCodeFormalParameter ("type", "DovaType *")); + result.add_parameter (new CCodeFormalParameter ("(*function) (void *value, int32_t value_index)", "DovaObject *")); + if (decl_only) { + return result; + } + + result.block = new CCodeBlock (); + + var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("DOVA_TYPE_GET_PRIVATE")); + priv_call.add_argument (new CCodeIdentifier ("type")); + + result.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (priv_call, "value_to_any"), new CCodeIdentifier ("function")))); + return result; + } + + public void declare_set_value_to_any_function (CCodeDeclarationSpace decl_space) { + if (decl_space.add_symbol_declaration (type_class, "dova_type_set_value_to_any")) { + return; + } + decl_space.add_type_member_declaration (create_set_value_to_any_function (true)); + } + + CCodeFunction create_set_value_from_any_function (bool decl_only = false) { + var result = new CCodeFunction ("dova_type_set_value_from_any"); + result.add_parameter (new CCodeFormalParameter ("type", "DovaType *")); + result.add_parameter (new CCodeFormalParameter ("(*function) (DovaObject *any, void *value, int32_t value_index)", "void")); + if (decl_only) { + return result; + } + + result.block = new CCodeBlock (); + + var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("DOVA_TYPE_GET_PRIVATE")); + priv_call.add_argument (new CCodeIdentifier ("type")); + + result.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (priv_call, "value_from_any"), new CCodeIdentifier ("function")))); + return result; + } + + public void declare_set_value_from_any_function (CCodeDeclarationSpace decl_space) { + if (decl_space.add_symbol_declaration (type_class, "dova_type_set_value_from_any")) { + return; + } + decl_space.add_type_member_declaration (create_set_value_from_any_function (true)); + } + public CCodeBlock generate_type_get_function (TypeSymbol cl, Class? base_class) { source_declarations.add_include ("stddef.h"); // calloc @@ -701,7 +766,7 @@ internal class Vala.DovaObjectModule : DovaArrayModule { ccall.add_argument (new CCodeIdentifier ("value_index")); ccall.add_argument (new CCodeIdentifier ("other")); ccall.add_argument (new CCodeIdentifier ("other_index")); - value_equals_function.block.add_statement (new CCodeExpressionStatement (ccall)); + value_equals_function.block.add_statement (new CCodeReturnStatement (ccall)); source_type_member_definition.append (value_equals_function); @@ -719,13 +784,51 @@ internal class Vala.DovaObjectModule : DovaArrayModule { ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (priv_call, "value_hash")); ccall.add_argument (new CCodeIdentifier ("value")); ccall.add_argument (new CCodeIdentifier ("value_index")); - value_hash_function.block.add_statement (new CCodeExpressionStatement (ccall)); + value_hash_function.block.add_statement (new CCodeReturnStatement (ccall)); source_type_member_definition.append (value_hash_function); declare_set_value_hash_function (source_declarations); declare_set_value_hash_function (header_declarations); source_type_member_definition.append (create_set_value_hash_function ()); + + var value_to_any_function = new CCodeFunction ("dova_type_value_to_any", "DovaObject *"); + value_to_any_function.add_parameter (new CCodeFormalParameter ("type", "DovaType *")); + value_to_any_function.add_parameter (new CCodeFormalParameter ("value", "void *")); + value_to_any_function.add_parameter (new CCodeFormalParameter ("value_index", "int32_t")); + + value_to_any_function.block = new CCodeBlock (); + + ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (priv_call, "value_to_any")); + ccall.add_argument (new CCodeIdentifier ("value")); + ccall.add_argument (new CCodeIdentifier ("value_index")); + value_to_any_function.block.add_statement (new CCodeReturnStatement (ccall)); + + source_type_member_definition.append (value_to_any_function); + + declare_set_value_to_any_function (source_declarations); + declare_set_value_to_any_function (header_declarations); + source_type_member_definition.append (create_set_value_to_any_function ()); + + var value_from_any_function = new CCodeFunction ("dova_type_value_from_any", "void"); + value_from_any_function.add_parameter (new CCodeFormalParameter ("type", "DovaType *")); + value_from_any_function.add_parameter (new CCodeFormalParameter ("any", "DovaObject *")); + value_from_any_function.add_parameter (new CCodeFormalParameter ("value", "void *")); + value_from_any_function.add_parameter (new CCodeFormalParameter ("value_index", "int32_t")); + + value_from_any_function.block = new CCodeBlock (); + + ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (priv_call, "value_from_any")); + ccall.add_argument (new CCodeIdentifier ("any")); + ccall.add_argument (new CCodeIdentifier ("value")); + ccall.add_argument (new CCodeIdentifier ("value_index")); + value_from_any_function.block.add_statement (new CCodeReturnStatement (ccall)); + + source_type_member_definition.append (value_from_any_function); + + declare_set_value_from_any_function (source_declarations); + declare_set_value_from_any_function (header_declarations); + source_type_member_definition.append (create_set_value_from_any_function ()); } current_symbol = old_symbol; diff --git a/codegen/valadovavaluemodule.vala b/codegen/valadovavaluemodule.vala index 75221f41a..855261225 100644 --- a/codegen/valadovavaluemodule.vala +++ b/codegen/valadovavaluemodule.vala @@ -239,6 +239,100 @@ internal class Vala.DovaValueModule : DovaObjectModule { type_init_fun.block.add_statement (new CCodeExpressionStatement (value_hash_call)); } +#if true + // generate method to box values + var value_to_any_fun = new CCodeFunction ("%s_value_to_any".printf (cl.get_lower_case_cname ()), "DovaObject*"); + value_to_any_fun.modifiers = CCodeModifiers.STATIC; + value_to_any_fun.add_parameter (new CCodeFormalParameter ("value", "void *")); + value_to_any_fun.add_parameter (new CCodeFormalParameter ("value_index", "int32_t")); + value_to_any_fun.block = new CCodeBlock (); + var alloc_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_alloc")); + alloc_call.add_argument (new CCodeFunctionCall (new CCodeIdentifier ("%s_type_get".printf (cl.get_lower_case_cname ())))); + cdecl = new CCodeDeclaration ("DovaObject *"); + cdecl.add_declarator (new CCodeVariableDeclarator ("result", alloc_call)); + value_to_any_fun.block.add_statement (cdecl); + var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("DOVA_VALUE_GET_PRIVATE")); + priv_call.add_argument (new CCodeIdentifier ("result")); + var copy_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_copy".printf (cl.get_lower_case_cname ()))); + copy_call.add_argument (priv_call); + copy_call.add_argument (new CCodeConstant ("0")); + copy_call.add_argument (new CCodeIdentifier ("value")); + copy_call.add_argument (new CCodeIdentifier ("value_index")); + value_to_any_fun.block.add_statement (new CCodeExpressionStatement (copy_call)); + value_to_any_fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result"))); + source_type_member_definition.append (value_to_any_fun); + + declare_set_value_to_any_function (source_declarations); + + var value_to_any_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_value_to_any")); + value_to_any_call.add_argument (new CCodeIdentifier ("type")); + value_to_any_call.add_argument (new CCodeIdentifier ("%s_value_to_any".printf (cl.get_lower_case_cname ()))); + type_init_fun.block.add_statement (new CCodeExpressionStatement (value_to_any_call)); + + // generate method to unbox values + var value_from_any_fun = new CCodeFunction ("%s_value_from_any".printf (cl.get_lower_case_cname ())); + value_from_any_fun.modifiers = CCodeModifiers.STATIC; + value_from_any_fun.add_parameter (new CCodeFormalParameter ("any", "DovaObject *")); + value_from_any_fun.add_parameter (new CCodeFormalParameter ("value", cl.get_cname () + "*")); + value_from_any_fun.add_parameter (new CCodeFormalParameter ("value_index", "int32_t")); + value_from_any_fun.block = new CCodeBlock (); + priv_call = new CCodeFunctionCall (new CCodeIdentifier ("DOVA_VALUE_GET_PRIVATE")); + priv_call.add_argument (new CCodeIdentifier ("any")); + copy_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_copy".printf (cl.get_lower_case_cname ()))); + copy_call.add_argument (new CCodeIdentifier ("value")); + copy_call.add_argument (new CCodeIdentifier ("value_index")); + copy_call.add_argument (priv_call); + copy_call.add_argument (new CCodeConstant ("0")); + value_from_any_fun.block.add_statement (new CCodeExpressionStatement (copy_call)); + source_type_member_definition.append (value_from_any_fun); + + declare_set_value_from_any_function (source_declarations); + + var value_from_any_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_value_from_any")); + value_from_any_call.add_argument (new CCodeIdentifier ("type")); + value_from_any_call.add_argument (new CCodeIdentifier ("%s_value_from_any".printf (cl.get_lower_case_cname ()))); + type_init_fun.block.add_statement (new CCodeExpressionStatement (value_from_any_call)); +#else + // generate method to box value + var value_to_any_fun = new CCodeFunction ("%s_value_to_any".printf (cl.get_lower_case_cname ()), "DovaObject*"); + value_to_any_fun.modifiers = CCodeModifiers.STATIC; + value_to_any_fun.add_parameter (new CCodeFormalParameter ("value", cl.get_cname () + "**")); + value_to_any_fun.add_parameter (new CCodeFormalParameter ("value_index", "int32_t")); + value_to_any_fun.block = new CCodeBlock (); + var val = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("value"), new CCodeIdentifier ("value_index")); + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_ref")); + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, val)); + value_to_any_fun.block.add_statement (new CCodeReturnStatement (ccall)); + source_type_member_definition.append (value_to_any_fun); + + declare_set_value_to_any_function (source_declarations); + + var value_to_any_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_value_to_any")); + value_to_any_call.add_argument (new CCodeIdentifier ("type")); + value_to_any_call.add_argument (new CCodeIdentifier ("%s_value_to_any".printf (cl.get_lower_case_cname ()))); + type_init_fun.block.add_statement (new CCodeExpressionStatement (value_to_any_call)); + + // generate method to unbox value + var value_from_any_fun = new CCodeFunction ("%s_value_from_any".printf (cl.get_lower_case_cname ())); + value_from_any_fun.modifiers = CCodeModifiers.STATIC; + value_from_any_fun.add_parameter (new CCodeFormalParameter ("any", "DovaObject *")); + value_from_any_fun.add_parameter (new CCodeFormalParameter ("value", cl.get_cname () + "**")); + value_from_any_fun.add_parameter (new CCodeFormalParameter ("value_index", "int32_t")); + value_from_any_fun.block = new CCodeBlock (); + ccall = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_ref")); + ccall.add_argument (new CCodeIdentifier ("any")); + value_from_any_fun.block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, val), ccall))); + value_from_any_fun.block.add_statement (new CCodeReturnStatement (ccall)); + source_type_member_definition.append (value_from_any_fun); + + declare_set_value_from_any_function (source_declarations); + + var value_from_any_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_value_from_any")); + value_from_any_call.add_argument (new CCodeIdentifier ("type")); + value_from_any_call.add_argument (new CCodeIdentifier ("%s_value_from_any".printf (cl.get_lower_case_cname ()))); + type_init_fun.block.add_statement (new CCodeExpressionStatement (value_from_any_call)); +#endif + source_type_member_definition.append (type_init_fun); cl.accept_children (codegen); @@ -320,7 +414,17 @@ internal class Vala.DovaValueModule : DovaObjectModule { // calloc source_declarations.add_include ("stdlib.h"); - var cdecl = new CCodeDeclaration ("DovaType *"); + + var cdecl = new CCodeDeclaration ("int"); + cdecl.add_declarator (new CCodeVariableDeclarator ("_%s_object_offset".printf (st.get_lower_case_cname ()), new CCodeConstant ("0"))); + cdecl.modifiers = CCodeModifiers.STATIC; + source_declarations.add_type_member_declaration (cdecl); + + string macro = "((%s *) (((char *) o) + _%s_object_offset))".printf (st.get_cname (), st.get_lower_case_cname ()); + source_declarations.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (st.get_upper_case_cname (null)), macro)); + + + cdecl = new CCodeDeclaration ("DovaType *"); cdecl.add_declarator (new CCodeVariableDeclarator ("%s_type".printf (st.get_lower_case_cname ()), new CCodeConstant ("NULL"))); cdecl.modifiers = CCodeModifiers.STATIC; source_declarations.add_type_member_declaration (cdecl); @@ -364,6 +468,8 @@ internal class Vala.DovaValueModule : DovaObjectModule { var base_size = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_get_object_size")); base_size.add_argument (base_type); + type_init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("_%s_object_offset".printf (st.get_lower_case_cname ())), base_size))); + var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); sizeof_call.add_argument (new CCodeIdentifier (st.get_cname ())); var set_size = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_object_size")); @@ -456,6 +562,59 @@ internal class Vala.DovaValueModule : DovaObjectModule { type_init_fun.block.add_statement (new CCodeExpressionStatement (value_hash_call)); } + // generate method to box values + var value_to_any_fun = new CCodeFunction ("%s_value_to_any".printf (st.get_lower_case_cname ()), "DovaObject*"); + value_to_any_fun.modifiers = CCodeModifiers.STATIC; + value_to_any_fun.add_parameter (new CCodeFormalParameter ("value", "void *")); + value_to_any_fun.add_parameter (new CCodeFormalParameter ("value_index", "int32_t")); + value_to_any_fun.block = new CCodeBlock (); + var alloc_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_alloc")); + alloc_call.add_argument (new CCodeFunctionCall (new CCodeIdentifier ("%s_type_get".printf (st.get_lower_case_cname ())))); + cdecl = new CCodeDeclaration ("DovaObject *"); + cdecl.add_declarator (new CCodeVariableDeclarator ("result", alloc_call)); + value_to_any_fun.block.add_statement (cdecl); + var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (st.get_upper_case_cname (null)))); + priv_call.add_argument (new CCodeIdentifier ("result")); + var copy_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_copy".printf (st.get_lower_case_cname ()))); + copy_call.add_argument (priv_call); + copy_call.add_argument (new CCodeConstant ("0")); + copy_call.add_argument (new CCodeIdentifier ("value")); + copy_call.add_argument (new CCodeIdentifier ("value_index")); + value_to_any_fun.block.add_statement (new CCodeExpressionStatement (copy_call)); + value_to_any_fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result"))); + source_type_member_definition.append (value_to_any_fun); + + declare_set_value_to_any_function (source_declarations); + + var value_to_any_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_value_to_any")); + value_to_any_call.add_argument (new CCodeIdentifier ("type")); + value_to_any_call.add_argument (new CCodeIdentifier ("%s_value_to_any".printf (st.get_lower_case_cname ()))); + type_init_fun.block.add_statement (new CCodeExpressionStatement (value_to_any_call)); + + // generate method to unbox values + var value_from_any_fun = new CCodeFunction ("%s_value_from_any".printf (st.get_lower_case_cname ())); + value_from_any_fun.modifiers = CCodeModifiers.STATIC; + value_from_any_fun.add_parameter (new CCodeFormalParameter ("any", "DovaObject *")); + value_from_any_fun.add_parameter (new CCodeFormalParameter ("value", st.get_cname () + "*")); + value_from_any_fun.add_parameter (new CCodeFormalParameter ("value_index", "int32_t")); + value_from_any_fun.block = new CCodeBlock (); + priv_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (st.get_upper_case_cname (null)))); + priv_call.add_argument (new CCodeIdentifier ("any")); + copy_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_copy".printf (st.get_lower_case_cname ()))); + copy_call.add_argument (new CCodeIdentifier ("value")); + copy_call.add_argument (new CCodeIdentifier ("value_index")); + copy_call.add_argument (priv_call); + copy_call.add_argument (new CCodeConstant ("0")); + value_from_any_fun.block.add_statement (new CCodeExpressionStatement (copy_call)); + source_type_member_definition.append (value_from_any_fun); + + declare_set_value_from_any_function (source_declarations); + + var value_from_any_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_set_value_from_any")); + value_from_any_call.add_argument (new CCodeIdentifier ("type")); + value_from_any_call.add_argument (new CCodeIdentifier ("%s_value_from_any".printf (st.get_lower_case_cname ()))); + type_init_fun.block.add_statement (new CCodeExpressionStatement (value_from_any_call)); + source_type_member_definition.append (type_init_fun); add_struct_copy_function (st); diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala index f756415e8..2e964f368 100644 --- a/vala/valadatatype.vala +++ b/vala/valadatatype.vala @@ -319,6 +319,11 @@ public abstract class Vala.DataType : CodeNode { return true; } + if (this is ValueType && target_type.data_type != null && target_type.data_type.get_full_name () == "Dova.Value") { + // allow implicit conversion to Dova.Value + return true; + } + if (target_type is DelegateType && this is DelegateType) { return ((DelegateType) target_type).delegate_symbol == ((DelegateType) this).delegate_symbol; }