From: Jürg Billeter Date: Wed, 17 May 2006 18:40:44 +0000 (+0000) Subject: support variable declarators, subtyping, constants, properties, and enums X-Git-Tag: VALA_0_0_1~58 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=dcff1b56ee95f373edac25924debfbb128351a26;p=thirdparty%2Fvala.git support variable declarators, subtyping, constants, properties, and enums 2006-05-17 Jürg Billeter * vala/parser.y: support variable declarators, subtyping, constants, properties, and enums * vala/valacodevisitor.vala: support formal parameters, property accessors, named arguments, and parenthesized expressions * vala/valasymbolbuilder.vala: visit enum values, constants, formal parameters, properties, and blocks * vala/valasymbolresolver.vala: save base class, accept void type, support type references with namespace name * vala/valasemanticanalyzer.vala: visitor to find static types of expressions * vala/valacodegenerator.vala: support parenthesized expressions * vala/valablock.vala: add begin and end visit events * vala/valaclass.vala: support base types and properties * vala/valaenum.vala: add values * vala/valaenumvalue.vala * vala/valaexpression.vala: add generic symbol reference * vala/valaforeachstatement.vala: add begin and end visit events * vala/valaformalparameter.vala: add visit event * vala/valaliteral.vala: mark class as abstract * vala/valamethod.vala: add return_type * vala/valanamedargument.vala: add accept method * vala/valanamespace.vala: visit fields * vala/valaobjectcreationexpression.vala: visit arguments * vala/valaparenthesizedexpression.vala: add visit event * vala/valaproperty.vala: add accessors * vala/valapropertyaccessor.vala * vala/valasimplename.vala: code style update * vala/valastruct.vala: add constants * vala/valavariabledeclarator.vala: add type reference * vala/vala.h: update * compiler/valacompiler.vala: invoke SemanticAnalyzer * ccode/valaccodefragment.vala: code style update * ccode/valaccodeparenthesizedexpression.vala: * valac/parser.y: support replacement of readonly fields * valac/context.c: resolve types in operation expressions svn path=/trunk/; revision=21 --- diff --git a/vala/ChangeLog b/vala/ChangeLog index b08cb2ddb..ec5808eb6 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,3 +1,41 @@ +2006-05-17 Jürg Billeter + + * vala/parser.y: support variable declarators, subtyping, constants, + properties, and enums + * vala/valacodevisitor.vala: support formal parameters, property + accessors, named arguments, and parenthesized expressions + * vala/valasymbolbuilder.vala: visit enum values, constants, formal + parameters, properties, and blocks + * vala/valasymbolresolver.vala: save base class, accept void type, + support type references with namespace name + * vala/valasemanticanalyzer.vala: visitor to find static types of + expressions + * vala/valacodegenerator.vala: support parenthesized expressions + * vala/valablock.vala: add begin and end visit events + * vala/valaclass.vala: support base types and properties + * vala/valaenum.vala: add values + * vala/valaenumvalue.vala + * vala/valaexpression.vala: add generic symbol reference + * vala/valaforeachstatement.vala: add begin and end visit events + * vala/valaformalparameter.vala: add visit event + * vala/valaliteral.vala: mark class as abstract + * vala/valamethod.vala: add return_type + * vala/valanamedargument.vala: add accept method + * vala/valanamespace.vala: visit fields + * vala/valaobjectcreationexpression.vala: visit arguments + * vala/valaparenthesizedexpression.vala: add visit event + * vala/valaproperty.vala: add accessors + * vala/valapropertyaccessor.vala + * vala/valasimplename.vala: code style update + * vala/valastruct.vala: add constants + * vala/valavariabledeclarator.vala: add type reference + * vala/vala.h: update + * compiler/valacompiler.vala: invoke SemanticAnalyzer + * ccode/valaccodefragment.vala: code style update + * ccode/valaccodeparenthesizedexpression.vala: + * valac/parser.y: support replacement of readonly fields + * valac/context.c: resolve types in operation expressions + 2006-05-16 Jürg Billeter * vala/scanner.l: fix multi-line comments diff --git a/vala/ccode/valaccodefragment.vala b/vala/ccode/valaccodefragment.vala index ee1b7cda3..f03e48e84 100644 --- a/vala/ccode/valaccodefragment.vala +++ b/vala/ccode/valaccodefragment.vala @@ -24,7 +24,7 @@ using GLib; namespace Vala { public class CCodeFragment : CCodeNode { - public readonly List# children; + public ref GLib.List children { get; construct; } public void append (CCodeNode node) { _children.append (node); diff --git a/vala/ccode/valaccodeparenthesizedexpression.vala b/vala/ccode/valaccodeparenthesizedexpression.vala new file mode 100644 index 000000000..3e30821a9 --- /dev/null +++ b/vala/ccode/valaccodeparenthesizedexpression.vala @@ -0,0 +1,37 @@ +/* valaccodeparenthesizedexpression.vala + * + * Copyright (C) 2006 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +using GLib; + +namespace Vala { + public class CCodeParenthesizedExpression : CCodeExpression { + public readonly ref CCodeExpression inner; + + public override void write (CCodeWriter writer) { + writer.write_string ("("); + + inner.write (writer); + + writer.write_string (")"); + } + } +} diff --git a/vala/compiler/valacompiler.vala b/vala/compiler/valacompiler.vala index 6c039b4a7..3824304b1 100644 --- a/vala/compiler/valacompiler.vala +++ b/vala/compiler/valacompiler.vala @@ -55,6 +55,9 @@ namespace Vala { var attributeprocessor = new AttributeProcessor (); attributeprocessor.process (context); + var analyzer = new SemanticAnalyzer (); + analyzer.analyze (context); + var code_generator = new CodeGenerator (); code_generator.emit (context); } diff --git a/vala/vala/parser.y b/vala/vala/parser.y index 6fbc252d1..ae4b1c4d9 100644 --- a/vala/vala/parser.y +++ b/vala/vala/parser.y @@ -64,11 +64,13 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); ValaClass *class; ValaStruct *struct_; ValaEnum *enum_; + ValaEnumValue *enum_value; ValaConstant *constant; ValaField *field; ValaMethod *method; ValaFormalParameter *formal_parameter; ValaProperty *property; + ValaPropertyAccessor *property_accessor; ValaLocalVariableDeclaration *local_variable_declaration; ValaVariableDeclarator *variable_declarator; ValaTypeParameter *type_parameter; @@ -223,10 +225,20 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %type return_statement %type namespace_declaration %type class_declaration +%type opt_class_base +%type class_base +%type type_list %type property_declaration +%type get_accessor_declaration +%type opt_set_accessor_declaration +%type set_accessor_declaration %type struct_declaration %type struct_header %type enum_declaration +%type enum_body +%type opt_enum_member_declarations +%type enum_member_declarations +%type enum_member_declaration %type constant_declaration %type constant_declarator %type field_declaration @@ -703,7 +715,12 @@ declaration_statement local_variable_declaration : local_variable_type variable_declarators SEMICOLON { + GList *l; $$ = vala_local_variable_declaration_new ($1, $2, src(@2)); + for (l = $2; l != NULL; l = l->next) { + ValaVariableDeclarator *decl = l->data; + decl->type_reference = g_object_ref ($1); + } } | VAR variable_declarators SEMICOLON { @@ -906,6 +923,9 @@ class_declaration for (l = $7; l != NULL; l = l->next) { vala_struct_add_type_parameter (current_struct, l->data); } + for (l = $8; l != NULL; l = l->next) { + vala_class_add_base_type (VALA_CLASS (current_struct), l->data); + } } class_body { @@ -944,16 +964,28 @@ modifier opt_class_base : /* empty */ + { + $$ = NULL; + } | class_base ; class_base : COLON type_list + { + $$ = $2; + } ; type_list : type_name + { + $$ = g_list_append (NULL, $1); + } | type_list COMMA type_name + { + $$ = g_list_append ($1, $3); + } ; class_body @@ -972,6 +1004,9 @@ class_member_declarations class_member_declaration : constant_declaration + { + vala_struct_add_constant (current_struct, $1); + } | field_declaration { vala_struct_add_field (current_struct, $1); @@ -981,6 +1016,9 @@ class_member_declaration vala_struct_add_method (current_struct, $1); } | property_declaration + { + vala_class_add_property (VALA_CLASS (current_struct), $1); + } ; constant_declaration @@ -1069,7 +1107,7 @@ method_header { GList *l; - $$ = vala_method_new ($7, src_com (@7, $1)); + $$ = vala_method_new ($7, $6, src_com (@7, $1)); VALA_CODE_NODE($$)->attributes = $2; for (l = $9; l != NULL; l = l->next) { @@ -1127,36 +1165,44 @@ parameter_modifier ; property_declaration - : comment opt_attributes opt_access_modifier opt_modifiers opt_ref type IDENTIFIER OPEN_BRACE accessor_declarations CLOSE_BRACE + : comment opt_attributes opt_access_modifier opt_modifiers opt_ref type IDENTIFIER OPEN_BRACE get_accessor_declaration opt_set_accessor_declaration CLOSE_BRACE { - $$ = vala_property_new ($7, $6, src_com (@6, $1)); + $$ = vala_property_new ($7, $6, $9, $10, src_com (@6, $1)); + } + | comment opt_attributes opt_access_modifier opt_modifiers opt_ref type IDENTIFIER OPEN_BRACE set_accessor_declaration CLOSE_BRACE + { + $$ = vala_property_new ($7, $6, NULL, $9, src_com (@6, $1)); } - ; - -accessor_declarations - : get_accessor_declaration opt_set_accessor_declaration - | set_accessor_declaration opt_get_accessor_declaration - ; - -opt_get_accessor_declaration - : /* empty */ - | get_accessor_declaration ; get_accessor_declaration : opt_attributes GET method_body + { + $$ = vala_property_accessor_new (TRUE, FALSE, FALSE, $3, src (@2)); + } ; opt_set_accessor_declaration : /* empty */ + { + $$ = NULL; + } | set_accessor_declaration ; set_accessor_declaration : opt_attributes SET method_body - | opt_attributes CONSTRUCT method_body - | opt_attributes CONSTRUCT SET method_body + { + $$ = vala_property_accessor_new (FALSE, TRUE, FALSE, $3, src (@2)); + } | opt_attributes SET CONSTRUCT method_body + { + $$ = vala_property_accessor_new (FALSE, TRUE, TRUE, $4, src (@2)); + } + | opt_attributes CONSTRUCT method_body + { + $$ = vala_property_accessor_new (FALSE, FALSE, TRUE, $3, src (@2)); + } ; struct_declaration @@ -1233,26 +1279,45 @@ interface_member_declaration enum_declaration : comment opt_attributes opt_access_modifier ENUM IDENTIFIER enum_body { + GList *l; $$ = vala_enum_new ($5, src_com (@5, $1)); + for (l = $6; l != NULL; l = l->next) { + vala_enum_add_value ($$, l->data); + } } ; enum_body : OPEN_BRACE opt_enum_member_declarations CLOSE_BRACE + { + $$ = $2; + } ; opt_enum_member_declarations : /* empty */ + { + $$ = NULL; + } | enum_member_declarations ; enum_member_declarations : enum_member_declaration + { + $$ = g_list_append (NULL, $1); + } | enum_member_declarations COMMA enum_member_declaration + { + $$ = g_list_append ($1, $3); + } ; enum_member_declaration : opt_attributes IDENTIFIER + { + $$ = vala_enum_value_new ($2); + } ; flags_declaration diff --git a/vala/vala/vala.h b/vala/vala/vala.h index 63f145dc6..a4591207e 100644 --- a/vala/vala/vala.h +++ b/vala/vala/vala.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,7 @@ #include #include #include +#include #include #include #include diff --git a/vala/vala/valablock.vala b/vala/vala/valablock.vala index f8d0b192a..685b860c2 100644 --- a/vala/vala/valablock.vala +++ b/vala/vala/valablock.vala @@ -24,19 +24,21 @@ using GLib; namespace Vala { public class Block : Statement { - public readonly List# statement_list; - public readonly SourceReference# source_reference; + public readonly ref List statement_list; + public readonly ref SourceReference source_reference; - public static Block# @new (List statement_list, SourceReference source) { + public static ref Block new (List statement_list, SourceReference source) { return (new Block (statement_list = statement_list, source_reference = source)); } public override void accept (CodeVisitor visitor) { + visitor.visit_begin_block (this); + foreach (Statement stmt in statement_list) { stmt.accept (visitor); } - visitor.visit_block (this); + visitor.visit_end_block (this); } } } diff --git a/vala/vala/valaclass.vala b/vala/vala/valaclass.vala index 607e93e48..e77332952 100644 --- a/vala/vala/valaclass.vala +++ b/vala/vala/valaclass.vala @@ -24,16 +24,43 @@ using GLib; namespace Vala { public class Class : Struct { - public readonly SourceReference# source_reference; + public readonly ref SourceReference source_reference; + public ref List base_types; + public ref Class base_class; + + ref List properties; + + public void add_base_type (TypeReference type) { + base_types.append (type); + } public static ref Class new (string name, SourceReference source) { return (new Class (name = name, source_reference = source)); } + public void add_property (Property prop) { + properties.append (prop); + prop.parent_type = this; + + if (prop.set_accessor != null && prop.set_accessor.body == null) { + /* automatic property accessor body generation */ + var f = new Field (name = "_%s".printf (prop.name), type_reference = prop.type_reference, source_reference = source_reference); + add_field (f); + } + } + public override void accept (CodeVisitor visitor) { visitor.visit_begin_class (this); + + foreach (TypeReference type in base_types) { + type.accept (visitor); + } visit_children (visitor); + + foreach (Property prop in properties) { + prop.accept (visitor); + } visitor.visit_end_class (this); } diff --git a/vala/vala/valacodegenerator.vala b/vala/vala/valacodegenerator.vala index fee4496e2..55e557efc 100644 --- a/vala/vala/valacodegenerator.vala +++ b/vala/vala/valacodegenerator.vala @@ -24,17 +24,17 @@ using GLib; namespace Vala { public class CodeGenerator : CodeVisitor { - CCodeFragment# header_begin; - CCodeFragment# header_type_declaration; - CCodeFragment# header_type_definition; - CCodeFragment# header_type_member_declaration; - CCodeFragment# source_begin; - CCodeFragment# source_include_directives; - CCodeFragment# source_type_member_declaration; - CCodeFragment# source_type_member_definition; + ref CCodeFragment header_begin; + ref CCodeFragment header_type_declaration; + ref CCodeFragment header_type_definition; + ref CCodeFragment header_type_member_declaration; + ref CCodeFragment source_begin; + ref CCodeFragment source_include_directives; + ref CCodeFragment source_type_member_declaration; + ref CCodeFragment source_type_member_definition; - CCodeStruct# instance_struct; - CCodeStruct# class_struct; + ref CCodeStruct instance_struct; + ref CCodeStruct class_struct; ref CCodeFunction function; ref CCodeBlock block; @@ -104,7 +104,7 @@ namespace Vala { header_type_definition.append (instance_struct); } - public override void visit_enum (Enum en) { + public override void visit_begin_enum (Enum en) { instance_struct = new CCodeEnum (name = "_%s".printf (en.name)); if (en.source_reference.comment != null) { @@ -140,11 +140,17 @@ namespace Vala { } - public override void visit_block (Block b) { + public override void visit_end_block (Block b) { var cblock = new CCodeBlock (); foreach (Statement stmt in b.statement_list) { - cblock.add_statement ((CCodeStatement) stmt.ccodenode); + if (stmt.ccodenode is CCodeFragment) { + foreach (CCodeStatement cstmt in ((CCodeFragment) stmt.ccodenode).children) { + cblock.add_statement (cstmt); + } + } else { + cblock.add_statement ((CCodeStatement) stmt.ccodenode); + } } b.ccodenode = cblock; @@ -155,18 +161,19 @@ namespace Vala { } public override void visit_declaration_statement (DeclarationStatement stmt) { - /* not yet handled var declarations */ - if (stmt.declaration.type_reference == null) { - return; - } - - var cdecl = new CCodeDeclarationStatement (type_name = stmt.declaration.type_reference.get_cname ()); + /* split declaration statement as var declarators might have different types */ + + var cfrag = new CCodeFragment (); foreach (VariableDeclarator decl in stmt.declaration.variable_declarators) { + var cdecl = new CCodeDeclarationStatement (type_name = decl.type_reference.get_cname ()); + cdecl.add_declarator ((CCodeVariableDeclarator) decl.ccodenode); + + cfrag.append (cdecl); } - stmt.ccodenode = cdecl; + stmt.ccodenode = cfrag; } public override void visit_variable_declarator (VariableDeclarator decl) { @@ -244,6 +251,10 @@ namespace Vala { expr.ccodenode = new CCodeIdentifier (name = expr.name); } + public override void visit_parenthesized_expression (ParenthesizedExpression expr) { + expr.ccodenode = new CCodeParenthesizedExpression (inner = (CCodeExpression) expr.inner.ccodenode); + } + public override void visit_member_access (MemberAccess expr) { expr.ccodenode = new CCodeIdentifier (name = expr.member_name); } diff --git a/vala/vala/valacodevisitor.vala b/vala/vala/valacodevisitor.vala index 98694c89d..e3b695a53 100644 --- a/vala/vala/valacodevisitor.vala +++ b/vala/vala/valacodevisitor.vala @@ -48,7 +48,13 @@ namespace Vala { public virtual void visit_end_struct (Struct st) { } - public virtual void visit_enum (Enum en) { + public virtual void visit_begin_enum (Enum en) { + } + + public virtual void visit_end_enum (Enum en) { + } + + public virtual void visit_enum_value (EnumValue ev) { } public virtual void visit_constant (Constant c) { @@ -63,7 +69,22 @@ namespace Vala { public virtual void visit_end_method (Method m) { } - public virtual void visit_property (Property prop) { + public virtual void visit_formal_parameter (FormalParameter p) { + } + + public virtual void visit_begin_property (Property prop) { + } + + public virtual void visit_end_property (Property prop) { + } + + public virtual void visit_begin_property_accessor (PropertyAccessor acc) { + } + + public virtual void visit_end_property_accessor (PropertyAccessor acc) { + } + + public virtual void visit_named_argument (NamedArgument n) { } public virtual void visit_type_parameter (TypeParameter p) { @@ -75,7 +96,10 @@ namespace Vala { public virtual void visit_type_reference (TypeReference type) { } - public virtual void visit_block (Block b) { + public virtual void visit_begin_block (Block b) { + } + + public virtual void visit_end_block (Block b) { } public virtual void visit_empty_statement (EmptyStatement stmt) { @@ -102,7 +126,10 @@ namespace Vala { public virtual void visit_for_statement (ForStatement stmt) { } - public virtual void visit_foreach_statement (ForeachStatement stmt) { + public virtual void visit_begin_foreach_statement (ForeachStatement stmt) { + } + + public virtual void visit_end_foreach_statement (ForeachStatement stmt) { } public virtual void visit_return_statement (ReturnStatement stmt) { @@ -129,6 +156,9 @@ namespace Vala { public virtual void visit_simple_name (SimpleName expr) { } + public virtual void visit_parenthesized_expression (ParenthesizedExpression expr) { + } + public virtual void visit_member_access (MemberAccess expr) { } diff --git a/vala/vala/valaenum.vala b/vala/vala/valaenum.vala index 5746e5514..10233007a 100644 --- a/vala/vala/valaenum.vala +++ b/vala/vala/valaenum.vala @@ -24,16 +24,27 @@ using GLib; namespace Vala { public class Enum : Type_ { - public readonly string# name; - public readonly SourceReference# source_reference; + public readonly ref string name; + public readonly ref SourceReference source_reference; public Namespace @namespace; + ref List values; - public static Enum# @new (string name, SourceReference source) { + public static ref Enum new (string name, SourceReference source) { return (new Enum (name = name, source_reference = source)); } + public void add_value (EnumValue value) { + values.append (value); + } + public override void accept (CodeVisitor visitor) { - visitor.visit_enum (this); + visitor.visit_begin_enum (this); + + foreach (EnumValue value in values) { + value.accept (visitor); + } + + visitor.visit_end_enum (this); } public override string get_cname () { diff --git a/vala/vala/valaenumvalue.vala b/vala/vala/valaenumvalue.vala new file mode 100644 index 000000000..0ed01b2fc --- /dev/null +++ b/vala/vala/valaenumvalue.vala @@ -0,0 +1,43 @@ +/* valaenumvalue.vala + * + * Copyright (C) 2006 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +using GLib; + +namespace Vala { + public class EnumValue : CodeNode { + public readonly ref string name; + public readonly ref IntegerLiteral value; + public readonly ref SourceReference source_reference; + + public static ref EnumValue new (string name) { + return (new EnumValue (name = name)); + } + + public static ref EnumValue new_with_value (string name, int value) { + return (new EnumValue (name = name, value = value)); + } + + public override void accept (CodeVisitor visitor) { + visitor.visit_enum_value (this); + } + } +} diff --git a/vala/vala/valaexpression.vala b/vala/vala/valaexpression.vala index 830709e92..a183a1616 100644 --- a/vala/vala/valaexpression.vala +++ b/vala/vala/valaexpression.vala @@ -24,8 +24,7 @@ using GLib; namespace Vala { public abstract class Expression : CodeNode { - TypeReference# static_type; - Field field_reference; - Method method_reference; + public ref TypeReference static_type; + public ref Symbol symbol_reference; } } diff --git a/vala/vala/valaforeachstatement.vala b/vala/vala/valaforeachstatement.vala index 20dacb077..bad70cb5d 100644 --- a/vala/vala/valaforeachstatement.vala +++ b/vala/vala/valaforeachstatement.vala @@ -24,22 +24,24 @@ using GLib; namespace Vala { public class ForeachStatement : Statement { - public readonly TypeReference# type_reference; - public readonly string# variable_name; - public readonly Expression# collection; - public readonly Statement# body; - public readonly SourceReference# source_reference; + public readonly ref TypeReference type_reference; + public readonly ref string variable_name; + public readonly ref Expression collection; + public readonly ref Statement body; + public readonly ref SourceReference source_reference; - public static ForeachStatement# @new (TypeReference type, string id, Expression col, Statement body, SourceReference source) { + public static ref ForeachStatement new (TypeReference type, string id, Expression col, Statement body, SourceReference source) { return (new ForeachStatement (type_reference = type, variable_name = id, collection = col, body = body, source_reference = source)); } public override void accept (CodeVisitor visitor) { + visitor.visit_begin_foreach_statement (this); + type_reference.accept (visitor); collection.accept (visitor); body.accept (visitor); - visitor.visit_foreach_statement (this); + visitor.visit_end_foreach_statement (this); } } } diff --git a/vala/vala/valaformalparameter.vala b/vala/vala/valaformalparameter.vala index 4a455f044..07dbff145 100644 --- a/vala/vala/valaformalparameter.vala +++ b/vala/vala/valaformalparameter.vala @@ -34,6 +34,8 @@ namespace Vala { public override void accept (CodeVisitor visitor) { type_reference.accept (visitor); + + visitor.visit_formal_parameter (this); } } } diff --git a/vala/vala/valaliteral.vala b/vala/vala/valaliteral.vala index 8d7029134..42d3939d8 100644 --- a/vala/vala/valaliteral.vala +++ b/vala/vala/valaliteral.vala @@ -23,6 +23,7 @@ using GLib; namespace Vala { - public class Literal : CodeNode { + public abstract class Literal : CodeNode { + public ref TypeReference static_type; } } diff --git a/vala/vala/valamethod.vala b/vala/vala/valamethod.vala index 94f08499e..0559ab0ad 100644 --- a/vala/vala/valamethod.vala +++ b/vala/vala/valamethod.vala @@ -25,9 +25,10 @@ using GLib; namespace Vala { public class Method : CodeNode { public readonly ref string name; - public readonly SourceReference# source_reference; + public readonly ref TypeReference return_type; + public readonly ref SourceReference source_reference; public CodeNode parent_type; - Statement# _body; + ref Statement _body; public Statement body { get { return _body; @@ -40,8 +41,8 @@ namespace Vala { public bool instance = true; ref List parameters; - public static Method# @new (string name, SourceReference source) { - return (new Method (name = name, source_reference = source)); + public static ref Method new (string name, TypeReference return_type, SourceReference source) { + return (new Method (name = name, return_type = return_type, source_reference = source)); } public void add_parameter (FormalParameter param) { @@ -51,6 +52,12 @@ namespace Vala { public override void accept (CodeVisitor visitor) { visitor.visit_begin_method (this); + return_type.accept (visitor); + + foreach (FormalParameter param in parameters) { + param.accept (visitor); + } + if (body != null) { body.accept (visitor); } diff --git a/vala/vala/valanamedargument.vala b/vala/vala/valanamedargument.vala index a96ec5842..a2f3ca35f 100644 --- a/vala/vala/valanamedargument.vala +++ b/vala/vala/valanamedargument.vala @@ -24,12 +24,18 @@ using GLib; namespace Vala { public class NamedArgument : CodeNode { - public readonly string# name; - public readonly Expression# argument; - public readonly SourceReference# source_reference; + public readonly ref string name; + public readonly ref Expression argument; + public readonly ref SourceReference source_reference; - public static NamedArgument# @new (string name, Expression arg, SourceReference source) { + public static ref NamedArgument new (string name, Expression arg, SourceReference source) { return (new NamedArgument (name = name, argument = arg, source_reference = source)); } + + public override void accept (CodeVisitor visitor) { + argument.accept (visitor); + + visitor.visit_named_argument (this); + } } } diff --git a/vala/vala/valanamespace.vala b/vala/vala/valanamespace.vala index 2766b1b83..4ac09dfcf 100644 --- a/vala/vala/valanamespace.vala +++ b/vala/vala/valanamespace.vala @@ -86,6 +86,10 @@ namespace Vala { en.accept (visitor); } + foreach (Field f in fields) { + f.accept (visitor); + } + visitor.visit_end_namespace (this); } diff --git a/vala/vala/valaobjectcreationexpression.vala b/vala/vala/valaobjectcreationexpression.vala index e8baace45..e3e05d608 100644 --- a/vala/vala/valaobjectcreationexpression.vala +++ b/vala/vala/valaobjectcreationexpression.vala @@ -24,16 +24,20 @@ using GLib; namespace Vala { public class ObjectCreationExpression : Expression { - public readonly TypeReference# type_reference; - public readonly List# named_argument_list; - public readonly SourceReference# source_reference; + public readonly ref TypeReference type_reference; + public readonly ref List named_argument_list; + public readonly ref SourceReference source_reference; - public static ObjectCreationExpression# @new (TypeReference type, List named_argument_list, SourceReference source) { + public static ref ObjectCreationExpression new (TypeReference type, List named_argument_list, SourceReference source) { return (new ObjectCreationExpression (type_reference = type, named_argument_list = named_argument_list, source_reference = source)); } public override void accept (CodeVisitor visitor) { type_reference.accept (visitor); + + foreach (NamedArgument arg in named_argument_list) { + arg.accept (visitor); + } visitor.visit_object_creation_expression (this); } diff --git a/vala/vala/valaparenthesizedexpression.vala b/vala/vala/valaparenthesizedexpression.vala index 2ab1abc82..a42e54d9f 100644 --- a/vala/vala/valaparenthesizedexpression.vala +++ b/vala/vala/valaparenthesizedexpression.vala @@ -24,15 +24,17 @@ using GLib; namespace Vala { public class ParenthesizedExpression : Expression { - public readonly Expression# inner; - public readonly SourceReference# source_reference; + public readonly ref Expression inner; + public readonly ref SourceReference source_reference; - public static ParenthesizedExpression# @new (Expression inner, SourceReference source) { + public static ref ParenthesizedExpression new (Expression inner, SourceReference source) { return (new ParenthesizedExpression (inner = inner, source_reference = source)); } public override void accept (CodeVisitor visitor) { inner.accept (visitor); + + visitor.visit_parenthesized_expression (this); } } } diff --git a/vala/vala/valaproperty.vala b/vala/vala/valaproperty.vala index f3d526740..fbbc1c3cd 100644 --- a/vala/vala/valaproperty.vala +++ b/vala/vala/valaproperty.vala @@ -26,16 +26,29 @@ namespace Vala { public class Property : CodeNode { public readonly ref string name; public readonly ref TypeReference type_reference; + public readonly ref PropertyAccessor get_accessor; + public readonly ref PropertyAccessor set_accessor; public readonly ref SourceReference source_reference; public CodeNode parent_type; public MemberAccessibility access; - public static ref Property new (string name, TypeReference type, SourceReference source) { - return (new Property (name = name, type_reference = type, source_reference = source)); + public static ref Property new (string name, TypeReference type, PropertyAccessor get_accessor, PropertyAccessor set_accessor, SourceReference source) { + return (new Property (name = name, type_reference = type, get_accessor = get_accessor, set_accessor = set_accessor, source_reference = source)); } public override void accept (CodeVisitor visitor) { - visitor.visit_property (this); + visitor.visit_begin_property (this); + + type_reference.accept (visitor); + + if (get_accessor != null) { + get_accessor.accept (visitor); + } + if (set_accessor != null) { + set_accessor.accept (visitor); + } + + visitor.visit_end_property (this); } } } diff --git a/vala/vala/valapropertyaccessor.vala b/vala/vala/valapropertyaccessor.vala new file mode 100644 index 000000000..908ad5d42 --- /dev/null +++ b/vala/vala/valapropertyaccessor.vala @@ -0,0 +1,47 @@ +/* valapropertyaccessor.vala + * + * Copyright (C) 2006 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +using GLib; + +namespace Vala { + public class PropertyAccessor : CodeNode { + public readonly ref bool readable; + public readonly ref bool writable; + public readonly ref bool construct_; + public readonly ref Statement body; + public readonly ref SourceReference source_reference; + + public static ref PropertyAccessor new (bool readable, bool writable, bool construct_, Statement body, SourceReference source) { + return (new PropertyAccessor (readable = readable, writable = writable, construct_ = construct_, body = body, source_reference = source)); + } + + public override void accept (CodeVisitor visitor) { + visitor.visit_begin_property_accessor (this); + + if (body != null) { + body.accept (visitor); + } + + visitor.visit_end_property_accessor (this); + } + } +} diff --git a/vala/vala/valasemanticanalyzer.vala b/vala/vala/valasemanticanalyzer.vala new file mode 100644 index 000000000..6f74ea33c --- /dev/null +++ b/vala/vala/valasemanticanalyzer.vala @@ -0,0 +1,222 @@ +/* valasemanticanalyzer.vala + * + * Copyright (C) 2006 Jürg Billeter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Author: + * Jürg Billeter + */ + +using GLib; + +namespace Vala { + public class SemanticAnalyzer : CodeVisitor { + ref Symbol root_symbol; + ref Symbol current_symbol; + + List current_using_directives; + TypeReference dummy; // required for broken dependency handlind + + public void analyze (CodeContext context) { + root_symbol = context.root; + current_symbol = root_symbol; + context.accept (this); + } + + public override void visit_begin_source_file (SourceFile file) { + current_using_directives = file.get_using_directives (); + } + + public override void visit_end_source_file (SourceFile file) { + current_using_directives = null; + } + + public override void visit_begin_namespace (Namespace ns) { + current_symbol = ns.symbol; + } + + public override void visit_end_namespace (Namespace ns) { + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_begin_class (Class cl) { + current_symbol = cl.symbol; + } + + public override void visit_end_class (Class cl) { + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_begin_struct (Struct st) { + current_symbol = st.symbol; + } + + public override void visit_end_struct (Struct st) { + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_begin_method (Method m) { + current_symbol = m.symbol; + } + + public override void visit_end_method (Method m) { + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_named_argument (NamedArgument n) { + } + + public override void visit_begin_block (Block b) { + current_symbol = b.symbol; + } + + public override void visit_end_block (Block b) { + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_variable_declarator (VariableDeclarator decl) { + if (decl.type_reference == null) { + /* var type */ + decl.type_reference = decl.initializer.static_type; + } + + decl.symbol = new Symbol (node = decl); + current_symbol.add (decl.name, decl.symbol); + } + + public override void visit_begin_foreach_statement (ForeachStatement stmt) { + stmt.symbol = new Symbol (node = stmt.type_reference); + current_symbol.add (stmt.variable_name, stmt.symbol); + } + + public override void visit_boolean_literal (BooleanLiteral expr) { + expr.static_type = new TypeReference (); + expr.static_type.type = (Type_) root_symbol.lookup ("bool").node; + } + + public override void visit_character_literal (CharacterLiteral expr) { + expr.static_type = new TypeReference (); + expr.static_type.type = (Type_) root_symbol.lookup ("char").node; + } + + public override void visit_integer_literal (IntegerLiteral expr) { + expr.static_type = new TypeReference (); + expr.static_type.type = (Type_) root_symbol.lookup ("int").node; + } + + public override void visit_string_literal (StringLiteral expr) { + expr.static_type = new TypeReference (); + expr.static_type.type = (Type_) root_symbol.lookup ("string").node; + } + + public override void visit_null_literal (NullLiteral expr) { + } + + public override void visit_literal_expression (LiteralExpression expr) { + expr.static_type = expr.literal.static_type; + } + + TypeReference get_static_type_for_node (CodeNode node) { + if (node is Field) { + var f = (Field) node; + return f.type_reference; + } else if (node is Property) { + var prop = (Property) node; + return prop.type_reference; + } else if (node is FormalParameter) { + var p = (FormalParameter) node; + return p.type_reference; + } else if (node is TypeReference) { + return (TypeReference) node; + } else if (node is VariableDeclarator) { + var decl = (VariableDeclarator) node; + return decl.type_reference; + } + return null; + } + + Symbol symbol_lookup_inherited (Symbol sym, string name) { + var result = sym.lookup (name); + if (result == null && sym.node is Class) { + var cl = (Class) sym.node; + for (cl = cl.base_class; cl != null && result == null; cl = cl.base_class) { + result = cl.symbol.lookup (name); + } + } + return result; + } + + public override void visit_simple_name (SimpleName expr) { + var sym = current_symbol; + while (sym != null && expr.symbol_reference == null) { + expr.symbol_reference = symbol_lookup_inherited (sym, expr.name); + sym = sym.parent_symbol; + } + + if (expr.symbol_reference == null) { + foreach (NamespaceReference ns in current_using_directives) { + var local_sym = ns.namespace_symbol.lookup (expr.name); + if (expr.symbol_reference != null && local_sym != null) { + // raise error + stderr.printf ("ambiguous symbol name %s\n", expr.name); + } + expr.symbol_reference = local_sym; + } + } + + if (expr.symbol_reference == null) { + stderr.printf ("symbol ´%s´ not found\n", expr.name); + } + + expr.static_type = get_static_type_for_node (expr.symbol_reference.node); + } + + public override void visit_parenthesized_expression (ParenthesizedExpression expr) { + expr.static_type = expr.inner.static_type; + } + + public override void visit_member_access (MemberAccess expr) { + if (expr.inner.static_type == null) { + if (expr.inner.symbol_reference.node is Type_) { + expr.symbol_reference = expr.inner.symbol_reference.lookup (expr.member_name); + } + } + + if (expr.symbol_reference == null) { + expr.symbol_reference = symbol_lookup_inherited (expr.inner.static_type.type.symbol, expr.member_name); + } + + if (expr.symbol_reference == null) { + stderr.printf ("%s: member ´%s´ not found\n", expr.source_reference.to_string (), expr.member_name); + } + + expr.static_type = get_static_type_for_node (expr.symbol_reference.node); + } + + public override void visit_invocation_expression (InvocationExpression expr) { + var m = (Method) expr.call.symbol_reference.node; + expr.static_type = m.return_type; + } + + public override void visit_object_creation_expression (ObjectCreationExpression expr) { + expr.static_type = expr.type_reference; + } + + public override void visit_cast_expression (CastExpression expr) { + expr.static_type = expr.type_reference; + } + } +} diff --git a/vala/vala/valasimplename.vala b/vala/vala/valasimplename.vala index a9bfec9cb..2c64a1329 100644 --- a/vala/vala/valasimplename.vala +++ b/vala/vala/valasimplename.vala @@ -24,10 +24,10 @@ using GLib; namespace Vala { public class SimpleName : Expression { - public readonly string# name; - public readonly SourceReference# source_reference; + public readonly ref string name; + public readonly ref SourceReference source_reference; - public static SimpleName# @new (string s, List type_argument_list, SourceReference source) { + public static ref SimpleName new (string s, List type_argument_list, SourceReference source) { return (new SimpleName (name = s, source_reference = source)); } diff --git a/vala/vala/valastruct.vala b/vala/vala/valastruct.vala index d08b05b82..c612b0261 100644 --- a/vala/vala/valastruct.vala +++ b/vala/vala/valastruct.vala @@ -29,8 +29,9 @@ namespace Vala { public Namespace @namespace; ref List type_parameters; - List# fields; - List# methods; + ref List constants; + ref List fields; + ref List methods; public ref string cname; public ref string lower_case_csuffix; @@ -45,6 +46,10 @@ namespace Vala { p.type = this; } + public void add_constant (Constant c) { + constants.append (c); + } + public void add_field (Field f) { fields.append (f); f.parent_type = this; @@ -68,6 +73,10 @@ namespace Vala { p.accept (visitor); } + foreach (Constant c in constants) { + c.accept (visitor); + } + foreach (Field f in fields) { f.accept (visitor); } diff --git a/vala/vala/valasymbolbuilder.vala b/vala/vala/valasymbolbuilder.vala index 77d2eeca3..e29bf2196 100644 --- a/vala/vala/valasymbolbuilder.vala +++ b/vala/vala/valasymbolbuilder.vala @@ -27,6 +27,7 @@ namespace Vala { Symbol root; Symbol current_namespace; Symbol current_type; + Symbol current_symbol; public void build (CodeContext context) { root = context.root; @@ -43,6 +44,12 @@ namespace Vala { ns.symbol = new Symbol (node = ns); root.add (ns.name, ns.symbol); } + + current_symbol = ns.symbol; + } + + public override void visit_end_namespace (Namespace ns) { + current_symbol = current_symbol.parent_symbol; } public override void visit_begin_class (Class cl) { @@ -53,6 +60,12 @@ namespace Vala { } cl.symbol = new Symbol (node = cl); cl.@namespace.symbol.add (cl.name, cl.symbol); + + current_symbol = cl.symbol; + } + + public override void visit_end_class (Class cl) { + current_symbol = current_symbol.parent_symbol; } public override void visit_begin_struct (Struct st) { @@ -63,9 +76,15 @@ namespace Vala { } st.symbol = new Symbol (node = st); st.@namespace.symbol.add (st.name, st.symbol); + + current_symbol = st.symbol; + } + + public override void visit_end_struct (Struct st) { + current_symbol = current_symbol.parent_symbol; } - public override void visit_enum (Enum en) { + public override void visit_begin_enum (Enum en) { if (en.@namespace.symbol.lookup (en.name) != null) { // TODO: raise error stderr.printf ("symbol conflict\n"); @@ -73,26 +92,105 @@ namespace Vala { } en.symbol = new Symbol (node = en); en.@namespace.symbol.add (en.name, en.symbol); + current_symbol = en.symbol; + } + + public override void visit_end_enum (Enum en) { + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_enum_value (EnumValue ev) { + ev.symbol = new Symbol (node = ev); + current_symbol.add (ev.name, ev.symbol); + } + + public override void visit_constant (Constant c) { + if (current_symbol.lookup (c.name) != null) { + // TODO: raise error + stderr.printf ("symbol conflict\n"); + return; + } + c.symbol = new Symbol (node = c); + current_symbol.add (c.name, c.symbol); } public override void visit_field (Field f) { - if (f.parent_type.symbol.lookup (f.name) != null) { + if (current_symbol.lookup (f.name) != null) { // TODO: raise error stderr.printf ("symbol conflict\n"); return; } f.symbol = new Symbol (node = f); - f.parent_type.symbol.add (f.name, f.symbol); + current_symbol.add (f.name, f.symbol); } public override void visit_begin_method (Method m) { - if (m.parent_type.symbol.lookup (m.name) != null) { + if (current_symbol.lookup (m.name) != null) { // TODO: raise error stderr.printf ("symbol conflict\n"); return; } m.symbol = new Symbol (node = m); - m.parent_type.symbol.add (m.name, m.symbol); + current_symbol.add (m.name, m.symbol); + current_symbol = m.symbol; + + if (m.instance) { + var type = new TypeReference (); + type.type = (Type_) m.symbol.parent_symbol.node; + current_symbol.add ("this", new Symbol (node = type)); + } + } + + public override void visit_end_method (Method m) { + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_formal_parameter (FormalParameter p) { + p.symbol = new Symbol (node = p); + current_symbol.add (p.name, p.symbol); + } + + public override void visit_begin_property (Property prop) { + if (current_symbol.lookup (prop.name) != null) { + // TODO: raise error + stderr.printf ("symbol conflict\n"); + return; + } + prop.symbol = new Symbol (node = prop); + current_symbol.add (prop.name, prop.symbol); + current_symbol = prop.symbol; + + var type = new TypeReference (); + type.type = (Type_) prop.symbol.parent_symbol.node; + current_symbol.add ("this", new Symbol (node = type)); + } + + public override void visit_end_property (Property prop) { + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_begin_property_accessor (PropertyAccessor acc) { + acc.symbol = new Symbol (node = acc); + acc.symbol.parent_symbol = current_symbol; + current_symbol = acc.symbol; + + if (acc.writable || acc.construct_) { + current_symbol.add ("value", new Symbol (node = ((Property) current_symbol.parent_symbol.node).type_reference)); + } + } + + public override void visit_end_property_accessor (PropertyAccessor acc) { + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_begin_block (Block b) { + b.symbol = new Symbol (node = b); + b.symbol.parent_symbol = current_symbol; + current_symbol = b.symbol; + } + + public override void visit_end_block (Block b) { + current_symbol = current_symbol.parent_symbol; } public override void visit_type_parameter (TypeParameter p) { diff --git a/vala/vala/valasymbolresolver.vala b/vala/vala/valasymbolresolver.vala index e8b27e9a9..036796169 100644 --- a/vala/vala/valasymbolresolver.vala +++ b/vala/vala/valasymbolresolver.vala @@ -24,11 +24,13 @@ using GLib; namespace Vala { public class SymbolResolver : CodeVisitor { + Symbol root_symbol; Symbol current_scope; List current_using_directives; public void resolve (CodeContext context) { - current_scope = context.root; + root_symbol = context.root; + current_scope = root_symbol; context.accept (this); } @@ -53,6 +55,15 @@ namespace Vala { } public override void visit_end_class (Class cl) { + foreach (TypeReference type in cl.base_types) { + if (type.type is Class) { + if (cl.base_class != null) { + stderr.printf ("error: multiple base classes specified\n"); + } + cl.base_class = type.type; + } + } + current_scope = current_scope.parent_symbol; } @@ -73,6 +84,10 @@ namespace Vala { } public override void visit_type_reference (TypeReference type) { + if (type.type_name.cmp ("void") == 0) { + return; + } + if (type.namespace_name == null) { Symbol sym = null; Symbol scope = current_scope; @@ -85,20 +100,33 @@ namespace Vala { var local_sym = ns.namespace_symbol.lookup (type.type_name); if (sym != null && local_sym != null) { // raise error - stderr.printf ("ambigous type name %s\n", type.type_name); + stderr.printf ("error: ambiguous type name %s\n", type.type_name); } sym = local_sym; } } if (sym == null) { // raise error, type not found - stderr.printf ("type %s not found\n", type.type_name); + stderr.printf ("error: type %s not found\n", type.type_name); } if (sym.node is TypeParameter) { type.type_parameter = sym.node; } else { type.type = (Type_) sym.node; } + } else { + var ns_symbol = root_symbol.lookup (type.namespace_name); + if (ns_symbol == null) { + // raise error + stderr.printf ("error: namespace ´%s´ not found\n", type.namespace_name); + } + + var sym = ns_symbol.lookup (type.type_name); + if (sym == null) { + // raise error + stderr.printf ("error: symbol ´%s´ not found in namespace ´%s´\n", type.type_name, type.namespace_name); + } + type.type = (Type_) sym.node; } } } diff --git a/vala/vala/valavariabledeclarator.vala b/vala/vala/valavariabledeclarator.vala index 55cfca6ea..21fd71553 100644 --- a/vala/vala/valavariabledeclarator.vala +++ b/vala/vala/valavariabledeclarator.vala @@ -27,6 +27,7 @@ namespace Vala { public readonly ref string name; public readonly ref Expression initializer; public readonly ref SourceReference source_reference; + public ref TypeReference type_reference; public static ref VariableDeclarator new (string name, Expression init, SourceReference source) { return (new VariableDeclarator (name = name, initializer = init, source_reference = source)); @@ -36,6 +37,10 @@ namespace Vala { if (initializer != null) { initializer.accept (visitor); } + + if (type_reference != null) { + type_reference.accept (visitor); + } visitor.visit_variable_declarator (this); } diff --git a/vala/valac/context.c b/vala/valac/context.c index 3af613b7b..637c93850 100644 --- a/vala/valac/context.c +++ b/vala/valac/context.c @@ -445,6 +445,14 @@ vala_context_resolve_types_in_expression (ValaContext *context, ValaNamespace *n case VALA_EXPRESSION_TYPE_MEMBER_ACCESS: vala_context_resolve_types_in_expression (context, namespace, expr->member_access.left); break; + case VALA_EXPRESSION_TYPE_OPERATION: + if (expr->op.left != NULL) { + vala_context_resolve_types_in_expression (context, namespace, expr->op.left); + } + if (expr->op.right != NULL) { + vala_context_resolve_types_in_expression (context, namespace, expr->op.right); + } + break; case VALA_EXPRESSION_TYPE_OBJECT_CREATION: vala_context_resolve_type_reference (context, namespace, NULL, expr->object_creation.type); for (l = expr->object_creation.named_argument_list; l != NULL; l = l->next) { diff --git a/vala/valac/parser.y b/vala/valac/parser.y index 5843f74fa..634041c38 100644 --- a/vala/valac/parser.y +++ b/vala/valac/parser.y @@ -293,6 +293,7 @@ ValaLocation *get_location (int lineno, int colno) %type accessor_declarations %type get_accessor_declaration %type set_accessor_declaration +%type accessor_body %type named_argument %type constant_declaration %type struct_declaration @@ -891,18 +892,73 @@ modifier ; property_declaration - : opt_attribute_sections opt_modifiers type_name IDENTIFIER OPEN_BRACE accessor_declarations CLOSE_BRACE + : opt_attribute_sections opt_modifiers opt_parameter_modifier type_name IDENTIFIER OPEN_BRACE accessor_declarations CLOSE_BRACE { - $$ = $6; - $$->name = g_strdup ($4); - $$->location = current_location (@4); - $$->return_type = $3; + $$ = $7; + $$->name = g_strdup ($5); + $$->location = current_location (@5); + $$->return_type = $4; /* default fields to private access */ if (($2 & VALA_MODIFIER_PUBLIC) == 0) { yyerror (&@2, "Properties must have a public modifier."); YYERROR; } $$->modifiers = $2; + + if ($$->get_statement == NULL && $$->set_statement == NULL) { + // no property bodies provided => create private field and public construct-only property + + ValaField *f = g_new0 (ValaField, 1); + + f->location = current_location (@5); + f->modifiers = VALA_MODIFIER_PRIVATE; + f->declaration_statement = g_new0 (ValaStatement, 1); + f->declaration_statement->type = VALA_STATEMENT_TYPE_VARIABLE_DECLARATION; + f->declaration_statement->location = current_location (@5); + f->declaration_statement->variable_declaration = g_new0 (ValaVariableDeclaration, 1); + f->declaration_statement->variable_declaration->type = $4; + f->declaration_statement->variable_declaration->declarator = g_new0 (ValaVariableDeclarator, 1); + f->declaration_statement->variable_declaration->declarator->name = g_strdup_printf ("_%s", $5); + f->declaration_statement->variable_declaration->declarator->location = current_location (@5); + f->class = current_class; + + ValaStatement *stmt; + + $$->get_statement = g_new0 (ValaStatement, 1); + $$->get_statement->type = VALA_STATEMENT_TYPE_BLOCK; + $$->get_statement->location = current_location (@5); + + stmt = g_new0 (ValaStatement, 1); + stmt->type = VALA_STATEMENT_TYPE_RETURN; + stmt->location = current_location (@5); + stmt->expr = g_new0 (ValaExpression, 1); + stmt->expr->type = VALA_EXPRESSION_TYPE_SIMPLE_NAME; + stmt->expr->location = current_location (@5); + stmt->expr->str = g_strdup_printf ("_%s", $5); + $$->get_statement->block.statements = g_list_append ($$->get_statement->block.statements, stmt); + + $$->set_statement = g_new0 (ValaStatement, 1); + $$->set_statement->type = VALA_STATEMENT_TYPE_BLOCK; + $$->set_statement->location = current_location (@5); + + stmt = g_new0 (ValaStatement, 1); + stmt->type = VALA_STATEMENT_TYPE_EXPRESSION; + stmt->location = current_location (@5); + stmt->expr = g_new0 (ValaExpression, 1); + stmt->expr->type = VALA_EXPRESSION_TYPE_ASSIGNMENT; + stmt->expr->location = current_location (@5); + stmt->expr->assignment.left = g_new0 (ValaExpression, 1); + stmt->expr->assignment.left->type = VALA_EXPRESSION_TYPE_SIMPLE_NAME; + stmt->expr->assignment.left->location = current_location (@5); + stmt->expr->assignment.left->str = g_strdup_printf ("_%s", $5); + stmt->expr->assignment.right = g_new0 (ValaExpression, 1); + stmt->expr->assignment.right->type = VALA_EXPRESSION_TYPE_SIMPLE_NAME; + stmt->expr->assignment.right->location = current_location (@5); + stmt->expr->assignment.right->str = "value"; + $$->set_statement->block.statements = g_list_append ($$->set_statement->block.statements, stmt); + + current_class->fields = g_list_append (current_class->fields, f); + } } ; @@ -932,27 +988,35 @@ accessor_declarations ; get_accessor_declaration - : GET block + : GET accessor_body { $$ = $2; } ; set_accessor_declaration - : SET block + : SET accessor_body { $$ = $2; } - | CONSTRUCT block + | CONSTRUCT accessor_body { $$ = $2; } - | CONSTRUCT SET block + | SET CONSTRUCT accessor_body { $$ = $3; } ; +accessor_body + : block + | SEMICOLON + { + $$ = NULL; + } + ; + block : OPEN_BRACE opt_statement_list CLOSE_BRACE {