}
}
- public override void visit_delegate (Delegate! cb) {
- cb.accept_children (this);
+ public override void visit_delegate (Delegate! d) {
+ d.accept_children (this);
- var cfundecl = new CCodeFunctionDeclarator (cb.get_cname ());
- foreach (FormalParameter param in cb.get_parameters ()) {
+ var cfundecl = new CCodeFunctionDeclarator (d.get_cname ());
+ foreach (FormalParameter param in d.get_parameters ()) {
cfundecl.add_parameter ((CCodeFormalParameter) param.ccodenode);
}
-
- var ctypedef = new CCodeTypeDefinition (cb.return_type.get_cname (), cfundecl);
-
- if (!cb.is_internal_symbol ()) {
+ if (d.instance) {
+ var cparam = new CCodeFormalParameter ("user_data", "void*");
+ cfundecl.add_parameter (cparam);
+ }
+
+ var ctypedef = new CCodeTypeDefinition (d.return_type.get_cname (), cfundecl);
+
+ if (!d.is_internal_symbol ()) {
header_type_definition.append (ctypedef);
} else {
source_type_member_declaration.append (ctypedef);
temp_vars.insert (0, len_decl);
}
+ } else if (decl.type_reference is DelegateType) {
+ var deleg_type = (DelegateType) decl.type_reference;
+ var d = deleg_type.delegate_symbol;
+ if (d.instance) {
+ // create variable to store delegate target
+ var target_decl = new VariableDeclarator (get_delegate_target_cname (decl.name));
+ target_decl.type_reference = new PointerType (new VoidType ());
+
+ temp_vars.insert (0, target_decl);
+ }
}
CCodeExpression rhs = null;
ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
rhs = ccomma;
+ } else if (decl.type_reference is DelegateType) {
+ var deleg_type = (DelegateType) decl.type_reference;
+ var d = deleg_type.delegate_symbol;
+ if (d.instance) {
+ var ccomma = new CCodeCommaExpression ();
+
+ var temp_decl = get_temp_variable_declarator (decl.type_reference, true, decl);
+ temp_vars.insert (0, temp_decl);
+ ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), rhs));
+
+ var lhs_delegate_target = new CCodeIdentifier (get_delegate_target_cname (decl.name));
+ var rhs_delegate_target = get_delegate_target_cexpression (decl.initializer);
+ ccomma.append_expression (new CCodeAssignment (lhs_delegate_target, rhs_delegate_target));
+
+ ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
+
+ rhs = ccomma;
+ }
}
} else if (decl.type_reference.data_type != null && decl.type_reference.data_type.is_reference_type ()) {
rhs = new CCodeConstant ("NULL");
visit_expression (expr);
}
+
+ private string! get_array_length_cname (string! array_cname, int dim) {
+ return "%s_length%d".printf (array_cname, dim);
+ }
public CCodeExpression! get_array_length_cexpression (Expression! array_expr, int dim) {
bool is_out = false;
return new CCodeConstant ("NULL");
}
}
+
+ private string! get_delegate_target_cname (string! delegate_cname) {
+ return "%s_target".printf (delegate_cname);
+ }
+
+ public CCodeExpression! get_delegate_target_cexpression (Expression! delegate_expr) {
+ bool is_out = false;
+
+ if (delegate_expr is UnaryExpression) {
+ var unary_expr = (UnaryExpression) delegate_expr;
+ if (unary_expr.operator == UnaryOperator.OUT || unary_expr.operator == UnaryOperator.REF) {
+ delegate_expr = unary_expr.inner;
+ is_out = true;
+ }
+ }
+
+ if (delegate_expr is InvocationExpression) {
+ var invocation_expr = (InvocationExpression) delegate_expr;
+ return invocation_expr.delegate_target;
+ } else if (delegate_expr.symbol_reference != null) {
+ if (delegate_expr.symbol_reference is FormalParameter) {
+ var param = (FormalParameter) delegate_expr.symbol_reference;
+ CCodeExpression target_expr = new CCodeIdentifier (get_delegate_target_cname (param.name));
+ if (param.type_reference.is_out || param.type_reference.is_ref) {
+ // accessing argument of out/ref param
+ target_expr = new CCodeParenthesizedExpression (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_expr));
+ }
+ if (is_out) {
+ // passing array as out/ref
+ return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
+ } else {
+ return target_expr;
+ }
+ } else if (delegate_expr.symbol_reference is VariableDeclarator) {
+ var decl = (VariableDeclarator) delegate_expr.symbol_reference;
+ var target_expr = new CCodeIdentifier (get_delegate_target_cname (decl.name));
+ if (is_out) {
+ return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
+ } else {
+ return target_expr;
+ }
+ } else if (delegate_expr.symbol_reference is Field) {
+ var field = (Field) delegate_expr.symbol_reference;
+ var target_cname = get_delegate_target_cname (field.name);
+
+ var ma = (MemberAccess) delegate_expr;
+
+ CCodeExpression pub_inst = null;
+ Typesymbol base_type = null;
+ CCodeExpression target_expr = null;
+
+ if (ma.inner == null) {
+ pub_inst = new CCodeIdentifier ("self");
+
+ if (current_type_symbol != null) {
+ /* base type is available if this is a type method */
+ base_type = (Typesymbol) current_type_symbol;
+ }
+ } else {
+ pub_inst = (CCodeExpression) ma.inner.ccodenode;
+
+ if (ma.inner.static_type != null) {
+ base_type = ma.inner.static_type.data_type;
+ }
+ }
+
+ if (field.instance) {
+ var instance_expression_type = new DataType ();
+ instance_expression_type.data_type = base_type;
+ var instance_target_type = new DataType ();
+ instance_target_type.data_type = (Typesymbol) field.parent_symbol;
+ CCodeExpression typed_inst = get_implicit_cast_expression (pub_inst, instance_expression_type, instance_target_type);
+
+ CCodeExpression inst;
+ if (field.access == SymbolAccessibility.PRIVATE) {
+ inst = new CCodeMemberAccess.pointer (typed_inst, "priv");
+ } else {
+ inst = typed_inst;
+ }
+ if (((Typesymbol) field.parent_symbol).is_reference_type ()) {
+ target_expr = new CCodeMemberAccess.pointer (inst, target_cname);
+ } else {
+ target_expr = new CCodeMemberAccess (inst, target_cname);
+ }
+ } else {
+ target_expr = new CCodeIdentifier (target_cname);
+ }
+
+ if (is_out) {
+ return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
+ } else {
+ return target_expr;
+ }
+ } else if (delegate_expr.symbol_reference is Method) {
+ var ma = (MemberAccess) delegate_expr;
+ if (ma.inner == null) {
+ if (current_method != null && current_method.instance) {
+ return new CCodeIdentifier ("self");
+ } else {
+ return new CCodeConstant ("NULL");
+ }
+ } else {
+ return (CCodeExpression) ma.inner.ccodenode;
+ }
+ }
+ }
+
+ return new CCodeConstant ("NULL");
+ }
public override void visit_element_access (ElementAccess! expr) {
expr.code_binding.emit ();
}
CCodeExpression cexpr = (CCodeExpression) arg.ccodenode;
+ Gee.List<CCodeExpression> extra_args = new ArrayList<CCodeExpression> ();
if (params_it.next ()) {
var param = params_it.get ();
ellipsis = param.ellipsis;
for (int dim = 1; dim <= arr.rank; dim++) {
ccall.add_argument (get_array_length_cexpression (arg, dim));
}
+ } else if (param.type_reference is DelegateType) {
+ var deleg_type = (DelegateType) param.type_reference;
+ var d = deleg_type.delegate_symbol;
+ if (d.instance) {
+ extra_args.add (get_delegate_target_cexpression (arg));
+ }
}
cexpr = get_implicit_cast_expression (cexpr, arg.static_type, param.type_reference);
}
ccall.add_argument (cexpr);
+
+ foreach (CCodeExpression extra_arg in extra_args) {
+ ccall.add_argument (extra_arg);
+ }
+
i++;
}
while (params_it.next ()) {
expr.append_array_size (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.instance) {
+ var temp_decl = get_temp_variable_declarator (new PointerType (new VoidType ()));
+ var temp_ref = new CCodeIdentifier (temp_decl.name);
+
+ temp_vars.insert (0, temp_decl);
+
+ ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
+
+ expr.delegate_target = temp_ref;
+ }
}
if (connection_type != null && ma.inner != null && ma.inner.static_type != null && ma.inner.static_type.data_type == connection_type && m.name == "get_object") {
if ((m == null || !m.printf_format) && !(m is DBusMethod)) {
ccall.add_argument (new CCodeConstant (m.sentinel));
}
+ } else if (itype is DelegateType) {
+ var deleg_type = (DelegateType) itype;
+ var d = deleg_type.delegate_symbol;
+ if (d.instance) {
+ ccall.add_argument (get_delegate_target_cexpression (expr.call));
+ }
}
if (m != null && m.instance && m.returns_modified_pointer) {
if (vdeclarator != null) {
vdeclarator.add_parameter ((CCodeFormalParameter) param.ccodenode);
}
+
+ if (param.type_reference is DelegateType) {
+ var deleg_type = (DelegateType) param.type_reference;
+ var d = deleg_type.delegate_symbol;
+ if (d.instance) {
+ var cparam = new CCodeFormalParameter (get_delegate_target_cname (param.name), "void*");
+ function.add_parameter (cparam);
+ if (vdeclarator != null) {
+ vdeclarator.add_parameter (cparam);
+ }
+ }
+ }
}
- // return array length if appropriate
if (!m.no_array_length && creturn_type.data_type is Array) {
+ // return array length if appropriate
var arr = (Array) creturn_type.data_type;
for (int dim = 1; dim <= arr.rank; dim++) {
vdeclarator.add_parameter (cparam);
}
}
+ } else if (creturn_type is DelegateType) {
+ // return delegate target if appropriate
+ var deleg_type = (DelegateType) creturn_type;
+ var d = deleg_type.delegate_symbol;
+ if (d.instance) {
+ var cparam = new CCodeFormalParameter (get_delegate_target_cname ("result"), "void*");
+ function.add_parameter (cparam);
+ if (vdeclarator != null) {
+ vdeclarator.add_parameter (cparam);
+ }
+ }
}
if (m.instance && m.instance_last) {
}
return null;
}
-
- private string! get_array_length_cname (string! array_cname, int dim) {
- return "%s_length%d".printf (array_cname, dim);
- }
public override void visit_creation_method (CreationMethod! m) {
if (m.body != null && current_type_symbol is Class && current_class.is_subtype_of (gobject_type)) {