2007-04-30 Jürg Billeter <j@bitron.ch>
+ * vala/parser.y, vala/valasymbolbuilder.vala,
+ vala/valaattributeprocessor.vala, vala/valasemanticanalyzer.vala,
+ vala/valacodegenerator.vala, vala/valainterfacewriter.vala,
+ vala/valaflags.vala: add basic support for flags, fixes bug 434511
+
+2007-04-30 Jürg Billeter <j@bitron.ch>
+
* vala/valasemanticanalyzer.vala: check that void return values are not
used, fixes bug 434503
%type <list> enum_member_declarations
%type <enum_value> enum_member_declaration
%type <flags> flags_declaration
+%type <list> flags_body
+%type <list> opt_flags_member_declarations
+%type <list> flags_member_declarations
+%type <flags_value> flags_member_declaration
%type <callback> callback_declaration
%type <constant> constant_declaration
%type <field> field_declaration
name = $6;
}
+ GList *l;
ValaSourceReference *src = src_com(@5, $1);
$$ = vala_flags_new (name, src);
g_free (name);
g_object_unref (src);
+
+ VALA_CODE_NODE($$)->attributes = $2;
+
+ if ($3 != 0) {
+ VALA_DATA_TYPE($$)->access = $3;
+ }
+ for (l = $7; l != NULL; l = l->next) {
+ vala_flags_add_value ($$, l->data);
+ g_object_unref (l->data);
+ }
}
;
flags_body
: OPEN_BRACE opt_flags_member_declarations CLOSE_BRACE
+ {
+ $$ = $2;
+ }
;
opt_flags_member_declarations
: /* empty */
- | flags_member_declarations
+ {
+ $$ = NULL;
+ }
+ | flags_member_declarations opt_comma
;
flags_member_declarations
: flags_member_declaration
+ {
+ $$ = g_list_append (NULL, $1);
+ }
| flags_member_declarations COMMA flags_member_declaration
+ {
+ $$ = g_list_append ($1, $3);
+ }
;
flags_member_declaration
: opt_attributes identifier
+ {
+ $$ = vala_flags_value_new ($2);
+ g_free ($2);
+ }
+ | opt_attributes identifier ASSIGN expression
+ {
+ $$ = vala_flags_value_new_with_value ($2, $4);
+ g_free ($2);
+ g_object_unref ($4);
+ }
;
callback_declaration
en.process_attributes ();
}
+ public override void visit_begin_flags (Flags! fl) {
+ fl.process_attributes ();
+ }
+
public override void visit_begin_method (Method! m) {
m.process_attributes ();
}
source_type_member_definition.append (base_init);
}
-
+
public override void visit_begin_enum (Enum! en) {
cenum = new CCodeEnum (en.get_cname ());
cenum.add_value (ev.get_cname (), val);
}
+ public override void visit_begin_flags (Flags! fl) {
+ cenum = new CCodeEnum (fl.get_cname ());
+
+ if (fl.source_reference.comment != null) {
+ header_type_definition.append (new CCodeComment (fl.source_reference.comment));
+ }
+ header_type_definition.append (cenum);
+ }
+
+ public override void visit_flags_value (FlagsValue! fv) {
+ string val;
+ if (fv.value is LiteralExpression) {
+ var lit = ((LiteralExpression) fv.value).literal;
+ if (lit is IntegerLiteral) {
+ val = ((IntegerLiteral) lit).value;
+ }
+ }
+ cenum.add_value (fv.get_cname (), val);
+ }
+
public override void visit_end_callback (Callback! cb) {
var cfundecl = new CCodeFunctionDeclarator (cb.get_cname ());
foreach (FormalParameter param in cb.get_parameters ()) {
public override string get_default_value () {
return "0";
- }
+ }
}
/* valaflags.vala
*
- * Copyright (C) 2006 Jürg Billeter
+ * Copyright (C) 2006-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
* Represents a flags declaration in the source code.
*/
public class Vala.Flags : DataType {
- List<FlagsValue> values;
- string cname;
+ private List<FlagsValue> values;
+ private string cname;
+ private string cprefix;
/**
* Creates a new flags.
* @param source reference to source code
* @return newly created flags
*/
- public Flags (string! _name, SourceReference source) {
- name = _name;
- source_reference = source;
+ public Flags (construct string! name, construct SourceReference source_reference = null) {
}
-
+
/**
* Appends the specified flags value to the list of values.
*
public void add_value (FlagsValue! value) {
values.append (value);
}
-
+
public override void accept (CodeVisitor! visitor) {
visitor.visit_begin_flags (this);
-
+
foreach (FlagsValue value in values) {
value.accept (visitor);
}
}
return cname;
}
-
+
public override ref string get_upper_case_cname (string infix) {
return "%s%s".printf (@namespace.get_lower_case_cprefix (), Namespace.camel_case_to_lower_case (name)).up ();
}
return false;
}
+ private void set_cname (string! cname) {
+ this.cname = cname;
+ }
+
+ /**
+ * Returns the string to be prepended to the name of members of this
+ * enum when used in C code.
+ *
+ * @return the prefix to be used in C code
+ */
+ public string! get_cprefix () {
+ if (cprefix == null) {
+ cprefix = "%s_".printf (get_upper_case_cname (null));
+ }
+ return cprefix;
+ }
+
+ /**
+ * Sets the string to be prepended to the name of members of this enum
+ * when used in C code.
+ *
+ * @param cprefix the prefix to be used in C code
+ */
+ public void set_cprefix (string! cprefix) {
+ this.cprefix = cprefix;
+ }
+
+ private void process_ccode_attribute (Attribute! a) {
+ if (a.has_argument ("cname")) {
+ set_cname (a.get_string ("cname"));
+ }
+ if (a.has_argument ("cprefix")) {
+ set_cprefix (a.get_string ("cprefix"));
+ }
+ if (a.has_argument ("cheader_filename")) {
+ var val = a.get_string ("cheader_filename");
+ foreach (string filename in val.split (",")) {
+ add_cheader_filename (filename);
+ }
+ }
+ }
+
+ /**
+ * Process all associated attributes.
+ */
+ public void process_attributes () {
+ foreach (Attribute a in attributes) {
+ if (a.name == "CCode") {
+ process_ccode_attribute (a);
+ }
+ }
+ }
+
+ public override string get_type_id () {
+ // FIXME: use GType-registered flags
+ return "G_TYPE_INT";
+ }
+
public override string get_marshaller_type_name () {
return "FLAGS";
}
public override string get_get_value_function () {
return "g_value_get_flags";
}
-
+
public override string get_set_value_function () {
return "g_value_set_flags";
}
internal_scope = true;
return;
}
-
+
write_indent ();
write_string ("[CCode (cprefix = \"%s\")]".printf (en.get_cprefix ()));
-
+
write_indent ();
write_string ("public enum ");
write_identifier (en.name);
internal_scope = false;
return;
}
-
+
write_end_block ();
write_newline ();
}
if (internal_scope) {
return;
}
-
+
write_indent ();
write_identifier (ev.name);
write_string (",");
write_newline ();
}
+ public override void visit_begin_flags (Flags! fl) {
+ if (fl.access == MemberAccessibility.PRIVATE) {
+ internal_scope = true;
+ return;
+ }
+
+ write_indent ();
+ write_string ("[CCode (cprefix = \"%s\")]".printf (fl.get_cprefix ()));
+
+ write_indent ();
+ write_string ("public flags ");
+ write_identifier (fl.name);
+ write_begin_block ();
+ }
+
+ public override void visit_end_flags (Flags! fl) {
+ if (fl.access == MemberAccessibility.PRIVATE) {
+ internal_scope = false;
+ return;
+ }
+
+ write_end_block ();
+ write_newline ();
+ }
+
+ public override void visit_flags_value (FlagsValue! fv) {
+ if (internal_scope) {
+ return;
+ }
+
+ write_indent ();
+ write_identifier (fv.name);
+ write_string (",");
+ write_newline ();
+ }
+
public override void visit_constant (Constant! c) {
if (internal_scope) {
return;
} else if (node is VariableDeclarator) {
var decl = (VariableDeclarator) node;
return decl.type_reference;
- } else if (node is EnumValue) {
+ } else if (node is EnumValue || node is FlagsValue) {
var type = new TypeReference ();
type.data_type = (DataType) node.symbol.parent_symbol.node;
return type;
current_symbol = current_symbol.parent_symbol;
}
-
+
public override void visit_begin_enum (Enum! en) {
if (add_symbol (en.name, en) == null) {
return;
}
-
+
current_symbol = en.symbol;
}
-
+
public override void visit_end_enum (Enum! en) {
if (en.error) {
/* skip enums with errors */
return;
}
-
+
current_symbol = current_symbol.parent_symbol;
}
ev.symbol = new Symbol (ev);
current_symbol.add (ev.name, ev.symbol);
}
-
+
+ public override void visit_begin_flags (Flags! fl) {
+ if (add_symbol (fl.name, fl) == null) {
+ return;
+ }
+
+ current_symbol = fl.symbol;
+ }
+
+ public override void visit_end_flags (Flags! fl) {
+ if (fl.error) {
+ /* skip flags with errors */
+ return;
+ }
+
+ current_symbol = current_symbol.parent_symbol;
+ }
+
+ public override void visit_flags_value (FlagsValue! fv) {
+ fv.symbol = new Symbol (fv);
+ current_symbol.add (fv.name, fv.symbol);
+ }
+
public override void visit_begin_callback (Callback! cb) {
if (add_symbol (cb.name, cb) == null) {
return;