]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Make the semantic analyzer be stateless
authorLuca Bruno <lucabru@src.gnome.org>
Sat, 6 Aug 2011 08:38:59 +0000 (10:38 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Mon, 11 Mar 2019 12:46:57 +0000 (13:46 +0100)
32 files changed:
vala/valaassignment.vala
vala/valabaseaccess.vala
vala/valabinaryexpression.vala
vala/valablock.vala
vala/valacatchclause.vala
vala/valaclass.vala
vala/valaconditionalexpression.vala
vala/valaconstant.vala
vala/valaconstructor.vala
vala/valacreationmethod.vala
vala/valadelegate.vala
vala/valadestructor.vala
vala/valaenum.vala
vala/valafield.vala
vala/valaforeachstatement.vala
vala/valainterface.vala
vala/valalambdaexpression.vala
vala/valalocalvariable.vala
vala/valalockstatement.vala
vala/valamemberaccess.vala
vala/valamethod.vala
vala/valamethodcall.vala
vala/valaobjectcreationexpression.vala
vala/valaparameter.vala
vala/valaproperty.vala
vala/valapropertyaccessor.vala
vala/valareturnstatement.vala
vala/valasemanticanalyzer.vala
vala/valastruct.vala
vala/valasubroutine.vala
vala/valaswitchsection.vala
vala/valaunlockstatement.vala

index 0b6fbc9adafb19c31efe0f803ead5f14eefdc87e..95cbcaf972bc47aa5da58de947558109088ed087 100644 (file)
@@ -117,19 +117,21 @@ 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);
-                       insert_statement (context.analyzer.insert_block, decl);
+                       insert_statement (insert_block, decl);
                        decl.check (context);
 
                        int i = 0;
                        ExpressionStatement stmt = null;
                        foreach (var expr in tuple.get_expressions ()) {
                                if (stmt != null) {
-                                       insert_statement (context.analyzer.insert_block, stmt);
+                                       insert_statement (insert_block, stmt);
                                        stmt.check (context);
                                }
 
@@ -165,7 +167,7 @@ public class Vala.Assignment : Expression {
                        }
 
                        if ((!(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;
@@ -272,15 +274,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;
index 955233bdc4fae5a0c0c84665b388e2c2f57e44ca..613990e0f77e6405ed1f865bfb7175c3ee137153 100644 (file)
@@ -56,38 +56,43 @@ 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);
+               var current_method = context.analyzer.get_current_method (this);
+               var current_property_accessor = context.analyzer.get_current_property_accessor (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 if (context.analyzer.current_class.is_compact && context.analyzer.current_method != null
-                   && !(context.analyzer.current_method is CreationMethod)) {
+               } else if (current_class.is_compact && current_method != null
+                   && !(current_method is CreationMethod)) {
                        error = true;
                        Report.error (source_reference, "Base access invalid in virtual overridden method of compact class");
                        return false;
-               } else if (context.analyzer.current_class.is_compact && context.analyzer.current_property_accessor != null) {
+               } else if (current_class.is_compact && current_property_accessor != null) {
                        error = true;
                        Report.error (source_reference, "Base access invalid in virtual overridden property of compact 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;
index 0dd61b6c19450bba83a6b22a2167f22e40303c7c..84f6a7437bd5c1fb6ff177586d13cd34ff04d43e 100644 (file)
@@ -140,9 +140,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_non_local_symbol (this) is Block
                    && (operator == BinaryOperator.AND || operator == BinaryOperator.OR)) {
                        // convert conditional expression into if statement
                        // required for flow analysis and exception handling
@@ -167,8 +169,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);
 
@@ -242,8 +244,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;
index 7419b5b9defeb79fe64986578ac4f3f2fa472a39..72e7801e2e66e4faefb45c992eb9fa2952e08e6e 100644 (file)
@@ -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);
        }
 
        /**
@@ -151,12 +153,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_non_local_symbol (parent_node).scope;
 
                for (int i = 0; i < statement_list.size; i++) {
                        statement_list[i].check (context);
@@ -170,9 +167,6 @@ public class Vala.Block : Symbol, Statement {
                        constant.active = false;
                }
 
-               context.analyzer.current_symbol = old_symbol;
-               context.analyzer.insert_block = old_insert_block;
-
                return !error;
        }
 
index 1ff94211620120701e6c1e06064ce048121a66f3..8c0b3253849dbf9129a6165332216f489ed887c0 100644 (file)
@@ -131,7 +131,6 @@ public class Vala.CatchClause : CodeNode {
                        if (variable_name != null) {
                                error_variable = new LocalVariable (error_type.copy (), variable_name, null, source_reference);
 
-                               body.scope.add (variable_name, error_variable);
                                body.add_local_variable (error_variable);
 
                                error_variable.checked = true;
index 51e8fbade672c685e592020da05bd07e53dc54eb..31615cbbd1fbb1a2e3e0d93ab5e480e67bc543dd 100644 (file)
@@ -522,14 +522,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;
@@ -819,9 +811,6 @@ public class Vala.Class : ObjectTypeSymbol {
                        }
                }
 
-               context.analyzer.current_source_file = old_source_file;
-               context.analyzer.current_symbol = old_symbol;
-
                return !error;
        }
 }
index 3395dd56f5dc7df04f61e9ba9975790f828e0e2b..b6884f616ac1943384385120ad14c610d4e70448 100644 (file)
@@ -145,7 +145,7 @@ public class Vala.ConditionalExpression : Expression {
 
                checked = true;
 
-               if (!(context.analyzer.current_symbol is Block)) {
+               if (!(context.analyzer.get_current_non_local_symbol (this) is Block)) {
                        Report.error (source_reference, "Conditional expressions may only be used in blocks");
                        error = true;
                        return false;
@@ -174,8 +174,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;
index 0a9266cf178f701560096bb003f6abc93b2fa0d3..bf6635e1876d202a3e806beef0b78f9fbe8312b6 100644 (file)
@@ -102,17 +102,6 @@ public class Vala.Constant : Symbol {
 
                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)) {
@@ -171,9 +160,6 @@ public class Vala.Constant : Symbol {
                        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;
index ae8f19e8da8e9a43ce3fb384946f92973199be6e..86f24de3f5e56afbf82accc2d8b4994f4472fd07 100644 (file)
@@ -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);
                }
@@ -85,8 +82,6 @@ public class Vala.Constructor : Subroutine {
                        }
                }
 
-               context.analyzer.current_symbol = context.analyzer.current_symbol.parent_symbol;
-
                return !error;
        }
 }
index ae8daab3853a5e046daa2528187e82d237baa616..e201624a93a6bda1c50100827abf3d9d7eb433c0 100644 (file)
@@ -88,19 +88,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 (parent_node).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;
-
                int i = 0;
                foreach (Parameter param in get_parameters()) {
                        param.check (context);
@@ -135,40 +127,23 @@ public class Vala.CreationMethod : Method {
                                if (context.profile == Profile.GOBJECT
                                    && 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;
index 4b4e7074ab4ea0a4f436f98ce42e68a6eaa75a58..039f6a5c6a72f25ee32d3cfe807d923942f8db42 100644 (file)
@@ -293,12 +293,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);
                }
@@ -315,8 +309,6 @@ public class Vala.Delegate : TypeSymbol, Callable {
                        }
                }
 
-               context.analyzer.current_source_file = old_source_file;
-
                return !error;
        }
 }
index 7ee3843bd0e80b8b7597d5dad2464d3ea944b0e3..ddfb0f9ea3db1e24b80e58c269e409b56603a07d 100644 (file)
@@ -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;
        }
 }
index 508ef12ef249998b238d248afec32231600b61fe..15cb2c83084cc4680280948fd268fe9c46cfa1f6 100644 (file)
@@ -158,14 +158,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;
-
                if (values.size <= 0) {
                        Report.error (source_reference, "Enum `%s' requires at least one value".printf (get_full_name ()));
                        error = true;
@@ -184,9 +176,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;
        }
 }
index 6bd54ff95b376cae725b98a02658c029389d9a08..fd2082d7161f7b7864e6b588f226bc20c9e75875 100644 (file)
@@ -84,14 +84,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");
@@ -189,9 +181,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;
        }
 }
index 67063bbe1759151cc76ae7203e753bfb07af75e1..ada291ccd7360ccb2cfce343bf5cc1e1216f99f1 100644 (file)
@@ -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);
index f6c503641797475d38d9ef706550b7001d5d2b85..61d1e50efdc220bb26a5e3babb09892824fe83f7 100644 (file)
@@ -194,14 +194,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)) {
@@ -364,9 +356,6 @@ public class Vala.Interface : ObjectTypeSymbol {
                        }
                }
 
-               context.analyzer.current_source_file = old_source_file;
-               context.analyzer.current_symbol = old_symbol;
-
                return !error;
        }
 }
index a22497e70a94623f2a21baf4052b70afdab50372..5e8fcee079d1afc643d778c86b5ed6f662238122 100644 (file)
@@ -137,10 +137,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;
@@ -159,7 +159,7 @@ public class Vala.LambdaExpression : Expression {
                                sym = sym.parent_symbol;
                        }
                }
-               method.owner = context.analyzer.current_symbol.scope;
+               method.owner = context.analyzer.get_current_non_local_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));
index 3a2ecae0155f4e511a50aff55de696126d2962ef..acc6a36070d5c0ada1073f561068f64f45dde3dd 100644 (file)
@@ -92,6 +92,16 @@ public class Vala.LocalVariable : Variable {
                        }
                }
 
+               // current_symbol is a Method if this is the `result'
+               // variable used for postconditions
+               var block = context.analyzer.get_current_block (this);
+               if (block != null) {
+                       /* so that we can use parent_symbol */
+                       block.add_local_variable (this);
+               }
+
+               active = false;
+
                if (variable_type != null) {
                        if (variable_type is VoidType) {
                                error = true;
@@ -211,15 +221,6 @@ 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;
-               if (block != null) {
-                       block.add_local_variable (this);
-               }
-
                active = true;
 
                return !error;
index e64d4a206956eb3fab99c2b8a9b7116cb08c75ea..be942acee71b04da5102ab02e988f14bb60da2c6 100644 (file)
@@ -114,7 +114,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");
@@ -122,7 +122,7 @@ public class Vala.LockStatement : CodeNode, Statement {
                }
 
                /* parent class must not be compact */
-               if (context.analyzer.current_class.is_compact) {
+               if (context.analyzer.get_current_class (this).is_compact) {
                        error = true;
                        resource.error = true;
                        Report.error (resource.source_reference, "Only members of the non-compact classes are lockable");
index dfd68a4aa65c2c54c316d5c20207169265861bf9..41b33693496f48af7162464fb9df26fc7f648c1f 100644 (file)
@@ -226,20 +226,20 @@ public class Vala.MemberAccess : Expression {
                        symbol_reference = base_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_non_local_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) {
@@ -484,13 +484,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) {
@@ -508,10 +510,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) {
@@ -529,10 +531,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) {
@@ -561,7 +563,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;
@@ -571,7 +573,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) {
@@ -589,14 +591,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;
                                }
@@ -715,7 +714,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_non_local_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
@@ -739,7 +738,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_non_local_symbol (this); this_symbol != null; this_symbol = this_symbol.parent_symbol) {
                                if (target_type == this_symbol) {
                                        in_target_type = true;
                                        break;
index 22980085f028102b5266def1e231349b3d8c3300..65bc183a6eb18ca1dbfd3bf943749f08652eda49 100644 (file)
@@ -771,14 +771,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.floating_reference = returns_floating_reference;
                return_type.check (context);
 
@@ -862,7 +854,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 ()));
@@ -890,9 +882,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 ()));
                }
index 80d0d772f5a961d6a1beab77d853b0a389741e57..041d096d2afc5c6b0d5086e083319a223472711b 100644 (file)
@@ -258,7 +258,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");
@@ -518,7 +518,8 @@ 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");
                                }
@@ -645,7 +646,7 @@ public class Vala.MethodCall : Expression {
                if (tree_can_fail) {
                        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_non_local_symbol (this) is Block)) {
                                // can't handle errors in field initializers
                                Report.error (source_reference, "Field initializers must not throw errors");
                        } else {
@@ -655,7 +656,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);
 
@@ -666,9 +667,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);
index 0b6a29391f1fb9ddb3b8b6a6dd94bbd098b4e1c3..4f30f5b84b5d3903c0bcee7ccb692611d85d060d 100644 (file)
@@ -293,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_non_local_symbol (this); this_symbol != null; this_symbol = this_symbol.parent_symbol) {
                                        if (this_symbol == cl) {
                                                in_target_type = true;
                                                break;
@@ -361,7 +361,8 @@ 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");
                                }
@@ -484,7 +485,7 @@ public class Vala.ObjectCreationExpression : Expression {
                if (tree_can_fail) {
                        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_non_local_symbol (this) is Block)) {
                                // can't handle errors in field initializers
                                Report.error (source_reference, "Field initializers must not throw errors");
                        } else {
@@ -494,7 +495,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
@@ -504,9 +505,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);
index 7c13a7c194922be56eab5877a2149e6e69483d9e..3c8bb0f09b6c1381b55566f457d75cda9afb60df 100644 (file)
@@ -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;
        }
 }
