From 53b8098fc464b863672627b6ef50cc44525cf6e9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=BCrg=20Billeter?= Date: Fri, 7 Jul 2006 07:56:56 +0000 Subject: [PATCH] use continue statements to decrease indentation levels add interface MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 2006-07-07 Jürg Billeter * vala/valacodecontext.vala: use continue statements to decrease indentation levels * vala/valasymbolbuilder.vala, vala/valasymbolresolver.vala, vala/valasemanticanalyzer.vala, vala/valamemorymanager.vala, vala/valacodegenerator.vala, vala/valaconditionalexpression.vala, vala/valaconstant.vala: add interface documentation, use implicit namespace specification * vala/valasemanticanalyzer.vala: check that if, while, for, and conditional expression conditions are boolean * vala/valaclass.vala: remove dummy accessor, breaks build with old vala compiler * compiler/valacompiler.vala: use implicit namespace specification * tests/test-016.vala: test conditional expressions * tests/Makefile.am: update svn path=/trunk/; revision=68 --- vala/ChangeLog | 17 + vala/compiler/valacompiler.vala | 326 ++- vala/tests/Makefile.am | 1 + vala/tests/test-016.vala | 13 + vala/vala/valaclass.vala | 3 - vala/vala/valacodecontext.vala | 135 +- vala/vala/valacodegenerator.vala | 3393 +++++++++++++++--------------- vala/vala/valaconditionalexpression.vala | 52 +- vala/vala/valaconstant.vala | 82 +- vala/vala/valamemorymanager.vala | 221 +- vala/vala/valasemanticanalyzer.vala | 1666 ++++++++------- vala/vala/valasymbolbuilder.vala | 458 ++-- vala/vala/valasymbolresolver.vala | 208 +- 13 files changed, 3366 insertions(+), 3209 deletions(-) create mode 100644 vala/tests/test-016.vala diff --git a/vala/ChangeLog b/vala/ChangeLog index 330a0a8..de43c01 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,5 +1,22 @@ 2006-07-07 Jürg Billeter + * vala/valacodecontext.vala: use continue statements to decrease + indentation levels + * vala/valasymbolbuilder.vala, vala/valasymbolresolver.vala, + vala/valasemanticanalyzer.vala, vala/valamemorymanager.vala, + vala/valacodegenerator.vala, vala/valaconditionalexpression.vala, + vala/valaconstant.vala: add interface documentation, use implicit + namespace specification + * vala/valasemanticanalyzer.vala: check that if, while, for, and + conditional expression conditions are boolean + * vala/valaclass.vala: remove dummy accessor, breaks build with old + vala compiler + * compiler/valacompiler.vala: use implicit namespace specification + * tests/test-016.vala: test conditional expressions + * tests/Makefile.am: update + +2006-07-07 Jürg Billeter + * vala/valacodecontext.vala: add interface documentation, use implicit namespace specification * vala/valasymbolbuilder.vala, vala/valasymbolresolver.vala, diff --git a/vala/compiler/valacompiler.vala b/vala/compiler/valacompiler.vala index c694439..d9979df 100644 --- a/vala/compiler/valacompiler.vala +++ b/vala/compiler/valacompiler.vala @@ -22,192 +22,190 @@ using GLib; -namespace Vala { - class Compiler { - static string directory; - static bool version; - static string[] sources; - static string[] vapi_directories; - static string library; - static string[] packages; - static bool disable_memory_management; - CodeContext context; +class Vala.Compiler { + static string directory; + static bool version; + static string[] sources; + static string[] vapi_directories; + static string library; + static string[] packages; + static bool disable_memory_management; + CodeContext context; + + const OptionEntry[] options = { + { "vapidir", 0, 0, OptionArg.FILENAME_ARRAY, out vapi_directories, "Look for package bindings in DIRECTORY", "DIRECTORY..." }, + { "pkg", 0, 0, OptionArg.STRING_ARRAY, out packages, "Include binding for PACKAGE", "PACKAGE..." }, + { "library", 0, 0, OptionArg.STRING, out library, "Library name", "NAME" }, + { "directory", 'd', 0, OptionArg.FILENAME, out directory, "Output directory", "DIRECTORY" }, + { "version", 0, 0, OptionArg.NONE, ref version, "Display version number", null }, + { "disable-memory-management", 0, 0, OptionArg.NONE, ref disable_memory_management, "Disable memory management", null }, + { "", 0, 0, OptionArg.FILENAME_ARRAY, out sources, null, "FILE..." }, + { null } + }; - const OptionEntry[] options = { - { "vapidir", 0, 0, OptionArg.FILENAME_ARRAY, out vapi_directories, "Look for package bindings in DIRECTORY", "DIRECTORY..." }, - { "pkg", 0, 0, OptionArg.STRING_ARRAY, out packages, "Include binding for PACKAGE", "PACKAGE..." }, - { "library", 0, 0, OptionArg.STRING, out library, "Library name", "NAME" }, - { "directory", 'd', 0, OptionArg.FILENAME, out directory, "Output directory", "DIRECTORY" }, - { "version", 0, 0, OptionArg.NONE, ref version, "Display version number", null }, - { "disable-memory-management", 0, 0, OptionArg.NONE, ref disable_memory_management, "Disable memory management", null }, - { "", 0, 0, OptionArg.FILENAME_ARRAY, out sources, null, "FILE..." }, - { null } - }; - - private int quit () { - if (Report.get_errors () == 0) { - stdout.printf ("Compilation succeeded - %d warning(s)\n", Report.get_warnings ()); - return 0; - } else { - stdout.printf ("Compilation failed: %d error(s), %d warning(s)\n", Report.get_errors (), Report.get_warnings ()); - return 1; + private int quit () { + if (Report.get_errors () == 0) { + stdout.printf ("Compilation succeeded - %d warning(s)\n", Report.get_warnings ()); + return 0; + } else { + stdout.printf ("Compilation failed: %d error(s), %d warning(s)\n", Report.get_errors (), Report.get_warnings ()); + return 1; + } + } + + private ref string get_package_path (string! pkg) { + var basename = "%s.vala".printf (pkg); + + if (vapi_directories != null) { + foreach (string vapidir in vapi_directories) { + var filename = Path.build_filename (vapidir, basename, null); + if (File.test (filename, FileTest.EXISTS)) { + return filename; + } } + vapi_directories = null; } - private ref string get_package_path (string! pkg) { - var basename = "%s.vala".printf (pkg); + var filename = Path.build_filename ("/usr/share/vala/vapi", basename, null); + if (File.test (filename, FileTest.EXISTS)) { + return filename; + } - if (vapi_directories != null) { - foreach (string vapidir in vapi_directories) { - var filename = Path.build_filename (vapidir, basename, null); - if (File.test (filename, FileTest.EXISTS)) { - return filename; - } - } - vapi_directories = null; - } - - var filename = Path.build_filename ("/usr/share/vala/vapi", basename, null); - if (File.test (filename, FileTest.EXISTS)) { - return filename; - } - - return null; + return null; + } + + private bool add_package (string! pkg) { + var package_path = get_package_path (pkg); + + if (package_path == null) { + return false; } - private bool add_package (string! pkg) { - var package_path = get_package_path (pkg); - - if (package_path == null) { - return false; - } - - context.add_source_file (new SourceFile (filename = package_path, pkg = true)); - - return true; + context.add_source_file (new SourceFile (filename = package_path, pkg = true)); + + return true; + } + + private int run () { + context = new CodeContext (); + + /* default package */ + if (!add_package ("glib-2.0")) { + Report.error (null, "glib-2.0 not found in specified Vala API directories"); } - private int run () { - context = new CodeContext (); - - /* default package */ - if (!add_package ("glib-2.0")) { - Report.error (null, "glib-2.0 not found in specified Vala API directories"); - } - - if (packages != null) { - foreach (string package in packages) { - if (!add_package (package)) { - Report.error (null, "%s not found in specified Vala API directories".printf (package)); - } - } - packages = null; - } - - if (Report.get_errors () > 0) { - return quit (); - } - - foreach (string source in sources) { - if (File.test (source, FileTest.EXISTS)) { - context.add_source_file (new SourceFile (filename = source)); - } else { - Report.error (null, "%s not found".printf (source)); + if (packages != null) { + foreach (string package in packages) { + if (!add_package (package)) { + Report.error (null, "%s not found in specified Vala API directories".printf (package)); } } - sources = null; - - if (Report.get_errors () > 0) { - return quit (); - } - - var parser = new Parser (); - parser.parse (context); - - if (Report.get_errors () > 0) { - return quit (); - } - - var builder = new SymbolBuilder (); - builder.build (context); - - if (Report.get_errors () > 0) { - return quit (); - } - - var attributeprocessor = new AttributeProcessor (); - attributeprocessor.process (context); - - if (Report.get_errors () > 0) { - return quit (); - } - - var resolver = new SymbolResolver (); - resolver.resolve (context); - - if (Report.get_errors () > 0) { - return quit (); - } - - var analyzer = new SemanticAnalyzer (memory_management = !disable_memory_management); - analyzer.analyze (context); - - if (Report.get_errors () > 0) { - return quit (); - } - - if (!disable_memory_management) { - var memory_manager = new MemoryManager (); - memory_manager.analyze (context); - - if (Report.get_errors () > 0) { - return quit (); - } + packages = null; + } + + if (Report.get_errors () > 0) { + return quit (); + } + + foreach (string source in sources) { + if (File.test (source, FileTest.EXISTS)) { + context.add_source_file (new SourceFile (filename = source)); + } else { + Report.error (null, "%s not found".printf (source)); } - - var code_generator = new CodeGenerator (memory_management = !disable_memory_management); - code_generator.emit (context); + } + sources = null; + + if (Report.get_errors () > 0) { + return quit (); + } + + var parser = new Parser (); + parser.parse (context); + + if (Report.get_errors () > 0) { + return quit (); + } + + var builder = new SymbolBuilder (); + builder.build (context); + + if (Report.get_errors () > 0) { + return quit (); + } + + var attributeprocessor = new AttributeProcessor (); + attributeprocessor.process (context); + + if (Report.get_errors () > 0) { + return quit (); + } + + var resolver = new SymbolResolver (); + resolver.resolve (context); + + if (Report.get_errors () > 0) { + return quit (); + } + + var analyzer = new SemanticAnalyzer (memory_management = !disable_memory_management); + analyzer.analyze (context); + + if (Report.get_errors () > 0) { + return quit (); + } + + if (!disable_memory_management) { + var memory_manager = new MemoryManager (); + memory_manager.analyze (context); if (Report.get_errors () > 0) { return quit (); } - - if (library != null) { - var interface_writer = new InterfaceWriter (); - interface_writer.write_file (context, "%s.vala".printf (library)); - - library = null; - } - - return quit (); } - static int main (int argc, string[] argv) { - Error err = null; + var code_generator = new CodeGenerator (memory_management = !disable_memory_management); + code_generator.emit (context); - var opt_context = OptionContext.@new ("- Vala Compiler"); - opt_context.set_help_enabled (true); - opt_context.add_main_entries (options, null); - opt_context.parse (ref argc, out argv, out err); - - if (err != null) { - return 1; - } + if (Report.get_errors () > 0) { + return quit (); + } + + if (library != null) { + var interface_writer = new InterfaceWriter (); + interface_writer.write_file (context, "%s.vala".printf (library)); - if (sources == null) { - stderr.printf ("No source file specified.\n"); + library = null; + } + + return quit (); + } + + static int main (int argc, string[] argv) { + Error err = null; + + var opt_context = OptionContext.@new ("- Vala Compiler"); + opt_context.set_help_enabled (true); + opt_context.add_main_entries (options, null); + opt_context.parse (ref argc, out argv, out err); + + if (err != null) { + return 1; + } + + if (sources == null) { + stderr.printf ("No source file specified.\n"); + return 1; + } + + foreach (string source in sources) { + if (!source.has_suffix (".vala")) { + stderr.printf ("Only .vala source files supported.\n"); return 1; } - - foreach (string source in sources) { - if (!source.has_suffix (".vala")) { - stderr.printf ("Only .vala source files supported.\n"); - return 1; - } - } - - var compiler = new Compiler (); - return compiler.run (); } + + var compiler = new Compiler (); + return compiler.run (); } } diff --git a/vala/tests/Makefile.am b/vala/tests/Makefile.am index 2297438..3c56280 100644 --- a/vala/tests/Makefile.am +++ b/vala/tests/Makefile.am @@ -16,4 +16,5 @@ EXTRA_DIST = \ test-013.vala \ test-014.vala \ test-015.vala \ + test-016.vala \ $(NULL) diff --git a/vala/tests/test-016.vala b/vala/tests/test-016.vala new file mode 100644 index 0000000..13dd2f0 --- /dev/null +++ b/vala/tests/test-016.vala @@ -0,0 +1,13 @@ +using GLib; + +class Maman.Bar { + static int main (int argc, string[] argv) { + stdout.printf ("Conditional Expression Test: 1"); + + stdout.printf (" %d", false ? -1 : 2); + + stdout.printf (" 3\n"); + + return 0; + } +} diff --git a/vala/vala/valaclass.vala b/vala/vala/valaclass.vala index 0fe8c1f..476710f 100644 --- a/vala/vala/valaclass.vala +++ b/vala/vala/valaclass.vala @@ -44,9 +44,6 @@ public class Vala.Class : DataType { get { return _has_private_fields; } - set { - /* FIXME: dummy accessor due to vala compiler bug */ - } } private string cname; diff --git a/vala/vala/valacodecontext.vala b/vala/vala/valacodecontext.vala index 9c9405d..f38726a 100644 --- a/vala/vala/valacodecontext.vala +++ b/vala/vala/valacodecontext.vala @@ -76,10 +76,12 @@ public class Vala.CodeContext { /* find cycles in dependencies between source files */ foreach (SourceFile file in source_files) { /* we're only interested in internal source files */ - if (!file.pkg) { - if (file.mark == 0) { - visit (file, null); - } + if (file.pkg) { + continue; + } + + if (file.mark == 0) { + visit (file, null); } } @@ -96,18 +98,20 @@ public class Vala.CodeContext { */ foreach (SourceFile file2 in source_files) { /* we're only interested in internal source files */ - if (!file2.pkg) { - foreach (SourceFile dep in file2.header_internal_dependencies) { - if (file2.cycle != null && dep.cycle == file2.cycle) { - /* in the same cycle */ - if (!file2.is_cycle_head) { - /* include header of cycle head */ - file2.header_internal_includes.append (file2.cycle.head.get_cheader_filename ()); - } - } else { - /* we can just include the headers if they are not in a cycle or not in the same cycle as the current file */ - file2.header_internal_includes.append (dep.get_cheader_filename ()); + if (file2.pkg) { + continue; + } + + foreach (SourceFile dep in file2.header_internal_dependencies) { + if (file2.cycle != null && dep.cycle == file2.cycle) { + /* in the same cycle */ + if (!file2.is_cycle_head) { + /* include header of cycle head */ + file2.header_internal_includes.append (file2.cycle.head.get_cheader_filename ()); } + } else { + /* we can just include the headers if they are not in a cycle or not in the same cycle as the current file */ + file2.header_internal_includes.append (dep.get_cheader_filename ()); } } } @@ -143,60 +147,69 @@ public class Vala.CodeContext { file.mark = 1; foreach (SourceFile dep in file.header_internal_dependencies) { - if (file != dep) { - if (dep.mark == 1) { - /* found cycle */ + if (file == dep) { + continue; + } + + if (dep.mark == 1) { + /* found cycle */ + + var cycle = new SourceFileCycle (); + cycles.append (cycle); + + bool cycle_start_found = false; + foreach (SourceFile cycle_file in l) { + ref SourceFileCycle ref_cycle_file_cycle = cycle_file.cycle; + if (!cycle_start_found) { + if (cycle_file == dep) { + cycle_start_found = true; + } + } - var cycle = new SourceFileCycle (); - cycles.append (cycle); + if (!cycle_start_found) { + continue; + } - bool cycle_start_found = false; - foreach (SourceFile cycle_file in l) { - ref SourceFileCycle ref_cycle_file_cycle = cycle_file.cycle; - if (!cycle_start_found) { - if (cycle_file == dep) { - cycle_start_found = true; + if (cycle_file.cycle != null) { + /* file already in a cycle */ + + if (cycle_file.cycle == cycle) { + /* file is in the same cycle, nothing to do */ + continue; + } + + /* file is in an other cycle, merge the two cycles */ + + /* broken memory management cycles.remove (cycle_file.cycle); */ + ref List newlist = null; + foreach (SourceFileCycle oldcycle in cycles) { + if (oldcycle != cycle_file.cycle) { + newlist.append (oldcycle); } } - if (cycle_start_found) { - if (cycle_file.cycle != null) { - /* file already in a cycle */ - if (cycle_file.cycle != cycle) { - /* file is in an other cycle, merge the two cycles */ - - /* broken memory management cycles.remove (cycle_file.cycle); */ - ref List newlist = null; - foreach (SourceFileCycle oldcycle in cycles) { - if (oldcycle != cycle_file.cycle) { - newlist.append (oldcycle); - } - } - cycles = null; - foreach (SourceFileCycle newcycle in newlist) { - cycles.append (newcycle); - } - newlist = null; - /* end workaround for broken memory management */ - - foreach (SourceFile inner_cycle_file in cycle_file.cycle.files) { - if (inner_cycle_file.cycle != cycle) { - /* file in inner cycle not yet added to outer cycle */ - cycle.files.append (inner_cycle_file); - inner_cycle_file.cycle = cycle; - } - } - } - } else { - cycle.files.append (cycle_file); - cycle_file.cycle = cycle; + cycles = null; + foreach (SourceFileCycle newcycle in newlist) { + cycles.append (newcycle); + } + newlist = null; + /* end workaround for broken memory management */ + + foreach (SourceFile inner_cycle_file in cycle_file.cycle.files) { + if (inner_cycle_file.cycle != cycle) { + /* file in inner cycle not yet added to outer cycle */ + cycle.files.append (inner_cycle_file); + inner_cycle_file.cycle = cycle; } } + } else { + cycle.files.append (cycle_file); + cycle_file.cycle = cycle; } - } else if (dep.mark == 0) { - /* found not yet visited file */ - - visit (dep, l); } + } else if (dep.mark == 0) { + /* found not yet visited file */ + + visit (dep, l); } } diff --git a/vala/vala/valacodegenerator.vala b/vala/vala/valacodegenerator.vala index 627ac9c..ceea93e 100644 --- a/vala/vala/valacodegenerator.vala +++ b/vala/vala/valacodegenerator.vala @@ -22,1989 +22,1998 @@ using GLib; -namespace Vala { - public class CodeGenerator : CodeVisitor { - public bool memory_management { get; construct; } - - Symbol current_symbol; - Symbol current_type_symbol; - - CCodeFragment header_begin; - CCodeFragment header_type_declaration; - CCodeFragment header_type_definition; - CCodeFragment header_type_member_declaration; - CCodeFragment source_begin; - CCodeFragment source_include_directives; - CCodeFragment source_type_member_declaration; - CCodeFragment source_type_member_definition; - - CCodeStruct instance_struct; - CCodeStruct type_struct; - CCodeStruct instance_priv_struct; - CCodeEnum prop_enum; - CCodeEnum cenum; - CCodeFunction function; - CCodeBlock block; - - /* all temporary variables */ - List temp_vars; - /* temporary variables that own their content */ - List temp_ref_vars; - - private int next_temp_var_id = 0; - - public void emit (CodeContext! context) { - context.find_header_cycles (); - - /* we're only interested in non-pkg source files */ - var source_files = context.get_source_files (); - foreach (SourceFile file in source_files) { - if (!file.pkg) { - file.accept (this); - } +/** + * Code visitor generating C Code. + */ +public class Vala.CodeGenerator : CodeVisitor { + /** + * Specifies whether automatic memory management is active. + */ + public bool memory_management { get; set; } + + Symbol current_symbol; + Symbol current_type_symbol; + + CCodeFragment header_begin; + CCodeFragment header_type_declaration; + CCodeFragment header_type_definition; + CCodeFragment header_type_member_declaration; + CCodeFragment source_begin; + CCodeFragment source_include_directives; + CCodeFragment source_type_member_declaration; + CCodeFragment source_type_member_definition; + + CCodeStruct instance_struct; + CCodeStruct type_struct; + CCodeStruct instance_priv_struct; + CCodeEnum prop_enum; + CCodeEnum cenum; + CCodeFunction function; + CCodeBlock block; + + /* all temporary variables */ + List temp_vars; + /* temporary variables that own their content */ + List temp_ref_vars; + + private int next_temp_var_id = 0; + + /** + * Generate and emit C code for the specified code context. + * + * @param context a code context + */ + public void emit (CodeContext! context) { + context.find_header_cycles (); + + /* we're only interested in non-pkg source files */ + var source_files = context.get_source_files (); + foreach (SourceFile file in source_files) { + if (!file.pkg) { + file.accept (this); } } - - public override void visit_begin_source_file (SourceFile! source_file) { - header_begin = new CCodeFragment (); - header_type_declaration = new CCodeFragment (); - header_type_definition = new CCodeFragment (); - header_type_member_declaration = new CCodeFragment (); - source_begin = new CCodeFragment (); - source_include_directives = new CCodeFragment (); - source_type_member_declaration = new CCodeFragment (); - source_type_member_definition = new CCodeFragment (); - - next_temp_var_id = 0; - - header_begin.append (new CCodeIncludeDirective (filename = "glib.h")); - source_include_directives.append (new CCodeIncludeDirective (filename = source_file.get_cheader_filename ())); - - ref 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) { - if (used_includes.find_custom (filename1, strcmp) == null) { - header_begin.append (new CCodeIncludeDirective (filename = filename1)); - used_includes.append (filename1); - } + } + + public override void visit_begin_source_file (SourceFile! source_file) { + header_begin = new CCodeFragment (); + header_type_declaration = new CCodeFragment (); + header_type_definition = new CCodeFragment (); + header_type_member_declaration = new CCodeFragment (); + source_begin = new CCodeFragment (); + source_include_directives = new CCodeFragment (); + source_type_member_declaration = new CCodeFragment (); + source_type_member_definition = new CCodeFragment (); + + next_temp_var_id = 0; + + header_begin.append (new CCodeIncludeDirective (filename = "glib.h")); + source_include_directives.append (new CCodeIncludeDirective (filename = source_file.get_cheader_filename ())); + + ref 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) { + if (used_includes.find_custom (filename1, strcmp) == null) { + header_begin.append (new CCodeIncludeDirective (filename = filename1)); + used_includes.append (filename1); } - foreach (string filename2 in source_file.header_internal_includes) { - if (used_includes.find_custom (filename2, strcmp) == null) { - header_begin.append (new CCodeIncludeDirective (filename = filename2)); - used_includes.append (filename2); - } + } + foreach (string filename2 in source_file.header_internal_includes) { + if (used_includes.find_custom (filename2, strcmp) == null) { + header_begin.append (new CCodeIncludeDirective (filename = filename2)); + used_includes.append (filename2); } - foreach (string filename3 in source_file.source_includes) { - if (used_includes.find_custom (filename3, strcmp) == null) { - source_include_directives.append (new CCodeIncludeDirective (filename = filename3)); - used_includes.append (filename3); - } + } + foreach (string filename3 in source_file.source_includes) { + if (used_includes.find_custom (filename3, strcmp) == null) { + source_include_directives.append (new CCodeIncludeDirective (filename = filename3)); + used_includes.append (filename3); } - if (source_file.is_cycle_head) { - foreach (SourceFile cycle_file in source_file.cycle.files) { - var namespaces = cycle_file.get_namespaces (); - foreach (Namespace ns in namespaces) { - var structs = ns.get_structs (); - foreach (Struct st in structs) { - header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct _%s".printf (st.get_cname ()), declarator = new CCodeVariableDeclarator (name = st.get_cname ()))); - } - var classes = ns.get_classes (); - foreach (Class cl in classes) { - header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct _%s".printf (cl.get_cname ()), declarator = new CCodeVariableDeclarator (name = cl.get_cname ()))); - header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct _%sClass".printf (cl.get_cname ()), declarator = new CCodeVariableDeclarator (name = "%sClass".printf (cl.get_cname ())))); - } + } + if (source_file.is_cycle_head) { + foreach (SourceFile cycle_file in source_file.cycle.files) { + var namespaces = cycle_file.get_namespaces (); + foreach (Namespace ns in namespaces) { + var structs = ns.get_structs (); + foreach (Struct st in structs) { + header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct _%s".printf (st.get_cname ()), declarator = new CCodeVariableDeclarator (name = st.get_cname ()))); + } + var classes = ns.get_classes (); + foreach (Class cl in classes) { + header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct _%s".printf (cl.get_cname ()), declarator = new CCodeVariableDeclarator (name = cl.get_cname ()))); + header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct _%sClass".printf (cl.get_cname ()), declarator = new CCodeVariableDeclarator (name = "%sClass".printf (cl.get_cname ())))); } } } } + } + + private static ref string get_define_for_filename (string! filename) { + var define = String.new ("__"); - private static ref string get_define_for_filename (string! filename) { - var define = String.new ("__"); - - var i = filename; - while (i.len () > 0) { - var c = i.get_char (); - /* FIXME: remove explicit cast when implicit cast works */ - if (c.isalnum () && c < (unichar) 128) { - define.append_unichar (c.toupper ()); - } else { - define.append_c ('_'); - } - - i = i.next_char (); + var i = filename; + while (i.len () > 0) { + var c = i.get_char (); + /* FIXME: remove explicit cast when implicit cast works */ + if (c.isalnum () && c < (unichar) 128) { + define.append_unichar (c.toupper ()); + } else { + define.append_c ('_'); } - - define.append ("__"); - - return define.str; + + i = i.next_char (); } - public override void visit_end_source_file (SourceFile! source_file) { - var header_define = get_define_for_filename (source_file.get_cheader_filename ()); - - CCodeComment comment = null; - if (source_file.comment != null) { - comment = new CCodeComment (text = source_file.comment); - } - - var writer = new CCodeWriter (filename = source_file.get_cheader_filename ()); - if (comment != null) { - comment.write (writer); - } - writer.write_newline (); - var once = new CCodeOnceSection (define = header_define); - once.append (new CCodeNewline ()); - once.append (header_begin); - once.append (new CCodeNewline ()); - once.append (new CCodeIdentifier (name = "G_BEGIN_DECLS")); - once.append (new CCodeNewline ()); - once.append (new CCodeNewline ()); - once.append (header_type_declaration); - once.append (new CCodeNewline ()); - once.append (header_type_definition); - once.append (new CCodeNewline ()); - once.append (header_type_member_declaration); - once.append (new CCodeNewline ()); - once.append (new CCodeIdentifier (name = "G_END_DECLS")); - once.append (new CCodeNewline ()); - once.append (new CCodeNewline ()); - once.write (writer); - writer.close (); - - writer = new CCodeWriter (filename = source_file.get_csource_filename ()); - if (comment != null) { - comment.write (writer); - } - source_begin.write (writer); - writer.write_newline (); - source_include_directives.write (writer); - writer.write_newline (); - source_type_member_declaration.write (writer); - writer.write_newline (); - source_type_member_definition.write (writer); - writer.write_newline (); - writer.close (); - - header_begin = null; - header_type_declaration = null; - header_type_definition = null; - header_type_member_declaration = null; - source_begin = null; - source_include_directives = null; - source_type_member_declaration = null; - source_type_member_definition = null; - } - - public override void visit_begin_class (Class! cl) { - current_symbol = cl.symbol; - current_type_symbol = cl.symbol; - - instance_struct = new CCodeStruct (name = "_%s".printf (cl.get_cname ())); - type_struct = new CCodeStruct (name = "_%sClass".printf (cl.get_cname ())); - instance_priv_struct = new CCodeStruct (name = "_%sPrivate".printf (cl.get_cname ())); - prop_enum = new CCodeEnum (); - prop_enum.add_value ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null)), null); - - - header_type_declaration.append (new CCodeNewline ()); - var macro = "(%s_get_type ())".printf (cl.get_lower_case_cname (null)); - header_type_declaration.append (new CCodeMacroReplacement (name = cl.get_upper_case_cname ("TYPE_"), replacement = macro)); + define.append ("__"); + + return define.str; + } + + public override void visit_end_source_file (SourceFile! source_file) { + var header_define = get_define_for_filename (source_file.get_cheader_filename ()); + + CCodeComment comment = null; + if (source_file.comment != null) { + comment = new CCodeComment (text = source_file.comment); + } + + var writer = new CCodeWriter (filename = source_file.get_cheader_filename ()); + if (comment != null) { + comment.write (writer); + } + writer.write_newline (); + var once = new CCodeOnceSection (define = header_define); + once.append (new CCodeNewline ()); + once.append (header_begin); + once.append (new CCodeNewline ()); + once.append (new CCodeIdentifier (name = "G_BEGIN_DECLS")); + once.append (new CCodeNewline ()); + once.append (new CCodeNewline ()); + once.append (header_type_declaration); + once.append (new CCodeNewline ()); + once.append (header_type_definition); + once.append (new CCodeNewline ()); + once.append (header_type_member_declaration); + once.append (new CCodeNewline ()); + once.append (new CCodeIdentifier (name = "G_END_DECLS")); + once.append (new CCodeNewline ()); + once.append (new CCodeNewline ()); + once.write (writer); + writer.close (); + + writer = new CCodeWriter (filename = source_file.get_csource_filename ()); + if (comment != null) { + comment.write (writer); + } + source_begin.write (writer); + writer.write_newline (); + source_include_directives.write (writer); + writer.write_newline (); + source_type_member_declaration.write (writer); + writer.write_newline (); + source_type_member_definition.write (writer); + writer.write_newline (); + writer.close (); + + header_begin = null; + header_type_declaration = null; + header_type_definition = null; + header_type_member_declaration = null; + source_begin = null; + source_include_directives = null; + source_type_member_declaration = null; + source_type_member_definition = null; + } - macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); - header_type_declaration.append (new CCodeMacroReplacement (name = "%s(obj)".printf (cl.get_upper_case_cname (null)), replacement = macro)); + public override void visit_begin_class (Class! cl) { + current_symbol = cl.symbol; + current_type_symbol = cl.symbol; - macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); - header_type_declaration.append (new CCodeMacroReplacement (name = "%s_CLASS(klass)".printf (cl.get_upper_case_cname (null)), replacement = macro)); + instance_struct = new CCodeStruct (name = "_%s".printf (cl.get_cname ())); + type_struct = new CCodeStruct (name = "_%sClass".printf (cl.get_cname ())); + instance_priv_struct = new CCodeStruct (name = "_%sPrivate".printf (cl.get_cname ())); + prop_enum = new CCodeEnum (); + prop_enum.add_value ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null)), null); + + + header_type_declaration.append (new CCodeNewline ()); + var macro = "(%s_get_type ())".printf (cl.get_lower_case_cname (null)); + header_type_declaration.append (new CCodeMacroReplacement (name = cl.get_upper_case_cname ("TYPE_"), replacement = macro)); - macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl.get_upper_case_cname ("TYPE_")); - header_type_declaration.append (new CCodeMacroReplacement (name = "%s(obj)".printf (cl.get_upper_case_cname ("IS_")), replacement = macro)); + macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); + header_type_declaration.append (new CCodeMacroReplacement (name = "%s(obj)".printf (cl.get_upper_case_cname (null)), replacement = macro)); - macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl.get_upper_case_cname ("TYPE_")); - header_type_declaration.append (new CCodeMacroReplacement (name = "%s_CLASS(klass)".printf (cl.get_upper_case_cname ("IS_")), replacement = macro)); + macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); + header_type_declaration.append (new CCodeMacroReplacement (name = "%s_CLASS(klass)".printf (cl.get_upper_case_cname (null)), replacement = macro)); - macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); - header_type_declaration.append (new CCodeMacroReplacement (name = "%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), replacement = macro)); - header_type_declaration.append (new CCodeNewline ()); + macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl.get_upper_case_cname ("TYPE_")); + header_type_declaration.append (new CCodeMacroReplacement (name = "%s(obj)".printf (cl.get_upper_case_cname ("IS_")), replacement = macro)); + macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl.get_upper_case_cname ("TYPE_")); + header_type_declaration.append (new CCodeMacroReplacement (name = "%s_CLASS(klass)".printf (cl.get_upper_case_cname ("IS_")), replacement = macro)); - if (cl.source_reference.file.cycle == null) { - header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (instance_struct.name), declarator = new CCodeVariableDeclarator (name = cl.get_cname ()))); - header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (type_struct.name), declarator = new CCodeVariableDeclarator (name = "%sClass".printf (cl.get_cname ())))); - } - header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (instance_priv_struct.name), declarator = new CCodeVariableDeclarator (name = "%sPrivate".printf (cl.get_cname ())))); - - instance_struct.add_field (cl.base_class.get_cname (), "parent"); - instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv"); - type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent"); + macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); + header_type_declaration.append (new CCodeMacroReplacement (name = "%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), replacement = macro)); + header_type_declaration.append (new CCodeNewline ()); - if (cl.source_reference.comment != null) { - header_type_definition.append (new CCodeComment (text = cl.source_reference.comment)); - } - header_type_definition.append (instance_struct); - header_type_definition.append (type_struct); - source_type_member_declaration.append (instance_priv_struct); - macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); - source_type_member_declaration.append (new CCodeMacroReplacement (name = "%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), replacement = macro)); - source_type_member_declaration.append (prop_enum); - } - - public override void visit_end_class (Class! cl) { - add_get_property_function (cl); - add_set_property_function (cl); - add_class_init_function (cl); - add_instance_init_function (cl); - if (memory_management) { - add_dispose_function (cl); - } - - var type_fun = new ClassRegisterFunction (class_reference = cl); - 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; + if (cl.source_reference.file.cycle == null) { + header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (instance_struct.name), declarator = new CCodeVariableDeclarator (name = cl.get_cname ()))); + header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (type_struct.name), declarator = new CCodeVariableDeclarator (name = "%sClass".printf (cl.get_cname ())))); } + header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (instance_priv_struct.name), declarator = new CCodeVariableDeclarator (name = "%sPrivate".printf (cl.get_cname ())))); - private void add_class_init_function (Class! cl) { - var class_init = new CCodeFunction (name = "%s_class_init".printf (cl.get_lower_case_cname (null)), return_type = "void"); - 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; - - ref CCodeFunctionCall ccall; - - if (cl.has_private_fields) { - ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_type_class_add_private")); - ccall.add_argument (new CCodeIdentifier (name = "klass")); - ccall.add_argument (new CCodeConstant (name = "sizeof (%sPrivate)".printf (cl.get_cname ()))); - init_block.add_statement (new CCodeExpressionStatement (expression = ccall)); - } - - ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "G_OBJECT_CLASS")); + instance_struct.add_field (cl.base_class.get_cname (), "parent"); + instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv"); + type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent"); + + if (cl.source_reference.comment != null) { + header_type_definition.append (new CCodeComment (text = cl.source_reference.comment)); + } + header_type_definition.append (instance_struct); + header_type_definition.append (type_struct); + source_type_member_declaration.append (instance_priv_struct); + macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); + source_type_member_declaration.append (new CCodeMacroReplacement (name = "%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), replacement = macro)); + source_type_member_declaration.append (prop_enum); + } + + public override void visit_end_class (Class! cl) { + add_get_property_function (cl); + add_set_property_function (cl); + add_class_init_function (cl); + add_instance_init_function (cl); + if (memory_management) { + add_dispose_function (cl); + } + + var type_fun = new ClassRegisterFunction (class_reference = cl); + 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) { + var class_init = new CCodeFunction (name = "%s_class_init".printf (cl.get_lower_case_cname (null)), return_type = "void"); + 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; + + ref CCodeFunctionCall ccall; + + if (cl.has_private_fields) { + ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_type_class_add_private")); ccall.add_argument (new CCodeIdentifier (name = "klass")); - init_block.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeMemberAccess (inner = ccall, member_name = "get_property", is_pointer = true), right = new CCodeIdentifier (name = "%s_get_property".printf (cl.get_lower_case_cname (null)))))); - init_block.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeMemberAccess (inner = ccall, member_name = "set_property", is_pointer = true), right = new CCodeIdentifier (name = "%s_set_property".printf (cl.get_lower_case_cname (null)))))); + ccall.add_argument (new CCodeConstant (name = "sizeof (%sPrivate)".printf (cl.get_cname ()))); + init_block.add_statement (new CCodeExpressionStatement (expression = ccall)); + } + + ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "G_OBJECT_CLASS")); + ccall.add_argument (new CCodeIdentifier (name = "klass")); + init_block.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeMemberAccess (inner = ccall, member_name = "get_property", is_pointer = true), right = new CCodeIdentifier (name = "%s_get_property".printf (cl.get_lower_case_cname (null)))))); + init_block.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeMemberAccess (inner = ccall, member_name = "set_property", is_pointer = true), right = new CCodeIdentifier (name = "%s_set_property".printf (cl.get_lower_case_cname (null)))))); + + if (cl.constructor != null) { + var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "G_OBJECT_CLASS")); + ccast.add_argument (new CCodeIdentifier (name = "klass")); + init_block.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeMemberAccess (inner = ccast, member_name = "constructor", is_pointer = true), right = new CCodeIdentifier (name = "%s_constructor".printf (cl.get_lower_case_cname (null)))))); + } + + if (memory_management && cl.get_fields () != null) { + var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "G_OBJECT_CLASS")); + ccast.add_argument (new CCodeIdentifier (name = "klass")); + init_block.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeMemberAccess (inner = ccast, member_name = "dispose", is_pointer = true), right = new CCodeIdentifier (name = "%s_dispose".printf (cl.get_lower_case_cname (null)))))); + } + + var methods = cl.get_methods (); + foreach (Method m in methods) { + if (m.is_virtual || m.is_override) { + var base_type = m.base_method.symbol.parent_symbol.node; - if (cl.constructor != null) { - var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "G_OBJECT_CLASS")); + 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 = "constructor", is_pointer = true), right = new CCodeIdentifier (name = "%s_constructor".printf (cl.get_lower_case_cname (null)))))); + 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 ())))); } - - if (memory_management && cl.get_fields () != null) { - var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "G_OBJECT_CLASS")); - ccast.add_argument (new CCodeIdentifier (name = "klass")); - init_block.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeMemberAccess (inner = ccast, member_name = "dispose", is_pointer = true), right = new CCodeIdentifier (name = "%s_dispose".printf (cl.get_lower_case_cname (null)))))); + } + + var props = cl.get_properties (); + foreach (Property prop in props) { + var cinst = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_object_class_install_property")); + cinst.add_argument (ccall); + cinst.add_argument (new CCodeConstant (name = prop.get_upper_case_cname ())); + var cspec = new CCodeFunctionCall (); + cspec.add_argument (prop.get_canonical_cconstant ()); + cspec.add_argument (new CCodeConstant (name = "\"foo\"")); + cspec.add_argument (new CCodeConstant (name = "\"bar\"")); + if (prop.type_reference.type is Class) { + cspec.call = new CCodeIdentifier (name = "g_param_spec_object"); + cspec.add_argument (new CCodeIdentifier (name = prop.type_reference.type.get_upper_case_cname ("TYPE_"))); + } else if (prop.type_reference.type_name == "string") { + cspec.call = new CCodeIdentifier (name = "g_param_spec_string"); + cspec.add_argument (new CCodeConstant (name = "NULL")); + } else if (prop.type_reference.type_name == "int" + || prop.type_reference.type is Enum) { + cspec.call = new CCodeIdentifier (name = "g_param_spec_int"); + cspec.add_argument (new CCodeConstant (name = "G_MININT")); + cspec.add_argument (new CCodeConstant (name = "G_MAXINT")); + cspec.add_argument (new CCodeConstant (name = "0")); + } else if (prop.type_reference.type_name == "bool") { + cspec.call = new CCodeIdentifier (name = "g_param_spec_boolean"); + cspec.add_argument (new CCodeConstant (name = "FALSE")); + } else { + cspec.call = new CCodeIdentifier (name = "g_param_spec_pointer"); } - var methods = cl.get_methods (); - foreach (Method m in methods) { - if (m.is_virtual || m.is_override) { - 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 ())))); - } + 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"); } - - var props = cl.get_properties (); - foreach (Property prop in props) { - var cinst = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_object_class_install_property")); - cinst.add_argument (ccall); - cinst.add_argument (new CCodeConstant (name = prop.get_upper_case_cname ())); - var cspec = new CCodeFunctionCall (); - cspec.add_argument (prop.get_canonical_cconstant ()); - cspec.add_argument (new CCodeConstant (name = "\"foo\"")); - cspec.add_argument (new CCodeConstant (name = "\"bar\"")); - if (prop.type_reference.type is Class) { - cspec.call = new CCodeIdentifier (name = "g_param_spec_object"); - cspec.add_argument (new CCodeIdentifier (name = prop.type_reference.type.get_upper_case_cname ("TYPE_"))); - } else if (prop.type_reference.type_name == "string") { - cspec.call = new CCodeIdentifier (name = "g_param_spec_string"); - cspec.add_argument (new CCodeConstant (name = "NULL")); - } else if (prop.type_reference.type_name == "int" - || prop.type_reference.type is Enum) { - cspec.call = new CCodeIdentifier (name = "g_param_spec_int"); - cspec.add_argument (new CCodeConstant (name = "G_MININT")); - cspec.add_argument (new CCodeConstant (name = "G_MAXINT")); - cspec.add_argument (new CCodeConstant (name = "0")); - } else if (prop.type_reference.type_name == "bool") { - cspec.call = new CCodeIdentifier (name = "g_param_spec_boolean"); - cspec.add_argument (new CCodeConstant (name = "FALSE")); - } else { - cspec.call = new CCodeIdentifier (name = "g_param_spec_pointer"); - } - - 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"); - } + 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)); } + cspec.add_argument (new CCodeConstant (name = pflags)); + cinst.add_argument (cspec); - source_type_member_definition.append (class_init); + init_block.add_statement (new CCodeExpressionStatement (expression = cinst)); } - private void add_instance_init_function (Class! cl) { - var instance_init = new CCodeFunction (name = "%s_init".printf (cl.get_lower_case_cname (null)), return_type = "void"); - 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; - - if (cl.has_private_fields) { - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null)))); - ccall.add_argument (new CCodeIdentifier (name = "self")); - init_block.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeMemberAccess (inner = new CCodeIdentifier (name = "self"), member_name = "priv", is_pointer = true), right = ccall))); - } - - var fields = cl.get_fields (); - foreach (Field f in fields) { - if (f.initializer != null) { - ref CCodeExpression lhs = null; - if (f.instance) { - if (f.access == MemberAccessibility.PRIVATE) { - lhs = new CCodeMemberAccess (inner = new CCodeMemberAccess (inner = new CCodeIdentifier (name = "self"), member_name = "priv", is_pointer = true), member_name = f.get_cname (), is_pointer = true); - } else { - lhs = new CCodeMemberAccess (inner = new CCodeIdentifier (name = "self"), member_name = f.get_cname (), is_pointer = true); - } - } /* else { - lhs = new CCodeIdentifier (name = "%s_%s".printf (cl.get_lower_case_cname (null), f.get_cname ())); - } */ - if (lhs != null) { - init_block.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = lhs, right = f.initializer.ccodenode))); + source_type_member_definition.append (class_init); + } + + private void add_instance_init_function (Class! cl) { + var instance_init = new CCodeFunction (name = "%s_init".printf (cl.get_lower_case_cname (null)), return_type = "void"); + 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; + + if (cl.has_private_fields) { + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null)))); + ccall.add_argument (new CCodeIdentifier (name = "self")); + init_block.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeMemberAccess (inner = new CCodeIdentifier (name = "self"), member_name = "priv", is_pointer = true), right = ccall))); + } + + var fields = cl.get_fields (); + foreach (Field f in fields) { + if (f.initializer != null) { + ref CCodeExpression lhs = null; + if (f.instance) { + if (f.access == MemberAccessibility.PRIVATE) { + lhs = new CCodeMemberAccess (inner = new CCodeMemberAccess (inner = new CCodeIdentifier (name = "self"), member_name = "priv", is_pointer = true), member_name = f.get_cname (), is_pointer = true); + } else { + lhs = new CCodeMemberAccess (inner = new CCodeIdentifier (name = "self"), member_name = f.get_cname (), is_pointer = true); } + } /* else { + lhs = new CCodeIdentifier (name = "%s_%s".printf (cl.get_lower_case_cname (null), f.get_cname ())); + } */ + if (lhs != null) { + init_block.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = lhs, right = f.initializer.ccodenode))); } } - - var init_sym = cl.symbol.lookup ("init"); - if (init_sym != null) { - var init_fun = (Method) init_sym.node; - init_block.add_statement (init_fun.body.ccodenode); - } - - source_type_member_definition.append (instance_init); } - private void add_dispose_function (Class! cl) { - function = new CCodeFunction (name = "%s_dispose".printf (cl.get_lower_case_cname (null)), return_type = "void"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeFormalParameter (name = "obj", type_name = "GObject *")); - - source_type_member_declaration.append (function.copy ()); - + var init_sym = cl.symbol.lookup ("init"); + if (init_sym != null) { + var init_fun = (Method) init_sym.node; + init_block.add_statement (init_fun.body.ccodenode); + } + + source_type_member_definition.append (instance_init); + } + + private void add_dispose_function (Class! cl) { + function = new CCodeFunction (name = "%s_dispose".printf (cl.get_lower_case_cname (null)), return_type = "void"); + function.modifiers = CCodeModifiers.STATIC; + + function.add_parameter (new CCodeFormalParameter (name = "obj", type_name = "GObject *")); + + source_type_member_declaration.append (function.copy ()); - var cblock = new CCodeBlock (); - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = cl.get_upper_case_cname (null))); - ccall.add_argument (new CCodeIdentifier (name = "obj")); - - var cdecl = new CCodeDeclaration (type_name = "%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator (name = "self", initializer = ccall)); - - cblock.add_statement (cdecl); - - - var fields = cl.get_fields (); - foreach (Field f in fields) { - if (f.instance && f.type_reference.is_lvalue_ref) { - var cself = new CCodeIdentifier (name = "self"); - CCodeExpression cstruct = cself; - if (f.access == MemberAccessibility.PRIVATE) { - cstruct = new CCodeMemberAccess (inner = cself, member_name = "priv", is_pointer = true); - } - var cfield = new CCodeMemberAccess (inner = cstruct, member_name = f.get_cname (), is_pointer = true); + var cblock = new CCodeBlock (); - cblock.add_statement (new CCodeExpressionStatement (expression = get_unref_expression (cfield, f.type_reference))); + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = cl.get_upper_case_cname (null))); + ccall.add_argument (new CCodeIdentifier (name = "obj")); + + var cdecl = new CCodeDeclaration (type_name = "%s *".printf (cl.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator (name = "self", initializer = ccall)); + + cblock.add_statement (cdecl); + + + var fields = cl.get_fields (); + foreach (Field f in fields) { + if (f.instance && f.type_reference.is_lvalue_ref) { + var cself = new CCodeIdentifier (name = "self"); + CCodeExpression cstruct = cself; + if (f.access == MemberAccessibility.PRIVATE) { + cstruct = new CCodeMemberAccess (inner = cself, member_name = "priv", is_pointer = true); } - } + var cfield = new CCodeMemberAccess (inner = cstruct, member_name = f.get_cname (), is_pointer = true); + cblock.add_statement (new CCodeExpressionStatement (expression = get_unref_expression (cfield, f.type_reference))); + } + } - cdecl = new CCodeDeclaration (type_name = "%sClass *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator (name = "klass")); - cblock.add_statement (cdecl); - cdecl = new CCodeDeclaration (type_name = "GObjectClass *"); - cdecl.add_declarator (new CCodeVariableDeclarator (name = "parent_class")); - cblock.add_statement (cdecl); - - - ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_type_class_peek")); - ccall.add_argument (new CCodeIdentifier (name = cl.get_upper_case_cname ("TYPE_"))); - var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_CLASS".printf (cl.get_upper_case_cname (null)))); - ccast.add_argument (ccall); - cblock.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeIdentifier (name = "klass"), right = ccast))); + cdecl = new CCodeDeclaration (type_name = "%sClass *".printf (cl.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator (name = "klass")); + cblock.add_statement (cdecl); - ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_type_class_peek_parent")); - ccall.add_argument (new CCodeIdentifier (name = "klass")); - ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "G_OBJECT_CLASS")); - ccast.add_argument (ccall); - cblock.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeIdentifier (name = "parent_class"), right = ccast))); + cdecl = new CCodeDeclaration (type_name = "GObjectClass *"); + cdecl.add_declarator (new CCodeVariableDeclarator (name = "parent_class")); + cblock.add_statement (cdecl); - - ccall = new CCodeFunctionCall (call = new CCodeMemberAccess (inner = new CCodeIdentifier (name = "parent_class"), member_name = "dispose", is_pointer = true)); - ccall.add_argument (new CCodeIdentifier (name = "obj")); - cblock.add_statement (new CCodeExpressionStatement (expression = ccall)); + ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_type_class_peek")); + ccall.add_argument (new CCodeIdentifier (name = cl.get_upper_case_cname ("TYPE_"))); + var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_CLASS".printf (cl.get_upper_case_cname (null)))); + ccast.add_argument (ccall); + cblock.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeIdentifier (name = "klass"), right = ccast))); - function.block = cblock; + ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_type_class_peek_parent")); + ccall.add_argument (new CCodeIdentifier (name = "klass")); + ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "G_OBJECT_CLASS")); + ccast.add_argument (ccall); + cblock.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeIdentifier (name = "parent_class"), right = ccast))); - source_type_member_definition.append (function); - } - private void add_get_property_function (Class! cl) { - var get_prop = new CCodeFunction (name = "%s_get_property".printf (cl.get_lower_case_cname (null)), return_type = "void"); - get_prop.add_parameter (new CCodeFormalParameter (type_name = "GObject *", name = "object")); - get_prop.add_parameter (new CCodeFormalParameter (type_name = "guint", name = "property_id")); - get_prop.add_parameter (new CCodeFormalParameter (type_name = "GValue *", name = "value")); - get_prop.add_parameter (new CCodeFormalParameter (type_name = "GParamSpec *", name = "pspec")); - - var block = new CCodeBlock (); - - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = cl.get_upper_case_cname (null))); - ccall.add_argument (new CCodeIdentifier (name = "object")); - var cdecl = new CCodeDeclaration (type_name = "%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator (name = "self", initializer = ccall)); - block.add_statement (cdecl); - - var cswitch = new CCodeSwitchStatement (expression = new CCodeIdentifier (name = "property_id")); - var props = cl.get_properties (); - foreach (Property prop in props) { - if (prop.get_accessor == null) { - continue; - } + ccall = new CCodeFunctionCall (call = new CCodeMemberAccess (inner = new CCodeIdentifier (name = "parent_class"), member_name = "dispose", is_pointer = true)); + ccall.add_argument (new CCodeIdentifier (name = "obj")); + cblock.add_statement (new CCodeExpressionStatement (expression = ccall)); - var ccase = new CCodeCaseStatement (expression = new CCodeIdentifier (name = prop.get_upper_case_cname ())); - 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")); - var csetcall = new CCodeFunctionCall (); - if (prop.type_reference.type is Class) { - csetcall.call = new CCodeIdentifier (name = "g_value_set_object"); - } else if (prop.type_reference.type_name == "string") { - csetcall.call = new CCodeIdentifier (name = "g_value_set_string"); - } else if (prop.type_reference.type_name == "int" - || prop.type_reference.type is Enum) { - csetcall.call = new CCodeIdentifier (name = "g_value_set_int"); - } else if (prop.type_reference.type_name == "bool") { - csetcall.call = new CCodeIdentifier (name = "g_value_set_boolean"); - } else { - csetcall.call = new CCodeIdentifier (name = "g_value_set_pointer"); - } - csetcall.add_argument (new CCodeIdentifier (name = "value")); - csetcall.add_argument (ccall); - ccase.add_statement (new CCodeExpressionStatement (expression = csetcall)); - ccase.add_statement (new CCodeBreakStatement ()); - cswitch.add_case (ccase); - } - block.add_statement (cswitch); - get_prop.block = block; - - source_type_member_definition.append (get_prop); - } + function.block = cblock; + + source_type_member_definition.append (function); + } + + private void add_get_property_function (Class! cl) { + var get_prop = new CCodeFunction (name = "%s_get_property".printf (cl.get_lower_case_cname (null)), return_type = "void"); + get_prop.add_parameter (new CCodeFormalParameter (type_name = "GObject *", name = "object")); + get_prop.add_parameter (new CCodeFormalParameter (type_name = "guint", name = "property_id")); + get_prop.add_parameter (new CCodeFormalParameter (type_name = "GValue *", name = "value")); + get_prop.add_parameter (new CCodeFormalParameter (type_name = "GParamSpec *", name = "pspec")); - private void add_set_property_function (Class! cl) { - var set_prop = new CCodeFunction (name = "%s_set_property".printf (cl.get_lower_case_cname (null)), return_type = "void"); - set_prop.add_parameter (new CCodeFormalParameter (type_name = "GObject *", name = "object")); - set_prop.add_parameter (new CCodeFormalParameter (type_name = "guint", name = "property_id")); - set_prop.add_parameter (new CCodeFormalParameter (type_name = "const GValue *", name = "value")); - set_prop.add_parameter (new CCodeFormalParameter (type_name = "GParamSpec *", name = "pspec")); - - var block = new CCodeBlock (); - - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = cl.get_upper_case_cname (null))); - ccall.add_argument (new CCodeIdentifier (name = "object")); - var cdecl = new CCodeDeclaration (type_name = "%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator (name = "self", initializer = ccall)); - block.add_statement (cdecl); - - var cswitch = new CCodeSwitchStatement (expression = new CCodeIdentifier (name = "property_id")); - var props = cl.get_properties (); - foreach (Property prop in props) { - if (prop.set_accessor == null) { - continue; - } + var block = new CCodeBlock (); + + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = cl.get_upper_case_cname (null))); + ccall.add_argument (new CCodeIdentifier (name = "object")); + var cdecl = new CCodeDeclaration (type_name = "%s *".printf (cl.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator (name = "self", initializer = ccall)); + block.add_statement (cdecl); + + var cswitch = new CCodeSwitchStatement (expression = new CCodeIdentifier (name = "property_id")); + var props = cl.get_properties (); + foreach (Property prop in props) { + if (prop.get_accessor == null) { + continue; + } + + var ccase = new CCodeCaseStatement (expression = new CCodeIdentifier (name = prop.get_upper_case_cname ())); + 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")); + var csetcall = new CCodeFunctionCall (); + if (prop.type_reference.type is Class) { + csetcall.call = new CCodeIdentifier (name = "g_value_set_object"); + } else if (prop.type_reference.type_name == "string") { + csetcall.call = new CCodeIdentifier (name = "g_value_set_string"); + } else if (prop.type_reference.type_name == "int" + || prop.type_reference.type is Enum) { + csetcall.call = new CCodeIdentifier (name = "g_value_set_int"); + } else if (prop.type_reference.type_name == "bool") { + csetcall.call = new CCodeIdentifier (name = "g_value_set_boolean"); + } else { + csetcall.call = new CCodeIdentifier (name = "g_value_set_pointer"); + } + csetcall.add_argument (new CCodeIdentifier (name = "value")); + csetcall.add_argument (ccall); + ccase.add_statement (new CCodeExpressionStatement (expression = csetcall)); + ccase.add_statement (new CCodeBreakStatement ()); + cswitch.add_case (ccase); + } + block.add_statement (cswitch); - var ccase = new CCodeCaseStatement (expression = new CCodeIdentifier (name = prop.get_upper_case_cname ())); - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name))); - ccall.add_argument (new CCodeIdentifier (name = "self")); - var cgetcall = new CCodeFunctionCall (); - if (prop.type_reference.type is Class) { - cgetcall.call = new CCodeIdentifier (name = "g_value_get_object"); - } else if (prop.type_reference.type_name == "string") { - cgetcall.call = new CCodeIdentifier (name = "g_value_get_string"); - } else if (prop.type_reference.type_name == "int" - || prop.type_reference.type is Enum) { - cgetcall.call = new CCodeIdentifier (name = "g_value_get_int"); - } else if (prop.type_reference.type_name == "bool") { - cgetcall.call = new CCodeIdentifier (name = "g_value_get_boolean"); - } else { - cgetcall.call = new CCodeIdentifier (name = "g_value_get_pointer"); - } - cgetcall.add_argument (new CCodeIdentifier (name = "value")); - ccall.add_argument (cgetcall); - ccase.add_statement (new CCodeExpressionStatement (expression = ccall)); - ccase.add_statement (new CCodeBreakStatement ()); - cswitch.add_case (ccase); + get_prop.block = block; + + source_type_member_definition.append (get_prop); + } + + private void add_set_property_function (Class! cl) { + var set_prop = new CCodeFunction (name = "%s_set_property".printf (cl.get_lower_case_cname (null)), return_type = "void"); + set_prop.add_parameter (new CCodeFormalParameter (type_name = "GObject *", name = "object")); + set_prop.add_parameter (new CCodeFormalParameter (type_name = "guint", name = "property_id")); + set_prop.add_parameter (new CCodeFormalParameter (type_name = "const GValue *", name = "value")); + set_prop.add_parameter (new CCodeFormalParameter (type_name = "GParamSpec *", name = "pspec")); + + var block = new CCodeBlock (); + + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = cl.get_upper_case_cname (null))); + ccall.add_argument (new CCodeIdentifier (name = "object")); + var cdecl = new CCodeDeclaration (type_name = "%s *".printf (cl.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator (name = "self", initializer = ccall)); + block.add_statement (cdecl); + + var cswitch = new CCodeSwitchStatement (expression = new CCodeIdentifier (name = "property_id")); + var props = cl.get_properties (); + foreach (Property prop in props) { + if (prop.set_accessor == null) { + continue; + } + + var ccase = new CCodeCaseStatement (expression = new CCodeIdentifier (name = prop.get_upper_case_cname ())); + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name))); + ccall.add_argument (new CCodeIdentifier (name = "self")); + var cgetcall = new CCodeFunctionCall (); + if (prop.type_reference.type is Class) { + cgetcall.call = new CCodeIdentifier (name = "g_value_get_object"); + } else if (prop.type_reference.type_name == "string") { + cgetcall.call = new CCodeIdentifier (name = "g_value_get_string"); + } else if (prop.type_reference.type_name == "int" + || prop.type_reference.type is Enum) { + cgetcall.call = new CCodeIdentifier (name = "g_value_get_int"); + } else if (prop.type_reference.type_name == "bool") { + cgetcall.call = new CCodeIdentifier (name = "g_value_get_boolean"); + } else { + cgetcall.call = new CCodeIdentifier (name = "g_value_get_pointer"); } - block.add_statement (cswitch); - - set_prop.block = block; - - source_type_member_definition.append (set_prop); + cgetcall.add_argument (new CCodeIdentifier (name = "value")); + ccall.add_argument (cgetcall); + ccase.add_statement (new CCodeExpressionStatement (expression = ccall)); + ccase.add_statement (new CCodeBreakStatement ()); + cswitch.add_case (ccase); } + block.add_statement (cswitch); - public override void visit_begin_struct (Struct! st) { - instance_struct = new CCodeStruct (name = "_%s".printf (st.name)); + set_prop.block = block; + + source_type_member_definition.append (set_prop); + } + + public override void visit_begin_struct (Struct! st) { + instance_struct = new CCodeStruct (name = "_%s".printf (st.name)); - if (st.source_reference.comment != null) { - header_type_definition.append (new CCodeComment (text = st.source_reference.comment)); - } - header_type_definition.append (instance_struct); + if (st.source_reference.comment != null) { + header_type_definition.append (new CCodeComment (text = st.source_reference.comment)); } + header_type_definition.append (instance_struct); + } - public override void visit_begin_interface (Interface! iface) { - current_symbol = iface.symbol; - current_type_symbol = iface.symbol; + public override void visit_begin_interface (Interface! iface) { + current_symbol = iface.symbol; + current_type_symbol = iface.symbol; - type_struct = new CCodeStruct (name = "_%sInterface".printf (iface.get_cname ())); - - header_type_declaration.append (new CCodeNewline ()); - var macro = "(%s_get_type ())".printf (iface.get_lower_case_cname (null)); - header_type_declaration.append (new CCodeMacroReplacement (name = iface.get_upper_case_cname ("TYPE_"), replacement = macro)); + type_struct = new CCodeStruct (name = "_%sInterface".printf (iface.get_cname ())); + + header_type_declaration.append (new CCodeNewline ()); + var macro = "(%s_get_type ())".printf (iface.get_lower_case_cname (null)); + header_type_declaration.append (new CCodeMacroReplacement (name = iface.get_upper_case_cname ("TYPE_"), replacement = macro)); - macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (iface.get_upper_case_cname ("TYPE_"), iface.get_cname ()); - header_type_declaration.append (new CCodeMacroReplacement (name = "%s(obj)".printf (iface.get_upper_case_cname (null)), replacement = macro)); + macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (iface.get_upper_case_cname ("TYPE_"), iface.get_cname ()); + header_type_declaration.append (new CCodeMacroReplacement (name = "%s(obj)".printf (iface.get_upper_case_cname (null)), replacement = macro)); - macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (iface.get_upper_case_cname ("TYPE_")); - header_type_declaration.append (new CCodeMacroReplacement (name = "%s(obj)".printf (iface.get_upper_case_cname ("IS_")), replacement = macro)); + macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (iface.get_upper_case_cname ("TYPE_")); + header_type_declaration.append (new CCodeMacroReplacement (name = "%s(obj)".printf (iface.get_upper_case_cname ("IS_")), replacement = macro)); - macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %sInterface))".printf (iface.get_upper_case_cname ("TYPE_"), iface.get_cname ()); - header_type_declaration.append (new CCodeMacroReplacement (name = "%s_GET_INTERFACE(obj)".printf (iface.get_upper_case_cname (null)), replacement = macro)); - header_type_declaration.append (new CCodeNewline ()); + macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %sInterface))".printf (iface.get_upper_case_cname ("TYPE_"), iface.get_cname ()); + header_type_declaration.append (new CCodeMacroReplacement (name = "%s_GET_INTERFACE(obj)".printf (iface.get_upper_case_cname (null)), replacement = macro)); + header_type_declaration.append (new CCodeNewline ()); - if (iface.source_reference.file.cycle == null) { - header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct _%s".printf (iface.get_cname ()), declarator = new CCodeVariableDeclarator (name = iface.get_cname ()))); - header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (type_struct.name), declarator = new CCodeVariableDeclarator (name = "%sInterface".printf (iface.get_cname ())))); - } - - type_struct.add_field ("GTypeInterface", "parent"); + if (iface.source_reference.file.cycle == null) { + header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct _%s".printf (iface.get_cname ()), declarator = new CCodeVariableDeclarator (name = iface.get_cname ()))); + header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (type_struct.name), declarator = new CCodeVariableDeclarator (name = "%sInterface".printf (iface.get_cname ())))); + } + + type_struct.add_field ("GTypeInterface", "parent"); - if (iface.source_reference.comment != null) { - header_type_definition.append (new CCodeComment (text = iface.source_reference.comment)); - } - header_type_definition.append (type_struct); + if (iface.source_reference.comment != null) { + header_type_definition.append (new CCodeComment (text = iface.source_reference.comment)); } + header_type_definition.append (type_struct); + } - public override void visit_end_interface (Interface! iface) { - var type_fun = new InterfaceRegisterFunction (interface_reference = iface); - type_fun.init_from_type (); - header_type_member_declaration.append (type_fun.get_declaration ()); - source_type_member_definition.append (type_fun); + public override void visit_end_interface (Interface! iface) { + var type_fun = new InterfaceRegisterFunction (interface_reference = iface); + 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) { - cenum = new CCodeEnum (name = en.get_cname ()); + current_type_symbol = null; + } + + public override void visit_begin_enum (Enum! en) { + cenum = new CCodeEnum (name = en.get_cname ()); - if (en.source_reference.comment != null) { - header_type_definition.append (new CCodeComment (text = en.source_reference.comment)); - } - header_type_definition.append (cenum); + if (en.source_reference.comment != null) { + header_type_definition.append (new CCodeComment (text = en.source_reference.comment)); } + header_type_definition.append (cenum); + } - public override void visit_enum_value (EnumValue! ev) { - cenum.add_value (ev.get_cname (), null); - } + public override void visit_enum_value (EnumValue! ev) { + cenum.add_value (ev.get_cname (), null); + } - public override void visit_end_callback (Callback! cb) { - var ctypedef = new CCodeTypeDefinition (); - - ctypedef.type_name = cb.return_type.get_cname (); - - var cfundecl = new CCodeFunctionDeclarator (name = cb.get_cname ()); - foreach (FormalParameter param in cb.get_parameters ()) { - cfundecl.add_parameter ((CCodeFormalParameter) param.ccodenode); - } - ctypedef.declarator = cfundecl; - - if (cb.access == MemberAccessibility.PUBLIC) { - header_type_declaration.append (ctypedef); - } else { - source_type_member_declaration.append (ctypedef); - } + public override void visit_end_callback (Callback! cb) { + var ctypedef = new CCodeTypeDefinition (); + + ctypedef.type_name = cb.return_type.get_cname (); + + var cfundecl = new CCodeFunctionDeclarator (name = cb.get_cname ()); + foreach (FormalParameter param in cb.get_parameters ()) { + cfundecl.add_parameter ((CCodeFormalParameter) param.ccodenode); + } + ctypedef.declarator = cfundecl; + + if (cb.access == MemberAccessibility.PUBLIC) { + header_type_declaration.append (ctypedef); + } else { + source_type_member_declaration.append (ctypedef); } + } - public override void visit_constant (Constant! c) { - if (c.symbol.parent_symbol.node is DataType) { - var t = (DataType) c.symbol.parent_symbol.node; - var cdecl = new CCodeDeclaration (type_name = c.type_reference.get_const_cname ()); - var arr = ""; - if (c.type_reference.array) { - arr = "[]"; - } - cdecl.add_declarator (new CCodeVariableDeclarator (name = "%s%s".printf (c.get_cname (), arr), initializer = c.initializer.ccodenode)); - cdecl.modifiers = CCodeModifiers.STATIC; - source_type_member_declaration.append (cdecl); + public override void visit_constant (Constant! c) { + if (c.symbol.parent_symbol.node is DataType) { + var t = (DataType) c.symbol.parent_symbol.node; + var cdecl = new CCodeDeclaration (type_name = c.type_reference.get_const_cname ()); + var arr = ""; + if (c.type_reference.array) { + arr = "[]"; } + cdecl.add_declarator (new CCodeVariableDeclarator (name = "%s%s".printf (c.get_cname (), arr), initializer = c.initializer.ccodenode)); + 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.get_cname ()); - } else if (f.access == MemberAccessibility.PRIVATE) { - if (f.instance) { - instance_priv_struct.add_field (f.type_reference.get_cname (), f.get_cname ()); - } else { - 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 ()); - 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); + } + + public override void visit_field (Field! f) { + if (f.access == MemberAccessibility.PUBLIC) { + instance_struct.add_field (f.type_reference.get_cname (), f.get_cname ()); + } else if (f.access == MemberAccessibility.PRIVATE) { + if (f.instance) { + instance_priv_struct.add_field (f.type_reference.get_cname (), f.get_cname ()); + } else { + 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 ()); + 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); } } } + } - public override void visit_begin_method (Method! m) { - current_symbol = m.symbol; + public override void visit_begin_method (Method! m) { + current_symbol = m.symbol; + } + + 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 (); - 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); + var ctype_check = new CCodeFunctionCall (call = new CCodeIdentifier (name = t.get_upper_case_cname ("IS_"))); + ctype_check.add_argument (new CCodeIdentifier (name = var_name)); + + ref CCodeExpression cexpr = ctype_check; + if (!non_null) { + var cnull = new CCodeBinaryExpression (operator = CCodeBinaryOperator.EQUALITY, left = new CCodeIdentifier (name = var_name), right = new CCodeConstant (name = "NULL")); + + cexpr = new CCodeBinaryExpression (operator = CCodeBinaryOperator.OR, left = cnull, right = ctype_check); } + ccheck.add_argument (cexpr); - 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); + 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"); + + 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" || ret_type is Enum || ret_type is Flags) { + ccheck.add_argument (new CCodeConstant (name = "0")); } else { - return create_type_check_statement (prop, null, t, non_null, var_name); + Report.error (method_node.source_reference, "not supported return type for runtime type checks"); + return null; } } - 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_"))); - ctype_check.add_argument (new CCodeIdentifier (name = var_name)); - - ref CCodeExpression cexpr = ctype_check; - if (!non_null) { - var cnull = new CCodeBinaryExpression (operator = CCodeBinaryOperator.EQUALITY, left = new CCodeIdentifier (name = var_name), right = new CCodeConstant (name = "NULL")); - - cexpr = new CCodeBinaryExpression (operator = CCodeBinaryOperator.OR, left = cnull, right = ctype_check); + return new CCodeExpressionStatement (expression = ccheck); + } + + private DataType find_parent_type (CodeNode node) { + var sym = node.symbol; + while (sym != null) { + if (sym.node is DataType) { + return (DataType) sym.node; } - ccheck.add_argument (cexpr); - - if (ret_type == null) { - /* void function */ - ccheck.call = new CCodeIdentifier (name = "g_return_if_fail"); + sym = sym.parent_symbol; + } + return null; + } + + public override void visit_end_method (Method! m) { + current_symbol = current_symbol.parent_symbol; + + if (m.name == "init") { + return; + } + + function = new CCodeFunction (name = m.get_real_cname (), return_type = m.return_type.get_cname ()); + CCodeFunctionDeclarator vdeclarator = null; + + if (m.instance) { + var this_type = new TypeReference (); + this_type.type = find_parent_type (m); + if (!m.is_override) { + var cparam = new CCodeFormalParameter (type_name = this_type.get_cname (), name = "self"); + function.add_parameter (cparam); } else { - ccheck.call = new CCodeIdentifier (name = "g_return_val_if_fail"); - - 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" || ret_type is Enum || ret_type is Flags) { - ccheck.add_argument (new CCodeConstant (name = "0")); - } else { - Report.error (method_node.source_reference, "not supported return type for runtime type checks"); - return null; - } + var base_type = new TypeReference (); + base_type.type = (DataType) m.base_method.symbol.parent_symbol.node; + var cparam = new CCodeFormalParameter (type_name = base_type.get_cname (), name = "base"); + function.add_parameter (cparam); } - - return new CCodeExpressionStatement (expression = ccheck); - } + if (m.is_abstract || m.is_virtual) { + var vdecl = new CCodeDeclaration (type_name = m.return_type.get_cname ()); + vdeclarator = new CCodeFunctionDeclarator (name = m.name); + vdecl.add_declarator (vdeclarator); + type_struct.add_declaration (vdecl); - private DataType find_parent_type (CodeNode node) { - var sym = node.symbol; - while (sym != null) { - if (sym.node is DataType) { - return (DataType) sym.node; - } - sym = sym.parent_symbol; + var cparam = new CCodeFormalParameter (type_name = this_type.get_cname (), name = "self"); + vdeclarator.add_parameter (cparam); } - return null; } - - public override void visit_end_method (Method! m) { - current_symbol = current_symbol.parent_symbol; - - if (m.name == "init") { - return; + + var params = m.get_parameters (); + foreach (FormalParameter param in params) { + function.add_parameter ((CCodeFormalParameter) param.ccodenode); + if (vdeclarator != null) { + vdeclarator.add_parameter ((CCodeFormalParameter) param.ccodenode); } + } - function = new CCodeFunction (name = m.get_real_cname (), return_type = m.return_type.get_cname ()); - CCodeFunctionDeclarator vdeclarator = null; - - if (m.instance) { - var this_type = new TypeReference (); - this_type.type = find_parent_type (m); - if (!m.is_override) { - var cparam = new CCodeFormalParameter (type_name = this_type.get_cname (), name = "self"); - function.add_parameter (cparam); - } else { - var base_type = new TypeReference (); - base_type.type = (DataType) m.base_method.symbol.parent_symbol.node; - var cparam = new CCodeFormalParameter (type_name = base_type.get_cname (), name = "base"); - function.add_parameter (cparam); + /* real function declaration and definition not needed + * for abstract methods */ + if (!m.is_abstract) { + if (m.access == MemberAccessibility.PUBLIC && !(m.is_virtual || m.is_override)) { + /* public methods need function declaration in + * header file except virtual/overridden methods */ + header_type_member_declaration.append (function.copy ()); + } else { + /* declare all other functions in source file to + * avoid dependency on order within source file */ + function.modifiers |= CCodeModifiers.STATIC; + source_type_member_declaration.append (function.copy ()); + } + + /* Methods imported from a plain C file don't + * have a body, e.g. Vala.Parser.parse_file () */ + if (m.body != null) { + function.block = (CCodeBlock) m.body.ccodenode; + + var cinit = new CCodeFragment (); + function.block.prepend_statement (cinit); + + if (m.symbol.parent_symbol.node is Class) { + var cl = (Class) m.symbol.parent_symbol.node; + if (m.is_override) { + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = cl.get_upper_case_cname (null))); + ccall.add_argument (new CCodeIdentifier (name = "base")); + + var cdecl = new CCodeDeclaration (type_name = "%s *".printf (cl.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator (name = "self", initializer = ccall)); + + cinit.append (cdecl); + } else if (m.instance) { + 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_method_type_check_statement (m, t, param.type_reference.non_null, param.name)); + } } - if (m.is_abstract || m.is_virtual) { - var vdecl = new CCodeDeclaration (type_name = m.return_type.get_cname ()); - vdeclarator = new CCodeFunctionDeclarator (name = m.name); - vdecl.add_declarator (vdeclarator); - type_struct.add_declaration (vdecl); - - var cparam = new CCodeFormalParameter (type_name = this_type.get_cname (), name = "self"); - vdeclarator.add_parameter (cparam); + + if (m.source_reference != null && m.source_reference.comment != null) { + source_type_member_definition.append (new CCodeComment (text = m.source_reference.comment)); } + source_type_member_definition.append (function); } - - var params = m.get_parameters (); - foreach (FormalParameter param in params) { - function.add_parameter ((CCodeFormalParameter) param.ccodenode); - if (vdeclarator != null) { - vdeclarator.add_parameter ((CCodeFormalParameter) param.ccodenode); - } - } - - /* real function declaration and definition not needed - * for abstract methods */ - if (!m.is_abstract) { - if (m.access == MemberAccessibility.PUBLIC && !(m.is_virtual || m.is_override)) { - /* public methods need function declaration in - * header file except virtual/overridden methods */ - header_type_member_declaration.append (function.copy ()); - } else { - /* declare all other functions in source file to - * avoid dependency on order within source file */ - function.modifiers |= CCodeModifiers.STATIC; - source_type_member_declaration.append (function.copy ()); - } - - /* Methods imported from a plain C file don't - * have a body, e.g. Vala.Parser.parse_file () */ - if (m.body != null) { - function.block = (CCodeBlock) m.body.ccodenode; - - var cinit = new CCodeFragment (); - function.block.prepend_statement (cinit); - - if (m.symbol.parent_symbol.node is Class) { - var cl = (Class) m.symbol.parent_symbol.node; - if (m.is_override) { - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = cl.get_upper_case_cname (null))); - ccall.add_argument (new CCodeIdentifier (name = "base")); - - var cdecl = new CCodeDeclaration (type_name = "%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator (name = "self", initializer = ccall)); - - cinit.append (cdecl); - } else if (m.instance) { - 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_method_type_check_statement (m, t, param.type_reference.non_null, param.name)); - } - } - - if (m.source_reference != null && 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.is_abstract || m.is_virtual) { - var cl = (Class) m.symbol.parent_symbol.node; + } + + if (m.is_abstract || m.is_virtual) { + var cl = (Class) m.symbol.parent_symbol.node; - var vfunc = new CCodeFunction (name = m.get_cname (), return_type = m.return_type.get_cname ()); + var vfunc = new CCodeFunction (name = m.get_cname (), return_type = m.return_type.get_cname ()); - var this_type = new TypeReference (); - this_type.type = (DataType) m.symbol.parent_symbol.node; + var this_type = new TypeReference (); + this_type.type = (DataType) m.symbol.parent_symbol.node; - var cparam = new CCodeFormalParameter (type_name = this_type.get_cname (), name = "self"); - vfunc.add_parameter (cparam); - - var vblock = new CCodeBlock (); - - var vcast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_GET_CLASS".printf (cl.get_upper_case_cname (null)))); - vcast.add_argument (new CCodeIdentifier (name = "self")); + var cparam = new CCodeFormalParameter (type_name = this_type.get_cname (), name = "self"); + vfunc.add_parameter (cparam); - var vcall = new CCodeFunctionCall (call = new CCodeMemberAccess (inner = vcast, member_name = m.name, is_pointer = true)); - vcall.add_argument (new CCodeIdentifier (name = "self")); + var vblock = new CCodeBlock (); - var params = m.get_parameters (); - foreach (FormalParameter param in params) { - vfunc.add_parameter ((CCodeFormalParameter) param.ccodenode); - vcall.add_argument (new CCodeIdentifier (name = param.name)); - } + var vcast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_GET_CLASS".printf (cl.get_upper_case_cname (null)))); + vcast.add_argument (new CCodeIdentifier (name = "self")); + + var vcall = new CCodeFunctionCall (call = new CCodeMemberAccess (inner = vcast, member_name = m.name, is_pointer = true)); + vcall.add_argument (new CCodeIdentifier (name = "self")); + + var params = m.get_parameters (); + foreach (FormalParameter param in params) { + vfunc.add_parameter ((CCodeFormalParameter) param.ccodenode); + vcall.add_argument (new CCodeIdentifier (name = param.name)); + } - vblock.add_statement (new CCodeExpressionStatement (expression = vcall)); + vblock.add_statement (new CCodeExpressionStatement (expression = vcall)); - header_type_member_declaration.append (vfunc.copy ()); - - vfunc.block = vblock; - - source_type_member_definition.append (vfunc); - } + header_type_member_declaration.append (vfunc.copy ()); - if (m.name == "main") { - 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); - } + vfunc.block = vblock; + + source_type_member_definition.append (vfunc); } - public override void visit_formal_parameter (FormalParameter! p) { - if (!p.ellipsis) { - p.ccodenode = new CCodeFormalParameter (type_name = p.type_reference.get_cname (), name = p.name); - } + if (m.name == "main") { + 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_end_property (Property! prop) { - prop_enum.add_value (prop.get_upper_case_cname (), null); + } + + public override void visit_formal_parameter (FormalParameter! p) { + if (!p.ellipsis) { + p.ccodenode = new CCodeFormalParameter (type_name = p.type_reference.get_cname (), name = p.name); } + } - 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 = (CCodeBlock) acc.body.ccodenode; + public override void visit_end_property (Property! prop) { + prop_enum.add_value (prop.get_upper_case_cname (), null); + } - 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_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")); } - public override void visit_end_constructor (Constructor! c) { - var cl = (Class) c.symbol.parent_symbol.node; + header_type_member_declaration.append (function.copy ()); - function = new CCodeFunction (name = "%s_constructor".printf (cl.get_lower_case_cname (null)), return_type = "GObject *"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeFormalParameter (name = "type", type_name = "GType")); - function.add_parameter (new CCodeFormalParameter (name = "n_construct_properties", type_name = "guint")); - function.add_parameter (new CCodeFormalParameter (name = "construct_properties", type_name = "GObjectConstructParam *")); - - source_type_member_declaration.append (function.copy ()); + 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_end_constructor (Constructor! c) { + var cl = (Class) c.symbol.parent_symbol.node; + + function = new CCodeFunction (name = "%s_constructor".printf (cl.get_lower_case_cname (null)), return_type = "GObject *"); + function.modifiers = CCodeModifiers.STATIC; + + function.add_parameter (new CCodeFormalParameter (name = "type", type_name = "GType")); + function.add_parameter (new CCodeFormalParameter (name = "n_construct_properties", type_name = "guint")); + function.add_parameter (new CCodeFormalParameter (name = "construct_properties", type_name = "GObjectConstructParam *")); + + source_type_member_declaration.append (function.copy ()); - var cblock = new CCodeBlock (); - var cdecl = new CCodeDeclaration (type_name = "GObject *"); - cdecl.add_declarator (new CCodeVariableDeclarator (name = "obj")); - cblock.add_statement (cdecl); - cdecl = new CCodeDeclaration (type_name = "%sClass *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator (name = "klass")); - cblock.add_statement (cdecl); + var cblock = new CCodeBlock (); + var cdecl = new CCodeDeclaration (type_name = "GObject *"); + cdecl.add_declarator (new CCodeVariableDeclarator (name = "obj")); + cblock.add_statement (cdecl); - cdecl = new CCodeDeclaration (type_name = "GObjectClass *"); - cdecl.add_declarator (new CCodeVariableDeclarator (name = "parent_class")); - cblock.add_statement (cdecl); - - - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_type_class_peek")); - ccall.add_argument (new CCodeIdentifier (name = cl.get_upper_case_cname ("TYPE_"))); - var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_CLASS".printf (cl.get_upper_case_cname (null)))); - ccast.add_argument (ccall); - cblock.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeIdentifier (name = "klass"), right = ccast))); + cdecl = new CCodeDeclaration (type_name = "%sClass *".printf (cl.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator (name = "klass")); + cblock.add_statement (cdecl); - ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_type_class_peek_parent")); - ccall.add_argument (new CCodeIdentifier (name = "klass")); - ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "G_OBJECT_CLASS")); - ccast.add_argument (ccall); - cblock.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeIdentifier (name = "parent_class"), right = ccast))); + cdecl = new CCodeDeclaration (type_name = "GObjectClass *"); + cdecl.add_declarator (new CCodeVariableDeclarator (name = "parent_class")); + cblock.add_statement (cdecl); - - ccall = new CCodeFunctionCall (call = new CCodeMemberAccess (inner = new CCodeIdentifier (name = "parent_class"), member_name = "constructor", is_pointer = true)); - ccall.add_argument (new CCodeIdentifier (name = "type")); - ccall.add_argument (new CCodeIdentifier (name = "n_construct_properties")); - ccall.add_argument (new CCodeIdentifier (name = "construct_properties")); - cblock.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeIdentifier (name = "obj"), right = ccall))); + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_type_class_peek")); + ccall.add_argument (new CCodeIdentifier (name = cl.get_upper_case_cname ("TYPE_"))); + var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_CLASS".printf (cl.get_upper_case_cname (null)))); + ccast.add_argument (ccall); + cblock.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeIdentifier (name = "klass"), right = ccast))); - ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = cl.get_upper_case_cname (null))); - ccall.add_argument (new CCodeIdentifier (name = "obj")); - - cdecl = new CCodeDeclaration (type_name = "%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator (name = "self", initializer = ccall)); - - cblock.add_statement (cdecl); + ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_type_class_peek_parent")); + ccall.add_argument (new CCodeIdentifier (name = "klass")); + ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "G_OBJECT_CLASS")); + ccast.add_argument (ccall); + cblock.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeIdentifier (name = "parent_class"), right = ccast))); + + ccall = new CCodeFunctionCall (call = new CCodeMemberAccess (inner = new CCodeIdentifier (name = "parent_class"), member_name = "constructor", is_pointer = true)); + ccall.add_argument (new CCodeIdentifier (name = "type")); + ccall.add_argument (new CCodeIdentifier (name = "n_construct_properties")); + ccall.add_argument (new CCodeIdentifier (name = "construct_properties")); + cblock.add_statement (new CCodeExpressionStatement (expression = new CCodeAssignment (left = new CCodeIdentifier (name = "obj"), right = ccall))); - cblock.add_statement (c.body.ccodenode); - - cblock.add_statement (new CCodeReturnStatement (return_expression = new CCodeIdentifier (name = "obj"))); - - function.block = cblock; - if (c.source_reference.comment != null) { - source_type_member_definition.append (new CCodeComment (text = c.source_reference.comment)); - } - source_type_member_definition.append (function); - } + ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = cl.get_upper_case_cname (null))); + ccall.add_argument (new CCodeIdentifier (name = "obj")); + + cdecl = new CCodeDeclaration (type_name = "%s *".printf (cl.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator (name = "self", initializer = ccall)); + + cblock.add_statement (cdecl); - public override void visit_begin_block (Block! b) { - current_symbol = b.symbol; + + cblock.add_statement (c.body.ccodenode); + + cblock.add_statement (new CCodeReturnStatement (return_expression = new CCodeIdentifier (name = "obj"))); + + function.block = cblock; + + if (c.source_reference.comment != null) { + source_type_member_definition.append (new CCodeComment (text = c.source_reference.comment)); } + source_type_member_definition.append (function); + } - public override void visit_end_block (Block! b) { - var local_vars = b.get_local_variables (); - foreach (VariableDeclarator decl in local_vars) { - decl.symbol.active = false; - } + public override void visit_begin_block (Block! b) { + current_symbol = b.symbol; + } + + public override void visit_end_block (Block! b) { + var local_vars = b.get_local_variables (); + foreach (VariableDeclarator decl in local_vars) { + decl.symbol.active = false; + } + + var cblock = new CCodeBlock (); - var cblock = new CCodeBlock (); + foreach (Statement stmt in b.get_statements ()) { + var src = stmt.source_reference; + if (src != null && src.comment != null) { + cblock.add_statement (new CCodeComment (text = src.comment)); + } - foreach (Statement stmt in b.get_statements ()) { - var src = stmt.source_reference; - if (src != null && src.comment != null) { - cblock.add_statement (new CCodeComment (text = src.comment)); - } - - if (stmt.ccodenode is CCodeFragment) { - foreach (CCodeStatement cstmt in ((CCodeFragment) stmt.ccodenode).children) { - cblock.add_statement (cstmt); - } - } else { - cblock.add_statement ((CCodeStatement) stmt.ccodenode); + if (stmt.ccodenode is CCodeFragment) { + foreach (CCodeStatement cstmt in ((CCodeFragment) stmt.ccodenode).children) { + cblock.add_statement (cstmt); } + } else { + cblock.add_statement ((CCodeStatement) stmt.ccodenode); } - - if (memory_management) { - foreach (VariableDeclarator decl in local_vars) { - if (decl.type_reference.type.is_reference_type () && decl.type_reference.is_lvalue_ref) { - cblock.add_statement (new CCodeExpressionStatement (expression = get_unref_expression (new CCodeIdentifier (name = decl.name), decl.type_reference))); - } + } + + if (memory_management) { + foreach (VariableDeclarator decl in local_vars) { + if (decl.type_reference.type.is_reference_type () && decl.type_reference.is_lvalue_ref) { + cblock.add_statement (new CCodeExpressionStatement (expression = get_unref_expression (new CCodeIdentifier (name = decl.name), decl.type_reference))); } } - - b.ccodenode = cblock; - - current_symbol = current_symbol.parent_symbol; } + + b.ccodenode = cblock; - public override void visit_empty_statement (EmptyStatement! stmt) { - stmt.ccodenode = new CCodeEmptyStatement (); - } + current_symbol = current_symbol.parent_symbol; + } - public override void visit_declaration_statement (DeclarationStatement! stmt) { - /* split declaration statement as var declarators - * might have different types */ - - var cfrag = new CCodeFragment (); - - foreach (VariableDeclarator decl in stmt.declaration.variable_declarators) { - var cdecl = new CCodeDeclaration (type_name = decl.type_reference.get_cname ()); - - cdecl.add_declarator ((CCodeVariableDeclarator) decl.ccodenode); + public override void visit_empty_statement (EmptyStatement! stmt) { + stmt.ccodenode = new CCodeEmptyStatement (); + } - cfrag.append (cdecl); - } - - stmt.ccodenode = cfrag; + public override void visit_declaration_statement (DeclarationStatement! stmt) { + /* split declaration statement as var declarators + * might have different types */ + + var cfrag = new CCodeFragment (); + + foreach (VariableDeclarator decl in stmt.declaration.variable_declarators) { + var cdecl = new CCodeDeclaration (type_name = decl.type_reference.get_cname ()); + + cdecl.add_declarator ((CCodeVariableDeclarator) decl.ccodenode); - foreach (VariableDeclarator decl in stmt.declaration.variable_declarators) { - if (decl.initializer != null) { - create_temp_decl (stmt, decl.initializer.temp_vars); - } - } + cfrag.append (cdecl); } + + stmt.ccodenode = cfrag; - public override void visit_variable_declarator (VariableDeclarator! decl) { - CCodeExpression rhs = null; + foreach (VariableDeclarator decl in stmt.declaration.variable_declarators) { if (decl.initializer != null) { - rhs = (CCodeExpression) decl.initializer.ccodenode; - - if (decl.type_reference.type != null - && decl.initializer.static_type.type != null - && decl.type_reference.type.is_reference_type () - && decl.initializer.static_type.type != decl.type_reference.type) { - rhs = new InstanceCast (type_reference = decl.type_reference.type, inner = rhs); - } - } else if (decl.type_reference.type != null && decl.type_reference.type.is_reference_type ()) { - rhs = new CCodeConstant (name = "NULL"); + create_temp_decl (stmt, decl.initializer.temp_vars); } - - decl.ccodenode = new CCodeVariableDeclarator (name = decl.name, initializer = rhs); - - decl.symbol.active = true; } + } - public override void visit_initializer_list (InitializerList! list) { - var clist = new CCodeInitializerList (); - foreach (Expression expr in list.initializers) { - clist.append ((CCodeExpression) expr.ccodenode); + public override void visit_variable_declarator (VariableDeclarator! decl) { + CCodeExpression rhs = null; + if (decl.initializer != null) { + rhs = (CCodeExpression) decl.initializer.ccodenode; + + if (decl.type_reference.type != null + && decl.initializer.static_type.type != null + && decl.type_reference.type.is_reference_type () + && decl.initializer.static_type.type != decl.type_reference.type) { + rhs = new InstanceCast (type_reference = decl.type_reference.type, inner = rhs); } - list.ccodenode = clist; + } else if (decl.type_reference.type != null && decl.type_reference.type.is_reference_type ()) { + rhs = new CCodeConstant (name = "NULL"); } - - private ref VariableDeclarator get_temp_variable_declarator (TypeReference! type) { - var decl = new VariableDeclarator (name = "__temp%d".printf (next_temp_var_id)); - decl.type_reference = type.copy (); - decl.type_reference.is_ref = false; - decl.type_reference.is_out = false; - - next_temp_var_id++; - return decl; + decl.ccodenode = new CCodeVariableDeclarator (name = decl.name, initializer = rhs); + + decl.symbol.active = true; + } + + public override void visit_initializer_list (InitializerList! list) { + var clist = new CCodeInitializerList (); + foreach (Expression expr in list.initializers) { + clist.append ((CCodeExpression) expr.ccodenode); } + list.ccodenode = clist; + } + + private ref VariableDeclarator get_temp_variable_declarator (TypeReference! type) { + var decl = new VariableDeclarator (name = "__temp%d".printf (next_temp_var_id)); + decl.type_reference = type.copy (); + decl.type_reference.is_ref = false; + decl.type_reference.is_out = false; - private ref CCodeExpression get_unref_expression (CCodeExpression! cvar, TypeReference! type) { - /* (foo == NULL ? NULL : foo = (unref (foo), NULL)) */ - - /* can be simplified to - * foo = (unref (foo), NULL) - * if foo is of static type non-null - */ + next_temp_var_id++; + + return decl; + } + + private ref CCodeExpression get_unref_expression (CCodeExpression! cvar, TypeReference! type) { + /* (foo == NULL ? NULL : foo = (unref (foo), NULL)) */ + + /* can be simplified to + * foo = (unref (foo), NULL) + * if foo is of static type non-null + */ - var cisnull = new CCodeBinaryExpression (operator = CCodeBinaryOperator.EQUALITY, left = cvar, right = new CCodeConstant (name = "NULL")); + var cisnull = new CCodeBinaryExpression (operator = CCodeBinaryOperator.EQUALITY, left = cvar, right = new CCodeConstant (name = "NULL")); - string unref_function; - if (type.type.is_reference_counting ()) { - unref_function = type.type.get_unref_function (); - } else { - unref_function = type.type.get_free_function (); - } + string unref_function; + if (type.type.is_reference_counting ()) { + unref_function = type.type.get_unref_function (); + } else { + unref_function = type.type.get_free_function (); + } + + if (type.array && type.type.name == "string") { + unref_function = "g_strfreev"; + } + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = unref_function)); + ccall.add_argument (cvar); - if (type.array && type.type.name == "string") { - unref_function = "g_strfreev"; - } - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = unref_function)); - ccall.add_argument (cvar); - - /* set freed references to NULL to prevent further use */ - var ccomma = new CCodeCommaExpression (); - - if (unref_function == "g_list_free") { - bool is_ref = false; - bool is_class = false; - var type_args = type.get_type_arguments (); - foreach (TypeReference type_arg in type_args) { - is_ref = type_arg.is_ref; - is_class = type_arg.type is Class; - } - - if (is_ref) { - var cunrefcall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_list_foreach")); - cunrefcall.add_argument (cvar); - if (is_class) { - cunrefcall.add_argument (new CCodeIdentifier (name = "(GFunc) g_object_unref")); - } else { - cunrefcall.add_argument (new CCodeIdentifier (name = "(GFunc) g_free")); - } - cunrefcall.add_argument (new CCodeConstant (name = "NULL")); - ccomma.inner.append (cunrefcall); + /* set freed references to NULL to prevent further use */ + var ccomma = new CCodeCommaExpression (); + + if (unref_function == "g_list_free") { + bool is_ref = false; + bool is_class = false; + var type_args = type.get_type_arguments (); + foreach (TypeReference type_arg in type_args) { + is_ref = type_arg.is_ref; + is_class = type_arg.type is Class; + } + + if (is_ref) { + var cunrefcall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_list_foreach")); + cunrefcall.add_argument (cvar); + if (is_class) { + cunrefcall.add_argument (new CCodeIdentifier (name = "(GFunc) g_object_unref")); + } else { + cunrefcall.add_argument (new CCodeIdentifier (name = "(GFunc) g_free")); } - } else if (unref_function == "g_string_free") { - ccall.add_argument (new CCodeConstant (name = "TRUE")); + cunrefcall.add_argument (new CCodeConstant (name = "NULL")); + ccomma.inner.append (cunrefcall); } - - ccomma.inner.append (ccall); - ccomma.inner.append (new CCodeConstant (name = "NULL")); - - var cassign = new CCodeAssignment (left = cvar, right = ccomma); - - return new CCodeConditionalExpression (condition = cisnull, true_expression = new CCodeConstant (name = "NULL"), false_expression = new CCodeParenthesizedExpression (inner = cassign)); + } else if (unref_function == "g_string_free") { + ccall.add_argument (new CCodeConstant (name = "TRUE")); } - public override void visit_end_full_expression (Expression! expr) { - if (!memory_management) { - temp_vars = null; - temp_ref_vars = null; - return; - } + ccomma.inner.append (ccall); + ccomma.inner.append (new CCodeConstant (name = "NULL")); - /* expr is a full expression, i.e. an initializer, the - * expression in an expression statement, the controlling - * expression in if, while, for, or foreach statements - * - * we unref temporary variables at the end of a full - * expression - */ - - /* can't automatically deep copy lists yet, so do it - * manually for now - * replace with - * expr.temp_vars = temp_vars; - * when deep list copying works - */ - expr.temp_vars = null; - foreach (VariableDeclarator decl1 in temp_vars) { - expr.temp_vars.append (decl1); - } + var cassign = new CCodeAssignment (left = cvar, right = ccomma); + + return new CCodeConditionalExpression (condition = cisnull, true_expression = new CCodeConstant (name = "NULL"), false_expression = new CCodeParenthesizedExpression (inner = cassign)); + } + + public override void visit_end_full_expression (Expression! expr) { + if (!memory_management) { temp_vars = null; - - if (temp_ref_vars == null) { - /* nothing to do without temporary variables */ - return; - } - - var full_expr_decl = get_temp_variable_declarator (expr.static_type); - expr.temp_vars.append (full_expr_decl); - - var expr_list = new CCodeCommaExpression (); - expr_list.inner.append (new CCodeAssignment (left = new CCodeIdentifier (name = full_expr_decl.name), right = expr.ccodenode)); - - foreach (VariableDeclarator decl in temp_ref_vars) { - expr_list.inner.append (get_unref_expression (new CCodeIdentifier (name = decl.name), decl.type_reference)); - } - - expr_list.inner.append (new CCodeIdentifier (name = full_expr_decl.name)); - - expr.ccodenode = expr_list; - temp_ref_vars = null; + return; + } + + /* expr is a full expression, i.e. an initializer, the + * expression in an expression statement, the controlling + * expression in if, while, for, or foreach statements + * + * we unref temporary variables at the end of a full + * expression + */ + + /* can't automatically deep copy lists yet, so do it + * manually for now + * replace with + * expr.temp_vars = temp_vars; + * when deep list copying works + */ + expr.temp_vars = null; + foreach (VariableDeclarator decl1 in temp_vars) { + expr.temp_vars.append (decl1); + } + temp_vars = null; + + if (temp_ref_vars == null) { + /* nothing to do without temporary variables */ + return; + } + + var full_expr_decl = get_temp_variable_declarator (expr.static_type); + expr.temp_vars.append (full_expr_decl); + + var expr_list = new CCodeCommaExpression (); + expr_list.inner.append (new CCodeAssignment (left = new CCodeIdentifier (name = full_expr_decl.name), right = expr.ccodenode)); + + foreach (VariableDeclarator decl in temp_ref_vars) { + expr_list.inner.append (get_unref_expression (new CCodeIdentifier (name = decl.name), decl.type_reference)); } - private void append_temp_decl (CCodeFragment! cfrag, List temp_vars) { - foreach (VariableDeclarator decl in temp_vars) { - var cdecl = new CCodeDeclaration (type_name = decl.type_reference.get_cname (true)); + expr_list.inner.append (new CCodeIdentifier (name = full_expr_decl.name)); + + expr.ccodenode = expr_list; + + temp_ref_vars = null; + } + + private void append_temp_decl (CCodeFragment! cfrag, List temp_vars) { + foreach (VariableDeclarator decl in temp_vars) { + var cdecl = new CCodeDeclaration (type_name = decl.type_reference.get_cname (true)); + + cdecl.add_declarator (new CCodeVariableDeclarator (name = decl.name)); - cdecl.add_declarator (new CCodeVariableDeclarator (name = decl.name)); - - cfrag.append (cdecl); - } + cfrag.append (cdecl); } + } - public override void visit_expression_statement (ExpressionStatement! stmt) { - stmt.ccodenode = new CCodeExpressionStatement (expression = (CCodeExpression) stmt.expression.ccodenode); - - /* free temporary objects */ - if (!memory_management) { - temp_vars = null; - temp_ref_vars = null; - return; - } - - if (temp_vars == null) { - /* nothing to do without temporary variables */ - return; - } - - var cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - - cfrag.append (stmt.ccodenode); - - foreach (VariableDeclarator decl in temp_ref_vars) { - cfrag.append (new CCodeExpressionStatement (expression = get_unref_expression (new CCodeIdentifier (name = decl.name), decl.type_reference))); - } - - stmt.ccodenode = cfrag; - + public override void visit_expression_statement (ExpressionStatement! stmt) { + stmt.ccodenode = new CCodeExpressionStatement (expression = (CCodeExpression) stmt.expression.ccodenode); + + /* free temporary objects */ + if (!memory_management) { temp_vars = null; temp_ref_vars = null; + return; } - private void create_temp_decl (Statement! stmt, List temp_vars) { - /* declare temporary variables */ - - if (temp_vars == null) { - /* nothing to do without temporary variables */ - return; - } - - var cfrag = new CCodeFragment (); - append_temp_decl (cfrag, temp_vars); - - cfrag.append (stmt.ccodenode); - - stmt.ccodenode = cfrag; + if (temp_vars == null) { + /* nothing to do without temporary variables */ + return; + } + + var cfrag = new CCodeFragment (); + append_temp_decl (cfrag, temp_vars); + + cfrag.append (stmt.ccodenode); + + foreach (VariableDeclarator decl in temp_ref_vars) { + cfrag.append (new CCodeExpressionStatement (expression = get_unref_expression (new CCodeIdentifier (name = decl.name), decl.type_reference))); + } + + stmt.ccodenode = cfrag; + + temp_vars = null; + temp_ref_vars = null; + } + + private void create_temp_decl (Statement! stmt, List temp_vars) { + /* declare temporary variables */ + + if (temp_vars == null) { + /* nothing to do without temporary variables */ + return; } + + var cfrag = new CCodeFragment (); + append_temp_decl (cfrag, temp_vars); + + cfrag.append (stmt.ccodenode); + + stmt.ccodenode = cfrag; + } - public override void visit_if_statement (IfStatement! stmt) { - if (stmt.false_statement != null) { - stmt.ccodenode = new CCodeIfStatement (condition = (CCodeExpression) stmt.condition.ccodenode, true_statement = (CCodeStatement) stmt.true_statement.ccodenode, false_statement = (CCodeStatement) stmt.false_statement.ccodenode); - } else { - stmt.ccodenode = new CCodeIfStatement (condition = (CCodeExpression) stmt.condition.ccodenode, true_statement = (CCodeStatement) stmt.true_statement.ccodenode); - } - - create_temp_decl (stmt, stmt.condition.temp_vars); + public override void visit_if_statement (IfStatement! stmt) { + if (stmt.false_statement != null) { + stmt.ccodenode = new CCodeIfStatement (condition = (CCodeExpression) stmt.condition.ccodenode, true_statement = (CCodeStatement) stmt.true_statement.ccodenode, false_statement = (CCodeStatement) stmt.false_statement.ccodenode); + } else { + stmt.ccodenode = new CCodeIfStatement (condition = (CCodeExpression) stmt.condition.ccodenode, true_statement = (CCodeStatement) stmt.true_statement.ccodenode); } + + create_temp_decl (stmt, stmt.condition.temp_vars); + } - public override void visit_while_statement (WhileStatement! stmt) { - stmt.ccodenode = new CCodeWhileStatement (condition = (CCodeExpression) stmt.condition.ccodenode, body = (CCodeStatement) stmt.body.ccodenode); - - create_temp_decl (stmt, stmt.condition.temp_vars); + public override void visit_while_statement (WhileStatement! stmt) { + stmt.ccodenode = new CCodeWhileStatement (condition = (CCodeExpression) stmt.condition.ccodenode, body = (CCodeStatement) stmt.body.ccodenode); + + create_temp_decl (stmt, stmt.condition.temp_vars); + } + + public override void visit_for_statement (ForStatement! stmt) { + var cfor = new CCodeForStatement (condition = (CCodeExpression) stmt.condition.ccodenode, body = (CCodeStatement) stmt.body.ccodenode); + + foreach (Expression init_expr in stmt.initializer) { + cfor.add_initializer ((CCodeExpression) init_expr.ccodenode); } + + foreach (Expression it_expr in stmt.iterator) { + cfor.add_iterator ((CCodeExpression) it_expr.ccodenode); + } + + stmt.ccodenode = cfor; + + create_temp_decl (stmt, stmt.condition.temp_vars); + } - public override void visit_for_statement (ForStatement! stmt) { - var cfor = new CCodeForStatement (condition = (CCodeExpression) stmt.condition.ccodenode, body = (CCodeStatement) stmt.body.ccodenode); + public override void visit_end_foreach_statement (ForeachStatement! stmt) { + var cblock = new CCodeBlock (); + + if (stmt.collection.static_type.array) { + var it_name = "%s_it".printf (stmt.variable_name); + + var citdecl = new CCodeDeclaration (type_name = stmt.collection.static_type.get_cname ()); + citdecl.add_declarator (new CCodeVariableDeclarator (name = it_name)); + cblock.add_statement (citdecl); - foreach (Expression init_expr in stmt.initializer) { - cfor.add_initializer ((CCodeExpression) init_expr.ccodenode); - } + var cbody = new CCodeBlock (); - foreach (Expression it_expr in stmt.iterator) { - cfor.add_iterator ((CCodeExpression) it_expr.ccodenode); - } + var cdecl = new CCodeDeclaration (type_name = stmt.type_reference.get_cname ()); + cdecl.add_declarator (new CCodeVariableDeclarator (name = stmt.variable_name, initializer = new CCodeIdentifier (name = "*%s".printf (it_name)))); + cbody.add_statement (cdecl); - stmt.ccodenode = cfor; + cbody.add_statement (stmt.body.ccodenode); - create_temp_decl (stmt, stmt.condition.temp_vars); - } - - public override void visit_end_foreach_statement (ForeachStatement! stmt) { - var cblock = new CCodeBlock (); + var ccond = new CCodeBinaryExpression (operator = CCodeBinaryOperator.INEQUALITY, left = new CCodeIdentifier (name = "*%s".printf (it_name)), right = new CCodeConstant (name = "NULL")); - if (stmt.collection.static_type.array) { - var it_name = "%s_it".printf (stmt.variable_name); + var cfor = new CCodeForStatement (condition = ccond, body = cbody); + cfor.add_initializer (new CCodeAssignment (left = new CCodeIdentifier (name = it_name), right = (CCodeExpression) stmt.collection.ccodenode)); + cfor.add_iterator (new CCodeAssignment (left = new CCodeIdentifier (name = it_name), right = new CCodeBinaryExpression (operator = CCodeBinaryOperator.PLUS, left = new CCodeIdentifier (name = it_name), right = new CCodeConstant (name = "1")))); + cblock.add_statement (cfor); + } else if (stmt.collection.static_type.type.name == "List") { + var it_name = "%s_it".printf (stmt.variable_name); + + var citdecl = new CCodeDeclaration (type_name = "GList *"); + citdecl.add_declarator (new CCodeVariableDeclarator (name = it_name)); + cblock.add_statement (citdecl); - var citdecl = new CCodeDeclaration (type_name = stmt.collection.static_type.get_cname ()); - citdecl.add_declarator (new CCodeVariableDeclarator (name = it_name)); - cblock.add_statement (citdecl); - - var cbody = new CCodeBlock (); - - var cdecl = new CCodeDeclaration (type_name = stmt.type_reference.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator (name = stmt.variable_name, initializer = new CCodeIdentifier (name = "*%s".printf (it_name)))); - cbody.add_statement (cdecl); - - cbody.add_statement (stmt.body.ccodenode); - - var ccond = new CCodeBinaryExpression (operator = CCodeBinaryOperator.INEQUALITY, left = new CCodeIdentifier (name = "*%s".printf (it_name)), right = new CCodeConstant (name = "NULL")); - - var cfor = new CCodeForStatement (condition = ccond, body = cbody); - cfor.add_initializer (new CCodeAssignment (left = new CCodeIdentifier (name = it_name), right = (CCodeExpression) stmt.collection.ccodenode)); - cfor.add_iterator (new CCodeAssignment (left = new CCodeIdentifier (name = it_name), right = new CCodeBinaryExpression (operator = CCodeBinaryOperator.PLUS, left = new CCodeIdentifier (name = it_name), right = new CCodeConstant (name = "1")))); - cblock.add_statement (cfor); - } else if (stmt.collection.static_type.type.name == "List") { - var it_name = "%s_it".printf (stmt.variable_name); + var cbody = new CCodeBlock (); - var citdecl = new CCodeDeclaration (type_name = "GList *"); - citdecl.add_declarator (new CCodeVariableDeclarator (name = it_name)); - cblock.add_statement (citdecl); - - var cbody = new CCodeBlock (); - - var cdecl = new CCodeDeclaration (type_name = stmt.type_reference.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator (name = stmt.variable_name, initializer = new CCodeMemberAccess (inner = new CCodeIdentifier (name = it_name), member_name = "data", is_pointer = true))); - cbody.add_statement (cdecl); - - cbody.add_statement (stmt.body.ccodenode); - - var ccond = new CCodeBinaryExpression (operator = CCodeBinaryOperator.INEQUALITY, left = new CCodeIdentifier (name = it_name), right = new CCodeConstant (name = "NULL")); - - var cfor = new CCodeForStatement (condition = ccond, body = cbody); - cfor.add_initializer (new CCodeAssignment (left = new CCodeIdentifier (name = it_name), right = (CCodeExpression) stmt.collection.ccodenode)); - cfor.add_iterator (new CCodeAssignment (left = new CCodeIdentifier (name = it_name), right = new CCodeMemberAccess (inner = new CCodeIdentifier (name = it_name), member_name = "next", is_pointer = true))); - cblock.add_statement (cfor); - } + var cdecl = new CCodeDeclaration (type_name = stmt.type_reference.get_cname ()); + cdecl.add_declarator (new CCodeVariableDeclarator (name = stmt.variable_name, initializer = new CCodeMemberAccess (inner = new CCodeIdentifier (name = it_name), member_name = "data", is_pointer = true))); + cbody.add_statement (cdecl); - stmt.ccodenode = cblock; - } - - public override void visit_break_statement (BreakStatement! stmt) { - stmt.ccodenode = new CCodeBreakStatement (); - } - - public override void visit_continue_statement (ContinueStatement! stmt) { - stmt.ccodenode = new CCodeContinueStatement (); - } - - private void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop) { - var b = (Block) sym.node; - - var local_vars = b.get_local_variables (); - foreach (VariableDeclarator decl in local_vars) { - if (decl.symbol.active && decl.type_reference.type.is_reference_type () && decl.type_reference.is_lvalue_ref) { - cfrag.append (new CCodeExpressionStatement (expression = get_unref_expression (new CCodeIdentifier (name = decl.name), decl.type_reference))); - } - } + cbody.add_statement (stmt.body.ccodenode); - if (sym.parent_symbol.node is Block) { - append_local_free (sym.parent_symbol, cfrag, stop_at_loop); - } - } - - private void create_local_free (Statement stmt) { - if (!memory_management) { - return; - } + var ccond = new CCodeBinaryExpression (operator = CCodeBinaryOperator.INEQUALITY, left = new CCodeIdentifier (name = it_name), right = new CCodeConstant (name = "NULL")); - var cfrag = new CCodeFragment (); - - append_local_free (current_symbol, cfrag, false); - - cfrag.append (stmt.ccodenode); - stmt.ccodenode = cfrag; + var cfor = new CCodeForStatement (condition = ccond, body = cbody); + cfor.add_initializer (new CCodeAssignment (left = new CCodeIdentifier (name = it_name), right = (CCodeExpression) stmt.collection.ccodenode)); + cfor.add_iterator (new CCodeAssignment (left = new CCodeIdentifier (name = it_name), right = new CCodeMemberAccess (inner = new CCodeIdentifier (name = it_name), member_name = "next", is_pointer = true))); + cblock.add_statement (cfor); } - private bool append_local_free_expr (Symbol sym, CCodeCommaExpression ccomma, bool stop_at_loop) { - var found = false; - - var b = (Block) sym.node; + stmt.ccodenode = cblock; + } - var local_vars = b.get_local_variables (); - foreach (VariableDeclarator decl in local_vars) { - if (decl.symbol.active && decl.type_reference.type.is_reference_type () && decl.type_reference.is_lvalue_ref) { - found = true; - ccomma.inner.append (get_unref_expression (new CCodeIdentifier (name = decl.name), decl.type_reference)); - } - } - - if (sym.parent_symbol.node is Block) { - found = found || append_local_free_expr (sym.parent_symbol, ccomma, stop_at_loop); - } - - return found; - } + public override void visit_break_statement (BreakStatement! stmt) { + stmt.ccodenode = new CCodeBreakStatement (); + } - private void create_local_free_expr (Expression expr) { - if (!memory_management) { - return; - } - - var return_expr_decl = get_temp_variable_declarator (expr.static_type); - - var ccomma = new CCodeCommaExpression (); - ccomma.inner.append (new CCodeAssignment (left = new CCodeIdentifier (name = return_expr_decl.name), right = expr.ccodenode)); + public override void visit_continue_statement (ContinueStatement! stmt) { + stmt.ccodenode = new CCodeContinueStatement (); + } + + private void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop) { + var b = (Block) sym.node; - if (!append_local_free_expr (current_symbol, ccomma, false)) { - /* no local variables need to be freed */ - return; + var local_vars = b.get_local_variables (); + foreach (VariableDeclarator decl in local_vars) { + if (decl.symbol.active && decl.type_reference.type.is_reference_type () && decl.type_reference.is_lvalue_ref) { + cfrag.append (new CCodeExpressionStatement (expression = get_unref_expression (new CCodeIdentifier (name = decl.name), decl.type_reference))); } + } + + if (sym.parent_symbol.node is Block) { + append_local_free (sym.parent_symbol, cfrag, stop_at_loop); + } + } - ccomma.inner.append (new CCodeIdentifier (name = return_expr_decl.name)); - - expr.ccodenode = ccomma; - expr.temp_vars.append (return_expr_decl); + private void create_local_free (Statement stmt) { + if (!memory_management) { + return; } + + var cfrag = new CCodeFragment (); + + append_local_free (current_symbol, cfrag, false); - public override void visit_return_statement (ReturnStatement! stmt) { - if (stmt.return_expression == null) { - stmt.ccodenode = new CCodeReturnStatement (); - - create_local_free (stmt); - } else { - create_local_free_expr (stmt.return_expression); + cfrag.append (stmt.ccodenode); + stmt.ccodenode = cfrag; + } + + private bool append_local_free_expr (Symbol sym, CCodeCommaExpression ccomma, bool stop_at_loop) { + var found = false; + + var b = (Block) sym.node; - stmt.ccodenode = new CCodeReturnStatement (return_expression = (CCodeExpression) stmt.return_expression.ccodenode); - - create_temp_decl (stmt, stmt.return_expression.temp_vars); + var local_vars = b.get_local_variables (); + foreach (VariableDeclarator decl in local_vars) { + if (decl.symbol.active && decl.type_reference.type.is_reference_type () && decl.type_reference.is_lvalue_ref) { + found = true; + ccomma.inner.append (get_unref_expression (new CCodeIdentifier (name = decl.name), decl.type_reference)); } } - - public override void visit_boolean_literal (BooleanLiteral! expr) { - if (expr.value) { - expr.ccodenode = new CCodeConstant (name = "TRUE"); - } else { - expr.ccodenode = new CCodeConstant (name = "FALSE"); - } + + if (sym.parent_symbol.node is Block) { + found = found || append_local_free_expr (sym.parent_symbol, ccomma, stop_at_loop); } + + return found; + } - public override void visit_character_literal (CharacterLiteral! expr) { - expr.ccodenode = new CCodeConstant (name = expr.value); + private void create_local_free_expr (Expression expr) { + if (!memory_management) { + return; } + + var return_expr_decl = get_temp_variable_declarator (expr.static_type); + + var ccomma = new CCodeCommaExpression (); + ccomma.inner.append (new CCodeAssignment (left = new CCodeIdentifier (name = return_expr_decl.name), right = expr.ccodenode)); - public override void visit_integer_literal (IntegerLiteral! expr) { - expr.ccodenode = new CCodeConstant (name = expr.value); + if (!append_local_free_expr (current_symbol, ccomma, false)) { + /* no local variables need to be freed */ + return; } - public override void visit_real_literal (RealLiteral! expr) { - expr.ccodenode = new CCodeConstant (name = expr.value); - } + ccomma.inner.append (new CCodeIdentifier (name = return_expr_decl.name)); + + expr.ccodenode = ccomma; + expr.temp_vars.append (return_expr_decl); + } - public override void visit_string_literal (StringLiteral! expr) { - expr.ccodenode = new CCodeConstant (name = expr.value); - } + public override void visit_return_statement (ReturnStatement! stmt) { + if (stmt.return_expression == null) { + stmt.ccodenode = new CCodeReturnStatement (); + + create_local_free (stmt); + } else { + create_local_free_expr (stmt.return_expression); - public override void visit_null_literal (NullLiteral! expr) { - expr.ccodenode = new CCodeConstant (name = "NULL"); + stmt.ccodenode = new CCodeReturnStatement (return_expression = (CCodeExpression) stmt.return_expression.ccodenode); + + create_temp_decl (stmt, stmt.return_expression.temp_vars); } + } - public override void visit_literal_expression (LiteralExpression! expr) { - expr.ccodenode = expr.literal.ccodenode; - - visit_expression (expr); + public override void visit_boolean_literal (BooleanLiteral! expr) { + if (expr.value) { + expr.ccodenode = new CCodeConstant (name = "TRUE"); + } else { + expr.ccodenode = new CCodeConstant (name = "FALSE"); } + } + + public override void visit_character_literal (CharacterLiteral! expr) { + expr.ccodenode = new CCodeConstant (name = expr.value); + } + + public override void visit_integer_literal (IntegerLiteral! expr) { + expr.ccodenode = new CCodeConstant (name = expr.value); + } + + public override void visit_real_literal (RealLiteral! expr) { + expr.ccodenode = new CCodeConstant (name = expr.value); + } + + public override void visit_string_literal (StringLiteral! expr) { + expr.ccodenode = new CCodeConstant (name = expr.value); + } + + public override void visit_null_literal (NullLiteral! expr) { + expr.ccodenode = new CCodeConstant (name = "NULL"); + } + + public override void visit_literal_expression (LiteralExpression! expr) { + expr.ccodenode = expr.literal.ccodenode; - private void process_cmember (MemberAccess! expr, CCodeExpression pub_inst, DataType base_type) { - if (expr.symbol_reference.node is Method) { - var m = (Method) expr.symbol_reference.node; - if (!m.is_override) { - expr.ccodenode = new CCodeIdentifier (name = m.get_cname ()); + visit_expression (expr); + } + + private void process_cmember (MemberAccess! expr, CCodeExpression pub_inst, DataType base_type) { + if (expr.symbol_reference.node is Method) { + var m = (Method) expr.symbol_reference.node; + if (!m.is_override) { + expr.ccodenode = new CCodeIdentifier (name = m.get_cname ()); + } else { + expr.ccodenode = new CCodeIdentifier (name = m.base_method.get_cname ()); + } + } else if (expr.symbol_reference.node is Field) { + var f = (Field) expr.symbol_reference.node; + if (f.instance) { + ref CCodeExpression typed_inst; + if (f.symbol.parent_symbol.node != base_type) { + typed_inst = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((DataType) f.symbol.parent_symbol.node).get_upper_case_cname (null))); + ((CCodeFunctionCall) typed_inst).add_argument (pub_inst); } else { - expr.ccodenode = new CCodeIdentifier (name = m.base_method.get_cname ()); + typed_inst = pub_inst; } - } else if (expr.symbol_reference.node is Field) { - var f = (Field) expr.symbol_reference.node; - if (f.instance) { - ref CCodeExpression typed_inst; - if (f.symbol.parent_symbol.node != base_type) { - typed_inst = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((DataType) 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.get_cname (), is_pointer = true); + ref CCodeExpression inst; + if (f.access == MemberAccessibility.PRIVATE) { + inst = new CCodeMemberAccess (inner = typed_inst, member_name = "priv", is_pointer = true); } else { - if (f.symbol.parent_symbol.node is DataType) { - var t = (DataType) f.symbol.parent_symbol.node; - expr.ccodenode = new CCodeIdentifier (name = "%s_%s".printf (t.get_lower_case_cname (null), f.get_cname ())); - } else { - expr.ccodenode = new CCodeIdentifier (name = f.get_cname ()); - } + inst = typed_inst; } - } else if (expr.symbol_reference.node is Constant) { - var c = (Constant) expr.symbol_reference.node; - expr.ccodenode = new CCodeIdentifier (name = c.get_cname ()); - } 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))); - - /* explicitly use strong reference as ccast - * gets unrefed at the end of the inner block - */ - ref CCodeExpression typed_pub_inst = pub_inst; - - /* cast if necessary */ - if (prop.no_accessor_method) { - var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "G_OBJECT")); - ccast.add_argument (pub_inst); - typed_pub_inst = ccast; - } else if (prop.symbol.parent_symbol.node != base_type) { - var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((DataType) prop.symbol.parent_symbol.node).get_upper_case_cname (null))); - ccast.add_argument (pub_inst); - typed_pub_inst = ccast; + expr.ccodenode = new CCodeMemberAccess (inner = inst, member_name = f.get_cname (), is_pointer = true); + } else { + if (f.symbol.parent_symbol.node is DataType) { + var t = (DataType) f.symbol.parent_symbol.node; + expr.ccodenode = new CCodeIdentifier (name = "%s_%s".printf (t.get_lower_case_cname (null), f.get_cname ())); + } else { + expr.ccodenode = new CCodeIdentifier (name = f.get_cname ()); } + } + } else if (expr.symbol_reference.node is Constant) { + var c = (Constant) expr.symbol_reference.node; + expr.ccodenode = new CCodeIdentifier (name = c.get_cname ()); + } 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))); + + /* explicitly use strong reference as ccast + * gets unrefed at the end of the inner block + */ + ref CCodeExpression typed_pub_inst = pub_inst; + + /* cast if necessary */ + if (prop.no_accessor_method) { + var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = "G_OBJECT")); + ccast.add_argument (pub_inst); + typed_pub_inst = ccast; + } else if (prop.symbol.parent_symbol.node != base_type) { + var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((DataType) prop.symbol.parent_symbol.node).get_upper_case_cname (null))); + ccast.add_argument (pub_inst); + typed_pub_inst = ccast; + } - ccall.add_argument (typed_pub_inst); - 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 if (expr.symbol_reference.node is VariableDeclarator) { - var decl = (VariableDeclarator) expr.symbol_reference.node; - expr.ccodenode = new CCodeIdentifier (name = decl.name); - } else if (expr.symbol_reference.node is FormalParameter) { - var p = (FormalParameter) expr.symbol_reference.node; - if (p.name == "this") { - expr.ccodenode = pub_inst; + ccall.add_argument (typed_pub_inst); + 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 if (expr.symbol_reference.node is VariableDeclarator) { + var decl = (VariableDeclarator) expr.symbol_reference.node; + expr.ccodenode = new CCodeIdentifier (name = decl.name); + } else if (expr.symbol_reference.node is FormalParameter) { + var p = (FormalParameter) expr.symbol_reference.node; + if (p.name == "this") { + expr.ccodenode = pub_inst; + } else { + if (p.type_reference.is_out || p.type_reference.is_ref) { + expr.ccodenode = new CCodeIdentifier (name = "*%s".printf (p.name)); } else { - if (p.type_reference.is_out || p.type_reference.is_ref) { - expr.ccodenode = new CCodeIdentifier (name = "*%s".printf (p.name)); - } else { - expr.ccodenode = new CCodeIdentifier (name = p.name); - } + expr.ccodenode = new CCodeIdentifier (name = p.name); } } } - - public override void visit_parenthesized_expression (ParenthesizedExpression! expr) { - expr.ccodenode = new CCodeParenthesizedExpression (inner = (CCodeExpression) expr.inner.ccodenode); + } + + public override void visit_parenthesized_expression (ParenthesizedExpression! expr) { + expr.ccodenode = new CCodeParenthesizedExpression (inner = (CCodeExpression) expr.inner.ccodenode); - visit_expression (expr); - } + visit_expression (expr); + } - public override void visit_member_access (MemberAccess! expr) { - CCodeExpression pub_inst = null; - DataType base_type = null; - - if (expr.inner == null) { - pub_inst = new CCodeIdentifier (name = "self"); + public override void visit_member_access (MemberAccess! expr) { + CCodeExpression pub_inst = null; + DataType base_type = null; + + if (expr.inner == null) { + pub_inst = new CCodeIdentifier (name = "self"); - if (current_type_symbol != null) { - /* base type is available if this is a type method */ - base_type = (DataType) current_type_symbol.node; - } - } else { - pub_inst = (CCodeExpression) expr.inner.ccodenode; + if (current_type_symbol != null) { + /* base type is available if this is a type method */ + base_type = (DataType) current_type_symbol.node; + } + } else { + pub_inst = (CCodeExpression) expr.inner.ccodenode; - if (expr.inner.static_type != null) { - base_type = expr.inner.static_type.type; - } + if (expr.inner.static_type != null) { + base_type = expr.inner.static_type.type; } + } - process_cmember (expr, pub_inst, base_type); + process_cmember (expr, pub_inst, base_type); - visit_expression (expr); - } + visit_expression (expr); + } - public override void visit_end_invocation_expression (InvocationExpression! expr) { - var ccall = new CCodeFunctionCall (call = (CCodeExpression) expr.call.ccodenode); - - Method m = null; - List params; - - if (!(expr.call is MemberAccess)) { - expr.error = true; - Report.error (expr.source_reference, "unsupported method invocation"); - return; - } - - var ma = (MemberAccess) expr.call; - - if (expr.call.symbol_reference.node is VariableDeclarator) { - var decl = (VariableDeclarator) expr.call.symbol_reference.node; - var cb = (Callback) decl.type_reference.type; - params = cb.get_parameters (); - } else if (expr.call.symbol_reference.node is FormalParameter) { - var param = (FormalParameter) expr.call.symbol_reference.node; - var cb = (Callback) param.type_reference.type; - params = cb.get_parameters (); + public override void visit_end_invocation_expression (InvocationExpression! expr) { + var ccall = new CCodeFunctionCall (call = (CCodeExpression) expr.call.ccodenode); + + Method m = null; + List params; + + if (!(expr.call is MemberAccess)) { + expr.error = true; + Report.error (expr.source_reference, "unsupported method invocation"); + return; + } + + var ma = (MemberAccess) expr.call; + + if (expr.call.symbol_reference.node is VariableDeclarator) { + var decl = (VariableDeclarator) expr.call.symbol_reference.node; + var cb = (Callback) decl.type_reference.type; + params = cb.get_parameters (); + } else if (expr.call.symbol_reference.node is FormalParameter) { + var param = (FormalParameter) expr.call.symbol_reference.node; + var cb = (Callback) param.type_reference.type; + params = cb.get_parameters (); + } else { + m = (Method) expr.call.symbol_reference.node; + params = m.get_parameters (); + } + + /* explicitly use strong reference as ccall gets unrefed + * at end of inner block + */ + ref CCodeExpression instance; + if (m != null && m.instance) { + var base_method = m; + if (m.is_override) { + base_method = m.base_method; + } + + var req_cast = false; + if (ma.inner == null) { + instance = new CCodeIdentifier (name = "self"); + /* require casts for overriden and inherited methods */ + req_cast = m.is_override || (m.symbol.parent_symbol != current_type_symbol); } else { - m = (Method) expr.call.symbol_reference.node; - params = m.get_parameters (); + instance = (CCodeExpression) ma.inner.ccodenode; + /* reqiure casts if the type of the used instance is + * different than the type which declared the method */ + req_cast = base_method.symbol.parent_symbol.node != ma.inner.static_type.type; } - /* explicitly use strong reference as ccall gets unrefed - * at end of inner block - */ - ref CCodeExpression instance; - if (m != null && m.instance) { - var base_method = m; - if (m.is_override) { - base_method = m.base_method; - } - - var req_cast = false; - if (ma.inner == null) { - instance = new CCodeIdentifier (name = "self"); - /* require casts for overriden and inherited methods */ - req_cast = m.is_override || (m.symbol.parent_symbol != current_type_symbol); - } else { - instance = (CCodeExpression) ma.inner.ccodenode; - /* reqiure casts if the type of the used instance is - * different than the type which declared the method */ - req_cast = base_method.symbol.parent_symbol.node != ma.inner.static_type.type; - } - - if (req_cast && ((DataType) m.symbol.parent_symbol.node).is_reference_type ()) { - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((DataType) base_method.symbol.parent_symbol.node).get_upper_case_cname (null))); - ccall.add_argument (instance); - instance = ccall; - } - - if (!m.instance_last) { - ccall.add_argument (instance); - } + if (req_cast && ((DataType) m.symbol.parent_symbol.node).is_reference_type ()) { + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((DataType) base_method.symbol.parent_symbol.node).get_upper_case_cname (null))); + ccall.add_argument (instance); + instance = ccall; } - var i = 1; - foreach (Expression arg in expr.argument_list) { - /* explicitly use strong reference as ccall gets - * unrefed at end of inner block - */ - ref CCodeExpression cexpr = (CCodeExpression) arg.ccodenode; - if (params != null) { - var param = (FormalParameter) params.data; - if (!param.ellipsis - && param.type_reference.type != null - && param.type_reference.type.is_reference_type () - && arg.static_type.type != null - && param.type_reference.type != arg.static_type.type) { - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = param.type_reference.type.get_upper_case_cname (null))); - ccall.add_argument (cexpr); - cexpr = ccall; - } - } - - ccall.add_argument (cexpr); - i++; - - if (params != null) { - params = params.next; - } + if (!m.instance_last) { + ccall.add_argument (instance); } - while (params != null) { + } + + var i = 1; + foreach (Expression arg in expr.argument_list) { + /* explicitly use strong reference as ccall gets + * unrefed at end of inner block + */ + ref CCodeExpression cexpr = (CCodeExpression) arg.ccodenode; + if (params != null) { var param = (FormalParameter) params.data; - - if (param.ellipsis) { - break; - } - - if (param.default_expression == null) { - Report.error (expr.source_reference, "no default expression for argument %d".printf (i)); - return; + if (!param.ellipsis + && param.type_reference.type != null + && param.type_reference.type.is_reference_type () + && arg.static_type.type != null + && param.type_reference.type != arg.static_type.type) { + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = param.type_reference.type.get_upper_case_cname (null))); + ccall.add_argument (cexpr); + cexpr = ccall; } - - /* evaluate default expression here as the code - * generator might not have visited the formal - * parameter yet */ - param.default_expression.accept (this); - - ccall.add_argument ((CCodeExpression) param.default_expression.ccodenode); - i++; + } + + ccall.add_argument (cexpr); + i++; + if (params != null) { params = params.next; } + } + while (params != null) { + var param = (FormalParameter) params.data; - if (m != null && m.instance && m.instance_last) { - ccall.add_argument (instance); + if (param.ellipsis) { + break; } - if (m != null && m.instance && m.returns_modified_pointer) { - expr.ccodenode = new CCodeAssignment (left = instance, right = ccall); - } else { - expr.ccodenode = ccall; - - visit_expression (expr); - } - } - - public override void visit_postfix_expression (PostfixExpression! expr) { - if (expr.increment) { - expr.ccodenode = new CCodeUnaryExpression (operator = CCodeUnaryOperator.POSTFIX_INCREMENT, inner = expr.inner.ccodenode); - } else { - expr.ccodenode = new CCodeUnaryExpression (operator = CCodeUnaryOperator.POSTFIX_DECREMENT, inner = expr.inner.ccodenode); + if (param.default_expression == null) { + Report.error (expr.source_reference, "no default expression for argument %d".printf (i)); + return; } - visit_expression (expr); - } + /* evaluate default expression here as the code + * generator might not have visited the formal + * parameter yet */ + param.default_expression.accept (this); - private ref CCodeExpression get_ref_expression (Expression! expr) { - /* (temp = expr, temp == NULL ? temp : ref (temp)) - * - * can be simplified to - * ref (expr) - * if static type of expr is non-null - * - * can be simplified to - * (expr == NULL ? expr : ref (expr)) - * if expr.ccodenode is CCodeSimpleName or CCodeMemberAccess - */ - - var decl = get_temp_variable_declarator (expr.static_type); - temp_vars.prepend (decl); - - var ctemp = new CCodeIdentifier (name = decl.name); - - var cisnull = new CCodeBinaryExpression (operator = CCodeBinaryOperator.EQUALITY, left = ctemp, right = new CCodeConstant (name = "NULL")); - - string ref_function; - if (expr.static_type.type.is_reference_counting ()) { - ref_function = expr.static_type.type.get_ref_function (); - } else { - ref_function = expr.static_type.type.get_dup_function (); - } + ccall.add_argument ((CCodeExpression) param.default_expression.ccodenode); + i++; - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = ref_function)); - ccall.add_argument (ctemp); - - var ccomma = new CCodeCommaExpression (); - ccomma.inner.append (new CCodeAssignment (left = ctemp, right = expr.ccodenode)); - ccomma.inner.append (new CCodeConditionalExpression (condition = cisnull, true_expression = ctemp, false_expression = ccall)); - - return ccomma; - } - - private void visit_expression (Expression! expr) { - if (expr.static_type != null && - expr.static_type.is_ref && - expr.static_type.floating_reference) { - /* constructor of GInitiallyUnowned subtype - * returns floating reference, sink it - */ - var csink = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_object_ref_sink")); - csink.add_argument ((CCodeExpression) expr.ccodenode); - - expr.ccodenode = csink; - } + params = params.next; + } - if (expr.ref_leaked) { - var decl = get_temp_variable_declarator (expr.static_type); - temp_vars.prepend (decl); - temp_ref_vars.prepend (decl); - expr.ccodenode = new CCodeParenthesizedExpression (inner = new CCodeAssignment (left = new CCodeIdentifier (name = decl.name), right = expr.ccodenode)); - } else if (expr.ref_missing) { - expr.ccodenode = get_ref_expression (expr); - } + if (m != null && m.instance && m.instance_last) { + ccall.add_argument (instance); } - - public override void visit_object_creation_expression (ObjectCreationExpression! expr) { - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_object_new")); - - ccall.add_argument (new CCodeConstant (name = expr.type_reference.get_upper_case_cname ("TYPE_"))); - - foreach (NamedArgument arg in expr.named_argument_list) { - ccall.add_argument (new CCodeConstant (name = "\"%s\"".printf (arg.name))); - ccall.add_argument ((CCodeExpression) arg.argument.ccodenode); - } - ccall.add_argument (new CCodeConstant (name = "NULL")); - + + if (m != null && m.instance && m.returns_modified_pointer) { + expr.ccodenode = new CCodeAssignment (left = instance, right = ccall); + } else { expr.ccodenode = ccall; - + visit_expression (expr); } + } - public override void visit_typeof_expression (TypeofExpression! expr) { - expr.ccodenode = new CCodeIdentifier (name = expr.type_reference.type.get_type_id ()); - } - - public override void visit_unary_expression (UnaryExpression! expr) { - CCodeUnaryOperator op; - if (expr.operator == UnaryOperator.PLUS) { - op = CCodeUnaryOperator.PLUS; - } else if (expr.operator == UnaryOperator.MINUS) { - op = CCodeUnaryOperator.MINUS; - } else if (expr.operator == UnaryOperator.LOGICAL_NEGATION) { - op = CCodeUnaryOperator.LOGICAL_NEGATION; - } else if (expr.operator == UnaryOperator.BITWISE_COMPLEMENT) { - op = CCodeUnaryOperator.BITWISE_COMPLEMENT; - } else if (expr.operator == UnaryOperator.REF) { - op = CCodeUnaryOperator.ADDRESS_OF; - } else if (expr.operator == UnaryOperator.OUT) { - op = CCodeUnaryOperator.ADDRESS_OF; - } - expr.ccodenode = new CCodeUnaryExpression (operator = op, inner = expr.inner.ccodenode); - - visit_expression (expr); + public override void visit_postfix_expression (PostfixExpression! expr) { + if (expr.increment) { + expr.ccodenode = new CCodeUnaryExpression (operator = CCodeUnaryOperator.POSTFIX_INCREMENT, inner = expr.inner.ccodenode); + } else { + expr.ccodenode = new CCodeUnaryExpression (operator = CCodeUnaryOperator.POSTFIX_DECREMENT, inner = expr.inner.ccodenode); } + + visit_expression (expr); + } + + private ref CCodeExpression get_ref_expression (Expression! expr) { + /* (temp = expr, temp == NULL ? temp : ref (temp)) + * + * can be simplified to + * ref (expr) + * if static type of expr is non-null + * + * can be simplified to + * (expr == NULL ? expr : ref (expr)) + * if expr.ccodenode is CCodeSimpleName or CCodeMemberAccess + */ + + var decl = get_temp_variable_declarator (expr.static_type); + temp_vars.prepend (decl); - public override void visit_cast_expression (CastExpression! expr) { - if (expr.type_reference.type is Struct || expr.type_reference.type is Enum || expr.type_reference.type is Flags) { - expr.ccodenode = expr.inner.ccodenode; - } else { - expr.ccodenode = new InstanceCast (type_reference = expr.type_reference.type, inner = (CCodeExpression) expr.inner.ccodenode); - } - - visit_expression (expr); + var ctemp = new CCodeIdentifier (name = decl.name); + + var cisnull = new CCodeBinaryExpression (operator = CCodeBinaryOperator.EQUALITY, left = ctemp, right = new CCodeConstant (name = "NULL")); + + string ref_function; + if (expr.static_type.type.is_reference_counting ()) { + ref_function = expr.static_type.type.get_ref_function (); + } else { + ref_function = expr.static_type.type.get_dup_function (); } + + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = ref_function)); + ccall.add_argument (ctemp); + + var ccomma = new CCodeCommaExpression (); + ccomma.inner.append (new CCodeAssignment (left = ctemp, right = expr.ccodenode)); + ccomma.inner.append (new CCodeConditionalExpression (condition = cisnull, true_expression = ctemp, false_expression = ccall)); - public override void visit_binary_expression (BinaryExpression! expr) { - expr.ccodenode = new CCodeBinaryExpression (operator = expr.operator, left = expr.left.ccodenode, right = expr.right.ccodenode); + return ccomma; + } + + private void visit_expression (Expression! expr) { + if (expr.static_type != null && + expr.static_type.is_ref && + expr.static_type.floating_reference) { + /* constructor of GInitiallyUnowned subtype + * returns floating reference, sink it + */ + var csink = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_object_ref_sink")); + csink.add_argument ((CCodeExpression) expr.ccodenode); - visit_expression (expr); + expr.ccodenode = csink; } - - public override void visit_type_check (TypeCheck! expr) { - var ccheck = new CCodeFunctionCall (call = new CCodeIdentifier (name = expr.type_reference.type.get_upper_case_cname ("IS_"))); - ccheck.add_argument ((CCodeExpression) expr.expression.ccodenode); - expr.ccodenode = ccheck; + + if (expr.ref_leaked) { + var decl = get_temp_variable_declarator (expr.static_type); + temp_vars.prepend (decl); + temp_ref_vars.prepend (decl); + expr.ccodenode = new CCodeParenthesizedExpression (inner = new CCodeAssignment (left = new CCodeIdentifier (name = decl.name), right = expr.ccodenode)); + } else if (expr.ref_missing) { + expr.ccodenode = get_ref_expression (expr); } + } + + public override void visit_object_creation_expression (ObjectCreationExpression! expr) { + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "g_object_new")); + + ccall.add_argument (new CCodeConstant (name = expr.type_reference.get_upper_case_cname ("TYPE_"))); - public override void visit_conditional_expression (ConditionalExpression! expr) { - expr.ccodenode = new CCodeConditionalExpression (condition = (CCodeExpression) expr.condition.ccodenode, true_expression = (CCodeExpression) expr.true_expression.ccodenode, false_expression = (CCodeExpression) expr.false_expression.ccodenode); + foreach (NamedArgument arg in expr.named_argument_list) { + ccall.add_argument (new CCodeConstant (name = "\"%s\"".printf (arg.name))); + ccall.add_argument ((CCodeExpression) arg.argument.ccodenode); } + ccall.add_argument (new CCodeConstant (name = "NULL")); + + expr.ccodenode = ccall; + + visit_expression (expr); + } + + public override void visit_typeof_expression (TypeofExpression! expr) { + expr.ccodenode = new CCodeIdentifier (name = expr.type_reference.type.get_type_id ()); + } + + public override void visit_unary_expression (UnaryExpression! expr) { + CCodeUnaryOperator op; + if (expr.operator == UnaryOperator.PLUS) { + op = CCodeUnaryOperator.PLUS; + } else if (expr.operator == UnaryOperator.MINUS) { + op = CCodeUnaryOperator.MINUS; + } else if (expr.operator == UnaryOperator.LOGICAL_NEGATION) { + op = CCodeUnaryOperator.LOGICAL_NEGATION; + } else if (expr.operator == UnaryOperator.BITWISE_COMPLEMENT) { + op = CCodeUnaryOperator.BITWISE_COMPLEMENT; + } else if (expr.operator == UnaryOperator.REF) { + op = CCodeUnaryOperator.ADDRESS_OF; + } else if (expr.operator == UnaryOperator.OUT) { + op = CCodeUnaryOperator.ADDRESS_OF; + } + expr.ccodenode = new CCodeUnaryExpression (operator = op, inner = expr.inner.ccodenode); + + visit_expression (expr); + } - public override void visit_end_lambda_expression (LambdaExpression! l) { - l.ccodenode = new CCodeIdentifier (name = l.method.get_cname ()); + public override void visit_cast_expression (CastExpression! expr) { + if (expr.type_reference.type is Struct || expr.type_reference.type is Enum || expr.type_reference.type is Flags) { + expr.ccodenode = expr.inner.ccodenode; + } else { + expr.ccodenode = new InstanceCast (type_reference = expr.type_reference.type, inner = (CCodeExpression) expr.inner.ccodenode); } + + visit_expression (expr); + } - public override void visit_end_assignment (Assignment! a) { - var ma = (MemberAccess) a.left; + public override void visit_binary_expression (BinaryExpression! expr) { + expr.ccodenode = new CCodeBinaryExpression (operator = expr.operator, left = expr.left.ccodenode, right = expr.right.ccodenode); + + visit_expression (expr); + } - if (a.left.symbol_reference.node is Property) { - var prop = (Property) a.left.symbol_reference.node; - var cl = (Class) prop.symbol.parent_symbol.node; + public override void visit_type_check (TypeCheck! expr) { + var ccheck = new CCodeFunctionCall (call = new CCodeIdentifier (name = expr.type_reference.type.get_upper_case_cname ("IS_"))); + ccheck.add_argument ((CCodeExpression) expr.expression.ccodenode); + expr.ccodenode = ccheck; + } - var set_func = "g_object_set"; - - if (!prop.no_accessor_method) { - set_func = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name); - } - - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = set_func)); + public override void visit_conditional_expression (ConditionalExpression! expr) { + expr.ccodenode = new CCodeConditionalExpression (condition = (CCodeExpression) expr.condition.ccodenode, true_expression = (CCodeExpression) expr.true_expression.ccodenode, false_expression = (CCodeExpression) expr.false_expression.ccodenode); + } - /* target instance is first argument */ - ref CCodeExpression instance; - var req_cast = false; + public override void visit_end_lambda_expression (LambdaExpression! l) { + l.ccodenode = new CCodeIdentifier (name = l.method.get_cname ()); + } - if (ma.inner == null) { - instance = new CCodeIdentifier (name = "self"); - /* require casts for inherited properties */ - req_cast = (prop.symbol.parent_symbol != current_type_symbol); - } else { - instance = (CCodeExpression) ma.inner.ccodenode; - /* require casts if the type of the used instance is - * different than the type which declared the property */ - req_cast = prop.symbol.parent_symbol.node != ma.inner.static_type.type; - } - - if (req_cast && ((DataType) prop.symbol.parent_symbol.node).is_reference_type ()) { - var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((DataType) prop.symbol.parent_symbol.node).get_upper_case_cname (null))); - ccast.add_argument (instance); - instance = ccast; - } + public override void visit_end_assignment (Assignment! a) { + var ma = (MemberAccess) a.left; - ccall.add_argument (instance); - - ref CCodeExpression cexpr = (CCodeExpression) a.right.ccodenode; - - if (prop.no_accessor_method) { - /* property name is second argument of g_object_set */ - ccall.add_argument (prop.get_canonical_cconstant ()); - } else if (prop.type_reference.type != null - && prop.type_reference.type.is_reference_type () - && a.right.static_type.type != null - && prop.type_reference.type != a.right.static_type.type) { - /* cast is necessary */ - var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = prop.type_reference.type.get_upper_case_cname (null))); - ccast.add_argument (cexpr); - cexpr = ccast; - } - - ccall.add_argument (cexpr); - - if (prop.no_accessor_method) { - ccall.add_argument (new CCodeConstant (name = "NULL")); - } - - a.ccodenode = ccall; - } else if (a.left.symbol_reference.node is Signal) { - var sig = (Signal) a.left.symbol_reference.node; + 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 set_func = "g_object_set"; + + if (!prop.no_accessor_method) { + set_func = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name); + } + + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = set_func)); + + /* target instance is first argument */ + ref CCodeExpression instance; + var req_cast = false; + + if (ma.inner == null) { + instance = new CCodeIdentifier (name = "self"); + /* require casts for inherited properties */ + req_cast = (prop.symbol.parent_symbol != current_type_symbol); + } else { + instance = (CCodeExpression) ma.inner.ccodenode; + /* require casts if the type of the used instance is + * different than the type which declared the property */ + req_cast = prop.symbol.parent_symbol.node != ma.inner.static_type.type; + } + + if (req_cast && ((DataType) prop.symbol.parent_symbol.node).is_reference_type ()) { + var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((DataType) prop.symbol.parent_symbol.node).get_upper_case_cname (null))); + ccast.add_argument (instance); + instance = ccast; + } + + ccall.add_argument (instance); - if (a.right.symbol_reference == null) { - a.right.error = true; - Report.error (a.right.source_reference, "unsupported expression for signal handler"); - return; - } + ref CCodeExpression cexpr = (CCodeExpression) a.right.ccodenode; + + if (prop.no_accessor_method) { + /* property name is second argument of g_object_set */ + ccall.add_argument (prop.get_canonical_cconstant ()); + } else if (prop.type_reference.type != null + && prop.type_reference.type.is_reference_type () + && a.right.static_type.type != null + && prop.type_reference.type != a.right.static_type.type) { + /* cast is necessary */ + var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = prop.type_reference.type.get_upper_case_cname (null))); + ccast.add_argument (cexpr); + cexpr = ccast; + } - var m = (Method) a.right.symbol_reference.node; - var connect_func = "g_signal_connect_object"; - if (!m.instance) { - connect_func = "g_signal_connect"; - } - - var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = connect_func)); + ccall.add_argument (cexpr); - if (ma.inner != null) { - ccall.add_argument ((CCodeExpression) ma.inner.ccodenode); - } else { - ccall.add_argument (new CCodeIdentifier (name = "self")); - } + if (prop.no_accessor_method) { + ccall.add_argument (new CCodeConstant (name = "NULL")); + } + + a.ccodenode = ccall; + } else if (a.left.symbol_reference.node is Signal) { + var sig = (Signal) a.left.symbol_reference.node; + + if (a.right.symbol_reference == null) { + a.right.error = true; + Report.error (a.right.source_reference, "unsupported expression for signal handler"); + return; + } + + var m = (Method) a.right.symbol_reference.node; + var connect_func = "g_signal_connect_object"; + if (!m.instance) { + connect_func = "g_signal_connect"; + } - ccall.add_argument (new CCodeConstant (name = "\"%s\"".printf (sig.name))); + var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = connect_func)); + + if (ma.inner != null) { + ccall.add_argument ((CCodeExpression) ma.inner.ccodenode); + } else { + ccall.add_argument (new CCodeIdentifier (name = "self")); + } - ccall.add_argument (new CCodeIdentifier (name = m.get_cname ())); + ccall.add_argument (new CCodeConstant (name = "\"%s\"".printf (sig.name))); - if (m.instance) { - if (a.right is MemberAccess) { - var right_ma = (MemberAccess) a.right; - if (right_ma.inner != null) { - ccall.add_argument ((CCodeExpression) right_ma.inner.ccodenode); - } else { - ccall.add_argument (new CCodeIdentifier (name = "self")); - } - } else if (a.right is LambdaExpression) { + ccall.add_argument (new CCodeIdentifier (name = m.get_cname ())); + + if (m.instance) { + if (a.right is MemberAccess) { + var right_ma = (MemberAccess) a.right; + if (right_ma.inner != null) { + ccall.add_argument ((CCodeExpression) right_ma.inner.ccodenode); + } else { ccall.add_argument (new CCodeIdentifier (name = "self")); } - - ccall.add_argument (new CCodeConstant (name = "G_CONNECT_SWAPPED")); - } else { - ccall.add_argument (new CCodeConstant (name = "NULL")); + } else if (a.right is LambdaExpression) { + ccall.add_argument (new CCodeIdentifier (name = "self")); } - - a.ccodenode = ccall; + + ccall.add_argument (new CCodeConstant (name = "G_CONNECT_SWAPPED")); } else { - /* explicitly use strong reference as ccast gets - * unrefed at end of inner block - */ - ref CCodeExpression rhs = (CCodeExpression) a.right.ccodenode; - - if (a.left.static_type.type != null - && a.right.static_type.type != null - && a.left.static_type.type.is_reference_type () - && a.right.static_type.type != a.left.static_type.type) { - var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = a.left.static_type.type.get_upper_case_cname (null))); - ccast.add_argument (rhs); - rhs = ccast; - } + ccall.add_argument (new CCodeConstant (name = "NULL")); + } + + a.ccodenode = ccall; + } else { + /* explicitly use strong reference as ccast gets + * unrefed at end of inner block + */ + ref CCodeExpression rhs = (CCodeExpression) a.right.ccodenode; + + if (a.left.static_type.type != null + && a.right.static_type.type != null + && a.left.static_type.type.is_reference_type () + && a.right.static_type.type != a.left.static_type.type) { + var ccast = new CCodeFunctionCall (call = new CCodeIdentifier (name = a.left.static_type.type.get_upper_case_cname (null))); + ccast.add_argument (rhs); + rhs = ccast; + } + + if (memory_management && a.left.static_type.is_lvalue_ref) { + /* unref old value */ + var ccomma = new CCodeCommaExpression (); - if (memory_management && a.left.static_type.is_lvalue_ref) { - /* unref old value */ - var ccomma = new CCodeCommaExpression (); - - var temp_decl = get_temp_variable_declarator (a.left.static_type); - temp_vars.prepend (temp_decl); - ccomma.inner.append (new CCodeAssignment (left = new CCodeIdentifier (name = temp_decl.name), right = rhs)); - ccomma.inner.append (get_unref_expression ((CCodeExpression) a.left.ccodenode, a.left.static_type)); - ccomma.inner.append (new CCodeIdentifier (name = temp_decl.name)); - - rhs = ccomma; - } + var temp_decl = get_temp_variable_declarator (a.left.static_type); + temp_vars.prepend (temp_decl); + ccomma.inner.append (new CCodeAssignment (left = new CCodeIdentifier (name = temp_decl.name), right = rhs)); + ccomma.inner.append (get_unref_expression ((CCodeExpression) a.left.ccodenode, a.left.static_type)); + ccomma.inner.append (new CCodeIdentifier (name = temp_decl.name)); - var cop = CCodeAssignmentOperator.SIMPLE; - if (a.operator == AssignmentOperator.BITWISE_OR) { - cop = CCodeAssignmentOperator.BITWISE_OR; - } else if (a.operator == AssignmentOperator.BITWISE_AND) { - cop = CCodeAssignmentOperator.BITWISE_AND; - } else if (a.operator == AssignmentOperator.BITWISE_XOR) { - cop = CCodeAssignmentOperator.BITWISE_XOR; - } else if (a.operator == AssignmentOperator.ADD) { - cop = CCodeAssignmentOperator.ADD; - } else if (a.operator == AssignmentOperator.SUB) { - cop = CCodeAssignmentOperator.SUB; - } else if (a.operator == AssignmentOperator.MUL) { - cop = CCodeAssignmentOperator.MUL; - } else if (a.operator == AssignmentOperator.DIV) { - cop = CCodeAssignmentOperator.DIV; - } else if (a.operator == AssignmentOperator.PERCENT) { - cop = CCodeAssignmentOperator.PERCENT; - } else if (a.operator == AssignmentOperator.SHIFT_LEFT) { - cop = CCodeAssignmentOperator.SHIFT_LEFT; - } else if (a.operator == AssignmentOperator.SHIFT_RIGHT) { - cop = CCodeAssignmentOperator.SHIFT_RIGHT; - } - - a.ccodenode = new CCodeAssignment (left = (CCodeExpression) a.left.ccodenode, right = rhs, operator = cop); + rhs = ccomma; + } + + var cop = CCodeAssignmentOperator.SIMPLE; + if (a.operator == AssignmentOperator.BITWISE_OR) { + cop = CCodeAssignmentOperator.BITWISE_OR; + } else if (a.operator == AssignmentOperator.BITWISE_AND) { + cop = CCodeAssignmentOperator.BITWISE_AND; + } else if (a.operator == AssignmentOperator.BITWISE_XOR) { + cop = CCodeAssignmentOperator.BITWISE_XOR; + } else if (a.operator == AssignmentOperator.ADD) { + cop = CCodeAssignmentOperator.ADD; + } else if (a.operator == AssignmentOperator.SUB) { + cop = CCodeAssignmentOperator.SUB; + } else if (a.operator == AssignmentOperator.MUL) { + cop = CCodeAssignmentOperator.MUL; + } else if (a.operator == AssignmentOperator.DIV) { + cop = CCodeAssignmentOperator.DIV; + } else if (a.operator == AssignmentOperator.PERCENT) { + cop = CCodeAssignmentOperator.PERCENT; + } else if (a.operator == AssignmentOperator.SHIFT_LEFT) { + cop = CCodeAssignmentOperator.SHIFT_LEFT; + } else if (a.operator == AssignmentOperator.SHIFT_RIGHT) { + cop = CCodeAssignmentOperator.SHIFT_RIGHT; } + + a.ccodenode = new CCodeAssignment (left = (CCodeExpression) a.left.ccodenode, right = rhs, operator = cop); } } } diff --git a/vala/vala/valaconditionalexpression.vala b/vala/vala/valaconditionalexpression.vala index a8766b5..6937edf 100644 --- a/vala/vala/valaconditionalexpression.vala +++ b/vala/vala/valaconditionalexpression.vala @@ -22,22 +22,42 @@ using GLib; -namespace Vala { - public class ConditionalExpression : Expression { - public Expression condition { get; construct; } - public Expression true_expression { get; construct; } - public Expression false_expression { get; construct; } - - public static ref ConditionalExpression new (Expression cond, Expression true_expr, Expression false_expr, SourceReference source) { - return (new ConditionalExpression (condition = cond, true_expression = true_expr, false_expression = false_expr, source_reference = source)); - } - - public override void accept (CodeVisitor visitor) { - condition.accept (visitor); - true_expression.accept (visitor); - false_expression.accept (visitor); +/** + * Represents a conditional expression in the source code. + */ +public class Vala.ConditionalExpression : Expression { + /** + * The condition. + */ + public Expression! condition { get; set construct; } + + /** + * The expression to be evaluated if the condition holds. + */ + public Expression! true_expression { get; set construct; } + + /** + * The expression to be evaluated if the condition doesn't hold. + */ + public Expression! false_expression { get; set construct; } + + /** + * Creates a new conditional expression. + * + * @param cond a condition + * @param true_expr expression to be evaluated if condition is true + * @param false_expr expression to be evaluated if condition is false + * @return newly created conditional expression + */ + public static ref ConditionalExpression! new (Expression! cond, Expression! true_expr, Expression! false_expr, SourceReference source) { + return (new ConditionalExpression (condition = cond, true_expression = true_expr, false_expression = false_expr, source_reference = source)); + } + + public override void accept (CodeVisitor! visitor) { + condition.accept (visitor); + true_expression.accept (visitor); + false_expression.accept (visitor); - visitor.visit_conditional_expression (this); - } + visitor.visit_conditional_expression (this); } } diff --git a/vala/vala/valaconstant.vala b/vala/vala/valaconstant.vala index c4dc7d6..ff19657 100644 --- a/vala/vala/valaconstant.vala +++ b/vala/vala/valaconstant.vala @@ -22,37 +22,63 @@ using GLib; -namespace Vala { - public class Constant : CodeNode { - public string name { get; construct; } - public TypeReference type_reference { get; construct; } - public Expression initializer { get; construct; } - public SourceReference source_reference { get; construct; } - - public static ref Constant new (string name, TypeReference type, Expression init, SourceReference source) { - return (new Constant (name = name, type_reference = type, initializer = init, source_reference = source)); - } - - public override void accept (CodeVisitor visitor) { - type_reference.accept (visitor); - - initializer.accept (visitor); +/** + * Represents a type member with a constant value. + */ +public class Vala.Constant : CodeNode { + /** + * The symbol name of this constant. + */ + public string! name { get; set construct; } - visitor.visit_constant (this); - } + /** + * The data type of this constant. + */ + public TypeReference! type_reference { get; set construct; } + + /** + * The value of this constant. + */ + public Expression! initializer { get; set construct; } + + private string cname; + + /** + * Creates a new constant. + * + * @param name constant name + * @param type constant type + * @param init constant value + * @param source reference to source code + * @return newly created constant + */ + public static ref Constant! new (string! name, TypeReference! type, Expression! init, SourceReference source) { + return (new Constant (name = name, type_reference = type, initializer = init, source_reference = source)); + } + + public override void accept (CodeVisitor visitor) { + type_reference.accept (visitor); - string cname; - public string get_cname () { - if (cname == null) { - if (symbol.parent_symbol.node is DataType) { - var t = (DataType) symbol.parent_symbol.node; - cname = "%s_%s".printf (t.get_upper_case_cname (null), name); - } else { - var ns = (Namespace) symbol.parent_symbol.node; - cname = "%s%s".printf (ns.get_cprefix ().up (), name); - } + initializer.accept (visitor); + + visitor.visit_constant (this); + } + + /** + * Returns the name of this constant as it is used in C code. + * + * @return the name to be used in C code + */ + public string! get_cname () { + if (cname == null) { + if (symbol.parent_symbol.node is DataType) { + var t = (DataType) symbol.parent_symbol.node; + cname = "%s_%s".printf (t.get_upper_case_cname (null), name); + } else { + var ns = (Namespace) symbol.parent_symbol.node; + cname = "%s%s".printf (ns.get_cprefix ().up (), name); } - return cname; } + return cname; } } diff --git a/vala/vala/valamemorymanager.vala b/vala/vala/valamemorymanager.vala index e288060..7ac01d3 100644 --- a/vala/vala/valamemorymanager.vala +++ b/vala/vala/valamemorymanager.vala @@ -22,144 +22,151 @@ using GLib; -namespace Vala { - public class MemoryManager : CodeVisitor { - Symbol current_symbol; - - public void analyze (CodeContext! context) { - context.accept (this); - } - - private void visit_possibly_leaked_expression (Expression! expr) { - if (expr.static_type != null && - expr.static_type.is_ref) { - /* mark reference as leaked */ - expr.ref_leaked = true; - } +/** + * Code visitor analyzing memory usage. The memory manager finds leaked and + * copied references. + */ +public class Vala.MemoryManager : CodeVisitor { + Symbol current_symbol; + + /** + * Analyze memory usage in the specified code context. + * + * @param context a code context + */ + public void analyze (CodeContext! context) { + context.accept (this); + } + + private void visit_possibly_leaked_expression (Expression! expr) { + if (expr.static_type != null && + expr.static_type.is_ref) { + /* mark reference as leaked */ + expr.ref_leaked = true; } + } - private void visit_possibly_missing_copy_expression (Expression! expr) { - if (expr.static_type != null && - (expr.static_type.type != null && - expr.static_type.type.is_reference_type ()) && - !expr.static_type.is_ref) { - /* mark reference as missing */ - expr.ref_missing = true; - } + private void visit_possibly_missing_copy_expression (Expression! expr) { + if (expr.static_type != null && + (expr.static_type.type != null && + expr.static_type.type.is_reference_type ()) && + !expr.static_type.is_ref) { + /* mark reference as missing */ + expr.ref_missing = true; } + } - public override void visit_begin_method (Method! m) { - current_symbol = m.symbol; - } - - public override void visit_begin_property (Property prop) { - current_symbol = prop.symbol; - } + public override void visit_begin_method (Method! m) { + current_symbol = m.symbol; + } + + public override void visit_begin_property (Property prop) { + current_symbol = prop.symbol; + } - public override void visit_named_argument (NamedArgument! n) { - visit_possibly_leaked_expression (n.argument); - } + public override void visit_named_argument (NamedArgument! n) { + visit_possibly_leaked_expression (n.argument); + } - public override void visit_variable_declarator (VariableDeclarator! decl) { - if (decl.initializer != null) { - if (decl.type_reference.is_lvalue_ref) { - visit_possibly_missing_copy_expression (decl.initializer); - } else { - visit_possibly_leaked_expression (decl.initializer); - } + public override void visit_variable_declarator (VariableDeclarator! decl) { + if (decl.initializer != null) { + if (decl.type_reference.is_lvalue_ref) { + visit_possibly_missing_copy_expression (decl.initializer); + } else { + visit_possibly_leaked_expression (decl.initializer); } } + } - public override void visit_expression_statement (ExpressionStatement! stmt) { - visit_possibly_leaked_expression (stmt.expression); - } + public override void visit_expression_statement (ExpressionStatement! stmt) { + visit_possibly_leaked_expression (stmt.expression); + } - public override void visit_return_statement (ReturnStatement! stmt) { - if (stmt.return_expression != null) { - if (current_symbol.node is Method) { - var m = (Method) current_symbol.node; - - if (m.return_type.is_ref) { - visit_possibly_missing_copy_expression (stmt.return_expression); - } else { - visit_possibly_leaked_expression (stmt.return_expression); - } + public override void visit_return_statement (ReturnStatement! stmt) { + if (stmt.return_expression != null) { + if (current_symbol.node is Method) { + var m = (Method) current_symbol.node; + + if (m.return_type.is_ref) { + visit_possibly_missing_copy_expression (stmt.return_expression); } else { - /* property get accessor */ visit_possibly_leaked_expression (stmt.return_expression); } + } else { + /* property get accessor */ + visit_possibly_leaked_expression (stmt.return_expression); } } + } - public override void visit_member_access (MemberAccess! expr) { - if (expr.inner != null) { - visit_possibly_leaked_expression (expr.inner); - } + public override void visit_member_access (MemberAccess! expr) { + if (expr.inner != null) { + visit_possibly_leaked_expression (expr.inner); } + } - public override void visit_end_invocation_expression (InvocationExpression! expr) { - List params; - - var msym = expr.call.symbol_reference; - if (msym.node is VariableDeclarator) { - var decl = (VariableDeclarator) msym.node; - var cb = (Callback) decl.type_reference.type; - params = cb.get_parameters (); - } else if (msym.node is FormalParameter) { - var param = (FormalParameter) msym.node; - var cb = (Callback) param.type_reference.type; - 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; - if (!param.ellipsis - && ((param.type_reference.type != null - && param.type_reference.type.is_reference_type ()) - || param.type_reference.type_parameter != null)) { - bool is_ref = param.type_reference.is_ref; - if (is_ref && param.type_reference.type_parameter != null) { - if (expr.call is MemberAccess) { - var instance_type = ((MemberAccess) expr.call).inner.static_type; - foreach (TypeReference type_arg in instance_type.get_type_arguments ()) { - /* generic method parameters may only be strong references if the type argument is strong, too */ - is_ref = type_arg.is_ref; - } + public override void visit_end_invocation_expression (InvocationExpression! expr) { + List params; + + var msym = expr.call.symbol_reference; + if (msym.node is VariableDeclarator) { + var decl = (VariableDeclarator) msym.node; + var cb = (Callback) decl.type_reference.type; + params = cb.get_parameters (); + } else if (msym.node is FormalParameter) { + var param = (FormalParameter) msym.node; + var cb = (Callback) param.type_reference.type; + 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; + if (!param.ellipsis + && ((param.type_reference.type != null + && param.type_reference.type.is_reference_type ()) + || param.type_reference.type_parameter != null)) { + bool is_ref = param.type_reference.is_ref; + if (is_ref && param.type_reference.type_parameter != null) { + if (expr.call is MemberAccess) { + var instance_type = ((MemberAccess) expr.call).inner.static_type; + foreach (TypeReference type_arg in instance_type.get_type_arguments ()) { + /* generic method parameters may only be strong references if the type argument is strong, too */ + is_ref = type_arg.is_ref; } } - - if (is_ref) { - visit_possibly_missing_copy_expression (arg); - } else { - visit_possibly_leaked_expression (arg); - } + } + + if (is_ref) { + visit_possibly_missing_copy_expression (arg); } else { visit_possibly_leaked_expression (arg); } - - params = params.next; } else { visit_possibly_leaked_expression (arg); } + + params = params.next; + } else { + visit_possibly_leaked_expression (arg); } } + } - public override void visit_binary_expression (BinaryExpression! expr) { - visit_possibly_leaked_expression (expr.left); - visit_possibly_leaked_expression (expr.right); - } + public override void visit_binary_expression (BinaryExpression! expr) { + visit_possibly_leaked_expression (expr.left); + visit_possibly_leaked_expression (expr.right); + } - public override void visit_end_assignment (Assignment! a) { - if (a.left.symbol_reference.node is Signal) { + public override void visit_end_assignment (Assignment! a) { + if (a.left.symbol_reference.node is Signal) { + } else { + if (a.left.static_type.is_lvalue_ref) { + visit_possibly_missing_copy_expression (a.right); } else { - if (a.left.static_type.is_lvalue_ref) { - visit_possibly_missing_copy_expression (a.right); - } else { - visit_possibly_leaked_expression (a.right); - } + visit_possibly_leaked_expression (a.right); } } } diff --git a/vala/vala/valasemanticanalyzer.vala b/vala/vala/valasemanticanalyzer.vala index 62c373e..4741dfa 100644 --- a/vala/vala/valasemanticanalyzer.vala +++ b/vala/vala/valasemanticanalyzer.vala @@ -22,995 +22,1039 @@ using GLib; -namespace Vala { - public class SemanticAnalyzer : CodeVisitor { - public bool memory_management { get; construct; } - - Symbol root_symbol; - Symbol current_symbol; - SourceFile current_source_file; - TypeReference current_return_type; +/** + * Code visitor analyzing and checking code. + */ +public class Vala.SemanticAnalyzer : CodeVisitor { + /** + * Specifies whether automatic memory management is active. + */ + public bool memory_management { get; set; } + + Symbol root_symbol; + Symbol current_symbol; + SourceFile current_source_file; + TypeReference current_return_type; + + List current_using_directives; + + TypeReference bool_type; + TypeReference string_type; + DataType initially_unowned_type; + + private int next_lambda_id = 0; + + /** + * Analyze and check code in the specified context. + * + * @param context a code context + */ + public void analyze (CodeContext! context) { + root_symbol = context.get_root (); + + bool_type = new TypeReference (); + bool_type.type = (DataType) root_symbol.lookup ("bool").node; + + string_type = new TypeReference (); + string_type.type = (DataType) root_symbol.lookup ("string").node; - List current_using_directives; + var glib_ns = root_symbol.lookup ("GLib"); - TypeReference bool_type; - TypeReference string_type; - DataType initially_unowned_type; + initially_unowned_type = (DataType) glib_ns.lookup ("InitiallyUnowned").node; - private int next_lambda_id = 0; + current_symbol = root_symbol; + context.accept (this); + } + + public override void visit_begin_source_file (SourceFile! file) { + current_source_file = file; + current_using_directives = file.get_using_directives (); - public void analyze (CodeContext context) { - root_symbol = context.get_root (); + next_lambda_id = 0; + } - bool_type = new TypeReference (); - bool_type.type = (DataType) root_symbol.lookup ("bool").node; + public override void visit_end_source_file (SourceFile! file) { + current_using_directives = null; + } - string_type = new TypeReference (); - string_type.type = (DataType) root_symbol.lookup ("string").node; - - var glib_ns = root_symbol.lookup ("GLib"); - - initially_unowned_type = (DataType) glib_ns.lookup ("InitiallyUnowned").node; + public override void visit_begin_namespace (Namespace! ns) { + current_symbol = ns.symbol; + } - current_symbol = root_symbol; - context.accept (this); - } + public override void visit_end_namespace (Namespace! ns) { + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_begin_class (Class! cl) { + current_symbol = cl.symbol; - public override void visit_begin_source_file (SourceFile! file) { - current_source_file = file; - current_using_directives = file.get_using_directives (); - - next_lambda_id = 0; + if (cl.base_class != null) { + current_source_file.add_symbol_dependency (cl.base_class.symbol, SourceFileDependencyType.HEADER_FULL); } + } - public override void visit_end_source_file (SourceFile! file) { - current_using_directives = null; - } + public override void visit_end_class (Class! cl) { + current_symbol = current_symbol.parent_symbol; + } - public override void visit_begin_namespace (Namespace! ns) { - current_symbol = ns.symbol; - } + public override void visit_begin_struct (Struct! st) { + current_symbol = st.symbol; + } - public override void visit_end_namespace (Namespace! ns) { - current_symbol = current_symbol.parent_symbol; - } + public override void visit_end_struct (Struct! st) { + current_symbol = current_symbol.parent_symbol; + } - public override void visit_begin_class (Class! cl) { - current_symbol = cl.symbol; - - if (cl.base_class != null) { - current_source_file.add_symbol_dependency (cl.base_class.symbol, SourceFileDependencyType.HEADER_FULL); + public override void visit_field (Field! f) { + if (f.access == MemberAccessibility.PUBLIC) { + if (f.type_reference.type != null) { + /* is null if it references a type parameter */ + current_source_file.add_symbol_dependency (f.type_reference.type.symbol, SourceFileDependencyType.HEADER_SHALLOW); } - } - - public override void visit_end_class (Class! cl) { - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_begin_struct (Struct! st) { - current_symbol = st.symbol; - } - - public override void visit_end_struct (Struct! st) { - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_field (Field! f) { - if (f.access == MemberAccessibility.PUBLIC) { - if (f.type_reference.type != null) { - /* is null if it references a type parameter */ - current_source_file.add_symbol_dependency (f.type_reference.type.symbol, SourceFileDependencyType.HEADER_SHALLOW); - } - } else { - if (f.type_reference.type != null) { - /* is null if it references a type parameter */ - current_source_file.add_symbol_dependency (f.type_reference.type.symbol, SourceFileDependencyType.SOURCE); - } + } else { + if (f.type_reference.type != null) { + /* is null if it references a type parameter */ + current_source_file.add_symbol_dependency (f.type_reference.type.symbol, SourceFileDependencyType.SOURCE); } } + } - 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 */ - current_source_file.add_symbol_dependency (m.return_type.type.symbol, SourceFileDependencyType.HEADER_SHALLOW); - } + 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 */ + current_source_file.add_symbol_dependency (m.return_type.type.symbol, SourceFileDependencyType.HEADER_SHALLOW); } + } - public override void visit_end_method (Method! m) { - current_symbol = current_symbol.parent_symbol; - current_return_type = null; + public override void visit_end_method (Method! m) { + current_symbol = current_symbol.parent_symbol; + current_return_type = null; - if (current_symbol.parent_symbol.node is Method) { - /* lambda expressions produce nested methods */ - var up_method = (Method) current_symbol.parent_symbol.node; - current_return_type = up_method.return_type; - } - - if (m.is_virtual || m.is_override) { - if (current_symbol.node is Class) { - var cl = (Class) current_symbol.node; - Class base_class; - for (base_class = cl; base_class != null; base_class = base_class.base_class) { - var sym = base_class.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 (current_symbol.parent_symbol.node is Method) { + /* lambda expressions produce nested methods */ + var up_method = (Method) current_symbol.parent_symbol.node; + current_return_type = up_method.return_type; + } + + if (m.is_virtual || m.is_override) { + if (current_symbol.node is Class) { + var cl = (Class) current_symbol.node; + Class base_class; + for (base_class = cl; base_class != null; base_class = base_class.base_class) { + var sym = base_class.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) { - /* FIXME: also look at interfaces implemented - * by one of the base types - */ - foreach (TypeReference type in cl.get_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) { + /* FIXME: also look at interfaces implemented + * by one of the base types + */ + foreach (TypeReference type in cl.get_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) { - Report.error (m.source_reference, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (m.symbol.get_full_name ())); - return; } - } - } - - public override void visit_formal_parameter (FormalParameter! p) { - if (!p.ellipsis) { - if (p.type_reference.type != null) { - /* is null if it references a type parameter */ - current_source_file.add_symbol_dependency (p.type_reference.type.symbol, SourceFileDependencyType.HEADER_SHALLOW); - current_source_file.add_symbol_dependency (p.type_reference.type.symbol, SourceFileDependencyType.SOURCE); + 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) { + Report.error (m.source_reference, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (m.symbol.get_full_name ())); + return; } } + } - public override void visit_end_property (Property! prop) { - if (prop.type_reference.type != null) { + public override void visit_formal_parameter (FormalParameter! p) { + if (!p.ellipsis) { + if (p.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); - current_source_file.add_symbol_dependency (prop.type_reference.type.symbol, SourceFileDependencyType.SOURCE); + current_source_file.add_symbol_dependency (p.type_reference.type.symbol, SourceFileDependencyType.HEADER_SHALLOW); + current_source_file.add_symbol_dependency (p.type_reference.type.symbol, SourceFileDependencyType.SOURCE); } } + } - 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 (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); + current_source_file.add_symbol_dependency (prop.type_reference.type.symbol, SourceFileDependencyType.SOURCE); } + } - public override void visit_end_property_accessor (PropertyAccessor! acc) { - current_return_type = null; + 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_begin_constructor (Constructor! c) { - current_symbol = c.symbol; - } + public override void visit_end_property_accessor (PropertyAccessor! acc) { + current_return_type = null; + } - public override void visit_end_constructor (Constructor! c) { - current_symbol = current_symbol.parent_symbol; - } + public override void visit_begin_constructor (Constructor! c) { + current_symbol = c.symbol; + } - public override void visit_begin_destructor (Destructor! d) { - current_symbol = d.symbol; - } + public override void visit_end_constructor (Constructor! c) { + current_symbol = current_symbol.parent_symbol; + } - public override void visit_end_destructor (Destructor! d) { - current_symbol = current_symbol.parent_symbol; - } + public override void visit_begin_destructor (Destructor! d) { + current_symbol = d.symbol; + } - public override void visit_named_argument (NamedArgument! n) { - } + public override void visit_end_destructor (Destructor! d) { + current_symbol = current_symbol.parent_symbol; + } - public override void visit_begin_block (Block! b) { - current_symbol = b.symbol; + public override void visit_named_argument (NamedArgument! n) { + } + + public override void visit_begin_block (Block! b) { + current_symbol = b.symbol; + } + + public override void visit_end_block (Block! b) { + foreach (VariableDeclarator decl in b.get_local_variables ()) { + decl.symbol.active = false; } + + current_symbol = current_symbol.parent_symbol; + } - public override void visit_end_block (Block! b) { - foreach (VariableDeclarator decl in b.get_local_variables ()) { - decl.symbol.active = false; + public override void visit_variable_declarator (VariableDeclarator! decl) { + if (decl.type_reference == null) { + /* var type */ + + if (decl.initializer == null) { + decl.error = true; + Report.error (decl.source_reference, "var declaration not allowed without initializer"); + return; } - - current_symbol = current_symbol.parent_symbol; + if (decl.initializer.static_type == null) { + decl.error = true; + Report.error (decl.source_reference, "var declaration not allowed with non-typed initializer"); + return; + } + + decl.type_reference = decl.initializer.static_type.copy (); + decl.type_reference.is_lvalue_ref = decl.type_reference.is_ref; + decl.type_reference.is_ref = false; } - - public override void visit_variable_declarator (VariableDeclarator! decl) { - if (decl.type_reference == null) { - /* var type */ - - if (decl.initializer == null) { - decl.error = true; - Report.error (decl.source_reference, "var declaration not allowed without initializer"); - return; - } - if (decl.initializer.static_type == null) { + + if (decl.initializer != null) { + if (decl.initializer.static_type == null) { + if (!(decl.initializer is MemberAccess)) { decl.error = true; - Report.error (decl.source_reference, "var declaration not allowed with non-typed initializer"); + Report.error (decl.source_reference, "expression type not allowed as initializer"); return; } - decl.type_reference = decl.initializer.static_type.copy (); - decl.type_reference.is_lvalue_ref = decl.type_reference.is_ref; - decl.type_reference.is_ref = false; - } - - if (decl.initializer != null) { - if (decl.initializer.static_type == null) { - if (!(decl.initializer is MemberAccess)) { - decl.error = true; - Report.error (decl.source_reference, "expression type not allowed as initializer"); - return; - } + if (decl.initializer.symbol_reference.node is Method && + decl.type_reference.type is Callback) { + var m = (Method) decl.initializer.symbol_reference.node; + var cb = (Callback) decl.type_reference.type; - if (decl.initializer.symbol_reference.node is Method && - decl.type_reference.type is Callback) { - var m = (Method) decl.initializer.symbol_reference.node; - var cb = (Callback) decl.type_reference.type; - - /* check whether method matches callback type */ - if (!cb.matches_method (m)) { - decl.error = true; - Report.error (decl.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.symbol.get_full_name (), cb.symbol.get_full_name ())); - return; - } - - decl.initializer.static_type = decl.type_reference; - } else { + /* check whether method matches callback type */ + if (!cb.matches_method (m)) { decl.error = true; - Report.error (decl.source_reference, "expression type not allowed as initializer"); + Report.error (decl.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.symbol.get_full_name (), cb.symbol.get_full_name ())); return; } + + decl.initializer.static_type = decl.type_reference; + } else { + decl.error = true; + Report.error (decl.source_reference, "expression type not allowed as initializer"); + return; } - - if (memory_management) { - if (decl.initializer.static_type.is_ref) { - /* rhs transfers ownership of the expression */ - if (!decl.type_reference.is_lvalue_ref) { - /* lhs doesn't own the value - * promote lhs type */ - - decl.type_reference.is_lvalue_ref = true; - } + } + + if (memory_management) { + if (decl.initializer.static_type.is_ref) { + /* rhs transfers ownership of the expression */ + if (!decl.type_reference.is_lvalue_ref) { + /* lhs doesn't own the value + * promote lhs type */ + + decl.type_reference.is_lvalue_ref = true; } } } - - if (decl.type_reference.type != null) { - current_source_file.add_symbol_dependency (decl.type_reference.type.symbol, SourceFileDependencyType.SOURCE); - } - - decl.symbol = new Symbol (node = decl); - current_symbol.add (decl.name, decl.symbol); - - var block = (Block) current_symbol.node; - block.add_local_variable (decl); - - decl.symbol.active = true; } - - public override void visit_expression_statement (ExpressionStatement! stmt) { - if (stmt.expression.static_type != null && - stmt.expression.static_type.is_ref) { - Report.warning (stmt.source_reference, "Short-living reference"); - return; - } + + if (decl.type_reference.type != null) { + current_source_file.add_symbol_dependency (decl.type_reference.type.symbol, SourceFileDependencyType.SOURCE); } - public override void visit_begin_foreach_statement (ForeachStatement! stmt) { - if (stmt.type_reference.type != null) { - current_source_file.add_symbol_dependency (stmt.type_reference.type.symbol, SourceFileDependencyType.SOURCE); - } - - stmt.variable_declarator = new VariableDeclarator (name = stmt.variable_name); - stmt.variable_declarator.type_reference = stmt.type_reference; + decl.symbol = new Symbol (node = decl); + current_symbol.add (decl.name, decl.symbol); - stmt.variable_declarator.symbol = new Symbol (node = stmt.variable_declarator); - current_symbol.add (stmt.variable_name, stmt.variable_declarator.symbol); - } + var block = (Block) current_symbol.node; + block.add_local_variable (decl); + + decl.symbol.active = true; + } - 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_expression_statement (ExpressionStatement! stmt) { + if (stmt.expression.static_type != null && + stmt.expression.static_type.is_ref) { + Report.warning (stmt.source_reference, "Short-living reference"); + return; } + } - public override void visit_boolean_literal (BooleanLiteral! expr) { - expr.static_type = bool_type; + public override void visit_if_statement (IfStatement! stmt) { + if (stmt.condition.static_type.type != bool_type.type) { + stmt.error = true; + Report.error (stmt.condition.source_reference, "Condition must be boolean"); + return; } + } - public override void visit_character_literal (CharacterLiteral! expr) { - expr.static_type = new TypeReference (); - expr.static_type.type = (DataType) root_symbol.lookup ("char").node; + public override void visit_while_statement (WhileStatement! stmt) { + if (stmt.condition.static_type.type != bool_type.type) { + stmt.error = true; + Report.error (stmt.condition.source_reference, "Condition must be boolean"); + return; } + } - public override void visit_integer_literal (IntegerLiteral! expr) { - expr.static_type = new TypeReference (); - expr.static_type.type = (DataType) root_symbol.lookup ("int").node; + public override void visit_for_statement (ForStatement! stmt) { + if (stmt.condition.static_type.type != bool_type.type) { + stmt.error = true; + Report.error (stmt.condition.source_reference, "Condition must be boolean"); + return; } + } - public override void visit_real_literal (IntegerLiteral! expr) { - expr.static_type = new TypeReference (); - expr.static_type.type = (DataType) root_symbol.lookup ("double").node; + public override void visit_begin_foreach_statement (ForeachStatement! stmt) { + if (stmt.type_reference.type != null) { + current_source_file.add_symbol_dependency (stmt.type_reference.type.symbol, SourceFileDependencyType.SOURCE); } + + stmt.variable_declarator = new VariableDeclarator (name = stmt.variable_name); + stmt.variable_declarator.type_reference = stmt.type_reference; + + stmt.variable_declarator.symbol = new Symbol (node = stmt.variable_declarator); + current_symbol.add (stmt.variable_name, stmt.variable_declarator.symbol); + } - public override void visit_string_literal (StringLiteral! expr) { - expr.static_type = string_type; + 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_null_literal (NullLiteral! expr) { - /* empty TypeReference represents null */ - - expr.static_type = new TypeReference (); - } - - public override void visit_literal_expression (LiteralExpression! expr) { - expr.static_type = expr.literal.static_type; - } - - ref TypeReference get_static_type_for_node (CodeNode! node) { - if (node is Field) { - var f = (Field) node; - return f.type_reference; - } else if (node is Constant) { - var c = (Constant) node; - return c.type_reference; - } else if (node is Property) { - var prop = (Property) node; - var type = prop.type_reference.copy (); - type.is_lvalue_ref = false; - return type; - } else if (node is FormalParameter) { - var p = (FormalParameter) node; - return p.type_reference; - } else if (node is TypeReference) { - return (TypeReference) node; - } else if (node is VariableDeclarator) { - var decl = (VariableDeclarator) node; - return decl.type_reference; - } else if (node is EnumValue) { - var type = new TypeReference (); - type.type = (DataType) node.symbol.parent_symbol.node; - return type; - } - return null; - } - - Symbol symbol_lookup_inherited (Symbol! sym, string! name) { - var result = sym.lookup (name); - if (result == null && sym.node is Class) { - var cl = (Class) sym.node; - for (cl = cl.base_class; cl != null && result == null; cl = cl.base_class) { - result = cl.symbol.lookup (name); - } + public override void visit_boolean_literal (BooleanLiteral! expr) { + expr.static_type = bool_type; + } + + public override void visit_character_literal (CharacterLiteral! expr) { + expr.static_type = new TypeReference (); + expr.static_type.type = (DataType) root_symbol.lookup ("char").node; + } + + public override void visit_integer_literal (IntegerLiteral! expr) { + expr.static_type = new TypeReference (); + expr.static_type.type = (DataType) root_symbol.lookup ("int").node; + } + + public override void visit_real_literal (IntegerLiteral! expr) { + expr.static_type = new TypeReference (); + expr.static_type.type = (DataType) root_symbol.lookup ("double").node; + } + + public override void visit_string_literal (StringLiteral! expr) { + expr.static_type = string_type; + } + + public override void visit_null_literal (NullLiteral! expr) { + /* empty TypeReference represents null */ + + expr.static_type = new TypeReference (); + } + + public override void visit_literal_expression (LiteralExpression! expr) { + expr.static_type = expr.literal.static_type; + } + + ref TypeReference get_static_type_for_node (CodeNode! node) { + if (node is Field) { + var f = (Field) node; + return f.type_reference; + } else if (node is Constant) { + var c = (Constant) node; + return c.type_reference; + } else if (node is Property) { + var prop = (Property) node; + var type = prop.type_reference.copy (); + type.is_lvalue_ref = false; + return type; + } else if (node is FormalParameter) { + var p = (FormalParameter) node; + return p.type_reference; + } else if (node is TypeReference) { + return (TypeReference) node; + } else if (node is VariableDeclarator) { + var decl = (VariableDeclarator) node; + return decl.type_reference; + } else if (node is EnumValue) { + var type = new TypeReference (); + type.type = (DataType) node.symbol.parent_symbol.node; + return type; + } + return null; + } + + Symbol symbol_lookup_inherited (Symbol! sym, string! name) { + var result = sym.lookup (name); + if (result == null && sym.node is Class) { + var cl = (Class) sym.node; + for (cl = cl.base_class; cl != null && result == null; cl = cl.base_class) { + result = cl.symbol.lookup (name); } - return result; } + return result; + } - public override void visit_parenthesized_expression (ParenthesizedExpression! expr) { - expr.static_type = expr.inner.static_type; - } + public override void visit_parenthesized_expression (ParenthesizedExpression! expr) { + expr.static_type = expr.inner.static_type; + } - public override void visit_member_access (MemberAccess! expr) { - Symbol base_symbol = null; + public override void visit_member_access (MemberAccess! expr) { + Symbol base_symbol = null; - if (expr.inner == null) { - base_symbol = current_symbol; - - var sym = current_symbol; - while (sym != null && expr.symbol_reference == null) { - expr.symbol_reference = symbol_lookup_inherited (sym, expr.member_name); - sym = sym.parent_symbol; - } + if (expr.inner == null) { + base_symbol = current_symbol; + + var sym = current_symbol; + while (sym != null && expr.symbol_reference == null) { + expr.symbol_reference = symbol_lookup_inherited (sym, expr.member_name); + sym = sym.parent_symbol; + } - if (expr.symbol_reference == null) { - foreach (NamespaceReference ns in current_using_directives) { - var local_sym = ns.namespace_symbol.lookup (expr.member_name); - if (local_sym != null) { - if (expr.symbol_reference != null) { - Report.error (expr.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (expr.member_name, expr.symbol_reference.get_full_name (), local_sym.get_full_name ())); - return; - } - expr.symbol_reference = local_sym; + if (expr.symbol_reference == null) { + foreach (NamespaceReference ns in current_using_directives) { + var local_sym = ns.namespace_symbol.lookup (expr.member_name); + if (local_sym != null) { + if (expr.symbol_reference != null) { + Report.error (expr.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (expr.member_name, expr.symbol_reference.get_full_name (), local_sym.get_full_name ())); + return; } + expr.symbol_reference = local_sym; } } - } else { - if (expr.inner.error) { - /* if there was an error in the inner expression, skip this check */ - return; - } - - if (expr.inner is MemberAccess) { - var base = (MemberAccess) expr.inner; - base_symbol = base.symbol_reference; - if (base_symbol.node is Namespace || - base_symbol.node is DataType) { - expr.symbol_reference = base_symbol.lookup (expr.member_name); - } - } - - if (expr.symbol_reference == null && expr.inner.static_type != null) { - base_symbol = expr.inner.static_type.type.symbol; - expr.symbol_reference = symbol_lookup_inherited (base_symbol, expr.member_name); - } } - - if (expr.symbol_reference == null) { - expr.error = true; - Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, base_symbol.get_full_name ())); + } else { + if (expr.inner.error) { + /* if there was an error in the inner expression, skip this check */ return; } - - current_source_file.add_symbol_dependency (expr.symbol_reference, SourceFileDependencyType.SOURCE); - - expr.static_type = get_static_type_for_node (expr.symbol_reference.node); - } - - private bool is_type_compatible (TypeReference! expression_type, TypeReference! expected_type) { - /* only null is compatible to null */ - if (expected_type.type == null && expected_type.type_parameter == null) { - return (expression_type.type == null && expected_type.type_parameter == null); - } - - /* null can be casted to any reference or array type */ - if (expression_type.type == null && - (expected_type.type_parameter != null || - expected_type.type.is_reference_type () || - expected_type.is_ref || - expected_type.array)) { - return true; - } - /* temporarily ignore type parameters */ - if (expected_type.type_parameter != null) { - return true; - } - - if (expression_type.array != expected_type.array) { - return false; - } - - if (expression_type.type == expected_type.type) { - return true; - } - - /* int may be implicitly casted to long */ - if (expression_type.type == root_symbol.lookup ("int").node && expected_type.type == root_symbol.lookup ("long").node) { - return true; - } - - /* int may be implicitly casted to uint */ - if (expression_type.type == root_symbol.lookup ("int").node && expected_type.type == root_symbol.lookup ("uint").node) { - return true; + if (expr.inner is MemberAccess) { + var base = (MemberAccess) expr.inner; + base_symbol = base.symbol_reference; + if (base_symbol.node is Namespace || + base_symbol.node is DataType) { + expr.symbol_reference = base_symbol.lookup (expr.member_name); + } } - /* int may be implicitly casted to double */ - if (expression_type.type == root_symbol.lookup ("int").node && expected_type.type == root_symbol.lookup ("double").node) { - return true; + if (expr.symbol_reference == null && expr.inner.static_type != null) { + base_symbol = expr.inner.static_type.type.symbol; + expr.symbol_reference = symbol_lookup_inherited (base_symbol, expr.member_name); } + } - /* char may be implicitly casted to unichar */ - if (expression_type.type == root_symbol.lookup ("char").node && expected_type.type == root_symbol.lookup ("unichar").node) { + if (expr.symbol_reference == null) { + expr.error = true; + Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, base_symbol.get_full_name ())); + return; + } + + current_source_file.add_symbol_dependency (expr.symbol_reference, SourceFileDependencyType.SOURCE); + + expr.static_type = get_static_type_for_node (expr.symbol_reference.node); + } + + private bool is_type_compatible (TypeReference! expression_type, TypeReference! expected_type) { + /* only null is compatible to null */ + if (expected_type.type == null && expected_type.type_parameter == null) { + return (expression_type.type == null && expected_type.type_parameter == null); + } + + /* null can be casted to any reference or array type */ + if (expression_type.type == null && + (expected_type.type_parameter != null || + expected_type.type.is_reference_type () || + expected_type.is_ref || + expected_type.array)) { + return true; + } + + /* temporarily ignore type parameters */ + if (expected_type.type_parameter != null) { + return true; + } + + if (expression_type.array != expected_type.array) { + return false; + } + + if (expression_type.type == expected_type.type) { + return true; + } + + /* int may be implicitly casted to long */ + if (expression_type.type == root_symbol.lookup ("int").node && expected_type.type == root_symbol.lookup ("long").node) { + return true; + } + + /* int may be implicitly casted to uint */ + if (expression_type.type == root_symbol.lookup ("int").node && expected_type.type == root_symbol.lookup ("uint").node) { + return true; + } + + /* int may be implicitly casted to double */ + if (expression_type.type == root_symbol.lookup ("int").node && expected_type.type == root_symbol.lookup ("double").node) { + return true; + } + + /* char may be implicitly casted to unichar */ + if (expression_type.type == root_symbol.lookup ("char").node && expected_type.type == root_symbol.lookup ("unichar").node) { + return true; + } + + /* non-class types must match exactly */ + if (!(expression_type.type is Class)) { + return false; + } + + var cl = (Class) expression_type.type; + + var base_class = cl.base_class; + for (; base_class != null; base_class = base_class.base_class) { + if (base_class == expected_type.type) { return true; } - - /* non-class types must match exactly */ - if (!(expression_type.type is Class)) { - return false; - } - - var cl = (Class) expression_type.type; - - var base_class = cl.base_class; - for (; base_class != null; base_class = base_class.base_class) { - if (base_class == expected_type.type) { - return true; - } - } - - return false; } + + return false; + } - public override void visit_begin_invocation_expression (InvocationExpression! expr) { - if (expr.call.error) { - /* if method resolving didn't succeed, skip this check */ + public override void visit_begin_invocation_expression (InvocationExpression! expr) { + if (expr.call.error) { + /* if method resolving didn't succeed, skip this check */ + expr.error = true; + return; + } + + var msym = expr.call.symbol_reference; + + List params; + + if (msym.node is VariableDeclarator) { + var decl = (VariableDeclarator) msym.node; + if (decl.type_reference.type is Callback) { + var cb = (Callback) decl.type_reference.type; + params = cb.get_parameters (); + } else { expr.error = true; + Report.error (expr.source_reference, "invocation not supported in this context"); return; } - - var msym = expr.call.symbol_reference; - - List params; - - if (msym.node is VariableDeclarator) { - var decl = (VariableDeclarator) msym.node; - if (decl.type_reference.type is Callback) { - var cb = (Callback) decl.type_reference.type; - params = cb.get_parameters (); - } else { - expr.error = true; - Report.error (expr.source_reference, "invocation not supported in this context"); - return; - } - } else if (msym.node is FormalParameter) { - var param = (FormalParameter) msym.node; - if (param.type_reference.type is Callback) { - var cb = (Callback) param.type_reference.type; - params = cb.get_parameters (); - } else { - expr.error = true; - Report.error (expr.source_reference, "invocation not supported in this context"); - return; - } - } else if (msym.node is Method) { - var m = (Method) msym.node; - params = m.parameters; + } else if (msym.node is FormalParameter) { + var param = (FormalParameter) msym.node; + if (param.type_reference.type is Callback) { + var cb = (Callback) param.type_reference.type; + params = cb.get_parameters (); } else { expr.error = true; Report.error (expr.source_reference, "invocation not supported in this context"); return; } - - List arg_it = expr.argument_list; - foreach (FormalParameter param in params) { - if (param.ellipsis) { - break; - } - - if (arg_it != null) { - var arg = (Expression) arg_it.data; + } else if (msym.node is Method) { + var m = (Method) msym.node; + params = m.parameters; + } else { + expr.error = true; + Report.error (expr.source_reference, "invocation not supported in this context"); + return; + } + + List arg_it = expr.argument_list; + foreach (FormalParameter param in params) { + if (param.ellipsis) { + break; + } + + if (arg_it != null) { + var arg = (Expression) arg_it.data; - /* store expected type for callback parameters */ - arg.expected_type = param.type_reference; - - arg_it = arg_it.next; - } + /* store expected type for callback parameters */ + arg.expected_type = param.type_reference; + + arg_it = arg_it.next; } } + } - public override void visit_end_invocation_expression (InvocationExpression! expr) { - if (expr.error) { - return; + public override void visit_end_invocation_expression (InvocationExpression! expr) { + if (expr.error) { + return; + } + + var msym = expr.call.symbol_reference; + + TypeReference ret_type; + List params; + + if (msym.node is VariableDeclarator) { + var decl = (VariableDeclarator) msym.node; + var cb = (Callback) decl.type_reference.type; + ret_type = cb.return_type; + params = cb.get_parameters (); + } else if (msym.node is FormalParameter) { + var param = (FormalParameter) msym.node; + var cb = (Callback) param.type_reference.type; + ret_type = cb.return_type; + params = cb.get_parameters (); + } else if (msym.node is Method) { + var m = (Method) msym.node; + ret_type = m.return_type; + params = m.parameters; + } + + expr.static_type = ret_type; + + List arg_it = expr.argument_list; + + bool ellipsis = false; + int i = 0; + foreach (FormalParameter param in params) { + if (param.ellipsis) { + ellipsis = true; + break; } - - var msym = expr.call.symbol_reference; - - TypeReference ret_type; - List params; - - if (msym.node is VariableDeclarator) { - var decl = (VariableDeclarator) msym.node; - var cb = (Callback) decl.type_reference.type; - ret_type = cb.return_type; - params = cb.get_parameters (); - } else if (msym.node is FormalParameter) { - var param = (FormalParameter) msym.node; - var cb = (Callback) param.type_reference.type; - ret_type = cb.return_type; - params = cb.get_parameters (); - } else if (msym.node is Method) { - var m = (Method) msym.node; - ret_type = m.return_type; - params = m.parameters; + + /* header file necessary if we need to cast argument */ + if (param.type_reference.type != null) { + current_source_file.add_symbol_dependency (param.type_reference.type.symbol, SourceFileDependencyType.SOURCE); } - - expr.static_type = ret_type; - - List arg_it = expr.argument_list; - - bool ellipsis = false; - int i = 0; - foreach (FormalParameter param in params) { - if (param.ellipsis) { - ellipsis = true; - break; - } - /* header file necessary if we need to cast argument */ - if (param.type_reference.type != null) { - current_source_file.add_symbol_dependency (param.type_reference.type.symbol, SourceFileDependencyType.SOURCE); + if (arg_it == null) { + if (param.default_expression == null) { + Report.error (expr.source_reference, "Method `%s' does not take %d arguments".printf (msym.get_full_name (), expr.argument_list.length ())); + return; } - - if (arg_it == null) { - if (param.default_expression == null) { - Report.error (expr.source_reference, "Method `%s' does not take %d arguments".printf (msym.get_full_name (), expr.argument_list.length ())); - return; - } - } else { - var arg = (Expression) arg_it.data; - if (arg.static_type != null && !is_type_compatible (arg.static_type, param.type_reference)) { - /* if there was an error in the argument, - * i.e. arg.static_type == null, skip type check */ - Report.error (expr.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.static_type.to_string (), param.type_reference.to_string ())); - return; - } - - arg_it = arg_it.next; - - i++; + } else { + var arg = (Expression) arg_it.data; + if (arg.static_type != null && !is_type_compatible (arg.static_type, param.type_reference)) { + /* if there was an error in the argument, + * i.e. arg.static_type == null, skip type check */ + Report.error (expr.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.static_type.to_string (), param.type_reference.to_string ())); + return; } - } - - if (!ellipsis && arg_it != null) { - Report.error (expr.source_reference, "Method `%s' does not take %d arguments".printf (msym.get_full_name (), expr.argument_list.length ())); - return; - } - } + + arg_it = arg_it.next; - public override void visit_object_creation_expression (ObjectCreationExpression! expr) { - if (expr.type_reference.type == null) { - /* if type resolving didn't succeed, skip this check */ - return; + i++; } + } - current_source_file.add_symbol_dependency (expr.type_reference.type.symbol, SourceFileDependencyType.SOURCE); + if (!ellipsis && arg_it != null) { + Report.error (expr.source_reference, "Method `%s' does not take %d arguments".printf (msym.get_full_name (), expr.argument_list.length ())); + return; + } + } - expr.static_type = expr.type_reference.copy (); - expr.static_type.is_ref = true; - - var cl = (Class) expr.type_reference.type; - while (cl != null) { - if (cl == initially_unowned_type) { - expr.static_type.floating_reference = true; - break; - } - - cl = cl.base_class; - } + public override void visit_object_creation_expression (ObjectCreationExpression! expr) { + if (expr.type_reference.type == null) { + /* if type resolving didn't succeed, skip this check */ + return; } + + current_source_file.add_symbol_dependency (expr.type_reference.type.symbol, SourceFileDependencyType.SOURCE); - public override void visit_unary_expression (UnaryExpression! expr) { - if (expr.inner.static_type == null) { - /* if there was an error in the inner expression, skip type check */ - return; + expr.static_type = expr.type_reference.copy (); + expr.static_type.is_ref = true; + + var cl = (Class) expr.type_reference.type; + while (cl != null) { + if (cl == initially_unowned_type) { + expr.static_type.floating_reference = true; + break; } - if (expr.operator == UnaryOperator.PLUS || expr.operator == UnaryOperator.MINUS) { - // integer or floating point type + cl = cl.base_class; + } + } - expr.static_type = expr.inner.static_type; - } else if (expr.operator == UnaryOperator.LOGICAL_NEGATION) { - // boolean type + public override void visit_unary_expression (UnaryExpression! expr) { + if (expr.inner.static_type == null) { + /* if there was an error in the inner expression, skip type check */ + return; + } + + if (expr.operator == UnaryOperator.PLUS || expr.operator == UnaryOperator.MINUS) { + // integer or floating point type - expr.static_type = expr.inner.static_type; - } else if (expr.operator == UnaryOperator.BITWISE_COMPLEMENT) { - // integer type + expr.static_type = expr.inner.static_type; + } else if (expr.operator == UnaryOperator.LOGICAL_NEGATION) { + // boolean type - expr.static_type = expr.inner.static_type; - } else if (expr.operator == UnaryOperator.REF) { - // value type + expr.static_type = expr.inner.static_type; + } else if (expr.operator == UnaryOperator.BITWISE_COMPLEMENT) { + // integer type - expr.static_type = expr.inner.static_type; - } else if (expr.operator == UnaryOperator.OUT) { - // reference type + expr.static_type = expr.inner.static_type; + } else if (expr.operator == UnaryOperator.REF) { + // value type - expr.static_type = expr.inner.static_type; - } else { - assert_not_reached (); - } + expr.static_type = expr.inner.static_type; + } else if (expr.operator == UnaryOperator.OUT) { + // reference type + + expr.static_type = expr.inner.static_type; + } else { + assert_not_reached (); } + } - public override void visit_cast_expression (CastExpression! expr) { - if (expr.type_reference.type == null) { - /* if type resolving didn't succeed, skip this check */ - return; - } - - current_source_file.add_symbol_dependency (expr.type_reference.type.symbol, SourceFileDependencyType.SOURCE); + public override void visit_cast_expression (CastExpression! expr) { + if (expr.type_reference.type == null) { + /* if type resolving didn't succeed, skip this check */ + return; + } + + current_source_file.add_symbol_dependency (expr.type_reference.type.symbol, SourceFileDependencyType.SOURCE); - expr.static_type = expr.type_reference; + expr.static_type = expr.type_reference; + } + + private bool check_binary_type (BinaryExpression! expr, string! operation) { + if (!is_type_compatible (expr.right.static_type, expr.left.static_type)) { + Report.error (expr.source_reference, "%s: Cannot convert from `%s' to `%s'".printf (operation, expr.right.static_type.to_string (), expr.left.static_type.to_string ())); + return false; } - private bool check_binary_type (BinaryExpression! expr, string! operation) { - if (!is_type_compatible (expr.right.static_type, expr.left.static_type)) { - Report.error (expr.source_reference, "%s: Cannot convert from `%s' to `%s'".printf (operation, expr.right.static_type.to_string (), expr.left.static_type.to_string ())); - return false; - } - - return true; + return true; + } + + public override void visit_binary_expression (BinaryExpression! expr) { + if (expr.left.static_type == null + || expr.right.static_type == null) { + /* if there were any errors in inner expressions, skip type check */ + return; } - - public override void visit_binary_expression (BinaryExpression! expr) { - if (expr.left.static_type == null - || expr.right.static_type == null) { - /* if there were any errors in inner expressions, skip type check */ + + if (expr.left.static_type.type == string_type.type + && expr.operator == BinaryOperator.PLUS) { + if (expr.right.static_type.type != string_type.type) { + Report.error (expr.source_reference, "Operands must be strings"); + } + + expr.static_type = string_type; + } else if (expr.operator == BinaryOperator.PLUS + || expr.operator == BinaryOperator.MINUS + || expr.operator == BinaryOperator.MUL + || expr.operator == BinaryOperator.DIV) { + // TODO: check for integer or floating point type in expr.left + + if (!check_binary_type (expr, "Arithmetic operation")) { return; } - - if (expr.left.static_type.type == string_type.type - && expr.operator == BinaryOperator.PLUS) { - if (expr.right.static_type.type != string_type.type) { - Report.error (expr.source_reference, "Operands must be strings"); - } - expr.static_type = string_type; - } else if (expr.operator == BinaryOperator.PLUS - || expr.operator == BinaryOperator.MINUS - || expr.operator == BinaryOperator.MUL - || expr.operator == BinaryOperator.DIV) { - // TODO: check for integer or floating point type in expr.left + expr.static_type = expr.left.static_type; + } else if (expr.operator == BinaryOperator.MOD + || expr.operator == BinaryOperator.SHIFT_LEFT + || expr.operator == BinaryOperator.SHIFT_RIGHT + || expr.operator == BinaryOperator.BITWISE_XOR) { + // TODO: check for integer type in expr.left - if (!check_binary_type (expr, "Arithmetic operation")) { - return; - } + if (!check_binary_type (expr, "Arithmetic operation")) { + return; + } - expr.static_type = expr.left.static_type; - } else if (expr.operator == BinaryOperator.MOD - || expr.operator == BinaryOperator.SHIFT_LEFT - || expr.operator == BinaryOperator.SHIFT_RIGHT - || expr.operator == BinaryOperator.BITWISE_XOR) { - // TODO: check for integer type in expr.left + expr.static_type = expr.left.static_type; + } else if (expr.operator == BinaryOperator.LESS_THAN + || expr.operator == BinaryOperator.GREATER_THAN + || expr.operator == BinaryOperator.LESS_THAN_OR_EQUAL + || expr.operator == BinaryOperator.GREATER_THAN_OR_EQUAL) { + if (expr.left.static_type.type == string_type.type + && expr.right.static_type.type == string_type.type) { + /* string comparison: convert to a.collate (b) OP 0 */ + + var cmp_call = new InvocationExpression (call = new MemberAccess (inner = expr.left, member_name = "collate")); + cmp_call.add_argument (expr.right); + expr.left = cmp_call; + + expr.right = new LiteralExpression (literal = new IntegerLiteral (value = "0")); + + expr.left.accept (this); + } else { + /* TODO: check for integer or floating point type in expr.left */ - if (!check_binary_type (expr, "Arithmetic operation")) { + if (!check_binary_type (expr, "Relational operation")) { return; } + } + + expr.static_type = bool_type; + } else if (expr.operator == BinaryOperator.EQUALITY + || expr.operator == BinaryOperator.INEQUALITY) { + /* relational operation */ - expr.static_type = expr.left.static_type; - } else if (expr.operator == BinaryOperator.LESS_THAN - || expr.operator == BinaryOperator.GREATER_THAN - || expr.operator == BinaryOperator.LESS_THAN_OR_EQUAL - || expr.operator == BinaryOperator.GREATER_THAN_OR_EQUAL) { - if (expr.left.static_type.type == string_type.type - && expr.right.static_type.type == string_type.type) { - /* string comparison: convert to a.collate (b) OP 0 */ - - var cmp_call = new InvocationExpression (call = new MemberAccess (inner = expr.left, member_name = "collate")); - cmp_call.add_argument (expr.right); - expr.left = cmp_call; - - expr.right = new LiteralExpression (literal = new IntegerLiteral (value = "0")); - - expr.left.accept (this); - } else { - /* TODO: check for integer or floating point type in expr.left */ - - if (!check_binary_type (expr, "Relational operation")) { - return; - } - } + 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; + } + + if (expr.left.static_type.type == string_type.type + && expr.right.static_type.type == string_type.type) { + /* string comparison: convert to a.collate (b) OP 0 */ - expr.static_type = bool_type; - } else if (expr.operator == BinaryOperator.EQUALITY - || expr.operator == BinaryOperator.INEQUALITY) { - /* relational operation */ - - 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; - } + var cmp_call = new InvocationExpression (call = new MemberAccess (inner = expr.left, member_name = "collate")); + cmp_call.add_argument (expr.right); + expr.left = cmp_call; - if (expr.left.static_type.type == string_type.type - && expr.right.static_type.type == string_type.type) { - /* string comparison: convert to a.collate (b) OP 0 */ - - var cmp_call = new InvocationExpression (call = new MemberAccess (inner = expr.left, member_name = "collate")); - cmp_call.add_argument (expr.right); - expr.left = cmp_call; - - expr.right = new LiteralExpression (literal = new IntegerLiteral (value = "0")); - - expr.left.accept (this); - } + expr.right = new LiteralExpression (literal = new IntegerLiteral (value = "0")); + + expr.left.accept (this); + } - expr.static_type = bool_type; - } else if (expr.operator == BinaryOperator.BITWISE_AND - || expr.operator == BinaryOperator.BITWISE_OR) { - // integer type or flags type + expr.static_type = bool_type; + } else if (expr.operator == BinaryOperator.BITWISE_AND + || expr.operator == BinaryOperator.BITWISE_OR) { + // integer type or flags type + + expr.static_type = expr.left.static_type; + } else if (expr.operator == BinaryOperator.AND + || expr.operator == BinaryOperator.OR) { + if (expr.left.static_type.type != bool_type.type || expr.right.static_type.type != bool_type.type) { + Report.error (expr.source_reference, "Operands must be boolean"); + } - expr.static_type = expr.left.static_type; - } else if (expr.operator == BinaryOperator.AND - || expr.operator == BinaryOperator.OR) { - if (expr.left.static_type.type != bool_type.type || expr.right.static_type.type != bool_type.type) { - Report.error (expr.source_reference, "Operands must be boolean"); - } + expr.static_type = bool_type; + } else { + assert_not_reached (); + } + } - expr.static_type = bool_type; - } else { - assert_not_reached (); - } + public override void visit_type_check (TypeCheck! expr) { + if (expr.type_reference.type == null) { + /* if type resolving didn't succeed, skip this check */ + return; } + + current_source_file.add_symbol_dependency (expr.type_reference.type.symbol, SourceFileDependencyType.SOURCE); - public override void visit_type_check (TypeCheck! expr) { - if (expr.type_reference.type == null) { - /* if type resolving didn't succeed, skip this check */ - return; - } - - current_source_file.add_symbol_dependency (expr.type_reference.type.symbol, SourceFileDependencyType.SOURCE); + expr.static_type = bool_type; + } - expr.static_type = bool_type; + public override void visit_conditional_expression (ConditionalExpression! expr) { + if (expr.condition.static_type.type != bool_type.type) { + expr.error = true; + Report.error (expr.condition.source_reference, "Condition must be boolean"); + return; } - private ref string get_lambda_name () { - var result = "__lambda%d".printf (next_lambda_id); + /* FIXME: use greatest lower bound in the type hierarchy */ + expr.static_type = expr.true_expression.static_type; + } + + private ref string get_lambda_name () { + var result = "__lambda%d".printf (next_lambda_id); - next_lambda_id++; - - return result; - } + next_lambda_id++; - private Method find_current_method () { - var sym = current_symbol; - while (sym != null) { - if (sym.node is Method) { - return (Method) sym.node; - } - sym = sym.parent_symbol; + return result; + } + + private Method find_current_method () { + var sym = current_symbol; + while (sym != null) { + if (sym.node is Method) { + return (Method) sym.node; } - return null; + sym = sym.parent_symbol; } + return null; + } - public override void visit_begin_lambda_expression (LambdaExpression! l) { - if (l.expected_type == null || !(l.expected_type.type is Callback)) { - l.error = true; - Report.error (l.source_reference, "lambda expression not allowed in this context"); - return; - } - - var current_method = find_current_method (); - - var cb = (Callback) l.expected_type.type; - l.method = new Method (name = get_lambda_name (), return_type = cb.return_type); - l.method.instance = cb.instance && current_method.instance; - l.method.symbol = new Symbol (node = l.method); - l.method.symbol.parent_symbol = current_symbol; - - var lambda_params = l.get_parameters (); - var lambda_param_it = lambda_params; - foreach (FormalParameter cb_param in cb.get_parameters ()) { - if (lambda_param_it == null) { - /* lambda expressions are allowed to have less parameters */ - break; - } - - var lambda_param = (string) lambda_param_it.data; - - var param = new FormalParameter (name = lambda_param); - param.type_reference = cb_param.type_reference; - param.symbol = new Symbol (node = param); - l.method.symbol.add (param.name, param.symbol); - - l.method.add_parameter (param); - - lambda_param_it = lambda_param_it.next; + public override void visit_begin_lambda_expression (LambdaExpression! l) { + if (l.expected_type == null || !(l.expected_type.type is Callback)) { + l.error = true; + Report.error (l.source_reference, "lambda expression not allowed in this context"); + return; + } + + var current_method = find_current_method (); + + var cb = (Callback) l.expected_type.type; + l.method = new Method (name = get_lambda_name (), return_type = cb.return_type); + l.method.instance = cb.instance && current_method.instance; + l.method.symbol = new Symbol (node = l.method); + l.method.symbol.parent_symbol = current_symbol; + + var lambda_params = l.get_parameters (); + var lambda_param_it = lambda_params; + foreach (FormalParameter cb_param in cb.get_parameters ()) { + if (lambda_param_it == null) { + /* lambda expressions are allowed to have less parameters */ + break; } - if (lambda_param_it != null) { - /* lambda expressions may not expect more parameters */ - l.error = true; - Report.error (l.source_reference, "lambda expression: too many parameters"); - return; - } + var lambda_param = (string) lambda_param_it.data; - var block = new Block (); - block.symbol = new Symbol (node = block); - block.symbol.parent_symbol = l.method.symbol; - if (l.method.return_type.type != null) { - block.add_statement (new ReturnStatement (return_expression = l.inner)); - } else { - block.add_statement (new ExpressionStatement (expression = l.inner)); - } + var param = new FormalParameter (name = lambda_param); + param.type_reference = cb_param.type_reference; + param.symbol = new Symbol (node = param); + l.method.symbol.add (param.name, param.symbol); - l.method.body = block; + l.method.add_parameter (param); - /* lambda expressions should be usable like MemberAccess of a method */ - l.symbol_reference = l.method.symbol; + lambda_param_it = lambda_param_it.next; + } + + if (lambda_param_it != null) { + /* lambda expressions may not expect more parameters */ + l.error = true; + Report.error (l.source_reference, "lambda expression: too many parameters"); + return; + } + + var block = new Block (); + block.symbol = new Symbol (node = block); + block.symbol.parent_symbol = l.method.symbol; + if (l.method.return_type.type != null) { + block.add_statement (new ReturnStatement (return_expression = l.inner)); + } else { + block.add_statement (new ExpressionStatement (expression = l.inner)); } + + l.method.body = block; + + /* lambda expressions should be usable like MemberAccess of a method */ + l.symbol_reference = l.method.symbol; + } - public override void visit_begin_assignment (Assignment! a) { - var ma = (MemberAccess) a.left; - - if (ma.symbol_reference.node is Signal) { - var sig = (Signal) ma.symbol_reference.node; + public override void visit_begin_assignment (Assignment! a) { + var ma = (MemberAccess) a.left; + + if (ma.symbol_reference.node is Signal) { + var sig = (Signal) ma.symbol_reference.node; - a.right.expected_type = new TypeReference (); - a.right.expected_type.type = sig.get_callback (); - } + a.right.expected_type = new TypeReference (); + a.right.expected_type.type = sig.get_callback (); } + } - public override void visit_end_assignment (Assignment! a) { - if (!(a.left is MemberAccess)) { - a.error = true; - Report.error (a.source_reference, "unsupported lvalue in assignment"); - return; - } + public override void visit_end_assignment (Assignment! a) { + if (!(a.left is MemberAccess)) { + a.error = true; + Report.error (a.source_reference, "unsupported lvalue in assignment"); + return; + } + + var ma = (MemberAccess) a.left; - var ma = (MemberAccess) a.left; + if (ma.symbol_reference.node is Signal) { + var sig = (Signal) ma.symbol_reference.node; + } else if (ma.symbol_reference.node is Property) { + var prop = (Property) ma.symbol_reference.node; + } else if (ma.symbol_reference.node is VariableDeclarator && a.right.static_type == null) { + var decl = (VariableDeclarator) ma.symbol_reference.node; - if (ma.symbol_reference.node is Signal) { - var sig = (Signal) ma.symbol_reference.node; - } else if (ma.symbol_reference.node is Property) { - var prop = (Property) ma.symbol_reference.node; - } else if (ma.symbol_reference.node is VariableDeclarator && a.right.static_type == null) { - var decl = (VariableDeclarator) ma.symbol_reference.node; + var right_ma = (MemberAccess) a.right; + if (right_ma.symbol_reference.node is Method && + decl.type_reference.type is Callback) { + var m = (Method) right_ma.symbol_reference.node; + var cb = (Callback) decl.type_reference.type; - var right_ma = (MemberAccess) a.right; - if (right_ma.symbol_reference.node is Method && - decl.type_reference.type is Callback) { - var m = (Method) right_ma.symbol_reference.node; - var cb = (Callback) decl.type_reference.type; - - /* check whether method matches callback type */ - if (!cb.matches_method (m)) { - decl.error = true; - Report.error (a.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.symbol.get_full_name (), cb.symbol.get_full_name ())); - return; - } - - a.right.static_type = decl.type_reference; - } else { - a.error = true; - Report.error (a.source_reference, "Assignment: Invalid callback assignment attempt"); - return; - } - } else if (a.left.static_type != null && a.right.static_type != null) { - if (!is_type_compatible (a.right.static_type, a.left.static_type)) { - /* if there was an error on either side, - * i.e. a.{left|right}.static_type == null, skip type check */ - Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ())); + /* check whether method matches callback type */ + if (!cb.matches_method (m)) { + decl.error = true; + Report.error (a.source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.symbol.get_full_name (), cb.symbol.get_full_name ())); return; } - if (memory_management) { - if (a.right.static_type.is_ref) { - /* rhs transfers ownership of the expression */ - if (!a.left.static_type.is_lvalue_ref) { - /* lhs doesn't own the value - * promote lhs type if it is a local variable - * error if it's not a local variable */ - if (!(ma.symbol_reference.node is VariableDeclarator)) { - Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable"); - } - - a.left.static_type.is_lvalue_ref = true; + a.right.static_type = decl.type_reference; + } else { + a.error = true; + Report.error (a.source_reference, "Assignment: Invalid callback assignment attempt"); + return; + } + } else if (a.left.static_type != null && a.right.static_type != null) { + if (!is_type_compatible (a.right.static_type, a.left.static_type)) { + /* if there was an error on either side, + * i.e. a.{left|right}.static_type == null, skip type check */ + Report.error (a.source_reference, "Assignment: Cannot convert from `%s' to `%s'".printf (a.right.static_type.to_string (), a.left.static_type.to_string ())); + return; + } + + if (memory_management) { + if (a.right.static_type.is_ref) { + /* rhs transfers ownership of the expression */ + if (!a.left.static_type.is_lvalue_ref) { + /* lhs doesn't own the value + * promote lhs type if it is a local variable + * error if it's not a local variable */ + if (!(ma.symbol_reference.node is VariableDeclarator)) { + Report.error (a.source_reference, "Invalid assignment from owned expression to unowned variable"); } - } else if (a.left.static_type.is_lvalue_ref) { - /* lhs wants to own the value - * rhs doesn't transfer the ownership - * code generator needs to add reference - * increment calls */ + + a.left.static_type.is_lvalue_ref = true; } + } else if (a.left.static_type.is_lvalue_ref) { + /* lhs wants to own the value + * rhs doesn't transfer the ownership + * code generator needs to add reference + * increment calls */ } } - - a.static_type = a.left.static_type; } + + a.static_type = a.left.static_type; } } diff --git a/vala/vala/valasymbolbuilder.vala b/vala/vala/valasymbolbuilder.vala index 187275d..32302ee 100644 --- a/vala/vala/valasymbolbuilder.vala +++ b/vala/vala/valasymbolbuilder.vala @@ -22,286 +22,292 @@ using GLib; -namespace Vala { - public class SymbolBuilder : CodeVisitor { - Symbol root; - Symbol current_type; - Symbol current_symbol; - - public void build (CodeContext! context) { - root = context.get_root (); - context.accept (this); +/** + * Code visitor building the symbol tree. + */ +public class Vala.SymbolBuilder : CodeVisitor { + Symbol root; + Symbol current_type; + Symbol current_symbol; + + /** + * Build the symbol tree for the specified code context. + * + * @param context a code context + */ + public void build (CodeContext! context) { + root = context.get_root (); + context.accept (this); + } + + public override void visit_begin_namespace (Namespace! ns) { + if (ns.name == null) { + ns.symbol = root; } - public override void visit_begin_namespace (Namespace! ns) { - if (ns.name == null) { - ns.symbol = root; - } - - if (ns.symbol == null) { - ns.symbol = root.lookup (ns.name); - } - if (ns.symbol == null) { - ns.symbol = new Symbol (node = ns); - root.add (ns.name, ns.symbol); - } - - current_symbol = ns.symbol; + if (ns.symbol == null) { + ns.symbol = root.lookup (ns.name); } - - public override void visit_end_namespace (Namespace! ns) { - current_symbol = current_symbol.parent_symbol; + if (ns.symbol == null) { + ns.symbol = new Symbol (node = ns); + root.add (ns.name, ns.symbol); } - private Symbol add_symbol (string! name, CodeNode! node) { - if (current_symbol.lookup (name) != null) { - node.error = true; - Report.error (node.source_reference, "`%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), name)); - return null; - } - node.symbol = new Symbol (node = node); - current_symbol.add (name, node.symbol); - - return node.symbol; - } + current_symbol = ns.symbol; + } - public override void visit_begin_class (Class! cl) { - if (add_symbol (cl.name, cl) == null) { - return; - } - - current_symbol = cl.symbol; - } - - public override void visit_end_class (Class! cl) { - if (cl.error) { - /* skip classes with errors */ - return; - } - - current_symbol = current_symbol.parent_symbol; - } + public override void visit_end_namespace (Namespace! ns) { + current_symbol = current_symbol.parent_symbol; + } + + private Symbol add_symbol (string! name, CodeNode! node) { + if (current_symbol.lookup (name) != null) { + node.error = true; + Report.error (node.source_reference, "`%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), name)); + return null; + } + node.symbol = new Symbol (node = node); + current_symbol.add (name, node.symbol); - public override void visit_begin_struct (Struct! st) { - if (add_symbol (st.name, st) == null) { - return; - } - - current_symbol = st.symbol; + return node.symbol; + } + + public override void visit_begin_class (Class! cl) { + if (add_symbol (cl.name, cl) == null) { + return; } - public override void visit_end_struct (Struct! st) { - if (st.error) { - /* skip structs with errors */ - return; - } - - current_symbol = current_symbol.parent_symbol; - } + current_symbol = cl.symbol; + } - public override void visit_begin_interface (Interface! iface) { - if (add_symbol (iface.name, iface) == null) { - return; - } - - current_symbol = iface.symbol; + public override void visit_end_class (Class! cl) { + if (cl.error) { + /* skip classes with errors */ + return; } - public override void visit_end_interface (Interface! iface) { - if (iface.error) { - /* skip interfaces with errors */ - return; - } - - current_symbol = current_symbol.parent_symbol; + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_begin_struct (Struct! st) { + if (add_symbol (st.name, st) == null) { + return; } - public override void visit_begin_enum (Enum! en) { - if (add_symbol (en.name, en) == null) { - return; - } - - current_symbol = en.symbol; + current_symbol = st.symbol; + } + + public override void visit_end_struct (Struct! st) { + if (st.error) { + /* skip structs with errors */ + return; } - public override void visit_end_enum (Enum! en) { - if (en.error) { - /* skip enums with errors */ - return; - } - - current_symbol = current_symbol.parent_symbol; - } + current_symbol = current_symbol.parent_symbol; + } - public override void visit_enum_value (EnumValue! ev) { - ev.symbol = new Symbol (node = ev); - current_symbol.add (ev.name, ev.symbol); + public override void visit_begin_interface (Interface! iface) { + if (add_symbol (iface.name, iface) == null) { + return; } - public override void visit_begin_callback (Callback! cb) { - if (add_symbol (cb.name, cb) == null) { - return; - } - - current_symbol = cb.symbol; + current_symbol = iface.symbol; + } + + public override void visit_end_interface (Interface! iface) { + if (iface.error) { + /* skip interfaces with errors */ + return; } - 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) { - add_symbol (c.name, c); + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_begin_enum (Enum! en) { + if (add_symbol (en.name, en) == null) { + return; } - public override void visit_field (Field! f) { - add_symbol (f.name, f); + current_symbol = en.symbol; + } + + public override void visit_end_enum (Enum! en) { + if (en.error) { + /* skip enums with errors */ + return; } - public override void visit_begin_method (Method! m) { - if (add_symbol (m.name, m) == null) { - return; - } - - 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; + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_enum_value (EnumValue! ev) { + ev.symbol = new Symbol (node = ev); + current_symbol.add (ev.name, ev.symbol); + } + + public override void visit_begin_callback (Callback! cb) { + if (add_symbol (cb.name, cb) == null) { + return; } - public override void visit_end_method (Method! m) { - if (m.error) { - /* skip methods with errors */ - return; - } - - current_symbol = current_symbol.parent_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_formal_parameter (FormalParameter! p) { - if (!p.ellipsis) { - add_symbol (p.name, p); - } + public override void visit_constant (Constant! c) { + add_symbol (c.name, c); + } + + public override void visit_field (Field! f) { + add_symbol (f.name, f); + } + + public override void visit_begin_method (Method! m) { + if (add_symbol (m.name, m) == null) { + return; } - public override void visit_begin_property (Property! prop) { - if (add_symbol (prop.name, prop) == null) { + 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; } - - current_symbol = prop.symbol; - - prop.this_parameter = new FormalParameter (name = "this", type_reference = new TypeReference ()); - prop.this_parameter.type_reference.type = (DataType) prop.symbol.parent_symbol.node; - prop.this_parameter.symbol = new Symbol (node = prop.this_parameter); - current_symbol.add (prop.this_parameter.name, prop.this_parameter.symbol); + + 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); } - public override void visit_end_property (Property! prop) { - if (prop.error) { - /* skip properties with errors */ - return; - } - - current_symbol = current_symbol.parent_symbol; + current_symbol = m.symbol; + } + + public override void visit_end_method (Method! m) { + if (m.error) { + /* skip methods with errors */ + return; } - public override void visit_begin_property_accessor (PropertyAccessor! acc) { - acc.symbol = new Symbol (node = acc); - acc.symbol.parent_symbol = current_symbol; - current_symbol = acc.symbol; - - if (acc.writable || acc.construct_) { - acc.value_parameter = new FormalParameter (name = "value", type_reference = ((Property) current_symbol.parent_symbol.node).type_reference); - acc.value_parameter.symbol = new Symbol (node = acc.value_parameter); - - current_symbol.add (acc.value_parameter.name, acc.value_parameter.symbol); - } + current_symbol = current_symbol.parent_symbol; + } - 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 MemberAccess (member_name = "_%s".printf (prop.name)))); - } else { - block.add_statement (new ExpressionStatement (expression = new Assignment (left = new MemberAccess (member_name = "_%s".printf (prop.name)), right = new MemberAccess (member_name = "value")))); - } - acc.body = block; - } + public override void visit_formal_parameter (FormalParameter! p) { + if (!p.ellipsis) { + add_symbol (p.name, p); + } + } + + public override void visit_begin_property (Property! prop) { + if (add_symbol (prop.name, prop) == null) { + return; } - public override void visit_end_property_accessor (PropertyAccessor! acc) { - current_symbol = current_symbol.parent_symbol; + current_symbol = prop.symbol; + + prop.this_parameter = new FormalParameter (name = "this", type_reference = new TypeReference ()); + prop.this_parameter.type_reference.type = (DataType) prop.symbol.parent_symbol.node; + prop.this_parameter.symbol = new Symbol (node = prop.this_parameter); + current_symbol.add (prop.this_parameter.name, prop.this_parameter.symbol); + } + + public override void visit_end_property (Property! prop) { + if (prop.error) { + /* skip properties with errors */ + return; } + + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_begin_property_accessor (PropertyAccessor! acc) { + acc.symbol = new Symbol (node = acc); + acc.symbol.parent_symbol = current_symbol; + current_symbol = acc.symbol; - public override void visit_begin_signal (Signal! sig) { - if (add_symbol (sig.name, sig) == null) { - return; - } + if (acc.writable || acc.construct_) { + acc.value_parameter = new FormalParameter (name = "value", type_reference = ((Property) current_symbol.parent_symbol.node).type_reference); + acc.value_parameter.symbol = new Symbol (node = acc.value_parameter); - current_symbol = sig.symbol; + current_symbol.add (acc.value_parameter.name, acc.value_parameter.symbol); } - public override void visit_end_signal (Signal! sig) { - if (sig.error) { - /* skip signals with errors */ - return; - } + if (acc.body == null) { + /* no accessor body specified, insert default body */ + + var prop = (Property) acc.symbol.parent_symbol.node; - current_symbol = current_symbol.parent_symbol; + var block = new Block (); + if (acc.readable) { + block.add_statement (new ReturnStatement (return_expression = new MemberAccess (member_name = "_%s".printf (prop.name)))); + } else { + block.add_statement (new ExpressionStatement (expression = new Assignment (left = new MemberAccess (member_name = "_%s".printf (prop.name)), right = new MemberAccess (member_name = "value")))); + } + acc.body = block; } + } + + public override void visit_end_property_accessor (PropertyAccessor! acc) { + current_symbol = current_symbol.parent_symbol; + } - 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_begin_signal (Signal! sig) { + if (add_symbol (sig.name, sig) == null) { + return; } + + current_symbol = sig.symbol; + } - public override void visit_end_constructor (Constructor! c) { - current_symbol = current_symbol.parent_symbol; + public override void visit_end_signal (Signal! sig) { + if (sig.error) { + /* skip signals with errors */ + return; } + + current_symbol = current_symbol.parent_symbol; + } - 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_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_destructor (Destructor! d) { - current_symbol = current_symbol.parent_symbol; - } + public override void visit_end_constructor (Constructor! c) { + current_symbol = current_symbol.parent_symbol; + } - public override void visit_begin_block (Block! b) { - b.symbol = new Symbol (node = b); - b.symbol.parent_symbol = current_symbol; - current_symbol = b.symbol; - } + public override void visit_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_block (Block! b) { - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_type_parameter (TypeParameter! p) { - add_symbol (p.name, p); - } + public override void visit_end_destructor (Destructor! d) { + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_begin_block (Block! b) { + b.symbol = new Symbol (node = b); + b.symbol.parent_symbol = current_symbol; + current_symbol = b.symbol; + } + + public override void visit_end_block (Block! b) { + current_symbol = current_symbol.parent_symbol; + } + + public override void visit_type_parameter (TypeParameter! p) { + add_symbol (p.name, p); } } diff --git a/vala/vala/valasymbolresolver.vala b/vala/vala/valasymbolresolver.vala index 737fc07..5107638 100644 --- a/vala/vala/valasymbolresolver.vala +++ b/vala/vala/valasymbolresolver.vala @@ -22,130 +22,136 @@ using GLib; -namespace Vala { - public class SymbolResolver : CodeVisitor { - Symbol root_symbol; - Symbol current_scope; - List current_using_directives; +/** + * Code visitor resolving symbol names. + */ +public class Vala.SymbolResolver : CodeVisitor { + Symbol root_symbol; + Symbol current_scope; + List current_using_directives; + + Class object_class; + + /** + * Resolve symbol names in the specified code context. + * + * @param context a code context + */ + public void resolve (CodeContext! context) { + root_symbol = context.get_root (); + current_scope = root_symbol; - Class object_class; + object_class = (Class) root_symbol.lookup ("GLib").lookup ("Object").node; - public void resolve (CodeContext context) { - root_symbol = context.get_root (); - current_scope = root_symbol; - - object_class = (Class) root_symbol.lookup ("GLib").lookup ("Object").node; - - context.accept (this); - } - - public override void visit_begin_source_file (SourceFile file) { - current_using_directives = file.get_using_directives (); - } + context.accept (this); + } + + public override void visit_begin_source_file (SourceFile! file) { + current_using_directives = file.get_using_directives (); + } - public override void visit_end_source_file (SourceFile file) { - current_using_directives = null; - } - - public override void visit_begin_namespace (Namespace ns) { - current_scope = ns.symbol; - } + public override void visit_end_source_file (SourceFile! file) { + current_using_directives = null; + } + + public override void visit_begin_namespace (Namespace! ns) { + current_scope = ns.symbol; + } - public override void visit_end_namespace (Namespace ns) { - current_scope = current_scope.parent_symbol; - } + public override void visit_end_namespace (Namespace! ns) { + current_scope = current_scope.parent_symbol; + } - public override void visit_begin_class (Class cl) { - current_scope = cl.symbol; - } + public override void visit_begin_class (Class! cl) { + current_scope = cl.symbol; + } - public override void visit_end_class (Class cl) { - foreach (TypeReference type in cl.get_base_types ()) { - if (type.type is Class) { - if (cl.base_class != null) { - Report.error (type.source_reference, "%s: Classes cannot have multiple base classes (`%s' and `%s')".printf (cl.symbol.get_full_name (), cl.base_class.symbol.get_full_name (), type.type.symbol.get_full_name ())); - return; - } - cl.base_class = (Class) type.type; + public override void visit_end_class (Class! cl) { + foreach (TypeReference type in cl.get_base_types ()) { + if (type.type is Class) { + if (cl.base_class != null) { + Report.error (type.source_reference, "%s: Classes cannot have multiple base classes (`%s' and `%s')".printf (cl.symbol.get_full_name (), cl.base_class.symbol.get_full_name (), type.type.symbol.get_full_name ())); + return; } + cl.base_class = (Class) type.type; } - if (cl.base_class == null && cl != object_class) { - cl.base_class = object_class; - } - - current_scope = current_scope.parent_symbol; } - - public override void visit_begin_struct (Struct st) { - current_scope = st.symbol; + if (cl.base_class == null && cl != object_class) { + cl.base_class = object_class; } + + current_scope = current_scope.parent_symbol; + } - public override void visit_end_struct (Struct st) { - current_scope = current_scope.parent_symbol; - } + public override void visit_begin_struct (Struct! st) { + current_scope = st.symbol; + } - public override void visit_namespace_reference (NamespaceReference ns) { - ns.namespace_symbol = current_scope.lookup (ns.name); - if (ns.namespace_symbol == null) { - Report.error (ns.source_reference, "The namespace name `%s' could not be found".printf (ns.name)); - return; - } + public override void visit_end_struct (Struct! st) { + current_scope = current_scope.parent_symbol; + } + + public override void visit_namespace_reference (NamespaceReference! ns) { + ns.namespace_symbol = current_scope.lookup (ns.name); + if (ns.namespace_symbol == null) { + Report.error (ns.source_reference, "The namespace name `%s' could not be found".printf (ns.name)); + return; } + } - public override void visit_type_reference (TypeReference type) { - if (type.type_name == "void") { - return; + public override void visit_type_reference (TypeReference! type) { + if (type.type_name == "void") { + return; + } + + if (type.namespace_name == null) { + Symbol sym = null; + Symbol scope = current_scope; + while (sym == null && scope != null) { + sym = scope.lookup (type.type_name); + scope = scope.parent_symbol; } - - if (type.namespace_name == null) { - Symbol sym = null; - Symbol scope = current_scope; - while (sym == null && scope != null) { - sym = scope.lookup (type.type_name); - scope = scope.parent_symbol; - } - if (sym == null) { - foreach (NamespaceReference ns in current_using_directives) { - var local_sym = ns.namespace_symbol.lookup (type.type_name); - if (local_sym != null) { - if (sym != null) { - Report.error (type.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (type.type_name, sym.get_full_name (), local_sym.get_full_name ())); - return; - } - sym = local_sym; + if (sym == null) { + foreach (NamespaceReference ns in current_using_directives) { + var local_sym = ns.namespace_symbol.lookup (type.type_name); + if (local_sym != null) { + if (sym != null) { + Report.error (type.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (type.type_name, sym.get_full_name (), local_sym.get_full_name ())); + return; } + sym = local_sym; } } - if (sym == null) { - Report.error (type.source_reference, "The type name `%s' could not be found".printf (type.type_name)); - return; - } - if (sym.node is TypeParameter) { - type.type_parameter = (TypeParameter) sym.node; - } else { - type.type = (DataType) sym.node; - } + } + if (sym == null) { + Report.error (type.source_reference, "The type name `%s' could not be found".printf (type.type_name)); + return; + } + if (sym.node is TypeParameter) { + type.type_parameter = (TypeParameter) sym.node; } else { - var ns_symbol = root_symbol.lookup (type.namespace_name); - if (ns_symbol == null) { - Report.error (type.source_reference, "The namespace name `%s' could not be found".printf (type.namespace_name)); - return; - } - - var sym = ns_symbol.lookup (type.type_name); - if (sym == null) { - Report.error (type.source_reference, "The type name `%s' does not exist in the namespace `%s'".printf (type.type_name, type.namespace_name)); - return; - } type.type = (DataType) sym.node; } + } else { + var ns_symbol = root_symbol.lookup (type.namespace_name); + if (ns_symbol == null) { + Report.error (type.source_reference, "The namespace name `%s' could not be found".printf (type.namespace_name)); + return; + } - if (type.type != null && !type.type.is_reference_type ()) { - /* reset is_lvalue_ref for contexts where types - * are ref by default (field declarations) - */ - type.is_lvalue_ref = false; + var sym = ns_symbol.lookup (type.type_name); + if (sym == null) { + Report.error (type.source_reference, "The type name `%s' does not exist in the namespace `%s'".printf (type.type_name, type.namespace_name)); + return; } + type.type = (DataType) sym.node; + } + + if (type.type != null && !type.type.is_reference_type ()) { + /* reset is_lvalue_ref for contexts where types + * are ref by default (field declarations) + */ + type.is_lvalue_ref = false; } } } -- 2.7.4