diff --git a/gobject/valaccodegenerator.vala b/gobject/valaccodegenerator.vala index 3eb4339..b5ec59d 100644 --- a/gobject/valaccodegenerator.vala +++ b/gobject/valaccodegenerator.vala @@ -273,9 +273,89 @@ public class Vala.CCodeGenerator : CodeGenerator { if (en.source_reference.comment != null) { header_type_definition.append (new CCodeComment (en.source_reference.comment)); } + // FIXME: should be privat-izable? header_type_definition.append (cenum); + CCodeFragment decl_frag; + CCodeFragment def_frag = source_type_member_definition; + if (en.access != SymbolAccessibility.PRIVATE) { + decl_frag = header_type_definition; + } else { + decl_frag = source_type_member_declaration; + } + + decl_frag.append (new CCodeNewline ()); + + var macro = "(%s_get_type ())".printf (en.get_lower_case_cname (null)); + decl_frag.append (new CCodeMacroReplacement (en.get_upper_case_cname ("TYPE_"), macro)); + en.accept_children (this); + + var clist = new CCodeInitializerList (); /* or during visit time? */ + CCodeInitializerList clist_ev = null; + foreach (EnumValue ev in en.get_values ()) { + clist_ev = new CCodeInitializerList (); + clist_ev.append (new CCodeConstant (ev.get_cname ())); + clist_ev.append (new CCodeIdentifier ("\"%s\"".printf (ev.get_cname ()))); + clist_ev.append (ev.get_canonical_cconstant ()); + clist.append (clist_ev); + } + + clist_ev = new CCodeInitializerList (); + clist_ev.append (new CCodeConstant ("0")); + clist_ev.append (new CCodeConstant ("NULL")); + clist_ev.append (new CCodeConstant ("NULL")); + clist.append (clist_ev); + + var enum_decl = new CCodeVariableDeclarator.with_initializer ("_%s[]".printf (en.get_cname ()), clist); + + CCodeDeclaration cdecl = null; + if (en.is_flags) { + cdecl = new CCodeDeclaration ("const GFlagsValue"); + } else { + cdecl = new CCodeDeclaration ("const GEnumValue"); + } + + cdecl.add_declarator (enum_decl); + cdecl.modifiers = CCodeModifiers.STATIC; + + def_frag.append (cdecl); + + var fun_name = "%s_get_type".printf (en.get_lower_case_cname (null)); + var regfun = new CCodeFunction (fun_name, "GType"); + var regblock = new CCodeBlock (); + + cdecl = new CCodeDeclaration ("GType"); + string type_id_name = "%s_type_id".printf (en.get_lower_case_cname (null)); + cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (type_id_name, new CCodeConstant ("0"))); + cdecl.modifiers = CCodeModifiers.STATIC; + regblock.add_statement (cdecl); + + var type_init = new CCodeBlock (); + + CCodeFunctionCall reg_call; + if (en.is_flags) { + reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_flags_register_static")); + } else { + reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_enum_register_static")); + } + + reg_call.add_argument (new CCodeConstant ("\"%s\"".printf (en.get_cname()))); + reg_call.add_argument (new CCodeIdentifier ("_%s".printf (en.get_cname ()))); + + type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (type_id_name), reg_call))); + + var cond = new CCodeFunctionCall (new CCodeIdentifier ("G_UNLIKELY")); + cond.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (type_id_name), new CCodeConstant ("0"))); + var cif = new CCodeIfStatement (cond, type_init); + regblock.add_statement (cif); + + regblock.add_statement (new CCodeReturnStatement (new CCodeConstant (type_id_name))); + + decl_frag.append (regfun.copy ()); + regfun.block = regblock; + def_frag.append (regfun); + } public override void visit_enum_value (EnumValue! ev) { diff --git a/gobject/valaccodegeneratorinterface.vala b/gobject/valaccodegeneratorinterface.vala index 89d33db..e358e47 100644 --- a/gobject/valaccodegeneratorinterface.vala +++ b/gobject/valaccodegeneratorinterface.vala @@ -104,8 +104,19 @@ public class Vala.CCodeGenerator { } else if (prop.type_reference.data_type == string_type.data_type) { cspec.call = new CCodeIdentifier ("g_param_spec_string"); cspec.add_argument (new CCodeConstant ("NULL")); - } else if (prop.type_reference.data_type == int_type.data_type - || prop.type_reference.data_type is Enum) { + } else if (prop.type_reference.data_type is Enum) { + if ((prop.type_reference.data_type as Enum).is_flags) { + cspec.call = new CCodeIdentifier ("g_param_spec_flags"); + } else { + cspec.call = new CCodeIdentifier ("g_param_spec_enum"); + } + cspec.add_argument (new CCodeIdentifier (prop.type_reference.data_type.get_upper_case_cname ("TYPE_"))); + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant (prop.type_reference.data_type.get_default_value ())); + } + } else if (prop.type_reference.data_type == int_type.data_type) { cspec.call = new CCodeIdentifier ("g_param_spec_int"); cspec.add_argument (new CCodeConstant ("G_MININT")); cspec.add_argument (new CCodeConstant ("G_MAXINT")); diff --git a/vala/valaenum.vala b/vala/valaenum.vala index d70a52b..5ca9b04 100644 --- a/vala/valaenum.vala +++ b/vala/valaenum.vala @@ -38,6 +38,9 @@ public class Vala.Enum : Typesymbol { private string cprefix; private string lower_case_cprefix; private string lower_case_csuffix; + private bool with_type = true; + private bool has_type_id; + private string type_id; /** * Creates a new enum. @@ -140,8 +143,8 @@ public class Vala.Enum : Typesymbol { return "%s%s%s".printf (parent_symbol.get_lower_case_cprefix (), infix, get_lower_case_csuffix ()); } - public override string get_upper_case_cname (string infix) { - return get_lower_case_cname (null).up (); + public override string get_upper_case_cname (string infix = null) { + return get_lower_case_cname (infix).up (); } public override bool is_reference_type () { @@ -160,7 +163,7 @@ public class Vala.Enum : Typesymbol { */ public string! get_cprefix () { if (cprefix == null) { - cprefix = "%s_".printf (get_upper_case_cname (null)); + cprefix = "%s_".printf (get_upper_case_cname ()); } return cprefix; } @@ -191,6 +194,12 @@ public class Vala.Enum : Typesymbol { add_cheader_filename (filename); } } + if (a.has_argument ("has_type_id")) { + has_type_id = a.get_bool ("has_type_id"); + } + if (a.has_argument ("type_id")) { + type_id = a.get_string ("type_id"); + } } /** @@ -202,31 +211,76 @@ public class Vala.Enum : Typesymbol { process_ccode_attribute (a); } else if (a.name == "Flags") { is_flags = true; + } else if (a.name == "NoType") { + with_type = false; } } } + private bool get_has_type_id () { + return has_type_id || with_type; + } + public override string get_type_id () { - // FIXME: use GType-registered enums - return "G_TYPE_INT"; + if (type_id == null) { + if (get_has_type_id ()) { + type_id = get_upper_case_cname ("TYPE_"); + } else { + type_id = "G_TYPE_INT"; + } + } + + return type_id; } public override string get_marshaller_type_name () { - // FIXME: use GType-registered enums + if (get_has_type_id ()) { + if (is_flags) { + return "FLAGS"; + } else { + return "ENUM"; + } + } else { return "INT"; } + } public override string get_get_value_function () { - // FIXME: use GType-registered enums + if (get_has_type_id ()) { + if (is_flags) { + return "g_value_get_flags"; + } else { + return "g_value_get_enum"; + } + } else { return "g_value_get_int"; } + } public override string get_set_value_function () { - // FIXME: use GType-registered enums + if (get_has_type_id ()) { + if (is_flags) { + return "g_value_set_flags"; + } else { + return "g_value_set_enum"; + } + } else { return "g_value_set_int"; } + } public override string get_default_value () { + if (values.size > 0) { + return values.get (0).get_cname (); + } else { return "0"; } + } + + public override bool is_subtype_of (Typesymbol! t) { + // FIXME: have genum... + if (this == t) { + return true; + } + } } diff --git a/vala/valaenumvalue.vala b/vala/valaenumvalue.vala index fde0561..a83539c 100644 --- a/vala/valaenumvalue.vala +++ b/vala/valaenumvalue.vala @@ -52,6 +52,33 @@ public class Vala.EnumValue : Symbol { public EnumValue.with_value (construct string! name, construct Expression value) { } + /** + * Returns the string literal of this signal to be used in C code. + * (FIXME: from vlaasignal.vala) + * + * @return string literal to be used in C code + */ + public CCodeConstant! get_canonical_cconstant () { + var str = new String ("\""); + + string i = name; + + while (i.len () > 0) { + unichar c = i.get_char (); + if (c == '_') { + str.append_c ('-'); + } else { + str.append_unichar (c.tolower ()); + } + + i = i.next_char (); + } + + str.append_c ('"'); + + return new CCodeConstant (str.str); + } + public override void accept (CodeVisitor! visitor) { visitor.visit_enum_value (this);