]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Make SemanticAnalyzer be stateless
authorLuca Bruno <lucabru@src.gnome.org>
Sat, 6 Aug 2011 08:38:59 +0000 (10:38 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 1 Apr 2020 08:17:51 +0000 (10:17 +0200)
33 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
vala/valayieldstatement.vala

index e67860825cf8212d01a222c72b0b51091f1b22ba..4c1f4bfdf62aef6b2598e6f721d0652404ede29e 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) {
                        unowned Tuple 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;
@@ -273,15 +275,16 @@ public class Vala.Assignment : Expression {
                                        left.value_type = dynamic_prop.property_type.copy ();
                                }
 
+                               unowned Method? 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
                                                error = true;
                                                Report.error (ma.source_reference, "Property `%s' is read-only".printf (prop.get_full_name ()));
index 68a3cb8f970f9c078cbea0e34f10e00f58dfb2e1..49e7cf5074fa9a5c4bd023fad05775c2fc66da2c 100644 (file)
@@ -56,40 +56,44 @@ 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) {
+               unowned Class? current_class = context.analyzer.get_current_class (this);
+               unowned Struct? current_struct = context.analyzer.get_current_struct (this);
+               unowned Method? current_method = context.analyzer.get_current_method (this);
+               unowned PropertyAccessor? 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)
-                   && (context.analyzer.current_method.overrides || context.analyzer.current_method.is_virtual)) {
+               } else if (current_class.is_compact && current_method != null
+                   && !(current_method is CreationMethod)
+                   && (current_method.overrides || current_method.is_virtual)) {
                        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
-                   && (context.analyzer.current_property_accessor.prop.overrides || context.analyzer.current_property_accessor.prop.is_virtual)) {
+               } 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.type_symbol is Class) {
                                        value_type = base_type.copy ();
                                        value_type.value_owned = false;
index bfcaba2abb2fc2b5fe02528b5f96cc7e7b35ee95..7f24a4bdafc66bf1b6fa902e962e42c17ac1f15d 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);
 
@@ -254,7 +256,7 @@ public class Vala.BinaryExpression : Expression {
                        var local = new LocalVariable (local_type, temp_name, left, source_reference);
                        var decl = new DeclarationStatement (local, source_reference);
 
-                       insert_statement (context.analyzer.insert_block, decl);
+                       insert_statement (insert_block, decl);
 
                        if (!decl.check (context)) {
                                error = true;
@@ -276,7 +278,7 @@ public class Vala.BinaryExpression : Expression {
 
                        var if_stmt = new IfStatement (cond, true_block, null, source_reference);
 
-                       insert_statement (context.analyzer.insert_block, if_stmt);
+                       insert_statement (insert_block, if_stmt);
 
                        if (!if_stmt.check (context)) {
                                error = true;
index a702ea0117bca185e7bd3285255b9ab4021428ee..3035bc77bb58f37a9eb561f23d3b5b189b67051f 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++) {
                        if (!statement_list[i].check (context)) {
@@ -172,9 +169,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 586fe287f86a6a23d33260404fdc38a6b6272b84..12567c72051c4e0caf8bfca1d423b53e90884c68 100644 (file)
@@ -524,14 +524,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;
@@ -848,9 +840,6 @@ public class Vala.Class : ObjectTypeSymbol {
                        }
                }
 
-               context.analyzer.current_source_file = old_source_file;
-               context.analyzer.current_symbol = old_symbol;
-
                return !error;
        }
 }
index db9342c4eb1e178d2acaafaaa37271f75b416f4f..438d44cc1073d50314014f421a4dafbb8bff19f2 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 b0beddc2b3d7ff437d80310d353c13f610130bad..35fd1617b310431c5eb8cafb48f98ea90a4205e5 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)) {
@@ -174,9 +163,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 a867f3a397366a32aa7c9407a7e2dcd9bd85d577..080239af9077e8fad7c3ec76dd1e7ce5f3ee0d64 100644 (file)
@@ -71,8 +71,6 @@ public class Vala.Constructor : Subroutine {
                        this_parameter.check (context);
                }
 
-               context.analyzer.current_symbol = this;
-
                if (body != null) {
                        body.check (context);
                }
@@ -87,8 +85,6 @@ public class Vala.Constructor : Subroutine {
                        }
                }
 
