+2006-07-03 Jürg Billeter <j@bitron.ch>
+
+ * 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 <j@bitron.ch>
* vala/valacodenode.vala, vala/valadatatype.vala,
+using GLib;
+
namespace Maman {
+ static int main (int argc, string[] argv) {
+ stdout.printf ("Namespace Test\n");
+ return 0;
+ }
}
-
+using GLib;
+
namespace Maman {
class Bar {
+ static int main (int argc, string[] argv) {
+ stdout.printf ("Class in Namespace Test\n");
+ return 0;
+ }
}
}
-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;
}
}
-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;
}
}
-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;
}
}
-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;
}
}
-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;
}
}
-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;
}
}
-
-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;
+ }
+}
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
{
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
{
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
{
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
{
name = $7;
}
-
GList *l;
ValaSourceReference *src = src_com(@6, $1);
current_class = vala_class_new (name, src);
;
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);
}
;
;
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
{
;
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;
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);
}
;
;
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);
}
;
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,
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<NamedArgument> 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<NamedArgument> 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);
}
}
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) {
} 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));
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) {
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);
}
}
}
- 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_")));
}
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;
}
}
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));
}
}
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);
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);
Symbol root_symbol;
Symbol current_symbol;
SourceFile current_source_file;
+ TypeReference current_return_type;
List<weak NamespaceReference> current_using_directives;
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 */
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) {
}
}
+ 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;
}
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;
}
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
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) {