]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Add suport for local constants
authorJürg Billeter <j@bitron.ch>
Wed, 13 Oct 2010 20:17:41 +0000 (22:17 +0200)
committerJürg Billeter <j@bitron.ch>
Wed, 13 Oct 2010 20:17:41 +0000 (22:17 +0200)
Fixes bug 530623.

codegen/valaccodebasemodule.vala
vala/valablock.vala
vala/valaconstant.vala
vala/valaparser.vala
vala/valasymbolresolver.vala

index 61eb626ec3083c34c0a9de9a94328c8f7e54276f..3d8b005889516e88dba809a1d8b6c2cae1c1431c 100644 (file)
@@ -719,6 +719,11 @@ public class Vala.CCodeBaseModule : CodeGenerator {
        }
 
        public void generate_constant_declaration (Constant c, CCodeFile decl_space, bool definition = false) {
+               if (c.parent_symbol is Block) {
+                       // local constant
+                       return;
+               }
+
                if (add_symbol_declaration (decl_space, c, c.get_cname ())) {
                        return;
                }
@@ -759,6 +764,31 @@ public class Vala.CCodeBaseModule : CodeGenerator {
        }
 
        public override void visit_constant (Constant c) {
+               if (c.parent_symbol is Block) {
+                       // local constant
+
+                       generate_type_declaration (c.type_reference, cfile);
+
+                       c.value.emit (this);
+
+                       string type_name = c.type_reference.get_const_cname ();
+                       string arr = "";
+                       if (c.type_reference is ArrayType) {
+                               arr = "[]";
+                       }
+
+                       if (c.type_reference.compatible (string_type)) {
+                               type_name = "const char";
+                               arr = "[]";
+                       }
+
+                       var cinitializer = get_cvalue (c.value);
+
+                       ccode.add_declaration (type_name, new CCodeVariableDeclarator ("%s%s".printf (c.get_cname (), arr), cinitializer), CCodeModifiers.STATIC);
+
+                       return;
+               }
+
                generate_constant_declaration (c, cfile, true);
 
                if (!c.is_internal_symbol ()) {
index d7b35f28f8f5f52b93669b0f3678ad8ba8150f8e..c5b044d6a71d875724748b1349734c0c1b44e898 100644 (file)
@@ -36,6 +36,7 @@ public class Vala.Block : Symbol, Statement {
 
        private List<Statement> statement_list = new ArrayList<Statement> ();
        private List<LocalVariable> local_variables = new ArrayList<LocalVariable> ();
+       private List<Constant> local_constants = new ArrayList<Constant> ();
        
        /**
         * Creates a new block.
@@ -90,7 +91,7 @@ public class Vala.Block : Symbol, Statement {
                var parent_block = parent_symbol;
                while (parent_block is Block || parent_block is Method || parent_block is PropertyAccessor) {
                        if (parent_block.scope.lookup (local.name) != null) {
-                               Report.error (local.source_reference, "Local variable `%s' conflicts with another local variable declared in a parent scope".printf (local.name));
+                               Report.error (local.source_reference, "Local variable `%s' conflicts with a local variable or constant declared in a parent scope".printf (local.name));
                                break;
                        }
                        parent_block = parent_block.parent_symbol;
@@ -111,6 +112,19 @@ public class Vala.Block : Symbol, Statement {
                return local_variables;
        }
 
+       public void add_local_constant (Constant constant) {
+               var parent_block = parent_symbol;
+               while (parent_block is Block || parent_block is Method || parent_block is PropertyAccessor) {
+                       if (parent_block.scope.lookup (constant.name) != null) {
+                               Report.error (constant.source_reference, "Local constant `%s' conflicts with a local variable or constant declared in a parent scope".printf (constant.name));
+                               break;
+                       }
+                       parent_block = parent_block.parent_symbol;
+               }
+               local_constants.add (constant);
+               scope.add (constant.name, constant);
+       }
+
        public override void accept (CodeVisitor visitor) {
                visitor.visit_block (this);
        }
@@ -143,6 +157,10 @@ public class Vala.Block : Symbol, Statement {
                        local.active = false;
                }
 
+               foreach (Constant constant in local_constants) {
+                       constant.active = false;
+               }
+
                // use get_statements () instead of statement_list to not miss errors within StatementList objects
                foreach (Statement stmt in get_statements ()) {
                        add_error_types (stmt.get_error_types ());
index 02b815f0c0fd003dbd36c7a7296bdfe8bceeb669..9860c3a38a6f4b074e764706151dafe0a72516ff 100644 (file)
@@ -217,6 +217,8 @@ public class Vala.Constant : Symbol, Lockable {
                analyzer.current_source_file = old_source_file;
                analyzer.current_symbol = old_symbol;
 
+               active = true;
+
                return !error;
        }
 
index 44fbd00a9215e473118a4e1106af761475c36d03..43dd8e09b057d75010ce1554ea375569614ab8d1 100644 (file)
@@ -1495,6 +1495,10 @@ public class Vala.Parser : CodeVisitor {
                                        is_decl = true;
                                        parse_local_variable_declarations (block);
                                        break;
+                               case TokenType.CONST:
+                                       is_decl = true;
+                                       parse_local_constant_declarations (block);
+                                       break;
                                case TokenType.OP_INC:
                                case TokenType.OP_DEC:
                                case TokenType.BASE:
@@ -1709,6 +1713,31 @@ public class Vala.Parser : CodeVisitor {
                return new LocalVariable (type, id, initializer, get_src (begin));
        }
 
+       void parse_local_constant_declarations (Block block) throws ParseError {
+               expect (TokenType.CONST);
+               var constant_type = parse_type (false, false);
+               do {
+                       DataType type_copy = constant_type.copy ();
+                       var local = parse_local_constant (type_copy);
+                       block.add_statement (new DeclarationStatement (local, local.source_reference));
+                       block.add_local_constant (local);
+                       local.active = false;
+               } while (accept (TokenType.COMMA));
+               expect (TokenType.SEMICOLON);
+       }
+
+       Constant parse_local_constant (DataType constant_type) throws ParseError {
+               var begin = get_location ();
+               string id = parse_identifier ();
+
+               var type = parse_inline_array_type (constant_type);
+
+               expect (TokenType.ASSIGN);
+               var initializer = parse_expression ();
+
+               return new Constant (id, type, initializer, get_src (begin));
+       }
+
        Statement parse_expression_statement () throws ParseError {
                var begin = get_location ();
                var expr = parse_statement_expression ();
index 0afb976c4ef234a34466be0d5a4c0a23ce5b6371..54b33095964752c07fd0b041211aa26ad474e75e 100644 (file)
@@ -158,9 +158,12 @@ public class Vala.SymbolResolver : CodeVisitor {
        }
 
        public override void visit_constant (Constant c) {
+               var old_scope = current_scope;
                current_scope = c.scope;
 
                c.accept_children (this);
+
+               current_scope = old_scope;
        }
 
        public override void visit_field (Field f) {