From: Jürg Billeter Date: Mon, 3 Jul 2006 18:43:15 +0000 (+0000) Subject: support implicit namespace specification in struct, interface, enum, and X-Git-Tag: VALA_0_0_1~19 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=629fa2ee7d1009e0f8d329441cfd4df0e04539e3;p=thirdparty%2Fvala.git support implicit namespace specification in struct, interface, enum, and 2006-07-03 Jürg Billeter * vala/parser.y: support implicit namespace specification in struct, interface, enum, and flags declaration * vala/valasymbolbuilder.vala: report error when declaring non-static namespace methods * vala/valasemanticanalyzer.vala: analyze return statements * vala/valacodegenerator.vala: correctly set GParamFlags for properties, initialize static variables, add preconditions to property accessors, support namespace methods * vala/valaassignment.vala, vala/valaattribute.vala: add interface documentation, use implicit namespace specification * tests/test-001.vala, tests/test-002.vala, tests/test-003.vala, tests/test-004.vala, tests/test-005.vala, tests/test-006.vala, tests/test-007.vala, tests/test-008.vala, tests/test-009.vala: update test cases to print test values svn path=/trunk/; revision=60 --- diff --git a/vala/ChangeLog b/vala/ChangeLog index 19df05130..2810b0439 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,3 +1,20 @@ +2006-07-03 Jürg Billeter + + * vala/parser.y: support implicit namespace specification in struct, + interface, enum, and flags declaration + * vala/valasymbolbuilder.vala: report error when declaring non-static + namespace methods + * vala/valasemanticanalyzer.vala: analyze return statements + * vala/valacodegenerator.vala: correctly set GParamFlags for properties, + initialize static variables, add preconditions to property accessors, + support namespace methods + * vala/valaassignment.vala, vala/valaattribute.vala: add interface + documentation, use implicit namespace specification + * tests/test-001.vala, tests/test-002.vala, tests/test-003.vala, + tests/test-004.vala, tests/test-005.vala, tests/test-006.vala, + tests/test-007.vala, tests/test-008.vala, tests/test-009.vala: + update test cases to print test values + 2006-06-30 Jürg Billeter * vala/valacodenode.vala, vala/valadatatype.vala, diff --git a/vala/tests/test-001.vala b/vala/tests/test-001.vala index 53ffd9b17..c83820987 100644 --- a/vala/tests/test-001.vala +++ b/vala/tests/test-001.vala @@ -1,3 +1,8 @@ +using GLib; + namespace Maman { + static int main (int argc, string[] argv) { + stdout.printf ("Namespace Test\n"); + return 0; + } } - diff --git a/vala/tests/test-002.vala b/vala/tests/test-002.vala index 740504d58..5c8c30796 100644 --- a/vala/tests/test-002.vala +++ b/vala/tests/test-002.vala @@ -1,5 +1,11 @@ +using GLib; + namespace Maman { class Bar { + static int main (int argc, string[] argv) { + stdout.printf ("Class in Namespace Test\n"); + return 0; + } } } diff --git a/vala/tests/test-003.vala b/vala/tests/test-003.vala index 054fd3b0a..a4a676987 100644 --- a/vala/tests/test-003.vala +++ b/vala/tests/test-003.vala @@ -1,7 +1,11 @@ -namespace Maman { - class Bar { - } - - class SubBar : Bar { +using GLib; + +class Maman.Bar { +} + +class Maman.SubBar : Bar { + static int main (int argc, string[] argv) { + stdout.printf ("Subtype Test\n"); + return 0; } } diff --git a/vala/tests/test-004.vala b/vala/tests/test-004.vala index 73755686a..f8c39ba3c 100644 --- a/vala/tests/test-004.vala +++ b/vala/tests/test-004.vala @@ -1,9 +1,20 @@ -namespace Maman { - class Bar { - public void do_action () { - } +using GLib; + +class Maman.Bar { + public void do_action () { + stdout.printf (" 2"); } +} + +class Maman.SubBar : Bar { + static int main (int argc, string[] argv) { + stdout.printf ("Inheritance Test: 1"); + + var bar = new SubBar (); + bar.do_action (); + + stdout.printf (" 3\n"); - class SubBar : Bar { + return 0; } } diff --git a/vala/tests/test-005.vala b/vala/tests/test-005.vala index ab2ef53de..026e12277 100644 --- a/vala/tests/test-005.vala +++ b/vala/tests/test-005.vala @@ -1,14 +1,19 @@ -namespace Maman { - class Bar { - public static int do_action (int i) { - return (i + 42); - } +using GLib; + +class Maman.Bar { + public static void do_action () { + stdout.printf (" 2"); } +} + +class Maman.SubBar : Bar { + static int main (int argc, string[] argv) { + stdout.printf ("Static Inheritance Test: 1"); + + do_action (); + + stdout.printf (" 3\n"); - class SubBar : Bar { - public static int main (int argc, string[] argv) { - int i = do_action (42); - return (argc + i); - } + return 0; } } diff --git a/vala/tests/test-006.vala b/vala/tests/test-006.vala index 0d3aa9706..b0488d319 100644 --- a/vala/tests/test-006.vala +++ b/vala/tests/test-006.vala @@ -1,32 +1,16 @@ -namespace Maman { - class Bar { - public int do_action (int i) { - return (i + 42); +using GLib; + +class Maman.Bar { + static int main (int argc, string[] argv) { + stdout.printf ("For Test: 1"); + + int i; + for (i = 2; i < 7; i++) { + stdout.printf (" %d", i); } - } - - class SubBar : Bar { - void init () { - do_action (42); - } - - public static int main (int argc, string[] argv) { - SubBar subbar = new SubBar (); - int i; - int j; - - for (i = 0; i < argc; i++) { - subbar.do_action (i); - } - - if (i == 1) { - j = 42; - } else { - j = argc; - } - - return (i * j); - } + stdout.printf (" 7\n"); + + return 0; } } diff --git a/vala/tests/test-007.vala b/vala/tests/test-007.vala index 0187db996..74db7212b 100644 --- a/vala/tests/test-007.vala +++ b/vala/tests/test-007.vala @@ -1,19 +1,24 @@ -namespace Maman { - class Bar { - public virtual string do_action (int i) { - return 1; - } +using GLib; + +class Maman.Bar { + public virtual void do_action () { + stdout.printf (" BAD"); } +} + +class Maman.SubBar : Bar { + public override void do_action () { + stdout.printf (" 2"); + } + + static int main (int argc, string[] argv) { + stdout.printf ("Virtual Method Test: 1"); + + Bar bar = new SubBar (); + bar.do_action (); - class SubBar : Bar { - public override string do_action (int i) { - return 2; - } - - public static int main (int argc, string[] argv) { - Bar bar = new SubBar (); - - return bar.do_action (1); - } + stdout.printf (" 3\n"); + + return 0; } } diff --git a/vala/tests/test-008.vala b/vala/tests/test-008.vala index 58cd9b034..0b6ab1e6e 100644 --- a/vala/tests/test-008.vala +++ b/vala/tests/test-008.vala @@ -1,22 +1,33 @@ -namespace Maman { - class Foo { - public int foo_a = 5; - public static int foo_b = 6; +using GLib; + +class Maman.Foo { + public int public_base_field = 2; +} + +class Maman.Bar : Foo { + public int public_field = 3; + private int private_field = 4; + private static int private_static_field = 5; + + void do_action () { + stdout.printf (" %d %d %d %d", public_base_field, public_field, + private_field, private_static_field); + public_base_field = 6; + public_field = 7; + private_field = 8; + private_static_field = 9; + stdout.printf (" %d %d %d %d", public_base_field, public_field, + private_field, private_static_field); } - class Bar : Foo { - public int a = 1; - private int b = 2; - public static int c = 3; - private static int d = 4; - static int e = 5; - int f = 6; - int g; + + static int main (int argc, string[] argv) { + stdout.printf ("Field Test: 1"); - public void test () { - int aa = 6; - a = 3 + b; - c = a + 5 + aa + foo_a + foo_b; - } + var bar = new Bar (); + bar.do_action (); + + stdout.printf (" 10\n"); + + return 0; } } - diff --git a/vala/tests/test-009.vala b/vala/tests/test-009.vala index bf40c6c03..934864a7f 100644 --- a/vala/tests/test-009.vala +++ b/vala/tests/test-009.vala @@ -1,14 +1,43 @@ -namespace Maman { - class Bar { - private int _a; - public int a { - get { - return _a; - } - set { - _a = value; - } +using GLib; + +class Maman.Foo { + private int _public_base_property = 2; + public int public_base_property { + get { + return _public_base_property; + } + set { + _public_base_property = value; } } } +class Maman.Bar : Foo { + private int _public_property = 3; + public int public_property { + get { + return _public_property; + } + set { + _public_property = value; + } + } + + void do_action () { + stdout.printf (" %d %d", public_base_property, public_property); + public_base_property = 4; + public_property = 5; + stdout.printf (" %d %d", public_base_property, public_property); + } + + static int main (int argc, string[] argv) { + stdout.printf ("Property Test: 1"); + + var bar = new Bar (); + bar.do_action (); + + stdout.printf (" 6\n"); + + return 0; + } +} diff --git a/vala/vala/parser.y b/vala/vala/parser.y index 76c53993f..6c3fdcc2f 100644 --- a/vala/vala/parser.y +++ b/vala/vala/parser.y @@ -1371,6 +1371,12 @@ namespace_member_declaration vala_namespace_add_struct (current_namespace, $1); g_object_unref ($1); } + + if (current_namespace_implicit) { + /* current namespace has been declared implicitly */ + current_namespace = vala_source_file_get_global_namespace (current_source_file); + current_namespace_implicit = FALSE; + } } | interface_declaration { @@ -1379,6 +1385,12 @@ namespace_member_declaration vala_namespace_add_interface (current_namespace, $1); g_object_unref ($1); } + + if (current_namespace_implicit) { + /* current namespace has been declared implicitly */ + current_namespace = vala_source_file_get_global_namespace (current_source_file); + current_namespace_implicit = FALSE; + } } | enum_declaration { @@ -1387,6 +1399,12 @@ namespace_member_declaration vala_namespace_add_enum (current_namespace, $1); g_object_unref ($1); } + + if (current_namespace_implicit) { + /* current namespace has been declared implicitly */ + current_namespace = vala_source_file_get_global_namespace (current_source_file); + current_namespace_implicit = FALSE; + } } | flags_declaration { @@ -1395,6 +1413,12 @@ namespace_member_declaration vala_namespace_add_flags (current_namespace, $1); g_object_unref ($1); } + + if (current_namespace_implicit) { + /* current namespace has been declared implicitly */ + current_namespace = vala_source_file_get_global_namespace (current_source_file); + current_namespace_implicit = FALSE; + } } | callback_declaration { @@ -1440,7 +1464,6 @@ class_declaration name = $7; } - GList *l; ValaSourceReference *src = src_com(@6, $1); current_class = vala_class_new (name, src); @@ -2020,21 +2043,35 @@ struct_declaration ; struct_header - : comment opt_attributes opt_access_modifier STRUCT IDENTIFIER opt_type_parameter_list + : comment opt_attributes opt_access_modifier STRUCT IDENTIFIER opt_name_specifier opt_type_parameter_list { + char *name = $5; + + if ($6 != NULL) { + ValaSourceReference *ns_src = src(@5); + current_namespace = vala_namespace_new ($5, ns_src); + g_free ($5); + g_object_unref (ns_src); + current_namespace_implicit = TRUE; + + vala_source_file_add_namespace (current_source_file, current_namespace); + g_object_unref (current_namespace); + + name = $6; + } + GList *l; ValaSourceReference *src = src_com(@5, $1); - $$ = vala_struct_new ($5, src); + $$ = vala_struct_new (name, src); + g_free (name); g_object_unref (src); - for (l = $6; l != NULL; l = l->next) { + for (l = $7; l != NULL; l = l->next) { vala_struct_add_type_parameter ($$, l->data); } VALA_CODE_NODE($$)->attributes = $2; if ($3 != 0) { VALA_DATA_TYPE($$)->access = $3; } - - g_free ($5); } ; @@ -2072,12 +2109,27 @@ struct_member_declaration ; interface_declaration - : comment opt_attributes opt_access_modifier INTERFACE IDENTIFIER + : comment opt_attributes opt_access_modifier INTERFACE IDENTIFIER opt_name_specifier { + char *name = $5; + + if ($6 != NULL) { + ValaSourceReference *ns_src = src(@5); + current_namespace = vala_namespace_new ($5, ns_src); + g_free ($5); + g_object_unref (ns_src); + current_namespace_implicit = TRUE; + + vala_source_file_add_namespace (current_source_file, current_namespace); + g_object_unref (current_namespace); + + name = $6; + } + ValaSourceReference *src = src_com(@5, $1); - current_interface = vala_interface_new ($5, src); + current_interface = vala_interface_new (name, src); + g_free (name); g_object_unref (src); - g_free ($5); } interface_body { @@ -2127,11 +2179,27 @@ interface_member_declaration ; enum_declaration - : comment opt_attributes opt_access_modifier ENUM IDENTIFIER enum_body + : comment opt_attributes opt_access_modifier ENUM IDENTIFIER opt_name_specifier enum_body { + char *name = $5; + + if ($6 != NULL) { + ValaSourceReference *ns_src = src(@5); + current_namespace = vala_namespace_new ($5, ns_src); + g_free ($5); + g_object_unref (ns_src); + current_namespace_implicit = TRUE; + + vala_source_file_add_namespace (current_source_file, current_namespace); + g_object_unref (current_namespace); + + name = $6; + } + GList *l; ValaSourceReference *src = src_com(@5, $1); - $$ = vala_enum_new ($5, src); + $$ = vala_enum_new (name, src); + g_free (name); g_object_unref (src); VALA_CODE_NODE($$)->attributes = $2; @@ -2139,12 +2207,10 @@ enum_declaration if ($3 != 0) { VALA_DATA_TYPE($$)->access = $3; } - for (l = $6; l != NULL; l = l->next) { + for (l = $7; l != NULL; l = l->next) { vala_enum_add_value ($$, l->data); g_object_unref (l->data); } - - g_free ($5); } ; @@ -2183,10 +2249,26 @@ enum_member_declaration ; flags_declaration - : comment opt_attributes opt_access_modifier FLAGS IDENTIFIER flags_body + : comment opt_attributes opt_access_modifier FLAGS IDENTIFIER opt_name_specifier flags_body { + char *name = $5; + + if ($6 != NULL) { + ValaSourceReference *ns_src = src(@5); + current_namespace = vala_namespace_new ($5, ns_src); + g_free ($5); + g_object_unref (ns_src); + current_namespace_implicit = TRUE; + + vala_source_file_add_namespace (current_source_file, current_namespace); + g_object_unref (current_namespace); + + name = $6; + } + ValaSourceReference *src = src_com(@5, $1); - $$ = vala_flags_new ($5, src); + $$ = vala_flags_new (name, src); + g_free (name); g_object_unref (src); } ; diff --git a/vala/vala/valaassignment.vala b/vala/vala/valaassignment.vala index ae3e0e9e4..b09f38d57 100644 --- a/vala/vala/valaassignment.vala +++ b/vala/vala/valaassignment.vala @@ -22,24 +22,46 @@ using GLib; -namespace Vala { - public class Assignment : Expression { - public Expression! left { get; set construct; } - public AssignmentOperator operator { get; set construct; } - public Expression! right { get; set construct; } - - public static ref Assignment! new (Expression! left, AssignmentOperator op, Expression! right, SourceReference source) { - return (new Assignment (left = left, operator = op, right = right, source_reference = source)); - } - - public override void accept (CodeVisitor! visitor) { - left.accept (visitor); - right.accept (visitor); +/** + * Represents an assignment expression in the source code. + */ +public class Vala.Assignment : Expression { + /** + * Left hand side of the assignment. + */ + public Expression! left { get; set construct; } + + /** + * Assignment operator. + */ + public AssignmentOperator operator { get; set construct; } + + /** + * Right hand side of the assignment. + */ + public Expression! right { get; set construct; } + + /** + * Creates a new assignment. + * + * @param left left hand side + * @param op assignment operator + * @param right right hand side + * @param source reference to source code + */ + public static ref Assignment! new (Expression! left, AssignmentOperator op, Expression! right, SourceReference source) { + return (new Assignment (left = left, operator = op, right = right, source_reference = source)); + } + + public override void accept (CodeVisitor! visitor) { + left.accept (visitor); + right.accept (visitor); - visitor.visit_assignment (this); - } + visitor.visit_assignment (this); } +} +namespace Vala { public enum AssignmentOperator { SIMPLE, BITWISE_OR, diff --git a/vala/vala/valaattribute.vala b/vala/vala/valaattribute.vala index 648b44d10..a8d79b3b7 100644 --- a/vala/vala/valaattribute.vala +++ b/vala/vala/valaattribute.vala @@ -22,18 +22,36 @@ using GLib; -namespace Vala { - public class Attribute : CodeNode { - public string! name { get; set construct; } +/** + * Represents an attribute specified in the source code. + */ +public class Vala.Attribute : CodeNode { + /** + * The name of the attribute type. + */ + public string! name { get; set construct; } - public List args; - - public static ref Attribute! new (string! name, SourceReference source) { - return (new Attribute (name = name, source_reference = source)); - } + /** + * Contains all specified attribute arguments. + */ + public List args; + + /** + * Creates a new attribute. + * + * @param name attribute type name + * @param source reference to source code + */ + public static ref Attribute! new (string! name, SourceReference source) { + return (new Attribute (name = name, source_reference = source)); + } - public void add_argument (NamedArgument! arg) { - args.append (arg); - } + /** + * Adds an attribute argument. + * + * @param arg named argument + */ + public void add_argument (NamedArgument! arg) { + args.append (arg); } } diff --git a/vala/vala/valacodegenerator.vala b/vala/vala/valacodegenerator.vala index 05acccaa8..275fb3aa7 100644 --- a/vala/vala/valacodegenerator.vala +++ b/vala/vala/valacodegenerator.vala @@ -263,6 +263,8 @@ namespace Vala { type_fun.init_from_type (); header_type_member_declaration.append (type_fun.get_declaration ()); source_type_member_definition.append (type_fun); + + current_type_symbol = null; } private void add_class_init_function (Class! cl) { @@ -337,7 +339,22 @@ namespace Vala { } else { cspec.call = new CCodeIdentifier (name = "g_param_spec_pointer"); } - cspec.add_argument (new CCodeConstant (name = "G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB")); + + var pflags = "G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB"; + if (prop.get_accessor != null) { + pflags = "%s%s".printf (pflags, " | G_PARAM_READABLE"); + } + if (prop.set_accessor != null) { + pflags = "%s%s".printf (pflags, " | G_PARAM_WRITABLE"); + if (prop.set_accessor.construct_) { + if (prop.set_accessor.writable) { + pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT"); + } else { + pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT_ONLY"); + } + } + } + cspec.add_argument (new CCodeConstant (name = pflags)); cinst.add_argument (cspec); init_block.add_statement (new CCodeExpressionStatement (expression = cinst)); @@ -597,6 +614,8 @@ namespace Vala { type_fun.init_from_type (); header_type_member_declaration.append (type_fun.get_declaration ()); source_type_member_definition.append (type_fun); + + current_type_symbol = null; } public override void visit_begin_enum (Enum! en) { @@ -636,7 +655,11 @@ namespace Vala { if (f.symbol.parent_symbol.node is DataType) { var t = (DataType) f.symbol.parent_symbol.node; var cdecl = new CCodeDeclaration (type_name = f.type_reference.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator (name = "%s_%s".printf (t.get_lower_case_cname (null), f.get_cname ()))); + var var_decl = new CCodeVariableDeclarator (name = "%s_%s".printf (t.get_lower_case_cname (null), f.get_cname ())); + if (f.initializer != null) { + var_decl.initializer = (CCodeExpression) f.initializer.ccodenode; + } + cdecl.add_declarator (var_decl); cdecl.modifiers = CCodeModifiers.STATIC; source_type_member_declaration.append (cdecl); } @@ -644,7 +667,19 @@ namespace Vala { } } - private ref CCodeStatement create_type_check_statement (Method! m, DataType! t, bool non_null, string! var_name) { + private ref CCodeStatement create_method_type_check_statement (Method! m, DataType! t, bool non_null, string! var_name) { + return create_type_check_statement (m, m.return_type.type, t, non_null, var_name); + } + + private ref CCodeStatement create_property_type_check_statement (Property! prop, bool getter, DataType! t, bool non_null, string! var_name) { + if (getter) { + return create_type_check_statement (prop, prop.type_reference.type, t, non_null, var_name); + } else { + return create_type_check_statement (prop, null, t, non_null, var_name); + } + } + + private ref CCodeStatement create_type_check_statement (CodeNode! method_node, DataType ret_type, DataType! t, bool non_null, string! var_name) { var ccheck = new CCodeFunctionCall (); var ctype_check = new CCodeFunctionCall (call = new CCodeIdentifier (name = t.get_upper_case_cname ("IS_"))); @@ -658,21 +693,20 @@ namespace Vala { } ccheck.add_argument (cexpr); - if (m.return_type.type == null) { + if (ret_type == null) { /* void function */ ccheck.call = new CCodeIdentifier (name = "g_return_if_fail"); } else { ccheck.call = new CCodeIdentifier (name = "g_return_val_if_fail"); - var ret_type = m.return_type.type; if (ret_type.is_reference_type ()) { ccheck.add_argument (new CCodeConstant (name = "NULL")); } else if (ret_type.name == "bool") { ccheck.add_argument (new CCodeConstant (name = "FALSE")); - } else if (ret_type.name == "int") { + } else if (ret_type.name == "int" || ret_type is Enum || ret_type is Flags) { ccheck.add_argument (new CCodeConstant (name = "0")); } else { - Report.error (m.source_reference, "not supported return type for runtime type checks"); + Report.error (method_node.source_reference, "not supported return type for runtime type checks"); return null; } } @@ -753,13 +787,13 @@ namespace Vala { cinit.append (cdecl); } else if (m.instance) { - cinit.append (create_type_check_statement (m, cl, true, "self")); + cinit.append (create_method_type_check_statement (m, cl, true, "self")); } } foreach (FormalParameter param in m.parameters) { var t = param.type_reference.type; if (t != null && (t is Class || t is Interface) && !param.type_reference.is_out) { - cinit.append (create_type_check_statement (m, t, param.type_reference.non_null, param.name)); + cinit.append (create_method_type_check_statement (m, t, param.type_reference.non_null, param.name)); } } @@ -850,6 +884,8 @@ namespace Vala { if (acc.body != null) { function.block = (CCodeBlock) acc.body.ccodenode; + + function.block.prepend_statement (create_property_type_check_statement (prop, acc.readable, cl, true, "self")); } source_type_member_definition.append (function); @@ -1480,7 +1516,12 @@ namespace Vala { public override void visit_simple_name (SimpleName! expr) { var pub_inst = new CCodeIdentifier (name = "self"); - var base_type = (DataType) current_type_symbol.node; + + DataType base_type = null; + if (current_type_symbol != null) { + /* base type is available if this is a type method */ + base_type = (DataType) current_type_symbol.node; + } process_cmember (expr, pub_inst, base_type); diff --git a/vala/vala/valasemanticanalyzer.vala b/vala/vala/valasemanticanalyzer.vala index 143e01912..afa5d66d3 100644 --- a/vala/vala/valasemanticanalyzer.vala +++ b/vala/vala/valasemanticanalyzer.vala @@ -29,6 +29,7 @@ namespace Vala { Symbol root_symbol; Symbol current_symbol; SourceFile current_source_file; + TypeReference current_return_type; List current_using_directives; @@ -106,6 +107,7 @@ namespace Vala { public override void visit_begin_method (Method! m) { current_symbol = m.symbol; + current_return_type = m.return_type; if (m.return_type.type != null) { /* is null if it is void or a reference to a type parameter */ @@ -115,6 +117,7 @@ namespace Vala { public override void visit_end_method (Method! m) { current_symbol = current_symbol.parent_symbol; + current_return_type = null; if (m.is_virtual || m.is_override) { if (current_symbol.node is Class) { @@ -176,6 +179,18 @@ namespace Vala { } } + public override void visit_begin_property_accessor (PropertyAccessor! acc) { + var prop = (Property) acc.symbol.parent_symbol.node; + + if (acc.readable) { + current_return_type = prop.type_reference; + } + } + + public override void visit_end_property_accessor (PropertyAccessor! acc) { + current_return_type = null; + } + public override void visit_begin_constructor (Constructor! c) { current_symbol = c.symbol; } @@ -260,6 +275,30 @@ namespace Vala { current_symbol.add (stmt.variable_name, stmt.variable_declarator.symbol); } + public override void visit_return_statement (ReturnStatement! stmt) { + if (current_return_type == null) { + Report.error (stmt.source_reference, "Return not allowed in this context"); + return; + } + + if (stmt.return_expression == null && current_return_type.type != null) { + Report.error (stmt.source_reference, "Return with value in void function"); + return; + } + + if (stmt.return_expression != null && current_return_type.type == null) { + Report.error (stmt.source_reference, "Return without value in non-void function"); + return; + } + + if (stmt.return_expression != null && + !is_type_compatible (stmt.return_expression.static_type, current_return_type)) { + Report.error (stmt.source_reference, "Return: Cannot convert from `%s' to `%s'".printf (stmt.return_expression.static_type.to_string (), current_return_type.to_string ())); + return; + } + + } + public override void visit_boolean_literal (BooleanLiteral! expr) { expr.static_type = bool_type; } @@ -669,7 +708,7 @@ namespace Vala { if (!is_type_compatible (expr.right.static_type, expr.left.static_type) && !is_type_compatible (expr.left.static_type, expr.right.static_type)) { Report.error (expr.source_reference, "Equality operation: `%s' and `%s' are incompatible, comparison would always evaluate to false".printf (expr.right.static_type.to_string (), expr.left.static_type.to_string ())); - return false; + return; } if (expr.left.static_type.type == string_type.type diff --git a/vala/vala/valasymbolbuilder.vala b/vala/vala/valasymbolbuilder.vala index dc7d8e873..dac696517 100644 --- a/vala/vala/valasymbolbuilder.vala +++ b/vala/vala/valasymbolbuilder.vala @@ -168,14 +168,21 @@ namespace Vala { return; } - current_symbol = m.symbol; - if (m.instance) { + if (!(m.symbol.parent_symbol.node is DataType)) { + Report.error (m.source_reference, "instance methods not allowed outside of data types"); + + m.error = true; + return; + } + m.this_parameter = new FormalParameter (name = "this", type_reference = new TypeReference ()); m.this_parameter.type_reference.type = (DataType) m.symbol.parent_symbol.node; m.this_parameter.symbol = new Symbol (node = m.this_parameter); current_symbol.add (m.this_parameter.name, m.this_parameter.symbol); } + + current_symbol = m.symbol; } public override void visit_end_method (Method! m) {