From b25848cbbb254bf822e05819bed05440586c94bf Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=BCrg=20Billeter?= Date: Thu, 22 Jun 2006 08:48:18 +0000 Subject: [PATCH] support LAMBDA and CALLBACK support callbacks and lambda expressions add MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 2006-06-22 Jürg Billeter * vala/scanner.l: support LAMBDA and CALLBACK * vala/parser.y: support callbacks and lambda expressions * vala/valacodevisitor.vala: add visit methods for callbacks and lambda expressions * vala/valasymbolbuilder.vala: use non-null parameter types, support callbacks * vala/valasemanticanalyzer.vala: partially support interface methods, support callback invocations * vala/valamemorymanager.vala: support callback invocations * vala/valacodegenerator.vala: partially support interface methods * vala/valacallback.vala: initial implementation * vala/valacodenode.vala: replace public fields by properties * vala/valaexpression.vala: add expected_type field * vala/valainvocationexpression.vala: also visit at beginning * vala/valalambdaexpression.vala * vala/valanamespace.vala: support callbacks * vala/vala.h: update * vala/Makefile.am: update svn path=/trunk/; revision=50 --- vala/ChangeLog | 21 +++++++++ vala/vala/Makefile.am | 3 ++ vala/vala/parser.y | 84 +++++++++++++++++++++++++++++++++ vala/vala/scanner.l | 2 + vala/vala/vala.h | 2 + vala/vala/valacallback.vala | 46 ++++++++++++++++++ vala/vala/valacodegenerator.vala | 8 ++-- vala/vala/valacodenode.vala | 6 +-- vala/vala/valacodevisitor.vala | 17 ++++++- vala/vala/valaexpression.vala | 5 ++ vala/vala/valainvocationexpression.vala | 4 +- vala/vala/valalambdaexpression.vala | 54 +++++++++++++++++++++ vala/vala/valamemorymanager.vala | 14 ++++-- vala/vala/valanamespace.vala | 10 ++++ vala/vala/valasemanticanalyzer.vala | 47 +++++++++++++++--- vala/vala/valasymbolbuilder.vala | 80 +++++++++++++++++++------------ 16 files changed, 356 insertions(+), 47 deletions(-) create mode 100644 vala/vala/valalambdaexpression.vala diff --git a/vala/ChangeLog b/vala/ChangeLog index 930b033..e01979b 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,3 +1,24 @@ +2006-06-22 Jürg Billeter + + * vala/scanner.l: support LAMBDA and CALLBACK + * vala/parser.y: support callbacks and lambda expressions + * vala/valacodevisitor.vala: add visit methods for callbacks and lambda + expressions + * vala/valasymbolbuilder.vala: use non-null parameter types, support + callbacks + * vala/valasemanticanalyzer.vala: partially support interface methods, + support callback invocations + * vala/valamemorymanager.vala: support callback invocations + * vala/valacodegenerator.vala: partially support interface methods + * vala/valacallback.vala: initial implementation + * vala/valacodenode.vala: replace public fields by properties + * vala/valaexpression.vala: add expected_type field + * vala/valainvocationexpression.vala: also visit at beginning + * vala/valalambdaexpression.vala + * vala/valanamespace.vala: support callbacks + * vala/vala.h: update + * vala/Makefile.am: update + 2006-06-18 Jürg Billeter * vala/scanner.l: support TYPEOF diff --git a/vala/vala/Makefile.am b/vala/vala/Makefile.am index 53388cf..0f466e8 100644 --- a/vala/vala/Makefile.am +++ b/vala/vala/Makefile.am @@ -140,6 +140,9 @@ libvala_la_SOURCES = \ valainvocationexpression.c \ valainvocationexpression.h \ valainvocationexpression.vala \ + valalambdaexpression.c \ + valalambdaexpression.h \ + valalambdaexpression.vala \ valaliteral.c \ valaliteral.h \ valaliteral.vala \ diff --git a/vala/vala/parser.y b/vala/vala/parser.y index 39b9ad7..53e5385 100644 --- a/vala/vala/parser.y +++ b/vala/vala/parser.y @@ -75,6 +75,7 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); ValaEnumValue *enum_value; ValaFlags *flags; ValaFlagsValue *flags_value; + ValaCallback *callback; ValaConstant *constant; ValaField *field; ValaMethod *method; @@ -125,6 +126,7 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %token OP_SHIFT_RIGHT ">>" %token OP_LE "<=" %token OP_GE ">=" +%token LAMBDA "=>" %token GENERIC_LT "generic <" %token OP_LT "<" %token OP_GT ">" @@ -145,6 +147,7 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %token ABSTRACT "abstract" %token BREAK "break" +%token CALLBACK "callback" %token CLASS "class" %token CONST "const" %token CONSTRUCT "construct" @@ -218,6 +221,9 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %type conditional_and_expression %type conditional_or_expression %type conditional_expression +%type lambda_expression +%type opt_lambda_parameter_list +%type lambda_parameter_list %type assignment %type assignment_operator %type opt_expression @@ -275,6 +281,7 @@ static void yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg); %type enum_member_declarations %type enum_member_declaration %type flags_declaration +%type callback_declaration %type constant_declaration %type constant_declarator %type field_declaration @@ -853,6 +860,48 @@ conditional_expression } ; +lambda_expression + : OPEN_PARENS opt_lambda_parameter_list CLOSE_PARENS LAMBDA expression + { + ValaSourceReference *src = src(@4); + $$ = VALA_EXPRESSION (vala_lambda_expression_new ($2, $5, src)); + if ($2 != NULL) { + g_list_free ($2); + } + g_object_unref ($5); + g_object_unref (src); + } + | IDENTIFIER LAMBDA expression + { + ValaSourceReference *src = src(@2); + $$ = VALA_EXPRESSION (vala_lambda_expression_new (NULL, $3, src)); + g_object_unref ($3); + g_object_unref (src); + vala_lambda_expression_add_parameter (VALA_LAMBDA_EXPRESSION ($$), $1); + g_free ($1); + } + ; + +opt_lambda_parameter_list + : /* empty */ + { + $$ = NULL; + } + | lambda_parameter_list + ; + +lambda_parameter_list + : IDENTIFIER COMMA IDENTIFIER + { + $$ = g_list_append (NULL, $1); + $$ = g_list_append ($$, $3); + } + | lambda_parameter_list COMMA IDENTIFIER + { + $$ = g_list_append ($1, $3); + } + ; + assignment : unary_expression assignment_operator expression { @@ -921,6 +970,7 @@ opt_expression expression : conditional_expression + | lambda_expression | assignment | error { @@ -1319,6 +1369,14 @@ namespace_member_declaration g_object_unref ($1); } } + | callback_declaration + { + /* skip declarations with errors */ + if ($1 != NULL) { + vala_namespace_add_callback (current_namespace, $1); + g_object_unref ($1); + } + } | field_declaration { /* skip declarations with errors */ @@ -2221,6 +2279,32 @@ flags_member_declaration : opt_attributes IDENTIFIER ; +callback_declaration + : comment opt_attributes opt_access_modifier CALLBACK type identifier_or_new OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS SEMICOLON + { + GList *l; + + ValaSourceReference *src = src_com(@6, $1); + $$ = vala_callback_new ($6, $5, src); + g_object_unref (src); + if ($3 != 0) { + VALA_TYPE_($$)->access = $3; + } + VALA_CODE_NODE($$)->attributes = $2; + + for (l = $8; l != NULL; l = l->next) { + vala_callback_add_parameter ($$, l->data); + g_object_unref (l->data); + } + if ($8 != NULL) { + g_list_free ($8); + } + + g_object_unref ($5); + g_free ($6); + } + ; + opt_attributes : /* empty */ { diff --git a/vala/vala/scanner.l b/vala/vala/scanner.l index c3fd708..d3b9b3e 100644 --- a/vala/vala/scanner.l +++ b/vala/vala/scanner.l @@ -92,6 +92,7 @@ literal ({literal_integer}|{literal_real}|{literal_character}|{literal_string} ">>" { uploc; return OP_SHIFT_RIGHT; } "<=" { uploc; return OP_LE; } ">=" { uploc; return OP_GE; } +"=>" { uploc; return LAMBDA; } "<"(("ref"|"weak")" "+)?({ident}".")?{ident}"#"?("[]""#"?)?(","" "*({ident}".")?{ident}"#"?("[]""#"?)?)*">" { yyless (1); uploc; return GENERIC_LT; } "<" { uploc; return OP_LT; } ">" { uploc; return OP_GT; } @@ -114,6 +115,7 @@ literal ({literal_integer}|{literal_real}|{literal_character}|{literal_string} "abstract" { uploc; return ABSTRACT; } "break" { uploc; return BREAK; } +"callback" { uploc; return CALLBACK; } "class" { uploc; return CLASS; } "const" { uploc; return CONST; } "construct" { uploc; return CONSTRUCT; } diff --git a/vala/vala/vala.h b/vala/vala/vala.h index 009001c..88733b1 100644 --- a/vala/vala/vala.h +++ b/vala/vala/vala.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/vala/vala/valacallback.vala b/vala/vala/valacallback.vala index 9cc73ac..0185c05 100644 --- a/vala/vala/valacallback.vala +++ b/vala/vala/valacallback.vala @@ -24,5 +24,51 @@ using GLib; namespace Vala { public class Callback : Type_ { + public TypeReference return_type { get; construct; } + public List parameters; + + public static ref Callback new (string! name, TypeReference return_type, SourceReference source) { + return (new Callback (name = name, return_type = return_type, source_reference = source)); + } + + public void add_parameter (FormalParameter! param) { + parameters.append (param); + } + + public ref List get_parameters () { + return parameters.copy (); + } + + public override void accept (CodeVisitor! visitor) { + visitor.visit_begin_callback (this); + + return_type.accept (visitor); + + foreach (FormalParameter param in parameters) { + param.accept (visitor); + } + + visitor.visit_end_callback (this); + } + + private string cname; + public override string get_cname () { + if (cname == null) { + cname = "%s%s".printf (@namespace.get_cprefix (), name); + } + return cname; + } + + public override bool is_reference_type () { + return true; + } + + public override string get_ref_function () { + return ""; + } + + public override string get_free_function () { + return ""; + } } } diff --git a/vala/vala/valacodegenerator.vala b/vala/vala/valacodegenerator.vala index 9e62282..70c7f26 100644 --- a/vala/vala/valacodegenerator.vala +++ b/vala/vala/valacodegenerator.vala @@ -302,7 +302,9 @@ namespace Vala { var methods = cl.get_methods (); foreach (Method m in methods) { if (m.is_virtual || m.is_override) { - var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_CLASS".printf (((Class) m.base_method.symbol.parent_symbol.node).get_upper_case_cname (null)))); + var base_type = m.base_method.symbol.parent_symbol.node; + + var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null)))); ccast.add_argument (new CCodeIdentifier (name = "klass")); init_block.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeMemberAccess (inner = ccast, member_name = m.name, is_pointer = true), right = new CCodeIdentifier (name = m.get_real_cname ())))); } @@ -695,7 +697,7 @@ namespace Vala { function.add_parameter (cparam); } else { var base_type = new TypeReference (); - base_type.type = (Class) m.base_method.symbol.parent_symbol.node; + base_type.type = (Type_) m.base_method.symbol.parent_symbol.node; var cparam = new CCodeFormalParameter (type_name = base_type.get_cname (), name = "base"); function.add_parameter (cparam); } @@ -1497,7 +1499,7 @@ namespace Vala { visit_expression (expr); } - public override void visit_invocation_expression (InvocationExpression! expr) { + public override void visit_end_invocation_expression (InvocationExpression! expr) { var ccall = new CCodeFunctionCall (call = (CCodeExpression) expr.call.ccodenode); var m = (Method) expr.call.symbol_reference.node; diff --git a/vala/vala/valacodenode.vala b/vala/vala/valacodenode.vala index a194caa..93aa1d9 100644 --- a/vala/vala/valacodenode.vala +++ b/vala/vala/valacodenode.vala @@ -24,10 +24,10 @@ using GLib; namespace Vala { public abstract class CodeNode { - public Symbol symbol; + public Symbol symbol { get; set; } public List attributes; - public CCodeNode ccodenode; - public bool error; + public CCodeNode ccodenode { get; set; } + public bool error { get; set; } public abstract void accept (CodeVisitor visitor); } diff --git a/vala/vala/valacodevisitor.vala b/vala/vala/valacodevisitor.vala index 7e568e8..cf773a9 100644 --- a/vala/vala/valacodevisitor.vala +++ b/vala/vala/valacodevisitor.vala @@ -72,6 +72,12 @@ namespace Vala { public virtual void visit_flags_value (FlagsValue! fv) { } + public virtual void visit_begin_callback (Callback! cb) { + } + + public virtual void visit_end_callback (Callback! cb) { + } + public virtual void visit_constant (Constant! c) { } @@ -207,7 +213,10 @@ namespace Vala { public virtual void visit_member_access (MemberAccess! expr) { } - public virtual void visit_invocation_expression (InvocationExpression! expr) { + public virtual void visit_begin_invocation_expression (InvocationExpression! expr) { + } + + public virtual void visit_end_invocation_expression (InvocationExpression! expr) { } public virtual void visit_postfix_expression (PostfixExpression! expr) { @@ -234,6 +243,12 @@ namespace Vala { public virtual void visit_conditional_expression (ConditionalExpression! expr) { } + public virtual void visit_begin_lambda_expression (LambdaExpression! expr) { + } + + public virtual void visit_end_lambda_expression (LambdaExpression! expr) { + } + public virtual void visit_assignment (Assignment! a) { } diff --git a/vala/vala/valaexpression.vala b/vala/vala/valaexpression.vala index 7f51b29..736da20 100644 --- a/vala/vala/valaexpression.vala +++ b/vala/vala/valaexpression.vala @@ -31,6 +31,11 @@ namespace Vala { */ public TypeReference static_type; + /* filled by semantic analyzer, used by lambda expressions in + * semantic analyzer + */ + public TypeReference expected_type; + public Symbol symbol_reference; /* set by memory manager, used by code generator */ diff --git a/vala/vala/valainvocationexpression.vala b/vala/vala/valainvocationexpression.vala index 1ed1943..4f1bb1c 100644 --- a/vala/vala/valainvocationexpression.vala +++ b/vala/vala/valainvocationexpression.vala @@ -36,12 +36,14 @@ namespace Vala { } public override void accept (CodeVisitor visitor) { + visitor.visit_begin_invocation_expression (this); + call.accept (visitor); foreach (Expression expr in argument_list) { expr.accept (visitor); } - visitor.visit_invocation_expression (this); + visitor.visit_end_invocation_expression (this); } } } diff --git a/vala/vala/valalambdaexpression.vala b/vala/vala/valalambdaexpression.vala new file mode 100644 index 0000000..ee46855 --- /dev/null +++ b/vala/vala/valalambdaexpression.vala @@ -0,0 +1,54 @@ +/* valalambdaexpression.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 LambdaExpression : Expression { + public List parameters { get; set; } + public Expression inner { get; set; } + + /* generated anonymous method */ + public Method method; + + public static ref LambdaExpression new (List params, Expression! inner, SourceReference source) { + return new LambdaExpression (parameters = params, inner = inner, source_reference = source); + } + + public void add_parameter (string! param) { + _parameters.append (param); + } + + public override void accept (CodeVisitor! visitor) { + visitor.visit_begin_lambda_expression (this); + + inner.accept (visitor); + visitor.visit_end_full_expression (inner); + + visitor.visit_end_lambda_expression (this); + + if (method != null) { + method.accept (visitor); + } + } + } +} diff --git a/vala/vala/valamemorymanager.vala b/vala/vala/valamemorymanager.vala index 0d2cf7d..ff3ad69 100644 --- a/vala/vala/valamemorymanager.vala +++ b/vala/vala/valamemorymanager.vala @@ -95,9 +95,17 @@ namespace Vala { visit_possibly_leaked_expression (expr.inner); } - public override void visit_invocation_expression (InvocationExpression! expr) { - var m = (Method) expr.call.symbol_reference.node; - var params = m.get_parameters (); + public override void visit_end_invocation_expression (InvocationExpression! expr) { + List params; + + var msym = expr.call.symbol_reference; + if (msym.node is Callback) { + var cb = (Callback) msym.node; + params = cb.get_parameters (); + } else { + var m = (Method) msym.node; + params = m.get_parameters (); + } foreach (Expression arg in expr.argument_list) { if (params != null) { var param = (FormalParameter) params.data; diff --git a/vala/vala/valanamespace.vala b/vala/vala/valanamespace.vala index 56a8a6f..630b0e3 100644 --- a/vala/vala/valanamespace.vala +++ b/vala/vala/valanamespace.vala @@ -32,6 +32,7 @@ namespace Vala { List structs; List enums; List flags_; + List callbacks; List fields; List methods; @@ -76,6 +77,11 @@ namespace Vala { flags_.append (fl); fl.@namespace = this; } + + public void add_callback (Callback! cb) { + callbacks.append (cb); + cb.@namespace = this; + } public ref List get_structs () { return structs.copy (); @@ -116,6 +122,10 @@ namespace Vala { fl.accept (visitor); } + foreach (Callback cb in callbacks) { + cb.accept (visitor); + } + foreach (Field f in fields) { f.accept (visitor); } diff --git a/vala/vala/valasemanticanalyzer.vala b/vala/vala/valasemanticanalyzer.vala index e2b044c..4a49214 100644 --- a/vala/vala/valasemanticanalyzer.vala +++ b/vala/vala/valasemanticanalyzer.vala @@ -131,6 +131,24 @@ namespace Vala { } } if (m.base_method == null) { + /* FIXME: also look at interfaces implemented + * by one of the base types + */ + foreach (TypeReference type in cl.base_types) { + if (type.type is Interface) { + var iface = (Interface) type.type; + var sym = iface.symbol.lookup (m.name); + if (sym != null && sym.node is Method) { + var base_method = (Method) sym.node; + if (base_method.is_abstract || base_method.is_virtual) { + m.base_method = base_method; + break; + } + } + } + } + } + if (m.base_method == null) { Report.error (m.source_reference, "%s: no suitable method found to override".printf (m.symbol.get_full_name ())); } } else if (current_symbol.node is Struct) { @@ -444,20 +462,37 @@ namespace Vala { return false; } - public override void visit_invocation_expression (InvocationExpression! expr) { + public override void visit_begin_invocation_expression (InvocationExpression! expr) { + } + + public override void visit_end_invocation_expression (InvocationExpression! expr) { if (expr.call.symbol_reference == null) { /* if method resolving didn't succeed, skip this check */ return; } + + var msym = expr.call.symbol_reference; + + TypeReference ret_type; + List params; + + if (msym.node is Callback) { + var cb = (Callback) msym.node; + ret_type = cb.return_type; + params = cb.parameters; + } else { + var m = (Method) msym.node; + ret_type = m.return_type; + params = m.parameters; + } - var m = (Method) expr.call.symbol_reference.node; - expr.static_type = m.return_type; + expr.static_type = ret_type; List arg_it = expr.argument_list; bool ellipsis = false; int i = 0; - foreach (FormalParameter param in m.parameters) { + foreach (FormalParameter param in params) { if (param.ellipsis) { ellipsis = true; break; @@ -470,7 +505,7 @@ namespace Vala { if (arg_it == null) { if (param.default_expression == null) { - Report.error (expr.source_reference, "Method `%s' does not take %d arguments".printf (m.symbol.get_full_name (), expr.argument_list.length ())); + Report.error (expr.source_reference, "Method `%s' does not take %d arguments".printf (msym.get_full_name (), expr.argument_list.length ())); return; } } else { @@ -489,7 +524,7 @@ namespace Vala { } if (!ellipsis && arg_it != null) { - Report.error (expr.source_reference, "Method `%s' does not take %d arguments".printf (m.symbol.get_full_name (), expr.argument_list.length ())); + Report.error (expr.source_reference, "Method `%s' does not take %d arguments".printf (msym.get_full_name (), expr.argument_list.length ())); return; } } diff --git a/vala/vala/valasymbolbuilder.vala b/vala/vala/valasymbolbuilder.vala index 908c6c0..752b48c 100644 --- a/vala/vala/valasymbolbuilder.vala +++ b/vala/vala/valasymbolbuilder.vala @@ -29,12 +29,12 @@ namespace Vala { Symbol current_type; Symbol current_symbol; - public void build (CodeContext context) { + public void build (CodeContext! context) { root = context.root; context.accept (this); } - public override void visit_begin_namespace (Namespace ns) { + public override void visit_begin_namespace (Namespace! ns) { if (ns.name == null) { ns.symbol = root; return; @@ -48,11 +48,11 @@ namespace Vala { current_symbol = ns.symbol; } - public override void visit_end_namespace (Namespace ns) { + public override void visit_end_namespace (Namespace! ns) { current_symbol = current_symbol.parent_symbol; } - public override void visit_begin_class (Class cl) { + public override void visit_begin_class (Class! cl) { if (cl.@namespace.symbol.lookup (cl.name) != null) { cl.error = true; Report.error (cl.source_reference, "The namespace `%s' already contains a definition for `%s'".printf (cl.@namespace.symbol.get_full_name (), cl.name)); @@ -64,7 +64,7 @@ namespace Vala { current_symbol = cl.symbol; } - public override void visit_end_class (Class cl) { + public override void visit_end_class (Class! cl) { if (cl.error) { /* skip classes with errors */ return; @@ -73,7 +73,7 @@ namespace Vala { current_symbol = current_symbol.parent_symbol; } - public override void visit_begin_struct (Struct st) { + public override void visit_begin_struct (Struct! st) { if (st.@namespace.symbol.lookup (st.name) != null) { st.error = true; Report.error (st.source_reference, "The namespace `%s' already contains a definition for `%s'".printf (st.@namespace.symbol.get_full_name (), st.name)); @@ -85,7 +85,7 @@ namespace Vala { current_symbol = st.symbol; } - public override void visit_end_struct (Struct st) { + public override void visit_end_struct (Struct! st) { if (st.error) { /* skip structs with errors */ return; @@ -94,7 +94,7 @@ namespace Vala { current_symbol = current_symbol.parent_symbol; } - public override void visit_begin_interface (Interface iface) { + public override void visit_begin_interface (Interface! iface) { if (iface.@namespace.symbol.lookup (iface.name) != null) { iface.error = true; Report.error (iface.source_reference, "The namespace `%s' already contains a definition for `%s'".printf (iface.@namespace.symbol.get_full_name (), iface.name)); @@ -106,7 +106,7 @@ namespace Vala { current_symbol = iface.symbol; } - public override void visit_end_interface (Interface iface) { + public override void visit_end_interface (Interface! iface) { if (iface.error) { /* skip interfaces with errors */ return; @@ -115,7 +115,7 @@ namespace Vala { current_symbol = current_symbol.parent_symbol; } - public override void visit_begin_enum (Enum en) { + public override void visit_begin_enum (Enum! en) { if (en.@namespace.symbol.lookup (en.name) != null) { en.error = true; Report.error (en.source_reference, "The namespace `%s' already contains a definition for `%s'".printf (en.@namespace.symbol.get_full_name (), en.name)); @@ -126,7 +126,7 @@ namespace Vala { current_symbol = en.symbol; } - public override void visit_end_enum (Enum en) { + public override void visit_end_enum (Enum! en) { if (en.error) { /* skip enums with errors */ return; @@ -135,12 +135,32 @@ namespace Vala { current_symbol = current_symbol.parent_symbol; } - public override void visit_enum_value (EnumValue ev) { + 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_begin_callback (Callback! cb) { + if (cb.@namespace.symbol.lookup (cb.name) != null) { + cb.error = true; + Report.error (cb.source_reference, "The namespace `%s' already contains a definition for `%s'".printf (cb.@namespace.symbol.get_full_name (), cb.name)); + return; + } + cb.symbol = new Symbol (node = cb); + cb.@namespace.symbol.add (cb.name, cb.symbol); + current_symbol = cb.symbol; + } + + public override void visit_end_callback (Callback! cb) { + if (cb.error) { + /* skip enums with errors */ + return; + } + + current_symbol = current_symbol.parent_symbol; + } - public override void visit_constant (Constant c) { + public override void visit_constant (Constant! c) { if (current_symbol.lookup (c.name) != null) { c.error = true; Report.error (c.source_reference, "The type `%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), c.name)); @@ -150,7 +170,7 @@ namespace Vala { current_symbol.add (c.name, c.symbol); } - public override void visit_field (Field f) { + public override void visit_field (Field! f) { if (current_symbol.lookup (f.name) != null) { f.error = true; Report.error (f.source_reference, "The type `%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), f.name)); @@ -160,7 +180,7 @@ namespace Vala { current_symbol.add (f.name, f.symbol); } - public override void visit_begin_method (Method m) { + public override void visit_begin_method (Method! m) { if (current_symbol.lookup (m.name) != null) { m.error = true; Report.error (m.source_reference, "The type `%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), m.name)); @@ -178,7 +198,7 @@ namespace Vala { } } - public override void visit_end_method (Method m) { + public override void visit_end_method (Method! m) { if (m.error) { /* skip methods with errors */ return; @@ -187,14 +207,14 @@ namespace Vala { current_symbol = current_symbol.parent_symbol; } - public override void visit_formal_parameter (FormalParameter p) { + public override void visit_formal_parameter (FormalParameter! p) { if (!p.ellipsis) { p.symbol = new Symbol (node = p); current_symbol.add (p.name, p.symbol); } } - public override void visit_begin_property (Property prop) { + public override void visit_begin_property (Property! prop) { if (current_symbol.lookup (prop.name) != null) { prop.error = true; Report.error (prop.source_reference, "The type `%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), prop.name)); @@ -210,7 +230,7 @@ namespace Vala { current_symbol.add (prop.this_parameter.name, prop.this_parameter.symbol); } - public override void visit_end_property (Property prop) { + public override void visit_end_property (Property! prop) { if (prop.error) { /* skip properties with errors */ return; @@ -219,7 +239,7 @@ namespace Vala { current_symbol = current_symbol.parent_symbol; } - public override void visit_begin_property_accessor (PropertyAccessor acc) { + 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; @@ -246,11 +266,11 @@ namespace Vala { } } - public override void visit_end_property_accessor (PropertyAccessor acc) { + public override void visit_end_property_accessor (PropertyAccessor! acc) { current_symbol = current_symbol.parent_symbol; } - public override void visit_begin_signal (Signal sig) { + public override void visit_begin_signal (Signal! sig) { if (current_symbol.lookup (sig.name) != null) { sig.error = true; Report.error (sig.source_reference, "The type `%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), sig.name)); @@ -261,7 +281,7 @@ namespace Vala { current_symbol = sig.symbol; } - public override void visit_end_signal (Signal sig) { + public override void visit_end_signal (Signal! sig) { if (sig.error) { /* skip signals with errors */ return; @@ -270,37 +290,37 @@ namespace Vala { current_symbol = current_symbol.parent_symbol; } - public override void visit_begin_constructor (Constructor c) { + public override void visit_begin_constructor (Constructor! c) { c.symbol = new Symbol (node = c); c.symbol.parent_symbol = current_symbol; current_symbol = c.symbol; } - public override void visit_end_constructor (Constructor c) { + public override void visit_end_constructor (Constructor! c) { current_symbol = current_symbol.parent_symbol; } - public override void visit_begin_destructor (Destructor d) { + public override void visit_begin_destructor (Destructor! d) { d.symbol = new Symbol (node = d); d.symbol.parent_symbol = current_symbol; current_symbol = d.symbol; } - public override void visit_end_destructor (Destructor d) { + public override void visit_end_destructor (Destructor! d) { current_symbol = current_symbol.parent_symbol; } - public override void visit_begin_block (Block b) { + 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) { + public override void visit_end_block (Block! b) { current_symbol = current_symbol.parent_symbol; } - public override void visit_type_parameter (TypeParameter p) { + public override void visit_type_parameter (TypeParameter! p) { if (p.type.symbol.lookup (p.name) != null) { Report.error (p.source_reference, "The method `%s' already has a parameter named `%s'".printf (current_symbol.get_full_name (), p.name)); return; -- 2.7.4