+2006-05-17 Jürg Billeter <j@bitron.ch>
+
+ * 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 <j@bitron.ch>
* vala/scanner.l: fix multi-line comments
namespace Vala {
public class CCodeFragment : CCodeNode {
- public readonly List<CCodeNode#># children;
+ public ref GLib.List<ref CCodeNode> children { get; construct; }
public void append (CCodeNode node) {
_children.append (node);
--- /dev/null
+/* 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 <j@bitron.ch>
+ */
+
+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 (")");
+ }
+ }
+}
var attributeprocessor = new AttributeProcessor ();
attributeprocessor.process (context);
+ var analyzer = new SemanticAnalyzer ();
+ analyzer.analyze (context);
+
var code_generator = new CodeGenerator ();
code_generator.emit (context);
}
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;
%type <statement> return_statement
%type <namespace> namespace_declaration
%type <class> class_declaration
+%type <list> opt_class_base
+%type <list> class_base
+%type <list> type_list
%type <property> property_declaration
+%type <property_accessor> get_accessor_declaration
+%type <property_accessor> opt_set_accessor_declaration
+%type <property_accessor> set_accessor_declaration
%type <struct_> struct_declaration
%type <struct_> struct_header
%type <enum_> enum_declaration
+%type <list> enum_body
+%type <list> opt_enum_member_declarations
+%type <list> enum_member_declarations
+%type <enum_value> enum_member_declaration
%type <constant> constant_declaration
%type <variable_declarator> constant_declarator
%type <field> field_declaration
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
{
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
{
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
class_member_declaration
: constant_declaration
+ {
+ vala_struct_add_constant (current_struct, $1);
+ }
| field_declaration
{
vala_struct_add_field (current_struct, $1);
vala_struct_add_method (current_struct, $1);
}
| property_declaration
+ {
+ vala_class_add_property (VALA_CLASS (current_struct), $1);
+ }
;
constant_declaration
{
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) {
;
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
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
#include <vala/valadeclarationstatement.h>
#include <vala/valaemptystatement.h>
#include <vala/valaenum.h>
+#include <vala/valaenumvalue.h>
#include <vala/valaexpression.h>
#include <vala/valaexpressionstatement.h>
#include <vala/valafield.h>
#include <vala/valaparser.h>
#include <vala/valapostfixexpression.h>
#include <vala/valaproperty.h>
+#include <vala/valapropertyaccessor.h>
#include <vala/valareturnstatement.h>
#include <vala/valasimplename.h>
#include <vala/valasourcefile.h>
namespace Vala {
public class Block : Statement {
- public readonly List<Statement#># statement_list;
- public readonly SourceReference# source_reference;
+ public readonly ref List<ref Statement> statement_list;
+ public readonly ref SourceReference source_reference;
- public static Block# @new (List<Statement> statement_list, SourceReference source) {
+ public static ref Block new (List<Statement> 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);
}
}
}
namespace Vala {
public class Class : Struct {
- public readonly SourceReference# source_reference;
+ public readonly ref SourceReference source_reference;
+ public ref List<ref TypeReference> base_types;
+ public ref Class base_class;
+
+ ref List<ref Property> 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);
}
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;
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) {
}
- 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;
}
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) {
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);
}
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) {
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) {
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) {
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) {
public virtual void visit_simple_name (SimpleName expr) {
}
+ public virtual void visit_parenthesized_expression (ParenthesizedExpression expr) {
+ }
+
public virtual void visit_member_access (MemberAccess expr) {
}
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<ref EnumValue> 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 () {
--- /dev/null
+/* 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 <j@bitron.ch>
+ */
+
+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);
+ }
+ }
+}
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;
}
}
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);
}
}
}
public override void accept (CodeVisitor visitor) {
type_reference.accept (visitor);
+
+ visitor.visit_formal_parameter (this);
}
}
}
using GLib;
namespace Vala {
- public class Literal : CodeNode {
+ public abstract class Literal : CodeNode {
+ public ref TypeReference static_type;
}
}
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;
public bool instance = true;
ref List<ref FormalParameter> 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) {
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);
}
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);
+ }
}
}
en.accept (visitor);
}
+ foreach (Field f in fields) {
+ f.accept (visitor);
+ }
+
visitor.visit_end_namespace (this);
}
namespace Vala {
public class ObjectCreationExpression : Expression {
- public readonly TypeReference# type_reference;
- public readonly List<NamedArgument#># named_argument_list;
- public readonly SourceReference# source_reference;
+ public readonly ref TypeReference type_reference;
+ public readonly ref List<ref NamedArgument> named_argument_list;
+ public readonly ref SourceReference source_reference;
- public static ObjectCreationExpression# @new (TypeReference type, List<NamedArgument> named_argument_list, SourceReference source) {
+ public static ref ObjectCreationExpression new (TypeReference type, List<NamedArgument> 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);
}
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);
}
}
}
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);
}
}
}
--- /dev/null
+/* 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 <j@bitron.ch>
+ */
+
+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);
+ }
+ }
+}
--- /dev/null
+/* 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 <j@bitron.ch>
+ */
+
+using GLib;
+
+namespace Vala {
+ public class SemanticAnalyzer : CodeVisitor {
+ ref Symbol root_symbol;
+ ref Symbol current_symbol;
+
+ List<NamespaceReference> 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;
+ }
+ }
+}
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));
}
public Namespace @namespace;
ref List<ref string> type_parameters;
- List<Field#># fields;
- List<Method#># methods;
+ ref List<ref Constant> constants;
+ ref List<ref Field> fields;
+ ref List<ref Method> methods;
public ref string cname;
public ref string lower_case_csuffix;
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;
p.accept (visitor);
}
+ foreach (Constant c in constants) {
+ c.accept (visitor);
+ }
+
foreach (Field f in fields) {
f.accept (visitor);
}
Symbol root;
Symbol current_namespace;
Symbol current_type;
+ Symbol current_symbol;
public void build (CodeContext context) {
root = context.root;
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) {
}
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) {
}
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");
}
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) {
namespace Vala {
public class SymbolResolver : CodeVisitor {
+ Symbol root_symbol;
Symbol current_scope;
List<NamespaceReference> current_using_directives;
public void resolve (CodeContext context) {
- current_scope = context.root;
+ root_symbol = context.root;
+ current_scope = root_symbol;
context.accept (this);
}
}
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;
}
}
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;
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;
}
}
}
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));
if (initializer != null) {
initializer.accept (visitor);
}
+
+ if (type_reference != null) {
+ type_reference.accept (visitor);
+ }
visitor.visit_variable_declarator (this);
}
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) {
%type <property> accessor_declarations
%type <statement> get_accessor_declaration
%type <statement> set_accessor_declaration
+%type <statement> accessor_body
%type <named_argument> named_argument
%type <constant> constant_declaration
%type <struct_> struct_declaration
;
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);
+ }
}
;
;
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
{