+2008-10-11 Jürg Billeter <j@bitron.ch>
+
+ * vala/valaclass.vala:
+ * vala/valacreationmethod.vala:
+ * vala/valainterfacewriter.vala:
+ * vala/valaobjecttype.vala:
+ * vala/valasemanticanalyzer.vala:
+ * vala/valastruct.vala:
+ * gobject/valaccodeinvocationexpressionbinding.vala:
+ * gobject/valaccodemethodbinding.vala:
+ * gobject/valagidlwriter.vala:
+
+ Support chaining constructors using `base' and `this'
+
2008-10-11 Jürg Billeter <j@bitron.ch>
* vala/valacfgbuilder.vala:
m = ((MethodType) itype).method_symbol;
} else if (itype is SignalType) {
ccall = (CCodeFunctionCall) expr.call.ccodenode;
+ } else if (itype is ObjectType) {
+ // constructor
+ var cl = (Class) ((ObjectType) itype).type_symbol;
+ m = cl.default_construction_method;
+ ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_real_cname ()));
+ ccall.add_argument (new CCodeIdentifier ("object_type"));
}
// the complete call expression, might include casts, comma expressions, and/or assignments
param.accept (codegen);
}
codegen.dynamic_method_binding ((DynamicMethod) m).generate_wrapper ();
+ } else if (m is CreationMethod) {
+ ccall_expr = new CCodeAssignment (new CCodeIdentifier ("self"), new CCodeCastExpression (ccall, codegen.current_class.get_cname () + "*"));
}
bool ellipsis = false;
if (in_gobject_creation_method && m.body != null) {
var cblock = new CCodeBlock ();
- // set construct properties
- foreach (CodeNode stmt in m.body.get_statements ()) {
- var expr_stmt = stmt as ExpressionStatement;
- if (expr_stmt != null) {
- var prop = expr_stmt.assigned_property ();
- if (prop != null && prop.set_accessor.construction) {
- if (stmt.ccodenode is CCodeFragment) {
- foreach (CCodeNode cstmt in ((CCodeFragment) stmt.ccodenode).get_children ()) {
- cblock.add_statement (cstmt);
+ if (!((CreationMethod) m).chain_up) {
+ // set construct properties
+ foreach (CodeNode stmt in m.body.get_statements ()) {
+ var expr_stmt = stmt as ExpressionStatement;
+ if (expr_stmt != null) {
+ var prop = expr_stmt.assigned_property ();
+ if (prop != null && prop.set_accessor.construction) {
+ if (stmt.ccodenode is CCodeFragment) {
+ foreach (CCodeNode cstmt in ((CCodeFragment) stmt.ccodenode).get_children ()) {
+ cblock.add_statement (cstmt);
+ }
+ } else {
+ cblock.add_statement (stmt.ccodenode);
}
- } else {
- cblock.add_statement (stmt.ccodenode);
}
}
}
- }
- add_object_creation (cblock, ((CreationMethod) m).n_construction_params > 0 || codegen.current_class.get_type_parameters ().size > 0);
+ add_object_creation (cblock, ((CreationMethod) m).n_construction_params > 0 || codegen.current_class.get_type_parameters ().size > 0);
+ } else {
+ var cdeclaration = new CCodeDeclaration ("%s *".printf (((Class) codegen.current_type_symbol).get_cname ()));
+ cdeclaration.add_declarator (new CCodeVariableDeclarator ("self"));
+
+ cblock.add_statement (cdeclaration);
+ }
// other initialization code
foreach (CodeNode stmt in m.body.get_statements ()) {
return;
}
- string name = "new";
- if (m.name.has_prefix (".new.")) {
- name = m.name.substring (5, m.name.len () - 5);
- }
-
write_indent ();
- stream.printf ("<constructor name=\"%s\" symbol=\"%s\"", name, m.get_cname ());
+ stream.printf ("<constructor name=\"%s\" symbol=\"%s\"", m.name, m.get_cname ());
stream.printf (">\n");
indent++;
if (m is CreationMethod) {
if (m.name == null) {
default_construction_method = m;
- m.name = ".new";
- } else {
- m.name = ".new." + m.name;
+ m.name = "new";
}
var cm = (CreationMethod) m;
*/
public string? custom_return_type_cname { get; set; }
+ /**
+ * Specifies whether this constructor chains up to a base
+ * constructor or a different constructor of the same class.
+ */
+ public bool chain_up { get; set; }
+
/**
* Creates a new method.
*
infix = "init";
}
- if (name.len () == ".new".len ()) {
+ if (name == "new") {
return "%s%s".printf (parent.get_lower_case_cprefix (), infix);
} else {
- return "%s%s_%s".printf (parent.get_lower_case_cprefix (), infix, name.offset (".new.".len ()));
+ return "%s%s_%s".printf (parent.get_lower_case_cprefix (), infix, name);
}
}
string infix = "construct";
- if (name.len () == ".new".len ()) {
+ if (name == "new") {
return "%s%s".printf (parent.get_lower_case_cprefix (), infix);
} else {
- return "%s%s_%s".printf (parent.get_lower_case_cprefix (), infix, name.offset (".new.".len ()));
+ return "%s%s_%s".printf (parent.get_lower_case_cprefix (), infix, name);
}
}
}
if (m is CreationMethod) {
var datatype = (TypeSymbol) m.parent_symbol;
write_identifier (datatype.name);
- write_identifier (m.name.offset (".new".len ()));
+ if (m.name != "new") {
+ write_string (".");
+ write_identifier (m.name);
+ }
write_string (" ");
} else if (m.binding == MemberBinding.STATIC) {
write_string ("static ");
return type_symbol.is_subtype_of (obj_target_type.type_symbol);
}
+
+ public override bool is_invokable () {
+ var cl = type_symbol as Class;
+ if (cl != null && cl.default_construction_method != null) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public override DataType? get_return_type () {
+ var cl = type_symbol as Class;
+ if (cl != null && cl.default_construction_method != null) {
+ return cl.default_construction_method.return_type;
+ } else {
+ return null;
+ }
+ }
+
+ public override Gee.List<FormalParameter>? get_parameters () {
+ var cl = type_symbol as Class;
+ if (cl != null && cl.default_construction_method != null) {
+ return cl.default_construction_method.get_parameters ();
+ } else {
+ return null;
+ }
+ }
}
if (expr.inner is MemberAccess || expr.inner is BaseAccess) {
base_symbol = expr.inner.symbol_reference;
- if (expr.creation_member && base_symbol is TypeSymbol) {
- // check for named creation method
- expr.symbol_reference = base_symbol.scope.lookup (".new." + expr.member_name);
- }
-
if (expr.symbol_reference == null && (base_symbol is Namespace || base_symbol is TypeSymbol)) {
expr.symbol_reference = base_symbol.scope.lookup (expr.member_name);
if (expr.inner is BaseAccess) {
}
}
- if (expr.symbol_reference == null && expr.inner is MemberAccess && base_symbol is Struct) {
- // check for named struct creation method
- expr.symbol_reference = base_symbol.scope.lookup (".new." + expr.member_name);
- }
-
if (expr.symbol_reference == null && expr.inner.value_type != null && expr.inner.value_type.is_dynamic) {
// allow late bound members for dynamic types
var dynamic_object_type = (ObjectType) expr.inner.value_type;
var mtype = expr.call.value_type;
+ if (mtype is ObjectType) {
+ // constructor chain-up
+ var cm = find_current_method () as CreationMethod;
+ assert (cm != null);
+ if (cm.chain_up) {
+ expr.error = true;
+ Report.error (expr.source_reference, "Multiple constructor calls in the same constructor are not permitted");
+ return;
+ }
+ cm.chain_up = true;
+ }
+
// check for struct construction
if (expr.call is MemberAccess &&
- (expr.call.symbol_reference is CreationMethod
+ ((expr.call.symbol_reference is CreationMethod
+ && expr.call.symbol_reference.parent_symbol is Struct)
|| expr.call.symbol_reference is Struct)) {
var struct_creation_expression = new ObjectCreationExpression ((MemberAccess) expr.call, expr.source_reference);
struct_creation_expression.struct_creation = true;
expr.parent_node.replace_expression (expr, struct_creation_expression);
struct_creation_expression.accept (this);
return;
+ } else if (expr.call is MemberAccess
+ && expr.call.symbol_reference is CreationMethod) {
+ // constructor chain-up
+ var cm = find_current_method () as CreationMethod;
+ assert (cm != null);
+ if (cm.chain_up) {
+ expr.error = true;
+ Report.error (expr.source_reference, "Multiple constructor calls in the same constructor are not permitted");
+ return;
+ }
+ cm.chain_up = true;
}
Gee.List<FormalParameter> params;
expr.symbol_reference = constructor;
- type_args = ((MemberAccess) expr.member_name.inner).get_type_arguments ();
+ // inner expression can also be base access when chaining constructors
+ var ma = expr.member_name.inner as MemberAccess;
+ if (ma != null) {
+ type_args = ma.get_type_arguments ();
+ }
} else if (constructor_sym is ErrorCode) {
type_sym = constructor_sym.parent_symbol;
if (m is CreationMethod) {
if (m.name == null) {
default_construction_method = m;
- m.name = ".new";
- } else {
- m.name = ".new." + m.name;
+ m.name = "new";
}
var cm = (CreationMethod) m;