index cd1bcaff54692fd041759f090779cae2a2abbe86..c4ab84c44b009329cded0b2433c848aeefd40b3f 100644 (file)
@@ -450,14 +450,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");
@@ -514,9 +506,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;
        }
 }
index e348c2510f555354af31d4b56580dec96b43d627..019e993dff64c5ca08560dd359b5ac775d1c213e 100644 (file)
@@ -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);
                }
@@ -206,8 +202,6 @@ public class Vala.PropertyAccessor : Subroutine {
                        }
                }
 
-               context.analyzer.current_symbol = old_symbol;
-
                return !error;
        }
 
index f51164968d69d81c99a22598674ab83afc49dfc6..e4fa6b506421c3481d71e6d71a1471c3ef246a3e 100644 (file)
@@ -83,8 +83,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.copy ();
+                       return_expression.target_type = current_return_type.copy ();
                }
 
                if (return_expression != null && !return_expression.check (context)) {
@@ -93,21 +95,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;
                }
@@ -118,14 +120,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;
@@ -133,15 +135,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 ()));
                }
 
                return !error;
index 485ab222dad6082b84bf73041bc82cb43d4e8509..3f3388851b0595b888f6073add41d7084df622c5 100644 (file)
@@ -30,108 +30,6 @@ using GLib;
 public class Vala.SemanticAnalyzer : CodeVisitor {
        CodeContext context;
 
-       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;
        public DataType string_type;
@@ -219,7 +117,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        gsource_type = (Class) glib_ns.scope.lookup ("Source");
                }
 
