summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Bruno <lucabru@src.gnome.org>2013-09-21 11:34:06 +0200
committerLuca Bruno <lucabru@src.gnome.org>2013-09-21 11:34:06 +0200
commited8f32bd6696291a1bc49597b70c30335ec2917d (patch)
tree0b3a5be189e23ce21cfb08173a2e2fbf0f9e7364
parentfe764132afa6e8b39fc7b0791f7ba257066e7945 (diff)
downloadvala-ed8f32bd6696291a1bc49597b70c30335ec2917d.tar.gz
Support chain up to constructv functions.
-rw-r--r--codegen/valaccodebasemodule.vala12
-rw-r--r--codegen/valaccodemethodcallmodule.vala10
-rw-r--r--codegen/valaccodemethodmodule.vala18
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/objects/chainup.vala39
-rw-r--r--vala/valaclass.vala4
-rw-r--r--vala/valamethodcall.vala19
-rw-r--r--vala/valasemanticanalyzer.vala2
8 files changed, 84 insertions, 21 deletions
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index e42c5785e..5cdd816cd 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -6205,6 +6205,18 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
return get_ccode_attribute(sym).real_name;
}
+ public static string get_ccode_constructv_name (CreationMethod m) {
+ const string infix = "constructv";
+
+ var parent = m.parent_symbol as Class;
+
+ if (m.name == ".new") {
+ return "%s%s".printf (get_ccode_lower_case_prefix (parent), infix);
+ } else {
+ return "%s%s_%s".printf (get_ccode_lower_case_prefix (parent), infix, m.name);
+ }
+ }
+
public static string get_ccode_vfunc_name (Method m) {
return get_ccode_attribute(m).vfunc_name;
}
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index 0bd462a13..728dccdd4 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -48,6 +48,8 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
// Enum.VALUE.to_string()
var en = (Enum) ma.inner.value_type.data_type;
ccall.call = new CCodeIdentifier (generate_enum_tostring_function (en));
+ } else if (expr.is_constructv_chainup) {
+ ccall.call = new CCodeIdentifier (get_ccode_constructv_name ((CreationMethod) m));
}
} else if (itype is SignalType) {
var sig_type = (SignalType) itype;
@@ -61,7 +63,11 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
var cl = (Class) ((ObjectType) itype).type_symbol;
m = cl.default_construction_method;
generate_method_declaration (m, cfile);
- ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_real_name (m)));
+ var real_name = get_ccode_real_name (m);
+ if (expr.is_constructv_chainup) {
+ real_name = get_ccode_constructv_name ((CreationMethod) m);
+ }
+ ccall = new CCodeFunctionCall (new CCodeIdentifier (real_name));
} else if (itype is StructValueType) {
// constructor
var st = (Struct) ((StructValueType) itype).type_symbol;
@@ -598,7 +604,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
* except when using printf-style arguments */
if (m == null) {
in_arg_map.set (get_param_pos (-1, true), new CCodeConstant ("NULL"));
- } else if (!m.printf_format && !m.scanf_format && get_ccode_sentinel (m) != "") {
+ } else if (!m.printf_format && !m.scanf_format && get_ccode_sentinel (m) != "" && !expr.is_constructv_chainup) {
in_arg_map.set (get_param_pos (-1, true), new CCodeConstant (get_ccode_sentinel (m)));
}
}
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index f0cddaec1..c7c7818f7 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -204,7 +204,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
if (m.is_variadic ()) {
// _constructv function
- function = new CCodeFunction (get_constructv_name ((CreationMethod) m));
+ function = new CCodeFunction (get_ccode_constructv_name ((CreationMethod) m));
cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
generate_cparameters (m, decl_space, cparam_map, function);
@@ -214,18 +214,6 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
}
}
- private string get_constructv_name (CreationMethod m) {
- const string infix = "constructv";
-
- var parent = m.parent_symbol as Class;
-
- if (m.name == ".new") {
- return "%s%s".printf (CCodeBaseModule.get_ccode_lower_case_prefix (parent), infix);
- } else {
- return "%s%s_%s".printf (CCodeBaseModule.get_ccode_lower_case_prefix (parent), infix, m.name);
- }
- }
-
void register_plugin_types (Symbol sym, Set<Symbol> registered_types) {
var ns = sym as Namespace;
var cl = sym as Class;
@@ -289,7 +277,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
public override void visit_method (Method m) {
string real_name = get_ccode_real_name (m);
if (m is CreationMethod && m.is_variadic ()) {
- real_name = get_constructv_name ((CreationMethod) m);
+ real_name = get_ccode_constructv_name ((CreationMethod) m);
}
push_context (new EmitContext (m));
@@ -1182,7 +1170,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
push_function (vfunc);
- string constructor = (m.is_variadic ()) ? get_constructv_name (m) : get_ccode_real_name (m);
+ string constructor = (m.is_variadic ()) ? get_ccode_constructv_name (m) : get_ccode_real_name (m);
var vcall = new CCodeFunctionCall (new CCodeIdentifier (constructor));
if (self_as_first_parameter) {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b84ee0411..b84d433eb 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -100,6 +100,7 @@ TESTS = \
delegates/bug638415.vala \
delegates/bug639751.vala \
delegates/bug703804.vala \
+ objects/chainup.vala \
objects/classes.vala \
objects/fields.vala \
objects/interfaces.vala \
diff --git a/tests/objects/chainup.vala b/tests/objects/chainup.vala
new file mode 100644
index 000000000..fdca08d67
--- /dev/null
+++ b/tests/objects/chainup.vala
@@ -0,0 +1,39 @@
+class FooBase {
+ public int bar;
+
+ public FooBase (int _, ...) {
+ va_list v = va_list ();
+ bar = v.arg ();
+ }
+
+ public FooBase.baz (int _, ...) {
+ va_list v = va_list ();
+ this (_, v);
+ }
+}
+
+class Foo : FooBase {
+ public Foo (int _, ...) {
+ va_list v = va_list ();
+ base (_, v);
+ }
+
+ public Foo.baz (int _, ...) {
+ va_list v = va_list ();
+ base.baz (_, v);
+ }
+
+ public Foo.qux (int _, ...) {
+ va_list v = va_list ();
+ this.baz (_, v);
+ }
+}
+
+void main () {
+ var foo = new Foo (0, 10);
+ assert (foo.bar == 10);
+ foo = new Foo.baz (0, 20);
+ assert (foo.bar == 20);
+ foo = new Foo.qux (0, 30);
+ assert (foo.bar == 30);
+}
diff --git a/vala/valaclass.vala b/vala/valaclass.vala
index 5110a7aa6..ba23a508f 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -151,7 +151,7 @@ public class Vala.Class : ObjectTypeSymbol {
/**
* Specifies the default construction method.
*/
- public Method default_construction_method { get; set; }
+ public CreationMethod default_construction_method { get; set; }
/**
* Specifies the instance constructor.
@@ -303,7 +303,7 @@ public class Vala.Class : ObjectTypeSymbol {
}
if (m is CreationMethod) {
if (m.name == null) {
- default_construction_method = m;
+ default_construction_method = (CreationMethod) m;
m.name = ".new";
}
diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala
index 5b0ba8a1d..89d2ba5cc 100644
--- a/vala/valamethodcall.vala
+++ b/vala/valamethodcall.vala
@@ -41,6 +41,11 @@ public class Vala.MethodCall : Expression {
public bool is_assert { get; private set; }
+ /**
+ * Whether this chain up uses the constructv function with va_list.
+ */
+ public bool is_constructv_chainup { get; private set; }
+
public Expression _call;
private List<Expression> argument_list = new ArrayList<Expression> ();
@@ -213,6 +218,8 @@ public class Vala.MethodCall : Expression {
var mtype = call.value_type;
+ CreationMethod base_cm = null;
+
if (mtype is ObjectType || call.symbol_reference == context.analyzer.object_type) {
// constructor chain-up
var cm = context.analyzer.find_current_method () as CreationMethod;
@@ -230,7 +237,7 @@ public class Vala.MethodCall : Expression {
if (mtype is ObjectType) {
var otype = (ObjectType) mtype;
var cl = (Class) otype.type_symbol;
- var base_cm = cl.default_construction_method;
+ base_cm = cl.default_construction_method;
if (base_cm == null) {
error = true;
Report.error (source_reference, "chain up to `%s' not supported".printf (cl.get_full_name ()));
@@ -301,7 +308,7 @@ public class Vala.MethodCall : Expression {
}
cm.chain_up = true;
- var base_cm = (CreationMethod) call.symbol_reference;
+ base_cm = (CreationMethod) call.symbol_reference;
if (!base_cm.has_construct_function) {
error = true;
Report.error (source_reference, "chain up to `%s' not supported".printf (base_cm.get_full_name ()));
@@ -720,6 +727,14 @@ public class Vala.MethodCall : Expression {
return false;
}
+ /* Check for constructv chain up */
+ if (base_cm != null && base_cm.is_variadic () && args.size == base_cm.get_parameters ().size) {
+ var this_last_arg = args[args.size-1];
+ if (this_last_arg.value_type is StructValueType && this_last_arg.value_type.data_type == context.analyzer.va_list_type.data_type) {
+ is_constructv_chainup = true;
+ }
+ }
+
if (may_throw) {
if (parent_node is LocalVariable || parent_node is ExpressionStatement) {
// simple statements, no side effects after method call
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 90923ac2c..8244896d0 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -150,6 +150,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
public DataType unichar_type;
public DataType double_type;
public DataType type_type;
+ public DataType va_list_type;
public Class object_type;
public StructValueType gvalue_type;
public ObjectType gvariant_type;
@@ -196,6 +197,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
size_t_type = new IntegerType ((Struct) root_symbol.scope.lookup ("size_t"));
ssize_t_type = new IntegerType ((Struct) root_symbol.scope.lookup ("ssize_t"));
double_type = new FloatingType ((Struct) root_symbol.scope.lookup ("double"));
+ va_list_type = new StructValueType ((Struct) root_symbol.scope.lookup ("va_list"));
var unichar_struct = (Struct) root_symbol.scope.lookup ("unichar");
if (unichar_struct != null) {