+2006-07-06 Jürg Billeter <j@bitron.ch>
+
+ * vala/parser.y, vala/valacodevisitor.vala, vala/valasymbolbuilder.vala,
+ vala/valasemanticanalyzer.vala, vala/valamemorymanager.vala,
+ vala/valacodegenerator.vala, vala/valatypereference.vala, vala/vala.h,
+ vala/Makefile.am: merge SimpleName into MemberAccess
+ * vala/valasymbolresolver.vala, vala/valainterfacewriter.vala: adapt to
+ change in Class
+ * vala/valasemanticanalyzer.vala: support non-static lambda expressions
+ and lambda expressions without return values
+ * vala/valacodegenerator.vala: support conditional expressions, support
+ lambda expressions as signal handlers, support read-only and
+ write-only properties
+ * vala/valacodevisitor.vala, vala/valamemorymanager.vala,
+ vala/valaassignment.vala: visit at beginning and end
+ * vala/valacallback.vala: add instance property
+ * vala/valasignal.vala: add get_callback method
+ * vala/valacastexpression.vala, vala/valacharacterliteral.vala,
+ vala/valaclass.vala, vala/valamemberaccess.vala, vala/valasignal.vala:
+ add interface documentation, use implicit namespace specification
+
2006-07-05 Jürg Billeter <j@bitron.ch>
* vala/parser.y: don't pass parameter list to lambda expression
valasignal.c \
valasignal.h \
valasignal.vala \
- valasimplename.c \
- valasimplename.h \
- valasimplename.vala \
valasourcefile.c \
valasourcefile.h \
valasourcefile.vala \
: IDENTIFIER
{
ValaSourceReference *src = src(@1);
- $$ = VALA_EXPRESSION (vala_simple_name_new ($1, src));
+ $$ = VALA_EXPRESSION (vala_member_access_new (NULL, $1, src));
g_free ($1);
g_object_unref (src);
}
#include <vala/valapropertyaccessor.h>
#include <vala/valareturnstatement.h>
#include <vala/valasignal.h>
-#include <vala/valasimplename.h>
#include <vala/valasourcefile.h>
#include <vala/valasourcereference.h>
#include <vala/valastringliteral.h>
public override void accept (CodeVisitor! visitor) {
left.accept (visitor);
+
+ visitor.visit_begin_assignment (this);
+
right.accept (visitor);
- visitor.visit_assignment (this);
+ visitor.visit_end_assignment (this);
}
}
*/
public TypeReference return_type { get; set; }
+ /**
+ * Specifies whether callback supports calling instance methods.
+ * The reference to the object instance will be appended to the end of
+ * the argument list in the generated C code.
+ */
+ public bool instance { get; set; }
+
private List<FormalParameter> parameters;
private string cname;
using GLib;
-namespace Vala {
- public class CastExpression : Expression {
- public Expression inner { get; construct; }
- public TypeReference type_reference { get; construct; }
+/**
+ * Represents a type cast in the source code.
+ */
+public class Vala.CastExpression : Expression {
+ /**
+ * The expression to be casted.
+ */
+ public Expression! inner { get; set construct; }
+
+ /**
+ * The target type.
+ */
+ public TypeReference! type_reference { get; set construct; }
- public static ref CastExpression new (Expression inner, TypeReference type, SourceReference source) {
- return (new CastExpression (inner = inner, type_reference = type, source_reference = source));
- }
-
- public override void accept (CodeVisitor visitor) {
- inner.accept (visitor);
- type_reference.accept (visitor);
+ /**
+ * Creates a new cast expression.
+ *
+ * @param inner expression to be casted
+ * @param type target type
+ * @return newly created cast expression
+ */
+ public static ref CastExpression! new (Expression! inner, TypeReference! type, SourceReference source) {
+ return (new CastExpression (inner = inner, type_reference = type, source_reference = source));
+ }
+
+ public override void accept (CodeVisitor visitor) {
+ inner.accept (visitor);
+ type_reference.accept (visitor);
- visitor.visit_cast_expression (this);
- }
+ visitor.visit_cast_expression (this);
}
}
using GLib;
-namespace Vala {
- public class CharacterLiteral : Literal {
- public string value { get; set; }
+/**
+ * Represents a single literal character.
+ */
+public class Vala.CharacterLiteral : Literal {
+ /**
+ * The literal value.
+ */
+ public string! value { get; set construct; }
- public static ref CharacterLiteral! new (string c, SourceReference source) {
- return (new CharacterLiteral (value = c, source_reference = source));
- }
-
- public override void accept (CodeVisitor! visitor) {
- visitor.visit_character_literal (this);
- }
+ /**
+ * Creates a new character literal.
+ *
+ * @param c character
+ * @param source reference to source code
+ * @return newly created character literal
+ */
+ public static ref CharacterLiteral! new (string! c, SourceReference source) {
+ return (new CharacterLiteral (value = c, source_reference = source));
+ }
+
+ public override void accept (CodeVisitor! visitor) {
+ visitor.visit_character_literal (this);
}
}
using GLib;
-namespace Vala {
- public class Class : DataType {
- List<string> type_parameters;
- public List<TypeReference> base_types;
- public Class base_class;
- public bool is_abstract;
-
- List<Constant> constants;
- List<Field> fields;
- List<Method> methods;
- List<Property> properties;
- List<Signal> signals;
-
- public Constructor constructor { get; set; }
- public Destructor destructor { get; set; }
-
- public string cname;
- public string lower_case_csuffix;
- public bool has_private_fields;
-
- public static ref Class new (string! name, SourceReference source) {
- return (new Class (name = name, source_reference = source));
+/**
+ * Represents a class declaration in the source code.
+ */
+public class Vala.Class : DataType {
+ /**
+ * Specifies the base class.
+ */
+ public Class base_class { get; set; }
+
+ /**
+ * Specifies whether this class is abstract. Abstract classes may not be
+ * instantiated.
+ */
+ public bool is_abstract { get; set; }
+
+ /**
+ * Specifies whether this class has private fields.
+ */
+ public bool has_private_fields {
+ get {
+ return _has_private_fields;
}
-
- public void add_base_type (TypeReference! type) {
- base_types.append (type);
+ set {
+ /* FIXME: dummy accessor due to vala compiler bug */
}
+ }
+
+ private string cname;
+ private string lower_case_csuffix;
+
+ private bool _has_private_fields;
+
+ List<string> type_parameters;
+
+ private List<TypeReference> base_types;
+
+ List<Constant> constants;
+ List<Field> fields;
+ List<Method> methods;
+ List<Property> properties;
+ List<Signal> signals;
+
+ /**
+ * Specifies the instance constructor.
+ */
+ public Constructor constructor { get; set; }
+
+ /**
+ * Specifies the instance destructor.
+ */
+ public Destructor destructor { get; set; }
+
+ /**
+ * Creates a new class.
+ *
+ * @param name type name
+ * @param source reference to source code
+ * @return newly created class
+ */
+ public static ref Class! new (string! name, SourceReference source) {
+ return (new Class (name = name, source_reference = source));
+ }
- public void add_type_parameter (TypeParameter! p) {
- type_parameters.append (p);
- p.type = this;
+ /**
+ * Adds the specified class or interface to the list of base types of
+ * this class.
+ *
+ * @param type a class or interface reference
+ */
+ public void add_base_type (TypeReference! type) {
+ base_types.append (type);
+ }
+
+ /**
+ * Returns a copy of the base type list.
+ *
+ * @return list of base types
+ */
+ public ref List<TypeReference> get_base_types () {
+ return base_types.copy ();
+ }
+
+ /**
+ * Appends the specified parameter to the list of type parameters.
+ *
+ * @param p a type parameter
+ */
+ public void add_type_parameter (TypeParameter! p) {
+ type_parameters.append (p);
+ p.type = this;
+ }
+
+ /**
+ * Adds the specified constant as a member to this class.
+ *
+ * @param c a constant
+ */
+ public void add_constant (Constant! c) {
+ constants.append (c);
+ }
+
+ /**
+ * Adds the specified field as a member to this class.
+ *
+ * @param f a field
+ */
+ public void add_field (Field! f) {
+ fields.append (f);
+ if (f.access == MemberAccessibility.PRIVATE) {
+ _has_private_fields = true;
}
+ }
+
+ /**
+ * Returns a copy of the list of fields.
+ *
+ * @return list of fields
+ */
+ public ref List<Field> get_fields () {
+ return fields.copy ();
+ }
+
+ /**
+ * Adds the specified method as a member to this class.
+ *
+ * @param m a method
+ */
+ public void add_method (Method! m) {
+ methods.append (m);
+ }
+
+ /**
+ * Returns a copy of the list of methods.
+ *
+ * @return list of methods
+ */
+ public ref List<Method> get_methods () {
+ return methods.copy ();
+ }
+
+ /**
+ * Adds the specified property as a member to this class.
+ *
+ * @param prop a property
+ */
+ public void add_property (Property! prop) {
+ properties.append (prop);
- public void add_constant (Constant! c) {
- constants.append (c);
+ if (prop.set_accessor != null && prop.set_accessor.body == null) {
+ /* automatic property accessor body generation */
+ var f = new Field (name = "_%s".printf (prop.name), type_reference = prop.type_reference, source_reference = prop.source_reference);
+ f.access = MemberAccessibility.PRIVATE;
+ add_field (f);
}
+ }
+
+ /**
+ * Returns a copy of the list of properties.
+ *
+ * @return list of properties
+ */
+ public ref List<Property> get_properties () {
+ return properties.copy ();
+ }
+
+ /**
+ * Adds the specified signal as a member to this class.
+ *
+ * @param sig a signal
+ */
+ public void add_signal (Signal! sig) {
+ signals.append (sig);
+ }
+
+ /**
+ * Returns a copy of the list of signals.
+ *
+ * @return list of signals
+ */
+ public ref List<Signal> get_signals () {
+ return signals.copy ();
+ }
+
+ public override void accept (CodeVisitor! visitor) {
+ visitor.visit_begin_class (this);
- public void add_field (Field! f) {
- fields.append (f);
- if (f.access == MemberAccessibility.PRIVATE) {
- has_private_fields = true;
- }
+ foreach (TypeReference type in base_types) {
+ type.accept (visitor);
}
-
- public ref List<Field> get_fields () {
- return fields.copy ();
+
+ foreach (TypeParameter p in type_parameters) {
+ p.accept (visitor);
}
- public void add_method (Method! m) {
- methods.append (m);
+ foreach (Field f in fields) {
+ f.accept (visitor);
}
- public ref List<Method> get_methods () {
- return methods.copy ();
+ foreach (Constant c in constants) {
+ c.accept (visitor);
}
- public void add_property (Property! prop) {
- properties.append (prop);
-
- if (prop.set_accessor != null && prop.set_accessor.body == null) {
- /* automatic property accessor body generation */
- var f = new Field (name = "_%s".printf (prop.name), type_reference = prop.type_reference, source_reference = prop.source_reference);
- f.access = MemberAccessibility.PRIVATE;
- add_field (f);
- }
+ foreach (Method m in methods) {
+ m.accept (visitor);
}
- public ref List<Property> get_properties () {
- return properties.copy ();
+ foreach (Property prop in properties) {
+ prop.accept (visitor);
}
- public void add_signal (Signal! sig) {
- signals.append (sig);
+ foreach (Signal sig in signals) {
+ sig.accept (visitor);
}
- public ref List<Signal> get_signals () {
- return signals.copy ();
+ if (constructor != null) {
+ constructor.accept (visitor);
}
-
- public override void accept (CodeVisitor! visitor) {
- visitor.visit_begin_class (this);
-
- foreach (TypeReference type in base_types) {
- type.accept (visitor);
- }
-
- foreach (TypeParameter p in type_parameters) {
- p.accept (visitor);
- }
-
- foreach (Field f in fields) {
- f.accept (visitor);
- }
-
- foreach (Constant c in constants) {
- c.accept (visitor);
- }
-
- foreach (Method m in methods) {
- m.accept (visitor);
- }
-
- foreach (Property prop in properties) {
- prop.accept (visitor);
- }
-
- foreach (Signal sig in signals) {
- sig.accept (visitor);
- }
-
- if (constructor != null) {
- constructor.accept (visitor);
- }
- if (destructor != null) {
- destructor.accept (visitor);
- }
-
- visitor.visit_end_class (this);
- }
-
- public override string get_cname () {
- if (cname == null) {
- cname = "%s%s".printf (@namespace.get_cprefix (), name);
- }
- return cname;
- }
-
- public void set_cname (string! cname) {
- this.cname = cname;
- }
-
- public string get_lower_case_csuffix () {
- if (lower_case_csuffix == null) {
- lower_case_csuffix = Namespace.camel_case_to_lower_case (name);
- }
- return lower_case_csuffix;
+ if (destructor != null) {
+ destructor.accept (visitor);
}
-
- public void set_lower_case_csuffix (string! csuffix) {
- this.lower_case_csuffix = csuffix;
+
+ visitor.visit_end_class (this);
+ }
+
+ public override string get_cname () {
+ if (cname == null) {
+ cname = "%s%s".printf (@namespace.get_cprefix (), name);
}
-
- public override ref string get_lower_case_cname (string infix) {
- if (infix == null) {
- infix = "";
- }
- return "%s%s%s".printf (@namespace.get_lower_case_cprefix (), infix, get_lower_case_csuffix ());
+ return cname;
+ }
+
+ /**
+ * Sets the name of this class as it is used in C code.
+ *
+ * @param cname the name to be used in C code
+ */
+ public void set_cname (string! cname) {
+ this.cname = cname;
+ }
+
+ /**
+ * Returns the string to be prepended to the name of members of this
+ * class when used in C code.
+ *
+ * @return the suffix to be used in C code
+ */
+ public string get_lower_case_csuffix () {
+ if (lower_case_csuffix == null) {
+ lower_case_csuffix = Namespace.camel_case_to_lower_case (name);
}
-
- public override ref string get_upper_case_cname (string! infix) {
- return get_lower_case_cname (infix).up ();
+ return lower_case_csuffix;
+ }
+
+ /**
+ * Sets the string to be prepended to the name of members of this class
+ * when used in C code.
+ *
+ * @param csuffix the suffix to be used in C code
+ */
+ public void set_lower_case_csuffix (string! csuffix) {
+ this.lower_case_csuffix = csuffix;
+ }
+
+ public override ref string get_lower_case_cname (string infix) {
+ if (infix == null) {
+ infix = "";
}
+ return "%s%s%s".printf (@namespace.get_lower_case_cprefix (), infix, get_lower_case_csuffix ());
+ }
+
+ public override ref string get_upper_case_cname (string! infix) {
+ return get_lower_case_cname (infix).up ();
+ }
- public override bool is_reference_type () {
- return true;
- }
-
- void process_ccode_attribute (Attribute! a) {
- foreach (NamedArgument arg in a.args) {
- if (arg.name == "cname") {
- /* this will already be checked during semantic analysis */
- if (arg.argument is LiteralExpression) {
- var lit = ((LiteralExpression) arg.argument).literal;
- if (lit is StringLiteral) {
- set_cname (((StringLiteral) lit).eval ());
- }
+ public override bool is_reference_type () {
+ return true;
+ }
+
+ private void process_ccode_attribute (Attribute! a) {
+ foreach (NamedArgument arg in a.args) {
+ if (arg.name == "cname") {
+ /* this will already be checked during semantic analysis */
+ if (arg.argument is LiteralExpression) {
+ var lit = ((LiteralExpression) arg.argument).literal;
+ if (lit is StringLiteral) {
+ set_cname (((StringLiteral) lit).eval ());
}
- } else if (arg.name == "cheader_filename") {
- /* this will already be checked during semantic analysis */
- if (arg.argument is LiteralExpression) {
- var lit = ((LiteralExpression) arg.argument).literal;
- if (lit is StringLiteral) {
- var val = ((StringLiteral) lit).eval ();
- foreach (string filename in val.split (",")) {
- add_cheader_filename (filename);
- }
+ }
+ } else if (arg.name == "cheader_filename") {
+ /* this will already be checked during semantic analysis */
+ if (arg.argument is LiteralExpression) {
+ var lit = ((LiteralExpression) arg.argument).literal;
+ if (lit is StringLiteral) {
+ var val = ((StringLiteral) lit).eval ();
+ foreach (string filename in val.split (",")) {
+ add_cheader_filename (filename);
}
}
}
}
}
-
- public void process_attributes () {
- foreach (Attribute a in attributes) {
- if (a.name == "CCode") {
- process_ccode_attribute (a);
- }
+ }
+
+ /**
+ * Process all associated attributes.
+ */
+ public void process_attributes () {
+ foreach (Attribute a in attributes) {
+ if (a.name == "CCode") {
+ process_ccode_attribute (a);
}
}
+ }
- public override bool is_reference_counting () {
- return true;
- }
-
- public override string get_ref_function () {
- return "g_object_ref";
- }
-
- public override string get_unref_function () {
- return "g_object_unref";
- }
+ public override bool is_reference_counting () {
+ return true;
+ }
+
+ public override string get_ref_function () {
+ return "g_object_ref";
+ }
+
+ public override string get_unref_function () {
+ return "g_object_unref";
}
}
var cswitch = new CCodeSwitchStatement (expression = new CCodeIdentifier (name = "property_id"));
var props = cl.get_properties ();
foreach (Property prop in props) {
+ if (prop.get_accessor == null) {
+ continue;
+ }
+
var ccase = new CCodeCaseStatement (expression = new CCodeIdentifier (name = prop.get_upper_case_cname ()));
var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_get_%s".printf (cl.get_lower_case_cname (null), prop.name)));
ccall.add_argument (new CCodeIdentifier (name = "self"));
var cswitch = new CCodeSwitchStatement (expression = new CCodeIdentifier (name = "property_id"));
var props = cl.get_properties ();
foreach (Property prop in props) {
+ if (prop.set_accessor == null) {
+ continue;
+ }
+
var ccase = new CCodeCaseStatement (expression = new CCodeIdentifier (name = prop.get_upper_case_cname ()));
var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name)));
ccall.add_argument (new CCodeIdentifier (name = "self"));
return new CCodeExpressionStatement (expression = ccheck);
}
-
+
+ private DataType find_parent_type (CodeNode node) {
+ var sym = node.symbol;
+ while (sym != null) {
+ if (sym.node is DataType) {
+ return (DataType) sym.node;
+ }
+ sym = sym.parent_symbol;
+ }
+ return null;
+ }
+
public override void visit_end_method (Method! m) {
current_symbol = current_symbol.parent_symbol;
if (m.name == "init") {
-
return;
}
if (m.instance) {
var this_type = new TypeReference ();
- this_type.type = (DataType) m.symbol.parent_symbol.node;
+ this_type.type = find_parent_type (m);
if (!m.is_override) {
var cparam = new CCodeFormalParameter (type_name = this_type.get_cname (), name = "self");
function.add_parameter (cparam);
visit_expression (expr);
}
- private void process_cmember (Expression! expr, CCodeExpression pub_inst, DataType base_type) {
+ private void process_cmember (MemberAccess! expr, CCodeExpression pub_inst, DataType base_type) {
if (expr.symbol_reference.node is Method) {
var m = (Method) expr.symbol_reference.node;
if (!m.is_override) {
}
}
- public override void visit_simple_name (SimpleName! expr) {
- var pub_inst = new CCodeIdentifier (name = "self");
-
- DataType base_type = null;
- if (current_type_symbol != null) {
- /* base type is available if this is a type method */
- base_type = (DataType) current_type_symbol.node;
- }
-
- process_cmember (expr, pub_inst, base_type);
-
- visit_expression (expr);
- }
-
public override void visit_parenthesized_expression (ParenthesizedExpression! expr) {
expr.ccodenode = new CCodeParenthesizedExpression (inner = (CCodeExpression) expr.inner.ccodenode);
}
public override void visit_member_access (MemberAccess! expr) {
- var pub_inst = (CCodeExpression) expr.inner.ccodenode;
+ CCodeExpression pub_inst = null;
DataType base_type = null;
- if (expr.inner.static_type != null) {
- base_type = expr.inner.static_type.type;
+
+ if (expr.inner == null) {
+ pub_inst = new CCodeIdentifier (name = "self");
+
+ if (current_type_symbol != null) {
+ /* base type is available if this is a type method */
+ base_type = (DataType) current_type_symbol.node;
+ }
+ } else {
+ pub_inst = (CCodeExpression) expr.inner.ccodenode;
+
+ if (expr.inner.static_type != null) {
+ base_type = expr.inner.static_type.type;
+ }
}
process_cmember (expr, pub_inst, base_type);
Method m = null;
List<FormalParameter> params;
+
+ if (!(expr.call is MemberAccess)) {
+ expr.error = true;
+ Report.error (expr.source_reference, "unsupported method invocation");
+ return;
+ }
+
+ var ma = (MemberAccess) expr.call;
+
if (expr.call.symbol_reference.node is VariableDeclarator) {
var decl = (VariableDeclarator) expr.call.symbol_reference.node;
var cb = (Callback) decl.type_reference.type;
}
var req_cast = false;
- if (expr.call is SimpleName) {
+ if (ma.inner == null) {
instance = new CCodeIdentifier (name = "self");
/* require casts for overriden and inherited methods */
req_cast = m.is_override || (m.symbol.parent_symbol != current_type_symbol);
- } else if (expr.call is MemberAccess) {
- var ma = (MemberAccess) expr.call;
+ } else {
instance = (CCodeExpression) ma.inner.ccodenode;
/* reqiure casts if the type of the used instance is
* different than the type which declared the method */
req_cast = base_method.symbol.parent_symbol.node != ma.inner.static_type.type;
- } else {
- Report.error (expr.source_reference, "unsupported method invocation");
}
if (req_cast && ((DataType) m.symbol.parent_symbol.node).is_reference_type ()) {
expr.ccodenode = ccheck;
}
+ public override void visit_conditional_expression (ConditionalExpression! expr) {
+ expr.ccodenode = new CCodeConditionalExpression (condition = (CCodeExpression) expr.condition.ccodenode, true_expression = (CCodeExpression) expr.true_expression.ccodenode, false_expression = (CCodeExpression) expr.false_expression.ccodenode);
+ }
+
public override void visit_end_lambda_expression (LambdaExpression! l) {
l.ccodenode = new CCodeIdentifier (name = l.method.get_cname ());
}
- public override void visit_assignment (Assignment! a) {
+ public override void visit_end_assignment (Assignment! a) {
+ var ma = (MemberAccess) a.left;
+
if (a.left.symbol_reference.node is Property) {
var prop = (Property) a.left.symbol_reference.node;
var cl = (Class) prop.symbol.parent_symbol.node;
/* target instance is first argument */
ref CCodeExpression instance;
var req_cast = false;
- if (a.left is SimpleName) {
+
+ if (ma.inner == null) {
instance = new CCodeIdentifier (name = "self");
/* require casts for inherited properties */
req_cast = (prop.symbol.parent_symbol != current_type_symbol);
- } else if (a.left is MemberAccess) {
- var ma = (MemberAccess) a.left;
+ } else {
instance = (CCodeExpression) ma.inner.ccodenode;
/* require casts if the type of the used instance is
* different than the type which declared the property */
req_cast = prop.symbol.parent_symbol.node != ma.inner.static_type.type;
- } else {
- Report.error (a.source_reference, "unexpected lvalue in assignment");
- return;
}
if (req_cast && ((DataType) prop.symbol.parent_symbol.node).is_reference_type ()) {
} else if (a.left.symbol_reference.node is Signal) {
var sig = (Signal) a.left.symbol_reference.node;
+ if (a.right.symbol_reference == null) {
+ a.right.error = true;
+ Report.error (a.right.source_reference, "unsupported expression for signal handler");
+ return;
+ }
+
var m = (Method) a.right.symbol_reference.node;
var connect_func = "g_signal_connect_object";
if (!m.instance) {
var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = connect_func));
- if (a.left is MemberAccess) {
- var expr = (MemberAccess) a.left;
- ccall.add_argument ((CCodeExpression) expr.inner.ccodenode);
- } else if (a.left is SimpleName) {
- ccall.add_argument (new CCodeIdentifier (name = "self"));
+ if (ma.inner != null) {
+ ccall.add_argument ((CCodeExpression) ma.inner.ccodenode);
} else {
- Report.error (a.source_reference, "unexpected lvalue in assignment");
- return;
+ ccall.add_argument (new CCodeIdentifier (name = "self"));
}
ccall.add_argument (new CCodeConstant (name = "\"%s\"".printf (sig.name)));
if (m.instance) {
if (a.right is MemberAccess) {
- var expr = (MemberAccess) a.right;
- ccall.add_argument ((CCodeExpression) expr.inner.ccodenode);
- } else if (a.right is SimpleName) {
+ var right_ma = (MemberAccess) a.right;
+ if (right_ma.inner != null) {
+ ccall.add_argument ((CCodeExpression) right_ma.inner.ccodenode);
+ } else {
+ ccall.add_argument (new CCodeIdentifier (name = "self"));
+ }
+ } else if (a.right is LambdaExpression) {
ccall.add_argument (new CCodeIdentifier (name = "self"));
- } else {
- Report.error (a.source_reference, "unsupported expression for signal handler");
- return;
}
ccall.add_argument (new CCodeConstant (name = "G_CONNECT_SWAPPED"));
}
/**
- * Visit operation called for simple names.
- *
- * @param expr a simple name
- */
- public virtual void visit_simple_name (SimpleName! expr) {
- }
-
- /**
* Visit operation called for parenthesized expressions.
*
* @param expr a parenthesized expression
}
/**
- * Visit operation called for assignments.
+ * Visit operation called at beginning of assignments.
+ *
+ * @param a an assignment
+ */
+ public virtual void visit_begin_assignment (Assignment! a) {
+ }
+
+ /**
+ * Visit operation called at end of assignments.
*
* @param a an assignment
*/
- public virtual void visit_assignment (Assignment! a) {
+ public virtual void visit_end_assignment (Assignment! a) {
}
/**
}
write_string ("class ");
write_identifier (cl.name);
- if (cl.base_types != null) {
+
+ var base_types = cl.get_base_types ();
+ if (base_types != null) {
write_string (" : ");
bool first = true;
- foreach (TypeReference base_type in cl.base_types) {
+ foreach (TypeReference base_type in base_types) {
if (!first) {
write_string (", ");
} else {
using GLib;
-namespace Vala {
- public class MemberAccess : Expression {
- public Expression inner { get; construct; }
- public string member_name { get; construct; }
-
- public static ref MemberAccess new (Expression inner, string member, SourceReference source) {
- return new MemberAccess (inner = inner, member_name = member, source_reference = source);
- }
-
- public override void accept (CodeVisitor visitor) {
+/**
+ * Represents an access to a type member in the source code.
+ */
+public class Vala.MemberAccess : Expression {
+ /**
+ * The parent of the member.
+ */
+ public Expression inner { get; set; }
+
+ /**
+ * The name of the member.
+ */
+ public string! member_name { get; set construct; }
+
+ /**
+ * Creates a new member access expression.
+ *
+ * @param inner parent of the member
+ * @param member member name
+ * @param source reference to source code
+ * @return newly created member access expression
+ */
+ public static ref MemberAccess! new (Expression inner, string! member, SourceReference source) {
+ return new MemberAccess (inner = inner, member_name = member, source_reference = source);
+ }
+
+ public override void accept (CodeVisitor visitor) {
+ if (inner != null) {
inner.accept (visitor);
-
- visitor.visit_member_access (this);
}
+
+ visitor.visit_member_access (this);
}
}
}
public override void visit_member_access (MemberAccess! expr) {
- visit_possibly_leaked_expression (expr.inner);
+ if (expr.inner != null) {
+ visit_possibly_leaked_expression (expr.inner);
+ }
}
public override void visit_end_invocation_expression (InvocationExpression! expr) {
visit_possibly_leaked_expression (expr.right);
}
- public override void visit_assignment (Assignment! a) {
+ public override void visit_end_assignment (Assignment! a) {
if (a.left.symbol_reference.node is Signal) {
} else {
if (a.left.static_type.is_lvalue_ref) {
/* FIXME: also look at interfaces implemented
* by one of the base types
*/
- foreach (TypeReference type in cl.base_types) {
+ foreach (TypeReference type in cl.get_base_types ()) {
if (type.type is Interface) {
var iface = (Interface) type.type;
var sym = iface.symbol.lookup (m.name);
if (decl.initializer != null) {
if (decl.initializer.static_type == null) {
+ if (!(decl.initializer is MemberAccess)) {
+ decl.error = true;
+ Report.error (decl.source_reference, "expression type not allowed as initializer");
+ return;
+ }
+
if (decl.initializer.symbol_reference.node is Method &&
decl.type_reference.type is Callback) {
var m = (Method) decl.initializer.symbol_reference.node;
return result;
}
- public override void visit_simple_name (SimpleName! expr) {
- var sym = current_symbol;
- while (sym != null && expr.symbol_reference == null) {
- expr.symbol_reference = symbol_lookup_inherited (sym, expr.name);
- sym = sym.parent_symbol;
- }
-
- if (expr.symbol_reference == null) {
- foreach (NamespaceReference ns in current_using_directives) {
- var local_sym = ns.namespace_symbol.lookup (expr.name);
- if (local_sym != null) {
- if (expr.symbol_reference != null) {
- Report.error (expr.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (expr.name, expr.symbol_reference.get_full_name (), local_sym.get_full_name ()));
- return;
- }
- expr.symbol_reference = local_sym;
- }
- }
- }
-
- if (expr.symbol_reference == null) {
- Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.name, current_symbol.get_full_name ()));
- return;
- }
-
- current_source_file.add_symbol_dependency (expr.symbol_reference, SourceFileDependencyType.SOURCE);
-
- expr.static_type = get_static_type_for_node (expr.symbol_reference.node);
- }
-
public override void visit_parenthesized_expression (ParenthesizedExpression! expr) {
expr.static_type = expr.inner.static_type;
}
public override void visit_member_access (MemberAccess! expr) {
- if (expr.inner.static_type == null
- && expr.inner.symbol_reference == null) {
- /* if there was an error in the inner expression, skip this check */
- return;
- }
-
- if (expr.inner.static_type == null) {
- if (expr.inner.symbol_reference.node is Namespace || expr.inner.symbol_reference.node is DataType) {
- expr.symbol_reference = expr.inner.symbol_reference.lookup (expr.member_name);
+ Symbol base_symbol = null;
+
+ if (expr.inner == null) {
+ base_symbol = current_symbol;
+
+ var sym = current_symbol;
+ while (sym != null && expr.symbol_reference == null) {
+ expr.symbol_reference = symbol_lookup_inherited (sym, expr.member_name);
+ sym = sym.parent_symbol;
+ }
+
+ if (expr.symbol_reference == null) {
+ foreach (NamespaceReference ns in current_using_directives) {
+ var local_sym = ns.namespace_symbol.lookup (expr.member_name);
+ if (local_sym != null) {
+ if (expr.symbol_reference != null) {
+ Report.error (expr.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (expr.member_name, expr.symbol_reference.get_full_name (), local_sym.get_full_name ()));
+ return;
+ }
+ expr.symbol_reference = local_sym;
+ }
+ }
+ }
+ } else {
+ if (expr.inner.error) {
+ /* if there was an error in the inner expression, skip this check */
+ return;
}
- }
- if (expr.symbol_reference == null && expr.inner.static_type != null) {
- expr.symbol_reference = symbol_lookup_inherited (expr.inner.static_type.type.symbol, expr.member_name);
+ if (expr.inner is MemberAccess) {
+ var base = (MemberAccess) expr.inner;
+ base_symbol = base.symbol_reference;
+ if (base_symbol.node is Namespace ||
+ base_symbol.node is DataType) {
+ expr.symbol_reference = base_symbol.lookup (expr.member_name);
+ }
+ }
+
+ if (expr.symbol_reference == null && expr.inner.static_type != null) {
+ base_symbol = expr.inner.static_type.type.symbol;
+ expr.symbol_reference = symbol_lookup_inherited (base_symbol, expr.member_name);
+ }
}
-
+
if (expr.symbol_reference == null) {
- if (expr.inner.static_type == null) {
- Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, expr.inner.symbol_reference.get_full_name ()));
- } else {
- Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, expr.inner.static_type.to_string ()));
- }
+ expr.error = true;
+ Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, base_symbol.get_full_name ()));
return;
}
}
public override void visit_begin_invocation_expression (InvocationExpression! expr) {
- if (expr.call.symbol_reference == null) {
+ if (expr.call.error) {
/* if method resolving didn't succeed, skip this check */
expr.error = true;
return;
return result;
}
+
+ private Method find_current_method () {
+ var sym = current_symbol;
+ while (sym != null) {
+ if (sym.node is Method) {
+ return (Method) sym.node;
+ }
+ sym = sym.parent_symbol;
+ }
+ return null;
+ }
public override void visit_begin_lambda_expression (LambdaExpression! l) {
if (l.expected_type == null || !(l.expected_type.type is Callback)) {
return;
}
+ var current_method = find_current_method ();
+
var cb = (Callback) l.expected_type.type;
l.method = new Method (name = get_lambda_name (), return_type = cb.return_type);
- l.method.instance = false;
+ l.method.instance = cb.instance && current_method.instance;
l.method.symbol = new Symbol (node = l.method);
l.method.symbol.parent_symbol = current_symbol;
var block = new Block ();
block.symbol = new Symbol (node = block);
block.symbol.parent_symbol = l.method.symbol;
- block.add_statement (new ReturnStatement (return_expression = l.inner));
+ if (l.method.return_type.type != null) {
+ block.add_statement (new ReturnStatement (return_expression = l.inner));
+ } else {
+ block.add_statement (new ExpressionStatement (expression = l.inner));
+ }
l.method.body = block;
+
+ /* lambda expressions should be usable like MemberAccess of a method */
+ l.symbol_reference = l.method.symbol;
}
- public override void visit_assignment (Assignment! a) {
- if (a.left.symbol_reference.node is Signal) {
- var sig = (Signal) a.left.symbol_reference.node;
- } else if (a.left.symbol_reference.node is Property) {
- var prop = (Property) a.left.symbol_reference.node;
- } else if (a.left.symbol_reference.node is VariableDeclarator && a.right.static_type == null) {
- var decl = (VariableDeclarator) a.left.symbol_reference.node;
- if (a.right.symbol_reference.node is Method &&
+ public override void visit_begin_assignment (Assignment! a) {
+ var ma = (MemberAccess) a.left;
+
+ if (ma.symbol_reference.node is Signal) {
+ var sig = (Signal) ma.symbol_reference.node;
+
+ a.right.expected_type = new TypeReference ();
+ a.right.expected_type.type = sig.get_callback ();
+ }
+ }
+
+ public override void visit_end_assignment (Assignment! a) {
+ if (!(a.left is MemberAccess)) {
+ a.error = true;
+ Report.error (a.source_reference, "unsupported lvalue in assignment");
+ return;
+ }
+
+ var ma = (MemberAccess) a.left;
+
+ if (ma.symbol_reference.node is Signal) {
+ var sig = (Signal) ma.symbol_reference.node;
+ } else if (ma.symbol_reference.node is Property) {
+ var prop = (Property) ma.symbol_reference.node;
+ } else if (ma.symbol_reference.node is VariableDeclarator && a.right.static_type == null) {
+ var decl = (VariableDeclarator) ma.symbol_reference.node;
+
+ var right_ma = (MemberAccess) a.right;
+ if (right_ma.symbol_reference.node is Method &&
decl.type_reference.type is Callback) {
- var m = (Method) a.right.symbol_reference.node;
+ var m = (Method) right_ma.symbol_reference.node;
var cb = (Callback) decl.type_reference.type;
/* check whether method matches callback type */
/* lhs doesn't own the value
* promote lhs type if it is a local variable
* error if it's not a local variable */
- if (!(a.left.symbol_reference.node is VariableDeclarator)) {
+ if (!(ma.symbol_reference.node is VariableDeclarator)) {
Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable");
}
using GLib;
-namespace Vala {
- public class Signal : CodeNode {
- public string name { get; construct; }
- public TypeReference return_type { get; construct; }
- public MemberAccessibility access;
- public List<FormalParameter> parameters;
-
- public static ref Signal new (string name, TypeReference return_type, SourceReference source) {
- return (new Signal (name = name, return_type = return_type, source_reference = source));
+/**
+ * Represents an object signal. Signals enable objects to provide notifications.
+ */
+public class Vala.Signal : CodeNode {
+ /**
+ * The symbol name of this signal.
+ */
+ public string! name { get; set construct; }
+
+ /**
+ * The return type of handlers of this signal.
+ */
+ public TypeReference! return_type { get; set construct; }
+
+ /**
+ * Specifies the accessibility of the signal. Currently only public
+ * accessibility is supported for signals.
+ */
+ public MemberAccessibility access;
+
+ private List<FormalParameter> parameters;
+ private Callback generated_callback;
+
+ /**
+ * Creates a new signal.
+ *
+ * @param name signal name
+ * @param return_type signal return type
+ * @param source reference to source code
+ * @return newly created signal
+ */
+ public static ref Signal! new (string! name, TypeReference! return_type, SourceReference source) {
+ return (new Signal (name = name, return_type = return_type, source_reference = source));
+ }
+
+ /**
+ * Append parameter to signal handler.
+ *
+ * @param param a formal parameter
+ */
+ public void add_parameter (FormalParameter! param) {
+ parameters.append (param);
+ }
+
+ /**
+ * Returns copy of list of signal handler parameters.
+ *
+ * @return parameter list
+ */
+ public ref List<FormalParameter> get_parameters () {
+ return parameters.copy ();
+ }
+
+ /**
+ * Returns generated callback to be used for signal handlers.
+ *
+ * @return callback
+ */
+ public Callback! get_callback () {
+ if (generated_callback == null) {
+ generated_callback = new Callback (return_type = return_type, instance = true);
+
+ var sender_param = new FormalParameter (name = "sender");
+ sender_param.type_reference = new TypeReference ();
+ sender_param.type_reference.type = (DataType) symbol.parent_symbol.node;
+ generated_callback.add_parameter (sender_param);
+
+ foreach (FormalParameter! param in parameters) {
+ generated_callback.add_parameter (param);
+ }
}
- public void add_parameter (FormalParameter param) {
- parameters.append (param);
- }
+ return generated_callback;
+ }
+
+ public override void accept (CodeVisitor! visitor) {
+ visitor.visit_begin_signal (this);
- public ref List<FormalParameter> get_parameters () {
- return parameters.copy ();
- }
+ return_type.accept (visitor);
- public override void accept (CodeVisitor visitor) {
- visitor.visit_begin_signal (this);
-
- return_type.accept (visitor);
-
- foreach (FormalParameter param in parameters) {
- param.accept (visitor);
- }
-
- visitor.visit_end_signal (this);
+ foreach (FormalParameter param in parameters) {
+ param.accept (visitor);
}
+
+ visitor.visit_end_signal (this);
}
}
+++ /dev/null
-/* valasimplename.vala
- *
- * Copyright (C) 2006 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
-
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
-
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author:
- * Jürg Billeter <j@bitron.ch>
- */
-
-using GLib;
-
-namespace Vala {
- public class SimpleName : Expression {
- public string name { get; construct; }
-
- public static ref SimpleName new (string s, SourceReference source) {
- return (new SimpleName (name = s, source_reference = source));
- }
-
- public override void accept (CodeVisitor visitor) {
- visitor.visit_simple_name (this);
- }
- }
-}
var block = new Block ();
if (acc.readable) {
- block.add_statement (new ReturnStatement (return_expression = new SimpleName (name = "_%s".printf (prop.name))));
+ block.add_statement (new ReturnStatement (return_expression = new MemberAccess (member_name = "_%s".printf (prop.name))));
} else {
- block.add_statement (new ExpressionStatement (expression = new Assignment (left = new SimpleName (name = "_%s".printf (prop.name)), right = new SimpleName (name = "value"))));
+ block.add_statement (new ExpressionStatement (expression = new Assignment (left = new MemberAccess (member_name = "_%s".printf (prop.name)), right = new MemberAccess (member_name = "value"))));
}
acc.body = block;
}
}
public override void visit_end_class (Class cl) {
- foreach (TypeReference type in cl.base_types) {
+ foreach (TypeReference type in cl.get_base_types ()) {
if (type.type is Class) {
if (cl.base_class != null) {
Report.error (type.source_reference, "%s: Classes cannot have multiple base classes (`%s' and `%s')".printf (cl.symbol.get_full_name (), cl.base_class.symbol.get_full_name (), type.type.symbol.get_full_name ()));
string type_name = null;
if (expr is MemberAccess) {
MemberAccess ma = (MemberAccess) expr;
- if (ma.inner is SimpleName) {
- SimpleName simple = (SimpleName) ma.inner;
- return (new TypeReference (namespace_name = simple.name, type_name = ma.member_name, source_reference = source));
+ if (ma.inner != null) {
+ if (ma.inner is MemberAccess) {
+ var simple = (MemberAccess) ma.inner;
+ return (new TypeReference (namespace_name = simple.member_name, type_name = ma.member_name, source_reference = source));
+ }
+ } else {
+ return (new TypeReference (type_name = ma.member_name, source_reference = source));
}
- } else if (expr is SimpleName) {
- SimpleName simple = (SimpleName) expr;
- return (new TypeReference (type_name = simple.name, source_reference = source));
}
/* FIXME: raise error */
return null;