From: Jürg Billeter Date: Wed, 13 Oct 2010 20:17:41 +0000 (+0200) Subject: Add suport for local constants X-Git-Tag: 0.11.1~122 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46fece1d814e59bb1443697fda41132a93bc4978;p=thirdparty%2Fvala.git Add suport for local constants Fixes bug 530623. --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 61eb626ec..3d8b00588 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -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 ()) { diff --git a/vala/valablock.vala b/vala/valablock.vala index d7b35f28f..c5b044d6a 100644 --- a/vala/valablock.vala +++ b/vala/valablock.vala @@ -36,6 +36,7 @@ public class Vala.Block : Symbol, Statement { private List statement_list = new ArrayList (); private List local_variables = new ArrayList (); + private List local_constants = new ArrayList (); /** * 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 ()); diff --git a/vala/valaconstant.vala b/vala/valaconstant.vala index 02b815f0c..9860c3a38 100644 --- a/vala/valaconstant.vala +++ b/vala/valaconstant.vala @@ -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; } diff --git a/vala/valaparser.vala b/vala/valaparser.vala index 44fbd00a9..43dd8e09b 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -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 (); diff --git a/vala/valasymbolresolver.vala b/vala/valasymbolresolver.vala index 0afb976c4..54b330959 100644 --- a/vala/valasymbolresolver.vala +++ b/vala/valasymbolresolver.vala @@ -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) {