summaryrefslogtreecommitdiff
path: root/vala
diff options
context:
space:
mode:
authorJürg Billeter <j@bitron.ch>2010-03-21 16:14:58 +0100
committerJürg Billeter <j@bitron.ch>2010-03-21 16:19:35 +0100
commit7082c10201cd471e85f80a07ab161ea20442f33d (patch)
tree15df14b0915d6b313068673c2536b4f6de68615a /vala
parent2a02ef9dbaaf496990d3e1f8747e91642ad6d5ee (diff)
downloadvala-7082c10201cd471e85f80a07ab161ea20442f33d.tar.gz
Fix closures in property accessors
Fixes bug 613483.
Diffstat (limited to 'vala')
-rw-r--r--vala/valamemberaccess.vala25
-rw-r--r--vala/valasemanticanalyzer.vala35
2 files changed, 53 insertions, 7 deletions
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index 63127c24f..981981ef7 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -446,10 +446,10 @@ public class Vala.MemberAccess : Expression {
if (member is LocalVariable) {
var local = (LocalVariable) member;
var block = local.parent_symbol as Block;
- if (block != null && analyzer.find_parent_method (block) != analyzer.current_method) {
+ if (block != null && analyzer.find_parent_method_or_property_accessor (block) != analyzer.current_method_or_property_accessor) {
// mark all methods between current method and the captured
// block as closures (to support nested closures)
- Symbol sym = analyzer.current_method;
+ Symbol sym = analyzer.current_method_or_property_accessor;
while (sym != block) {
var method = sym as Method;
if (method != null) {
@@ -467,10 +467,10 @@ public class Vala.MemberAccess : Expression {
} else if (member is FormalParameter) {
var param = (FormalParameter) member;
var m = param.parent_symbol as Method;
- if (m != null && m != analyzer.current_method && param != m.this_parameter) {
+ if (m != null && m != analyzer.current_method_or_property_accessor && param != m.this_parameter) {
// mark all methods between current method and the captured
// parameter as closures (to support nested closures)
- Symbol sym = analyzer.current_method;
+ Symbol sym = analyzer.current_method_or_property_accessor;
while (sym != m) {
var method = sym as Method;
if (method != null) {
@@ -486,6 +486,23 @@ public class Vala.MemberAccess : Expression {
error = true;
Report.error (source_reference, "Cannot capture reference or output parameter `%s'".printf (param.get_full_name ()));
}
+ } else {
+ var acc = param.parent_symbol.parent_symbol as PropertyAccessor;
+ if (acc != null && acc != analyzer.current_method_or_property_accessor && param != acc.prop.this_parameter) {
+ // mark all methods between current method and the captured
+ // parameter as closures (to support nested closures)
+ Symbol sym = analyzer.current_method_or_property_accessor;
+ while (sym != m) {
+ var method = sym as Method;
+ if (method != null) {
+ method.closure = true;
+ }
+ sym = sym.parent_symbol;
+ }
+
+ param.captured = true;
+ acc.body.captured = true;
+ }
}
} else if (member is Field) {
var f = (Field) member;
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index bafc2466d..130e2ca4d 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -58,7 +58,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
public Method? current_method {
get {
- var sym = current_symbol;
+ unowned Symbol sym = current_symbol;
while (sym is Block) {
sym = sym.parent_symbol;
}
@@ -68,7 +68,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
public Method? current_async_method {
get {
- var sym = current_symbol;
+ unowned Symbol sym = current_symbol;
while (sym is Block || sym is Method) {
var m = sym as Method;
if (m != null && m.coroutine) {
@@ -83,7 +83,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
public PropertyAccessor? current_property_accessor {
get {
- var sym = current_symbol;
+ unowned Symbol sym = current_symbol;
while (sym is Block) {
sym = sym.parent_symbol;
}
@@ -91,6 +91,22 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
}
}
+ public Symbol? current_method_or_property_accessor {
+ get {
+ unowned Symbol sym = current_symbol;
+ while (sym is Block) {
+ sym = sym.parent_symbol;
+ }
+ if (sym is Method) {
+ return sym;
+ } else if (sym is PropertyAccessor) {
+ return sym;
+ } else {
+ return null;
+ }
+ }
+ }
+
public DataType? current_return_type {
get {
var m = current_method;
@@ -809,6 +825,19 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
return sym as Method;
}
+ public Symbol? find_parent_method_or_property_accessor (Symbol sym) {
+ while (sym is Block) {
+ sym = sym.parent_symbol;
+ }
+ if (sym is Method) {
+ return sym;
+ } else if (sym is PropertyAccessor) {
+ return sym;
+ } else {
+ return null;
+ }
+ }
+
public bool is_in_constructor () {
var sym = current_symbol;
while (sym != null) {