[vala/wip/transform: 1/95] Make the semantic analyzer be stateless
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/transform: 1/95] Make the semantic analyzer be stateless
- Date: Mon, 20 Mar 2017 14:28:34 +0000 (UTC)
commit df0dc4ee76af928a23c2df1b67500ef84bfc26ed
Author: Luca Bruno <lucabru src gnome org>
Date: Sat Aug 6 10:38:59 2011 +0200
Make the semantic analyzer be stateless
vala/valaassignment.vala | 15 +-
vala/valabaseaccess.vala | 17 ++-
vala/valabinaryexpression.vala | 12 +-
vala/valablock.vala | 12 +-
vala/valacatchclause.vala | 1 -
vala/valaclass.vala | 67 +++++++--
vala/valaconditionalexpression.vala | 6 +-
vala/valaconstant.vala | 14 --
vala/valaconstructor.vala | 7 +-
vala/valacreationmethod.vala | 27 +----
vala/valadelegate.vala | 8 -
vala/valadestructor.vala | 5 -
vala/valaenum.vala | 11 --
vala/valaerrorcode.vala | 12 ++-
vala/valafield.vala | 11 --
vala/valaforeachstatement.vala | 10 +-
vala/valainterface.vala | 11 --
vala/valalambdaexpression.vala | 8 +-
vala/valalocalvariable.vala | 4 +-
vala/valalockstatement.vala | 25 +++-
vala/valamemberaccess.vala | 41 +++---
vala/valamethod.vala | 13 +--
vala/valamethodcall.vala | 15 +-
vala/valaobjectcreationexpression.vala | 24 ++-
vala/valaparameter.vala | 11 --
vala/valaproperty.vala | 11 --
vala/valapropertyaccessor.vala | 6 -
vala/valareturnstatement.vala | 22 ++--
vala/valasemanticanalyzer.vala | 253 ++++++++++++++------------------
vala/valastruct.vala | 11 --
vala/valasubroutine.vala | 2 +-
vala/valaswitchlabel.vala | 14 ++-
vala/valaswitchsection.vala | 14 +--
vala/valaunlockstatement.vala | 2 +-
vala/valayieldstatement.vala | 2 +-
35 files changed, 311 insertions(+), 413 deletions(-)
---
diff --git a/vala/valaassignment.vala b/vala/valaassignment.vala
index 88e45ff..f80f725 100644
--- a/vala/valaassignment.vala
+++ b/vala/valaassignment.vala
@@ -108,20 +108,22 @@ public class Vala.Assignment : Expression {
checked = true;
+ var insert_block = context.analyzer.get_insert_block (this);
+
if (left is Tuple && operator == AssignmentOperator.SIMPLE && parent_node is
ExpressionStatement) {
var tuple = (Tuple) left;
var local = new LocalVariable (null, get_temp_name (), right, right.source_reference);
var decl = new DeclarationStatement (local, source_reference);
decl.check (context);
- insert_statement (context.analyzer.insert_block, decl);
+ insert_statement (insert_block, decl);
int i = 0;
ExpressionStatement stmt = null;
foreach (var expr in tuple.get_expressions ()) {
if (stmt != null) {
stmt.check (context);
- insert_statement (context.analyzer.insert_block, stmt);
+ insert_statement (insert_block, stmt);
}
var temp_access = new MemberAccess.simple (local.name,
right.source_reference);
@@ -156,7 +158,7 @@ public class Vala.Assignment : Expression {
}
if ((!(ma.symbol_reference is Signal || ma.symbol_reference is DynamicProperty) &&
ma.value_type == null) ||
- (ma.inner == null && ma.member_name == "this" &&
context.analyzer.is_in_instance_method ())) {
+ (ma.inner == null && ma.member_name == "this" &&
context.analyzer.is_in_instance_method (this))) {
error = true;
Report.error (source_reference, "unsupported lvalue in assignment");
return false;
@@ -317,15 +319,16 @@ public class Vala.Assignment : Expression {
left.value_type = dynamic_prop.property_type.copy ();
}
+ var current_method = context.analyzer.get_current_method (this);
if (prop.set_accessor == null
- || (!prop.set_accessor.writable && !(context.analyzer.find_current_method
() is CreationMethod || context.analyzer.is_in_constructor ()))) {
+ || (!prop.set_accessor.writable && !(current_method is CreationMethod ||
context.analyzer.is_in_constructor (this)))) {
ma.error = true;
Report.error (ma.source_reference, "Property `%s' is
read-only".printf (prop.get_full_name ()));
return false;
} else if (!context.deprecated
&& !prop.set_accessor.writable
- && context.analyzer.find_current_method () is CreationMethod) {
- if (ma.inner.symbol_reference != context.analyzer.find_current_method
().this_parameter) {
+ && current_method is CreationMethod) {
+ if (ma.inner.symbol_reference != current_method.this_parameter) {
// trying to set construct-only property in creation method
for foreign instance
Report.error (ma.source_reference, "Property `%s' is
read-only".printf (prop.get_full_name ()));
return false;
diff --git a/vala/valabaseaccess.vala b/vala/valabaseaccess.vala
index 8058540..4d7caed 100644
--- a/vala/valabaseaccess.vala
+++ b/vala/valabaseaccess.vala
@@ -56,29 +56,32 @@ public class Vala.BaseAccess : Expression {
checked = true;
- if (!context.analyzer.is_in_instance_method ()) {
+ if (!context.analyzer.is_in_instance_method (this)) {
error = true;
Report.error (source_reference, "Base access invalid outside of instance methods");
return false;
}
- if (context.analyzer.current_class == null) {
- if (context.analyzer.current_struct == null) {
+ var current_class = context.analyzer.get_current_class (this);
+ var current_struct = context.analyzer.get_current_struct (this);
+
+ if (current_class == null) {
+ if (current_struct == null) {
error = true;
Report.error (source_reference, "Base access invalid outside of class and
struct");
return false;
- } else if (context.analyzer.current_struct.base_type == null) {
+ } else if (current_struct.base_type == null) {
error = true;
Report.error (source_reference, "Base access invalid without base type");
return false;
}
- value_type = context.analyzer.current_struct.base_type;
- } else if (context.analyzer.current_class.base_class == null) {
+ value_type = current_struct.base_type;
+ } else if (current_class.base_class == null) {
error = true;
Report.error (source_reference, "Base access invalid without base class");
return false;
} else {
- foreach (var base_type in context.analyzer.current_class.get_base_types ()) {
+ foreach (var base_type in current_class.get_base_types ()) {
if (base_type.data_type is Class) {
value_type = base_type.copy ();
value_type.value_owned = false;
diff --git a/vala/valabinaryexpression.vala b/vala/valabinaryexpression.vala
index 9a740d2..6832d1e 100644
--- a/vala/valabinaryexpression.vala
+++ b/vala/valabinaryexpression.vala
@@ -152,9 +152,11 @@ public class Vala.BinaryExpression : Expression {
checked = true;
+ var insert_block = context.analyzer.get_insert_block (this);
+
// some expressions are not in a block,
// for example, expressions in method contracts
- if (context.analyzer.current_symbol is Block
+ if (context.analyzer.get_current_symbol (this) is Block
&& (operator == BinaryOperator.AND || operator == BinaryOperator.OR)) {
// convert conditional expression into if statement
// required for flow analysis and exception handling
@@ -179,8 +181,8 @@ public class Vala.BinaryExpression : Expression {
var if_stmt = new IfStatement (left, true_block, false_block, source_reference);
- insert_statement (context.analyzer.insert_block, decl);
- insert_statement (context.analyzer.insert_block, if_stmt);
+ insert_statement (insert_block, decl);
+ insert_statement (insert_block, if_stmt);
decl.check (context);
@@ -235,8 +237,8 @@ public class Vala.BinaryExpression : Expression {
var if_stmt = new IfStatement (cond, true_block, null, source_reference);
- insert_statement (context.analyzer.insert_block, decl);
- insert_statement (context.analyzer.insert_block, if_stmt);
+ insert_statement (insert_block, decl);
+ insert_statement (insert_block, if_stmt);
if (!decl.check (context)) {
error = true;
diff --git a/vala/valablock.vala b/vala/valablock.vala
index 4064b6e..6388a57 100644
--- a/vala/valablock.vala
+++ b/vala/valablock.vala
@@ -97,10 +97,12 @@ public class Vala.Block : Symbol, Statement {
parent_block = parent_block.parent_symbol;
}
local_variables.add (local);
+ scope.add (local.name, local);
}
public void remove_local_variable (LocalVariable local) {
local_variables.remove (local);
+ scope.remove (local.name);
}
/**
@@ -142,12 +144,7 @@ public class Vala.Block : Symbol, Statement {
checked = true;
- owner = context.analyzer.current_symbol.scope;
-
- var old_symbol = context.analyzer.current_symbol;
- var old_insert_block = context.analyzer.insert_block;
- context.analyzer.current_symbol = this;
- context.analyzer.insert_block = this;
+ owner = context.analyzer.get_current_symbol (parent_node).scope;
for (int i = 0; i < statement_list.size; i++) {
statement_list[i].check (context);
@@ -166,9 +163,6 @@ public class Vala.Block : Symbol, Statement {
add_error_types (stmt.get_error_types ());
}
- context.analyzer.current_symbol = old_symbol;
- context.analyzer.insert_block = old_insert_block;
-
return !error;
}
diff --git a/vala/valacatchclause.vala b/vala/valacatchclause.vala
index 84e4ba3..e3efd58 100644
--- a/vala/valacatchclause.vala
+++ b/vala/valacatchclause.vala
@@ -125,7 +125,6 @@ public class Vala.CatchClause : CodeNode {
if (variable_name != null) {
error_variable = new LocalVariable (error_type.copy (), variable_name);
- body.scope.add (variable_name, error_variable);
body.add_local_variable (error_variable);
error_variable.checked = true;
diff --git a/vala/valaclass.vala b/vala/valaclass.vala
index 211c321..d276223 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -156,17 +156,41 @@ public class Vala.Class : ObjectTypeSymbol {
/**
* Specifies the instance constructor.
*/
- public Constructor constructor { get; set; }
+ public Constructor constructor {
+ get { return _constructor; }
+ set {
+ _constructor = value;
+ if (_constructor != null) {
+ _constructor.owner = scope;
+ }
+ }
+ }
/**
* Specifies the class constructor.
*/
- public Constructor class_constructor { get; set; }
+ public Constructor class_constructor {
+ get { return _class_constructor; }
+ set {
+ _class_constructor = value;
+ if (_class_constructor != null) {
+ _class_constructor.owner = scope;
+ }
+ }
+ }
/**
* Specifies the static class constructor.
*/
- public Constructor static_constructor { get; set; }
+ public Constructor static_constructor {
+ get { return _static_constructor; }
+ set {
+ _static_constructor = value;
+ if (_static_constructor != null) {
+ _static_constructor.owner = scope;
+ }
+ }
+ }
/**
* Specifies the instance destructor.
@@ -176,6 +200,7 @@ public class Vala.Class : ObjectTypeSymbol {
set {
_destructor = value;
if (_destructor != null) {
+ _destructor.owner = scope;
if (_destructor.this_parameter != null) {
_destructor.scope.remove (_destructor.this_parameter.name);
}
@@ -188,12 +213,28 @@ public class Vala.Class : ObjectTypeSymbol {
/**
* Specifies the class destructor.
*/
- public Destructor? static_destructor { get; set; }
+ public Destructor? static_destructor {
+ get { return _static_destructor; }
+ set {
+ _static_destructor = value;
+ if (_static_destructor != null) {
+ _static_destructor.owner = scope;
+ }
+ }
+ }
/**
* Specifies the class destructor.
*/
- public Destructor? class_destructor { get; set; }
+ public Destructor? class_destructor {
+ get { return _class_destructor; }
+ set {
+ _class_destructor = value;
+ if (_class_destructor != null) {
+ _class_destructor.owner = scope;
+ }
+ }
+ }
/**
* Specifies whether this class denotes an error base.
@@ -204,7 +245,12 @@ public class Vala.Class : ObjectTypeSymbol {
}
}
+ Constructor _constructor;
+ Constructor _class_constructor;
+ Constructor _static_constructor;
Destructor? _destructor;
+ Destructor? _class_destructor;
+ Destructor? _static_destructor;
/**
* Creates a new class.
@@ -608,14 +654,6 @@ public class Vala.Class : ObjectTypeSymbol {
checked = true;
- var old_source_file = context.analyzer.current_source_file;
- var old_symbol = context.analyzer.current_symbol;
-
- if (source_reference != null) {
- context.analyzer.current_source_file = source_reference.file;
- }
- context.analyzer.current_symbol = this;
-
foreach (DataType base_type_reference in get_base_types ()) {
if (!base_type_reference.check (context)) {
error = true;
@@ -865,9 +903,6 @@ public class Vala.Class : ObjectTypeSymbol {
}
}
- context.analyzer.current_source_file = old_source_file;
- context.analyzer.current_symbol = old_symbol;
-
return !error;
}
}
diff --git a/vala/valaconditionalexpression.vala b/vala/valaconditionalexpression.vala
index daf8b7a..4a3d139 100644
--- a/vala/valaconditionalexpression.vala
+++ b/vala/valaconditionalexpression.vala
@@ -111,7 +111,7 @@ public class Vala.ConditionalExpression : Expression {
checked = true;
- if (!(context.analyzer.current_symbol is Block)) {
+ if (!(context.analyzer.get_current_symbol (this) is Block)) {
Report.error (source_reference, "Conditional expressions may only be used in blocks");
error = true;
return false;
@@ -140,8 +140,8 @@ public class Vala.ConditionalExpression : Expression {
var if_stmt = new IfStatement (condition, true_block, false_block, source_reference);
- insert_statement (context.analyzer.insert_block, decl);
- insert_statement (context.analyzer.insert_block, if_stmt);
+ insert_statement (context.analyzer.get_insert_block (this), decl);
+ insert_statement (context.analyzer.get_insert_block (this), if_stmt);
if (!if_stmt.check (context) || true_expression.error || false_expression.error) {
error = true;
diff --git a/vala/valaconstant.vala b/vala/valaconstant.vala
index 53b84c6..eed0ded 100644
--- a/vala/valaconstant.vala
+++ b/vala/valaconstant.vala
@@ -112,17 +112,6 @@ public class Vala.Constant : Symbol, Lockable {
checked = true;
- var old_source_file = context.analyzer.current_source_file;
- var old_symbol = context.analyzer.current_symbol;
-
- if (source_reference != null) {
- context.analyzer.current_source_file = source_reference.file;
- }
- if (!(parent_symbol is Block)) {
- // non-local constant
- context.analyzer.current_symbol = this;
- }
-
type_reference.check (context);
if (!check_const_type (type_reference, context)) {
@@ -181,9 +170,6 @@ public class Vala.Constant : Symbol, Lockable {
Report.warning (source_reference, "%s hides inherited constant `%s'. Use the `new'
keyword if hiding was intentional".printf (get_full_name (), get_hidden_member ().get_full_name ()));
}
- context.analyzer.current_source_file = old_source_file;
- context.analyzer.current_symbol = old_symbol;
-
active = true;
return !error;
diff --git a/vala/valaconstructor.vala b/vala/valaconstructor.vala
index d16fc13..3d19596 100644
--- a/vala/valaconstructor.vala
+++ b/vala/valaconstructor.vala
@@ -67,12 +67,9 @@ public class Vala.Constructor : Subroutine {
checked = true;
- this_parameter = new Parameter ("this", new ObjectType (context.analyzer.current_class));
+ this_parameter = new Parameter ("this", new ObjectType (context.analyzer.get_current_class
(this)));
scope.add (this_parameter.name, this_parameter);
- owner = context.analyzer.current_symbol.scope;
- context.analyzer.current_symbol = this;
-
if (body != null) {
body.check (context);
}
@@ -83,8 +80,6 @@ public class Vala.Constructor : Subroutine {
}
}
- context.analyzer.current_symbol = context.analyzer.current_symbol.parent_symbol;
-
return !error;
}
}
diff --git a/vala/valacreationmethod.vala b/vala/valacreationmethod.vala
index 451dd81..202a121 100644
--- a/vala/valacreationmethod.vala
+++ b/vala/valacreationmethod.vala
@@ -86,19 +86,11 @@ public class Vala.CreationMethod : Method {
if (class_name != null && class_name != parent_symbol.name) {
// class_name is null for constructors generated by GIdlParser
- Report.error (source_reference, "missing return type in method `%s.%s´".printf
(context.analyzer.current_symbol.get_full_name (), class_name));
+ Report.error (source_reference, "missing return type in method `%s.%s´".printf
(context.analyzer.get_current_symbol (this).get_full_name (), class_name));
error = true;
return false;
}
- var old_source_file = context.analyzer.current_source_file;
- var old_symbol = context.analyzer.current_symbol;
-
- if (source_reference != null) {
- context.analyzer.current_source_file = source_reference.file;
- }
- context.analyzer.current_symbol = this;
-
foreach (Parameter param in get_parameters()) {
param.check (context);
}
@@ -124,40 +116,23 @@ public class Vala.CreationMethod : Method {
if (!chain_up && cl != null && cl.base_class != null) {
if (cl.base_class.default_construction_method != null
&& !cl.base_class.default_construction_method.has_construct_function) {
- // directly chain up to Object
- var old_insert_block = context.analyzer.insert_block;
- context.analyzer.current_symbol = body;
- context.analyzer.insert_block = body;
var stmt = new ExpressionStatement (new MethodCall (new MemberAccess
(new MemberAccess.simple ("GLib", source_reference), "Object", source_reference), source_reference),
source_reference);
body.insert_statement (0, stmt);
stmt.check (context);
-
- context.analyzer.current_symbol = this;
- context.analyzer.insert_block = old_insert_block;
} else if (cl.base_class.default_construction_method == null
|| cl.base_class.default_construction_method.access ==
SymbolAccessibility.PRIVATE) {
Report.error (source_reference, "unable to chain up to private base
constructor");
} else if (cl.base_class.default_construction_method.get_required_arguments
() > 0) {
Report.error (source_reference, "unable to chain up to base
constructor requiring arguments");
} else {
- var old_insert_block = context.analyzer.insert_block;
- context.analyzer.current_symbol = body;
- context.analyzer.insert_block = body;
-
var stmt = new ExpressionStatement (new MethodCall (new BaseAccess
(source_reference), source_reference), source_reference);
body.insert_statement (0, stmt);
stmt.check (context);
-
- context.analyzer.current_symbol = this;
- context.analyzer.insert_block = old_insert_block;
}
}
}
- context.analyzer.current_source_file = old_source_file;
- context.analyzer.current_symbol = old_symbol;
-
if (is_abstract || is_virtual || overrides) {
Report.error (source_reference, "The creation method `%s' cannot be marked as
override, virtual, or abstract".printf (get_full_name ()));
return false;
diff --git a/vala/valadelegate.vala b/vala/valadelegate.vala
index 6f4ae3b..555e978 100644
--- a/vala/valadelegate.vala
+++ b/vala/valadelegate.vala
@@ -296,12 +296,6 @@ public class Vala.Delegate : TypeSymbol, Callable {
checked = true;
- var old_source_file = context.analyzer.current_source_file;
-
- if (source_reference != null) {
- context.analyzer.current_source_file = source_reference.file;
- }
-
foreach (TypeParameter p in type_parameters) {
p.check (context);
}
@@ -316,8 +310,6 @@ public class Vala.Delegate : TypeSymbol, Callable {
error_type.check (context);
}
- context.analyzer.current_source_file = old_source_file;
-
return !error;
}
}
diff --git a/vala/valadestructor.vala b/vala/valadestructor.vala
index 7ee3843..ddfb0f9 100644
--- a/vala/valadestructor.vala
+++ b/vala/valadestructor.vala
@@ -67,15 +67,10 @@ public class Vala.Destructor : Subroutine {
checked = true;
- owner = context.analyzer.current_symbol.scope;
- context.analyzer.current_symbol = this;
-
if (body != null) {
body.check (context);
}
- context.analyzer.current_symbol = context.analyzer.current_symbol.parent_symbol;
-
return !error;
}
}
diff --git a/vala/valaenum.vala b/vala/valaenum.vala
index acb8eb3..97c13e6 100644
--- a/vala/valaenum.vala
+++ b/vala/valaenum.vala
@@ -163,14 +163,6 @@ public class Vala.Enum : TypeSymbol {
checked = true;
- var old_source_file = context.analyzer.current_source_file;
- var old_symbol = context.analyzer.current_symbol;
-
- if (source_reference != null) {
- context.analyzer.current_source_file = source_reference.file;
- }
- context.analyzer.current_symbol = this;
-
foreach (EnumValue value in values) {
value.check (context);
}
@@ -183,9 +175,6 @@ public class Vala.Enum : TypeSymbol {
c.check (context);
}
- context.analyzer.current_source_file = old_source_file;
- context.analyzer.current_symbol = old_symbol;
-
return !error;
}
}
diff --git a/vala/valaerrorcode.vala b/vala/valaerrorcode.vala
index aa97641..62ff540 100644
--- a/vala/valaerrorcode.vala
+++ b/vala/valaerrorcode.vala
@@ -29,7 +29,17 @@ public class Vala.ErrorCode : TypeSymbol {
/**
* Specifies the numerical representation of this enum value.
*/
- public Expression value { get; set; }
+ public Expression? value {
+ get { return _value; }
+ set {
+ _value = value;
+ if (_value != null) {
+ _value.parent_node = this;
+ }
+ }
+ }
+
+ private Expression _value;
/**
* Creates a new enum value.
diff --git a/vala/valafield.vala b/vala/valafield.vala
index 88f8090..7ef631e 100644
--- a/vala/valafield.vala
+++ b/vala/valafield.vala
@@ -92,14 +92,6 @@ public class Vala.Field : Variable, Lockable {
checked = true;
- var old_source_file = context.analyzer.current_source_file;
- var old_symbol = context.analyzer.current_symbol;
-
- if (source_reference != null) {
- context.analyzer.current_source_file = source_reference.file;
- }
- context.analyzer.current_symbol = this;
-
if (variable_type is VoidType) {
error = true;
Report.error (source_reference, "'void' not supported as field type");
@@ -190,9 +182,6 @@ public class Vala.Field : Variable, Lockable {
Report.warning (source_reference, "%s hides inherited field `%s'. Use the `new'
keyword if hiding was intentional".printf (get_full_name (), get_hidden_member ().get_full_name ()));
}
- context.analyzer.current_source_file = old_source_file;
- context.analyzer.current_symbol = old_symbol;
-
return !error;
}
}
diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala
index 4de3f52..2241066 100644
--- a/vala/valaforeachstatement.vala
+++ b/vala/valaforeachstatement.vala
@@ -154,6 +154,8 @@ public class Vala.ForeachStatement : Block {
checked = true;
+ owner = context.analyzer.get_current_symbol (parent_node).scope;
+
// analyze collection expression first, used for type inference
if (!collection.check (context)) {
// ignore inner error
@@ -353,16 +355,10 @@ public class Vala.ForeachStatement : Block {
element_variable = new LocalVariable (type_reference, variable_name, null, source_reference);
- body.scope.add (variable_name, element_variable);
-
body.add_local_variable (element_variable);
element_variable.active = true;
element_variable.checked = true;
- // analyze body
- owner = context.analyzer.current_symbol.scope;
- context.analyzer.current_symbol = this;
-
// call add_local_variable to check for shadowed variable
add_local_variable (element_variable);
remove_local_variable (element_variable);
@@ -373,8 +369,6 @@ public class Vala.ForeachStatement : Block {
local.active = false;
}
- context.analyzer.current_symbol = context.analyzer.current_symbol.parent_symbol;
-
collection_variable = new LocalVariable (collection_type.copy (), "%s_collection".printf
(variable_name));
add_local_variable (collection_variable);
diff --git a/vala/valainterface.vala b/vala/valainterface.vala
index 621c6e8..91870c4 100644
--- a/vala/valainterface.vala
+++ b/vala/valainterface.vala
@@ -369,14 +369,6 @@ public class Vala.Interface : ObjectTypeSymbol {
checked = true;
- var old_source_file = context.analyzer.current_source_file;
- var old_symbol = context.analyzer.current_symbol;
-
- if (source_reference != null) {
- context.analyzer.current_source_file = source_reference.file;
- }
- context.analyzer.current_symbol = this;
-
foreach (DataType prerequisite_reference in get_prerequisites ()) {
// check whether prerequisite is at least as accessible as the interface
if (!context.analyzer.is_type_accessible (this, prerequisite_reference)) {
@@ -515,9 +507,6 @@ public class Vala.Interface : ObjectTypeSymbol {
}
}
- context.analyzer.current_source_file = old_source_file;
- context.analyzer.current_symbol = old_symbol;
-
return !error;
}
}
diff --git a/vala/valalambdaexpression.vala b/vala/valalambdaexpression.vala
index 1d6f957..55407b6 100644
--- a/vala/valalambdaexpression.vala
+++ b/vala/valalambdaexpression.vala
@@ -139,10 +139,10 @@ public class Vala.LambdaExpression : Expression {
method.used = true;
method.version.check (source_reference);
- if (!cb.has_target || !context.analyzer.is_in_instance_method ()) {
+ if (!cb.has_target || !context.analyzer.is_in_instance_method (this)) {
method.binding = MemberBinding.STATIC;
} else {
- var sym = context.analyzer.current_symbol;
+ var sym = context.analyzer.get_current_symbol (this);
while (method.this_parameter == null) {
if (sym is Property) {
var prop = (Property) sym;
@@ -161,7 +161,7 @@ public class Vala.LambdaExpression : Expression {
sym = sym.parent_symbol;
}
}
- method.owner = context.analyzer.current_symbol.scope;
+ method.owner = context.analyzer.get_current_symbol (this).scope;
var lambda_params = get_parameters ();
Iterator<Parameter> lambda_param_it = lambda_params.iterator ();
@@ -220,7 +220,7 @@ public class Vala.LambdaExpression : Expression {
method.body.owner = method.scope;
// support use of generics in closures
- var m = context.analyzer.find_parent_method (context.analyzer.current_symbol);
+ var m = context.analyzer.get_current_method (this);
if (m != null) {
foreach (var type_param in m.get_type_parameters ()) {
method.add_type_parameter (new TypeParameter (type_param.name,
type_param.source_reference));
diff --git a/vala/valalocalvariable.vala b/vala/valalocalvariable.vala
index c113807..61013a9 100644
--- a/vala/valalocalvariable.vala
+++ b/vala/valalocalvariable.vala
@@ -189,11 +189,9 @@ public class Vala.LocalVariable : Variable {
}
}
- context.analyzer.current_symbol.scope.add (name, this);
-
// current_symbol is a Method if this is the `result'
// variable used for postconditions
- var block = context.analyzer.current_symbol as Block;
+ var block = context.analyzer.get_current_block (this);
if (block != null) {
block.add_local_variable (this);
}
diff --git a/vala/valalockstatement.vala b/vala/valalockstatement.vala
index e0d4216..b94e88c 100644
--- a/vala/valalockstatement.vala
+++ b/vala/valalockstatement.vala
@@ -36,13 +36,30 @@ public class Vala.LockStatement : CodeNode, Statement {
/**
* Expression representing the resource to be locked.
*/
- public Expression resource { get; set; }
+ public Expression resource {
+ get { return _resource; }
+ set {
+ _resource = value;
+ _resource.parent_node = this;
+ }
+ }
/**
* The statement during its execution the resource is locked.
*/
- public Block? body { get; set; }
-
+ public Block? body {
+ get { return _body; }
+ set {
+ _body = value;
+ if (_body != null) {
+ _body.parent_node = this;
+ }
+ }
+ }
+
+ private Expression _resource;
+ private Block _body;
+
public LockStatement (Expression resource, Block? body, SourceReference? source_reference = null) {
this.body = body;
this.source_reference = source_reference;
@@ -91,7 +108,7 @@ public class Vala.LockStatement : CodeNode, Statement {
}
/* parent symbol must be the current class */
- if (resource.symbol_reference.parent_symbol != context.analyzer.current_class) {
+ if (resource.symbol_reference.parent_symbol != context.analyzer.get_current_class (this)) {
error = true;
resource.error = true;
Report.error (resource.source_reference, "Only members of the current class are
lockable");
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index c00f5fc..80a593b 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -220,20 +220,20 @@ public class Vala.MemberAccess : Expression {
symbol_reference = context.analyzer.root_symbol.scope.lookup (member_name);
} else if (inner == null) {
if (member_name == "this") {
- if (!context.analyzer.is_in_instance_method ()) {
+ if (!context.analyzer.is_in_instance_method (this)) {
error = true;
Report.error (source_reference, "This access invalid outside of
instance methods");
return false;
}
}
- base_symbol = context.analyzer.current_symbol;
+ base_symbol = context.analyzer.get_current_symbol (this);
// track whether method has been found to make sure that access
// to instance member is denied from within static lambda expressions
bool method_found = false;
- var sym = context.analyzer.current_symbol;
+ var sym = base_symbol;
while (sym != null && symbol_reference == null) {
if (!method_found) {
if (sym is CreationMethod) {
@@ -476,13 +476,15 @@ public class Vala.MemberAccess : Expression {
return false;
}
+ var current_method_or_property_accessor =
context.analyzer.get_current_method_or_property_accessor (this);
+
if (member is LocalVariable) {
var local = (LocalVariable) member;
var block = local.parent_symbol as Block;
- if (block != null && context.analyzer.find_parent_method_or_property_accessor (block)
!= context.analyzer.current_method_or_property_accessor) {
+ if (block != null && context.analyzer.get_current_method_or_property_accessor (block)
!= current_method_or_property_accessor) {
// mark all methods between current method and the captured
// block as closures (to support nested closures)
- Symbol sym = context.analyzer.current_method_or_property_accessor;
+ Symbol sym = current_method_or_property_accessor;
while (sym != block) {
var method = sym as Method;
if (method != null) {
@@ -500,10 +502,10 @@ public class Vala.MemberAccess : Expression {
} else if (member is Parameter) {
var param = (Parameter) member;
var m = param.parent_symbol as Method;
- if (m != null && m != context.analyzer.current_method_or_property_accessor && param
!= m.this_parameter) {
+ if (m != null && m != 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 = context.analyzer.current_method_or_property_accessor;
+ Symbol sym = current_method_or_property_accessor;
while (sym != m) {
var method = sym as Method;
if (method != null) {
@@ -521,10 +523,10 @@ public class Vala.MemberAccess : Expression {
}
} else {
var acc = param.parent_symbol.parent_symbol as PropertyAccessor;
- if (acc != null && acc !=
context.analyzer.current_method_or_property_accessor && param != acc.prop.this_parameter) {
+ if (acc != null && acc != 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 = context.analyzer.current_method_or_property_accessor;
+ Symbol sym = current_method_or_property_accessor;
while (sym != m) {
var method = sym as Method;
if (method != null) {
@@ -553,7 +555,7 @@ public class Vala.MemberAccess : Expression {
access = c.access;
var block = c.parent_symbol as Block;
- if (block != null && context.analyzer.find_parent_method_or_property_accessor (block)
!= context.analyzer.current_method_or_property_accessor) {
+ if (block != null && context.analyzer.get_current_method_or_property_accessor (block)
!= current_method_or_property_accessor) {
error = true;
Report.error (source_reference, "internal error: accessing local constants of
outer methods is not supported yet");
return false;
@@ -563,7 +565,7 @@ public class Vala.MemberAccess : Expression {
if (m.is_async_callback) {
// ensure to use right callback method for virtual/abstract async methods
// and also for lambda expressions within async methods
- var async_method = context.analyzer.current_async_method;
+ var async_method = context.analyzer.get_current_async_method (this);
bool is_valid_access = false;
if (async_method != null) {
@@ -581,14 +583,11 @@ public class Vala.MemberAccess : Expression {
return false;
}
- if (async_method != context.analyzer.current_method) {
- Symbol sym = context.analyzer.current_method;
- while (sym != async_method) {
- var method = sym as Method;
- if (method != null) {
- method.closure = true;
- }
- sym = sym.parent_symbol;
+ var current_method = context.analyzer.get_current_method (this);
+ if (async_method != current_method) {
+ while (current_method != async_method) {
+ current_method.closure = true;
+ current_method = context.analyzer.get_current_method
(current_method.parent_symbol);
}
async_method.body.captured = true;
}
@@ -704,7 +703,7 @@ public class Vala.MemberAccess : Expression {
var target_type = (TypeSymbol) member.parent_symbol;
bool in_subtype = false;
- for (Symbol this_symbol = context.analyzer.current_symbol; this_symbol != null;
this_symbol = this_symbol.parent_symbol) {
+ for (Symbol this_symbol = context.analyzer.get_current_symbol (this); this_symbol !=
null; this_symbol = this_symbol.parent_symbol) {
if (this_symbol == target_type) {
// required for interfaces with non-abstract methods
// accessing protected interface members
@@ -728,7 +727,7 @@ public class Vala.MemberAccess : Expression {
var target_type = member.parent_symbol;
bool in_target_type = false;
- for (Symbol this_symbol = context.analyzer.current_symbol; this_symbol != null;
this_symbol = this_symbol.parent_symbol) {
+ for (Symbol this_symbol = context.analyzer.get_current_symbol (this); this_symbol !=
null; this_symbol = this_symbol.parent_symbol) {
if (target_type == this_symbol) {
in_target_type = true;
break;
diff --git a/vala/valamethod.vala b/vala/valamethod.vala
index f79ec7b..c910669 100644
--- a/vala/valamethod.vala
+++ b/vala/valamethod.vala
@@ -688,14 +688,6 @@ public class Vala.Method : Subroutine, Callable {
return false;
}
- var old_source_file = context.analyzer.current_source_file;
- var old_symbol = context.analyzer.current_symbol;
-
- if (source_reference != null) {
- context.analyzer.current_source_file = source_reference.file;
- }
- context.analyzer.current_symbol = this;
-
return_type.check (context);
var init_attr = get_attribute ("ModuleInit");
@@ -761,7 +753,7 @@ public class Vala.Method : Subroutine, Callable {
body.check (context);
}
- if (context.analyzer.current_struct != null) {
+ if (context.analyzer.get_current_struct (this) != null) {
if (is_abstract || is_virtual || overrides) {
error = true;
Report.error (source_reference, "A struct member `%s' cannot be marked as
override, virtual, or abstract".printf (get_full_name ()));
@@ -789,9 +781,6 @@ public class Vala.Method : Subroutine, Callable {
}
}
- context.analyzer.current_source_file = old_source_file;
- context.analyzer.current_symbol = old_symbol;
-
if (!external_package && !overrides && !hides && get_hidden_member () != null) {
Report.warning (source_reference, "%s hides inherited method `%s'. Use the `new'
keyword if hiding was intentional".printf (get_full_name (), get_hidden_member ().get_full_name ()));
}
diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala
index 525042e..994d5b5 100644
--- a/vala/valamethodcall.vala
+++ b/vala/valamethodcall.vala
@@ -233,7 +233,7 @@ public class Vala.MethodCall : Expression {
CreationMethod base_cm = null;
if (is_chainup) {
- var cm = context.analyzer.find_current_method () as CreationMethod;
+ var cm = context.analyzer.get_current_method (this) as CreationMethod;
if (cm == null) {
error = true;
Report.error (source_reference, "invocation not supported in this context");
@@ -474,11 +474,12 @@ public class Vala.MethodCall : Expression {
error = true;
Report.error (source_reference, "yield expression requires async
method");
}
- if (context.analyzer.current_method == null ||
!context.analyzer.current_method.coroutine) {
+ var current_method = context.analyzer.get_current_method (this);
+ if (current_method == null || !current_method.coroutine) {
error = true;
Report.error (source_reference, "yield expression not available
outside async method");
}
- context.analyzer.current_method.yield_count++;
+ current_method.yield_count++;
}
if (m != null && m.coroutine && !is_yield_expression && ((MemberAccess)
call).member_name != "end") {
// .begin call of async method, no error can happen here
@@ -615,7 +616,7 @@ public class Vala.MethodCall : Expression {
if (may_throw) {
if (parent_node is LocalVariable || parent_node is ExpressionStatement) {
// simple statements, no side effects after method call
- } else if (!(context.analyzer.current_symbol is Block)) {
+ } else if (!(context.analyzer.get_current_symbol (this) is Block)) {
// can't handle errors in field initializers
Report.error (source_reference, "Field initializers must not throw errors");
} else {
@@ -625,7 +626,7 @@ public class Vala.MethodCall : Expression {
var local = new LocalVariable (value_type.copy (), get_temp_name (), null,
source_reference);
var decl = new DeclarationStatement (local, source_reference);
- insert_statement (context.analyzer.insert_block, decl);
+ insert_statement (context.analyzer.get_insert_block (this), decl);
var temp_access = SemanticAnalyzer.create_temp_access (local, target_type);
@@ -636,9 +637,9 @@ public class Vala.MethodCall : Expression {
// move temp variable to insert block to ensure the
// variable is in the same block as the declaration
// otherwise there will be scoping issues in the generated code
- var block = (Block) context.analyzer.current_symbol;
+ var block = context.analyzer.get_current_block (this);
block.remove_local_variable (local);
- context.analyzer.insert_block.add_local_variable (local);
+ context.analyzer.get_insert_block (this).add_local_variable (local);
old_parent_node.replace_expression (this, temp_access);
temp_access.check (context);
diff --git a/vala/valaobjectcreationexpression.vala b/vala/valaobjectcreationexpression.vala
index 869b649..49157c7 100644
--- a/vala/valaobjectcreationexpression.vala
+++ b/vala/valaobjectcreationexpression.vala
@@ -41,7 +41,13 @@ public class Vala.ObjectCreationExpression : Expression {
* The construction method to use or the data type to be created
* with the default construction method.
*/
- public MemberAccess member_name { get; set; }
+ public MemberAccess member_name {
+ get { return _member_name; }
+ set {
+ _member_name = value;
+ _member_name.parent_node = this;
+ }
+ }
public bool is_yield_expression { get; set; }
@@ -52,6 +58,7 @@ public class Vala.ObjectCreationExpression : Expression {
private List<MemberInitializer> object_initializer = new ArrayList<MemberInitializer> ();
private DataType _data_type;
+ private MemberAccess _member_name;
/**
* Creates a new object creation expression.
@@ -286,7 +293,7 @@ public class Vala.ObjectCreationExpression : Expression {
if (symbol_reference != null
&& (symbol_reference.access == SymbolAccessibility.PRIVATE ||
symbol_reference.access == SymbolAccessibility.PROTECTED)) {
bool in_target_type = false;
- for (Symbol this_symbol = context.analyzer.current_symbol; this_symbol !=
null; this_symbol = this_symbol.parent_symbol) {
+ for (Symbol this_symbol = context.analyzer.get_current_symbol (this);
this_symbol != null; this_symbol = this_symbol.parent_symbol) {
if (this_symbol == cl) {
in_target_type = true;
break;
@@ -354,11 +361,12 @@ public class Vala.ObjectCreationExpression : Expression {
error = true;
Report.error (source_reference, "yield expression requires async
method");
}
- if (context.analyzer.current_method == null ||
!context.analyzer.current_method.coroutine) {
+ var current_method = context.analyzer.get_current_method (this);
+ if (current_method == null || !current_method.coroutine) {
error = true;
Report.error (source_reference, "yield expression not available
outside async method");
}
- context.analyzer.current_method.yield_count++;
+ current_method.yield_count++;
}
// FIXME partial code duplication of MethodCall.check
@@ -482,7 +490,7 @@ public class Vala.ObjectCreationExpression : Expression {
if (may_throw) {
if (parent_node is LocalVariable || parent_node is ExpressionStatement) {
// simple statements, no side effects after method call
- } else if (!(context.analyzer.current_symbol is Block)) {
+ } else if (!(context.analyzer.get_current_symbol (this) is Block)) {
// can't handle errors in field initializers
Report.error (source_reference, "Field initializers must not throw errors");
} else {
@@ -492,7 +500,7 @@ public class Vala.ObjectCreationExpression : Expression {
var local = new LocalVariable (value_type.copy (), get_temp_name (), null,
source_reference);
var decl = new DeclarationStatement (local, source_reference);
- insert_statement (context.analyzer.insert_block, decl);
+ insert_statement (context.analyzer.get_insert_block (this), decl);
var temp_access = SemanticAnalyzer.create_temp_access (local, target_type);
// don't set initializer earlier as this changes parent_node and
parent_statement
@@ -502,9 +510,9 @@ public class Vala.ObjectCreationExpression : Expression {
// move temp variable to insert block to ensure the
// variable is in the same block as the declaration
// otherwise there will be scoping issues in the generated code
- var block = (Block) context.analyzer.current_symbol;
+ var block = context.analyzer.get_current_block (this);
block.remove_local_variable (local);
- context.analyzer.insert_block.add_local_variable (local);
+ context.analyzer.get_insert_block (this).add_local_variable (local);
old_parent_node.replace_expression (this, temp_access);
temp_access.check (context);
diff --git a/vala/valaparameter.vala b/vala/valaparameter.vala
index 3982071..c878287 100644
--- a/vala/valaparameter.vala
+++ b/vala/valaparameter.vala
@@ -132,14 +132,6 @@ public class Vala.Parameter : Variable {
checked = true;
- var old_source_file = context.analyzer.current_source_file;
- var old_symbol = context.analyzer.current_symbol;
-
- if (source_reference != null) {
- context.analyzer.current_source_file = source_reference.file;
- }
- context.analyzer.current_symbol = parent_symbol;
-
if (variable_type != null) {
if (variable_type is VoidType) {
error = true;
@@ -204,9 +196,6 @@ public class Vala.Parameter : Variable {
}
}
- context.analyzer.current_source_file = old_source_file;
- context.analyzer.current_symbol = old_symbol;
-
return !error;
}
}
diff --git a/vala/valaproperty.vala b/vala/valaproperty.vala
index bc6b18e..21aa2ed 100644
--- a/vala/valaproperty.vala
+++ b/vala/valaproperty.vala
@@ -424,14 +424,6 @@ public class Vala.Property : Symbol, Lockable {
}
}
- var old_source_file = context.analyzer.current_source_file;
- var old_symbol = context.analyzer.current_symbol;
-
- if (source_reference != null) {
- context.analyzer.current_source_file = source_reference.file;
- }
- context.analyzer.current_symbol = this;
-
if (property_type is VoidType) {
error = true;
Report.error (source_reference, "'void' not supported as property type");
@@ -484,9 +476,6 @@ public class Vala.Property : Symbol, Lockable {
Report.error (initializer.source_reference, "Expected initializer of type `%s' but
got `%s'".printf (property_type.to_string (), initializer.value_type.to_string ()));
}
- context.analyzer.current_source_file = old_source_file;
- context.analyzer.current_symbol = old_symbol;
-
return !error;
}
}
diff --git a/vala/valapropertyaccessor.vala b/vala/valapropertyaccessor.vala
index 81981b8..ccc1be5 100644
--- a/vala/valapropertyaccessor.vala
+++ b/vala/valapropertyaccessor.vala
@@ -150,10 +150,6 @@ public class Vala.PropertyAccessor : Subroutine {
return false;
}
- var old_symbol = context.analyzer.current_symbol;
-
- context.analyzer.current_symbol = this;
-
if (writable || construction) {
value_parameter = new Parameter ("value", value_type, source_reference);
}
@@ -198,8 +194,6 @@ public class Vala.PropertyAccessor : Subroutine {
}
}
- context.analyzer.current_symbol = old_symbol;
-
return !error;
}
diff --git a/vala/valareturnstatement.vala b/vala/valareturnstatement.vala
index e407aec..9cc8017 100644
--- a/vala/valareturnstatement.vala
+++ b/vala/valareturnstatement.vala
@@ -77,8 +77,10 @@ public class Vala.ReturnStatement : CodeNode, Statement {
checked = true;
+ var current_return_type = context.analyzer.get_current_return_type (this);
+
if (return_expression != null) {
- return_expression.target_type = context.analyzer.current_return_type;
+ return_expression.target_type = current_return_type;
}
if (return_expression != null && !return_expression.check (context)) {
@@ -87,21 +89,21 @@ public class Vala.ReturnStatement : CodeNode, Statement {
return false;
}
- if (context.analyzer.current_return_type == null) {
+ if (current_return_type == null) {
error = true;
Report.error (source_reference, "Return not allowed in this context");
return false;
}
if (return_expression == null) {
- if (!(context.analyzer.current_return_type is VoidType)) {
+ if (!(current_return_type is VoidType)) {
error = true;
Report.error (source_reference, "Return without value in non-void function");
}
return !error;
}
- if (context.analyzer.current_return_type is VoidType) {
+ if (current_return_type is VoidType) {
Report.error (source_reference, "Return with value in void function");
return false;
}
@@ -112,14 +114,14 @@ public class Vala.ReturnStatement : CodeNode, Statement {
return false;
}
- if (!return_expression.value_type.compatible (context.analyzer.current_return_type)) {
+ if (!return_expression.value_type.compatible (current_return_type)) {
error = true;
- Report.error (source_reference, "Return: Cannot convert from `%s' to `%s'".printf
(return_expression.value_type.to_string (), context.analyzer.current_return_type.to_string ()));
+ Report.error (source_reference, "Return: Cannot convert from `%s' to `%s'".printf
(return_expression.value_type.to_string (), current_return_type.to_string ()));
return false;
}
if (return_expression.value_type.is_disposable () &&
- !context.analyzer.current_return_type.value_owned) {
+ !current_return_type.value_owned) {
error = true;
Report.error (source_reference, "Return value transfers ownership but method return
type hasn't been declared to transfer ownership");
return false;
@@ -127,15 +129,15 @@ public class Vala.ReturnStatement : CodeNode, Statement {
var local = return_expression.symbol_reference as LocalVariable;
if (local != null && local.variable_type.is_disposable () &&
- !context.analyzer.current_return_type.value_owned) {
+ !current_return_type.value_owned) {
error = true;
Report.error (source_reference, "Local variable with strong reference used as return
value and method return type has not been declared to transfer ownership");
return false;
}
if (return_expression is NullLiteral
- && !context.analyzer.current_return_type.nullable) {
- Report.warning (source_reference, "`null' incompatible with return type `%s`".printf
(context.analyzer.current_return_type.to_string ()));
+ && !current_return_type.nullable) {
+ Report.warning (source_reference, "`null' incompatible with return type `%s`".printf
(current_return_type.to_string ()));
}
add_error_types (return_expression.get_error_types ());
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index f3b1a63..03d5253 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -31,107 +31,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
public CodeContext context { get; set; }
public Symbol root_symbol;
- public Symbol current_symbol { get; set; }
- public SourceFile current_source_file { get; set; }
-
- public TypeSymbol? current_type_symbol {
- get {
- var sym = current_symbol;
- while (sym != null) {
- if (sym is TypeSymbol) {
- return (TypeSymbol) sym;
- }
- sym = sym.parent_symbol;
- }
- return null;
- }
- }
-
- public Class? current_class {
- get { return current_type_symbol as Class; }
- }
-
-
- public Struct? current_struct {
- get { return current_type_symbol as Struct; }
- }
-
- public Method? current_method {
- get {
- unowned Symbol sym = current_symbol;
- while (sym is Block) {
- sym = sym.parent_symbol;
- }
- return sym as Method;
- }
- }
-
- public Method? current_async_method {
- get {
- unowned Symbol sym = current_symbol;
- while (sym is Block || sym is Method) {
- var m = sym as Method;
- if (m != null && m.coroutine) {
- break;
- }
-
- sym = sym.parent_symbol;
- }
- return sym as Method;
- }
- }
-
- public PropertyAccessor? current_property_accessor {
- get {
- unowned Symbol sym = current_symbol;
- while (sym is Block) {
- sym = sym.parent_symbol;
- }
- return sym as PropertyAccessor;
- }
- }
-
- 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;
- if (m != null) {
- return m.return_type;
- }
-
- var acc = current_property_accessor;
- if (acc != null) {
- if (acc.readable) {
- return acc.value_type;
- } else {
- return void_type;
- }
- }
-
- if (is_in_constructor () || is_in_destructor ()) {
- return void_type;
- }
-
- return null;
- }
- }
-
- public Block insert_block;
public DataType void_type = new VoidType ();
public DataType bool_type;
@@ -221,17 +120,120 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
gsource_type = (Class) glib_ns.scope.lookup ("Source");
- current_symbol = root_symbol;
context.root.check (context);
context.accept (this);
}
public override void visit_source_file (SourceFile file) {
- current_source_file = file;
-
file.check (context);
}
+ public unowned Symbol get_current_symbol (CodeNode node) {
+ while (!(node is Symbol) || is_local_symbol ((Symbol) node)) {
+ node = node.parent_node;
+ }
+ return (Symbol) node;
+ }
+
+ public bool is_local_symbol (Symbol sym) {
+ if (sym is LocalVariable) {
+ return true;
+ }
+ if (sym is Constant && sym.parent_symbol is Block) {
+ return true;
+ }
+ return false;
+ }
+
+ public unowned TypeSymbol? get_current_type_symbol (CodeNode node) {
+ unowned Symbol sym = get_current_symbol (node);
+ while (sym != null && !(sym is TypeSymbol)) {
+ sym = sym.parent_symbol;
+ }
+ return (TypeSymbol) sym;
+ }
+
+ public unowned Class? get_current_class (CodeNode node) {
+ return get_current_type_symbol (node) as Class;
+ }
+
+
+ public unowned Struct? get_current_struct (CodeNode node) {
+ return get_current_type_symbol (node) as Struct;
+ }
+
+ public unowned Method? get_current_method (CodeNode node) {
+ unowned Symbol sym = get_current_symbol (node);
+ while (sym is Block) {
+ sym = sym.parent_symbol;
+ }
+ return sym as Method;
+ }
+
+ public unowned Method? get_current_async_method (CodeNode node) {
+ unowned Method m = get_current_method (node);
+ while (m != null && !m.coroutine) {
+ m = get_current_method (m.parent_symbol);
+ }
+ return m;
+ }
+
+ public unowned PropertyAccessor? get_current_property_accessor (CodeNode node) {
+ unowned Symbol sym = get_current_symbol (node);
+ while (sym is Block) {
+ sym = sym.parent_symbol;
+ }
+ return sym as PropertyAccessor;
+ }
+
+ public unowned Symbol? get_current_method_or_property_accessor (CodeNode node) {
+ unowned Symbol sym = get_current_symbol (node);
+ 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 unowned DataType? get_current_return_type (CodeNode node) {
+ unowned Method m = get_current_method (node);
+ if (m != null) {
+ return m.return_type;
+ }
+
+ unowned PropertyAccessor acc = get_current_property_accessor (node);
+ if (acc != null) {
+ if (acc.readable) {
+ return acc.value_type;
+ } else {
+ return void_type;
+ }
+ }
+
+ if (is_in_constructor (node) || is_in_destructor (node)) {
+ return void_type;
+ }
+
+ return null;
+ }
+
+ public unowned Block? get_current_block (CodeNode node) {
+ return get_current_symbol (node) as Block;
+ }
+
+ public unowned Block? get_insert_block (CodeNode node) {
+ unowned Block? block = get_current_block (node);
+ if (block is ForeachStatement) {
+ block = block.parent_symbol as Block;
+ }
+ return block;
+ }
+
// check whether type is at least as accessible as the specified symbol
public bool is_type_accessible (Symbol sym, DataType type) {
return type.is_accessible (sym);
@@ -867,8 +869,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
return actual_type;
}
- public bool is_in_instance_method () {
- var sym = current_symbol;
+ public bool is_in_instance_method (CodeNode node) {
+ unowned Symbol sym = get_current_symbol (node);
while (sym != null) {
if (sym is CreationMethod) {
return true;
@@ -985,39 +987,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
}
}
- public Method? find_current_method () {
- var sym = current_symbol;
- while (sym != null) {
- if (sym is Method) {
- return (Method) sym;
- }
- sym = sym.parent_symbol;
- }
- return null;
- }
-
- public Method? find_parent_method (Symbol sym) {
- while (sym is Block) {
- sym = sym.parent_symbol;
- }
- 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;
+ public bool is_in_constructor (CodeNode node) {
+ unowned Symbol sym = get_current_symbol (node);
while (sym != null) {
if (sym is Constructor) {
return true;
@@ -1027,8 +998,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
return false;
}
- public bool is_in_destructor () {
- var sym = current_symbol;
+ public bool is_in_destructor (CodeNode node) {
+ unowned Symbol sym = get_current_symbol (node);
while (sym != null) {
if (sym is Destructor) {
return true;
diff --git a/vala/valastruct.vala b/vala/valastruct.vala
index 21985d7..feff638 100644
--- a/vala/valastruct.vala
+++ b/vala/valastruct.vala
@@ -481,14 +481,6 @@ public class Vala.Struct : TypeSymbol {
checked = true;
- var old_source_file = context.analyzer.current_source_file;
- var old_symbol = context.analyzer.current_symbol;
-
- if (source_reference != null) {
- context.analyzer.current_source_file = source_reference.file;
- }
- context.analyzer.current_symbol = this;
-
if (base_type != null) {
base_type.check (context);
@@ -546,9 +538,6 @@ public class Vala.Struct : TypeSymbol {
}
}
- context.analyzer.current_source_file = old_source_file;
- context.analyzer.current_symbol = old_symbol;
-
return !error;
}
}
diff --git a/vala/valasubroutine.vala b/vala/valasubroutine.vala
index 73cab98..0ef8bf3 100644
--- a/vala/valasubroutine.vala
+++ b/vala/valasubroutine.vala
@@ -45,7 +45,7 @@ public abstract class Vala.Subroutine : Symbol {
set {
_body = value;
if (_body != null) {
- _body.owner = scope;
+ _body.parent_node = this;
}
}
}
diff --git a/vala/valaswitchlabel.vala b/vala/valaswitchlabel.vala
index 9468b0e..d6e5541 100644
--- a/vala/valaswitchlabel.vala
+++ b/vala/valaswitchlabel.vala
@@ -29,9 +29,19 @@ public class Vala.SwitchLabel : CodeNode {
/**
* Specifies the label expression.
*/
- public Expression expression { get; set; }
+ public Expression expression {
+ get { return _expression; }
+ set {
+ _expression = value;
+ _expression.parent_node = this;
+ }
+ }
+
+ public weak SwitchSection section {
+ get { return (SwitchSection) parent_node; }
+ }
- public weak SwitchSection section { get; set; }
+ private Expression _expression;
/**
* Creates a new switch case label.
diff --git a/vala/valaswitchsection.vala b/vala/valaswitchsection.vala
index bf9932f..0e8395d 100644
--- a/vala/valaswitchsection.vala
+++ b/vala/valaswitchsection.vala
@@ -49,7 +49,7 @@ public class Vala.SwitchSection : Block {
}
labels.add (label);
- label.section = this;
+ label.parent_node = this;
}
/**
@@ -92,17 +92,12 @@ public class Vala.SwitchSection : Block {
checked = true;
+ owner = context.analyzer.get_current_symbol (parent_node).scope;
+
foreach (SwitchLabel label in get_labels ()) {
label.check (context);
}
- owner = context.analyzer.current_symbol.scope;
-
- var old_symbol = context.analyzer.current_symbol;
- var old_insert_block = context.analyzer.insert_block;
- context.analyzer.current_symbol = this;
- context.analyzer.insert_block = this;
-
foreach (Statement st in get_statements ()) {
st.check (context);
}
@@ -116,9 +111,6 @@ public class Vala.SwitchSection : Block {
add_error_types (stmt.get_error_types ());
}
- context.analyzer.current_symbol = old_symbol;
- context.analyzer.insert_block = old_insert_block;
-
return !error;
}
diff --git a/vala/valaunlockstatement.vala b/vala/valaunlockstatement.vala
index ff2f401..c9f8ff7 100644
--- a/vala/valaunlockstatement.vala
+++ b/vala/valaunlockstatement.vala
@@ -58,7 +58,7 @@ public class Vala.UnlockStatement : CodeNode, Statement {
}
/* parent symbol must be the current class */
- if (resource.symbol_reference.parent_symbol != context.analyzer.current_class) {
+ if (resource.symbol_reference.parent_symbol != context.analyzer.get_current_class (this)) {
error = true;
resource.error = true;
Report.error (resource.source_reference, "Only members of the current class are
lockable");
diff --git a/vala/valayieldstatement.vala b/vala/valayieldstatement.vala
index 8b2069f..084ae26 100644
--- a/vala/valayieldstatement.vala
+++ b/vala/valayieldstatement.vala
@@ -75,7 +75,7 @@ public class Vala.YieldStatement : CodeNode, Statement {
error = yield_expression.error;
}
- context.analyzer.current_method.yield_count++;
+ context.analyzer.get_current_method (this).yield_count++;
return !error;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]