diff options
author | Jürg Billeter <j@bitron.ch> | 2007-05-03 09:54:30 +0000 |
---|---|---|
committer | Jürg Billeter <juergbi@src.gnome.org> | 2007-05-03 09:54:30 +0000 |
commit | ec85900a21288ea1894350dde49e2609c3f2af88 (patch) | |
tree | ca49ba56dc4ccb0d6a0f9e2874211cb91e5a171b /vala | |
parent | 7a65d693c55ed8f4bdee9e698296434ba066e528 (diff) | |
download | vala-ec85900a21288ea1894350dde49e2609c3f2af88.tar.gz |
move code generator to new gobject directory update
2007-05-03 Jürg Billeter <j@bitron.ch>
* gobject/valacodegenerator.vala: move code generator to new gobject
directory
* configure.ac, Makefile.am, vala/Makefile.am, gobject/Makefile.am,
compiler/Makefile.am, vapi/Makefile.am: update
svn path=/trunk/; revision=305
Diffstat (limited to 'vala')
-rw-r--r-- | vala/Makefile.am | 14 | ||||
-rw-r--r-- | vala/valacodegenerator.vala | 4177 |
2 files changed, 5 insertions, 4186 deletions
diff --git a/vala/Makefile.am b/vala/Makefile.am index f9a1fb15c..73f724be0 100644 --- a/vala/Makefile.am +++ b/vala/Makefile.am @@ -7,11 +7,11 @@ INCLUDES = \ BUILT_SOURCES = parser.h vala.vala.stamp AM_YFLAGS = -d -lib_LTLIBRARIES = \ - libvala.la +noinst_LTLIBRARIES = \ + libvalacore.la $(NULL) -libvala_la_SOURCES = \ +libvalacore_la_SOURCES = \ parser.y \ scanner.l \ vala.h \ @@ -76,9 +76,6 @@ libvala_la_SOURCES = \ valacodecontext.c \ valacodecontext.h \ valacodecontext.vala \ - valacodegenerator.c \ - valacodegenerator.h \ - valacodegenerator.vala \ valacodenode.c \ valacodenode.h \ valacodenode.vala \ @@ -352,7 +349,6 @@ valainclude_HEADERS = \ valaclass.h \ valaclassregisterfunction.h \ valacodecontext.h \ - valacodegenerator.h \ valacodenode.h \ valacodevisitor.h \ valaconditionalexpression.h \ @@ -438,11 +434,11 @@ valainclude_HEADERS = \ valawhilestatement.h \ $(NULL) -vala.vala vala.vala.stamp: $(filter %.vala,$(libvala_la_SOURCES)) +vala.vala vala.vala.stamp: $(filter %.vala,$(libvalacore_la_SOURCES)) $(VALAC) --vapidir $(srcdir)/../vapi --vapidir ../ccode --pkg ccode --library vala $^ touch $@ -libvala_la_LIBADD = \ +libvalacore_la_LIBADD = \ $(GLIB_LIBS) \ ../ccode/libvalaccode.la \ $(NULL) diff --git a/vala/valacodegenerator.vala b/vala/valacodegenerator.vala deleted file mode 100644 index 8a8807142..000000000 --- a/vala/valacodegenerator.vala +++ /dev/null @@ -1,4177 +0,0 @@ -/* valacodegenerator.vala - * - * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Author: - * Jürg Billeter <j@bitron.ch> - * Raffaele Sandrini <rasa@gmx.ch> - */ - -using GLib; - -/** - * Code visitor generating C Code. - */ -public class Vala.CodeGenerator : CodeVisitor { - /** - * Specifies whether automatic memory management is active. - */ - public bool memory_management { get; set; } - - private CodeContext context; - - Symbol root_symbol; - Symbol current_symbol; - Symbol current_type_symbol; - Class current_class; - TypeReference current_return_type; - - 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_signal_marshaller_declaration; - CCodeFragment source_type_member_definition; - CCodeFragment instance_init_fragment; - CCodeFragment instance_dispose_fragment; - CCodeFragment source_signal_marshaller_definition; - CCodeFragment module_init_fragment; - - CCodeStruct instance_struct; - CCodeStruct type_struct; - CCodeStruct instance_priv_struct; - CCodeEnum prop_enum; - CCodeEnum cenum; - CCodeFunction function; - CCodeBlock block; - - /* all temporary variables */ - List<VariableDeclarator> temp_vars; - /* temporary variables that own their content */ - List<VariableDeclarator> temp_ref_vars; - /* cache to check whether a certain marshaller has been created yet */ - HashTable<string,bool> user_marshal_list; - /* (constant) hash table with all predefined marshallers */ - HashTable<string,bool> predefined_marshal_list; - - private int next_temp_var_id = 0; - private bool in_creation_method = false; - - TypeReference bool_type; - TypeReference char_type; - TypeReference unichar_type; - TypeReference short_type; - TypeReference ushort_type; - TypeReference int_type; - TypeReference uint_type; - TypeReference long_type; - TypeReference ulong_type; - TypeReference int64_type; - TypeReference uint64_type; - TypeReference string_type; - TypeReference float_type; - TypeReference double_type; - DataType list_type; - DataType slist_type; - TypeReference mutex_type; - DataType type_module_type; - - private bool in_plugin = false; - private string module_init_param_name; - - private bool string_h_needed; - - public CodeGenerator (bool manage_memory = true) { - memory_management = manage_memory; - } - - construct { - predefined_marshal_list = new HashTable (str_hash, str_equal); - predefined_marshal_list.insert ("VOID:VOID", true); - predefined_marshal_list.insert ("VOID:BOOLEAN", true); - predefined_marshal_list.insert ("VOID:CHAR", true); - predefined_marshal_list.insert ("VOID:UCHAR", true); - predefined_marshal_list.insert ("VOID:INT", true); - predefined_marshal_list.insert ("VOID:UINT", true); - predefined_marshal_list.insert ("VOID:LONG", true); - predefined_marshal_list.insert ("VOID:ULONG", true); - predefined_marshal_list.insert ("VOID:ENUM", true); - predefined_marshal_list.insert ("VOID:FLAGS", true); - predefined_marshal_list.insert ("VOID:FLOAT", true); - predefined_marshal_list.insert ("VOID:DOUBLE", true); - predefined_marshal_list.insert ("VOID:STRING", true); - predefined_marshal_list.insert ("VOID:POINTER", true); - predefined_marshal_list.insert ("VOID:OBJECT", true); - predefined_marshal_list.insert ("STRING:OBJECT,POINTER", true); - predefined_marshal_list.insert ("VOID:UINT,POINTER", true); - predefined_marshal_list.insert ("BOOLEAN:FLAGS", true); - } - - /** - * Generate and emit C code for the specified code context. - * - * @param context a code context - */ - public void emit (CodeContext! context) { - this.context = context; - - context.find_header_cycles (); - - root_symbol = context.get_root (); - - bool_type = new TypeReference (); - bool_type.data_type = (DataType) root_symbol.lookup ("bool").node; - - char_type = new TypeReference (); - char_type.data_type = (DataType) root_symbol.lookup ("char").node; - - unichar_type = new TypeReference (); - unichar_type.data_type = (DataType) root_symbol.lookup ("unichar").node; - - short_type = new TypeReference (); - short_type.data_type = (DataType) root_symbol.lookup ("short").node; - - ushort_type = new TypeReference (); - ushort_type.data_type = (DataType) root_symbol.lookup ("ushort").node; - - int_type = new TypeReference (); - int_type.data_type = (DataType) root_symbol.lookup ("int").node; - - uint_type = new TypeReference (); - uint_type.data_type = (DataType) root_symbol.lookup ("uint").node; - - long_type = new TypeReference (); - long_type.data_type = (DataType) root_symbol.lookup ("long").node; - - ulong_type = new TypeReference (); - ulong_type.data_type = (DataType) root_symbol.lookup ("ulong").node; - - int64_type = new TypeReference (); - int64_type.data_type = (DataType) root_symbol.lookup ("int64").node; - - uint64_type = new TypeReference (); - uint64_type.data_type = (DataType) root_symbol.lookup ("uint64").node; - - float_type = new TypeReference (); - float_type.data_type = (DataType) root_symbol.lookup ("float").node; - - double_type = new TypeReference (); - double_type.data_type = (DataType) root_symbol.lookup ("double").node; - - string_type = new TypeReference (); - string_type.data_type = (DataType) root_symbol.lookup ("string").node; - - var glib_ns = root_symbol.lookup ("GLib"); - - list_type = (DataType) glib_ns.lookup ("List").node; - slist_type = (DataType) glib_ns.lookup ("SList").node; - - mutex_type = new TypeReference (); - mutex_type.data_type = (DataType) glib_ns.lookup ("Mutex").node; - - type_module_type = (DataType) glib_ns.lookup ("TypeModule").node; - - if (context.module_init_method != null) { - module_init_fragment = new CCodeFragment (); - foreach (FormalParameter parameter in context.module_init_method.get_parameters ()) { - if (parameter.type_reference.data_type == type_module_type) { - in_plugin = true; - module_init_param_name = parameter.name; - break; - } - } - } - - /* 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); - } - } - } - - private ref CCodeIncludeDirective get_internal_include (string! filename) { - return new CCodeIncludeDirective (filename, context.library == null); - } - - 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 (); - source_signal_marshaller_definition = new CCodeFragment (); - source_signal_marshaller_declaration = new CCodeFragment (); - - user_marshal_list = new HashTable (str_hash, str_equal); - - next_temp_var_id = 0; - - string_h_needed = false; - - header_begin.append (new CCodeIncludeDirective ("glib.h")); - header_begin.append (new CCodeIncludeDirective ("glib-object.h")); - source_include_directives.append (new CCodeIncludeDirective (source_file.get_cheader_filename (), true)); - - ref List<weak string> used_includes = null; - used_includes.append ("glib.h"); - used_includes.append ("glib-object.h"); - used_includes.append (source_file.get_cheader_filename ()); - - foreach (string filename1 in source_file.get_header_external_includes ()) { - if (used_includes.find_custom (filename1, strcmp) == null) { - header_begin.append (new CCodeIncludeDirective (filename1)); - used_includes.append (filename1); - } - } - foreach (string filename2 in source_file.get_header_internal_includes ()) { - if (used_includes.find_custom (filename2, strcmp) == null) { - header_begin.append (get_internal_include (filename2)); - used_includes.append (filename2); - } - } - foreach (string filename3 in source_file.get_source_external_includes ()) { - if (used_includes.find_custom (filename3, strcmp) == null) { - source_include_directives.append (new CCodeIncludeDirective (filename3)); - used_includes.append (filename3); - } - } - foreach (string filename4 in source_file.get_source_internal_includes ()) { - if (used_includes.find_custom (filename4, strcmp) == null) { - source_include_directives.append (get_internal_include (filename4)); - used_includes.append (filename4); - } - } - 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 ("struct _%s".printf (st.get_cname ()), new CCodeVariableDeclarator (st.get_cname ()))); - } - var classes = ns.get_classes (); - foreach (Class cl in classes) { - header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (cl.get_cname ()), new CCodeVariableDeclarator (cl.get_cname ()))); - header_type_declaration.append (new CCodeTypeDefinition ("struct _%sClass".printf (cl.get_cname ()), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ())))); - } - var ifaces = ns.get_interfaces (); - foreach (Interface iface in ifaces) { - header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (iface.get_cname ()), new CCodeVariableDeclarator (iface.get_cname ()))); - header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (iface.get_type_cname ()), new CCodeVariableDeclarator (iface.get_type_cname ()))); - } - } - } - } - - /* generate hardcoded "well-known" macros */ - source_begin.append (new CCodeMacroReplacement ("VALA_FREE_CHECKED(o,f)", "((o) == NULL ? NULL : ((o) = (f (o), NULL)))")); - source_begin.append (new CCodeMacroReplacement ("VALA_FREE_UNCHECKED(o,f)", "((o) = (f (o), NULL))")); - } - - private static ref string get_define_for_filename (string! filename) { - var define = new String ("__"); - - var i = filename; - while (i.len () > 0) { - var c = i.get_char (); - if (c.isalnum () && c < 0x80) { - define.append_unichar (c.toupper ()); - } else { - define.append_c ('_'); - } - - i = i.next_char (); - } - - 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 ()); - - if (string_h_needed) { - source_include_directives.append (new CCodeIncludeDirective ("string.h")); - } - - CCodeComment comment = null; - if (source_file.comment != null) { - comment = new CCodeComment (source_file.comment); - } - - var writer = new CCodeWriter (source_file.get_cheader_filename ()); - if (comment != null) { - comment.write (writer); - } - writer.write_newline (); - var once = new CCodeOnceSection (header_define); - once.append (new CCodeNewline ()); - once.append (header_begin); - once.append (new CCodeNewline ()); - once.append (new CCodeIdentifier ("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 ("G_END_DECLS")); - once.append (new CCodeNewline ()); - once.append (new CCodeNewline ()); - once.write (writer); - writer.close (); - - writer = new CCodeWriter (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_signal_marshaller_declaration.write (writer); - writer.write_newline (); - source_type_member_definition.write (writer); - writer.write_newline (); - source_signal_marshaller_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; - source_signal_marshaller_definition = null; - source_signal_marshaller_declaration = null; - } - - public override void visit_begin_class (Class! cl) { - current_symbol = cl.symbol; - current_type_symbol = cl.symbol; - current_class = cl; - - if (cl.is_static) { - return; - } - - instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ())); - type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ())); - instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ())); - prop_enum = new CCodeEnum (); - prop_enum.add_value ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null)), null); - instance_init_fragment = new CCodeFragment (); - instance_dispose_fragment = new CCodeFragment (); - - - header_type_declaration.append (new CCodeNewline ()); - var macro = "(%s_get_type ())".printf (cl.get_lower_case_cname (null)); - header_type_declaration.append (new CCodeMacroReplacement (cl.get_upper_case_cname ("TYPE_"), 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 ("%s(obj)".printf (cl.get_upper_case_cname (null)), 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 ("%s_CLASS(klass)".printf (cl.get_upper_case_cname (null)), macro)); - - macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl.get_upper_case_cname ("TYPE_")); - header_type_declaration.append (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname ("IS_")), macro)); - - macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl.get_upper_case_cname ("TYPE_")); - header_type_declaration.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname ("IS_")), 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 ("%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), macro)); - header_type_declaration.append (new CCodeNewline ()); - - - if (cl.source_reference.file.cycle == null) { - header_type_declaration.append (new CCodeTypeDefinition ("struct %s".printf (instance_struct.name), new CCodeVariableDeclarator (cl.get_cname ()))); - header_type_declaration.append (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ())))); - } - header_type_declaration.append (new CCodeTypeDefinition ("struct %s".printf (instance_priv_struct.name), new CCodeVariableDeclarator ("%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"); - - if (cl.source_reference.comment != null) { - header_type_definition.append (new CCodeComment (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 ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro)); - source_type_member_declaration.append (prop_enum); - } - - public override void visit_end_class (Class! cl) { - if (!cl.is_static) { - add_get_property_function (cl); - add_set_property_function (cl); - add_class_init_function (cl); - - foreach (TypeReference base_type in cl.get_base_types ()) { - if (base_type.data_type is Interface) { - add_interface_init_function (cl, (Interface) base_type.data_type); - } - } - - add_instance_init_function (cl); - if (memory_management && cl.get_fields () != null) { - add_dispose_function (cl); - } - - var type_fun = new ClassRegisterFunction (cl); - type_fun.init_from_type (in_plugin); - header_type_member_declaration.append (type_fun.get_declaration ()); - source_type_member_definition.append (type_fun.get_definition ()); - - if (in_plugin) { - // FIXME resolve potential dependency issues, i.e. base types have to be registered before derived types - var register_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_register_type".printf (cl.get_lower_case_cname (null)))); - register_call.add_argument (new CCodeIdentifier (module_init_param_name)); - module_init_fragment.append (new CCodeExpressionStatement (register_call)); - } - } - - current_type_symbol = null; - current_class = null; - instance_dispose_fragment = null; - } - - private void add_class_init_function (Class! cl) { - var class_init = new CCodeFunction ("%s_class_init".printf (cl.get_lower_case_cname (null)), "void"); - class_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ()))); - class_init.modifiers = CCodeModifiers.STATIC; - - var init_block = new CCodeBlock (); - class_init.block = init_block; - - ref CCodeFunctionCall ccall; - - /* save pointer to parent class */ - var parent_decl = new CCodeDeclaration ("gpointer"); - var parent_var_decl = new CCodeVariableDeclarator ("%s_parent_class".printf (cl.get_lower_case_cname (null))); - parent_var_decl.initializer = new CCodeConstant ("NULL"); - parent_decl.add_declarator (parent_var_decl); - parent_decl.modifiers = CCodeModifiers.STATIC; - source_type_member_declaration.append (parent_decl); - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent")); - ccall.add_argument (new CCodeIdentifier ("klass")); - var parent_assignment = new CCodeAssignment (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null))), ccall); - init_block.add_statement (new CCodeExpressionStatement (parent_assignment)); - - /* add struct for private fields */ - if (cl.has_private_fields) { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_add_private")); - ccall.add_argument (new CCodeIdentifier ("klass")); - ccall.add_argument (new CCodeConstant ("sizeof (%sPrivate)".printf (cl.get_cname ()))); - init_block.add_statement (new CCodeExpressionStatement (ccall)); - } - - /* set property handlers */ - ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); - ccall.add_argument (new CCodeIdentifier ("klass")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "get_property"), new CCodeIdentifier ("%s_get_property".printf (cl.get_lower_case_cname (null)))))); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "set_property"), new CCodeIdentifier ("%s_set_property".printf (cl.get_lower_case_cname (null)))))); - - /* set constructor */ - if (cl.constructor != null) { - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); - ccast.add_argument (new CCodeIdentifier ("klass")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "constructor"), new CCodeIdentifier ("%s_constructor".printf (cl.get_lower_case_cname (null)))))); - } - - /* set dispose function */ - if (memory_management && cl.get_fields () != null) { - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); - ccast.add_argument (new CCodeIdentifier ("klass")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "dispose"), new CCodeIdentifier ("%s_dispose".printf (cl.get_lower_case_cname (null)))))); - } - - /* connect overridden methods */ - var methods = cl.get_methods (); - foreach (Method m in methods) { - if (m.base_method == null) { - continue; - } - var base_type = m.base_method.symbol.parent_symbol.node; - - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null)))); - ccast.add_argument (new CCodeIdentifier ("klass")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.name), new CCodeIdentifier (m.get_real_cname ())))); - } - - /* create destroy_func properties for generic types */ - foreach (TypeParameter type_param in cl.get_type_parameters ()) { - string func_name = "%s_destroy_func".printf (type_param.name.down ()); - var func_name_constant = new CCodeConstant ("\"%s-destroy-func\"".printf (type_param.name.down ())); - string enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up (); - var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); - cinst.add_argument (ccall); - cinst.add_argument (new CCodeConstant (enum_value)); - var cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_pointer")); - cspec.add_argument (func_name_constant); - cspec.add_argument (new CCodeConstant ("\"destroy func\"")); - cspec.add_argument (new CCodeConstant ("\"destroy func\"")); - cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY")); - cinst.add_argument (cspec); - init_block.add_statement (new CCodeExpressionStatement (cinst)); - prop_enum.add_value (enum_value, null); - - instance_priv_struct.add_field ("GDestroyNotify", func_name); - } - - /* create properties */ - var props = cl.get_properties (); - foreach (Property prop in props) { - if (prop.overrides || prop.base_interface_property != null) { - var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_override_property")); - cinst.add_argument (ccall); - cinst.add_argument (new CCodeConstant (prop.get_upper_case_cname ())); - cinst.add_argument (prop.get_canonical_cconstant ()); - - init_block.add_statement (new CCodeExpressionStatement (cinst)); - } else { - var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); - cinst.add_argument (ccall); - cinst.add_argument (new CCodeConstant (prop.get_upper_case_cname ())); - cinst.add_argument (get_param_spec (prop)); - - init_block.add_statement (new CCodeExpressionStatement (cinst)); - } - } - - /* create signals */ - foreach (Signal sig in cl.get_signals ()) { - init_block.add_statement (new CCodeExpressionStatement (get_signal_creation (sig, cl))); - } - - source_type_member_definition.append (class_init); - } - - private void add_interface_init_function (Class! cl, Interface! iface) { - var iface_init = new CCodeFunction ("%s_%s_interface_init".printf (cl.get_lower_case_cname (null), iface.get_lower_case_cname (null)), "void"); - iface_init.add_parameter (new CCodeFormalParameter ("iface", "%s *".printf (iface.get_type_cname ()))); - iface_init.modifiers = CCodeModifiers.STATIC; - - var init_block = new CCodeBlock (); - iface_init.block = init_block; - - ref CCodeFunctionCall ccall; - - /* save pointer to parent vtable */ - string parent_iface_var = "%s_%s_parent_iface".printf (cl.get_lower_case_cname (null), iface.get_lower_case_cname (null)); - var parent_decl = new CCodeDeclaration (iface.get_type_cname () + "*"); - var parent_var_decl = new CCodeVariableDeclarator (parent_iface_var); - parent_var_decl.initializer = new CCodeConstant ("NULL"); - parent_decl.add_declarator (parent_var_decl); - parent_decl.modifiers = CCodeModifiers.STATIC; - source_type_member_declaration.append (parent_decl); - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent")); - ccall.add_argument (new CCodeIdentifier ("iface")); - var parent_assignment = new CCodeAssignment (new CCodeIdentifier (parent_iface_var), ccall); - init_block.add_statement (new CCodeExpressionStatement (parent_assignment)); - - var methods = cl.get_methods (); - foreach (Method m in methods) { - if (m.base_interface_method == null) { - continue; - } - - var base_type = m.base_interface_method.symbol.parent_symbol.node; - if (base_type != iface) { - continue; - } - - var ciface = new CCodeIdentifier ("iface"); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.name), new CCodeIdentifier (m.get_real_cname ())))); - } - - source_type_member_definition.append (iface_init); - } - - private void add_instance_init_function (Class! cl) { - var instance_init = new CCodeFunction ("%s_init".printf (cl.get_lower_case_cname (null)), "void"); - instance_init.add_parameter (new CCodeFormalParameter ("self", "%s *".printf (cl.get_cname ()))); - instance_init.modifiers = CCodeModifiers.STATIC; - - var init_block = new CCodeBlock (); - instance_init.block = init_block; - - if (cl.has_private_fields) { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null)))); - ccall.add_argument (new CCodeIdentifier ("self")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall))); - } - - init_block.add_statement (instance_init_fragment); - - 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 ("%s_dispose".printf (cl.get_lower_case_cname (null)), "void"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeFormalParameter ("obj", "GObject *")); - - source_type_member_declaration.append (function.copy ()); - - - var cblock = new CCodeBlock (); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null))); - ccall.add_argument (new CCodeIdentifier ("obj")); - - var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall)); - - cblock.add_statement (cdecl); - - cblock.add_statement (instance_dispose_fragment); - - cdecl = new CCodeDeclaration ("%sClass *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator ("klass")); - cblock.add_statement (cdecl); - - cdecl = new CCodeDeclaration ("GObjectClass *"); - cdecl.add_declarator (new CCodeVariableDeclarator ("parent_class")); - cblock.add_statement (cdecl); - - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek")); - ccall.add_argument (new CCodeIdentifier (cl.get_upper_case_cname ("TYPE_"))); - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (cl.get_upper_case_cname (null)))); - ccast.add_argument (ccall); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("klass"), ccast))); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent")); - ccall.add_argument (new CCodeIdentifier ("klass")); - ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); - ccast.add_argument (ccall); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_class"), ccast))); - - - ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier ("parent_class"), "dispose")); - ccall.add_argument (new CCodeIdentifier ("obj")); - cblock.add_statement (new CCodeExpressionStatement (ccall)); - - - function.block = cblock; - - source_type_member_definition.append (function); - } - - private ref CCodeIdentifier! get_value_setter_function (TypeReference! type_reference) { - if (type_reference.data_type is Class || type_reference.data_type is Interface) { - return new CCodeIdentifier ("g_value_set_object"); - } else if (type_reference.data_type == string_type.data_type) { - return new CCodeIdentifier ("g_value_set_string"); - } else if (type_reference.data_type == int_type.data_type - || type_reference.data_type is Enum) { - return new CCodeIdentifier ("g_value_set_int"); - } else if (type_reference.data_type == uint_type.data_type) { - return new CCodeIdentifier ("g_value_set_uint"); - } else if (type_reference.data_type == long_type.data_type) { - return new CCodeIdentifier ("g_value_set_long"); - } else if (type_reference.data_type == ulong_type.data_type) { - return new CCodeIdentifier ("g_value_set_ulong"); - } else if (type_reference.data_type == bool_type.data_type) { - return new CCodeIdentifier ("g_value_set_boolean"); - } else if (type_reference.data_type == float_type.data_type) { - return new CCodeIdentifier ("g_value_set_float"); - } else if (type_reference.data_type == double_type.data_type) { - return new CCodeIdentifier ("g_value_set_double"); - } else { - return new CCodeIdentifier ("g_value_set_pointer"); - } - } - - private void add_get_property_function (Class! cl) { - var get_prop = new CCodeFunction ("%s_get_property".printf (cl.get_lower_case_cname (null)), "void"); - get_prop.modifiers = CCodeModifiers.STATIC; - get_prop.add_parameter (new CCodeFormalParameter ("object", "GObject *")); - get_prop.add_parameter (new CCodeFormalParameter ("property_id", "guint")); - get_prop.add_parameter (new CCodeFormalParameter ("value", "GValue *")); - get_prop.add_parameter (new CCodeFormalParameter ("pspec", "GParamSpec *")); - - var block = new CCodeBlock (); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null))); - ccall.add_argument (new CCodeIdentifier ("object")); - var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall)); - block.add_statement (cdecl); - - var cswitch = new CCodeSwitchStatement (new CCodeIdentifier ("property_id")); - var props = cl.get_properties (); - foreach (Property prop in props) { - if (prop.get_accessor == null || prop.is_abstract) { - continue; - } - - bool is_virtual = prop.base_property != null || prop.base_interface_property != null; - - string prefix = cl.get_lower_case_cname (null); - if (is_virtual) { - prefix += "_real"; - } - - var ccase = new CCodeCaseStatement (new CCodeIdentifier (prop.get_upper_case_cname ())); - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_get_%s".printf (prefix, prop.name))); - ccall.add_argument (new CCodeIdentifier ("self")); - var csetcall = new CCodeFunctionCall (); - csetcall.call = get_value_setter_function (prop.type_reference); - csetcall.add_argument (new CCodeIdentifier ("value")); - csetcall.add_argument (ccall); - ccase.add_statement (new CCodeExpressionStatement (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); - } - - private void add_set_property_function (Class! cl) { - var set_prop = new CCodeFunction ("%s_set_property".printf (cl.get_lower_case_cname (null)), "void"); - set_prop.modifiers = CCodeModifiers.STATIC; - set_prop.add_parameter (new CCodeFormalParameter ("object", "GObject *")); - set_prop.add_parameter (new CCodeFormalParameter ("property_id", "guint")); - set_prop.add_parameter (new CCodeFormalParameter ("value", "const GValue *")); - set_prop.add_parameter (new CCodeFormalParameter ("pspec", "GParamSpec *")); - - var block = new CCodeBlock (); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null))); - ccall.add_argument (new CCodeIdentifier ("object")); - var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall)); - block.add_statement (cdecl); - - var cswitch = new CCodeSwitchStatement (new CCodeIdentifier ("property_id")); - var props = cl.get_properties (); - foreach (Property prop in props) { - if (prop.set_accessor == null || prop.is_abstract) { - continue; - } - - bool is_virtual = prop.base_property != null || prop.base_interface_property != null; - - string prefix = cl.get_lower_case_cname (null); - if (is_virtual) { - prefix += "_real"; - } - - var ccase = new CCodeCaseStatement (new CCodeIdentifier (prop.get_upper_case_cname ())); - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_set_%s".printf (prefix, prop.name))); - ccall.add_argument (new CCodeIdentifier ("self")); - var cgetcall = new CCodeFunctionCall (); - if (prop.type_reference.data_type is Class || prop.type_reference.data_type is Interface) { - cgetcall.call = new CCodeIdentifier ("g_value_get_object"); - } else if (prop.type_reference.type_name == "string") { - cgetcall.call = new CCodeIdentifier ("g_value_get_string"); - } else if (prop.type_reference.type_name == "int" || prop.type_reference.data_type is Enum) { - cgetcall.call = new CCodeIdentifier ("g_value_get_int"); - } else if (prop.type_reference.type_name == "uint") { - cgetcall.call = new CCodeIdentifier ("g_value_get_uint"); - } else if (prop.type_reference.type_name == "long") { - cgetcall.call = new CCodeIdentifier ("g_value_get_long"); - } else if (prop.type_reference.type_name == "ulong") { - cgetcall.call = new CCodeIdentifier ("g_value_get_ulong"); - } else if (prop.type_reference.type_name == "bool") { - cgetcall.call = new CCodeIdentifier ("g_value_get_boolean"); - } else if (prop.type_reference.type_name == "float") { - cgetcall.call = new CCodeIdentifier ("g_value_get_float"); - } else if (prop.type_reference.type_name == "double") { - cgetcall.call = new CCodeIdentifier ("g_value_get_double"); - } else { - cgetcall.call = new CCodeIdentifier ("g_value_get_pointer"); - } - cgetcall.add_argument (new CCodeIdentifier ("value")); - ccall.add_argument (cgetcall); - ccase.add_statement (new CCodeExpressionStatement (ccall)); - ccase.add_statement (new CCodeBreakStatement ()); - cswitch.add_case (ccase); - } - block.add_statement (cswitch); - - /* destroy func properties for generic types */ - foreach (TypeParameter type_param in cl.get_type_parameters ()) { - string func_name = "%s_destroy_func".printf (type_param.name.down ()); - string enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up (); - - var ccase = new CCodeCaseStatement (new CCodeIdentifier (enum_value)); - var cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name); - var cgetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer")); - cgetcall.add_argument (new CCodeIdentifier ("value")); - ccase.add_statement (new CCodeExpressionStatement (new CCodeAssignment (cfield, cgetcall))); - ccase.add_statement (new CCodeBreakStatement ()); - cswitch.add_case (ccase); - } - - set_prop.block = block; - - source_type_member_definition.append (set_prop); - } - - public override void visit_begin_struct (Struct! st) { - current_type_symbol = st.symbol; - - instance_struct = new CCodeStruct ("_%s".printf (st.get_cname ())); - - if (st.source_reference.file.cycle == null) { - header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (st.get_cname ()), new CCodeVariableDeclarator (st.get_cname ()))); - } - - if (st.source_reference.comment != null) { - header_type_definition.append (new CCodeComment (st.source_reference.comment)); - } - header_type_definition.append (instance_struct); - } - - public override void visit_end_struct (Struct! st) { - current_type_symbol = null; - } - - public override void visit_begin_interface (Interface! iface) { - current_symbol = iface.symbol; - current_type_symbol = iface.symbol; - - if (iface.is_static) { - return; - } - - type_struct = new CCodeStruct ("_%s".printf (iface.get_type_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 (iface.get_upper_case_cname ("TYPE_"), 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 ("%s(obj)".printf (iface.get_upper_case_cname (null)), macro)); - - macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (iface.get_upper_case_cname ("TYPE_")); - header_type_declaration.append (new CCodeMacroReplacement ("%s(obj)".printf (iface.get_upper_case_cname ("IS_")), macro)); - - macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (iface.get_upper_case_cname ("TYPE_"), iface.get_type_cname ()); - header_type_declaration.append (new CCodeMacroReplacement ("%s_GET_INTERFACE(obj)".printf (iface.get_upper_case_cname (null)), macro)); - header_type_declaration.append (new CCodeNewline ()); - - - if (iface.source_reference.file.cycle == null) { - header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (iface.get_cname ()), new CCodeVariableDeclarator (iface.get_cname ()))); - header_type_declaration.append (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator (iface.get_type_cname ()))); - } - - type_struct.add_field ("GTypeInterface", "parent"); - - if (iface.source_reference.comment != null) { - header_type_definition.append (new CCodeComment (iface.source_reference.comment)); - } - header_type_definition.append (type_struct); - } - - public override void visit_end_interface (Interface! iface) { - if (!iface.is_static) { - add_interface_base_init_function (iface); - - var type_fun = new InterfaceRegisterFunction (iface); - type_fun.init_from_type (); - header_type_member_declaration.append (type_fun.get_declaration ()); - source_type_member_definition.append (type_fun.get_definition ()); - } - - current_type_symbol = null; - } - - private ref CCodeFunctionCall! get_param_spec (Property! prop) { - var cspec = new CCodeFunctionCall (); - cspec.add_argument (prop.get_canonical_cconstant ()); - cspec.add_argument (new CCodeConstant ("\"foo\"")); - cspec.add_argument (new CCodeConstant ("\"bar\"")); - if (prop.type_reference.data_type is Class || prop.type_reference.data_type is Interface) { - cspec.call = new CCodeIdentifier ("g_param_spec_object"); - cspec.add_argument (new CCodeIdentifier (prop.type_reference.data_type.get_upper_case_cname ("TYPE_"))); - } else if (prop.type_reference.data_type == string_type.data_type) { - cspec.call = new CCodeIdentifier ("g_param_spec_string"); - cspec.add_argument (new CCodeConstant ("NULL")); - } else if (prop.type_reference.data_type == int_type.data_type - || prop.type_reference.data_type is Enum) { - cspec.call = new CCodeIdentifier ("g_param_spec_int"); - cspec.add_argument (new CCodeConstant ("G_MININT")); - cspec.add_argument (new CCodeConstant ("G_MAXINT")); - cspec.add_argument (new CCodeConstant ("0")); - } else if (prop.type_reference.data_type == uint_type.data_type) { - cspec.call = new CCodeIdentifier ("g_param_spec_uint"); - cspec.add_argument (new CCodeConstant ("0")); - cspec.add_argument (new CCodeConstant ("G_MAXUINT")); - cspec.add_argument (new CCodeConstant ("0U")); - } else if (prop.type_reference.data_type == long_type.data_type) { - cspec.call = new CCodeIdentifier ("g_param_spec_long"); - cspec.add_argument (new CCodeConstant ("G_MINLONG")); - cspec.add_argument (new CCodeConstant ("G_MAXLONG")); - cspec.add_argument (new CCodeConstant ("0L")); - } else if (prop.type_reference.data_type == ulong_type.data_type) { - cspec.call = new CCodeIdentifier ("g_param_spec_ulong"); - cspec.add_argument (new CCodeConstant ("0")); - cspec.add_argument (new CCodeConstant ("G_MAXULONG")); - cspec.add_argument (new CCodeConstant ("0UL")); - } else if (prop.type_reference.data_type == bool_type.data_type) { - cspec.call = new CCodeIdentifier ("g_param_spec_boolean"); - cspec.add_argument (new CCodeConstant ("FALSE")); - } else if (prop.type_reference.data_type == float_type.data_type) { - cspec.call = new CCodeIdentifier ("g_param_spec_float"); - cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT")); - cspec.add_argument (new CCodeConstant ("G_MAXFLOAT")); - cspec.add_argument (new CCodeConstant ("0.0F")); - } else if (prop.type_reference.data_type == double_type.data_type) { - cspec.call = new CCodeIdentifier ("g_param_spec_double"); - cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE")); - cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE")); - cspec.add_argument (new CCodeConstant ("0.0")); - } else { - cspec.call = new CCodeIdentifier ("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.construction) { - 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 (pflags)); - - return cspec; - } - - private ref CCodeFunctionCall! get_signal_creation (Signal! sig, DataType! type) { - var csignew = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_new")); - csignew.add_argument (new CCodeConstant ("\"%s\"".printf (sig.name))); - csignew.add_argument (new CCodeIdentifier (type.get_upper_case_cname ("TYPE_"))); - csignew.add_argument (new CCodeConstant ("G_SIGNAL_RUN_LAST")); - csignew.add_argument (new CCodeConstant ("0")); - csignew.add_argument (new CCodeConstant ("NULL")); - csignew.add_argument (new CCodeConstant ("NULL")); - - string marshaller = get_signal_marshaller_function (sig); - - var marshal_arg = new CCodeIdentifier (marshaller); - csignew.add_argument (marshal_arg); - - var params = sig.get_parameters (); - var params_len = params.length (); - if (sig.return_type.type_parameter != null) { - csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); - } else if (sig.return_type.data_type == null) { - csignew.add_argument (new CCodeConstant ("G_TYPE_NONE")); - } else { - csignew.add_argument (new CCodeConstant (sig.return_type.data_type.get_type_id ())); - } - csignew.add_argument (new CCodeConstant ("%d".printf (params_len))); - foreach (FormalParameter param in params) { - if (param.type_reference.type_parameter != null) { - csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); - } else { - csignew.add_argument (new CCodeConstant (param.type_reference.data_type.get_type_id ())); - } - } - - marshal_arg.name = marshaller; - - return csignew; - } - - private void add_interface_base_init_function (Interface! iface) { - var base_init = new CCodeFunction ("%s_base_init".printf (iface.get_lower_case_cname (null)), "void"); - base_init.add_parameter (new CCodeFormalParameter ("iface", "%sIface *".printf (iface.get_cname ()))); - base_init.modifiers = CCodeModifiers.STATIC; - - var init_block = new CCodeBlock (); - - /* make sure not to run the initialization code twice */ - base_init.block = new CCodeBlock (); - var decl = new CCodeDeclaration (bool_type.get_cname ()); - decl.modifiers |= CCodeModifiers.STATIC; - decl.add_declarator (new CCodeVariableDeclarator.with_initializer ("initialized", new CCodeConstant ("FALSE"))); - base_init.block.add_statement (decl); - var cif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("initialized")), init_block); - base_init.block.add_statement (cif); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("initialized"), new CCodeConstant ("TRUE")))); - - /* create properties */ - var props = iface.get_properties (); - foreach (Property prop in props) { - var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_interface_install_property")); - cinst.add_argument (new CCodeIdentifier ("iface")); - cinst.add_argument (get_param_spec (prop)); - - init_block.add_statement (new CCodeExpressionStatement (cinst)); - } - - /* create signals */ - foreach (Signal sig in iface.get_signals ()) { - init_block.add_statement (new CCodeExpressionStatement (get_signal_creation (sig, iface))); - } - - source_type_member_definition.append (base_init); - } - - public override void visit_begin_enum (Enum! en) { - cenum = new CCodeEnum (en.get_cname ()); - - if (en.source_reference.comment != null) { - header_type_definition.append (new CCodeComment (en.source_reference.comment)); - } - header_type_definition.append (cenum); - } - - public override void visit_enum_value (EnumValue! ev) { - string val; - if (ev.value is LiteralExpression) { - var lit = ((LiteralExpression) ev.value).literal; - if (lit is IntegerLiteral) { - val = ((IntegerLiteral) lit).value; - } - } - cenum.add_value (ev.get_cname (), val); - } - - public override void visit_begin_flags (Flags! fl) { - cenum = new CCodeEnum (fl.get_cname ()); - - if (fl.source_reference.comment != null) { - header_type_definition.append (new CCodeComment (fl.source_reference.comment)); - } - header_type_definition.append (cenum); - } - - public override void visit_flags_value (FlagsValue! fv) { - string val; - if (fv.value is LiteralExpression) { - var lit = ((LiteralExpression) fv.value).literal; - if (lit is IntegerLiteral) { - val = ((IntegerLiteral) lit).value; - } - } - cenum.add_value (fv.get_cname (), val); - } - - public override void visit_end_callback (Callback! cb) { - var cfundecl = new CCodeFunctionDeclarator (cb.get_cname ()); - foreach (FormalParameter param in cb.get_parameters ()) { - cfundecl.add_parameter ((CCodeFormalParameter) param.ccodenode); - } - - var ctypedef = new CCodeTypeDefinition (cb.return_type.get_cname (), cfundecl); - - if (cb.access != MemberAccessibility.PRIVATE) { - header_type_declaration.append (ctypedef); - } else { - source_type_member_declaration.append (ctypedef); - } - } - - public override void visit_member (Member! m) { - /* stuff meant for all lockable members */ - if (m is Lockable && ((Lockable)m).get_lock_used ()) { - instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (m.symbol)); - - instance_init_fragment.append ( - new CCodeExpressionStatement ( - new CCodeAssignment ( - new CCodeMemberAccess.pointer ( - new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), - get_symbol_lock_name (m.symbol)), - new CCodeFunctionCall (new CCodeIdentifier (((Struct)mutex_type.data_type).default_construction_method.get_cname ()))))); - - var fc = new CCodeFunctionCall (new CCodeIdentifier ("VALA_FREE_CHECKED")); - fc.add_argument ( - new CCodeMemberAccess.pointer ( - new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), - get_symbol_lock_name (m.symbol))); - fc.add_argument (new CCodeIdentifier (mutex_type.data_type.get_free_function ())); - if (instance_dispose_fragment != null) { - instance_dispose_fragment.append (new CCodeExpressionStatement (fc)); - } - } - } - - 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 (c.type_reference.get_const_cname ()); - var arr = ""; - if (c.type_reference.data_type is Array) { - arr = "[]"; - } - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("%s%s".printf (c.get_cname (), arr), (CCodeExpression) c.initializer.ccodenode)); - cdecl.modifiers = CCodeModifiers.STATIC; - - if (c.access != MemberAccessibility.PRIVATE) { - header_type_member_declaration.append (cdecl); - } else { - source_type_member_declaration.append (cdecl); - } - } - } - - public override void visit_field (Field! f) { - CCodeExpression lhs = null; - CCodeStruct st = null; - - if (f.access != MemberAccessibility.PRIVATE) { - st = instance_struct; - if (f.instance) { - lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), f.get_cname ()); - } - } else if (f.access == MemberAccessibility.PRIVATE) { - if (f.instance) { - st = instance_priv_struct; - lhs = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), f.get_cname ()); - } else { - if (f.symbol.parent_symbol.node is DataType) { - var t = (DataType) f.symbol.parent_symbol.node; - var cdecl = new CCodeDeclaration (f.type_reference.get_cname ()); - var var_decl = new CCodeVariableDeclarator (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); - } - } - } - - if (f.instance) { - st.add_field (f.type_reference.get_cname (), f.get_cname ()); - if (f.type_reference.data_type is Array && !f.no_array_length) { - // create fields to store array dimensions - var arr = (Array) f.type_reference.data_type; - - for (int dim = 1; dim <= arr.rank; dim++) { - var len_type = new TypeReference (); - len_type.data_type = int_type.data_type; - - st.add_field (len_type.get_cname (), get_array_length_cname (f.name, dim)); - } - } - - if (f.initializer != null) { - instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, (CCodeExpression) f.initializer.ccodenode))); - - if (f.type_reference.data_type is Array && !f.no_array_length && - f.initializer is ArrayCreationExpression) { - var ma = new MemberAccess.simple (f.name); - ma.symbol_reference = f.symbol; - - var array_len_lhs = get_array_length_cexpression (ma, 1); - var sizes = ((ArrayCreationExpression) f.initializer).get_sizes (); - var size = (Expression) sizes.data; - instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (array_len_lhs, (CCodeExpression) size.ccodenode))); - } - } - - if (f.type_reference.takes_ownership && instance_dispose_fragment != null) { - instance_dispose_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.type_reference))); - } - } - } - - public override void visit_begin_method (Method! m) { - current_symbol = m.symbol; - current_return_type = m.return_type; - } - - 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.data_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.data_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 (); - - if (t is Class || t is Interface) { - var ctype_check = new CCodeFunctionCall (new CCodeIdentifier (t.get_upper_case_cname ("IS_"))); - ctype_check.add_argument (new CCodeIdentifier (var_name)); - - ref CCodeExpression cexpr = ctype_check; - if (!non_null) { - var cnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL")); - - cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cnull, ctype_check); - } - ccheck.add_argument (cexpr); - } else if (!non_null) { - return null; - } else { - var cnonnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL")); - ccheck.add_argument (cnonnull); - } - - if (ret_type == null) { - /* void function */ - ccheck.call = new CCodeIdentifier ("g_return_if_fail"); - } else { - ccheck.call = new CCodeIdentifier ("g_return_val_if_fail"); - - if (ret_type.is_reference_type () || ret_type is Pointer) { - ccheck.add_argument (new CCodeConstant ("NULL")); - } else if (ret_type.get_default_value () != null) { - ccheck.add_argument (new CCodeConstant (ret_type.get_default_value ())); - } else { - Report.warning (method_node.source_reference, "not supported return type for runtime type checks"); - return new CCodeExpressionStatement (new CCodeConstant ("0")); - } - } - - return new CCodeExpressionStatement (ccheck); - } - - 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; - } - return null; - } - - private ref string! get_array_length_cname (string! array_cname, int dim) { - return "%s_length%d".printf (array_cname, dim); - } - - public override void visit_end_method (Method! m) { - current_symbol = current_symbol.parent_symbol; - current_return_type = null; - - if (current_type_symbol != null && current_type_symbol.node is Interface) { - var iface = (Interface) current_type_symbol.node; - if (iface.is_static) { - return; - } - } - - if (current_symbol.parent_symbol != null && - 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; - } - - function = new CCodeFunction (m.get_real_cname (), m.return_type.get_cname ()); - CCodeFunctionDeclarator vdeclarator = null; - - CCodeFormalParameter instance_param = null; - - if (m.instance) { - var this_type = new TypeReference (); - this_type.data_type = find_parent_type (m); - if (m.base_interface_method != null) { - var base_type = new TypeReference (); - base_type.data_type = (DataType) m.base_interface_method.symbol.parent_symbol.node; - instance_param = new CCodeFormalParameter ("base", base_type.get_cname ()); - } else if (m.overrides) { - var base_type = new TypeReference (); - base_type.data_type = (DataType) m.base_method.symbol.parent_symbol.node; - instance_param = new CCodeFormalParameter ("base", base_type.get_cname ()); - } else { - if (m.instance_by_reference) { - instance_param = new CCodeFormalParameter ("*self", this_type.get_cname ()); - } else { - instance_param = new CCodeFormalParameter ("self", this_type.get_cname ()); - } - } - if (!m.instance_last) { - function.add_parameter (instance_param); - } - - if (m.is_abstract || m.is_virtual) { - var vdecl = new CCodeDeclaration (m.return_type.get_cname ()); - vdeclarator = new CCodeFunctionDeclarator (m.name); - vdecl.add_declarator (vdeclarator); - type_struct.add_declaration (vdecl); - - vdeclarator.add_parameter (instance_param); - } - } - - if (m is CreationMethod && current_class != null) { - // memory management for generic types - foreach (TypeParameter type_param in current_class.get_type_parameters ()) { - var cparam = new CCodeFormalParameter ("%s_destroy_func".printf (type_param.name.down ()), "GDestroyNotify"); - function.add_parameter (cparam); - } - } - - var params = m.get_parameters (); - foreach (FormalParameter param in params) { - if (!param.no_array_length && param.type_reference.data_type is Array) { - var arr = (Array) param.type_reference.data_type; - - var length_ctype = "int"; - if (param.type_reference.is_out) { - length_ctype = "int*"; - } - - for (int dim = 1; dim <= arr.rank; dim++) { - var cparam = new CCodeFormalParameter (get_array_length_cname (param.name, dim), length_ctype); - function.add_parameter (cparam); - if (vdeclarator != null) { - vdeclarator.add_parameter (cparam); - } - } - } - - function.add_parameter ((CCodeFormalParameter) param.ccodenode); - if (vdeclarator != null) { - vdeclarator.add_parameter ((CCodeFormalParameter) param.ccodenode); - } - } - - if (m.instance && m.instance_last) { - function.add_parameter (instance_param); - } - - /* real function declaration and definition not needed - * for abstract methods */ - if (!m.is_abstract) { - if (m.access != MemberAccessibility.PRIVATE && m.base_method == null && m.base_interface_method == null) { - /* 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.overrides || m.base_interface_method != null) { - var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null))); - ccall.add_argument (new CCodeIdentifier ("base")); - - var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall)); - - cinit.append (cdecl); - } else if (m.instance) { - cinit.append (create_method_type_check_statement (m, cl, true, "self")); - } - } - foreach (FormalParameter param in m.get_parameters ()) { - var t = param.type_reference.data_type; - if (t != null && t.is_reference_type () && !param.type_reference.is_out) { - var type_check = create_method_type_check_statement (m, t, param.type_reference.non_null, param.name); - if (type_check != null) { - cinit.append (type_check); - } - } - } - - if (m.source_reference != null && m.source_reference.comment != null) { - source_type_member_definition.append (new CCodeComment (m.source_reference.comment)); - } - source_type_member_definition.append (function); - - if (m is CreationMethod) { - if (current_class != null) { - int n_params = ((CreationMethod) m).n_construction_params; - n_params += (int) current_class.get_type_parameters ().length (); - - // declare construction parameter array - var cparamsinit = new CCodeFunctionCall (new CCodeIdentifier ("g_new0")); - cparamsinit.add_argument (new CCodeIdentifier ("GParameter")); - cparamsinit.add_argument (new CCodeConstant (n_params.to_string ())); - - var cdecl = new CCodeDeclaration ("GParameter *"); - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("__params", cparamsinit)); - cinit.append (cdecl); - - cdecl = new CCodeDeclaration ("GParameter *"); - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("__params_it", new CCodeIdentifier ("__params"))); - cinit.append (cdecl); - - /* destroy func properties for generic types */ - foreach (TypeParameter type_param in current_class.get_type_parameters ()) { - string func_name = "%s_destroy_func".printf (type_param.name.down ()); - var func_name_constant = new CCodeConstant ("\"%s-destroy-func\"".printf (type_param.name.down ())); - - // this property is used as a construction parameter - var cpointer = new CCodeIdentifier ("__params_it"); - - var ccomma = new CCodeCommaExpression (); - // set name in array for current parameter - var cnamemember = new CCodeMemberAccess.pointer (cpointer, "name"); - ccomma.append_expression (new CCodeAssignment (cnamemember, func_name_constant)); - var gvaluearg = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (cpointer, "value")); - - // initialize GValue in array for current parameter - var cvalueinit = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init")); - cvalueinit.add_argument (gvaluearg); - cvalueinit.add_argument (new CCodeIdentifier ("G_TYPE_POINTER")); - ccomma.append_expression (cvalueinit); - - // set GValue for current parameter - var cvalueset = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_pointer")); - cvalueset.add_argument (gvaluearg); - cvalueset.add_argument (new CCodeIdentifier (func_name)); - ccomma.append_expression (cvalueset); - - // move pointer to next parameter in array - ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, cpointer)); - - cinit.append (new CCodeExpressionStatement (ccomma)); - } - } else { - var st = (Struct) m.symbol.parent_symbol.node; - var cdecl = new CCodeDeclaration (st.get_cname () + "*"); - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_new0")); - ccall.add_argument (new CCodeConstant (st.get_cname ())); - ccall.add_argument (new CCodeConstant ("1")); - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall)); - cinit.append (cdecl); - } - } - - if (context.module_init_method == m && in_plugin) { - // GTypeModule-based plug-in, register types - cinit.append (module_init_fragment); - } - } - } - - if (m.is_abstract || m.is_virtual) { - var vfunc = new CCodeFunction (m.get_cname (), m.return_type.get_cname ()); - - var this_type = new TypeReference (); - this_type.data_type = (DataType) m.symbol.parent_symbol.node; - - var cparam = new CCodeFormalParameter ("self", this_type.get_cname ()); - vfunc.add_parameter (cparam); - - var vblock = new CCodeBlock (); - - CCodeFunctionCall vcast = null; - if (m.symbol.parent_symbol.node is Interface) { - var iface = (Interface) m.symbol.parent_symbol.node; - - vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_INTERFACE".printf (iface.get_upper_case_cname (null)))); - } else { - var cl = (Class) m.symbol.parent_symbol.node; - - vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (cl.get_upper_case_cname (null)))); - } - vcast.add_argument (new CCodeIdentifier ("self")); - - var vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, m.name)); - vcall.add_argument (new CCodeIdentifier ("self")); - - var params = m.get_parameters (); - foreach (FormalParameter param in params) { - vfunc.add_parameter ((CCodeFormalParameter) param.ccodenode); - vcall.add_argument (new CCodeIdentifier (param.name)); - } - - if (m.return_type.data_type == null) { - vblock.add_statement (new CCodeExpressionStatement (vcall)); - } else { - /* pass method return value */ - vblock.add_statement (new CCodeReturnStatement (vcall)); - } - - header_type_member_declaration.append (vfunc.copy ()); - - vfunc.block = vblock; - - source_type_member_definition.append (vfunc); - } - - if (m is CreationMethod) { - var creturn = new CCodeReturnStatement (); - creturn.return_expression = new CCodeIdentifier ("self"); - function.block.add_statement (creturn); - } - - bool return_value = true; - bool args_parameter = true; - if (is_possible_entry_point (m, ref return_value, ref args_parameter)) { - // m is possible entry point, add appropriate startup code - var cmain = new CCodeFunction ("main", "int"); - cmain.add_parameter (new CCodeFormalParameter ("argc", "int")); - cmain.add_parameter (new CCodeFormalParameter ("argv", "char **")); - var main_block = new CCodeBlock (); - main_block.add_statement (new CCodeExpressionStatement (new CCodeFunctionCall (new CCodeIdentifier ("g_type_init")))); - var main_call = new CCodeFunctionCall (new CCodeIdentifier (function.name)); - if (args_parameter) { - main_call.add_argument (new CCodeIdentifier ("argc")); - main_call.add_argument (new CCodeIdentifier ("argv")); - } - if (return_value) { - main_block.add_statement (new CCodeReturnStatement (main_call)); - } else { - // method returns void, always use 0 as exit code - main_block.add_statement (new CCodeExpressionStatement (main_call)); - main_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("0"))); - } - cmain.block = main_block; - source_type_member_definition.append (cmain); - } - } - - public override void visit_begin_creation_method (CreationMethod! m) { - current_symbol = m.symbol; - current_return_type = m.return_type; - in_creation_method = true; - } - - public override void visit_end_creation_method (CreationMethod! m) { - if (current_class != null && m.body != null) { - add_object_creation ((CCodeBlock) m.body.ccodenode); - } - - in_creation_method = false; - - visit_end_method (m); - } - - private bool is_possible_entry_point (Method! m, ref bool return_value, ref bool args_parameter) { - if (m.name == null || m.name != "main") { - // method must be called "main" - return false; - } - - if (m.instance) { - // method must be static - return false; - } - - if (m.return_type.data_type == null) { - return_value = false; - } else if (m.return_type.data_type == int_type.data_type) { - return_value = true; - } else { - // return type must be void or int - return false; - } - - var params = m.get_parameters (); - if (params.length () == 0) { - // method may have no parameters - args_parameter = false; - return true; - } - - if (params.length () > 1) { - // method must not have more than one parameter - return false; - } - - var param = (FormalParameter) params.data; - - if (param.type_reference.is_out) { - // parameter must not be an out parameter - return false; - } - - if (!(param.type_reference.data_type is Array)) { - // parameter must be an array - return false; - } - - var array_type = (Array) param.type_reference.data_type; - if (array_type.element_type != string_type.data_type) { - // parameter must be an array of strings - return false; - } - - args_parameter = true; - return true; - } - - public override void visit_formal_parameter (FormalParameter! p) { - if (!p.ellipsis) { - p.ccodenode = new CCodeFormalParameter (p.name, p.type_reference.get_cname (false, !p.type_reference.takes_ownership)); - } - } - - public override void visit_end_property (Property! prop) { - prop_enum.add_value (prop.get_upper_case_cname (), 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; - } else { - // void - current_return_type = new TypeReference (); - } - } - - public override void visit_end_property_accessor (PropertyAccessor! acc) { - var prop = (Property) acc.symbol.parent_symbol.node; - - current_return_type = null; - - var t = (DataType) prop.symbol.parent_symbol.node; - - var this_type = new TypeReference (); - this_type.data_type = t; - var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ()); - var cvalueparam = new CCodeFormalParameter ("value", prop.type_reference.get_cname (false, true)); - - if (prop.is_abstract || prop.is_virtual) { - if (acc.readable) { - function = new CCodeFunction ("%s_get_%s".printf (t.get_lower_case_cname (null), prop.name), prop.type_reference.get_cname ()); - } else { - function = new CCodeFunction ("%s_set_%s".printf (t.get_lower_case_cname (null), prop.name), "void"); - } - function.add_parameter (cselfparam); - if (acc.writable || acc.construction) { - function.add_parameter (cvalueparam); - } - - header_type_member_declaration.append (function.copy ()); - - var block = new CCodeBlock (); - function.block = block; - - if (acc.readable) { - // declare temporary variable to save the property value - var decl = new CCodeDeclaration (prop.type_reference.get_cname ()); - decl.add_declarator (new CCodeVariableDeclarator ("value")); - block.add_statement (decl); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get")); - - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT")); - ccast.add_argument (new CCodeIdentifier ("self")); - ccall.add_argument (ccast); - - // property name is second argument of g_object_get - ccall.add_argument (prop.get_canonical_cconstant ()); - - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value"))); - - ccall.add_argument (new CCodeConstant ("NULL")); - - block.add_statement (new CCodeExpressionStatement (ccall)); - block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("value"))); - } else { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_set")); - - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT")); - ccast.add_argument (new CCodeIdentifier ("self")); - ccall.add_argument (ccast); - - // property name is second argument of g_object_set - ccall.add_argument (prop.get_canonical_cconstant ()); - - ccall.add_argument (new CCodeIdentifier ("value")); - - ccall.add_argument (new CCodeConstant ("NULL")); - - block.add_statement (new CCodeExpressionStatement (ccall)); - } - - source_type_member_definition.append (function); - } - - if (!prop.is_abstract) { - bool is_virtual = prop.base_property != null || prop.base_interface_property != null; - - string prefix = t.get_lower_case_cname (null); - if (is_virtual) { - prefix += "_real"; - } - if (acc.readable) { - function = new CCodeFunction ("%s_get_%s".printf (prefix, prop.name), prop.type_reference.get_cname ()); - } else { - function = new CCodeFunction ("%s_set_%s".printf (prefix, prop.name), "void"); - } - if (is_virtual) { - function.modifiers |= CCodeModifiers.STATIC; - } - function.add_parameter (cselfparam); - if (acc.writable || acc.construction) { - function.add_parameter (cvalueparam); - } - - if (!is_virtual) { - header_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, t, true, "self")); - } - - source_type_member_definition.append (function); - } - } - - private string get_marshaller_type_name (TypeReference t) { - if (t.type_parameter != null) { - return ("POINTER"); - } else if (t.data_type == null) { - return ("VOID"); - } else { - return t.data_type.get_marshaller_type_name (); - } - } - - private ref string get_signal_marshaller_function (Signal! sig, string prefix = null) { - var signature = get_signal_signature (sig); - string ret; - var params = sig.get_parameters (); - - if (prefix == null) { - // FIXME remove equality check with cast in next revision - if (predefined_marshal_list.lookup (signature) != (bool) null) { - prefix = "g_cclosure_marshal"; - } else { - prefix = "g_cclosure_user_marshal"; - } - } - - ret = "%s_%s_".printf (prefix, get_marshaller_type_name (sig.return_type)); - - if (params == null) { - ret = ret + "_VOID"; - } else { - foreach (FormalParameter p in params) { - ret = "%s_%s".printf (ret, get_marshaller_type_name (p.type_reference)); - } - } - - return ret; - } - - private string get_value_type_name_from_type_reference (TypeReference! t) { - if (t.type_parameter != null) { - return "gpointer"; - } else if (t.data_type == null) { - return "void"; - } else if (t.data_type is Class || t.data_type is Interface) { - return "GObject *"; - } else if (t.data_type is Struct) { - if (((Struct) t.data_type).is_reference_type ()) { - return "gpointer"; - } else { - return t.data_type.get_cname (); - } - } else if (t.data_type is Enum) { - return "gint"; - } else if (t.data_type is Flags) { - return "guint"; - } else if (t.data_type is Array) { - return "gpointer"; - } - - return null; - } - - private ref string get_signal_signature (Signal! sig) { - string signature; - var params = sig.get_parameters (); - - signature = "%s:".printf (get_marshaller_type_name (sig.return_type)); - if (params == null) { - signature = signature + "VOID"; - } else { - bool first = true; - foreach (FormalParameter p in params) { - if (first) { - signature = signature + get_marshaller_type_name (p.type_reference); - first = false; - } else { - signature = "%s,%s".printf (signature, get_marshaller_type_name (p.type_reference)); - } - } - } - - return signature; - } - - public override void visit_end_signal (Signal! sig) { - string signature; - var params = sig.get_parameters (); - int n_params, i; - - /* check whether a signal with the same signature already exists for this source file (or predefined) */ - signature = get_signal_signature (sig); - // FIXME remove equality checks with cast in next revision - if (predefined_marshal_list.lookup (signature) != (bool) null || user_marshal_list.lookup (signature) != (bool) null) { - return; - } - - var signal_marshaller = new CCodeFunction (get_signal_marshaller_function (sig), "void"); - signal_marshaller.modifiers = CCodeModifiers.STATIC; - - signal_marshaller.add_parameter (new CCodeFormalParameter ("closure", "GClosure *")); - signal_marshaller.add_parameter (new CCodeFormalParameter ("return_value", "GValue *")); - signal_marshaller.add_parameter (new CCodeFormalParameter ("n_param_values", "guint")); - signal_marshaller.add_parameter (new CCodeFormalParameter ("param_values", "const GValue *")); - signal_marshaller.add_parameter (new CCodeFormalParameter ("invocation_hint", "gpointer")); - signal_marshaller.add_parameter (new CCodeFormalParameter ("marshal_data", "gpointer")); - - source_signal_marshaller_declaration.append (signal_marshaller.copy ()); - - var marshaller_body = new CCodeBlock (); - - var callback_decl = new CCodeFunctionDeclarator (get_signal_marshaller_function (sig, "GMarshalFunc")); - callback_decl.add_parameter (new CCodeFormalParameter ("data1", "gpointer")); - n_params = 1; - foreach (FormalParameter p in params) { - callback_decl.add_parameter (new CCodeFormalParameter ("arg_%d".printf (n_params), get_value_type_name_from_type_reference (p.type_reference))); - n_params++; - } - callback_decl.add_parameter (new CCodeFormalParameter ("data2", "gpointer")); - marshaller_body.add_statement (new CCodeTypeDefinition (get_value_type_name_from_type_reference (sig.return_type), callback_decl)); - - var var_decl = new CCodeDeclaration (get_signal_marshaller_function (sig, "GMarshalFunc")); - var_decl.modifiers = CCodeModifiers.REGISTER; - var_decl.add_declarator (new CCodeVariableDeclarator ("callback")); - marshaller_body.add_statement (var_decl); - - var_decl = new CCodeDeclaration ("GCClosure *"); - var_decl.modifiers = CCodeModifiers.REGISTER; - var_decl.add_declarator (new CCodeVariableDeclarator.with_initializer ("cc", new CCodeCastExpression (new CCodeIdentifier ("closure"), "GCClosure *"))); - marshaller_body.add_statement (var_decl); - - var_decl = new CCodeDeclaration ("gpointer"); - var_decl.modifiers = CCodeModifiers.REGISTER; - var_decl.add_declarator (new CCodeVariableDeclarator ("data1")); - var_decl.add_declarator (new CCodeVariableDeclarator ("data2")); - marshaller_body.add_statement (var_decl); - - CCodeFunctionCall fc; - - if (sig.return_type.data_type != null) { - var_decl = new CCodeDeclaration (get_value_type_name_from_type_reference (sig.return_type)); - var_decl.add_declarator (new CCodeVariableDeclarator ("v_return")); - marshaller_body.add_statement (var_decl); - - fc = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); - fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("return_value"), new CCodeConstant ("NULL"))); - marshaller_body.add_statement (new CCodeExpressionStatement (fc)); - } - - fc = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); - fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("n_param_values"), new CCodeConstant (n_params.to_string()))); - marshaller_body.add_statement (new CCodeExpressionStatement (fc)); - - var data = new CCodeMemberAccess (new CCodeIdentifier ("closure"), "data", true); - var param = new CCodeMemberAccess (new CCodeMemberAccess (new CCodeIdentifier ("param_values"), "data[0]", true), "v_pointer"); - var cond = new CCodeFunctionCall (new CCodeConstant ("G_CCLOSURE_SWAP_DATA")); - cond.add_argument (new CCodeIdentifier ("closure")); - var true_block = new CCodeBlock (); - true_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("data1"), data))); - true_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("data2"), param))); - var false_block = new CCodeBlock (); - false_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("data1"), param))); - false_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("data2"), data))); - marshaller_body.add_statement (new CCodeIfStatement (cond, true_block, false_block)); - - var c_assign = new CCodeAssignment (new CCodeIdentifier ("callback"), new CCodeCastExpression (new CCodeConditionalExpression (new CCodeIdentifier ("marshal_data"), new CCodeIdentifier ("marshal_data"), new CCodeMemberAccess (new CCodeIdentifier ("cc"), "callback", true)), get_signal_marshaller_function (sig, "GMarshalFunc"))); - marshaller_body.add_statement (new CCodeExpressionStatement (c_assign)); - - fc = new CCodeFunctionCall (new CCodeIdentifier ("callback")); - fc.add_argument (new CCodeIdentifier ("data1")); - i = 1; - foreach (FormalParameter p in params) { - string get_value_function; - if (p.type_reference.type_parameter != null) { - get_value_function = "g_value_get_pointer"; - } else { - get_value_function = p.type_reference.data_type.get_get_value_function (); - } - var inner_fc = new CCodeFunctionCall (new CCodeIdentifier (get_value_function)); - inner_fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("param_values"), new CCodeIdentifier (i.to_string ()))); - fc.add_argument (inner_fc); - i++; - } - fc.add_argument (new CCodeIdentifier ("data2")); - - if (sig.return_type.data_type != null) { - marshaller_body.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("v_return"), fc))); - - CCodeFunctionCall set_fc; - if (sig.return_type.type_parameter != null) { - set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_pointer")); - } else if (sig.return_type.data_type is Class || sig.return_type.data_type is Interface) { - set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_take_object")); - } else if (sig.return_type.data_type == string_type.data_type) { - set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_take_string")); - } else { - set_fc = new CCodeFunctionCall (new CCodeIdentifier (sig.return_type.data_type.get_set_value_function ())); - } - set_fc.add_argument (new CCodeIdentifier ("return_value")); - set_fc.add_argument (new CCodeIdentifier ("v_return")); - - marshaller_body.add_statement (new CCodeExpressionStatement (set_fc)); - } else { - marshaller_body.add_statement (new CCodeExpressionStatement (fc)); - } - - signal_marshaller.block = marshaller_body; - - source_signal_marshaller_definition.append (signal_marshaller); - user_marshal_list.insert (signature, true); - } - - public override void visit_end_constructor (Constructor! c) { - var cl = (Class) c.symbol.parent_symbol.node; - - function = new CCodeFunction ("%s_constructor".printf (cl.get_lower_case_cname (null)), "GObject *"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeFormalParameter ("type", "GType")); - function.add_parameter (new CCodeFormalParameter ("n_construct_properties", "guint")); - function.add_parameter (new CCodeFormalParameter ("construct_properties", "GObjectConstructParam *")); - - source_type_member_declaration.append (function.copy ()); - - - var cblock = new CCodeBlock (); - var cdecl = new CCodeDeclaration ("GObject *"); - cdecl.add_declarator (new CCodeVariableDeclarator ("obj")); - cblock.add_statement (cdecl); - - cdecl = new CCodeDeclaration ("%sClass *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator ("klass")); - cblock.add_statement (cdecl); - - cdecl = new CCodeDeclaration ("GObjectClass *"); - cdecl.add_declarator (new CCodeVariableDeclarator ("parent_class")); - cblock.add_statement (cdecl); - - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek")); - ccall.add_argument (new CCodeIdentifier (cl.get_upper_case_cname ("TYPE_"))); - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (cl.get_upper_case_cname (null)))); - ccast.add_argument (ccall); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("klass"), ccast))); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent")); - ccall.add_argument (new CCodeIdentifier ("klass")); - ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); - ccast.add_argument (ccall); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_class"), ccast))); - - - ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier ("parent_class"), "constructor")); - ccall.add_argument (new CCodeIdentifier ("type")); - ccall.add_argument (new CCodeIdentifier ("n_construct_properties")); - ccall.add_argument (new CCodeIdentifier ("construct_properties")); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("obj"), ccall))); - - - ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null))); - ccall.add_argument (new CCodeIdentifier ("obj")); - - cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall)); - - cblock.add_statement (cdecl); - - - cblock.add_statement (c.body.ccodenode); - - cblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("obj"))); - - function.block = cblock; - - if (c.source_reference.comment != null) { - source_type_member_definition.append (new CCodeComment (c.source_reference.comment)); - } - source_type_member_definition.append (function); - } - - public override void visit_begin_block (Block! b) { - current_symbol = b.symbol; - } - - private void add_object_creation (CCodeBlock! b) { - var cl = (Class) current_type_symbol.node; - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_newv")); - ccall.add_argument (new CCodeConstant (cl.get_type_id ())); - ccall.add_argument (new CCodeConstant ("__params_it - __params")); - ccall.add_argument (new CCodeConstant ("__params")); - - var cdecl = new CCodeVariableDeclarator ("self"); - cdecl.initializer = ccall; - - var cdeclaration = new CCodeDeclaration ("%s *".printf (cl.get_cname ())); - cdeclaration.add_declarator (cdecl); - - b.add_statement (cdeclaration); - } - - 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 (); - - foreach (Statement stmt in b.get_statements ()) { - var src = stmt.source_reference; - if (src != null && src.comment != null) { - cblock.add_statement (new CCodeComment (src.comment)); - } - - if (stmt.ccodenode is CCodeFragment) { - foreach (CCodeStatement cstmt in ((CCodeFragment) stmt.ccodenode).get_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.takes_ownership) { - cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference))); - } - } - } - - b.ccodenode = cblock; - - current_symbol = current_symbol.parent_symbol; - } - - public override void visit_empty_statement (EmptyStatement! stmt) { - stmt.ccodenode = new CCodeEmptyStatement (); - } - - private bool struct_has_instance_fields (Struct! st) { - foreach (Field f in st.get_fields ()) { - if (f.instance) { - return true; - } - } - - return false; - } - - 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.get_variable_declarators ()) { - var cdecl = new CCodeDeclaration (decl.type_reference.get_cname (false, !decl.type_reference.takes_ownership)); - - cdecl.add_declarator ((CCodeVariableDeclarator) decl.ccodenode); - - cfrag.append (cdecl); - - /* try to initialize uninitialized variables */ - if (decl.initializer == null && decl.type_reference.data_type is Struct) { - if (decl.type_reference.data_type.is_reference_type ()) { - ((CCodeVariableDeclarator) decl.ccodenode).initializer = new CCodeConstant ("NULL"); - } else if (decl.type_reference.data_type.get_default_value () != null) { - ((CCodeVariableDeclarator) decl.ccodenode).initializer = new CCodeConstant (decl.type_reference.data_type.get_default_value ()); - } else if (decl.type_reference.data_type is Struct && - struct_has_instance_fields ((Struct) decl.type_reference.data_type)) { - var st = (Struct) decl.type_reference.data_type; - - /* memset needs string.h */ - string_h_needed = true; - - var czero = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - czero.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (decl.name))); - czero.add_argument (new CCodeConstant ("0")); - czero.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (decl.type_reference.get_cname ()))); - - cfrag.append (new CCodeExpressionStatement (czero)); - } else { - Report.warning (decl.source_reference, "unable to initialize a variable of type `%s'".printf (decl.type_reference.data_type.symbol.get_full_name ())); - } - } - } - - stmt.ccodenode = cfrag; - - foreach (VariableDeclarator decl in stmt.declaration.get_variable_declarators ()) { - if (decl.initializer != null) { - create_temp_decl (stmt, decl.initializer.temp_vars); - } - } - - create_temp_decl (stmt, temp_vars); - temp_vars = null; - } - - public override void visit_variable_declarator (VariableDeclarator! decl) { - if (decl.type_reference.data_type is Array) { - // create variables to store array dimensions - var arr = (Array) decl.type_reference.data_type; - - for (int dim = 1; dim <= arr.rank; dim++) { - var len_decl = new VariableDeclarator (get_array_length_cname (decl.name, dim)); - len_decl.type_reference = new TypeReference (); - len_decl.type_reference.data_type = int_type.data_type; - - temp_vars.prepend (len_decl); - } - } - - CCodeExpression rhs = null; - if (decl.initializer != null) { - rhs = (CCodeExpression) decl.initializer.ccodenode; - - if (decl.type_reference.data_type != null - && decl.initializer.static_type.data_type != null - && decl.type_reference.data_type.is_reference_type () - && decl.initializer.static_type.data_type != decl.type_reference.data_type) { - // FIXME: use C cast if debugging disabled - rhs = new InstanceCast (rhs, decl.type_reference.data_type); - } - - if (decl.type_reference.data_type is Array) { - var ccomma = new CCodeCommaExpression (); - - var temp_decl = get_temp_variable_declarator (decl.type_reference); - temp_vars.prepend (temp_decl); - ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), rhs)); - - var lhs_array_len = new CCodeIdentifier (get_array_length_cname (decl.name, 1)); - var rhs_array_len = get_array_length_cexpression (decl.initializer, 1); - ccomma.append_expression (new CCodeAssignment (lhs_array_len, rhs_array_len)); - - ccomma.append_expression (new CCodeIdentifier (temp_decl.name)); - - rhs = ccomma; - } - } else if (decl.type_reference.data_type != null && decl.type_reference.data_type.is_reference_type ()) { - rhs = new CCodeConstant ("NULL"); - } - - decl.ccodenode = new CCodeVariableDeclarator.with_initializer (decl.name, rhs); - - decl.symbol.active = true; - } - - public override void visit_end_initializer_list (InitializerList! list) { - if (list.expected_type != null && list.expected_type.data_type is Array) { - /* TODO */ - } else { - var clist = new CCodeInitializerList (); - foreach (Expression expr in list.get_initializers ()) { - clist.append ((CCodeExpression) expr.ccodenode); - } - list.ccodenode = clist; - } - } - - private ref VariableDeclarator get_temp_variable_declarator (TypeReference! type, bool takes_ownership = true) { - var decl = new VariableDeclarator ("__temp%d".printf (next_temp_var_id)); - decl.type_reference = type.copy (); - decl.type_reference.reference_to_value_type = false; - decl.type_reference.is_out = false; - decl.type_reference.takes_ownership = takes_ownership; - - next_temp_var_id++; - - return decl; - } - - private CCodeExpression get_destroy_func_expression (TypeReference! type) { - if (type.data_type != null) { - string unref_function; - if (type.data_type.is_reference_counting ()) { - unref_function = type.data_type.get_unref_function (); - } else { - unref_function = type.data_type.get_free_function (); - } - return new CCodeIdentifier (unref_function); - } else if (type.type_parameter != null && current_class != null) { - string func_name = "%s_destroy_func".printf (type.type_parameter.name.down ()); - return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name); - } else { - return new CCodeConstant ("NULL"); - } - } - - 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 - */ - - if (type.is_null) { - return new CCodeConstant ("NULL"); - } - - var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cvar, new CCodeConstant ("NULL")); - if (type.data_type == null) { - if (current_class == null) { - return new CCodeConstant ("NULL"); - } - - // unref functions are optional for type parameters - var cunrefisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, get_destroy_func_expression (type), new CCodeConstant ("NULL")); - cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cisnull, cunrefisnull); - } - - var ccall = new CCodeFunctionCall (get_destroy_func_expression (type)); - ccall.add_argument (cvar); - - /* set freed references to NULL to prevent further use */ - var ccomma = new CCodeCommaExpression (); - - // TODO cleanup - if (type.data_type != null && !type.data_type.is_reference_counting ()) { - string unref_function = type.data_type.get_free_function (); - if (unref_function == "g_list_free") { - bool is_ref = false; - bool is_class = false; - bool is_interface = false; - - foreach (TypeReference type_arg in type.get_type_arguments ()) { - is_ref |= type_arg.takes_ownership; - is_class |= type_arg.data_type is Class; - is_interface |= type_arg.data_type is Interface; - } - - if (is_ref) { - var cunrefcall = new CCodeFunctionCall (new CCodeIdentifier ("g_list_foreach")); - cunrefcall.add_argument (cvar); - if (is_class || is_interface) { - cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_object_unref")); - } else { - cunrefcall.add_argument (new CCodeIdentifier ("(GFunc) g_free")); - } - cunrefcall.add_argument (new CCodeConstant ("NULL")); - ccomma.append_expression (cunrefcall); - } - } else if (unref_function == "g_string_free") { - ccall.add_argument (new CCodeConstant ("TRUE")); - } - } - - ccomma.append_expression (ccall); - ccomma.append_expression (new CCodeConstant ("NULL")); - - var cassign = new CCodeAssignment (cvar, ccomma); - - // g_free (NULL) is allowed - if (type.non_null || (type.data_type != null && !type.data_type.is_reference_counting () && type.data_type.get_free_function () == "g_free")) { - return new CCodeParenthesizedExpression (cassign); - } - - return new CCodeConditionalExpression (cisnull, new CCodeConstant ("NULL"), new CCodeParenthesizedExpression (cassign)); - } - - public override void visit_end_full_expression (Expression! expr) { - if (!memory_management) { - temp_vars = null; - 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.append_expression (new CCodeAssignment (new CCodeIdentifier (full_expr_decl.name), (CCodeExpression) expr.ccodenode)); - - foreach (VariableDeclarator decl in temp_ref_vars) { - expr_list.append_expression (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference)); - } - - expr_list.append_expression (new CCodeIdentifier (full_expr_decl.name)); - - expr.ccodenode = expr_list; - - temp_ref_vars = null; - } - - private void append_temp_decl (CCodeFragment! cfrag, List<VariableDeclarator> temp_vars) { - foreach (VariableDeclarator decl in temp_vars) { - var cdecl = new CCodeDeclaration (decl.type_reference.get_cname (true, !decl.type_reference.takes_ownership)); - - var vardecl = new CCodeVariableDeclarator (decl.name); - cdecl.add_declarator (vardecl); - - if (decl.type_reference.data_type != null && decl.type_reference.data_type.is_reference_type ()) { - vardecl.initializer = new CCodeConstant ("NULL"); - } - - cfrag.append (cdecl); - } - } - - public override void visit_expression_statement (ExpressionStatement! stmt) { - stmt.ccodenode = new CCodeExpressionStatement ((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 (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference))); - } - - stmt.ccodenode = cfrag; - - temp_vars = null; - temp_ref_vars = null; - } - - private void create_temp_decl (Statement! stmt, List<VariableDeclarator> 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 ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode, (CCodeStatement) stmt.false_statement.ccodenode); - } else { - stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode); - } - - create_temp_decl (stmt, stmt.condition.temp_vars); - } - - public override void visit_switch_statement (SwitchStatement! stmt) { - // we need a temporary variable to save the property value - var temp_decl = get_temp_variable_declarator (stmt.expression.static_type); - stmt.expression.temp_vars.prepend (temp_decl); - - var ctemp = new CCodeIdentifier (temp_decl.name); - - var cinit = new CCodeAssignment (ctemp, (CCodeExpression) stmt.expression.ccodenode); - - var cswitchblock = new CCodeFragment (); - cswitchblock.append (new CCodeExpressionStatement (cinit)); - stmt.ccodenode = cswitchblock; - - create_temp_decl (stmt, stmt.expression.temp_vars); - - List<weak Statement> default_statements = null; - - // generate nested if statements - ref CCodeStatement ctopstmt = null; - CCodeIfStatement coldif = null; - foreach (SwitchSection section in stmt.get_sections ()) { - if (section.has_default_label ()) { - default_statements = section.get_statements (); - } else { - CCodeBinaryExpression cor = null; - foreach (SwitchLabel label in section.get_labels ()) { - var ccmp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, (CCodeExpression) label.expression.ccodenode); - if (cor == null) { - cor = ccmp; - } else { - cor = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cor, ccmp); - } - } - - var cblock = new CCodeBlock (); - foreach (Statement body_stmt in section.get_statements ()) { - if (body_stmt.ccodenode is CCodeFragment) { - foreach (CCodeStatement cstmt in ((CCodeFragment) body_stmt.ccodenode).get_children ()) { - cblock.add_statement (cstmt); - } - } else { - cblock.add_statement ((CCodeStatement) body_stmt.ccodenode); - } - } - - var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0")); - - var cif = new CCodeIfStatement (cor, cdo); - if (coldif != null) { - coldif.false_statement = cif; - } else { - ctopstmt = cif; - } - coldif = cif; - } - } - - if (default_statements != null) { - var cblock = new CCodeBlock (); - foreach (Statement body_stmt in default_statements) { - cblock.add_statement ((CCodeStatement) body_stmt.ccodenode); - } - - var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0")); - - if (coldif == null) { - // there is only one section and that section - // contains a default label - ctopstmt = cdo; - } else { - coldif.false_statement = cdo; - } - } - - cswitchblock.append (ctopstmt); - } - - public override void visit_while_statement (WhileStatement! stmt) { - stmt.ccodenode = new CCodeWhileStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.body.ccodenode); - - create_temp_decl (stmt, stmt.condition.temp_vars); - } - - public override void visit_do_statement (DoStatement! stmt) { - stmt.ccodenode = new CCodeDoStatement ((CCodeStatement) stmt.body.ccodenode, (CCodeExpression) stmt.condition.ccodenode); - - create_temp_decl (stmt, stmt.condition.temp_vars); - } - - public override void visit_for_statement (ForStatement! stmt) { - var cfor = new CCodeForStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.body.ccodenode); - stmt.ccodenode = cfor; - - foreach (Expression init_expr in stmt.get_initializer ()) { - cfor.add_initializer ((CCodeExpression) init_expr.ccodenode); - create_temp_decl (stmt, init_expr.temp_vars); - } - - foreach (Expression it_expr in stmt.get_iterator ()) { - cfor.add_iterator ((CCodeExpression) it_expr.ccodenode); - create_temp_decl (stmt, it_expr.temp_vars); - } - - create_temp_decl (stmt, stmt.condition.temp_vars); - } - - public override void visit_end_foreach_statement (ForeachStatement! stmt) { - var cblock = new CCodeBlock (); - CCodeForStatement cfor; - VariableDeclarator collection_backup = get_temp_variable_declarator (stmt.collection.static_type); - - stmt.collection.temp_vars.prepend (collection_backup); - var cfrag = new CCodeFragment (); - append_temp_decl (cfrag, stmt.collection.temp_vars); - cblock.add_statement (cfrag); - cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (collection_backup.name), (CCodeExpression) stmt.collection.ccodenode))); - - stmt.ccodenode = cblock; - - if (stmt.collection.static_type.data_type is Array) { - var arr = (Array) stmt.collection.static_type.data_type; - - var array_len = get_array_length_cexpression (stmt.collection, 1); - - /* the array has no length parameter i.e. is NULL-terminated array */ - if (array_len is CCodeConstant) { - var it_name = "%s_it".printf (stmt.variable_name); - - var citdecl = new CCodeDeclaration (stmt.collection.static_type.get_cname ()); - citdecl.add_declarator (new CCodeVariableDeclarator (it_name)); - cblock.add_statement (citdecl); - - var cbody = new CCodeBlock (); - - var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, new CCodeIdentifier ("*%s".printf (it_name)))); - cbody.add_statement (cdecl); - - cbody.add_statement (stmt.body.ccodenode); - - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("*%s".printf (it_name)), new CCodeConstant ("NULL")); - - var cfor = new CCodeForStatement (ccond, cbody); - - cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name))); - - cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1")))); - cblock.add_statement (cfor); - /* the array has a length parameter */ - } else { - var it_name = (stmt.variable_name + "_it"); - - var citdecl = new CCodeDeclaration ("int"); - citdecl.add_declarator (new CCodeVariableDeclarator (it_name)); - cblock.add_statement (citdecl); - - var cbody = new CCodeBlock (); - - var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name)))); - cbody.add_statement (cdecl); - - cbody.add_statement (stmt.body.ccodenode); - - var ccond_ind1 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, array_len, new CCodeConstant ("-1")); - var ccond_ind2 = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), array_len); - var ccond_ind = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_ind1, ccond_ind2); - - /* only check for null if the containers elements are of reference-type */ - CCodeBinaryExpression ccond; - if (arr.element_type.is_reference_type ()) { - var ccond_term1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, array_len, new CCodeConstant ("-1")); - var ccond_term2 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name)), new CCodeConstant ("NULL")); - var ccond_term = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_term1, ccond_term2); - - ccond = new CCodeBinaryExpression (CCodeBinaryOperator.OR, new CCodeParenthesizedExpression (ccond_ind), new CCodeParenthesizedExpression (ccond_term)); - } else { - ccond = ccond_ind; - } - - var cfor = new CCodeForStatement (ccond, cbody); - cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0"))); - cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1")))); - cblock.add_statement (cfor); - } - } else if (stmt.collection.static_type.data_type == list_type || - stmt.collection.static_type.data_type == slist_type) { - var it_name = "%s_it".printf (stmt.variable_name); - - var citdecl = new CCodeDeclaration (stmt.collection.static_type.get_cname ()); - citdecl.add_declarator (new CCodeVariableDeclarator (it_name)); - cblock.add_statement (citdecl); - - var cbody = new CCodeBlock (); - - CCodeExpression element_expr = new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "data"); - - /* cast pointer to actual type if appropriate */ - if (stmt.type_reference.data_type is Struct) { - var st = (Struct) stmt.type_reference.data_type; - if (st == uint_type.data_type) { - var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GPOINTER_TO_UINT")); - cconv.add_argument (element_expr); - element_expr = cconv; - } else if (st == bool_type.data_type || st.is_integer_type ()) { - var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GPOINTER_TO_INT")); - cconv.add_argument (element_expr); - element_expr = cconv; - } - } - - var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ()); - cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr)); - cbody.add_statement (cdecl); - - cbody.add_statement (stmt.body.ccodenode); - - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (it_name), new CCodeConstant ("NULL")); - - var cfor = new CCodeForStatement (ccond, cbody); - - cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name))); - - cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "next"))); - cblock.add_statement (cfor); - } - - if (memory_management && stmt.collection.static_type.transfers_ownership) { - cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (collection_backup.name), stmt.collection.static_type))); - } - } - - 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.data_type.is_reference_type () && decl.type_reference.takes_ownership) { - cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (decl.name), decl.type_reference))); - } - } - - 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 cfrag = new CCodeFragment (); - - append_local_free (current_symbol, cfrag, false); - - 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; - - var local_vars = b.get_local_variables (); - foreach (VariableDeclarator decl in local_vars) { - if (decl.symbol.active && decl.type_reference.data_type.is_reference_type () && decl.type_reference.takes_ownership) { - found = true; - ccomma.append_expression (get_unref_expression (new CCodeIdentifier (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; - } - - 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.append_expression (new CCodeAssignment (new CCodeIdentifier (return_expr_decl.name), (CCodeExpression) expr.ccodenode)); - - if (!append_local_free_expr (current_symbol, ccomma, false)) { - /* no local variables need to be freed */ - return; - } - - ccomma.append_expression (new CCodeIdentifier (return_expr_decl.name)); - - expr.ccodenode = ccomma; - expr.temp_vars.append (return_expr_decl); - } - - public override void visit_begin_return_statement (ReturnStatement! stmt) { - if (stmt.return_expression != null) { - // avoid unnecessary ref/unref pair - if (stmt.return_expression.ref_missing && - stmt.return_expression.symbol_reference != null && - stmt.return_expression.symbol_reference.node is VariableDeclarator) { - var decl = (VariableDeclarator) stmt.return_expression.symbol_reference.node; - if (decl.type_reference.takes_ownership) { - /* return expression is local variable taking ownership and - * current method is transferring ownership */ - - stmt.return_expression.ref_sink = true; - - // don't ref expression - stmt.return_expression.ref_missing = false; - } - } - } - } - - public override void visit_end_return_statement (ReturnStatement! stmt) { - if (stmt.return_expression == null) { - stmt.ccodenode = new CCodeReturnStatement (); - - create_local_free (stmt); - } else { - Symbol return_expression_symbol = null; - - // avoid unnecessary ref/unref pair - if (stmt.return_expression.ref_sink && - stmt.return_expression.symbol_reference != null && - stmt.return_expression.symbol_reference.node is VariableDeclarator) { - var decl = (VariableDeclarator) stmt.return_expression.symbol_reference.node; - if (decl.type_reference.takes_ownership) { - /* return expression is local variable taking ownership and - * current method is transferring ownership */ - - // don't unref expression - return_expression_symbol = decl.symbol; - return_expression_symbol.active = false; - } - } - - create_local_free_expr (stmt.return_expression); - - if (stmt.return_expression.static_type != null && - stmt.return_expression.static_type.data_type != current_return_type.data_type) { - /* cast required */ - if (current_return_type.data_type is Class || current_return_type.data_type is Interface) { - stmt.return_expression.ccodenode = new InstanceCast ((CCodeExpression) stmt.return_expression.ccodenode, current_return_type.data_type); - } - } - - stmt.ccodenode = new CCodeReturnStatement ((CCodeExpression) stmt.return_expression.ccodenode); - - create_temp_decl (stmt, stmt.return_expression.temp_vars); - - if (return_expression_symbol != null) { - return_expression_symbol.active = true; - } - } - } - - private ref string get_symbol_lock_name (Symbol! sym) { - return "__lock_%s".printf (sym.name); - } - - /** - * Visit operation called for lock statements. - * - * @param stmt a lock statement - */ - public override void visit_lock_statement (LockStatement! stmt) { - var cn = new CCodeFragment (); - CCodeExpression l = null; - CCodeFunctionCall fc; - var inner_node = ((MemberAccess)stmt.resource).inner; - - if (inner_node == null) { - l = new CCodeIdentifier ("self"); - } else if (stmt.resource.symbol_reference.parent_symbol.node != current_class) { - l = new CCodeFunctionCall (new CCodeIdentifier (((DataType) stmt.resource.symbol_reference.parent_symbol.node).get_upper_case_cname ())); - ((CCodeFunctionCall) l).add_argument ((CCodeExpression)inner_node.ccodenode); - } else { - l = (CCodeExpression)inner_node.ccodenode; - } - l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (stmt.resource.symbol_reference)); - - fc = new CCodeFunctionCall (new CCodeIdentifier (((Method)mutex_type.data_type.symbol.lookup ("lock").node).get_cname ())); - fc.add_argument (l); - cn.append (new CCodeExpressionStatement (fc)); - - cn.append (stmt.body.ccodenode); - - fc = new CCodeFunctionCall (new CCodeIdentifier (((Method)mutex_type.data_type.symbol.lookup ("unlock").node).get_cname ())); - fc.add_argument (l); - cn.append (new CCodeExpressionStatement (fc)); - - stmt.ccodenode = cn; - } - - /** - * Visit operations called for array creation expresions. - * - * @param expr an array creation expression - */ - public override void visit_end_array_creation_expression (ArrayCreationExpression! expr) { - /* FIXME: rank > 1 not supported yet */ - if (expr.rank > 1) { - expr.error = true; - Report.error (expr.source_reference, "Creating arrays with rank greater than 1 is not supported yet"); - } - - var sizes = expr.get_sizes (); - var gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0")); - gnew.add_argument (new CCodeIdentifier (expr.element_type.get_cname ())); - /* FIXME: had to add Expression cast due to possible compiler bug */ - gnew.add_argument ((CCodeExpression) ((Expression) sizes.first ().data).ccodenode); - - if (expr.initializer_list != null) { - var ce = new CCodeCommaExpression (); - var temp_var = get_temp_variable_declarator (expr.static_type); - var name_cnode = new CCodeIdentifier (temp_var.name); - int i = 0; - - temp_vars.prepend (temp_var); - - /* FIXME: had to add Expression cast due to possible compiler bug */ - ce.append_expression (new CCodeAssignment (name_cnode, gnew)); - - foreach (Expression e in expr.initializer_list.get_initializers ()) { - ce.append_expression (new CCodeAssignment (new CCodeElementAccess (name_cnode, new CCodeConstant (i.to_string ())), (CCodeExpression) e.ccodenode)); - i++; - } - - ce.append_expression (name_cnode); - - expr.ccodenode = ce; - } else { - expr.ccodenode = gnew; - } - } - - public override void visit_boolean_literal (BooleanLiteral! expr) { - expr.ccodenode = new CCodeConstant (expr.value ? "TRUE" : "FALSE"); - } - - public override void visit_character_literal (CharacterLiteral! expr) { - if (expr.get_char () >= 0x20 && expr.get_char () < 0x80) { - expr.ccodenode = new CCodeConstant (expr.value); - } else { - expr.ccodenode = new CCodeConstant ("%uU".printf (expr.get_char ())); - } - } - - public override void visit_integer_literal (IntegerLiteral! expr) { - expr.ccodenode = new CCodeConstant (expr.value); - } - - public override void visit_real_literal (RealLiteral! expr) { - expr.ccodenode = new CCodeConstant (expr.value); - } - - public override void visit_string_literal (StringLiteral! expr) { - expr.ccodenode = new CCodeConstant (expr.value); - } - - public override void visit_null_literal (NullLiteral! expr) { - expr.ccodenode = new CCodeConstant ("NULL"); - } - - public override void visit_literal_expression (LiteralExpression! expr) { - expr.ccodenode = expr.literal.ccodenode; - - 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 (expr.inner is BaseAccess) { - if (m.base_interface_method != null) { - var base_iface = (Interface) m.base_interface_method.symbol.parent_symbol.node; - string parent_iface_var = "%s_%s_parent_iface".printf (current_class.get_lower_case_cname (null), base_iface.get_lower_case_cname (null)); - - expr.ccodenode = new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), m.name); - return; - } else if (m.base_method != null) { - var base_class = (Class) m.base_method.symbol.parent_symbol.node; - var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null)))); - vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null)))); - - expr.ccodenode = new CCodeMemberAccess.pointer (vcast, m.name); - return; - } - } - - if (m.base_interface_method != null) { - expr.ccodenode = new CCodeIdentifier (m.base_interface_method.get_cname ()); - } else if (m.base_method != null) { - expr.ccodenode = new CCodeIdentifier (m.base_method.get_cname ()); - } else { - expr.ccodenode = new CCodeIdentifier (m.get_cname ()); - } - } else if (expr.symbol_reference.node is ArrayLengthField) { - expr.ccodenode = get_array_length_cexpression (expr.inner, 1); - } 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) { - // FIXME: use C cast if debugging disabled - typed_inst = new CCodeFunctionCall (new CCodeIdentifier (((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.pointer (typed_inst, "priv"); - } else { - inst = typed_inst; - } - if (((DataType) f.symbol.parent_symbol.node).is_reference_type ()) { - expr.ccodenode = new CCodeMemberAccess.pointer (inst, f.get_cname ()); - } else { - expr.ccodenode = new CCodeMemberAccess (inst, f.get_cname ()); - } - } else { - expr.ccodenode = new CCodeIdentifier (f.get_cname ()); - } - } else if (expr.symbol_reference.node is Constant) { - var c = (Constant) expr.symbol_reference.node; - expr.ccodenode = new CCodeIdentifier (c.get_cname ()); - } else if (expr.symbol_reference.node is Property) { - var prop = (Property) expr.symbol_reference.node; - - if (!prop.no_accessor_method) { - var base_property = prop; - if (prop.base_property != null) { - base_property = prop.base_property; - } else if (prop.base_interface_property != null) { - base_property = prop.base_interface_property; - } - var base_property_type = (DataType) base_property.symbol.parent_symbol.node; - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_get_%s".printf (base_property_type.get_lower_case_cname (null), base_property.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 (base_property_type != base_type) { - // FIXME: use C cast if debugging disabled - var ccast = new CCodeFunctionCall (new CCodeIdentifier (base_property_type.get_upper_case_cname (null))); - ccast.add_argument (pub_inst); - typed_pub_inst = ccast; - } - - ccall.add_argument (typed_pub_inst); - expr.ccodenode = ccall; - } else { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get")); - - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT")); - ccast.add_argument (pub_inst); - ccall.add_argument (ccast); - - // property name is second argument of g_object_get - ccall.add_argument (prop.get_canonical_cconstant ()); - - - // we need a temporary variable to save the property value - var temp_decl = get_temp_variable_declarator (expr.static_type); - temp_vars.prepend (temp_decl); - - var ctemp = new CCodeIdentifier (temp_decl.name); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp)); - - - ccall.add_argument (new CCodeConstant ("NULL")); - - var ccomma = new CCodeCommaExpression (); - ccomma.append_expression (ccall); - ccomma.append_expression (ctemp); - expr.ccodenode = ccomma; - } - } else if (expr.symbol_reference.node is EnumValue) { - var ev = (EnumValue) expr.symbol_reference.node; - expr.ccodenode = new CCodeConstant (ev.get_cname ()); - } else if (expr.symbol_reference.node is VariableDeclarator) { - var decl = (VariableDeclarator) expr.symbol_reference.node; - expr.ccodenode = new CCodeIdentifier (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.reference_to_value_type) { - expr.ccodenode = new CCodeIdentifier ("(*%s)".printf (p.name)); - } else { - expr.ccodenode = new CCodeIdentifier (p.name); - } - } - } else if (expr.symbol_reference.node is Signal) { - var sig = (Signal) expr.symbol_reference.node; - var cl = (DataType) sig.symbol.parent_symbol.node; - - if (sig.has_emitter) { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_%s".printf (cl.get_lower_case_cname (null), sig.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 (cl != base_type) { - // FIXME: use C cast if debugging disabled - var ccast = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null))); - ccast.add_argument (pub_inst); - typed_pub_inst = ccast; - } - - ccall.add_argument (typed_pub_inst); - expr.ccodenode = ccall; - } else { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name")); - - // FIXME: use C cast if debugging disabled - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT")); - ccast.add_argument (pub_inst); - ccall.add_argument (ccast); - - ccall.add_argument (sig.get_canonical_cconstant ()); - - expr.ccodenode = ccall; - } - } - } - - public override void visit_parenthesized_expression (ParenthesizedExpression! expr) { - expr.ccodenode = new CCodeParenthesizedExpression ((CCodeExpression) expr.inner.ccodenode); - - 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 ("self"); - - if (current_type_symbol != null) { - /* base type is available if this is a type method */ - base_type = (DataType) current_type_symbol.node; - - if (!base_type.is_reference_type ()) { - pub_inst = new CCodeIdentifier ("(*self)"); - } - } - } else { - pub_inst = (CCodeExpression) expr.inner.ccodenode; - - if (expr.inner.static_type != null) { - base_type = expr.inner.static_type.data_type; - } - } - - process_cmember (expr, pub_inst, base_type); - - visit_expression (expr); - } - - private ref CCodeExpression! get_array_length_cexpression (Expression! array_expr, int dim) { - bool is_out = false; - - if (array_expr is UnaryExpression) { - var unary_expr = (UnaryExpression) array_expr; - if (unary_expr.operator == UnaryOperator.OUT) { - array_expr = unary_expr.inner; - is_out = true; - } - } - - if (array_expr is ArrayCreationExpression) { - var size = ((ArrayCreationExpression) array_expr).get_sizes (); - var length_expr = (Expression) size.nth_data (dim - 1); - return (CCodeExpression) length_expr.ccodenode; - } else if (array_expr.symbol_reference != null) { - if (array_expr.symbol_reference.node is FormalParameter) { - var param = (FormalParameter) array_expr.symbol_reference.node; - if (!param.no_array_length) { - var length_expr = new CCodeIdentifier (get_array_length_cname (param.name, dim)); - if (is_out) { - return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, length_expr); - } else { - return length_expr; - } - } - } else if (array_expr.symbol_reference.node is VariableDeclarator) { - var decl = (VariableDeclarator) array_expr.symbol_reference.node; - var length_expr = new CCodeIdentifier (get_array_length_cname (decl.name, dim)); - if (is_out) { - return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, length_expr); - } else { - return length_expr; - } - } else if (array_expr.symbol_reference.node is Field) { - var field = (Field) array_expr.symbol_reference.node; - if (!field.no_array_length) { - var length_cname = get_array_length_cname (field.name, dim); - - var ma = (MemberAccess) array_expr; - - CCodeExpression pub_inst = null; - DataType base_type = null; - CCodeExpression length_expr = null; - - if (ma.inner == null) { - pub_inst = new CCodeIdentifier ("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) ma.inner.ccodenode; - - if (ma.inner.static_type != null) { - base_type = ma.inner.static_type.data_type; - } - } - - if (field.instance) { - ref CCodeExpression typed_inst; - if (field.symbol.parent_symbol.node != base_type) { - // FIXME: use C cast if debugging disabled - typed_inst = new CCodeFunctionCall (new CCodeIdentifier (((DataType) field.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 (field.access == MemberAccessibility.PRIVATE) { - inst = new CCodeMemberAccess.pointer (typed_inst, "priv"); - } else { - inst = typed_inst; - } - if (((DataType) field.symbol.parent_symbol.node).is_reference_type ()) { - length_expr = new CCodeMemberAccess.pointer (inst, length_cname); - } else { - length_expr = new CCodeMemberAccess (inst, length_cname); - } - } else { - length_expr = new CCodeIdentifier (length_cname); - } - - if (is_out) { - return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, length_expr); - } else { - return length_expr; - } - } - } - } - - /* if we reach this point we were not able to get the explicit length of the array - * this is not allowed for an array of non-reference-type structs - */ - if (((Array)array_expr.static_type.data_type).element_type is Struct) { - var s = (Struct)((Array)array_expr.static_type.data_type).element_type; - if (!s.is_reference_type ()) { - array_expr.error = true; - Report.error (array_expr.source_reference, "arrays of value-type structs with no explicit length parameter are not supported"); - } - } - - if (!is_out) { - return new CCodeConstant ("-1"); - } else { - return new CCodeConstant ("NULL"); - } - } - - public override void visit_end_invocation_expression (InvocationExpression! expr) { - var ccall = new CCodeFunctionCall ((CCodeExpression) expr.call.ccodenode); - - Method m = null; - List<weak FormalParameter> 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 Invokable) { - var i = (Invokable) expr.call.symbol_reference.node; - params = i.get_parameters (); - - if (i is Method) { - m = (Method) i; - } else if (i is Signal) { - ccall = (CCodeFunctionCall) expr.call.ccodenode; - } - } - - if (m is ArrayResizeMethod) { - var array = (Array) m.symbol.parent_symbol.node; - ccall.add_argument (new CCodeIdentifier (array.get_cname ())); - } - - /* 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.base_interface_method != null) { - base_method = m.base_interface_method; - } else if (m.base_method != null) { - base_method = m.base_method; - } - - var req_cast = false; - if (ma.inner == null) { - instance = new CCodeIdentifier ("self"); - /* require casts for overriden and inherited methods */ - req_cast = m.overrides || m.base_interface_method != null || (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.data_type; - } - - if (m.instance_by_reference && (ma.inner != null || m.symbol.parent_symbol != current_type_symbol)) { - instance = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance); - } - - if (req_cast && ((DataType) m.symbol.parent_symbol.node).is_reference_type ()) { - // FIXME: use C cast if debugging disabled - var ccall = new CCodeFunctionCall (new CCodeIdentifier (((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); - } - } - - bool ellipsis = false; - - var i = 1; - weak List<weak FormalParameter> params_it = params; - foreach (Expression arg in expr.get_argument_list ()) { - /* explicitly use strong reference as ccall gets - * unrefed at end of inner block - */ - ref CCodeExpression cexpr = (CCodeExpression) arg.ccodenode; - if (params_it != null) { - var param = (FormalParameter) params_it.data; - ellipsis = param.ellipsis; - if (!ellipsis) { - if (param.type_reference.data_type != null - && param.type_reference.data_type.is_reference_type () - && arg.static_type.data_type != null) { - if (!param.no_array_length && param.type_reference.data_type is Array) { - var arr = (Array) param.type_reference.data_type; - for (int dim = 1; dim <= arr.rank; dim++) { - ccall.add_argument (get_array_length_cexpression (arg, dim)); - } - } - if (param.type_reference.data_type != arg.static_type.data_type) { - // FIXME: use C cast if debugging disabled - var ccall = new CCodeFunctionCall (new CCodeIdentifier (param.type_reference.data_type.get_upper_case_cname (null))); - ccall.add_argument (cexpr); - cexpr = ccall; - } - } else if (param.type_reference.data_type is Callback) { - cexpr = new CCodeCastExpression (cexpr, param.type_reference.data_type.get_cname ()); - } else if (param.type_reference.data_type == null - && arg.static_type.data_type is Struct) { - /* convert integer to pointer if this is a generic method parameter */ - var st = (Struct) arg.static_type.data_type; - if (st == bool_type.data_type || st.is_integer_type ()) { - var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GINT_TO_POINTER")); - cconv.add_argument (cexpr); - cexpr = cconv; - } - } - } - } - - ccall.add_argument (cexpr); - i++; - - if (params_it != null) { - params_it = params_it.next; - } - } - while (params_it != null) { - var param = (FormalParameter) params_it.data; - - if (param.ellipsis) { - ellipsis = true; - break; - } - - if (param.default_expression == null) { - Report.error (expr.source_reference, "no default expression for argument %d".printf (i)); - return; - } - - /* evaluate default expression here as the code - * generator might not have visited the formal - * parameter yet */ - param.default_expression.accept (this); - - if (!param.no_array_length && param.type_reference != null && - param.type_reference.data_type is Array) { - var arr = (Array) param.type_reference.data_type; - for (int dim = 1; dim <= arr.rank; dim++) { - ccall.add_argument (get_array_length_cexpression (param.default_expression, dim)); - } - } - - ccall.add_argument ((CCodeExpression) param.default_expression.ccodenode); - i++; - - params_it = params_it.next; - } - - if (m != null && m.instance && m.instance_last) { - ccall.add_argument (instance); - } else if (ellipsis) { - /* ensure variable argument list ends with NULL - * except when using printf-style arguments */ - if (m == null || !m.printf_format) { - ccall.add_argument (new CCodeConstant ("NULL")); - } - } - - if (m != null && m.instance && m.returns_modified_pointer) { - expr.ccodenode = new CCodeAssignment (instance, ccall); - } else { - /* cast pointer to actual type if this is a generic method return value */ - if (m != null && m.return_type.type_parameter != null && expr.static_type.data_type != null) { - if (expr.static_type.data_type is Struct) { - var st = (Struct) expr.static_type.data_type; - if (st == uint_type.data_type) { - var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GPOINTER_TO_UINT")); - cconv.add_argument (ccall); - ccall = cconv; - } else if (st == bool_type.data_type || st.is_integer_type ()) { - var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GPOINTER_TO_INT")); - cconv.add_argument (ccall); - ccall = cconv; - } - } - } - - expr.ccodenode = ccall; - - visit_expression (expr); - } - - if (m is ArrayResizeMethod) { - // FIXME: size expression must not be evaluated twice at runtime (potential side effects) - var new_size = (CCodeExpression) ((CodeNode) expr.get_argument_list ().data).ccodenode; - - var temp_decl = get_temp_variable_declarator (int_type); - var temp_ref = new CCodeIdentifier (temp_decl.name); - - temp_vars.prepend (temp_decl); - - /* memset needs string.h */ - string_h_needed = true; - - var clen = get_array_length_cexpression (ma.inner, 1); - var celems = (CCodeExpression)ma.inner.ccodenode; - var csizeof = new CCodeIdentifier ("sizeof (%s)".printf (ma.inner.static_type.data_type.get_cname ())); - var cdelta = new CCodeParenthesizedExpression (new CCodeBinaryExpression (CCodeBinaryOperator.MINUS, temp_ref, clen)); - var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN, temp_ref, clen); - - var czero = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - czero.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, celems, clen)); - czero.add_argument (new CCodeConstant ("0")); - czero.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, csizeof, cdelta)); - - var ccomma = new CCodeCommaExpression (); - ccomma.append_expression (new CCodeAssignment (temp_ref, new_size)); - ccomma.append_expression ((CCodeExpression) expr.ccodenode); - ccomma.append_expression (new CCodeConditionalExpression (ccheck, czero, new CCodeConstant ("NULL"))); - ccomma.append_expression (new CCodeAssignment (get_array_length_cexpression (ma.inner, 1), temp_ref)); - - expr.ccodenode = ccomma; - } - } - - public override void visit_element_access (ElementAccess! expr) - { - List<weak Expression> indices = expr.get_indices (); - int rank = indices.length (); - - if (rank == 1) { - /* FIXME: had to add Expression cast due to possible compiler bug */ - expr.ccodenode = new CCodeElementAccess ((CCodeExpression)expr.container.ccodenode, (CCodeExpression)((Expression)indices.first ().data).ccodenode); - } else { - expr.error = true; - Report.error (expr.source_reference, "Arrays with more then one dimension are not supported yet"); - return; - } - - visit_expression (expr); - } - - public override void visit_base_access (BaseAccess! expr) { - expr.ccodenode = new InstanceCast (new CCodeIdentifier ("self"), expr.static_type.data_type); - } - - public override void visit_postfix_expression (PostfixExpression! expr) { - MemberAccess ma = find_property_access (expr.inner); - if (ma != null) { - // property postfix expression - var prop = (Property) ma.symbol_reference.node; - - var ccomma = new CCodeCommaExpression (); - - // assign current value to temp variable - var temp_decl = get_temp_variable_declarator (prop.type_reference); - temp_vars.prepend (temp_decl); - ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), (CCodeExpression) expr.inner.ccodenode)); - - // increment/decrement property - var op = expr.increment ? CCodeBinaryOperator.PLUS : CCodeBinaryOperator.MINUS; - var cexpr = new CCodeBinaryExpression (op, new CCodeIdentifier (temp_decl.name), new CCodeConstant ("1")); - var ccall = get_property_set_call (prop, ma, cexpr); - ccomma.append_expression (ccall); - - // return previous value - ccomma.append_expression (new CCodeIdentifier (temp_decl.name)); - - expr.ccodenode = ccomma; - return; - } - - var op = expr.increment ? CCodeUnaryOperator.POSTFIX_INCREMENT : CCodeUnaryOperator.POSTFIX_DECREMENT; - - expr.ccodenode = new CCodeUnaryExpression (op, (CCodeExpression) expr.inner.ccodenode); - - visit_expression (expr); - } - - private MemberAccess find_property_access (Expression! expr) { - if (expr is ParenthesizedExpression) { - var pe = (ParenthesizedExpression) expr; - return find_property_access (pe.inner); - } - - if (!(expr is MemberAccess)) { - return null; - } - - var ma = (MemberAccess) expr; - if (ma.symbol_reference.node is Property) { - return ma; - } - - return null; - } - - private ref CCodeExpression get_ref_expression (Expression! expr) { - /* (temp = expr, temp == NULL ? NULL : ref (temp)) - * - * can be simplified to - * ref (expr) - * if static type of expr is non-null - */ - - if (expr.static_type.data_type == null && - expr.static_type.type_parameter != null) { - Report.warning (expr.source_reference, "Missing generics support for memory management"); - return (CCodeExpression) expr.ccodenode; - } - - string ref_function; - if (expr.static_type.data_type.is_reference_counting ()) { - ref_function = expr.static_type.data_type.get_ref_function (); - } else { - if (expr.static_type.data_type != string_type.data_type) { - // duplicating non-reference counted structs may cause side-effects (and performance issues) - Report.warning (expr.source_reference, "duplicating %s instance, use weak variable or explicitly invoke copy method".printf (expr.static_type.data_type.name)); - } - ref_function = expr.static_type.data_type.get_dup_function (); - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (ref_function)); - - if (expr.static_type.non_null) { - ccall.add_argument ((CCodeExpression) expr.ccodenode); - - return ccall; - } else { - var decl = get_temp_variable_declarator (expr.static_type, false); - temp_vars.prepend (decl); - - var ctemp = new CCodeIdentifier (decl.name); - - var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, new CCodeConstant ("NULL")); - - ccall.add_argument (ctemp); - - var ccomma = new CCodeCommaExpression (); - ccomma.append_expression (new CCodeAssignment (ctemp, (CCodeExpression) expr.ccodenode)); - - if (ref_function == "g_list_copy") { - bool is_ref = false; - bool is_class = false; - bool is_interface = false; - - foreach (TypeReference type_arg in expr.static_type.get_type_arguments ()) { - is_ref |= type_arg.takes_ownership; - is_class |= type_arg.data_type is Class; - is_interface |= type_arg.data_type is Interface; - } - - if (is_ref && (is_class || is_interface)) { - var crefcall = new CCodeFunctionCall (new CCodeIdentifier ("g_list_foreach")); - - crefcall.add_argument (ctemp); - crefcall.add_argument (new CCodeIdentifier ("(GFunc) g_object_ref")); - crefcall.add_argument (new CCodeConstant ("NULL")); - - ccomma.append_expression (crefcall); - } - } - - ccomma.append_expression (new CCodeConditionalExpression (cisnull, new CCodeConstant ("NULL"), ccall)); - - return ccomma; - } - } - - private void visit_expression (Expression! expr) { - if (expr.static_type != null && - expr.static_type.transfers_ownership && - expr.static_type.floating_reference) { - /* constructor of GInitiallyUnowned subtype - * returns floating reference, sink it - */ - var csink = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref_sink")); - csink.add_argument ((CCodeExpression) expr.ccodenode); - - expr.ccodenode = csink; - } - - 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 (new CCodeAssignment (new CCodeIdentifier (decl.name), (CCodeExpression) expr.ccodenode)); - } else if (expr.ref_missing) { - expr.ccodenode = get_ref_expression (expr); - } - } - - public override void visit_end_object_creation_expression (ObjectCreationExpression! expr) { - if (expr.symbol_reference == null) { - // no creation method - if (expr.type_reference.data_type is Class) { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_new")); - - ccall.add_argument (new CCodeConstant (expr.type_reference.data_type.get_type_id ())); - - ccall.add_argument (new CCodeConstant ("NULL")); - - expr.ccodenode = ccall; - } else if (expr.type_reference.data_type == list_type || - expr.type_reference.data_type == slist_type) { - // NULL is an empty list - expr.ccodenode = new CCodeConstant ("NULL"); - } else { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_new0")); - - ccall.add_argument (new CCodeConstant (expr.type_reference.data_type.get_cname ())); - - ccall.add_argument (new CCodeConstant ("1")); - - expr.ccodenode = ccall; - } - } else { - // use creation method - var m = (Method) expr.symbol_reference.node; - var params = m.get_parameters (); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ())); - - if (expr.type_reference.data_type is Class) { - foreach (TypeReference type_arg in expr.type_reference.get_type_arguments ()) { - if (type_arg.takes_ownership) { - ccall.add_argument (get_destroy_func_expression (type_arg)); - } else { - ccall.add_argument (new CCodeConstant ("NULL")); - } - } - } - - bool ellipsis = false; - - int i = 1; - weak List<weak FormalParameter> params_it = params; - foreach (Expression arg in expr.get_argument_list ()) { - /* explicitly use strong reference as ccall gets - * unrefed at end of inner block - */ - ref CCodeExpression cexpr = (CCodeExpression) arg.ccodenode; - if (params_it != null) { - var param = (FormalParameter) params_it.data; - ellipsis = param.ellipsis; - if (!param.ellipsis - && param.type_reference.data_type != null - && param.type_reference.data_type.is_reference_type () - && arg.static_type.data_type != null - && param.type_reference.data_type != arg.static_type.data_type) { - // FIXME: use C cast if debugging disabled - var ccall = new CCodeFunctionCall (new CCodeIdentifier (param.type_reference.data_type.get_upper_case_cname (null))); - ccall.add_argument (cexpr); - cexpr = ccall; - } - } - - ccall.add_argument (cexpr); - i++; - - if (params_it != null) { - params_it = params_it.next; - } - } - while (params_it != null) { - var param = (FormalParameter) params_it.data; - - if (param.ellipsis) { - ellipsis = true; - break; - } - - if (param.default_expression == null) { - Report.error (expr.source_reference, "no default expression for argument %d".printf (i)); - return; - } - - /* 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++; - - params_it = params_it.next; - } - - if (ellipsis) { - // ensure variable argument list ends with NULL - ccall.add_argument (new CCodeConstant ("NULL")); - } - - expr.ccodenode = ccall; - } - - visit_expression (expr); - } - - public override void visit_typeof_expression (TypeofExpression! expr) { - expr.ccodenode = new CCodeIdentifier (expr.type_reference.data_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.INCREMENT) { - op = CCodeUnaryOperator.PREFIX_INCREMENT; - } else if (expr.operator == UnaryOperator.DECREMENT) { - op = CCodeUnaryOperator.PREFIX_DECREMENT; - } else if (expr.operator == UnaryOperator.REF) { - op = CCodeUnaryOperator.ADDRESS_OF; - } else if (expr.operator == UnaryOperator.OUT) { - op = CCodeUnaryOperator.ADDRESS_OF; - } - expr.ccodenode = new CCodeUnaryExpression (op, (CCodeExpression) expr.inner.ccodenode); - - visit_expression (expr); - } - - public override void visit_cast_expression (CastExpression! expr) { - if (expr.type_reference.data_type is Class || expr.type_reference.data_type is Interface) { - // GObject cast - expr.ccodenode = new InstanceCast ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.data_type); - } else { - expr.ccodenode = new CCodeCastExpression ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.get_cname ()); - } - - visit_expression (expr); - } - - public override void visit_pointer_indirection (PointerIndirection! expr) { - expr.ccodenode = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, (CCodeExpression) expr.inner.ccodenode); - } - - public override void visit_addressof_expression (AddressofExpression! expr) { - expr.ccodenode = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) expr.inner.ccodenode); - } - - public override void visit_reference_transfer_expression (ReferenceTransferExpression! expr) { - /* (tmp = var, var = null, tmp) */ - var ccomma = new CCodeCommaExpression (); - var temp_decl = get_temp_variable_declarator (expr.static_type); - temp_vars.prepend (temp_decl); - var cvar = new CCodeIdentifier (temp_decl.name); - - ccomma.append_expression (new CCodeAssignment (cvar, (CCodeExpression) expr.inner.ccodenode)); - ccomma.append_expression (new CCodeAssignment ((CCodeExpression) expr.inner.ccodenode, new CCodeConstant ("NULL"))); - ccomma.append_expression (cvar); - expr.ccodenode = ccomma; - - visit_expression (expr); - } - - public override void visit_binary_expression (BinaryExpression! expr) { - CCodeBinaryOperator op; - if (expr.operator == BinaryOperator.PLUS) { - op = CCodeBinaryOperator.PLUS; - } else if (expr.operator == BinaryOperator.MINUS) { - op = CCodeBinaryOperator.MINUS; - } else if (expr.operator == BinaryOperator.MUL) { - op = CCodeBinaryOperator.MUL; - } else if (expr.operator == BinaryOperator.DIV) { - op = CCodeBinaryOperator.DIV; - } else if (expr.operator == BinaryOperator.MOD) { - op = CCodeBinaryOperator.MOD; - } else if (expr.operator == BinaryOperator.SHIFT_LEFT) { - op = CCodeBinaryOperator.SHIFT_LEFT; - } else if (expr.operator == BinaryOperator.SHIFT_RIGHT) { - op = CCodeBinaryOperator.SHIFT_RIGHT; - } else if (expr.operator == BinaryOperator.LESS_THAN) { - op = CCodeBinaryOperator.LESS_THAN; - } else if (expr.operator == BinaryOperator.GREATER_THAN) { - op = CCodeBinaryOperator.GREATER_THAN; - } else if (expr.operator == BinaryOperator.LESS_THAN_OR_EQUAL) { - op = CCodeBinaryOperator.LESS_THAN_OR_EQUAL; - } else if (expr.operator == BinaryOperator.GREATER_THAN_OR_EQUAL) { - op = CCodeBinaryOperator.GREATER_THAN_OR_EQUAL; - } else if (expr.operator == BinaryOperator.EQUALITY) { - op = CCodeBinaryOperator.EQUALITY; - } else if (expr.operator == BinaryOperator.INEQUALITY) { - op = CCodeBinaryOperator.INEQUALITY; - } else if (expr.operator == BinaryOperator.BITWISE_AND) { - op = CCodeBinaryOperator.BITWISE_AND; - } else if (expr.operator == BinaryOperator.BITWISE_OR) { - op = CCodeBinaryOperator.BITWISE_OR; - } else if (expr.operator == BinaryOperator.BITWISE_XOR) { - op = CCodeBinaryOperator.BITWISE_XOR; - } else if (expr.operator == BinaryOperator.AND) { - op = CCodeBinaryOperator.AND; - } else if (expr.operator == BinaryOperator.OR) { - op = CCodeBinaryOperator.OR; - } - - var cleft = (CCodeExpression) expr.left.ccodenode; - var cright = (CCodeExpression) expr.right.ccodenode; - - if (expr.operator == BinaryOperator.EQUALITY || - expr.operator == BinaryOperator.INEQUALITY) { - if (expr.left.static_type != null && expr.right.static_type != null && - expr.left.static_type.data_type is Class && expr.right.static_type.data_type is Class) { - var left_cl = (Class) expr.left.static_type.data_type; - var right_cl = (Class) expr.right.static_type.data_type; - - if (left_cl != right_cl) { - if (left_cl.is_subtype_of (right_cl)) { - cleft = new InstanceCast (cleft, right_cl); - } else if (right_cl.is_subtype_of (left_cl)) { - cright = new InstanceCast (cright, left_cl); - } - } - } - } - - expr.ccodenode = new CCodeBinaryExpression (op, cleft, cright); - - visit_expression (expr); - } - - public override void visit_type_check (TypeCheck! expr) { - var ccheck = new CCodeFunctionCall (new CCodeIdentifier (expr.type_reference.data_type.get_upper_case_cname ("IS_"))); - ccheck.add_argument ((CCodeExpression) expr.expression.ccodenode); - expr.ccodenode = ccheck; - } - - public override void visit_conditional_expression (ConditionalExpression! expr) { - expr.ccodenode = new CCodeConditionalExpression ((CCodeExpression) expr.condition.ccodenode, (CCodeExpression) expr.true_expression.ccodenode, (CCodeExpression) expr.false_expression.ccodenode); - } - - public override void visit_end_lambda_expression (LambdaExpression! l) { - l.ccodenode = new CCodeIdentifier (l.method.get_cname ()); - } - - public override void visit_end_assignment (Assignment! a) { - MemberAccess ma = null; - - if (a.left is MemberAccess) { - ma = (MemberAccess)a.left; - } - - if (a.left.symbol_reference != null && a.left.symbol_reference.node is Property) { - var prop = (Property) a.left.symbol_reference.node; - - if (current_class != null && ma.inner == null && in_creation_method) { - // this property is used as a construction parameter - var cpointer = new CCodeIdentifier ("__params_it"); - - var ccomma = new CCodeCommaExpression (); - // set name in array for current parameter - var cnamemember = new CCodeMemberAccess.pointer (cpointer, "name"); - var cnameassign = new CCodeAssignment (cnamemember, prop.get_canonical_cconstant ()); - ccomma.append_expression (cnameassign); - - var gvaluearg = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (cpointer, "value")); - - // initialize GValue in array for current parameter - var cvalueinit = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init")); - cvalueinit.add_argument (gvaluearg); - cvalueinit.add_argument (new CCodeIdentifier (prop.type_reference.data_type.get_type_id ())); - ccomma.append_expression (cvalueinit); - - // set GValue for current parameter - var cvalueset = new CCodeFunctionCall (get_value_setter_function (prop.type_reference)); - cvalueset.add_argument (gvaluearg); - cvalueset.add_argument ((CCodeExpression) a.right.ccodenode); - ccomma.append_expression (cvalueset); - - // move pointer to next parameter in array - ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, cpointer)); - - a.ccodenode = ccomma; - } else { - ref CCodeExpression cexpr = (CCodeExpression) a.right.ccodenode; - - if (!prop.no_accessor_method - && prop.type_reference.data_type != null - && prop.type_reference.data_type.is_reference_type () - && a.right.static_type.data_type != null - && prop.type_reference.data_type != a.right.static_type.data_type) { - /* cast is necessary */ - var ccast = new CCodeFunctionCall (new CCodeIdentifier (prop.type_reference.data_type.get_upper_case_cname (null))); - ccast.add_argument (cexpr); - cexpr = ccast; - } - - if (a.operator != AssignmentOperator.SIMPLE) { - CCodeBinaryOperator cop; - if (a.operator == AssignmentOperator.BITWISE_OR) { - cop = CCodeBinaryOperator.BITWISE_OR; - } else if (a.operator == AssignmentOperator.BITWISE_AND) { - cop = CCodeBinaryOperator.BITWISE_AND; - } else if (a.operator == AssignmentOperator.BITWISE_XOR) { - cop = CCodeBinaryOperator.BITWISE_XOR; - } else if (a.operator == AssignmentOperator.ADD) { - cop = CCodeBinaryOperator.PLUS; - } else if (a.operator == AssignmentOperator.SUB) { - cop = CCodeBinaryOperator.MINUS; - } else if (a.operator == AssignmentOperator.MUL) { - cop = CCodeBinaryOperator.MUL; - } else if (a.operator == AssignmentOperator.DIV) { - cop = CCodeBinaryOperator.DIV; - } else if (a.operator == AssignmentOperator.PERCENT) { - cop = CCodeBinaryOperator.MOD; - } else if (a.operator == AssignmentOperator.SHIFT_LEFT) { - cop = CCodeBinaryOperator.SHIFT_LEFT; - } else if (a.operator == AssignmentOperator.SHIFT_RIGHT) { - cop = CCodeBinaryOperator.SHIFT_RIGHT; - } - cexpr = new CCodeBinaryExpression (cop, (CCodeExpression) a.left.ccodenode, new CCodeParenthesizedExpression (cexpr)); - } - - var ccall = get_property_set_call (prop, ma, cexpr); - - // assignments are expressions, so return the current property value - var ccomma = new CCodeCommaExpression (); - ccomma.append_expression (ccall); // update property - ccomma.append_expression ((CCodeExpression) ma.ccodenode); // current property value - - a.ccodenode = ccomma; - } - } else if (a.left.symbol_reference != null && a.left.symbol_reference.node is Signal) { - var sig = (Signal) a.left.symbol_reference.node; - - var m = (Method) a.right.symbol_reference.node; - - string connect_func; - bool disconnect = false; - - if (a.operator == AssignmentOperator.ADD) { - connect_func = "g_signal_connect_object"; - if (!m.instance) { - connect_func = "g_signal_connect"; - } - } else if (a.operator == AssignmentOperator.SUB) { - connect_func = "g_signal_handlers_disconnect_matched"; - disconnect = true; - } else { - a.error = true; - Report.error (a.source_reference, "Specified compound assignment type for signals not supported."); - return; - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (connect_func)); - - if (ma.inner != null) { - ccall.add_argument ((CCodeExpression) ma.inner.ccodenode); - } else { - ccall.add_argument (new CCodeIdentifier ("self")); - } - - if (!disconnect) { - ccall.add_argument (sig.get_canonical_cconstant ()); - } else { - ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA")); - - // get signal id - var ccomma = new CCodeCommaExpression (); - var temp_decl = get_temp_variable_declarator (uint_type); - temp_vars.prepend (temp_decl); - var parse_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_parse_name")); - parse_call.add_argument (sig.get_canonical_cconstant ()); - var decl_type = (DataType) sig.symbol.parent_symbol.node; - parse_call.add_argument (new CCodeIdentifier (decl_type.get_type_id ())); - parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name))); - parse_call.add_argument (new CCodeConstant ("NULL")); - parse_call.add_argument (new CCodeConstant ("FALSE")); - ccomma.append_expression (parse_call); - ccomma.append_expression (new CCodeIdentifier (temp_decl.name)); - - ccall.add_argument (ccomma); - - ccall.add_argument (new CCodeConstant ("0")); - ccall.add_argument (new CCodeConstant ("NULL")); - } - - ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (m.get_cname ()), "GCallback")); - - 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 ("self")); - } - } else if (a.right is LambdaExpression) { - ccall.add_argument (new CCodeIdentifier ("self")); - } - if (!disconnect) { - ccall.add_argument (new CCodeConstant ("0")); - } - } else { - ccall.add_argument (new CCodeConstant ("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.data_type != null - && a.right.static_type.data_type != null - && a.left.static_type.data_type.is_reference_type () - && a.right.static_type.data_type != a.left.static_type.data_type) { - var ccast = new CCodeFunctionCall (new CCodeIdentifier (a.left.static_type.data_type.get_upper_case_cname (null))); - ccast.add_argument (rhs); - rhs = ccast; - } - - bool unref_old = (memory_management && a.left.static_type.takes_ownership); - bool array = false; - if (a.left.static_type.data_type is Array) { - array = !(get_array_length_cexpression (a.left, 1) is CCodeConstant); - } - - if (unref_old || array) { - var ccomma = new CCodeCommaExpression (); - - var temp_decl = get_temp_variable_declarator (a.left.static_type); - temp_vars.prepend (temp_decl); - ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), rhs)); - if (unref_old) { - /* unref old value */ - ccomma.append_expression (get_unref_expression ((CCodeExpression) a.left.ccodenode, a.left.static_type)); - } - - if (array) { - var lhs_array_len = get_array_length_cexpression (a.left, 1); - var rhs_array_len = get_array_length_cexpression (a.right, 1); - ccomma.append_expression (new CCodeAssignment (lhs_array_len, rhs_array_len)); - } - - ccomma.append_expression (new CCodeIdentifier (temp_decl.name)); - - 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 ((CCodeExpression) a.left.ccodenode, rhs, cop); - } - } - - private ref CCodeFunctionCall get_property_set_call (Property! prop, MemberAccess! ma, CCodeExpression! cexpr) { - 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 (new CCodeIdentifier (set_func)); - - /* target instance is first argument */ - ref CCodeExpression instance; - var req_cast = false; - - if (ma.inner == null) { - instance = new CCodeIdentifier ("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.data_type; - } - - if (req_cast && ((DataType) prop.symbol.parent_symbol.node).is_reference_type ()) { - var ccast = new CCodeFunctionCall (new CCodeIdentifier (((DataType) prop.symbol.parent_symbol.node).get_upper_case_cname (null))); - ccast.add_argument (instance); - instance = ccast; - } - - ccall.add_argument (instance); - - if (prop.no_accessor_method) { - /* property name is second argument of g_object_set */ - ccall.add_argument (prop.get_canonical_cconstant ()); - } - - ccall.add_argument (cexpr); - - if (prop.no_accessor_method) { - ccall.add_argument (new CCodeConstant ("NULL")); - } - - return ccall; - } -} |