-               current_symbol = root_symbol;
                context.root.check (context);
                context.accept (this);
 
@@ -227,11 +124,122 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        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 != null && !(node is Symbol)) {
+                       node = node.parent_node;
+               }
+               return (Symbol) node;
+       }
+
+       public unowned Symbol? get_current_non_local_symbol (CodeNode node) {
+               while (node != null && (!(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 || (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 != null && !(sym is Method)) {
+                       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 != null && !(sym is PropertyAccessor)) {
+                       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 != null && !(sym is Method) && !(sym is PropertyAccessor)) {
+                       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) {
+               while (node != null && !(node is Block)) {
+                       node = node.parent_node;
+               }
+               return (Block) node;
+       }
+
+       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);
@@ -903,8 +911,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;
@@ -1021,39 +1029,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;
@@ -1063,8 +1040,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;
index c96632805221ba5e52d61ab56d538b28490e6cb7..e47bc3f2435db198b02de6710f7f3bbc203ce8d9 100644 (file)
@@ -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);
 
@@ -564,9 +556,6 @@ public class Vala.Struct : TypeSymbol {
                        }
                }
 
-               context.analyzer.current_source_file = old_source_file;
-               context.analyzer.current_symbol = old_symbol;
-
                return !error;
        }
 }
index e9c05ac23feefa109413ad2c514a78c1482c270e..0ef8bf333008497445406ae0f617bd03e744a904 100644 (file)
@@ -45,7 +45,6 @@ public abstract class Vala.Subroutine : Symbol {
                set {
                        _body = value;
                        if (_body != null) {
-                               _body.owner = scope;
                                _body.parent_node = this;
                        }
                }
index 2b6bc60ab73ed9b87ebbc3dc3c6cade939451fad..9e94edea10741cadbdc944a6dba2175bdbbe174b 100644 (file)
@@ -99,17 +99,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);
                }
@@ -118,9 +113,6 @@ public class Vala.SwitchSection : Block {
                        local.active = false;
                }
 
-               context.analyzer.current_symbol = old_symbol;
-               context.analyzer.insert_block = old_insert_block;
-
                return !error;
        }
 
index d60d5706c5439a4b211137804162c2a527852e34..e97458ea8e8648698b184239ac029e4b9d97bddb 100644 (file)
@@ -72,7 +72,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");
@@ -80,7 +80,7 @@ public class Vala.UnlockStatement : CodeNode, Statement {
                }
 
                /* parent class must not be compact */
-               if (context.analyzer.current_class.is_compact) {
+               if (context.analyzer.get_current_class (this).is_compact) {
                        error = true;
                        resource.error = true;
                        Report.error (resource.source_reference, "Only members of the non-compact classes are lockable");