+2006-08-09 Jürg Billeter <j@bitron.ch>
+
+ * vala/parser.y: adapt to Vala.Signal change
+ * vala/valaattributeprocessor.vala: process signal attributes
+ * vala/valacodegenerator.vala: manage memory of element access
+ expressions, mark get_property and set_property functions static,
+ support signal emitter functions
+ * vala/valacodecontext.vala: use get_cinclude_filename method
+ * vala/valainterfacewriter.vala: use C header filename of namespace,
+ support signals, support NoAccessorMethod attribute
+ * vala/valadatatype.vala: add default arguments
+ * vala/valaenum.vala: make set_cprefix method public
+ * vala/valanamespace.vala: add get_cheader_filename and
+ set_cheader_filename methods
+ * vala/valasignal.vala: add has_emitter property, add process_attributes
+ method
+ * vala/valasourcefile.vala: add get_cinclude_filename method
+ * compiler/valacompiler.vala: adapt to SourceFile changes
+
2006-08-05 Jürg Billeter <j@bitron.ch>
* vala/valaparser.vala: only parse .vala source files
return false;
}
- context.add_source_file (new SourceFile (package_path, true));
+ context.add_source_file (new SourceFile (context, package_path, true));
return true;
}
foreach (string source in sources) {
if (File.test (source, FileTest.EXISTS)) {
- context.add_source_file (new SourceFile (source));
+ context.add_source_file (new SourceFile (context, source));
} else {
Report.error (null, "%s not found".printf (source));
}
$$ = vala_signal_new ($6, $5, src);
g_object_unref (src);
if ($3 != 0) {
- $$->access = $3;
+ vala_signal_set_access ($$, $3);
}
VALA_CODE_NODE($$)->attributes = $2;
public override void visit_field (Field! f) {
f.process_attributes ();
}
+
+ public override void visit_begin_signal (Signal! sig) {
+ sig.process_attributes ();
+ }
}
/* in the same cycle */
if (!file2.is_cycle_head) {
/* include header of cycle head */
- file2.add_header_internal_include (file2.cycle.head.get_cheader_filename ());
+ file2.add_header_internal_include (file2.cycle.head.get_cinclude_filename ());
}
} else {
/* we can just include the headers if they are not in a cycle or not in the same cycle as the current file */
- file2.add_header_internal_include (dep.get_cheader_filename ());
+ file2.add_header_internal_include (dep.get_cinclude_filename ());
}
}
}
}
private ref CCodeIncludeDirective get_internal_include (string! filename) {
- if (context.library != null) {
- return new CCodeIncludeDirective ("%s/%s".printf (context.library, filename));
- } else {
- return new CCodeIncludeDirective (filename, true);
- }
+ return new CCodeIncludeDirective (filename, context.library == null);
}
public override void visit_begin_source_file (SourceFile! source_file) {
private void add_get_property_function (Class! cl) {
var get_prop = new CCodeFunction ("%s_get_property".printf (cl.get_lower_case_cname (null)), "void");
+ get_prop.modifiers = CCodeModifiers.STATIC;
get_prop.add_parameter (new CCodeFormalParameter ("object", "GObject *"));
get_prop.add_parameter (new CCodeFormalParameter ("property_id", "guint"));
get_prop.add_parameter (new CCodeFormalParameter ("value", "GValue *"));
private void add_set_property_function (Class! cl) {
var set_prop = new CCodeFunction ("%s_set_property".printf (cl.get_lower_case_cname (null)), "void");
+ set_prop.modifiers = CCodeModifiers.STATIC;
set_prop.add_parameter (new CCodeFormalParameter ("object", "GObject *"));
set_prop.add_parameter (new CCodeFormalParameter ("property_id", "guint"));
set_prop.add_parameter (new CCodeFormalParameter ("value", "const GValue *"));
ref CCodeExpression typed_pub_inst = pub_inst;
/* cast if necessary */
- if (prop.symbol.parent_symbol.node != base_type) {
- var ccast = new CCodeFunctionCall (new CCodeIdentifier (((DataType) prop.symbol.parent_symbol.node).get_upper_case_cname (null)));
+ if (cl != base_type) {
+ var ccast = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
ccast.add_argument (pub_inst);
typed_pub_inst = ccast;
}
}
} else if (expr.symbol_reference.node is Signal) {
var sig = (Signal) expr.symbol_reference.node;
+ var cl = (Class) sig.symbol.parent_symbol.node;
- var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
+ if (sig.has_emitter) {
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_%s".printf (cl.get_lower_case_cname (null), sig.name)));
+
+ /* explicitly use strong reference as ccast
+ * gets unrefed at the end of the inner block
+ */
+ ref CCodeExpression typed_pub_inst = pub_inst;
- var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT"));
- ccast.add_argument (pub_inst);
- ccall.add_argument (ccast);
+ /* cast if necessary */
+ if (cl != base_type) {
+ var ccast = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
+ ccast.add_argument (pub_inst);
+ typed_pub_inst = ccast;
+ }
- ccall.add_argument (new CCodeConstant ("\"%s\"".printf (sig.name)));
-
- expr.ccodenode = ccall;
+ ccall.add_argument (typed_pub_inst);
+ expr.ccodenode = ccall;
+ } else {
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
+
+ var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT"));
+ ccast.add_argument (pub_inst);
+ ccall.add_argument (ccast);
+
+ ccall.add_argument (sig.get_canonical_cconstant ());
+
+ expr.ccodenode = ccall;
+ }
}
}
public override void visit_element_access (ElementAccess! expr)
{
expr.ccodenode = new CCodeElementAccess ((CCodeExpression) expr.container.ccodenode, (CCodeExpression) expr.index.ccodenode);
+
+ visit_expression (expr);
}
public override void visit_postfix_expression (PostfixExpression! expr) {
* name or null
* @return the upper case name to be used in C code
*/
- public abstract ref string get_upper_case_cname (string infix);
+ public abstract ref string get_upper_case_cname (string infix = null);
/**
* Returns the C name of this data type in lower case. Words are
* name or null
* @return the lower case name to be used in C code
*/
- public abstract ref string get_lower_case_cname (string infix);
+ public abstract ref string get_lower_case_cname (string infix = null);
/**
* Returns a list of C header filenames users of this data type must
return cprefix;
}
- private void set_cprefix (string! 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;
}
stream = null;
}
- public override void visit_begin_source_file (SourceFile! source_file) {
- current_cheader_filename = source_file.get_cheader_filename ();
-
- if (context.library != null) {
- current_cheader_filename = "%s/%s".printf (context.library, current_cheader_filename);
- }
- }
-
public override void visit_begin_namespace (Namespace! ns) {
if (ns.name == null) {
return;
}
+
+ current_cheader_filename = ns.get_cheader_filename ();
write_indent ();
write_string ("[CCode (cheader_filename = \"%s\")]".printf (current_cheader_filename));
}
write_indent ();
+ write_string ("[CCode (cprefix = \"%s\")]".printf (en.get_cprefix ()));
+
+ write_indent ();
write_string ("public enum ");
write_identifier (en.name);
write_begin_block ();
}
write_string (" ");
+ if (f.name == "callback" || f.name == "flags" ||
+ f.name == "out") {
+ write_string ("@");
+ }
write_identifier (f.name);
write_string (";");
write_newline ();
return;
}
+ if (prop.no_accessor_method) {
+ write_indent ();
+ write_string ("[NoAccessorMethod ()]");
+ }
+
write_indent ();
write_string ("public ");
if (!prop.type_reference.takes_ownership) {
write_newline ();
}
+ public override void visit_begin_signal (Signal! sig) {
+ if (internal_scope || sig.access != MemberAccessibility.PUBLIC) {
+ return;
+ }
+
+ if (sig.has_emitter) {
+ write_indent ();
+ write_string ("[HasEmitter ()]");
+ }
+
+ write_indent ();
+ write_string ("public signal ");
+
+ var type = sig.return_type.data_type;
+ if (type == null) {
+ write_string ("void");
+ } else {
+ if (sig.return_type.transfers_ownership) {
+ write_string ("ref ");
+ }
+ write_string (sig.return_type.data_type.symbol.get_full_name ());
+ if (sig.return_type.non_null) {
+ write_string ("!");
+ }
+ }
+
+ write_string (" ");
+ write_identifier (sig.name);
+
+ write_string (" ");
+
+ write_params (sig.get_parameters ());
+
+ write_string (";");
+
+ write_newline ();
+ }
+
private void write_indent () {
int i;
*/
public ref List<string> get_cheader_filenames () {
if (cheader_filenames == null) {
- cheader_filenames.append (source_reference.file.get_cheader_filename ());
+ cheader_filenames.append (source_reference.file.get_cinclude_filename ());
}
return cheader_filenames.copy ();
}
+ /**
+ * Returns the C header filename of this namespace.
+ *
+ * @return header filename
+ */
+ public ref string get_cheader_filename () {
+ var s = new String ();
+ bool first = true;
+ foreach (string cheader_filename in get_cheader_filenames ()) {
+ if (first) {
+ first = false;
+ } else {
+ s.append_c (',');
+ }
+ s.append (cheader_filename);
+ }
+ return s.str;
+ }
+
+ /**
+ * Sets the C header filename of this namespace to the specified
+ * filename.
+ *
+ * @param cheader_filename header filename
+ */
+ public void set_cheader_filename (string! cheader_filename) {
+ cheader_filenames = null;
+ cheader_filenames.append (cheader_filename);
+ }
+
private void process_ccode_attribute (Attribute! a) {
foreach (NamedArgument arg in a.args) {
if (arg.name == "cprefix") {
* Specifies the accessibility of the signal. Currently only public
* accessibility is supported for signals.
*/
- public MemberAccessibility access;
+ public MemberAccessibility access { get; set; }
+
+ /**
+ * Specifies whether this signal has an emitter wrapper function.
+ */
+ public bool has_emitter { get; set; }
private List<FormalParameter> parameters;
private Callback generated_callback;
visitor.visit_end_signal (this);
}
+
+ /**
+ * Process all associated attributes.
+ */
+ public void process_attributes () {
+ foreach (Attribute a in attributes) {
+ if (a.name == "HasEmitter") {
+ has_emitter = true;
+ }
+ }
+ }
}
*/
public int mark { get; set; }
+ /**
+ * The context this source file belongs to.
+ */
+ public weak CodeContext context { get; set; }
+
private List<NamespaceReference> using_directives;
private Namespace global_namespace;
private List<Namespace> namespaces;
private string cheader_filename = null;
-
private string csource_filename = null;
+ private string cinclude_filename = null;
private List<weak string> header_external_includes;
private List<weak string> header_internal_includes;
* @param pkg true if this is a VAPI package file
* @return newly created source file
*/
- public construct (string! _filename, bool _pkg = false) {
+ public construct (CodeContext! _context, string! _filename, bool _pkg = false) {
+ context = _context;
filename = _filename;
pkg = _pkg;
}
}
/**
+ * Returns the filename to use when including the generated C header
+ * file.
+ *
+ * @return C header filename to include
+ */
+ public string! get_cinclude_filename () {
+ if (cinclude_filename == null) {
+ var basename = filename.ndup ((uint) (filename.len () - ".vala".len ()));
+ if (context.library != null) {
+ cinclude_filename = "%s/%s.h".printf (context.library, basename);
+ } else {
+ cinclude_filename = "%s.h".printf (basename);
+ }
+ }
+ return cinclude_filename;
+ }
+
+ /**
* Adds the specified symbol to the list of symbols code in this source
* file depends on.
*