-               context.analyzer.current_symbol = parent_symbol;
-
                return !error;
        }
 }
index 23d40fd393e33327c0fb191d80482b336a7064a3..e6301209e5ed7031d91aceecce36b73472002ab9 100644 (file)
@@ -88,7 +88,7 @@ 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;
                }
@@ -97,14 +97,6 @@ public class Vala.CreationMethod : Method {
                        this_parameter.check (context);
                }
 
-               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()) {
                        if (!param.check (context)) {
@@ -141,40 +133,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) {
                        error = true;
                        Report.error (source_reference, "The creation method `%s' cannot be marked as override, virtual, or abstract".printf (get_full_name ()));
index abe9f86348cafd0fac9b5e355c6f845eb4794471..f9b89ebd5ffd927c9182879c6ecc3c3aea133f74 100644 (file)
@@ -299,12 +299,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);
                }
@@ -329,8 +323,6 @@ public class Vala.Delegate : TypeSymbol, Callable {
                        }
                }
 
-               context.analyzer.current_source_file = old_source_file;
-
                return !error;
        }
 }
index 61797ea228a7ebdc3b49fa95cd8d72b4e8463eaa..f04a10c256ccd838c076aa8d4933e2bcbe15ee5e 100644 (file)
@@ -71,14 +71,10 @@ public class Vala.Destructor : Subroutine {
                        this_parameter.check (context);
                }
 
-               context.analyzer.current_symbol = this;
-
                if (body != null) {
                        body.check (context);
                }
 
-               context.analyzer.current_symbol = parent_symbol;
-
                return !error;
        }
 }
index 592e6e7a8d9b79a6bdc4ac090d0adbbcb32a252a..3caa4b6cc2d2d983e659572d2abc65a951a4a61f 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 c7201d02e46e5cc0d802f156b4b4976021dec14e..4cda8aeb82fca6f82922f56152369b5e2fc781ed 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");
@@ -224,9 +216,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 77a033596526be382bab0cc9147672c8f5091e7f..d53f816fb7a258cf432b92eef44e590a061d7347 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 019003936118ccf342a7c34527b9e6268d285ca3..2f3463e71b5c8e026f1f8741f526e59b6bfc8bf8 100644 (file)
@@ -158,14 +158,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)) {
@@ -325,9 +317,6 @@ public class Vala.Interface : ObjectTypeSymbol {
                        }
                }
 
-               context.analyzer.current_source_file = old_source_file;
-               context.analyzer.current_symbol = old_symbol;
-
                return !error;
        }
 }
index 6024df5473f05bfde8cee85d9d3cb287f86ed812..395e550a8aa237125c774a4687093dc9dd67323f 100644 (file)
@@ -145,10 +145,10 @@ public class Vala.LambdaExpression : Expression {
                        method.copy_attribute_bool (cb, "CCode", "delegate_target");
                }
 
-               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;
@@ -167,7 +167,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 ();
@@ -229,7 +229,7 @@ public class Vala.LambdaExpression : Expression {
                method.body.owner = method.scope;
 
                // support use of generics in closures
-               unowned Method? m = SemanticAnalyzer.find_parent_method (context.analyzer.current_symbol);
+               unowned Method? 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 64e16325b6926303047e28ae743d6d51e8340d1f..6450348122a58849591fb0ed1866dbddc9d9e7b8 100644 (file)
@@ -96,6 +96,16 @@ public class Vala.LocalVariable : Variable {
                        }
                }
 
