From: Jürg Billeter Date: Sat, 5 Sep 2009 16:16:07 +0000 (+0200) Subject: Add support for properties in structs X-Git-Tag: 0.7.6~131 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=472db6e7c82ddc95fa0135652dc2481f9c53c6c4;p=thirdparty%2Fvala.git Add support for properties in structs --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index a5f628b99..f70190363 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -1250,10 +1250,13 @@ internal class Vala.CCodeBaseModule : CCodeModule { } if (prop.binding == MemberBinding.INSTANCE) { - var t = (ObjectTypeSymbol) prop.parent_symbol; - var this_type = new ObjectType (t); + var t = (TypeSymbol) prop.parent_symbol; + var this_type = get_data_type_for_symbol (t); generate_type_declaration (this_type, decl_space); var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ()); + if (t is Struct) { + cselfparam.type_name += "*"; + } function.add_parameter (cselfparam); } @@ -1295,7 +1298,7 @@ internal class Vala.CCodeBaseModule : CCodeModule { acc.accept_children (codegen); - var t = (ObjectTypeSymbol) prop.parent_symbol; + var t = (TypeSymbol) prop.parent_symbol; if (acc.construction && !t.is_subtype_of (gobject_type)) { Report.error (acc.source_reference, "construct properties require GLib.Object"); @@ -1319,8 +1322,11 @@ internal class Vala.CCodeBaseModule : CCodeModule { } } - var this_type = new ObjectType (t); + var this_type = get_data_type_for_symbol (t); var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ()); + if (t is Struct) { + cselfparam.type_name += "*"; + } CCodeFormalParameter cvalueparam; if (returns_real_struct) { cvalueparam = new CCodeFormalParameter ("value", acc.value_type.get_cname () + "*"); @@ -3966,7 +3972,31 @@ internal class Vala.CCodeBaseModule : CCodeModule { if (prop.binding == MemberBinding.INSTANCE) { /* target instance is first argument */ - ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner)); + var instance = (CCodeExpression) get_ccodenode (ma.inner); + + if (prop.parent_symbol is Struct) { + // we need to pass struct instance by reference + var unary = instance as CCodeUnaryExpression; + if (unary != null && unary.operator == CCodeUnaryOperator.POINTER_INDIRECTION) { + // *expr => expr + instance = unary.inner; + } else if (instance is CCodeIdentifier || instance is CCodeMemberAccess) { + instance = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance); + } else { + // if instance is e.g. a function call, we can't take the address of the expression + // (tmp = expr, &tmp) + var ccomma = new CCodeCommaExpression (); + + var temp_var = get_temp_variable (ma.inner.target_type); + temp_vars.insert (0, temp_var); + ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), instance)); + ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name))); + + instance = ccomma; + } + } + + ccall.add_argument (instance); } if (prop.no_accessor_method) { diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala index b00230918..d698a0317 100644 --- a/codegen/valaccodememberaccessmodule.vala +++ b/codegen/valaccodememberaccessmodule.vala @@ -244,6 +244,28 @@ internal class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { var ccall = new CCodeFunctionCall (new CCodeIdentifier (getter_cname)); if (prop.binding == MemberBinding.INSTANCE) { + if (prop.parent_symbol is Struct) { + // we need to pass struct instance by reference + var unary = pub_inst as CCodeUnaryExpression; + if (unary != null && unary.operator == CCodeUnaryOperator.POINTER_INDIRECTION) { + // *expr => expr + pub_inst = unary.inner; + } else if (pub_inst is CCodeIdentifier || pub_inst is CCodeMemberAccess) { + pub_inst = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, pub_inst); + } else { + // if instance is e.g. a function call, we can't take the address of the expression + // (tmp = expr, &tmp) + var ccomma = new CCodeCommaExpression (); + + var temp_var = get_temp_variable (expr.inner.target_type); + temp_vars.insert (0, temp_var); + ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), pub_inst)); + ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name))); + + pub_inst = ccomma; + } + } + ccall.add_argument (pub_inst); } diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala index dbc1cb891..164a25afd 100644 --- a/vala/valacodewriter.vala +++ b/vala/valacodewriter.vala @@ -362,6 +362,7 @@ public class Vala.CodeWriter : CodeVisitor { } visit_sorted (st.get_constants ()); visit_sorted (st.get_methods ()); + visit_sorted (st.get_properties ()); current_scope = current_scope.parent_scope; diff --git a/vala/valaparser.vala b/vala/valaparser.vala index 569bff477..fa5bc3d1c 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -2517,6 +2517,8 @@ public class Vala.Parser : CodeVisitor { st.add_field ((Field) sym); } else if (sym is Constant) { st.add_constant ((Constant) sym); + } else if (sym is Property) { + st.add_property ((Property) sym); } else { Report.error (sym.source_reference, "unexpected declaration in struct"); } diff --git a/vala/valastruct.vala b/vala/valastruct.vala index e060d8c79..17ed9ecbc 100644 --- a/vala/valastruct.vala +++ b/vala/valastruct.vala @@ -31,6 +31,7 @@ public class Vala.Struct : TypeSymbol { private Gee.List constants = new ArrayList (); private Gee.List fields = new ArrayList (); private Gee.List methods = new ArrayList (); + private Gee.List properties = new ArrayList (); private DataType _base_type = null; private string cname; @@ -210,6 +211,32 @@ public class Vala.Struct : TypeSymbol { return new ReadOnlyList (methods); } + /** + * Adds the specified property as a member to this struct. + * + * @param prop a property + */ + public void add_property (Property prop) { + properties.add (prop); + scope.add (prop.name, prop); + + prop.this_parameter = new FormalParameter ("this", SemanticAnalyzer.get_data_type_for_symbol (this)); + prop.scope.add (prop.this_parameter.name, prop.this_parameter); + + if (prop.field != null) { + add_field (prop.field); + } + } + + /** + * Returns a copy of the list of properties. + * + * @return list of properties + */ + public Gee.List get_properties () { + return new ReadOnlyList (properties); + } + public override void accept (CodeVisitor visitor) { visitor.visit_struct (this); } @@ -234,6 +261,10 @@ public class Vala.Struct : TypeSymbol { foreach (Method m in methods) { m.accept (visitor); } + + foreach (Property prop in properties) { + prop.accept (visitor); + } } public override string get_cname (bool const_type = false) { @@ -758,6 +789,10 @@ public class Vala.Struct : TypeSymbol { m.check (analyzer); } + foreach (Property prop in properties) { + prop.check (analyzer); + } + if (!external && !external_package && base_type == null && get_fields ().size == 0 && !is_boolean_type () && !is_integer_type () && !is_floating_type ()) { error = true;