[vala/wip/cpp] cpp: Add basic support for using C++ libraries
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/cpp] cpp: Add basic support for using C++ libraries
- Date: Sat, 31 Mar 2012 20:59:41 +0000 (UTC)
commit 4dfd1fdcf9be28d47ad02232d78bbf4acb393c62
Author: Luca Bruno <lucabru src gnome org>
Date: Sat Mar 31 22:56:00 2012 +0200
cpp: Add basic support for using C++ libraries
ccode/Makefile.am | 3 +
ccode/valacppdeletestatement.vala | 47 ++++
ccode/valacppmethodcall.vala | 45 ++++
ccode/valacppobjectcreation.vala | 38 +++
codegen/Makefile.am | 1 +
codegen/valaccodebasemodule.vala | 2 +-
codegen/valacppmodule.vala | 524 +++++++++++++++++++++++++++++++++++++
codegen/valagerrormodule.vala | 2 +-
8 files changed, 660 insertions(+), 2 deletions(-)
---
diff --git a/ccode/Makefile.am b/ccode/Makefile.am
index c63dd06..eb542ee 100644
--- a/ccode/Makefile.am
+++ b/ccode/Makefile.am
@@ -64,6 +64,9 @@ libvalaccode_la_VALASOURCES = \
valaccodewhilestatement.vala \
valaccodewriter.vala \
valaccodeelementaccess.vala \
+ valacppdeletestatement.vala \
+ valacppmethodcall.vala \
+ valacppobjectcreation.vala \
$(NULL)
libvalaccode_la_SOURCES = \
diff --git a/ccode/valacppdeletestatement.vala b/ccode/valacppdeletestatement.vala
new file mode 100644
index 0000000..ba62964
--- /dev/null
+++ b/ccode/valacppdeletestatement.vala
@@ -0,0 +1,47 @@
+/* valacppdeletestatement.vala
+ *
+ * Copyright (C) 2012 Luca Bruno
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Luca Bruno <lucabru src gnome org>
+ */
+
+using GLib;
+
+/**
+ * Represents a delete statement in the C++ code.
+ */
+public class Vala.CppDeleteStatement : CCodeStatement {
+ /**
+ * The optional expression to return.
+ */
+ public CCodeExpression delete_expression { get; set; }
+
+ public CppDeleteStatement (CCodeExpression expr) {
+ delete_expression = expr;
+ }
+
+ public override void write (CCodeWriter writer) {
+ writer.write_indent (line);
+ writer.write_string ("delete ");
+
+ delete_expression.write (writer);
+
+ writer.write_string (";");
+ writer.write_newline ();
+ }
+}
diff --git a/ccode/valacppmethodcall.vala b/ccode/valacppmethodcall.vala
new file mode 100644
index 0000000..5411f8d
--- /dev/null
+++ b/ccode/valacppmethodcall.vala
@@ -0,0 +1,45 @@
+/* valacppmethodcall.vala
+ *
+ * Copyright (C) 2012 Luca Bruno
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Luca Bruno <lucabru src gnome org>
+ */
+
+using GLib;
+
+/**
+ * Represents a method call in the C++ code.
+ */
+public class Vala.CppMethodCall : CCodeFunctionCall {
+ /**
+ * Instance on which to call the C++ method.
+ */
+ CCodeExpression instance;
+
+ public CppMethodCall (CCodeExpression call, CCodeExpression instance) {
+ base (call);
+ this.instance = instance;
+ }
+
+ public override void write (CCodeWriter writer) {
+ instance.write_inner (writer);
+ writer.write_string ("->");
+
+ base.write (writer);
+ }
+}
diff --git a/ccode/valacppobjectcreation.vala b/ccode/valacppobjectcreation.vala
new file mode 100644
index 0000000..47e33b8
--- /dev/null
+++ b/ccode/valacppobjectcreation.vala
@@ -0,0 +1,38 @@
+/* valacppobjectcreation.vala
+ *
+ * Copyright (C) 2012 Luca Bruno
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Luca Bruno <lucabru src gnome org>
+ */
+
+using GLib;
+
+/**
+ * Represents a 'new' expression in the C++ code.
+ */
+public class Vala.CppObjectCreation : CCodeFunctionCall {
+ public CppObjectCreation (CCodeExpression? call = null) {
+ base (call);
+ }
+
+ public override void write (CCodeWriter writer) {
+ writer.write_string ("new ");
+
+ base.write (writer);
+ }
+}
diff --git a/codegen/Makefile.am b/codegen/Makefile.am
index 2535a88..dbf558f 100644
--- a/codegen/Makefile.am
+++ b/codegen/Makefile.am
@@ -27,6 +27,7 @@ libvala_la_VALASOURCES = \
valaccodemethodmodule.vala \
valaccodestructmodule.vala \
valaclassregisterfunction.vala \
+ valacppmodule.vala \
valactype.vala \
valadovaarraymodule.vala \
valadovaassignmentmodule.vala \
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 866e8b9..c3e9c7d 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -2878,7 +2878,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
return element_destroy_func_expression;
}
- public CCodeExpression? get_destroy_func_expression (DataType type, bool is_chainup = false) {
+ public virtual CCodeExpression? get_destroy_func_expression (DataType type, bool is_chainup = false) {
if (context.profile == Profile.GOBJECT && (type.data_type == glist_type || type.data_type == gslist_type || type.data_type == gnode_type || type.data_type == gqueue_type)) {
// create wrapper function to free list elements if necessary
diff --git a/codegen/valacppmodule.vala b/codegen/valacppmodule.vala
new file mode 100644
index 0000000..1f65236
--- /dev/null
+++ b/codegen/valacppmodule.vala
@@ -0,0 +1,524 @@
+/* valacppmodule.vala
+ *
+ * Copyright (C) 2012 Luca Bruno
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Luca Bruno <lucabru src gnome org>
+ */
+
+
+public class Vala.CppModule : CCodeDelegateModule {
+ public string get_cpp_name (Symbol sym) {
+ return sym.name;
+ }
+
+ public string get_cpp_full_name (Symbol sym) {
+ if (sym.parent_symbol == context.root) {
+ return get_cpp_name (sym);
+ } else {
+ return "%s::%s".printf (get_cpp_full_name (sym.parent_symbol), get_cpp_name (sym));
+ }
+ }
+
+ public string get_cpp_wrapper_name (Symbol sym) {
+ return get_cpp_full_name (sym).replace ("::", "__");
+ }
+
+ public override CCodeExpression? get_destroy_func_expression (DataType type, bool is_chainup = false) {
+ var cl = type.data_type as Class;
+ if (cl == null || cl.get_attribute ("Cpp") == null) {
+ return base.get_destroy_func_expression (type, is_chainup);
+ }
+
+ string destroy_func = "_vala_cpp_%s_free".printf (get_cpp_wrapper_name (cl));
+ if (!add_wrapper (destroy_func)) {
+ // wrapper already defined
+ return new CCodeIdentifier (destroy_func);
+ }
+
+ var function = new CCodeFunction (destroy_func, "void");
+ function.modifiers = CCodeModifiers.STATIC;
+ function.add_parameter (new CCodeParameter ("self", get_cpp_full_name (cl)+"*"));
+
+ push_function (function);
+
+ ccode.add_statement (new CppDeleteStatement (new CCodeIdentifier ("self")));
+
+ pop_function ();
+
+ cfile.add_function_declaration (function);
+ cfile.add_function (function);
+
+ return new CCodeIdentifier (destroy_func);
+ }
+
+ public override void visit_object_creation_expression (ObjectCreationExpression expr) {
+ var cl = expr.type_reference.data_type as Class;
+ var m = expr.symbol_reference as CreationMethod;
+ if (cl == null || m == null || cl.get_attribute ("Cpp") == null) {
+ base.visit_object_creation_expression (expr);
+ return;
+ }
+
+ check_type (expr.type_reference);
+ generate_method_declaration (m, cfile);
+
+ var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
+ var creation_call = new CppObjectCreation (new CCodeIdentifier (get_cpp_full_name (cl)));
+
+ bool ellipsis = false;
+ int i = 1;
+ int arg_pos;
+ Iterator<Parameter> params_it = m.get_parameters().iterator ();
+ foreach (Expression arg in expr.get_argument_list ()) {
+ CCodeExpression cexpr = get_cvalue (arg);
+ Parameter param = null;
+ if (params_it.next ()) {
+ param = params_it.get ();
+ ellipsis = param.ellipsis;
+ if (!ellipsis) {
+ if (get_ccode_array_length (param) && param.variable_type is ArrayType) {
+ var array_type = (ArrayType) param.variable_type;
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ carg_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), get_array_length_cexpression (arg, dim));
+ }
+ } else if (param.variable_type is DelegateType) {
+ var deleg_type = (DelegateType) param.variable_type;
+ var d = deleg_type.delegate_symbol;
+ if (d.has_target) {
+ CCodeExpression delegate_target_destroy_notify;
+ var delegate_target = get_delegate_target_cexpression (arg, out delegate_target_destroy_notify);
+ carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), delegate_target);
+ if (deleg_type.value_owned) {
+ carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param) + 0.01), delegate_target_destroy_notify);
+ }
+ }
+ }
+
+ cexpr = handle_struct_argument (param, arg, cexpr);
+
+ if (get_ccode_type (param) != null) {
+ cexpr = new CCodeCastExpression (cexpr, get_ccode_type (param));
+ }
+ } else {
+ cexpr = handle_struct_argument (null, arg, cexpr);
+ }
+
+ arg_pos = get_param_pos (get_ccode_pos (param), ellipsis);
+ } else {
+ // default argument position
+ cexpr = handle_struct_argument (null, arg, cexpr);
+ arg_pos = get_param_pos (i, ellipsis);
+ }
+
+ carg_map.set (arg_pos, cexpr);
+
+ i++;
+ }
+ while (params_it.next ()) {
+ var param = params_it.get ();
+
+ if (param.ellipsis) {
+ ellipsis = true;
+ break;
+ }
+
+ if (param.initializer == null) {
+ Report.error (expr.source_reference, "no default expression for argument %d".printf (i));
+ return;
+ }
+
+ /* evaluate default expression here as the code
+ * generator might not have visited the formal
+ * parameter yet */
+ param.initializer.emit (this);
+
+ carg_map.set (get_param_pos (get_ccode_pos (param)), get_cvalue (param.initializer));
+ i++;
+ }
+
+ // append C arguments in the right order
+ int last_pos = -1;
+ int min_pos;
+ while (true) {
+ min_pos = -1;
+ foreach (int pos in carg_map.get_keys ()) {
+ if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
+ min_pos = pos;
+ }
+ }
+ if (min_pos == -1) {
+ break;
+ }
+ creation_call.add_argument (carg_map.get (min_pos));
+ last_pos = min_pos;
+ }
+ var temp_value = create_temp_value (expr.value_type, false, expr);
+ ccode.add_assignment (get_cvalue_ (temp_value), creation_call);
+ expr.target_value = temp_value;
+ ((GLibValue) expr.target_value).lvalue = true;
+ }
+
+ public override void visit_method_call (MethodCall expr) {
+ var itype = expr.call.value_type;
+ var ma = expr.call as MemberAccess;
+ Method m;
+ if (ma != null && ma.inner != null && ma.symbol_reference is Method) {
+ m = (Method) ma.symbol_reference;
+ if (m.parent_symbol.get_attribute ("Cpp") == null) {
+ base.visit_method_call (expr);
+ return;
+ }
+ } else {
+ base.visit_method_call (expr);
+ return;
+ }
+
+ var ccall = new CppMethodCall (new CCodeIdentifier (get_cpp_name (m)), get_cvalue (ma.inner));
+ CCodeExpression ccall_expr = ccall;
+
+ var in_arg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
+ var out_arg_map = in_arg_map;
+
+ bool ellipsis = false;
+
+ int i = 1;
+ int arg_pos;
+ Iterator<Parameter> params_it = m.get_parameters().iterator ();
+ foreach (Expression arg in expr.get_argument_list ()) {
+ CCodeExpression cexpr = get_cvalue (arg);
+
+ var carg_map = in_arg_map;
+
+ if (params_it.next ()) {
+ var param = params_it.get ();
+ ellipsis = param.params_array || param.ellipsis;
+ if (!ellipsis) {
+ if (param.direction == ParameterDirection.OUT) {
+ carg_map = out_arg_map;
+ }
+
+ var unary = arg as UnaryExpression;
+ if (unary == null || unary.operator != UnaryOperator.OUT) {
+ if (get_ccode_array_length (param) && param.variable_type is ArrayType) {
+ var array_type = (ArrayType) param.variable_type;
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ CCodeExpression? array_length_expr = null;
+ if (get_ccode_array_length_type (param) != null) {
+ array_length_expr = new CCodeCastExpression (get_array_length_cexpression (arg, dim), get_ccode_array_length_type (param));
+ } else {
+ array_length_expr = get_array_length_cexpression (arg, dim);
+ }
+ carg_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), array_length_expr);
+ }
+ } else if (param.variable_type is DelegateType) {
+ var deleg_type = (DelegateType) param.variable_type;
+ var d = deleg_type.delegate_symbol;
+ if (d.has_target) {
+ CCodeExpression delegate_target_destroy_notify;
+ var delegate_target = get_delegate_target_cexpression (arg, out delegate_target_destroy_notify);
+ assert (delegate_target != null);
+ if (get_ccode_type (param) == "GClosure*") {
+ // one single GClosure parameter
+ var closure_new = new CCodeFunctionCall (new CCodeIdentifier ("g_cclosure_new"));
+ closure_new.add_argument (new CCodeCastExpression (cexpr, "GCallback"));
+ closure_new.add_argument (delegate_target);
+ closure_new.add_argument (delegate_target_destroy_notify);
+ cexpr = new CCodeConditionalExpression (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cexpr, new CCodeIdentifier ("NULL")), new CCodeIdentifier ("NULL"), closure_new);
+ } else {
+ carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), delegate_target);
+ if (deleg_type.value_owned) {
+ assert (delegate_target_destroy_notify != null);
+ carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param) + 0.01), delegate_target_destroy_notify);
+ }
+ }
+ }
+ } else if (param.variable_type is MethodType) {
+ // callbacks in dynamic method calls
+ CCodeExpression delegate_target_destroy_notify;
+ carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), get_delegate_target_cexpression (arg, out delegate_target_destroy_notify));
+ } else if (param.variable_type is GenericType) {
+ if (m != null && get_ccode_simple_generics (m)) {
+ var generic_type = (GenericType) param.variable_type;
+ int type_param_index = m.get_type_parameter_index (generic_type.type_parameter.name);
+ var type_arg = ma.get_type_arguments ().get (type_param_index);
+ if (param.variable_type.value_owned) {
+ if (requires_copy (type_arg)) {
+ carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), get_destroy_func_expression (type_arg));
+ } else {
+ carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), new CCodeConstant ("NULL"));
+ }
+ }
+ }
+ }
+
+ cexpr = handle_struct_argument (param, arg, cexpr);
+ } else {
+ arg.target_value = null;
+
+ var temp_var = get_temp_variable (param.variable_type, param.variable_type.value_owned);
+ emit_temp_var (temp_var);
+ set_cvalue (arg, get_variable_cexpression (temp_var.name));
+ arg.target_value.value_type = arg.target_type;
+
+ cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue (arg));
+
+ if (get_ccode_array_length (param) && param.variable_type is ArrayType) {
+ var array_type = (ArrayType) param.variable_type;
+ var array_length_type = int_type;
+ if (get_ccode_array_length_type (param) != null) {
+ array_length_type = new CType (get_ccode_array_length_type (param));
+ }
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ var temp_array_length = get_temp_variable (array_length_type);
+ emit_temp_var (temp_array_length);
+ append_array_length (arg, get_variable_cexpression (temp_array_length.name));
+ carg_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_array_lengths (arg).get (dim - 1)));
+ }
+ } else if (param.variable_type is DelegateType) {
+ var deleg_type = (DelegateType) param.variable_type;
+ var d = deleg_type.delegate_symbol;
+ if (d.has_target) {
+ temp_var = get_temp_variable (new PointerType (new VoidType ()));
+ emit_temp_var (temp_var);
+ set_delegate_target (arg, get_variable_cexpression (temp_var.name));
+ carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_delegate_target (arg)));
+ if (deleg_type.value_owned) {
+ temp_var = get_temp_variable (gdestroynotify_type);
+ emit_temp_var (temp_var);
+ set_delegate_target_destroy_notify (arg, get_variable_cexpression (temp_var.name));
+ carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param) + 0.01), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_delegate_target_destroy_notify (arg)));
+ }
+ }
+ }
+ }
+
+ if (get_ccode_type (param) != null) {
+ cexpr = new CCodeCastExpression (cexpr, get_ccode_type (param));
+ }
+ } else {
+ cexpr = handle_struct_argument (null, arg, cexpr);
+ }
+ arg_pos = get_param_pos (get_ccode_pos (param), ellipsis);
+ } else {
+ // default argument position
+ cexpr = handle_struct_argument (null, arg, cexpr);
+ arg_pos = get_param_pos (i, ellipsis);
+ }
+
+ carg_map.set (arg_pos, cexpr);
+
+ if (arg is NamedArgument && ellipsis) {
+ var named_arg = (NamedArgument) arg;
+ string name = string.joinv ("-", named_arg.name.split ("_"));
+ carg_map.set (get_param_pos (i - 0.1, ellipsis), new CCodeConstant ("\"%s\"".printf (name)));
+ }
+
+ i++;
+ }
+ if (params_it.next ()) {
+ var param = params_it.get ();
+
+ /* if there are more parameters than arguments,
+ * the additional parameter is an ellipsis parameter
+ * otherwise there is a bug in the semantic analyzer
+ */
+ assert (param.params_array || param.ellipsis);
+ ellipsis = true;
+ }
+
+ /* add length argument for methods returning arrays */
+ if (m != null && m.return_type is ArrayType) {
+ var array_type = (ArrayType) m.return_type;
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ if (get_ccode_array_null_terminated (m)) {
+ // handle calls to methods returning null-terminated arrays
+ var temp_var = get_temp_variable (itype.get_return_type (), true, null, false);
+ var temp_ref = get_variable_cexpression (temp_var.name);
+
+ emit_temp_var (temp_var);
+
+ ccall_expr = new CCodeAssignment (temp_ref, ccall_expr);
+
+ requires_array_length = true;
+ var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length"));
+ len_call.add_argument (temp_ref);
+
+ append_array_length (expr, len_call);
+ } else if (get_ccode_array_length (m)) {
+ LocalVariable temp_var;
+
+ if (get_ccode_array_length_type (m) == null) {
+ temp_var = get_temp_variable (int_type);
+ } else {
+ temp_var = get_temp_variable (new CType (get_ccode_array_length_type (m)));
+ }
+ var temp_ref = get_variable_cexpression (temp_var.name);
+
+ emit_temp_var (temp_var);
+
+ out_arg_map.set (get_param_pos (get_ccode_array_length_pos (m) + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
+
+ append_array_length (expr, temp_ref);
+ } else {
+ append_array_length (expr, new CCodeConstant ("-1"));
+ }
+ }
+ } else if (m != null && m.return_type is DelegateType) {
+ var deleg_type = (DelegateType) m.return_type;
+ var d = deleg_type.delegate_symbol;
+ if (d.has_target) {
+ var temp_var = get_temp_variable (new PointerType (new VoidType ()));
+ var temp_ref = get_variable_cexpression (temp_var.name);
+
+ emit_temp_var (temp_var);
+
+ out_arg_map.set (get_param_pos (get_ccode_delegate_target_pos (m)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
+
+ set_delegate_target (expr, temp_ref);
+
+ if (deleg_type.value_owned) {
+ temp_var = get_temp_variable (gdestroynotify_type);
+ temp_ref = get_variable_cexpression (temp_var.name);
+
+ emit_temp_var (temp_var);
+
+ out_arg_map.set (get_param_pos (get_ccode_delegate_target_pos (m) + 0.01), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
+
+ set_delegate_target_destroy_notify (expr, temp_ref);
+ } else {
+ set_delegate_target_destroy_notify (expr, new CCodeConstant ("NULL"));
+ }
+ } else {
+ set_delegate_target (expr, new CCodeConstant ("NULL"));
+ }
+ }
+
+ if (ellipsis) {
+ /* ensure variable argument list ends with NULL
+ * except when using printf-style arguments */
+ if (m == null) {
+ in_arg_map.set (get_param_pos (-1, true), new CCodeConstant ("NULL"));
+ } else if (!m.printf_format && !m.scanf_format && get_ccode_sentinel (m) != "") {
+ in_arg_map.set (get_param_pos (-1, true), new CCodeConstant (get_ccode_sentinel (m)));
+ }
+ }
+
+ if (itype is DelegateType) {
+ var deleg_type = (DelegateType) itype;
+ var d = deleg_type.delegate_symbol;
+ if (d.has_target) {
+ CCodeExpression delegate_target_destroy_notify;
+ in_arg_map.set (get_param_pos (get_ccode_instance_pos (d)), get_delegate_target_cexpression (expr.call, out delegate_target_destroy_notify));
+ out_arg_map.set (get_param_pos (get_ccode_instance_pos (d)), get_delegate_target_cexpression (expr.call, out delegate_target_destroy_notify));
+ }
+ }
+
+ // structs are returned via out parameter
+ bool return_result_via_out_param = itype.get_return_type ().is_real_non_null_struct_type ();
+
+ CCodeExpression out_param_ref = null;
+
+ if (return_result_via_out_param) {
+ var out_param_var = get_temp_variable (itype.get_return_type ());
+ out_param_ref = get_variable_cexpression (out_param_var.name);
+ emit_temp_var (out_param_var);
+ out_arg_map.set (get_param_pos (-3), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, out_param_ref));
+ }
+
+ // append C arguments in the right order
+
+ int last_pos;
+ int min_pos;
+
+ last_pos = -1;
+ while (true) {
+ min_pos = -1;
+ foreach (int pos in in_arg_map.get_keys ()) {
+ if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
+ min_pos = pos;
+ }
+ }
+ if (min_pos == -1) {
+ break;
+ }
+ ccall.add_argument (in_arg_map.get (min_pos));
+ last_pos = min_pos;
+ }
+
+ if (return_result_via_out_param) {
+ ccode.add_expression (ccall_expr);
+ ccall_expr = out_param_ref;
+ }
+
+ if (expr.parent_node is ExpressionStatement && !expr.value_type.is_disposable ()) {
+ if (ccall_expr != null && !return_result_via_out_param) {
+ ccode.add_expression (ccall_expr);
+ }
+ } else {
+ var result_type = itype.get_return_type ();
+
+ if (expr.formal_value_type is GenericType && !(expr.value_type is GenericType)) {
+ var st = expr.formal_value_type.type_parameter.parent_symbol.parent_symbol as Struct;
+ if (expr.formal_value_type.type_parameter.parent_symbol == garray_type ||
+ (st != null && get_ccode_name (st) == "va_list")) {
+ // GArray and va_list don't use pointer-based generics
+ // above logic copied from visit_expression ()
+ // TODO avoid code duplication
+ result_type = expr.value_type;
+ }
+ }
+
+ if (!return_result_via_out_param) {
+ var temp_var = get_temp_variable (result_type, result_type.value_owned);
+ var temp_ref = get_variable_cexpression (temp_var.name);
+
+ emit_temp_var (temp_var);
+
+ ccode.add_assignment (temp_ref, ccall_expr);
+ set_cvalue (expr, temp_ref);
+ } else {
+ set_cvalue (expr, ccall_expr);
+ }
+ ((GLibValue) expr.target_value).lvalue = true;
+ }
+
+ params_it = m.get_parameters().iterator ();
+ foreach (Expression arg in expr.get_argument_list ()) {
+ if (params_it.next ()) {
+ var param = params_it.get ();
+ if (param.params_array || param.ellipsis) {
+ // ignore ellipsis arguments as we currently don't use temporary variables for them
+ break;
+ }
+ }
+
+ var unary = arg as UnaryExpression;
+ if (unary == null || unary.operator != UnaryOperator.OUT) {
+ continue;
+ }
+
+ if (requires_destroy (unary.inner.value_type)) {
+ // unref old value
+ ccode.add_expression (destroy_value (unary.inner.target_value));
+ }
+
+ // assign new value
+ store_value (unary.inner.target_value, transform_value (unary.target_value, unary.inner.value_type, arg));
+ }
+ }
+}
diff --git a/codegen/valagerrormodule.vala b/codegen/valagerrormodule.vala
index 23d11a3..3047ad4 100644
--- a/codegen/valagerrormodule.vala
+++ b/codegen/valagerrormodule.vala
@@ -23,7 +23,7 @@
using GLib;
-public class Vala.GErrorModule : CCodeDelegateModule {
+public class Vala.GErrorModule : CppModule {
private int current_try_id = 0;
private int next_try_id = 0;
private bool is_in_catch = false;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]