+               // current_symbol is a Method if this is the `result'
+               // variable used for postconditions
+               unowned Block? 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 is VarType)) {
                        if (variable_type is VoidType) {
                                error = true;
@@ -125,9 +135,6 @@ public class Vala.LocalVariable : Variable {
                        }
                }
 
-               // local variables are defined even on errors
-               context.analyzer.current_symbol.scope.add (name, this);
-
                if (error) {
                        return false;
                }
@@ -226,13 +233,6 @@ public class Vala.LocalVariable : Variable {
                        }
                }
 
-               // current_symbol is a Method if this is the `result'
-               // variable used for postconditions
-               unowned Block? block = context.analyzer.current_symbol as Block;
-               if (block != null) {
-                       block.add_local_variable (this);
-               }
-
                active = true;
 
                return !error;
index 81fe0ed4fe9e8a823e5c9a0c598876e7f5be52e6..42363d7df01a8ed7749cb78c35305b35e2670e58 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 b8d5d12524c2607440d7470410e5b5168f85b8a4..5c4b7f6ebd7552aaaa764e9a473cf1a8499b1806 100644 (file)
@@ -227,20 +227,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;
 
-                       unowned Symbol? sym = context.analyzer.current_symbol;
+                       unowned Symbol? sym = base_symbol;
                        while (sym != null && symbol_reference == null) {
                                if (!method_found) {
                                        if (sym is CreationMethod) {
@@ -522,13 +522,15 @@ public class Vala.MemberAccess : Expression {
                        return false;
                }
 
+               unowned Symbol? current_method_or_property_accessor = context.analyzer.get_current_method_or_property_accessor (this);
+
                if (member is LocalVariable) {
                        unowned LocalVariable local = (LocalVariable) member;
                        unowned Block? block = local.parent_symbol as Block;
-                       if (block != null && SemanticAnalyzer.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)
-                               unowned Symbol? sym = context.analyzer.current_method_or_property_accessor;
+                               unowned Symbol? sym = current_method_or_property_accessor;
                                while (sym != block) {
                                        unowned Method? method = sym as Method;
                                        if (method != null) {
@@ -546,10 +548,10 @@ public class Vala.MemberAccess : Expression {
                } else if (member is Parameter) {
                        unowned Parameter param = (Parameter) member;
                        unowned Method? 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)
-                               unowned Symbol? sym = context.analyzer.current_method_or_property_accessor;
+                               unowned Symbol? sym = current_method_or_property_accessor;
                                while (sym != m) {
                                        unowned Method? method = sym as Method;
                                        if (method != null) {
@@ -567,10 +569,10 @@ public class Vala.MemberAccess : Expression {
                                }
                        } else {
                                unowned PropertyAccessor? 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)
-                                       unowned Symbol? sym = context.analyzer.current_method_or_property_accessor;
+                                       unowned Symbol? sym = current_method_or_property_accessor;
                                        while (sym != m) {
                                                unowned Method? method = sym as Method;
                                                if (method != null) {
@@ -599,7 +601,7 @@ public class Vala.MemberAccess : Expression {
                        access = c.access;
 
                        unowned Block? block = c.parent_symbol as Block;
-                       if (block != null && SemanticAnalyzer.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;
@@ -609,7 +611,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
-                               unowned Method? async_method = context.analyzer.current_async_method;
+                               unowned Method? async_method = context.analyzer.get_current_async_method (this);
 
                                bool is_valid_access = false;
                                if (async_method != null) {
@@ -627,14 +629,11 @@ public class Vala.MemberAccess : Expression {
                                        return false;
                                }
 
-                               if (async_method != context.analyzer.current_method) {
-                                       unowned Symbol? sym = context.analyzer.current_method;
-                                       while (sym != async_method) {
-                                               unowned Method? method = sym as Method;
-                                               if (method != null) {
-                                                       method.closure = true;
-                                               }
-                                               sym = sym.parent_symbol;
+                               unowned Method? 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;
                                }
@@ -763,7 +762,7 @@ public class Vala.MemberAccess : Expression {
                        unowned TypeSymbol 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
@@ -787,7 +786,7 @@ public class Vala.MemberAccess : Expression {
                        unowned Symbol? 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 81788830905e09fba5ccde4f0aad280ccbdfb617..6164a3e4837432f7d60fa36194ae3bd82bfa31f7 100644 (file)
@@ -785,14 +785,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);
                if (!external_package) {
@@ -923,7 +915,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 ()));
@@ -951,9 +943,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 98a7a878e9fade6465523e09d97435e374f333b5..787fc99e51410dd40ece8bb764717082b2695fad 100644 (file)
@@ -257,7 +257,7 @@ public class Vala.MethodCall : Expression {
                unowned CreationMethod? base_cm = null;
 
                if (is_chainup) {
-                       unowned CreationMethod? cm = context.analyzer.find_current_method () as CreationMethod;
+                       unowned CreationMethod? cm = context.analyzer.get_current_method (this) as CreationMethod;
                        if (cm == null) {
                                error = true;
                                Report.error (source_reference, "invocation not supported in this context");
@@ -517,7 +517,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) {
+                               unowned Method? 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");
                                }
@@ -654,7 +655,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
                                error = true;
                                Report.error (source_reference, "Field initializers must not throw errors");
@@ -665,7 +666,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);
                                temp_access.formal_target_type = formal_target_type;
@@ -677,9 +678,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 bc326f9c529edcc6e6357fc87f0cfe7c657fb694..6cb791d933ddb78afa74da7802948eab6ceb7c2c 100644 (file)
@@ -294,7 +294,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;
@@ -362,7 +362,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");
                                }
@@ -503,7 +504,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 {
@@ -513,7 +514,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);
                                temp_access.formal_target_type = formal_target_type;
@@ -525,9 +526,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 f99f484dab506fee25ed16bec16a3320da98cb9f..e81fc76b6418cbc3a3cc7f4dedf6cd8d278167da 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;
@@ -224,9 +216,6 @@ public class Vala.Parameter : Variable {
                        }
                }
 
-               context.analyzer.current_source_file = old_source_file;
-               context.analyzer.current_symbol = old_symbol;
-
                return !error;
        }
 }
index faa7fdf01e4844ff050e953eb6a45635e64fa5b0..53592d05bd5be9ac4f973dc60638c18406aa7bdc 100644 (file)
@@ -454,14 +454,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");
@@ -521,9 +513,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 101fc018f740ac72cc8d4026f39b0d33564da75f..89e85d543f153efdbe9d5941df1be4536e0aacd5 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);
                        // Inherit important atttributes
@@ -250,8 +246,6 @@ public class Vala.PropertyAccessor : Subroutine {
                        }
                }
 
-               context.analyzer.current_symbol = old_symbol;
-
                return !error;
        }
 
index 8ba02e6491b9d42e5c876422b0f67e00a11e702a..e79e047a93df7b6057dfdc7dd3d28a81efed3794 100644 (file)
@@ -83,27 +83,29 @@ public class Vala.ReturnStatement : CodeNode, Statement {
 
                checked = true;
 
-               if (context.analyzer.current_return_type == null) {
+               unowned DataType? current_return_type = context.analyzer.get_current_return_type (this);
+
+               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) {
                        error = true;
                        Report.error (source_reference, "Return with value in void function");
                        return false;
                }
 
-               return_expression.target_type = context.analyzer.current_return_type.copy ();
+               return_expression.target_type = current_return_type.copy ();
 
                if (!return_expression.check (context)) {
                        // ignore inner error
@@ -117,14 +119,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;
@@ -132,15 +134,16 @@ public class Vala.ReturnStatement : CodeNode, Statement {
 
                unowned LocalVariable? 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");
+                       Report.error (source_reference, "Local variable with strong reference used as return value and method return type has not been decla
+                       red 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 f2d2bdd1f71c5f063d950ecda600a6bb8f65eac1..fa72a5d7bef1e232d0b1e8a83cb4817481a3c7a2 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 {
-                       unowned Symbol? 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) {
-                               unowned Method? 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 {
-                       unowned Method? m = current_method;
-                       if (m != null) {
-                               return m.return_type;
-                       }
-
-                       unowned PropertyAccessor? 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 char_type;
@@ -175,7 +73,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
        // keep replaced alive to make sure they remain valid
        // for the whole execution of CodeNode.accept
-       public List<CodeNode> replaced_nodes = new ArrayList<CodeNode> ();
+       public Set<CodeNode> replaced_nodes = new HashSet<CodeNode> (direct_hash, direct_equal);
 
        public SemanticAnalyzer () {
        }
@@ -248,7 +146,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        delegate_target_destroy_type = new DelegateType (destroy_notify);
                }
 
-               current_symbol = root_symbol;
                context.root.check (context);
                context.accept (this);
 
@@ -256,11 +153,130 @@ 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 Namespace? get_current_namespace (CodeNode node) {
+               unowned Symbol sym = get_current_symbol (node);
+               while (sym != null && !(sym is Namespace)) {
+                       sym = sym.parent_symbol;
+               }
+               return (Namespace) 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);
@@ -1005,8 +1021,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                return actual_type;
        }
 
-       public bool is_in_instance_method () {
-               unowned Symbol? 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;
@@ -1125,37 +1141,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                }
        }
 
-       public unowned Method? find_current_method () {
-               unowned Symbol? sym = current_symbol;
-               while (sym != null) {
-                       if (sym is Method) {
-                               return (Method) sym;
-                       }
-                       sym = sym.parent_symbol;
-               }
-               return null;
-       }
-
-       public static unowned Method? find_parent_method (Symbol sym) {
-               while (sym is Block) {
-                       sym = sym.parent_symbol;
-               }
-               return sym as Method;
-       }
-
-       public static unowned 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 static unowned TypeSymbol? find_parent_type_symbol (Symbol sym) {
                while (sym != null) {
                        if (sym is TypeSymbol) {
@@ -1235,8 +1220,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                return this_type;
        }
 
-       public bool is_in_constructor () {
-               unowned Symbol? 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;
@@ -1246,8 +1231,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                return false;
        }
 
-       public bool is_in_destructor () {
-               unowned Symbol? 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 53a952753425e810e16ad8a4060c02b6cc3bc1a4..e9b0a04a3922a7bfb95e702ba4839beb930801ff 100644 (file)
@@ -490,14 +490,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);
 
@@ -573,9 +565,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 075feaa3876ae1cf92297275bbaf50aeabb85170..dbfa2d833f3ef90ed158a73ff4e19f83bc58ccbf 100644 (file)
@@ -88,6 +88,8 @@ public class Vala.SwitchSection : Block {
                        return !error;
                }
 
+               owner = context.analyzer.get_current_non_local_symbol (parent_node).scope;
+
                foreach (SwitchLabel label in get_labels ()) {
                        label.check (context);
                }
index bc8ebcbe446c3b96808238f7567fcac2b87d24e2..fb77552c3b9e95a9fff3e31c4b94a63dab824244 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");
index 91d8e7f9f67acdea4514c7dbb2644a84ab38a21d..2e9838e92e30933fb3938f1cce186e929162f73e 100644 (file)
@@ -42,7 +42,8 @@ public class Vala.YieldStatement : CodeNode, Statement {
 
                checked = true;
 
-               if (context.analyzer.current_method == null || !context.analyzer.current_method.coroutine) {
+               unowned Method? current_method = context.analyzer.get_current_method (this);
+               if (current_method == null || !current_method.coroutine) {
                        error = true;
                        Report.error (source_reference, "yield statement not available outside async method");
                }