2007-08-06 Jürg Billeter <j@bitron.ch>
+ * vala/Makefile.am, vala/parser.y, vala/valaarray.vala,
+ vala/valabindingprovider.vala, vala/valaclass.vala,
+ vala/valaenum.vala, vala/valainterface.vala,
+ vala/valamemorymanager.vala, vala/valamethod.vala,
+ vala/valasemanticanalyzer.vala, vala/valasymbol.vala,
+ vala/valasymbolresolver.vala, vala/valavariabledeclarator.vala,
+ gobject/Makefile.am, gobject/valacodegenerator.vala,
+ gobject/valacodegeneratorassignment.vala,
+ gobject/valacodegeneratorclass.vala,
+ gobject/valacodegeneratorinterface.vala,
+ gobject/valacodegeneratorinvocationexpression.vala,
+ gobject/valacodegeneratormethod.vala,
+ gobject/valadbusbindingprovider.vala, gobject/valadbusmethod.vala,
+ gobject/valadbussignal.vala, compiler/valacompiler.vala,
+ vapi/dbus-glib-1.vala, vapi/hal.vala: add experimental D-Bus client
+ support
+
+2007-08-06 Jürg Billeter <j@bitron.ch>
+
* gobject/valacodegenerator.vala,
gobject/valacodegeneratorassignment.vala: fixes for multi-dimension
arrays
if (Report.get_errors () > 0) {
return quit ();
}
-
+
+ var dbus_binding_provider = new DBusBindingProvider ();
+ dbus_binding_provider.context = context;
+
var analyzer = new SemanticAnalyzer (!disable_memory_management);
+ analyzer.add_binding_provider (dbus_binding_provider);
analyzer.analyze (context);
if (Report.get_errors () > 0) {
valacodegeneratorstruct.c \
valacodegeneratorstruct.h \
valacodegeneratorstruct.vala \
+ valadbusbindingprovider.c \
+ valadbusbindingprovider.h \
+ valadbusbindingprovider.vala \
+ valadbusmethod.c \
+ valadbusmethod.h \
+ valadbusmethod.vala \
+ valadbussignal.c \
+ valadbussignal.h \
+ valadbussignal.vala \
valainterfaceregisterfunction.c \
valainterfaceregisterfunction.h \
valainterfaceregisterfunction.vala \
valacodegeneratorsignal.h \
valacodegeneratorsourcefile.h \
valacodegeneratorstruct.h \
+ valadbusbindingprovider.h \
+ valadbusmethod.h \
+ valadbussignal.h \
valainterfaceregisterfunction.h \
valatyperegisterfunction.h \
$(NULL)
DataType glist_type;
DataType gslist_type;
DataType gstring_type;
+ DataType garray_type;
TypeReference mutex_type;
DataType type_module_type;
DataType iterable_type;
DataType iterator_type;
DataType list_type;
DataType map_type;
+ DataType connection_type;
Method substring_method;
glist_type = (DataType) glib_ns.scope.lookup ("List");
gslist_type = (DataType) glib_ns.scope.lookup ("SList");
gstring_type = (DataType) glib_ns.scope.lookup ("String");
+ garray_type = (DataType) glib_ns.scope.lookup ("Array");
mutex_type = new TypeReference ();
mutex_type.data_type = (DataType) glib_ns.scope.lookup ("Mutex");
list_type = (DataType) gee_ns.scope.lookup ("List");
map_type = (DataType) gee_ns.scope.lookup ("Map");
}
+
+ var dbus_ns = root_symbol.scope.lookup ("DBus");
+ if (dbus_ns != null) {
+ connection_type = (DataType) dbus_ns.scope.lookup ("Connection");
+ }
/* we're only interested in non-pkg source files */
var source_files = context.get_source_files ();
}
public override void visit_variable_declarator (VariableDeclarator! decl) {
+ decl.accept_children (this);
+
if (decl.type_reference.data_type is Array) {
// create variables to store array dimensions
var arr = (Array) decl.type_reference.data_type;
bool disconnect = false;
if (a.operator == AssignmentOperator.ADD) {
- connect_func = "g_signal_connect_object";
- if (!m.instance) {
- connect_func = "g_signal_connect";
+ if (sig is DBusSignal) {
+ connect_func = "dbus_g_proxy_connect_signal";
+ } else {
+ connect_func = "g_signal_connect_object";
+ if (!m.instance) {
+ connect_func = "g_signal_connect";
+ }
}
} else if (a.operator == AssignmentOperator.SUB) {
- connect_func = "g_signal_handlers_disconnect_matched";
+ if (sig is DBusSignal) {
+ connect_func = "dbus_g_proxy_disconnect_signal";
+ } else {
+ connect_func = "g_signal_handlers_disconnect_matched";
+ }
disconnect = true;
} else {
a.error = true;
ccall.add_argument (new CCodeIdentifier ("self"));
}
- if (!disconnect) {
+ if (!disconnect || sig is DBusSignal) {
ccall.add_argument (sig.get_canonical_cconstant ());
} else {
ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA"));
ccall.add_argument (new CCodeIdentifier ("self"));
}
if (!disconnect) {
- ccall.add_argument (new CCodeConstant ("0"));
+ if (sig is DBusSignal) {
+ // free_data_func
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ } else {
+ // connect_flags
+ ccall.add_argument (new CCodeConstant ("0"));
+ }
}
} else {
ccall.add_argument (new CCodeConstant ("NULL"));
}
a.ccodenode = ccall;
+
+ if (sig is DBusSignal && !disconnect) {
+ bool first = true;
+ foreach (FormalParameter param in m.get_parameters ()) {
+ if (first) {
+ // skip sender parameter
+ first = false;
+ continue;
+ }
+ sig.add_parameter (param);
+ }
+
+ sig.accept (this);
+
+ // FIXME should only be done once per marshaller
+ var register_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_register_marshaller"));
+ register_call.add_argument (new CCodeIdentifier (get_signal_marshaller_function (sig)));
+ register_call.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
+
+ var add_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_add_signal"));
+ if (ma.inner != null) {
+ add_call.add_argument ((CCodeExpression) ma.inner.ccodenode);
+ } else {
+ add_call.add_argument (new CCodeIdentifier ("self"));
+ }
+ add_call.add_argument (sig.get_canonical_cconstant ());
+
+ first = true;
+ foreach (FormalParameter param in m.get_parameters ()) {
+ if (first) {
+ // skip sender parameter
+ first = false;
+ continue;
+ }
+ if (param.type_reference.data_type is Array && ((Array) param.type_reference.data_type).element_type != string_type.data_type) {
+ var array = (Array) param.type_reference.data_type;
+ var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection"));
+ carray_type.add_argument (new CCodeConstant ("\"GArray\""));
+ carray_type.add_argument (new CCodeIdentifier (array.element_type.get_type_id ()));
+ register_call.add_argument (carray_type);
+ add_call.add_argument (carray_type);
+ } else {
+ register_call.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ()));
+ add_call.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ()));
+ }
+ }
+ register_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+ add_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+
+ var ccomma = new CCodeCommaExpression ();
+ ccomma.append_expression (register_call);
+ ccomma.append_expression (add_call);
+ ccomma.append_expression (ccall);
+ a.ccodenode = ccomma;
+ }
} else if (a.left is ElementAccess && !(((ElementAccess) a.left).container.static_type.data_type is Array)) {
// custom element access
CCodeExpression rhs = (CCodeExpression) a.right.ccodenode;
def_frag.append (instance_struct);
def_frag.append (type_struct);
/* only add the *Private struct if it is not empty, i.e. we actually have private data */
- if (cl.has_private_fields) {
+ if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
source_type_member_declaration.append (instance_priv_struct);
macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ());
source_type_member_declaration.append (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro));
cl.accept_children (this);
if (!cl.is_static) {
- if (class_has_readable_properties (cl)) {
+ if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) {
add_get_property_function (cl);
}
- if (class_has_writable_properties (cl)) {
+ if (class_has_writable_properties (cl) || cl.get_type_parameters ().size > 0) {
add_set_property_function (cl);
}
add_class_init_function (cl);
init_block.add_statement (new CCodeExpressionStatement (parent_assignment));
/* add struct for private fields */
- if (cl.has_private_fields) {
+ if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_add_private"));
ccall.add_argument (new CCodeIdentifier ("klass"));
ccall.add_argument (new CCodeConstant ("sizeof (%sPrivate)".printf (cl.get_cname ())));
/* set property handlers */
ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
ccall.add_argument (new CCodeIdentifier ("klass"));
- if (class_has_readable_properties (cl)) {
+ if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) {
init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "get_property"), new CCodeIdentifier ("%s_get_property".printf (cl.get_lower_case_cname (null))))));
}
- if (class_has_writable_properties (cl)) {
+ if (class_has_writable_properties (cl) || cl.get_type_parameters ().size > 0) {
init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "set_property"), new CCodeIdentifier ("%s_set_property".printf (cl.get_lower_case_cname (null))))));
}
var init_block = new CCodeBlock ();
instance_init.block = init_block;
- if (cl.has_private_fields) {
+ if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null))));
ccall.add_argument (new CCodeIdentifier ("self"));
init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall)));
current_symbol = iface;
current_type_symbol = iface;
- if (!iface.is_static) {
+ if (!iface.is_static && !iface.declaration_only) {
type_struct = new CCodeStruct ("_%s".printf (iface.get_type_cname ()));
header_type_declaration.append (new CCodeNewline ());
iface.accept_children (this);
- if (!iface.is_static) {
+ if (!iface.is_static && !iface.declaration_only) {
add_interface_base_init_function (iface);
var type_fun = new InterfaceRegisterFunction (iface);
if (ma.inner == null) {
instance = new CCodeIdentifier ("self");
/* require casts for overriden and inherited methods */
- req_cast = m.overrides || m.base_interface_method != null || (m.parent_symbol != current_type_symbol);
+ req_cast = m.overrides || m.base_interface_method != null || (m.parent_symbol != null && m.parent_symbol != current_type_symbol);
} else {
instance = (CCodeExpression) ma.inner.ccodenode;
/* reqiure casts if the type of the used instance is
* different than the type which declared the method */
- req_cast = base_method.parent_symbol != ma.inner.static_type.data_type;
+ req_cast = base_method.parent_symbol != null && base_method.parent_symbol != ma.inner.static_type.data_type;
}
if (m.instance_by_reference && (ma.inner != null || m.parent_symbol != current_type_symbol)) {
var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
csizeof.add_argument (new CCodeIdentifier (array.get_cname ()));
ccall.add_argument (csizeof);
+ } else if (m is DBusMethod) {
+ bool found_out = false;
+ Expression callback = null;
+ foreach (Expression arg in expr.get_argument_list ()) {
+ if (arg.symbol_reference is Method) {
+ // callback
+ if (callback != null) {
+ Report.error (expr.source_reference, "only one reply callback may be specified in invocation of DBus method");
+ expr.error = true;
+ return;
+ } else if (found_out) {
+ Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method");
+ expr.error = true;
+ return;
+ }
+ callback = arg;
+ } else if (arg is UnaryExpression && ((UnaryExpression) arg).operator == UnaryOperator.OUT) {
+ // out arg
+ if (callback != null) {
+ Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method");
+ expr.error = true;
+ return;
+ }
+ found_out = true;
+ } else {
+ // in arg
+ if (callback != null || found_out) {
+ Report.error (expr.source_reference, "in argument must not follow out argument or reply callback in invocation of DBus method");
+ expr.error = true;
+ return;
+ }
+ }
+ }
+
+ ccall.add_argument (new CCodeConstant ("\"%s\"".printf (m.name)));
+
+ if (callback != null) {
+ var reply_method = (Method) callback.symbol_reference;
+
+ var cb_fun = new CCodeFunction ("_%s_cb".printf (reply_method.get_cname ()), "void");
+ cb_fun.modifiers = CCodeModifiers.STATIC;
+ cb_fun.add_parameter (new CCodeFormalParameter ("proxy", "DBusGProxy*"));
+ cb_fun.add_parameter (new CCodeFormalParameter ("call", "DBusGProxyCall*"));
+ cb_fun.add_parameter (new CCodeFormalParameter ("user_data", "void*"));
+ cb_fun.block = new CCodeBlock ();
+ var cerrdecl = new CCodeDeclaration ("GError*");
+ cerrdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("error", new CCodeConstant ("NULL")));
+ cb_fun.block.add_statement (cerrdecl);
+ var cend_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_end_call"));
+ cend_call.add_argument (new CCodeIdentifier ("proxy"));
+ cend_call.add_argument (new CCodeIdentifier ("call"));
+ cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
+ var creply_call = new CCodeFunctionCall ((CCodeExpression) callback.ccodenode);
+ creply_call.add_argument (new CCodeIdentifier ("user_data"));
+ int param_count = reply_method.get_parameters ().size;
+ int i = 0;
+ foreach (FormalParameter param in reply_method.get_parameters ()) {
+ if ((++i) == param_count) {
+ // error parameter
+ break;
+ }
+ if (param.type_reference.data_type is Array && ((Array) param.type_reference.data_type).element_type != string_type.data_type) {
+ var array = (Array) param.type_reference.data_type;
+ var cdecl = new CCodeDeclaration ("GArray*");
+ cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
+ cb_fun.block.add_statement (cdecl);
+ cend_call.add_argument (get_dbus_array_type (array));
+ cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
+ creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "len"));
+ creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "data"));
+ } else {
+ var cdecl = new CCodeDeclaration (param.type_reference.get_cname ());
+ cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
+ cb_fun.block.add_statement (cdecl);
+ cend_call.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ()));
+ cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
+ creply_call.add_argument (new CCodeIdentifier (param.name));
+ }
+ }
+ cend_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+ cb_fun.block.add_statement (new CCodeExpressionStatement (cend_call));
+ creply_call.add_argument (new CCodeIdentifier ("error"));
+ cb_fun.block.add_statement (new CCodeExpressionStatement (creply_call));
+ source_type_member_definition.append (cb_fun);
+
+ ccall.add_argument (new CCodeIdentifier (cb_fun.name));
+ ccall.add_argument (new CCodeConstant ("self"));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ } else if (found_out || m.return_type.data_type != null) {
+ ccall.call = new CCodeIdentifier ("dbus_g_proxy_call");
+
+ // method can fail
+ current_method_inner_error = true;
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("inner_error")));
+ } else {
+ ccall.call = new CCodeIdentifier ("dbus_g_proxy_call_no_reply");
+ }
}
bool ellipsis = false;
var i = 1;
Iterator<FormalParameter> params_it = params.iterator ();
foreach (Expression arg in expr.get_argument_list ()) {
- /* explicitly use strong reference as ccall gets
- * unrefed at end of inner block
- */
+ if (m is DBusMethod) {
+ if (arg.symbol_reference is Method) {
+ // callback parameter
+ break;
+ }
+
+ ccall.add_argument (new CCodeIdentifier (arg.static_type.data_type.get_type_id ()));
+ }
+
CCodeExpression cexpr = (CCodeExpression) arg.ccodenode;
if (params_it.next ()) {
var param = params_it.get ();
}
/* add length argument for methods returning arrays */
- if (m != null && m.return_type.data_type is Array) {
+ if (m != null && m.return_type.data_type is Array && !(m is DBusMethod)) {
var arr = (Array) m.return_type.data_type;
for (int dim = 1; dim <= arr.rank; dim++) {
if (!m.no_array_length) {
}
}
- if (expr.can_fail) {
+ if (connection_type != null && ma.inner != null && ma.inner.static_type != null && ma.inner.static_type.data_type == connection_type && m.name == "get_object") {
+ var dbus_iface = (Interface) m.return_type.data_type;
+ var dbus_attr = dbus_iface.get_attribute ("DBusInterface");
+ ccall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_attr.get_string ("name"))));
+ } else if (m is DBusMethod) {
+ ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+ }
+
+ if (expr.can_fail && !(m is DBusMethod)) {
// method can fail
current_method_inner_error = true;
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("inner_error")));
} else if (ellipsis) {
/* ensure variable argument list ends with NULL
* except when using printf-style arguments */
- if (m == null || !m.printf_format) {
+ if ((m == null || !m.printf_format) && !(m is DBusMethod)) {
ccall.add_argument (new CCodeConstant ("NULL"));
}
}
ccomma.append_expression (cndupcall);
expr.ccodenode = ccomma;
+ } else if (m is DBusMethod && m.return_type.data_type != null) {
+ if (m.return_type.data_type is Array && ((Array) m.return_type.data_type).element_type != string_type.data_type) {
+ var array = (Array) m.return_type.data_type;
+
+ ccall.add_argument (get_dbus_array_type (array));
+
+ var garray_type_reference = new TypeReference ();
+ garray_type_reference.data_type = garray_type;
+ var temp_decl = get_temp_variable_declarator (garray_type_reference);
+ temp_vars.insert (0, temp_decl);
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name)));
+
+ ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+
+ var ccomma = new CCodeCommaExpression ();
+ ccomma.append_expression (ccall);
+ ccomma.append_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier (temp_decl.name), "data"));
+ expr.ccodenode = ccomma;
+
+ if (!m.no_array_length) {
+ expr.append_array_size (new CCodeMemberAccess.pointer (new CCodeIdentifier (temp_decl.name), "len"));
+ } else {
+ expr.append_array_size (new CCodeConstant ("-1"));
+ }
+ } else {
+ ccall.add_argument (new CCodeIdentifier (m.return_type.data_type.get_type_id ()));
+
+ var temp_decl = get_temp_variable_declarator (m.return_type);
+ temp_vars.insert (0, temp_decl);
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name)));
+
+ ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
+
+ var ccomma = new CCodeCommaExpression ();
+ ccomma.append_expression (ccall);
+ ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
+ expr.ccodenode = ccomma;
+ }
}
}
+
+ private CCodeExpression! get_dbus_array_type (Array! array) {
+ var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection"));
+ carray_type.add_argument (new CCodeConstant ("\"GArray\""));
+ carray_type.add_argument (new CCodeIdentifier (array.element_type.get_type_id ()));
+ return carray_type;
+ }
}
private CCodeStatement create_type_check_statement (CodeNode! method_node, DataType ret_type, DataType! t, bool non_null, string! var_name) {
var ccheck = new CCodeFunctionCall ();
- if (t is Class || t is Interface) {
+ if (t is Class || (t is Interface && !((Interface) t).declaration_only)) {
var ctype_check = new CCodeFunctionCall (new CCodeIdentifier (t.get_upper_case_cname ("IS_")));
ctype_check.add_argument (new CCodeIdentifier (var_name));
--- /dev/null
+/* valadbusbindingprovider.vala
+ *
+ * Copyright (C) 2007 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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:
+ * Jürg Billeter <j@bitron.ch>
+ */
+
+using GLib;
+using Gee;
+
+/**
+ * Dynamic binding provider for DBus objects.
+ */
+public class Vala.DBusBindingProvider : BindingProvider {
+ public CodeContext context {
+ set {
+ _context = value;
+
+ string_type = (DataType) _context.root.scope.lookup ("string");
+
+ var dbus_ns = _context.root.scope.lookup ("DBus");
+ if (dbus_ns != null) {
+ connection_type = (DataType) dbus_ns.scope.lookup ("Connection");
+ dbus_error_type = (DataType) dbus_ns.scope.lookup ("Error");
+ }
+ }
+ }
+
+ private CodeContext _context;
+ private DataType string_type;
+ private DataType connection_type;
+ private DataType dbus_error_type;
+
+ private Collection<Symbol> symbols = new ArrayList<Symbol> ();
+
+ public DBusBindingProvider () {
+ }
+
+ public Symbol get_binding (MemberAccess! ma) {
+ if (connection_type != null && ma.inner != null && ma.inner.static_type.data_type == connection_type) {
+ var type_args = ma.get_type_arguments ();
+ if (type_args.size != 1) {
+ return null;
+ }
+ Iterator<TypeReference> type_args_it = type_args.iterator ();
+ type_args_it.next ();
+ var ret_type = new TypeReference ();
+ ret_type.data_type = type_args_it.get ().data_type;
+ if (!is_dbus_interface (ret_type.data_type)) {
+ return null;
+ }
+ var m = new Method ("get_object", ret_type, ma.source_reference);
+ m.set_cname ("dbus_g_proxy_new_for_name");
+ m.add_cheader_filename ("dbus/dbus-glib.h");
+ m.access = MemberAccessibility.PUBLIC;
+ var string_type_ref = new TypeReference ();
+ string_type_ref.data_type = string_type;
+ m.add_parameter (new FormalParameter ("name", string_type_ref));
+ m.add_parameter (new FormalParameter ("path", string_type_ref));
+ symbols.add (m);
+ return m;
+ } else if (ma.inner != null && is_dbus_interface (ma.inner.static_type.data_type)) {
+ if (ma.parent_node is InvocationExpression) {
+ var expr = (InvocationExpression) ma.parent_node;
+ var ret_type = new TypeReference ();
+ if (expr.expected_type != null) {
+ ret_type.data_type = expr.expected_type.data_type;
+ ret_type.transfers_ownership = ret_type.data_type.is_reference_type ();
+ }
+ var m = new DBusMethod (ma.member_name, ret_type, ma.source_reference);
+ if (expr.expected_type != null) {
+ var error_type = new TypeReference ();
+ error_type.data_type = dbus_error_type;
+ m.add_error_domain (error_type);
+ }
+ m.access = MemberAccessibility.PUBLIC;
+ m.add_parameter (new FormalParameter.with_ellipsis ());
+ symbols.add (m);
+ return m;
+ } else if (ma.parent_node is Assignment) {
+ var a = (Assignment) ma.parent_node;
+ if (a.left != ma) {
+ return null;
+ }
+ var s = new DBusSignal (ma.member_name, new TypeReference (), ma.source_reference);
+ s.access = MemberAccessibility.PUBLIC;
+ symbols.add (s);
+ return s;
+ }
+ }
+ return null;
+ }
+
+ private bool is_dbus_interface (DataType! t) {
+ if (!(t is Interface)) {
+ return false;
+ }
+ return (t.get_attribute ("DBusInterface") != null);
+ }
+}
+
--- /dev/null
+/* valadbusmethod.vala
+ *
+ * Copyright (C) 2007 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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:
+ * Jürg Billeter <j@bitron.ch>
+ */
+
+using GLib;
+using Gee;
+
+/**
+ * Represents a dynamic bound DBus method.
+ */
+public class Vala.DBusMethod : Method {
+ public DBusMethod (construct string name, construct TypeReference return_type, construct SourceReference source_reference = null) {
+ }
+
+ public override Collection<string> get_cheader_filenames () {
+ return new ReadOnlyCollection<string> ();
+ }
+
+ public override string! get_default_cname () {
+ return "dbus_g_proxy_begin_call";
+ }
+}
--- /dev/null
+/* valadbussignal.vala
+ *
+ * Copyright (C) 2007 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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:
+ * Jürg Billeter <j@bitron.ch>
+ */
+
+using GLib;
+
+/**
+ * Represents a dynamic bound DBus signal.
+ */
+public class Vala.DBusSignal : Signal {
+ public DBusSignal (construct string name, construct TypeReference return_type, construct SourceReference source_reference = null) {
+ }
+}
valabinaryexpression.c \
valabinaryexpression.h \
valabinaryexpression.vala \
+ valabindingprovider.c \
+ valabindingprovider.h \
+ valabindingprovider.vala \
valablock.c \
valablock.h \
valablock.vala \
valaattributeprocessor.h \
valabaseaccess.h \
valabinaryexpression.h \
+ valabindingprovider.h \
valablock.h \
valabooleanliteral.h \
valabreakstatement.h \
interface_body
: OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE
+ | SEMICOLON
+ {
+ vala_symbol_set_is_imported (symbol_stack->data, TRUE);
+ vala_interface_set_declaration_only (VALA_INTERFACE (symbol_stack->data), TRUE);
+ }
;
opt_interface_member_declarations
return "g_value_set_pointer";
}
+ public override string get_type_id () {
+ if (element_type == source_reference.file.context.root.scope.lookup ("string")) {
+ return "G_TYPE_STRV";
+ } else {
+ return null;
+ }
+ }
+
public ArrayLengthField get_length_field () {
if (length_field == null) {
length_field = new ArrayLengthField (source_reference);
--- /dev/null
+/* valabindingprovider.vala
+ *
+ * Copyright (C) 2007 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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:
+ * Jürg Billeter <j@bitron.ch>
+ */
+
+using GLib;
+
+/**
+ * Interface for dynamic binding providers.
+ */
+public interface Vala.BindingProvider {
+ /**
+ * Return custom binding for the specified member access expression.
+ *
+ * @param ma member access expression
+ * @return resolved symbol or null if no binding can be provided
+ */
+ public abstract Symbol get_binding (MemberAccess! ma);
+}
+
if (a.has_argument ("cname")) {
set_cname (a.get_string ("cname"));
}
+ if (a.has_argument ("lower_case_csuffix")) {
+ lower_case_csuffix = a.get_string ("lower_case_csuffix");
+ }
if (a.has_argument ("cheader_filename")) {
var val = a.get_string ("cheader_filename");
foreach (string filename in val.split (",")) {
}
public override string get_upper_case_cname (string infix) {
- return "%s%s".printf (parent_symbol.get_lower_case_cprefix (), camel_case_to_lower_case (name)).up ();
+ return get_lower_case_cname (null).up ();
}
public override bool is_reference_type () {
if (a.has_argument ("cprefix")) {
set_cprefix (a.get_string ("cprefix"));
}
+ if (a.has_argument ("lower_case_csuffix")) {
+ lower_case_csuffix = a.get_string ("lower_case_csuffix");
+ }
if (a.has_argument ("cheader_filename")) {
var val = a.get_string ("cheader_filename");
foreach (string filename in val.split (",")) {
*/
public bool is_static { get; set; }
+ public bool declaration_only { get; set; }
+
private Gee.List<TypeParameter> type_parameters = new ArrayList<TypeParameter> ();
private Gee.List<TypeReference> prerequisites = new ArrayList<TypeReference> ();
}
}
}
-
+
+ private void process_dbus_interface_attribute (Attribute! a) {
+ if (declaration_only) {
+ cname = "DBusGProxy";
+ }
+ }
+
/**
* Process all associated attributes.
*/
foreach (Attribute a in attributes) {
if (a.name == "CCode") {
process_ccode_attribute (a);
+ } else if (a.name == "DBusInterface") {
+ process_dbus_interface_attribute (a);
}
}
}
}
public override void visit_variable_declarator (VariableDeclarator! decl) {
+ decl.accept_children (this);
+
if (decl.initializer != null) {
if (decl.type_reference.takes_ownership) {
visit_possibly_missing_copy_expression (decl.initializer);
}
}
}
-
- /**
- * Specifies whether this is an imported method i.e. the Import
- * attribute ist set for this method.
- */
- public bool is_imported { get; set; }
-
+
/**
* Specifies whether this method expects printf-style format arguments.
*/
private int next_lambda_id = 0;
+ private Collection<BindingProvider> binding_providers = new ArrayList<BindingProvider> ();
+
public SemanticAnalyzer (bool manage_memory = true) {
memory_management = manage_memory;
}
+ public void add_binding_provider (BindingProvider! binding_provider) {
+ binding_providers.add (binding_provider);
+ }
+
/**
* Analyze and check code in the specified context.
*
}
public override void visit_variable_declarator (VariableDeclarator! decl) {
+ if (decl.initializer != null) {
+ decl.initializer.expected_type = decl.type_reference;
+ }
+
+ decl.accept_children (this);
+
if (decl.type_reference == null) {
/* var type */
}
if (expr.symbol_reference == null) {
- expr.error = true;
- Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, base_symbol.get_full_name ()));
- return;
+ /* allow plug-ins to provide custom member bindings */
+ foreach (BindingProvider binding_provider in binding_providers) {
+ expr.symbol_reference = binding_provider.get_binding (expr);
+ if (expr.symbol_reference != null) {
+ break;
+ }
+ }
+
+ if (expr.symbol_reference == null) {
+ expr.error = true;
+ Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, base_symbol.get_full_name ()));
+ return;
+ }
}
var member = expr.symbol_reference;
a.right.expected_type = new TypeReference ();
a.right.expected_type.data_type = sig.get_callback ();
+ } else {
+ a.right.expected_type = ma.static_type;
}
} else if (a.left is ElementAccess) {
// do nothing
public Scope scope {
get { return _scope; }
}
+
+ /**
+ * Specifies whether this is an imported symbol e.g. the Import
+ * attribute has been set.
+ */
+ public bool is_imported { get; set; }
private weak Scope _owner;
private Scope _scope;
}
}
+ public override void visit_variable_declarator (VariableDeclarator! decl) {
+ decl.accept_children (this);
+ }
+
public override void visit_throw_statement (ThrowStatement! stmt) {
stmt.accept_children (this);
}
}
public override void accept (CodeVisitor! visitor) {
+ visitor.visit_variable_declarator (this);
+ }
+
+ public override void accept_children (CodeVisitor! visitor) {
if (initializer != null) {
initializer.accept (visitor);
if (type_reference != null) {
type_reference.accept (visitor);
}
-
- visitor.visit_variable_declarator (this);
}
public Collection<FormalParameter> get_parameters () {
* Jürg Billeter <j@bitron.ch>
*/
-[CCode (cheader_filename = "dbus/dbus-glib-lowlevel.h")]
+[CCode (cheader_filename = "dbus/dbus-glib-lowlevel.h,dbus/dbus-glib.h")]
namespace DBus {
[CCode (cprefix = "DBUS_BUS_")]
public enum BusType {
STARTER
}
- public struct Bus {
- public static Connection get (BusType type, ref Error error);
+ public struct RawBus {
+ [CCode (cname = "dbus_bus_get")]
+ public static RawConnection get (BusType type, ref Error error);
}
[ReferenceType (dup_function = "dbus_connection_ref", free_function = "dbus_connection_unref")]
- public struct Connection {
+ [CCode (cname = "DBusConnection")]
+ public struct RawConnection {
[CCode (cname = "dbus_connection_setup_with_g_main")]
- public void setup_with_main (GLib.MainContext context);
+ public void setup_with_main (GLib.MainContext context = null);
}
- public struct Error {
+ [CCode (cname = "DBusError")]
+ public struct RawError {
public string name;
public string message;
[InstanceByReference]
public bool is_set ();
}
+
+ [ErrorDomain]
+ [CCode (cname = "DBusGError", lower_case_csuffix = "gerror", cprefix = "DBUS_GERROR_")]
+ public enum Error {
+ FAILED,
+ NO_MEMORY,
+ SERVICE_UNKNOWN,
+ NAME_HAS_NO_OWNER,
+ NO_REPLY,
+ IO_ERROR,
+ BAD_ADDRESS,
+ NOT_SUPPORTED,
+ LIMITS_EXCEEDED,
+ ACCESS_DENIED,
+ AUTH_FAILED,
+ NO_SERVER,
+ TIMEOUT,
+ NO_NETWORK,
+ ADDRESS_IN_USE,
+ DISCONNECTED,
+ INVALID_ARGS,
+ FILE_NOT_FOUND,
+ FILE_EXISTS,
+ UNKNOWN_METHOD,
+ TIMED_OUT,
+ MATCH_RULE_NOT_FOUND,
+ MATCH_RULE_INVALID,
+ SPAWN_EXEC_FAILED,
+ SPAWN_FORK_FAILED,
+ SPAWN_CHILD_EXITED,
+ SPAWN_CHILD_SIGNALED,
+ SPAWN_FAILED,
+ UNIX_PROCESS_ID_UNKNOWN,
+ INVALID_SIGNATURE,
+ INVALID_FILE_CONTENT,
+ SELINUX_SECURITY_CONTEXT_UNKNOWN,
+ REMOTE_EXCEPTION
+ }
+
+ public struct Bus {
+ [CCode (cname = "dbus_g_bus_get")]
+ public static Connection get (BusType type) throws Error;
+
+ }
+
+ [ReferenceType (dup_function = "dbus_g_connection_ref", free_function = "dbus_g_connection_unref")]
+ [CCode (cname = "DBusGConnection")]
+ public struct Connection {
+ }
+
+ [CCode (cname = "DBusGProxy", lower_case_csuffix = "g_proxy")]
+ public class Proxy {
+ public Proxy.for_name (Connection! connection, string! name, string! path, string! interface_);
+ public bool call (string! method, out GLib.Error error, GLib.Type first_arg_type, ...);
+ public weak ProxyCall begin_call (string! method, ProxyCallNotify notify, pointer data, GLib.DestroyNotify destroy, GLib.Type first_arg_type, ...);
+ public bool end_call (ProxyCall call, out GLib.Error error, GLib.Type first_arg_type, ...);
+ public void cancel_call (ProxyCall call);
+ }
+
+ [CCode (cname = "DBusGProxyCallNotify")]
+ public static delegate void ProxyCallNotify (Proxy proxy, ProxyCall call_id, pointer user_data);
+
+ [ReferenceType]
+ public struct ProxyCall {
+ }
}
[CCode (cprefix = "libhal_ctx_")]
public struct Context {
public Context ();
- public bool init (ref DBus.Error error);
- public bool set_dbus_connection (DBus.Connection conn);
+ public bool init (ref DBus.RawError error);
+ public bool set_dbus_connection (DBus.RawConnection conn);
public bool set_user_data (pointer user_data);
public pointer get_user_data ();
public bool set_device_added (DeviceAdded _callback);
public bool set_device_removed (DeviceRemoved _callback);
[NoArrayLength]
[CCode (cname = "libhal_find_device_by_capability")]
- public string[] find_device_by_capability (string capability, ref int num_devices, ref DBus.Error error);
+ public string[] find_device_by_capability (string capability, ref int num_devices, ref DBus.RawError error);
[CCode (cname = "libhal_device_get_property_string")]
- public string device_get_property_string (string udi, string key, ref DBus.Error error);
+ public string device_get_property_string (string udi, string key, ref DBus.RawError error);
[CCode (cname = "libhal_device_get_property_int")]
- public int device_get_property_int (string udi, string key, ref DBus.Error error);
+ public int device_get_property_int (string udi, string key, ref DBus.RawError error);
[CCode (cname = "libhal_device_get_property_uint64")]
- public uint64 device_get_property_uint64 (string udi, string key, ref DBus.Error error);
+ public uint64 device_get_property_uint64 (string udi, string key, ref DBus.RawError error);
[CCode (cname = "libhal_device_query_capability")]
- public bool device_query_capability (string udi, string capability, ref DBus.Error error);
+ public bool device_query_capability (string udi, string capability, ref DBus.RawError error);
}
}