From: Jürg Billeter Date: Mon, 22 May 2006 20:04:08 +0000 (+0000) Subject: support abstract methods and static fields support parameter symbol X-Git-Tag: VALA_0_0_1~46 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5ec772c29f45e11614aa96a5cdc0ec0746c4fe20;p=thirdparty%2Fvala.git support abstract methods and static fields support parameter symbol 2006-05-22 Jürg Billeter * vala/parser.y: support abstract methods and static fields * vala/valasourcefile.vala: support parameter symbol dependencies * vala/valasymbolbuilder.vala: insert default body for get accessors * vala/valasemanticanalyzer.vala: add property type dependency * vala/valacodegenerator.vala: add constants, private static fields, main function, property accessors, this, casting for member access * vala/valablock.vala: add add_statement method * vala/valafield.vala: add instance field * vala/valamethod.vala: add is_abstract field * valac/generator.c: mark generated properties as writable svn path=/trunk/; revision=33 --- diff --git a/vala/ChangeLog b/vala/ChangeLog index 17234dcfb..8cce560e2 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,3 +1,16 @@ +2006-05-22 Jürg Billeter + + * vala/parser.y: support abstract methods and static fields + * vala/valasourcefile.vala: support parameter symbol dependencies + * vala/valasymbolbuilder.vala: insert default body for get accessors + * vala/valasemanticanalyzer.vala: add property type dependency + * vala/valacodegenerator.vala: add constants, private static fields, + main function, property accessors, this, casting for member access + * vala/valablock.vala: add add_statement method + * vala/valafield.vala: add instance field + * vala/valamethod.vala: add is_abstract field + * valac/generator.c: mark generated properties as writable + 2006-05-22 Jürg Billeter * vala/valacodegenerator.c: add class instance private struct, type diff --git a/vala/vala/parser.y b/vala/vala/parser.y index 33ffbd07d..bdc3c2d46 100644 --- a/vala/vala/parser.y +++ b/vala/vala/parser.y @@ -1099,6 +1099,9 @@ field_declaration if ($3 != 0) { $$->access = $3; } + if (($4 & VALA_MODIFIER_STATIC) == VALA_MODIFIER_STATIC) { + $$->instance = FALSE; + } } ; @@ -1174,6 +1177,9 @@ method_header if (($4 & VALA_MODIFIER_STATIC) == VALA_MODIFIER_STATIC) { $$->instance = FALSE; } + if (($4 & VALA_MODIFIER_ABSTRACT) == VALA_MODIFIER_ABSTRACT) { + $$->is_abstract = TRUE; + } VALA_CODE_NODE($$)->attributes = $2; for (l = $9; l != NULL; l = l->next) { diff --git a/vala/vala/valablock.vala b/vala/vala/valablock.vala index 3866688cb..f0ed1ea1f 100644 --- a/vala/vala/valablock.vala +++ b/vala/vala/valablock.vala @@ -30,6 +30,10 @@ namespace Vala { return (new Block (statement_list = statement_list, source_reference = source)); } + public void add_statement (Statement stmt) { + _statement_list.append (stmt); + } + public override void accept (CodeVisitor visitor) { visitor.visit_begin_block (this); diff --git a/vala/vala/valacodegenerator.vala b/vala/vala/valacodegenerator.vala index 9bf93bf66..4cd3ac35b 100644 --- a/vala/vala/valacodegenerator.vala +++ b/vala/vala/valacodegenerator.vala @@ -24,6 +24,8 @@ using GLib; namespace Vala { public class CodeGenerator : CodeVisitor { + Symbol current_symbol; + CCodeFragment header_begin; CCodeFragment header_type_declaration; CCodeFragment header_type_definition; @@ -65,9 +67,11 @@ namespace Vala { source_type_member_declaration = new CCodeFragment (); source_type_member_definition = new CCodeFragment (); + header_begin.append (new CCodeIncludeDirective (filename = "glib.h")); source_include_directives.append (new CCodeIncludeDirective (filename = source_file.get_cheader_filename ())); List used_includes = null; + used_includes.append ("glib.h"); used_includes.append (source_file.get_cheader_filename ()); foreach (string filename1 in source_file.header_external_includes) { @@ -178,8 +182,10 @@ namespace Vala { source_type_member_declaration = null; source_type_member_definition = null; } - + public override void visit_begin_class (Class cl) { + current_symbol = cl.symbol; + instance_struct = new CCodeStruct (name = "_%s".printf (cl.get_cname ())); class_struct = new CCodeStruct (name = "_%sClass".printf (cl.get_cname ())); instance_priv_struct = new CCodeStruct (name = "_%sPrivate".printf (cl.get_cname ())); @@ -263,6 +269,9 @@ namespace Vala { class_init.add_parameter (new CCodeFormalParameter (type_name = "%sClass *".printf (cl.get_cname ()), name = "klass")); class_init.modifiers = CCodeModifiers.STATIC; + var init_block = new CCodeBlock (); + class_init.block = init_block; + source_type_member_definition.append (class_init); } @@ -271,6 +280,9 @@ namespace Vala { instance_init.add_parameter (new CCodeFormalParameter (type_name = "%s *".printf (cl.get_cname ()), name = "self")); instance_init.modifiers = CCodeModifiers.STATIC; + var init_block = new CCodeBlock (); + instance_init.block = init_block; + source_type_member_definition.append (instance_init); } @@ -295,16 +307,40 @@ namespace Vala { public override void visit_enum_value (EnumValue ev) { cenum.add_value (ev.get_cname (), null); } + + public override void visit_constant (Constant c) { + if (c.symbol.parent_symbol.node is Struct) { + var t = (Struct) c.symbol.parent_symbol.node; + var cdecl = new CCodeDeclarationStatement (type_name = "const %s".printf (c.type_reference.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator (name = "%s_%s".printf (t.get_lower_case_cname (null), c.name))); + cdecl.modifiers = CCodeModifiers.STATIC; + source_type_member_declaration.append (cdecl); + } + } public override void visit_field (Field f) { if (f.access == MemberAccessibility.PUBLIC) { instance_struct.add_field (f.type_reference.get_cname (), f.name); } else if (f.access == MemberAccessibility.PRIVATE) { - instance_priv_struct.add_field (f.type_reference.get_cname (), f.name); + if (f.instance) { + instance_priv_struct.add_field (f.type_reference.get_cname (), f.name); + } else { + if (f.symbol.parent_symbol.node is Struct) { + var t = (Struct) f.symbol.parent_symbol.node; + var cdecl = new CCodeDeclarationStatement (type_name = f.type_reference.get_cname ()); + cdecl.add_declarator (new CCodeVariableDeclarator (name = "%s_%s".printf (t.get_lower_case_cname (null), f.name))); + cdecl.modifiers = CCodeModifiers.STATIC; + source_type_member_declaration.append (cdecl); + } + } } } public override void visit_end_method (Method m) { + if (m.name.collate ("init") == 0) { + return; + } + function = new CCodeFunction (name = m.get_cname (), return_type = m.return_type.get_cname ()); if (m.instance) { @@ -328,18 +364,69 @@ namespace Vala { if (m.body != null) { function.block = m.body.ccodenode; + } else if (m.is_abstract) { + function.block = new CCodeBlock (); } if (m.source_reference.comment != null) { source_type_member_definition.append (new CCodeComment (text = m.source_reference.comment)); } source_type_member_definition.append (function); + + if (m.name.collate ("main") == 0) { + var cmain = new CCodeFunction (name = "main", return_type = "int"); + cmain.add_parameter (new CCodeFormalParameter (type_name = "int", name = "argc")); + cmain.add_parameter (new CCodeFormalParameter (type_name = "char **", name = "argv")); + var main_block = new CCodeBlock (); + main_block.add_statement (new CCodeExpressionStatement (expression = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_type_init")))); + var main_call = new CCodeFunctionCall (call = new CCodeIdentifier (name = function.name)); + main_call.add_argument (new CCodeIdentifier (name = "argc")); + main_call.add_argument (new CCodeIdentifier (name = "argv")); + main_block.add_statement (new CCodeReturnStatement (return_expression = main_call)); + cmain.block = main_block; + source_type_member_definition.append (cmain); + } } public override void visit_formal_parameter (FormalParameter p) { p.ccodenode = new CCodeFormalParameter (type_name = p.type_reference.get_cname (), name = p.name); } + public override void visit_begin_property (Property prop) { + } + + public override void visit_end_property (Property prop) { + } + + public override void visit_begin_property_accessor (PropertyAccessor acc) { + } + + public override void visit_end_property_accessor (PropertyAccessor acc) { + var prop = (Property) acc.symbol.parent_symbol.node; + var cl = (Class) prop.symbol.parent_symbol.node; + + if (acc.readable) { + function = new CCodeFunction (name = "%s_get_%s".printf (cl.get_lower_case_cname (null), prop.name), return_type = prop.type_reference.get_cname ()); + } else { + function = new CCodeFunction (name = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name), return_type = "void"); + } + var this_type = new TypeReference (); + this_type.type = cl; + var cparam = new CCodeFormalParameter (type_name = this_type.get_cname (), name = "self"); + function.add_parameter (cparam); + if (acc.writable || acc.construct_) { + function.add_parameter (new CCodeFormalParameter (type_name = prop.type_reference.get_cname (), name = "value")); + } + + header_type_member_declaration.append (function.copy ()); + + if (acc.body != null) { + function.block = acc.body.ccodenode; + } + + source_type_member_definition.append (function); + } + public override void visit_end_block (Block b) { var cblock = new CCodeBlock (); @@ -452,19 +539,51 @@ namespace Vala { } public override void visit_simple_name (SimpleName expr) { - if (expr.symbol_reference.node is Method) { + if (expr.name.collate ("this") == 0) { + expr.ccodenode = new CCodeIdentifier (name = "self"); + } else if (expr.symbol_reference.node is Method) { var m = (Method) expr.symbol_reference.node; expr.ccodenode = new CCodeIdentifier (name = m.get_cname ()); } else if (expr.symbol_reference.node is Field) { var f = (Field) expr.symbol_reference.node; - var pub_inst = new CCodeIdentifier (name = "self"); - ref CCodeExpression inst; - if (f.access == MemberAccessibility.PRIVATE) { - inst = new CCodeMemberAccess (inner = pub_inst, member_name = "priv", is_pointer = true); + if (f.instance) { + var pub_inst = new CCodeIdentifier (name = "self"); + ref CCodeExpression typed_inst; + if (f.symbol.parent_symbol != current_symbol) { + typed_inst = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((Type_) f.symbol.parent_symbol.node).get_upper_case_cname (null))); + ((CCodeFunctionCall) typed_inst).add_argument (pub_inst); + } else { + typed_inst = pub_inst; + } + ref CCodeExpression inst; + if (f.access == MemberAccessibility.PRIVATE) { + inst = new CCodeMemberAccess (inner = typed_inst, member_name = "priv", is_pointer = true); + } else { + inst = typed_inst; + } + expr.ccodenode = new CCodeMemberAccess (inner = inst, member_name = f.name, is_pointer = true); } else { - inst = pub_inst; + if (f.symbol.parent_symbol.node is Struct) { + var t = (Struct) f.symbol.parent_symbol.node; + expr.ccodenode = new CCodeIdentifier (name = "%s_%s".printf (t.get_lower_case_cname (null), expr.name)); + } else { + expr.ccodenode = new CCodeIdentifier (name = expr.name); + } } - expr.ccodenode = new CCodeMemberAccess (inner = inst, member_name = f.name, is_pointer = true); + } else if (expr.symbol_reference.node is Constant) { + var c = (Constant) expr.symbol_reference.node; + if (c.symbol.parent_symbol.node is Struct) { + var t = (Struct) c.symbol.parent_symbol.node; + expr.ccodenode = new CCodeIdentifier (name = "%s_%s".printf (t.get_lower_case_cname (null), expr.name)); + } else { + expr.ccodenode = new CCodeIdentifier (name = expr.name); + } + } else if (expr.symbol_reference.node is Property) { + var prop = (Property) expr.symbol_reference.node; + var cl = (Class) prop.symbol.parent_symbol.node; + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_get_%s".printf (cl.get_lower_case_cname (null), prop.name))); + ccall.add_argument (new CCodeIdentifier (name = "self")); + expr.ccodenode = ccall; } else { expr.ccodenode = new CCodeIdentifier (name = expr.name); } @@ -478,8 +597,34 @@ namespace Vala { if (expr.symbol_reference.node is Method) { var m = (Method) expr.symbol_reference.node; expr.ccodenode = new CCodeIdentifier (name = m.get_cname ()); + } else if (expr.symbol_reference.node is Field) { + var f = (Field) expr.symbol_reference.node; + var pub_inst = expr.inner.ccodenode; + ref CCodeExpression typed_inst; + if (f.symbol.parent_symbol.node != expr.inner.static_type.type) { + typed_inst = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((Type_) f.symbol.parent_symbol.node).get_upper_case_cname (null))); + ((CCodeFunctionCall) typed_inst).add_argument (pub_inst); + } else { + typed_inst = pub_inst; + } + ref CCodeExpression inst; + if (f.access == MemberAccessibility.PRIVATE) { + inst = new CCodeMemberAccess (inner = typed_inst, member_name = "priv", is_pointer = true); + } else { + inst = typed_inst; + } + expr.ccodenode = new CCodeMemberAccess (inner = inst, member_name = f.name, is_pointer = true); + } else if (expr.symbol_reference.node is Property) { + var prop = (Property) expr.symbol_reference.node; + var cl = (Class) prop.symbol.parent_symbol.node; + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_get_%s".printf (cl.get_lower_case_cname (null), prop.name))); + ccall.add_argument (expr.inner.ccodenode); + expr.ccodenode = ccall; + } else if (expr.symbol_reference.node is EnumValue) { + var ev = (EnumValue) expr.symbol_reference.node; + expr.ccodenode = new CCodeConstant (name = ev.get_cname ()); } else { - expr.ccodenode = new CCodeIdentifier (name = expr.member_name); + expr.ccodenode = new CCodeMemberAccess (inner = (CCodeExpression) expr.inner.ccodenode, member_name = expr.member_name, is_pointer = true); } } @@ -547,7 +692,23 @@ namespace Vala { } public override void visit_assignment (Assignment a) { - a.ccodenode = new CCodeAssignment (left = (CCodeExpression) a.left.ccodenode, right = (CCodeExpression) a.right.ccodenode); + if (a.left.symbol_reference.node is Property) { + var prop = (Property) a.left.symbol_reference.node; + var cl = (Class) prop.symbol.parent_symbol.node; + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name))); + if (a.left is MemberAccess) { + var expr = (MemberAccess) a.left; + ccall.add_argument (expr.inner.ccodenode); + } else if (a.left is SimpleName) { + ccall.add_argument (new CCodeIdentifier (name = "self")); + } else { + stderr.printf ("error: unexpected lvalue in assignment\n"); + } + ccall.add_argument ((CCodeExpression) a.right.ccodenode); + a.ccodenode = ccall; + } else { + a.ccodenode = new CCodeAssignment (left = (CCodeExpression) a.left.ccodenode, right = (CCodeExpression) a.right.ccodenode); + } } } } diff --git a/vala/vala/valafield.vala b/vala/vala/valafield.vala index 9b544d552..cd37a2247 100644 --- a/vala/vala/valafield.vala +++ b/vala/vala/valafield.vala @@ -28,6 +28,7 @@ namespace Vala { public TypeReference type_reference { get; construct; } public Expression initializer { get; construct; } public MemberAccessibility access; + public bool instance = true; public SourceReference source_reference { get; construct; } public static ref Field new (string name, TypeReference type, Expression init, SourceReference source) { diff --git a/vala/vala/valamethod.vala b/vala/vala/valamethod.vala index 44b7e5eeb..9647fc41d 100644 --- a/vala/vala/valamethod.vala +++ b/vala/vala/valamethod.vala @@ -38,6 +38,7 @@ namespace Vala { } public MemberAccessibility access; public bool instance = true; + public bool is_abstract; List parameters; public string cname; diff --git a/vala/vala/valasemanticanalyzer.vala b/vala/vala/valasemanticanalyzer.vala index 2e7f045a7..83935cf88 100644 --- a/vala/vala/valasemanticanalyzer.vala +++ b/vala/vala/valasemanticanalyzer.vala @@ -108,6 +108,13 @@ namespace Vala { } } + public override void visit_end_property (Property prop) { + if (prop.type_reference.type != null) { + /* is null if it references a type parameter */ + current_source_file.add_symbol_dependency (prop.type_reference.type.symbol, SourceFileDependencyType.HEADER_SHALLOW); + } + } + public override void visit_named_argument (NamedArgument n) { } diff --git a/vala/vala/valasourcefile.vala b/vala/vala/valasourcefile.vala index 7b19fc03d..c783ad6e7 100644 --- a/vala/vala/valasourcefile.vala +++ b/vala/vala/valasourcefile.vala @@ -33,6 +33,8 @@ namespace Vala { Namespace global_namespace; List namespaces; + TypeReference dummy_type_reference; // dummy type reference due to broken dependency handling + private void init () { global_namespace = new Namespace (source_reference = new SourceReference (file = this)); } @@ -114,6 +116,13 @@ namespace Vala { } else { return; } + } else if (sym.node is FormalParameter) { + var fp = (FormalParameter) sym.node; + t = fp.type_reference.type; + if (t == null) { + /* generic type parameter */ + return; + } } else { return; } diff --git a/vala/vala/valasymbolbuilder.vala b/vala/vala/valasymbolbuilder.vala index e29bf2196..e425a7866 100644 --- a/vala/vala/valasymbolbuilder.vala +++ b/vala/vala/valasymbolbuilder.vala @@ -177,6 +177,19 @@ namespace Vala { if (acc.writable || acc.construct_) { current_symbol.add ("value", new Symbol (node = ((Property) current_symbol.parent_symbol.node).type_reference)); } + + if (acc.body == null) { + /* no accessor body specified, insert default body */ + + var prop = (Property) acc.symbol.parent_symbol.node; + + var block = new Block (); + if (acc.readable) { + block.add_statement (new ReturnStatement (return_expression = new SimpleName (name = prop.name))); + } else { + } + acc.body = block; + } } public override void visit_end_property_accessor (PropertyAccessor acc) { diff --git a/vala/valac/generator.c b/vala/valac/generator.c index dc1eace91..000c2b6b6 100644 --- a/vala/valac/generator.c +++ b/vala/valac/generator.c @@ -1403,19 +1403,19 @@ vala_code_generator_process_methods2 (ValaCodeGenerator *generator, ValaClass *c /* paramspec */ if (strcmp (prop->return_type->type_name, "string") == 0) { fprintf (generator->c_file, "g_param_spec_string"); - fprintf (generator->c_file, " (\"%s\", \"foo\", \"bar\", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)", prop->name); + fprintf (generator->c_file, " (\"%s\", \"foo\", \"bar\", NULL, G_PARAM_CONSTRUCT | G_PARAM_READWRITE)", prop->name); } else if (prop->return_type->symbol->type == VALA_SYMBOL_TYPE_ENUM || strcmp (prop->return_type->type_name, "int") == 0) { fprintf (generator->c_file, "g_param_spec_int"); - fprintf (generator->c_file, " (\"%s\", \"foo\", \"bar\", G_MININT, G_MAXINT, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)", prop->name); + fprintf (generator->c_file, " (\"%s\", \"foo\", \"bar\", G_MININT, G_MAXINT, 0, G_PARAM_CONSTRUCT | G_PARAM_READWRITE)", prop->name); } else if (strcmp (prop->return_type->type_name, "bool") == 0) { fprintf (generator->c_file, "g_param_spec_boolean"); - fprintf (generator->c_file, " (\"%s\", \"foo\", \"bar\", FALSE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)", prop->name); + fprintf (generator->c_file, " (\"%s\", \"foo\", \"bar\", FALSE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE)", prop->name); } else if (prop->return_type->symbol->type == VALA_SYMBOL_TYPE_CLASS) { fprintf (generator->c_file, "g_param_spec_object"); - fprintf (generator->c_file, " (\"%s\", \"foo\", \"bar\", %sTYPE_%s, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)", prop->name, prop->return_type->symbol->class->namespace->upper_case_cname, prop->return_type->symbol->class->upper_case_cname); + fprintf (generator->c_file, " (\"%s\", \"foo\", \"bar\", %sTYPE_%s, G_PARAM_CONSTRUCT | G_PARAM_READWRITE)", prop->name, prop->return_type->symbol->class->namespace->upper_case_cname, prop->return_type->symbol->class->upper_case_cname); } else { fprintf (generator->c_file, "g_param_spec_pointer"); - fprintf (generator->c_file, " (\"%s\", \"foo\", \"bar\", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)", prop->name); + fprintf (generator->c_file, " (\"%s\", \"foo\", \"bar\", G_PARAM_CONSTRUCT | G_PARAM_READWRITE)", prop->name); } fprintf (generator->c_file, ");\n");