From: Alan Knowles Date: Sat, 20 Jan 2024 17:01:58 +0000 (+0800) Subject: change run to use meson/ninja and then exec. - remove libvala code from application... X-Git-Tag: release-5.0.1~12 X-Git-Url: http://git.roojs.org/?p=roobuilder;a=commitdiff_plain;h=fdd0aa3d4dcb5df79ba27d6721a44d1283d738e8 change run to use meson/ninja and then exec. - remove libvala code from application (as its not used for compile) + caching on toSource --- diff --git a/.roobuilder.jcfg b/.roobuilder.jcfg index 0ebdbf701..1dc1f9cfe 100644 --- a/.roobuilder.jcfg +++ b/.roobuilder.jcfg @@ -28,37 +28,6 @@ "src/Builder4/WindowState.vala", "src/Palete/GirObject.vala", "src/Palete/Gir.vala", - "src/codegen/valaccodearraymodule.vala", - "src/codegen/valaccodeassignmentmodule.vala", - "src/codegen/valaccodeattribute.vala", - "src/codegen/valaccodebasemodule.vala", - "src/codegen/valaccodecompiler.vala", - "src/codegen/valaccodecontrolflowmodule.vala", - "src/codegen/valaccodedelegatemodule.vala", - "src/codegen/valaccodememberaccessmodule.vala", - "src/codegen/valaccodemethodcallmodule.vala", - "src/codegen/valaccodemethodmodule.vala", - "src/codegen/valaccodestructmodule.vala", - "src/codegen/valaccode.vala", - "src/codegen/valaclassregisterfunction.vala", - "src/codegen/valactype.vala", - "src/codegen/valaenumregisterfunction.vala", - "src/codegen/valagasyncmodule.vala", - "src/codegen/valagdbusclientmodule.vala", - "src/codegen/valagdbusservermodule.vala", - "src/codegen/valagdbusmodule.vala", - "src/codegen/valagerrormodule.vala", - "src/codegen/valagirwriter.vala", - "src/codegen/valaglibvalue.vala", - "src/codegen/valagobjectmodule.vala", - "src/codegen/valagsignalmodule.vala", - "src/codegen/valagtkmodule.vala", - "src/codegen/valagtypemodule.vala", - "src/codegen/valagvaluemodule.vala", - "src/codegen/valagvariantmodule.vala", - "src/codegen/valainterfaceregisterfunction.vala", - "src/codegen/valastructregisterfunction.vala", - "src/codegen/valatyperegisterfunction.vala", "src/JsRender/Dir.vala", "src/JsRender/Gtk.vala", "src/JsRender/JsonGen.vala", @@ -76,67 +45,10 @@ "src/Palete/Gtk.vala", "src/Palete/Palete.vala", "src/Palete/Roo.vala", - "src/Palete/ValaSourceCompiler.vala", "src/Palete/VapiParser.vala", "src/Builder4/WindowLeftTree.bjs", "src/Builder4/PopoverAddProp.bjs", "src/Builder4/PopoverFileDetails.bjs", - "src/ccode/valaccode.vala", - "src/ccode/valaccodeassignment.vala", - "src/ccode/valaccodebinaryexpression.vala", - "src/ccode/valaccodeblock.vala", - "src/ccode/valaccodebreakstatement.vala", - "src/ccode/valaccodecasestatement.vala", - "src/ccode/valaccodecastexpression.vala", - "src/ccode/valaccodecommaexpression.vala", - "src/ccode/valaccodecomment.vala", - "src/ccode/valaccodeconditionalexpression.vala", - "src/ccode/valaccodeconstant.vala", - "src/ccode/valaccodeconstantidentifier.vala", - "src/ccode/valaccodecontinuestatement.vala", - "src/ccode/valaccodedeclaration.vala", - "src/ccode/valaccodedeclarator.vala", - "src/ccode/valaccodedefine.vala", - "src/ccode/valaccodedostatement.vala", - "src/ccode/valaccodeelementaccess.vala", - "src/ccode/valaccodeemptystatement.vala", - "src/ccode/valaccodeenum.vala", - "src/ccode/valaccodeenumvalue.vala", - "src/ccode/valaccodeexpression.vala", - "src/ccode/valaccodeexpressionstatement.vala", - "src/ccode/valaccodefile.vala", - "src/ccode/valaccodeforstatement.vala", - "src/ccode/valaccodefragment.vala", - "src/ccode/valaccodefunction.vala", - "src/ccode/valaccodefunctioncall.vala", - "src/ccode/valaccodefunctiondeclarator.vala", - "src/ccode/valaccodeggnucsection.vala", - "src/ccode/valaccodegotostatement.vala", - "src/ccode/valaccodeidentifier.vala", - "src/ccode/valaccodeifsection.vala", - "src/ccode/valaccodeifstatement.vala", - "src/ccode/valaccodeincludedirective.vala", - "src/ccode/valaccodeinitializerlist.vala", - "src/ccode/valaccodeinvalidexpression.vala", - "src/ccode/valaccodelabel.vala", - "src/ccode/valaccodelinedirective.vala", - "src/ccode/valaccodemacroreplacement.vala", - "src/ccode/valaccodememberaccess.vala", - "src/ccode/valaccodemodifiers.vala", - "src/ccode/valaccodenewline.vala", - "src/ccode/valaccodenode.vala", - "src/ccode/valaccodeoncesection.vala", - "src/ccode/valaccodeparameter.vala", - "src/ccode/valaccodeparenthesizedexpression.vala", - "src/ccode/valaccodereturnstatement.vala", - "src/ccode/valaccodestatement.vala", - "src/ccode/valaccodestruct.vala", - "src/ccode/valaccodeswitchstatement.vala", - "src/ccode/valaccodetypedefinition.vala", - "src/ccode/valaccodeunaryexpression.vala", - "src/ccode/valaccodevariabledeclarator.vala", - "src/ccode/valaccodewhilestatement.vala", - "src/ccode/valaccodewriter.vala", "src/Project/GtkValaSettings.vala", "src/Project/Project.vala", "src/Project/Gtk.vala", @@ -146,12 +58,12 @@ "src/Resources.vala", "src/Spawn.vala", "src/Application.vala", - "src/Palete/ValalCompileQueue.vala", "src/Palete/Javascript.vala", "src/Project/Meson.vala", "src/Palete/RooDatabase.vala", "src/Palete/LanguageClient.vala", "src/Palete/LanguageClientVala.vala", + "src/Palete/LanguageClientJavascript.vala", "src/Lsp.vala", "src/Palete/LanguageClientDummy.vala", "src/Palete/ValaCompileRequest.vala" @@ -177,4 +89,4 @@ "jsonrpc-glib-1.0", "gio-unix-2.0" ] -} +} \ No newline at end of file diff --git a/meson.build b/meson.build index 471a2b3ed..12bb9e1d3 100644 --- a/meson.build +++ b/meson.build @@ -70,37 +70,6 @@ roobuilder_src = files([ 'src/Builder4/WindowState.vala', 'src/Palete/GirObject.vala', 'src/Palete/Gir.vala', - 'src/codegen/valaccodearraymodule.vala', - 'src/codegen/valaccodeassignmentmodule.vala', - 'src/codegen/valaccodeattribute.vala', - 'src/codegen/valaccodebasemodule.vala', - 'src/codegen/valaccodecompiler.vala', - 'src/codegen/valaccodecontrolflowmodule.vala', - 'src/codegen/valaccodedelegatemodule.vala', - 'src/codegen/valaccodememberaccessmodule.vala', - 'src/codegen/valaccodemethodcallmodule.vala', - 'src/codegen/valaccodemethodmodule.vala', - 'src/codegen/valaccodestructmodule.vala', - 'src/codegen/valaccode.vala', - 'src/codegen/valaclassregisterfunction.vala', - 'src/codegen/valactype.vala', - 'src/codegen/valaenumregisterfunction.vala', - 'src/codegen/valagasyncmodule.vala', - 'src/codegen/valagdbusclientmodule.vala', - 'src/codegen/valagdbusservermodule.vala', - 'src/codegen/valagdbusmodule.vala', - 'src/codegen/valagerrormodule.vala', - 'src/codegen/valagirwriter.vala', - 'src/codegen/valaglibvalue.vala', - 'src/codegen/valagobjectmodule.vala', - 'src/codegen/valagsignalmodule.vala', - 'src/codegen/valagtkmodule.vala', - 'src/codegen/valagtypemodule.vala', - 'src/codegen/valagvaluemodule.vala', - 'src/codegen/valagvariantmodule.vala', - 'src/codegen/valainterfaceregisterfunction.vala', - 'src/codegen/valastructregisterfunction.vala', - 'src/codegen/valatyperegisterfunction.vala', 'src/JsRender/Dir.vala', 'src/JsRender/Gtk.vala', 'src/JsRender/JsonGen.vala', @@ -118,67 +87,10 @@ roobuilder_src = files([ 'src/Palete/Gtk.vala', 'src/Palete/Palete.vala', 'src/Palete/Roo.vala', - 'src/Palete/ValaSourceCompiler.vala', 'src/Palete/VapiParser.vala', 'src/Builder4/WindowLeftTree.vala', 'src/Builder4/PopoverAddProp.vala', 'src/Builder4/PopoverFileDetails.vala', - 'src/ccode/valaccode.vala', - 'src/ccode/valaccodeassignment.vala', - 'src/ccode/valaccodebinaryexpression.vala', - 'src/ccode/valaccodeblock.vala', - 'src/ccode/valaccodebreakstatement.vala', - 'src/ccode/valaccodecasestatement.vala', - 'src/ccode/valaccodecastexpression.vala', - 'src/ccode/valaccodecommaexpression.vala', - 'src/ccode/valaccodecomment.vala', - 'src/ccode/valaccodeconditionalexpression.vala', - 'src/ccode/valaccodeconstant.vala', - 'src/ccode/valaccodeconstantidentifier.vala', - 'src/ccode/valaccodecontinuestatement.vala', - 'src/ccode/valaccodedeclaration.vala', - 'src/ccode/valaccodedeclarator.vala', - 'src/ccode/valaccodedefine.vala', - 'src/ccode/valaccodedostatement.vala', - 'src/ccode/valaccodeelementaccess.vala', - 'src/ccode/valaccodeemptystatement.vala', - 'src/ccode/valaccodeenum.vala', - 'src/ccode/valaccodeenumvalue.vala', - 'src/ccode/valaccodeexpression.vala', - 'src/ccode/valaccodeexpressionstatement.vala', - 'src/ccode/valaccodefile.vala', - 'src/ccode/valaccodeforstatement.vala', - 'src/ccode/valaccodefragment.vala', - 'src/ccode/valaccodefunction.vala', - 'src/ccode/valaccodefunctioncall.vala', - 'src/ccode/valaccodefunctiondeclarator.vala', - 'src/ccode/valaccodeggnucsection.vala', - 'src/ccode/valaccodegotostatement.vala', - 'src/ccode/valaccodeidentifier.vala', - 'src/ccode/valaccodeifsection.vala', - 'src/ccode/valaccodeifstatement.vala', - 'src/ccode/valaccodeincludedirective.vala', - 'src/ccode/valaccodeinitializerlist.vala', - 'src/ccode/valaccodeinvalidexpression.vala', - 'src/ccode/valaccodelabel.vala', - 'src/ccode/valaccodelinedirective.vala', - 'src/ccode/valaccodemacroreplacement.vala', - 'src/ccode/valaccodememberaccess.vala', - 'src/ccode/valaccodemodifiers.vala', - 'src/ccode/valaccodenewline.vala', - 'src/ccode/valaccodenode.vala', - 'src/ccode/valaccodeoncesection.vala', - 'src/ccode/valaccodeparameter.vala', - 'src/ccode/valaccodeparenthesizedexpression.vala', - 'src/ccode/valaccodereturnstatement.vala', - 'src/ccode/valaccodestatement.vala', - 'src/ccode/valaccodestruct.vala', - 'src/ccode/valaccodeswitchstatement.vala', - 'src/ccode/valaccodetypedefinition.vala', - 'src/ccode/valaccodeunaryexpression.vala', - 'src/ccode/valaccodevariabledeclarator.vala', - 'src/ccode/valaccodewhilestatement.vala', - 'src/ccode/valaccodewriter.vala', 'src/Project/GtkValaSettings.vala', 'src/Project/Project.vala', 'src/Project/Gtk.vala', @@ -193,6 +105,7 @@ roobuilder_src = files([ 'src/Palete/RooDatabase.vala', 'src/Palete/LanguageClient.vala', 'src/Palete/LanguageClientVala.vala', + 'src/Palete/LanguageClientJavascript.vala', 'src/Lsp.vala', 'src/Palete/LanguageClientDummy.vala', 'src/Palete/ValaCompileRequest.vala', diff --git a/src/Application.vala b/src/Application.vala index bf402782a..9eb45bd67 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -182,7 +182,7 @@ this.testBjs(cur_project); this.languageServer(cur_project); this.compileBjs(cur_project); - this.compileVala(); + //this.compileVala(); } @@ -250,6 +250,7 @@ }); } + } void listProjects() @@ -544,7 +545,7 @@ GLib.Process.exit(Posix.EXIT_SUCCESS); } - + /* void compileVala() { if (BuilderApplication.opt_compile_target == null) { @@ -555,6 +556,7 @@ GLib.Process.exit(Posix.EXIT_SUCCESS); } + */ void pullResources() { if (!opt_pull_resources) { diff --git a/src/Builder4/DialogFiles.bjs b/src/Builder4/DialogFiles.bjs index c7412a0fd..bc2d2975e 100644 --- a/src/Builder4/DialogFiles.bjs +++ b/src/Builder4/DialogFiles.bjs @@ -1,4 +1,4 @@ -{ +g{ "build_module" : "builder", "gen_extended" : false, "items" : [ @@ -1186,7 +1186,6 @@ " // cl list...", " ", " _this.is_loading = true;", - " ", " Project.Project.loadAll();", " _this.project_list.el.set_model(new Gtk.SingleSelection(null));", " Project.Project.loadIntoStore(this.projectmodel.el);", diff --git a/src/Builder4/DialogFiles.vala b/src/Builder4/DialogFiles.vala index 34294b267..5035a6bc7 100644 --- a/src/Builder4/DialogFiles.vala +++ b/src/Builder4/DialogFiles.vala @@ -179,7 +179,7 @@ public class DialogFiles : Object // cl list... _this.is_loading = true; - + Project.Project.loadAll(); _this.project_list.el.set_model(new Gtk.SingleSelection(null)); Project.Project.loadIntoStore(this.projectmodel.el); diff --git a/src/Builder4/MainWindow.bjs b/src/Builder4/MainWindow.bjs index 705b18bf6..53ac0f249 100644 --- a/src/Builder4/MainWindow.bjs +++ b/src/Builder4/MainWindow.bjs @@ -667,17 +667,25 @@ "\t\t\tthis.last_request.killChildren(this.last_request.terminal_pid);", "\t\t}", "\t}", + "\tvar pr = _this.windowstate.project as Project.Gtk;", + "\tif (pr == null) {", + "\t\treturn;", + "\t}", + "\t", "\t", "\tthis.last_request= new Palete.ValaCompileRequest(", - "\t\tPalete.ValaCompileRequestType.RUN,", - "\t\t_this.windowstate.file,", - "\t\tnull,", - "\t\tnull,", - "\t\t\"\"", + "\t\tpr,", + "\t\tpr.firstBuildModuleWith(_this.windowstate.file)", "\t);", - "\tthis.last_request.run();", - "\t ", - "\t_this.windowstate.compile_results.el.set_parent(this.el);", + "\tthis.last_request.onOutput.connect( ( str) => {", + "\t\t_this.windowstate.compile_results.addLine(str);", + "\t});", + "\tthis.last_request.run.begin( ( a, r) => {", + "\t\tthis.last_request.run.end(r);", + "\t});", + "\t if (_this.windowstate.compile_results.el.parent == null) {", + "\t\t_this.windowstate.compile_results.el.set_parent(this.el);", + "\t}", "\t_this.windowstate.compile_results.show(this.el,true);", "\t ", "}" diff --git a/src/Builder4/MainWindow.vala b/src/Builder4/MainWindow.vala index 71de0b269..665be5f83 100644 --- a/src/Builder4/MainWindow.vala +++ b/src/Builder4/MainWindow.vala @@ -1471,17 +1471,25 @@ public class Xcls_MainWindow : Object this.last_request.killChildren(this.last_request.terminal_pid); } } + var pr = _this.windowstate.project as Project.Gtk; + if (pr == null) { + return; + } + this.last_request= new Palete.ValaCompileRequest( - Palete.ValaCompileRequestType.RUN, - _this.windowstate.file, - null, - null, - "" + pr, + pr.firstBuildModuleWith(_this.windowstate.file) ); - this.last_request.run(); - - _this.windowstate.compile_results.el.set_parent(this.el); + this.last_request.onOutput.connect( ( str) => { + _this.windowstate.compile_results.addLine(str); + }); + this.last_request.run.begin( ( a, r) => { + this.last_request.run.end(r); + }); + if (_this.windowstate.compile_results.el.parent == null) { + _this.windowstate.compile_results.el.set_parent(this.el); + } _this.windowstate.compile_results.show(this.el,true); }); diff --git a/src/Builder4/ValaCompileResults.bjs b/src/Builder4/ValaCompileResults.bjs index 4f8e5e481..d09cd7853 100644 --- a/src/Builder4/ValaCompileResults.bjs +++ b/src/Builder4/ValaCompileResults.bjs @@ -73,6 +73,22 @@ } ], "xtype" : "Popover", + "| void addLine" : [ + "(string str) {", + "\t ", + "\t", + "\t", + "\tvar buf = (GtkSource.Buffer)this.sourceview.el.get_buffer();", + "\tGtk.TextIter iter;", + "\tbuf.get_end_iter (out iter);", + "\tbuf.insert(ref iter, str, str.length);", + "\t/// scroll..", + "\tbuf.get_end_iter (out iter);", + "\tthis.sourceview.el.scroll_to_iter(iter, 0.0f, true, 0.0f, 1.0f);", + " ", + "}", + "" + ], "| void show" : [ "( Gtk.Widget onbtn, bool reset) {", "\tvar win = this.window.el;", @@ -106,26 +122,6 @@ " ", "}", "" - ], - "| void xaddLine" : [ - "(string str) {", - "\t/*", - "\tif (this.window.windowstate.project.path != BuilderApplication.valasource.file.project.path) {", - "\t\t// not our project.", - "\t\treturn;", - "\t}", - "\t", - "\t", - "\tvar buf = (GtkSource.Buffer)this.sourceview.el.get_buffer();", - "\tGtk.TextIter iter;", - "\tbuf.get_end_iter (out iter);", - "\tbuf.insert(ref iter, str, str.length);", - "\t/// scroll..", - "\tbuf.get_end_iter (out iter);", - "\tthis.sourceview.el.scroll_to_iter(iter, 0.0f, true, 0.0f, 1.0f);", - " */", - "}", - "" ] } ], diff --git a/src/Builder4/ValaCompileResults.vala b/src/Builder4/ValaCompileResults.vala index 2510146af..bf3f4ecf9 100644 --- a/src/Builder4/ValaCompileResults.vala +++ b/src/Builder4/ValaCompileResults.vala @@ -1,201 +1,197 @@ - static Xcls_ValaCompileResults _ValaCompileResults; - - public class Xcls_ValaCompileResults : Object - { - public Gtk.Popover el; - private Xcls_ValaCompileResults _this; - - public static Xcls_ValaCompileResults singleton() - { - if (_ValaCompileResults == null) { - _ValaCompileResults= new Xcls_ValaCompileResults(); - } - return _ValaCompileResults; - } - public Xcls_compile_view compile_view; - public Xcls_sourceview sourceview; - - // my vars (def) - public bool modal; - public Xcls_MainWindow window; - public bool active; - - // ctor - public Xcls_ValaCompileResults() - { - _this = this; - this.el = new Gtk.Popover(); - - // my vars (dec) - this.modal = true; - this.active = true; - - // set gobject values - this.el.width_request = 600; - this.el.height_request = 400; - this.el.position = Gtk.PositionType.TOP; - new Xcls_compile_view( _this ); - this.el.set_child ( _this.compile_view.el ); - } - - // user defined functions - public void xaddLine (string str) { - /* - if (this.window.windowstate.project.path != BuilderApplication.valasource.file.project.path) { - // not our project. - return; - } - - - var buf = (GtkSource.Buffer)this.sourceview.el.get_buffer(); - Gtk.TextIter iter; - buf.get_end_iter (out iter); - buf.insert(ref iter, str, str.length); - /// scroll.. - buf.get_end_iter (out iter); - this.sourceview.el.scroll_to_iter(iter, 0.0f, true, 0.0f, 1.0f); - */ - } - public void show ( Gtk.Widget onbtn, bool reset) { - var win = this.window.el; - var w = win.get_width(); - var h = win.get_height(); - - // left tree = 250, editor area = 500? - - var new_w = int.min(750, w-100); - if (new_w > (w-100)) { - new_w = w-100; - } - this.el.set_size_request( int.max(100, new_w), int.max(100, h-120)); - if (this.el.parent == null) { - this.el.set_parent(win); - } - // Gtk.Allocation rect; - //onbtn.get_allocation(out rect); - //this.el.set_pointing_to(rect); - - this.el.popup(); - // not sure why.. - - if (reset) { - var buf = (GtkSource.Buffer)this.sourceview.el.get_buffer(); - buf.set_text("",0); - } - - - - - } - public class Xcls_compile_view : Object - { - public Gtk.Box el; - private Xcls_ValaCompileResults _this; - - - // my vars (def) - - // ctor - public Xcls_compile_view(Xcls_ValaCompileResults _owner ) - { - _this = _owner; - _this.compile_view = this; - this.el = new Gtk.Box( Gtk.Orientation.VERTICAL, 0 ); - - // my vars (dec) - - // set gobject values - this.el.homogeneous = false; - this.el.hexpand = true; - this.el.vexpand = true; - var child_1 = new Xcls_ScrolledWindow3( _this ); - child_1.ref(); - this.el.append( child_1.el ); - } - - // user defined functions - } - public class Xcls_ScrolledWindow3 : Object - { - public Gtk.ScrolledWindow el; - private Xcls_ValaCompileResults _this; - - - // my vars (def) - - // ctor - public Xcls_ScrolledWindow3(Xcls_ValaCompileResults _owner ) - { - _this = _owner; - this.el = new Gtk.ScrolledWindow(); - - // my vars (dec) - - // set gobject values - this.el.hexpand = true; - this.el.vexpand = true; - new Xcls_sourceview( _this ); - this.el.child = _this.sourceview.el; - - // init method - - { - this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC); - - - } - } - - // user defined functions - } - public class Xcls_sourceview : Object - { - public GtkSource.View el; - private Xcls_ValaCompileResults _this; - - - // my vars (def) - public Gtk.CssProvider css; - - // ctor - public Xcls_sourceview(Xcls_ValaCompileResults _owner ) - { - _this = _owner; - _this.sourceview = this; - this.el = new GtkSource.View(); - - // my vars (dec) - - // set gobject values - this.el.name = "compile-results-view"; - this.el.editable = false; - this.el.show_line_numbers = false; - this.el.hexpand = true; - this.el.vexpand = true; - - // init method - - { - - this.css = new Gtk.CssProvider(); - - this.css.load_from_string( - "#compile-results-view { font: 10px monospace ;}" - ); - - Gtk.StyleContext.add_provider_for_display( - this.el.get_display(), - this.css, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); - - - } - } - - // user defined functions - } - - - - } +static Xcls_ValaCompileResults _ValaCompileResults; + +public class Xcls_ValaCompileResults : Object +{ + public Gtk.Popover el; + private Xcls_ValaCompileResults _this; + + public static Xcls_ValaCompileResults singleton() + { + if (_ValaCompileResults == null) { + _ValaCompileResults= new Xcls_ValaCompileResults(); + } + return _ValaCompileResults; + } + public Xcls_compile_view compile_view; + public Xcls_sourceview sourceview; + + // my vars (def) + public bool modal; + public Xcls_MainWindow window; + public bool active; + + // ctor + public Xcls_ValaCompileResults() + { + _this = this; + this.el = new Gtk.Popover(); + + // my vars (dec) + this.modal = true; + this.active = true; + + // set gobject values + this.el.width_request = 600; + this.el.height_request = 400; + this.el.position = Gtk.PositionType.TOP; + new Xcls_compile_view( _this ); + this.el.set_child ( _this.compile_view.el ); + } + + // user defined functions + public void show ( Gtk.Widget onbtn, bool reset) { + var win = this.window.el; + var w = win.get_width(); + var h = win.get_height(); + + // left tree = 250, editor area = 500? + + var new_w = int.min(750, w-100); + if (new_w > (w-100)) { + new_w = w-100; + } + this.el.set_size_request( int.max(100, new_w), int.max(100, h-120)); + if (this.el.parent == null) { + this.el.set_parent(win); + } + // Gtk.Allocation rect; + //onbtn.get_allocation(out rect); + //this.el.set_pointing_to(rect); + + this.el.popup(); + // not sure why.. + + if (reset) { + var buf = (GtkSource.Buffer)this.sourceview.el.get_buffer(); + buf.set_text("",0); + } + + + + + } + public void addLine (string str) { + + + + var buf = (GtkSource.Buffer)this.sourceview.el.get_buffer(); + Gtk.TextIter iter; + buf.get_end_iter (out iter); + buf.insert(ref iter, str, str.length); + /// scroll.. + buf.get_end_iter (out iter); + this.sourceview.el.scroll_to_iter(iter, 0.0f, true, 0.0f, 1.0f); + + } + public class Xcls_compile_view : Object + { + public Gtk.Box el; + private Xcls_ValaCompileResults _this; + + + // my vars (def) + + // ctor + public Xcls_compile_view(Xcls_ValaCompileResults _owner ) + { + _this = _owner; + _this.compile_view = this; + this.el = new Gtk.Box( Gtk.Orientation.VERTICAL, 0 ); + + // my vars (dec) + + // set gobject values + this.el.homogeneous = false; + this.el.hexpand = true; + this.el.vexpand = true; + var child_1 = new Xcls_ScrolledWindow3( _this ); + child_1.ref(); + this.el.append( child_1.el ); + } + + // user defined functions + } + public class Xcls_ScrolledWindow3 : Object + { + public Gtk.ScrolledWindow el; + private Xcls_ValaCompileResults _this; + + + // my vars (def) + + // ctor + public Xcls_ScrolledWindow3(Xcls_ValaCompileResults _owner ) + { + _this = _owner; + this.el = new Gtk.ScrolledWindow(); + + // my vars (dec) + + // set gobject values + this.el.hexpand = true; + this.el.vexpand = true; + new Xcls_sourceview( _this ); + this.el.child = _this.sourceview.el; + + // init method + + { + this.el.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC); + + + } + } + + // user defined functions + } + public class Xcls_sourceview : Object + { + public GtkSource.View el; + private Xcls_ValaCompileResults _this; + + + // my vars (def) + public Gtk.CssProvider css; + + // ctor + public Xcls_sourceview(Xcls_ValaCompileResults _owner ) + { + _this = _owner; + _this.sourceview = this; + this.el = new GtkSource.View(); + + // my vars (dec) + + // set gobject values + this.el.name = "compile-results-view"; + this.el.editable = false; + this.el.show_line_numbers = false; + this.el.hexpand = true; + this.el.vexpand = true; + + // init method + + { + + this.css = new Gtk.CssProvider(); + + this.css.load_from_string( + "#compile-results-view { font: 10px monospace ;}" + ); + + Gtk.StyleContext.add_provider_for_display( + this.el.get_display(), + this.css, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION + ); + + + } + } + + // user defined functions + } + + + +} diff --git a/src/Builder4/ValaProjectSettingsPopover.bjs b/src/Builder4/ValaProjectSettingsPopover.bjs index d6e46327f..7eb681597 100644 --- a/src/Builder4/ValaProjectSettingsPopover.bjs +++ b/src/Builder4/ValaProjectSettingsPopover.bjs @@ -450,7 +450,7 @@ " expand.set_hide_expander( jr.childfiles.n_items < 1);", " \texpand.set_list_row(lr);", " ", - " expand.set_hide_expander( jr.xtype != \"Dir\" );", + " \texpand.set_hide_expander( jr.xtype != \"Dir\" );", " \t expand.set_list_row(lr);", " ", " \t// bind image...", @@ -510,16 +510,16 @@ "\t//GLib.debug(\"change %s to %s\", lbl.label, np.name);", "", "\t//btn.active = jr.compile_group_selected;", - "\t ", - " \tjr.bind_property(\"compile_group_selected\",", - " btn, \"active\",", - " GLib.BindingFlags.BIDIRECTIONAL); ", + "\tbtn.active = _this.selected_target.has_file(jr);", + "\t", + " \t//jr.bind_property(\"compile_group_selected\",", + " // btn, \"active\",", + " // GLib.BindingFlags.BIDIRECTIONAL); ", " \t// bind image...", " \t", "}" ], "setup" : [ - "", "(listitem) => {", "", "\tvar btn = new Gtk.CheckButton();", @@ -909,6 +909,7 @@ "\t\treturn true;", "\t}", "\treturn false;", + "\t", "}", "" ], @@ -916,7 +917,6 @@ "() => {", "\t if (!this.done) {", " _this.el.show();", - " ", " }", "}" ] diff --git a/src/Builder4/ValaProjectSettingsPopover.vala b/src/Builder4/ValaProjectSettingsPopover.vala index a3b6dadad..c5d8d74bc 100644 --- a/src/Builder4/ValaProjectSettingsPopover.vala +++ b/src/Builder4/ValaProjectSettingsPopover.vala @@ -72,11 +72,11 @@ public class ValaProjectSettingsPopover : Object return true; } return false; + }); this.el.hide.connect( () => { if (!this.done) { _this.el.show(); - } }); } @@ -1248,7 +1248,7 @@ public class ValaProjectSettingsPopover : Object expand.set_hide_expander( jr.childfiles.n_items < 1); expand.set_list_row(lr); - expand.set_hide_expander( jr.xtype != "Dir" ); + expand.set_hide_expander( jr.xtype != "Dir" ); expand.set_list_row(lr); // bind image... @@ -1333,10 +1333,11 @@ public class ValaProjectSettingsPopover : Object //GLib.debug("change %s to %s", lbl.label, np.name); //btn.active = jr.compile_group_selected; - - jr.bind_property("compile_group_selected", - btn, "active", - GLib.BindingFlags.BIDIRECTIONAL); + btn.active = _this.selected_target.has_file(jr); + + //jr.bind_property("compile_group_selected", + // btn, "active", + // GLib.BindingFlags.BIDIRECTIONAL); // bind image... }); diff --git a/src/JsRender/Gtk.vala b/src/JsRender/Gtk.vala index 3ae204c0b..57ce6446d 100644 --- a/src/JsRender/Gtk.vala +++ b/src/JsRender/Gtk.vala @@ -148,16 +148,24 @@ namespace JsRender { } public override void setSource(string str) {} + int last_source_version = -2; + string last_source; public override string toSourceCode() // no seed support currently. { - return NodeToVala.mungeFile(this); + if (this.version == this.last_source_version) { + return this.last_source; + } + this.last_source = NodeToVala.mungeFile(this); + this.last_source_version = this.version; + return this.last_source; + } // this is only used by dumping code... public override string toSource() // no seed support currently. { - return NodeToVala.mungeFile(this); + return this.toSourceCode(); } diff --git a/src/JsRender/JsRender.vala b/src/JsRender/JsRender.vala index 3e9818587..29d8df1f5 100644 --- a/src/JsRender/JsRender.vala +++ b/src/JsRender/JsRender.vala @@ -79,6 +79,9 @@ namespace JsRender { private int _version = 1; // should we increment this based on the node..? public int version { get { + if (this.tree != null) { + return this.tree.updated_count; + } return ++this._version; // increased on every call? - bit of a kludge until we do real versioning } private set { diff --git a/src/JsRender/Node.vala b/src/JsRender/Node.vala index 0f91ab8c8..de6cba3af 100644 --- a/src/JsRender/Node.vala +++ b/src/JsRender/Node.vala @@ -119,7 +119,10 @@ public class JsRender.Node : GLib.Object { set { this.nodeTitleProp = ""; // ?? should trigger set? this.iconFilename = ""; - this. _updated_count = value; + this._updated_count = value; + if (this.parent != null) { + this.parent.updated_count++; + } } } // changes to this trigger updates on the tree.. diff --git a/src/Palete/CompletionProvider.vala b/src/Palete/CompletionProvider.vala index 35a0f61be..9c365af04 100644 --- a/src/Palete/CompletionProvider.vala +++ b/src/Palete/CompletionProvider.vala @@ -205,7 +205,7 @@ namespace Palete { this.file.getLanguageServer().document_change_real(this.file, this.editor.tempFileContents()); try { - yield this.file.getLanguageServer().completion(this.file, line, offset, 1, out res); + res = yield this.file.getLanguageServer().completion(this.file, line, offset, 1); } catch (GLib.Error e) { GLib.debug("got error %s", e.message); res = null; diff --git a/src/Palete/LanguageClient.vala b/src/Palete/LanguageClient.vala index 5f06a22e1..245e3217c 100644 --- a/src/Palete/LanguageClient.vala +++ b/src/Palete/LanguageClient.vala @@ -138,7 +138,7 @@ namespace Palete { return true; } bool in_close = false; - public void onClose() + protected void onClose() { if (this.in_close) { return; @@ -439,6 +439,7 @@ namespace Palete { } + // called by close window (on last window)... public void exit () throws GLib.Error { if (!this.isReady()) { @@ -455,6 +456,7 @@ namespace Palete { this.onClose(); } + // not used currently.. public async void shutdown () throws GLib.Error { if (!this.isReady()) { @@ -479,16 +481,16 @@ namespace Palete { @triggerType 1 = typing or ctl-spac, 2 = tiggercharactres? 3= inside completion? */ - public async void completion (JsRender.JsRender file, int line, int offset , int triggerType = 1, out Lsp.CompletionList? ret) throws GLib.Error + public async Lsp.CompletionList? completion(JsRender.JsRender file, int line, int offset , int triggerType = 1) throws GLib.Error { /* partial_result_token , work_done_token context = null) */ GLib.debug("get completion %s @ %d:%d", file.relpath, line, offset); - ret = new Lsp.CompletionList(); + var ret = new Lsp.CompletionList(); if (!this.isReady()) { GLib.debug("completion - language server not ready"); - return; + return ret; } // make sure completion has the latest info.. //if (this.change_queue_file != null && this.change_queue_file.path != file.path) { @@ -532,13 +534,13 @@ namespace Palete { ret = Json.gobject_deserialize (typeof (Lsp.CompletionList), json) as Lsp.CompletionList; this.log(LanguageClientAction.COMPLETE_REPLY, "GOT complete %d items".printf(ret.items.size) ); GLib.debug ("LS replied with Object"); - return; + return ret; } if (json.get_node_type() != Json.NodeType.ARRAY) { GLib.debug ("LS replied with %s", Json.to_string (Json.gvariant_serialize (return_value), true)); this.log(LanguageClientAction.ERROR_REPLY, "GOT something else??"); - return; + return ret; } var ar = json.get_array(); @@ -550,7 +552,7 @@ namespace Palete { } this.log(LanguageClientAction.COMPLETE_REPLY, "GOT array %d items".printf(ret.items.size) ); GLib.debug ("LS replied with Array"); - + return ret; } diff --git a/src/Palete/LanguageClientDummy.vala b/src/Palete/LanguageClientDummy.vala index b829fc2bb..d83ac1c9c 100644 --- a/src/Palete/LanguageClientDummy.vala +++ b/src/Palete/LanguageClientDummy.vala @@ -16,7 +16,10 @@ namespace Palete { public override void startServer() { } - + public new bool isReady() + { + return false; + } } } \ No newline at end of file diff --git a/src/Palete/ValaCompileRequest.vala b/src/Palete/ValaCompileRequest.vala index 798bf04c0..90035262e 100644 --- a/src/Palete/ValaCompileRequest.vala +++ b/src/Palete/ValaCompileRequest.vala @@ -2,244 +2,105 @@ namespace Palete { - public enum ValaCompileRequestType { - PROP_CHANGE, - FILE_CHANGE, - PROJECT, - RUN - } + public class ValaCompileRequest : Object { - ValaCompileRequestType requestType; - - public JsRender.JsRender? file = null; - JsRender.Node? node = null; - JsRender.NodeProp? prop = null; - string alt_code = ""; - string tmpfile = ""; - Spawn? compiler = null; - /// ValaCompileQueue? queue = null; - + Project.Gtk project; + string target; + Spawn? spawn = null; + public signal void onOutput(string str); public Gee.HashMap? errorByType = null; public Gee.HashMap? errorByFile = null; public ValaCompileRequest ( - ValaCompileRequestType requestType, - JsRender.JsRender file , - JsRender.Node? node, - JsRender.NodeProp? prop, - string alt_code = "" + Project.Gtk project, + string target ) { - this.requestType = requestType; - this.file = file; - this.node = node; - this.prop = prop; - this.alt_code = alt_code; - } - public bool eq(ValaCompileRequest c) { - var neq = false; - if (this.node == null && c.node == null) { - neq = true; - } else if (this.node == null || c.node == null) { - neq = false; - } else { - neq = this.node.oid == c.node.oid ; - } - - var peq = false; - if (this.prop == null && c.prop == null) { - peq = true; - } else if (this.prop == null || c.prop == null) { - peq = false; - } else { - peq = this.prop.name == c.prop.name ; - } - - - return - this.requestType == c.requestType && - this.file.path == c.file.path && - neq && peq && - this.alt_code == c.alt_code; - - - - } - public string target() - { - var pr = (Project.Gtk) this.file.project; - return pr.firstBuildModuleWith(this.file); - - } - - string generateTempContents() { - - var oldcode = ""; - var contents = this.alt_code; - if (this.requestType == ValaCompileRequestType.PROP_CHANGE) { - oldcode = this.prop.val; - this.prop.val = this.alt_code; - contents = this.file.toSourceCode(); - this.prop.val = oldcode; - } - return contents; + this.project = project; + this.target = target; } - - - bool generateTempFile() { - var contents = this.generateTempContents(); - - var pr = this.file.project; - - this.tmpfile = pr.path + "/build/tmp-%u.vala".printf( (uint) GLib.get_real_time()) ; - try { - GLib.FileUtils.set_contents(this.tmpfile,contents); - } catch (GLib.FileError e) { - GLib.debug("Error creating temp build file %s : %s", tmpfile, e.message); - return false; - } - return true; - } + - public bool run() + + + public async bool run() { //this.queue = queue; - if ( this.target() == "") { + + if ( this.target == "") { GLib.debug("missing target"); - this.onCompileFail(); + return false; } - string[] args = {}; - args += BuilderApplication._self; - if (this.requestType != ValaCompileRequestType.RUN) { - args += "--skip-linking"; - } - args += "--project"; - args += this.file.project.path; - args += "--target"; - args += this.target(); - if (this.requestType == ValaCompileRequestType.PROP_CHANGE || this.requestType == ValaCompileRequestType.FILE_CHANGE) { - - if (!this.generateTempFile()) { - GLib.debug("failed to make temp file"); - this.onCompileFail(); - return false; - } - args += "--add-file"; - args += this.tmpfile; - args += "--skip-file"; - args += this.file.targetName(); // ?? bjs??? - } - var pr = (Project.Gtk)(file.project); - try { - pr.makeProjectSubdir("build"); - this.compiler = new Spawn(pr.path + "/build", args); - } catch (GLib.Error e) { - GLib.debug("Spawn failed: %s", e.message); + BuilderApplication.showSpinner("spinner", "running meson"); - this.onCompileFail(); + var res = yield this.runMeson(); + + if (0 != res) { + GLib.debug("Failed to run Meson"); + BuilderApplication.showSpinner(""); return false; } - this.compiler.output_line.connect(this.onOutput); - this.compiler.complete.connect(this.onCompileComplete); - try { - this.compiler.run(); - } catch (GLib.Error e) { - GLib.debug("Spawn error %s", e.message); - this.onCompileFail(); + BuilderApplication.showSpinner("spinner", "running ninja"); + res = yield this.runNinja(); + if (0 != res) { + GLib.debug("Failed to run ninja"); return false; } - return true; // it's running.. - } - void onCompileFail() // only called before we start (assumes spinner has nto started etc.. - { - this.compiler = null; - this.deleteTemp(); - } - - public void cancel() { - if (this.compiler != null && this.compiler.pid > 0) { - Posix.kill(this.compiler.pid, 9); - } - this.compiler = null; - this.deleteTemp(); + + BuilderApplication.showSpinner(""); + return this.execResult(); + } - public void deleteTemp() - { - if (this.tmpfile == "") { - return; - } - if (GLib.FileUtils.test(this.tmpfile, GLib.FileTest.EXISTS)) { - GLib.FileUtils.unlink(this.tmpfile); + async int runMeson() { + if (GLib.FileUtils.test(this.project.path + "/build", GLib.FileTest.EXISTS)) { + return 0; //assume it's been set up. } - var cf = this.tmpfile.substring(0, this.tmpfile.length-4) + "c"; - GLib.debug("try remove %s",cf); - if (GLib.FileUtils.test(cf, GLib.FileTest.EXISTS)) { - GLib.FileUtils.unlink(cf); - } - var ccf = GLib.Path.get_dirname(cf) + "/build/" + GLib.Path.get_basename(cf); - GLib.debug("try remove %s",ccf); - if (GLib.FileUtils.test(ccf, GLib.FileTest.EXISTS)) { - GLib.FileUtils.unlink(ccf); - } - this.tmpfile = ""; + string[] args = { "/usr/bin/meson" ,"setup","build", "--prefix=/" }; + + this.spawn = new Spawn(this.project.path , args); + this.spawn.output_line.connect(( str) => { + this.onOutput(str); + }); + var res = yield this.spawn.run_async(); + return res; } - public void onCompileComplete(int res, string output, string stderr) - { - this.deleteTemp(); - this.compiler.isZombie(); - GLib.debug("compile got %s", output); - if (output == "") { - BuilderApplication.showSpinner("face-sad", "compile failed - no error message?"); - return; - } - if (this.requestType == ValaCompileRequestType.RUN) { - BuilderApplication.showSpinner(""); - this.execResult(); - return; - } - // below is not used anymore - as we dont use this - try { - //GLib.debug("GOT output %s", output); - - var pa = new Json.Parser(); - pa.load_from_data(output); - var node = pa.get_root(); + async int runNinja() + { + if (!GLib.FileUtils.test(this.project.path + "/build", GLib.FileTest.EXISTS)) { + GLib.debug("build is missing"); + return -1; //assume it's been set up. + } + string[] args = { "/usr/bin/ninja"}; - if (node.get_node_type () != Json.NodeType.OBJECT) { - BuilderApplication.showSpinner(""); - return; - } - var ret = node.get_object (); - //CompileError.parseCompileResults(this,ret); - BuilderApplication.showSpinner(""); - - - - - - } catch (GLib.Error e) { - GLib.debug("parsing output got error %s", e.message); - BuilderApplication.showSpinner(""); - return; - + this.spawn = new Spawn(this.project.path + "/build" , args); + this.spawn.output_line.connect(( str) => { + this.onOutput(str); + }); + var res = yield this.spawn.run_async(); + return res; + + } + public void cancel() { + if (this.spawn != null && this.spawn.pid > 0) { + Posix.kill(this.spawn.pid, 9); } - } + this.spawn = null; + + } + - public void onOutput(string line) - { - // pass it to UI? - - } + /* + public int totalErrors(string type, JsRender.JsRender? file=null) { var ar = this.errorByType.get(type); @@ -266,25 +127,10 @@ namespace Palete { } return ret; } + */ + - public void runJavascript( ) - { - //this.queue = queue; - - var contents = this.alt_code == "" ? this.file.toSourceCode() : this.generateTempContents(); - - Javascript.singleton().validate(contents, this.file ); - - - BuilderApplication.showSpinner(""); - BuilderApplication.updateCompileResults(); - - //this.queue.onCompileComplete(this); - - - // see pack file (from palete/palete..palete_palete_javascriptHasCompressionErrors.) - } public void killChildren(int pid) { if (pid < 1) { @@ -313,20 +159,20 @@ namespace Palete { } public int terminal_pid = 0; - public void execResult() + public bool execResult() { this.killChildren(this.terminal_pid); this.terminal_pid = 0; - var exe = this.target(); - var pr = (Project.Gtk) this.file.project; + var exe = this.target; + var pr = (Project.Gtk) this.project; var cg = pr.compilegroups.get(exe); var exbin = pr.path + "/build/" + exe; if (!GLib.FileUtils.test(exbin, GLib.FileTest.EXISTS)) { GLib.debug("Missing output file: %s\n",exbin); - return; + return false; } var gdb_cfg = pr.path + "/build/.gdb-script"; if (!GLib.FileUtils.test(gdb_cfg, GLib.FileTest.EXISTS)) { @@ -365,8 +211,9 @@ namespace Palete { } catch(GLib.Error e) { GLib.debug("Failed to spawn: %s", e.message); - return; + return false; } + return true; } diff --git a/src/Project/GtkValaSettings.vala b/src/Project/GtkValaSettings.vala index 0b92cce8f..ed51c6830 100644 --- a/src/Project/GtkValaSettings.vala +++ b/src/Project/GtkValaSettings.vala @@ -66,18 +66,18 @@ namespace Project public bool has_file(JsRender.JsRender file) { - GLib.debug("Checking %s has file %s", this.name, file.path); + //GLib.debug("Checking %s has file %s", this.name, file.path); var pr = (Gtk) file.project; for(var i = 0; i < this.sources.size;i++) { var path = pr.path + "/" + this.sources.get(i); - GLib.debug("check %s", path); + //GLib.debug("check %s =%s or %s", path , file.path, file.targetName()); - if (path == file.path) { - GLib.debug("GOT IT"); + if (path == file.path || path == file.targetName()) { + //GLib.debug("GOT IT"); return true; } } - GLib.debug("CANT FIND IT"); + //GLib.debug("CANT FIND IT"); return false; } diff --git a/src/Project/Project.vala b/src/Project/Project.vala index 5741178df..c15db61f6 100644 --- a/src/Project/Project.vala +++ b/src/Project/Project.vala @@ -492,6 +492,14 @@ namespace Project { } GLib.debug("load is_scanned = false"); + + // used to load paths.. + this.sub_paths = new Gee.ArrayList(); + this.files = new Gee.HashMap(); + this.loadSubDirectories("", 0); // must happend before loadJson! (as compile groups checks if file exists. + + + if (FileUtils.test(this.path + "/.roobuilder.jcfg", FileTest.EXISTS)) { var pa = new Json.Parser(); @@ -512,12 +520,7 @@ namespace Project { this.loadJson(obj); } - // used to load paths.. - this.sub_paths = new Gee.ArrayList(); - this.files = new Gee.HashMap(); - this.loadSubDirectories("", 0); - - this.initDatabase(); + this.initDatabase(); this.is_scanned = true; // loaded.. dont need to do it again.. GLib.debug("load is_scanned = true"); diff --git a/src/Spawn.vala b/src/Spawn.vala index b4c4c2099..7b63163e1 100644 --- a/src/Spawn.vala +++ b/src/Spawn.vala @@ -323,6 +323,23 @@ public class Spawn : Object } + public async int run_async() + { + GLib.MainLoop loop = new GLib.MainLoop (); + this.complete.connect( (res, str, stderr) => { + loop.quit (); + }); + + this.run(); + + loop.run (); + return this.result; + + + + } + + public void tidyup() // or kill diff --git a/src/ccode/Makefile.am b/src/ccode/Makefile.am deleted file mode 100644 index c87c5dd1d..000000000 --- a/src/ccode/Makefile.am +++ /dev/null @@ -1,109 +0,0 @@ -include $(top_srcdir)/Makefile.common - -NULL = - -AM_CPPFLAGS = \ - -DG_LOG_DOMAIN=\"vala-ccode\" \ - $(COVERAGE_CFLAGS) \ - -I$(top_srcdir)/gee \ - -I$(top_srcdir)/vala \ - $(GLIB_CFLAGS) \ - $(NULL) - -BUILT_SOURCES = ccode.vala.stamp - -noinst_LTLIBRARIES = \ - libvalaccode.la \ - $(NULL) - -libvalaccode_la_VALASOURCES = \ - valaccode.vala \ - valaccodeassignment.vala \ - valaccodebinaryexpression.vala \ - valaccodeblock.vala \ - valaccodebreakstatement.vala \ - valaccodecasestatement.vala \ - valaccodecastexpression.vala \ - valaccodecommaexpression.vala \ - valaccodecomment.vala \ - valaccodeconditionalexpression.vala \ - valaccodeconstant.vala \ - valaccodeconstantidentifier.vala \ - valaccodecontinuestatement.vala \ - valaccodedeclaration.vala \ - valaccodedeclarator.vala \ - valaccodedefine.vala \ - valaccodedostatement.vala \ - valaccodeemptystatement.vala \ - valaccodeenum.vala \ - valaccodeenumvalue.vala \ - valaccodeexpression.vala \ - valaccodeexpressionstatement.vala \ - valaccodefile.vala \ - valaccodeforstatement.vala \ - valaccodefragment.vala \ - valaccodefunction.vala \ - valaccodefunctioncall.vala \ - valaccodefunctiondeclarator.vala \ - valaccodeggnucsection.vala \ - valaccodegotostatement.vala \ - valaccodeidentifier.vala \ - valaccodeifstatement.vala \ - valaccodeincludedirective.vala \ - valaccodeinitializerlist.vala \ - valaccodeinvalidexpression.vala \ - valaccodelabel.vala \ - valaccodelinedirective.vala \ - valaccodeifsection.vala \ - valaccodemacroreplacement.vala \ - valaccodememberaccess.vala \ - valaccodemodifiers.vala \ - valaccodenewline.vala \ - valaccodenode.vala \ - valaccodeoncesection.vala \ - valaccodeparameter.vala \ - valaccodeparenthesizedexpression.vala \ - valaccodereturnstatement.vala \ - valaccodestatement.vala \ - valaccodestruct.vala \ - valaccodeswitchstatement.vala \ - valaccodetypedefinition.vala \ - valaccodeunaryexpression.vala \ - valaccodevariabledeclarator.vala \ - valaccodewhilestatement.vala \ - valaccodewriter.vala \ - valaccodeelementaccess.vala \ - $(NULL) - -libvalaccode_la_SOURCES = \ - ccode.vala.stamp \ - $(libvalaccode_la_VALASOURCES:.vala=.c) \ - $(NULL) - -ccode.vapi ccode.vala.stamp: $(libvalaccode_la_VALASOURCES) - $(VALA_V)$(VALAC) \ - $(COVERAGE_VALAFLAGS) \ - $(VALAFLAGS) \ - -C \ - --vapidir $(top_srcdir)/vapi --pkg gobject-2.0 \ - --vapidir $(top_srcdir)/gee --pkg gee \ - --vapidir $(top_srcdir)/vala --pkg vala \ - --pkg config \ - -H valaccode.h \ - --library ccode \ - $^ - touch $@ - -libvalaccode_la_LIBADD = \ - $(COVERAGE_LIBS) \ - $(GLIB_LIBS) \ - $(top_builddir)/vala/libvala@PACKAGE_SUFFIX@.la \ - $(NULL) - -EXTRA_DIST = $(libvalaccode_la_VALASOURCES) ccode.vapi ccode.vala.stamp valaccode.h - -MAINTAINERCLEANFILES = \ - ccode.vapi \ - valaccode.h \ - $(libvalaccode_la_VALASOURCES:.vala=.c) \ - $(NULL) diff --git a/src/ccode/valaccode.vala b/src/ccode/valaccode.vala deleted file mode 100644 index 07f4bed2a..000000000 --- a/src/ccode/valaccode.vala +++ /dev/null @@ -1,59 +0,0 @@ -/* valaccode.vala - * - * Copyright (C) 2020 Rico Tzschichholz - * - * 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.1 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: - * Rico Tzschichholz - */ - -namespace Vala { - public unowned string GNUC_CONST; - public unowned string GNUC_DEPRECATED; - public unowned string GNUC_FORMAT; - public unowned string GNUC_INTERNAL; - public unowned string GNUC_NO_INLINE; - public unowned string GNUC_PRINTF; - public unowned string GNUC_SCANF; - public unowned string GNUC_UNUSED; - - public static void ccode_init (Vala.Profile profile) { - switch (profile) { - case Vala.Profile.GOBJECT: - GNUC_CONST = " G_GNUC_CONST "; - GNUC_DEPRECATED = " G_GNUC_DEPRECATED "; - GNUC_FORMAT = " G_GNUC_FORMAT(%d) "; - GNUC_INTERNAL = " G_GNUC_INTERNAL "; - GNUC_NO_INLINE = " G_GNUC_NO_INLINE "; - GNUC_PRINTF = " G_GNUC_PRINTF(%d,%d) "; - GNUC_SCANF = " G_GNUC_SCANF(%d,%d) "; - GNUC_UNUSED = " G_GNUC_UNUSED "; - break; - case Vala.Profile.POSIX: - GNUC_CONST = " __attribute__((__const__)) "; - GNUC_DEPRECATED = " __attribute__((__deprecated__)) "; - GNUC_FORMAT = " __attribute__((__format_arg__ (arg_idx))) "; - GNUC_INTERNAL = " __attribute__((visibility(\"hidden\"))) "; - GNUC_NO_INLINE = " __attribute__((noinline)) "; - GNUC_PRINTF = " __attribute__((__format__ (__printf__, %d, %d))) "; - GNUC_SCANF = " __attribute__((__format__ (__scanf__, %d, %d))) "; - GNUC_UNUSED = " __attribute__((__unused__)) "; - break; - default: - assert_not_reached (); - } - } -} diff --git a/src/ccode/valaccodeassignment.vala b/src/ccode/valaccodeassignment.vala deleted file mode 100644 index 247496df0..000000000 --- a/src/ccode/valaccodeassignment.vala +++ /dev/null @@ -1,90 +0,0 @@ -/* valaccodeassignment.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents an assignment expression in the C code. - */ -public class Vala.CCodeAssignment : CCodeExpression { - /** - * Left hand side of the assignment. - */ - public CCodeExpression left { get; set; } - - /** - * Assignment operator. - */ - public CCodeAssignmentOperator operator { get; set; } - - /** - * Right hand side of the assignment. - */ - public CCodeExpression right { get; set; } - - public CCodeAssignment (CCodeExpression l, CCodeExpression r, CCodeAssignmentOperator op = CCodeAssignmentOperator.SIMPLE) { - left = l; - operator = op; - right = r; - } - - public override void write (CCodeWriter writer) { - left.write (writer); - - switch (operator) { - case CCodeAssignmentOperator.SIMPLE: writer.write_string (" = "); break; - case CCodeAssignmentOperator.BITWISE_OR: writer.write_string (" |= "); break; - case CCodeAssignmentOperator.BITWISE_AND: writer.write_string (" &= "); break; - case CCodeAssignmentOperator.BITWISE_XOR: writer.write_string (" ^= "); break; - case CCodeAssignmentOperator.ADD: writer.write_string (" += "); break; - case CCodeAssignmentOperator.SUB: writer.write_string (" -= "); break; - case CCodeAssignmentOperator.MUL: writer.write_string (" *= "); break; - case CCodeAssignmentOperator.DIV: writer.write_string (" /= "); break; - case CCodeAssignmentOperator.PERCENT: writer.write_string (" %= "); break; - case CCodeAssignmentOperator.SHIFT_LEFT: writer.write_string (" <<= "); break; - case CCodeAssignmentOperator.SHIFT_RIGHT: writer.write_string (" >>= "); break; - default: assert_not_reached (); - } - - right.write (writer); - } - - public override void write_inner (CCodeWriter writer) { - writer.write_string ("("); - this.write (writer); - writer.write_string (")"); - } -} - -public enum Vala.CCodeAssignmentOperator { - SIMPLE, - BITWISE_OR, - BITWISE_AND, - BITWISE_XOR, - ADD, - SUB, - MUL, - DIV, - PERCENT, - SHIFT_LEFT, - SHIFT_RIGHT -} diff --git a/src/ccode/valaccodebinaryexpression.vala b/src/ccode/valaccodebinaryexpression.vala deleted file mode 100644 index f001c0825..000000000 --- a/src/ccode/valaccodebinaryexpression.vala +++ /dev/null @@ -1,104 +0,0 @@ -/* valaccodebinaryexpression.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents an expression with two operands in C code. - */ -public class Vala.CCodeBinaryExpression : CCodeExpression { - /** - * The binary operator. - */ - public CCodeBinaryOperator operator { get; set; } - - /** - * The left operand. - */ - public CCodeExpression left { get; set; } - - /** - * The right operand. - */ - public CCodeExpression right { get; set; } - - public CCodeBinaryExpression (CCodeBinaryOperator op, CCodeExpression l, CCodeExpression r) { - operator = op; - left = l; - right = r; - } - - public override void write (CCodeWriter writer) { - left.write_inner (writer); - - switch (operator) { - case CCodeBinaryOperator.PLUS: writer.write_string (" + "); break; - case CCodeBinaryOperator.MINUS: writer.write_string (" - "); break; - case CCodeBinaryOperator.MUL: writer.write_string (" * "); break; - case CCodeBinaryOperator.DIV: writer.write_string (" / "); break; - case CCodeBinaryOperator.MOD: writer.write_string (" % "); break; - case CCodeBinaryOperator.SHIFT_LEFT: writer.write_string (" << "); break; - case CCodeBinaryOperator.SHIFT_RIGHT: writer.write_string (" >> "); break; - case CCodeBinaryOperator.LESS_THAN: writer.write_string (" < "); break; - case CCodeBinaryOperator.GREATER_THAN: writer.write_string (" > "); break; - case CCodeBinaryOperator.LESS_THAN_OR_EQUAL: writer.write_string (" <= "); break; - case CCodeBinaryOperator.GREATER_THAN_OR_EQUAL: writer.write_string (" >= "); break; - case CCodeBinaryOperator.EQUALITY: writer.write_string (" == "); break; - case CCodeBinaryOperator.INEQUALITY: writer.write_string (" != "); break; - case CCodeBinaryOperator.BITWISE_AND: writer.write_string (" & "); break; - case CCodeBinaryOperator.BITWISE_OR: writer.write_string (" | "); break; - case CCodeBinaryOperator.BITWISE_XOR: writer.write_string (" ^ "); break; - case CCodeBinaryOperator.AND: writer.write_string (" && "); break; - case CCodeBinaryOperator.OR: writer.write_string (" || "); break; - default: assert_not_reached (); - } - - right.write_inner (writer); - } - - public override void write_inner (CCodeWriter writer) { - writer.write_string ("("); - this.write (writer); - writer.write_string (")"); - } -} - -public enum Vala.CCodeBinaryOperator { - PLUS, - MINUS, - MUL, - DIV, - MOD, - SHIFT_LEFT, - SHIFT_RIGHT, - LESS_THAN, - GREATER_THAN, - LESS_THAN_OR_EQUAL, - GREATER_THAN_OR_EQUAL, - EQUALITY, - INEQUALITY, - BITWISE_AND, - BITWISE_OR, - BITWISE_XOR, - AND, - OR -} diff --git a/src/ccode/valaccodeblock.vala b/src/ccode/valaccodeblock.vala deleted file mode 100644 index 6c9bbe4af..000000000 --- a/src/ccode/valaccodeblock.vala +++ /dev/null @@ -1,84 +0,0 @@ -/* valaccodeblock.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a C code block. - */ -public class Vala.CCodeBlock : CCodeStatement { - /** - * Specifies whether a newline at the end of the block should be - * suppressed. - */ - public bool suppress_newline { get; set; } - - private List statements = new ArrayList (); - - /** - * Prepend the specified statement to the list of statements. - */ - public void prepend_statement (CCodeNode statement) { - statements.insert (0, statement); - } - - /** - * Append the specified statement to the list of statements. - */ - public void add_statement (CCodeNode statement) { - /* allow generic nodes to include comments */ - statements.add (statement); - } - - public override void write (CCodeWriter writer) { - // the last reachable statement - CCodeNode last_statement = null; - - writer.write_begin_block (); - foreach (CCodeNode statement in statements) { - statement.write_declaration (writer); - - // determine last reachable statement - if (statement is CCodeLabel || statement is CCodeCaseStatement) { - last_statement = null; - } else if (statement is CCodeReturnStatement || statement is CCodeGotoStatement - || statement is CCodeContinueStatement || statement is CCodeBreakStatement) { - last_statement = statement; - } - } - - foreach (CCodeNode statement in statements) { - statement.write (writer); - - // only output reachable code - if (statement == last_statement) { - break; - } - } - - writer.write_end_block (); - - if (!suppress_newline) { - writer.write_newline (); - } - } -} diff --git a/src/ccode/valaccodebreakstatement.vala b/src/ccode/valaccodebreakstatement.vala deleted file mode 100644 index a032e2431..000000000 --- a/src/ccode/valaccodebreakstatement.vala +++ /dev/null @@ -1,34 +0,0 @@ -/* valaccodebreakstatement.vala - * - * Copyright (C) 2006-2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a break statement in the C code. - */ -public class Vala.CCodeBreakStatement : CCodeStatement { - public override void write (CCodeWriter writer) { - writer.write_indent (line); - writer.write_string ("break;"); - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodecasestatement.vala b/src/ccode/valaccodecasestatement.vala deleted file mode 100644 index 021d28078..000000000 --- a/src/ccode/valaccodecasestatement.vala +++ /dev/null @@ -1,45 +0,0 @@ -/* valaccodecasestatement.vala - * - * Copyright (C) 2006-2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a case block in a switch statement in C code. - */ -public class Vala.CCodeCaseStatement : CCodeStatement { - /** - * The case expression. - */ - public CCodeExpression expression { get; set; } - - public CCodeCaseStatement (CCodeExpression expression) { - this.expression = expression; - } - - public override void write (CCodeWriter writer) { - writer.write_indent (line); - writer.write_string ("case "); - expression.write (writer); - writer.write_string (":"); - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodecastexpression.vala b/src/ccode/valaccodecastexpression.vala deleted file mode 100644 index a06b1fa39..000000000 --- a/src/ccode/valaccodecastexpression.vala +++ /dev/null @@ -1,57 +0,0 @@ -/* valaccodecastexpression.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a type cast in the generated C code. - */ -public class Vala.CCodeCastExpression : CCodeExpression { - /** - * The expression to be cast. - */ - public CCodeExpression inner { get; set; } - - /** - * The target type. - */ - public string type_name { get; set; } - - public CCodeCastExpression (CCodeExpression expr, string type) { - inner = expr; - type_name = type; - } - - public override void write (CCodeWriter writer) { - writer.write_string ("("); - writer.write_string (type_name); - writer.write_string (") "); - - inner.write_inner (writer); - } - - public override void write_inner (CCodeWriter writer) { - writer.write_string ("("); - this.write (writer); - writer.write_string (")"); - } -} diff --git a/src/ccode/valaccodecommaexpression.vala b/src/ccode/valaccodecommaexpression.vala deleted file mode 100644 index 3221788ed..000000000 --- a/src/ccode/valaccodecommaexpression.vala +++ /dev/null @@ -1,62 +0,0 @@ -/* valaccodecommaexpression.vala - * - * Copyright (C) 2006-2010 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a comma separated expression list in the C code. - */ -public class Vala.CCodeCommaExpression : CCodeExpression { - private List inner = new ArrayList (); - - /** - * Appends the specified expression to the expression list. - * - * @param expr a C code expression - */ - public void append_expression (CCodeExpression expr) { - inner.add (expr); - } - - public void set_expression (int index, CCodeExpression expr) { - inner[index] = expr; - } - - public unowned List get_inner () { - return inner; - } - - public override void write (CCodeWriter writer) { - bool first = true; - - writer.write_string ("("); - foreach (CCodeExpression expr in inner) { - if (!first) { - writer.write_string (", "); - } else { - first = false; - } - expr.write (writer); - } - writer.write_string (")"); - } -} diff --git a/src/ccode/valaccodecomment.vala b/src/ccode/valaccodecomment.vala deleted file mode 100644 index 2902ebfd7..000000000 --- a/src/ccode/valaccodecomment.vala +++ /dev/null @@ -1,41 +0,0 @@ -/* valaccodecomment.vala - * - * Copyright (C) 2006 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a comment in the C code. - */ -public class Vala.CCodeComment : CCodeNode { - /** - * The text content of the comment. - */ - public string text { get; set; } - - public CCodeComment (string _text) { - text = _text; - } - - public override void write (CCodeWriter writer) { - writer.write_comment (text); - } -} diff --git a/src/ccode/valaccodeconditionalexpression.vala b/src/ccode/valaccodeconditionalexpression.vala deleted file mode 100644 index 24e5f9e74..000000000 --- a/src/ccode/valaccodeconditionalexpression.vala +++ /dev/null @@ -1,63 +0,0 @@ -/* valaccodeconditionalexpression.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a conditional expression in C code. - */ -public class Vala.CCodeConditionalExpression : CCodeExpression { - /** - * The condition. - */ - public CCodeExpression condition { get; set; } - - /** - * The expression to be evaluated if the condition holds. - */ - public CCodeExpression true_expression { get; set; } - - /** - * The expression to be evaluated if the condition doesn't hold. - */ - public CCodeExpression false_expression { get; set; } - - public CCodeConditionalExpression (CCodeExpression cond, CCodeExpression true_expr, CCodeExpression false_expr) { - condition = cond; - true_expression = true_expr; - false_expression = false_expr; - } - - public override void write (CCodeWriter writer) { - condition.write_inner (writer); - writer.write_string (" ? "); - true_expression.write_inner (writer); - writer.write_string (" : "); - false_expression.write_inner (writer); - } - - public override void write_inner (CCodeWriter writer) { - writer.write_string ("("); - this.write (writer); - writer.write_string (")"); - } -} diff --git a/src/ccode/valaccodeconstant.vala b/src/ccode/valaccodeconstant.vala deleted file mode 100644 index a3377237a..000000000 --- a/src/ccode/valaccodeconstant.vala +++ /dev/null @@ -1,112 +0,0 @@ -/* valaccodeconstant.vala - * - * Copyright (C) 2006-2010 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * A constant C expression. - */ -public class Vala.CCodeConstant : CCodeExpression { - /** - * The name of this constant. - */ - public string name { get; set; } - - public CCodeConstant (string _name) { - name = _name; - } - - const int LINE_LENGTH = 70; - - public CCodeConstant.string (string _name) { - assert (_name[0] == '\"'); - - if (_name.length <= LINE_LENGTH) { - name = _name; - return; - } - - var builder = new StringBuilder ("\""); - - char* p = _name; - char* end = p + _name.length; - - // remove quotes - p++; - end--; - - int col = 0; - while (p < end) { - if (col >= LINE_LENGTH) { - builder.append ("\" \\\n\""); - col = 0; - } - if (*p == '\\') { - char* begin_of_char = p; - - builder.append_c (p[0]); - builder.append_c (p[1]); - p += 2; - switch (p[-1]) { - case 'x': - // hexadecimal character - while (p < end && p->isxdigit ()) { - builder.append_c (*p); - p++; - } - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - // octal character - while (p < end && p - begin_of_char <= 3 && *p >= '0' && *p <= '7') { - builder.append_c (*p); - p++; - } - break; - case 'n': - // break line at \n - col = LINE_LENGTH; - break; - } - col += (int) (p - begin_of_char); - } else { - builder.append_unichar (((string) p).get_char ()); - p += ((char*) ((string) p).next_char () - p); - col++; - } - } - - builder.append_c ('"'); - - this.name = builder.str; - } - - public override void write (CCodeWriter writer) { - writer.write_string (name); - } -} diff --git a/src/ccode/valaccodeconstantidentifier.vala b/src/ccode/valaccodeconstantidentifier.vala deleted file mode 100644 index 0495389f1..000000000 --- a/src/ccode/valaccodeconstantidentifier.vala +++ /dev/null @@ -1,35 +0,0 @@ -/* valaccodeconstantidentifier.vala - * - * Copyright (C) 2021 Rico Tzschichholz - * - * 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.1 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: - * Rico Tzschichholz - */ - -using GLib; - -/** - * Represents a constant identifier in the C code. - */ -public class Vala.CCodeConstantIdentifier : CCodeIdentifier { - /** - * The name of this constant identifier. - */ - public CCodeConstantIdentifier (string name) { - base (name); - } -} diff --git a/src/ccode/valaccodecontinuestatement.vala b/src/ccode/valaccodecontinuestatement.vala deleted file mode 100644 index 013f201de..000000000 --- a/src/ccode/valaccodecontinuestatement.vala +++ /dev/null @@ -1,34 +0,0 @@ -/* valaccodecontinuestatement.vala - * - * Copyright (C) 2006-2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a continue statement in the C code. - */ -public class Vala.CCodeContinueStatement : CCodeStatement { - public override void write (CCodeWriter writer) { - writer.write_indent (line); - writer.write_string ("continue;"); - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodedeclaration.vala b/src/ccode/valaccodedeclaration.vala deleted file mode 100644 index d9bdd82b8..000000000 --- a/src/ccode/valaccodedeclaration.vala +++ /dev/null @@ -1,140 +0,0 @@ -/* valaccodedeclaration.vala - * - * Copyright (C) 2006-2010 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a local variable declaration in the C code. - */ -public class Vala.CCodeDeclaration : CCodeStatement { - /** - * The type of the local variable. - */ - public string type_name { get; set; } - - private List declarators = new ArrayList (); - - public CCodeDeclaration (string type_name) { - this.type_name = type_name; - } - - /** - * Adds the specified declarator to this declaration. - * - * @param decl a declarator - */ - public void add_declarator (CCodeDeclarator decl) { - declarators.add (decl); - } - - /** - * Returns the list of declarators. - * - * @return declarators list - */ - public unowned List get_declarators () { - return declarators; - } - - public override void write (CCodeWriter writer) { - if ((modifiers & (CCodeModifiers.STATIC | CCodeModifiers.INTERNAL | CCodeModifiers.EXTERN)) == 0) { - foreach (CCodeDeclarator decl in declarators) { - decl.write_initialization (writer); - } - } - } - - private bool has_initializer () { - foreach (CCodeDeclarator decl in declarators) { - var var_decl = decl as CCodeVariableDeclarator; - if (var_decl != null && var_decl.initializer == null) { - return false; - } - } - return true; - } - - public override void write_declaration (CCodeWriter writer) { - if ((modifiers & (CCodeModifiers.STATIC | CCodeModifiers.INTERNAL | CCodeModifiers.EXTERN)) != 0) { - // combined declaration and initialization for static and extern variables - writer.write_indent (line); - if ((modifiers & CCodeModifiers.INTERNAL) != 0) { - writer.write_string (GNUC_INTERNAL); - } - if ((modifiers & CCodeModifiers.STATIC) != 0) { - writer.write_string ("static "); - } - if ((modifiers & CCodeModifiers.VOLATILE) != 0) { - writer.write_string ("volatile "); - } - if ((modifiers & CCodeModifiers.EXTERN) != 0 && !has_initializer ()) { - writer.write_string ("VALA_EXTERN "); - } - if ((modifiers & CCodeModifiers.THREAD_LOCAL) != 0) { - writer.write_string ("thread_local "); - } - writer.write_string (type_name); - writer.write_string (" "); - - bool first = true; - foreach (CCodeDeclarator decl in declarators) { - if (!first) { - writer.write_string (", "); - } else { - first = false; - } - decl.write (writer); - } - - writer.write_string (";"); - writer.write_newline (); - return; - } - - writer.write_indent (); - if ((modifiers & CCodeModifiers.REGISTER) == CCodeModifiers.REGISTER) { - writer.write_string ("register "); - } - if ((modifiers & CCodeModifiers.VOLATILE) != 0) { - writer.write_string ("volatile "); - } - writer.write_string (type_name); - writer.write_string (" "); - - bool first = true; - foreach (CCodeDeclarator decl in declarators) { - if (!first) { - writer.write_string (", "); - } else { - first = false; - } - decl.write_declaration (writer); - } - - if (CCodeModifiers.DEPRECATED in modifiers) { - writer.write_string (GNUC_DEPRECATED); - } - - writer.write_string (";"); - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodedeclarator.vala b/src/ccode/valaccodedeclarator.vala deleted file mode 100644 index 634dbb856..000000000 --- a/src/ccode/valaccodedeclarator.vala +++ /dev/null @@ -1,42 +0,0 @@ -/* valaccodedeclarator.vala - * - * Copyright (C) 2006-2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a variable or function pointer declarator in the C code. - */ -public abstract class Vala.CCodeDeclarator : CCodeNode { - /** - * The declarator name. - */ - public string name { get; set; } - - /** - * Writes initialization statements for this declarator with the - * specified C code writer if necessary. - * - * @param writer a C code writer - */ - public virtual void write_initialization (CCodeWriter writer) { - } -} diff --git a/src/ccode/valaccodedefine.vala b/src/ccode/valaccodedefine.vala deleted file mode 100644 index 24ad09828..000000000 --- a/src/ccode/valaccodedefine.vala +++ /dev/null @@ -1,68 +0,0 @@ -/* valaccodedefine.vala - * - * Copyright (C) 2018 Dr. Michael 'Mickey' Lauer - * - * 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.1 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: - * Dr. Michael 'Mickey' Lauer - * Rico Tzschichholz - */ - -using GLib; - -/** - * Represents a definition in the C code. - */ -public class Vala.CCodeDefine : CCodeNode { - /** - * The name of this definition. - */ - public string name { get; set; } - - /** - * The value of this definition. - */ - public string? value { get; set; } - - /** - * The value expression of this definition. - */ - public CCodeExpression? value_expression { get; set; } - - public CCodeDefine (string name, string? value = null) { - this.name = name; - this.value = value; - } - - public CCodeDefine.with_expression (string name, CCodeExpression expression) { - this.name = name; - this.value_expression = expression; - } - - public override void write (CCodeWriter writer) { - writer.write_indent (); - writer.write_string ("#define "); - writer.write_string (name); - if (value != null) { - writer.write_string (" "); - writer.write_string (@value); - } else if (value_expression != null) { - writer.write_string (" "); - value_expression.write_inner (writer); - } - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodedostatement.vala b/src/ccode/valaccodedostatement.vala deleted file mode 100644 index 18c803e94..000000000 --- a/src/ccode/valaccodedostatement.vala +++ /dev/null @@ -1,62 +0,0 @@ -/* valaccodedostatement.vala - * - * Copyright (C) 2006-2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a do iteration statement in the C code. - */ -public class Vala.CCodeDoStatement : CCodeStatement { - /** - * The loop body. - */ - public CCodeStatement body { get; set; } - - /** - * The loop condition. - */ - public CCodeExpression condition { get; set; } - - public CCodeDoStatement (CCodeStatement stmt, CCodeExpression cond) { - body = stmt; - condition = cond; - } - - public override void write (CCodeWriter writer) { - writer.write_indent (line); - writer.write_string ("do"); - - /* while shouldn't be on a separate line */ - if (body is CCodeBlock) { - var cblock = (CCodeBlock) body; - cblock.suppress_newline = true; - } - - body.write (writer); - - writer.write_string (" while ("); - - condition.write (writer); - - writer.write_string (");"); - } -} diff --git a/src/ccode/valaccodeelementaccess.vala b/src/ccode/valaccodeelementaccess.vala deleted file mode 100644 index a99af44b5..000000000 --- a/src/ccode/valaccodeelementaccess.vala +++ /dev/null @@ -1,66 +0,0 @@ -/* valaccodememberaccess.vala - * - * Copyright (C) 2006 Raffaele Sandrini - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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: - * Raffaele Sandrini - * Jürg Billeter - */ - -using GLib; - -/** - * Represents an access to an array member in the C code. - */ -public class Vala.CCodeElementAccess : CCodeExpression { - /** - * Expression representing the container on which we want to access. - */ - public CCodeExpression container { get; set; } - - /** - * Expression representing the index we want to access inside the - * container. - */ - public List indices { get; set; } - - public CCodeElementAccess (CCodeExpression cont, CCodeExpression i) { - container = cont; - indices = new ArrayList (); - indices.add (i); - } - - public CCodeElementAccess.with_indices (CCodeExpression cont, List i) { - container = cont; - indices = i; - } - - public override void write (CCodeWriter writer) { - container.write_inner (writer); - writer.write_string ("["); - bool first = true; - foreach (var index in indices) { - if (!first) { - writer.write_string ("]["); - } - index.write (writer); - first = false; - } - writer.write_string ("]"); - } -} diff --git a/src/ccode/valaccodeemptystatement.vala b/src/ccode/valaccodeemptystatement.vala deleted file mode 100644 index 2a27a4a78..000000000 --- a/src/ccode/valaccodeemptystatement.vala +++ /dev/null @@ -1,34 +0,0 @@ -/* valaccodeemptystatement.vala - * - * Copyright (C) 2006 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents an empty statement in the C code. - */ -public class Vala.CCodeEmptyStatement : CCodeStatement { - public override void write (CCodeWriter writer) { - writer.write_indent (); - writer.write_string (";"); - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodeenum.vala b/src/ccode/valaccodeenum.vala deleted file mode 100644 index d59db0e5a..000000000 --- a/src/ccode/valaccodeenum.vala +++ /dev/null @@ -1,79 +0,0 @@ -/* valaccodeenum.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents an enum in the C code. - */ -public class Vala.CCodeEnum : CCodeNode { - /** - * The name of this enum. - */ - public string name { get; set; } - - private List values = new ArrayList (); - - public CCodeEnum (string? name = null) { - this.name = name; - } - - /** - * Adds the specified value to this enum. - * - * @param value optional numerical value - */ - public void add_value (CCodeEnumValue value) { - values.add (value); - } - - public override void write (CCodeWriter writer) { - if (name != null) { - writer.write_string ("typedef "); - } - writer.write_string ("enum "); - writer.write_begin_block (); - bool first = true; - foreach (CCodeEnumValue value in values) { - if (!first) { - writer.write_string (","); - writer.write_newline (); - } - writer.write_indent (); - value.write (writer); - first = false; - } - if (!first) { - writer.write_newline (); - } - writer.write_end_block (); - if (name != null) { - writer.write_string (" "); - writer.write_string (name); - } - if (CCodeModifiers.DEPRECATED in modifiers) { - writer.write_string (GNUC_DEPRECATED); - } - writer.write_string (";"); - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodeenumvalue.vala b/src/ccode/valaccodeenumvalue.vala deleted file mode 100644 index 23d37c492..000000000 --- a/src/ccode/valaccodeenumvalue.vala +++ /dev/null @@ -1,56 +0,0 @@ -/* valaccodeenumvalue.vala - * - * Copyright (C) 2007-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents an enum value in the C code. - */ -public class Vala.CCodeEnumValue : CCodeNode { - /** - * The name of this enum value. - */ - public string name { get; set; } - - /** - * The numerical representation of this enum value. - */ - public CCodeExpression? value { get; set; } - - public CCodeEnumValue (string name, CCodeExpression? value = null) { - this.name = name; - this.value = value; - } - - public override void write (CCodeWriter writer) { - writer.write_string (name); - if (CCodeModifiers.DEPRECATED in modifiers) { - // FIXME Requires GCC 6.0 to work at this place - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47043 - //writer.write_string (GNUC_DEPRECATED); - } - if (value != null) { - writer.write_string (" = "); - value.write (writer); - } - } -} diff --git a/src/ccode/valaccodeexpression.vala b/src/ccode/valaccodeexpression.vala deleted file mode 100644 index 420eba7d5..000000000 --- a/src/ccode/valaccodeexpression.vala +++ /dev/null @@ -1,32 +0,0 @@ -/* valaccodeexpression.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents an expression node in the C code tree. - */ -public abstract class Vala.CCodeExpression : CCodeNode { - public virtual void write_inner (CCodeWriter writer) { - this.write (writer); - } -} diff --git a/src/ccode/valaccodeexpressionstatement.vala b/src/ccode/valaccodeexpressionstatement.vala deleted file mode 100644 index ae721939a..000000000 --- a/src/ccode/valaccodeexpressionstatement.vala +++ /dev/null @@ -1,64 +0,0 @@ -/* valaccodeexpressionstatement.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a C code statement that evaluates a given expression. - */ -public class Vala.CCodeExpressionStatement : CCodeStatement { - /** - * The expression to evaluate. - */ - public CCodeExpression expression { get; set; } - - public CCodeExpressionStatement (CCodeExpression expr) { - expression = expr; - } - - public override void write (CCodeWriter writer) { - if (expression is CCodeCommaExpression) { - // expand comma expression into multiple statements - // to improve code readability - var ccomma = expression as CCodeCommaExpression; - - foreach (CCodeExpression expr in ccomma.get_inner ()) { - write_expression (writer, expr); - } - } else if (expression is CCodeParenthesizedExpression) { - var cpar = expression as CCodeParenthesizedExpression; - - write_expression (writer, cpar.inner); - } else { - write_expression (writer, expression); - } - } - - private void write_expression (CCodeWriter writer, CCodeExpression? expr) { - writer.write_indent (line); - if (expr != null) { - expr.write (writer); - } - writer.write_string (";"); - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodefile.vala b/src/ccode/valaccodefile.vala deleted file mode 100644 index f61da07df..000000000 --- a/src/ccode/valaccodefile.vala +++ /dev/null @@ -1,229 +0,0 @@ -/* valaccodefile.vala - * - * Copyright (C) 2009-2011 Jürg Billeter - * - * 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.1 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 - */ - - -public class Vala.CCodeFile { - public CCodeFileType file_type { get; private set; } - - public weak SourceFile? file { get; private set; } - - Set features = new HashSet (str_hash, str_equal); - Set declarations = new HashSet (str_hash, str_equal); - Set definitions = new HashSet (str_hash, str_equal); - Set includes = new HashSet (str_hash, str_equal); - CCodeFragment comments = new CCodeFragment (); - CCodeFragment feature_test_macros = new CCodeFragment (); - CCodeFragment define_directives = new CCodeFragment (); - CCodeFragment include_directives = new CCodeFragment (); - CCodeFragment type_declaration = new CCodeFragment (); - CCodeFragment type_definition = new CCodeFragment (); - CCodeFragment type_member_declaration = new CCodeFragment (); - CCodeFragment constant_declaration = new CCodeFragment (); - CCodeFragment type_member_definition = new CCodeFragment (); - - public CCodeFile (CCodeFileType type = CCodeFileType.SOURCE, SourceFile? source_file = null) { - file = source_file; - file_type = type; - } - - public bool add_declaration (string name) { - if (name in declarations) { - return true; - } - declarations.add (name); - return false; - } - - public void add_comment (CCodeComment comment) { - comments.append (comment); - } - - public void add_feature_test_macro (string feature_test_macro) { - if (!(feature_test_macro in features)) { - feature_test_macros.append (new CCodeDefine (feature_test_macro)); - features.add (feature_test_macro); - } - } - - public void add_include (string filename, bool local = false) { - if (!(filename in includes)) { - include_directives.append (new CCodeIncludeDirective (filename, local)); - includes.add (filename); - } - } - - public void add_define (CCodeNode node) { - define_directives.append (node); - } - - public void add_type_declaration (CCodeNode node) { - type_declaration.append (node); - } - - public void add_type_definition (CCodeNode node) { - type_definition.append (node); - } - - public void add_type_member_declaration (CCodeNode node) { - type_member_declaration.append (node); - } - - public void add_constant_declaration (CCodeNode node) { - constant_declaration.append (node); - } - - public void add_type_member_definition (CCodeNode node) { - type_member_definition.append (node); - } - - public void add_function_declaration (CCodeFunction func) { - declarations.add (func.name); - - var decl = func.copy (); - decl.is_declaration = true; - type_member_declaration.append (decl); - } - - public void add_function (CCodeFunction func) { - if (!definitions.add (func.name)) { - Report.error (null, "internal: Redefinition of `%s'", func.name); - return; - } - - type_member_definition.append (func); - } - - public List get_symbols () { - var symbols = new ArrayList (str_equal); - get_symbols_from_fragment (symbols, type_member_declaration); - return symbols; - } - - void get_symbols_from_fragment (List symbols, CCodeFragment fragment) { - foreach (CCodeNode node in fragment.get_children ()) { - if (node is CCodeFragment) { - get_symbols_from_fragment (symbols, (CCodeFragment) node); - } else { - var func = node as CCodeFunction; - if (func != null) { - symbols.add (func.name); - } - } - } - } - - static string get_define_for_filename (string filename) { - var define = new StringBuilder ("__"); - - var i = filename; - while (i.length > 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 bool store (string filename, string? source_filename, bool write_version, bool line_directives, string? begin_decls = null, string? end_decls = null) { - var writer = new CCodeWriter (filename, source_filename); - if (!writer.open (write_version)) { - return false; - } - - if (file_type == CCodeFileType.SOURCE) { - writer.line_directives = line_directives; - - comments.write (writer); - writer.write_newline (); - feature_test_macros.write (writer); - writer.write_newline (); - include_directives.write (writer); - writer.write_newline (); - define_directives.write (writer); - writer.write_newline (); - type_declaration.write_combined (writer); - writer.write_newline (); - type_definition.write_combined (writer); - writer.write_newline (); - type_member_declaration.write_declaration (writer); - writer.write_newline (); - type_member_declaration.write (writer); - writer.write_newline (); - constant_declaration.write_combined (writer); - writer.write_newline (); - type_member_definition.write (writer); - writer.write_newline (); - } else { - writer.write_newline (); - - var once = new CCodeOnceSection (get_define_for_filename (writer.filename)); - once.append (new CCodeNewline ()); - once.append (include_directives); - once.append (new CCodeNewline ()); - - if (begin_decls != null) { - once.append (new CCodeIdentifier (begin_decls)); - once.append (new CCodeNewline ()); - } - - once.append (new CCodeNewline ()); - once.append (define_directives); - once.append (new CCodeNewline ()); - once.append (type_declaration); - once.append (new CCodeNewline ()); - once.append (type_definition); - once.append (new CCodeNewline ()); - once.append (type_member_declaration); - once.append (new CCodeNewline ()); - once.append (constant_declaration); - once.append (new CCodeNewline ()); - - if (end_decls != null) { - once.append (new CCodeIdentifier (end_decls)); - once.append (new CCodeNewline ()); - } - - once.append (new CCodeNewline ()); - once.write (writer); - } - - writer.close (); - - return true; - } -} - -[Flags] -public enum CCodeFileType { - SOURCE, - PUBLIC_HEADER, - INTERNAL_HEADER, - HEADER = PUBLIC_HEADER | INTERNAL_HEADER -} diff --git a/src/ccode/valaccodeforstatement.vala b/src/ccode/valaccodeforstatement.vala deleted file mode 100644 index f821e0d46..000000000 --- a/src/ccode/valaccodeforstatement.vala +++ /dev/null @@ -1,104 +0,0 @@ -/* valaccodeforstatement.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a for iteration statement in the C code. - */ -public class Vala.CCodeForStatement : CCodeStatement { - /** - * The loop condition. - */ - public CCodeExpression? condition { get; set; } - - /** - * The loop body. - */ - public CCodeStatement body { get; set; } - - private List initializer = new ArrayList (); - private List iterator = new ArrayList (); - - public CCodeForStatement (CCodeExpression? condition, CCodeStatement? body = null) { - this.condition = condition; - this.body = body; - } - - /** - * Appends the specified expression to the list of initializers. - * - * @param expr an initializer expression - */ - public void add_initializer (CCodeExpression expr) { - initializer.add (expr); - } - - /** - * Appends the specified expression to the iterator. - * - * @param expr an iterator expression - */ - public void add_iterator (CCodeExpression expr) { - iterator.add (expr); - } - - public override void write (CCodeWriter writer) { - bool first; - - writer.write_indent (line); - writer.write_string ("for ("); - - first = true; - foreach (CCodeExpression init_expr in initializer) { - if (!first) { - writer.write_string (", "); - } else { - first = false; - } - if (init_expr != null) { - init_expr.write (writer); - } - } - - writer.write_string ("; "); - if (condition != null) { - condition.write (writer); - } - writer.write_string ("; "); - - first = true; - foreach (CCodeExpression it_expr in iterator) { - if (!first) { - writer.write_string (", "); - } else { - first = false; - } - if (it_expr != null) { - it_expr.write (writer); - } - } - - writer.write_string (")"); - body.write (writer); - } -} diff --git a/src/ccode/valaccodefragment.vala b/src/ccode/valaccodefragment.vala deleted file mode 100644 index 49d415307..000000000 --- a/src/ccode/valaccodefragment.vala +++ /dev/null @@ -1,66 +0,0 @@ -/* valaccodefragment.vala - * - * Copyright (C) 2006-2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a container for C code nodes. - */ -public class Vala.CCodeFragment : CCodeNode { - private List children = new ArrayList (); - - /** - * Appends the specified code node to this code fragment. - * - * @param node a C code node - */ - public void append (CCodeNode node) { - children.add (node); - } - - /** - * Returns the list of children. - * - * @return children list - */ - public unowned List get_children () { - return children; - } - - public override void write (CCodeWriter writer) { - foreach (CCodeNode node in children) { - node.write (writer); - } - } - - public override void write_declaration (CCodeWriter writer) { - foreach (CCodeNode node in children) { - node.write_declaration (writer); - } - } - - public override void write_combined (CCodeWriter writer) { - foreach (CCodeNode node in children) { - node.write_combined (writer); - } - } -} diff --git a/src/ccode/valaccodefunction.vala b/src/ccode/valaccodefunction.vala deleted file mode 100644 index 395ffdc8b..000000000 --- a/src/ccode/valaccodefunction.vala +++ /dev/null @@ -1,336 +0,0 @@ -/* valaccodefunction.vala - * - * Copyright (C) 2006-2012 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a function declaration in the C code. - */ -public class Vala.CCodeFunction : CCodeNode { - /** - * The name of this function. - */ - public string name { get; set; } - - /** - * The function return type. - */ - public string return_type { get; set; } - - public bool is_declaration { get; set; } - - /** - * The function body. - */ - public CCodeBlock block { get; set; } - - /** - * The current line directive. - */ - public CCodeLineDirective current_line { get; set; } - - /** - * The current block to be written into. - */ - public CCodeBlock current_block { get; set; } - - private List parameters = new ArrayList (); - - List statement_stack = new ArrayList (); - - public CCodeFunction (string name, string return_type = "void") { - this.name = name; - this.return_type = return_type; - this.block = new CCodeBlock (); - current_block = block; - } - - /** - * Appends the specified parameter to the list of function parameters. - * - * @param param a formal parameter - */ - public void add_parameter (CCodeParameter param) { - parameters.add (param); - } - - public void insert_parameter (int position, CCodeParameter param) { - parameters.insert (position, param); - } - - public int get_parameter_count () { - return parameters.size; - } - - public CCodeParameter get_parameter (int position) { - return parameters[position]; - } - - /** - * Returns a copy of this function. - * - * @return copied function - */ - public CCodeFunction copy () { - var func = new CCodeFunction (name, return_type); - func.modifiers = modifiers; - - /* no deep copy for lists available yet - * func.parameters = parameters.copy (); - */ - foreach (CCodeParameter param in parameters) { - func.parameters.add (param); - } - - func.is_declaration = is_declaration; - func.block = block; - return func; - } - - public override void write (CCodeWriter writer) { - writer.write_indent (line); - if (CCodeModifiers.INTERNAL in modifiers) { - writer.write_string (GNUC_INTERNAL); - } else if (is_declaration && CCodeModifiers.EXTERN in modifiers) { - writer.write_string ("VALA_EXTERN "); - } - if (!is_declaration && CCodeModifiers.NO_INLINE in modifiers) { - writer.write_string (GNUC_NO_INLINE); - } - if (CCodeModifiers.STATIC in modifiers) { - writer.write_string ("static "); - } - if (CCodeModifiers.INLINE in modifiers) { - writer.write_string ("inline "); - } - writer.write_string (return_type); - if (is_declaration) { - writer.write_string (" "); - } else { - writer.write_newline (); - } - writer.write_string (name); - writer.write_string (" ("); - int param_pos_begin = (is_declaration ? return_type.char_count () + 1 : 0 ) + name.char_count () + 2; - - bool has_args = (CCodeModifiers.PRINTF in modifiers || CCodeModifiers.SCANF in modifiers); - int i = 0; - int format_arg_index = -1; - int args_index = -1; - foreach (CCodeParameter param in parameters) { - if (i > 0) { - writer.write_string (","); - writer.write_newline (); - writer.write_nspaces (param_pos_begin); - } - param.write (writer); - if (CCodeModifiers.FORMAT_ARG in param.modifiers) { - format_arg_index = i; - } - if (has_args && param.ellipsis) { - args_index = i; - } else if (has_args && param.type_name == "va_list" && format_arg_index < 0) { - format_arg_index = i - 1; - } - i++; - } - if (i == 0) { - writer.write_string ("void"); - } - - writer.write_string (")"); - - if (is_declaration) { - if (CCodeModifiers.DEPRECATED in modifiers) { - writer.write_string (GNUC_DEPRECATED); - } - - if (CCodeModifiers.PRINTF in modifiers) { - format_arg_index = (format_arg_index >= 0 ? format_arg_index + 1 : args_index); - writer.write_string (GNUC_PRINTF.printf (format_arg_index, args_index + 1)); - } else if (CCodeModifiers.SCANF in modifiers) { - format_arg_index = (format_arg_index >= 0 ? format_arg_index + 1 : args_index); - writer.write_string (GNUC_SCANF.printf (format_arg_index, args_index + 1)); - } else if (format_arg_index >= 0) { - writer.write_string (GNUC_FORMAT.printf (format_arg_index + 1)); - } - - if (CCodeModifiers.CONST in modifiers) { - writer.write_string (GNUC_CONST); - } - if (CCodeModifiers.UNUSED in modifiers) { - writer.write_string (GNUC_UNUSED); - } - - if (CCodeModifiers.CONSTRUCTOR in modifiers) { - writer.write_string (" __attribute__((constructor))"); - } else if (CCodeModifiers.DESTRUCTOR in modifiers) { - writer.write_string (" __attribute__((destructor))"); - } - - writer.write_string (";"); - } else { - writer.write_newline (); - block.write (writer); - writer.write_newline (); - } - writer.write_newline (); - } - - public void add_statement (CCodeNode stmt) { - stmt.line = current_line; - current_block.add_statement (stmt); - } - - public void open_block () { - statement_stack.add (current_block); - var parent_block = current_block; - - current_block = new CCodeBlock (); - - parent_block.add_statement (current_block); - } - - public void open_if (CCodeExpression condition) { - statement_stack.add (current_block); - var parent_block = current_block; - - current_block = new CCodeBlock (); - - var cif = new CCodeIfStatement (condition, current_block); - cif.line = current_line; - statement_stack.add (cif); - - parent_block.add_statement (cif); - } - - public void add_else () { - current_block = new CCodeBlock (); - - var cif = (CCodeIfStatement) statement_stack[statement_stack.size - 1]; - cif.line = current_line; - assert (cif.false_statement == null); - cif.false_statement = current_block; - } - - public void else_if (CCodeExpression condition) { - var parent_if = (CCodeIfStatement) statement_stack.remove_at (statement_stack.size - 1); - assert (parent_if.false_statement == null); - - current_block = new CCodeBlock (); - - var cif = new CCodeIfStatement (condition, current_block); - cif.line = current_line; - parent_if.false_statement = cif; - statement_stack.add (cif); - } - - public void open_while (CCodeExpression condition) { - statement_stack.add (current_block); - var parent_block = current_block; - - current_block = new CCodeBlock (); - - var cwhile = new CCodeWhileStatement (condition, current_block); - cwhile.line = current_line; - parent_block.add_statement (cwhile); - } - - public void open_for (CCodeExpression? initializer, CCodeExpression condition, CCodeExpression? iterator) { - statement_stack.add (current_block); - var parent_block = current_block; - - current_block = new CCodeBlock (); - - var cfor = new CCodeForStatement (condition, current_block); - cfor.line = current_line; - if (initializer != null) { - cfor.add_initializer (initializer); - } - if (iterator != null) { - cfor.add_iterator (iterator); - } - - parent_block.add_statement (cfor); - } - - public void open_switch (CCodeExpression expression) { - statement_stack.add (current_block); - var parent_block = current_block; - - var cswitch = new CCodeSwitchStatement (expression); - cswitch.line = current_line; - current_block = cswitch; - - parent_block.add_statement (cswitch); - } - - public void add_label (string label) { - add_statement (new CCodeLabel (label)); - } - - public void add_case (CCodeExpression expression) { - add_statement (new CCodeCaseStatement (expression)); - } - - public void add_default () { - add_statement (new CCodeLabel ("default")); - } - - public void add_goto (string target) { - add_statement (new CCodeGotoStatement (target)); - } - - public void add_expression (CCodeExpression expression) { - add_statement (new CCodeExpressionStatement (expression)); - } - - public void add_assignment (CCodeExpression left, CCodeExpression right) { - add_expression (new CCodeAssignment (left, right)); - } - - public void add_return (CCodeExpression? expression = null) { - add_statement (new CCodeReturnStatement (expression)); - } - - public void add_break () { - add_statement (new CCodeBreakStatement ()); - } - - public void add_continue () { - add_statement (new CCodeContinueStatement ()); - } - - public void add_declaration (string type_name, CCodeDeclarator declarator, CCodeModifiers modifiers = 0) { - var stmt = new CCodeDeclaration (type_name); - stmt.add_declarator (declarator); - stmt.modifiers = modifiers; - add_statement (stmt); - } - - public void close () { - do { - var top = statement_stack.remove_at (statement_stack.size - 1); - current_block = top as CCodeBlock; - } while (current_block == null); - } -} diff --git a/src/ccode/valaccodefunctioncall.vala b/src/ccode/valaccodefunctioncall.vala deleted file mode 100644 index 1d2e364c0..000000000 --- a/src/ccode/valaccodefunctioncall.vala +++ /dev/null @@ -1,81 +0,0 @@ -/* valaccodefunctioncall.vala - * - * Copyright (C) 2006-2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a function call in the C code. - */ -public class Vala.CCodeFunctionCall : CCodeExpression { - /** - * The function to be called. - */ - public CCodeExpression? call { get; set; } - - private List arguments = new ArrayList (); - - public CCodeFunctionCall (CCodeExpression? call = null) { - this.call = call; - } - - /** - * Appends the specified expression to the list of arguments. - * - * @param expr a C code expression - */ - public void add_argument (CCodeExpression expr) { - arguments.add (expr); - } - - public void insert_argument (int index, CCodeExpression expr) { - arguments.insert (index, expr); - } - - /** - * Returns the list of arguments. - * - * @return list of arguments - */ - public unowned List get_arguments () { - return arguments; - } - - public override void write (CCodeWriter writer) { - call.write_inner (writer); - writer.write_string (" ("); - - bool first = true; - foreach (CCodeExpression expr in arguments) { - if (!first) { - writer.write_string (", "); - } else { - first = false; - } - - if (expr != null) { - expr.write (writer); - } - } - - writer.write_string (")"); - } -} diff --git a/src/ccode/valaccodefunctiondeclarator.vala b/src/ccode/valaccodefunctiondeclarator.vala deleted file mode 100644 index 2ba21e957..000000000 --- a/src/ccode/valaccodefunctiondeclarator.vala +++ /dev/null @@ -1,92 +0,0 @@ -/* valaccodefunctiondeclarator.vala - * - * Copyright (C) 2006-2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a function pointer declarator in the C code. - */ -public class Vala.CCodeFunctionDeclarator : CCodeDeclarator { - private List parameters = new ArrayList (); - - public CCodeFunctionDeclarator (string name) { - this.name = name; - } - - /** - * Appends the specified parameter to the list of function parameters. - * - * @param param a formal parameter - */ - public void add_parameter (CCodeParameter param) { - parameters.add (param); - } - - public override void write (CCodeWriter writer) { - write_declaration (writer); - } - - public override void write_declaration (CCodeWriter writer) { - writer.write_string ("(*"); - writer.write_string (name); - writer.write_string (") ("); - - bool has_args = (CCodeModifiers.PRINTF in modifiers || CCodeModifiers.SCANF in modifiers); - int i = 0; - int format_arg_index = -1; - int args_index = -1; - foreach (CCodeParameter param in parameters) { - if (i > 0) { - writer.write_string (", "); - } - param.write (writer); - if (CCodeModifiers.FORMAT_ARG in param.modifiers) { - format_arg_index = i; - } - if (has_args && param.ellipsis) { - args_index = i; - } else if (has_args && param.type_name == "va_list" && format_arg_index < 0) { - format_arg_index = i - 1; - } - i++; - } - if (i == 0) { - writer.write_string ("void"); - } - - writer.write_string (")"); - - if (CCodeModifiers.DEPRECATED in modifiers) { - writer.write_string (GNUC_DEPRECATED); - } - - if (CCodeModifiers.PRINTF in modifiers) { - format_arg_index = (format_arg_index >= 0 ? format_arg_index + 1 : args_index); - writer.write_string (GNUC_PRINTF.printf (format_arg_index, args_index + 1)); - } else if (CCodeModifiers.SCANF in modifiers) { - format_arg_index = (format_arg_index >= 0 ? format_arg_index + 1 : args_index); - writer.write_string (GNUC_SCANF.printf (format_arg_index, args_index + 1)); - } else if (format_arg_index >= 0) { - writer.write_string (GNUC_FORMAT.printf (format_arg_index + 1)); - } - } -} diff --git a/src/ccode/valaccodeggnucsection.vala b/src/ccode/valaccodeggnucsection.vala deleted file mode 100644 index f4a28e384..000000000 --- a/src/ccode/valaccodeggnucsection.vala +++ /dev/null @@ -1,65 +0,0 @@ -/* valaccodeggnucsection.vala - * - * Copyright (C) 2016 Rico Tzschichholz - * - * 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.1 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: - * Rico Tzschichholz - */ - -using GLib; - -/** - * Represents a section that should be processed on condition. - */ -public class Vala.CCodeGGnucSection : CCodeFragment { - /** - * The expression - */ - public GGnucSectionType section_type { get; set; } - - public CCodeGGnucSection (GGnucSectionType t) { - section_type = t; - } - - public override void write (CCodeWriter writer) { - writer.write_string ("G_GNUC_BEGIN_"); - writer.write_string (section_type.to_string ()); - writer.write_newline (); - foreach (CCodeNode node in get_children ()) { - node.write_combined (writer); - } - writer.write_string ("G_GNUC_END_"); - writer.write_string (section_type.to_string ()); - writer.write_newline (); - } - - public override void write_declaration (CCodeWriter writer) { - } -} - -public enum Vala.GGnucSectionType { - IGNORE_DEPRECATIONS; - - public unowned string to_string () { - switch (this) { - case IGNORE_DEPRECATIONS: - return "IGNORE_DEPRECATIONS"; - default: - assert_not_reached (); - } - } -} diff --git a/src/ccode/valaccodegotostatement.vala b/src/ccode/valaccodegotostatement.vala deleted file mode 100644 index b1e0d2980..000000000 --- a/src/ccode/valaccodegotostatement.vala +++ /dev/null @@ -1,45 +0,0 @@ -/* valaccodegotostatement.vala - * - * Copyright (C) 2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a goto statement in the C code. - */ -public class Vala.CCodeGotoStatement : CCodeStatement { - /** - * The name of the target label. - */ - public string name { get; set; } - - public CCodeGotoStatement (string name) { - this.name = name; - } - - public override void write (CCodeWriter writer) { - writer.write_indent (); - writer.write_string ("goto "); - writer.write_string (name); - writer.write_string (";"); - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodeidentifier.vala b/src/ccode/valaccodeidentifier.vala deleted file mode 100644 index f0b1f0106..000000000 --- a/src/ccode/valaccodeidentifier.vala +++ /dev/null @@ -1,41 +0,0 @@ -/* valaccodeidentifier.vala - * - * Copyright (C) 2006 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a identifier in the C code. - */ -public class Vala.CCodeIdentifier : CCodeExpression { - /** - * The name of this identifier. - */ - public string name { get; set; } - - public CCodeIdentifier (string _name) { - name = _name; - } - - public override void write (CCodeWriter writer) { - writer.write_string (name); - } -} diff --git a/src/ccode/valaccodeifsection.vala b/src/ccode/valaccodeifsection.vala deleted file mode 100644 index 44c3fe7f7..000000000 --- a/src/ccode/valaccodeifsection.vala +++ /dev/null @@ -1,78 +0,0 @@ -/* valaccodeifsection.vala - * - * Copyright (C) 2013 Jürg Billeter - * - * 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.1 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: - * Marc-André Lurau - */ - -using GLib; - -/** - * Represents a section that should be processed on condition. - */ -public class Vala.CCodeIfSection : CCodeFragment { - /** - * The conditional expression, or null if there is no condition. - */ - public string? expression { get; set; } - - CCodeIfSection? else_section; - bool is_else_section; - - public CCodeIfSection (string? expr) { - expression = expr; - is_else_section = false; - } - - public unowned CCodeIfSection append_else (string? expr = null) { - else_section = new CCodeIfSection (expr); - else_section.is_else_section = true; - return else_section; - } - - public override void write (CCodeWriter writer) { - if (is_else_section) { - if (expression != null) { - writer.write_string ("#elif "); - writer.write_string (expression); - } else { - writer.write_string ("#else"); - } - } else if (expression != null) { - writer.write_string ("#if "); - writer.write_string (expression); - } - writer.write_newline (); - foreach (CCodeNode node in get_children ()) { - node.write_combined (writer); - } - if (else_section != null) { - else_section.write_combined (writer); - } else { - writer.write_string ("#endif"); - writer.write_newline (); - } - } - - public override void write_declaration (CCodeWriter writer) { - } - - public override void write_combined (CCodeWriter writer) { - write (writer); - } -} diff --git a/src/ccode/valaccodeifstatement.vala b/src/ccode/valaccodeifstatement.vala deleted file mode 100644 index c4522302e..000000000 --- a/src/ccode/valaccodeifstatement.vala +++ /dev/null @@ -1,92 +0,0 @@ -/* valaccodeifstatement.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents an if selection statement in the C code. - */ -public class Vala.CCodeIfStatement : CCodeStatement { - /** - * The boolean condition to evaluate. - */ - public CCodeExpression condition { get; set; } - - /** - * The statement to be evaluated if the condition holds. - */ - public CCodeStatement true_statement { get; set; } - - /** - * The optional statement to be evaluated if the condition doesn't hold. - */ - public CCodeStatement? false_statement { get; set; } - - public CCodeIfStatement (CCodeExpression cond, CCodeStatement true_stmt, CCodeStatement? false_stmt = null) { - condition = cond; - true_statement = true_stmt; - false_statement = false_stmt; - } - - /** - * Specifies whether this if statement is part of an else if statement. - * This only affects the output formatting. - */ - public bool else_if { get; set; } - - public override void write (CCodeWriter writer) { - if (!else_if) { - writer.write_indent (line); - } else { - writer.write_string (" "); - } - writer.write_string ("if ("); - if (condition != null) { - condition.write (writer); - } - writer.write_string (")"); - - /* else shouldn't be on a separate line */ - if (false_statement != null && true_statement is CCodeBlock) { - var cblock = (CCodeBlock) true_statement; - cblock.suppress_newline = true; - } - - true_statement.write (writer); - if (false_statement != null) { - if (writer.bol) { - writer.write_indent (); - writer.write_string ("else"); - } else { - writer.write_string (" else"); - } - - /* else if should be on one line */ - if (false_statement is CCodeIfStatement) { - var cif = (CCodeIfStatement) false_statement; - cif.else_if = true; - } - - false_statement.write (writer); - } - } -} diff --git a/src/ccode/valaccodeincludedirective.vala b/src/ccode/valaccodeincludedirective.vala deleted file mode 100644 index 184185d95..000000000 --- a/src/ccode/valaccodeincludedirective.vala +++ /dev/null @@ -1,59 +0,0 @@ -/* valaccodeincludedirective.vala - * - * Copyright (C) 2006 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents an include preprocessor directive in the C code. - */ -public class Vala.CCodeIncludeDirective : CCodeNode { - /** - * The file to be included. - */ - public string filename { get; set; } - - /** - * Specifies whether the specified file should be searched in the local - * directory. - */ - public bool local { get; set; } - - public CCodeIncludeDirective (string _filename, bool _local = false) { - filename = _filename; - local = _local; - } - - public override void write (CCodeWriter writer) { - writer.write_indent (); - writer.write_string ("#include "); - if (local) { - writer.write_string ("\""); - writer.write_string (filename); - writer.write_string ("\""); - } else { - writer.write_string ("<"); - writer.write_string (filename); - writer.write_string (">"); - } - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodeinitializerlist.vala b/src/ccode/valaccodeinitializerlist.vala deleted file mode 100644 index 2be3a846a..000000000 --- a/src/ccode/valaccodeinitializerlist.vala +++ /dev/null @@ -1,58 +0,0 @@ -/* valaccodeinitializerlist.vala - * - * Copyright (C) 2006-2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a struct or array initializer list in the C code. - */ -public class Vala.CCodeInitializerList : CCodeExpression { - private List initializers = new ArrayList (); - - /** - * Appends the specified expression to this initializer list. - * - * @param expr an expression - */ - public void append (CCodeExpression expr) { - initializers.add (expr); - } - - public override void write (CCodeWriter writer) { - writer.write_string ("{"); - - bool first = true; - foreach (CCodeExpression expr in initializers) { - if (!first) { - writer.write_string (", "); - } else { - first = false; - } - - if (expr != null) { - expr.write (writer); - } - } - - writer.write_string ("}"); - } -} diff --git a/src/ccode/valaccodeinvalidexpression.vala b/src/ccode/valaccodeinvalidexpression.vala deleted file mode 100644 index cf01e31b3..000000000 --- a/src/ccode/valaccodeinvalidexpression.vala +++ /dev/null @@ -1,33 +0,0 @@ -/* valaccodeinvalidexpression.vala - * - * Copyright (C) 2009 Jürg Billeter - * - * 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.1 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 - */ - -/** - * Represents an invalid expression. - */ -public class Vala.CCodeInvalidExpression : CCodeExpression { - public CCodeInvalidExpression () { - } - - public override void write (CCodeWriter writer) { - assert_not_reached (); - } -} diff --git a/src/ccode/valaccodelabel.vala b/src/ccode/valaccodelabel.vala deleted file mode 100644 index c0a85788f..000000000 --- a/src/ccode/valaccodelabel.vala +++ /dev/null @@ -1,44 +0,0 @@ -/* valaccodelabel.vala - * - * Copyright (C) 2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a label declaration in the C code. - */ -public class Vala.CCodeLabel : CCodeStatement { - /** - * The name of this label. - */ - public string name { get; set; } - - public CCodeLabel (string name) { - this.name = name; - } - - public override void write (CCodeWriter writer) { - writer.write_indent (); - writer.write_string (name); - writer.write_string (":"); - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodelinedirective.vala b/src/ccode/valaccodelinedirective.vala deleted file mode 100644 index c5e61114b..000000000 --- a/src/ccode/valaccodelinedirective.vala +++ /dev/null @@ -1,51 +0,0 @@ -/* valaccodelinedirective.vala - * - * Copyright (C) 2006 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a line directive in the C code. - */ -public class Vala.CCodeLineDirective : CCodeNode { - /** - * The name of the source file to be presumed. - */ - public string filename { get; set; } - - /** - * The line number in the source file to be presumed. - */ - public int line_number { get; set; } - - public CCodeLineDirective (string _filename, int _line) { - filename = _filename; - line_number = _line; - } - - public override void write (CCodeWriter writer) { - if (!writer.bol) { - writer.write_newline (); - } - writer.write_string ("#line %d \"%s\"".printf (line_number, filename)); - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodemacroreplacement.vala b/src/ccode/valaccodemacroreplacement.vala deleted file mode 100644 index c295eedf9..000000000 --- a/src/ccode/valaccodemacroreplacement.vala +++ /dev/null @@ -1,36 +0,0 @@ -/* valaccodemacroreplacement.vala - * - * Copyright (C) 2006-2009 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a preprocessor macro replacement definition in the C code. - */ -public class Vala.CCodeMacroReplacement : CCodeDefine { - public CCodeMacroReplacement (string name, string replacement) { - base (name, replacement); - } - - public CCodeMacroReplacement.with_expression (string name, CCodeExpression replacement_expression) { - base.with_expression (name, replacement_expression); - } -} diff --git a/src/ccode/valaccodememberaccess.vala b/src/ccode/valaccodememberaccess.vala deleted file mode 100644 index 2ed1fe9f9..000000000 --- a/src/ccode/valaccodememberaccess.vala +++ /dev/null @@ -1,65 +0,0 @@ -/* valaccodememberaccess.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents an access to a struct member in the C code. - */ -public class Vala.CCodeMemberAccess : CCodeExpression { - /** - * The parent of the member. - */ - public CCodeExpression inner { get; set; } - - /** - * The name of the member. - */ - public string member_name { get; set; } - - /** - * Specifies whether the member access happens by pointer dereferencing. - */ - public bool is_pointer { get; set; } - - public CCodeMemberAccess (CCodeExpression container, string member, bool pointer = false) { - inner = container; - member_name = member; - is_pointer = pointer; - } - - public CCodeMemberAccess.pointer (CCodeExpression container, string member) { - inner = container; - member_name = member; - is_pointer = true; - } - - public override void write (CCodeWriter writer) { - inner.write_inner (writer); - if (is_pointer) { - writer.write_string ("->"); - } else { - writer.write_string ("."); - } - writer.write_string (member_name); - } -} diff --git a/src/ccode/valaccodemodifiers.vala b/src/ccode/valaccodemodifiers.vala deleted file mode 100644 index 6a8b09b1b..000000000 --- a/src/ccode/valaccodemodifiers.vala +++ /dev/null @@ -1,46 +0,0 @@ -/* valaccodemodifiers.vala - * - * Copyright (C) 2006-2010 Jürg Billeter - * Copyright (C) 2006-2008 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.1 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 - * Raffaele Sandrini - */ - -using GLib; - -[Flags] -public enum Vala.CCodeModifiers { - NONE = 0, - STATIC, - REGISTER, - EXTERN, - INLINE, - VOLATILE, - DEPRECATED, - THREAD_LOCAL, - INTERNAL, - CONST, - UNUSED, - CONSTRUCTOR, - DESTRUCTOR, - FORMAT_ARG, - PRINTF, - SCANF, - NO_INLINE -} diff --git a/src/ccode/valaccodenewline.vala b/src/ccode/valaccodenewline.vala deleted file mode 100644 index 937f04612..000000000 --- a/src/ccode/valaccodenewline.vala +++ /dev/null @@ -1,32 +0,0 @@ -/* valaccodenewline.vala - * - * Copyright (C) 2006 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a line break in the C code. - */ -public class Vala.CCodeNewline : CCodeNode { - public override void write (CCodeWriter writer) { - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodenode.vala b/src/ccode/valaccodenode.vala deleted file mode 100644 index d8c3e5cdf..000000000 --- a/src/ccode/valaccodenode.vala +++ /dev/null @@ -1,68 +0,0 @@ -/* valaccodenode.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a node in the C code tree. - */ -public abstract class Vala.CCodeNode { - /** - * The source file name and line number to be presumed for this code - * node. - */ - public CCodeLineDirective line { get; set; } - - /** - * The modifiers for this code node which will be handled as needed - * in every subclass. - */ - public CCodeModifiers modifiers { get; set; } - - /** - * Writes this code node and all children with the specified C code - * writer. - * - * @param writer a C code writer - */ - public abstract void write (CCodeWriter writer); - - /** - * Writes declaration for this code node with the specified C code - * writer if necessary. - * - * @param writer a C code writer - */ - public virtual void write_declaration (CCodeWriter writer) { - } - - /** - * Writes declaration and implementation combined for this code node and - * all children with the specified C code writer. - * - * @param writer a C code writer - */ - public virtual void write_combined (CCodeWriter writer) { - write_declaration (writer); - write (writer); - } -} diff --git a/src/ccode/valaccodeoncesection.vala b/src/ccode/valaccodeoncesection.vala deleted file mode 100644 index 30b9a369e..000000000 --- a/src/ccode/valaccodeoncesection.vala +++ /dev/null @@ -1,56 +0,0 @@ -/* valaccodeoncesection.vala - * - * Copyright (C) 2006-2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a section that should only to processed once. - */ -public class Vala.CCodeOnceSection : CCodeFragment { - /** - * The name of the guarding define. - */ - public string define { get; set; } - - public CCodeOnceSection (string def) { - define = def; - } - - public override void write (CCodeWriter writer) { - writer.write_indent (); - writer.write_string ("#ifndef "); - writer.write_string (define); - writer.write_newline (); - writer.write_string ("#define "); - writer.write_string (define); - writer.write_newline (); - foreach (CCodeNode node in get_children ()) { - node.write_combined (writer); - } - writer.write_indent (); - writer.write_string ("#endif"); - writer.write_newline (); - } - - public override void write_declaration (CCodeWriter writer) { - } -} diff --git a/src/ccode/valaccodeparameter.vala b/src/ccode/valaccodeparameter.vala deleted file mode 100644 index 8e90695a7..000000000 --- a/src/ccode/valaccodeparameter.vala +++ /dev/null @@ -1,75 +0,0 @@ -/* valaccodeparameter.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a formal parameter in a C method signature. - */ -public class Vala.CCodeParameter : CCodeNode { - /** - * The parameter name. - */ - public string name { get; set; } - - /** - * The parameter type. - */ - public string type_name { get; set; } - - /** - * Specifies whether the function accepts an indefinite number of - * arguments. - */ - public bool ellipsis { get; set; } - - CCodeDeclarator? declarator; - - public CCodeParameter (string n, string type) { - name = n; - type_name = type; - } - - public CCodeParameter.with_ellipsis () { - ellipsis = true; - } - - public CCodeParameter.with_declarator (string type, CCodeDeclarator decl) { - name = decl.name; - type_name = type; - declarator = decl; - } - - public override void write (CCodeWriter writer) { - if (!ellipsis) { - writer.write_string (type_name); - writer.write_string (" "); - if (declarator != null) { - declarator.write (writer); - } else { - writer.write_string (name); - } - } else { - writer.write_string ("..."); - } - } -} diff --git a/src/ccode/valaccodeparenthesizedexpression.vala b/src/ccode/valaccodeparenthesizedexpression.vala deleted file mode 100644 index 08b0807b6..000000000 --- a/src/ccode/valaccodeparenthesizedexpression.vala +++ /dev/null @@ -1,45 +0,0 @@ -/* valaccodeparenthesizedexpression.vala - * - * Copyright (C) 2006 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a parenthesized expression in the C code. - */ -public class Vala.CCodeParenthesizedExpression : CCodeExpression { - /** - * The expression in the parenthesis. - */ - public CCodeExpression inner { get; set; } - - public CCodeParenthesizedExpression (CCodeExpression expr) { - inner = expr; - } - - public override void write (CCodeWriter writer) { - writer.write_string ("("); - - inner.write (writer); - - writer.write_string (")"); - } -} diff --git a/src/ccode/valaccodereturnstatement.vala b/src/ccode/valaccodereturnstatement.vala deleted file mode 100644 index 50be0ac7f..000000000 --- a/src/ccode/valaccodereturnstatement.vala +++ /dev/null @@ -1,50 +0,0 @@ -/* valaccodereturnstatement.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a return statement in the C code. - */ -public class Vala.CCodeReturnStatement : CCodeStatement { - /** - * The optional expression to return. - */ - public CCodeExpression? return_expression { get; set; } - - public CCodeReturnStatement (CCodeExpression? expr = null) { - return_expression = expr; - } - - public override void write (CCodeWriter writer) { - writer.write_indent (line); - writer.write_string ("return"); - - if (return_expression != null) { - writer.write_string (" "); - return_expression.write (writer); - } - - writer.write_string (";"); - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodestatement.vala b/src/ccode/valaccodestatement.vala deleted file mode 100644 index 693d7efd4..000000000 --- a/src/ccode/valaccodestatement.vala +++ /dev/null @@ -1,29 +0,0 @@ -/* valaccodestatement.vala - * - * Copyright (C) 2006 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a statement in the C code. - */ -public abstract class Vala.CCodeStatement : CCodeNode { -} diff --git a/src/ccode/valaccodestruct.vala b/src/ccode/valaccodestruct.vala deleted file mode 100644 index 9630a37c4..000000000 --- a/src/ccode/valaccodestruct.vala +++ /dev/null @@ -1,80 +0,0 @@ -/* valaccodestruct.vala - * - * Copyright (C) 2006-2010 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a struct declaration in the C code. - */ -public class Vala.CCodeStruct : CCodeNode { - /** - * The struct name. - */ - public string name { get; set; } - - public bool is_empty { get { return declarations.size == 0; } } - - private List declarations = new ArrayList (); - - public CCodeStruct (string name) { - this.name = name; - } - - /** - * Adds the specified declaration as member to this struct. - * - * @param decl a variable declaration - */ - public void add_declaration (CCodeDeclaration decl) { - declarations.add (decl); - } - - /** - * Adds a variable with the specified type and name to this struct. - * - * @param type_name field type - * @param name member name - */ - public void add_field (string type_name, string name, CCodeModifiers modifiers = 0, CCodeDeclaratorSuffix? declarator_suffix = null) { - var decl = new CCodeDeclaration (type_name); - decl.add_declarator (new CCodeVariableDeclarator (name, null, declarator_suffix)); - decl.modifiers = modifiers; - add_declaration (decl); - } - - public override void write (CCodeWriter writer) { - writer.write_string ("struct "); - writer.write_string (name); - writer.write_begin_block (); - foreach (CCodeDeclaration decl in declarations) { - decl.write_declaration (writer); - } - - writer.write_end_block (); - if (CCodeModifiers.DEPRECATED in modifiers) { - writer.write_string (GNUC_DEPRECATED); - } - writer.write_string (";"); - writer.write_newline (); - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodeswitchstatement.vala b/src/ccode/valaccodeswitchstatement.vala deleted file mode 100644 index ba6534211..000000000 --- a/src/ccode/valaccodeswitchstatement.vala +++ /dev/null @@ -1,46 +0,0 @@ -/* valaccodeswitchstatement.vala - * - * Copyright (C) 2006-2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a switch selection statement in the C code. - */ -public class Vala.CCodeSwitchStatement : CCodeBlock { - /** - * The switch expression. - */ - public CCodeExpression expression { get; set; } - - public CCodeSwitchStatement (CCodeExpression expression) { - this.expression = expression; - } - - public override void write (CCodeWriter writer) { - writer.write_indent (line); - writer.write_string ("switch ("); - expression.write (writer); - writer.write_string (")"); - - base.write (writer); - } -} diff --git a/src/ccode/valaccodetypedefinition.vala b/src/ccode/valaccodetypedefinition.vala deleted file mode 100644 index 39f014a9c..000000000 --- a/src/ccode/valaccodetypedefinition.vala +++ /dev/null @@ -1,64 +0,0 @@ -/* valaccodetypedefinition.vala - * - * Copyright (C) 2006-2007 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a typedef in the C code. - */ -public class Vala.CCodeTypeDefinition : CCodeNode { - /** - * The type name. - */ - public string type_name { get; set; } - - /** - * The type declarator. - */ - public CCodeDeclarator declarator { get; set; } - - public CCodeTypeDefinition (string type, CCodeDeclarator decl) { - type_name = type; - declarator = decl; - } - - public override void write (CCodeWriter writer) { - } - - public override void write_declaration (CCodeWriter writer) { - writer.write_indent (); - writer.write_string ("typedef "); - - writer.write_string (type_name); - - writer.write_string (" "); - - declarator.write_declaration (writer); - - if (CCodeModifiers.DEPRECATED in modifiers) { - writer.write_string (GNUC_DEPRECATED); - } - - writer.write_string (";"); - writer.write_newline (); - } -} diff --git a/src/ccode/valaccodeunaryexpression.vala b/src/ccode/valaccodeunaryexpression.vala deleted file mode 100644 index fb318815f..000000000 --- a/src/ccode/valaccodeunaryexpression.vala +++ /dev/null @@ -1,96 +0,0 @@ -/* valaccodeunaryexpression.vala - * - * Copyright (C) 2006-2009 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents an expression with one operand in the C code. - */ -public class Vala.CCodeUnaryExpression : CCodeExpression { - /** - * The unary operator. - */ - public CCodeUnaryOperator operator { get; set; } - - /** - * The operand. - */ - public CCodeExpression inner { get; set; } - - public CCodeUnaryExpression (CCodeUnaryOperator op, CCodeExpression expr) { - operator = op; - inner = expr; - } - - public override void write (CCodeWriter writer) { - switch (operator) { - case CCodeUnaryOperator.PLUS: writer.write_string ("+"); inner.write_inner (writer); break; - case CCodeUnaryOperator.MINUS: writer.write_string ("-"); inner.write_inner (writer); break; - case CCodeUnaryOperator.LOGICAL_NEGATION: writer.write_string ("!"); inner.write_inner (writer); break; - case CCodeUnaryOperator.BITWISE_COMPLEMENT: writer.write_string ("~"); inner.write_inner (writer); break; - case CCodeUnaryOperator.POINTER_INDIRECTION: - var inner_unary = inner as CCodeUnaryExpression; - if (inner_unary != null && inner_unary.operator == CCodeUnaryOperator.ADDRESS_OF) { - // simplify expression - inner_unary.inner.write (writer); - return; - } - writer.write_string ("*"); - inner.write_inner (writer); - break; - case CCodeUnaryOperator.ADDRESS_OF: - var inner_unary = inner as CCodeUnaryExpression; - if (inner_unary != null && inner_unary.operator == CCodeUnaryOperator.POINTER_INDIRECTION) { - // simplify expression - inner_unary.inner.write (writer); - return; - } - writer.write_string ("&"); - inner.write_inner (writer); - break; - case CCodeUnaryOperator.PREFIX_INCREMENT: writer.write_string ("++"); inner.write_inner (writer); break; - case CCodeUnaryOperator.PREFIX_DECREMENT: writer.write_string ("--"); inner.write_inner (writer); break; - case CCodeUnaryOperator.POSTFIX_INCREMENT: inner.write_inner (writer); writer.write_string ("++"); break; - case CCodeUnaryOperator.POSTFIX_DECREMENT: inner.write_inner (writer); writer.write_string ("--"); break; - default: assert_not_reached (); - } - } - - public override void write_inner (CCodeWriter writer) { - writer.write_string ("("); - this.write (writer); - writer.write_string (")"); - } -} - -public enum Vala.CCodeUnaryOperator { - PLUS, - MINUS, - LOGICAL_NEGATION, - BITWISE_COMPLEMENT, - POINTER_INDIRECTION, - ADDRESS_OF, - PREFIX_INCREMENT, - PREFIX_DECREMENT, - POSTFIX_INCREMENT, - POSTFIX_DECREMENT -} diff --git a/src/ccode/valaccodevariabledeclarator.vala b/src/ccode/valaccodevariabledeclarator.vala deleted file mode 100644 index f5d2302cf..000000000 --- a/src/ccode/valaccodevariabledeclarator.vala +++ /dev/null @@ -1,128 +0,0 @@ -/* valaccodevariabledeclarator.vala - * - * Copyright (C) 2006-2009 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a variable declarator in the C code. - */ -public class Vala.CCodeVariableDeclarator : CCodeDeclarator { - /** - * The optional initializer expression. - */ - public CCodeExpression? initializer { get; set; } - - /** - * The optional declarator suffix. - */ - public CCodeDeclaratorSuffix? declarator_suffix { get; set; } - - /** - * Initializer only used to zero memory, safe to initialize as part - * of declaration at beginning of block instead of separate assignment. - */ - public bool init0 { get; set; } - - public CCodeVariableDeclarator (string name, CCodeExpression? initializer = null, CCodeDeclaratorSuffix? declarator_suffix = null) { - this.name = name; - this.initializer = initializer; - this.declarator_suffix = declarator_suffix; - } - - public CCodeVariableDeclarator.zero (string name, CCodeExpression? initializer, CCodeDeclaratorSuffix? declarator_suffix = null) { - this.name = name; - this.initializer = initializer; - this.declarator_suffix = declarator_suffix; - this.init0 = true; - } - - public override void write (CCodeWriter writer) { - writer.write_string (name); - - if (declarator_suffix != null) { - declarator_suffix.write (writer); - } - - if (initializer != null) { - writer.write_string (" = "); - initializer.write (writer); - } - } - - public override void write_declaration (CCodeWriter writer) { - writer.write_string (name); - - if (declarator_suffix != null) { - declarator_suffix.write (writer); - } - - if (initializer != null && init0) { - writer.write_string (" = "); - initializer.write (writer); - } - } - - public override void write_initialization (CCodeWriter writer) { - if (initializer != null && !init0) { - writer.write_indent (line); - - writer.write_string (name); - writer.write_string (" = "); - initializer.write (writer); - - writer.write_string (";"); - writer.write_newline (); - } - } -} - -public class Vala.CCodeDeclaratorSuffix { - bool array; - List? array_length; - - public CCodeDeclaratorSuffix.with_array (CCodeExpression? array_length = null) { - if (array_length != null) { - this.array_length = new ArrayList (); - this.array_length.add (array_length); - } - array = true; - } - - public CCodeDeclaratorSuffix.with_multi_array (List? array_length = null) { - this.array_length = array_length; - array = true; - } - - public void write (CCodeWriter writer) { - if (array_length != null && array_length.size > 0) { - foreach (var length in array_length) { - writer.write_string ("["); - if (length != null) { - length.write (writer); - } - writer.write_string ("]"); - } - } else if (array) { - writer.write_string ("[]"); - } - } -} diff --git a/src/ccode/valaccodewhilestatement.vala b/src/ccode/valaccodewhilestatement.vala deleted file mode 100644 index 836806e01..000000000 --- a/src/ccode/valaccodewhilestatement.vala +++ /dev/null @@ -1,54 +0,0 @@ -/* valaccodewhilestatement.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a while iteration statement in the C code. - */ -public class Vala.CCodeWhileStatement : CCodeStatement { - /** - * The loop condition. - */ - public CCodeExpression condition { get; set; } - - /** - * The loop body. - */ - public CCodeStatement body { get; set; } - - public CCodeWhileStatement (CCodeExpression cond, CCodeStatement? stmt = null) { - condition = cond; - body = stmt; - } - - public override void write (CCodeWriter writer) { - writer.write_indent (line); - writer.write_string ("while ("); - - condition.write (writer); - - writer.write_string (")"); - - body.write (writer); - } -} diff --git a/src/ccode/valaccodewriter.vala b/src/ccode/valaccodewriter.vala deleted file mode 100644 index 21cc41720..000000000 --- a/src/ccode/valaccodewriter.vala +++ /dev/null @@ -1,274 +0,0 @@ -/* valaccodewriter.vala - * - * Copyright (C) 2006-2009 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Represents a writer to write C source files. - */ -public class Vala.CCodeWriter { - /** - * Specifies the file to be written. - */ - public string filename { get; set; } - - /** - * Specifies the source file used to generate this one. - */ - private string source_filename; - - /** - * Specifies whether to emit line directives. - */ - public bool line_directives { get; set; } - - /** - * Specifies whether the output stream is at the beginning of a line. - */ - public bool bol { - get { return _bol; } - } - - static GLib.Regex fix_indent_regex; - - private string temp_filename; - private bool file_exists; - - private FileStream? stream; - - private int indent; - private int current_line_number = 1; - private bool using_line_directive; - - /* at begin of line */ - private bool _bol = true; - /* at begin after empty line */ - private bool _bael = false; - - public CCodeWriter (string filename, string? source_filename = null) { - this.filename = filename; - this.source_filename = source_filename; - } - - /** - * Opens the file. - * - * @return true if the file has been opened successfully, - * false otherwise - */ - public bool open (bool write_version) { - file_exists = FileUtils.test (filename, FileTest.EXISTS); - if (file_exists) { - temp_filename = "%s.valatmp".printf (filename); - stream = FileStream.open (temp_filename, "w"); - } else { - /* - * File doesn't exist. In case of a particular destination (-d flag), - * check and create the directory structure. - */ - var dirname = Path.get_dirname (filename); - DirUtils.create_with_parents (dirname, 0755); - stream = FileStream.open (filename, "w"); - } - - if (stream == null) { - return false; - } - - var opening = write_version ? - "/* %s generated by valac %s, the Vala compiler".printf (Path.get_basename (filename), Vala.BUILD_VERSION) : - "/* %s generated by valac, the Vala compiler".printf (Path.get_basename (filename)); - write_string (opening); - - // Write the file name if known - if (source_filename != null) { - write_newline (); - write_string (" * generated from %s".printf (Path.get_basename (source_filename))); - } - - write_string (", do not modify */"); - write_newline (); - write_newline (); - - return true; - } - - /** - * Closes the file. - */ - public void close () { - stream = null; - - if (file_exists) { - var changed = true; - - try { - var old_file = new MappedFile (filename, false); - var new_file = new MappedFile (temp_filename, false); - var len = old_file.get_length (); - if (len == new_file.get_length ()) { - if (Memory.cmp (old_file.get_contents (), new_file.get_contents (), len) == 0) { - changed = false; - } - } - old_file = null; - new_file = null; - } catch (FileError e) { - // assume changed if mmap comparison doesn't work - } - - if (changed) { - FileUtils.rename (temp_filename, filename); - } else { - FileUtils.unlink (temp_filename); - if (source_filename != null) { - var stats = Stat (source_filename); - var target_stats = Stat (filename); - if (stats.st_mtime >= target_stats.st_mtime) { - UTimBuf timebuf = { stats.st_atime + 1, stats.st_mtime + 1 }; - FileUtils.utime (filename, timebuf); - } - } - } - } - } - - /** - * Writes tabs according to the current indent level. - */ - public void write_indent (CCodeLineDirective? line = null) { - if (line_directives) { - if (line != null) { - line.write (this); - using_line_directive = true; - } else if (using_line_directive) { - // no corresponding Vala line, emit line directive for C line - write_string ("#line %d \"%s\"".printf (current_line_number + 1, Path.get_basename (filename))); - write_newline (); - using_line_directive = false; - } - } - - if (!_bol) { - write_newline (); - } - - stream.puts (string.nfill (indent, '\t')); - _bol = false; - } - - /** - * Writes n spaces. - */ - public void write_nspaces (uint n) { - stream.puts (string.nfill (n, ' ')); - } - - /** - * Writes the specified string. - * - * @param s a string - */ - public void write_string (string s) { - stream.puts (s); - _bol = false; - } - - /** - * Writes a newline. - */ - public void write_newline () { - if (!_bol) { - _bael = false; - } else if (!_bael) { - _bael = true; - } else { - return; - } - stream.putc ('\n'); - current_line_number++; - _bol = true; - } - - /** - * Opens a new block, increasing the indent level. - */ - public void write_begin_block () { - if (!_bol) { - stream.putc (' '); - } else { - write_indent (); - } - stream.putc ('{'); - write_newline (); - indent++; - } - - /** - * Closes the current block, decreasing the indent level. - */ - public void write_end_block () { - assert (indent > 0); - - indent--; - write_indent (); - stream.putc ('}'); - } - - /** - * Writes the specified text as comment. - * - * @param text the comment text - */ - public void write_comment (string text) { - try { - write_indent (); - stream.puts ("/*"); - bool first = true; - - // discard tabs at beginning of line - if (fix_indent_regex == null) - fix_indent_regex = new GLib.Regex ("^\t+");; - - foreach (unowned string line in text.split ("\n")) { - if (!first) { - write_indent (); - } else { - first = false; - } - - var lineparts = fix_indent_regex.replace_literal (line, -1, 0, "").split ("*/"); - - for (int i = 0; lineparts[i] != null; i++) { - stream.puts (lineparts[i]); - if (lineparts[i+1] != null) { - stream.puts ("* /"); - } - } - } - stream.puts ("*/"); - write_newline (); - } catch (RegexError e) { - // ignore - } - } -} diff --git a/src/codegen/valaccode.vala b/src/codegen/valaccode.vala deleted file mode 100644 index 9b1da33f7..000000000 --- a/src/codegen/valaccode.vala +++ /dev/null @@ -1,471 +0,0 @@ -/* valaccode.vala - * - * Copyright (C) 2017 Rico Tzschichholz - * - * 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.1 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: - * Rico Tzschichholz - */ - -namespace Vala { - static int? ccode_attribute_cache_index = null; - - static unowned CCodeAttribute get_ccode_attribute (CodeNode node) { - if (ccode_attribute_cache_index == null) { - ccode_attribute_cache_index = CodeNode.get_attribute_cache_index (); - } - - unowned AttributeCache? attr = node.get_attribute_cache (ccode_attribute_cache_index); - if (attr == null) { - var new_attr = new CCodeAttribute (node); - node.set_attribute_cache (ccode_attribute_cache_index, new_attr); - attr = new_attr; - } - return (CCodeAttribute) attr; - } - - public static string get_ccode_name (CodeNode node) { - return get_ccode_attribute(node).name; - } - - public static string get_ccode_const_name (CodeNode node) { - return get_ccode_attribute(node).const_name; - } - - public static string get_ccode_type_name (ObjectTypeSymbol sym) { - return get_ccode_attribute (sym).type_name; - } - - public static string get_ccode_type_cast_function (ObjectTypeSymbol sym) { - assert (!(sym is Class && ((Class) sym).is_compact)); - return get_ccode_upper_case_name (sym); - } - - public static string get_ccode_type_get_function (ObjectTypeSymbol sym) { - var func_name = sym.get_attribute_string ("CCode", "type_get_function"); - if (func_name != null) { - return func_name; - } - if (sym is Class) { - assert (!((Class) sym).is_compact); - return "%s_GET_CLASS".printf (get_ccode_upper_case_name (sym)); - } else if (sym is Interface) { - return "%s_GET_INTERFACE".printf (get_ccode_upper_case_name (sym)); - } else { - Report.error (sym.source_reference, "`CCode.type_get_function' not supported"); - return ""; - } - } - - public static string get_ccode_class_get_private_function (Class cl) { - assert (!cl.is_compact); - return "%s_GET_CLASS_PRIVATE".printf (get_ccode_upper_case_name (cl)); - } - - public static string get_ccode_class_type_function (Class cl) { - assert (!cl.is_compact); - return "%s_CLASS".printf (get_ccode_upper_case_name (cl)); - } - - public static string get_ccode_lower_case_name (CodeNode node, string? infix = null) { - unowned Symbol? sym = node as Symbol; - if (sym != null) { - if (infix == null) { - infix = ""; - } - if (sym is Delegate) { - return "%s%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), infix, Symbol.camel_case_to_lower_case (sym.name)); - } else if (sym is Signal) { - return get_ccode_attribute (sym).name.replace ("-", "_"); - } else if (sym is ErrorCode) { - return get_ccode_name (sym).ascii_down (); - } else { - return "%s%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), infix, get_ccode_lower_case_suffix (sym)); - } - } else if (node is ErrorType) { - unowned ErrorType type = (ErrorType) node; - if (type.error_domain == null) { - if (infix == null) { - return "g_error"; - } else { - return "g_%s_error".printf (infix); - } - } else if (type.error_code == null) { - return get_ccode_lower_case_name (type.error_domain, infix); - } else { - return get_ccode_lower_case_name (type.error_code, infix); - } - } else if (node is DelegateType) { - unowned DelegateType type = (DelegateType) node; - return get_ccode_lower_case_name (type.delegate_symbol, infix); - } else if (node is PointerType) { - unowned PointerType type = (PointerType) node; - return get_ccode_lower_case_name (type.base_type, infix); - } else if (node is GenericType) { - return "valageneric"; - } else if (node is VoidType) { - return "valavoid"; - } else { - unowned DataType type = (DataType) node; - return get_ccode_lower_case_name (type.type_symbol, infix); - } - } - - public static string get_ccode_upper_case_name (Symbol sym, string? infix = null) { - if (sym is Property) { - return "%s_%s".printf (get_ccode_lower_case_name (sym.parent_symbol), Symbol.camel_case_to_lower_case (sym.name)).ascii_up (); - } else { - return get_ccode_lower_case_name (sym, infix).ascii_up (); - } - } - - public static string get_ccode_header_filenames (Symbol sym) { - return get_ccode_attribute(sym).header_filenames; - } - - public static string get_ccode_feature_test_macros (Symbol sym) { - return get_ccode_attribute(sym).feature_test_macros; - } - - public static string get_ccode_prefix (Symbol sym) { - return get_ccode_attribute(sym).prefix; - } - - public static string get_ccode_lower_case_prefix (Symbol sym) { - return get_ccode_attribute(sym).lower_case_prefix; - } - - public static string get_ccode_lower_case_suffix (Symbol sym) { - return get_ccode_attribute(sym).lower_case_suffix; - } - - public static string get_ccode_ref_function (TypeSymbol sym) { - return get_ccode_attribute(sym).ref_function; - } - - public static string get_ccode_quark_name (ErrorDomain edomain) { - return "%s-quark".printf (get_ccode_lower_case_name (edomain).replace ("_", "-")); - } - - public static bool is_reference_counting (TypeSymbol sym) { - if (sym is Class) { - return get_ccode_ref_function (sym) != null; - } else if (sym is Interface) { - return true; - } else { - return false; - } - } - - public static bool is_ref_function_void (DataType type) { - unowned Class? cl = type.type_symbol as Class; - if (cl != null) { - return get_ccode_ref_function_void (cl); - } else { - return false; - } - } - - public static bool is_free_function_address_of (DataType type) { - unowned Class? cl = type.type_symbol as Class; - if (cl != null) { - return get_ccode_free_function_address_of (cl); - } else { - return false; - } - } - - public static bool get_ccode_ref_function_void (Class cl) { - return get_ccode_attribute(cl).ref_function_void; - } - - public static bool get_ccode_free_function_address_of (Class cl) { - return get_ccode_attribute(cl).free_function_address_of; - } - - public static string get_ccode_unref_function (ObjectTypeSymbol sym) { - return get_ccode_attribute(sym).unref_function; - } - - public static string get_ccode_ref_sink_function (ObjectTypeSymbol sym) { - return get_ccode_attribute(sym).ref_sink_function; - } - - public static string get_ccode_copy_function (TypeSymbol sym) { - return get_ccode_attribute(sym).copy_function; - } - - public static string get_ccode_destroy_function (TypeSymbol sym) { - return get_ccode_attribute(sym).destroy_function; - } - - public static string? get_ccode_dup_function (TypeSymbol sym) { - if (sym is Struct) { - return get_ccode_attribute (sym).dup_function; - } - return get_ccode_copy_function (sym); - } - - public static string get_ccode_free_function (TypeSymbol sym) { - return get_ccode_attribute(sym).free_function; - } - - public static bool get_ccode_is_gboxed (TypeSymbol sym) { - return get_ccode_free_function (sym) == "g_boxed_free"; - } - - public static bool get_ccode_finish_instance (Method m) { - assert (m.coroutine); - return get_ccode_attribute (m).finish_instance; - } - - public static string get_ccode_type_id (CodeNode node) { - return get_ccode_attribute(node).type_id; - } - - public static string get_ccode_type_function (TypeSymbol sym) { - assert (!((sym is Class && ((Class) sym).is_compact) || sym is ErrorCode || sym is ErrorDomain || sym is Delegate)); - return "%s_get_type".printf (get_ccode_lower_case_name (sym)); - } - - public static string get_ccode_marshaller_type_name (CodeNode node) { - return get_ccode_attribute(node).marshaller_type_name; - } - - public static string get_ccode_get_value_function (CodeNode sym) { - return get_ccode_attribute(sym).get_value_function; - } - - public static string get_ccode_set_value_function (CodeNode sym) { - return get_ccode_attribute(sym).set_value_function; - } - - public static string get_ccode_take_value_function (CodeNode sym) { - return get_ccode_attribute(sym).take_value_function; - } - - public static string get_ccode_param_spec_function (CodeNode sym) { - return get_ccode_attribute(sym).param_spec_function; - } - - public static string get_ccode_type_check_function (TypeSymbol sym) { - unowned Class? cl = sym as Class; - var a = sym.get_attribute_string ("CCode", "type_check_function"); - if (cl != null && a != null) { - return a; - } else if ((cl != null && cl.is_compact) || sym is Struct || sym is Enum || sym is Delegate) { - return ""; - } else { - return get_ccode_upper_case_name (sym, "IS_"); - } - } - - public static string get_ccode_class_type_check_function (Class cl) { - assert (!cl.is_compact); - return "%s_CLASS".printf (get_ccode_type_check_function (cl)); - } - - public static string get_ccode_default_value (TypeSymbol sym) { - return get_ccode_attribute(sym).default_value; - } - - public static string get_ccode_default_value_on_error (TypeSymbol sym) { - return get_ccode_attribute (sym).default_value_on_error; - } - - public static bool get_ccode_has_copy_function (Struct st) { - return st.get_attribute_bool ("CCode", "has_copy_function", true); - } - - public static bool get_ccode_has_destroy_function (Struct st) { - return st.get_attribute_bool ("CCode", "has_destroy_function", true); - } - - public static double get_ccode_instance_pos (CodeNode node) { - if (node is Delegate) { - return node.get_attribute_double ("CCode", "instance_pos", -2); - } else { - return node.get_attribute_double ("CCode", "instance_pos", 0); - } - } - - public static double get_ccode_error_pos (Callable c) { - return c.get_attribute_double ("CCode", "error_pos", -1); - } - - public static bool get_ccode_array_length (CodeNode node) { - return get_ccode_attribute(node).array_length; - } - - public static string get_ccode_array_length_type (CodeNode node) { - if (node is ArrayType) { - return get_ccode_name (((ArrayType) node).length_type); - } else if (node is DataType) { - Report.error (node.source_reference, "`CCode.array_length_type' not supported"); - return ""; - } else { - assert (node is Method || node is Parameter || node is Delegate || node is Property || node is Field); - return get_ccode_attribute(node).array_length_type; - } - } - - public static bool get_ccode_array_null_terminated (CodeNode node) { - return get_ccode_attribute(node).array_null_terminated; - } - - public static string? get_ccode_array_length_name (CodeNode node) { - return get_ccode_attribute(node).array_length_name; - } - - public static string? get_ccode_array_length_expr (CodeNode node) { - return get_ccode_attribute(node).array_length_expr; - } - - public static double get_ccode_array_length_pos (CodeNode node) { - var a = node.get_attribute ("CCode"); - if (a != null && a.has_argument ("array_length_pos")) { - return a.get_double ("array_length_pos"); - } - if (node is Parameter) { - unowned Parameter param = (Parameter) node; - return get_ccode_pos (param) + 0.1; - } else { - return -3; - } - } - - public static double get_ccode_delegate_target_pos (CodeNode node) { - var a = node.get_attribute ("CCode"); - if (a != null && a.has_argument ("delegate_target_pos")) { - return a.get_double ("delegate_target_pos"); - } - if (node is Parameter) { - unowned Parameter param = (Parameter) node; - return get_ccode_pos (param) + 0.1; - } else { - return -3; - } - } - - public static double get_ccode_destroy_notify_pos (CodeNode node) { - var a = node.get_attribute ("CCode"); - if (a != null && a.has_argument ("destroy_notify_pos")) { - return a.get_double ("destroy_notify_pos"); - } - return get_ccode_delegate_target_pos (node) + 0.01; - } - - public static bool get_ccode_delegate_target (CodeNode node) { - return get_ccode_attribute(node).delegate_target; - } - - public static string get_ccode_delegate_target_name (Variable variable) { - return get_ccode_attribute(variable).delegate_target_name; - } - - public static string get_ccode_delegate_target_destroy_notify_name (Variable variable) { - return get_ccode_attribute(variable).delegate_target_destroy_notify_name; - } - - public static double get_ccode_pos (Parameter param) { - return get_ccode_attribute(param).pos; - } - - public static string? get_ccode_type (CodeNode node) { - return get_ccode_attribute(node).ctype; - } - - public static bool get_ccode_simple_generics (Method m) { - return m.get_attribute_bool ("CCode", "simple_generics"); - } - - public static string get_ccode_real_name (Symbol sym) { - return get_ccode_attribute(sym).real_name; - } - - public static string get_ccode_constructv_name (CreationMethod m) { - const string infix = "constructv"; - - unowned Class parent = (Class) m.parent_symbol; - - if (m.name == ".new") { - return "%s%s".printf (get_ccode_lower_case_prefix (parent), infix); - } else { - return "%s%s_%s".printf (get_ccode_lower_case_prefix (parent), infix, m.name); - } - } - - public static string get_ccode_vfunc_name (Method m) { - return get_ccode_attribute(m).vfunc_name; - } - - public static double get_ccode_async_result_pos (Method m) { - assert (m.coroutine); - return m.get_attribute_double ("CCode", "async_result_pos", 0.1); - } - - public static string get_ccode_finish_name (Method m) { - assert (m.coroutine); - return get_ccode_attribute(m).finish_name; - } - - public static string get_ccode_finish_vfunc_name (Method m) { - assert (m.coroutine); - return get_ccode_attribute(m).finish_vfunc_name; - } - - public static string get_ccode_finish_real_name (Method m) { - assert (m.coroutine); - return get_ccode_attribute(m).finish_real_name; - } - - public static bool get_ccode_no_accessor_method (Property p) { - return p.get_attribute ("NoAccessorMethod") != null; - } - - public static bool get_ccode_concrete_accessor (Property p) { - return p.get_attribute ("ConcreteAccessor") != null; - } - - public static bool get_ccode_has_emitter (Signal sig) { - return sig.get_attribute ("HasEmitter") != null; - } - - public static bool get_ccode_has_type_id (TypeSymbol sym) { - return sym.get_attribute_bool ("CCode", "has_type_id", true); - } - - public static bool get_ccode_has_new_function (Method m) { - return m.get_attribute_bool ("CCode", "has_new_function", true); - } - - public static bool get_ccode_has_generic_type_parameter (Method m) { - var a = m.get_attribute ("CCode"); - return a != null && a.has_argument ("generic_type_pos"); - } - - public static double get_ccode_generic_type_pos (Method m) { - return m.get_attribute_double ("CCode", "generic_type_pos"); - } - - public static bool get_ccode_no_wrapper (Method m) { - return m.get_attribute ("NoWrapper") != null; - } - - public static string get_ccode_sentinel (Method m) { - return get_ccode_attribute(m).sentinel; - } -} diff --git a/src/codegen/valaccodearraymodule.vala b/src/codegen/valaccodearraymodule.vala deleted file mode 100644 index 9a84ef848..000000000 --- a/src/codegen/valaccodearraymodule.vala +++ /dev/null @@ -1,962 +0,0 @@ -/* valaccodearraymodule.vala - * - * Copyright (C) 2006-2010 Jürg Billeter - * Copyright (C) 2006-2008 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.1 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 - * Raffaele Sandrini - */ - - -public class Vala.CCodeArrayModule : CCodeMethodCallModule { - int next_array_dup_id = 0; - int next_array_add_id = 0; - - void append_initializer_list (CCodeExpression name_cnode, InitializerList initializer_list, int rank, ref int i) { - foreach (Expression e in initializer_list.get_initializers ()) { - if (rank > 1) { - append_initializer_list (name_cnode, (InitializerList) e, rank - 1, ref i); - } else { - ccode.add_assignment (new CCodeElementAccess (name_cnode, new CCodeConstant (i.to_string ())), get_cvalue (e)); - i++; - } - } - } - - public override void visit_array_creation_expression (ArrayCreationExpression expr) { - var array_type = expr.target_type as ArrayType; - if (array_type != null && array_type.fixed_length) { - // no heap allocation for fixed-length arrays - - var temp_var = get_temp_variable (array_type, true, expr); - temp_var.init = true; - var name_cnode = get_variable_cexpression (temp_var.name); - int i = 0; - - emit_temp_var (temp_var); - - append_initializer_list (name_cnode, expr.initializer_list, expr.rank, ref i); - - set_cvalue (expr, name_cnode); - - return; - } - - CCodeFunctionCall gnew; - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdlib.h"); - gnew = new CCodeFunctionCall (new CCodeIdentifier ("calloc")); - } else { - gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0")); - gnew.add_argument (new CCodeIdentifier (get_ccode_name (expr.element_type))); - } - - bool first = true; - CCodeExpression cexpr = null; - - // iterate over each dimension - foreach (Expression size in expr.get_sizes ()) { - CCodeExpression csize = get_cvalue (size); - append_array_length (expr, csize); - - if (first) { - cexpr = csize; - first = false; - } else { - cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, cexpr, csize); - } - } - - // add extra item to have array NULL-terminated for all reference types - if (expr.element_type.type_symbol != null && expr.element_type.type_symbol.is_reference_type ()) { - cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, cexpr, new CCodeConstant ("1")); - } - - gnew.add_argument (cexpr); - - if (context.profile == Profile.POSIX) { - var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - csizeof.add_argument (new CCodeIdentifier (get_ccode_name (expr.element_type))); - gnew.add_argument (csizeof); - } - - var temp_var = get_temp_variable (expr.value_type, true, expr); - var name_cnode = get_variable_cexpression (temp_var.name); - int i = 0; - - emit_temp_var (temp_var); - - ccode.add_assignment (name_cnode, gnew); - - if (expr.initializer_list != null) { - append_initializer_list (name_cnode, expr.initializer_list, expr.rank, ref i); - } - - set_cvalue (expr, name_cnode); - } - - public override string get_array_length_cname (string array_cname, int dim) { - return "%s_length%d".printf (array_cname, dim); - } - - public override string get_variable_array_length_cname (Variable variable, int dim) { - string? length_cname = get_ccode_array_length_name (variable); - if (length_cname == null) { - length_cname = get_array_length_cname (get_ccode_name (variable), dim); - } - return (!) length_cname; - } - - public override CCodeExpression get_array_length_cexpression (Expression array_expr, int dim = -1) { - return get_array_length_cvalue (array_expr.target_value, dim); - } - - public override CCodeExpression get_array_length_cvalue (TargetValue value, int dim = -1) { - var array_type = value.value_type as ArrayType; - - if (array_type != null && array_type.fixed_length) { - return get_ccodenode (array_type.length); - } - - // dim == -1 => total size over all dimensions - if (dim == -1) { - if (array_type != null && array_type.rank > 1) { - CCodeExpression cexpr = get_array_length_cvalue (value, 1); - for (dim = 2; dim <= array_type.rank; dim++) { - cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, cexpr, get_array_length_cvalue (value, dim)); - } - return cexpr; - } else { - dim = 1; - } - } - - List size = ((GLibValue) value).array_length_cvalues; - if (size == null || size.size < dim) { - Report.error (array_type.source_reference, "internal: invalid array_length for given dimension"); - return new CCodeInvalidExpression (); - } - return size[dim - 1]; - } - - public override string get_array_size_cname (string array_cname) { - return "_%s_size_".printf (array_cname); - } - - public override void visit_element_access (ElementAccess expr) { - List indices = expr.get_indices (); - int rank = indices.size; - - var ccontainer = get_cvalue (expr.container); - var cindex = get_cvalue (indices[0]); - if (expr.container.symbol_reference is ArrayLengthField) { - /* Figure if cindex is a constant expression and calculate dim...*/ - var lit = indices[0] as IntegerLiteral; - var memberaccess = expr.container as MemberAccess; - if (lit != null && memberaccess != null) { - int dim = int.parse (lit.value); - set_cvalue (expr, get_array_length_cexpression (memberaccess.inner, dim + 1)); - } else { - Report.error (expr.source_reference, "internal error: only integer literals supported as index"); - } - } else if (expr.container.symbol_reference is Constant && rank > 1) { - // access to element in a multi-dimensional array constant - var cindices = new ArrayList (); - cindices.add (cindex); - for (int i = 1; i < rank; i++) { - cindices.add (get_cvalue (indices[i])); - } - set_cvalue (expr, new CCodeElementAccess.with_indices (ccontainer, cindices)); - } else { - // access to element in an array - for (int i = 1; i < rank; i++) { - var cmul = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, cindex, get_array_length_cexpression (expr.container, i + 1)); - cindex = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, cmul, get_cvalue (indices[i])); - if (expr.container.is_constant ()) { - ccontainer = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, ccontainer); - } - } - set_cvalue (expr, new CCodeElementAccess (ccontainer, cindex)); - } - - expr.target_value.value_type = expr.value_type.copy (); - if (!expr.lvalue) { - expr.target_value = store_temp_value (expr.target_value, expr); - } - ((GLibValue) expr.target_value).lvalue = true; - } - - public override void visit_slice_expression (SliceExpression expr) { - var ccontainer = get_cvalue (expr.container); - var cstart = get_cvalue (expr.start); - var cstop = get_cvalue (expr.stop); - - var cstartpointer = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, ccontainer, cstart); - var splicelen = new CCodeBinaryExpression (CCodeBinaryOperator.MINUS, cstop, cstart); - - set_cvalue (expr, cstartpointer); - ((GLibValue) expr.target_value).non_null = get_non_null (expr.container.target_value); - // Make sure no previous length values are preserved - set_array_length (expr, splicelen); - } - - void append_struct_array_free_loop (Struct st) { - var cforinit = new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")); - var cforcond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("array_length")); - var cforiter = new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("i"), new CCodeConstant ("1"))); - ccode.open_for (cforinit, cforcond, cforiter); - - var cptrarray = new CCodeIdentifier ("array"); - var cea = new CCodeElementAccess (cptrarray, new CCodeIdentifier ("i")); - - var cfreecall = new CCodeFunctionCall (get_destroy_func_expression (new StructValueType (st))); - cfreecall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cea)); - ccode.add_expression (cfreecall); - - ccode.close (); - } - - public override string? append_struct_array_free (Struct st) { - string cname = "_vala_%s_array_free".printf (get_ccode_name (st)); - - if (cfile.add_declaration (cname)) { - return cname; - } - - generate_type_declaration (ssize_t_type, cfile); - - var fun = new CCodeFunction (cname, "void"); - fun.modifiers = CCodeModifiers.STATIC; - fun.add_parameter (new CCodeParameter ("array", "%s *".printf (get_ccode_name (st)))); - fun.add_parameter (new CCodeParameter ("array_length", get_ccode_name (ssize_t_type))); - - push_function (fun); - - var ccondarr = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("array"), new CCodeConstant ("NULL")); - ccode.open_if (ccondarr); - - ccode.add_declaration (get_ccode_name (ssize_t_type), new CCodeVariableDeclarator ("i")); - append_struct_array_free_loop (st); - - ccode.close (); - - CCodeFunctionCall carrfree; - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdlib.h"); - carrfree = new CCodeFunctionCall (new CCodeIdentifier ("free")); - } else { - carrfree = new CCodeFunctionCall (new CCodeIdentifier ("g_free")); - } - carrfree.add_argument (new CCodeIdentifier ("array")); - ccode.add_expression (carrfree); - - pop_function (); - - cfile.add_function_declaration (fun); - cfile.add_function (fun); - - return cname; - } - - public override string? append_struct_array_destroy (Struct st) { - string cname = "_vala_%s_array_destroy".printf (get_ccode_name (st)); - - if (cfile.add_declaration (cname)) { - return cname; - } - - generate_type_declaration (ssize_t_type, cfile); - - var fun = new CCodeFunction (cname, "void"); - fun.modifiers = CCodeModifiers.STATIC; - fun.add_parameter (new CCodeParameter ("array", "%s *".printf (get_ccode_name (st)))); - fun.add_parameter (new CCodeParameter ("array_length", get_ccode_name (ssize_t_type))); - - push_function (fun); - - var ccondarr = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("array"), new CCodeConstant ("NULL")); - ccode.open_if (ccondarr); - - ccode.add_declaration (get_ccode_name (ssize_t_type), new CCodeVariableDeclarator ("i")); - append_struct_array_free_loop (st); - - ccode.close (); - - pop_function (); - - cfile.add_function_declaration (fun); - cfile.add_function (fun); - - return cname; - } - - void append_vala_array_free_loop () { - var cforinit = new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")); - var cforcond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("array_length")); - var cforiter = new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("i"), new CCodeConstant ("1"))); - ccode.open_for (cforinit, cforcond, cforiter); - - var cptrarray = new CCodeCastExpression (new CCodeIdentifier ("array"), "%s*".printf (get_ccode_name (pointer_type))); - var cea = new CCodeElementAccess (cptrarray, new CCodeIdentifier ("i")); - - var cfreecond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, cea, new CCodeConstant ("NULL")); - ccode.open_if (cfreecond); - - var cfreecall = new CCodeFunctionCall (new CCodeIdentifier ("destroy_func")); - cfreecall.add_argument (cea); - ccode.add_expression (cfreecall); - - ccode.close (); - } - - public override void append_vala_array_free () { - // _vala_array_destroy only frees elements but not the array itself - generate_type_declaration (delegate_target_destroy_type, cfile); - generate_type_declaration (ssize_t_type, cfile); - - var fun = new CCodeFunction ("_vala_array_destroy", "void"); - fun.modifiers = CCodeModifiers.STATIC; - fun.add_parameter (new CCodeParameter ("array", get_ccode_name (pointer_type))); - fun.add_parameter (new CCodeParameter ("array_length", get_ccode_name (ssize_t_type))); - fun.add_parameter (new CCodeParameter ("destroy_func", get_ccode_name (delegate_target_destroy_type))); - - push_function (fun); - - var ccondarr = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("array"), new CCodeConstant ("NULL")); - var ccondfunc = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("destroy_func"), new CCodeConstant ("NULL")); - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccondarr, ccondfunc)); - - ccode.add_declaration (get_ccode_name (ssize_t_type), new CCodeVariableDeclarator ("i")); - append_vala_array_free_loop (); - - ccode.close (); - - pop_function (); - - cfile.add_function_declaration (fun); - cfile.add_function (fun); - - // _vala_array_free frees elements and array - - fun = new CCodeFunction ("_vala_array_free", "void"); - fun.modifiers = CCodeModifiers.STATIC; - fun.add_parameter (new CCodeParameter ("array", get_ccode_name (pointer_type))); - fun.add_parameter (new CCodeParameter ("array_length", get_ccode_name (ssize_t_type))); - fun.add_parameter (new CCodeParameter ("destroy_func", get_ccode_name (delegate_target_destroy_type))); - - push_function (fun); - - // call _vala_array_destroy to free the array elements - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_destroy")); - ccall.add_argument (new CCodeIdentifier ("array")); - ccall.add_argument (new CCodeIdentifier ("array_length")); - ccall.add_argument (new CCodeIdentifier ("destroy_func")); - ccode.add_expression (ccall); - - CCodeFunctionCall carrfree; - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdlib.h"); - carrfree = new CCodeFunctionCall (new CCodeIdentifier ("free")); - } else { - carrfree = new CCodeFunctionCall (new CCodeIdentifier ("g_free")); - } - carrfree.add_argument (new CCodeIdentifier ("array")); - ccode.add_expression (carrfree); - - pop_function (); - - cfile.add_function_declaration (fun); - cfile.add_function (fun); - } - - public override void append_vala_array_move () { - cfile.add_include ("string.h"); - generate_type_declaration (ssize_t_type, cfile); - - // assumes that overwritten array elements are null before invocation - // FIXME will leak memory if that's not the case - var fun = new CCodeFunction ("_vala_array_move", "void"); - fun.modifiers = CCodeModifiers.STATIC; - fun.add_parameter (new CCodeParameter ("array", get_ccode_name (pointer_type))); - fun.add_parameter (new CCodeParameter ("element_size", get_ccode_name (size_t_type))); - fun.add_parameter (new CCodeParameter ("src", get_ccode_name (ssize_t_type))); - fun.add_parameter (new CCodeParameter ("dest", get_ccode_name (ssize_t_type))); - fun.add_parameter (new CCodeParameter ("length", get_ccode_name (ssize_t_type))); - - push_function (fun); - - var array = new CCodeCastExpression (new CCodeIdentifier ("array"), "char*"); - var element_size = new CCodeIdentifier ("element_size"); - var length = new CCodeIdentifier ("length"); - var src = new CCodeIdentifier ("src"); - var src_end = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, src, length); - var dest = new CCodeIdentifier ("dest"); - var dest_end = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, dest, length); - var src_address = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, array, new CCodeBinaryExpression (CCodeBinaryOperator.MUL, src, element_size)); - var dest_address = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, array, new CCodeBinaryExpression (CCodeBinaryOperator.MUL, dest, element_size)); - var dest_end_address = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, array, new CCodeBinaryExpression (CCodeBinaryOperator.MUL, dest_end, element_size)); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("memmove")); - ccall.add_argument (dest_address); - ccall.add_argument (src_address); - ccall.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, length, element_size)); - ccode.add_expression (ccall); - - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, src, dest), new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN, src_end, dest))); - - var czero1 = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - czero1.add_argument (src_address); - czero1.add_argument (new CCodeConstant ("0")); - czero1.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeBinaryExpression (CCodeBinaryOperator.MINUS, dest, src), element_size)); - ccode.add_expression (czero1); - - ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN, src, dest), new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, src, dest_end))); - - var czero2 = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - czero2.add_argument (dest_end_address); - czero2.add_argument (new CCodeConstant ("0")); - czero2.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeBinaryExpression (CCodeBinaryOperator.MINUS, src, dest), element_size)); - ccode.add_expression (czero2); - - ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, src, dest)); - - var czero3 = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - czero3.add_argument (src_address); - czero3.add_argument (new CCodeConstant ("0")); - czero3.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, length, element_size)); - ccode.add_expression (czero3); - - ccode.close (); - - pop_function (); - - cfile.add_function_declaration (fun); - cfile.add_function (fun); - } - - public override void append_vala_array_length () { - generate_type_declaration (ssize_t_type, cfile); - - var fun = new CCodeFunction ("_vala_array_length", get_ccode_name (ssize_t_type)); - fun.modifiers = CCodeModifiers.STATIC; - fun.add_parameter (new CCodeParameter ("array", get_ccode_name (pointer_type))); - - push_function (fun); - - ccode.add_declaration (get_ccode_name (ssize_t_type), new CCodeVariableDeclarator ("length", new CCodeConstant ("0"))); - - // return 0 if the array is NULL - // avoids an extra NULL check on the caller side - var array_check = new CCodeIdentifier ("array"); - ccode.open_if (array_check); - - var array_element_check = new CCodeElementAccess (new CCodeCastExpression (new CCodeIdentifier ("array"), "%s*".printf (get_ccode_name (pointer_type))), new CCodeConstant ("length")); - ccode.open_while (array_element_check); - ccode.add_expression (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("length"))); - ccode.close (); - - ccode.close (); - - ccode.add_return (new CCodeIdentifier ("length")); - - pop_function (); - - cfile.add_function_declaration (fun); - cfile.add_function (fun); - } - - public override TargetValue? copy_value (TargetValue value, CodeNode node) { - var type = value.value_type; - var cexpr = get_cvalue_ (value); - - if (type is ArrayType) { - var array_type = (ArrayType) type; - - if (!array_type.fixed_length) { - return base.copy_value (value, node); - } - - var temp_value = create_temp_value (type, false, node); - - var copy_call = new CCodeFunctionCall (new CCodeIdentifier (generate_array_copy_wrapper (array_type))); - copy_call.add_argument (cexpr); - copy_call.add_argument (get_cvalue_ (temp_value)); - ccode.add_expression (copy_call); - - return temp_value; - } else { - return base.copy_value (value, node); - } - } - - public override CCodeExpression? get_dup_func_expression (DataType type, SourceReference? source_reference, bool is_chainup) { - if (type is ArrayType) { - var array_type = (ArrayType) type; - // fixed length arrays use different code - // generated by overridden get_ref_cexpression method - assert (!array_type.fixed_length); - return new CCodeIdentifier (generate_array_dup_wrapper (array_type)); - } else { - return base.get_dup_func_expression (type, source_reference, is_chainup); - } - } - - public override CCodeExpression destroy_value (TargetValue value, bool is_macro_definition = false) { - unowned ArrayType? array_type = value.value_type as ArrayType; - - if (array_type != null && array_type.fixed_length) { - unowned Struct? st = array_type.element_type.type_symbol as Struct; - if (st != null && !array_type.element_type.nullable) { - var ccall = new CCodeFunctionCall (new CCodeIdentifier (append_struct_array_destroy (st))); - ccall.add_argument (get_cvalue_ (value)); - ccall.add_argument (get_ccodenode (array_type.length)); - return ccall; - } - - requires_array_free = true; - generate_type_declaration (delegate_target_destroy_type, cfile); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_destroy")); - ccall.add_argument (get_cvalue_ (value)); - ccall.add_argument (get_ccodenode (array_type.length)); - ccall.add_argument (new CCodeCastExpression (get_destroy_func_expression (array_type.element_type), get_ccode_name (delegate_target_destroy_type))); - - return ccall; - } else { - return base.destroy_value (value, is_macro_definition); - } - } - - string generate_array_dup_wrapper (ArrayType array_type) { - string dup_func = "_vala_array_dup%d".printf (++next_array_dup_id); - - if (!add_wrapper (dup_func)) { - // wrapper already defined - return dup_func; - } - - // declaration - generate_type_declaration (ssize_t_type, cfile); - - var function = new CCodeFunction (dup_func, get_ccode_name (array_type)); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("self", get_ccode_name (array_type))); - // total length over all dimensions - function.add_parameter (new CCodeParameter ("length", get_ccode_name (ssize_t_type))); - if (array_type.element_type is GenericType) { - // dup function array elements - function.add_parameter (new CCodeParameter (get_ccode_copy_function (((GenericType) array_type.element_type).type_parameter), "GBoxedCopyFunc")); - } - - // definition - - push_context (new EmitContext ()); - push_function (function); - - if (requires_copy (array_type.element_type)) { - var cvardecl = new CCodeVariableDeclarator ("result"); - CCodeFunctionCall gnew; - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdlib.h"); - gnew = new CCodeFunctionCall (new CCodeIdentifier ("calloc")); - } else { - gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0")); - gnew.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - } - - CCodeExpression length_expr = new CCodeIdentifier ("length"); - CCodeBinaryOperator length_check_op; - // add extra item to have array NULL-terminated for all reference types - if (array_type.element_type.type_symbol != null && array_type.element_type.type_symbol.is_reference_type ()) { - length_expr = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, length_expr, new CCodeConstant ("1")); - length_check_op = CCodeBinaryOperator.GREATER_THAN_OR_EQUAL; - } else { - length_check_op = CCodeBinaryOperator.GREATER_THAN; - } - gnew.add_argument (length_expr); - - if (context.profile == Profile.POSIX) { - var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - csizeof.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - gnew.add_argument (csizeof); - } - - // only attempt to dup if length >=/> 0, this deals with negative lengths and returns NULL - var length_check = new CCodeBinaryExpression (length_check_op, new CCodeIdentifier ("length"), new CCodeConstant ("0")); - ccode.open_if (length_check); - - ccode.add_declaration (get_ccode_name (array_type), cvardecl); - ccode.add_assignment (new CCodeIdentifier ("result"), gnew); - - ccode.add_declaration (get_ccode_name (ssize_t_type), new CCodeVariableDeclarator ("i")); - - ccode.open_for (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")), - new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("length")), - new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i"))); - - ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("result"), new CCodeIdentifier ("i")), get_cvalue_ (copy_value (new GLibValue (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), true), array_type))); - ccode.close (); - - ccode.add_return (new CCodeIdentifier ("result")); - - ccode.close (); - ccode.add_return (new CCodeConstant ("NULL")); - } else { - // only dup if length > 0, this deals with negative lengths and returns NULL - var length_check = new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN, new CCodeIdentifier ("length"), new CCodeConstant ("0")); - ccode.open_if (length_check); - - var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - sizeof_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - var length_expr = new CCodeIdentifier ("length"); - - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdlib.h"); - cfile.add_include ("string.h"); - - var alloc = new CCodeFunctionCall (new CCodeIdentifier ("calloc")); - alloc.add_argument (length_expr); - alloc.add_argument (sizeof_call); - - var cvardecl = new CCodeVariableDeclarator ("result"); - ccode.add_declaration (get_ccode_name (array_type), cvardecl); - ccode.add_assignment (new CCodeIdentifier ("result"), alloc); - - var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy")); - dup_call.add_argument (new CCodeIdentifier ("result")); - dup_call.add_argument (new CCodeIdentifier ("self")); - dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, length_expr, sizeof_call)); - ccode.add_expression (dup_call); - - ccode.add_return (new CCodeIdentifier ("result")); - } else { - CCodeFunctionCall dup_call; - if (context.require_glib_version (2, 68)) { - dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup2")); - } else { - requires_memdup2 = true; - dup_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_memdup2")); - } - dup_call.add_argument (new CCodeIdentifier ("self")); - dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, length_expr, sizeof_call)); - - ccode.add_return (dup_call); - } - - ccode.close (); - ccode.add_return (new CCodeConstant ("NULL")); - } - - // append to file - - cfile.add_function_declaration (function); - cfile.add_function (function); - - pop_context (); - - return dup_func; - } - - string generate_array_copy_wrapper (ArrayType array_type) { - string dup_func = "_vala_array_copy%d".printf (++next_array_dup_id); - - if (!add_wrapper (dup_func)) { - // wrapper already defined - return dup_func; - } - - // declaration - - var function = new CCodeFunction (dup_func, "void"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (array_type)))); - function.add_parameter (new CCodeParameter ("dest", "%s *".printf (get_ccode_name (array_type)))); - - // definition - - push_context (new EmitContext ()); - push_function (function); - - if (requires_copy (array_type.element_type)) { - ccode.add_declaration (get_ccode_name (array_type.length_type), new CCodeVariableDeclarator ("i")); - - ccode.open_for (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")), - new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), get_ccodenode (array_type.length)), - new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i"))); - - - ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("dest"), new CCodeIdentifier ("i")), get_cvalue_ (copy_value (new GLibValue (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), true), array_type))); - } else { - cfile.add_include ("string.h"); - - var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy")); - dup_call.add_argument (new CCodeIdentifier ("dest")); - dup_call.add_argument (new CCodeIdentifier ("self")); - - var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - sizeof_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, get_ccodenode (array_type.length), sizeof_call)); - - ccode.add_expression (dup_call); - } - - // append to file - - cfile.add_function_declaration (function); - cfile.add_function (function); - - pop_context (); - - return dup_func; - } - - string generate_array_add_wrapper (ArrayType array_type) { - string add_func = "_vala_array_add%d".printf (++next_array_add_id); - - if (!add_wrapper (add_func)) { - // wrapper already defined - return add_func; - } - - var function = new CCodeFunction (add_func, "void"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("array", "%s *".printf (get_ccode_name (array_type)))); - function.add_parameter (new CCodeParameter ("length", "%s*".printf (get_ccode_name (array_type.length_type)))); - function.add_parameter (new CCodeParameter ("size", "%s*".printf (get_ccode_name (array_type.length_type)))); - - push_function (function); - - string typename = get_ccode_name (array_type.element_type); - CCodeExpression value = new CCodeIdentifier ("value"); - if (array_type.element_type.is_real_struct_type ()) { - if (!array_type.element_type.nullable || !array_type.element_type.value_owned) { - typename = "const " + typename; - } - if (!array_type.element_type.nullable) { - typename += "*"; - value = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, value); - } - } - function.add_parameter (new CCodeParameter ("value", typename)); - - var array = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("array")); - var length = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("length")); - var size = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("size")); - - CCodeFunctionCall renew_call; - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdlib.h"); - renew_call = new CCodeFunctionCall (new CCodeIdentifier ("realloc")); - renew_call.add_argument (array); - } else { - renew_call = new CCodeFunctionCall (new CCodeIdentifier ("g_renew")); - renew_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - renew_call.add_argument (array); - } - CCodeExpression renew_call_size; - if (array_type.element_type.is_reference_type_or_type_parameter ()) { - // NULL terminate array - renew_call_size = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, size, new CCodeConstant ("1")); - } else { - renew_call_size = size; - } - if (context.profile == Profile.POSIX) { - var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - csizeof.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - renew_call_size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, size, csizeof); - } - renew_call.add_argument (renew_call_size); - - var csizecheck = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, length, size); - ccode.open_if (csizecheck); - ccode.add_assignment (size, new CCodeConditionalExpression (size, new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("2"), size), new CCodeConstant ("4"))); - ccode.add_assignment (array, renew_call); - ccode.close (); - - ccode.add_assignment (new CCodeElementAccess (array, new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, length)), value); - - if (array_type.element_type.is_reference_type_or_type_parameter ()) { - // NULL terminate array - ccode.add_assignment (new CCodeElementAccess (array, length), new CCodeConstant ("NULL")); - } - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return add_func; - } - - bool is_array_add (Assignment assignment) { - var binary = assignment.right as BinaryExpression; - if (binary != null && binary.left.value_type is ArrayType) { - if (binary.operator == BinaryOperator.PLUS) { - if (assignment.left.symbol_reference == binary.left.symbol_reference) { - return true; - } - } - } - - return false; - } - - public override void visit_assignment (Assignment assignment) { - if (!is_array_add (assignment)) { - base.visit_assignment (assignment); - return; - } - - var binary = (BinaryExpression) assignment.right; - - var array = assignment.left; - var array_type = (ArrayType) array.value_type; - var element = binary.right; - - var array_var = array.symbol_reference; - if (array_type.rank == 1 && array_var != null && array_var.is_internal_symbol () - && (array_var is LocalVariable || array_var is Field)) { - // valid array add - } else { - Report.error (assignment.source_reference, "Array concatenation not supported for public array variables and parameters"); - return; - } - - var value_param = new Parameter ("value", element.target_type); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_array_add_wrapper (array_type))); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue (array))); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_array_length_cexpression (array))); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_array_size_cvalue (array.target_value))); - ccall.add_argument (handle_struct_argument (value_param, element, get_cvalue (element))); - - ccode.add_expression (ccall); - } - - public override CCodeParameter generate_parameter (Parameter param, CCodeFile decl_space, Map cparam_map, Map? carg_map) { - unowned ArrayType? array_type = param.variable_type as ArrayType; - if (array_type == null || param.params_array) { - return base.generate_parameter (param, decl_space, cparam_map, carg_map); - } - - string? ctypename = get_ccode_type (param); - if (ctypename == null) { - ctypename = get_ccode_name (param.variable_type); - - if (param.direction != ParameterDirection.IN) { - ctypename += "*"; - } - } - - var main_cparam = new CCodeParameter.with_declarator (ctypename, new CCodeVariableDeclarator (get_ccode_name (param), null, get_ccode_declarator_suffix (array_type))); - - generate_type_declaration (array_type.element_type, decl_space); - - cparam_map.set (get_param_pos (get_ccode_pos (param)), main_cparam); - if (carg_map != null) { - carg_map.set (get_param_pos (get_ccode_pos (param)), get_parameter_cexpression (param)); - } - - if (!array_type.fixed_length && get_ccode_array_length (param)) { - var length_ctype = get_ccode_array_length_type (param); - if (param.direction != ParameterDirection.IN) { - length_ctype = "%s*".printf (length_ctype); - } - - for (int dim = 1; dim <= array_type.rank; dim++) { - var cparam = new CCodeParameter (get_variable_array_length_cname (param, dim), length_ctype); - cparam_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), cparam); - if (carg_map != null) { - carg_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), get_cexpression (cparam.name)); - } - } - } - - return main_cparam; - } - - public override void append_params_array (Method m) { - var local = m.params_array_var; - var array_type = (ArrayType) local.variable_type; - - var local_length = new LocalVariable (array_type.length_type.copy (), get_array_length_cname (local.name, 1), null, local.source_reference); - var local_size = new LocalVariable (array_type.length_type.copy (), get_array_size_cname (get_local_cname (local))); - - CCodeFunctionCall gnew; - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdlib.h"); - gnew = new CCodeFunctionCall (new CCodeIdentifier ("calloc")); - } else { - gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0")); - gnew.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - } - - CCodeExpression length_expr = get_local_cexpression (local_length); - // add extra item to have array NULL-terminated for all reference types - if (array_type.element_type.type_symbol != null && array_type.element_type.type_symbol.is_reference_type ()) { - length_expr = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, length_expr, new CCodeConstant ("1")); - } - gnew.add_argument (length_expr); - if (context.profile == Profile.POSIX) { - var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - csizeof.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - gnew.add_argument (csizeof); - } - ccode.add_assignment (get_local_cexpression (local), gnew); - - var element = new LocalVariable (array_type.element_type.copy (), "_%s_element".printf (get_ccode_name (local)), null, local.source_reference); - emit_temp_var (element); - - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdarg.h"); - } - - if (!(m is CreationMethod) || m.parent_symbol is Struct) { - ccode.add_declaration ("va_list", new CCodeVariableDeclarator ("_va_list_%s".printf (get_ccode_name (local)))); - var vastart = new CCodeFunctionCall (new CCodeIdentifier ("va_start")); - vastart.add_argument (new CCodeIdentifier ("_va_list_%s".printf (get_ccode_name (local)))); - vastart.add_argument (new CCodeIdentifier ("_first_%s".printf (get_ccode_name (local)))); - ccode.add_expression (vastart); - } - - ccode.add_assignment (get_local_cexpression (element), new CCodeIdentifier ("_first_%s".printf (get_ccode_name (local)))); - ccode.open_while (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_local_cexpression (element), new CCodeConstant ("NULL"))); - - var vaarg = new CCodeFunctionCall (new CCodeIdentifier ("va_arg")); - vaarg.add_argument (new CCodeIdentifier ("_va_list_%s".printf (get_ccode_name (local)))); - vaarg.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_array_add_wrapper (array_type))); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_local_cexpression (local))); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_local_cexpression (local_length))); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_local_cexpression (local_size))); - ccall.add_argument (get_local_cexpression (element)); - - ccode.add_expression (ccall); - ccode.add_assignment (get_local_cexpression (element), vaarg); - - ccode.close (); - - var vaend = new CCodeFunctionCall (new CCodeIdentifier ("va_end")); - vaend.add_argument (new CCodeIdentifier ("_va_list_%s".printf (get_ccode_name (local)))); - ccode.add_expression (vaend); - } -} diff --git a/src/codegen/valaccodeassignmentmodule.vala b/src/codegen/valaccodeassignmentmodule.vala deleted file mode 100644 index fa2540ba1..000000000 --- a/src/codegen/valaccodeassignmentmodule.vala +++ /dev/null @@ -1,249 +0,0 @@ -/* valaccodeassignmentmodule.vala - * - * Copyright (C) 2006-2010 Jürg Billeter - * Copyright (C) 2006-2008 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.1 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 - * Raffaele Sandrini - */ - -using GLib; - -/** - * The link between an assignment and generated code. - */ -public class Vala.CCodeAssignmentModule : CCodeMemberAccessModule { - TargetValue emit_simple_assignment (Assignment assignment) { - if (requires_destroy (assignment.left.value_type)) { - /* unref old value */ - ccode.add_expression (destroy_value (assignment.left.target_value)); - } - - if (assignment.operator == AssignmentOperator.SIMPLE) { - store_value (assignment.left.target_value, assignment.right.target_value, assignment.source_reference); - } else { - CCodeAssignmentOperator cop; - - switch (assignment.operator) { - case AssignmentOperator.BITWISE_OR: cop = CCodeAssignmentOperator.BITWISE_OR; break; - case AssignmentOperator.BITWISE_AND: cop = CCodeAssignmentOperator.BITWISE_AND; break; - case AssignmentOperator.BITWISE_XOR: cop = CCodeAssignmentOperator.BITWISE_XOR; break; - case AssignmentOperator.ADD: cop = CCodeAssignmentOperator.ADD; break; - case AssignmentOperator.SUB: cop = CCodeAssignmentOperator.SUB; break; - case AssignmentOperator.MUL: cop = CCodeAssignmentOperator.MUL; break; - case AssignmentOperator.DIV: cop = CCodeAssignmentOperator.DIV; break; - case AssignmentOperator.PERCENT: - // FIXME Code duplication with CCodeBaseModule.visit_binary_expression() - var cleft = get_cvalue (assignment.left); - var cright = get_cvalue (assignment.right); - if (assignment.value_type.equals (double_type)) { - cfile.add_include ("math.h"); - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("fmod")); - ccall.add_argument (cleft); - ccall.add_argument (cright); - set_cvalue (assignment.right, ccall); - cop = CCodeAssignmentOperator.SIMPLE; - } else if (assignment.value_type.equals (float_type)) { - cfile.add_include ("math.h"); - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("fmodf")); - ccall.add_argument (cleft); - ccall.add_argument (cright); - set_cvalue (assignment.right, ccall); - cop = CCodeAssignmentOperator.SIMPLE; - } else { - cop = CCodeAssignmentOperator.PERCENT; - } - break; - case AssignmentOperator.SHIFT_LEFT: cop = CCodeAssignmentOperator.SHIFT_LEFT; break; - case AssignmentOperator.SHIFT_RIGHT: cop = CCodeAssignmentOperator.SHIFT_RIGHT; break; - default: assert_not_reached (); - } - - CCodeExpression codenode = new CCodeAssignment (get_cvalue (assignment.left), get_cvalue (assignment.right), cop); - ccode.add_expression (codenode); - } - - if (assignment.left.value_type is ArrayType && (((ArrayType) assignment.left.value_type).inline_allocated)) { - unowned Variable variable = (Variable) assignment.left.symbol_reference; - return load_variable (variable, assignment.left.target_value); - } else { - return assignment.left.target_value; - } - } - - public override void visit_assignment (Assignment assignment) { - if (assignment.left.error || assignment.right.error) { - assignment.error = true; - return; - } - - if (assignment.left.symbol_reference is Property) { - unowned MemberAccess ma = (MemberAccess) assignment.left; - unowned Property prop = (Property) assignment.left.symbol_reference; - - store_property (prop, ma.inner, assignment.right.target_value); - assignment.target_value = assignment.right.target_value; - } else if (assignment.left.symbol_reference is Variable && is_simple_struct_creation ((Variable) assignment.left.symbol_reference, assignment.right)) { - // delegate to visit_object_creation_expression - } else { - assignment.target_value = emit_simple_assignment (assignment); - } - } - - public override void store_value (TargetValue lvalue, TargetValue value, SourceReference? source_reference = null) { - var array_type = lvalue.value_type as ArrayType; - - if (array_type != null && array_type.fixed_length) { - cfile.add_include ("string.h"); - - // it is necessary to use memcpy for fixed-length (stack-allocated) arrays - // simple assignments do not work in C - var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - sizeof_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - var size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, get_ccodenode (array_type.length), sizeof_call); - - var ccopy = new CCodeFunctionCall (new CCodeIdentifier ("memcpy")); - ccopy.add_argument (get_cvalue_ (lvalue)); - ccopy.add_argument (get_cvalue_ (value)); - ccopy.add_argument (size); - ccode.add_expression (ccopy); - - return; - } - - var cexpr = get_cvalue_ (value); - if (get_ctype (lvalue) != null) { - cexpr = new CCodeCastExpression (cexpr, get_ctype (lvalue)); - } - - ccode.add_assignment (get_cvalue_ (lvalue), cexpr); - - if (array_type != null && ((GLibValue) lvalue).array_length_cvalues != null) { - var glib_value = (GLibValue) value; - if (glib_value.array_length_cvalues != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - ccode.add_assignment (get_array_length_cvalue (lvalue, dim), get_array_length_cvalue (value, dim)); - } - } else if (glib_value.array_null_terminated) { - requires_array_length = true; - var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length")); - len_call.add_argument (get_cvalue_ (value)); - - ccode.add_assignment (get_array_length_cvalue (lvalue, 1), len_call); - } else { - for (int dim = 1; dim <= array_type.rank; dim++) { - ccode.add_assignment (get_array_length_cvalue (lvalue, dim), new CCodeConstant ("-1")); - } - } - - if (array_type.rank == 1 && get_array_size_cvalue (lvalue) != null) { - ccode.add_assignment (get_array_size_cvalue (lvalue), get_array_length_cvalue (lvalue, 1)); - } - } - - var delegate_type = lvalue.value_type as DelegateType; - if (delegate_type != null && delegate_type.delegate_symbol.has_target) { - var lvalue_target = get_delegate_target_cvalue (lvalue); - var rvalue_target = get_delegate_target_cvalue (value); - if (lvalue_target != null) { - if (rvalue_target != null) { - ccode.add_assignment (lvalue_target, rvalue_target); - } else { - Report.error (source_reference, "Assigning delegate without required target in scope"); - ccode.add_assignment (lvalue_target, new CCodeInvalidExpression ()); - } - var lvalue_destroy_notify = get_delegate_target_destroy_notify_cvalue (lvalue); - var rvalue_destroy_notify = get_delegate_target_destroy_notify_cvalue (value); - if (lvalue_destroy_notify != null) { - if (rvalue_destroy_notify != null) { - ccode.add_assignment (lvalue_destroy_notify, rvalue_destroy_notify); - } else { - ccode.add_assignment (lvalue_destroy_notify, new CCodeConstant ("NULL")); - } - } - } - } - } - - public override void store_local (LocalVariable local, TargetValue value, bool initializer, SourceReference? source_reference = null) { - if (!initializer && requires_destroy (local.variable_type)) { - /* unref old value */ - ccode.add_expression (destroy_local (local)); - } - - store_value (get_local_cvalue (local), value, source_reference); - } - - public override void store_parameter (Parameter param, TargetValue _value, bool capturing_parameter = false, SourceReference? source_reference = null) { - var value = _value; - - bool capturing_parameter_in_coroutine = capturing_parameter && is_in_coroutine (); - - var param_type = param.variable_type.copy (); - if (param.captured || is_in_coroutine ()) { - if (!param_type.value_owned && !no_implicit_copy (param_type)) { - // parameter value has been implicitly copied into a heap data structure - // treat parameter as owned - param_type.value_owned = true; - - var old_coroutine = is_in_coroutine (); - if (old_coroutine) { - current_method.coroutine = false; - } - - if (requires_copy (param_type) && !capturing_parameter_in_coroutine) { - // do not copy value when capturing parameter in coroutine - // as the value was already copied on coroutine initialization - value = copy_value (value, param); - } - - if (old_coroutine) { - current_method.coroutine = true; - } - } - } - - if (requires_destroy (param_type)) { - /* unref old value */ - ccode.add_expression (destroy_parameter (param)); - } - - store_value (get_parameter_cvalue (param), value, source_reference); - } - - public override void store_field (Vala.Field field, Vala.TargetValue? instance, Vala.TargetValue value, Vala.SourceReference? source_reference = null, bool initializer = false) - { - var lvalue = get_field_cvalue (field, instance); - var type = lvalue.value_type; - if (lvalue.actual_value_type != null) { - type = lvalue.actual_value_type; - } - if (!initializer && (!(field.variable_type is DelegateType) || get_ccode_delegate_target (field)) && requires_destroy (type)) { - /* unref old value */ - ccode.add_expression (destroy_field (field, instance)); - } - if (initializer && instance != null && get_ccode_delegate_target (field) && get_delegate_target_cvalue (value) == null) { - unowned DelegateType delegate_type = field.variable_type as DelegateType; - if (delegate_type != null && delegate_type.delegate_symbol.has_target) { - ((GLibValue) value).delegate_target_cvalue = get_cvalue_ (instance); - } - } - - store_value (lvalue, value, source_reference); - } -} \ No newline at end of file diff --git a/src/codegen/valaccodeattribute.vala b/src/codegen/valaccodeattribute.vala deleted file mode 100644 index bd4c6b29d..000000000 --- a/src/codegen/valaccodeattribute.vala +++ /dev/null @@ -1,1676 +0,0 @@ -/* valaccodeattribute.vala - * - * Copyright (C) 2011 Luca Bruno - * - * 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.1 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: - * Luca Bruno - */ - - -/** - * Cache for the CCode attribute - */ -public class Vala.CCodeAttribute : AttributeCache { - private weak CodeNode node; - private weak Symbol? sym; - private Attribute ccode; - - public string name { - get { - if (_name == null) { - if (ccode != null) { - _name = ccode.get_string ("cname"); - } - if (_name == null) { - _name = get_default_name (); - } - } - return _name; - } - } - - public string const_name { - get { - if (_const_name == null) { - if (ccode != null) { - _const_name = ccode.get_string ("const_cname"); - } - if (_const_name == null) { - _const_name = get_default_const_name (); - } - } - return _const_name; - } - } - - public string type_name { - get { - if (_type_name == null) { - if (ccode != null) { - _type_name = ccode.get_string ("type_cname"); - } - if (_type_name == null) { - if (sym is Class) { - _type_name = "%sClass".printf (get_ccode_name (sym)); - } else if (sym is Interface) { - _type_name = "%sIface".printf (get_ccode_name (sym)); - } else { - Report.error (sym.source_reference, "`CCode.type_cname' not supported"); - _type_name = ""; - } - } - } - return _type_name; - } - } - - public string feature_test_macros { - get { - if (_feature_test_macros == null) { - if (ccode != null) { - _feature_test_macros = ccode.get_string ("feature_test_macro"); - } - if (_feature_test_macros == null) { - _feature_test_macros = ""; - } - } - return _feature_test_macros; - } - } - - public string header_filenames { - get { - if (_header_filenames == null) { - if (ccode != null) { - _header_filenames = ccode.get_string ("cheader_filename"); - } - if (_header_filenames == null) { - _header_filenames = get_default_header_filenames (); - } - } - return _header_filenames; - } - } - - public string prefix { - get { - if (_prefix == null) { - if (ccode != null) { - _prefix = ccode.get_string ("cprefix"); - } - if (_prefix == null) { - _prefix = get_default_prefix (); - } - } - return _prefix; - } - } - - public string lower_case_prefix { - get { - if (_lower_case_prefix == null) { - if (ccode != null) { - _lower_case_prefix = ccode.get_string ("lower_case_cprefix"); - if (_lower_case_prefix == null && (sym is ObjectTypeSymbol || sym is Struct)) { - _lower_case_prefix = ccode.get_string ("cprefix"); - } - } - if (_lower_case_prefix == null) { - _lower_case_prefix = get_default_lower_case_prefix (); - } - } - return _lower_case_prefix; - } - } - - public string lower_case_suffix { - get { - if (_lower_case_suffix == null) { - if (ccode != null) { - _lower_case_suffix = ccode.get_string ("lower_case_csuffix"); - } - if (_lower_case_suffix == null) { - _lower_case_suffix = get_default_lower_case_suffix (); - } - } - return _lower_case_suffix; - } - } - - public string ref_function { - get { - if (!ref_function_set) { - if (ccode != null) { - _ref_function = ccode.get_string ("ref_function"); - } - if (_ref_function == null) { - _ref_function = get_default_ref_function (); - } - ref_function_set = true; - } - return _ref_function; - } - } - - public bool ref_function_void { - get { - if (_ref_function_void == null) { - if (ccode != null && ccode.has_argument ("ref_function_void")) { - _ref_function_void = ccode.get_bool ("ref_function_void"); - } else { - var cl = (Class) sym; - if (cl.base_class != null) { - _ref_function_void = get_ccode_ref_function_void (cl.base_class); - } else { - _ref_function_void = false; - } - } - } - return _ref_function_void; - } - } - - public string unref_function { - get { - if (!unref_function_set) { - if (ccode != null) { - _unref_function = ccode.get_string ("unref_function"); - } - if (_unref_function == null) { - _unref_function = get_default_unref_function (); - } - unref_function_set = true; - } - return _unref_function; - } - } - - public string ref_sink_function { - get { - if (_ref_sink_function == null) { - if (ccode != null) { - _ref_sink_function = ccode.get_string ("ref_sink_function"); - } - if (_ref_sink_function == null) { - _ref_sink_function = get_default_ref_sink_function (); - } - } - return _ref_sink_function; - } - } - - public string copy_function { - get { - if (!copy_function_set) { - if (ccode != null) { - _copy_function = ccode.get_string ("copy_function"); - } - if (_copy_function == null && sym is Struct) { - _copy_function = "%scopy".printf (lower_case_prefix); - } - if (_copy_function == null && sym is TypeParameter) { - _copy_function = "%s_dup_func".printf (sym.name.ascii_down ()); - } - copy_function_set = true; - } - return _copy_function; - } - } - - public string destroy_function { - get { - if (!destroy_function_set) { - if (ccode != null) { - _destroy_function = ccode.get_string ("destroy_function"); - } - if (_destroy_function == null && sym is Struct) { - _destroy_function = "%sdestroy".printf (lower_case_prefix); - } - if (_destroy_function == null && sym is TypeParameter) { - _destroy_function = "%s_destroy_func".printf (sym.name.ascii_down ()); - } - destroy_function_set = true; - } - return _destroy_function; - } - } - - public string dup_function { - get { - if (!dup_function_set) { - if (ccode != null) { - _dup_function = ccode.get_string ("dup_function"); - } - if (_dup_function == null && !sym.external_package - && sym is Struct && !((Struct) sym).is_simple_type ()) { - _dup_function = "%sdup".printf (lower_case_prefix); - } - dup_function_set = true; - } - return _dup_function; - } - } - - public string free_function { - get { - if (!free_function_set) { - if (ccode != null) { - _free_function = ccode.get_string ("free_function"); - } - if (_free_function == null) { - _free_function = get_default_free_function (); - } - free_function_set = true; - } - return _free_function; - } - } - - public bool free_function_address_of { - get { - if (_free_function_address_of == null) { - if (ccode != null && ccode.has_argument ("free_function_address_of")) { - _free_function_address_of = ccode.get_bool ("free_function_address_of"); - } else { - unowned Class cl = (Class) sym; - if (cl.base_class != null) { - _free_function_address_of = get_ccode_free_function_address_of (cl.base_class); - } else { - _free_function_address_of = false; - } - } - } - return _free_function_address_of; - } - } - - public string ctype { - get { - if (!ctype_set) { - if (ccode != null) { - _ctype = ccode.get_string ("type"); - if (_ctype == null) { - _ctype = ccode.get_string ("ctype"); - if (_ctype != null) { - Report.deprecated (node.source_reference, "[CCode (ctype = \"...\")] is deprecated, use [CCode (type = \"...\")] instead."); - } - } - } - ctype_set = true; - } - return _ctype; - } - } - - public string type_id { - get { - if (_type_id == null) { - if (ccode != null) { - _type_id = ccode.get_string ("type_id"); - } - if (_type_id == null && sym is TypeParameter) { - _type_id = "%s_type".printf (sym.name.ascii_down ()); - } - if (_type_id == null) { - _type_id = get_default_type_id (); - } - } - return _type_id; - } - } - - public string marshaller_type_name { - get { - if (_marshaller_type_name == null) { - if (ccode != null) { - _marshaller_type_name = ccode.get_string ("marshaller_type_name"); - } - if (_marshaller_type_name == null) { - _marshaller_type_name = get_default_marshaller_type_name (); - } - } - return _marshaller_type_name; - } - } - - public string get_value_function { - get { - if (_get_value_function == null) { - if (ccode != null) { - _get_value_function = ccode.get_string ("get_value_function"); - } - if (_get_value_function == null) { - _get_value_function = get_default_get_value_function (); - } - } - return _get_value_function; - } - } - - public string set_value_function { - get { - if (_set_value_function == null) { - if (ccode != null) { - _set_value_function = ccode.get_string ("set_value_function"); - } - if (_set_value_function == null) { - _set_value_function = get_default_set_value_function (); - } - } - return _set_value_function; - } - } - - public string take_value_function { - get { - if (_take_value_function == null) { - if (ccode != null) { - _take_value_function = ccode.get_string ("take_value_function"); - } - if (_take_value_function == null) { - _take_value_function = get_default_take_value_function (); - } - } - return _take_value_function; - } - } - - public string param_spec_function { - get { - if (_param_spec_function == null) { - if (ccode != null) { - _param_spec_function = ccode.get_string ("param_spec_function"); - } - if (_param_spec_function == null) { - _param_spec_function = get_default_param_spec_function (); - } - } - return _param_spec_function; - } - } - - public string default_value { - get { - if (_default_value == null) { - if (ccode != null) { - _default_value = ccode.get_string ("default_value"); - } - if (_default_value == null) { - _default_value = get_default_default_value (); - } - } - return _default_value; - } - } - - public string default_value_on_error { - get { - if (_default_value_on_error == null) { - if (ccode != null) { - _default_value_on_error = ccode.get_string ("default_value_on_error"); - } - if (_default_value_on_error == null) { - _default_value_on_error = default_value; - } - } - return _default_value_on_error; - } - } - - public double pos { - get { - if (_pos == null) { - if (ccode != null && ccode.has_argument ("pos")) { - _pos = ccode.get_double ("pos"); - } else { - unowned Parameter param = (Parameter) node; - unowned Callable? callable = param.parent_symbol as Callable; - unowned Method? method = param.parent_symbol as Method; - if (method != null && method.coroutine) { - int index = method.get_async_begin_parameters ().index_of (param); - if (index < 0) { - index = method.get_async_end_parameters ().index_of (param); - } - if (index < 0) { - Report.error (param.source_reference, "internal: Parameter `%s' not found in `%s'", param.name, method.get_full_name ()); - } - _pos = index + 1.0; - } else if (callable != null) { - _pos = callable.get_parameters ().index_of (param) + 1.0; - } else { - _pos = 0.0; - } - } - } - return _pos; - } - } - - public string real_name { - get { - if (_real_name == null) { - if (ccode != null && sym is CreationMethod) { - _real_name = ccode.get_string ("construct_function"); - } - if (_real_name == null) { - _real_name = get_default_real_name (); - } - } - return _real_name; - } - } - - public string vfunc_name { - get { - if (_vfunc_name == null) { - if (ccode != null) { - _vfunc_name = ccode.get_string ("vfunc_name"); - } - if (_vfunc_name == null) { - unowned Method? m = node as Method; - if (m != null && m.signal_reference != null) { - _vfunc_name = get_ccode_lower_case_name (m.signal_reference); - } else { - _vfunc_name = sym.name; - } - } - } - return _vfunc_name; - } - } - - public string finish_name { - get { - if (_finish_name == null) { - if (ccode != null) { - _finish_name = ccode.get_string ("finish_name"); - if (_finish_name == null) { - _finish_name = ccode.get_string ("finish_function"); - if (_finish_name != null) { - Report.deprecated (node.source_reference, "[CCode (finish_function = \"...\")] is deprecated, use [CCode (finish_name = \"...\")] instead."); - } - } - } - if (_finish_name == null) { - _finish_name = get_finish_name_for_basename (name); - } - } - return _finish_name; - } - } - - public string finish_vfunc_name { - get { - if (_finish_vfunc_name == null) { - if (ccode != null) { - _finish_vfunc_name = ccode.get_string ("finish_vfunc_name"); - } - if (_finish_vfunc_name == null) { - _finish_vfunc_name = get_finish_name_for_basename (vfunc_name); - } - } - return _finish_vfunc_name; - } - } - - public string finish_real_name { - get { - if (_finish_real_name == null) { - unowned Method? m = node as Method; - if (m != null && !(m is CreationMethod) && !(m.is_abstract || m.is_virtual)) { - _finish_real_name = finish_name; - } else { - _finish_real_name = get_finish_name_for_basename (real_name); - } - } - return _finish_real_name; - } - } - - public bool finish_instance { - get { - if (_finish_instance == null) { - unowned Method? m = node as Method; - bool is_creation_method = m is CreationMethod; - if (ccode == null || m == null || m.is_abstract || m.is_virtual) { - _finish_instance = !is_creation_method; - } else { - _finish_instance = ccode.get_bool ("finish_instance", !is_creation_method); - } - } - return _finish_instance; - } - } - - public bool delegate_target { - get { - if (_delegate_target == null) { - if (ccode != null) { - _delegate_target = ccode.get_bool ("delegate_target", get_default_delegate_target ()); - } else { - _delegate_target = get_default_delegate_target (); - } - } - return _delegate_target; - } - } - - public string delegate_target_name { - get { - if (_delegate_target_name == null) { - if (ccode != null) { - _delegate_target_name = ccode.get_string ("delegate_target_cname"); - } - if (_delegate_target_name == null) { - _delegate_target_name = "%s_target".printf (name); - } - } - return _delegate_target_name; - } - } - - public string delegate_target_destroy_notify_name { - get { - if (_delegate_target_destroy_notify_name == null) { - if (ccode != null) { - _delegate_target_destroy_notify_name = ccode.get_string ("destroy_notify_cname"); - } - if (_delegate_target_destroy_notify_name == null) { - _delegate_target_destroy_notify_name = "%s_destroy_notify".printf (delegate_target_name); - } - } - return _delegate_target_destroy_notify_name; - } - } - - public bool array_length { - get { - if (_array_length == null) { - if (node.get_attribute ("NoArrayLength") != null) { - Report.deprecated (node.source_reference, "[NoArrayLength] is deprecated, use [CCode (array_length = false)] instead."); - _array_length = false; - } else if (ccode != null && ccode.has_argument ("array_length")) { - _array_length = ccode.get_bool ("array_length"); - } else { - _array_length = get_default_array_length (); - } - } - return _array_length; - } - } - - public bool array_null_terminated { - get { - if (_array_null_terminated == null) { - // If arrays claim to have an array-length and also are null-terminated then rely on the given length - if (ccode != null && ccode.has_argument ("array_length") && ccode.get_bool ("array_length")) { - _array_null_terminated = false; - } else if (ccode != null && ccode.has_argument ("array_null_terminated")) { - _array_null_terminated = ccode.get_bool ("array_null_terminated"); - } else { - _array_null_terminated = get_default_array_null_terminated (); - } - } - return _array_null_terminated; - } - } - - public string array_length_type { - get { - if (_array_length_type == null) { - if (ccode != null && ccode.has_argument ("array_length_type")) { - _array_length_type = ccode.get_string ("array_length_type"); - } else { - _array_length_type = get_default_array_length_type (); - } - } - return _array_length_type; - } - } - - public string sentinel { - get { - if (_sentinel == null) { - if (ccode != null) { - _sentinel = ccode.get_string ("sentinel", "NULL"); - } else { - _sentinel = "NULL"; - } - } - return _sentinel; - } - } - - public string? array_length_name { get; private set; } - public string? array_length_expr { get; private set; } - - private string _name; - private string _const_name; - private string _type_name; - private string _feature_test_macros; - private string _header_filenames; - private string _prefix; - private string _lower_case_prefix; - private string _lower_case_suffix; - private string? _ref_function; - private bool ref_function_set; - private bool? _ref_function_void; - private string? _unref_function; - private bool unref_function_set; - private string _ref_sink_function; - private string? _copy_function; - private bool copy_function_set; - private string? _destroy_function; - private bool destroy_function_set; - private string? _dup_function; - private bool dup_function_set; - private string? _free_function; - private bool free_function_set; - private bool? _free_function_address_of; - private string _type_id; - private string _marshaller_type_name; - private string _get_value_function; - private string _set_value_function; - private string _take_value_function; - private string _param_spec_function; - private string _default_value; - private string _default_value_on_error; - private double? _pos; - private string _vfunc_name; - private string _finish_name; - private string _finish_vfunc_name; - private string _finish_real_name; - private bool? _finish_instance; - private string _real_name; - private bool? _delegate_target; - private string _delegate_target_name; - private string _delegate_target_destroy_notify_name; - private string _ctype; - private bool ctype_set = false; - private bool? _array_length; - private string _array_length_type; - private bool? _array_null_terminated; - private string _sentinel; - - private static int dynamic_method_id; - - public CCodeAttribute (CodeNode node) { - this.node = node; - this.sym = node as Symbol; - - ccode = node.get_attribute ("CCode"); - if (ccode != null) { - array_length_name = ccode.get_string ("array_length_cname"); - array_length_expr = ccode.get_string ("array_length_cexpr"); - } - } - - private string get_default_name () { - if (sym != null) { - if (sym is Constant && !(sym is EnumValue)) { - if (sym.parent_symbol is Block) { - // local constant - return sym.name; - } - return "%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol).ascii_up (), sym.name); - } else if (sym is Field) { - var cname = sym.name; - if (((Field) sym).binding == MemberBinding.STATIC) { - cname = "%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), sym.name); - } - if (cname[0].isdigit ()) { - Report.error (node.source_reference, "Field name starts with a digit. Use the `cname' attribute to provide a valid C name if intended"); - return ""; - } - return cname; - } else if (sym is CreationMethod) { - unowned CreationMethod m = (CreationMethod) sym; - string infix; - if (m.parent_symbol is Struct) { - infix = "init"; - } else { - infix = "new"; - } - if (m.name == ".new") { - return "%s%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), infix); - } else { - return "%s%s_%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), infix, m.name); - } - } else if (sym is DynamicMethod) { - return "_dynamic_%s%d".printf (sym.name, dynamic_method_id++); - } else if (sym is Method) { - unowned Method m = (Method) sym; - if (m.is_async_callback) { - return "%s_co".printf (get_ccode_real_name ((Method) m.parent_symbol)); - } - if (m.signal_reference != null) { - return "%s%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), get_ccode_lower_case_name (m.signal_reference)); - } - if (sym.name == "main" && sym.parent_symbol.name == null) { - // avoid conflict with generated main function - if (m.coroutine) { - return "_vala_main_async"; - } else { - return "_vala_main"; - } - } else if (sym.name.has_prefix ("_")) { - return "_%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), sym.name.substring (1)); - } else { - return "%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), sym.name); - } - } else if (sym is Property) { - return sym.name.replace ("_", "-"); - } else if (sym is PropertyAccessor) { - unowned PropertyAccessor acc = (PropertyAccessor) sym; - var t = (TypeSymbol) acc.prop.parent_symbol; - - if (acc.readable) { - return "%sget_%s".printf (get_ccode_lower_case_prefix (t), acc.prop.name); - } else { - return "%sset_%s".printf (get_ccode_lower_case_prefix (t), acc.prop.name); - } - } else if (sym is Signal) { - return Symbol.camel_case_to_lower_case (sym.name).replace ("_", "-");; - } else if (sym is LocalVariable) { - unowned string name = sym.name; - if (CCodeBaseModule.reserved_identifiers.contains (name)) { - return "_%s_".printf (name); - } else { - return name; - } - } else if (sym is Parameter) { - unowned Parameter param = (Parameter) sym; - if (param.ellipsis) { - return "..."; - } - unowned string name = sym.name; - if (CCodeBaseModule.reserved_identifiers.contains (name)) { - return "_%s_".printf (name); - } else { - return name; - } - } else if (sym is TypeParameter) { - assert (node is GenericType); - var type = (GenericType) node; - if (type.value_owned) { - if (CodeContext.get ().profile == Profile.GOBJECT) { - return "gpointer"; - } else { - return "void *"; - } - } else { - if (CodeContext.get ().profile == Profile.GOBJECT) { - return "gconstpointer"; - } else { - return "const void *"; - } - } - } else { - return "%s%s".printf (get_ccode_prefix (sym.parent_symbol), sym.name); - } - } else if (node is ObjectType) { - var type = (ObjectType) node; - - string cname; - if (!type.value_owned) { - cname = get_ccode_const_name (type.type_symbol); - } else { - cname = get_ccode_name (type.type_symbol); - } - return "%s*".printf (cname); - } else if (node is ArrayType) { - var type = (ArrayType) node; - var cname = get_ccode_name (type.element_type); - if (type.inline_allocated) { - return cname; - } else { - return "%s*".printf (cname); - } - } else if (node is DelegateType) { - var type = (DelegateType) node; - return get_ccode_name (type.delegate_symbol); - } else if (node is ErrorType) { - return "GError*"; - } else if (node is GenericType) { - var type = (GenericType) node; - if (type.value_owned) { - if (CodeContext.get ().profile == Profile.GOBJECT) { - return "gpointer"; - } else { - return "void *"; - } - } else { - if (CodeContext.get ().profile == Profile.GOBJECT) { - return "gconstpointer"; - } else { - return "const void *"; - } - } - } else if (node is MethodType) { - if (CodeContext.get ().profile == Profile.GOBJECT) { - return "gpointer"; - } else { - return "void *"; - } - } else if (node is NullType) { - if (CodeContext.get ().profile == Profile.GOBJECT) { - return "gpointer"; - } else { - return "void *"; - } - } else if (node is PointerType) { - var type = (PointerType) node; - if (type.base_type.type_symbol != null && type.base_type.type_symbol.is_reference_type ()) { - return get_ccode_name (type.base_type); - } else { - return "%s*".printf (get_ccode_name (type.base_type)); - } - } else if (node is VoidType) { - return "void"; - } else if (node is ClassType) { - var type = (ClassType) node; - return "%s*".printf (get_ccode_type_name (type.class_symbol)); - } else if (node is InterfaceType) { - var type = (InterfaceType) node; - return "%s*".printf (get_ccode_type_name (type.interface_symbol)); - } else if (node is ValueType) { - var type = (ValueType) node; - var cname = get_ccode_name (type.type_symbol); - if (type.nullable) { - return "%s*".printf (cname); - } else { - return cname; - } - } else if (node is CType) { - return ((CType) node).ctype_name; - } else { - Report.error (node.source_reference, "Unresolved type reference"); - return ""; - } - } - - private string get_default_header_filenames () { - if (sym is DynamicProperty || sym is DynamicMethod) { - return ""; - } - if (sym.parent_symbol != null && !sym.is_extern) { - var parent_headers = get_ccode_header_filenames (sym.parent_symbol); - if (parent_headers.length > 0) { - return parent_headers; - } - } - if (sym.source_reference != null && !sym.external_package && !sym.is_extern) { - // don't add default include directives for VAPI files - return sym.source_reference.file.get_cinclude_filename (); - } - return ""; - } - - private string get_default_prefix () { - if (sym is ObjectTypeSymbol) { - return name; - } else if (sym is Enum || sym is ErrorDomain) { - return "%s_".printf (get_ccode_upper_case_name (sym)); - } else if (sym is Namespace) { - if (sym.name != null) { - var parent_prefix = ""; - if (sym.parent_symbol != null) { - parent_prefix = get_ccode_prefix (sym.parent_symbol); - } - return "%s%s".printf (parent_prefix, sym.name); - } else { - return ""; - } - } else if (sym.name != null) { - return sym.name; - } - return ""; - } - - private string get_default_lower_case_prefix () { - if (sym is Namespace) { - if (sym.name == null) { - return ""; - } else { - return "%s%s_".printf (get_ccode_lower_case_prefix (sym.parent_symbol), Symbol.camel_case_to_lower_case (sym.name)); - } - } else if (sym is Method) { - // for lambda expressions - return ""; - } else { - return "%s_".printf (get_ccode_lower_case_name (sym)); - } - } - - private string get_default_lower_case_suffix () { - if (sym is ObjectTypeSymbol) { - var csuffix = Symbol.camel_case_to_lower_case (sym.name); - - // FIXME Code duplication with GirParser.Node.get_default_lower_case_suffix() - // remove underscores in some cases to avoid conflicts of type macros - if (csuffix.has_prefix ("type_")) { - csuffix = "type" + csuffix.substring ("type_".length); - } else if (csuffix.has_prefix ("is_")) { - csuffix = "is" + csuffix.substring ("is_".length); - } - if (csuffix.has_suffix ("_class")) { - csuffix = csuffix.substring (0, csuffix.length - "_class".length) + "class"; - } - return csuffix; - } else if (sym is Signal) { - return get_ccode_attribute (sym).name.replace ("-", "_"); - } else if (sym.name != null) { - return Symbol.camel_case_to_lower_case (sym.name); - } - return ""; - } - - private string? get_default_ref_function () { - if (sym is Class) { - unowned Class cl = (Class) sym; - if (cl.is_fundamental ()) { - return "%sref".printf (lower_case_prefix); - } else if (cl.base_class != null) { - return get_ccode_ref_function (cl.base_class); - } - } else if (sym is Interface) { - foreach (var prereq in ((Interface) sym).get_prerequisites ()) { - string ref_func = get_ccode_ref_function ((ObjectTypeSymbol) prereq.type_symbol); - if (ref_func != null) { - return ref_func; - } - } - } - return null; - } - - private string? get_default_unref_function () { - if (sym is Class) { - unowned Class cl = (Class) sym; - if (cl.is_fundamental ()) { - return "%sunref".printf (lower_case_prefix); - } else if (cl.base_class != null) { - return get_ccode_unref_function (cl.base_class); - } - } else if (sym is Interface) { - foreach (var prereq in ((Interface) sym).get_prerequisites ()) { - string unref_func = get_ccode_unref_function ((ObjectTypeSymbol) prereq.type_symbol); - if (unref_func != null) { - return unref_func; - } - } - } - return null; - } - - private string get_default_ref_sink_function () { - if (sym is Class) { - unowned Class? base_class = ((Class) sym).base_class; - if (base_class != null) { - return get_ccode_ref_sink_function (base_class); - } - } else if (sym is Interface) { - foreach (var prereq in ((Interface) sym).get_prerequisites ()) { - string ref_sink_func = get_ccode_ref_sink_function ((ObjectTypeSymbol) prereq.type_symbol); - if (ref_sink_func != "") { - return ref_sink_func; - } - } - } - return ""; - } - - private string? get_default_free_function () { - if (sym is Class) { - unowned Class cl = (Class) sym; - if (cl.base_class != null) { - return get_ccode_free_function (cl.base_class); - } - return "%sfree".printf (lower_case_prefix); - } else if (sym is Struct) { - if (!sym.external_package && !((Struct) sym).is_simple_type ()) { - return "%sfree".printf (lower_case_prefix); - } - } - return null; - } - - private string get_default_type_id () { - if (sym != null) { - if (sym is Class && !((Class) sym).is_compact || sym is Interface) { - return get_ccode_upper_case_name (sym, "TYPE_"); - } else if (sym is Struct) { - unowned Struct st = (Struct) sym; - unowned Struct? base_struct = st.base_struct; - if (!get_ccode_has_type_id (st) || (base_struct != null && base_struct.is_simple_type ())) { - if (base_struct != null) { - return get_ccode_type_id (base_struct); - } - if (!st.is_simple_type ()) { - return "G_TYPE_POINTER"; - } - } else { - return get_ccode_upper_case_name (st, "TYPE_"); - } - } else if (sym is Enum) { - unowned Enum en = (Enum) sym; - if (get_ccode_has_type_id (en)) { - return get_ccode_upper_case_name (en, "TYPE_"); - } else { - return en.is_flags ? "G_TYPE_UINT" : "G_TYPE_INT"; - } - } else { - return "G_TYPE_POINTER"; - } - } else if (node is ArrayType && ((ArrayType) node).element_type.type_symbol == CodeContext.get ().analyzer.string_type.type_symbol) { - return "G_TYPE_STRV"; - } else if (node is PointerType || node is DelegateType) { - return "G_TYPE_POINTER"; - } else if (node is ErrorType) { - return "G_TYPE_ERROR"; - } else if (node is VoidType) { - return "G_TYPE_NONE"; - } else { - var type = (DataType) node; - if (type.type_symbol != null) { - return get_ccode_type_id (type.type_symbol); - } - } - return ""; - } - - private string get_default_marshaller_type_name () { - if (sym != null) { - if (sym is Class) { - unowned Class cl = (Class) sym; - if (cl.base_class != null) { - return get_ccode_marshaller_type_name (cl.base_class); - } else if (!cl.is_compact) { - return get_ccode_upper_case_name (cl); - } else if (type_id == "G_TYPE_POINTER") { - return "POINTER"; - } else { - return "BOXED"; - } - } else if (sym is Enum) { - unowned Enum en = (Enum) sym; - if (get_ccode_has_type_id (en)) { - if (en.is_flags) { - return "FLAGS"; - } else { - return "ENUM"; - } - } else { - if (en.is_flags) { - return "UINT"; - } else { - return "INT"; - } - } - } else if (sym is Interface) { - foreach (var prereq in ((Interface) sym).get_prerequisites ()) { - var type_name = get_ccode_marshaller_type_name (prereq.type_symbol); - if (type_name != "") { - return type_name; - } - } - return "POINTER"; - } else if (sym is Struct) { - unowned Struct st = (Struct) sym; - unowned Struct? base_st = st.base_struct; - while (base_st != null) { - if (get_ccode_has_type_id (base_st)) { - return get_ccode_marshaller_type_name (base_st); - } else { - base_st = base_st.base_struct; - } - } - if (st.is_simple_type ()) { - Report.error (st.source_reference, "The type `%s' doesn't declare a marshaller type name", st.get_full_name ()); - } else if (get_ccode_has_type_id (st)) { - return "BOXED"; - } else { - return "POINTER"; - } - } else if (sym is Parameter) { - unowned Parameter param = (Parameter) sym; - if (param.direction != ParameterDirection.IN) { - return "POINTER"; - } else { - return get_ccode_marshaller_type_name (param.variable_type); - } - } else { - return "POINTER"; - } - } else if (node is ValueType && ((ValueType) node).nullable) { - return "POINTER"; - } else if (node is PointerType || node is GenericType) { - return "POINTER"; - } else if (node is ErrorType) { - return "POINTER"; - } else if (node is ArrayType) { - unowned ArrayType array_type = (ArrayType) node; - if (array_type.element_type.type_symbol == CodeContext.get ().analyzer.string_type.type_symbol) { - return "BOXED,%s".printf (get_ccode_marshaller_type_name (array_type.length_type.type_symbol)); - } else { - var ret = "POINTER"; - var length_marshaller_type_name = get_ccode_marshaller_type_name (array_type.length_type.type_symbol); - for (var i = 0; i < array_type.rank; i++) { - ret = "%s,%s".printf (ret, length_marshaller_type_name); - } - return ret; - } - } else if (node is DelegateType) { - unowned DelegateType delegate_type = (DelegateType) node; - var ret = "POINTER"; - if (delegate_type.delegate_symbol.has_target) { - ret = "%s,POINTER".printf (ret); - if (delegate_type.is_disposable ()) { - ret = "%s,POINTER".printf (ret); - } - } - return ret; - } else if (node is VoidType) { - return "VOID"; - } else { - return get_ccode_marshaller_type_name (((DataType) node).type_symbol); - } - return ""; - } - - private string get_default_get_value_function () { - if (sym is Class) { - unowned Class cl = (Class) sym; - if (cl.is_fundamental ()) { - return get_ccode_lower_case_name (cl, "value_get_"); - } else if (cl.base_class != null) { - return get_ccode_get_value_function (cl.base_class); - } else if (type_id == "G_TYPE_POINTER") { - return "g_value_get_pointer"; - } else { - return "g_value_get_boxed"; - } - } else if (sym is Enum) { - unowned Enum en = (Enum) sym; - if (get_ccode_has_type_id (en)) { - if (en.is_flags) { - return "g_value_get_flags"; - } else { - return "g_value_get_enum"; - } - } else { - if (en.is_flags) { - return "g_value_get_uint"; - } else { - return "g_value_get_int"; - } - } - } else if (sym is Interface) { - foreach (var prereq in ((Interface) sym).get_prerequisites ()) { - var type_name = get_ccode_get_value_function (prereq.type_symbol); - if (type_name != "") { - return type_name; - } - } - return "g_value_get_pointer"; - } else if (sym is Struct) { - unowned Struct st = (Struct) sym; - unowned Struct? base_st = st.base_struct; - while (base_st != null) { - if (get_ccode_has_type_id (base_st)) { - return get_ccode_get_value_function (base_st); - } else { - base_st = base_st.base_struct; - } - } - if (st.is_simple_type ()) { - Report.error (st.source_reference, "The type `%s' doesn't declare a GValue get function", st.get_full_name ()); - } else if (get_ccode_has_type_id (st)) { - return "g_value_get_boxed"; - } else { - return "g_value_get_pointer"; - } - } else { - return "g_value_get_pointer"; - } - return ""; - } - - private string get_default_set_value_function () { - if (sym is Class) { - unowned Class cl = (Class) sym; - if (cl.is_fundamental ()) { - return get_ccode_lower_case_name (cl, "value_set_"); - } else if (cl.base_class != null) { - return get_ccode_set_value_function (cl.base_class); - } else if (type_id == "G_TYPE_POINTER") { - return "g_value_set_pointer"; - } else { - return "g_value_set_boxed"; - } - } else if (sym is Enum) { - unowned Enum en = (Enum) sym; - if (get_ccode_has_type_id (en)) { - if (en.is_flags) { - return "g_value_set_flags"; - } else { - return "g_value_set_enum"; - } - } else { - if (en.is_flags) { - return "g_value_set_uint"; - } else { - return "g_value_set_int"; - } - } - } else if (sym is Interface) { - foreach (var prereq in ((Interface) sym).get_prerequisites ()) { - var type_name = get_ccode_set_value_function (prereq.type_symbol); - if (type_name != "") { - return type_name; - } - } - return "g_value_set_pointer"; - } else if (sym is Struct) { - unowned Struct st = (Struct) sym; - unowned Struct? base_st = st.base_struct; - while (base_st != null) { - if (get_ccode_has_type_id (base_st)) { - return get_ccode_set_value_function (base_st); - } else { - base_st = base_st.base_struct; - } - } - if (st.is_simple_type ()) { - Report.error (st.source_reference, "The type `%s' doesn't declare a GValue set function", st.get_full_name ()); - } else if (get_ccode_has_type_id (st)) { - return "g_value_set_boxed"; - } else { - return "g_value_set_pointer"; - } - } else { - return "g_value_set_pointer"; - } - return ""; - } - - private string get_default_take_value_function () { - if (sym is Class) { - unowned Class cl = (Class) sym; - if (cl.is_fundamental ()) { - return get_ccode_lower_case_name (cl, "value_take_"); - } else if (cl.base_class != null) { - return get_ccode_take_value_function (cl.base_class); - } else if (type_id == "G_TYPE_POINTER") { - return "g_value_set_pointer"; - } else { - return "g_value_take_boxed"; - } - } else if (sym is Enum) { - unowned Enum en = (Enum) sym; - if (get_ccode_has_type_id (en)) { - if (en.is_flags) { - return "g_value_take_flags"; - } else { - return "g_value_take_enum"; - } - } else { - if (en.is_flags) { - return "g_value_take_uint"; - } else { - return "g_value_take_int"; - } - } - } else if (sym is Interface) { - foreach (var prereq in ((Interface) sym).get_prerequisites ()) { - var func = get_ccode_take_value_function (prereq.type_symbol); - if (func != "") { - return func; - } - } - return "g_value_set_pointer"; - } else if (sym is Struct) { - unowned Struct st = (Struct) sym; - unowned Struct? base_st = st.base_struct; - while (base_st != null) { - if (get_ccode_has_type_id (base_st)) { - return get_ccode_take_value_function (base_st); - } else { - base_st = base_st.base_struct; - } - } - if (st.is_simple_type ()) { - Report.error (st.source_reference, "The type `%s' doesn't declare a GValue take function", st.get_full_name ()); - } else if (get_ccode_has_type_id (st)) { - return "g_value_take_boxed"; - } else { - return "g_value_set_pointer"; - } - } else { - return "g_value_set_pointer"; - } - return ""; - } - - private string get_default_param_spec_function () { - if (node is Symbol) { - if (sym is Class) { - unowned Class cl = (Class) sym; - if (cl.is_fundamental ()) { - return get_ccode_lower_case_name (cl, "param_spec_"); - } else if (cl.base_class != null) { - return get_ccode_param_spec_function (cl.base_class); - } else if (type_id == "G_TYPE_POINTER") { - return "g_param_spec_pointer"; - } else { - return "g_param_spec_boxed"; - } - } else if (sym is Interface) { - foreach (var prereq in ((Interface) sym).get_prerequisites ()) { - var func = get_ccode_param_spec_function (prereq.type_symbol); - if (func != "") { - return func; - } - } - return "g_param_spec_pointer"; - } else if (sym is Enum) { - unowned Enum e = (Enum) sym; - if (get_ccode_has_type_id (e)) { - if (e.is_flags) { - return "g_param_spec_flags"; - } else { - return "g_param_spec_enum"; - } - } else { - if (e.is_flags) { - return "g_param_spec_uint"; - } else { - return "g_param_spec_int"; - } - } - } else if (sym is Struct) { - var type_id = get_ccode_type_id (sym); - if (type_id == "G_TYPE_INT") { - return "g_param_spec_int"; - } else if (type_id == "G_TYPE_UINT") { - return "g_param_spec_uint"; - } else if (type_id == "G_TYPE_INT64") { - return "g_param_spec_int64"; - } else if (type_id == "G_TYPE_UINT64") { - return "g_param_spec_uint64"; - } else if (type_id == "G_TYPE_LONG") { - return "g_param_spec_long"; - } else if (type_id == "G_TYPE_ULONG") { - return "g_param_spec_ulong"; - } else if (type_id == "G_TYPE_BOOLEAN") { - return "g_param_spec_boolean"; - } else if (type_id == "G_TYPE_CHAR") { - return "g_param_spec_char"; - } else if (type_id == "G_TYPE_UCHAR") { - return "g_param_spec_uchar"; - }else if (type_id == "G_TYPE_FLOAT") { - return "g_param_spec_float"; - } else if (type_id == "G_TYPE_DOUBLE") { - return "g_param_spec_double"; - } else if (type_id == "G_TYPE_GTYPE") { - return "g_param_spec_gtype"; - } else { - return "g_param_spec_boxed"; - } - } - } else if (node is ArrayType && ((ArrayType) node).element_type.type_symbol == CodeContext.get ().analyzer.string_type.type_symbol) { - return "g_param_spec_boxed"; - } else if (node is DataType && ((DataType) node).type_symbol != null) { - return get_ccode_param_spec_function (((DataType) node).type_symbol); - } - - return "g_param_spec_pointer"; - } - - private string get_default_default_value () { - if (sym is Enum) { - unowned Enum en = (Enum) sym; - if (en.is_flags) { - return "0U"; - } else { - return "0"; - } - } else if (sym is Struct) { - unowned Struct st = (Struct) sym; - unowned Struct? base_st = st.base_struct; - if (base_st != null) { - return get_ccode_default_value (base_st); - } - } - return ""; - } - - private string get_finish_name_for_basename (string basename) { - string result = basename; - if (result.has_suffix ("_async")) { - result = result.substring (0, result.length - "_async".length); - } - return "%s_finish".printf (result); - } - - private string get_default_real_name () { - if (sym is CreationMethod) { - unowned CreationMethod m = (CreationMethod) sym; - unowned Class? parent = m.parent_symbol as Class; - - if (parent == null || parent.is_compact) { - return name; - } - - string infix = "construct"; - - if (m.name == ".new") { - return "%s%s".printf (get_ccode_lower_case_prefix (parent), infix); - } else { - return "%s%s_%s".printf (get_ccode_lower_case_prefix (parent), infix, m.name); - } - } else if (sym is Method) { - unowned Method m = (Method) sym; - if (m.base_method != null || m.base_interface_method != null || m.signal_reference != null) { - string m_name; - if (m.signal_reference != null) { - m_name = get_ccode_lower_case_name (m.signal_reference); - } else { - m_name = m.name; - } - if (m.base_interface_type != null) { - return "%sreal_%s%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), - get_ccode_lower_case_prefix (m.base_interface_type.type_symbol), - m_name); - } else { - return "%sreal_%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), m_name); - } - } else { - return name; - } - } else if (sym is PropertyAccessor) { - unowned PropertyAccessor acc = (PropertyAccessor) sym; - unowned Property prop = (Property) acc.prop; - if (prop.base_property != null || prop.base_interface_property != null) { - if (acc.readable) { - return "%sreal_get_%s".printf (get_ccode_lower_case_prefix (prop.parent_symbol), prop.name); - } else { - return "%sreal_set_%s".printf (get_ccode_lower_case_prefix (prop.parent_symbol), prop.name); - } - } else { - return name; - } - } - assert_not_reached (); - } - - private string get_default_const_name () { - if (node is DataType) { - unowned DataType type = (DataType) node; - string ptr; - TypeSymbol t; - // FIXME: workaround to make constant arrays possible - if (type is ArrayType) { - t = ((ArrayType) type).element_type.type_symbol; - } else { - t = type.type_symbol; - } - if (!t.is_reference_type ()) { - ptr = ""; - } else { - ptr = "*"; - } - - return "const %s%s".printf (get_ccode_name (t), ptr); - } else { - if (node is Class && ((Class) node).is_immutable) { - return "const %s".printf (name); - } else { - return name; - } - } - } - - private bool get_default_delegate_target () { - if (node is Field || node is Parameter || node is LocalVariable) { - if (node is Parameter) { - unowned Parameter param = (Parameter) node; - if (param.base_parameter != null) { - return get_ccode_delegate_target (param.base_parameter); - } - } - unowned DelegateType? delegate_type = ((Variable) node).variable_type as DelegateType; - return delegate_type != null && delegate_type.delegate_symbol.has_target; - } else if (node is Callable) { - if (node is Method) { - unowned Method method = (Method) node; - if (method.base_method != null && method.base_method != method) { - return get_ccode_delegate_target (method.base_method); - } else if (method.base_interface_method != null && method.base_interface_method != method) { - return get_ccode_delegate_target (method.base_interface_method); - } - } - unowned DelegateType? delegate_type = ((Callable) node).return_type as DelegateType; - return delegate_type != null && delegate_type.delegate_symbol.has_target; - } else if (node is Property) { - unowned Property prop = (Property) node; - if (prop.base_property != null && prop.base_property != prop) { - return get_ccode_delegate_target (prop.base_property); - } else if (prop.base_interface_property != null && prop.base_interface_property != prop) { - return get_ccode_delegate_target (prop.base_interface_property); - } - unowned DelegateType? delegate_type = prop.property_type as DelegateType; - return delegate_type != null && delegate_type.delegate_symbol.has_target; - } else if (node is PropertyAccessor) { - return get_ccode_delegate_target (((PropertyAccessor) node).prop); - } else if (node is Expression) { - unowned Symbol? symbol = ((Expression) node).symbol_reference; - if (symbol != null) { - return get_ccode_delegate_target (symbol); - } - } - return false; - } - - private bool get_default_array_length () { - if (node is Parameter) { - unowned Parameter param = (Parameter) node; - if (param.base_parameter != null) { - return get_ccode_array_length (param.base_parameter); - } - } else if (node is Method) { - unowned Method method = (Method) node; - if (method.base_method != null && method.base_method != method) { - return get_ccode_array_length (method.base_method); - } else if (method.base_interface_method != null && method.base_interface_method != method) { - return get_ccode_array_length (method.base_interface_method); - } - } else if (node is Property) { - unowned Property prop = (Property) node; - if (prop.base_property != null && prop.base_property != prop) { - return get_ccode_array_length (prop.base_property); - } else if (prop.base_interface_property != null && prop.base_interface_property != prop) { - return get_ccode_array_length (prop.base_interface_property); - } - } else if (node is PropertyAccessor) { - return get_ccode_array_length (((PropertyAccessor) node).prop); - } - return true; - } - - private bool get_default_array_null_terminated () { - if (node is Parameter) { - unowned Parameter param = (Parameter) node; - if (param.base_parameter != null) { - return get_ccode_array_null_terminated (param.base_parameter); - } - } else if (node is Method) { - unowned Method method = (Method) node; - if (method.base_method != null && method.base_method != method) { - return get_ccode_array_null_terminated (method.base_method); - } else if (method.base_interface_method != null && method.base_interface_method != method) { - return get_ccode_array_null_terminated (method.base_interface_method); - } - } else if (node is Property) { - unowned Property prop = (Property) node; - if (prop.base_property != null && prop.base_property != prop) { - return get_ccode_array_null_terminated (prop.base_property); - } else if (prop.base_interface_property != null && prop.base_interface_property != prop) { - return get_ccode_array_null_terminated (prop.base_interface_property); - } - } else if (node is PropertyAccessor) { - return get_ccode_array_null_terminated (((PropertyAccessor) node).prop); - } - return false; - } - - private string get_default_array_length_type () { - if (node is Field || node is Parameter) { - if (node is Parameter) { - unowned Parameter param = (Parameter) node; - if (param.base_parameter != null) { - return get_ccode_array_length_type (param.base_parameter); - } - } - return get_ccode_array_length_type (((Variable) node).variable_type); - } else if (node is Method || node is Delegate) { - if (node is Method) { - unowned Method method = (Method) node; - if (method.base_method != null && method.base_method != method) { - return get_ccode_array_length_type (method.base_method); - } else if (method.base_interface_method != null && method.base_interface_method != method) { - return get_ccode_array_length_type (method.base_interface_method); - } - } - return get_ccode_array_length_type (((Callable) node).return_type); - } else if (node is Property) { - unowned Property prop = (Property) node; - if (prop.base_property != null && prop.base_property != prop) { - return get_ccode_array_length_type (prop.base_property); - } else if (prop.base_interface_property != null && prop.base_interface_property != prop) { - return get_ccode_array_length_type (prop.base_interface_property); - } else { - return get_ccode_array_length_type (prop.property_type); - } - } else if (node is PropertyAccessor) { - return get_ccode_array_length_type (((PropertyAccessor) node).prop); - } else { - Report.error (node.source_reference, "`CCode.array_length_type' not supported"); - return ""; - } - } -} diff --git a/src/codegen/valaccodebasemodule.vala b/src/codegen/valaccodebasemodule.vala deleted file mode 100644 index 65a6df560..000000000 --- a/src/codegen/valaccodebasemodule.vala +++ /dev/null @@ -1,6859 +0,0 @@ -/* valaccodebasemodule.vala - * - * Copyright (C) 2006-2012 Jürg Billeter - * Copyright (C) 2006-2008 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.1 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 - * Raffaele Sandrini - */ - - -/** - * Code visitor generating C Code. - */ -public abstract class Vala.CCodeBaseModule : CodeGenerator { - public class EmitContext { - public Symbol? current_symbol; - public ArrayList symbol_stack = new ArrayList (); - public TryStatement current_try; - public int current_try_id; - public int next_try_id; - public CatchClause current_catch; - public CCodeFunction ccode; - public ArrayList ccode_stack = new ArrayList (); - public ArrayList temp_ref_values = new ArrayList (); - public int next_temp_var_id; - public int current_inner_error_id; - public bool current_method_inner_error; - public bool current_method_return; - public int next_coroutine_state = 1; - public Map variable_name_map = new HashMap (str_hash, str_equal); - public Map closure_variable_count_map = new HashMap (str_hash, str_equal); - public Map closure_variable_clash_map = new HashMap (); - public bool is_in_method_precondition; - - public EmitContext (Symbol? symbol = null) { - current_symbol = symbol; - } - - public void push_symbol (Symbol symbol) { - symbol_stack.add (current_symbol); - current_symbol = symbol; - } - - public void pop_symbol () { - current_symbol = symbol_stack.remove_at (symbol_stack.size - 1); - } - } - - public CodeContext context { get; set; } - - public Symbol root_symbol; - - public EmitContext emit_context = new EmitContext (); - - List emit_context_stack = new ArrayList (); - - public CCodeLineDirective? current_line = null; - - List line_directive_stack = new ArrayList (); - - public Symbol current_symbol { get { return emit_context.current_symbol; } } - - public TryStatement current_try { - get { return emit_context.current_try; } - set { emit_context.current_try = value; } - } - - public int current_try_id { - get { return emit_context.current_try_id; } - set { emit_context.current_try_id = value; } - } - - public int next_try_id { - get { return emit_context.next_try_id; } - set { emit_context.next_try_id = value; } - } - - public CatchClause current_catch { - get { return emit_context.current_catch; } - set { emit_context.current_catch = value; } - } - - public int current_inner_error_id { - get { return emit_context.current_inner_error_id; } - set { emit_context.current_inner_error_id = value; } - } - - public bool is_in_method_precondition { - get { return emit_context.is_in_method_precondition; } - set { emit_context.is_in_method_precondition = value; } - } - - public TypeSymbol? current_type_symbol { - get { - var sym = current_symbol; - while (sym != null) { - if (sym is TypeSymbol) { - return (TypeSymbol) sym; - } - sym = sym.parent_symbol; - } - return null; - } - } - - public Class? current_class { - get { return current_type_symbol as Class; } - } - - public Method? current_method { - get { - var sym = current_symbol; - while (sym is Block) { - sym = sym.parent_symbol; - } - return sym as Method; - } - } - - public PropertyAccessor? current_property_accessor { - get { - var sym = current_symbol; - while (sym is Block) { - sym = sym.parent_symbol; - } - return sym as PropertyAccessor; - } - } - - public Constructor? current_constructor { - get { - var sym = current_symbol; - while (sym is Block) { - sym = sym.parent_symbol; - } - return sym as Constructor; - } - } - - public Destructor? current_destructor { - get { - var sym = current_symbol; - while (sym is Block) { - sym = sym.parent_symbol; - } - return sym as Destructor; - } - } - - public DataType? current_return_type { - get { - var m = current_method; - if (m != null) { - return m.return_type; - } - - var acc = current_property_accessor; - if (acc != null) { - if (acc.readable) { - return acc.value_type; - } else { - return void_type; - } - } - - if (is_in_constructor () || is_in_destructor ()) { - return void_type; - } - - return null; - } - } - - public bool is_in_coroutine () { - return current_method != null && current_method.coroutine; - } - - public bool is_in_constructor () { - if (current_method != null) { - // make sure to not return true in lambda expression inside constructor - return false; - } - var sym = current_symbol; - while (sym != null) { - if (sym is Constructor) { - return true; - } - sym = sym.parent_symbol; - } - return false; - } - - public bool is_in_destructor () { - if (current_method != null) { - // make sure to not return true in lambda expression inside constructor - return false; - } - var sym = current_symbol; - while (sym != null) { - if (sym is Destructor) { - return true; - } - sym = sym.parent_symbol; - } - return false; - } - - public Block? current_closure_block { - get { - return next_closure_block (current_symbol); - } - } - - public unowned Block? next_closure_block (Symbol sym) { - while (true) { - unowned Method method = sym as Method; - if (method != null && !method.closure) { - // parent blocks are not captured by this method - break; - } - - unowned Block block = sym as Block; - if (method == null && block == null) { - // no closure block - break; - } - - if (block != null && block.captured) { - // closure block found - return block; - } - sym = sym.parent_symbol; - } - return null; - } - - public CCodeFile header_file; - public CCodeFile internal_header_file; - public CCodeFile cfile; - - public EmitContext class_init_context; - public EmitContext base_init_context; - public EmitContext class_finalize_context; - public EmitContext base_finalize_context; - public EmitContext instance_init_context; - public EmitContext instance_finalize_context; - - public CCodeStruct param_spec_struct; - public CCodeStruct closure_struct; - public CCodeEnum prop_enum; - public CCodeEnum signal_enum; - - public CCodeFunction ccode { get { return emit_context.ccode; } } - - /* temporary variables that own their content */ - public ArrayList temp_ref_values { get { return emit_context.temp_ref_values; } } - /* cache to check whether a certain marshaller has been created yet */ - public Set user_marshal_set; - /* (constant) hash table with all predefined marshallers */ - public Set predefined_marshal_set; - /* (constant) hash table with all reserved identifiers in the generated code */ - public static Set reserved_identifiers; - - public int next_temp_var_id { - get { return emit_context.next_temp_var_id; } - set { emit_context.next_temp_var_id = value; } - } - - public int next_regex_id = 0; - public bool in_creation_method { get { return current_method is CreationMethod; } } - - public bool current_method_inner_error { - get { return emit_context.current_method_inner_error; } - set { emit_context.current_method_inner_error = value; } - } - - public bool current_method_return { - get { return emit_context.current_method_return; } - set { emit_context.current_method_return = value; } - } - - int next_block_id = 0; - Map block_map = new HashMap (); - - /* count of emitted inner_error variables in methods */ - Map method_inner_error_var_count = new HashMap (); - - public DataType void_type = new VoidType (); - public DataType bool_type; - public DataType char_type; - public DataType uchar_type; - public DataType? unichar_type; - public DataType short_type; - public DataType ushort_type; - public DataType int_type; - public DataType uint_type; - public DataType long_type; - public DataType ulong_type; - public DataType int8_type; - public DataType uint8_type; - public DataType int16_type; - public DataType uint16_type; - public DataType int32_type; - public DataType uint32_type; - public DataType int64_type; - public DataType uint64_type; - public DataType size_t_type; - public DataType ssize_t_type; - public DataType string_type; - public DataType regex_type; - public DataType float_type; - public DataType double_type; - public DataType pointer_type; - public TypeSymbol gtype_type; - public TypeSymbol gobject_type; - public ErrorType gerror_type; - public Class glist_type; - public Class gslist_type; - public Class gnode_type; - public Class gqueue_type; - public Class gvaluearray_type; - public TypeSymbol gstringbuilder_type; - public Class garray_type; - public TypeSymbol gbytearray_type; - public TypeSymbol genericarray_type; - public Class gsequence_type; - public Class gsequence_iter_type; - public TypeSymbol gthreadpool_type; - public DataType gquark_type; - public Struct gvalue_type; - public Class gvariant_type; - public Struct mutex_type; - public Struct gmutex_type; - public Struct grecmutex_type; - public Struct grwlock_type; - public Struct gcond_type; - public Class gsource_type; - public TypeSymbol type_module_type; - public TypeSymbol dbus_proxy_type; - public Class gtk_widget_type; - public DataType delegate_target_type; - public DelegateType delegate_target_destroy_type; - Delegate destroy_notify; - Class gerror; - - public bool in_plugin = false; - public string module_init_param_name; - - public bool requires_assert; - public bool requires_array_free; - public bool requires_array_move; - public bool requires_array_length; - public bool requires_array_n_elements; - public bool requires_clear_mutex; - public bool requires_memdup2; - public bool requires_vala_extern; - - public Set wrappers; - Set generated_external_symbols; - - public Map variable_name_map { get { return emit_context.variable_name_map; } } - - public static int ccode_attribute_cache_index = CodeNode.get_attribute_cache_index (); - - protected CCodeBaseModule () { - if (Vala.get_build_version () != Vala.BUILD_VERSION) { - Report.error (null, "Integrity check failed (libvala %s doesn't match ccodegen %s)".printf (Vala.get_build_version (), Vala.BUILD_VERSION)); - } - - predefined_marshal_set = new HashSet (str_hash, str_equal); - predefined_marshal_set.add ("VOID:VOID"); - predefined_marshal_set.add ("VOID:BOOLEAN"); - predefined_marshal_set.add ("VOID:CHAR"); - predefined_marshal_set.add ("VOID:UCHAR"); - predefined_marshal_set.add ("VOID:INT"); - predefined_marshal_set.add ("VOID:UINT"); - predefined_marshal_set.add ("VOID:LONG"); - predefined_marshal_set.add ("VOID:ULONG"); - predefined_marshal_set.add ("VOID:ENUM"); - predefined_marshal_set.add ("VOID:FLAGS"); - predefined_marshal_set.add ("VOID:FLOAT"); - predefined_marshal_set.add ("VOID:DOUBLE"); - predefined_marshal_set.add ("VOID:STRING"); - predefined_marshal_set.add ("VOID:POINTER"); - predefined_marshal_set.add ("VOID:OBJECT"); - predefined_marshal_set.add ("STRING:OBJECT,POINTER"); - predefined_marshal_set.add ("VOID:UINT,POINTER"); - predefined_marshal_set.add ("BOOLEAN:FLAGS"); - predefined_marshal_set.add ("VOID:BOXED"); - predefined_marshal_set.add ("VOID:VARIANT"); - predefined_marshal_set.add ("BOOLEAN:BOXED,BOXED"); - - reserved_identifiers = new HashSet (str_hash, str_equal); - - // C99 keywords - reserved_identifiers.add ("_Bool"); - reserved_identifiers.add ("_Complex"); - reserved_identifiers.add ("_Imaginary"); - reserved_identifiers.add ("asm"); - reserved_identifiers.add ("auto"); - reserved_identifiers.add ("break"); - reserved_identifiers.add ("case"); - reserved_identifiers.add ("char"); - reserved_identifiers.add ("const"); - reserved_identifiers.add ("continue"); - reserved_identifiers.add ("default"); - reserved_identifiers.add ("do"); - reserved_identifiers.add ("double"); - reserved_identifiers.add ("else"); - reserved_identifiers.add ("enum"); - reserved_identifiers.add ("extern"); - reserved_identifiers.add ("float"); - reserved_identifiers.add ("for"); - reserved_identifiers.add ("goto"); - reserved_identifiers.add ("if"); - reserved_identifiers.add ("inline"); - reserved_identifiers.add ("int"); - reserved_identifiers.add ("long"); - reserved_identifiers.add ("register"); - reserved_identifiers.add ("restrict"); - reserved_identifiers.add ("return"); - reserved_identifiers.add ("short"); - reserved_identifiers.add ("signed"); - reserved_identifiers.add ("sizeof"); - reserved_identifiers.add ("static"); - reserved_identifiers.add ("struct"); - reserved_identifiers.add ("switch"); - reserved_identifiers.add ("typedef"); - reserved_identifiers.add ("union"); - reserved_identifiers.add ("unsigned"); - reserved_identifiers.add ("void"); - reserved_identifiers.add ("volatile"); - reserved_identifiers.add ("while"); - - // C11 keywords - reserved_identifiers.add ("_Alignas"); - reserved_identifiers.add ("_Alignof"); - reserved_identifiers.add ("_Atomic"); - reserved_identifiers.add ("_Generic"); - reserved_identifiers.add ("_Noreturn"); - reserved_identifiers.add ("_Static_assert"); - reserved_identifiers.add ("_Thread_local"); - - // MSVC keywords - reserved_identifiers.add ("cdecl"); - - // reserved for Vala/GObject naming conventions - reserved_identifiers.add ("error"); - reserved_identifiers.add ("result"); - reserved_identifiers.add ("self"); - } - - public override void emit (CodeContext context) { - this.context = context; - - ccode_init (context.profile); - - root_symbol = context.root; - - bool_type = new BooleanType ((Struct) root_symbol.scope.lookup ("bool")); - char_type = new IntegerType ((Struct) root_symbol.scope.lookup ("char")); - uchar_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uchar")); - short_type = new IntegerType ((Struct) root_symbol.scope.lookup ("short")); - ushort_type = new IntegerType ((Struct) root_symbol.scope.lookup ("ushort")); - int_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int")); - uint_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint")); - long_type = new IntegerType ((Struct) root_symbol.scope.lookup ("long")); - ulong_type = new IntegerType ((Struct) root_symbol.scope.lookup ("ulong")); - int8_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int8")); - uint8_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint8")); - int16_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int16")); - uint16_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint16")); - int32_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int32")); - uint32_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint32")); - int64_type = new IntegerType ((Struct) root_symbol.scope.lookup ("int64")); - uint64_type = new IntegerType ((Struct) root_symbol.scope.lookup ("uint64")); - size_t_type = new IntegerType ((Struct) root_symbol.scope.lookup ("size_t")); - ssize_t_type = new IntegerType ((Struct) root_symbol.scope.lookup ("ssize_t")); - float_type = new FloatingType ((Struct) root_symbol.scope.lookup ("float")); - double_type = new FloatingType ((Struct) root_symbol.scope.lookup ("double")); - string_type = new ObjectType ((Class) root_symbol.scope.lookup ("string")); - var unichar_struct = (Struct) root_symbol.scope.lookup ("unichar"); - if (unichar_struct != null) { - unichar_type = new IntegerType (unichar_struct); - } - - if (context.profile == Profile.GOBJECT) { - var glib_ns = root_symbol.scope.lookup ("GLib"); - - gtype_type = (TypeSymbol) glib_ns.scope.lookup ("Type"); - gobject_type = (TypeSymbol) glib_ns.scope.lookup ("Object"); - gerror_type = new ErrorType (null, null); - glist_type = (Class) glib_ns.scope.lookup ("List"); - gslist_type = (Class) glib_ns.scope.lookup ("SList"); - gnode_type = (Class) glib_ns.scope.lookup ("Node"); - gqueue_type = (Class) glib_ns.scope.lookup ("Queue"); - gvaluearray_type = (Class) glib_ns.scope.lookup ("ValueArray"); - gstringbuilder_type = (TypeSymbol) glib_ns.scope.lookup ("StringBuilder"); - garray_type = (Class) glib_ns.scope.lookup ("Array"); - gbytearray_type = (TypeSymbol) glib_ns.scope.lookup ("ByteArray"); - genericarray_type = (TypeSymbol) glib_ns.scope.lookup ("GenericArray"); - gsequence_type = (Class) glib_ns.scope.lookup ("Sequence"); - gsequence_iter_type = (Class) glib_ns.scope.lookup ("SequenceIter"); - gthreadpool_type = (TypeSymbol) glib_ns.scope.lookup ("ThreadPool"); - - gerror = (Class) root_symbol.scope.lookup ("GLib").scope.lookup ("Error"); - gquark_type = new IntegerType ((Struct) glib_ns.scope.lookup ("Quark")); - gvalue_type = (Struct) glib_ns.scope.lookup ("Value"); - gvariant_type = (Class) glib_ns.scope.lookup ("Variant"); - gsource_type = (Class) glib_ns.scope.lookup ("Source"); - - gmutex_type = (Struct) glib_ns.scope.lookup ("Mutex"); - grecmutex_type = (Struct) glib_ns.scope.lookup ("RecMutex"); - grwlock_type = (Struct) glib_ns.scope.lookup ("RWLock"); - gcond_type = (Struct) glib_ns.scope.lookup ("Cond"); - - mutex_type = grecmutex_type; - - type_module_type = (TypeSymbol) glib_ns.scope.lookup ("TypeModule"); - - regex_type = new ObjectType ((Class) root_symbol.scope.lookup ("GLib").scope.lookup ("Regex")); - - if (context.module_init_method != null) { - foreach (Parameter parameter in context.module_init_method.get_parameters ()) { - if (parameter.variable_type.type_symbol.is_subtype_of (type_module_type)) { - in_plugin = true; - module_init_param_name = parameter.name; - break; - - } - } - } - - dbus_proxy_type = (TypeSymbol) glib_ns.scope.lookup ("DBusProxy"); - - pointer_type = new StructValueType ((Struct) glib_ns.scope.lookup ("pointer")); - - delegate_target_type = pointer_type; - destroy_notify = (Delegate) glib_ns.scope.lookup ("DestroyNotify"); - delegate_target_destroy_type = new DelegateType (destroy_notify); - } else { - pointer_type = new PointerType (new VoidType ()); - - delegate_target_type = pointer_type; - destroy_notify = new Delegate ("ValaDestroyNotify", new VoidType ()); - destroy_notify.add_parameter (new Parameter ("data", new PointerType (new VoidType ()))); - destroy_notify.has_target = false; - destroy_notify.owner = root_symbol.scope; - delegate_target_destroy_type = new DelegateType (destroy_notify); - } - - var gtk_ns = root_symbol.scope.lookup ("Gtk"); - if (gtk_ns != null) { - gtk_widget_type = (Class) gtk_ns.scope.lookup ("Widget"); - } - - header_file = new CCodeFile (CCodeFileType.PUBLIC_HEADER); - internal_header_file = new CCodeFile (CCodeFileType.INTERNAL_HEADER); - - /* we're only interested in non-pkg source files */ - var source_files = context.get_source_files (); - foreach (SourceFile file in source_files) { - if (file.file_type == SourceFileType.SOURCE || - (context.header_filename != null && file.file_type == SourceFileType.FAST)) { - file.accept (this); - } - } - - // generate symbols file for public API - if (context.symbols_filename != null) { - var stream = FileStream.open (context.symbols_filename, "w"); - if (stream == null) { - Report.error (null, "unable to open `%s' for writing", context.symbols_filename); - this.context = null; - return; - } - - foreach (string symbol in header_file.get_symbols ()) { - stream.puts (symbol); - stream.putc ('\n'); - } - - stream = null; - } - - // generate C header file for public API - if (context.header_filename != null) { - bool ret; - if (context.profile == Profile.GOBJECT) { - header_file.add_include ("glib.h"); - ret = header_file.store (context.header_filename, null, context.version_header, false, "G_BEGIN_DECLS", "G_END_DECLS"); - } else { - ret = header_file.store (context.header_filename, null, context.version_header, false, "#ifdef __cplusplus\nextern \"C\" {\n#endif", "#ifdef __cplusplus\n}\n#endif"); - } - if (!ret) { - Report.error (null, "unable to open `%s' for writing", context.header_filename); - } - } - - // generate C header file for internal API - if (context.internal_header_filename != null) { - bool ret; - if (context.profile == Profile.GOBJECT) { - internal_header_file.add_include ("glib.h"); - ret = internal_header_file.store (context.internal_header_filename, null, context.version_header, false, "G_BEGIN_DECLS", "G_END_DECLS"); - } else { - ret = internal_header_file.store (context.internal_header_filename, null, context.version_header, false, "#ifdef __cplusplus\nextern \"C\" {\n#endif", "#ifdef __cplusplus\n}\n#endif"); - } - if (!ret) { - Report.error (null, "unable to open `%s' for writing", context.internal_header_filename); - } - } - - this.context = null; - } - - public void push_context (EmitContext emit_context) { - if (this.emit_context != null) { - emit_context_stack.add (this.emit_context); - } - - this.emit_context = emit_context; - if (ccode != null) { - ccode.current_line = current_line; - } - } - - public void pop_context () { - if (emit_context_stack.size > 0) { - this.emit_context = emit_context_stack.remove_at (emit_context_stack.size - 1); - if (ccode != null) { - ccode.current_line = current_line; - } - } else { - this.emit_context = null; - } - } - - public void push_line (SourceReference? source_reference) { - line_directive_stack.add (current_line); - if (source_reference != null) { - current_line = new CCodeLineDirective (source_reference.file.get_relative_filename (), source_reference.begin.line); - if (ccode != null) { - ccode.current_line = current_line; - } - } - } - - public void pop_line () { - current_line = line_directive_stack.remove_at (line_directive_stack.size - 1); - if (ccode != null) { - ccode.current_line = current_line; - } - } - - public void push_function (CCodeFunction func) { - emit_context.ccode_stack.add (ccode); - emit_context.ccode = func; - ccode.current_line = current_line; - } - - public void pop_function () { - emit_context.ccode = emit_context.ccode_stack.remove_at (emit_context.ccode_stack.size - 1); - if (ccode != null) { - ccode.current_line = current_line; - } - } - - public bool add_symbol_declaration (CCodeFile decl_space, Symbol sym, string name) { - bool in_generated_header = context.header_filename != null - && (decl_space.file_type != CCodeFileType.PUBLIC_HEADER && !sym.is_internal_symbol () && !(sym is Class && ((Class) sym).is_opaque)); - if (decl_space.add_declaration (name)) { - return true; - } - if (sym.source_reference != null) { - sym.source_reference.file.used = true; - } - if (sym.anonymous) { - return in_generated_header; - } - // constants with initializer-list are special - if (sym is Constant && ((Constant) sym).value is InitializerList) { - return false; - } - // sealed classes are special - if (!sym.external_package && sym is Class && ((Class) sym).is_sealed) { - return false; - } - if (sym.external_package || in_generated_header - || (sym.is_extern && get_ccode_header_filenames (sym).length > 0)) { - // add feature test macros - foreach (unowned string feature_test_macro in get_ccode_feature_test_macros (sym).split (",")) { - decl_space.add_feature_test_macro (feature_test_macro); - } - // add appropriate include file - foreach (unowned string header_filename in get_ccode_header_filenames (sym).split (",")) { - decl_space.add_include (header_filename, - !sym.is_extern && (!sym.external_package || (sym.external_package && sym.from_commandline))); - } - // declaration complete - return true; - } else { - // require declaration - return false; - } - } - - public virtual void append_vala_array_free () { - } - - public virtual void append_vala_array_move () { - } - - public virtual void append_vala_array_length () { - } - - public virtual void append_params_array (Method m) { - } - - public void append_vala_clear_mutex (string typename, string funcprefix) { - // memset - cfile.add_include ("string.h"); - - var fun = new CCodeFunction ("_vala_clear_" + typename); - fun.modifiers = CCodeModifiers.STATIC; - fun.add_parameter (new CCodeParameter ("mutex", typename + " *")); - - push_function (fun); - - ccode.add_declaration (typename, new CCodeVariableDeclarator.zero ("zero_mutex", new CCodeConstant ("{ 0 }"))); - - var cmp = new CCodeFunctionCall (new CCodeIdentifier ("memcmp")); - cmp.add_argument (new CCodeIdentifier ("mutex")); - cmp.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("zero_mutex"))); - cmp.add_argument (new CCodeIdentifier ("sizeof (" + typename + ")")); - ccode.open_if (cmp); - - var mutex_clear = new CCodeFunctionCall (new CCodeIdentifier (funcprefix + "_clear")); - mutex_clear.add_argument (new CCodeIdentifier ("mutex")); - ccode.add_expression (mutex_clear); - - var mset = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - mset.add_argument (new CCodeIdentifier ("mutex")); - mset.add_argument (new CCodeConstant ("0")); - mset.add_argument (new CCodeIdentifier ("sizeof (" + typename + ")")); - ccode.add_expression (mset); - - ccode.close (); - - pop_function (); - - cfile.add_function_declaration (fun); - cfile.add_function (fun); - } - - void append_vala_memdup2 () { - // g_malloc - cfile.add_include ("glib.h"); - // memcpy - cfile.add_include ("string.h"); - - var fun = new CCodeFunction ("_vala_memdup2", "gpointer"); - fun.modifiers = CCodeModifiers.STATIC | CCodeModifiers.INLINE; - fun.add_parameter (new CCodeParameter ("mem", "gconstpointer")); - fun.add_parameter (new CCodeParameter ("byte_size", "gsize")); - - push_function (fun); - - ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("new_mem")); - - ccode.open_if (new CCodeIdentifier ("mem && byte_size != 0")); - - var malloc = new CCodeFunctionCall (new CCodeIdentifier ("g_malloc")); - malloc.add_argument (new CCodeIdentifier ("byte_size")); - ccode.add_assignment (new CCodeIdentifier ("new_mem"), malloc); - var mcpy = new CCodeFunctionCall (new CCodeIdentifier ("memcpy")); - mcpy.add_argument (new CCodeIdentifier ("new_mem")); - mcpy.add_argument (new CCodeIdentifier ("mem")); - mcpy.add_argument (new CCodeIdentifier ("byte_size")); - ccode.add_expression (mcpy); - - ccode.add_else (); - - ccode.add_assignment (new CCodeIdentifier ("new_mem"), new CCodeConstant ("NULL")); - - ccode.close (); - - ccode.add_return (new CCodeIdentifier ("new_mem")); - - pop_function (); - - cfile.add_function_declaration (fun); - cfile.add_function (fun); - } - - /** - * Define a macro hint for exporting a symbol in a portable way. - */ - void append_vala_extern_define (CCodeFile decl_space) { - var extern_define = new CCodeIfSection ("!defined(VALA_EXTERN)"); - - CCodeIfSection if_section; - if_section = new CCodeIfSection ("defined(_MSC_VER)"); - extern_define.append (if_section); - if_section.append (new CCodeDefine ("VALA_EXTERN", "__declspec(dllexport) extern")); - if_section = if_section.append_else ("__GNUC__ >= 4"); - if_section.append (new CCodeDefine ("VALA_EXTERN", "__attribute__((visibility(\"default\"))) extern")); - if_section = if_section.append_else (); - if_section.append (new CCodeDefine ("VALA_EXTERN", "extern")); - - decl_space.add_define (extern_define); - } - - public override void visit_source_file (SourceFile source_file) { - cfile = new CCodeFile (CCodeFileType.SOURCE, source_file); - - user_marshal_set = new HashSet (str_hash, str_equal); - - next_regex_id = 0; - - requires_assert = false; - requires_array_free = false; - requires_array_move = false; - requires_array_length = false; - requires_array_n_elements = false; - requires_clear_mutex = false; - requires_vala_extern = false; - - wrappers = new HashSet (str_hash, str_equal); - generated_external_symbols = new HashSet (); - - source_file.accept_children (this); - - if (context.report.get_errors () > 0) { - return; - } - - /* For fast-vapi, we only wanted the header declarations - * to be emitted, so bail out here without writing the - * C code output. - */ - if (source_file.file_type == SourceFileType.FAST) { - return; - } - - if (requires_assert) { - cfile.add_type_declaration (new CCodeMacroReplacement.with_expression ("_vala_assert(expr, msg)", new CCodeConstant ("if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);"))); - cfile.add_type_declaration (new CCodeMacroReplacement.with_expression ("_vala_return_if_fail(expr, msg)", new CCodeConstant ("if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }"))); - cfile.add_type_declaration (new CCodeMacroReplacement.with_expression ("_vala_return_val_if_fail(expr, msg, val)", new CCodeConstant ("if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }"))); - cfile.add_type_declaration (new CCodeMacroReplacement.with_expression ("_vala_warn_if_fail(expr, msg)", new CCodeConstant ("if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);"))); - } - if (requires_array_free) { - append_vala_array_free (); - } - if (requires_array_move) { - append_vala_array_move (); - } - if (requires_array_length) { - append_vala_array_length (); - } - if (requires_array_n_elements) { - cfile.add_type_declaration (new CCodeMacroReplacement.with_expression ("VALA_N_ELEMENTS(arr)", new CCodeConstant ("(sizeof (arr) / sizeof ((arr)[0]))"))); - } - if (requires_clear_mutex) { - append_vala_clear_mutex ("GMutex", "g_mutex"); - append_vala_clear_mutex ("GRecMutex", "g_rec_mutex"); - append_vala_clear_mutex ("GRWLock", "g_rw_lock"); - append_vala_clear_mutex ("GCond", "g_cond"); - } - if (requires_memdup2) { - append_vala_memdup2 (); - } - if (requires_vala_extern) { - if (context.header_filename != null) { - if (!header_file.add_declaration ("VALA_EXTERN")) { - append_vala_extern_define (header_file); - } - cfile.add_include (source_file.get_cinclude_filename (), true); - internal_header_file.add_include (source_file.get_cinclude_filename (), true); - } else { - if (!cfile.add_declaration ("VALA_EXTERN")) { - append_vala_extern_define (cfile); - append_vala_extern_define (internal_header_file); - } - } - } - - var comments = source_file.get_comments(); - if (comments != null) { - foreach (Comment comment in comments) { - var ccomment = new CCodeComment (comment.content); - cfile.add_comment (ccomment); - } - } - - if (!cfile.store (source_file.get_csource_filename (), source_file.filename, context.version_header, context.debug)) { - Report.error (null, "unable to open `%s' for writing", source_file.get_csource_filename ()); - } - - cfile = null; - } - - public virtual bool generate_enum_declaration (Enum en, CCodeFile decl_space) { - if (add_symbol_declaration (decl_space, en, get_ccode_name (en))) { - return false; - } - - var cenum = new CCodeEnum (get_ccode_name (en)); - - if (en.version.deprecated) { - if (context.profile == Profile.GOBJECT) { - decl_space.add_include ("glib.h"); - } - cenum.modifiers |= CCodeModifiers.DEPRECATED; - } - - var current_cfile = cfile; - cfile = decl_space; - - int flag_shift = 0; - foreach (EnumValue ev in en.get_values ()) { - CCodeEnumValue c_ev; - if (ev.value == null) { - c_ev = new CCodeEnumValue (get_ccode_name (ev)); - if (en.is_flags) { - c_ev.value = new CCodeConstant ("1 << %d".printf (flag_shift)); - flag_shift += 1; - } - } else { - ev.value.emit (this); - c_ev = new CCodeEnumValue (get_ccode_name (ev), get_cvalue (ev.value)); - } - c_ev.modifiers |= (ev.version.deprecated ? CCodeModifiers.DEPRECATED : 0); - cenum.add_value (c_ev); - } - - cfile = current_cfile; - - decl_space.add_type_declaration (cenum); - decl_space.add_type_declaration (new CCodeNewline ()); - - if (context.profile != Profile.GOBJECT || !get_ccode_has_type_id (en)) { - return true; - } - - decl_space.add_include ("glib-object.h"); - decl_space.add_type_declaration (new CCodeNewline ()); - - var fun_name = get_ccode_type_function (en); - - var macro = "(%s ())".printf (fun_name); - decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (en), macro)); - - var regfun = new CCodeFunction (fun_name, "GType"); - regfun.modifiers = CCodeModifiers.CONST; - - if (en.is_private_symbol ()) { - // avoid C warning as this function is not always used - regfun.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.UNUSED; - } else if (context.hide_internal && en.is_internal_symbol ()) { - regfun.modifiers |= CCodeModifiers.INTERNAL; - } else { - regfun.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - decl_space.add_function_declaration (regfun); - - return true; - } - - public override void visit_enum (Enum en) { - push_line (en.source_reference); - - if (en.comment != null) { - cfile.add_type_member_definition (new CCodeComment (en.comment.content)); - } - - generate_enum_declaration (en, cfile); - - if (!en.is_internal_symbol ()) { - generate_enum_declaration (en, header_file); - } - if (!en.is_private_symbol ()) { - generate_enum_declaration (en, internal_header_file); - } - - en.accept_children (this); - - pop_line (); - } - - public void visit_member (Symbol m) { - /* stuff meant for all lockable members */ - if (m is Lockable && ((Lockable) m).lock_used) { - CCodeExpression l = new CCodeIdentifier ("self"); - var init_context = class_init_context; - var finalize_context = class_finalize_context; - - if (m.is_instance_member ()) { - l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (get_ccode_name (m))); - init_context = instance_init_context; - finalize_context = instance_finalize_context; - } else if (m.is_class_member ()) { - var get_class_private_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_get_private_function ((Class) m.parent_symbol))); - get_class_private_call.add_argument (new CCodeIdentifier ("klass")); - l = new CCodeMemberAccess.pointer (get_class_private_call, get_symbol_lock_name (get_ccode_name (m))); - } else { - l = new CCodeIdentifier (get_symbol_lock_name ("%s_%s".printf (get_ccode_lower_case_name (m.parent_symbol), get_ccode_name (m)))); - } - - push_context (init_context); - var initf = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (mutex_type.default_construction_method))); - initf.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l)); - ccode.add_expression (initf); - pop_context (); - - if (finalize_context != null) { - push_context (finalize_context); - var fc = new CCodeFunctionCall (new CCodeIdentifier ("g_rec_mutex_clear")); - fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l)); - ccode.add_expression (fc); - pop_context (); - } - } - } - - static void constant_array_ranks_sizes (InitializerList initializer_list, int[] sizes, int rank = 0) { - sizes[rank] = int.max (sizes[rank], initializer_list.size); - rank++; - foreach (var expr in initializer_list.get_initializers()) { - if (expr is InitializerList && ((InitializerList) expr).target_type is ArrayType) { - constant_array_ranks_sizes ((InitializerList) expr, sizes, rank); - } - } - } - - CCodeDeclaratorSuffix? get_constant_declarator_suffix (Constant c) { - unowned ArrayType? array = c.type_reference as ArrayType; - unowned InitializerList? initializer_list = c.value as InitializerList; - if (array == null || initializer_list == null) { - if (c.type_reference.compatible (string_type)) { - return new CCodeDeclaratorSuffix.with_array (); - } - return null; - } - - var lengths = new ArrayList (); - int[] sizes = new int[array.rank]; - constant_array_ranks_sizes (initializer_list, sizes); - for (int i = 0; i < array.rank; i++) { - lengths.add (new CCodeConstant ("%d".printf (sizes[i]))); - } - return new CCodeDeclaratorSuffix.with_multi_array (lengths); - } - - public void generate_constant_declaration (Constant c, CCodeFile decl_space, bool definition = false) { - if (c.parent_symbol is Block) { - // local constant - return; - } - - if (add_symbol_declaration (decl_space, c, get_ccode_name (c))) { - return; - } - - if (!c.external && c.value != null) { - generate_type_declaration (c.type_reference, decl_space); - - c.value.emit (this); - - var initializer_list = c.value as InitializerList; - if (initializer_list != null) { - var cdecl = new CCodeDeclaration (get_ccode_const_name (c.type_reference)); - var cinitializer = get_cvalue (c.value); - if (!definition) { - // never output value in header - // special case needed as this method combines declaration and definition - cinitializer = null; - } - - cdecl.add_declarator (new CCodeVariableDeclarator (get_ccode_name (c), cinitializer, get_constant_declarator_suffix (c))); - if (c.is_private_symbol ()) { - cdecl.modifiers = CCodeModifiers.STATIC; - } else { - cdecl.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - decl_space.add_constant_declaration (cdecl); - } else { - if (c.value is StringLiteral && ((StringLiteral) c.value).translate) { - // translated string constant - var m = (Method) root_symbol.scope.lookup ("GLib").scope.lookup ("_"); - add_symbol_declaration (decl_space, m, get_ccode_name (m)); - } - - var cdefine = new CCodeDefine.with_expression (get_ccode_name (c), get_cvalue (c.value)); - decl_space.add_define (cdefine); - } - } - } - - public override void visit_constant (Constant c) { - push_line (c.source_reference); - - if (c.parent_symbol is Block) { - // local constant - - generate_type_declaration (c.type_reference, cfile); - - c.value.emit (this); - - string type_name; - if (c.type_reference.compatible (string_type)) { - type_name = "const char"; - } else { - type_name = get_ccode_const_name (c.type_reference); - } - - var cinitializer = get_cvalue (c.value); - - ccode.add_declaration (type_name, new CCodeVariableDeclarator (get_ccode_name (c), cinitializer, get_constant_declarator_suffix (c)), CCodeModifiers.STATIC); - } else { - generate_constant_declaration (c, cfile, true); - - if (!c.is_internal_symbol ()) { - generate_constant_declaration (c, header_file); - } - if (!c.is_private_symbol ()) { - generate_constant_declaration (c, internal_header_file); - } - } - - pop_line (); - } - - public void append_field (CCodeStruct ccode_struct, Field f, CCodeFile decl_space) { - generate_type_declaration (f.variable_type, decl_space); - - CCodeModifiers modifiers = (f.is_volatile ? CCodeModifiers.VOLATILE : 0) | (f.version.deprecated ? CCodeModifiers.DEPRECATED : 0); - ccode_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers, get_ccode_declarator_suffix (f.variable_type)); - - if (f.variable_type is ArrayType && get_ccode_array_length (f)) { - // create fields to store array dimensions - var array_type = (ArrayType) f.variable_type; - if (!array_type.fixed_length) { - var length_ctype = get_ccode_array_length_type (f); - for (int dim = 1; dim <= array_type.rank; dim++) { - string length_cname = get_variable_array_length_cname (f, dim); - ccode_struct.add_field (length_ctype, length_cname); - } - if (array_type.rank == 1 && f.is_internal_symbol ()) { - ccode_struct.add_field (length_ctype, get_array_size_cname (get_ccode_name (f))); - } - } - } else if (get_ccode_delegate_target (f)) { - var delegate_type = (DelegateType) f.variable_type; - if (delegate_type.delegate_symbol.has_target) { - // create field to store delegate target - ccode_struct.add_field (get_ccode_name (delegate_target_type), get_ccode_delegate_target_name (f)); - if (delegate_type.is_disposable ()) { - ccode_struct.add_field (get_ccode_name (delegate_target_destroy_type), get_ccode_delegate_target_destroy_notify_name (f)); - } - } - } - } - - public void generate_field_declaration (Field f, CCodeFile decl_space) { - if (add_symbol_declaration (decl_space, f, get_ccode_name (f))) { - return; - } - - generate_type_declaration (f.variable_type, decl_space); - - var cdecl = new CCodeDeclaration (get_ccode_name (f.variable_type)); - cdecl.add_declarator (new CCodeVariableDeclarator (get_ccode_name (f), null, get_ccode_declarator_suffix (f.variable_type))); - if (f.is_private_symbol ()) { - cdecl.modifiers = CCodeModifiers.STATIC; - } else { - cdecl.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - if (f.version.deprecated) { - cdecl.modifiers |= CCodeModifiers.DEPRECATED; - } - if (f.is_volatile) { - cdecl.modifiers |= CCodeModifiers.VOLATILE; - } - decl_space.add_type_member_declaration (cdecl); - - if (f.lock_used) { - // Declare mutex for static member - var flock = new CCodeDeclaration (get_ccode_name (mutex_type)); - var flock_decl = new CCodeVariableDeclarator (get_symbol_lock_name ("%s_%s".printf (get_ccode_lower_case_name (f.parent_symbol), get_ccode_name (f))), new CCodeConstant ("{0}")); - flock.add_declarator (flock_decl); - - if (f.is_private_symbol ()) { - flock.modifiers = CCodeModifiers.STATIC; - } else { - flock.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - decl_space.add_type_member_declaration (flock); - } - - if (f.variable_type is ArrayType && get_ccode_array_length (f)) { - var array_type = (ArrayType) f.variable_type; - - if (!array_type.fixed_length) { - var length_ctype = get_ccode_array_length_type (f); - - for (int dim = 1; dim <= array_type.rank; dim++) { - cdecl = new CCodeDeclaration (length_ctype); - cdecl.add_declarator (new CCodeVariableDeclarator (get_variable_array_length_cname (f, dim))); - if (f.is_private_symbol ()) { - cdecl.modifiers = CCodeModifiers.STATIC; - } else { - cdecl.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - decl_space.add_type_member_declaration (cdecl); - } - } - } else if (get_ccode_delegate_target (f)) { - var delegate_type = (DelegateType) f.variable_type; - if (delegate_type.delegate_symbol.has_target) { - // create field to store delegate target - - cdecl = new CCodeDeclaration (get_ccode_name (delegate_target_type)); - cdecl.add_declarator (new CCodeVariableDeclarator (get_ccode_delegate_target_name (f))); - if (f.is_private_symbol ()) { - cdecl.modifiers = CCodeModifiers.STATIC; - } else { - cdecl.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - decl_space.add_type_member_declaration (cdecl); - - if (delegate_type.is_disposable ()) { - cdecl = new CCodeDeclaration (get_ccode_name (delegate_target_destroy_type)); - cdecl.add_declarator (new CCodeVariableDeclarator (get_ccode_delegate_target_destroy_notify_name (f))); - if (f.is_private_symbol ()) { - cdecl.modifiers = CCodeModifiers.STATIC; - } else { - cdecl.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - decl_space.add_type_member_declaration (cdecl); - } - } - } - } - - public override void visit_field (Field f) { - push_line (f.source_reference); - visit_member (f); - - var cl = f.parent_symbol as Class; - bool is_gtypeinstance = (cl != null && !cl.is_compact); - - CCodeExpression lhs = null; - - if (f.binding == MemberBinding.INSTANCE) { - if (is_gtypeinstance && f.access == SymbolAccessibility.PRIVATE) { - lhs = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), get_ccode_name (f)); - } else { - lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), get_ccode_name (f)); - } - - if (f.initializer != null) { - push_context (instance_init_context); - - f.initializer.emit (this); - - var rhs = get_cvalue (f.initializer); - if (!is_simple_struct_creation (f, f.initializer)) { - // otherwise handled in visit_object_creation_expression - - ccode.add_assignment (lhs, rhs); - - if (f.variable_type is ArrayType && get_ccode_array_length (f)) { - var array_type = (ArrayType) f.variable_type; - var field_value = get_field_cvalue (f, load_this_parameter ((TypeSymbol) f.parent_symbol)); - - var glib_value = (GLibValue) f.initializer.target_value; - if (glib_value.array_length_cvalues != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - var array_len_lhs = get_array_length_cvalue (field_value, dim); - ccode.add_assignment (array_len_lhs, get_array_length_cvalue (glib_value, dim)); - } - } else if (glib_value.array_null_terminated) { - requires_array_length = true; - var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length")); - len_call.add_argument (get_cvalue_ (glib_value)); - - ccode.add_assignment (get_array_length_cvalue (field_value, 1), len_call); - } else { - for (int dim = 1; dim <= array_type.rank; dim++) { - ccode.add_assignment (get_array_length_cvalue (field_value, dim), new CCodeConstant ("-1")); - } - } - - if (array_type.rank == 1 && f.is_internal_symbol ()) { - var lhs_array_size = get_array_size_cvalue (field_value); - var rhs_array_len = get_array_length_cvalue (field_value, 1); - ccode.add_assignment (lhs_array_size, rhs_array_len); - } - } else if (get_ccode_delegate_target (f)) { - var delegate_type = (DelegateType) f.variable_type; - if (delegate_type.delegate_symbol.has_target) { - var field_value = get_field_cvalue (f, load_this_parameter ((TypeSymbol) f.parent_symbol)); - var target_cvalue = get_delegate_target_cvalue (f.initializer.target_value); - if (target_cvalue != null) { - ccode.add_assignment (get_delegate_target_cvalue (field_value), target_cvalue); - } else { - ccode.add_assignment (get_delegate_target_cvalue (field_value), new CCodeIdentifier ("self")); - } - if (delegate_type.is_disposable ()) { - var destroy_cvalue = get_delegate_target_destroy_notify_cvalue (f.initializer.target_value); - if (destroy_cvalue != null) { - ccode.add_assignment (get_delegate_target_destroy_notify_cvalue (field_value), destroy_cvalue); - } else { - ccode.add_assignment (get_delegate_target_destroy_notify_cvalue (field_value), new CCodeConstant ("NULL")); - } - } - } - } - } - - foreach (var value in temp_ref_values) { - ccode.add_expression (destroy_value (value)); - } - - temp_ref_values.clear (); - - pop_context (); - } - - if ((!(f.variable_type is DelegateType) || get_ccode_delegate_target (f)) && requires_destroy (f.variable_type) && instance_finalize_context != null) { - push_context (instance_finalize_context); - ccode.add_expression (destroy_field (f, load_this_parameter ((TypeSymbol) f.parent_symbol))); - pop_context (); - } - } else if (f.binding == MemberBinding.CLASS) { - if (f.access == SymbolAccessibility.PRIVATE) { - var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_get_private_function (cl))); - ccall.add_argument (new CCodeIdentifier ("klass")); - lhs = new CCodeMemberAccess (ccall, get_ccode_name (f), true); - } else { - lhs = new CCodeMemberAccess (new CCodeIdentifier ("klass"), get_ccode_name (f), true); - } - - if (f.initializer != null) { - push_context (class_init_context); - - f.initializer.emit (this); - - var rhs = get_cvalue (f.initializer); - - ccode.add_assignment (lhs, rhs); - - foreach (var value in temp_ref_values) { - ccode.add_expression (destroy_value (value)); - } - - temp_ref_values.clear (); - - pop_context (); - } - } else { - generate_field_declaration (f, cfile); - - if (!f.is_internal_symbol ()) { - generate_field_declaration (f, header_file); - } - if (!f.is_private_symbol ()) { - generate_field_declaration (f, internal_header_file); - } - - if (!f.external) { - lhs = new CCodeIdentifier (get_ccode_name (f)); - - var var_decl = new CCodeVariableDeclarator (get_ccode_name (f), null, get_ccode_declarator_suffix (f.variable_type)); - var_decl.initializer = default_value_for_type (f.variable_type, true); - - if (class_init_context != null) { - push_context (class_init_context); - } else { - push_context (new EmitContext ()); - } - - if (f.initializer != null) { - f.initializer.emit (this); - - var init = get_cvalue (f.initializer); - if (is_constant_ccode_expression (init)) { - var_decl.initializer = init; - } - } - - var var_def = new CCodeDeclaration (get_ccode_name (f.variable_type)); - var_def.add_declarator (var_decl); - if (!f.is_private_symbol ()) { - var_def.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } else { - var_def.modifiers = CCodeModifiers.STATIC; - } - if (f.version.deprecated) { - var_def.modifiers |= CCodeModifiers.DEPRECATED; - } - if (f.is_volatile) { - var_def.modifiers |= CCodeModifiers.VOLATILE; - } - cfile.add_type_member_declaration (var_def); - - /* add array length fields where necessary */ - if (f.variable_type is ArrayType && get_ccode_array_length (f)) { - var array_type = (ArrayType) f.variable_type; - - if (!array_type.fixed_length) { - var length_ctype = get_ccode_array_length_type (f); - - for (int dim = 1; dim <= array_type.rank; dim++) { - var len_def = new CCodeDeclaration (length_ctype); - len_def.add_declarator (new CCodeVariableDeclarator (get_variable_array_length_cname (f, dim), new CCodeConstant ("0"))); - if (!f.is_private_symbol ()) { - len_def.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } else { - len_def.modifiers = CCodeModifiers.STATIC; - } - cfile.add_type_member_declaration (len_def); - } - - if (array_type.rank == 1 && f.is_internal_symbol ()) { - var cdecl = new CCodeDeclaration (length_ctype); - cdecl.add_declarator (new CCodeVariableDeclarator (get_array_size_cname (get_ccode_name (f)), new CCodeConstant ("0"))); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_type_member_declaration (cdecl); - } - } - } else if (get_ccode_delegate_target (f)) { - var delegate_type = (DelegateType) f.variable_type; - if (delegate_type.delegate_symbol.has_target) { - // create field to store delegate target - - var target_def = new CCodeDeclaration (get_ccode_name (delegate_target_type)); - target_def.add_declarator (new CCodeVariableDeclarator (get_ccode_delegate_target_name (f), new CCodeConstant ("NULL"))); - if (!f.is_private_symbol ()) { - target_def.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } else { - target_def.modifiers = CCodeModifiers.STATIC; - } - cfile.add_type_member_declaration (target_def); - - if (delegate_type.is_disposable ()) { - var target_destroy_notify_def = new CCodeDeclaration (get_ccode_name (delegate_target_destroy_type)); - target_destroy_notify_def.add_declarator (new CCodeVariableDeclarator (get_ccode_delegate_target_destroy_notify_name (f), new CCodeConstant ("NULL"))); - if (!f.is_private_symbol ()) { - target_destroy_notify_def.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } else { - target_destroy_notify_def.modifiers = CCodeModifiers.STATIC; - } - cfile.add_type_member_declaration (target_destroy_notify_def); - - } - } - } - - if (f.initializer != null) { - var rhs = get_cvalue (f.initializer); - if (!is_constant_ccode_expression (rhs)) { - if (is_gtypeinstance) { - if (f.initializer is InitializerList) { - ccode.open_block (); - - var temp_decl = get_temp_variable (f.variable_type); - var vardecl = new CCodeVariableDeclarator.zero (temp_decl.name, rhs); - ccode.add_declaration (get_ccode_name (temp_decl.variable_type), vardecl); - - var tmp = get_variable_cexpression (temp_decl.name); - ccode.add_assignment (lhs, tmp); - - ccode.close (); - } else { - ccode.add_assignment (lhs, rhs); - } - - if (f.variable_type is ArrayType && get_ccode_array_length (f)) { - var array_type = (ArrayType) f.variable_type; - var field_value = get_field_cvalue (f, null); - - var glib_value = (GLibValue) f.initializer.target_value; - if (glib_value.array_length_cvalues != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - var array_len_lhs = get_array_length_cvalue (field_value, dim); - ccode.add_assignment (array_len_lhs, get_array_length_cvalue (glib_value, dim)); - } - } else if (glib_value.array_null_terminated) { - requires_array_length = true; - var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length")); - len_call.add_argument (get_cvalue_ (glib_value)); - - ccode.add_assignment (get_array_length_cvalue (field_value, 1), len_call); - } else { - for (int dim = 1; dim <= array_type.rank; dim++) { - ccode.add_assignment (get_array_length_cvalue (field_value, dim), new CCodeConstant ("-1")); - } - } - } - } else { - f.error = true; - Report.error (f.source_reference, "Non-constant field initializers not supported in this context"); - return; - } - } - } - - pop_context (); - } - } - - pop_line (); - } - - public static bool is_constant_ccode_expression (CCodeExpression cexpr) { - if (cexpr is CCodeConstant || cexpr is CCodeConstantIdentifier) { - return true; - } else if (cexpr is CCodeCastExpression) { - var ccast = (CCodeCastExpression) cexpr; - return is_constant_ccode_expression (ccast.inner); - } else if (cexpr is CCodeUnaryExpression) { - var cunary = (CCodeUnaryExpression) cexpr; - switch (cunary.operator) { - case CCodeUnaryOperator.PREFIX_INCREMENT: - case CCodeUnaryOperator.PREFIX_DECREMENT: - case CCodeUnaryOperator.POSTFIX_INCREMENT: - case CCodeUnaryOperator.POSTFIX_DECREMENT: - return false; - default: - break; - } - return is_constant_ccode_expression (cunary.inner); - } else if (cexpr is CCodeBinaryExpression) { - var cbinary = (CCodeBinaryExpression) cexpr; - return is_constant_ccode_expression (cbinary.left) && is_constant_ccode_expression (cbinary.right); - } - - var cparenthesized = (cexpr as CCodeParenthesizedExpression); - return (null != cparenthesized && is_constant_ccode_expression (cparenthesized.inner)); - } - - public static bool is_constant_ccode (CodeNode expr) { - if (expr is Constant) { - // Local constants are not considered constant in C - return !(((Constant) expr).parent_symbol is Block); - } else if (expr is IntegerLiteral) { - return ((IntegerLiteral) expr).is_constant (); - } else if (expr is MemberAccess) { - return is_constant_ccode (((MemberAccess) expr).symbol_reference); - } else if (expr is CastExpression) { - return is_constant_ccode (((CastExpression) expr).inner); - } - - return false; - } - - /** - * Returns whether the passed cexpr is a pure expression, i.e. an - * expression without side-effects. - */ - public static bool is_pure_ccode_expression (CCodeExpression cexpr) { - if (cexpr is CCodeConstant || cexpr is CCodeIdentifier) { - return true; - } else if (cexpr is CCodeBinaryExpression) { - var cbinary = (CCodeBinaryExpression) cexpr; - return is_pure_ccode_expression (cbinary.left) && is_pure_ccode_expression (cbinary.right); - } else if (cexpr is CCodeUnaryExpression) { - var cunary = (CCodeUnaryExpression) cexpr; - switch (cunary.operator) { - case CCodeUnaryOperator.PREFIX_INCREMENT: - case CCodeUnaryOperator.PREFIX_DECREMENT: - case CCodeUnaryOperator.POSTFIX_INCREMENT: - case CCodeUnaryOperator.POSTFIX_DECREMENT: - return false; - default: - return is_pure_ccode_expression (cunary.inner); - } - } else if (cexpr is CCodeMemberAccess) { - var cma = (CCodeMemberAccess) cexpr; - return is_pure_ccode_expression (cma.inner); - } else if (cexpr is CCodeElementAccess) { - var cea = (CCodeElementAccess) cexpr; - return is_pure_ccode_expression (cea.container) && is_pure_ccode_expression (cea.indices[0]); - } else if (cexpr is CCodeCastExpression) { - var ccast = (CCodeCastExpression) cexpr; - return is_pure_ccode_expression (ccast.inner); - } else if (cexpr is CCodeParenthesizedExpression) { - var cparenthesized = (CCodeParenthesizedExpression) cexpr; - return is_pure_ccode_expression (cparenthesized.inner); - } - - return false; - } - - public override void visit_property (Property prop) { - visit_member (prop); - - if (prop.get_accessor != null) { - prop.get_accessor.accept (this); - } - if (prop.set_accessor != null) { - prop.set_accessor.accept (this); - } - } - - public void generate_type_declaration (DataType type, CCodeFile decl_space) { - if (type is ObjectType) { - var object_type = (ObjectType) type; - if (object_type.type_symbol is Class) { - var cl = (Class) object_type.type_symbol; - generate_class_declaration (cl, decl_space); - if (!cl.is_compact && cl.has_type_parameters ()) { - generate_struct_declaration ((Struct) gtype_type, decl_space); - } - } else if (object_type.type_symbol is Interface) { - var iface = (Interface) object_type.type_symbol; - generate_interface_declaration (iface, decl_space); - if (iface.has_type_parameters ()) { - generate_struct_declaration ((Struct) gtype_type, decl_space); - } - } - } else if (type is DelegateType) { - var deleg_type = (DelegateType) type; - var d = deleg_type.delegate_symbol; - generate_delegate_declaration (d, decl_space); - if (d.has_target) { - generate_type_declaration (delegate_target_type, decl_space); - if (deleg_type.is_disposable ()) { - generate_type_declaration (delegate_target_destroy_type, decl_space); - } - } - } else if (type.type_symbol is Enum) { - var en = (Enum) type.type_symbol; - generate_enum_declaration (en, decl_space); - } else if (type is ValueType) { - var value_type = (ValueType) type; - generate_struct_declaration ((Struct) value_type.type_symbol, decl_space); - } else if (type is ArrayType) { - var array_type = (ArrayType) type; - generate_type_declaration (array_type.element_type, decl_space); - if (array_type.length_type != null) { - generate_type_declaration (array_type.length_type, decl_space); - } - } else if (type is ErrorType) { - var error_type = (ErrorType) type; - if (error_type.error_domain != null) { - generate_error_domain_declaration (error_type.error_domain, decl_space); - } else { - generate_class_declaration (gerror, decl_space); - } - } else if (type is PointerType) { - var pointer_type = (PointerType) type; - generate_type_declaration (pointer_type.base_type, decl_space); - } else if (type is MethodType) { - var method = ((MethodType) type).method_symbol; - if (method.has_type_parameters () && !get_ccode_simple_generics (method)) { - generate_struct_declaration ((Struct) gtype_type, decl_space); - } - } - - foreach (DataType type_arg in type.get_type_arguments ()) { - generate_type_declaration (type_arg, decl_space); - } - } - - public virtual void generate_class_struct_declaration (Class cl, CCodeFile decl_space) { - } - - public virtual void generate_struct_declaration (Struct st, CCodeFile decl_space) { - } - - public virtual void generate_delegate_declaration (Delegate d, CCodeFile decl_space) { - } - - public virtual void generate_cparameters (Method m, CCodeFile decl_space, Map cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, Map? carg_map = null, CCodeFunctionCall? vcall = null, int direction = 3) { - } - - public void generate_property_accessor_declaration (PropertyAccessor acc, CCodeFile decl_space) { - if (add_symbol_declaration (decl_space, acc, get_ccode_name (acc))) { - return; - } - - var prop = (Property) acc.prop; - - bool returns_real_struct = acc.readable && prop.property_type.is_real_non_null_struct_type (); - - - CCodeParameter cvalueparam; - if (returns_real_struct) { - cvalueparam = new CCodeParameter ("result", "%s *".printf (get_ccode_name (acc.value_type))); - } else if (!acc.readable && prop.property_type.is_real_non_null_struct_type ()) { - cvalueparam = new CCodeParameter ("value", "%s *".printf (get_ccode_name (acc.value_type))); - } else { - cvalueparam = new CCodeParameter ("value", get_ccode_name (acc.value_type)); - } - generate_type_declaration (acc.value_type, decl_space); - - CCodeFunction function; - if (acc.readable && !returns_real_struct) { - function = new CCodeFunction (get_ccode_name (acc), get_ccode_name (acc.value_type)); - } else { - function = new CCodeFunction (get_ccode_name (acc), "void"); - } - - if (prop.binding == MemberBinding.INSTANCE) { - var t = (TypeSymbol) prop.parent_symbol; - var this_type = SemanticAnalyzer.get_data_type_for_symbol (t); - generate_type_declaration (this_type, decl_space); - var cselfparam = new CCodeParameter ("self", get_ccode_name (this_type)); - if (t is Struct && !((Struct) t).is_simple_type ()) { - cselfparam.type_name += "*"; - } - - function.add_parameter (cselfparam); - } - - if (acc.writable || acc.construction || returns_real_struct) { - function.add_parameter (cvalueparam); - } - - if (acc.value_type is ArrayType && get_ccode_array_length (prop)) { - var array_type = (ArrayType) acc.value_type; - var length_ctype = get_ccode_array_length_type (prop); - for (int dim = 1; dim <= array_type.rank; dim++) { - function.add_parameter (new CCodeParameter (get_array_length_cname (acc.readable ? "result" : "value", dim), acc.readable ? length_ctype + "*" : length_ctype)); - } - } else if ((acc.value_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { - function.add_parameter (new CCodeParameter (get_delegate_target_cname (acc.readable ? "result" : "value"), acc.readable ? get_ccode_name (delegate_target_type) + "*" : get_ccode_name (delegate_target_type))); - if (!acc.readable && acc.value_type.value_owned) { - function.add_parameter (new CCodeParameter (get_delegate_target_destroy_notify_cname ("value"), get_ccode_name (delegate_target_destroy_type))); - } - } - - if (prop.version.deprecated) { - if (context.profile == Profile.GOBJECT) { - decl_space.add_include ("glib.h"); - } - function.modifiers |= CCodeModifiers.DEPRECATED; - } - - if (!prop.is_abstract - && (prop.is_private_symbol () || (!acc.readable && !acc.writable) || acc.access == SymbolAccessibility.PRIVATE)) { - function.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && (prop.is_internal_symbol () || acc.access == SymbolAccessibility.INTERNAL)) { - function.modifiers |= CCodeModifiers.INTERNAL; - } else { - function.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - decl_space.add_function_declaration (function); - } - - public override void visit_property_accessor (PropertyAccessor acc) { - push_context (new EmitContext (acc)); - push_line (acc.source_reference); - - var prop = (Property) acc.prop; - - if (acc.comment != null) { - cfile.add_type_member_definition (new CCodeComment (acc.comment.content)); - } - - bool returns_real_struct = acc.readable && prop.property_type.is_real_non_null_struct_type (); - - if (acc.result_var != null) { - acc.result_var.accept (this); - } - - var t = (TypeSymbol) prop.parent_symbol; - - // do not declare overriding properties and interface implementations - if (prop.is_abstract || prop.is_virtual - || (prop.base_property == null && prop.base_interface_property == null)) { - generate_property_accessor_declaration (acc, cfile); - - // do not declare construct-only properties in header files - if (acc.readable || acc.writable) { - if (!prop.is_internal_symbol () - && (acc.access == SymbolAccessibility.PUBLIC - || acc.access == SymbolAccessibility.PROTECTED)) { - generate_property_accessor_declaration (acc, header_file); - } - if (!prop.is_private_symbol () && acc.access != SymbolAccessibility.PRIVATE) { - generate_property_accessor_declaration (acc, internal_header_file); - } - } - } - - if (acc.source_type == SourceFileType.FAST) { - pop_line (); - pop_context (); - return; - } - - var this_type = SemanticAnalyzer.get_data_type_for_symbol (t); - var cselfparam = new CCodeParameter ("self", get_ccode_name (this_type)); - if (t is Struct && !((Struct) t).is_simple_type ()) { - cselfparam.type_name += "*"; - } - CCodeParameter cvalueparam; - if (returns_real_struct) { - cvalueparam = new CCodeParameter ("result", "%s *".printf (get_ccode_name (acc.value_type))); - } else if (!acc.readable && prop.property_type.is_real_non_null_struct_type ()) { - cvalueparam = new CCodeParameter ("value", "%s *".printf (get_ccode_name (acc.value_type))); - } else { - cvalueparam = new CCodeParameter ("value", get_ccode_name (acc.value_type)); - } - - if (prop.is_abstract || prop.is_virtual) { - CCodeFunction function; - if (acc.readable && !returns_real_struct) { - function = new CCodeFunction (get_ccode_name (acc), get_ccode_name (current_return_type)); - } else { - function = new CCodeFunction (get_ccode_name (acc), "void"); - } - function.add_parameter (cselfparam); - if (acc.writable || acc.construction || returns_real_struct) { - function.add_parameter (cvalueparam); - } - - if (acc.value_type is ArrayType && get_ccode_array_length (prop)) { - var array_type = (ArrayType) acc.value_type; - var length_ctype = get_ccode_array_length_type (prop); - for (int dim = 1; dim <= array_type.rank; dim++) { - function.add_parameter (new CCodeParameter (get_array_length_cname (acc.readable ? "result" : "value", dim), acc.readable ? length_ctype + "*": length_ctype)); - } - } else if ((acc.value_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { - function.add_parameter (new CCodeParameter (get_delegate_target_cname (acc.readable ? "result" : "value"), acc.readable ? get_ccode_name (delegate_target_type) + "*" : get_ccode_name (delegate_target_type))); - if (!acc.readable && acc.value_type.value_owned) { - function.add_parameter (new CCodeParameter (get_delegate_target_destroy_notify_cname ("value"), get_ccode_name (delegate_target_destroy_type))); - } - } - - if (!prop.is_abstract - && (prop.is_private_symbol () || !(acc.readable || acc.writable) || acc.access == SymbolAccessibility.PRIVATE)) { - // accessor function should be private if the property is an internal symbol or it's a construct-only setter - function.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && (prop.is_internal_symbol () || acc.access == SymbolAccessibility.INTERNAL)) { - function.modifiers |= CCodeModifiers.INTERNAL; - } - - push_function (function); - - if (acc.value_type.is_non_null_simple_type () && default_value_for_type (acc.value_type, false) == null) { - var vardecl = new CCodeVariableDeclarator ("result", default_value_for_type (acc.value_type, true)); - vardecl.init0 = true; - ccode.add_declaration (get_ccode_name (acc.value_type), vardecl); - } - - if (prop.binding == MemberBinding.INSTANCE) { - if (!acc.readable || returns_real_struct) { - create_property_type_check_statement (prop, false, t, true, "self"); - } else { - create_property_type_check_statement (prop, true, t, true, "self"); - } - } - - CCodeExpression vcast; - if (prop.parent_symbol is Interface) { - var iface = (Interface) prop.parent_symbol; - - vcast = new CCodeIdentifier ("_iface_"); - var vcastcall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (iface))); - ((CCodeFunctionCall) vcastcall).add_argument (new CCodeIdentifier ("self")); - ccode.add_declaration ("%s*".printf (get_ccode_type_name (iface)), new CCodeVariableDeclarator ("_iface_")); - ccode.add_assignment (vcast, vcastcall); - } else { - var cl = (Class) prop.parent_symbol; - if (!cl.is_compact) { - vcast = new CCodeIdentifier ("_klass_"); - var vcastcall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (cl))); - ((CCodeFunctionCall) vcastcall).add_argument (new CCodeIdentifier ("self")); - ccode.add_declaration ("%s*".printf (get_ccode_type_name (cl)), new CCodeVariableDeclarator ("_klass_")); - ccode.add_assignment (vcast, vcastcall); - } else { - vcast = new CCodeIdentifier ("self"); - } - } - - if (acc.readable) { - var vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "get_%s".printf (prop.name))); - vcall.add_argument (new CCodeIdentifier ("self")); - - // check if vfunc pointer is properly set - ccode.open_if (vcall.call); - - if (returns_real_struct) { - vcall.add_argument (new CCodeIdentifier ("result")); - ccode.add_expression (vcall); - } else { - if (acc.value_type is ArrayType && get_ccode_array_length (prop)) { - var array_type = (ArrayType) acc.value_type; - - for (int dim = 1; dim <= array_type.rank; dim++) { - var len_expr = new CCodeIdentifier (get_array_length_cname ("result", dim)); - vcall.add_argument (len_expr); - } - } else if ((acc.value_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { - vcall.add_argument (new CCodeIdentifier (get_delegate_target_cname ("result"))); - } - - ccode.add_return (vcall); - } - ccode.close (); - - if (acc.value_type.is_non_null_simple_type () && default_value_for_type (acc.value_type, false) == null) { - ccode.add_return (new CCodeIdentifier ("result")); - } else if (!(acc.value_type is VoidType)) { - ccode.add_return (default_value_for_type (acc.value_type, false, true)); - } - } else { - var vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "set_%s".printf (prop.name))); - vcall.add_argument (new CCodeIdentifier ("self")); - vcall.add_argument (new CCodeIdentifier ("value")); - - // check if vfunc pointer is properly set - ccode.open_if (vcall.call); - - if (acc.value_type is ArrayType && get_ccode_array_length (prop)) { - var array_type = (ArrayType) acc.value_type; - - for (int dim = 1; dim <= array_type.rank; dim++) { - var len_expr = new CCodeIdentifier (get_array_length_cname ("value", dim)); - vcall.add_argument (len_expr); - } - } else if ((acc.value_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { - vcall.add_argument (new CCodeIdentifier (get_delegate_target_cname ("value"))); - if (!acc.readable && acc.value_type.value_owned) { - vcall.add_argument (new CCodeIdentifier (get_delegate_target_destroy_notify_cname ("value"))); - } - } - - ccode.add_expression (vcall); - ccode.close (); - } - - pop_function (); - - cfile.add_function (function); - } - - if (!prop.is_abstract && acc.body != null) { - bool is_virtual = prop.base_property != null || prop.base_interface_property != null; - - string cname = get_ccode_real_name (acc); - - CCodeFunction function; - if (acc.writable || acc.construction || returns_real_struct) { - function = new CCodeFunction (cname, "void"); - } else { - function = new CCodeFunction (cname, get_ccode_name (acc.value_type)); - } - - ObjectType base_type = null; - if (prop.binding == MemberBinding.INSTANCE) { - if (is_virtual) { - if (prop.base_property != null) { - base_type = new ObjectType ((ObjectTypeSymbol) prop.base_property.parent_symbol); - } else if (prop.base_interface_property != null) { - base_type = new ObjectType ((ObjectTypeSymbol) prop.base_interface_property.parent_symbol); - } - function.modifiers |= CCodeModifiers.STATIC; - function.add_parameter (new CCodeParameter ("base", get_ccode_name (base_type))); - } else { - function.add_parameter (cselfparam); - } - } - if (acc.writable || acc.construction || returns_real_struct) { - function.add_parameter (cvalueparam); - } - - if (acc.value_type is ArrayType && get_ccode_array_length (prop)) { - var array_type = (ArrayType) acc.value_type; - var length_ctype = get_ccode_array_length_type (prop); - for (int dim = 1; dim <= array_type.rank; dim++) { - function.add_parameter (new CCodeParameter (get_array_length_cname (acc.readable ? "result" : "value", dim), acc.readable ? length_ctype + "*" : length_ctype)); - } - } else if ((acc.value_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) acc.value_type).delegate_symbol.has_target) { - function.add_parameter (new CCodeParameter (get_delegate_target_cname (acc.readable ? "result" : "value"), acc.readable ? get_ccode_name (delegate_target_type) + "*" : get_ccode_name (delegate_target_type))); - if (!acc.readable && acc.value_type.value_owned) { - function.add_parameter (new CCodeParameter (get_delegate_target_destroy_notify_cname ("value"), get_ccode_name (delegate_target_destroy_type))); - } - } - - if (!is_virtual) { - if (prop.is_private_symbol () || !(acc.readable || acc.writable) || acc.access == SymbolAccessibility.PRIVATE) { - // accessor function should be private if the property is an internal symbol or it's a construct-only setter - function.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && (prop.is_internal_symbol () || acc.access == SymbolAccessibility.INTERNAL)) { - function.modifiers |= CCodeModifiers.INTERNAL; - } - } - - push_function (function); - - if (prop.binding == MemberBinding.INSTANCE && !is_virtual) { - if (!acc.readable || returns_real_struct) { - create_property_type_check_statement (prop, false, t, true, "self"); - } else { - create_property_type_check_statement (prop, true, t, true, "self"); - } - } - - if (acc.readable && !returns_real_struct) { - // do not declare result variable if exit block is known to be unreachable - if (acc.return_block == null || acc.return_block.get_predecessors ().size > 0) { - ccode.add_declaration (get_ccode_name (acc.value_type), new CCodeVariableDeclarator ("result")); - } - } - - if (is_virtual) { - ccode.add_declaration (get_ccode_name (this_type), new CCodeVariableDeclarator ("self")); - ccode.add_assignment (new CCodeIdentifier ("self"), get_cvalue_ (transform_value (new GLibValue (base_type, new CCodeIdentifier ("base"), true), this_type, acc))); - } - - // notify on property changes - if (context.analyzer.is_gobject_property (prop) && - prop.notify && - (acc.writable || acc.construction)) { - var notify_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_notify_by_pspec")); - notify_call.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *")); - notify_call.add_argument (get_param_spec_cexpression (prop)); - - var get_accessor = prop.get_accessor; - if (get_accessor != null && get_accessor.automatic_body) { - var property_type = prop.property_type; - var get_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_real_name (get_accessor))); - get_call.add_argument (new CCodeIdentifier (is_virtual ? "base" : "self")); - - if (property_type is ArrayType && get_ccode_array_length (prop)) { - ccode.add_declaration (get_ccode_name (property_type), new CCodeVariableDeclarator ("old_value")); - ccode.add_declaration (get_ccode_array_length_type (prop), new CCodeVariableDeclarator ("old_value_length")); - get_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("old_value_length"))); - ccode.add_assignment (new CCodeIdentifier ("old_value"), get_call); - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("old_value"), new CCodeIdentifier ("value"))); - } else if (property_type.compatible (string_type)) { - ccode.add_declaration (get_ccode_name (property_type), new CCodeVariableDeclarator ("old_value")); - ccode.add_assignment (new CCodeIdentifier ("old_value"), get_call); - CCodeFunctionCall ccall; - if (context.profile == Profile.POSIX) { - cfile.add_include ("string.h"); - ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_cmp_wrapper (new CCodeIdentifier ("strcmp")))); - } else { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_strcmp0")); - } - ccall.add_argument (new CCodeIdentifier ("value")); - ccall.add_argument (new CCodeIdentifier ("old_value")); - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, ccall, new CCodeConstant ("0"))); - } else if (property_type is StructValueType) { - ccode.add_declaration (get_ccode_name (property_type), new CCodeVariableDeclarator ("old_value")); - if (property_type.nullable) { - ccode.add_assignment (new CCodeIdentifier ("old_value"), get_call); - } else { - get_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("old_value"))); - ccode.add_expression (get_call); - } - var equalfunc = generate_struct_equal_function ((Struct) property_type.type_symbol); - var ccall = new CCodeFunctionCall (new CCodeIdentifier (equalfunc)); - ccall.add_argument (new CCodeIdentifier ("value")); - if (property_type.nullable) { - ccall.add_argument (new CCodeIdentifier ("old_value")); - } else { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("old_value"))); - } - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, ccall, new CCodeConstant ("TRUE"))); - } else { - ccode.add_declaration (get_ccode_name (property_type), new CCodeVariableDeclarator ("old_value")); - ccode.add_assignment (new CCodeIdentifier ("old_value"), get_call); - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("old_value"), new CCodeIdentifier ("value"))); - } - - acc.body.emit (this); - ccode.add_expression (notify_call); - ccode.close (); - - if (prop.get_accessor.value_type.is_disposable ()) { - var old_value = new GLibValue (prop.get_accessor.value_type, new CCodeIdentifier ("old_value"), true); - if (property_type is ArrayType && get_ccode_array_length (prop)) { - old_value.append_array_length_cvalue (new CCodeIdentifier ("old_value_length")); - } - ccode.add_expression (destroy_value (old_value)); - } - } else { - acc.body.emit (this); - ccode.add_expression (notify_call); - } - } else { - acc.body.emit (this); - } - - if (current_method_inner_error) { - ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL"))); - } - - pop_function (); - - cfile.add_function (function); - } - - pop_line (); - pop_context (); - } - - public override void visit_destructor (Destructor d) { - if (d.binding == MemberBinding.STATIC && !in_plugin) { - Report.error (d.source_reference, "static destructors are only supported for dynamic types"); - d.error = true; - return; - } - } - - public int get_block_id (Block b) { - int result = block_map[b]; - if (result == 0) { - result = ++next_block_id; - block_map[b] = result; - } - return result; - } - - public bool no_implicit_copy (DataType type) { - // note: implicit copy of array is planned to be forbidden - unowned Class? cl = type.type_symbol as Class; - return (type is DelegateType || - type is ArrayType || - (cl != null && !cl.is_immutable && !is_reference_counting (cl) && !get_ccode_is_gboxed (cl))); - } - - void capture_parameter (Parameter param, CCodeStruct data, int block_id) { - generate_type_declaration (param.variable_type, cfile); - - var param_type = param.variable_type.copy (); - if (!param.variable_type.value_owned) { - param_type.value_owned = !no_implicit_copy (param.variable_type); - } - data.add_field (get_ccode_name (param_type), get_ccode_name (param), 0, get_ccode_declarator_suffix (param_type)); - - // create copy if necessary as captured variables may need to be kept alive - param.captured = false; - var value = load_parameter (param); - - var array_type = param.variable_type as ArrayType; - var deleg_type = param.variable_type as DelegateType; - - if (array_type != null && get_ccode_array_length (param) && !((ArrayType) array_type).fixed_length) { - var length_ctype = get_ccode_array_length_type (param); - for (int dim = 1; dim <= array_type.rank; dim++) { - data.add_field (length_ctype, get_variable_array_length_cname (param, dim)); - } - } else if (deleg_type != null && deleg_type.delegate_symbol.has_target) { - data.add_field (get_ccode_name (delegate_target_type), get_ccode_delegate_target_name (param)); - if (param.variable_type.is_disposable ()) { - data.add_field (get_ccode_name (delegate_target_destroy_type), get_ccode_delegate_target_destroy_notify_name (param)); - // reference transfer for delegates - var lvalue = get_parameter_cvalue (param); - ((GLibValue) value).delegate_target_destroy_notify_cvalue = get_delegate_target_destroy_notify_cvalue (lvalue); - } - } - param.captured = true; - - store_parameter (param, value, true); - } - - public override void visit_block (Block b) { - emit_context.push_symbol (b); - - var local_vars = b.get_local_variables (); - - if (b.parent_node is Block || b.parent_node is SwitchStatement || b.parent_node is TryStatement) { - ccode.open_block (); - } - - if (b.parent_node is TryStatement && b == ((TryStatement) b.parent_node).finally_body) { - // finally-block with nested error handling - if (((TryStatement) b.parent_node).body.tree_can_fail) { - if (is_in_coroutine ()) { - // _inner_error0_ gets added to closure_struct in CCodeMethodModule.visit_method() - if (current_inner_error_id > 0 - && (!method_inner_error_var_count.contains (current_method) - || method_inner_error_var_count.get (current_method) < current_inner_error_id)) { - // no initialization necessary, closure struct is zeroed - closure_struct.add_field ("GError*", "_inner_error%d_".printf (current_inner_error_id)); - method_inner_error_var_count.set (current_method, current_inner_error_id); - } - } else { - ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL"))); - } - } - } - - if (b.captured) { - var parent_block = next_closure_block (b.parent_symbol); - - int block_id = get_block_id (b); - string struct_name = "Block%dData".printf (block_id); - - var data = new CCodeStruct ("_" + struct_name); - data.add_field ("int", "_ref_count_"); - if (parent_block != null) { - int parent_block_id = get_block_id (parent_block); - - data.add_field ("Block%dData *".printf (parent_block_id), "_data%d_".printf (parent_block_id)); - } else { - unowned DataType? this_type = get_this_type (); - if (this_type != null) { - data.add_field (get_ccode_name (this_type), "self"); - } - - if (current_method != null) { - // allow capturing generic type parameters - foreach (var type_param in current_method.get_type_parameters ()) { - data.add_field ("GType", get_ccode_type_id (type_param)); - data.add_field ("GBoxedCopyFunc", get_ccode_copy_function (type_param)); - data.add_field ("GDestroyNotify", get_ccode_destroy_function (type_param)); - } - } - } - foreach (var local in local_vars) { - if (local.captured) { - generate_type_declaration (local.variable_type, cfile); - - data.add_field (get_ccode_name (local.variable_type), get_local_cname (local), 0, get_ccode_declarator_suffix (local.variable_type)); - - if (local.variable_type is ArrayType && !((ArrayType) local.variable_type).fixed_length) { - var array_type = (ArrayType) local.variable_type; - var length_ctype = get_ccode_array_length_type (array_type); - for (int dim = 1; dim <= array_type.rank; dim++) { - data.add_field (length_ctype, get_array_length_cname (get_local_cname (local), dim)); - } - data.add_field (length_ctype, get_array_size_cname (get_local_cname (local))); - } else if (local.variable_type is DelegateType && ((DelegateType) local.variable_type).delegate_symbol.has_target) { - data.add_field (get_ccode_name (delegate_target_type), get_delegate_target_cname (get_local_cname (local))); - if (local.variable_type.is_disposable ()) { - data.add_field (get_ccode_name (delegate_target_destroy_type), get_delegate_target_destroy_notify_cname (get_local_cname (local))); - } - } else if (local.variable_type.type_symbol == context.analyzer.va_list_type.type_symbol) { - Report.error (local.source_reference, "internal: Capturing `va_list' variable `%s' is not allowed", local.get_full_name ()); - b.error = true; - } - } - } - - var data_alloc = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0")); - data_alloc.add_argument (new CCodeIdentifier (struct_name)); - - if (is_in_coroutine ()) { - closure_struct.add_field (struct_name + "*", "_data%d_".printf (block_id)); - } else { - ccode.add_declaration (struct_name + "*", new CCodeVariableDeclarator ("_data%d_".printf (block_id))); - } - ccode.add_assignment (get_variable_cexpression ("_data%d_".printf (block_id)), data_alloc); - - // initialize ref_count - ccode.add_assignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_ref_count_"), new CCodeIdentifier ("1")); - - if (parent_block != null) { - int parent_block_id = get_block_id (parent_block); - - var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_ref".printf (parent_block_id))); - ref_call.add_argument (get_variable_cexpression ("_data%d_".printf (parent_block_id))); - - ccode.add_assignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)), ref_call); - } else { - // skip self assignment in toplevel block of creation methods with chainup as self is not set at the beginning of the method - // the chainup statement takes care of assigning self in the closure struct - bool in_creation_method_with_chainup = (current_method is CreationMethod && current_class != null && current_class.base_class != null); - - unowned DataType? this_type = get_this_type (); - if (this_type != null && (!in_creation_method_with_chainup || current_method.body != b)) { - CCodeExpression instance; - if (is_in_destructor ()) { - // never increase reference count for self in finalizers to avoid infinite recursion on following unref - instance = new CCodeIdentifier ("self"); - } else { - var ref_call = new CCodeFunctionCall (get_dup_func_expression (this_type, b.source_reference)); - ref_call.add_argument (get_this_cexpression ()); - instance = ref_call; - } - - ccode.add_assignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "self"), instance); - } - - if (current_method != null) { - // allow capturing generic type parameters - var data_var = get_variable_cexpression ("_data%d_".printf (block_id)); - foreach (var type_param in current_method.get_type_parameters ()) { - var type = get_ccode_type_id (type_param); - var dup_func = get_ccode_copy_function (type_param); - var destroy_func = get_ccode_destroy_function (type_param); - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, type), get_variable_cexpression (type)); - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, dup_func), get_variable_cexpression (dup_func)); - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, destroy_func), get_variable_cexpression (destroy_func)); - } - } - } - - if (b.parent_symbol is Method) { - var m = (Method) b.parent_symbol; - - // parameters are captured with the top-level block of the method - foreach (var param in m.get_parameters ()) { - if (param.captured) { - capture_parameter (param, data, block_id); - - if (param.variable_type.type_symbol == context.analyzer.va_list_type.type_symbol) { - Report.error (param.source_reference, "internal: Capturing `va_list' parameter `%s' is not allowed", param.get_full_name ()); - b.error = true; - } - } - } - - if (m.coroutine) { - // capture async data to allow invoking callback from inside closure - data.add_field (get_ccode_name (pointer_type), "_async_data_"); - - // async method is suspended while waiting for callback, - // so we never need to care about memory management of async data - ccode.add_assignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_async_data_"), new CCodeIdentifier ("_data_")); - } - } else if (b.parent_symbol is PropertyAccessor) { - var acc = (PropertyAccessor) b.parent_symbol; - - if (!acc.readable && acc.value_parameter.captured) { - capture_parameter (acc.value_parameter, data, block_id); - } - } else if (b.parent_symbol is ForeachStatement) { - var stmt = (ForeachStatement) b.parent_symbol; - if (!stmt.use_iterator && stmt.element_variable.captured) { - ccode.add_assignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_local_cname (stmt.element_variable)), get_variable_cexpression (get_local_cname (stmt.element_variable))); - } - } - - var typedef = new CCodeTypeDefinition ("struct _" + struct_name, new CCodeVariableDeclarator (struct_name)); - cfile.add_type_declaration (typedef); - cfile.add_type_definition (data); - - // create ref/unref functions - var ref_fun = new CCodeFunction ("block%d_data_ref".printf (block_id), struct_name + "*"); - ref_fun.add_parameter (new CCodeParameter ("_data%d_".printf (block_id), struct_name + "*")); - ref_fun.modifiers = CCodeModifiers.STATIC; - - push_function (ref_fun); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_inc")); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_ref_count_"))); - ccode.add_expression (ccall); - ccode.add_return (new CCodeIdentifier ("_data%d_".printf (block_id))); - - pop_function (); - - cfile.add_function_declaration (ref_fun); - cfile.add_function (ref_fun); - - var unref_fun = new CCodeFunction ("block%d_data_unref".printf (block_id), "void"); - unref_fun.add_parameter (new CCodeParameter ("_userdata_", "void *")); - unref_fun.modifiers = CCodeModifiers.STATIC; - - push_function (unref_fun); - - ccode.add_declaration (struct_name + "*", new CCodeVariableDeclarator ("_data%d_".printf (block_id), new CCodeCastExpression (new CCodeIdentifier ("_userdata_"), struct_name + "*"))); - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_dec_and_test")); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_ref_count_"))); - ccode.open_if (ccall); - - CCodeExpression outer_block = new CCodeIdentifier ("_data%d_".printf (block_id)); - unowned Block parent_closure_block = b; - while (true) { - parent_closure_block = next_closure_block (parent_closure_block.parent_symbol); - if (parent_closure_block == null) { - break; - } - int parent_block_id = get_block_id (parent_closure_block); - outer_block = new CCodeMemberAccess.pointer (outer_block, "_data%d_".printf (parent_block_id)); - } - - var this_type = get_this_type (); - if (this_type != null) { - // assign "self" for type parameters - ccode.add_declaration(get_ccode_name (this_type), new CCodeVariableDeclarator ("self")); - ccode.add_assignment (new CCodeIdentifier ("self"), new CCodeMemberAccess.pointer (outer_block, "self")); - } - - if (current_method != null) { - // assign captured generic type parameters - foreach (var type_param in current_method.get_type_parameters ()) { - var type = get_ccode_type_id (type_param); - var dup_func = get_ccode_copy_function (type_param); - var destroy_func = get_ccode_destroy_function (type_param); - ccode.add_declaration ("GType", new CCodeVariableDeclarator (type)); - ccode.add_declaration ("GBoxedCopyFunc", new CCodeVariableDeclarator (dup_func)); - ccode.add_declaration ("GDestroyNotify", new CCodeVariableDeclarator (destroy_func)); - ccode.add_assignment (new CCodeIdentifier (type), new CCodeMemberAccess.pointer (outer_block, type)); - ccode.add_assignment (new CCodeIdentifier (dup_func), new CCodeMemberAccess.pointer (outer_block, dup_func)); - ccode.add_assignment (new CCodeIdentifier (destroy_func), new CCodeMemberAccess.pointer (outer_block, destroy_func)); - } - } - - // free in reverse order - for (int i = local_vars.size - 1; i >= 0; i--) { - var local = local_vars[i]; - if (local.captured) { - if (requires_destroy (local.variable_type)) { - bool old_coroutine = false; - if (current_method != null) { - old_coroutine = current_method.coroutine; - current_method.coroutine = false; - } - - ccode.add_expression (destroy_local (local)); - - if (old_coroutine) { - current_method.coroutine = true; - } - } - } - } - - if (b.parent_symbol is Method) { - var m = (Method) b.parent_symbol; - - // parameters are captured with the top-level block of the method - foreach (var param in m.get_parameters ()) { - if (param.captured) { - var param_type = param.variable_type.copy (); - if (!param_type.value_owned) { - param_type.value_owned = !no_implicit_copy (param_type); - } - - if (requires_destroy (param_type)) { - bool old_coroutine = false; - if (m != null) { - old_coroutine = m.coroutine; - m.coroutine = false; - } - - ccode.add_expression (destroy_parameter (param)); - - if (old_coroutine) { - m.coroutine = true; - } - } - } - } - } else if (b.parent_symbol is PropertyAccessor) { - var acc = (PropertyAccessor) b.parent_symbol; - - if (!acc.readable && acc.value_parameter.captured) { - var param_type = acc.value_parameter.variable_type.copy (); - if (!param_type.value_owned) { - param_type.value_owned = !no_implicit_copy (param_type); - } - - if (requires_destroy (param_type)) { - ccode.add_expression (destroy_parameter (acc.value_parameter)); - } - } - } - - // free parent block and "self" after captured variables - // because they may require type parameters - if (parent_block != null) { - int parent_block_id = get_block_id (parent_block); - - var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (parent_block_id))); - unref_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id))); - ccode.add_expression (unref_call); - ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)), new CCodeConstant ("NULL")); - } else { - this_type = get_this_type (); - if (this_type != null) { - this_type = this_type.copy (); - this_type.value_owned = true; - if (this_type.is_disposable () && !is_in_destructor ()) { - // reference count for self is not increased in finalizers - var this_value = new GLibValue (this_type, new CCodeIdentifier ("self"), true); - ccode.add_expression (destroy_value (this_value)); - } - } - } - - var data_free = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); - data_free.add_argument (new CCodeIdentifier (struct_name)); - data_free.add_argument (new CCodeIdentifier ("_data%d_".printf (block_id))); - ccode.add_expression (data_free); - - ccode.close (); - - pop_function (); - - cfile.add_function_declaration (unref_fun); - cfile.add_function (unref_fun); - } - - foreach (Statement stmt in b.get_statements ()) { - push_line (stmt.source_reference); - stmt.emit (this); - pop_line (); - } - - if (!b.unreachable_exit) { - if (b.parent_symbol is Method) { - unowned Method m = (Method) b.parent_symbol; - // check postconditions - foreach (var postcondition in m.get_postconditions ()) { - create_postcondition_statement (postcondition); - } - } - - // free in reverse order - for (int i = local_vars.size - 1; i >= 0; i--) { - var local = local_vars[i]; - local.active = false; - if (!local.unreachable && !local.captured && requires_destroy (local.variable_type)) { - ccode.add_expression (destroy_local (local)); - } - } - - if (b.parent_symbol is Method) { - var m = (Method) b.parent_symbol; - foreach (Parameter param in m.get_parameters ()) { - if (!param.captured && !param.ellipsis && !param.params_array && requires_destroy (param.variable_type) && param.direction == ParameterDirection.IN) { - ccode.add_expression (destroy_parameter (param)); - } else if (param.direction == ParameterDirection.OUT && !m.coroutine) { - return_out_parameter (param); - } - } - } else if (b.parent_symbol is PropertyAccessor) { - var acc = (PropertyAccessor) b.parent_symbol; - if (acc.value_parameter != null && !acc.value_parameter.captured && requires_destroy (acc.value_parameter.variable_type)) { - ccode.add_expression (destroy_parameter (acc.value_parameter)); - } - } - - if (b.captured) { - int block_id = get_block_id (b); - - var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (block_id))); - data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id))); - ccode.add_expression (data_unref); - ccode.add_assignment (get_variable_cexpression ("_data%d_".printf (block_id)), new CCodeConstant ("NULL")); - } - } - - if (b.parent_node is Block || b.parent_node is SwitchStatement || b.parent_node is TryStatement) { - ccode.close (); - } - - emit_context.pop_symbol (); - } - - public override void visit_declaration_statement (DeclarationStatement stmt) { - stmt.declaration.accept (this); - } - - public CCodeExpression get_cexpression (string name) { - if (is_in_coroutine ()) { - return new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), name); - } else { - return new CCodeIdentifier (name); - } - } - - public CCodeExpression get_local_cexpression (LocalVariable local) { - return get_cexpression (get_local_cname (local)); - } - - public CCodeExpression get_parameter_cexpression (Parameter param) { - return get_cexpression (get_ccode_name (param)); - } - - public CCodeExpression get_variable_cexpression (string name) { - return get_cexpression (get_variable_cname (name)); - } - - public CCodeExpression get_this_cexpression () { - return get_cexpression ("self"); - } - - public CCodeExpression get_this_class_cexpression (Class cl, TargetValue? instance = null) { - CCodeExpression cast; - CCodeFunctionCall call; - if (instance != null) { - // Accessing the member of an instance - if (cl.external_package) { - call = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_INSTANCE_GET_CLASS")); - call.add_argument (get_cvalue_ (instance)); - call.add_argument (new CCodeIdentifier (get_ccode_type_id (cl))); - call.add_argument (new CCodeIdentifier (get_ccode_type_name (cl))); - } else { - call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (cl))); - call.add_argument (get_cvalue_ (instance)); - } - cast = call; - } else if (get_this_type () != null) { - // Accessing the member from within an instance method - if (cl.external_package) { - call = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_INSTANCE_GET_CLASS")); - call.add_argument (get_this_cexpression ()); - call.add_argument (new CCodeIdentifier (get_ccode_type_id (cl))); - call.add_argument (new CCodeIdentifier (get_ccode_type_name (cl))); - } else { - call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (cl))); - call.add_argument (get_this_cexpression ()); - } - cast = call; - } else { - // Accessing the member from a static or class constructor - if (current_class == cl) { - cast = new CCodeIdentifier ("klass"); - } else { - call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (cl))); - call.add_argument (new CCodeIdentifier ("klass")); - cast = call; - } - } - return cast; - } - - public CCodeExpression get_this_interface_cexpression (Interface iface, TargetValue? instance = null) { - unowned Class? cl = current_class; - if (cl != null && cl.implements (iface)) { - return new CCodeIdentifier ("%s_%s_parent_iface".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface))); - } - - if (cl != null && !cl.is_a (iface)) { - Report.warning (cl.source_reference, "internal: `%s' is not a `%s'", cl.get_full_name (), iface.get_full_name ()); - } - - CCodeExpression cast; - CCodeFunctionCall call; - if (instance != null) { - if (iface.external_package) { - call = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_INSTANCE_GET_INTERFACE")); - call.add_argument (get_cvalue_ (instance)); - call.add_argument (new CCodeIdentifier (get_ccode_type_id (iface))); - call.add_argument (new CCodeIdentifier (get_ccode_type_name (iface))); - } else { - call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (iface))); - call.add_argument (get_cvalue_ (instance)); - } - cast = call; - } else if (get_this_type () != null) { - if (iface.external_package) { - call = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_INSTANCE_GET_INTERFACE")); - call.add_argument (get_this_cexpression ()); - call.add_argument (new CCodeIdentifier (get_ccode_type_id (iface))); - call.add_argument (new CCodeIdentifier (get_ccode_type_name (iface))); - } else { - call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (iface))); - call.add_argument (get_this_cexpression ()); - } - cast = call; - } else { - Report.error (null, "internal: missing instance"); - cast = null; - assert_not_reached (); - } - return cast; - } - - public CCodeExpression get_inner_error_cexpression () { - return get_cexpression ("_inner_error%d_".printf (current_inner_error_id)); - } - - public string get_local_cname (LocalVariable local) { - var cname = get_variable_cname (local.name); - if (cname[0].isdigit ()) { - cname = "_%s_".printf (cname); - } - if (is_in_coroutine ()) { - var clash_index = emit_context.closure_variable_clash_map.get (local); - if (clash_index > 0) { - cname = "_vala%d_%s".printf (clash_index, cname); - } - } - return cname; - } - - public string get_variable_cname (string name) { - if (name[0] == '.') { - if (name == ".result") { - return "result"; - } - // compiler-internal variable - if (!variable_name_map.contains (name)) { - variable_name_map.set (name, "_tmp%d_".printf (next_temp_var_id)); - next_temp_var_id++; - } - return variable_name_map.get (name); - } else if (reserved_identifiers.contains (name)) { - return "_%s_".printf (name); - } else { - return name; - } - } - - public bool is_simple_struct_creation (Variable variable, Expression expr) { - unowned Struct? st = variable.variable_type.type_symbol as Struct; - var creation = expr as ObjectCreationExpression; - if (creation != null && st != null && (!st.is_simple_type () || get_ccode_name (st) == "va_list") && !variable.variable_type.nullable && - variable.variable_type.type_symbol != gvalue_type && creation.get_object_initializer ().size == 0) { - return true; - } else { - return false; - } - } - - static bool is_foreach_element_variable (LocalVariable local) { - var block = local.parent_symbol; - if (block != null) { - var stmt = block.parent_symbol as ForeachStatement; - if (stmt != null && !stmt.use_iterator && stmt.element_variable == local) { - return true; - } - } - return false; - } - - public override void visit_local_variable (LocalVariable local) { - /* Declaration */ - - generate_type_declaration (local.variable_type, cfile); - - // captured element variables of foreach statements (without iterator) require local declaration - var declared = !local.captured || is_foreach_element_variable (local); - if (declared) { - if (is_in_coroutine ()) { - var count = emit_context.closure_variable_count_map.get (local.name); - if (count > 0) { - emit_context.closure_variable_clash_map.set (local, count); - } - emit_context.closure_variable_count_map.set (local.name, count + 1); - - closure_struct.add_field (get_ccode_name (local.variable_type), get_local_cname (local), 0, get_ccode_declarator_suffix (local.variable_type)); - } else { - var cvar = new CCodeVariableDeclarator (get_local_cname (local), null, get_ccode_declarator_suffix (local.variable_type)); - - // try to initialize uninitialized variables - // initialization not necessary for variables stored in closure - CCodeExpression? size = null; - if (!requires_memset_init (local, out size)) { - cvar.initializer = default_value_for_type (local.variable_type, true); - cvar.init0 = true; - } else if (size != null && local.initializer == null) { - cfile.add_include ("string.h"); - var memset_call = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - memset_call.add_argument (get_variable_cexpression (local.name)); - memset_call.add_argument (new CCodeConstant ("0")); - memset_call.add_argument (size); - ccode.add_expression (memset_call); - } - - ccode.add_declaration (get_ccode_name (local.variable_type), cvar); - } - } - - /* Emit initializer */ - if (local.initializer != null) { - local.initializer.emit (this); - - visit_end_full_expression (local.initializer); - } - - - CCodeExpression rhs = null; - if (local.initializer != null && get_cvalue (local.initializer) != null) { - rhs = get_cvalue (local.initializer); - } - - /* Additional temp variables */ - - if (declared) { - if (local.variable_type is ArrayType) { - // create variables to store array dimensions - var array_type = (ArrayType) local.variable_type; - - if (!array_type.fixed_length) { - for (int dim = 1; dim <= array_type.rank; dim++) { - var len_var = new LocalVariable (array_type.length_type.copy (), get_array_length_cname (get_local_cname (local), dim)); - len_var.init = local.initializer == null; - emit_temp_var (len_var); - } - - if (array_type.rank == 1) { - var size_var = new LocalVariable (array_type.length_type.copy (), get_array_size_cname (get_local_cname (local))); - size_var.init = local.initializer == null; - emit_temp_var (size_var); - } - } - } else if (local.variable_type is DelegateType) { - var deleg_type = (DelegateType) local.variable_type; - if (deleg_type.delegate_symbol.has_target) { - // create variable to store delegate target - var target_var = new LocalVariable (delegate_target_type.copy (), get_delegate_target_cname (get_local_cname (local))); - target_var.init = local.initializer == null; - emit_temp_var (target_var); - if (deleg_type.is_disposable ()) { - var target_destroy_notify_var = new LocalVariable (delegate_target_destroy_type.copy (), get_delegate_target_destroy_notify_cname (get_local_cname (local))); - target_destroy_notify_var.init = local.initializer == null; - emit_temp_var (target_destroy_notify_var); - } - } - } - } - - /* Store the initializer */ - - if (rhs != null) { - if (!is_simple_struct_creation (local, local.initializer)) { - store_local (local, local.initializer.target_value, true, local.source_reference); - } - } - - if (local.initializer != null && local.initializer.tree_can_fail) { - add_simple_check (local.initializer); - } - - local.active = true; - } - - /** - * Create a temporary variable and return lvalue access to it - */ - public TargetValue create_temp_value (DataType type, bool init, CodeNode node_reference, bool? value_owned = null) { - if (type is VoidType) { - Report.error (node_reference.source_reference, "internal: 'void' not supported as variable type"); - } - - var local = new LocalVariable (type.copy (), "_tmp%d_".printf (next_temp_var_id++), null, node_reference.source_reference); - local.init = init; - if (value_owned != null) { - local.variable_type.value_owned = value_owned; - } - - var array_type = local.variable_type as ArrayType; - var deleg_type = local.variable_type as DelegateType; - - emit_temp_var (local); - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - var len_var = new LocalVariable (array_type.length_type.copy (), get_array_length_cname (local.name, dim), null, node_reference.source_reference); - len_var.init = init; - emit_temp_var (len_var); - } - } else if (deleg_type != null && deleg_type.delegate_symbol.has_target) { - var target_var = new LocalVariable (delegate_target_type.copy (), get_delegate_target_cname (local.name), null, node_reference.source_reference); - target_var.init = init; - emit_temp_var (target_var); - if (deleg_type.is_disposable ()) { - var target_destroy_notify_var = new LocalVariable (delegate_target_destroy_type.copy (), get_delegate_target_destroy_notify_cname (local.name), null, node_reference.source_reference); - target_destroy_notify_var.init = init; - emit_temp_var (target_destroy_notify_var); - } - } - - var value = get_local_cvalue (local); - set_array_size_cvalue (value, null); - return value; - } - - /** - * Load a temporary variable returning unowned or owned rvalue access to it, depending on the ownership of the value type. - */ - public TargetValue load_temp_value (TargetValue lvalue) { - var value = ((GLibValue) lvalue).copy (); - var deleg_type = value.value_type as DelegateType; - if (deleg_type != null) { - if (!deleg_type.delegate_symbol.has_target) { - value.delegate_target_cvalue = new CCodeConstant ("NULL"); - ((GLibValue) value).lvalue = false; - } else if (!deleg_type.is_disposable ()) { - value.delegate_target_destroy_notify_cvalue = new CCodeConstant ("NULL"); - ((GLibValue) value).lvalue = false; - } - } - return value; - } - - /** - * Store a value in a temporary variable and return unowned or owned rvalue access to it, depending on the ownership of the given type. - */ - public TargetValue store_temp_value (TargetValue initializer, CodeNode node_reference, bool? value_owned = null) { - var lvalue = create_temp_value (initializer.value_type, false, node_reference, value_owned); - store_value (lvalue, initializer, node_reference.source_reference); - return load_temp_value (lvalue); - } - - public override void visit_initializer_list (InitializerList list) { - if (list.target_type.type_symbol is Struct) { - /* initializer is used as struct initializer */ - unowned Struct st = (Struct) list.target_type.type_symbol; - while (st.base_struct != null) { - st = st.base_struct; - } - - if (list.parent_node is Constant || list.parent_node is Field || list.parent_node is InitializerList) { - var clist = new CCodeInitializerList (); - - var field_it = st.get_fields ().iterator (); - foreach (Expression expr in list.get_initializers ()) { - Field field = null; - while (field == null) { - field_it.next (); - field = field_it.get (); - if (field.binding != MemberBinding.INSTANCE) { - // we only initialize instance fields - field = null; - } - } - - var cexpr = get_cvalue (expr); - - string ctype = get_ccode_type (field); - if (ctype != null) { - cexpr = new CCodeCastExpression (cexpr, ctype); - } - - clist.append (cexpr); - - var array_type = field.variable_type as ArrayType; - if (array_type != null && !array_type.fixed_length && get_ccode_array_length (field) && !get_ccode_array_null_terminated (field)) { - for (int dim = 1; dim <= array_type.rank; dim++) { - clist.append (get_array_length_cvalue (expr.target_value, dim)); - } - if (array_type.rank == 1 && field.is_internal_symbol ()) { - clist.append (get_array_length_cvalue (expr.target_value, 1)); - } - } - } - - if (list.size <= 0) { - clist.append (new CCodeConstant ("0")); - } - - if (list.parent_node is Constant - || (list.parent_node is Expression && ((Expression) list.parent_node).value_type is ArrayType)) { - set_cvalue (list, clist); - } else { - set_cvalue (list, new CCodeCastExpression (clist, get_ccode_name (list.target_type.type_symbol))); - } - } else { - // used as expression - var instance = create_temp_value (list.value_type, true, list); - - var field_it = st.get_fields ().iterator (); - foreach (Expression expr in list.get_initializers ()) { - Field field = null; - while (field == null) { - field_it.next (); - field = field_it.get (); - if (field.binding != MemberBinding.INSTANCE) { - // we only initialize instance fields - field = null; - } - } - - store_field (field, instance, expr.target_value, expr.source_reference); - } - - list.target_value = instance; - } - } else { - var clist = new CCodeInitializerList (); - foreach (Expression expr in list.get_initializers ()) { - clist.append (get_cvalue (expr)); - } - set_cvalue (list, clist); - } - } - - public LocalVariable get_temp_variable (DataType type, bool value_owned = true, CodeNode? node_reference = null, bool init = false) { - var var_type = type.copy (); - var_type.value_owned = value_owned; - var local = new LocalVariable (var_type, "_tmp%d_".printf (next_temp_var_id)); - local.init = init; - - if (node_reference != null) { - local.source_reference = node_reference.source_reference; - } - - next_temp_var_id++; - - return local; - } - - bool is_in_generic_type (GenericType type) { - if (current_symbol != null && type.type_parameter.parent_symbol is TypeSymbol - && (current_method == null || current_method.binding == MemberBinding.INSTANCE)) { - return true; - } else { - return false; - } - } - - void require_generic_accessors (Interface iface) { - if (iface.get_attribute ("GenericAccessors") == null) { - Report.error (iface.source_reference, - "missing generic type for interface `%s', add GenericAccessors attribute to interface declaration", - iface.get_full_name ()); - } - } - - CCodeExpression get_generic_type_expression (string identifier, GenericType type, bool is_chainup = false) { - if (type.type_parameter.parent_symbol is Interface) { - unowned Interface iface = (Interface) type.type_parameter.parent_symbol; - require_generic_accessors (iface); - - var cast_self = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (iface))); - cast_self.add_argument (get_this_cexpression ()); - var function_call = new CCodeFunctionCall (new CCodeMemberAccess.pointer (cast_self, "get_%s".printf (identifier))); - function_call.add_argument (get_this_cexpression ()); - return function_call; - } - - if (is_in_generic_type (type) && !is_chainup && !in_creation_method) { - return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (get_this_cexpression (), "priv"), identifier); - } else { - return get_variable_cexpression (identifier); - } - } - - public CCodeExpression get_type_id_expression (DataType type, bool is_chainup = false) { - if (type is GenericType) { - var type_parameter = ((GenericType) type).type_parameter; - string identifier = get_ccode_type_id (type_parameter); - return get_generic_type_expression (identifier, (GenericType) type, is_chainup); - } else { - string type_id = get_ccode_type_id (type); - if (type_id == "") { - type_id = "G_TYPE_INVALID"; - } else { - generate_type_declaration (type, cfile); - } - return new CCodeIdentifier (type_id); - } - } - - public virtual CCodeExpression? get_dup_func_expression (DataType type, SourceReference? source_reference, bool is_chainup = false) { - if (type is ErrorType) { - return new CCodeIdentifier ("g_error_copy"); - } else if (type is GenericType) { - var type_parameter = ((GenericType) type).type_parameter; - string identifier = get_ccode_copy_function (type_parameter); - return get_generic_type_expression (identifier, (GenericType) type, is_chainup); - } else if (type.type_symbol != null) { - string dup_function; - unowned Class? cl = type.type_symbol as Class; - if (is_reference_counting (type.type_symbol)) { - dup_function = get_ccode_ref_function ((ObjectTypeSymbol) type.type_symbol); - if (type.type_symbol is Interface && dup_function == null) { - Report.error (source_reference, "missing class prerequisite for interface `%s', add GLib.Object to interface declaration if unsure", type.type_symbol.get_full_name ()); - return new CCodeInvalidExpression(); - } - } else if (cl != null && cl.is_immutable) { - // allow duplicates of immutable instances as for example strings - dup_function = get_ccode_dup_function (type.type_symbol); - if (dup_function == null) { - dup_function = ""; - } - } else if (get_ccode_is_gboxed (type.type_symbol)) { - // allow duplicates of gboxed instances - dup_function = generate_dup_func_wrapper (type); - if (dup_function == null) { - dup_function = ""; - } - } else if (type is ValueType) { - dup_function = get_ccode_dup_function (type.type_symbol); - if (dup_function == null && type.nullable) { - dup_function = generate_struct_dup_wrapper ((ValueType) type); - } else if (dup_function == null) { - dup_function = ""; - } - } else { - // duplicating non-reference counted objects may cause side-effects (and performance issues) - Report.error (source_reference, "duplicating `%s' instance, use unowned variable or explicitly invoke copy method", type.type_symbol.name); - return new CCodeInvalidExpression(); - } - - return new CCodeIdentifier (dup_function); - } else if (type is PointerType) { - var pointer_type = (PointerType) type; - return get_dup_func_expression (pointer_type.base_type, source_reference); - } else { - return new CCodeConstant ("NULL"); - } - } - - void make_comparable_cexpression (ref DataType left_type, ref CCodeExpression cleft, ref DataType right_type, ref CCodeExpression cright) { - unowned Struct? left_type_as_struct = left_type.type_symbol as Struct; - unowned Struct? right_type_as_struct = right_type.type_symbol as Struct; - unowned ObjectTypeSymbol? left_type_as_object_type = left_type.type_symbol as ObjectTypeSymbol; - unowned ObjectTypeSymbol? right_type_as_object_type = right_type.type_symbol as ObjectTypeSymbol; - - if (left_type_as_object_type != null && (!(left_type_as_object_type is Class) || !((Class) left_type_as_object_type).is_compact) - && right_type_as_object_type != null && (!(right_type_as_object_type is Class) || !((Class) right_type_as_object_type).is_compact)) { - if (left_type_as_object_type != right_type_as_object_type) { - if (left_type_as_object_type.is_subtype_of (right_type_as_object_type)) { - cleft = generate_instance_cast (cleft, right_type_as_object_type); - } else if (right_type_as_object_type.is_subtype_of (left_type_as_object_type)) { - cright = generate_instance_cast (cright, left_type_as_object_type); - } - } - } else if (left_type_as_struct != null && right_type_as_struct != null) { - if (left_type is StructValueType) { - // real structs (uses compare/equal function) - if (!left_type.nullable) { - cleft = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cleft); - } - if (!right_type.nullable) { - cright = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cright); - } - } else { - // integer or floating or boolean type - if (left_type.nullable && right_type.nullable) { - // FIXME also compare contents, not just address - } else if (left_type.nullable) { - // FIXME check left value is not null - cleft = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cleft); - } else if (right_type.nullable) { - // FIXME check right value is not null - cright = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cright); - } - } - } - } - - private string generate_struct_equal_function (Struct st) { - if (st.base_struct != null) { - return generate_struct_equal_function (st.base_struct); - } - - string equal_func = "_%sequal".printf (get_ccode_lower_case_prefix (st)); - - if (!add_wrapper (equal_func)) { - // wrapper already defined - return equal_func; - } - - var function = new CCodeFunction (equal_func, get_ccode_name (bool_type)); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("s1", "const %s *".printf (get_ccode_name (st)))); - function.add_parameter (new CCodeParameter ("s2", "const %s *".printf (get_ccode_name (st)))); - - push_function (function); - - // if (s1 == s2) return TRUE; - { - var cexp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("s1"), new CCodeIdentifier ("s2")); - ccode.open_if (cexp); - ccode.add_return (get_boolean_cconstant (true)); - ccode.close (); - } - // if (s1 == NULL || s2 == NULL) return FALSE; - { - var cexp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("s1"), new CCodeConstant ("NULL")); - ccode.open_if (cexp); - ccode.add_return (get_boolean_cconstant (false)); - ccode.close (); - - cexp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("s2"), new CCodeConstant ("NULL")); - ccode.open_if (cexp); - ccode.add_return (get_boolean_cconstant (false)); - ccode.close (); - } - - bool has_instance_fields = false; - foreach (Field f in st.get_fields ()) { - if (f.binding != MemberBinding.INSTANCE) { - // we only compare instance fields - continue; - } - - has_instance_fields = true; - - CCodeExpression cexp; // if (cexp) return FALSE; - var s1 = (CCodeExpression) new CCodeMemberAccess.pointer (new CCodeIdentifier ("s1"), get_ccode_name (f)); // s1->f - var s2 = (CCodeExpression) new CCodeMemberAccess.pointer (new CCodeIdentifier ("s2"), get_ccode_name (f)); // s2->f - - var variable_type = f.variable_type.copy (); - make_comparable_cexpression (ref variable_type, ref s1, ref variable_type, ref s2); - - if (!(f.variable_type is NullType) && f.variable_type.compatible (string_type)) { - CCodeFunctionCall ccall; - if (context.profile == Profile.POSIX) { - cfile.add_include ("string.h"); - ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_cmp_wrapper (new CCodeIdentifier ("strcmp")))); - } else { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_strcmp0")); - } - ccall.add_argument (s1); - ccall.add_argument (s2); - cexp = ccall; - } else if (f.variable_type is StructValueType) { - var equalfunc = generate_struct_equal_function (f.variable_type.type_symbol as Struct); - var ccall = new CCodeFunctionCall (new CCodeIdentifier (equalfunc)); - ccall.add_argument (s1); - ccall.add_argument (s2); - cexp = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, ccall); - } else { - cexp = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, s1, s2); - } - - ccode.open_if (cexp); - ccode.add_return (get_boolean_cconstant (false)); - ccode.close (); - } - - if (!has_instance_fields) { - // either opaque structure or simple type - if (st.is_simple_type ()) { - var cexp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("s1")), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("s2"))); - ccode.add_return (cexp); - } else { - ccode.add_return (get_boolean_cconstant (false)); - } - } else { - ccode.add_return (get_boolean_cconstant (true)); - } - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return equal_func; - } - - private string generate_numeric_equal_function (TypeSymbol sym) { - string equal_func = "_%sequal".printf (get_ccode_lower_case_prefix (sym)); - - if (!add_wrapper (equal_func)) { - // wrapper already defined - return equal_func; - } - - var function = new CCodeFunction (equal_func, get_ccode_name (bool_type)); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("s1", "const %s *".printf (get_ccode_name (sym)))); - function.add_parameter (new CCodeParameter ("s2", "const %s *".printf (get_ccode_name (sym)))); - - push_function (function); - - // if (s1 == s2) return TRUE; - { - var cexp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("s1"), new CCodeIdentifier ("s2")); - ccode.open_if (cexp); - ccode.add_return (get_boolean_cconstant (true)); - ccode.close (); - } - // if (s1 == NULL || s2 == NULL) return FALSE; - { - var cexp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("s1"), new CCodeConstant ("NULL")); - ccode.open_if (cexp); - ccode.add_return (get_boolean_cconstant (false)); - ccode.close (); - - cexp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("s2"), new CCodeConstant ("NULL")); - ccode.open_if (cexp); - ccode.add_return (get_boolean_cconstant (false)); - ccode.close (); - } - // return (*s1 == *s2); - { - var cexp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("s1")), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("s2"))); - ccode.add_return (cexp); - } - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return equal_func; - } - - private string generate_struct_dup_wrapper (ValueType value_type) { - string dup_func = "_%sdup".printf (get_ccode_lower_case_prefix (value_type.type_symbol)); - - if (!add_wrapper (dup_func)) { - // wrapper already defined - return dup_func; - } - - var function = new CCodeFunction (dup_func, get_ccode_name (value_type)); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("self", get_ccode_name (value_type))); - - push_function (function); - - if (value_type.type_symbol == gvalue_type) { - var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_boxed_copy")); - dup_call.add_argument (new CCodeIdentifier ("G_TYPE_VALUE")); - dup_call.add_argument (new CCodeIdentifier ("self")); - - ccode.add_return (dup_call); - } else { - ccode.add_declaration (get_ccode_name (value_type), new CCodeVariableDeclarator ("dup")); - - CCodeFunctionCall creation_call; - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdlib.h"); - creation_call = new CCodeFunctionCall (new CCodeIdentifier ("calloc")); - creation_call.add_argument (new CCodeConstant ("1")); - var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - csizeof.add_argument (new CCodeIdentifier (get_ccode_name (value_type.type_symbol))); - creation_call.add_argument (csizeof); - } else { - cfile.add_include ("glib.h"); - creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new0")); - creation_call.add_argument (new CCodeIdentifier (get_ccode_name (value_type.type_symbol))); - creation_call.add_argument (new CCodeConstant ("1")); - } - ccode.add_assignment (new CCodeIdentifier ("dup"), creation_call); - - var st = value_type.type_symbol as Struct; - if (st != null && st.is_disposable ()) { - if (!get_ccode_has_copy_function (st)) { - generate_struct_copy_function (st); - } - - var copy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_copy_function (st))); - copy_call.add_argument (new CCodeIdentifier ("self")); - copy_call.add_argument (new CCodeIdentifier ("dup")); - ccode.add_expression (copy_call); - } else { - cfile.add_include ("string.h"); - - var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - sizeof_call.add_argument (new CCodeConstant (get_ccode_name (value_type.type_symbol))); - - var copy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy")); - copy_call.add_argument (new CCodeIdentifier ("dup")); - copy_call.add_argument (new CCodeIdentifier ("self")); - copy_call.add_argument (sizeof_call); - ccode.add_expression (copy_call); - } - - ccode.add_return (new CCodeIdentifier ("dup")); - } - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return dup_func; - } - - protected string generate_dup_func_wrapper (DataType type) { - string destroy_func = "_vala_%s_copy".printf (get_ccode_name (type.type_symbol)); - - if (!add_wrapper (destroy_func)) { - // wrapper already defined - return destroy_func; - } - - var function = new CCodeFunction (destroy_func, get_ccode_name (type)); - function.modifiers = CCodeModifiers.STATIC; - function.add_parameter (new CCodeParameter ("self", get_ccode_name (type))); - - push_function (function); - - var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_boxed_copy")); - free_call.add_argument (new CCodeIdentifier (get_ccode_type_id (type.type_symbol))); - free_call.add_argument (new CCodeIdentifier ("self")); - - ccode.add_return (free_call); - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return destroy_func; - } - - protected string generate_free_function_address_of_wrapper (DataType type) { - string destroy_func = "_vala_%s_free_function_address_of".printf (get_ccode_name (type.type_symbol)); - - if (!add_wrapper (destroy_func)) { - // wrapper already defined - return destroy_func; - } - - var function = new CCodeFunction (destroy_func, "void"); - function.modifiers = CCodeModifiers.STATIC; - function.add_parameter (new CCodeParameter ("self", get_ccode_name (type))); - - push_function (function); - - unowned Class? cl = type.type_symbol as Class; - assert (cl != null); - - var free_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_free_function (cl))); - free_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("self"))); - - ccode.add_expression (free_call); - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return destroy_func; - } - - protected string generate_destroy_function_content_of_wrapper (DataType type) { - // g_array_set_clear_func has a specific GDestroyNotify where the content of an element is given - string destroy_func = "_vala_%s_free_function_content_of".printf (get_ccode_name (type.type_symbol)); - - if (!add_wrapper (destroy_func)) { - // wrapper already defined - return destroy_func; - } - - var function = new CCodeFunction (destroy_func, "void"); - function.modifiers = CCodeModifiers.STATIC; - function.add_parameter (new CCodeParameter ("data", get_ccode_name (pointer_type))); - push_function (function); - - ccode.add_declaration (get_ccode_name (type), new CCodeVariableDeclarator ("self")); - var cast = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeCastExpression (new CCodeIdentifier ("data"), get_ccode_name (type) + "*")); - ccode.add_assignment (new CCodeIdentifier ("self"), cast); - - var free_call = new CCodeFunctionCall (get_destroy0_func_expression (type)); - free_call.add_argument (new CCodeIdentifier ("self")); - - ccode.add_expression (free_call); - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return destroy_func; - } - - protected string generate_free_func_wrapper (DataType type) { - string destroy_func = "_vala_%s_free".printf (get_ccode_name (type.type_symbol)); - - if (!add_wrapper (destroy_func)) { - // wrapper already defined - return destroy_func; - } - - var function = new CCodeFunction (destroy_func, "void"); - function.modifiers = CCodeModifiers.STATIC; - function.add_parameter (new CCodeParameter ("self", get_ccode_name (type))); - - push_function (function); - - if (get_ccode_is_gboxed (type.type_symbol) || (gvalue_type != null && type.type_symbol == gvalue_type)) { - var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_boxed_free")); - free_call.add_argument (new CCodeIdentifier (get_ccode_type_id (type.type_symbol))); - free_call.add_argument (new CCodeIdentifier ("self")); - - ccode.add_expression (free_call); - } else { - unowned Struct? st = type.type_symbol as Struct; - if (st != null && st.is_disposable ()) { - if (!get_ccode_has_destroy_function (st)) { - generate_struct_destroy_function (st); - } - - var destroy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_destroy_function (st))); - destroy_call.add_argument (new CCodeIdentifier ("self")); - ccode.add_expression (destroy_call); - } - - CCodeFunctionCall free_call; - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdlib.h"); - free_call = new CCodeFunctionCall (new CCodeIdentifier ("free")); - } else { - cfile.add_include ("glib.h"); - free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free")); - } - free_call.add_argument (new CCodeIdentifier ("self")); - - ccode.add_expression (free_call); - } - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return destroy_func; - } - - public CCodeExpression? get_destroy0_func_expression (DataType type, bool is_chainup = false) { - var element_destroy_func_expression = get_destroy_func_expression (type, is_chainup); - - if (!(type is GenericType) && element_destroy_func_expression is CCodeIdentifier) { - var freeid = (CCodeIdentifier) element_destroy_func_expression; - string free0_func = "_%s0_".printf (freeid.name); - - if (add_wrapper (free0_func)) { - var function = new CCodeFunction (free0_func, "void"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("var", get_ccode_name (pointer_type))); - - push_function (function); - - ccode.add_expression (destroy_value (new GLibValue (type, new CCodeIdentifier ("var"), true), true)); - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - } - - element_destroy_func_expression = new CCodeIdentifier (free0_func); - } - - return element_destroy_func_expression; - } - - public CCodeExpression? get_destroy_func_expression (DataType type, bool is_chainup = false) { - if (context.profile == Profile.GOBJECT && (type.type_symbol == glist_type || type.type_symbol == gslist_type || type.type_symbol == gnode_type || type.type_symbol == gqueue_type)) { - // create wrapper function to free list elements if necessary - - bool elements_require_free = false; - bool generic_elements = false; - CCodeExpression element_destroy_func_expression = null; - - foreach (DataType type_arg in type.get_type_arguments ()) { - elements_require_free = requires_destroy (type_arg); - if (elements_require_free) { - element_destroy_func_expression = get_destroy0_func_expression (type_arg); - generic_elements = (type_arg is GenericType); - } - } - - if (elements_require_free) { - CCodeExpression? cexpr = null; - if (element_destroy_func_expression is CCodeIdentifier || element_destroy_func_expression is CCodeMemberAccess) { - cexpr = new CCodeIdentifier (generate_collection_free_wrapper (type, (generic_elements ? null : element_destroy_func_expression as CCodeIdentifier))); - if (generic_elements) { - // adding second argument early, instance parameter will be inserted by destroy_value() - cexpr = new CCodeFunctionCall (cexpr); - ((CCodeFunctionCall) cexpr).add_argument (element_destroy_func_expression); - } - } else { - Report.error (null, "internal error: No useable element_destroy_function found"); - } - return cexpr; - } else { - return new CCodeIdentifier (get_ccode_free_function (type.type_symbol)); - } - } else if (type is ErrorType) { - cfile.add_include ("glib.h"); - return new CCodeIdentifier ("g_error_free"); - } else if (type is GenericType) { - var type_parameter = ((GenericType) type).type_parameter; - string identifier = get_ccode_destroy_function (type_parameter); - return get_generic_type_expression (identifier, (GenericType) type, is_chainup); - } else if (type.type_symbol != null) { - string unref_function; - if (type is ReferenceType) { - if (is_reference_counting (type.type_symbol)) { - unref_function = get_ccode_unref_function ((ObjectTypeSymbol) type.type_symbol); - if (type.type_symbol is Interface && unref_function == null) { - Report.error (type.source_reference, "missing class prerequisite for interface `%s', add GLib.Object to interface declaration if unsure", type.type_symbol.get_full_name ()); - return null; - } - } else { - if (get_ccode_is_gboxed (type.type_symbol)) { - unref_function = generate_free_func_wrapper (type); - } else { - if (is_free_function_address_of (type)) { - unref_function = generate_free_function_address_of_wrapper (type); - } else { - unref_function = get_ccode_free_function (type.type_symbol); - } - } - } - } else { - if (type.nullable) { - if (get_ccode_is_gboxed (type.type_symbol)) { - unref_function = generate_free_func_wrapper (type); - } else { - unref_function = get_ccode_free_function (type.type_symbol); - } - if (unref_function == null) { - if (type.type_symbol is Struct && ((Struct) type.type_symbol).is_disposable ()) { - unref_function = generate_free_func_wrapper (type); - } else { - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdlib.h"); - unref_function = "free"; - } else { - cfile.add_include ("glib.h"); - unref_function = "g_free"; - } - } - } - } else if (type is EnumValueType) { - unref_function = null; - } else { - unowned Struct? st = type.type_symbol as Struct; - if (st != null && st.is_disposable ()) { - if (!get_ccode_has_destroy_function (st)) { - generate_struct_destroy_function (st); - } - unref_function = get_ccode_destroy_function (st); - } else { - unref_function = null; - } - } - } - if (unref_function == null) { - return new CCodeConstant ("NULL"); - } - return new CCodeIdentifier (unref_function); - } else if (type is ArrayType) { - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdlib.h"); - return new CCodeIdentifier ("free"); - } else { - cfile.add_include ("glib.h"); - return new CCodeIdentifier ("g_free"); - } - } else if (type is PointerType) { - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdlib.h"); - return new CCodeIdentifier ("free"); - } else { - cfile.add_include ("glib.h"); - return new CCodeIdentifier ("g_free"); - } - } else { - return new CCodeConstant ("NULL"); - } - } - - private string generate_collection_free_wrapper (DataType collection_type, CCodeIdentifier? element_destroy_func_expression) { - string destroy_func; - - string? destroy_func_wrapper = null; - if (element_destroy_func_expression != null) { - destroy_func_wrapper = "_%s_%s".printf (get_ccode_free_function (collection_type.type_symbol), element_destroy_func_expression.name); - if (!add_wrapper (destroy_func_wrapper)) { - // wrapper already defined - return destroy_func_wrapper; - } - } - - if (collection_type.type_symbol == gnode_type) { - destroy_func = "_g_node_free_all"; - if (!add_wrapper (destroy_func)) { - // wrapper already defined - return destroy_func; - } - - var function = new CCodeFunction (destroy_func, "void"); - function.add_parameter (new CCodeParameter ("self", get_ccode_name (collection_type))); - function.add_parameter (new CCodeParameter ("free_func", "GDestroyNotify")); - - push_function (function); - - CCodeFunctionCall element_free_call; - string destroy_node_func = "%s_node".printf (destroy_func); - var wrapper = new CCodeFunction (destroy_node_func, get_ccode_name (bool_type)); - wrapper.modifiers = CCodeModifiers.STATIC; - wrapper.add_parameter (new CCodeParameter ("node", get_ccode_name (collection_type))); - wrapper.add_parameter (new CCodeParameter ("free_func", "GDestroyNotify")); - push_function (wrapper); - - var free_call = new CCodeFunctionCall (new CCodeIdentifier ("free_func")); - free_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier("node"), "data")); - - var data_isnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeMemberAccess.pointer (new CCodeIdentifier("node"), "data"), new CCodeConstant ("NULL")); - var ccomma_data = new CCodeCommaExpression (); - ccomma_data.append_expression (new CCodeConditionalExpression (data_isnull, new CCodeConstant ("NULL"), free_call)); - ccode.add_expression (ccomma_data); - - ccode.add_return (new CCodeConstant ("FALSE")); - - pop_function (); - cfile.add_function_declaration (wrapper); - cfile.add_function (wrapper); - - /* Now the code to call g_traverse with the above */ - element_free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_node_traverse")); - element_free_call.add_argument (new CCodeIdentifier("self")); - element_free_call.add_argument (new CCodeConstant ("G_POST_ORDER")); - element_free_call.add_argument (new CCodeConstant ("G_TRAVERSE_ALL")); - element_free_call.add_argument (new CCodeConstant ("-1")); - element_free_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (destroy_node_func), "GNodeTraverseFunc")); - element_free_call.add_argument (new CCodeIdentifier ("free_func")); - - var free_func_isnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("free_func"), new CCodeConstant ("NULL")); - var ccomma = new CCodeCommaExpression (); - ccomma.append_expression (new CCodeConditionalExpression (free_func_isnull, new CCodeConstant ("NULL"), element_free_call)); - - ccode.add_expression (ccomma); - - var cfreecall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_free_function (gnode_type))); - cfreecall.add_argument (new CCodeIdentifier ("self")); - ccode.add_expression (cfreecall); - - function.modifiers = CCodeModifiers.STATIC; - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - } else if (collection_type.type_symbol == glist_type) { - destroy_func = "g_list_free_full"; - } else if (collection_type.type_symbol == gslist_type) { - destroy_func = "g_slist_free_full"; - } else if (collection_type.type_symbol == gqueue_type) { - destroy_func = "g_queue_free_full"; - } else { - Report.error (null, "internal error: type of collection not supported"); - return ""; - } - - if (element_destroy_func_expression != null) { - var function = new CCodeFunction (destroy_func_wrapper, "void"); - function.add_parameter (new CCodeParameter ("self", get_ccode_name (collection_type))); - - push_function (function); - - var collection_free_call = new CCodeFunctionCall (new CCodeIdentifier (destroy_func)); - collection_free_call.add_argument (new CCodeIdentifier ("self")); - collection_free_call.add_argument (new CCodeCastExpression (element_destroy_func_expression, "GDestroyNotify")); - ccode.add_expression (collection_free_call); - - function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.INLINE; - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return destroy_func_wrapper; - } - - return destroy_func; - } - - public virtual string? append_struct_array_destroy (Struct st) { - return null; - } - - public virtual string? append_struct_array_free (Struct st) { - return null; - } - - public CCodeExpression destroy_local (LocalVariable local) { - return destroy_value (get_local_cvalue (local)); - } - - public CCodeExpression destroy_parameter (Parameter param) { - return destroy_value (get_parameter_cvalue (param)); - } - - public CCodeExpression destroy_field (Field field, TargetValue? instance) { - return destroy_value (get_field_cvalue (field, instance)); - } - - public virtual CCodeExpression destroy_value (TargetValue value, bool is_macro_definition = false) { - var type = value.value_type; - if (value.actual_value_type != null) { - type = value.actual_value_type; - } - var cvar = get_cvalue_ (value); - - if (type is DelegateType) { - if (context.profile != Profile.GOBJECT) { - // Required for NULL - cfile.add_include ("stddef.h"); - } - - var delegate_target = get_delegate_target_cvalue (value); - var delegate_target_destroy_notify = get_delegate_target_destroy_notify_cvalue (value); - - var ccall = new CCodeFunctionCall (delegate_target_destroy_notify); - ccall.add_argument (delegate_target); - - var destroy_call = new CCodeCommaExpression (); - destroy_call.append_expression (ccall); - destroy_call.append_expression (new CCodeConstant ("NULL")); - - var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, delegate_target_destroy_notify, new CCodeConstant ("NULL")); - - var ccomma = new CCodeCommaExpression (); - ccomma.append_expression (new CCodeConditionalExpression (cisnull, new CCodeConstant ("NULL"), destroy_call)); - ccomma.append_expression (new CCodeAssignment (cvar, new CCodeConstant ("NULL"))); - ccomma.append_expression (new CCodeAssignment (delegate_target, new CCodeConstant ("NULL"))); - ccomma.append_expression (new CCodeAssignment (delegate_target_destroy_notify, new CCodeConstant ("NULL"))); - - return ccomma; - } - - bool is_gcollection = (type.type_symbol == glist_type || type.type_symbol == gslist_type || type.type_symbol == gnode_type || type.type_symbol == gqueue_type); - CCodeFunctionCall ccall; - var cexpr = get_destroy_func_expression (type); - if (is_gcollection && cexpr is CCodeFunctionCall) { - ccall = (CCodeFunctionCall) cexpr; - } else { - ccall = new CCodeFunctionCall (cexpr); - } - - if (type is ValueType && !type.nullable) { - // normal value type, no null check - unowned Struct? st = type.type_symbol as Struct; - if (st != null && st.is_simple_type ()) { - // used for va_list - ccall.add_argument (cvar); - } else { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cvar)); - } - - if (gvalue_type != null && type.type_symbol == gvalue_type) { - // g_value_unset must not be called for already unset values - var cisvalid = new CCodeFunctionCall (new CCodeIdentifier ("G_IS_VALUE")); - cisvalid.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cvar)); - - var ccomma = new CCodeCommaExpression (); - ccomma.append_expression (ccall); - ccomma.append_expression (new CCodeConstant ("NULL")); - - return new CCodeConditionalExpression (cisvalid, ccomma, new CCodeConstant ("NULL")); - } else if ((type.type_symbol == gmutex_type || - type.type_symbol == grecmutex_type || - type.type_symbol == grwlock_type || - type.type_symbol == gcond_type)) { - // g_mutex_clear must not be called for uninitialized mutex - // also, g_mutex_clear does not clear the struct - requires_clear_mutex = true; - ccall.call = new CCodeIdentifier ("_vala_clear_" + get_ccode_name (type.type_symbol)); - return ccall; - } else { - return ccall; - } - } - - if (!is_gcollection && ccall.call is CCodeIdentifier && !(type is ArrayType) && !(type is GenericType) && !is_macro_definition) { - // generate and use NULL-aware free macro to simplify code - - var freeid = (CCodeIdentifier) ccall.call; - string free0_func = "_%s0".printf (freeid.name); - - if (add_wrapper (free0_func)) { - var macro = destroy_value (new GLibValue (type, new CCodeIdentifier ("var"), true), true); - cfile.add_type_declaration (new CCodeMacroReplacement.with_expression ("%s(var)".printf (free0_func), macro)); - } - - // FIXME this breaks in our macro, so this should not happen - while (cvar is CCodeCastExpression) { - cvar = ((CCodeCastExpression) cvar).inner; - } - if (cvar is CCodeFunctionCall) { - cvar = ((CCodeFunctionCall) cvar).get_arguments ()[0]; - } - - ccall = new CCodeFunctionCall (new CCodeIdentifier (free0_func)); - ccall.add_argument (cvar); - return ccall; - } - - if (context.profile != Profile.GOBJECT) { - // Required for NULL - cfile.add_include ("stddef.h"); - } - - /* (foo == NULL ? NULL : foo = (unref (foo), NULL)) */ - - /* can be simplified to - * foo = (unref (foo), NULL) - * if foo is of static type non-null - */ - - var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cvar, new CCodeConstant ("NULL")); - if (type is GenericType) { - var parent = ((GenericType) type).type_parameter.parent_symbol; - var cl = parent as Class; - if ((!(parent is Method) && !(parent is ObjectTypeSymbol)) || (cl != null && cl.is_compact)) { - 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); - } - - // glib collections already have the free_func argument, so make sure the instance parameter gets first - ccall.insert_argument (0, cvar); - - /* set freed references to NULL to prevent further use */ - var ccomma = new CCodeCommaExpression (); - - if (context.profile == Profile.GOBJECT - && type.type_symbol != null && !is_reference_counting (type.type_symbol) - && type.type_symbol.is_subtype_of (gstringbuilder_type)) { - ccall.add_argument (new CCodeConstant ("TRUE")); - } else if (context.profile == Profile.GOBJECT - && type.type_symbol == gthreadpool_type) { - ccall.add_argument (new CCodeConstant ("FALSE")); - ccall.add_argument (new CCodeConstant ("TRUE")); - } else if (type is ArrayType) { - var array_type = (ArrayType) type; - if (requires_destroy (array_type.element_type)) { - CCodeExpression csizeexpr = null; - if (((GLibValue) value).array_length_cvalues != null) { - csizeexpr = get_array_length_cvalue (value); - } else if (get_array_null_terminated (value)) { - requires_array_length = true; - var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length")); - len_call.add_argument (cvar); - csizeexpr = len_call; - } else { - csizeexpr = get_array_length_cexpr (value); - } - - if (csizeexpr != null) { - unowned Struct? st = array_type.element_type.type_symbol as Struct; - if (st != null && !array_type.element_type.nullable) { - ccall.call = new CCodeIdentifier (append_struct_array_free (st)); - ccall.add_argument (csizeexpr); - } else { - requires_array_free = true; - generate_type_declaration (delegate_target_destroy_type, cfile); - - ccall.call = new CCodeIdentifier ("_vala_array_free"); - ccall.add_argument (csizeexpr); - ccall.add_argument (new CCodeCastExpression (get_destroy_func_expression (array_type.element_type), get_ccode_name (delegate_target_destroy_type))); - } - } - } - } - - ccomma.append_expression (ccall); - ccomma.append_expression (new CCodeConstant ("NULL")); - - var cassign = new CCodeAssignment (cvar, ccomma); - - // g_free (NULL) is allowed - bool uses_gfree = (type.type_symbol != null && !is_reference_counting (type.type_symbol) && get_ccode_free_function (type.type_symbol) == "g_free"); - uses_gfree = uses_gfree || type is ArrayType; - if (uses_gfree) { - return cassign; - } - - return new CCodeConditionalExpression (cisnull, new CCodeConstant ("NULL"), cassign); - } - - public override void visit_end_full_expression (Expression expr) { - /* 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 - */ - if (temp_ref_values.size == 0) { - /* nothing to do without temporary variables */ - return; - } - - var local_decl = expr.parent_node as LocalVariable; - if (!(local_decl != null && is_simple_struct_creation (local_decl, local_decl.initializer))) { - expr.target_value = store_temp_value (expr.target_value, expr); - } - - foreach (var value in temp_ref_values) { - ccode.add_expression (destroy_value (value)); - } - - temp_ref_values.clear (); - } - - public void emit_temp_var (LocalVariable local, bool on_error = false) { - generate_type_declaration (local.variable_type, cfile); - - var init = (!local.name.has_prefix ("*") && local.init); - if (is_in_coroutine ()) { - closure_struct.add_field (get_ccode_name (local.variable_type), local.name, 0, get_ccode_declarator_suffix (local.variable_type)); - - // even though closure struct is zerod, we need to initialize temporary variables - // as they might be used multiple times when declared in a loop - - if (init) { - var initializer = default_value_for_type (local.variable_type, false, on_error); - if (initializer == null) { - cfile.add_include ("string.h"); - var memset_call = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - memset_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (local.name))); - memset_call.add_argument (new CCodeConstant ("0")); - CCodeExpression? size = null; - requires_memset_init (local, out size); - if (size == null) { - size = new CCodeIdentifier ("sizeof (%s)".printf (get_ccode_name (local.variable_type))); - } - memset_call.add_argument (size); - ccode.add_expression (memset_call); - } else { - ccode.add_assignment (get_variable_cexpression (local.name), initializer); - } - } - } else { - var cvar = new CCodeVariableDeclarator (local.name, null, get_ccode_declarator_suffix (local.variable_type)); - CCodeExpression? size = null; - if (init && !requires_memset_init (local, out size)) { - cvar.initializer = default_value_for_type (local.variable_type, true, on_error); - cvar.init0 = true; - } else if (init && size != null && local.initializer == null) { - cfile.add_include ("string.h"); - var memset_call = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - memset_call.add_argument (get_variable_cexpression (local.name)); - memset_call.add_argument (new CCodeConstant ("0")); - memset_call.add_argument (size); - ccode.add_expression (memset_call); - } - ccode.add_declaration (get_ccode_name (local.variable_type), cvar); - } - } - - public override void visit_expression_statement (ExpressionStatement stmt) { - if (stmt.expression.error) { - stmt.error = true; - return; - } - - /* free temporary objects and handle errors */ - - foreach (var value in temp_ref_values) { - ccode.add_expression (destroy_value (value)); - } - - if (stmt.tree_can_fail && stmt.expression.tree_can_fail) { - // simple case, no node breakdown necessary - add_simple_check (stmt.expression); - } - - temp_ref_values.clear (); - } - - protected virtual void append_scope_free (Symbol sym, CodeNode? stop_at = null) { - var b = (Block) sym; - - var local_vars = b.get_local_variables (); - // free in reverse order - for (int i = local_vars.size - 1; i >= 0; i--) { - var local = local_vars[i]; - if (!local.unreachable && local.active && !local.captured && requires_destroy (local.variable_type)) { - ccode.add_expression (destroy_local (local)); - } - } - - if (b.captured) { - int block_id = get_block_id (b); - - var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (block_id))); - data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id))); - ccode.add_expression (data_unref); - ccode.add_assignment (get_variable_cexpression ("_data%d_".printf (block_id)), new CCodeConstant ("NULL")); - } - } - - public void append_local_free (Symbol sym, Statement? jump_stmt = null, CodeNode? stop_at = null) { - var b = (Block) sym; - - append_scope_free (sym, stop_at); - - if (jump_stmt is BreakStatement) { - if (b.parent_node is LoopStatement || - b.parent_node is ForeachStatement || - b.parent_node is SwitchStatement) { - return; - } - } else if (jump_stmt is ContinueStatement) { - if (b.parent_node is LoopStatement || - b.parent_node is ForeachStatement) { - return; - } - } - - if (stop_at != null && b.parent_node == stop_at) { - return; - } - - if (sym.parent_symbol is Block) { - append_local_free (sym.parent_symbol, jump_stmt, stop_at); - } else if (sym.parent_symbol is Method) { - append_param_free ((Method) sym.parent_symbol); - } else if (sym.parent_symbol is PropertyAccessor) { - var acc = (PropertyAccessor) sym.parent_symbol; - if (acc.value_parameter != null && requires_destroy (acc.value_parameter.variable_type)) { - ccode.add_expression (destroy_parameter (acc.value_parameter)); - } - } - } - - private void append_param_free (Method m) { - foreach (Parameter param in m.get_parameters ()) { - if (!param.captured && !param.ellipsis && !param.params_array && requires_destroy (param.variable_type) && param.direction == ParameterDirection.IN) { - ccode.add_expression (destroy_parameter (param)); - } - } - } - - public void append_out_param_free (Method? m) { - if (m == null) { - return; - } - foreach (Parameter param in m.get_parameters ()) { - if (param.direction == ParameterDirection.OUT && param.variable_type.is_disposable ()) { - ccode.add_expression (destroy_parameter (param)); - } - } - } - - public bool variable_accessible_in_finally (LocalVariable local) { - if (current_try == null) { - return false; - } - - var sym = current_symbol; - - while (!(sym is Method || sym is PropertyAccessor) && sym.scope.lookup (local.name) == null) { - if ((sym.parent_node is TryStatement && ((TryStatement) sym.parent_node).finally_body != null) || - (sym.parent_node is CatchClause && ((TryStatement) sym.parent_node.parent_node).finally_body != null)) { - - return true; - } - - sym = sym.parent_symbol; - } - - return false; - } - - public void return_out_parameter (Parameter param) { - var delegate_type = param.variable_type as DelegateType; - - var value = get_parameter_cvalue (param); - - var old_coroutine = is_in_coroutine (); - current_method.coroutine = false; - - ccode.open_if (get_parameter_cexpression (param)); - ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_parameter_cexpression (param)), get_cvalue_ (value)); - - if (get_ccode_delegate_target (param) && delegate_type != null && delegate_type.delegate_symbol.has_target) { - ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_cexpression (get_ccode_delegate_target_name (param))), get_delegate_target_cvalue (value)); - if (delegate_type.is_disposable ()) { - ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_cexpression (get_ccode_delegate_target_destroy_notify_name (param))), get_delegate_target_destroy_notify_cvalue (get_parameter_cvalue (param))); - } - } - - if (param.variable_type.is_disposable ()){ - ccode.add_else (); - current_method.coroutine = old_coroutine; - ccode.add_expression (destroy_parameter (param)); - current_method.coroutine = false; - } - ccode.close (); - - var array_type = param.variable_type as ArrayType; - if (array_type != null && !array_type.fixed_length && get_ccode_array_length (param)) { - for (int dim = 1; dim <= array_type.rank; dim++) { - string length_cname = get_variable_array_length_cname (param, dim); - ccode.open_if (get_cexpression (length_cname)); - ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_cexpression (length_cname)), get_array_length_cvalue (value, dim)); - ccode.close (); - } - } - - current_method.coroutine = old_coroutine; - } - - public override void visit_return_statement (ReturnStatement stmt) { - Symbol return_expression_symbol = null; - - if (stmt.return_expression != null) { - // avoid unnecessary ref/unref pair - var local = stmt.return_expression.symbol_reference as LocalVariable; - if (local != null && !local.active) { - /* return expression is local variable taking ownership and - * current method is transferring ownership */ - - return_expression_symbol = local; - } - } - - // return array length if appropriate - if (((current_method != null && get_ccode_array_length (current_method)) || (current_property_accessor != null && get_ccode_array_length (current_property_accessor))) && current_return_type is ArrayType) { - var temp_value = store_temp_value (stmt.return_expression.target_value, stmt); - - var array_type = (ArrayType) current_return_type; - for (int dim = 1; dim <= array_type.rank; dim++) { - var len_l = get_cexpression (get_array_length_cname ("result", dim)); - var len_r = get_array_length_cvalue (temp_value, dim); - if (!is_in_coroutine ()) { - ccode.open_if (len_l); - len_l = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, len_l); - ccode.add_assignment (len_l, len_r); - ccode.close (); - } else { - ccode.add_assignment (len_l, len_r); - } - } - - stmt.return_expression.target_value = temp_value; - } else if (((current_method != null && get_ccode_delegate_target (current_method)) || (current_property_accessor != null && get_ccode_delegate_target (current_property_accessor))) && current_return_type is DelegateType) { - var delegate_type = (DelegateType) current_return_type; - if (delegate_type.delegate_symbol.has_target) { - var temp_value = store_temp_value (stmt.return_expression.target_value, stmt); - - var target_l = get_cexpression (get_delegate_target_cname ("result")); - if (!is_in_coroutine ()) { - target_l = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_l); - } - var target_r = get_delegate_target_cvalue (temp_value); - ccode.add_assignment (target_l, target_r); - if (delegate_type.is_disposable ()) { - var target_l_destroy_notify = get_cexpression (get_delegate_target_destroy_notify_cname ("result")); - if (!is_in_coroutine ()) { - target_l_destroy_notify = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_l_destroy_notify); - } - var target_r_destroy_notify = get_delegate_target_destroy_notify_cvalue (temp_value); - ccode.add_assignment (target_l_destroy_notify, target_r_destroy_notify); - } - - stmt.return_expression.target_value = temp_value; - } - } - - if (stmt.return_expression != null) { - // assign method result to `result' - CCodeExpression result_lhs = get_cexpression ("result"); - if (current_return_type.is_real_non_null_struct_type () && !is_in_coroutine ()) { - result_lhs = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, result_lhs); - } - ccode.add_assignment (result_lhs, get_cvalue (stmt.return_expression)); - } - - if (current_method != null) { - // check postconditions - foreach (Expression postcondition in current_method.get_postconditions ()) { - create_postcondition_statement (postcondition); - } - } - - // free local variables - append_local_free (current_symbol); - - if (current_method != null && !current_method.coroutine) { - // assign values to output parameters if they are not NULL - // otherwise, free the value if necessary - foreach (var param in current_method.get_parameters ()) { - if (param.direction != ParameterDirection.OUT) { - continue; - } - - return_out_parameter (param); - } - } - - // TODO: don't duplicate the code in CCodeMethodModule, we do this right now because it needs to be before return - if (current_method != null && current_method.get_attribute ("Profile") != null) { - string prefix = "_vala_prof_%s".printf (get_ccode_real_name (current_method)); - - var level = new CCodeIdentifier (prefix + "_level"); - ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeUnaryExpression (CCodeUnaryOperator.PREFIX_DECREMENT, level))); - - var timer = new CCodeIdentifier (prefix + "_timer"); - - var stop_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_stop")); - stop_call.add_argument (timer); - ccode.add_expression (stop_call); - - ccode.close (); - } - - if (is_in_constructor ()) { - ccode.add_return (new CCodeIdentifier ("obj")); - } else if (is_in_destructor ()) { - // do not call return as member cleanup and chain up to base finalizer - // still need to be executed - ccode.add_goto ("_return"); - } else if (is_in_coroutine ()) { - } else if (current_method is CreationMethod) { - ccode.add_return (new CCodeIdentifier ("self")); - } else if (current_return_type is VoidType || current_return_type.is_real_non_null_struct_type ()) { - // structs are returned via out parameter - ccode.add_return (); - } else { - ccode.add_return (new CCodeIdentifier ("result")); - } - - if (return_expression_symbol != null) { - return_expression_symbol.active = true; - } - - // required for destructors - current_method_return = true; - } - - public string get_symbol_lock_name (string symname) { - return "__lock_%s".printf (symname.replace ("-", "_")); - } - - private CCodeExpression get_lock_expression (Statement stmt, Expression resource) { - CCodeExpression l = null; - var member = resource.symbol_reference; - var parent = (TypeSymbol)resource.symbol_reference.parent_symbol; - - if (member.is_instance_member ()) { - l = get_cvalue (((MemberAccess) resource).inner); - l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (get_ccode_name (member))); - } else if (member.is_class_member ()) { - unowned Class cl = (Class) parent; - var cast = get_this_class_cexpression (cl); - var get_class_private_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_get_private_function (cl))); - get_class_private_call.add_argument (cast); - l = new CCodeMemberAccess.pointer (get_class_private_call, get_symbol_lock_name (get_ccode_name (member))); - } else { - string lock_name = "%s_%s".printf (get_ccode_lower_case_name (parent), get_ccode_name (member)); - l = new CCodeIdentifier (get_symbol_lock_name (lock_name)); - } - return l; - } - - public override void visit_lock_statement (LockStatement stmt) { - var l = get_lock_expression (stmt, stmt.resource); - - var fc = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (mutex_type.scope.lookup ("lock")))); - fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l)); - - ccode.add_expression (fc); - } - - public override void visit_unlock_statement (UnlockStatement stmt) { - var l = get_lock_expression (stmt, stmt.resource); - - var fc = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (mutex_type.scope.lookup ("unlock")))); - fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l)); - - ccode.add_expression (fc); - } - - public override void visit_delete_statement (DeleteStatement stmt) { - unowned DataType type = stmt.expression.value_type; - unowned PointerType? pointer_type = type as PointerType; - if (pointer_type != null && pointer_type.base_type.type_symbol != null && pointer_type.base_type.type_symbol.is_reference_type ()) { - type = pointer_type.base_type; - } - - ccode.add_expression (destroy_value (new GLibValue (type, get_cvalue (stmt.expression)))); - } - - static bool is_compact_class_destructor_call (Expression expr) { - unowned Class? cl = expr.value_type.type_symbol as Class; - if (cl != null && cl.is_compact && expr.parent_node is MemberAccess) { - unowned MethodType? mt = ((MemberAccess) expr.parent_node).value_type as MethodType; - if (mt != null && mt.method_symbol != null && mt.method_symbol.get_attribute ("DestroysInstance") != null) { - return true; - } - } - return false; - } - - public override void visit_expression (Expression expr) { - if (get_cvalue (expr) != null && !expr.lvalue) { - if (expr.formal_value_type is GenericType && !(expr.value_type is GenericType)) { - var type_parameter = ((GenericType) expr.formal_value_type).type_parameter; - var st = type_parameter.parent_symbol.parent_symbol as Struct; - if (type_parameter.parent_symbol != garray_type && - (st == null || get_ccode_name (st) != "va_list")) { - // GArray and va_list don't use pointer-based generics - set_cvalue (expr, convert_from_generic_pointer (get_cvalue (expr), expr.value_type)); - ((GLibValue) expr.target_value).lvalue = false; - } - } - - // memory management, implicit casts, and boxing/unboxing - if (expr.value_type != null) { - // FIXME: temporary workaround until the refactoring is complete, not all target_value have a value_type - expr.target_value.value_type = expr.value_type; - expr.target_value = transform_value (expr.target_value, expr.target_type, expr); - } - - if (expr.target_value == null) { - return; - } - - if (expr.formal_target_type is GenericType && !(expr.target_type is GenericType)) { - if (((GenericType) expr.formal_target_type).type_parameter.parent_symbol != garray_type) { - // GArray doesn't use pointer-based generics - set_cvalue (expr, convert_to_generic_pointer (get_cvalue (expr), expr.target_type)); - ((GLibValue) expr.target_value).lvalue = false; - } - } - - // Allow null to initialize non-null struct inside initializer list - if (expr is NullLiteral && expr.parent_node is InitializerList - && expr.target_type != null && expr.target_type.is_real_non_null_struct_type ()) { - var clist = new CCodeInitializerList (); - clist.append (new CCodeConstant ("0")); - set_cvalue (expr, new CCodeCastExpression (clist, get_ccode_name (expr.target_type.type_symbol))); - } - - if (!(expr.value_type is ValueType && !expr.value_type.nullable)) { - ((GLibValue) expr.target_value).non_null = expr.is_non_null (); - } - } else if (expr.value_type != null && is_compact_class_destructor_call (expr)) { - // transfer ownership here and consume given instance - var temp_value = store_temp_value (expr.target_value, expr); - ccode.add_assignment (get_cvalue (expr), new CCodeConstant ("NULL")); - expr.target_value = temp_value; - } - } - - public override void visit_boolean_literal (BooleanLiteral expr) { - set_cvalue (expr, get_boolean_cconstant (expr.value)); - } - - public override void visit_character_literal (CharacterLiteral expr) { - if (expr.get_char () >= 0x20 && expr.get_char () < 0x80) { - set_cvalue (expr, new CCodeConstant (expr.value)); - } else { - set_cvalue (expr, new CCodeConstant ("%uU".printf (expr.get_char ()))); - } - } - - public override void visit_integer_literal (IntegerLiteral expr) { - set_cvalue (expr, new CCodeConstant (expr.value + expr.type_suffix)); - } - - public override void visit_real_literal (RealLiteral expr) { - string c_literal = expr.value; - if (c_literal.has_suffix ("d") || c_literal.has_suffix ("D")) { - // there is no suffix for double in C - c_literal = c_literal.substring (0, c_literal.length - 1); - } - if (!("." in c_literal || "e" in c_literal || "E" in c_literal)) { - // C requires period or exponent part for floating constants - if ("f" in c_literal || "F" in c_literal) { - c_literal = c_literal.substring (0, c_literal.length - 1) + ".f"; - } else { - c_literal += "."; - } - } - set_cvalue (expr, new CCodeConstant (c_literal)); - } - - public override void visit_string_literal (StringLiteral expr) { - set_cvalue (expr, new CCodeConstant.string (expr.value.replace ("\n", "\\n"))); - - if (expr.translate) { - // translated string constant - var translate = new CCodeFunctionCall (new CCodeIdentifier ("_")); - translate.add_argument (get_cvalue (expr)); - set_cvalue (expr, translate); - } - } - - public override void visit_regex_literal (RegexLiteral expr) { - string[] parts = expr.value.split ("/", 3); - string re = parts[2].escape (""); - string flags = "0"; - - if (parts[1].contains ("i")) { - flags += " | G_REGEX_CASELESS"; - } - if (parts[1].contains ("m")) { - flags += " | G_REGEX_MULTILINE"; - } - if (parts[1].contains ("s")) { - flags += " | G_REGEX_DOTALL"; - } - if (parts[1].contains ("x")) { - flags += " | G_REGEX_EXTENDED"; - } - - var cdecl = new CCodeDeclaration ("GRegex*"); - - var cname = "_tmp_regex_%d".printf (next_regex_id); - if (this.next_regex_id == 0) { - var fun = new CCodeFunction ("_thread_safe_regex_init", "GRegex*"); - fun.modifiers = CCodeModifiers.STATIC | CCodeModifiers.INLINE; - fun.add_parameter (new CCodeParameter ("re", "GRegex**")); - fun.add_parameter (new CCodeParameter ("pattern", "const gchar *")); - fun.add_parameter (new CCodeParameter ("compile_flags", "GRegexCompileFlags")); - - push_function (fun); - - var once_enter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_enter")); - if (context.require_glib_version (2, 68)) { - once_enter_call.add_argument (new CCodeConstant ("(gsize*) re")); - } else { - once_enter_call.add_argument (new CCodeConstant ("(volatile gsize*) re")); - } - ccode.open_if (once_enter_call); - - var regex_new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_regex_new")); - regex_new_call.add_argument (new CCodeConstant ("pattern")); - regex_new_call.add_argument (new CCodeConstant ("compile_flags")); - regex_new_call.add_argument (new CCodeConstant ("0")); - regex_new_call.add_argument (new CCodeConstant ("NULL")); - ccode.add_assignment (new CCodeIdentifier ("GRegex* val"), regex_new_call); - - var once_leave_call = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_leave")); - if (context.require_glib_version (2, 68)) { - once_leave_call.add_argument (new CCodeConstant ("(gsize*) re")); - } else { - once_leave_call.add_argument (new CCodeConstant ("(volatile gsize*) re")); - } - once_leave_call.add_argument (new CCodeConstant ("(gsize) val")); - ccode.add_expression (once_leave_call); - - ccode.close (); - - ccode.add_return (new CCodeIdentifier ("*re")); - - pop_function (); - - cfile.add_function (fun); - } - this.next_regex_id++; - - cdecl.add_declarator (new CCodeVariableDeclarator (cname + " = NULL")); - cdecl.modifiers = CCodeModifiers.STATIC; - - var regex_const = new CCodeConstant ("_thread_safe_regex_init (&%s, \"%s\", %s)".printf (cname, re, flags)); - - cfile.add_constant_declaration (cdecl); - set_cvalue (expr, regex_const); - } - - public override void visit_null_literal (NullLiteral expr) { - if (context.profile == Profile.GOBJECT) { - cfile.add_include ("glib.h"); - } else { - cfile.add_include ("stddef.h"); - } - set_cvalue (expr, new CCodeConstant ("NULL")); - - var array_type = expr.target_type as ArrayType; - var delegate_type = expr.target_type as DelegateType; - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - append_array_length (expr, new CCodeConstant ("0")); - } - } else if (delegate_type != null && delegate_type.delegate_symbol.has_target) { - set_delegate_target (expr, new CCodeConstant ("NULL")); - set_delegate_target_destroy_notify (expr, new CCodeConstant ("NULL")); - } - } - - public abstract TargetValue get_local_cvalue (LocalVariable local); - - public abstract TargetValue get_parameter_cvalue (Parameter param); - - public abstract TargetValue get_field_cvalue (Field field, TargetValue? instance); - - public abstract TargetValue load_variable (Variable variable, TargetValue value, Expression? expr = null); - - public abstract TargetValue load_this_parameter (TypeSymbol sym); - - public abstract void store_value (TargetValue lvalue, TargetValue value, SourceReference? source_reference = null); - - public virtual string get_delegate_target_cname (string delegate_cname) { - assert_not_reached (); - } - - public virtual CCodeExpression get_delegate_target_cexpression (Expression delegate_expr, out CCodeExpression delegate_target_destroy_notify) { - assert_not_reached (); - } - - public virtual CCodeExpression get_delegate_target_cvalue (TargetValue value) { - return new CCodeInvalidExpression (); - } - - public virtual CCodeExpression get_delegate_target_destroy_notify_cvalue (TargetValue value) { - return new CCodeInvalidExpression (); - } - - public virtual string get_delegate_target_destroy_notify_cname (string delegate_cname) { - assert_not_reached (); - } - - public override void visit_base_access (BaseAccess expr) { - unowned Class? cl = expr.value_type.type_symbol as Class; - if (cl != null && !cl.is_compact) { - set_cvalue (expr, generate_instance_cast (get_this_cexpression (), cl)); - } else { - expr.target_value = load_this_parameter (expr.value_type.type_symbol); - } - } - - 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; - - // increment/decrement property - var op = expr.increment ? CCodeBinaryOperator.PLUS : CCodeBinaryOperator.MINUS; - var cexpr = new CCodeBinaryExpression (op, get_cvalue (expr.inner), new CCodeConstant ("1")); - store_property (prop, ma.inner, new GLibValue (expr.value_type, cexpr)); - - // return previous value - expr.target_value = expr.inner.target_value; - return; - } - - // assign current value to temp variable - var temp_value = store_temp_value (expr.inner.target_value, expr); - - // increment/decrement variable - var op = expr.increment ? CCodeBinaryOperator.PLUS : CCodeBinaryOperator.MINUS; - var cexpr = new CCodeBinaryExpression (op, get_cvalue_ (temp_value), new CCodeConstant ("1")); - ccode.add_assignment (get_cvalue (expr.inner), cexpr); - - // return previous value - expr.target_value = temp_value; - } - - private MemberAccess? find_property_access (Expression expr) { - if (!(expr is MemberAccess)) { - return null; - } - - var ma = (MemberAccess) expr; - if (ma.symbol_reference is Property) { - return ma; - } - - return null; - } - - static bool is_limited_generic_type (GenericType type) { - unowned Class? cl = type.type_parameter.parent_symbol as Class; - unowned Struct? st = type.type_parameter.parent_symbol as Struct; - if ((cl != null && cl.is_compact) || st != null) { - // compact classes and structs only - // have very limited generics support - return true; - } - return false; - } - - public static bool requires_copy (DataType type) { - if (!type.is_disposable ()) { - return false; - } - - unowned Class? cl = type.type_symbol as Class; - if (cl != null && is_reference_counting (cl) - && get_ccode_ref_function (cl) == "") { - // empty ref_function => no ref necessary - return false; - } - - if (type is GenericType) { - if (is_limited_generic_type ((GenericType) type)) { - return false; - } - } - - return true; - } - - public static bool requires_destroy (DataType type) { - if (!type.is_disposable ()) { - return false; - } - - var array_type = type as ArrayType; - if (array_type != null && array_type.fixed_length) { - return requires_destroy (array_type.element_type); - } - - unowned Class? cl = type.type_symbol as Class; - if (cl != null && is_reference_counting (cl) - && get_ccode_unref_function (cl) == "") { - // empty unref_function => no unref necessary - return false; - } - - if (type is GenericType) { - if (is_limited_generic_type ((GenericType) type)) { - return false; - } - } - - return true; - } - - public virtual TargetValue? copy_value (TargetValue value, CodeNode node) { - var type = value.value_type; - var cexpr = get_cvalue_ (value); - var result = ((GLibValue) value).copy (); - - if (type is DelegateType) { - var delegate_type = (DelegateType) type; - if (get_ccode_delegate_target (node) && delegate_type.delegate_symbol.has_target && !context.deprecated) { - Report.deprecated (node.source_reference, "copying delegates is not supported"); - } - result.delegate_target_destroy_notify_cvalue = new CCodeConstant ("NULL"); - return result; - } - - if (type is ValueType && !type.nullable) { - // normal value type, no null check - - // use temp-var for upcoming address-of operator - var temp_cvalue = create_temp_value (type, false, node); - store_value (temp_cvalue, value, node.source_reference); - cexpr = get_cvalue_ (temp_cvalue); - - var temp_value = create_temp_value (type, true, node, true); - var ctemp = get_cvalue_ (temp_value); - - var vt = (ValueType) type; - var st = (Struct) vt.type_symbol; - var copy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_copy_function (st))); - copy_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr)); - copy_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp)); - - if (!get_ccode_has_copy_function (st)) { - generate_struct_copy_function (st); - } - - if (gvalue_type != null && type.type_symbol == gvalue_type) { - var cisvalid = new CCodeFunctionCall (new CCodeIdentifier ("G_IS_VALUE")); - cisvalid.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr)); - - ccode.open_if (cisvalid); - - // GValue requires g_value_init in addition to g_value_copy - var value_type_call = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE")); - value_type_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr)); - - var init_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init")); - init_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp)); - init_call.add_argument (value_type_call); - ccode.add_expression (init_call); - ccode.add_expression (copy_call); - - ccode.add_else (); - - // g_value_init/copy must not be called for uninitialized values - store_value (temp_value, temp_cvalue, node.source_reference); - ccode.close (); - } else { - ccode.add_expression (copy_call); - } - - return temp_value; - } - - /* (temp = expr, temp == NULL ? NULL : ref (temp)) - * - * can be simplified to - * ref (expr) - * if static type of expr is non-null - */ - - var dupexpr = get_dup_func_expression (type, node.source_reference); - - if (dupexpr == null) { - node.error = true; - return null; - } - - if (dupexpr is CCodeIdentifier && !(type is ArrayType) && !(type is GenericType) && !is_ref_function_void (type)) { - // generate and call NULL-aware ref function to reduce number - // of temporary variables and simplify code - - var dupid = (CCodeIdentifier) dupexpr; - string dup0_func = "_%s0".printf (dupid.name); - - // g_strdup is already NULL-safe - if (dupid.name == "g_strdup") { - dup0_func = dupid.name; - } else if (add_wrapper (dup0_func)) { - var dup0_fun = new CCodeFunction (dup0_func, get_ccode_name (pointer_type)); - dup0_fun.add_parameter (new CCodeParameter ("self", get_ccode_name (pointer_type))); - dup0_fun.modifiers = CCodeModifiers.STATIC; - - push_function (dup0_fun); - - var dup_call = new CCodeFunctionCall (dupexpr); - dup_call.add_argument (new CCodeIdentifier ("self")); - - ccode.add_return (new CCodeConditionalExpression (new CCodeIdentifier ("self"), dup_call, new CCodeConstant ("NULL"))); - - pop_function (); - - cfile.add_function (dup0_fun); - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (dup0_func)); - ccall.add_argument (cexpr); - result.cvalue = ccall; - result.value_type.value_owned = true; - return store_temp_value (result, node); - } - - var ccall = new CCodeFunctionCall (dupexpr); - - if (!(type is ArrayType) && get_non_null (value) && !is_ref_function_void (type)) { - // expression is non-null - ccall.add_argument (cexpr); - - return store_temp_value (new GLibValue (type, ccall), node); - } else { - CCodeExpression ccallarg; - if (node is SliceExpression) { - ccallarg = cexpr; - cexpr = get_cvalue (((SliceExpression) node).container); - } else { - ccallarg = cexpr; - } - var cnotnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, cexpr, new CCodeConstant ("NULL")); - if (type is GenericType) { - // dup functions are optional for type parameters - var cdupnotnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_dup_func_expression (type, node.source_reference), new CCodeConstant ("NULL")); - cnotnull = new CCodeBinaryExpression (CCodeBinaryOperator.AND, cnotnull, cdupnotnull); - } - - if (type is GenericType) { - // cast from gconstpointer to gpointer as GBoxedCopyFunc expects gpointer - ccall.add_argument (new CCodeCastExpression (ccallarg, get_ccode_name (pointer_type))); - } else { - ccall.add_argument (ccallarg); - } - - if (type is ArrayType) { - var array_type = (ArrayType) type; - ccall.add_argument (get_array_length_cvalue (value)); - - if (array_type.element_type is GenericType) { - var elem_dupexpr = get_dup_func_expression (array_type.element_type, node.source_reference); - if (elem_dupexpr == null) { - elem_dupexpr = new CCodeConstant ("NULL"); - } - ccall.add_argument (elem_dupexpr); - } - } - - CCodeExpression cifnull; - if (type is GenericType) { - // the value might be non-null even when the dup function is null, - // so we may not just use NULL for type parameters - - // cast from gconstpointer to gpointer as methods in - // generic classes may not return gconstpointer - cifnull = new CCodeCastExpression (cexpr, get_ccode_name (pointer_type)); - } else if (type.type_symbol != null) { - cifnull = new CCodeConstant ("NULL"); - } else { - cifnull = cexpr; - } - - if (is_ref_function_void (type)) { - ccode.open_if (cnotnull); - ccode.add_expression (ccall); - ccode.close (); - } else { - if (get_non_null (value)) { - result.cvalue = ccall; - } else { - var ccond = new CCodeConditionalExpression (cnotnull, ccall, cifnull); - result.cvalue = ccond; - } - result = (GLibValue) store_temp_value (result, node, true); - } - return result; - } - } - - public virtual void generate_class_declaration (Class cl, CCodeFile decl_space) { - if (add_symbol_declaration (decl_space, cl, get_ccode_name (cl))) { - return; - } - } - - public virtual void generate_interface_declaration (Interface iface, CCodeFile decl_space) { - } - - public virtual bool generate_method_declaration (Method m, CCodeFile decl_space) { - return false; - } - - public virtual void generate_error_domain_declaration (ErrorDomain edomain, CCodeFile decl_space) { - } - - public void add_generic_type_arguments (Method m, Map arg_map, List type_args, CodeNode expr, bool is_chainup = false, List? type_parameters = null) { - int type_param_index = 0; - foreach (var type_arg in type_args) { - if (get_ccode_simple_generics (m)) { - if (requires_copy (type_arg)) { - arg_map.set (get_param_pos (-1 + 0.1 * type_param_index + 0.03), get_destroy0_func_expression (type_arg, is_chainup)); - } else { - arg_map.set (get_param_pos (-1 + 0.1 * type_param_index + 0.03), new CCodeConstant ("NULL")); - } - type_param_index++; - continue; - } - - if (type_parameters != null) { - var type_param_name = type_parameters.get (type_param_index).name.ascii_down ().replace ("_", "-"); - arg_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeConstant ("\"%s-type\"".printf (type_param_name))); - arg_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeConstant ("\"%s-dup-func\"".printf (type_param_name))); - arg_map.set (get_param_pos (0.1 * type_param_index + 0.05), new CCodeConstant ("\"%s-destroy-func\"".printf (type_param_name))); - } - - arg_map.set (get_param_pos (0.1 * type_param_index + 0.02), get_type_id_expression (type_arg, is_chainup)); - if (requires_copy (type_arg)) { - var dup_func = get_dup_func_expression (type_arg, type_arg.source_reference ?? expr.source_reference, is_chainup); - if (dup_func == null) { - // type doesn't contain a copy function - expr.error = true; - return; - } - arg_map.set (get_param_pos (0.1 * type_param_index + 0.04), new CCodeCastExpression (dup_func, "GBoxedCopyFunc")); - arg_map.set (get_param_pos (0.1 * type_param_index + 0.06), new CCodeCastExpression (get_destroy_func_expression (type_arg, is_chainup), "GDestroyNotify")); - } else { - arg_map.set (get_param_pos (0.1 * type_param_index + 0.04), new CCodeConstant ("NULL")); - arg_map.set (get_param_pos (0.1 * type_param_index + 0.06), new CCodeConstant ("NULL")); - } - type_param_index++; - } - } - - public override void visit_object_creation_expression (ObjectCreationExpression expr) { - CCodeExpression instance = null; - CCodeExpression creation_expr = null; - - unowned Struct? st = expr.type_reference.type_symbol as Struct; - if ((st != null && (!st.is_simple_type () || get_ccode_name (st) == "va_list")) || expr.get_object_initializer ().size > 0) { - // value-type initialization or object creation expression with object initializer - - var local = expr.parent_node as LocalVariable; - var field = expr.parent_node as Field; - var a = expr.parent_node as Assignment; - if (local != null && is_simple_struct_creation (local, local.initializer)) { - instance = get_cvalue_ (get_local_cvalue (local)); - } else if (field != null && is_simple_struct_creation (field, field.initializer)) { - // field initialization - var thisparam = load_this_parameter ((TypeSymbol) field.parent_symbol); - instance = get_cvalue_ (get_field_cvalue (field, thisparam)); - } else if (a != null && a.left.symbol_reference is Variable && is_simple_struct_creation ((Variable) a.left.symbol_reference, a.right)) { - if (requires_destroy (a.left.value_type)) { - /* unref old value */ - ccode.add_expression (destroy_value (a.left.target_value)); - } - - local = a.left.symbol_reference as LocalVariable; - field = a.left.symbol_reference as Field; - var param = a.left.symbol_reference as Parameter; - if (local != null) { - instance = get_cvalue_ (get_local_cvalue (local)); - } else if (field != null) { - var inner = ((MemberAccess) a.left).inner; - instance = get_cvalue_ (get_field_cvalue (field, inner != null ? inner.target_value : null)); - } else if (param != null) { - instance = get_cvalue_ (get_parameter_cvalue (param)); - } - } else if (expr.is_chainup) { - instance = get_this_cexpression (); - } else { - var temp_value = create_temp_value (expr.type_reference, true, expr); - instance = get_cvalue_ (temp_value); - } - } - - if (expr.symbol_reference == null) { - // no creation method - if (expr.type_reference.type_symbol is Struct) { - // memset needs string.h - cfile.add_include ("string.h"); - var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance)); - creation_call.add_argument (new CCodeConstant ("0")); - creation_call.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (get_ccode_name (expr.type_reference)))); - - creation_expr = creation_call; - } - } else if (expr.type_reference.type_symbol == glist_type || - expr.type_reference.type_symbol == gslist_type) { - // NULL is an empty list - set_cvalue (expr, new CCodeConstant ("NULL")); - } else if (expr.symbol_reference is Method) { - // use creation method - var m = (Method) expr.symbol_reference; - var params = m.get_parameters (); - CCodeFunctionCall creation_call; - - CCodeFunctionCall async_call = null; - CCodeFunctionCall finish_call = null; - - generate_method_declaration (m, cfile); - - if (m is CreationMethod && !m.external && m.external_package) { - unowned CreationMethod cm = (CreationMethod) m; - if (!cm.chain_up) { - Report.error (cm.source_reference, "internal: Creation method implementation in binding must be chained up"); - } - // internal VAPI creation methods - // only add them once per source file - if (add_generated_external_symbol (cm)) { - visit_creation_method (cm); - } - } - - unowned Class? cl = expr.type_reference.type_symbol as Class; - - if (!get_ccode_has_new_function (m)) { - // use construct function directly - creation_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_real_name (m))); - creation_call.add_argument (new CCodeIdentifier (get_ccode_type_id (cl))); - } else { - creation_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m))); - } - - if ((st != null && !st.is_simple_type ()) && !(get_ccode_instance_pos (m) < 0)) { - if (expr.is_chainup) { - creation_call.add_argument (instance); - } else { - creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance)); - } - } else if (st != null && get_ccode_name (st) == "va_list") { - creation_call.add_argument (instance); - if (get_ccode_name (m) == "va_start") { - unowned Class? parent = current_method.parent_symbol as Class; - if (in_creation_method && parent != null && !parent.is_compact) { - creation_call = new CCodeFunctionCall (new CCodeIdentifier ("va_copy")); - creation_call.add_argument (instance); - creation_call.add_argument (new CCodeIdentifier ("_vala_va_list")); - } else { - Parameter last_param = null; - // FIXME: this doesn't take into account exception handling parameters - foreach (var param in current_method.get_parameters ()) { - if (param.ellipsis || param.params_array) { - break; - } - last_param = param; - } - int nParams = ccode.get_parameter_count (); - if (nParams == 0 || !ccode.get_parameter (nParams - 1).ellipsis) { - Report.error (expr.source_reference, "`va_list' used in method with fixed args"); - } else if (nParams == 1) { - Report.error (expr.source_reference, "`va_list' used in method without parameter"); - } else { - creation_call.add_argument (new CCodeIdentifier (ccode.get_parameter (nParams - 2).name)); - } - } - } - } - - generate_type_declaration (expr.type_reference, cfile); - - var in_arg_map = new HashMap (direct_hash, direct_equal); - var out_arg_map = in_arg_map; - - if (m != null && m.coroutine) { - // async call - - async_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m))); - finish_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_name (m))); - - creation_call = finish_call; - - // output arguments used separately - out_arg_map = new HashMap (direct_hash, direct_equal); - // pass GAsyncResult stored in closure to finish function - out_arg_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_res_")); - } - - if (cl != null && (!cl.is_compact || get_ccode_simple_generics (m))) { - add_generic_type_arguments (m, in_arg_map, expr.type_reference.get_type_arguments (), expr); - } - - bool ellipsis = false; - - int i = 1; - int arg_pos; - Iterator params_it = params.iterator (); - foreach (Expression arg in expr.get_argument_list ()) { - CCodeExpression cexpr = get_cvalue (arg); - - var carg_map = in_arg_map; - - Parameter param = null; - if (params_it.next ()) { - param = params_it.get (); - ellipsis = param.ellipsis || param.params_array; - if (!ellipsis) { - if (param.direction == ParameterDirection.OUT) { - carg_map = out_arg_map; - } - - if (get_ccode_array_length (param) && param.variable_type is ArrayType) { - var array_type = (ArrayType) param.variable_type; - for (int dim = 1; dim <= array_type.rank; dim++) { - carg_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), get_array_length_cexpression (arg, dim)); - } - } else if (get_ccode_delegate_target (param) && param.variable_type is DelegateType) { - var deleg_type = (DelegateType) param.variable_type; - var d = deleg_type.delegate_symbol; - if (d.has_target) { - CCodeExpression delegate_target_destroy_notify; - var delegate_target = get_delegate_target_cexpression (arg, out delegate_target_destroy_notify); - carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), delegate_target); - if (deleg_type.is_disposable ()) { - carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), delegate_target_destroy_notify); - } - } - } - - cexpr = handle_struct_argument (param, arg, cexpr); - - if (get_ccode_type (param) != null) { - cexpr = new CCodeCastExpression (cexpr, get_ccode_type (param)); - } - } else { - cexpr = handle_struct_argument (null, arg, cexpr); - } - - arg_pos = get_param_pos (get_ccode_pos (param), ellipsis); - } else { - // default argument position - cexpr = handle_struct_argument (null, arg, cexpr); - arg_pos = get_param_pos (i, ellipsis); - } - - carg_map.set (arg_pos, cexpr); - - i++; - } - if (params_it.next ()) { - var param = params_it.get (); - - /* if there are more parameters than arguments, - * the additional parameter is an ellipsis parameter - * otherwise there is a bug in the semantic analyzer - */ - assert (param.params_array || param.ellipsis); - ellipsis = true; - } - - if (expr.tree_can_fail) { - // method can fail - current_method_inner_error = true; - // add &inner_error before the ellipsis arguments - out_arg_map.set (get_param_pos (-1), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ())); - } - - if (ellipsis) { - /* ensure variable argument list ends with NULL - * except when using printf-style arguments */ - if (m == null) { - in_arg_map.set (get_param_pos (-1, true), new CCodeConstant ("NULL")); - } else if (!m.printf_format && !m.scanf_format && get_ccode_sentinel (m) != "") { - in_arg_map.set (get_param_pos (-1, true), new CCodeConstant (get_ccode_sentinel (m))); - } - } - - if ((st != null && !st.is_simple_type ()) && get_ccode_instance_pos (m) < 0) { - // instance parameter is at the end in a struct creation method - out_arg_map.set (get_param_pos (-3), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance)); - } - - if (m != null && m.coroutine) { - if (expr.is_yield_expression) { - // asynchronous call - in_arg_map.set (get_param_pos (-1), new CCodeIdentifier (generate_ready_function (current_method))); - in_arg_map.set (get_param_pos (-0.9), new CCodeIdentifier ("_data_")); - } - } - - if (m != null && m.coroutine && m.parent_symbol is Class) { - if (get_ccode_finish_instance (m)) { - var tmp = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_source_object_"); - out_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), tmp); - } - } - - // append C arguments in the right order - - int last_pos; - int min_pos; - - if (async_call != creation_call) { - // don't append out arguments for .begin() calls - last_pos = -1; - while (true) { - min_pos = -1; - foreach (int pos in out_arg_map.get_keys ()) { - if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { - min_pos = pos; - } - } - if (min_pos == -1) { - break; - } - creation_call.add_argument (out_arg_map.get (min_pos)); - last_pos = min_pos; - } - } - - if (async_call != null) { - last_pos = -1; - while (true) { - min_pos = -1; - foreach (int pos in in_arg_map.get_keys ()) { - if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { - min_pos = pos; - } - } - if (min_pos == -1) { - break; - } - async_call.add_argument (in_arg_map.get (min_pos)); - last_pos = min_pos; - } - } - - if (expr.is_yield_expression) { - // set state before calling async function to support immediate callbacks - int state = emit_context.next_coroutine_state++; - - ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ())); - ccode.add_expression (async_call); - ccode.add_return (new CCodeConstant ("FALSE")); - ccode.add_label ("_state_%d".printf (state)); - } - - creation_expr = creation_call; - - // cast the return value of the creation method back to the intended type if - // it requested a special C return type - if (get_ccode_type (m) != null) { - creation_expr = new CCodeCastExpression (creation_expr, get_ccode_name (expr.type_reference)); - } - } else if (expr.symbol_reference is ErrorCode) { - var ecode = (ErrorCode) expr.symbol_reference; - var edomain = (ErrorDomain) ecode.parent_symbol; - CCodeFunctionCall creation_call; - - generate_error_domain_declaration (edomain, cfile); - - if (expr.get_argument_list ().size == 1) { - // must not be a format argument - creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_error_new_literal")); - } else { - creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_error_new")); - } - creation_call.add_argument (new CCodeIdentifier (get_ccode_upper_case_name (edomain))); - creation_call.add_argument (new CCodeIdentifier (get_ccode_name (ecode))); - - foreach (Expression arg in expr.get_argument_list ()) { - creation_call.add_argument (get_cvalue (arg)); - } - - creation_expr = creation_call; - } else { - assert (false); - } - - var local = expr.parent_node as LocalVariable; - if (local != null && is_simple_struct_creation (local, local.initializer)) { - // no temporary variable necessary - ccode.add_expression (creation_expr); - set_cvalue (expr, instance); - } else if (instance != null) { - if (expr.type_reference.type_symbol is Struct) { - ccode.add_expression (creation_expr); - } else { - ccode.add_assignment (instance, creation_expr); - } - - foreach (MemberInitializer init in expr.get_object_initializer ()) { - if (init.symbol_reference is Field) { - var f = (Field) init.symbol_reference; - var instance_target_type = SemanticAnalyzer.get_data_type_for_symbol ((TypeSymbol) f.parent_symbol); - var typed_inst = transform_value (new GLibValue (expr.type_reference, instance, true), instance_target_type, init); - store_field (f, typed_inst, init.initializer.target_value, init.source_reference); - - var cl = f.parent_symbol as Class; - if (cl != null) { - generate_class_struct_declaration (cl, cfile); - } - } else if (init.symbol_reference is Property) { - var p = (Property) init.symbol_reference; - if (p.base_property != null) { - p = p.base_property; - } else if (p.base_interface_property != null) { - p = p.base_interface_property; - } - var instance_target_type = SemanticAnalyzer.get_data_type_for_symbol ((TypeSymbol) p.parent_symbol); - var typed_inst = transform_value (new GLibValue (expr.type_reference, instance), instance_target_type, init); - var inst_ma = new MemberAccess.simple ("fake"); - inst_ma.target_value = typed_inst; - store_property (p, inst_ma, init.initializer.target_value); - // FIXME Do not ref/copy in the first place - if (!p.set_accessor.value_type.value_owned && requires_destroy (init.initializer.target_value.value_type)) { - ccode.add_expression (destroy_value (init.initializer.target_value)); - } - } else { - Report.error (init.source_reference, "internal: Unsupported symbol"); - } - } - - set_cvalue (expr, instance); - } else if (creation_expr != null) { - var temp_value = create_temp_value (expr.value_type, false, expr); - ccode.add_assignment (get_cvalue_ (temp_value), creation_expr); - expr.target_value = temp_value; - - unowned Class? cl = expr.type_reference.type_symbol as Class; - if (context.gobject_tracing) { - // GObject creation tracing enabled - - if (cl != null && cl.is_subtype_of (gobject_type)) { - // creating GObject - - // instance can be NULL in error cases - ccode.open_if (get_cvalue_ (expr.target_value)); - - var set_data_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_set_data")); - set_data_call.add_argument (new CCodeCastExpression (get_cvalue_ (expr.target_value), "GObject *")); - set_data_call.add_argument (new CCodeConstant ("\"vala-creation-function\"")); - - string func_name = ""; - if (current_method != null) { - func_name = current_method.get_full_name (); - } else if (current_property_accessor != null) { - func_name = current_property_accessor.get_full_name (); - } - - set_data_call.add_argument (new CCodeConstant ("\"%s\"".printf (func_name))); - - ccode.add_expression (set_data_call); - - ccode.close (); - } - } - - // create a special GDestroyNotify for created GArray and set with g_array_set_clear_func (since glib 2.32) - if (cl != null && cl == garray_type) { - var type_arg = expr.type_reference.get_type_arguments ().get (0); - if (requires_destroy (type_arg)) { - var clear_func = new CCodeFunctionCall (new CCodeIdentifier ("g_array_set_clear_func")); - clear_func.add_argument (get_cvalue_ (expr.target_value)); - string destroy_func; - if (type_arg.is_non_null_simple_type () || type_arg.is_real_non_null_struct_type ()) { - destroy_func = get_ccode_destroy_function (type_arg.type_symbol); - } else { - destroy_func = generate_destroy_function_content_of_wrapper (type_arg); - } - clear_func.add_argument (new CCodeCastExpression (new CCodeIdentifier (destroy_func), "GDestroyNotify")); - ccode.add_expression (clear_func); - } - } - } - - ((GLibValue) expr.target_value).lvalue = true; - } - - public CCodeExpression? handle_struct_argument (Parameter? param, Expression arg, CCodeExpression? cexpr) { - DataType type; - if (param != null) { - type = param.variable_type; - } else { - // varargs - type = arg.value_type; - } - - var unary = arg as UnaryExpression; - // pass non-simple struct instances always by reference - if (!(arg.value_type is NullType) && type.is_real_struct_type ()) { - // we already use a reference for arguments of ref, out, and nullable parameters - if (!(unary != null && (unary.operator == UnaryOperator.OUT || unary.operator == UnaryOperator.REF)) && !type.nullable) { - if (cexpr is CCodeIdentifier || cexpr is CCodeMemberAccess) { - return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr); - } else { - // if cexpr is e.g. a function call, we can't take the address of the expression - var temp_value = create_temp_value (type, false, arg); - ccode.add_assignment (get_cvalue_ (temp_value), cexpr); - return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue_ (temp_value)); - } - } - } - - return cexpr; - } - - public override void visit_sizeof_expression (SizeofExpression expr) { - generate_type_declaration (expr.type_reference, cfile); - - var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - csizeof.add_argument (new CCodeIdentifier (get_ccode_name (expr.type_reference))); - set_cvalue (expr, csizeof); - } - - public override void visit_typeof_expression (TypeofExpression expr) { - cfile.add_include ("glib-object.h"); - - set_cvalue (expr, get_type_id_expression (expr.type_reference)); - } - - public override void visit_unary_expression (UnaryExpression expr) { - if (expr.operator == UnaryOperator.REF || expr.operator == UnaryOperator.OUT) { - var glib_value = (GLibValue) expr.inner.target_value; - - var ref_value = new GLibValue (glib_value.value_type); - if (expr.target_type != null && glib_value.value_type.is_real_struct_type () && glib_value.value_type.nullable != expr.target_type.nullable) { - // the only possibility is that value_type is nullable and target_type is non-nullable - ref_value.cvalue = glib_value.cvalue; - } else { - ref_value.cvalue = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, glib_value.cvalue); - } - - if (glib_value.array_length_cvalues != null) { - for (int i = 0; i < glib_value.array_length_cvalues.size; i++) { - ref_value.append_array_length_cvalue (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, glib_value.array_length_cvalues[i])); - } - } - - if (glib_value.delegate_target_cvalue != null) { - ref_value.delegate_target_cvalue = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, glib_value.delegate_target_cvalue); - } - if (glib_value.delegate_target_destroy_notify_cvalue != null) { - ref_value.delegate_target_destroy_notify_cvalue = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, glib_value.delegate_target_destroy_notify_cvalue); - } - - expr.target_value = ref_value; - return; - } - - if (expr.operator == UnaryOperator.INCREMENT || expr.operator == UnaryOperator.DECREMENT) { - // increment/decrement variable - var op = expr.operator == UnaryOperator.INCREMENT ? CCodeBinaryOperator.PLUS : CCodeBinaryOperator.MINUS; - var cexpr = new CCodeBinaryExpression (op, get_cvalue_ (expr.inner.target_value), new CCodeConstant ("1")); - ccode.add_assignment (get_cvalue (expr.inner), cexpr); - - // assign new value to temp variable - var temp_value = store_temp_value (expr.inner.target_value, expr); - - MemberAccess ma = find_property_access (expr.inner); - if (ma != null) { - // property postfix expression - var prop = (Property) ma.symbol_reference; - - store_property (prop, ma.inner, temp_value); - } - - // return new value - expr.target_value = temp_value; - return; - } - - CCodeUnaryOperator op; - switch (expr.operator) { - case UnaryOperator.PLUS: - op = CCodeUnaryOperator.PLUS; - break; - case UnaryOperator.MINUS: - op = CCodeUnaryOperator.MINUS; - break; - case UnaryOperator.LOGICAL_NEGATION: - op = CCodeUnaryOperator.LOGICAL_NEGATION; - break; - case UnaryOperator.BITWISE_COMPLEMENT: - op = CCodeUnaryOperator.BITWISE_COMPLEMENT; - break; - case UnaryOperator.INCREMENT: - op = CCodeUnaryOperator.PREFIX_INCREMENT; - break; - case UnaryOperator.DECREMENT: - op = CCodeUnaryOperator.PREFIX_DECREMENT; - break; - default: - assert_not_reached (); - } - set_cvalue (expr, new CCodeUnaryExpression (op, get_cvalue (expr.inner))); - } - - public virtual CCodeExpression? deserialize_expression (DataType type, CCodeExpression variant_expr, CCodeExpression? expr, CCodeExpression? error_expr = null, out bool may_fail = null) { - assert_not_reached (); - } - - public virtual CCodeExpression? serialize_expression (DataType type, CCodeExpression expr) { - assert_not_reached (); - } - - public override void visit_cast_expression (CastExpression expr) { - if (expr.is_silent_cast) { - set_cvalue (expr, new CCodeInvalidExpression ()); - expr.error = true; - Report.error (expr.source_reference, "Operation not supported for this type"); - return; - } - - generate_type_declaration (expr.type_reference, cfile); - - // recompute array length when casting to other array type - var array_type = expr.type_reference as ArrayType; - if (array_type != null && expr.inner.value_type is ArrayType) { - if (array_type.element_type is GenericType || ((ArrayType) expr.inner.value_type).element_type is GenericType) { - // element size unknown for generic arrays, retain array length as is - for (int dim = 1; dim <= array_type.rank; dim++) { - append_array_length (expr, get_array_length_cexpression (expr.inner, dim)); - } - } else { - var sizeof_to = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - sizeof_to.add_argument (new CCodeConstant (get_ccode_name (array_type.element_type))); - - var sizeof_from = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - sizeof_from.add_argument (new CCodeConstant (get_ccode_name (((ArrayType) expr.inner.value_type).element_type))); - - for (int dim = 1; dim <= array_type.rank; dim++) { - append_array_length (expr, new CCodeBinaryExpression (CCodeBinaryOperator.DIV, new CCodeBinaryExpression (CCodeBinaryOperator.MUL, get_array_length_cexpression (expr.inner, dim), sizeof_from), sizeof_to)); - } - } - } else if (array_type != null) { - CCodeExpression array_length_expr; - - var sizeof_to = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - sizeof_to.add_argument (new CCodeConstant (get_ccode_name (array_type.element_type))); - var sizeof_from = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - - var value_type = expr.inner.value_type; - if (value_type is ValueType) { - sizeof_from.add_argument (new CCodeConstant (get_ccode_name (value_type.type_symbol))); - array_length_expr = new CCodeBinaryExpression (CCodeBinaryOperator.DIV, sizeof_from, sizeof_to); - } else if (value_type is PointerType && ((PointerType) value_type).base_type is ValueType) { - sizeof_from.add_argument (new CCodeConstant (get_ccode_name (((PointerType) value_type).base_type.type_symbol))); - array_length_expr = new CCodeBinaryExpression (CCodeBinaryOperator.DIV, sizeof_from, sizeof_to); - } else { - // cast from unsupported non-array to array, set invalid length - // required by string.data, e.g. - array_length_expr = new CCodeConstant ("-1"); - } - - for (int dim = 1; dim <= array_type.rank; dim++) { - append_array_length (expr, array_length_expr); - } - } - - var innercexpr = get_cvalue (expr.inner); - if (expr.type_reference is ValueType && !expr.type_reference.nullable && - expr.inner.value_type is ValueType && expr.inner.value_type.nullable) { - // handle nested cast expressions - unowned Expression? inner_expr = expr.inner; - while (inner_expr is CastExpression) { - inner_expr = ((CastExpression) inner_expr).inner; - } - if (inner_expr.value_type.value_owned - && !(inner_expr.symbol_reference is Variable || inner_expr is ElementAccess)) { - // heap allocated struct leaked, destroy it - var value = new GLibValue (new PointerType (new VoidType ()), innercexpr); - temp_ref_values.insert (0, value); - } - // nullable integer or float or boolean or struct or enum cast to non-nullable - innercexpr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, innercexpr); - } else if (expr.type_reference is ValueType && expr.type_reference.nullable && - expr.inner.value_type.is_real_non_null_struct_type ()) { - // real non-null struct cast to nullable - innercexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, innercexpr); - } else if (expr.type_reference is ArrayType && !(expr.inner is Literal) - && expr.inner.value_type is ValueType && !expr.inner.value_type.nullable) { - // integer or float or boolean or struct or enum to array cast - innercexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, innercexpr); - } - set_cvalue (expr, new CCodeCastExpression (innercexpr, get_ccode_name (expr.type_reference))); - //TODO Use get_non_null (expr.inner.target_value) - ((GLibValue) expr.target_value).non_null = expr.is_non_null (); - - if (expr.type_reference is DelegateType) { - var target = get_delegate_target (expr.inner); - if (target != null) { - set_delegate_target (expr, target); - } else { - set_delegate_target (expr, new CCodeConstant ("NULL")); - } - var target_destroy_notify = get_delegate_target_destroy_notify (expr.inner); - if (target_destroy_notify != null) { - set_delegate_target_destroy_notify (expr, target_destroy_notify); - } else { - set_delegate_target_destroy_notify (expr, new CCodeConstant ("NULL")); - } - } - } - - public override void visit_named_argument (NamedArgument expr) { - set_cvalue (expr, get_cvalue (expr.inner)); - } - - public override void visit_pointer_indirection (PointerIndirection expr) { - set_cvalue (expr, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_cvalue (expr.inner))); - ((GLibValue) expr.target_value).lvalue = get_lvalue (expr.inner.target_value); - } - - public override void visit_addressof_expression (AddressofExpression expr) { - set_cvalue (expr, new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue (expr.inner))); - } - - public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) { - /* tmp = expr.inner; expr.inner = NULL; expr = tmp; */ - expr.target_value = store_temp_value (expr.inner.target_value, expr); - - if (expr.inner.value_type is StructValueType && !expr.inner.value_type.nullable) { - // memset needs string.h - cfile.add_include ("string.h"); - var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue (expr.inner))); - creation_call.add_argument (new CCodeConstant ("0")); - creation_call.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (get_ccode_name (expr.inner.value_type)))); - ccode.add_expression (creation_call); - } else if (expr.value_type is DelegateType) { - ccode.add_assignment (get_cvalue (expr.inner), new CCodeConstant ("NULL")); - var target = get_delegate_target_cvalue (expr.inner.target_value); - if (target != null) { - ccode.add_assignment (target, new CCodeConstant ("NULL")); - } - var target_destroy_notify = get_delegate_target_destroy_notify_cvalue (expr.inner.target_value); - if (target_destroy_notify != null) { - ccode.add_assignment (target_destroy_notify, new CCodeConstant ("NULL")); - } - } else if (expr.inner.value_type is ArrayType) { - var array_type = (ArrayType) expr.inner.value_type; - var glib_value = (GLibValue) expr.inner.target_value; - - ccode.add_assignment (get_cvalue (expr.inner), new CCodeConstant ("NULL")); - if (glib_value.array_length_cvalues != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - ccode.add_assignment (get_array_length_cvalue (glib_value, dim), new CCodeConstant ("0")); - } - } - } else { - ccode.add_assignment (get_cvalue (expr.inner), new CCodeConstant ("NULL")); - } - } - - public override void visit_binary_expression (BinaryExpression expr) { - var cleft = get_cvalue (expr.left); - var cright = get_cvalue (expr.right); - - CCodeExpression? left_chain = null; - if (expr.is_chained) { - var lbe = (BinaryExpression) expr.left; - - var temp_decl = get_temp_variable (lbe.right.target_type, true, null, false); - emit_temp_var (temp_decl); - var cvar = get_variable_cexpression (temp_decl.name); - var clbe = (CCodeBinaryExpression) get_cvalue (lbe); - if (lbe.is_chained) { - clbe = (CCodeBinaryExpression) clbe.right; - } - ccode.add_assignment (cvar, get_cvalue (lbe.right)); - clbe.right = get_variable_cexpression (temp_decl.name); - left_chain = cleft; - cleft = cvar; - } - - CCodeBinaryOperator op; - switch (expr.operator) { - case BinaryOperator.PLUS: - op = CCodeBinaryOperator.PLUS; - break; - case BinaryOperator.MINUS: - op = CCodeBinaryOperator.MINUS; - break; - case BinaryOperator.MUL: - op = CCodeBinaryOperator.MUL; - break; - case BinaryOperator.DIV: - op = CCodeBinaryOperator.DIV; - break; - case BinaryOperator.MOD: - // FIXME Code duplication with CCodeAssignmentModule.emit_simple_assignment() - if (expr.value_type.equals (double_type)) { - cfile.add_include ("math.h"); - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("fmod")); - ccall.add_argument (cleft); - ccall.add_argument (cright); - set_cvalue (expr, ccall); - return; - } else if (expr.value_type.equals (float_type)) { - cfile.add_include ("math.h"); - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("fmodf")); - ccall.add_argument (cleft); - ccall.add_argument (cright); - set_cvalue (expr, ccall); - return; - } else { - op = CCodeBinaryOperator.MOD; - } - break; - case BinaryOperator.SHIFT_LEFT: - op = CCodeBinaryOperator.SHIFT_LEFT; - break; - case BinaryOperator.SHIFT_RIGHT: - op = CCodeBinaryOperator.SHIFT_RIGHT; - break; - case BinaryOperator.LESS_THAN: - op = CCodeBinaryOperator.LESS_THAN; - break; - case BinaryOperator.GREATER_THAN: - op = CCodeBinaryOperator.GREATER_THAN; - break; - case BinaryOperator.LESS_THAN_OR_EQUAL: - op = CCodeBinaryOperator.LESS_THAN_OR_EQUAL; - break; - case BinaryOperator.GREATER_THAN_OR_EQUAL: - op = CCodeBinaryOperator.GREATER_THAN_OR_EQUAL; - break; - case BinaryOperator.EQUALITY: - op = CCodeBinaryOperator.EQUALITY; - break; - case BinaryOperator.INEQUALITY: - op = CCodeBinaryOperator.INEQUALITY; - break; - case BinaryOperator.BITWISE_AND: - op = CCodeBinaryOperator.BITWISE_AND; - break; - case BinaryOperator.BITWISE_OR: - op = CCodeBinaryOperator.BITWISE_OR; - break; - case BinaryOperator.BITWISE_XOR: - op = CCodeBinaryOperator.BITWISE_XOR; - break; - case BinaryOperator.AND: - op = CCodeBinaryOperator.AND; - break; - case BinaryOperator.OR: - op = CCodeBinaryOperator.OR; - break; - case BinaryOperator.IN: - if (expr.right.value_type is ArrayType) { - unowned ArrayType array_type = (ArrayType) expr.right.value_type; - unowned DataType element_type = array_type.element_type; - var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_array_contains_wrapper (array_type))); - CCodeExpression node = ccall; - - ccall.add_argument (cright); - ccall.add_argument (get_array_length_cexpression (expr.right)); - if (element_type is StructValueType) { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cleft)); - } else if (element_type is ValueType && !element_type.nullable - && expr.left.value_type is ValueType && expr.left.value_type.nullable) { - // null check - var cnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cleft, new CCodeConstant ("NULL")); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cleft)); - node = new CCodeParenthesizedExpression (new CCodeConditionalExpression (cnull, new CCodeConstant ("FALSE"), ccall)); - } else { - ccall.add_argument (cleft); - } - set_cvalue (expr, node); - } else { - set_cvalue (expr, new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, cright, cleft), cleft)); - } - return; - default: - assert_not_reached (); - } - - if (expr.operator == BinaryOperator.EQUALITY || - expr.operator == BinaryOperator.INEQUALITY) { - var left_type = expr.left.target_type; - var right_type = expr.right.target_type; - make_comparable_cexpression (ref left_type, ref cleft, ref right_type, ref cright); - - if (left_type is StructValueType && right_type is StructValueType) { - var equalfunc = generate_struct_equal_function ((Struct) left_type.type_symbol); - var ccall = new CCodeFunctionCall (new CCodeIdentifier (equalfunc)); - ccall.add_argument (cleft); - ccall.add_argument (cright); - cleft = ccall; - cright = get_boolean_cconstant (true); - } else if ((left_type is IntegerType || left_type is FloatingType || left_type is BooleanType || left_type is EnumValueType) && left_type.nullable && - (right_type is IntegerType || right_type is FloatingType || right_type is BooleanType || right_type is EnumValueType) && right_type.nullable) { - var equalfunc = generate_numeric_equal_function ((TypeSymbol) left_type.type_symbol); - var ccall = new CCodeFunctionCall (new CCodeIdentifier (equalfunc)); - ccall.add_argument (cleft); - ccall.add_argument (cright); - cleft = ccall; - cright = get_boolean_cconstant (true); - } - } - - bool is_string_comparison = !(expr.left.value_type is NullType) && expr.left.value_type.compatible (string_type) - && !(expr.right.value_type is NullType) && expr.right.value_type.compatible (string_type); - bool has_string_literal = (expr.left is StringLiteral || expr.right is StringLiteral); - - if (is_string_comparison || (has_string_literal && expr.operator != BinaryOperator.PLUS)) { - switch (expr.operator) { - case BinaryOperator.PLUS: - // string concatenation - if (expr.left.is_constant () && expr.right.is_constant ()) { - string left, right; - - if (cleft is CCodeIdentifier) { - left = ((CCodeIdentifier) cleft).name; - } else if (cleft is CCodeConstant) { - left = ((CCodeConstant) cleft).name; - } else { - Report.error (expr.source_reference, "internal: Unsupported expression"); - left = "NULL"; - } - if (cright is CCodeIdentifier) { - right = ((CCodeIdentifier) cright).name; - } else if (cright is CCodeConstant) { - right = ((CCodeConstant) cright).name; - } else { - Report.error (expr.source_reference, "internal: Unsupported expression"); - right = "NULL"; - } - - set_cvalue (expr, new CCodeConstant ("%s %s".printf (left, right))); - } else { - var temp_value = create_temp_value (expr.value_type, false, expr); - CCodeFunctionCall ccall; - - if (context.profile == Profile.POSIX) { - // convert to strcat (strcpy (malloc (1 + strlen (a) + strlen (b)), a), b) - ccall = new CCodeFunctionCall (new CCodeIdentifier ("strcat")); - var strcpy = new CCodeFunctionCall (new CCodeIdentifier ("strcpy")); - var malloc = new CCodeFunctionCall (new CCodeIdentifier ("malloc")); - - var strlen_a = new CCodeFunctionCall (new CCodeIdentifier ("strlen")); - strlen_a.add_argument (cleft); - var strlen_b = new CCodeFunctionCall (new CCodeIdentifier ("strlen")); - strlen_b.add_argument (cright); - var newlength = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("1"), - new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, strlen_a, strlen_b)); - malloc.add_argument (newlength); - - strcpy.add_argument (malloc); - strcpy.add_argument (cleft); - - ccall.add_argument (strcpy); - ccall.add_argument (cright); - } else { - // convert to g_strconcat (a, b, NULL) - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat")); - ccall.add_argument (cleft); - ccall.add_argument (cright); - ccall.add_argument (new CCodeConstant("NULL")); - } - - ccode.add_assignment (get_cvalue_ (temp_value), ccall); - expr.target_value = temp_value; - } - return; - case BinaryOperator.EQUALITY: - case BinaryOperator.INEQUALITY: - case BinaryOperator.LESS_THAN: - case BinaryOperator.GREATER_THAN: - case BinaryOperator.LESS_THAN_OR_EQUAL: - case BinaryOperator.GREATER_THAN_OR_EQUAL: - CCodeFunctionCall ccall; - if (context.profile == Profile.POSIX) { - cfile.add_include ("string.h"); - ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_cmp_wrapper (new CCodeIdentifier ("strcmp")))); - } else { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_strcmp0")); - } - ccall.add_argument (cleft); - ccall.add_argument (cright); - cleft = ccall; - cright = new CCodeConstant ("0"); - break; - default: - break; - } - } - - set_cvalue (expr, new CCodeBinaryExpression (op, cleft, cright)); - if (left_chain != null) { - set_cvalue (expr, new CCodeBinaryExpression (CCodeBinaryOperator.AND, left_chain, get_cvalue (expr))); - } - } - - public CCodeExpression? create_type_check (CCodeNode ccodenode, DataType type) { - var et = type as ErrorType; - if (et != null && et.error_code != null) { - var matches_call = new CCodeFunctionCall (new CCodeIdentifier ("g_error_matches")); - matches_call.add_argument ((CCodeExpression) ccodenode); - matches_call.add_argument (new CCodeIdentifier (get_ccode_upper_case_name (et.error_domain))); - matches_call.add_argument (new CCodeIdentifier (get_ccode_name (et.error_code))); - return matches_call; - } else if (et != null && et.error_domain != null) { - var instance_domain = new CCodeMemberAccess.pointer ((CCodeExpression) ccodenode, "domain"); - var type_domain = new CCodeIdentifier (get_ccode_upper_case_name (et.error_domain)); - return new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, instance_domain, type_domain); - } else { - CCodeFunctionCall ccheck; - if (type is GenericType || type.type_symbol == null || type.type_symbol.external_package) { - ccheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE")); - ccheck.add_argument ((CCodeExpression) ccodenode); - ccheck.add_argument (get_type_id_expression (type)); - } else { - ccheck = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_check_function (type.type_symbol))); - ccheck.add_argument ((CCodeExpression) ccodenode); - } - - return ccheck; - } - } - - string generate_array_contains_wrapper (ArrayType array_type) { - string array_contains_func = "_vala_%s_array_contains".printf (get_ccode_lower_case_name (array_type.element_type)); - - if (!add_wrapper (array_contains_func)) { - return array_contains_func; - } - - generate_type_declaration (ssize_t_type, cfile); - - var function = new CCodeFunction (array_contains_func, get_ccode_name (bool_type)); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("stack", "%s *".printf (get_ccode_name (array_type.element_type)))); - function.add_parameter (new CCodeParameter ("stack_length", get_ccode_name (ssize_t_type))); - if (array_type.element_type is StructValueType) { - function.add_parameter (new CCodeParameter ("needle", "const %s *".printf (get_ccode_name (array_type.element_type)))); - } else { - function.add_parameter (new CCodeParameter ("needle", "const %s".printf (get_ccode_name (array_type.element_type)))); - } - - push_function (function); - - ccode.add_declaration (get_ccode_name (ssize_t_type), new CCodeVariableDeclarator ("i")); - - var cloop_initializer = new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")); - var cloop_condition = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("stack_length")); - var cloop_iterator = new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")); - ccode.open_for (cloop_initializer, cloop_condition, cloop_iterator); - - var celement = new CCodeElementAccess (new CCodeIdentifier ("stack"), new CCodeIdentifier ("i")); - var cneedle = new CCodeIdentifier ("needle"); - CCodeBinaryExpression cif_condition; - if (array_type.element_type.compatible (string_type)) { - CCodeFunctionCall ccall; - if (context.profile == Profile.POSIX) { - cfile.add_include ("string.h"); - ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_cmp_wrapper (new CCodeIdentifier ("strcmp")))); - } else { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_strcmp0")); - } - ccall.add_argument (celement); - ccall.add_argument (cneedle); - cif_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccall, new CCodeConstant ("0")); - } else if (array_type.element_type is StructValueType) { - var equalfunc = generate_struct_equal_function ((Struct) array_type.element_type.type_symbol); - var ccall = new CCodeFunctionCall (new CCodeIdentifier (equalfunc)); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, celement)); - ccall.add_argument (cneedle); - cif_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccall, get_boolean_cconstant (true)); - } else { - cif_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cneedle, celement); - } - - ccode.open_if (cif_condition); - ccode.add_return (get_boolean_cconstant (true)); - ccode.close (); - - ccode.close (); - - ccode.add_return (get_boolean_cconstant (false)); - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return array_contains_func; - } - - string generate_cmp_wrapper (CCodeIdentifier cmpid) { - // generate and call NULL-aware cmp function to reduce number - // of temporary variables and simplify code - - string cmp0_func = "_%s0".printf (cmpid.name); - - // g_strcmp0 is already NULL-safe - if (cmpid.name == "g_strcmp0") { - cmp0_func = cmpid.name; - } else if (add_wrapper (cmp0_func)) { - var cmp0_fun = new CCodeFunction (cmp0_func, get_ccode_name (int_type)); - cmp0_fun.add_parameter (new CCodeParameter ("s1", "const void *")); - cmp0_fun.add_parameter (new CCodeParameter ("s2", "const void *")); - cmp0_fun.modifiers = CCodeModifiers.STATIC; - - push_function (cmp0_fun); - - // s1 != s2; - var noteq = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("s1"), new CCodeIdentifier ("s2")); - - // if (!s1) return -(s1 != s2); - { - var cexp = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("s1")); - ccode.open_if (cexp); - ccode.add_return (new CCodeUnaryExpression (CCodeUnaryOperator.MINUS, noteq)); - ccode.close (); - } - // if (!s2) return s1 != s2; - { - var cexp = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("s2")); - ccode.open_if (cexp); - ccode.add_return (noteq); - ccode.close (); - } - // return strcmp (s1, s2); - var cmp_call = new CCodeFunctionCall (cmpid); - cmp_call.add_argument (new CCodeIdentifier ("s1")); - cmp_call.add_argument (new CCodeIdentifier ("s2")); - ccode.add_return (cmp_call); - - pop_function (); - - cfile.add_function (cmp0_fun); - } - - return cmp0_func; - } - - public override void visit_type_check (TypeCheck expr) { - generate_type_declaration (expr.type_reference, cfile); - - var type = expr.expression.value_type; - var pointer_type = type as PointerType; - if (pointer_type != null) { - type = pointer_type.base_type; - } - unowned Class? cl = type.type_symbol as Class; - unowned Interface? iface = type.type_symbol as Interface; - if ((cl != null && !cl.is_compact) || iface != null || type is GenericType || type is ErrorType) { - set_cvalue (expr, create_type_check (get_cvalue (expr.expression), expr.type_reference)); - } else { - set_cvalue (expr, new CCodeInvalidExpression ()); - } - - if (get_cvalue (expr) is CCodeInvalidExpression) { - Report.error (expr.source_reference, "type check expressions not supported for compact classes, structs, and enums"); - } - } - - public override void visit_lambda_expression (LambdaExpression lambda) { - var delegate_type = (DelegateType) lambda.target_type; - - lambda.accept_children (this); - - bool expr_owned = lambda.value_type.value_owned; - - set_cvalue (lambda, new CCodeIdentifier (get_ccode_name (lambda.method))); - - unowned DataType? this_type; - if (lambda.method.closure) { - int block_id = get_block_id (current_closure_block); - var delegate_target = get_variable_cexpression ("_data%d_".printf (block_id)); - if (expr_owned || delegate_type.is_called_once) { - var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_ref".printf (block_id))); - ref_call.add_argument (delegate_target); - delegate_target = ref_call; - set_delegate_target_destroy_notify (lambda, new CCodeIdentifier ("block%d_data_unref".printf (block_id))); - } else { - set_delegate_target_destroy_notify (lambda, new CCodeConstant ("NULL")); - } - set_delegate_target (lambda, delegate_target); - } else if ((this_type = get_this_type ()) != null) { - CCodeExpression delegate_target = get_this_cexpression (); - delegate_target = convert_to_generic_pointer (delegate_target, this_type); - if (expr_owned || delegate_type.is_called_once) { - var ref_call = new CCodeFunctionCall (get_dup_func_expression (this_type, lambda.source_reference)); - ref_call.add_argument (delegate_target); - delegate_target = ref_call; - set_delegate_target_destroy_notify (lambda, get_destroy_func_expression (this_type)); - } else { - set_delegate_target_destroy_notify (lambda, new CCodeConstant ("NULL")); - } - set_delegate_target (lambda, delegate_target); - } else { - set_delegate_target (lambda, new CCodeConstant ("NULL")); - set_delegate_target_destroy_notify (lambda, new CCodeConstant ("NULL")); - } - } - - public CCodeExpression convert_from_generic_pointer (CCodeExpression cexpr, DataType actual_type) { - unowned SemanticAnalyzer analyzer = context.analyzer; - var result = cexpr; - if (analyzer.is_reference_type_argument (actual_type) || analyzer.is_nullable_value_type_argument (actual_type)) { - generate_type_declaration (actual_type, cfile); - result = new CCodeCastExpression (cexpr, get_ccode_name (actual_type)); - } else if (analyzer.is_signed_integer_type_argument (actual_type)) { - // FIXME this should not happen - while (cexpr is CCodeCastExpression) { - cexpr = ((CCodeCastExpression) cexpr).inner; - } - result = new CCodeCastExpression (new CCodeCastExpression (cexpr, "gintptr"), get_ccode_name (actual_type)); - } else if (analyzer.is_unsigned_integer_type_argument (actual_type)) { - // FIXME this should not happen - while (cexpr is CCodeCastExpression) { - cexpr = ((CCodeCastExpression) cexpr).inner; - } - result = new CCodeCastExpression (new CCodeCastExpression (cexpr, "guintptr"), get_ccode_name (actual_type)); - } - return result; - } - - public CCodeExpression convert_to_generic_pointer (CCodeExpression cexpr, DataType actual_type) { - unowned SemanticAnalyzer analyzer = context.analyzer; - var result = cexpr; - if (analyzer.is_signed_integer_type_argument (actual_type)) { - // FIXME this should not happen - while (cexpr is CCodeCastExpression) { - cexpr = ((CCodeCastExpression) cexpr).inner; - } - result = new CCodeCastExpression (new CCodeCastExpression (cexpr, "gintptr"), get_ccode_name (pointer_type)); - } else if (analyzer.is_unsigned_integer_type_argument (actual_type)) { - // FIXME this should not happen - while (cexpr is CCodeCastExpression) { - cexpr = ((CCodeCastExpression) cexpr).inner; - } - result = new CCodeCastExpression (new CCodeCastExpression (cexpr, "guintptr"), get_ccode_name (pointer_type)); - } - return result; - } - - int next_variant_function_id = 0; - - public TargetValue transform_value (TargetValue value, DataType? target_type, CodeNode node) { - var type = value.value_type; - var result = ((GLibValue) value).copy (); - - if (type.value_owned - && (target_type == null || target_type is GenericType || !target_type.floating_reference) - && type.floating_reference) { - /* floating reference, sink it. - */ - unowned ObjectTypeSymbol? cl = type.type_symbol as ObjectTypeSymbol; - var sink_func = (cl != null) ? get_ccode_ref_sink_function (cl) : ""; - - if (sink_func != "") { - if (type.nullable) { - var is_not_null = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, result.cvalue, new CCodeConstant ("NULL")); - ccode.open_if (is_not_null); - } - - var csink = new CCodeFunctionCall (new CCodeIdentifier (sink_func)); - csink.add_argument (result.cvalue); - ccode.add_expression (csink); - - if (type.nullable) { - ccode.close (); - } - } else { - Report.error (node.source_reference, "type `%s' does not support floating references", type.type_symbol.name); - } - } - - bool boxing = (type is ValueType && !type.nullable - && target_type is ValueType && target_type.nullable); - bool unboxing = (type is ValueType && type.nullable - && target_type is ValueType && !target_type.nullable); - - bool gvalue_boxing = (context.profile == Profile.GOBJECT - && target_type != null - && target_type.type_symbol == gvalue_type - && !(type is NullType) - && get_ccode_type_id (type) != "G_TYPE_VALUE"); - bool gvariant_boxing = (context.profile == Profile.GOBJECT - && target_type != null - && target_type.type_symbol == gvariant_type - && !(type is NullType) - && type.type_symbol != gvariant_type); - - if (type.value_owned - && (target_type == null || !target_type.value_owned || boxing || unboxing || gvariant_boxing) - && !gvalue_boxing /* gvalue can assume ownership of value, no need to free it */) { - // value leaked, destroy it - if (target_type is PointerType) { - // manual memory management for pointers - } else if (requires_destroy (type)) { - if (!is_lvalue_access_allowed (type)) { - // cannot assign to a temporary variable - temp_ref_values.insert (0, result.copy ()); - } else { - var temp_value = create_temp_value (type, false, node); - temp_ref_values.insert (0, ((GLibValue) temp_value).copy ()); - store_value (temp_value, result, node.source_reference); - result.cvalue = get_cvalue_ (temp_value); - } - } - } - - if (target_type == null) { - // value will be destroyed, no need for implicit casts - return result; - } - - result.value_type = target_type.copy (); - - if (gvalue_boxing) { - // implicit conversion to GValue - var temp_value = create_temp_value (target_type, true, node, true); - - if (!target_type.value_owned) { - // boxed GValue leaked, destroy it - temp_ref_values.insert (0, ((GLibValue) temp_value).copy ()); - } - - if (target_type.nullable) { - var newcall = new CCodeFunctionCall (new CCodeIdentifier ("g_new0")); - newcall.add_argument (new CCodeConstant ("GValue")); - newcall.add_argument (new CCodeConstant ("1")); - var newassignment = new CCodeAssignment (get_cvalue_ (temp_value), newcall); - ccode.add_expression (newassignment); - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_init")); - if (target_type.nullable) { - ccall.add_argument (get_cvalue_ (temp_value)); - } else { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue_ (temp_value))); - } - var type_id = get_ccode_type_id (type); - if (type_id == "") { - Report.error (node.source_reference, "GValue boxing of type `%s' is not supported", type.to_string ()); - } - ccall.add_argument (new CCodeIdentifier (type_id)); - ccode.add_expression (ccall); - - if (requires_destroy (type)) { - ccall = new CCodeFunctionCall (get_value_taker_function (type)); - } else { - ccall = new CCodeFunctionCall (get_value_setter_function (type)); - } - if (target_type.nullable) { - ccall.add_argument (get_cvalue_ (temp_value)); - } else { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue_ (temp_value))); - } - if (type.is_real_non_null_struct_type ()) { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, result.cvalue)); - } else { - ccall.add_argument (result.cvalue); - } - - ccode.add_expression (ccall); - - result = (GLibValue) temp_value; - } else if (gvariant_boxing) { - // implicit conversion to GVariant - string variant_func = "_variant_new%d".printf (++next_variant_function_id); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (variant_func)); - ccall.add_argument (result.cvalue); - - var cfunc = new CCodeFunction (variant_func, "GVariant*"); - cfunc.modifiers = CCodeModifiers.STATIC; - cfunc.add_parameter (new CCodeParameter ("value", get_ccode_name (type))); - - if (type is ArrayType) { - // return array length if appropriate - var array_type = (ArrayType) type; - var length_ctype = get_ccode_array_length_type (array_type); - for (int dim = 1; dim <= array_type.rank; dim++) { - ccall.add_argument (get_array_length_cvalue (value, dim)); - cfunc.add_parameter (new CCodeParameter (get_array_length_cname ("value", dim), length_ctype)); - } - } - - push_function (cfunc); - - // sink floating reference - var sink = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_ref_sink")); - sink.add_argument (serialize_expression (type, new CCodeIdentifier ("value"))); - ccode.add_return (sink); - - pop_function (); - - cfile.add_function_declaration (cfunc); - cfile.add_function (cfunc); - - result.cvalue = ccall; - result.value_type.value_owned = true; - - result = (GLibValue) store_temp_value (result, node); - if (!target_type.value_owned) { - // value leaked - temp_ref_values.insert (0, ((GLibValue) result).copy ()); - } - } else if (boxing) { - // value needs to be boxed - - result.value_type.nullable = false; - if (!result.lvalue || !result.value_type.equals (value.value_type)) { - result.cvalue = get_implicit_cast_expression (result.cvalue, value.value_type, result.value_type, node); - if (!(result.cvalue is CCodeConstantIdentifier)) { - result = (GLibValue) store_temp_value (result, node); - } - } - result.cvalue = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, result.cvalue); - result.lvalue = false; - result.value_type.nullable = true; - } else if (unboxing) { - // unbox value - - result.cvalue = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, result.cvalue); - } else { - // TODO: rewrite get_implicit_cast_expression to return a GLibValue - var old_cexpr = result.cvalue; - result.cvalue = get_implicit_cast_expression (result.cvalue, type, target_type, node); - result.lvalue = result.lvalue && result.cvalue == old_cexpr; - } - - bool array_needs_copy = false; - if (type is ArrayType && target_type is ArrayType) { - var array = (ArrayType) type; - var target_array = (ArrayType) target_type; - if (target_array.element_type.value_owned && !array.element_type.value_owned) { - array_needs_copy = requires_copy (target_array.element_type); - } - } - - if (!gvalue_boxing && !gvariant_boxing && target_type.value_owned && (!type.value_owned || boxing || unboxing || array_needs_copy) && requires_copy (target_type) && !(type is NullType)) { - // need to copy value - var copy = (GLibValue) copy_value (result, node); - if (target_type.type_symbol is Interface && copy == null) { - Report.error (node.source_reference, "missing class prerequisite for interface `%s', add GLib.Object to interface declaration if unsure", target_type.type_symbol.get_full_name ()); - return result; - } - // need to free old array after copying it - if (array_needs_copy && requires_destroy (type)) { - result.value_type = type.copy (); - ccode.add_expression (destroy_value (result)); - } - result = copy; - - // implicit array copying is deprecated, but allow it for internal codegen usage - var prop_acc = node as PropertyAccessor; - if ((prop_acc != null && !prop_acc.automatic_body) - && result.value_type is ArrayType) { - Report.deprecated (node.source_reference, "implicit copy of array is deprecated, explicitly invoke the copy method instead"); - } - } - - return result; - } - - public virtual CCodeExpression get_implicit_cast_expression (CCodeExpression source_cexpr, DataType? expression_type, DataType? target_type, CodeNode? node) { - var cexpr = source_cexpr; - - if (expression_type.type_symbol != null && expression_type.type_symbol == target_type.type_symbol) { - // same type, no cast required - return cexpr; - } - - if (expression_type is NullType) { - // null literal, no cast required when not converting to generic type pointer - return cexpr; - } - - generate_type_declaration (target_type, cfile); - - unowned Class? cl = target_type.type_symbol as Class; - unowned Interface? iface = target_type.type_symbol as Interface; - if (context.checking && (iface != null || (cl != null && !cl.is_compact))) { - // checked cast for strict subtypes of GTypeInstance - return generate_instance_cast (cexpr, target_type.type_symbol); - } else if (target_type.type_symbol != null && get_ccode_name (expression_type) != get_ccode_name (target_type)) { - unowned Struct? st = target_type.type_symbol as Struct; - if (target_type.type_symbol.is_reference_type () || (st != null && st.is_simple_type ())) { - // don't cast non-simple structs - return new CCodeCastExpression (cexpr, get_ccode_name (target_type)); - } else { - return cexpr; - } - } else { - return cexpr; - } - } - - public void store_property (Property prop, Expression? instance, TargetValue value) { - unowned Property base_prop = prop; - if (prop.base_property != null) { - base_prop = prop.base_property; - } else if (prop.base_interface_property != null) { - base_prop = prop.base_interface_property; - } - if (instance is BaseAccess && (base_prop.is_abstract || base_prop.is_virtual)) { - CCodeExpression? vcast = null; - if (base_prop.parent_symbol is Class) { - unowned Class base_class = (Class) base_prop.parent_symbol; - vcast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (base_class))); - ((CCodeFunctionCall) vcast).add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (current_class)))); - } else if (base_prop.parent_symbol is Interface) { - unowned Interface base_iface = (Interface) base_prop.parent_symbol; - vcast = get_this_interface_cexpression (base_iface); - } - if (vcast != null) { - var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "set_%s".printf (prop.name))); - ccall.add_argument ((CCodeExpression) get_ccodenode (instance)); - var cexpr = get_cvalue_ (value); - if (prop.property_type.is_real_non_null_struct_type ()) { - //TODO Make use of get_lvalue (value) - if (!(cexpr is CCodeConstant || cexpr is CCodeIdentifier)) { - var temp_value = store_temp_value (value, instance); - cexpr = get_cvalue_ (temp_value); - } - cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr); - } - ccall.add_argument (cexpr); - - ccode.add_expression (ccall); - } else { - Report.error (instance.source_reference, "internal: Invalid assignment to `%s'", base_prop.get_full_name ()); - } - return; - } - - var set_func = "g_object_set"; - - if (!get_ccode_no_accessor_method (prop) && !(prop is DynamicProperty)) { - generate_property_accessor_declaration (base_prop.set_accessor, cfile); - set_func = get_ccode_name (base_prop.set_accessor); - - if (!prop.external && prop.external_package) { - // internal VAPI properties - // only add them once per source file - if (add_generated_external_symbol (prop)) { - visit_property (prop); - } - } - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (set_func)); - - if (prop.binding == MemberBinding.INSTANCE) { - /* target instance is first argument */ - var cinstance = (CCodeExpression) get_ccodenode (instance); - - if (prop.parent_symbol is Struct && !((Struct) prop.parent_symbol).is_simple_type ()) { - // we need to pass struct instance by reference if it isn't a simple-type - var instance_value = instance.target_value; - if (!get_lvalue (instance_value)) { - instance_value = store_temp_value (instance_value, instance); - } - cinstance = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue_ (instance_value)); - } - - ccall.add_argument (cinstance); - } - - if (get_ccode_no_accessor_method (prop) || prop is DynamicProperty) { - /* property name is second argument of g_object_set */ - ccall.add_argument (get_property_canonical_cconstant (prop)); - } - - var cexpr = get_cvalue_ (value); - - if (prop.property_type.is_real_non_null_struct_type ()) { - //TODO Make use of get_lvalue (value) - if (!(cexpr is CCodeConstant || cexpr is CCodeIdentifier)) { - var temp_value = store_temp_value (value, instance); - cexpr = get_cvalue_ (temp_value); - } - cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr); - } - - var array_type = prop.property_type as ArrayType; - - ccall.add_argument (cexpr); - - if (array_type != null && get_ccode_array_length (prop)) { - for (int dim = 1; dim <= array_type.rank; dim++) { - ccall.add_argument (get_array_length_cvalue (value, dim)); - } - } else if (prop.property_type is DelegateType) { - var delegate_type = (DelegateType) prop.property_type; - if (get_ccode_delegate_target (prop) && delegate_type.delegate_symbol.has_target) { - ccall.add_argument (get_delegate_target_cvalue (value)); - if (base_prop.set_accessor.value_type.value_owned) { - ccall.add_argument (get_delegate_target_destroy_notify_cvalue (value)); - } - } - } - - if (get_ccode_no_accessor_method (prop) || prop is DynamicProperty) { - ccall.add_argument (new CCodeConstant ("NULL")); - } - - ccode.add_expression (ccall); - } - - public bool add_wrapper (string wrapper_name) { - return wrappers.add (wrapper_name); - } - - public bool add_generated_external_symbol (Symbol external_symbol) { - return generated_external_symbols.add (external_symbol); - } - - public static DataType get_callable_creturn_type (Callable c) { - assert (c is Method || c is Delegate); - var creturn_type = c.return_type.copy (); - if (c is CreationMethod) { - unowned Class? cl = c.parent_symbol as Class; - unowned Struct? st = c.parent_symbol as Struct; - if (cl != null) { - // object creation methods return the new object in C - // in Vala they have no return type - creturn_type = new ObjectType (cl); - } else if (st != null && st.is_simple_type ()) { - // constructors return simple type structs by value - creturn_type = new StructValueType (st); - } - } else if (c.return_type.is_real_non_null_struct_type ()) { - // structs are returned via out parameter - creturn_type = new VoidType (); - } - return creturn_type; - } - - public CCodeExpression? default_value_for_type (DataType type, bool initializer_expression, bool on_error = false) { - unowned Struct? st = type.type_symbol as Struct; - var array_type = type as ArrayType; - if (type.type_symbol != null && !type.nullable - && (on_error ? get_ccode_default_value_on_error (type.type_symbol) : get_ccode_default_value (type.type_symbol)) != "") { - CCodeExpression val = new CCodeConstant (on_error ? get_ccode_default_value_on_error (type.type_symbol) : get_ccode_default_value (type.type_symbol)); - if (st != null && st.get_fields ().size > 0) { - val = new CCodeCastExpression (val, get_ccode_name (st)); - } - return val; - } else if (initializer_expression && !type.nullable && - (st != null || (array_type != null && array_type.fixed_length))) { - // 0-initialize struct with struct initializer { 0 } - // only allowed as initializer expression in C - var clist = new CCodeInitializerList (); - clist.append (new CCodeConstant ("0")); - return clist; - } else if ((type.type_symbol != null && type.type_symbol.is_reference_type ()) - || type.nullable - || type is PointerType || type is DelegateType - || (array_type != null && !array_type.fixed_length)) { - return new CCodeConstant ("NULL"); - } else if (type is GenericType) { - return new CCodeConstant ("NULL"); - } else if (type is ErrorType) { - return new CCodeConstant ("NULL"); - } else if (type is CType) { - return new CCodeConstant (((CType) type).cdefault_value); - } - return null; - } - - private void create_property_type_check_statement (Property prop, bool check_return_type, TypeSymbol t, bool non_null, string var_name) { - if (check_return_type) { - create_type_check_statement (prop, prop.property_type, t, non_null, var_name); - } else { - create_type_check_statement (prop, new VoidType (), t, non_null, var_name); - } - } - - public virtual void create_type_check_statement (CodeNode method_node, DataType ret_type, TypeSymbol t, bool non_null, string var_name) { - } - - public int get_param_pos (double param_pos, bool ellipsis = false) { - if (!ellipsis) { - if (param_pos >= 0) { - return (int) (param_pos * 1000); - } else { - return (int) ((100 + param_pos) * 1000); - } - } else { - if (param_pos >= 0) { - return (int) ((100 + param_pos) * 1000); - } else { - return (int) ((200 + param_pos) * 1000); - } - } - } - - public CCodeExpression? get_ccodenode (Expression node) { - if (get_cvalue (node) == null) { - node.emit (this); - } - return get_cvalue (node); - } - - public bool is_lvalue_access_allowed (DataType type) { - var array_type = type as ArrayType; - if (array_type != null && array_type.inline_allocated) { - return false; - } - if (type.type_symbol != null) { - return type.type_symbol.get_attribute_bool ("CCode", "lvalue_access", true); - } - return true; - } - - public bool requires_memset_init (Variable variable, out CCodeExpression? size) { - unowned ArrayType? array_type = variable.variable_type as ArrayType; - if (array_type != null && array_type.fixed_length) { - var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - sizeof_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, get_ccodenode (array_type.length), sizeof_call); - return !is_constant_ccode (array_type.length); - } - size = null; - return false; - } - - public CCodeDeclaratorSuffix? get_ccode_declarator_suffix (DataType type) { - var array_type = type as ArrayType; - if (array_type != null) { - if (array_type.fixed_length) { - return new CCodeDeclaratorSuffix.with_array (get_ccodenode (array_type.length)); - } else if (array_type.inline_allocated) { - return new CCodeDeclaratorSuffix.with_array (); - } - } - return null; - } - - public CCodeConstant get_signal_canonical_constant (Signal sig, string? detail = null) { - return new CCodeConstant ("\"%s%s\"".printf (get_ccode_name (sig), (detail != null ? "::%s".printf (detail) : ""))); - } - - public CCodeConstant get_property_canonical_cconstant (Property prop) { - return new CCodeConstant ("\"%s\"".printf (get_ccode_name (prop))); - } - - public override void visit_class (Class cl) { - } - - public void create_postcondition_statement (Expression postcondition) { - var cassert = new CCodeFunctionCall (new CCodeIdentifier ("_vala_warn_if_fail")); - - postcondition.emit (this); - - string message = ((string) postcondition.source_reference.begin.pos).substring (0, (int) (postcondition.source_reference.end.pos - postcondition.source_reference.begin.pos)); - cassert.add_argument (get_cvalue (postcondition)); - cassert.add_argument (new CCodeConstant ("\"%s\"".printf (message.replace ("\n", " ").escape ("")))); - requires_assert = true; - - ccode.add_expression (cassert); - - foreach (var value in temp_ref_values) { - ccode.add_expression (destroy_value (value)); - } - - temp_ref_values.clear (); - } - - public unowned DataType? get_this_type () { - if (current_method != null && current_method.binding == MemberBinding.INSTANCE) { - return current_method.this_parameter.variable_type; - } else if (current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE) { - return current_property_accessor.prop.this_parameter.variable_type; - } else if (current_constructor != null && current_constructor.binding == MemberBinding.INSTANCE) { - return current_constructor.this_parameter.variable_type; - } else if (current_destructor != null && current_destructor.binding == MemberBinding.INSTANCE) { - return current_destructor.this_parameter.variable_type; - } - return null; - } - - public CCodeFunctionCall generate_instance_cast (CCodeExpression expr, TypeSymbol type) { - var result = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_CAST")); - result.add_argument (expr); - result.add_argument (new CCodeIdentifier (get_ccode_type_id (type))); - result.add_argument (new CCodeIdentifier (get_ccode_name (type))); - return result; - } - - void generate_struct_destroy_function (Struct st) { - if (cfile.add_declaration (get_ccode_destroy_function (st))) { - // only generate function once per source file - return; - } - - var function = new CCodeFunction (get_ccode_destroy_function (st), "void"); - function.modifiers = CCodeModifiers.STATIC; - function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (st)))); - - push_context (new EmitContext ()); - push_function (function); - - var this_value = load_this_parameter (st); - foreach (Field f in st.get_fields ()) { - if (f.binding == MemberBinding.INSTANCE) { - if ((!(f.variable_type is DelegateType) || get_ccode_delegate_target (f)) && requires_destroy (f.variable_type)) { - ccode.add_expression (destroy_field (f, this_value)); - } - } - } - - pop_function (); - pop_context (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - } - - void generate_struct_copy_function (Struct st) { - if (cfile.add_declaration (get_ccode_copy_function (st))) { - // only generate function once per source file - return; - } - - var function = new CCodeFunction (get_ccode_copy_function (st), "void"); - function.modifiers = CCodeModifiers.STATIC; - function.add_parameter (new CCodeParameter ("self", "const %s *".printf (get_ccode_name (st)))); - function.add_parameter (new CCodeParameter ("dest", "%s *".printf (get_ccode_name (st)))); - - push_context (new EmitContext ()); - push_function (function); - - var dest_struct = new GLibValue (SemanticAnalyzer.get_data_type_for_symbol (st), new CCodeIdentifier ("(*dest)"), true); - foreach (Field f in st.get_fields ()) { - if (f.binding == MemberBinding.INSTANCE) { - var value = load_field (f, load_this_parameter ((TypeSymbol) st)); - if ((!(f.variable_type is DelegateType) || get_ccode_delegate_target (f)) && requires_copy (f.variable_type)) { - value = copy_value (value, f); - if (value == null) { - // error case, continue to avoid critical - continue; - } - } - store_field (f, dest_struct, value); - } - } - - pop_function (); - pop_context (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - } - - public void return_default_value (DataType return_type, bool on_error = false) { - unowned Struct? st = return_type.type_symbol as Struct; - if (st != null && st.is_simple_type () && !return_type.nullable) { - // 0-initialize struct with struct initializer { 0 } - // only allowed as initializer expression in C - var ret_temp_var = get_temp_variable (return_type, true, null, true); - emit_temp_var (ret_temp_var, on_error); - ccode.add_return (new CCodeIdentifier (ret_temp_var.name)); - } else { - ccode.add_return (default_value_for_type (return_type, false, on_error)); - } - } - - public virtual void generate_dynamic_method_wrapper (DynamicMethod method) { - } - - public virtual CCodeExpression get_param_spec_cexpression (Property prop) { - return new CCodeInvalidExpression (); - } - - public virtual CCodeExpression get_param_spec (Property prop) { - return new CCodeInvalidExpression (); - } - - public virtual CCodeExpression get_signal_creation (Signal sig, ObjectTypeSymbol type) { - return new CCodeInvalidExpression (); - } - - public virtual CCodeExpression get_value_getter_function (DataType type_reference) { - return new CCodeInvalidExpression (); - } - - public virtual CCodeExpression get_value_setter_function (DataType type_reference) { - return new CCodeInvalidExpression (); - } - - public virtual CCodeExpression get_value_taker_function (DataType type_reference) { - return new CCodeInvalidExpression (); - } - - public virtual void register_dbus_info (CCodeBlock block, ObjectTypeSymbol bindable) { - } - - public virtual string get_dynamic_signal_cname (DynamicSignal node) { - return ""; - } - - public virtual string get_array_length_cname (string array_cname, int dim) { - return ""; - } - - public virtual string get_variable_array_length_cname (Variable variable, int dim) { - return ""; - } - - public virtual CCodeExpression get_array_length_cexpression (Expression array_expr, int dim = -1) { - return new CCodeInvalidExpression (); - } - - public virtual CCodeExpression get_array_length_cvalue (TargetValue value, int dim = -1) { - return new CCodeInvalidExpression (); - } - - public virtual string get_array_size_cname (string array_cname) { - return ""; - } - - public virtual void add_simple_check (CodeNode node, bool always_fails = false) { - } - - public virtual string generate_ready_function (Method m) { - return ""; - } - - public CCodeExpression get_boolean_cconstant (bool b) { - if (context.profile == Profile.GOBJECT) { - return new CCodeConstant (b ? "TRUE" : "FALSE"); - } else { - cfile.add_include ("stdbool.h"); - return new CCodeConstant (b ? "true" : "false"); - } - } -} diff --git a/src/codegen/valaccodecompiler.vala b/src/codegen/valaccodecompiler.vala deleted file mode 100644 index 29ac1b43c..000000000 --- a/src/codegen/valaccodecompiler.vala +++ /dev/null @@ -1,120 +0,0 @@ -/* valaccodecompiler.vala - * - * Copyright (C) 2007-2009 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Interface to the C compiler. - */ -public class Vala.CCodeCompiler { - public CCodeCompiler () { - } - - /** - * Compile generated C code to object code and optionally link object - * files. - * - * @param context a code context - */ - public void compile (CodeContext context, string? cc_command, string[] cc_options) { - string pc = ""; - if (context.profile == Profile.GOBJECT) { - pc += " gobject-2.0"; - } - foreach (string pkg in context.get_packages ()) { - if (context.pkg_config_exists (pkg)) { - pc += " " + pkg; - } - } - string? pkgflags; - if (pc.length > 0) { - pkgflags = context.pkg_config_compile_flags (pc); - if (pkgflags == null) { - return; - } - } else { - pkgflags = ""; - } - - // TODO compile the C code files in parallel - - if (cc_command == null) { - cc_command = "cc"; - } - string cmdline = cc_command; - if (context.debug) { - cmdline += " -g"; - } - if (context.compile_only) { - cmdline += " -c"; - } else if (context.output != null) { - string output = context.output; - if (context.directory != null && context.directory != "" && !Path.is_absolute (context.output)) { - output = "%s%c%s".printf (context.directory, Path.DIR_SEPARATOR, context.output); - } - cmdline += " -o " + Shell.quote (output); - } - - /* we're only interested in non-pkg source files */ - var source_files = context.get_source_files (); - foreach (SourceFile file in source_files) { - if (file.file_type == SourceFileType.SOURCE) { - cmdline += " " + Shell.quote (file.get_csource_filename ()); - } - } - var c_source_files = context.get_c_source_files (); - foreach (string file in c_source_files) { - cmdline += " " + Shell.quote (file); - } - - // add libraries after source files to fix linking - // with --as-needed and on Windows - cmdline += " " + pkgflags.strip (); - foreach (string cc_option in cc_options) { - cmdline += " " + Shell.quote (cc_option); - } - - if (context.verbose_mode) { - //stdout.printf ("%s\n", cmdline); - } - - int exit_status = 0; - try { - Process.spawn_command_line_sync (cmdline, null, null, out exit_status); - } catch (Error e) { - Report.error (null, e.message); - } - if (exit_status != 0) { - Report.error (null, "cc exited with status %d", exit_status); - } - - - /* remove generated C source and header files */ - if (!context.save_csources) { - foreach (SourceFile file in source_files) { - if (file.file_type == SourceFileType.SOURCE) { - FileUtils.unlink (file.get_csource_filename ()); - } - } - } - } -} diff --git a/src/codegen/valaccodecontrolflowmodule.vala b/src/codegen/valaccodecontrolflowmodule.vala deleted file mode 100644 index 9ecbced2f..000000000 --- a/src/codegen/valaccodecontrolflowmodule.vala +++ /dev/null @@ -1,472 +0,0 @@ -/* valaccodecontrolflowmodule.vala - * - * Copyright (C) 2006-2011 Jürg Billeter - * Copyright (C) 2006-2008 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.1 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 - * Raffaele Sandrini - */ - -using GLib; - -public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule { - public override void visit_if_statement (IfStatement stmt) { - ccode.open_if (get_cvalue (stmt.condition)); - - stmt.true_statement.emit (this); - - if (stmt.false_statement != null) { - ccode.add_else (); - stmt.false_statement.emit (this); - } - - ccode.close (); - } - - void visit_string_switch_statement (SwitchStatement stmt) { - // we need a temporary variable to save the property value - var temp_value = create_temp_value (stmt.expression.value_type, false, stmt); - var ctemp = get_cvalue_ (temp_value); - - var cinit = new CCodeAssignment (ctemp, get_cvalue (stmt.expression)); - var czero = new CCodeConstant ("0"); - - var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free")); - free_call.add_argument (ctemp); - - var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), ctemp); - var cquark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string")); - cquark.add_argument (ctemp); - - var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cquark); - - int label_temp_id = next_temp_var_id++; - - temp_value = create_temp_value (gquark_type, true, stmt); - - int label_count = 0; - - foreach (SwitchSection section in stmt.get_sections ()) { - if (section.has_default_label ()) { - continue; - } - - foreach (SwitchLabel label in section.get_labels ()) { - label.expression.emit (this); - var cexpr = get_cvalue (label.expression); - - if (is_constant_ccode_expression (cexpr)) { - var cname = "_tmp%d_label%d".printf (label_temp_id, label_count++); - - ccode.add_declaration (get_ccode_name (gquark_type), new CCodeVariableDeclarator (cname, czero), CCodeModifiers.STATIC); - } - } - } - - ccode.add_expression (cinit); - - ctemp = get_cvalue_ (temp_value); - cinit = new CCodeAssignment (ctemp, ccond); - - ccode.add_expression (cinit); - - if (stmt.expression.value_type.value_owned) { - // free owned string - ccode.add_expression (free_call); - } - - SwitchSection default_section = null; - label_count = 0; - - int n = 0; - - foreach (SwitchSection section in stmt.get_sections ()) { - if (section.has_default_label ()) { - default_section = section; - continue; - } - - CCodeBinaryExpression cor = null; - foreach (SwitchLabel label in section.get_labels ()) { - label.expression.emit (this); - var cexpr = get_cvalue (label.expression); - - if (is_constant_ccode_expression (cexpr)) { - var cname = new CCodeIdentifier ("_tmp%d_label%d".printf (label_temp_id, label_count++)); - var ccondition = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, czero, cname); - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); - cinit = new CCodeAssignment (cname, ccall); - - ccall.add_argument (cexpr); - - cexpr = new CCodeConditionalExpression (ccondition, cname, cinit); - } else { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string")); - ccall.add_argument (cexpr); - cexpr = ccall; - } - - var ccmp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, cexpr); - - if (cor == null) { - cor = ccmp; - } else { - cor = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cor, ccmp); - } - } - - if (n > 0) { - ccode.else_if (cor); - } else { - ccode.open_if (cor); - } - - ccode.open_switch (new CCodeConstant ("0")); - ccode.add_default (); - - section.emit (this); - - ccode.close (); - - n++; - } - - if (default_section != null) { - if (n > 0) { - ccode.add_else (); - } - - ccode.open_switch (new CCodeConstant ("0")); - ccode.add_default (); - - default_section.emit (this); - - ccode.close (); - } - - if (n > 0) { - ccode.close (); - } - } - - public override void visit_switch_statement (SwitchStatement stmt) { - if (stmt.expression.value_type.compatible (string_type)) { - visit_string_switch_statement (stmt); - return; - } - - ccode.open_switch (get_cvalue (stmt.expression)); - - bool has_default = false; - - foreach (SwitchSection section in stmt.get_sections ()) { - if (section.has_default_label ()) { - ccode.add_default (); - has_default = true; - } - section.emit (this); - } - - if (!has_default) { - // silence C compiler - ccode.add_default (); - ccode.add_break (); - } - - ccode.close (); - } - - public override void visit_switch_label (SwitchLabel label) { - if (((SwitchStatement) label.section.parent_node).expression.value_type.compatible (string_type)) { - return; - } - - if (label.expression != null) { - label.expression.emit (this); - - visit_end_full_expression (label.expression); - - ccode.add_case (get_cvalue (label.expression)); - } - } - - public override void visit_loop_statement (LoopStatement stmt) { - if (context.profile == Profile.GOBJECT) { - ccode.open_while (new CCodeConstant ("TRUE")); - } else { - cfile.add_include ("stdbool.h"); - ccode.open_while (new CCodeConstant ("true")); - } - - stmt.body.emit (this); - - ccode.close (); - } - - public override void visit_foreach_statement (ForeachStatement stmt) { - ccode.open_block (); - - var collection_backup = stmt.collection_variable; - var collection_type = collection_backup.variable_type; - - var array_type = collection_type as ArrayType; - if (array_type != null) { - // avoid assignment issues - array_type.inline_allocated = false; - array_type.fixed_length = false; - } - - visit_local_variable (collection_backup); - ccode.add_assignment (get_variable_cexpression (get_local_cname (collection_backup)), get_cvalue (stmt.collection)); - - if (stmt.tree_can_fail && stmt.collection.tree_can_fail) { - // exception handling - add_simple_check (stmt.collection); - } - - if (stmt.collection.value_type is ArrayType) { - array_type = (ArrayType) stmt.collection.value_type; - - var array_len = get_variable_cexpression (get_array_length_cname (get_local_cname (collection_backup), 1)); - - // store array length for use by _vala_array_free - ccode.add_assignment (array_len, get_array_length_cexpression (stmt.collection)); - - var iterator_variable = new LocalVariable (array_type.length_type.copy (), stmt.variable_name + "_it"); - visit_local_variable (iterator_variable); - var it_name = get_local_cname (iterator_variable); - - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (it_name), array_len); - - ccode.open_for (new CCodeAssignment (get_variable_cexpression (it_name), new CCodeConstant ("0")), - ccond, - new CCodeAssignment (get_variable_cexpression (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (it_name), new CCodeConstant ("1")))); - - CCodeExpression element_expr = new CCodeElementAccess (get_variable_cexpression (get_local_cname (collection_backup)), get_variable_cexpression (it_name)); - - var element_type = array_type.element_type.copy (); - element_type.value_owned = false; - element_expr = get_cvalue_ (transform_value (new GLibValue (element_type, element_expr, true), stmt.type_reference, stmt)); - - visit_local_variable (stmt.element_variable); - ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr); - - // set array length for stacked arrays - if (stmt.type_reference is ArrayType) { - var inner_array_type = (ArrayType) stmt.type_reference; - for (int dim = 1; dim <= inner_array_type.rank; dim++) { - ccode.add_assignment (get_variable_cexpression (get_array_length_cname (get_local_cname (stmt.element_variable), dim)), new CCodeConstant ("-1")); - } - } - - stmt.body.emit (this); - - ccode.close (); - } else if (stmt.collection.value_type.compatible (new ObjectType (garray_type))) { - // iterating over a GArray - - var iterator_variable = new LocalVariable (uint_type.copy (), "%s_index".printf (stmt.variable_name)); - visit_local_variable (iterator_variable); - var arr_index = get_variable_cname (get_local_cname (iterator_variable)); - - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (arr_index), new CCodeMemberAccess.pointer (get_variable_cexpression (get_local_cname (collection_backup)), "len")); - - ccode.open_for (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeConstant ("0")), - ccond, - new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (arr_index), new CCodeConstant ("1")))); - - var get_item = new CCodeFunctionCall (new CCodeIdentifier ("g_array_index")); - get_item.add_argument (get_variable_cexpression (get_local_cname (collection_backup))); - get_item.add_argument (new CCodeIdentifier (get_ccode_name (stmt.type_reference))); - get_item.add_argument (get_variable_cexpression (arr_index)); - - if (collection_type.get_type_arguments ().size != 1) { - Report.error (stmt.source_reference, "internal error: missing generic type argument"); - stmt.error = true; - return; - } - - var element_type = collection_type.get_type_arguments ().get (0).copy (); - element_type.value_owned = false; - var element_expr = get_cvalue_ (transform_value (new GLibValue (element_type, get_item, true), stmt.type_reference, stmt)); - - visit_local_variable (stmt.element_variable); - ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr); - - stmt.body.emit (this); - - ccode.close (); - } else if (stmt.collection.value_type.compatible (new ObjectType (glist_type)) || stmt.collection.value_type.compatible (new ObjectType (gslist_type))) { - // iterating over a GList or GSList - - var iterator_variable = new LocalVariable (collection_type.copy (), stmt.variable_name + "_it"); - visit_local_variable (iterator_variable); - var it_name = get_local_cname (iterator_variable); - - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (it_name), new CCodeConstant ("NULL")); - - ccode.open_for (new CCodeAssignment (get_variable_cexpression (it_name), get_variable_cexpression (get_local_cname (collection_backup))), - ccond, - new CCodeAssignment (get_variable_cexpression (it_name), new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "next"))); - - CCodeExpression element_expr = new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "data"); - - if (collection_type.get_type_arguments ().size != 1) { - Report.error (stmt.source_reference, "internal error: missing generic type argument"); - stmt.error = true; - return; - } - - var element_data_type = collection_type.get_type_arguments ().get (0).copy (); - element_data_type.value_owned = false; - element_expr = convert_from_generic_pointer (element_expr, element_data_type); - element_expr = get_cvalue_ (transform_value (new GLibValue (element_data_type, element_expr), stmt.type_reference, stmt)); - - visit_local_variable (stmt.element_variable); - ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr); - - stmt.body.emit (this); - - ccode.close (); - } else if (stmt.collection.value_type.compatible (new ObjectType ((Class) genericarray_type))) { - // iterating over a GenericArray / GPtrArray - - var iterator_variable = new LocalVariable (uint_type.copy (), "%s_index".printf (stmt.variable_name)); - visit_local_variable (iterator_variable); - var arr_index = get_variable_cname (get_local_cname (iterator_variable)); - - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (arr_index), new CCodeMemberAccess.pointer (get_variable_cexpression (get_local_cname (collection_backup)), "len")); - - ccode.open_for (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeConstant ("0")), - ccond, - new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (arr_index), new CCodeConstant ("1")))); - - var get_item = new CCodeFunctionCall (new CCodeIdentifier ("g_ptr_array_index")); - get_item.add_argument (get_variable_cexpression (get_local_cname (collection_backup))); - get_item.add_argument (get_variable_cexpression (arr_index)); - - CCodeExpression element_expr = get_item; - - if (stmt.type_reference.value_owned) { - element_expr = get_cvalue_ (copy_value (new GLibValue (stmt.type_reference, element_expr), stmt.element_variable)); - } - - visit_local_variable (stmt.element_variable); - ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr); - - stmt.body.emit (this); - - ccode.close (); - } else if (stmt.collection.value_type.compatible (new ObjectType (gvaluearray_type))) { - // iterating over a GValueArray - - var iterator_variable = new LocalVariable (uint_type.copy (), "%s_index".printf (stmt.variable_name)); - visit_local_variable (iterator_variable); - var arr_index = get_variable_cname (get_local_cname (iterator_variable)); - - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (arr_index), new CCodeMemberAccess.pointer (get_variable_cexpression (get_local_cname (collection_backup)), "n_values")); - - ccode.open_for (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeConstant ("0")), - ccond, - new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (arr_index), new CCodeConstant ("1")))); - - var get_item = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_get_nth")); - get_item.add_argument (get_variable_cexpression (get_local_cname (collection_backup))); - get_item.add_argument (get_variable_cexpression (arr_index)); - - CCodeExpression element_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_item); - - if (stmt.type_reference.value_owned) { - element_expr = get_cvalue_ (copy_value (new GLibValue (stmt.type_reference, element_expr), new StructValueType (gvalue_type))); - } - - visit_local_variable (stmt.element_variable); - ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr); - - stmt.body.emit (this); - - ccode.close (); - } else if (stmt.collection.value_type.compatible (new ObjectType (gsequence_type))) { - // iterating over a GSequence - - var iterator_variable = new LocalVariable (new ObjectType (gsequence_iter_type), "%s_iter".printf (stmt.variable_name)); - visit_local_variable (iterator_variable); - var sequence_iter = get_variable_cname (get_local_cname (iterator_variable)); - - var ccond_is_end = new CCodeFunctionCall (new CCodeIdentifier ("g_sequence_iter_is_end")); - ccond_is_end.add_argument (get_variable_cexpression (sequence_iter)); - var ccond = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, ccond_is_end); - var cbegin = new CCodeFunctionCall (new CCodeIdentifier ("g_sequence_get_begin_iter")); - cbegin.add_argument (get_variable_cexpression (get_local_cname (collection_backup))); - var cnext = new CCodeFunctionCall (new CCodeIdentifier ("g_sequence_iter_next")); - cnext.add_argument (get_variable_cexpression (sequence_iter)); - - ccode.open_for (new CCodeAssignment (get_variable_cexpression (sequence_iter), cbegin), - ccond, - new CCodeAssignment (get_variable_cexpression (sequence_iter), cnext)); - - var get_item = new CCodeFunctionCall (new CCodeIdentifier ("g_sequence_get")); - get_item.add_argument (get_variable_cexpression (sequence_iter)); - - CCodeExpression element_expr = get_item; - - if (collection_type.get_type_arguments ().size != 1) { - Report.error (stmt.source_reference, "internal error: missing generic type argument"); - stmt.error = true; - return; - } - - var element_type = collection_type.get_type_arguments ().get (0).copy (); - element_type.value_owned = false; - element_expr = convert_from_generic_pointer (element_expr, element_type); - element_expr = get_cvalue_ (transform_value (new GLibValue (element_type, element_expr), stmt.type_reference, stmt)); - - visit_local_variable (stmt.element_variable); - ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr); - - stmt.body.emit (this); - - ccode.close (); - } else { - Report.error (stmt.source_reference, "internal error: unsupported collection type"); - stmt.error = true; - return; - } - - foreach (LocalVariable local in stmt.get_local_variables ()) { - if (requires_destroy (local.variable_type)) { - ccode.add_expression (destroy_local (local)); - } - } - - ccode.close (); - } - - public override void visit_break_statement (BreakStatement stmt) { - append_local_free (current_symbol, stmt); - - ccode.add_break (); - } - - public override void visit_continue_statement (ContinueStatement stmt) { - append_local_free (current_symbol, stmt); - - ccode.add_continue (); - } -} - diff --git a/src/codegen/valaccodedelegatemodule.vala b/src/codegen/valaccodedelegatemodule.vala deleted file mode 100644 index 64ad460c3..000000000 --- a/src/codegen/valaccodedelegatemodule.vala +++ /dev/null @@ -1,511 +0,0 @@ -/* valaccodedelegatemodule.vala - * - * Copyright (C) 2006-2010 Jürg Billeter - * Copyright (C) 2006-2008 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.1 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 - * Raffaele Sandrini - */ - - -/** - * The link between an assignment and generated code. - */ -public class Vala.CCodeDelegateModule : CCodeArrayModule { - public override void generate_delegate_declaration (Delegate d, CCodeFile decl_space) { - if (add_symbol_declaration (decl_space, d, get_ccode_name (d))) { - return; - } - - // internally generated delegates don't require a typedef - if (d.sender_type != null) { - return; - } - - var creturn_type = get_callable_creturn_type (d); - if (creturn_type is DelegateType && ((DelegateType) creturn_type).delegate_symbol == d) { - // recursive delegate - creturn_type = new DelegateType ((Delegate) context.root.scope.lookup ("GLib").scope.lookup ("Callback")); - } - - generate_type_declaration (creturn_type, decl_space); - - var cparam_map = new HashMap (direct_hash, direct_equal); - - var cfundecl = new CCodeFunctionDeclarator (get_ccode_name (d)); - foreach (Parameter param in d.get_parameters ()) { - generate_parameter (param, decl_space, cparam_map, null); - } - - // FIXME partial code duplication with CCodeMethodModule.generate_cparameters - - if (d.return_type.is_real_non_null_struct_type ()) { - // structs are returned via out parameter - var cparam = new CCodeParameter ("result", get_ccode_name (d.return_type) + "*"); - cparam_map.set (get_param_pos (-3), cparam); - } else if (get_ccode_array_length (d) && d.return_type is ArrayType) { - // return array length if appropriate - var array_type = (ArrayType) d.return_type; - var length_ctype = get_ccode_array_length_type (d) + "*"; - - for (int dim = 1; dim <= array_type.rank; dim++) { - var cparam = new CCodeParameter (get_array_length_cname ("result", dim), length_ctype); - cparam_map.set (get_param_pos (get_ccode_array_length_pos (d) + 0.01 * dim), cparam); - } - } else if (get_ccode_delegate_target (d) && d.return_type is DelegateType) { - // return delegate target if appropriate - var deleg_type = (DelegateType) d.return_type; - if (deleg_type.delegate_symbol.has_target) { - generate_type_declaration (delegate_target_type, decl_space); - var cparam = new CCodeParameter (get_delegate_target_cname ("result"), get_ccode_name (delegate_target_type) + "*"); - cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (d)), cparam); - if (deleg_type.is_disposable ()) { - generate_type_declaration (delegate_target_destroy_type, decl_space); - cparam = new CCodeParameter (get_delegate_target_destroy_notify_cname ("result"), get_ccode_name (delegate_target_destroy_type) + "*"); - cparam_map.set (get_param_pos (get_ccode_destroy_notify_pos (d)), cparam); - } - } - } - - if (d.has_target) { - generate_type_declaration (delegate_target_type, decl_space); - var cparam = new CCodeParameter ("user_data", get_ccode_name (delegate_target_type)); - cparam_map.set (get_param_pos (get_ccode_instance_pos (d)), cparam); - } - if (d.tree_can_fail) { - generate_type_declaration (gerror_type, decl_space); - var cparam = new CCodeParameter ("error", "GError**"); - cparam_map.set (get_param_pos (get_ccode_error_pos (d)), cparam); - } - - // append C parameters in the right order - int last_pos = -1; - int min_pos; - while (true) { - min_pos = -1; - foreach (int pos in cparam_map.get_keys ()) { - if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { - min_pos = pos; - } - } - if (min_pos == -1) { - break; - } - cfundecl.add_parameter (cparam_map.get (min_pos)); - last_pos = min_pos; - } - - var ctypedef = new CCodeTypeDefinition (get_ccode_name (creturn_type), cfundecl); - - if (d.version.deprecated) { - if (context.profile == Profile.GOBJECT) { - decl_space.add_include ("glib.h"); - } - ctypedef.modifiers |= CCodeModifiers.DEPRECATED; - } - - decl_space.add_type_declaration (ctypedef); - } - - public override void visit_delegate (Delegate d) { - generate_delegate_declaration (d, cfile); - - if (!d.is_internal_symbol ()) { - generate_delegate_declaration (d, header_file); - } - if (!d.is_private_symbol ()) { - generate_delegate_declaration (d, internal_header_file); - } - - d.accept_children (this); - } - - public override string get_delegate_target_cname (string delegate_cname) { - return "%s_target".printf (delegate_cname); - } - - public override CCodeExpression get_delegate_target_cexpression (Expression delegate_expr, out CCodeExpression delegate_target_destroy_notify) { - delegate_target_destroy_notify = get_delegate_target_destroy_notify_cvalue (delegate_expr.target_value); - return get_delegate_target_cvalue (delegate_expr.target_value); - } - - public override CCodeExpression get_delegate_target_cvalue (TargetValue value) { - return ((GLibValue) value).delegate_target_cvalue; - } - - public override CCodeExpression get_delegate_target_destroy_notify_cvalue (TargetValue value) { - return ((GLibValue) value).delegate_target_destroy_notify_cvalue; - } - - public override string get_delegate_target_destroy_notify_cname (string delegate_cname) { - return "%s_target_destroy_notify".printf (delegate_cname); - } - - public override CCodeExpression get_implicit_cast_expression (CCodeExpression source_cexpr, DataType? expression_type, DataType? target_type, CodeNode? node) { - if (target_type is DelegateType && expression_type is MethodType) { - var dt = (DelegateType) target_type; - var mt = (MethodType) expression_type; - - var method = mt.method_symbol; - if (method.base_method != null) { - method = method.base_method; - } else if (method.base_interface_method != null) { - method = method.base_interface_method; - } - - if (method.is_variadic ()) { - Report.warning (node.source_reference, "internal: Variadic method requires a direct cast to delegate"); - } else { - return new CCodeIdentifier (generate_delegate_wrapper (method, dt, node)); - } - } - - return base.get_implicit_cast_expression (source_cexpr, expression_type, target_type, node); - } - - public string generate_delegate_wrapper (Method m, DelegateType dt, CodeNode? node) { - var d = dt.delegate_symbol; - string delegate_name; - var sig = d.parent_symbol as Signal; - var dynamic_sig = sig as DynamicSignal; - if (dynamic_sig != null) { - delegate_name = get_dynamic_signal_cname (dynamic_sig); - } else if (sig != null) { - delegate_name = get_ccode_lower_case_prefix (sig.parent_symbol) + get_ccode_lower_case_name (sig); - } else { - delegate_name = Symbol.camel_case_to_lower_case (get_ccode_name (d)); - } - - string wrapper_name = "_%s_%s".printf (get_ccode_name (m), delegate_name); - - if (!add_wrapper (wrapper_name)) { - // wrapper already defined - return wrapper_name; - } - - // declaration - var creturn_type = get_callable_creturn_type (d); - - var function = new CCodeFunction (wrapper_name, get_ccode_name (creturn_type)); - function.modifiers = CCodeModifiers.STATIC; - - push_function (function); - - var cparam_map = new HashMap (direct_hash, direct_equal); - - if (d.has_target) { - var cparam = new CCodeParameter ("self", get_ccode_name (delegate_target_type)); - cparam_map.set (get_param_pos (get_ccode_instance_pos (d)), cparam); - } - - if (d.sender_type != null) { - var param = new Parameter ("_sender", d.sender_type); - generate_parameter (param, cfile, cparam_map, null); - } - - var d_params = d.get_parameters (); - foreach (Parameter param in d_params) { - if (dynamic_sig != null - && param.variable_type is ArrayType - && ((ArrayType) param.variable_type).element_type.type_symbol == string_type.type_symbol) { - // use null-terminated string arrays for dynamic signals for compatibility reasons - param.set_attribute_bool ("CCode", "array_length", false); - param.set_attribute_bool ("CCode", "array_null_terminated", true); - } - - generate_parameter (param, cfile, cparam_map, null); - } - if (get_ccode_array_length (d) && d.return_type is ArrayType) { - // return array length if appropriate - var array_type = (ArrayType) d.return_type; - var length_ctype = get_ccode_array_length_type (d) + "*"; - - for (int dim = 1; dim <= array_type.rank; dim++) { - var cparam = new CCodeParameter (get_array_length_cname ("result", dim), length_ctype); - cparam_map.set (get_param_pos (get_ccode_array_length_pos (d) + 0.01 * dim), cparam); - } - } else if (d.return_type is DelegateType) { - // return delegate target if appropriate - var deleg_type = (DelegateType) d.return_type; - - if (get_ccode_delegate_target (d) && deleg_type.delegate_symbol.has_target) { - var cparam = new CCodeParameter (get_delegate_target_cname ("result"), get_ccode_name (delegate_target_type) + "*"); - cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (d)), cparam); - if (deleg_type.is_disposable ()) { - cparam = new CCodeParameter (get_delegate_target_destroy_notify_cname ("result"), get_ccode_name (delegate_target_destroy_type) + "*"); - cparam_map.set (get_param_pos (get_ccode_destroy_notify_pos (d)), cparam); - } - } - } else if (d.return_type.is_real_non_null_struct_type ()) { - var cparam = new CCodeParameter ("result", "%s*".printf (get_ccode_name (d.return_type))); - cparam_map.set (get_param_pos (-3), cparam); - } - - if (m.tree_can_fail) { - var cparam = new CCodeParameter ("error", "GError**"); - cparam_map.set (get_param_pos (get_ccode_error_pos (d)), cparam); - } - - // append C parameters in the right order - int last_pos = -1; - int min_pos; - while (true) { - min_pos = -1; - foreach (int pos in cparam_map.get_keys ()) { - if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { - min_pos = pos; - } - } - if (min_pos == -1) { - break; - } - function.add_parameter (cparam_map.get (min_pos)); - last_pos = min_pos; - } - - - // definition - - var carg_map = new HashMap (direct_hash, direct_equal); - - int i = 0; - if (m.binding == MemberBinding.INSTANCE || m.closure) { - CCodeExpression arg; - if (d.has_target) { - arg = new CCodeIdentifier ("self"); - if (!m.closure && m.this_parameter != null) { - arg = convert_from_generic_pointer (arg, m.this_parameter.variable_type); - } - } else { - // use first delegate parameter as instance - if (d_params.size == 0 || m.closure) { - Report.error (node != null ? node.source_reference : null, "internal: Cannot create delegate wrapper"); - arg = new CCodeInvalidExpression (); - } else { - arg = new CCodeIdentifier (get_ccode_name (d_params.get (0))); - i = 1; - } - } - carg_map.set (get_param_pos (get_ccode_instance_pos (m)), arg); - } - - bool first = true; - - foreach (Parameter param in m.get_parameters ()) { - if (first && d.sender_type != null && m.get_parameters ().size == d.get_parameters ().size + 1) { - // sender parameter - carg_map.set (get_param_pos (get_ccode_pos (param)), new CCodeIdentifier ("_sender")); - - first = false; - continue; - } - - CCodeExpression arg; - arg = new CCodeIdentifier (get_ccode_name (d_params.get (i))); - if (d_params.get (i).variable_type is GenericType) { - arg = convert_from_generic_pointer (arg, param.variable_type); - } - carg_map.set (get_param_pos (get_ccode_pos (param)), arg); - - // handle array arguments - if (get_ccode_array_length (param) && param.variable_type is ArrayType) { - var array_type = (ArrayType) param.variable_type; - for (int dim = 1; dim <= array_type.rank; dim++) { - CCodeExpression clength; - if (get_ccode_array_null_terminated (d_params.get (i))) { - requires_array_length = true; - var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length")); - len_call.add_argument (new CCodeIdentifier (d_params.get (i).name)); - clength = len_call; - } else if (!get_ccode_array_length (d_params.get (i))) { - clength = new CCodeConstant ("-1"); - } else { - clength = new CCodeIdentifier (get_variable_array_length_cname (d_params.get (i), dim)); - } - carg_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), clength); - } - } else if (get_ccode_delegate_target (param) && param.variable_type is DelegateType) { - var deleg_type = (DelegateType) param.variable_type; - - if (deleg_type.delegate_symbol.has_target) { - var ctarget = new CCodeIdentifier (get_ccode_delegate_target_name (d_params.get (i))); - carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), ctarget); - if (deleg_type.is_disposable ()) { - var ctarget_destroy_notify = new CCodeIdentifier (get_ccode_delegate_target_destroy_notify_name (d_params.get (i))); - carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (m)), ctarget_destroy_notify); - } - } - } - - i++; - } - if (get_ccode_array_length (m) && m.return_type is ArrayType) { - var array_type = (ArrayType) m.return_type; - for (int dim = 1; dim <= array_type.rank; dim++) { - CCodeExpression clength; - if (!get_ccode_array_length (d)) { - clength = new CCodeConstant ("NULL"); - } else { - clength = new CCodeIdentifier (get_array_length_cname ("result", dim)); - } - carg_map.set (get_param_pos (get_ccode_array_length_pos (m) + 0.01 * dim), clength); - } - } else if (get_ccode_delegate_target (m) && m.return_type is DelegateType) { - var deleg_type = (DelegateType) m.return_type; - - if (deleg_type.delegate_symbol.has_target) { - var ctarget = new CCodeIdentifier (get_delegate_target_cname ("result")); - carg_map.set (get_param_pos (get_ccode_delegate_target_pos (m)), ctarget); - if (deleg_type.is_disposable ()) { - var ctarget_destroy_notify = new CCodeIdentifier (get_delegate_target_destroy_notify_cname ("result")); - carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (m)), ctarget_destroy_notify); - } - } - } else if (m.return_type.is_real_non_null_struct_type ()) { - carg_map.set (get_param_pos (-3), new CCodeIdentifier ("result")); - } - - if (m.tree_can_fail) { - carg_map.set (get_param_pos (get_ccode_error_pos (m)), new CCodeIdentifier ("error")); - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m))); - - // append C arguments in the right order - last_pos = -1; - while (true) { - min_pos = -1; - foreach (int pos in carg_map.get_keys ()) { - if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { - min_pos = pos; - } - } - if (min_pos == -1) { - break; - } - ccall.add_argument (carg_map.get (min_pos)); - last_pos = min_pos; - } - - if (m.coroutine) { - ccall.add_argument (new CCodeConstant ("NULL")); - ccall.add_argument (new CCodeConstant ("NULL")); - } - - if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) { - ccode.add_expression (ccall); - if (!(d.return_type is VoidType || d.return_type.is_real_non_null_struct_type ())) { - // return a default value - ccode.add_declaration (get_ccode_name (creturn_type), new CCodeVariableDeclarator ("result", default_value_for_type (d.return_type, true))); - } - } else { - CCodeExpression result = ccall; - if (d.return_type is GenericType) { - result = convert_to_generic_pointer (result, m.return_type); - } - ccode.add_declaration (get_ccode_name (creturn_type), new CCodeVariableDeclarator ("result", result)); - } - - if (d.has_target /* TODO: && dt.value_owned */ && dt.is_called_once) { - // destroy notify "self" after the call - CCodeExpression? destroy_notify = null; - if (m.closure) { - int block_id = get_block_id (current_closure_block); - destroy_notify = new CCodeIdentifier ("block%d_data_unref".printf (block_id)); - } else if (get_this_type () != null && m.binding != MemberBinding.STATIC && !m.is_async_callback && is_reference_counting (m.this_parameter.variable_type.type_symbol)) { - destroy_notify = get_destroy_func_expression (m.this_parameter.variable_type); - } - - if (destroy_notify != null) { - var unref_call = new CCodeFunctionCall (destroy_notify); - unref_call.add_argument (new CCodeIdentifier ("self")); - ccode.add_expression (unref_call); - } - } - - if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) || - !(d.return_type is VoidType || d.return_type.is_real_non_null_struct_type ())) { - ccode.add_return (new CCodeIdentifier ("result")); - } - - pop_function (); - - // append to file - cfile.add_function_declaration (function); - cfile.add_function (function); - - return wrapper_name; - } - - public override CCodeParameter generate_parameter (Parameter param, CCodeFile decl_space, Map cparam_map, Map? carg_map) { - if (!(param.variable_type is DelegateType || param.variable_type is MethodType)) { - return base.generate_parameter (param, decl_space, cparam_map, carg_map); - } - - var param_type = param.variable_type; - if (param_type is DelegateType && ((DelegateType) param_type).delegate_symbol == param.parent_symbol) { - // recursive delegate - param_type = new DelegateType ((Delegate) context.root.scope.lookup ("GLib").scope.lookup ("Callback")); - } - - generate_type_declaration (param_type, decl_space); - - string ctypename = get_ccode_name (param_type); - string target_ctypename = get_ccode_name (delegate_target_type); - string target_destroy_notify_ctypename = get_ccode_name (delegate_target_destroy_type); - - if (param.direction != ParameterDirection.IN) { - ctypename += "*"; - target_ctypename += "*"; - target_destroy_notify_ctypename += "*"; - } - - var main_cparam = new CCodeParameter (get_ccode_name (param), ctypename); - - cparam_map.set (get_param_pos (get_ccode_pos (param)), main_cparam); - if (carg_map != null) { - carg_map.set (get_param_pos (get_ccode_pos (param)), get_parameter_cexpression (param)); - } - - if (param_type is DelegateType) { - unowned DelegateType deleg_type = (DelegateType) param_type; - if (get_ccode_delegate_target (param) && deleg_type.delegate_symbol.has_target) { - var cparam = new CCodeParameter (get_ccode_delegate_target_name (param), target_ctypename); - cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), cparam); - if (carg_map != null) { - carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), get_cexpression (cparam.name)); - } - if (deleg_type.is_disposable ()) { - cparam = new CCodeParameter (get_ccode_delegate_target_destroy_notify_name (param), target_destroy_notify_ctypename); - cparam_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), cparam); - if (carg_map != null) { - carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), get_cexpression (cparam.name)); - } - } - } - } else if (param_type is MethodType) { - var cparam = new CCodeParameter (get_ccode_delegate_target_name (param), target_ctypename); - cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), cparam); - if (carg_map != null) { - carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), get_cexpression (cparam.name)); - } - } - - return main_cparam; - } -} diff --git a/src/codegen/valaccodememberaccessmodule.vala b/src/codegen/valaccodememberaccessmodule.vala deleted file mode 100644 index 6f01e8a0b..000000000 --- a/src/codegen/valaccodememberaccessmodule.vala +++ /dev/null @@ -1,822 +0,0 @@ -/* valaccodememberaccessmodule.vala - * - * Copyright (C) 2006-2010 Jürg Billeter - * Copyright (C) 2006-2008 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.1 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 - * Raffaele Sandrini - */ - -public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { - public override void visit_member_access (MemberAccess expr) { - CCodeExpression pub_inst = null; - - if (expr.inner != null) { - pub_inst = get_cvalue (expr.inner); - } - - var array_type = expr.value_type as ArrayType; - var delegate_type = expr.value_type as DelegateType; - - if (expr.symbol_reference is Method) { - var m = (Method) expr.symbol_reference; - - if (!(m is DynamicMethod || m is ArrayMoveMethod || m is ArrayResizeMethod || m is ArrayCopyMethod)) { - generate_method_declaration (m, cfile); - - if (!m.external && m.external_package) { - // internal VAPI methods - // only add them once per source file - if (add_generated_external_symbol (m)) { - visit_method (m); - } - } - } - - if (expr.inner is BaseAccess) { - CCodeExpression? vcast = null; - if (m.base_method != null) { - unowned Class base_class = (Class) m.base_method.parent_symbol; - vcast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (base_class))); - ((CCodeFunctionCall) vcast).add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (current_class)))); - } else if (m.base_interface_method != null) { - unowned Interface base_iface = (Interface) m.base_interface_method.parent_symbol; - vcast = get_this_interface_cexpression (base_iface); - } - if (vcast != null) { - set_cvalue (expr, new CCodeMemberAccess.pointer (vcast, get_ccode_vfunc_name (m))); - return; - } - } - - if (m.base_method != null) { - if (get_ccode_no_wrapper (m.base_method)) { - unowned Class base_class = (Class) m.base_method.parent_symbol; - if (!base_class.is_compact) { - var vclass = get_this_class_cexpression (base_class, expr.inner.target_value); - set_cvalue (expr, new CCodeMemberAccess.pointer (vclass, get_ccode_vfunc_name (m))); - } else { - set_cvalue (expr, new CCodeMemberAccess.pointer (pub_inst, get_ccode_vfunc_name (m))); - } - } else { - set_cvalue (expr, new CCodeIdentifier (get_ccode_name (m.base_method))); - } - } else if (m.base_interface_method != null) { - if (get_ccode_no_wrapper (m.base_interface_method)) { - unowned Interface base_iface = (Interface) m.base_interface_method.parent_symbol; - var vclass = get_this_interface_cexpression (base_iface, expr.inner.target_value); - set_cvalue (expr, new CCodeMemberAccess.pointer (vclass, get_ccode_vfunc_name (m))); - } else { - set_cvalue (expr, new CCodeIdentifier (get_ccode_name (m.base_interface_method))); - } - } else if (m is CreationMethod) { - set_cvalue (expr, new CCodeIdentifier (get_ccode_real_name (m))); - } else { - set_cvalue (expr, new CCodeIdentifier (get_ccode_name (m))); - } - - set_delegate_target_destroy_notify (expr, new CCodeConstant ("NULL")); - if (m.binding == MemberBinding.STATIC) { - set_delegate_target (expr, new CCodeConstant ("NULL")); - } else if (m.is_async_callback) { - if (current_method.closure) { - var block = ((Method) m.parent_symbol).body; - set_delegate_target (expr, new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), "_async_data_")); - } else { - set_delegate_target (expr, new CCodeIdentifier ("_data_")); - } - } else if (expr.inner != null && !expr.prototype_access) { - // expr.inner is null in the special case of referencing the method in a constant initializer - var delegate_target = (CCodeExpression) get_ccodenode (expr.inner); - delegate_type = expr.target_type as DelegateType; - if ((expr.value_type.value_owned || (delegate_type != null && delegate_type.is_called_once)) && expr.inner.value_type.type_symbol != null && is_reference_counting (expr.inner.value_type.type_symbol)) { - var ref_call = new CCodeFunctionCall (get_dup_func_expression (expr.inner.value_type, expr.source_reference)); - ref_call.add_argument (delegate_target); - delegate_target = ref_call; - set_delegate_target_destroy_notify (expr, get_destroy_func_expression (expr.inner.value_type)); - } - set_delegate_target (expr, delegate_target); - } - } else if (expr.symbol_reference is ArrayLengthField) { - set_cvalue (expr, get_array_length_cexpression (expr.inner, 1)); - } else if (expr.symbol_reference is DelegateTargetField) { - CCodeExpression delegate_target_destroy_notify; - set_cvalue (expr, get_delegate_target_cexpression (expr.inner, out delegate_target_destroy_notify) ?? new CCodeConstant ("NULL")); - } else if (expr.symbol_reference is DelegateDestroyField) { - CCodeExpression delegate_target_destroy_notify; - get_delegate_target_cexpression (expr.inner, out delegate_target_destroy_notify); - set_cvalue (expr, delegate_target_destroy_notify ?? new CCodeConstant ("NULL")); - } else if (expr.symbol_reference is GenericDupField) { - set_cvalue (expr, get_dup_func_expression (expr.inner.value_type, expr.source_reference)); - } else if (expr.symbol_reference is GenericDestroyField) { - set_cvalue (expr, get_destroy_func_expression (expr.inner.value_type)); - } else if (expr.symbol_reference is Field) { - var field = (Field) expr.symbol_reference; - if (expr.lvalue) { - expr.target_value = get_field_cvalue (field, expr.inner != null ? expr.inner.target_value : null); - } else { - expr.target_value = load_field (field, expr.inner != null ? expr.inner.target_value : null, expr); - } - } else if (expr.symbol_reference is EnumValue) { - var ev = (EnumValue) expr.symbol_reference; - - generate_enum_declaration ((Enum) ev.parent_symbol, cfile); - - set_cvalue (expr, new CCodeConstant (get_ccode_name (ev))); - } else if (expr.symbol_reference is Constant) { - var c = (Constant) expr.symbol_reference; - - generate_constant_declaration (c, cfile, - c.source_reference != null && expr.source_reference != null && - c.source_reference.file == expr.source_reference.file); - - string fn = c.get_full_name (); - if (fn == "GLib.Log.FILE") { - string s = Path.get_basename (expr.source_reference.file.filename); - set_cvalue (expr, new CCodeConstant ("\"%s\"".printf (s))); - } else if (fn == "GLib.Log.LINE") { - int i = expr.source_reference.begin.line; - set_cvalue (expr, new CCodeConstant ("%d".printf (i))); - } else if (fn == "GLib.Log.METHOD") { - string s = ""; - if (current_method != null) { - s = current_method.get_full_name (); - } - set_cvalue (expr, new CCodeConstant ("\"%s\"".printf (s))); - } else if (c.type_reference.is_non_null_simple_type ()) { - set_cvalue (expr, new CCodeConstant (get_ccode_name (c))); - } else { - set_cvalue (expr, new CCodeConstantIdentifier (get_ccode_name (c))); - } - - if (array_type != null) { - string sub = ""; - for (int i = 0; i < array_type.rank; i++) { - CCodeFunctionCall ccall; - if (context.profile == Profile.POSIX) { - requires_array_n_elements = true; - ccall = new CCodeFunctionCall (new CCodeIdentifier ("VALA_N_ELEMENTS")); - } else { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_N_ELEMENTS")); - } - ccall.add_argument (new CCodeIdentifier (get_ccode_name (c) + sub)); - append_array_length (expr, ccall); - sub += "[0]"; - } - ((GLibValue) expr.target_value).non_null = true; - } - } else if (expr.symbol_reference is Property) { - var prop = (Property) expr.symbol_reference; - - if (!(prop is DynamicProperty)) { - generate_property_accessor_declaration (prop.get_accessor, cfile); - - if (!prop.external && prop.external_package) { - // internal VAPI properties - // only add them once per source file - if (add_generated_external_symbol (prop)) { - visit_property (prop); - } - } - } - - if (pub_inst == null && prop.binding == MemberBinding.INSTANCE) { - // FIXME Report this with proper source-reference on the vala side! - Report.error (prop.source_reference, "Invalid access to instance member `%s'", prop.get_full_name ()); - set_cvalue (expr, new CCodeInvalidExpression ()); - return; - } - - unowned Property base_prop = prop; - if (prop.base_property != null) { - base_prop = prop.base_property; - } else if (prop.base_interface_property != null) { - base_prop = prop.base_interface_property; - } - if (expr.inner is BaseAccess && (base_prop.is_abstract || base_prop.is_virtual)) { - CCodeExpression? vcast = null; - if (base_prop.parent_symbol is Class) { - unowned Class base_class = (Class) base_prop.parent_symbol; - vcast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (base_class))); - ((CCodeFunctionCall) vcast).add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (current_class)))); - } else if (base_prop.parent_symbol is Interface) { - unowned Interface base_iface = (Interface) base_prop.parent_symbol; - vcast = get_this_interface_cexpression (base_iface); - } - if (vcast != null) { - var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "get_%s".printf (prop.name))); - ccall.add_argument (get_cvalue (expr.inner)); - if (prop.property_type.is_real_non_null_struct_type ()) { - var temp_value = (GLibValue) create_temp_value (prop.get_accessor.value_type, false, expr); - expr.target_value = load_temp_value (temp_value); - var ctemp = get_cvalue_ (temp_value); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp)); - ccode.add_expression (ccall); - } else { - set_cvalue (expr, ccall); - } - } else { - Report.error (expr.source_reference, "internal: Invalid access to `%s'", base_prop.get_full_name ()); - } - } else if (prop.binding == MemberBinding.INSTANCE && - prop.get_accessor.automatic_body && - !prop.get_accessor.value_type.value_owned && - current_type_symbol == prop.parent_symbol && - current_type_symbol is Class && - prop.base_property == null && - prop.base_interface_property == null && - !(prop.property_type is ArrayType || prop.property_type is DelegateType)) { - CCodeExpression inst = pub_inst; - if (!((Class) current_type_symbol).is_compact) { - inst = new CCodeMemberAccess.pointer (inst, "priv"); - } - set_cvalue (expr, new CCodeMemberAccess.pointer (inst, get_ccode_name (prop.field))); - } else if (!get_ccode_no_accessor_method (prop) && !(prop is DynamicProperty)) { - var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.get_accessor))); - - if (prop.binding == MemberBinding.INSTANCE) { - if (prop.parent_symbol is Struct && !((Struct) prop.parent_symbol).is_simple_type ()) { - // we need to pass struct instance by reference - var instance = expr.inner.target_value; - if (!get_lvalue (instance)) { - instance = store_temp_value (instance, expr); - } - pub_inst = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue_ (instance)); - } - - ccall.add_argument (pub_inst); - } - - bool prop_is_real_non_null_struct_type = prop.property_type.is_real_non_null_struct_type (); - bool requires_init = prop.property_type is DelegateType || prop_is_real_non_null_struct_type; - var temp_value = (GLibValue) create_temp_value (prop.get_accessor.value_type, requires_init, expr); - expr.target_value = load_temp_value (temp_value); - var ctemp = get_cvalue_ (temp_value); - - // Property access to real struct types is handled differently - // The value is returned by out parameter - if (prop_is_real_non_null_struct_type) { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp)); - ccode.add_expression (ccall); - } else { - array_type = prop.property_type as ArrayType; - if (array_type != null) { - if (get_ccode_array_null_terminated (prop)) { - requires_array_length = true; - var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length")); - len_call.add_argument (ctemp); - - ccode.add_assignment (ctemp, ccall); - ccode.add_assignment (temp_value.array_length_cvalues[0], len_call); - } else if (get_ccode_array_length (prop)) { - var temp_refs = new ArrayList (); - for (int dim = 1; dim <= array_type.rank; dim++) { - var length_ctype = get_ccode_array_length_type (prop); - var temp_var = get_temp_variable (new CType (length_ctype, "0"), true, null, true); - var temp_ref = get_variable_cexpression (temp_var.name); - emit_temp_var (temp_var); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref)); - temp_refs.add (temp_ref); - } - - ccode.add_assignment (ctemp, ccall); - for (int dim = 1; dim <= array_type.rank; dim++) { - ccode.add_assignment (temp_value.array_length_cvalues[dim - 1], temp_refs.get (dim - 1)); - } - } else { - ccode.add_assignment (ctemp, ccall); - } - } else { - ccode.add_assignment (ctemp, ccall); - - delegate_type = prop.property_type as DelegateType; - if (delegate_type != null && get_ccode_delegate_target (prop) && delegate_type.delegate_symbol.has_target) { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_delegate_target_cvalue (temp_value))); - } else { - if (temp_value.delegate_target_cvalue != null) { - ccode.add_assignment (temp_value.delegate_target_cvalue, new CCodeConstant ("NULL")); - } - if (temp_value.delegate_target_destroy_notify_cvalue != null) { - ccode.add_assignment (temp_value.delegate_target_destroy_notify_cvalue, new CCodeConstant ("NULL")); - } - } - } - } - } else { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_get")); - ccall.add_argument (pub_inst); - - // property name is second argument of g_object_get - ccall.add_argument (get_property_canonical_cconstant (prop)); - - // g_object_get always returns owned values - // therefore, property getters of properties - // without accessor methods need to be marked as owned - if (!(prop is DynamicProperty) && !prop.get_accessor.value_type.value_owned) { - // only report error for types where there actually - // is a difference between `owned' and `unowned' - var owned_value_type = prop.get_accessor.value_type.copy (); - owned_value_type.value_owned = true; - if (requires_copy (owned_value_type)) { - Report.error (prop.get_accessor.source_reference, "unowned return value for getter of property `%s' not supported without accessor", prop.get_full_name ()); - } - } - - if (expr.value_type.is_real_struct_type ()) { - // gobject allocates structs on heap - expr.value_type.nullable = true; - } - - var temp_var = get_temp_variable (expr.value_type); - var ctemp = get_variable_cexpression (temp_var.name); - emit_temp_var (temp_var); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp)); - ccall.add_argument (new CCodeConstant ("NULL")); - ccode.add_expression (ccall); - set_cvalue (expr, ctemp); - } - - if (prop.get_accessor.value_type is GenericType) { - expr.target_value.value_type = prop.get_accessor.value_type.copy (); - } else { - expr.target_value.value_type = expr.value_type.copy (); - } - expr.target_value = store_temp_value (expr.target_value, expr); - } else if (expr.symbol_reference is LocalVariable) { - var local = (LocalVariable) expr.symbol_reference; - - if (expr.parent_node is ReturnStatement && - current_return_type.value_owned && - local.variable_type.value_owned && - !local.captured && - !variable_accessible_in_finally (local) && - !(local.variable_type is ArrayType && ((ArrayType) local.variable_type).inline_allocated)) { - /* return expression is local variable taking ownership and - * current method is transferring ownership */ - - // don't ref expression - expr.value_type.value_owned = true; - - // don't unref variable - local.active = false; - - var glib_value = (GLibValue) get_local_cvalue (local); - expr.target_value = glib_value; - if (glib_value.delegate_target_cvalue == null) { - glib_value.delegate_target_cvalue = new CCodeConstant ("NULL"); - } - if (glib_value.delegate_target_destroy_notify_cvalue == null) { - glib_value.delegate_target_destroy_notify_cvalue = new CCodeConstant ("NULL"); - } - } else { - if (expr.lvalue) { - expr.target_value = get_local_cvalue (local); - } else { - expr.target_value = load_local (local, expr); - } - } - } else if (expr.symbol_reference is Parameter) { - var param = (Parameter) expr.symbol_reference; - if (expr.lvalue) { - expr.target_value = get_parameter_cvalue (param); - } else { - expr.target_value = load_parameter (param, expr); - } - } - - // Add cast for narrowed type access of variables if needed - if (expr.symbol_reference is Variable) { - unowned GLibValue cvalue = (GLibValue) expr.target_value; - if (!(cvalue.value_type is GenericType) && cvalue.value_type.type_symbol != null - && cvalue.value_type.type_symbol != expr.value_type.type_symbol) { - cvalue.cvalue = new CCodeCastExpression (cvalue.cvalue, get_ccode_name (expr.value_type)); - } - } - } - - /* Returns lvalue access to the given local variable */ - public override TargetValue get_local_cvalue (LocalVariable local) { - var result = new GLibValue (local.variable_type.copy ()); - result.lvalue = true; - - var array_type = local.variable_type as ArrayType; - var delegate_type = local.variable_type as DelegateType; - if (local.is_result) { - // used in postconditions - // structs are returned as out parameter - if (local.variable_type != null && local.variable_type.is_real_non_null_struct_type ()) { - result.cvalue = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result")); - } else { - result.cvalue = new CCodeIdentifier ("result"); - } - if (array_type != null && !array_type.fixed_length && ((current_method != null && get_ccode_array_length (current_method)) || current_property_accessor != null)) { - for (int dim = 1; dim <= array_type.rank; dim++) { - result.append_array_length_cvalue (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (get_array_length_cname ("result", dim)))); - } - } - } else if (local.captured) { - // captured variables are stored on the heap - var block = (Block) local.parent_symbol; - result.cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_local_cname (local)); - if (array_type != null && !array_type.fixed_length) { - for (int dim = 1; dim <= array_type.rank; dim++) { - result.append_array_length_cvalue (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_array_length_cname (get_local_cname (local), dim))); - } - if (array_type.rank == 1) { - result.array_size_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_array_size_cname (get_local_cname (local))); - } - } else if (delegate_type != null && delegate_type.delegate_symbol.has_target) { - result.delegate_target_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_cname (get_local_cname (local))); - if (delegate_type.is_disposable ()) { - result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_destroy_notify_cname (get_local_cname (local))); - } - } - } else { - result.cvalue = get_local_cexpression (local); - if (array_type != null && !array_type.fixed_length) { - for (int dim = 1; dim <= array_type.rank; dim++) { - result.append_array_length_cvalue (get_variable_cexpression (get_array_length_cname (get_local_cname (local), dim))); - } - if (array_type.rank == 1) { - result.array_size_cvalue = get_variable_cexpression (get_array_size_cname (get_local_cname (local))); - } - } else if (delegate_type != null && delegate_type.delegate_symbol.has_target) { - if (is_in_coroutine ()) { - result.delegate_target_cvalue = get_variable_cexpression (get_delegate_target_cname (get_local_cname (local))); - if (local.variable_type.is_disposable ()) { - result.delegate_target_destroy_notify_cvalue = get_variable_cexpression (get_delegate_target_destroy_notify_cname (get_local_cname (local))); - } - } else { - result.delegate_target_cvalue = new CCodeIdentifier (get_delegate_target_cname (get_local_cname (local))); - if (local.variable_type.is_disposable ()) { - result.delegate_target_destroy_notify_cvalue = new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_local_cname (local))); - } - } - } - } - - return result; - } - - /* Returns access values to the given parameter */ - public override TargetValue get_parameter_cvalue (Parameter param) { - var result = new GLibValue (param.variable_type.copy ()); - result.lvalue = true; - result.array_null_terminated = get_ccode_array_null_terminated (param); - if (get_ccode_array_length_expr (param) != null) { - result.array_length_cexpr = new CCodeConstant (get_ccode_array_length_expr (param)); - } - result.ctype = get_ccode_type (param); - - var array_type = result.value_type as ArrayType; - var delegate_type = result.value_type as DelegateType; - - bool is_unowned_delegate = delegate_type != null && !param.variable_type.value_owned; - if ((param.captured || is_in_coroutine ()) && !is_unowned_delegate) { - result.value_type.value_owned = true; - } - - if (param.name == "this") { - if (is_in_coroutine ()) { - // use closure - result.cvalue = get_this_cexpression (); - } else { - unowned Struct? st = result.value_type.type_symbol as Struct; - if (st != null && !st.is_simple_type ()) { - result.cvalue = new CCodeIdentifier ("(*self)"); - } else { - result.cvalue = new CCodeIdentifier ("self"); - } - } - } else { - string name = get_ccode_name (param); - - if (param.captured && !is_in_method_precondition) { - // captured variables are stored on the heap - var block = param.parent_symbol as Block; - if (block == null) { - block = ((Method) param.parent_symbol).body; - } - result.cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_ccode_name (param)); - if (array_type != null && get_ccode_array_length (param)) { - for (int dim = 1; dim <= array_type.rank; dim++) { - result.append_array_length_cvalue (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_variable_array_length_cname (param, dim))); - } - } else if (delegate_type != null && delegate_type.delegate_symbol.has_target) { - result.delegate_target_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_ccode_delegate_target_name (param)); - if (result.value_type.is_disposable ()) { - result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_ccode_delegate_target_destroy_notify_name (param)); - } - } - } else if (is_in_coroutine ()) { - // use closure - result.cvalue = get_parameter_cexpression (param); - if (delegate_type != null && delegate_type.delegate_symbol.has_target) { - result.delegate_target_cvalue = get_variable_cexpression (get_ccode_delegate_target_name (param)); - if (delegate_type.is_disposable ()) { - result.delegate_target_destroy_notify_cvalue = get_variable_cexpression (get_ccode_delegate_target_destroy_notify_name (param)); - } - } - } else { - unowned Struct? type_as_struct = result.value_type.type_symbol as Struct; - - if (param.direction == ParameterDirection.OUT) { - name = "_vala_%s".printf (name); - } - - if (param.direction == ParameterDirection.REF || - (param.direction == ParameterDirection.IN && type_as_struct != null && !type_as_struct.is_simple_type () && !result.value_type.nullable)) { - result.cvalue = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (name)); - } else { - result.cvalue = get_variable_cexpression (name); - } - if (get_ccode_delegate_target (param) && delegate_type != null && delegate_type.delegate_symbol.has_target) { - var target_cname = get_ccode_delegate_target_name (param); - var destroy_cname = get_ccode_delegate_target_destroy_notify_name (param); - if (param.direction == ParameterDirection.OUT) { - target_cname = "_vala_%s".printf (target_cname); - destroy_cname = "_vala_%s".printf (destroy_cname); - } - CCodeExpression target_expr = new CCodeIdentifier (target_cname); - CCodeExpression delegate_target_destroy_notify = new CCodeIdentifier (destroy_cname); - if (param.direction == ParameterDirection.REF) { - // accessing argument of ref param - target_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_expr); - delegate_target_destroy_notify = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, delegate_target_destroy_notify); - } - result.delegate_target_cvalue = target_expr; - if (result.value_type.is_disposable ()) { - result.delegate_target_destroy_notify_cvalue = delegate_target_destroy_notify; - } - } - } - if (!param.captured && array_type != null) { - if (get_ccode_array_length (param) && !get_ccode_array_null_terminated (param)) { - for (int dim = 1; dim <= array_type.rank; dim++) { - CCodeExpression length_expr = get_cexpression (get_variable_array_length_cname (param, dim)); - if (param.direction == ParameterDirection.OUT) { - length_expr = get_cexpression (get_array_length_cname (name, dim)); - } else if (param.direction == ParameterDirection.REF) { - // accessing argument of ref param - length_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, length_expr); - } - result.append_array_length_cvalue (length_expr); - } - } - } - } - - return result; - } - - /* Returns lvalue access to the given field */ - public override TargetValue get_field_cvalue (Field field, TargetValue? instance) { - var value_type = field.variable_type.copy (); - - var result = new GLibValue (value_type); - if (instance != null) { - result.actual_value_type = field.variable_type.get_actual_type (instance.value_type, null, field); - } - result.lvalue = true; - result.array_null_terminated = get_ccode_array_null_terminated (field); - if (get_ccode_array_length_expr (field) != null) { - result.array_length_cexpr = new CCodeConstant (get_ccode_array_length_expr (field)); - } - result.ctype = get_ccode_type (field); - - var array_type = result.value_type as ArrayType; - if (field.binding == MemberBinding.INSTANCE) { - CCodeExpression pub_inst = null; - - if (instance != null) { - pub_inst = get_cvalue_ (instance); - } - - var instance_target_type = SemanticAnalyzer.get_data_type_for_symbol (field.parent_symbol); - - unowned Class? cl = instance_target_type.type_symbol as Class; - bool is_gtypeinstance = ((instance_target_type.type_symbol == cl) && (cl == null || !cl.is_compact)); - - CCodeExpression inst; - if (is_gtypeinstance && field.access == SymbolAccessibility.PRIVATE) { - inst = new CCodeMemberAccess.pointer (pub_inst, "priv"); - } else { - if (cl != null) { - generate_class_struct_declaration (cl, cfile); - } - inst = pub_inst; - } - - if (inst == null) { - // FIXME Report this with proper source-reference on the vala side! - Report.error (field.source_reference, "Invalid access to instance member `%s'", field.get_full_name ()); - result.cvalue = new CCodeInvalidExpression (); - return result; - } - - if (instance_target_type.type_symbol.is_reference_type () || (instance != null && instance.value_type is PointerType)) { - result.cvalue = new CCodeMemberAccess.pointer (inst, get_ccode_name (field)); - } else { - result.cvalue = new CCodeMemberAccess (inst, get_ccode_name (field)); - } - - if (array_type != null && get_ccode_array_length (field)) { - for (int dim = 1; dim <= array_type.rank; dim++) { - CCodeExpression length_expr = null; - string length_cname = get_variable_array_length_cname (field, dim); - - if (((TypeSymbol) field.parent_symbol).is_reference_type ()) { - length_expr = new CCodeMemberAccess.pointer (inst, length_cname); - } else { - length_expr = new CCodeMemberAccess (inst, length_cname); - } - - result.append_array_length_cvalue (length_expr); - } - if (array_type.rank == 1 && field.is_internal_symbol ()) { - string size_cname = get_array_size_cname (get_ccode_name (field)); - - if (((TypeSymbol) field.parent_symbol).is_reference_type ()) { - set_array_size_cvalue (result, new CCodeMemberAccess.pointer (inst, size_cname)); - } else { - set_array_size_cvalue (result, new CCodeMemberAccess (inst, size_cname)); - } - } - } else if (get_ccode_delegate_target (field)) { - string target_cname = get_ccode_delegate_target_name (field); - string target_destroy_notify_cname = get_ccode_delegate_target_destroy_notify_name (field); - - if (((TypeSymbol) field.parent_symbol).is_reference_type ()) { - result.delegate_target_cvalue = new CCodeMemberAccess.pointer (inst, target_cname); - if (result.value_type.is_disposable ()){ - result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess.pointer (inst, target_destroy_notify_cname); - } - } else { - result.delegate_target_cvalue = new CCodeMemberAccess (inst, target_cname); - if (result.value_type.is_disposable ()) { - result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess (inst, target_destroy_notify_cname); - } - } - } - } else if (field.binding == MemberBinding.CLASS) { - unowned Class cl = (Class) field.parent_symbol; - var cast = get_this_class_cexpression (cl, instance); - if (field.access == SymbolAccessibility.PRIVATE) { - var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_get_private_function (cl))); - ccall.add_argument (cast); - result.cvalue = new CCodeMemberAccess.pointer (ccall, get_ccode_name (field)); - } else { - result.cvalue = new CCodeMemberAccess.pointer (cast, get_ccode_name (field)); - } - - } else { - generate_field_declaration (field, cfile); - - result.cvalue = new CCodeIdentifier (get_ccode_name (field)); - - if (array_type != null && get_ccode_array_length (field)) { - for (int dim = 1; dim <= array_type.rank; dim++) { - string length_cname = get_variable_array_length_cname (field, dim); - result.append_array_length_cvalue (new CCodeIdentifier (length_cname)); - } - if (array_type.rank == 1 && field.is_internal_symbol ()) { - set_array_size_cvalue (result, new CCodeIdentifier (get_array_size_cname (get_ccode_name (field)))); - } - } else if (get_ccode_delegate_target (field)) { - result.delegate_target_cvalue = new CCodeIdentifier (get_ccode_delegate_target_name (field)); - if (result.value_type.is_disposable ()) { - result.delegate_target_destroy_notify_cvalue = new CCodeIdentifier (get_ccode_delegate_target_destroy_notify_name (field)); - } - } - } - - return result; - } - - public override TargetValue load_variable (Variable variable, TargetValue value, Expression? expr = null) { - var result = (GLibValue) value; - var array_type = result.value_type as ArrayType; - var delegate_type = result.value_type as DelegateType; - if (array_type != null) { - if (array_type.fixed_length) { - result.array_length_cvalues = null; - result.append_array_length_cvalue (get_ccodenode (array_type.length)); - result.lvalue = false; - } else if (get_ccode_array_null_terminated (variable)) { - requires_array_length = true; - var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length")); - len_call.add_argument (result.cvalue); - - result.array_length_cvalues = null; - result.append_array_length_cvalue (len_call); - result.lvalue = false; - } else if (get_ccode_array_length_expr (variable) != null) { - var length_expr = new CCodeConstant (get_ccode_array_length_expr (variable)); - - result.array_length_cvalues = null; - result.append_array_length_cvalue (length_expr); - result.lvalue = false; - } else if (!get_ccode_array_length (variable)) { - result.array_length_cvalues = null; - for (int dim = 1; dim <= array_type.rank; dim++) { - result.append_array_length_cvalue (new CCodeConstant ("-1")); - } - result.lvalue = false; - } else if (get_ccode_array_length_type (variable.variable_type) != get_ccode_array_length_type (array_type)) { - for (int dim = 1; dim <= array_type.rank; dim++) { - // cast if variable does not use int for array length - result.array_length_cvalues[dim - 1] = new CCodeCastExpression (result.array_length_cvalues[dim - 1], get_ccode_array_length_type (array_type)); - } - result.lvalue = false; - } - result.array_size_cvalue = null; - result.non_null = array_type.inline_allocated; - } else if (delegate_type != null) { - if (!get_ccode_delegate_target (variable)) { - result.delegate_target_cvalue = new CCodeConstant ("NULL"); - result.delegate_target_destroy_notify_cvalue = new CCodeConstant ("NULL"); - } - - result.lvalue = false; - } - result.value_type.value_owned = false; - - bool use_temp = true; - if (!is_lvalue_access_allowed (result.value_type)) { - // special handling for types such as va_list - use_temp = false; - } - if (variable is Parameter) { - var param = (Parameter) variable; - if (variable.name == "this") { - use_temp = false; - } else if ((param.direction != ParameterDirection.OUT) - && !(param.variable_type.is_real_non_null_struct_type ())) { - use_temp = false; - } - } - if (variable.single_assignment && !result.value_type.is_real_non_null_struct_type ()) { - // no need to copy values from variables that are assigned exactly once - // as there is no risk of modification - // except for structs that are always passed by reference - use_temp = false; - } - if (result.value_type.is_non_null_simple_type ()) { - // no need to an extra copy of variables that are stack allocated simple types - use_temp = false; - } - // our implementation of postfix-expressions require temporary variables - if (expr is MemberAccess && ((MemberAccess) expr).tainted_access) { - use_temp = true; - } - - var local = variable as LocalVariable; - if (local != null && local.name[0] == '.') { - // already a temporary variable generated internally - // and safe to access without temporary variable - use_temp = false; - } - - if (use_temp) { - result = (GLibValue) store_temp_value (result, variable); - } - - return result; - } - - /* Returns unowned access to the given local variable */ - public override TargetValue load_local (LocalVariable local, Expression? expr = null) { - return load_variable (local, get_local_cvalue (local), expr); - } - - /* Returns unowned access to the given parameter */ - public override TargetValue load_parameter (Parameter param, Expression? expr = null) { - return load_variable (param, get_parameter_cvalue (param), expr); - } - - /* Convenience method returning access to "this" */ - public override TargetValue load_this_parameter (TypeSymbol sym) { - var param = new Parameter ("this", SemanticAnalyzer.get_data_type_for_symbol (sym)); - return load_parameter (param); - } - - /* Returns unowned access to the given field */ - public override TargetValue load_field (Field field, TargetValue? instance, Expression? expr = null) { - return load_variable (field, get_field_cvalue (field, instance), expr); - } -} diff --git a/src/codegen/valaccodemethodcallmodule.vala b/src/codegen/valaccodemethodcallmodule.vala deleted file mode 100644 index 6332271ad..000000000 --- a/src/codegen/valaccodemethodcallmodule.vala +++ /dev/null @@ -1,1154 +0,0 @@ -/* valaccodemethodcallmodule.vala - * - * Copyright (C) 2006-2010 Jürg Billeter - * Copyright (C) 2006-2008 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.1 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 - * Raffaele Sandrini - */ - -using GLib; - -public class Vala.CCodeMethodCallModule : CCodeAssignmentModule { - public override void visit_method_call (MethodCall expr) { - // the bare function call - var ccall = new CCodeFunctionCall (get_cvalue (expr.call)); - - CCodeFunctionCall async_call = null; - CCodeFunctionCall finish_call = null; - - Method m = null; - Delegate deleg = null; - List params; - - var ma = expr.call as MemberAccess; - - var itype = expr.call.value_type; - params = itype.get_parameters (); - - if (itype is MethodType) { - assert (ma != null); - m = ((MethodType) itype).method_symbol; - - if (!get_ccode_simple_generics (m)) { - context.analyzer.check_type_arguments (ma); - } - - if (ma.inner != null && ma.inner.value_type is EnumValueType && ((EnumValueType) ma.inner.value_type).get_to_string_method() == m) { - // Enum.VALUE.to_string() - unowned Enum en = (Enum) ma.inner.value_type.type_symbol; - ccall.call = new CCodeIdentifier (generate_enum_to_string_function (en)); - } else if (context.profile == Profile.POSIX && ma.inner != null && ma.inner.value_type != null && ma.inner.value_type.type_symbol == string_type.type_symbol && ma.member_name == "printf") { - ccall.call = new CCodeIdentifier (generate_string_printf_function ()); - } else if (expr.is_constructv_chainup) { - ccall.call = new CCodeIdentifier (get_ccode_constructv_name ((CreationMethod) m)); - } - } else if (itype is SignalType) { - var sig_type = (SignalType) itype; - if (ma != null && ma.inner is BaseAccess && sig_type.signal_symbol.is_virtual) { - m = sig_type.signal_symbol.default_handler; - } else { - ccall = (CCodeFunctionCall) get_cvalue (expr.call); - } - } else if (itype is ObjectType) { - // constructor - var cl = (Class) ((ObjectType) itype).type_symbol; - m = cl.default_construction_method; - generate_method_declaration (m, cfile); - var real_name = get_ccode_real_name (m); - if (expr.is_constructv_chainup) { - real_name = get_ccode_constructv_name ((CreationMethod) m); - } - ccall = new CCodeFunctionCall (new CCodeIdentifier (real_name)); - } else if (itype is StructValueType) { - // constructor - var st = (Struct) ((StructValueType) itype).type_symbol; - m = st.default_construction_method; - generate_method_declaration (m, cfile); - ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_real_name (m))); - } else if (itype is DelegateType) { - deleg = ((DelegateType) itype).delegate_symbol; - } - - var in_arg_map = new HashMap (direct_hash, direct_equal); - var out_arg_map = in_arg_map; - - if (m != null && m.coroutine) { - // async call - - async_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m))); - finish_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_name (m))); - - if (ma.inner is BaseAccess) { - CCodeExpression? vcast = null; - if (m.base_method != null) { - unowned Class base_class = (Class) m.base_method.parent_symbol; - vcast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (base_class))); - ((CCodeFunctionCall) vcast).add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (current_class)))); - } else if (m.base_interface_method != null) { - unowned Interface base_iface = (Interface) m.base_interface_method.parent_symbol; - vcast = get_this_interface_cexpression (base_iface); - } - if (vcast != null) { - async_call.call = new CCodeMemberAccess.pointer (vcast, get_ccode_vfunc_name (m)); - finish_call.call = new CCodeMemberAccess.pointer (vcast, get_ccode_finish_vfunc_name (m)); - } - } else if (m != null && get_ccode_no_wrapper (m) && m.binding == MemberBinding.INSTANCE && !(m is CreationMethod)) { - var instance_value = ma.inner.target_value; - if ((ma.member_name == "begin" || ma.member_name == "end") && ma.inner.symbol_reference == ma.symbol_reference) { - var inner_ma = (MemberAccess) ma.inner; - instance_value = inner_ma.inner.target_value; - } - - CCodeExpression? vcast = null; - if (m.parent_symbol is Class) { - unowned Class base_class = (Class) m.parent_symbol; - vcast = get_this_class_cexpression (base_class, instance_value); - } else if (m.parent_symbol is Interface) { - unowned Interface base_iface = (Interface) m.parent_symbol; - vcast = get_this_interface_cexpression (base_iface, instance_value); - } - if (vcast != null) { - async_call.call = new CCodeMemberAccess.pointer (vcast, get_ccode_vfunc_name (m)); - finish_call.call = new CCodeMemberAccess.pointer (vcast, get_ccode_finish_vfunc_name (m)); - } - } - - if (ma.member_name == "begin" && ma.inner.symbol_reference == ma.symbol_reference) { - // no finish call - ccall = async_call; - params = m.get_async_begin_parameters (); - } else if (ma.member_name == "end" && ma.inner.symbol_reference == ma.symbol_reference) { - // no async call - ccall = finish_call; - params = m.get_async_end_parameters (); - } else if (!expr.is_yield_expression) { - // same as .begin, backwards compatible to bindings without async methods - ccall = async_call; - params = m.get_async_begin_parameters (); - } else { - ccall = finish_call; - // output arguments used separately - out_arg_map = new HashMap (direct_hash, direct_equal); - // pass GAsyncResult stored in closure to finish function - out_arg_map.set (get_param_pos (get_ccode_async_result_pos (m)), get_variable_cexpression ("_res_")); - } - } - - if (m is CreationMethod && m.parent_symbol is Class) { - if (context.profile == Profile.GOBJECT) { - if (!((Class) m.parent_symbol).is_compact) { - ccall.add_argument (get_variable_cexpression ("object_type")); - } - } else { - ccall.add_argument (get_this_cexpression ()); - } - - if (!current_class.is_compact) { - int type_param_index = 0; - if (current_class != m.parent_symbol) { - // chain up to base class - foreach (DataType base_type in current_class.get_base_types ()) { - if (base_type.type_symbol is Class) { - List type_parameters = null; - if (get_ccode_real_name (m) == "g_object_new") { - // gobject-style chainup - type_parameters = ((Class) base_type.type_symbol).get_type_parameters (); - type_param_index += type_parameters.size; - } - add_generic_type_arguments (m, in_arg_map, base_type.get_type_arguments (), expr, true, type_parameters); - break; - } - } - } else { - // chain up to other constructor in same class - var cl = (Class) m.parent_symbol; - foreach (TypeParameter type_param in cl.get_type_parameters ()) { - in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeIdentifier (get_ccode_type_id (type_param))); - in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeIdentifier (get_ccode_copy_function (type_param))); - in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeIdentifier (get_ccode_destroy_function (type_param))); - type_param_index++; - } - } - if (current_class.has_type_parameters () && get_ccode_real_name (m) == "g_object_new") { - // gobject-style construction - foreach (var type_param in current_class.get_type_parameters ()) { - var type_param_name = type_param.name.ascii_down ().replace ("_", "-"); - in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeConstant ("\"%s-type\"".printf (type_param_name))); - in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeIdentifier (get_ccode_type_id (type_param))); - in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeConstant ("\"%s-dup-func\"".printf (type_param_name))); - in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.04), new CCodeIdentifier (get_ccode_copy_function (type_param))); - in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.05), new CCodeConstant ("\"%s-destroy-func\"".printf (type_param_name))); - in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.06), new CCodeIdentifier (get_ccode_destroy_function (type_param))); - type_param_index++; - } - } - } else if (current_class.is_subtype_of (gsource_type)) { - // g_source_new - - string class_prefix = get_ccode_lower_case_name (current_class); - string prepare_func = "NULL"; - string check_func = "NULL"; - foreach (Method impl in current_class.get_methods ()) { - if (!impl.overrides) { - continue; - } - switch (impl.name) { - case "prepare": - prepare_func = "%s_real_prepare".printf (class_prefix); - break; - case "check": - check_func = "%s_real_check".printf (class_prefix); - break; - default: - break; - } - } - - var funcs = new CCodeDeclaration ("const GSourceFuncs"); - funcs.modifiers = CCodeModifiers.STATIC; - funcs.add_declarator (new CCodeVariableDeclarator ("_source_funcs", new CCodeConstant ("{ %s, %s, %s_real_dispatch, %s_finalize}".printf (prepare_func, check_func, class_prefix, class_prefix)))); - ccode.add_statement (funcs); - - ccall.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_source_funcs")), "GSourceFuncs *")); - - var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - csizeof.add_argument (new CCodeIdentifier (get_ccode_name (current_class))); - ccall.add_argument (csizeof); - } else if (current_class.base_class != null && get_ccode_simple_generics (m)) { - if (current_class != m.parent_symbol) { - foreach (DataType base_type in current_class.get_base_types ()) { - if (base_type.type_symbol is Class) { - add_generic_type_arguments (m, in_arg_map, base_type.get_type_arguments (), expr); - break; - } - } - } else { - // TODO: simple generics are only supported in bindings. - } - } - } else if (m is CreationMethod && m.parent_symbol is Struct) { - ccall.add_argument (get_this_cexpression ()); - } else if (m != null && m.has_type_parameters () && !get_ccode_has_generic_type_parameter (m) && !get_ccode_simple_generics (m) && (ccall != finish_call || expr.is_yield_expression)) { - // generic method - // don't add generic arguments for .end() calls - add_generic_type_arguments (m, in_arg_map, ma.get_type_arguments (), expr); - } - - // the complete call expression, might include casts, comma expressions, and/or assignments - CCodeExpression ccall_expr = ccall; - - if (m is ArrayResizeMethod && context.profile != Profile.POSIX) { - var array_type = (ArrayType) ma.inner.value_type; - in_arg_map.set (get_param_pos (0), new CCodeIdentifier (get_ccode_name (array_type.element_type))); - } else if (m is ArrayMoveMethod) { - requires_array_move = true; - } else if (m is ArrayCopyMethod) { - expr.target_value = copy_value (ma.inner.target_value, expr); - return; - } - - CCodeExpression instance = null; - if (m != null && m.is_async_callback) { - if (current_method.closure) { - var block = ((Method) m.parent_symbol).body; - instance = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), "_async_data_"); - } else { - instance = new CCodeIdentifier ("_data_"); - } - - in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance); - out_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance); - } else if (m != null && m.binding == MemberBinding.INSTANCE && !(m is CreationMethod)) { - var instance_value = ma.inner.target_value; - if ((ma.member_name == "begin" || ma.member_name == "end") && ma.inner.symbol_reference == ma.symbol_reference) { - var inner_ma = (MemberAccess) ma.inner; - instance_value = inner_ma.inner.target_value; - } - instance = get_cvalue_ (instance_value); - - var st = m.parent_symbol as Struct; - if (st != null && !st.is_simple_type ()) { - // we need to pass struct instance by reference - if (!get_lvalue (instance_value)) { - instance_value = store_temp_value (instance_value, expr); - } - instance = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue_ (instance_value)); - } - - if (!m.coroutine) { - in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance); - } else if (expr.is_yield_expression) { - in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance); - if (get_ccode_finish_instance (m)) { - out_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance); - } - } else if (ma.member_name != "end" || get_ccode_finish_instance (m)) { - out_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance); - in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance); - } - } else if (m != null && m.binding == MemberBinding.CLASS) { - unowned Class cl = (Class) m.parent_symbol; - var cast = get_this_class_cexpression (cl, ma.inner != null ? ma.inner.target_value : null); - in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), cast); - out_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), cast); - } - - if (m != null && get_ccode_has_generic_type_parameter (m)) { - // insert type argument for macros - if (m.has_type_parameters ()) { - // generic method - int type_param_index = 0; - foreach (var type_arg in ma.get_type_arguments ()) { - // real structs are passed by reference for simple generics - if (get_ccode_simple_generics (m) && type_arg.is_real_struct_type () && !type_arg.nullable && !(type_arg is PointerType)) { - type_arg = new PointerType (type_arg); - } - in_arg_map.set (get_param_pos (get_ccode_generic_type_pos (m) + 0.01 * type_param_index), new CCodeIdentifier (get_ccode_name (type_arg))); - type_param_index++; - } - } else { - // method in generic type - int type_param_index = 0; - foreach (var type_arg in ma.inner.value_type.get_type_arguments ()) { - in_arg_map.set (get_param_pos (get_ccode_generic_type_pos (m) + 0.01 * type_param_index), new CCodeIdentifier (get_ccode_name (type_arg))); - type_param_index++; - } - } - } - - if (m is ArrayMoveMethod) { - var array_type = (ArrayType) ma.inner.value_type; - var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - csizeof.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - in_arg_map.set (get_param_pos (0.1), csizeof); - } else if (m is DynamicMethod) { - emit_context.push_symbol (m); - m.clear_parameters (); - int param_nr = 1; - foreach (Expression arg in expr.get_argument_list ()) { - var unary = arg as UnaryExpression; - if (unary != null && unary.operator == UnaryOperator.OUT) { - // out argument - var param = new Parameter ("param%d".printf (param_nr), unary.inner.value_type); - param.direction = ParameterDirection.OUT; - m.add_parameter (param); - } else if (unary != null && unary.operator == UnaryOperator.REF) { - // ref argument - var param = new Parameter ("param%d".printf (param_nr), unary.inner.value_type); - param.direction = ParameterDirection.REF; - m.add_parameter (param); - } else { - // in argument - m.add_parameter (new Parameter ("param%d".printf (param_nr), arg.value_type)); - } - param_nr++; - } - foreach (Parameter param in m.get_parameters ()) { - param.accept (this); - } - generate_dynamic_method_wrapper ((DynamicMethod) m); - emit_context.pop_symbol (); - } else if (m is CreationMethod && context.profile == Profile.GOBJECT && m.parent_symbol is Class) { - ccode.add_assignment (get_this_cexpression (), new CCodeCastExpression (ccall, get_ccode_name (current_class) + "*")); - - if (current_method.body.captured) { - // capture self after setting it - var ref_call = new CCodeFunctionCall (get_dup_func_expression (new ObjectType (current_class), expr.source_reference)); - ref_call.add_argument (get_this_cexpression ()); - - ccode.add_assignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (current_method.body))), "self"), ref_call); - } - - //FIXME Only needed for non-"g_object_new" calls, if there is no property clash - if (!current_class.is_compact && current_class.has_type_parameters ()) { - /* type, dup func, and destroy func fields for generic types */ - var priv_access = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"); - foreach (TypeParameter type_param in current_class.get_type_parameters ()) { - var type = get_ccode_type_id (type_param); - var dup_func = get_ccode_copy_function (type_param); - var destroy_func = get_ccode_destroy_function (type_param); - ccode.add_assignment (new CCodeMemberAccess.pointer (priv_access, type), new CCodeIdentifier (type)); - ccode.add_assignment (new CCodeMemberAccess.pointer (priv_access, dup_func), new CCodeIdentifier (dup_func)); - ccode.add_assignment (new CCodeMemberAccess.pointer (priv_access, destroy_func), new CCodeIdentifier (destroy_func)); - } - } - // object chainup can't be used as expression - ccall_expr = null; - } - - bool ellipsis = false; - - int i = 1; - int arg_pos; - Iterator params_it = params.iterator (); - foreach (Expression arg in expr.get_argument_list ()) { - CCodeExpression cexpr = get_cvalue (arg); - - var carg_map = in_arg_map; - - Parameter? param = null; - if (params_it.next ()) { - param = params_it.get (); - ellipsis = param.params_array || param.ellipsis; - } - - if (param != null && !ellipsis) { - if (param.direction == ParameterDirection.OUT) { - carg_map = out_arg_map; - } - - var unary = arg as UnaryExpression; - if (unary == null || unary.operator != UnaryOperator.OUT) { - if (get_ccode_array_length (param) && param.variable_type is ArrayType && !((ArrayType) param.variable_type).fixed_length) { - var array_type = (ArrayType) param.variable_type; - var length_ctype = get_ccode_array_length_type (param); - if (unary != null && unary.operator == UnaryOperator.REF) { - length_ctype = "%s*".printf (length_ctype); - } - for (int dim = 1; dim <= array_type.rank; dim++) { - var array_length_expr = new CCodeCastExpression (get_array_length_cexpression (arg, dim), length_ctype); - carg_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), array_length_expr); - } - } else if (get_ccode_delegate_target (param) && param.variable_type is DelegateType) { - var deleg_type = (DelegateType) param.variable_type; - if (deleg_type.delegate_symbol.has_target) { - CCodeExpression delegate_target_destroy_notify; - var delegate_target = get_delegate_target_cexpression (arg, out delegate_target_destroy_notify); - assert (delegate_target != null); - if (get_ccode_type (param) == "GClosure*") { - // one single GClosure parameter - var closure_new = new CCodeFunctionCall (new CCodeIdentifier ("g_cclosure_new")); - closure_new.add_argument (new CCodeCastExpression (cexpr, "GCallback")); - closure_new.add_argument (delegate_target); - closure_new.add_argument (new CCodeCastExpression (delegate_target_destroy_notify, "GClosureNotify")); - //TODO Use get_non_null (arg.target_value) - if (arg.is_non_null ()) { - cexpr = closure_new; - } else { - cexpr = new CCodeConditionalExpression (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cexpr, new CCodeConstant ("NULL")), new CCodeConstant ("NULL"), closure_new); - } - } else { - // Override previously given target/destroy only if it was NULL - // TODO https://gitlab.gnome.org/GNOME/vala/issues/59 - var node = carg_map.get (get_param_pos (get_ccode_delegate_target_pos (param))); - if (node == null || (node is CCodeConstant && ((CCodeConstant) node).name == "NULL")) { - carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), delegate_target); - if (deleg_type.is_disposable ()) { - assert (delegate_target_destroy_notify != null); - carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), delegate_target_destroy_notify); - } - } - } - } - } else if (param.variable_type is MethodType) { - // callbacks in dynamic method calls - CCodeExpression delegate_target_destroy_notify; - carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), get_delegate_target_cexpression (arg, out delegate_target_destroy_notify)); - } else if (param.variable_type is GenericType) { - if (m != null && get_ccode_simple_generics (m)) { - var generic_type = (GenericType) param.variable_type; - int type_param_index = m.get_type_parameter_index (generic_type.type_parameter.name); - var type_arg = ma.get_type_arguments ().get (type_param_index); - if (param.variable_type.value_owned) { - if (requires_copy (type_arg)) { - carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), get_destroy_func_expression (type_arg)); - } else { - carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), new CCodeConstant ("NULL")); - } - } - } - } - - cexpr = handle_struct_argument (param, arg, cexpr); - } else { - arg.target_value = null; - - var temp_var = get_temp_variable (param.variable_type, param.variable_type.value_owned, null, true); - emit_temp_var (temp_var); - set_cvalue (arg, get_variable_cexpression (temp_var.name)); - arg.target_value.value_type = arg.target_type; - - cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue (arg)); - - if (get_ccode_array_length (param) && param.variable_type is ArrayType && !((ArrayType) param.variable_type).fixed_length) { - var array_type = (ArrayType) param.variable_type; - var length_ctype = get_ccode_array_length_type (param); - for (int dim = 1; dim <= array_type.rank; dim++) { - var temp_array_length = get_temp_variable (new CType (length_ctype, "0"), true, null, true); - emit_temp_var (temp_array_length); - append_array_length (arg, get_variable_cexpression (temp_array_length.name)); - carg_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_array_lengths (arg).get (dim - 1))); - } - } else if (get_ccode_delegate_target (param) && param.variable_type is DelegateType) { - var deleg_type = (DelegateType) param.variable_type; - if (deleg_type.delegate_symbol.has_target) { - temp_var = get_temp_variable (delegate_target_type, true, null, true); - emit_temp_var (temp_var); - set_delegate_target (arg, get_variable_cexpression (temp_var.name)); - carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_delegate_target (arg))); - if (deleg_type.is_disposable ()) { - temp_var = get_temp_variable (delegate_target_destroy_type, true, null, true); - emit_temp_var (temp_var); - set_delegate_target_destroy_notify (arg, get_variable_cexpression (temp_var.name)); - carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_delegate_target_destroy_notify (arg))); - } - } - } - } - - if (get_ccode_type (param) != null) { - cexpr = new CCodeCastExpression (cexpr, get_ccode_type (param)); - } - } else { - // ellipsis arguments - var unary = arg as UnaryExpression; - if (ellipsis && unary != null && unary.operator == UnaryOperator.OUT) { - carg_map = out_arg_map; - - arg.target_value = null; - - // infer type and ownership from argument expression - var temp_var = get_temp_variable (arg.value_type, arg.value_type.value_owned, null, true); - emit_temp_var (temp_var); - set_cvalue (arg, get_variable_cexpression (temp_var.name)); - arg.target_value.value_type = arg.value_type; - - if (arg.value_type is DelegateType && ((DelegateType) arg.value_type).delegate_symbol.has_target) { - // Initialize target/destroy cvalues to allow assignment of delegates from varargs - unowned GLibValue arg_value = (GLibValue) arg.target_value; - if (arg_value.delegate_target_cvalue == null) { - arg_value.delegate_target_cvalue = new CCodeConstant ("NULL"); - } - if (arg_value.delegate_target_destroy_notify_cvalue == null) { - arg_value.delegate_target_destroy_notify_cvalue = new CCodeConstant ("NULL"); - } - } - - cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue (arg)); - } else { - cexpr = handle_struct_argument (null, arg, cexpr); - } - } - - if (itype is SignalType && ((SignalType) itype).signal_symbol is DynamicSignal) { - arg_pos = get_param_pos (i, false); - } else { - arg_pos = get_param_pos (param != null && !ellipsis ? get_ccode_pos (param) : i, ellipsis); - } - carg_map.set (arg_pos, cexpr); - - if (m is ArrayResizeMethod && context.profile == Profile.POSIX) { - var csizeof = new CCodeIdentifier ("sizeof (%s)".printf (get_ccode_name (((ArrayType) ma.inner.value_type).element_type))); - carg_map.set (arg_pos, new CCodeBinaryExpression (CCodeBinaryOperator.MUL, csizeof, cexpr)); - } else { - carg_map.set (arg_pos, cexpr); - } - - if (arg is NamedArgument && ellipsis) { - var named_arg = (NamedArgument) arg; - string name = string.joinv ("-", named_arg.name.split ("_")); - carg_map.set (get_param_pos (i - 0.1, ellipsis), new CCodeConstant ("\"%s\"".printf (name))); - } - - i++; - } - if (params_it.next ()) { - var param = params_it.get (); - - /* if there are more parameters than arguments, - * the additional parameter is an ellipsis parameter - * otherwise there is a bug in the semantic analyzer - */ - assert (param.params_array || param.ellipsis); - ellipsis = true; - } - - /* add length argument for methods returning arrays */ - if (m != null && m.return_type is ArrayType && async_call != ccall) { - var array_type = (ArrayType) m.return_type; - for (int dim = 1; dim <= array_type.rank; dim++) { - if (get_ccode_array_null_terminated (m)) { - // handle calls to methods returning null-terminated arrays - var temp_var = get_temp_variable (itype.get_return_type (), true, null, false); - var temp_ref = get_variable_cexpression (temp_var.name); - - emit_temp_var (temp_var); - - ccall_expr = new CCodeAssignment (temp_ref, ccall_expr); - - requires_array_length = true; - var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length")); - len_call.add_argument (temp_ref); - - append_array_length (expr, len_call); - } else if (get_ccode_array_length (m)) { - var length_ctype = get_ccode_array_length_type (m); - var temp_var = get_temp_variable (new CType (length_ctype, "0"), true, null, true); - var temp_ref = get_variable_cexpression (temp_var.name); - - emit_temp_var (temp_var); - - out_arg_map.set (get_param_pos (get_ccode_array_length_pos (m) + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref)); - - append_array_length (expr, temp_ref); - } else if (get_ccode_array_length_expr (m) != null) { - append_array_length (expr, new CCodeConstant (get_ccode_array_length_expr (m))); - } else { - append_array_length (expr, new CCodeConstant ("-1")); - } - } - } else if (m != null && m.return_type is DelegateType && async_call != ccall) { - var deleg_type = (DelegateType) m.return_type; - if (get_ccode_delegate_target (m) && deleg_type.delegate_symbol.has_target) { - var temp_var = get_temp_variable (delegate_target_type, true, null, true); - var temp_ref = get_variable_cexpression (temp_var.name); - - emit_temp_var (temp_var); - - out_arg_map.set (get_param_pos (get_ccode_delegate_target_pos (m)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref)); - - set_delegate_target (expr, temp_ref); - - if (deleg_type.is_disposable ()) { - temp_var = get_temp_variable (delegate_target_destroy_type, true, null, true); - temp_ref = get_variable_cexpression (temp_var.name); - - emit_temp_var (temp_var); - - out_arg_map.set (get_param_pos (get_ccode_destroy_notify_pos (m)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref)); - - set_delegate_target_destroy_notify (expr, temp_ref); - } else { - set_delegate_target_destroy_notify (expr, new CCodeConstant ("NULL")); - } - } else { - set_delegate_target (expr, new CCodeConstant ("NULL")); - if (deleg_type.delegate_symbol.has_target) { - set_delegate_target_destroy_notify (expr, new CCodeConstant ("NULL")); - } - } - } - - // add length argument for delegates returning arrays - // TODO: avoid code duplication with methods returning arrays, see above - if (deleg != null && deleg.return_type is ArrayType) { - var array_type = (ArrayType) deleg.return_type; - for (int dim = 1; dim <= array_type.rank; dim++) { - if (get_ccode_array_null_terminated (deleg)) { - // handle calls to methods returning null-terminated arrays - var temp_var = get_temp_variable (itype.get_return_type (), true, null, false); - var temp_ref = get_variable_cexpression (temp_var.name); - - emit_temp_var (temp_var); - - ccall_expr = new CCodeAssignment (temp_ref, ccall_expr); - - requires_array_length = true; - var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length")); - len_call.add_argument (temp_ref); - - append_array_length (expr, len_call); - } else if (get_ccode_array_length (deleg)) { - var length_ctype = get_ccode_array_length_type (deleg); - var temp_var = get_temp_variable (new CType (length_ctype, "0"), true, null, true); - var temp_ref = get_variable_cexpression (temp_var.name); - - emit_temp_var (temp_var); - - out_arg_map.set (get_param_pos (get_ccode_array_length_pos (deleg) + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref)); - - append_array_length (expr, temp_ref); - } else { - append_array_length (expr, new CCodeConstant ("-1")); - } - } - } else if (deleg != null && deleg.return_type is DelegateType && get_ccode_delegate_target (deleg)) { - var deleg_type = (DelegateType) deleg.return_type; - if (deleg_type.delegate_symbol.has_target) { - var temp_var = get_temp_variable (delegate_target_type, true, null, true); - var temp_ref = get_variable_cexpression (temp_var.name); - - emit_temp_var (temp_var); - - out_arg_map.set (get_param_pos (get_ccode_delegate_target_pos (deleg)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref)); - - set_delegate_target (expr, temp_ref); - - if (deleg_type.is_disposable ()) { - temp_var = get_temp_variable (delegate_target_destroy_type, true, null, true); - temp_ref = get_variable_cexpression (temp_var.name); - - emit_temp_var (temp_var); - - out_arg_map.set (get_param_pos (get_ccode_destroy_notify_pos (deleg)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref)); - - set_delegate_target_destroy_notify (expr, temp_ref); - } - } - } - - if (m != null && m.coroutine) { - if (expr.is_yield_expression) { - // asynchronous call - in_arg_map.set (get_param_pos (-1), new CCodeIdentifier (generate_ready_function (current_method))); - in_arg_map.set (get_param_pos (-0.9), new CCodeIdentifier ("_data_")); - } - } - - if (expr.tree_can_fail) { - // method can fail - current_method_inner_error = true; - // add &inner_error before the ellipsis arguments - out_arg_map.set (get_param_pos (get_ccode_error_pos ((Callable) m ?? deleg)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ())); - } else if (m != null && m.has_error_type_parameter () && async_call != ccall) { - // inferred error argument from base method - out_arg_map.set (get_param_pos (get_ccode_error_pos (m)), new CCodeConstant ("NULL")); - } - - if (ellipsis) { - /* ensure variable argument list ends with NULL - * except when using printf-style arguments */ - if (itype is SignalType) { - // g_signal_emit*() does not require more - } else if (m == null) { - in_arg_map.set (get_param_pos (-1, true), new CCodeConstant ("NULL")); - } else if (!m.printf_format && !m.scanf_format && get_ccode_sentinel (m) != "" && !expr.is_constructv_chainup) { - in_arg_map.set (get_param_pos (-1, true), new CCodeConstant (get_ccode_sentinel (m))); - } - } - - if (deleg != null && deleg.has_target) { - CCodeExpression delegate_target_destroy_notify; - in_arg_map.set (get_param_pos (get_ccode_instance_pos (deleg)), get_delegate_target_cexpression (expr.call, out delegate_target_destroy_notify)); - out_arg_map.set (get_param_pos (get_ccode_instance_pos (deleg)), get_delegate_target_cexpression (expr.call, out delegate_target_destroy_notify)); - } - - // structs are returned via out parameter - bool return_result_via_out_param = itype.get_return_type ().is_real_non_null_struct_type (); - - // pass address for the return value of non-void signals without emitter functions - if (itype is SignalType && !(itype.get_return_type () is VoidType)) { - var sig = ((SignalType) itype).signal_symbol; - - if (ma != null && ma.inner is BaseAccess && sig.is_virtual) { - // normal return value for base access - } else if (!get_ccode_has_emitter (sig) || ma.source_reference.file == sig.source_reference.file) { - return_result_via_out_param = true; - } - } - - if (async_call == ccall) { - // skip out parameter for .begin() calls - return_result_via_out_param = false; - } - - CCodeExpression out_param_ref = null; - - if (return_result_via_out_param) { - var out_param_var = get_temp_variable (itype.get_return_type (), true, null, true); - out_param_ref = get_variable_cexpression (out_param_var.name); - emit_temp_var (out_param_var); - out_arg_map.set (get_param_pos (-3), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, out_param_ref)); - } - - // append C arguments in the right order - - int last_pos; - int min_pos; - - if (async_call != ccall) { - // don't append out arguments for .begin() calls - last_pos = -1; - while (true) { - min_pos = -1; - foreach (int pos in out_arg_map.get_keys ()) { - if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { - min_pos = pos; - } - } - if (min_pos == -1) { - break; - } - ccall.add_argument (out_arg_map.get (min_pos)); - last_pos = min_pos; - } - } - - if (async_call != null) { - last_pos = -1; - while (true) { - min_pos = -1; - foreach (int pos in in_arg_map.get_keys ()) { - if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { - min_pos = pos; - } - } - if (min_pos == -1) { - break; - } - async_call.add_argument (in_arg_map.get (min_pos)); - last_pos = min_pos; - } - } - - if (expr.is_yield_expression) { - // set state before calling async function to support immediate callbacks - int state = emit_context.next_coroutine_state++; - - ccode.add_assignment (get_variable_cexpression ("_state_"), new CCodeConstant (state.to_string ())); - ccode.add_expression (async_call); - ccode.add_return (new CCodeConstant ("FALSE")); - ccode.add_label ("_state_%d".printf (state)); - } - - if (expr.is_assert) { - string message = ((string) expr.source_reference.begin.pos).substring (0, (int) (expr.source_reference.end.pos - expr.source_reference.begin.pos)); - ccall.call = new CCodeIdentifier ("_vala_assert"); - ccall.add_argument (new CCodeConstant ("\"%s\"".printf (message.replace ("\n", " ").escape ("")))); - requires_assert = true; - - } - - // Transform and add free function argument to GLib.[List,Queue,SList].remove[_all] calls - unowned DataType? collection_type = null; - if (ma != null && ma.inner != null) { - collection_type = ma.inner.value_type; - } - if (collection_type != null - && (collection_type.type_symbol == glist_type || collection_type.type_symbol == gslist_type || collection_type.type_symbol == gqueue_type) - && (ma.member_name == "remove" || ma.member_name == "remove_all") - //FIXME Perform stricter type argument check earlier - && collection_type.check_type_arguments (context)) { - var remove_method = (Method) collection_type.type_symbol.scope.lookup (ma.member_name + "_full"); - var type_arg = collection_type.get_type_arguments ()[0]; - if (remove_method != null && requires_destroy (type_arg)) { - // only add them once per source file - if (add_generated_external_symbol (remove_method)) { - visit_method (remove_method); - } - ccall.call = new CCodeIdentifier (get_ccode_name (remove_method)); - ccall.add_argument (get_destroy0_func_expression (type_arg)); - } - } - - if (return_result_via_out_param) { - ccode.add_expression (ccall_expr); - ccall_expr = out_param_ref; - } - - if (m != null && m.binding == MemberBinding.INSTANCE && m.returns_modified_pointer) { - if (ma != null && ma.inner.symbol_reference is Property && ma.inner is MemberAccess) { - var prop = (Property) ma.inner.symbol_reference; - store_property (prop, ((MemberAccess) ma.inner).inner, new GLibValue (expr.value_type, ccall_expr)); - ccall_expr = null; - } else { - ccall_expr = new CCodeAssignment (instance, ccall_expr); - } - } - - // real structs are passed by reference for simple generics - if (m != null && get_ccode_simple_generics (m) && m.return_type is GenericType - && expr.value_type.is_real_struct_type () && !expr.value_type.nullable && !(expr.value_type is PointerType)) { - ccall_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeParenthesizedExpression (ccall_expr)); - } - - if (m != null && get_ccode_type (m) != null && get_ccode_type (m) != get_ccode_name (m.return_type)) { - // Bug 699956: Implement cast for method return type if [CCode type=] annotation is specified - ccall_expr = new CCodeCastExpression (ccall_expr, get_ccode_name (m.return_type)); - } - - if (m is ArrayResizeMethod) { - // FIXME: size expression must not be evaluated twice at runtime (potential side effects) - Iterator arg_it = expr.get_argument_list ().iterator (); - arg_it.next (); - var new_size = get_cvalue (arg_it.get ()); - - var array_type = (ArrayType) ma.inner.value_type; - var temp_decl = get_temp_variable (array_type.length_type); - var temp_ref = get_variable_cexpression (temp_decl.name); - - emit_temp_var (temp_decl); - - /* memset needs string.h */ - cfile.add_include ("string.h"); - - var clen = get_array_length_cexpression (ma.inner, 1); - var celems = get_cvalue (ma.inner); - var csizeof = new CCodeIdentifier ("sizeof (%s)".printf (get_ccode_name (array_type.element_type))); - var cdelta = 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)); - - ccode.add_assignment (temp_ref, new_size); - ccode.add_expression (ccall_expr); - ccode.add_expression (new CCodeConditionalExpression (ccheck, czero, new CCodeConstant ("NULL"))); - ccode.add_assignment (get_array_length_cexpression (ma.inner, 1), temp_ref); - - var array_var = ma.inner.symbol_reference; - if (array_var != null && array_var.is_internal_symbol () - && (array_var is LocalVariable || array_var is Field)) { - ccode.add_assignment (get_array_size_cvalue (ma.inner.target_value), temp_ref); - } - - return; - } - - if (expr.parent_node is ExpressionStatement && !expr.value_type.is_disposable ()) { - if (ccall_expr != null && !return_result_via_out_param) { - ccode.add_expression (ccall_expr); - } - } else { - var result_type = itype.get_return_type (); - - if (expr.formal_value_type is GenericType && !(expr.value_type is GenericType)) { - var type_parameter = ((GenericType) expr.formal_value_type).type_parameter; - var st = type_parameter.parent_symbol.parent_symbol as Struct; - if (type_parameter.parent_symbol == garray_type || - (st != null && get_ccode_name (st) == "va_list")) { - // GArray and va_list don't use pointer-based generics - // above logic copied from visit_expression () - // TODO avoid code duplication - result_type = expr.value_type; - } - if (st != null && get_ccode_name (st) == "va_list" && ma.member_name == "arg") { - if (result_type is DelegateType && ((DelegateType) result_type).delegate_symbol.has_target) { - set_cvalue (expr, null); - // Initialize target/destroy cvalues to allow assignment of delegates from varargs - unowned GLibValue arg_value = (GLibValue) expr.target_value; - if (arg_value.delegate_target_cvalue == null) { - arg_value.delegate_target_cvalue = new CCodeConstant ("NULL"); - } - if (arg_value.delegate_target_destroy_notify_cvalue == null) { - arg_value.delegate_target_destroy_notify_cvalue = new CCodeConstant ("NULL"); - } - } - } - } - - if (m != null && m.get_format_arg_index () >= 0) { - set_cvalue (expr, ccall_expr); - } else if (m != null && m.get_attribute_bool ("CCode", "use_inplace", false)) { - set_cvalue (expr, ccall_expr); - } else if (!return_result_via_out_param - && !has_ref_out_argument (expr) - && (result_type is ValueType && !result_type.is_disposable ())) { - set_cvalue (expr, ccall_expr); - } else if (!return_result_via_out_param) { - var temp_var = get_temp_variable (result_type, result_type.value_owned, null, false); - var temp_ref = get_variable_cexpression (temp_var.name); - - emit_temp_var (temp_var); - - ccode.add_assignment (temp_ref, ccall_expr); - set_cvalue (expr, temp_ref); - ((GLibValue) expr.target_value).lvalue = true; - } else { - set_cvalue (expr, ccall_expr); - ((GLibValue) expr.target_value).lvalue = true; - } - } - - params_it = params.iterator (); - foreach (Expression arg in expr.get_argument_list ()) { - Parameter param = null; - - if (params_it.next ()) { - param = params_it.get (); - } - - var unary = arg as UnaryExpression; - - // update possible stale _*_size_ variable - if (unary != null && unary.operator == UnaryOperator.REF) { - if (param != null && get_ccode_array_length (param) && param.variable_type is ArrayType - && !((ArrayType) param.variable_type).fixed_length && ((ArrayType) param.variable_type).rank == 1) { - unowned Variable? array_var = unary.inner.symbol_reference as Variable; - if ((array_var is LocalVariable || array_var is Field) && array_var.is_internal_symbol () - && array_var.variable_type is ArrayType && !((ArrayType) array_var.variable_type).fixed_length) { - ccode.add_assignment (get_array_size_cvalue (unary.inner.target_value), get_array_length_cvalue (unary.inner.target_value, 1)); - } - } - } - - if (unary == null || unary.operator != UnaryOperator.OUT) { - continue; - } - - if (requires_destroy (unary.inner.value_type)) { - // unref old value - ccode.add_expression (destroy_value (unary.inner.target_value)); - } - - // infer type of out-parameter from argument - if (ma.symbol_reference is DynamicMethod && unary.target_value.value_type == null) { - unary.target_value.value_type = unary.inner.value_type.copy (); - } - - // assign new value - store_value (unary.inner.target_value, transform_value (unary.target_value, unary.inner.value_type, arg), expr.source_reference); - - // handle out null terminated arrays - if (param != null && get_ccode_array_null_terminated (param)) { - requires_array_length = true; - var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length")); - len_call.add_argument (get_cvalue_ (unary.inner.target_value)); - - ccode.add_assignment (get_array_length_cvalue (unary.inner.target_value, 1), len_call); - } - } - - if (m is CreationMethod && m.parent_symbol is Class && ((current_class.is_compact && current_class.base_class != null) || current_class.is_subtype_of (gsource_type))) { - var cinitcall = new CCodeFunctionCall (new CCodeIdentifier ("%s_instance_init".printf (get_ccode_lower_case_name (current_class, null)))); - cinitcall.add_argument (get_this_cexpression ()); - if (!current_class.is_compact) { - cinitcall.add_argument (new CCodeConstant ("NULL")); - } - ccode.add_expression (cinitcall); - } - } - - private string generate_enum_to_string_function (Enum en) { - var to_string_func = "_%s_to_string".printf (get_ccode_lower_case_name (en)); - - if (!add_wrapper (to_string_func)) { - // wrapper already defined - return to_string_func; - } - // declaration - - var function = new CCodeFunction (to_string_func, "const char*"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("value", get_ccode_name (en))); - - // definition - push_context (new EmitContext ()); - push_function (function); - - ccode.open_switch (new CCodeConstant ("value")); - foreach (var enum_value in en.get_values ()) { - ccode.add_case (new CCodeIdentifier (get_ccode_name (enum_value))); - ccode.add_return (new CCodeConstant ("\""+get_ccode_name (enum_value)+"\"")); - } - ccode.close (); - ccode.add_return (new CCodeConstant ("NULL")); - - // append to file - cfile.add_function_declaration (function); - cfile.add_function (function); - - pop_context (); - - return to_string_func; - } - - bool has_ref_out_argument (MethodCall c) { - foreach (var arg in c.get_argument_list ()) { - unowned UnaryExpression? unary = arg as UnaryExpression; - if (unary != null && (unary.operator == UnaryOperator.OUT || unary.operator == UnaryOperator.REF)) { - return true; - } - } - return false; - } - - string generate_string_printf_function () { - if (!add_wrapper ("string_printf")) { - // wrapper already defined - return "string_printf"; - } - - // declaration - var function = new CCodeFunction ("string_printf", "char*"); - function.add_parameter (new CCodeParameter ("format", "const char*")); - function.add_parameter (new CCodeParameter.with_ellipsis ()); - function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.PRINTF; - - // definition - push_context (new EmitContext ()); - push_function (function); - - ccode.add_declaration ("int", new CCodeVariableDeclarator ("length")); - ccode.add_declaration ("va_list", new CCodeVariableDeclarator ("ap")); - ccode.add_declaration ("char*", new CCodeVariableDeclarator ("result")); - - var vastart = new CCodeFunctionCall (new CCodeIdentifier ("va_start")); - vastart.add_argument (new CCodeIdentifier ("ap")); - vastart.add_argument (new CCodeIdentifier ("format")); - - ccode.add_expression (vastart); - - if (context.profile == Profile.POSIX) { - cfile.add_include ("stdio.h"); - } - - var vsnprintf = new CCodeFunctionCall (new CCodeIdentifier ("vsnprintf")); - vsnprintf.add_argument (new CCodeConstant ("NULL")); - vsnprintf.add_argument (new CCodeConstant ("0")); - vsnprintf.add_argument (new CCodeIdentifier ("format")); - vsnprintf.add_argument (new CCodeIdentifier ("ap")); - - ccode.add_assignment (new CCodeIdentifier ("length"), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, vsnprintf, new CCodeConstant ("1"))); - - var va_end = new CCodeFunctionCall (new CCodeIdentifier ("va_end")); - va_end.add_argument (new CCodeIdentifier ("ap")); - - ccode.add_expression (va_end); - - var malloc = new CCodeFunctionCall (new CCodeIdentifier ("malloc")); - malloc.add_argument (new CCodeIdentifier ("length")); - - ccode.add_assignment (new CCodeIdentifier ("result"), malloc); - - vastart = new CCodeFunctionCall (new CCodeIdentifier ("va_start")); - vastart.add_argument (new CCodeIdentifier ("ap")); - vastart.add_argument (new CCodeIdentifier ("format")); - - ccode.add_expression (vastart); - - vsnprintf = new CCodeFunctionCall (new CCodeIdentifier ("vsnprintf")); - vsnprintf.add_argument (new CCodeIdentifier ("result")); - vsnprintf.add_argument (new CCodeIdentifier ("length")); - vsnprintf.add_argument (new CCodeIdentifier ("format")); - vsnprintf.add_argument (new CCodeIdentifier ("ap")); - - ccode.add_expression (vsnprintf); - - va_end = new CCodeFunctionCall (new CCodeIdentifier ("va_end")); - va_end.add_argument (new CCodeIdentifier ("ap")); - - ccode.add_expression (va_end); - - ccode.add_return (new CCodeIdentifier ("result")); - - // append to file - cfile.add_include ("stdarg.h"); - cfile.add_function_declaration (function); - cfile.add_function (function); - - pop_context (); - - return "string_printf"; - } -} - diff --git a/src/codegen/valaccodemethodmodule.vala b/src/codegen/valaccodemethodmodule.vala deleted file mode 100644 index 77ff73c31..000000000 --- a/src/codegen/valaccodemethodmodule.vala +++ /dev/null @@ -1,1420 +0,0 @@ -/* valaccodemethodmodule.vala - * - * Copyright (C) 2007-2010 Jürg Billeter - * - * 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.1 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 - * Raffaele Sandrini - */ - -using GLib; - -/** - * The link between a method and generated code. - */ -public abstract class Vala.CCodeMethodModule : CCodeStructModule { - - private bool ellipses_to_valist = false; - - string get_creturn_type (Method m, string default_value) { - string type = get_ccode_type (m); - if (type == null) { - return default_value; - } - return type; - } - - bool is_gtypeinstance_creation_method (Method m) { - bool result = false; - - var cl = m.parent_symbol as Class; - if (m is CreationMethod && cl != null && !cl.is_compact) { - result = true; - } - - return result; - } - - public virtual void generate_method_result_declaration (Method m, CCodeFile decl_space, CCodeFunction cfunc, Map cparam_map, Map? carg_map) { - var creturn_type = get_callable_creturn_type (m); - cfunc.return_type = get_creturn_type (m, get_ccode_name (creturn_type)); - - generate_type_declaration (m.return_type, decl_space); - - if (m.return_type.is_real_non_null_struct_type ()) { - // structs are returned via out parameter - var cparam = new CCodeParameter ("result", get_ccode_name (m.return_type) + "*"); - cparam_map.set (get_param_pos (-3), cparam); - if (carg_map != null) { - carg_map.set (get_param_pos (-3), get_cexpression ("result")); - } - } else if (get_ccode_array_length (m) && m.return_type is ArrayType) { - // return array length if appropriate - var array_type = (ArrayType) m.return_type; - var length_ctype = get_ccode_array_length_type (m) + "*"; - - for (int dim = 1; dim <= array_type.rank; dim++) { - var cparam = new CCodeParameter (get_array_length_cname ("result", dim), length_ctype); - cparam_map.set (get_param_pos (get_ccode_array_length_pos (m) + 0.01 * dim), cparam); - if (carg_map != null) { - carg_map.set (get_param_pos (get_ccode_array_length_pos (m) + 0.01 * dim), get_cexpression (cparam.name)); - } - } - } else if (get_ccode_delegate_target (m) && m.return_type is DelegateType) { - // return delegate target if appropriate - var deleg_type = (DelegateType) m.return_type; - if (deleg_type.delegate_symbol.has_target) { - var cparam = new CCodeParameter (get_delegate_target_cname ("result"), get_ccode_name (delegate_target_type) + "*"); - cparam_map.set (get_param_pos (get_ccode_delegate_target_pos (m)), cparam); - if (carg_map != null) { - carg_map.set (get_param_pos (get_ccode_delegate_target_pos (m)), get_cexpression (cparam.name)); - } - if (deleg_type.is_disposable ()) { - cparam = new CCodeParameter (get_delegate_target_destroy_notify_cname ("result"), get_ccode_name (delegate_target_destroy_type) + "*"); - cparam_map.set (get_param_pos (get_ccode_destroy_notify_pos (m)), cparam); - if (carg_map != null) { - carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (m)), get_cexpression (cparam.name)); - } - } - } - } - - if (m.has_error_type_parameter ()) { - var error_types = new ArrayList (); - m.get_error_types (error_types); - foreach (DataType error_type in error_types) { - generate_type_declaration (error_type, decl_space); - } - - var cparam = new CCodeParameter ("error", "GError**"); - cparam_map.set (get_param_pos (get_ccode_error_pos (m)), cparam); - if (carg_map != null) { - carg_map.set (get_param_pos (get_ccode_error_pos (m)), new CCodeIdentifier (cparam.name)); - } - } - } - - public void complete_async () { - var data_var = new CCodeIdentifier ("_data_"); - var async_result_expr = new CCodeMemberAccess.pointer (data_var, "_async_result"); - - var finish_call = new CCodeFunctionCall (new CCodeIdentifier ("g_task_return_pointer")); - finish_call.add_argument (async_result_expr); - finish_call.add_argument (data_var); - finish_call.add_argument (new CCodeConstant ("NULL")); - ccode.add_expression (finish_call); - - // Preserve the "complete now" behavior if state != 0, do so by - // iterating the GTask's main context till the task is complete. - var state = new CCodeMemberAccess.pointer (data_var, "_state_"); - var zero = new CCodeConstant ("0"); - var state_is_not_zero = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, state, zero); - ccode.open_if (state_is_not_zero); - - CCodeExpression task_is_complete; - - var task_complete = new CCodeFunctionCall (new CCodeIdentifier ("g_task_get_completed")); - task_complete.add_argument (async_result_expr); - task_is_complete = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, task_complete); - - ccode.open_while (task_is_complete); - var task_context = new CCodeFunctionCall (new CCodeIdentifier ("g_task_get_context")); - task_context.add_argument (async_result_expr); - var iterate_context = new CCodeFunctionCall (new CCodeIdentifier ("g_main_context_iteration")); - iterate_context.add_argument (task_context); - iterate_context.add_argument (new CCodeConstant ("TRUE")); - ccode.add_expression (iterate_context); - ccode.close (); - - ccode.close (); - - var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - unref.add_argument (async_result_expr); - ccode.add_expression (unref); - - ccode.add_return (new CCodeConstant ("FALSE")); - } - - public override bool generate_method_declaration (Method m, CCodeFile decl_space) { - if (m.is_async_callback) { - return false; - } - if ((m.is_abstract || m.is_virtual) && get_ccode_no_wrapper (m)) { - return false; - } - if (add_symbol_declaration (decl_space, m, get_ccode_name (m))) { - return false; - } - - generate_type_declaration (new MethodType (m), decl_space); - - var function = new CCodeFunction (get_ccode_name (m)); - - if (m.is_private_symbol () && !m.external) { - function.modifiers |= CCodeModifiers.STATIC; - if (m.is_inline) { - function.modifiers |= CCodeModifiers.INLINE; - } - } else if (context.hide_internal && m.is_internal_symbol () && !m.external) { - function.modifiers |= CCodeModifiers.INTERNAL; - } else if (!m.entry_point && !m.external) { - function.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - if (m.entry_point) { - function.modifiers |= CCodeModifiers.STATIC; - } - - if (m.version.deprecated) { - if (context.profile == Profile.GOBJECT) { - decl_space.add_include ("glib.h"); - } - function.modifiers |= CCodeModifiers.DEPRECATED; - } - - var cparam_map = new HashMap (direct_hash, direct_equal); - var carg_map = new HashMap (direct_hash, direct_equal); - - var cl = m.parent_symbol as Class; - - // do not generate _new functions for creation methods of abstract classes - if (!(m is CreationMethod && cl != null && cl.is_abstract && !cl.is_compact)) { - bool etv_tmp = ellipses_to_valist; - ellipses_to_valist = false; - generate_cparameters (m, decl_space, cparam_map, function, null, carg_map, new CCodeFunctionCall (new CCodeIdentifier ("fake"))); - ellipses_to_valist = etv_tmp; - - decl_space.add_function_declaration (function); - } - - if (is_gtypeinstance_creation_method (m)) { - // _construct function - function = new CCodeFunction (get_ccode_real_name (m)); - - if (m.is_private_symbol ()) { - function.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && m.is_internal_symbol ()) { - function.modifiers |= CCodeModifiers.INTERNAL; - } else { - function.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - cparam_map = new HashMap (direct_hash, direct_equal); - bool etv_tmp = ellipses_to_valist; - ellipses_to_valist = false; - generate_cparameters (m, decl_space, cparam_map, function); - ellipses_to_valist = etv_tmp; - - decl_space.add_function_declaration (function); - - if (m.is_variadic ()) { - // _constructv function - function = new CCodeFunction (get_ccode_constructv_name ((CreationMethod) m)); - - if (!m.is_private_symbol ()) { - function.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - cparam_map = new HashMap (direct_hash, direct_equal); - generate_cparameters (m, decl_space, cparam_map, function); - - decl_space.add_function_declaration (function); - } - } - - return true; - } - - void register_plugin_types (Symbol sym, Set registered_types) { - var ns = sym as Namespace; - var cl = sym as Class; - var iface = sym as Interface; - if (ns != null) { - foreach (var ns_ns in ns.get_namespaces ()) { - register_plugin_types (ns_ns, registered_types); - } - foreach (var ns_cl in ns.get_classes ()) { - register_plugin_types (ns_cl, registered_types); - } - foreach (var ns_iface in ns.get_interfaces ()) { - register_plugin_types (ns_iface, registered_types); - } - } else if (cl != null) { - register_plugin_type (cl, registered_types); - foreach (var cl_cl in cl.get_classes ()) { - register_plugin_types (cl_cl, registered_types); - } - } else if (iface != null) { - register_plugin_type (iface, registered_types); - foreach (var iface_cl in iface.get_classes ()) { - register_plugin_types (iface_cl, registered_types); - } - } - } - - void register_plugin_type (ObjectTypeSymbol type_symbol, Set registered_types) { - if (type_symbol.external_package) { - return; - } - - if (!registered_types.add (type_symbol)) { - // already registered - return; - } - - var cl = type_symbol as Class; - if (cl != null) { - if (cl.is_compact) { - return; - } - - // register base types first - foreach (var base_type in cl.get_base_types ()) { - register_plugin_type ((ObjectTypeSymbol) base_type.type_symbol, registered_types); - } - } - - // Add function prototypes for required register-type-calls which are likely external - if (type_symbol.source_reference.file != cfile.file) { - // TODO Duplicated source with TypeRegisterFunction.init_from_type() - var register_func = new CCodeFunction ("%s_register_type".printf (get_ccode_lower_case_name (type_symbol, null)), "GType"); - register_func.add_parameter (new CCodeParameter ("module", "GTypeModule *")); - register_func.is_declaration = true; - cfile.add_function_declaration (register_func); - } - - var register_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_register_type".printf (get_ccode_lower_case_name (type_symbol, null)))); - register_call.add_argument (new CCodeIdentifier (module_init_param_name)); - ccode.add_expression (register_call); - - var iface = type_symbol as Interface; - if (iface != null) { - string? dbus_name = GDBusModule.get_dbus_name(type_symbol); - - if (dbus_name != null) { - string proxy_cname = get_ccode_lower_case_prefix (type_symbol) + "proxy"; - var register_proxy = new CCodeFunctionCall (new CCodeIdentifier ("%s_register_dynamic_type".printf (proxy_cname))); - register_proxy.add_argument (new CCodeIdentifier (module_init_param_name)); - ccode.add_expression (register_proxy); - } - } - } - - /** - * This function generates the code the given method. If the method is - * a constructor, _construct is generated, unless it's variadic, in which - * case _constructv is generated (and _construct is generated together - * with _new in visit_creation_method). - */ - public override void visit_method (Method m) { - push_context (new EmitContext (m)); - push_line (m.source_reference); - - bool in_gobject_creation_method = false; - bool in_fundamental_creation_method = false; - - bool profile = m.get_attribute ("Profile") != null; - - string real_name = get_ccode_real_name (m); - - if (m is CreationMethod) { - unowned Class? cl = m.parent_symbol as Class; - if (cl != null && !cl.is_compact) { - if (cl.base_class == null) { - in_fundamental_creation_method = true; - } else if (gobject_type != null && cl.is_subtype_of (gobject_type)) { - in_gobject_creation_method = true; - } - } - if (cl != null && !cl.is_compact && m.is_variadic ()) { - real_name = get_ccode_constructv_name ((CreationMethod) m); - } - } - - var creturn_type = get_callable_creturn_type (m); - - foreach (Parameter param in m.get_parameters ()) { - param.accept (this); - } - - // do not declare overriding methods and interface implementations - if ((m.is_abstract || m.is_virtual - || (m.base_method == null && m.base_interface_method == null)) - && m.signal_reference == null) { - generate_method_declaration (m, cfile); - - if (!m.is_internal_symbol ()) { - generate_method_declaration (m, header_file); - } - if (!m.is_private_symbol ()) { - generate_method_declaration (m, internal_header_file); - } - } - - if (profile) { - string prefix = "_vala_prof_%s".printf (real_name); - - cfile.add_include ("stdio.h"); - - var counter = new CCodeIdentifier (prefix + "_counter"); - var counter_decl = new CCodeDeclaration (get_ccode_name (int_type)); - counter_decl.add_declarator (new CCodeVariableDeclarator (counter.name)); - counter_decl.modifiers = CCodeModifiers.STATIC; - cfile.add_type_member_declaration (counter_decl); - - // nesting level for recursive functions - var level = new CCodeIdentifier (prefix + "_level"); - var level_decl = new CCodeDeclaration (get_ccode_name (int_type)); - level_decl.add_declarator (new CCodeVariableDeclarator (level.name)); - level_decl.modifiers = CCodeModifiers.STATIC; - cfile.add_type_member_declaration (level_decl); - - var timer = new CCodeIdentifier (prefix + "_timer"); - var timer_decl = new CCodeDeclaration ("GTimer *"); - timer_decl.add_declarator (new CCodeVariableDeclarator (timer.name)); - timer_decl.modifiers = CCodeModifiers.STATIC; - cfile.add_type_member_declaration (timer_decl); - - var constructor = new CCodeFunction (prefix + "_init"); - constructor.modifiers = CCodeModifiers.STATIC | CCodeModifiers.CONSTRUCTOR; - cfile.add_function_declaration (constructor); - push_function (constructor); - - ccode.add_assignment (timer, new CCodeFunctionCall (new CCodeIdentifier ("g_timer_new"))); - - var stop_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_stop")); - stop_call.add_argument (timer); - ccode.add_expression (stop_call); - - pop_function (); - cfile.add_function (constructor); - - - var destructor = new CCodeFunction (prefix + "_exit"); - destructor.modifiers = CCodeModifiers.STATIC | CCodeModifiers.DESTRUCTOR; - cfile.add_function_declaration (destructor); - push_function (destructor); - - var elapsed_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_elapsed")); - elapsed_call.add_argument (timer); - elapsed_call.add_argument (new CCodeConstant ("NULL")); - - var print_call = new CCodeFunctionCall (new CCodeIdentifier ("fprintf")); - print_call.add_argument (new CCodeIdentifier ("stderr")); - print_call.add_argument (new CCodeConstant ("\"%s: %%gs (%%d calls)\\n\"".printf (m.get_full_name ()))); - print_call.add_argument (elapsed_call); - print_call.add_argument (counter); - ccode.add_expression (print_call); - - pop_function (); - cfile.add_function (destructor); - } - - CCodeFunction function; - function = new CCodeFunction (real_name); - - if (m.is_inline) { - function.modifiers |= CCodeModifiers.INLINE; - } - - if (m.entry_point) { - function.modifiers |= CCodeModifiers.STATIC; - } - - var cparam_map = new HashMap (direct_hash, direct_equal); - - generate_cparameters (m, cfile, cparam_map, function); - - // generate *_real_* functions for virtual methods - // also generate them for abstract methods of classes to prevent faulty subclassing - if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) { - if (!m.coroutine) { - if (m.base_method != null || m.base_interface_method != null) { - // declare *_real_* function - function.modifiers |= CCodeModifiers.STATIC; - cfile.add_function_declaration (function); - } else if (m.is_private_symbol ()) { - function.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && m.is_internal_symbol ()) { - function.modifiers |= CCodeModifiers.INTERNAL; - } - } else { - if (m.body != null) { - function = new CCodeFunction (real_name + "_co", get_ccode_name (bool_type)); - - // data struct to hold parameters, local variables, and the return value - function.add_parameter (new CCodeParameter ("_data_", Symbol.lower_case_to_camel_case (get_ccode_const_name (m)) + "Data*")); - function.modifiers |= CCodeModifiers.STATIC; - cfile.add_function_declaration (function); - } - } - } - - if (m.comment != null) { - cfile.add_type_member_definition (new CCodeComment (m.comment.content)); - } - - push_function (function); - - unowned CCodeBlock? co_switch_block = null; - - // generate *_real_* functions for virtual methods - // also generate them for abstract methods of classes to prevent faulty subclassing - if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) { - if (m.body != null) { - if (m.coroutine) { - ccode.open_switch (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_")); - - // initial coroutine state - ccode.add_case (new CCodeConstant ("0")); - ccode.add_goto ("_state_0"); - - co_switch_block = ccode.current_block; - - ccode.close (); - - // coroutine body - ccode.add_label ("_state_0"); - } - - if (m.closure) { - // add variables for parent closure blocks - // as closures only have one parameter for the innermost closure block - var closure_block = current_closure_block; - int block_id = get_block_id (closure_block); - while (true) { - var parent_closure_block = next_closure_block (closure_block.parent_symbol); - if (parent_closure_block == null) { - break; - } - int parent_block_id = get_block_id (parent_closure_block); - - var parent_data = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)); - ccode.add_declaration ("Block%dData*".printf (parent_block_id), new CCodeVariableDeclarator ("_data%d_".printf (parent_block_id))); - ccode.add_assignment (new CCodeIdentifier ("_data%d_".printf (parent_block_id)), parent_data); - - closure_block = parent_closure_block; - block_id = parent_block_id; - } - - // add self variable for closures - // as closures have block data parameter - if (m.binding == MemberBinding.INSTANCE) { - var cself = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "self"); - ccode.add_declaration (get_ccode_name (SemanticAnalyzer.get_data_type_for_symbol (current_type_symbol)), new CCodeVariableDeclarator ("self")); - ccode.add_assignment (new CCodeIdentifier ("self"), cself); - } - - // allow capturing generic type parameters - var data_var = get_variable_cexpression ("_data%d_".printf (block_id)); - foreach (var type_param in m.get_type_parameters ()) { - var type = get_ccode_type_id (type_param); - var dup_func = get_ccode_copy_function (type_param); - var destroy_func = get_ccode_destroy_function (type_param); - ccode.add_declaration ("GType", new CCodeVariableDeclarator (type)); - ccode.add_declaration ("GBoxedCopyFunc", new CCodeVariableDeclarator (dup_func)); - ccode.add_declaration ("GDestroyNotify", new CCodeVariableDeclarator (destroy_func)); - ccode.add_assignment (new CCodeIdentifier (type), new CCodeMemberAccess.pointer (data_var, type)); - ccode.add_assignment (new CCodeIdentifier (dup_func), new CCodeMemberAccess.pointer (data_var, dup_func)); - ccode.add_assignment (new CCodeIdentifier (destroy_func), new CCodeMemberAccess.pointer (data_var, destroy_func)); - } - } else if (m.parent_symbol is Class && !m.coroutine) { - var cl = (Class) m.parent_symbol; - if (m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) { - Method base_method; - ReferenceType base_expression_type; - if (m.overrides && m.base_method != null) { - base_method = m.base_method; - base_expression_type = new ObjectType ((Class) base_method.parent_symbol); - } else { - base_method = m.base_interface_method; - base_expression_type = new ObjectType ((Interface) base_method.parent_symbol); - } - var self_target_type = new ObjectType (cl); - CCodeExpression cself = get_cvalue_ (transform_value (new GLibValue (base_expression_type, new CCodeIdentifier ("base"), true), self_target_type, m)); - - ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self")); - ccode.add_assignment (new CCodeIdentifier ("self"), cself); - } else if (m.binding == MemberBinding.INSTANCE - && !(m is CreationMethod) - && m.base_method == null && m.base_interface_method == null) { - create_method_type_check_statement (m, creturn_type, cl, true, "self"); - } - } - - foreach (Parameter param in m.get_parameters ()) { - if (param.ellipsis || param.params_array) { - if (param.params_array) { - append_params_array (m); - } - break; - } - - if (param.direction != ParameterDirection.OUT) { - unowned TypeSymbol? t = param.variable_type.type_symbol; - if (t != null && (t.is_reference_type () || param.variable_type.is_real_struct_type ())) { - var cname = get_ccode_name (param); - if (param.direction == ParameterDirection.REF && !param.variable_type.is_real_struct_type ()) { - cname = "*"+cname; - } - create_method_type_check_statement (m, creturn_type, t, !param.variable_type.nullable, cname); - } - } else if (!m.coroutine) { - // declare local variable for out parameter to allow assignment even when caller passes NULL - var vardecl = new CCodeVariableDeclarator.zero ("_vala_%s".printf (get_ccode_name (param)), default_value_for_type (param.variable_type, true), get_ccode_declarator_suffix (param.variable_type)); - ccode.add_declaration (get_ccode_name (param.variable_type), vardecl); - - if (param.variable_type is ArrayType) { - // create variables to store array dimensions - var array_type = (ArrayType) param.variable_type; - - if (!array_type.fixed_length) { - var length_ctype = get_ccode_array_length_type (param); - for (int dim = 1; dim <= array_type.rank; dim++) { - vardecl = new CCodeVariableDeclarator.zero (get_array_length_cname ("_vala_%s".printf (get_ccode_name (param)), dim), new CCodeConstant ("0")); - ccode.add_declaration (length_ctype, vardecl); - } - } - } else if (param.variable_type is DelegateType) { - var deleg_type = (DelegateType) param.variable_type; - if (deleg_type.delegate_symbol.has_target) { - // create variable to store delegate target - vardecl = new CCodeVariableDeclarator.zero ("_vala_%s".printf (get_ccode_delegate_target_name (param)), new CCodeConstant ("NULL")); - ccode.add_declaration (get_ccode_name (delegate_target_type), vardecl); - - if (deleg_type.is_disposable ()) { - vardecl = new CCodeVariableDeclarator.zero ("_vala_%s".printf (get_ccode_delegate_target_destroy_notify_name (param)), new CCodeConstant ("NULL")); - ccode.add_declaration (get_ccode_name (delegate_target_destroy_type), vardecl); - } - } - } - } - } - - if (m is CreationMethod) { - if (in_gobject_creation_method) { - if (!m.coroutine) { - ccode.add_declaration ("%s *".printf (get_ccode_name (current_type_symbol)), new CCodeVariableDeclarator.zero ("self", new CCodeConstant ("NULL"))); - } - } else if (is_gtypeinstance_creation_method (m)) { - var cl = (Class) m.parent_symbol; - ccode.add_declaration (get_ccode_name (cl) + "*", new CCodeVariableDeclarator.zero ("self", new CCodeConstant ("NULL"))); - - if (cl.is_fundamental () && !((CreationMethod) m).chain_up) { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_create_instance")); - ccall.add_argument (get_variable_cexpression ("object_type")); - ccode.add_assignment (get_this_cexpression (), new CCodeCastExpression (ccall, get_ccode_name (cl) + "*")); - - /* type, dup func, and destroy func fields for generic types */ - var priv_access = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"); - foreach (TypeParameter type_param in current_class.get_type_parameters ()) { - var type = get_ccode_type_id (type_param); - var dup_func = get_ccode_copy_function (type_param); - var destroy_func = get_ccode_destroy_function (type_param); - ccode.add_assignment (new CCodeMemberAccess.pointer (priv_access, type), new CCodeIdentifier (type)); - ccode.add_assignment (new CCodeMemberAccess.pointer (priv_access, dup_func), new CCodeIdentifier (dup_func)); - ccode.add_assignment (new CCodeMemberAccess.pointer (priv_access, destroy_func), new CCodeIdentifier (destroy_func)); - } - } - } else if (current_type_symbol is Class) { - var cl = (Class) m.parent_symbol; - if (!m.coroutine) { - ccode.add_declaration (get_ccode_name (cl) + "*", new CCodeVariableDeclarator ("self")); - } - - if (!((CreationMethod) m).chain_up) { - // TODO implicitly chain up to base class as in add_object_creation - // g_slice_new0 needs glib.h - cfile.add_include ("glib.h"); - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0")); - ccall.add_argument (new CCodeIdentifier (get_ccode_name (cl))); - ccode.add_assignment (get_this_cexpression (), ccall); - } - - if (cl.base_class == null && !(((CreationMethod) m).chain_up && cl.is_compact)) { - var cinitcall = new CCodeFunctionCall (new CCodeIdentifier ("%s_instance_init".printf (get_ccode_lower_case_name (cl, null)))); - cinitcall.add_argument (get_this_cexpression ()); - if (!cl.is_compact) { - cinitcall.add_argument (new CCodeConstant ("NULL")); - } - ccode.add_expression (cinitcall); - } - } else if (m.parent_symbol is Struct) { - unowned Struct st = (Struct) m.parent_symbol; - if (st.is_simple_type ()) { - var vardecl = new CCodeVariableDeclarator ("self", default_value_for_type (creturn_type, true)); - vardecl.init0 = true; - ccode.add_declaration (get_ccode_name (creturn_type), vardecl); - } else if (!((CreationMethod) m).chain_up) { - // memset needs string.h - cfile.add_include ("string.h"); - var czero = new CCodeFunctionCall (new CCodeIdentifier ("memset")); - czero.add_argument (new CCodeIdentifier ("self")); - czero.add_argument (new CCodeConstant ("0")); - czero.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (get_ccode_name (st)))); - ccode.add_expression (czero); - } - } else { - Report.error (m.source_reference, "internal: creation method not supported in `%s'", m.parent_symbol.get_full_name ()); - } - } - - if (context.module_init_method == m && in_plugin) { - // GTypeModule-based plug-in, register types - register_plugin_types (context.root, new HashSet ()); - } - - foreach (Expression precondition in m.get_preconditions ()) { - create_precondition_statement (m, creturn_type, precondition); - } - } - } - - if (profile) { - string prefix = "_vala_prof_%s".printf (real_name); - - var level = new CCodeIdentifier (prefix + "_level"); - ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, level))); - - var counter = new CCodeIdentifier (prefix + "_counter"); - ccode.add_expression (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, counter)); - - var timer = new CCodeIdentifier (prefix + "_timer"); - var cont_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_continue")); - cont_call.add_argument (timer); - ccode.add_expression (cont_call); - - ccode.close (); - } - - if (m.body != null) { - m.body.emit (this); - - if (co_switch_block != null) { - // after counting the number of yields for coroutines, append the case statements to the switch - var old_block = ccode.current_block; - ccode.current_block = co_switch_block; - - for (int state = 1; state < emit_context.next_coroutine_state; state++) { - ccode.add_case (new CCodeConstant (state.to_string ())); - ccode.add_goto ("_state_%d".printf (state)); - } - - // let gcc know that this can't happen - ccode.add_default (); - ccode.add_expression (new CCodeFunctionCall (new CCodeIdentifier ("g_assert_not_reached"))); - - ccode.current_block = old_block; - co_switch_block = null; - } - } - - // we generate the same code if we see a return statement, this handles the case without returns - if (profile && m.return_type is VoidType) { - string prefix = "_vala_prof_%s".printf (real_name); - - var level = new CCodeIdentifier (prefix + "_level"); - ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeUnaryExpression (CCodeUnaryOperator.PREFIX_DECREMENT, level))); - - var timer = new CCodeIdentifier (prefix + "_timer"); - - var stop_call = new CCodeFunctionCall (new CCodeIdentifier ("g_timer_stop")); - stop_call.add_argument (timer); - ccode.add_expression (stop_call); - - ccode.close (); - } - - // generate *_real_* functions for virtual methods - // also generate them for abstract methods of classes to prevent faulty subclassing - if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) { - /* Methods imported from a plain C file don't - * have a body, e.g. Vala.Parser.parse_file () */ - if (m.body != null) { - if (current_method_inner_error) { - cfile.add_include ("glib.h"); - /* always separate error parameter and inner_error local variable - * as error may be set to NULL but we're always interested in inner errors - */ - if (m.coroutine) { - // no initialization necessary, closure struct is zeroed - closure_struct.add_field ("GError*", "_inner_error%d_".printf (current_inner_error_id)); - } else { - ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL"))); - } - } - - // For non-void return-types GAsyncModule.visit_return_statement () will take care of this - if (m.return_type is VoidType && m.coroutine) { - // epilogue - complete_async (); - } - - if (m is CreationMethod) { - if (current_type_symbol is Class && !m.coroutine) { - CCodeExpression cresult = new CCodeIdentifier ("self"); - if (get_ccode_type (m) != null) { - cresult = new CCodeCastExpression (cresult, get_ccode_type (m)); - } - - ccode.add_return (cresult); - } else if (current_type_symbol is Struct && ((Struct) current_type_symbol).is_simple_type ()) { - // constructors return simple type structs by value - ccode.add_return (new CCodeIdentifier ("self")); - } - } - - cfile.add_function (ccode); - } - } - - if (m.is_abstract && current_type_symbol is Class) { - // generate helpful error message if a sublcass does not implement an abstract method. - // This is only meaningful for subclasses implemented in C since the vala compiler would - // complain during compile time of such en error. - - // add critical warning that this method should not have been called - var cerrorcall = new CCodeFunctionCall (new CCodeIdentifier ("g_critical")); - if (!((Class) current_type_symbol).is_compact) { - var type_from_instance_call = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE")); - type_from_instance_call.add_argument (new CCodeIdentifier ("self")); - - var type_name_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name")); - type_name_call.add_argument (type_from_instance_call); - - cerrorcall.add_argument (new CCodeConstant ("\"Type `%%s' does not implement abstract method `%s'\"".printf (get_ccode_name (m)))); - cerrorcall.add_argument (type_name_call); - } else { - cerrorcall.add_argument (new CCodeConstant ("\"Abstract method `%s' is not implemented\"".printf (get_ccode_name (m)))); - } - - ccode.add_expression (cerrorcall); - - // add return statement - return_default_value (creturn_type); - - cfile.add_function (ccode); - } - - if (current_method_return && !(m.return_type is VoidType) && !m.return_type.is_real_non_null_struct_type () && !m.coroutine) { - CCodeVariableDeclarator vardecl; - if (m.is_abstract) { - vardecl = new CCodeVariableDeclarator ("result", default_value_for_type (m.return_type, true)); - vardecl.init0 = true; - } else { - vardecl = new CCodeVariableDeclarator ("result"); - } - ccode.add_declaration (get_ccode_name (m.return_type), vardecl); - } - - pop_context (); - - if ((m.is_abstract || m.is_virtual) && !m.coroutine - && !get_ccode_no_wrapper (m) - // If the method is a signal handler, the declaration is not needed. - // the name should be reserved for the emitter! - && m.signal_reference == null) { - - cparam_map = new HashMap (direct_hash, direct_equal); - var carg_map = new HashMap (direct_hash, direct_equal); - - generate_vfunc (m, creturn_type, cparam_map, carg_map); - } - - if (m.entry_point) { - // m is possible entry point, add appropriate startup code - - if (m.coroutine) { - // add callback for async main - var asyncmain_callback = new CCodeFunction (real_name + "_callback"); - asyncmain_callback.add_parameter (new CCodeParameter ("source_object", "GObject*")); - asyncmain_callback.add_parameter (new CCodeParameter ("res", "GAsyncResult*")); - asyncmain_callback.add_parameter (new CCodeParameter ("user_data", "gpointer")); - asyncmain_callback.modifiers |= CCodeModifiers.STATIC; - - push_function (asyncmain_callback); - ccode.add_declaration ("GMainLoop*", new CCodeVariableDeclarator.zero ("loop", new CCodeIdentifier ("user_data"))); - - // get the return value - var finish_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_real_name (m))); - finish_call.add_argument (new CCodeIdentifier ("res")); - if (m.return_type is VoidType) { - ccode.add_expression (finish_call); - } else { - // save the return value - var asyncmain_result = new CCodeIdentifier (real_name + "_result"); - var asyncmain_result_decl = new CCodeDeclaration (get_ccode_name (int_type)); - asyncmain_result_decl.add_declarator (new CCodeVariableDeclarator (asyncmain_result.name)); - asyncmain_result_decl.modifiers = CCodeModifiers.STATIC; - cfile.add_type_member_declaration (asyncmain_result_decl); - ccode.add_assignment (asyncmain_result, finish_call); - } - - // quit the main loop - var loop_quit_call = new CCodeFunctionCall (new CCodeIdentifier ("g_main_loop_quit")); - loop_quit_call.add_argument (new CCodeIdentifier ("loop")); - ccode.add_expression (loop_quit_call); - - pop_function (); - cfile.add_function (asyncmain_callback); - } - - var cmain = new CCodeFunction ("main", "int"); - cmain.line = function.line; - cmain.add_parameter (new CCodeParameter ("argc", "int")); - cmain.add_parameter (new CCodeParameter ("argv", "char **")); - push_function (cmain); - - if (context.profile == Profile.GOBJECT) { - if (context.mem_profiler) { - var mem_profiler_init_call = new CCodeFunctionCall (new CCodeIdentifier ("g_mem_set_vtable")); - mem_profiler_init_call.line = cmain.line; - mem_profiler_init_call.add_argument (new CCodeConstant ("glib_mem_profiler_table")); - ccode.add_expression (mem_profiler_init_call); - } - } - - var main_call = new CCodeFunctionCall (new CCodeIdentifier (m.coroutine ? real_name : function.name)); - if (m.get_parameters ().size == 1) { - main_call.add_argument (new CCodeIdentifier ("argv")); - main_call.add_argument (new CCodeIdentifier ("argc")); - } - - if (m.coroutine) { - // main method is asynchronous, so we have to setup GMainLoop and run it - var main_loop_new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_main_loop_new")); - main_loop_new_call.add_argument (new CCodeConstantIdentifier ("NULL")); - main_loop_new_call.add_argument (new CCodeConstantIdentifier ("FALSE")); - ccode.add_declaration ("GMainLoop*", new CCodeVariableDeclarator.zero ("loop", main_loop_new_call)); - - // add some more arguments to main_call - main_call.add_argument (new CCodeIdentifier (real_name + "_callback")); - main_call.add_argument (new CCodeIdentifier ("loop")); - ccode.add_expression (main_call); - - var main_loop_run_call = new CCodeFunctionCall (new CCodeIdentifier ("g_main_loop_run")); - main_loop_run_call.add_argument (new CCodeIdentifier ("loop")); - ccode.add_expression (main_loop_run_call); - - var main_loop_unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_main_loop_unref")); - main_loop_unref_call.add_argument (new CCodeIdentifier ("loop")); - ccode.add_expression (main_loop_unref_call); - - if (m.return_type is VoidType) { - // method returns void, always use 0 as exit code - ccode.add_return (new CCodeConstant ("0")); - } else { - // get the saved return value - ccode.add_return (new CCodeIdentifier (real_name + "_result")); - } - } else { - if (m.return_type is VoidType) { - // method returns void, always use 0 as exit code - ccode.add_expression (main_call); - ccode.add_return (new CCodeConstant ("0")); - } else { - ccode.add_return (main_call); - } - } - pop_function (); - cfile.add_function (cmain); - } - - pop_line (); - } - - public virtual CCodeParameter generate_parameter (Parameter param, CCodeFile decl_space, Map cparam_map, Map? carg_map) { - CCodeParameter cparam; - if (!param.ellipsis && !param.params_array) { - generate_type_declaration (param.variable_type, decl_space); - - string? ctypename = get_ccode_type (param); - if (ctypename == null) { - ctypename = get_ccode_name (param.variable_type); - - // pass non-simple structs always by reference - unowned Struct? st = param.variable_type.type_symbol as Struct; - if (st != null) { - if (!st.is_simple_type () && param.direction == ParameterDirection.IN) { - if (st.is_immutable && !param.variable_type.value_owned) { - ctypename = "const " + ctypename; - } - - if (!param.variable_type.nullable) { - ctypename += "*"; - } - } - } - - if (param.direction != ParameterDirection.IN) { - ctypename += "*"; - } - } - - cparam = new CCodeParameter (get_ccode_name (param), ctypename); - if (param.format_arg) { - cparam.modifiers = CCodeModifiers.FORMAT_ARG; - } - } else { - var va_list_name = "_vala_va_list"; - - // Add _first_* parameter for the params array parameter - if (param.params_array) { - var param_type = ((ArrayType) param.variable_type).element_type; - string ctypename = get_ccode_name (param_type); - - generate_type_declaration (param_type, decl_space); - - // pass non-simple structs always by reference - if (param_type.type_symbol is Struct) { - var st = (Struct) param_type.type_symbol; - if (!st.is_simple_type () && param.direction == ParameterDirection.IN) { - if (st.is_immutable && !param.variable_type.value_owned) { - ctypename = "const " + ctypename; - } - - if (!param_type.nullable) { - ctypename += "*"; - } - } - } - - cparam = new CCodeParameter ("_first_%s".printf (get_ccode_name (param)), ctypename); - cparam_map.set (get_param_pos (get_ccode_pos (param) - 0.1, true), cparam); - - va_list_name = "_va_list_%s".printf (get_ccode_name (param)); - } - - if (ellipses_to_valist) { - cparam = new CCodeParameter (va_list_name, "va_list"); - } else { - cparam = new CCodeParameter.with_ellipsis (); - } - } - - cparam_map.set (get_param_pos (get_ccode_pos (param), param.ellipsis || param.params_array), cparam); - if (carg_map != null && !param.ellipsis && !param.params_array) { - carg_map.set (get_param_pos (get_ccode_pos (param), param.ellipsis || param.params_array), get_parameter_cexpression (param)); - } - - return cparam; - } - - public override void generate_cparameters (Method m, CCodeFile decl_space, Map cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, Map? carg_map = null, CCodeFunctionCall? vcall = null, int direction = 3) { - if (m.closure) { - var closure_block = current_closure_block; - int block_id = get_block_id (closure_block); - var instance_param = new CCodeParameter ("_data%d_".printf (block_id), "Block%dData*".printf (block_id)); - cparam_map.set (get_param_pos (get_ccode_instance_pos (m)), instance_param); - } else if (m.parent_symbol is Class && m is CreationMethod) { - var cl = (Class) m.parent_symbol; - if (!cl.is_compact && vcall == null && (direction & 1) == 1) { - cparam_map.set (get_param_pos (get_ccode_instance_pos (m)), new CCodeParameter ("object_type", "GType")); - } - } else if (m.binding == MemberBinding.INSTANCE && (direction != 2 || get_ccode_finish_instance (m))) { - var this_type = SemanticAnalyzer.get_this_type (m); - - generate_type_declaration (this_type, decl_space); - - CCodeParameter instance_param = null; - if (m.base_interface_method != null && !m.is_abstract && !m.is_virtual) { - var base_type = new ObjectType ((Interface) m.base_interface_method.parent_symbol); - instance_param = new CCodeParameter ("base", get_ccode_name (base_type)); - } else if (m.overrides) { - var base_type = new ObjectType ((Class) m.base_method.parent_symbol); - instance_param = new CCodeParameter ("base", get_ccode_name (base_type)); - } else { - unowned Struct? st = m.parent_symbol as Struct; - if (st != null && !st.is_simple_type ()) { - instance_param = new CCodeParameter ("*self", get_ccode_name (this_type)); - } else if (st != null && st.is_simple_type () && m is CreationMethod) { - // constructors return simple type structs by value - } else { - instance_param = new CCodeParameter ("self", get_ccode_name (this_type)); - } - } - if (instance_param != null) { - cparam_map.set (get_param_pos (get_ccode_instance_pos (m)), instance_param); - } - } else if (m.binding == MemberBinding.CLASS) { - var this_type = SemanticAnalyzer.get_this_type (m); - var class_param = new CCodeParameter ("klass", get_ccode_name (this_type)); - cparam_map.set (get_param_pos (get_ccode_instance_pos (m)), class_param); - } - - // memory management for generic types - List? type_parameters = null; - if (is_gtypeinstance_creation_method (m) && (direction & 1) == 1) { - type_parameters = ((Class) m.parent_symbol).get_type_parameters (); - } else if (!m.closure && (direction & 1) == 1) { - type_parameters = m.get_type_parameters (); - } - if (type_parameters != null) { - int type_param_index = 0; - foreach (var type_param in type_parameters) { - var type = get_ccode_type_id (type_param); - var dup_func = get_ccode_copy_function (type_param); - var destroy_func = get_ccode_destroy_function (type_param); - cparam_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeParameter (type, "GType")); - cparam_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeParameter (dup_func, "GBoxedCopyFunc")); - cparam_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeParameter (destroy_func, "GDestroyNotify")); - if (carg_map != null) { - carg_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeIdentifier (type)); - carg_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeIdentifier (dup_func)); - carg_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeIdentifier (destroy_func)); - } - type_param_index++; - } - } - - var needs_format_arg = m.get_format_arg_index () < 0 && (m.printf_format || m.scanf_format); - - CCodeParameter? prev_cparam = null; - foreach (Parameter param in m.get_parameters ()) { - if (param.direction != ParameterDirection.OUT) { - if ((direction & 1) == 0) { - // no in parameters - continue; - } - } else { - if ((direction & 2) == 0) { - // no out parameters - continue; - } - } - - var cparam = generate_parameter (param, decl_space, cparam_map, carg_map); - - // if there is no explicit FormatArg annotation while this method throws an error - // it is required to mark the parameter located right before ellipsis as format-arg - // to account for the parameter shifting caused by the inserted GError parameter - if (needs_format_arg) { - if (prev_cparam != null && cparam.ellipsis) { - prev_cparam.modifiers |= CCodeModifiers.FORMAT_ARG; - } - prev_cparam = cparam; - } - } - - if ((direction & 2) != 0) { - generate_method_result_declaration (m, decl_space, func, cparam_map, carg_map); - } - - // append C parameters in the right order - int last_pos = -1; - int min_pos; - while (true) { - min_pos = -1; - foreach (int pos in cparam_map.get_keys ()) { - if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { - min_pos = pos; - } - } - if (min_pos == -1) { - break; - } - func.add_parameter (cparam_map.get (min_pos)); - if (vdeclarator != null) { - vdeclarator.add_parameter (cparam_map.get (min_pos)); - } - if (vcall != null) { - var arg = carg_map.get (min_pos); - if (arg != null) { - vcall.add_argument (arg); - } - } - last_pos = min_pos; - } - - if (m.printf_format) { - func.modifiers |= CCodeModifiers.PRINTF; - } else if (m.scanf_format) { - func.modifiers |= CCodeModifiers.SCANF; - } - - if (m.version.deprecated) { - func.modifiers |= CCodeModifiers.DEPRECATED; - } - } - - public void generate_vfunc (Method m, DataType return_type, Map cparam_map, Map carg_map, string suffix = "", int direction = 3) { - push_context (new EmitContext ()); - - CCodeFunction vfunc; - if (suffix == "_finish") { - vfunc = new CCodeFunction (get_ccode_finish_name (m)); - } else { - vfunc = new CCodeFunction (get_ccode_name (m)); - } - - CCodeExpression vcast; - if (m.parent_symbol is Interface) { - vcast = new CCodeIdentifier ("_iface_"); - } else { - var cl = (Class) m.parent_symbol; - if (!cl.is_compact) { - vcast = new CCodeIdentifier ("_klass_"); - } else { - vcast = new CCodeIdentifier ("self"); - } - } - - CCodeFunctionCall vcall; - if (suffix == "_finish") { - vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, get_ccode_finish_vfunc_name (m))); - } else { - vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, get_ccode_vfunc_name (m))); - } - - carg_map.set (get_param_pos (get_ccode_instance_pos (m)), new CCodeIdentifier ("self")); - - generate_cparameters (m, cfile, cparam_map, vfunc, null, carg_map, vcall, direction); - - push_function (vfunc); - - if (m.return_type.is_non_null_simple_type () && default_value_for_type (m.return_type, false) == null) { - // the type check will use the result variable - CCodeVariableDeclarator vardecl; - if (m.is_abstract) { - vardecl = new CCodeVariableDeclarator ("result", default_value_for_type (m.return_type, true)); - vardecl.init0 = true; - } else { - vardecl = new CCodeVariableDeclarator ("result"); - } - ccode.add_declaration (get_ccode_name (m.return_type), vardecl); - } - - // add a typecheck statement for "self" - create_method_type_check_statement (m, return_type, (TypeSymbol) m.parent_symbol, true, "self"); - - foreach (Expression precondition in m.get_preconditions ()) { - create_precondition_statement (m, return_type, precondition); - } - - if (m.parent_symbol is Interface) { - var iface = (Interface) m.parent_symbol; - - var vcastcall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (iface))); - ((CCodeFunctionCall) vcastcall).add_argument (new CCodeIdentifier ("self")); - ccode.add_declaration ("%s*".printf (get_ccode_type_name (iface)), new CCodeVariableDeclarator ("_iface_")); - ccode.add_assignment (vcast, vcastcall); - } else { - var cl = (Class) m.parent_symbol; - if (!cl.is_compact) { - var vcastcall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (cl))); - ((CCodeFunctionCall) vcastcall).add_argument (new CCodeIdentifier ("self")); - ccode.add_declaration ("%s*".printf (get_ccode_type_name (cl)), new CCodeVariableDeclarator ("_klass_")); - ccode.add_assignment (vcast, vcastcall); - } - } - - // check if vfunc pointer is properly set - ccode.open_if (vcall.call); - - if (return_type is VoidType || return_type.is_real_non_null_struct_type ()) { - ccode.add_expression (vcall); - } else if (m.get_postconditions ().size == 0) { - /* pass method return value */ - ccode.add_return (vcall); - } else { - /* store method return value for postconditions */ - ccode.add_declaration (get_creturn_type (m, get_ccode_name (return_type)), new CCodeVariableDeclarator ("result")); - ccode.add_assignment (new CCodeIdentifier ("result"), vcall); - } - - if (m.get_postconditions ().size > 0) { - foreach (Expression postcondition in m.get_postconditions ()) { - create_postcondition_statement (postcondition); - } - - if (!(return_type is VoidType)) { - ccode.add_return (new CCodeIdentifier ("result")); - } - } - - ccode.close (); - - if (m.return_type.is_non_null_simple_type () && default_value_for_type (m.return_type, false) == null) { - ccode.add_return (new CCodeIdentifier ("result")); - } else if (!(return_type is VoidType)) { - ccode.add_return (default_value_for_type (return_type, false, true)); - } - - if (m.printf_format) { - vfunc.modifiers |= CCodeModifiers.PRINTF; - } else if (m.scanf_format) { - vfunc.modifiers |= CCodeModifiers.SCANF; - } - - if (m.version.deprecated) { - vfunc.modifiers |= CCodeModifiers.DEPRECATED; - } - - cfile.add_function (vfunc); - - pop_context (); - } - - private void create_method_type_check_statement (Method m, DataType return_type, TypeSymbol t, bool non_null, string var_name) { - if (!m.coroutine) { - create_type_check_statement (m, return_type, t, non_null, var_name); - } - } - - private void create_precondition_statement (Method m, DataType ret_type, Expression precondition) { - is_in_method_precondition = true; - - var ccheck = new CCodeFunctionCall (); - - precondition.emit (this); - - ccheck.add_argument (get_cvalue (precondition)); - - string message = ((string) precondition.source_reference.begin.pos).substring (0, (int) (precondition.source_reference.end.pos - precondition.source_reference.begin.pos)); - ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (message.replace ("\n", " ").escape ("")))); - requires_assert = true; - - if (m is CreationMethod) { - if (m.parent_symbol is Class) { - ccheck.call = new CCodeIdentifier ("_vala_return_val_if_fail"); - ccheck.add_argument (new CCodeConstant ("NULL")); - } else { - // creation method of struct - ccheck.call = new CCodeIdentifier ("_vala_return_if_fail"); - } - } else if (m.coroutine) { - // _co function - ccheck.call = new CCodeIdentifier ("_vala_return_val_if_fail"); - ccheck.add_argument (new CCodeConstant ("FALSE")); - } else if (ret_type is VoidType) { - /* void function */ - ccheck.call = new CCodeIdentifier ("_vala_return_if_fail"); - } else { - ccheck.call = new CCodeIdentifier ("_vala_return_val_if_fail"); - - var cdefault = default_value_for_type (ret_type, false); - if (cdefault != null) { - ccheck.add_argument (cdefault); - } else { - return; - } - } - - ccode.add_expression (ccheck); - - current_method_return = true; - is_in_method_precondition = false; - } - - public override void visit_creation_method (CreationMethod m) { - push_line (m.source_reference); - - unowned Class? cl = m.parent_symbol as Class; - if (cl != null && !cl.is_compact) { - ellipses_to_valist = true; - } else { - ellipses_to_valist = false; - } - visit_method (m); - ellipses_to_valist = false; - - if ((!m.external && m.external_package) || m.source_type == SourceFileType.FAST) { - pop_line (); - return; - } - - // do not generate _new functions for creation methods of abstract classes - if (current_type_symbol is Class && !current_class.is_compact && !current_class.is_abstract) { - // _new function - create_aux_constructor (m, get_ccode_name (m), false); - - // _construct function (if visit_method generated _constructv) - if (m.is_variadic ()) { - create_aux_constructor (m, get_ccode_real_name (m), true); - } - } - - pop_line (); - } - - private void create_aux_constructor (CreationMethod m, string func_name, bool self_as_first_parameter) { - var vfunc = new CCodeFunction (func_name); - if (m.is_private_symbol ()) { - vfunc.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && m.is_internal_symbol ()) { - vfunc.modifiers |= CCodeModifiers.INTERNAL; - } - - var cparam_map = new HashMap (direct_hash, direct_equal); - var carg_map = new HashMap (direct_hash, direct_equal); - - push_function (vfunc); - - string constructor = (m.is_variadic ()) ? get_ccode_constructv_name (m) : get_ccode_real_name (m); - var vcall = new CCodeFunctionCall (new CCodeIdentifier (constructor)); - - if (self_as_first_parameter) { - cparam_map.set (get_param_pos (get_ccode_instance_pos (m)), new CCodeParameter ("object_type", "GType")); - vcall.add_argument (get_variable_cexpression ("object_type")); - } else { - vcall.add_argument (new CCodeIdentifier (get_ccode_type_id (current_class))); - } - - - generate_cparameters (m, cfile, cparam_map, vfunc, null, carg_map, vcall); - - if (m.is_variadic ()) { - int last_pos = -1; - int second_last_pos = -1; - foreach (int pos in cparam_map.get_keys ()) { - if (pos > last_pos) { - second_last_pos = last_pos; - last_pos = pos; - } else if (pos > second_last_pos) { - second_last_pos = pos; - } - } - - var carg = carg_map.get (second_last_pos); - if (carg == null) { - // params arrays have an implicit first argument, refer to the cparameter name - carg = new CCodeIdentifier (cparam_map.get (second_last_pos).name); - vcall.add_argument (carg); - } - - var vastart = new CCodeFunctionCall (new CCodeIdentifier ("va_start")); - vastart.add_argument (new CCodeIdentifier ("_vala_va_list_obj")); - vastart.add_argument (carg); - - ccode.add_declaration ("va_list", new CCodeVariableDeclarator ("_vala_va_list_obj")); - ccode.add_expression (vastart); - - vcall.add_argument (new CCodeIdentifier("_vala_va_list_obj")); - } - - ccode.add_return (vcall); - - pop_function (); - - cfile.add_function (vfunc); - } -} - -// vim:sw=8 noet diff --git a/src/codegen/valaccodestructmodule.vala b/src/codegen/valaccodestructmodule.vala deleted file mode 100644 index 9c1e71310..000000000 --- a/src/codegen/valaccodestructmodule.vala +++ /dev/null @@ -1,369 +0,0 @@ -/* valaccodestructmodule.vala - * - * Copyright (C) 2006-2009 Jürg Billeter - * Copyright (C) 2006-2008 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.1 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 - * Raffaele Sandrini - */ - -using GLib; - -public abstract class Vala.CCodeStructModule : CCodeBaseModule { - public override void generate_struct_declaration (Struct st, CCodeFile decl_space) { - if (add_symbol_declaration (decl_space, st, get_ccode_name (st))) { - return; - } - - if (st.base_struct != null) { - generate_struct_declaration (st.base_struct, decl_space); - } else if (!st.external_package) { - // custom simple type structs cannot have a type id which depends on head-allocation - if (st.get_attribute ("SimpleType") != null && !st.has_attribute_argument ("CCode", "type_id")) { - st.set_attribute_bool ("CCode", "has_type_id", false); - } - } - - if (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ()) { - string typename; - // See GTypeModule.visit_struct() - if (st.base_struct != null) { - typename = get_ccode_name (st.base_struct); - } else if (st.is_boolean_type ()) { - // typedef for boolean types - decl_space.add_include ("stdbool.h"); - typename = "bool"; - } else if (st.is_integer_type ()) { - // typedef for integral types - decl_space.add_include ("stdint.h"); - typename = "%sint%d_t".printf (st.signed ? "" : "u", st.width); - } else if (st.is_floating_type ()) { - // typedef for floating types - typename = (st.width == 64 ? "double" : "float"); - } else { - assert_not_reached (); - } - decl_space.add_type_declaration (new CCodeTypeDefinition (typename, new CCodeVariableDeclarator (get_ccode_name (st)))); - return; - } - - if (context.profile == Profile.GOBJECT) { - if (get_ccode_has_type_id (st)) { - decl_space.add_include ("glib-object.h"); - decl_space.add_type_declaration (new CCodeNewline ()); - var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (st, null)); - decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (st), macro)); - - var type_fun = new StructRegisterFunction (st); - type_fun.init_from_type (context, false, true); - decl_space.add_type_member_declaration (type_fun.get_declaration ()); - - requires_vala_extern = true; - } - } - - if (st.base_struct == null) { - decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (st)), new CCodeVariableDeclarator (get_ccode_name (st)))); - } else { - decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (st.base_struct), new CCodeVariableDeclarator (get_ccode_name (st)))); - } - - var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (st))); - - if (st.version.deprecated) { - if (context.profile == Profile.GOBJECT) { - decl_space.add_include ("glib.h"); - } - instance_struct.modifiers |= CCodeModifiers.DEPRECATED; - } - - foreach (Field f in st.get_fields ()) { - if (f.binding == MemberBinding.INSTANCE) { - append_field (instance_struct, f, decl_space); - } - } - - if (st.base_struct == null) { - decl_space.add_type_definition (instance_struct); - } - - if (st.is_simple_type ()) { - return; - } - - var function = new CCodeFunction (get_ccode_dup_function (st), get_ccode_name (st) + "*"); - if (st.is_private_symbol ()) { - function.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && st.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } else { - function.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*")); - decl_space.add_function_declaration (function); - - function = new CCodeFunction (get_ccode_free_function (st), "void"); - if (st.is_private_symbol ()) { - function.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && st.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } else { - function.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*")); - decl_space.add_function_declaration (function); - - if (st.is_disposable ()) { - function = new CCodeFunction (get_ccode_copy_function (st), "void"); - if (st.is_private_symbol ()) { - function.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && st.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } else { - function.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*")); - function.add_parameter (new CCodeParameter ("dest", get_ccode_name (st) + "*")); - decl_space.add_function_declaration (function); - - function = new CCodeFunction (get_ccode_destroy_function (st), "void"); - if (st.is_private_symbol ()) { - function.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && st.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } else { - function.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*")); - decl_space.add_function_declaration (function); - } - } - - public override void visit_struct (Struct st) { - push_context (new EmitContext (st)); - push_line (st.source_reference); - - var old_instance_finalize_context = instance_finalize_context; - instance_finalize_context = new EmitContext (); - - generate_struct_declaration (st, cfile); - - if (!st.is_internal_symbol ()) { - generate_struct_declaration (st, header_file); - } - if (!st.is_private_symbol ()) { - generate_struct_declaration (st, internal_header_file); - } - - if (!st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) { - if (st.is_disposable ()) { - begin_struct_destroy_function (st); - } - } - - st.accept_children (this); - - if (!st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) { - if (st.is_disposable ()) { - add_struct_copy_function (st); - add_struct_destroy_function (st); - } - - if (!st.is_simple_type ()) { - add_struct_dup_function (st); - add_struct_free_function (st); - } - } - - instance_finalize_context = old_instance_finalize_context; - - pop_line (); - pop_context (); - } - - void add_struct_dup_function (Struct st) { - var function = new CCodeFunction (get_ccode_dup_function (st), get_ccode_name (st) + "*"); - if (st.access == SymbolAccessibility.PRIVATE) { - function.modifiers = CCodeModifiers.STATIC; - } - - function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*")); - - push_function (function); - - ccode.add_declaration (get_ccode_name (st) + "*", new CCodeVariableDeclarator ("dup")); - - if (context.profile == Profile.GOBJECT) { - // g_new0 needs glib.h - cfile.add_include ("glib.h"); - var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new0")); - creation_call.add_argument (new CCodeConstant (get_ccode_name (st))); - creation_call.add_argument (new CCodeConstant ("1")); - ccode.add_assignment (new CCodeIdentifier ("dup"), creation_call); - } else if (context.profile == Profile.POSIX) { - // calloc needs stdlib.h - cfile.add_include ("stdlib.h"); - - var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - sizeof_call.add_argument (new CCodeConstant (get_ccode_name (st))); - - var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("calloc")); - creation_call.add_argument (new CCodeConstant ("1")); - creation_call.add_argument (sizeof_call); - ccode.add_assignment (new CCodeIdentifier ("dup"), creation_call); - } - - if (st.is_disposable ()) { - var copy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_copy_function (st))); - copy_call.add_argument (new CCodeIdentifier ("self")); - copy_call.add_argument (new CCodeIdentifier ("dup")); - ccode.add_expression (copy_call); - } else { - cfile.add_include ("string.h"); - - var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - sizeof_call.add_argument (new CCodeConstant (get_ccode_name (st))); - - var copy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy")); - copy_call.add_argument (new CCodeIdentifier ("dup")); - copy_call.add_argument (new CCodeIdentifier ("self")); - copy_call.add_argument (sizeof_call); - ccode.add_expression (copy_call); - } - - ccode.add_return (new CCodeIdentifier ("dup")); - - pop_function (); - - cfile.add_function (function); - } - - void add_struct_free_function (Struct st) { - var function = new CCodeFunction (get_ccode_free_function (st), "void"); - if (st.is_private_symbol ()) { - function.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && st.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } - - function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*")); - - push_function (function); - - if (st.is_disposable ()) { - var destroy_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_destroy_function (st))); - destroy_call.add_argument (new CCodeIdentifier ("self")); - ccode.add_expression (destroy_call); - } - - if (context.profile == Profile.GOBJECT) { - // g_free needs glib.h - cfile.add_include ("glib.h"); - var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free")); - free_call.add_argument (new CCodeIdentifier ("self")); - ccode.add_expression (free_call); - } else if (context.profile == Profile.POSIX) { - // free needs stdlib.h - cfile.add_include ("stdlib.h"); - var free_call = new CCodeFunctionCall (new CCodeIdentifier ("free")); - free_call.add_argument (new CCodeIdentifier ("self")); - ccode.add_expression (free_call); - } - - pop_function (); - - cfile.add_function (function); - } - - void add_struct_copy_function (Struct st) { - var function = new CCodeFunction (get_ccode_copy_function (st), "void"); - if (st.is_private_symbol ()) { - function.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && st.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } - - function.add_parameter (new CCodeParameter ("self", "const " + get_ccode_name (st) + "*")); - function.add_parameter (new CCodeParameter ("dest", get_ccode_name (st) + "*")); - - push_function (function); - - var dest_struct = new GLibValue (SemanticAnalyzer.get_data_type_for_symbol (st), new CCodeIdentifier ("(*dest)"), true); - unowned Struct sym = st; - while (sym.base_struct != null) { - sym = sym.base_struct; - } - foreach (var f in sym.get_fields ()) { - if (f.binding == MemberBinding.INSTANCE) { - var value = load_field (f, load_this_parameter ((TypeSymbol) st)); - if ((!(f.variable_type is DelegateType) || get_ccode_delegate_target (f)) && requires_copy (f.variable_type)) { - value = copy_value (value, f); - if (value == null) { - // error case, continue to avoid critical - continue; - } - } - store_field (f, dest_struct, value); - } - } - - pop_function (); - - cfile.add_function (function); - } - - void begin_struct_destroy_function (Struct st) { - push_context (instance_finalize_context); - - var function = new CCodeFunction (get_ccode_destroy_function (st), "void"); - if (st.is_private_symbol ()) { - function.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && st.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } - - function.add_parameter (new CCodeParameter ("self", get_ccode_name (st) + "*")); - - push_function (function); - - pop_context (); - } - - void add_struct_destroy_function (Struct st) { - unowned Struct sym = st; - while (sym.base_struct != null) { - sym = sym.base_struct; - } - if (st != sym) { - push_context (instance_finalize_context); - - var destroy_func = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_destroy_function (sym))); - destroy_func.add_argument (new CCodeIdentifier ("self")); - ccode.add_expression (destroy_func); - - pop_context (); - } - - cfile.add_function (instance_finalize_context.ccode); - } -} - diff --git a/src/codegen/valaclassregisterfunction.vala b/src/codegen/valaclassregisterfunction.vala deleted file mode 100644 index 625ac12a5..000000000 --- a/src/codegen/valaclassregisterfunction.vala +++ /dev/null @@ -1,202 +0,0 @@ -/* valaclassregisterfunction.vala - * - * Copyright (C) 2006-2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * C function to register a class at runtime. - */ -public class Vala.ClassRegisterFunction : TypeRegisterFunction { - /** - * Specifies the class to be registered. - */ - public weak Class class_reference { get; set; } - - /** - * Creates a new C function to register the specified class at runtime. - * - * @param cl a class - * @return newly created class register function - */ - public ClassRegisterFunction (Class cl) { - class_reference = cl; - } - - public override TypeSymbol get_type_declaration () { - return class_reference; - } - - public override string get_type_struct_name () { - return get_ccode_type_name (class_reference); - } - - public override string get_base_init_func_name () { - if (class_reference.class_constructor != null) { - return "%s_base_init".printf (get_ccode_lower_case_name (class_reference, null)); - } else { - return "NULL"; - } - } - - public override string get_class_finalize_func_name () { - if (class_reference.static_destructor != null) { - return "%s_class_finalize".printf (get_ccode_lower_case_name (class_reference, null)); - } else { - return "NULL"; - } - } - - public override string get_base_finalize_func_name () { - if (class_reference.class_destructor != null) { - return "%s_base_finalize".printf (get_ccode_lower_case_name (class_reference, null)); - } else { - return "NULL"; - } - } - - public override string get_class_init_func_name () { - return "%s_class_init".printf (get_ccode_lower_case_name (class_reference, null)); - } - - public override string get_instance_struct_size () { - return "sizeof (%s)".printf (get_ccode_name (class_reference)); - } - - public override string get_instance_init_func_name () { - return "%s_instance_init".printf (get_ccode_lower_case_name (class_reference, null)); - } - - public override string get_parent_type_name () { - return get_ccode_type_id (class_reference.base_class); - } - - public override string get_type_flags () { - if (class_reference.is_abstract) { - return "G_TYPE_FLAG_ABSTRACT"; - } else if (CodeContext.get ().require_glib_version (2, 70) && class_reference.is_sealed) { - return "G_TYPE_FLAG_FINAL"; - } else { - return "0"; - } - } - - public override SymbolAccessibility get_accessibility () { - return class_reference.access; - } - - public override string? get_gtype_value_table_init_function_name () { - bool is_fundamental = !class_reference.is_compact && class_reference.base_class == null; - if ( is_fundamental ) - return "%s_init".printf (get_ccode_lower_case_name (class_reference, "value_")); - - return null; - } - - public override string? get_gtype_value_table_free_function_name () { - bool is_fundamental = !class_reference.is_compact && class_reference.base_class == null; - if ( is_fundamental ) - return "%s_free_value".printf (get_ccode_lower_case_name (class_reference, "value_")); - - return null; - } - - public override string? get_gtype_value_table_copy_function_name () { - bool is_fundamental = !class_reference.is_compact && class_reference.base_class == null; - if ( is_fundamental ) - return "%s_copy_value".printf (get_ccode_lower_case_name (class_reference, "value_")); - - return null; - } - - public override string? get_gtype_value_table_peek_pointer_function_name () { - bool is_fundamental = !class_reference.is_compact && class_reference.base_class == null; - if ( is_fundamental ) - return "%s_peek_pointer".printf (get_ccode_lower_case_name (class_reference, "value_")); - - return null; - } - - public override string? get_gtype_value_table_collect_value_function_name () { - bool is_fundamental = !class_reference.is_compact && class_reference.base_class == null; - if ( is_fundamental ) - return "%s_collect_value".printf (get_ccode_lower_case_name (class_reference, "value_")); - - return null; - } - - public override string? get_gtype_value_table_lcopy_value_function_name () { - bool is_fundamental = !class_reference.is_compact && class_reference.base_class == null; - if ( is_fundamental ) - return "%s_lcopy_value".printf (get_ccode_lower_case_name (class_reference, "value_")); - - return null; - } - - public override CCodeFragment get_type_interface_init_declaration () { - var frag = new CCodeFragment (); - - foreach (DataType base_type in class_reference.get_base_types ()) { - if (!(base_type.type_symbol is Interface)) { - continue; - } - - unowned Interface iface = (Interface) base_type.type_symbol; - - var iface_info_name = "%s_info".printf (get_ccode_lower_case_name (iface, null)); - - var ctypedecl = new CCodeDeclaration ("const GInterfaceInfo"); - ctypedecl.modifiers = CCodeModifiers.STATIC; - ctypedecl.add_declarator (new CCodeVariableDeclarator (iface_info_name, new CCodeConstant ("{ (GInterfaceInitFunc) %s_%s_interface_init, (GInterfaceFinalizeFunc) NULL, NULL}".printf (get_ccode_lower_case_name (class_reference), get_ccode_lower_case_name (iface))))); - frag.append (ctypedecl); - } - - return frag; - } - - public override void get_type_interface_init_statements (CodeContext context, CCodeBlock block, bool plugin) { - foreach (DataType base_type in class_reference.get_base_types ()) { - if (!(base_type.type_symbol is Interface)) { - continue; - } - - unowned Interface iface = (Interface) base_type.type_symbol; - - var iface_info_name = "%s_info".printf (get_ccode_lower_case_name (iface, null)); - if (!plugin) { - var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_add_interface_static")); - reg_call.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (class_reference, null)))); - reg_call.add_argument (new CCodeIdentifier (get_ccode_type_id (iface))); - reg_call.add_argument (new CCodeIdentifier ("&%s".printf (iface_info_name))); - block.add_statement (new CCodeExpressionStatement (reg_call)); - } else { - var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_module_add_interface")); - reg_call.add_argument (new CCodeIdentifier ("module")); - reg_call.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (class_reference, null)))); - reg_call.add_argument (new CCodeIdentifier (get_ccode_type_id (iface))); - reg_call.add_argument (new CCodeIdentifier ("&%s".printf (iface_info_name))); - block.add_statement (new CCodeExpressionStatement (reg_call)); - } - } - - ((CCodeBaseModule) context.codegen).register_dbus_info (block, class_reference); - } -} diff --git a/src/codegen/valactype.vala b/src/codegen/valactype.vala deleted file mode 100644 index 88894069e..000000000 --- a/src/codegen/valactype.vala +++ /dev/null @@ -1,45 +0,0 @@ -/* valactype.vala - * - * Copyright (C) 2009 Mark Lee - * - * 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.1 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: - * Mark Lee - */ - -/** - * A C type, used only for code generation purposes. - */ -public class Vala.CType : DataType { - /** - * The name of the C type. - */ - public string ctype_name { get; set; } - - /** - * The default value of the C type. - */ - public string cdefault_value { get; set; } - - public CType (string ctype_name, string cdefault_value) { - this.ctype_name = ctype_name; - this.cdefault_value = cdefault_value; - } - - public override DataType copy () { - return new CType (ctype_name, cdefault_value); - } -} diff --git a/src/codegen/valaenumregisterfunction.vala b/src/codegen/valaenumregisterfunction.vala deleted file mode 100644 index c2235a3a0..000000000 --- a/src/codegen/valaenumregisterfunction.vala +++ /dev/null @@ -1,52 +0,0 @@ -/* valaenumregisterfunction.vala - * - * Copyright (C) 2008 Jürg Billeter - * Copyright (C) 2010 Marc-Andre Lureau - * - * 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.1 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 - */ - -using GLib; - -/** - * C function to register an enum at runtime. - */ -public class Vala.EnumRegisterFunction : TypeRegisterFunction { - /** - * Specifies the enum to be registered. - */ - public weak Enum enum_reference { get; set; } - - /** - * Creates a new C function to register the specified enum at runtime. - * - * @param en an enum - * @return newly created enum register function - */ - public EnumRegisterFunction (Enum en) { - enum_reference = en; - } - - public override TypeSymbol get_type_declaration () { - return enum_reference; - } - - public override SymbolAccessibility get_accessibility () { - return enum_reference.access; - } -} diff --git a/src/codegen/valagasyncmodule.vala b/src/codegen/valagasyncmodule.vala deleted file mode 100644 index bbe810496..000000000 --- a/src/codegen/valagasyncmodule.vala +++ /dev/null @@ -1,846 +0,0 @@ -/* valagasyncmodule.vala - * - * Copyright (C) 2008-2012 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -public class Vala.GAsyncModule : GtkModule { - CCodeStruct generate_data_struct (Method m) { - string dataname = Symbol.lower_case_to_camel_case (get_ccode_name (m)) + "Data"; - var data = new CCodeStruct ("_" + dataname); - - data.add_field ("int", "_state_"); - data.add_field ("GObject*", "_source_object_"); - data.add_field ("GAsyncResult*", "_res_"); - data.add_field ("GTask*", "_async_result"); - - if (m is CreationMethod) { - data.add_field ("GType", "object_type"); - } - - if (m.binding == MemberBinding.INSTANCE) { - var type_sym = (TypeSymbol) m.parent_symbol; - if (type_sym is ObjectTypeSymbol) { - data.add_field (get_ccode_name (type_sym) + "*", "self"); - } else { - data.add_field (get_ccode_name (type_sym), "self"); - } - } - - foreach (Parameter param in m.get_parameters ()) { - var param_type = param.variable_type.copy (); - param_type.value_owned = true; - data.add_field (get_ccode_name (param_type), get_ccode_name (param), 0, get_ccode_declarator_suffix (param_type)); - - if (param.variable_type is ArrayType) { - var array_type = (ArrayType) param.variable_type; - if (get_ccode_array_length (param) && !((ArrayType) array_type).fixed_length) { - var length_ctype = get_ccode_array_length_type (param); - for (int dim = 1; dim <= array_type.rank; dim++) { - data.add_field (length_ctype, get_variable_array_length_cname (param, dim)); - } - } - } else if (param.variable_type is DelegateType) { - var deleg_type = (DelegateType) param.variable_type; - if (deleg_type.delegate_symbol.has_target) { - data.add_field (get_ccode_name (delegate_target_type), get_ccode_delegate_target_name (param)); - if (deleg_type.is_disposable ()) { - data.add_field (get_ccode_name (delegate_target_destroy_type), get_ccode_delegate_target_destroy_notify_name (param)); - } - } - } - } - - foreach (var type_param in m.get_type_parameters ()) { - data.add_field ("GType", get_ccode_type_id (type_param)); - data.add_field ("GBoxedCopyFunc", get_ccode_copy_function (type_param)); - data.add_field ("GDestroyNotify", get_ccode_destroy_function (type_param)); - } - - if (!(m.return_type is VoidType)) { - data.add_field (get_ccode_name (m.return_type), "result"); - if (m.return_type is ArrayType) { - var array_type = (ArrayType) m.return_type; - if (get_ccode_array_length (m)) { - var length_ctype = get_ccode_array_length_type (m); - for (int dim = 1; dim <= array_type.rank; dim++) { - data.add_field (length_ctype, get_array_length_cname ("result", dim)); - } - } - } else if (m.return_type is DelegateType) { - var deleg_type = (DelegateType) m.return_type; - if (deleg_type.delegate_symbol.has_target) { - data.add_field (get_ccode_name (delegate_target_type), get_delegate_target_cname ("result")); - data.add_field (get_ccode_name (delegate_target_destroy_type), get_delegate_target_destroy_notify_cname ("result")); - } - } - } - - return data; - } - - CCodeFunction generate_free_function (Method m) { - var dataname = Symbol.lower_case_to_camel_case (get_ccode_name (m)) + "Data"; - - var freefunc = new CCodeFunction (get_ccode_real_name (m) + "_data_free", "void"); - freefunc.modifiers = CCodeModifiers.STATIC; - freefunc.add_parameter (new CCodeParameter ("_data", "gpointer")); - - push_context (new EmitContext (m)); - push_function (freefunc); - - ccode.add_declaration (dataname + "*", new CCodeVariableDeclarator ("_data_", new CCodeIdentifier ("_data"))); - - foreach (Parameter param in m.get_parameters ()) { - if (!param.captured && param.direction != ParameterDirection.OUT) { - var param_type = param.variable_type.copy (); - if (!param_type.value_owned) { - param_type.value_owned = !no_implicit_copy (param_type); - } - - if (requires_destroy (param_type)) { - ccode.add_expression (destroy_parameter (param)); - } - } - } - - if (requires_destroy (m.return_type)) { - if (get_ccode_array_length (m) || !(m.return_type is ArrayType)) { - /* this is very evil. */ - var v = new LocalVariable (m.return_type, ".result"); - ccode.add_expression (destroy_local (v)); - } else { - var v = new GLibValue (m.return_type, new CCodeIdentifier ("_data_->result"), true); - v.array_null_terminated = get_ccode_array_null_terminated (m); - ccode.add_expression (destroy_value (v)); - } - } - - if (m.binding == MemberBinding.INSTANCE) { - var this_type = m.this_parameter.variable_type.copy (); - this_type.value_owned = true; - - if (requires_destroy (this_type)) { - ccode.add_expression (destroy_parameter (m.this_parameter)); - } - } - - var freecall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); - freecall.add_argument (new CCodeIdentifier (dataname)); - freecall.add_argument (new CCodeIdentifier ("_data_")); - ccode.add_expression (freecall); - - pop_context (); - - cfile.add_function_declaration (freefunc); - cfile.add_function (freefunc); - - return freefunc; - } - - void generate_async_function (Method m) { - push_context (new EmitContext ()); - - var dataname = Symbol.lower_case_to_camel_case (get_ccode_name (m)) + "Data"; - var asyncfunc = new CCodeFunction (get_ccode_real_name (m), "void"); - var cparam_map = new HashMap (direct_hash, direct_equal); - - cparam_map.set (get_param_pos (-1), new CCodeParameter ("_callback_", "GAsyncReadyCallback")); - cparam_map.set (get_param_pos (-0.9), new CCodeParameter ("_user_data_", "gpointer")); - - generate_cparameters (m, cfile, cparam_map, asyncfunc, null, null, null, 1); - - if (m.base_method != null || m.base_interface_method != null) { - // declare *_real_* function - asyncfunc.modifiers |= CCodeModifiers.STATIC; - cfile.add_function_declaration (asyncfunc); - } else if (m.is_private_symbol ()) { - asyncfunc.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && m.is_internal_symbol ()) { - asyncfunc.modifiers |= CCodeModifiers.INTERNAL; - } - - push_function (asyncfunc); - - // FIXME partial code duplication with CCodeMethodModule.visit_method - unowned Class? cl = m.parent_symbol as Class; - if (cl != null) { - if (m.binding == MemberBinding.INSTANCE && !(m is CreationMethod) - && m.base_method == null && m.base_interface_method == null) { - create_type_check_statement (m, new VoidType (), cl, true, "self"); - } - } - foreach (Parameter param in m.get_parameters ()) { - if (param.ellipsis || param.params_array) { - break; - } - - if (param.direction == ParameterDirection.IN) { - unowned TypeSymbol? t = param.variable_type.type_symbol; - if (t != null && (t.is_reference_type () || param.variable_type.is_real_struct_type ())) { - create_type_check_statement (m, new VoidType (), t, !param.variable_type.nullable, get_ccode_name (param)); - } - } - } - - // logic copied from valaccodemethodmodule - if (m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) { - Method base_method; - - if (m.overrides && m.base_method != null) { - base_method = m.base_method; - } else { - base_method = m.base_interface_method; - } - - var base_expression_type = new ObjectType ((ObjectTypeSymbol) base_method.parent_symbol); - var type_symbol = m.parent_symbol as ObjectTypeSymbol; - - var self_target_type = new ObjectType (type_symbol); - var cself = get_cvalue_ (transform_value (new GLibValue (base_expression_type, new CCodeIdentifier ("base"), true), self_target_type, m)); - ccode.add_declaration ("%s *".printf (get_ccode_name (type_symbol)), new CCodeVariableDeclarator ("self")); - ccode.add_assignment (new CCodeIdentifier ("self"), cself); - } - - var dataalloc = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0")); - dataalloc.add_argument (new CCodeIdentifier (dataname)); - - var data_var = new CCodeIdentifier ("_data_"); - - ccode.add_declaration (dataname + "*", new CCodeVariableDeclarator ("_data_")); - ccode.add_assignment (data_var, dataalloc); - - var create_result = new CCodeFunctionCall (new CCodeIdentifier ("g_task_new")); - - var t = m.parent_symbol as TypeSymbol; - if (!(m is CreationMethod) && m.binding == MemberBinding.INSTANCE && - t != null && t.is_subtype_of (gobject_type)) { - var gobject_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT")); - gobject_cast.add_argument (new CCodeIdentifier ("self")); - - create_result.add_argument (gobject_cast); - } else { - create_result.add_argument (new CCodeConstant ("NULL")); - } - - Parameter cancellable_param = null; - - foreach (Parameter param in m.get_parameters ()) { - if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") { - cancellable_param = param; - break; - } - } - - if (cancellable_param == null) { - create_result.add_argument (new CCodeConstant ("NULL")); - } else { - create_result.add_argument (new CCodeIdentifier (get_ccode_name (cancellable_param))); - } - - create_result.add_argument (new CCodeIdentifier ("_callback_")); - create_result.add_argument (new CCodeIdentifier ("_user_data_")); - - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "_async_result"), create_result); - - var attach_data_call = new CCodeFunctionCall (new CCodeIdentifier ("g_task_set_task_data")); - - attach_data_call.add_argument (new CCodeMemberAccess.pointer (data_var, "_async_result")); - attach_data_call.add_argument (data_var); - attach_data_call.add_argument (new CCodeIdentifier (get_ccode_real_name (m) + "_data_free")); - ccode.add_expression (attach_data_call); - - if (m is CreationMethod) { - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "object_type"), new CCodeIdentifier ("object_type")); - } else if (m.binding == MemberBinding.INSTANCE) { - var this_type = m.this_parameter.variable_type.copy (); - this_type.value_owned = true; - - // create copy if necessary as variables in async methods may need to be kept alive - CCodeExpression cself = new CCodeIdentifier ("self"); - if (this_type.is_real_non_null_struct_type ()) { - cself = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cself); - } - if (requires_copy (this_type)) { - cself = get_cvalue_ (copy_value (new GLibValue (m.this_parameter.variable_type, cself, true), m.this_parameter)); - } - - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "self"), cself); - } - - emit_context.push_symbol (m); - foreach (Parameter param in m.get_parameters ()) { - if (param.direction != ParameterDirection.OUT) { - // create copy if necessary as variables in async methods may need to be kept alive - var old_captured = param.captured; - param.captured = false; - current_method.coroutine = false; - - TargetValue value; - if (param.variable_type.value_owned) { - // do not use load_parameter for reference/ownership transfer - // otherwise delegate destroy notify will not be moved - value = get_parameter_cvalue (param); - } else { - value = load_parameter (param); - } - - current_method.coroutine = true; - - store_parameter (param, value); - - param.captured = old_captured; - } - } - emit_context.pop_symbol (); - - foreach (var type_param in m.get_type_parameters ()) { - var type = get_ccode_type_id (type_param); - var dup_func = get_ccode_copy_function (type_param); - var destroy_func = get_ccode_destroy_function (type_param); - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, type), new CCodeIdentifier (type)); - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, dup_func), new CCodeIdentifier (dup_func)); - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, destroy_func), new CCodeIdentifier (destroy_func)); - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_real_name (m) + "_co")); - ccall.add_argument (data_var); - ccode.add_expression (ccall); - - cfile.add_function (asyncfunc); - - pop_context (); - } - - public void append_struct (CCodeStruct structure) { - var typename = new CCodeVariableDeclarator (structure.name.substring (1)); - var typedef = new CCodeTypeDefinition ("struct " + structure.name, typename); - cfile.add_type_declaration (typedef); - cfile.add_type_definition (structure); - } - - public override bool generate_method_declaration (Method m, CCodeFile decl_space) { - if (m.coroutine) { - if ((m.is_abstract || m.is_virtual) && get_ccode_no_wrapper (m)) { - return false; - } - if (add_symbol_declaration (decl_space, m, get_ccode_name (m))) { - return false; - } - - generate_type_declaration (new MethodType (m), decl_space); - - var cl = m.parent_symbol as Class; - - var asyncfunc = new CCodeFunction (get_ccode_name (m), "void"); - var cparam_map = new HashMap (direct_hash, direct_equal); - var carg_map = new HashMap (direct_hash, direct_equal); - - if (m.is_private_symbol () || m.entry_point) { - asyncfunc.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && m.is_internal_symbol ()) { - asyncfunc.modifiers |= CCodeModifiers.INTERNAL; - } else { - asyncfunc.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - // do not generate _new functions for creation methods of abstract classes - if (!(m is CreationMethod && cl != null && cl.is_abstract)) { - generate_cparameters (m, decl_space, cparam_map, asyncfunc, null, carg_map, new CCodeFunctionCall (new CCodeIdentifier ("fake")), 1); - - decl_space.add_function_declaration (asyncfunc); - } - - var finishfunc = new CCodeFunction (get_ccode_finish_name (m)); - cparam_map = new HashMap (direct_hash, direct_equal); - carg_map = new HashMap (direct_hash, direct_equal); - - if (m.is_private_symbol () || m.entry_point) { - finishfunc.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && m.is_internal_symbol ()) { - finishfunc.modifiers |= CCodeModifiers.INTERNAL; - } else { - finishfunc.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - // do not generate _new functions for creation methods of abstract classes - if (!(m is CreationMethod && cl != null && cl.is_abstract)) { - generate_cparameters (m, decl_space, cparam_map, finishfunc, null, carg_map, new CCodeFunctionCall (new CCodeIdentifier ("fake")), 2); - - decl_space.add_function_declaration (finishfunc); - } - - if (m is CreationMethod && cl != null) { - // _construct function - var function = new CCodeFunction (get_ccode_real_name (m)); - - if (m.is_private_symbol ()) { - function.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && m.is_internal_symbol ()) { - function.modifiers |= CCodeModifiers.INTERNAL; - } else { - function.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - cparam_map = new HashMap (direct_hash, direct_equal); - generate_cparameters (m, decl_space, cparam_map, function, null, null, null, 1); - - decl_space.add_function_declaration (function); - - function = new CCodeFunction (get_ccode_finish_real_name (m)); - - if (m.is_private_symbol ()) { - function.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && m.is_internal_symbol ()) { - function.modifiers |= CCodeModifiers.INTERNAL; - } else { - function.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - cparam_map = new HashMap (direct_hash, direct_equal); - generate_cparameters (m, decl_space, cparam_map, function, null, null, null, 2); - - decl_space.add_function_declaration (function); - } - - return true; - } else { - return base.generate_method_declaration (m, decl_space); - } - } - - public override void visit_method (Method m) { - if (m.coroutine) { - cfile.add_include ("gio/gio.h"); - if (!m.is_internal_symbol ()) { - header_file.add_include ("gio/gio.h"); - } - - if (!m.is_abstract && m.body != null) { - var data = generate_data_struct (m); - - closure_struct = data; - - generate_free_function (m); - generate_async_function (m); - generate_finish_function (m); - - // append the _co function - base.visit_method (m); - closure_struct = null; - - // only append data struct here to make sure all struct member - // types are declared before the struct definition - append_struct (data); - } else { - generate_method_declaration (m, cfile); - - if (!m.is_internal_symbol ()) { - generate_method_declaration (m, header_file); - } - if (!m.is_private_symbol ()) { - generate_method_declaration (m, internal_header_file); - } - } - - if ((m.is_abstract || m.is_virtual) && !get_ccode_no_wrapper (m)) { - // generate virtual function wrappers - var cparam_map = new HashMap (direct_hash, direct_equal); - var carg_map = new HashMap (direct_hash, direct_equal); - generate_vfunc (m, new VoidType (), cparam_map, carg_map, "", 1); - - cparam_map = new HashMap (direct_hash, direct_equal); - carg_map = new HashMap (direct_hash, direct_equal); - generate_vfunc (m, m.return_type, cparam_map, carg_map, "_finish", 2); - } - } else { - base.visit_method (m); - } - } - - public override void visit_creation_method (CreationMethod m) { - if (!m.coroutine) { - base.visit_creation_method (m); - } else { - push_line (m.source_reference); - - bool visible = !m.is_private_symbol (); - - visit_method (m); - - if (m.source_type == SourceFileType.FAST) { - return; - } - - // do not generate _new functions for creation methods of abstract classes - if (current_type_symbol is Class && !current_class.is_compact && !current_class.is_abstract) { - var vfunc = new CCodeFunction (get_ccode_name (m)); - - var cparam_map = new HashMap (direct_hash, direct_equal); - var carg_map = new HashMap (direct_hash, direct_equal); - - push_function (vfunc); - - var vcall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_real_name (m))); - vcall.add_argument (new CCodeIdentifier (get_ccode_type_id (current_class))); - - generate_cparameters (m, cfile, cparam_map, vfunc, null, carg_map, vcall, 1); - ccode.add_expression (vcall); - - if (!visible) { - vfunc.modifiers |= CCodeModifiers.STATIC; - } - - pop_function (); - - cfile.add_function (vfunc); - - - vfunc = new CCodeFunction (get_ccode_finish_name (m)); - - cparam_map = new HashMap (direct_hash, direct_equal); - carg_map = new HashMap (direct_hash, direct_equal); - - push_function (vfunc); - - vcall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_real_name (m))); - - generate_cparameters (m, cfile, cparam_map, vfunc, null, carg_map, vcall, 2); - ccode.add_return (vcall); - - if (!visible) { - vfunc.modifiers |= CCodeModifiers.STATIC; - } - - pop_function (); - - cfile.add_function (vfunc); - } - - pop_line (); - } - } - - void generate_finish_function (Method m) { - push_context (new EmitContext ()); - - string dataname = Symbol.lower_case_to_camel_case (get_ccode_name (m)) + "Data"; - - var finishfunc = new CCodeFunction (get_ccode_finish_real_name (m)); - - var cparam_map = new HashMap (direct_hash, direct_equal); - - cparam_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeParameter ("_res_", "GAsyncResult*")); - - generate_cparameters (m, cfile, cparam_map, finishfunc, null, null, null, 2); - - if (m.is_private_symbol () || m.base_method != null || m.base_interface_method != null) { - finishfunc.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && m.is_internal_symbol ()) { - finishfunc.modifiers |= CCodeModifiers.INTERNAL; - } - - push_function (finishfunc); - - var return_type = m.return_type; - if (m is CreationMethod) { - var type_sym = (TypeSymbol) m.parent_symbol; - if (type_sym is ObjectTypeSymbol) { - ccode.add_declaration (get_ccode_name (type_sym) + "*", new CCodeVariableDeclarator ("result")); - return_type = SemanticAnalyzer.get_this_type (m, type_sym); - } - } else if (!(return_type is VoidType) && !return_type.is_real_non_null_struct_type ()) { - ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator ("result")); - } - - var data_var = new CCodeIdentifier ("_data_"); - - ccode.add_declaration (dataname + "*", new CCodeVariableDeclarator ("_data_")); - - var async_result_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_TASK")); - async_result_cast.add_argument (new CCodeIdentifier ("_res_")); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_task_propagate_pointer")); - ccall.add_argument (async_result_cast); - - if (m.tree_can_fail) { - ccall.add_argument (new CCodeIdentifier ("error")); - } else { - ccall.add_argument (new CCodeConstant ("NULL")); - } - - ccode.add_assignment (data_var, ccall); - - bool has_cancellable = false; - - foreach (Parameter param in m.get_parameters ()) { - if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") { - has_cancellable = true; - break; - } - } - - // If a task is cancelled, g_task_propagate_pointer returns NULL - if (m.tree_can_fail || has_cancellable) { - var is_null = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), data_var); - - ccode.open_if (is_null); - return_default_value (return_type); - ccode.close (); - } - - emit_context.push_symbol (m); - foreach (Parameter param in m.get_parameters ()) { - if (param.direction != ParameterDirection.IN) { - return_out_parameter (param); - if (!(param.variable_type is ValueType) || param.variable_type.nullable) { - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, get_ccode_name (param)), new CCodeConstant ("NULL")); - } - } - } - emit_context.pop_symbol (); - - if (m is CreationMethod) { - ccode.add_assignment (new CCodeIdentifier ("result"), new CCodeMemberAccess.pointer (data_var, "self")); - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "self"), new CCodeConstant ("NULL")); - ccode.add_return (new CCodeIdentifier ("result")); - } else if (return_type.is_real_non_null_struct_type ()) { - // structs are returned via out parameter - CCodeExpression cexpr = new CCodeMemberAccess.pointer (data_var, "result"); - if (requires_copy (return_type)) { - cexpr = get_cvalue_ (copy_value (new GLibValue (return_type, cexpr, true), return_type)); - } - ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result")), cexpr); - } else if (!(return_type is VoidType)) { - ccode.add_assignment (new CCodeIdentifier ("result"), new CCodeMemberAccess.pointer (data_var, "result")); - if (return_type is ArrayType) { - var array_type = (ArrayType) return_type; - if (get_ccode_array_length (m)) { - for (int dim = 1; dim <= array_type.rank; dim++) { - ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_array_length_cname ("result", dim))), new CCodeMemberAccess.pointer (data_var, get_array_length_cname ("result", dim))); - } - } - } else if (return_type is DelegateType && ((DelegateType) return_type).delegate_symbol.has_target) { - ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_delegate_target_cname ("result"))), new CCodeMemberAccess.pointer (data_var, get_delegate_target_cname ("result"))); - } - if (!(return_type is ValueType) || return_type.nullable) { - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "result"), new CCodeConstant ("NULL")); - } - ccode.add_return (new CCodeIdentifier ("result")); - } - - pop_function (); - - cfile.add_function (finishfunc); - - pop_context (); - } - - public override string generate_ready_function (Method m) { - // generate ready callback handler - - var dataname = Symbol.lower_case_to_camel_case (get_ccode_name (m)) + "Data"; - - var readyfunc = new CCodeFunction (get_ccode_name (m) + "_ready", "void"); - - if (!add_wrapper (readyfunc.name)) { - // wrapper already defined - return readyfunc.name; - } - - readyfunc.add_parameter (new CCodeParameter ("source_object", "GObject*")); - readyfunc.add_parameter (new CCodeParameter ("_res_", "GAsyncResult*")); - readyfunc.add_parameter (new CCodeParameter ("_user_data_", "gpointer")); - - push_function (readyfunc); - - var data_var = new CCodeIdentifier ("_data_"); - - ccode.add_declaration (dataname + "*", new CCodeVariableDeclarator ("_data_")); - ccode.add_assignment (data_var, new CCodeIdentifier ("_user_data_")); - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "_source_object_"), new CCodeIdentifier ("source_object")); - ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, "_res_"), new CCodeIdentifier ("_res_")); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_real_name (m) + "_co")); - ccall.add_argument (data_var); - ccode.add_expression (ccall); - - readyfunc.modifiers |= CCodeModifiers.STATIC; - - pop_function (); - - cfile.add_function_declaration (readyfunc); - cfile.add_function (readyfunc); - - return readyfunc.name; - } - - public override void generate_virtual_method_declaration (Method m, CCodeFile decl_space, CCodeStruct type_struct) { - if (!m.coroutine) { - base.generate_virtual_method_declaration (m, decl_space, type_struct); - return; - } - - if (!m.is_abstract && !m.is_virtual) { - return; - } - - var creturn_type = get_callable_creturn_type (m); - - // add vfunc field to the type struct - var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m)); - var cparam_map = new HashMap (direct_hash, direct_equal); - - generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator, null, null, 1); - - var vdecl = new CCodeDeclaration ("void"); - vdecl.add_declarator (vdeclarator); - type_struct.add_declaration (vdecl); - - // add vfunc field to the type struct - vdeclarator = new CCodeFunctionDeclarator (get_ccode_finish_vfunc_name (m)); - cparam_map = new HashMap (direct_hash, direct_equal); - - generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator, null, null, 2); - - vdecl = new CCodeDeclaration (get_ccode_name (creturn_type)); - vdecl.add_declarator (vdeclarator); - type_struct.add_declaration (vdecl); - } - - public override void visit_yield_statement (YieldStatement stmt) { - if (!is_in_coroutine ()) { - return; - } - - int state = emit_context.next_coroutine_state++; - - ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ())); - ccode.add_return (new CCodeConstant ("FALSE")); - ccode.add_label ("_state_%d".printf (state)); - ccode.add_statement (new CCodeEmptyStatement ()); - } - - public override void return_with_exception (CCodeExpression error_expr) - { - if (!is_in_coroutine ()) { - base.return_with_exception (error_expr); - return; - } - - var async_result_expr = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_async_result"); - CCodeFunctionCall set_error = null; - - set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_task_return_error")); - set_error.add_argument (async_result_expr); - set_error.add_argument (error_expr); - ccode.add_expression (set_error); - - // free local variables - append_local_free (current_symbol); - - // free possibly already assigned out-parameter - append_out_param_free (current_method); - - // We already returned the error above, we must not return anything else here. - var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - unref.add_argument (async_result_expr); - ccode.add_expression (unref); - - ccode.add_return (new CCodeConstant ("FALSE")); - } - - public override void visit_return_statement (ReturnStatement stmt) { - base.visit_return_statement (stmt); - - if (!is_in_coroutine ()) { - return; - } - - complete_async (); - } - - public override void generate_cparameters (Method m, CCodeFile decl_space, Map cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, Map? carg_map = null, CCodeFunctionCall? vcall = null, int direction = 3) { - if (m.coroutine) { - decl_space.add_include ("gio/gio.h"); - - if (direction == 1) { - cparam_map.set (get_param_pos (-1), new CCodeParameter ("_callback_", "GAsyncReadyCallback")); - cparam_map.set (get_param_pos (-0.9), new CCodeParameter ("_user_data_", "gpointer")); - if (carg_map != null) { - carg_map.set (get_param_pos (-1), new CCodeIdentifier ("_callback_")); - carg_map.set (get_param_pos (-0.9), new CCodeIdentifier ("_user_data_")); - } - } else if (direction == 2) { - cparam_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeParameter ("_res_", "GAsyncResult*")); - if (carg_map != null) { - carg_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeIdentifier ("_res_")); - } - } - } - base.generate_cparameters (m, decl_space, cparam_map, func, vdeclarator, carg_map, vcall, direction); - } - - public string generate_async_callback_wrapper () { - string async_callback_wrapper_func = "_vala_g_async_ready_callback"; - - if (!add_wrapper (async_callback_wrapper_func)) { - return async_callback_wrapper_func; - } - - var function = new CCodeFunction (async_callback_wrapper_func, "void"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("*source_object", "GObject")); - function.add_parameter (new CCodeParameter ("*res", "GAsyncResult")); - function.add_parameter (new CCodeParameter ("*user_data", "void")); - - push_function (function); - - var res_ref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref")); - res_ref.add_argument (new CCodeIdentifier ("res")); - - CCodeFunctionCall ccall = null; - - // store reference to async result of inner async function in out async result - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_task_return_pointer")); - ccall.add_argument (new CCodeIdentifier ("user_data")); - ccall.add_argument (res_ref); - ccall.add_argument (new CCodeIdentifier ("g_object_unref")); - ccode.add_expression (ccall); - - // free async result - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - ccall.add_argument (new CCodeIdentifier ("user_data")); - ccode.add_expression (ccall); - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return async_callback_wrapper_func; - } -} diff --git a/src/codegen/valagdbusclientmodule.vala b/src/codegen/valagdbusclientmodule.vala deleted file mode 100644 index 697b08758..000000000 --- a/src/codegen/valagdbusclientmodule.vala +++ /dev/null @@ -1,1248 +0,0 @@ -/* valagdbusclientmodule.vala - * - * Copyright (C) 2010-2011 Jürg Billeter - * - * 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.1 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 - * Philip Van Hoof - */ - -public class Vala.GDBusClientModule : GDBusModule { - enum CallType { - SYNC, - ASYNC, - FINISH, - NO_REPLY - } - - public CCodeConstant get_dbus_timeout (Symbol symbol) { - int timeout = -1; - - var dbus = symbol.get_attribute ("DBus"); - if (dbus != null && dbus.has_argument ("timeout")) { - timeout = dbus.get_integer ("timeout"); - } else if (symbol.parent_symbol != null) { - return get_dbus_timeout (symbol.parent_symbol); - } - - return new CCodeConstant (timeout.to_string ()); - } - - public override void generate_dynamic_method_wrapper (DynamicMethod method) { - var func = new CCodeFunction (get_ccode_name (method)); - func.modifiers = CCodeModifiers.STATIC; - - var cparam_map = new HashMap (direct_hash, direct_equal); - - generate_cparameters (method, cfile, cparam_map, func); - - push_function (func); - - if (method.dynamic_type.type_symbol == dbus_proxy_type) { - generate_marshalling (method, CallType.SYNC, null, method.name, -1); - } else { - Report.error (method.source_reference, "dynamic methods are not supported for `%s'", method.dynamic_type.to_string ()); - } - - pop_function (); - - cfile.add_function_declaration (func); - cfile.add_function (func); - } - - void generate_proxy_interface_init (Interface main_iface, Interface iface) { - // also generate proxy for prerequisites - foreach (var prereq in iface.get_prerequisites ()) { - if (prereq.type_symbol is Interface) { - generate_proxy_interface_init (main_iface, (Interface) prereq.type_symbol); - } - } - - string lower_cname = get_ccode_lower_case_prefix (main_iface) + "proxy"; - - var proxy_iface_init = new CCodeFunction (lower_cname + "_" + get_ccode_lower_case_prefix (iface) + "interface_init", "void"); - proxy_iface_init.add_parameter (new CCodeParameter ("iface", get_ccode_name (iface) + "Iface*")); - - push_function (proxy_iface_init); - - foreach (Method m in iface.get_methods ()) { - if (!m.is_abstract) { - continue; - } - - var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), get_ccode_vfunc_name (m)); - if (!m.coroutine) { - ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_method (main_iface, iface, m))); - } else { - ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_async_dbus_proxy_method (main_iface, iface, m))); - vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), get_ccode_finish_vfunc_name (m)); - ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_finish_dbus_proxy_method (main_iface, iface, m))); - } - } - - foreach (Property prop in iface.get_properties ()) { - if (!prop.is_abstract) { - continue; - } - - if (prop.get_accessor != null) { - var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "get_" + prop.name); - ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_get (main_iface, iface, prop))); - } - if (prop.set_accessor != null) { - var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"), "set_" + prop.name); - ccode.add_assignment (vfunc_entry, new CCodeIdentifier (generate_dbus_proxy_property_set (main_iface, iface, prop))); - } - } - - proxy_iface_init.modifiers = CCodeModifiers.STATIC; - pop_function (); - cfile.add_function_declaration (proxy_iface_init); - cfile.add_function (proxy_iface_init); - } - - string implement_interface (CCodeFunctionCall define_type, Interface main_iface, Interface iface) { - string result = ""; - - // also implement prerequisites - foreach (var prereq in iface.get_prerequisites ()) { - if (prereq.type_symbol is Interface) { - result += implement_interface (define_type, main_iface, (Interface) prereq.type_symbol); - } - } - - string interface_macro; - - if (in_plugin) { - interface_macro = "G_IMPLEMENT_INTERFACE_DYNAMIC"; - } else { - interface_macro = "G_IMPLEMENT_INTERFACE"; - } - - result += "%s (%s, %sproxy_%sinterface_init) ".printf ( - interface_macro, - get_ccode_upper_case_name (iface, "TYPE_"), - get_ccode_lower_case_prefix (main_iface), - get_ccode_lower_case_prefix (iface)); - return result; - } - - public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) { - base.generate_interface_declaration (iface, decl_space); - - string dbus_iface_name = get_dbus_name (iface); - if (dbus_iface_name == null) { - return; - } - - string get_type_name = "%sproxy_get_type".printf (get_ccode_lower_case_prefix (iface)); - - if (add_symbol_declaration (decl_space, iface, get_type_name)) { - return; - } - - decl_space.add_type_declaration (new CCodeNewline ()); - var macro = "(%s ())".printf (get_type_name); - decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_PROXY".printf (get_ccode_type_id (iface)), macro)); - - // declare proxy_get_type function - var proxy_get_type = new CCodeFunction (get_type_name, "GType"); - proxy_get_type.modifiers = CCodeModifiers.CONST | CCodeModifiers.EXTERN; - requires_vala_extern = true; - - decl_space.add_function_declaration (proxy_get_type); - - if (in_plugin) { - var proxy_register_type = new CCodeFunction ("%sproxy_register_dynamic_type".printf (get_ccode_lower_case_prefix (iface))); - proxy_register_type.add_parameter (new CCodeParameter ("module", "GTypeModule*")); - proxy_register_type.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - - decl_space.add_function_declaration (proxy_register_type); - } - } - - public override void visit_interface (Interface iface) { - base.visit_interface (iface); - - string dbus_iface_name = get_dbus_name (iface); - if (dbus_iface_name == null) { - return; - } - - cfile.add_include ("gio/gio.h"); - - // create proxy class - string cname = get_ccode_name (iface) + "Proxy"; - string lower_cname = get_ccode_lower_case_prefix (iface) + "proxy"; - - cfile.add_type_declaration (new CCodeTypeDefinition ("GDBusProxy", new CCodeVariableDeclarator (cname))); - cfile.add_type_declaration (new CCodeTypeDefinition ("GDBusProxyClass", new CCodeVariableDeclarator (cname + "Class"))); - - string type_macro; - - if (in_plugin) { - type_macro = "G_DEFINE_DYNAMIC_TYPE_EXTENDED"; - } else { - type_macro = "G_DEFINE_TYPE_EXTENDED"; - } - - var define_type = new CCodeFunctionCall (new CCodeIdentifier (type_macro)); - define_type.add_argument (new CCodeIdentifier (cname)); - define_type.add_argument (new CCodeIdentifier (lower_cname)); - define_type.add_argument (new CCodeIdentifier ("G_TYPE_DBUS_PROXY")); - define_type.add_argument (new CCodeConstant ("0")); - define_type.add_argument (new CCodeIdentifier (implement_interface (define_type, iface, iface))); - - cfile.add_type_member_definition (define_type); - - var proxy_class_init = new CCodeFunction (lower_cname + "_class_init", "void"); - proxy_class_init.add_parameter (new CCodeParameter ("klass", cname + "Class*")); - proxy_class_init.modifiers = CCodeModifiers.STATIC; - push_function (proxy_class_init); - var proxy_class = new CCodeFunctionCall (new CCodeIdentifier ("G_DBUS_PROXY_CLASS")); - proxy_class.add_argument (new CCodeIdentifier ("klass")); - ccode.add_assignment (new CCodeMemberAccess.pointer (proxy_class, "g_signal"), new CCodeIdentifier (lower_cname + "_g_signal")); - pop_function (); - cfile.add_function (proxy_class_init); - - generate_signal_handler_function (iface); - - if (in_plugin) { - var proxy_class_finalize = new CCodeFunction (lower_cname + "_class_finalize", "void"); - proxy_class_finalize.add_parameter (new CCodeParameter ("klass", cname + "Class*")); - proxy_class_finalize.modifiers = CCodeModifiers.STATIC; - cfile.add_function (proxy_class_finalize); - - var proxy_type_init = new CCodeFunction (lower_cname + "_register_dynamic_type", "void"); - proxy_type_init.add_parameter (new CCodeParameter ("module", "GTypeModule*")); - push_function (proxy_type_init); - var call_register_type = new CCodeFunctionCall (new CCodeIdentifier (lower_cname + "_register_type")); - call_register_type.add_argument (new CCodeIdentifier ("module")); - ccode.add_expression (call_register_type); - pop_function (); - cfile.add_function(proxy_type_init); - } - - var proxy_instance_init = new CCodeFunction (lower_cname + "_init", "void"); - proxy_instance_init.add_parameter (new CCodeParameter ("self", cname + "*")); - proxy_instance_init.modifiers = CCodeModifiers.STATIC; - push_function (proxy_instance_init); - - // TODO Replaces setting of "vala-dbus-interface-info" - var dbus_proxy_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_DBUS_PROXY")); - dbus_proxy_cast.add_argument (new CCodeIdentifier ("self")); - var set_interface_info = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_set_interface_info")); - set_interface_info.add_argument (dbus_proxy_cast); - set_interface_info.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (iface)), "GDBusInterfaceInfo *")); - ccode.add_expression (set_interface_info); - - pop_function (); - cfile.add_function (proxy_instance_init); - - generate_proxy_interface_init (iface, iface); - } - - public override void visit_method_call (MethodCall expr) { - var mtype = expr.call.value_type as MethodType; - bool bus_get_proxy_async = (mtype != null && get_ccode_name (mtype.method_symbol) == "g_bus_get_proxy"); - bool bus_get_proxy_sync = (mtype != null && get_ccode_name (mtype.method_symbol) == "g_bus_get_proxy_sync"); - bool conn_get_proxy_async = (mtype != null && get_ccode_name (mtype.method_symbol) == "g_dbus_connection_get_proxy"); - bool conn_get_proxy_sync = (mtype != null && get_ccode_name (mtype.method_symbol) == "g_dbus_connection_get_proxy_sync"); - if (!bus_get_proxy_async && !bus_get_proxy_sync && !conn_get_proxy_async && !conn_get_proxy_sync) { - base.visit_method_call (expr); - return; - } - - var ma = (MemberAccess) expr.call; - var type_arg = ma.get_type_arguments ().get (0); - - CCodeExpression proxy_type; - CCodeExpression dbus_iface_name; - - var object_type = type_arg as ObjectType; - if (object_type != null) { - var iface = (Interface) object_type.type_symbol; - - if (get_dbus_name (iface) == null) { - Report.error (expr.source_reference, "`%s' is not a D-Bus interface", iface.get_full_name ()); - return; - } - - proxy_type = new CCodeIdentifier ("%s_PROXY".printf (get_ccode_type_id (iface))); - dbus_iface_name = new CCodeConstant ("\"%s\"".printf (get_dbus_name (iface))); - } else { - // use runtime type information for generic methods - - var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); - quark.add_argument (new CCodeConstant ("\"vala-dbus-proxy-type\"")); - - var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata")); - get_qdata.add_argument (get_type_id_expression (type_arg)); - get_qdata.add_argument (quark); - - proxy_type = new CCodeFunctionCall (new CCodeCastExpression (get_qdata, "GType (*) (void)")); - - quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); - quark.add_argument (new CCodeConstant ("\"vala-dbus-interface-name\"")); - - get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata")); - get_qdata.add_argument (get_type_id_expression (type_arg)); - get_qdata.add_argument (quark); - - dbus_iface_name = get_qdata; - } - - if (bus_get_proxy_async || conn_get_proxy_async) { - if (ma.member_name == "end" && ma.inner.symbol_reference == ma.symbol_reference) { - // method can fail - current_method_inner_error = true; - - var args = expr.get_argument_list (); - Expression res = args.get (0); - - var source_var = get_temp_variable (expr.value_type, expr.value_type.value_owned); - var source_ref = get_variable_cexpression (source_var.name); - emit_temp_var (source_var); - var source = new CCodeFunctionCall (new CCodeIdentifier ("g_async_result_get_source_object")); - source.add_argument (get_cvalue (res)); - ccode.add_assignment (source_ref, source); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_async_initable_new_finish")); - ccall.add_argument (new CCodeCastExpression (source_ref, "GAsyncInitable *")); - ccall.add_argument (get_cvalue (res)); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ())); - - var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned); - var temp_ref = get_variable_cexpression (temp_var.name); - emit_temp_var (temp_var); - ccode.add_assignment (temp_ref, new CCodeCastExpression (ccall, get_ccode_name (expr.value_type))); - - // g_async_result_get_source_object transfers ownership, unref after use - var unref_proxy = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - unref_proxy.add_argument (source_ref); - ccode.add_expression (unref_proxy); - - set_cvalue (expr, temp_ref); - - return; - } - } - - var base_arg_index = 0; - if (bus_get_proxy_async || bus_get_proxy_sync) - base_arg_index = 1; - - var args = expr.get_argument_list (); - Expression name = args.get (base_arg_index + 0); - Expression object_path = args.get (base_arg_index + 1); - Expression flags = args.get (base_arg_index + 2); - Expression cancellable = args.get (base_arg_index + 3); - - // method can fail - current_method_inner_error = true; - - CCodeFunctionCall ccall; - if (bus_get_proxy_async || conn_get_proxy_async) { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_async_initable_new_async")); - } else { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_initable_new")); - } - ccall.add_argument (proxy_type); - if (bus_get_proxy_async || conn_get_proxy_async) { - // I/O priority - ccall.add_argument (new CCodeConstant ("0")); - } - ccall.add_argument (get_cvalue (cancellable)); - if (bus_get_proxy_async || conn_get_proxy_async) { - if (expr.is_yield_expression) { - // asynchronous call - ccall.add_argument (new CCodeIdentifier (generate_ready_function (current_method))); - ccall.add_argument (new CCodeIdentifier ("_data_")); - } else { - // begin - Expression callback = args.get (base_arg_index + 4); - ccall.add_argument (get_cvalue (callback)); - ccall.add_argument (get_delegate_target (callback)); - } - } else { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ())); - } - ccall.add_argument (new CCodeConstant ("\"g-flags\"")); - ccall.add_argument (get_cvalue (flags)); - ccall.add_argument (new CCodeConstant ("\"g-name\"")); - ccall.add_argument (get_cvalue (name)); - if (bus_get_proxy_async || bus_get_proxy_sync) { - Expression bus_type = args.get (0); - ccall.add_argument (new CCodeConstant ("\"g-bus-type\"")); - ccall.add_argument (get_cvalue (bus_type)); - } else { - Expression connection = ma.inner; - if (ma.member_name == "begin" && ma.inner.symbol_reference == ma.symbol_reference) { - var inner_ma = (MemberAccess) ma.inner; - connection = inner_ma.inner; - } - ccall.add_argument (new CCodeConstant ("\"g-connection\"")); - ccall.add_argument (get_cvalue (connection)); - } - ccall.add_argument (new CCodeConstant ("\"g-object-path\"")); - ccall.add_argument (get_cvalue (object_path)); - ccall.add_argument (new CCodeConstant ("\"g-interface-name\"")); - ccall.add_argument (dbus_iface_name); - ccall.add_argument (new CCodeConstant ("NULL")); - - if (bus_get_proxy_async || conn_get_proxy_async) { - if (expr.is_yield_expression) { - int state = emit_context.next_coroutine_state++; - - ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_state_"), new CCodeConstant (state.to_string ())); - ccode.add_expression (ccall); - ccode.add_return (new CCodeConstant ("FALSE")); - ccode.add_label ("_state_%d".printf (state)); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_async_initable_new_finish")); - ccall.add_argument (new CCodeCastExpression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_source_object_"), "GAsyncInitable *")); - // pass GAsyncResult stored in closure to finish function - ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), "_res_")); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ())); - } else { - // begin - ccode.add_expression (ccall); - return; - } - } - - var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned); - var temp_ref = get_variable_cexpression (temp_var.name); - - emit_temp_var (temp_var); - - ccode.add_assignment (temp_ref, new CCodeCastExpression (ccall, get_ccode_name (expr.value_type))); - set_cvalue (expr, temp_ref); - } - - string generate_dbus_signal_handler (Signal sig, ObjectTypeSymbol sym) { - string wrapper_name = "_dbus_handle_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig)); - - var function = new CCodeFunction (wrapper_name); - function.modifiers = CCodeModifiers.STATIC; - function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*")); - function.add_parameter (new CCodeParameter ("parameters", "GVariant*")); - - push_function (function); - - ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_arguments_iter")); - - var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init")); - iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter"))); - iter_init.add_argument (new CCodeIdentifier ("parameters")); - ccode.add_expression (iter_init); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name")); - ccall.add_argument (new CCodeIdentifier ("self")); - ccall.add_argument (get_signal_canonical_constant (sig)); - - foreach (Parameter param in sig.get_parameters ()) { - var param_name = get_variable_cname (param.name); - var owned_type = param.variable_type.copy (); - owned_type.value_owned = true; - - ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true))); - - unowned Struct? st = param.variable_type.type_symbol as Struct; - if (st != null && !st.is_simple_type ()) { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param_name))); - } else { - ccall.add_argument (new CCodeIdentifier (param_name)); - } - - if (param.variable_type is ArrayType) { - var array_type = (ArrayType) param.variable_type; - var length_ctype = get_ccode_array_length_type (array_type); - - for (int dim = 1; dim <= array_type.rank; dim++) { - string length_cname = get_variable_array_length_cname (param, dim); - - ccode.add_declaration (length_ctype, new CCodeVariableDeclarator (length_cname, new CCodeConstant ("0"))); - ccall.add_argument (new CCodeIdentifier (length_cname)); - } - } - - read_expression (param.variable_type, new CCodeIdentifier ("_arguments_iter"), new CCodeIdentifier (param_name), param); - } - - ccode.add_expression (ccall); - - foreach (Parameter param in sig.get_parameters ()) { - var owned_type = param.variable_type.copy (); - owned_type.value_owned = true; - - if (requires_destroy (owned_type)) { - // keep local alive (symbol_reference is weak) - var local = new LocalVariable (owned_type, param.name); - ccode.add_expression (destroy_local (local)); - } - } - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return wrapper_name; - } - - void generate_signal_handler_function (ObjectTypeSymbol sym) { - var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "proxy_g_signal", "void"); - cfunc.add_parameter (new CCodeParameter ("proxy", "GDBusProxy*")); - cfunc.add_parameter (new CCodeParameter ("sender_name", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("signal_name", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*")); - - cfunc.modifiers |= CCodeModifiers.STATIC; - - cfile.add_function_declaration (cfunc); - - push_function (cfunc); - - bool firstif = true; - - foreach (Signal sig in sym.get_signals ()) { - if (sig.access != SymbolAccessibility.PUBLIC) { - continue; - } - - cfile.add_include ("string.h"); - - var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); - ccheck.add_argument (new CCodeIdentifier ("signal_name")); - ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig)))); - - var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")); - if (firstif) { - ccode.open_if (cond); - firstif = false; - } else { - ccode.else_if (cond); - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_signal_handler (sig, sym))); - ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("proxy"), get_ccode_name (sym) + "*")); - ccall.add_argument (new CCodeIdentifier ("parameters")); - - ccode.add_expression (ccall); - } - if (!firstif) { - ccode.close (); - } - - pop_function (); - - cfile.add_function (cfunc); - } - - void generate_marshalling (Method m, CallType call_type, string? iface_name, string? method_name, int method_timeout) { - var gdbusproxy = new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"); - - var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_connection")); - connection.add_argument (gdbusproxy); - - bool uses_fd = dbus_method_uses_file_descriptor (m); - if (uses_fd) { - cfile.add_include ("gio/gunixfdlist.h"); - ccode.add_declaration ("GUnixFDList*", new CCodeVariableDeclarator ("_fd_list")); - } - - bool has_error_argument = m.tree_can_fail; - CCodeExpression error_argument; - if (has_error_argument) { - error_argument = new CCodeIdentifier ("error"); - } else { - error_argument = new CCodeConstant ("NULL"); - } - - if (call_type != CallType.FINISH) { - var destination = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_name")); - destination.add_argument (gdbusproxy); - - var interface_name = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_interface_name")); - interface_name.add_argument (gdbusproxy); - - var object_path = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_object_path")); - object_path.add_argument (gdbusproxy); - - CCodeExpression timeout; - if (method_timeout <= 0) { - timeout = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_default_timeout")); - ((CCodeFunctionCall) timeout).add_argument (gdbusproxy); - } else { - timeout = new CCodeConstant ("%d".printf (method_timeout)); - } - - // register errors - var error_types = new ArrayList (); - m.get_error_types (error_types); - foreach (var error_type in error_types) { - var errtype = (ErrorType) error_type; - if (errtype.error_domain != null) { - ccode.add_expression (new CCodeIdentifier (get_ccode_upper_case_name (errtype.error_domain))); - } - } - - // build D-Bus message - - ccode.add_declaration ("GDBusMessage", new CCodeVariableDeclarator ("*_message")); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_call")); - ccall.add_argument (destination); - ccall.add_argument (object_path); - if (iface_name != null) { - ccall.add_argument (new CCodeConstant ("\"%s\"".printf (iface_name))); - } else { - ccall.add_argument (interface_name); - } - ccall.add_argument (new CCodeConstant ("\"%s\"".printf (method_name))); - ccode.add_assignment (new CCodeIdentifier ("_message"), ccall); - - ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments")); - ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder")); - - var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init")); - builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder"))); - builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE")); - ccode.add_expression (builder_init); - - if (uses_fd) { - ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new"))); - } - - CCodeExpression cancellable = new CCodeConstant ("NULL"); - - foreach (Parameter param in m.get_parameters ()) { - if (param.direction == ParameterDirection.IN) { - CCodeExpression expr = new CCodeIdentifier (get_variable_cname (param.name)); - if (param.variable_type.is_real_struct_type ()) { - expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr); - } - - if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") { - cancellable = expr; - continue; - } - - if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") { - // ignore BusName sender parameters - continue; - } - - send_dbus_value (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param); - } - } - - var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end")); - builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder"))); - ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end); - - var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body")); - set_body.add_argument (new CCodeIdentifier ("_message")); - set_body.add_argument (new CCodeIdentifier ("_arguments")); - ccode.add_expression (set_body); - - if (uses_fd) { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list")); - ccall.add_argument (new CCodeIdentifier ("_message")); - ccall.add_argument (new CCodeIdentifier ("_fd_list")); - ccode.add_expression (ccall); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - ccall.add_argument (new CCodeIdentifier ("_fd_list")); - ccode.add_expression (ccall); - } - - // send D-Bus message - - if (call_type == CallType.SYNC) { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message_with_reply_sync")); - ccall.add_argument (connection); - ccall.add_argument (new CCodeIdentifier ("_message")); - ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE")); - ccall.add_argument (timeout); - ccall.add_argument (new CCodeConstant ("NULL")); - ccall.add_argument (cancellable); - ccall.add_argument (error_argument); - ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall); - } else if (call_type == CallType.NO_REPLY) { - var set_flags = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_flags")); - set_flags.add_argument (new CCodeIdentifier ("_message")); - set_flags.add_argument (new CCodeConstant ("G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED")); - ccode.add_expression (set_flags); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message")); - ccall.add_argument (connection); - ccall.add_argument (new CCodeIdentifier ("_message")); - ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE")); - ccall.add_argument (new CCodeConstant ("NULL")); - ccall.add_argument (error_argument); - ccode.add_expression (ccall); - } else if (call_type == CallType.ASYNC) { - var callback_specified = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("_callback_"), new CCodeConstant ("NULL")); - ccode.open_if (callback_specified); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message_with_reply")); - ccall.add_argument (connection); - ccall.add_argument (new CCodeIdentifier ("_message")); - ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE")); - ccall.add_argument (timeout); - ccall.add_argument (new CCodeConstant ("NULL")); - ccall.add_argument (cancellable); - - CCodeFunctionCall res_wrapper = null; - - // use wrapper as source_object wouldn't be correct otherwise - ccall.add_argument (new CCodeIdentifier (generate_async_callback_wrapper ())); - res_wrapper = new CCodeFunctionCall (new CCodeIdentifier ("g_task_new")); - res_wrapper.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *")); - res_wrapper.add_argument (new CCodeConstant ("NULL")); - res_wrapper.add_argument (new CCodeIdentifier ("_callback_")); - res_wrapper.add_argument (new CCodeIdentifier ("_user_data_")); - ccall.add_argument (res_wrapper); - - ccode.add_expression (ccall); - - ccode.add_else (); - - var set_flags = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_flags")); - set_flags.add_argument (new CCodeIdentifier ("_message")); - set_flags.add_argument (new CCodeConstant ("G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED")); - ccode.add_expression (set_flags); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message")); - ccall.add_argument (connection); - ccall.add_argument (new CCodeIdentifier ("_message")); - ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE")); - ccall.add_argument (new CCodeConstant ("NULL")); - ccall.add_argument (new CCodeConstant ("NULL")); - ccode.add_expression (ccall); - - ccode.close (); - } - - // free D-Bus message - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - ccall.add_argument (new CCodeIdentifier ("_message")); - ccode.add_expression (ccall); - } else { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message_with_reply_finish")); - ccall.add_argument (connection); - - // unwrap async result - ccode.add_declaration ("GAsyncResult", new CCodeVariableDeclarator ("*_inner_res")); - - var inner_res = new CCodeFunctionCall (new CCodeIdentifier ("g_task_propagate_pointer")); - inner_res.add_argument (new CCodeCastExpression (new CCodeIdentifier ("_res_"), "GTask *")); - inner_res.add_argument (new CCodeConstant ("NULL")); - ccode.add_assignment (new CCodeIdentifier ("_inner_res"), inner_res); - - ccall.add_argument (new CCodeIdentifier ("_inner_res")); - ccall.add_argument (error_argument); - ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall); - - // _inner_res is guaranteed to be non-NULL, so just unref it - var unref_inner_res = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - unref_inner_res.add_argument (new CCodeIdentifier ("_inner_res")); - ccode.add_expression (unref_inner_res); - } - - if (call_type == CallType.SYNC || call_type == CallType.FINISH) { - ccode.add_declaration ("GDBusMessage", new CCodeVariableDeclarator ("*_reply_message")); - - var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - unref_reply.add_argument (new CCodeIdentifier ("_reply_message")); - - // return on io error - var reply_is_null = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply_message")); - ccode.open_if (reply_is_null); - return_default_value (m.return_type); - ccode.close (); - - // return on remote error - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_to_gerror")); - ccall.add_argument (new CCodeIdentifier ("_reply_message")); - ccall.add_argument (error_argument); - ccode.open_if (ccall); - ccode.add_expression (unref_reply); - return_default_value (m.return_type); - ccode.close (); - - bool has_result = !(m.return_type is VoidType); - - if (uses_fd) { - ccode.add_declaration ("gint", new CCodeVariableDeclarator.zero ("_fd_index", new CCodeConstant ("0"))); - ccode.add_declaration ("gint", new CCodeVariableDeclarator ("_fd")); - } - - foreach (Parameter param in m.get_parameters ()) { - if (param.direction == ParameterDirection.OUT) { - has_result = true; - } - } - - if (has_result) { - ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply")); - ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_reply_iter")); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_get_body")); - ccall.add_argument (new CCodeIdentifier ("_reply_message")); - ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall); - - var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init")); - iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_iter"))); - iter_init.add_argument (new CCodeIdentifier ("_reply")); - ccode.add_expression (iter_init); - - foreach (Parameter param in m.get_parameters ()) { - if (param.direction == ParameterDirection.OUT) { - ccode.add_declaration (get_ccode_name (param.variable_type), new CCodeVariableDeclarator.zero ("_vala_%s".printf (param.name), default_value_for_type (param.variable_type, true))); - - var array_type = param.variable_type as ArrayType; - if (array_type != null) { - var length_ctype = get_ccode_array_length_type (array_type); - for (int dim = 1; dim <= array_type.rank; dim++) { - ccode.add_declaration (length_ctype, new CCodeVariableDeclarator ("_vala_%s_length%d".printf (param.name, dim), new CCodeConstant ("0"))); - } - } - - var target = new CCodeIdentifier ("_vala_%s".printf (param.name)); - bool may_fail; - - receive_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_message"), new CCodeIdentifier ("_reply_iter"), target, param, error_argument, out may_fail); - - // TODO check that parameter is not NULL (out parameters are optional) - // free value if parameter is NULL - ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_variable_cname (param.name))), target); - - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - // TODO check that parameter is not NULL (out parameters are optional) - ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("%s_length%d".printf (param.name, dim))), new CCodeIdentifier ("_vala_%s_length%d".printf (param.name, dim))); - } - } - - if (may_fail && has_error_argument) { - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("error"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")))); - ccode.add_expression (unref_reply); - return_default_value (m.return_type); - ccode.close (); - } - } - } - - if (!(m.return_type is VoidType)) { - if (m.return_type.is_real_non_null_struct_type ()) { - var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result")); - receive_dbus_value (m.return_type, new CCodeIdentifier ("_reply_message"), new CCodeIdentifier ("_reply_iter"), target, m); - } else { - ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator.zero ("_result", default_value_for_type (m.return_type, true))); - - var array_type = m.return_type as ArrayType; - if (array_type != null) { - var length_ctype = get_ccode_array_length_type (array_type); - for (int dim = 1; dim <= array_type.rank; dim++) { - ccode.add_declaration (length_ctype, new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0"))); - } - } - - bool may_fail; - receive_dbus_value (m.return_type, new CCodeIdentifier ("_reply_message"), new CCodeIdentifier ("_reply_iter"), new CCodeIdentifier ("_result"), m, new CCodeIdentifier ("error"), out may_fail); - - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - // TODO check that parameter is not NULL (out parameters are optional) - ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim))); - } - } - - if (may_fail) { - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("error"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")))); - ccode.add_expression (unref_reply); - return_default_value (m.return_type); - ccode.close (); - } - } - } - } - - ccode.add_expression (unref_reply); - - if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) { - ccode.add_return (new CCodeIdentifier ("_result")); - } - } - } - - string generate_dbus_proxy_method (Interface main_iface, Interface iface, Method m) { - string proxy_name = "%sproxy_%s".printf (get_ccode_lower_case_prefix (main_iface), m.name); - - string dbus_iface_name = get_dbus_name (iface); - - bool no_reply = is_dbus_no_reply (m); - - var function = new CCodeFunction (proxy_name); - function.modifiers = CCodeModifiers.STATIC; - - var cparam_map = new HashMap (direct_hash, direct_equal); - - generate_cparameters (m, cfile, cparam_map, function); - - push_function (function); - - generate_marshalling (m, no_reply ? CallType.NO_REPLY : CallType.SYNC, dbus_iface_name, get_dbus_name_for_member (m), get_dbus_timeout_for_member (m)); - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return proxy_name; - } - - string generate_async_dbus_proxy_method (Interface main_iface, Interface iface, Method m) { - string proxy_name = "%sproxy_%s_async".printf (get_ccode_lower_case_prefix (main_iface), m.name); - - string dbus_iface_name = get_dbus_name (iface); - - var function = new CCodeFunction (proxy_name, "void"); - function.modifiers = CCodeModifiers.STATIC; - - var cparam_map = new HashMap (direct_hash, direct_equal); - - cparam_map.set (get_param_pos (-1), new CCodeParameter ("_callback_", "GAsyncReadyCallback")); - cparam_map.set (get_param_pos (-0.9), new CCodeParameter ("_user_data_", "gpointer")); - - generate_cparameters (m, cfile, cparam_map, function, null, null, null, 1); - - push_function (function); - - generate_marshalling (m, CallType.ASYNC, dbus_iface_name, get_dbus_name_for_member (m), get_dbus_timeout_for_member (m)); - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return proxy_name; - } - - string generate_finish_dbus_proxy_method (Interface main_iface, Interface iface, Method m) { - string proxy_name = "%sproxy_%s_finish".printf (get_ccode_lower_case_prefix (main_iface), m.name); - - var function = new CCodeFunction (proxy_name); - function.modifiers = CCodeModifiers.STATIC; - - var cparam_map = new HashMap (direct_hash, direct_equal); - - cparam_map.set (get_param_pos (get_ccode_async_result_pos (m)), new CCodeParameter ("_res_", "GAsyncResult*")); - - generate_cparameters (m, cfile, cparam_map, function, null, null, null, 2); - - push_function (function); - - generate_marshalling (m, CallType.FINISH, null, null, -1); - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return proxy_name; - } - - string generate_dbus_proxy_property_get (Interface main_iface, Interface iface, Property prop) { - string proxy_name = "%sdbus_proxy_get_%s".printf (get_ccode_lower_case_prefix (main_iface), prop.name); - - string dbus_iface_name = get_dbus_name (iface); - - var owned_type = prop.get_accessor.value_type.copy (); - owned_type.value_owned = true; - if (owned_type.is_disposable () && !prop.get_accessor.value_type.value_owned) { - Report.error (prop.get_accessor.value_type.source_reference, "Properties used in D-Bus clients require owned get accessor"); - } - - var array_type = prop.get_accessor.value_type as ArrayType; - - var function = new CCodeFunction (proxy_name); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("self", "%s*".printf (get_ccode_name (iface)))); - - if (prop.property_type.is_real_non_null_struct_type ()) { - function.add_parameter (new CCodeParameter ("result", "%s*".printf (get_ccode_name (prop.get_accessor.value_type)))); - } else { - if (array_type != null) { - var length_ctype = get_ccode_array_length_type (array_type) + "*"; - for (int dim = 1; dim <= array_type.rank; dim++) { - function.add_parameter (new CCodeParameter ("result_length%d".printf (dim), length_ctype)); - } - } - - function.return_type = get_ccode_name (prop.get_accessor.value_type); - } - - push_function (function); - - ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_inner_reply")); - - // first try cached value - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_cached_property")); - ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *")); - ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop)))); - ccode.add_assignment (new CCodeIdentifier ("_inner_reply"), ccall); - - // if not successful, retrieve value via D-Bus - ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_inner_reply"))); - - ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments")); - ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply")); - ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder")); - - var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init")); - builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder"))); - builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE")); - ccode.add_expression (builder_init); - - // interface name - write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)), null); - // property name - write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))), null); - - var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end")); - builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder"))); - ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync")); - ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *")); - ccall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties.Get\"")); - ccall.add_argument (new CCodeIdentifier ("_arguments")); - ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE")); - ccall.add_argument (get_dbus_timeout (prop)); - ccall.add_argument (new CCodeConstant ("NULL")); - ccall.add_argument (new CCodeConstant ("NULL")); - - ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall); - - // return on error - ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply"))); - return_default_value (prop.property_type); - ccode.close (); - - var get_variant = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get")); - get_variant.add_argument (new CCodeIdentifier ("_reply")); - get_variant.add_argument (new CCodeConstant ("\"(v)\"")); - get_variant.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_inner_reply"))); - ccode.add_expression (get_variant); - - var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref")); - unref_reply.add_argument (new CCodeIdentifier ("_reply")); - ccode.add_expression (unref_reply); - - ccode.close (); - - if (prop.property_type.is_real_non_null_struct_type ()) { - var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result")); - var result = deserialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("_inner_reply"), target); - ccode.add_assignment (target, result); - } else { - ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator ("_result")); - - if (get_dbus_signature (prop) != null) { - // raw GVariant - ccode.add_assignment (new CCodeIdentifier ("_result"), new CCodeIdentifier("_inner_reply")); - } else { - if (array_type != null) { - var length_ctype = get_ccode_array_length_type (array_type); - for (int dim = 1; dim <= array_type.rank; dim++) { - ccode.add_declaration (length_ctype, new CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0"))); - } - } - - var result = deserialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("_inner_reply"), new CCodeIdentifier ("_result")); - ccode.add_assignment (new CCodeIdentifier ("_result"), result); - - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - // TODO check that parameter is not NULL (out parameters are optional) - ccode.add_assignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new CCodeIdentifier ("_result_length%d".printf (dim))); - } - } - } - } - - if (prop.property_type.is_real_non_null_struct_type () || get_dbus_signature (prop) == null) { - unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref")); - unref_reply.add_argument (new CCodeIdentifier ("_inner_reply")); - ccode.add_expression (unref_reply); - } - - if (prop.property_type.is_real_non_null_struct_type ()) { - ccode.add_return (); - } else { - ccode.add_return (new CCodeIdentifier ("_result")); - } - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return proxy_name; - } - - string generate_dbus_proxy_property_set (Interface main_iface, Interface iface, Property prop) { - string proxy_name = "%sdbus_proxy_set_%s".printf (get_ccode_lower_case_prefix (main_iface), prop.name); - - string dbus_iface_name = get_dbus_name (iface); - - var array_type = prop.set_accessor.value_type as ArrayType; - - var function = new CCodeFunction (proxy_name); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("self", "%s*".printf (get_ccode_name (iface)))); - - if (prop.property_type.is_real_non_null_struct_type ()) { - function.add_parameter (new CCodeParameter ("value", "%s*".printf (get_ccode_name (prop.set_accessor.value_type)))); - } else { - function.add_parameter (new CCodeParameter ("value", get_ccode_name (prop.set_accessor.value_type))); - - if (array_type != null) { - var length_ctype = get_ccode_array_length_type (array_type); - for (int dim = 1; dim <= array_type.rank; dim++) { - function.add_parameter (new CCodeParameter ("value_length%d".printf (dim), length_ctype)); - } - } - } - - push_function (function); - - ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments")); - ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply")); - - ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder")); - - var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init")); - builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder"))); - builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE")); - ccode.add_expression (builder_init); - - // interface name - write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (dbus_iface_name)), null); - // property name - write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))), null); - - // property value (as variant) - var builder_open = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_open")); - builder_open.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder"))); - builder_open.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_VARIANT")); - ccode.add_expression (builder_open); - - if (prop.property_type.is_real_non_null_struct_type ()) { - write_expression (prop.set_accessor.value_type, new CCodeIdentifier ("_arguments_builder"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("value")), prop); - } else { - write_expression (prop.set_accessor.value_type, new CCodeIdentifier ("_arguments_builder"), new CCodeIdentifier ("value"), prop); - } - - var builder_close = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_close")); - builder_close.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder"))); - ccode.add_expression (builder_close); - - var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end")); - builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder"))); - ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync")); - ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *")); - ccall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties.Set\"")); - ccall.add_argument (new CCodeIdentifier ("_arguments")); - ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE")); - ccall.add_argument (get_dbus_timeout (prop)); - ccall.add_argument (new CCodeConstant ("NULL")); - ccall.add_argument (new CCodeConstant ("NULL")); - - ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall); - - // return on error - ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("_reply"))); - ccode.add_return (); - ccode.close (); - - var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref")); - unref_reply.add_argument (new CCodeIdentifier ("_reply")); - ccode.add_expression (unref_reply); - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return proxy_name; - } - - public override void register_dbus_info (CCodeBlock block, ObjectTypeSymbol sym) { - if (!(sym is Interface)) { - return; - } - - string dbus_iface_name = get_dbus_name (sym); - if (dbus_iface_name == null) { - return; - } - - var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); - quark.add_argument (new CCodeConstant ("\"vala-dbus-proxy-type\"")); - - var proxy_type = new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "proxy_get_type"); - - var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata")); - set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null)))); - set_qdata.add_argument (quark); - set_qdata.add_argument (new CCodeCastExpression (proxy_type, "void*")); - - block.add_statement (new CCodeExpressionStatement (set_qdata)); - - quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); - quark.add_argument (new CCodeConstant ("\"vala-dbus-interface-name\"")); - - set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata")); - set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null)))); - set_qdata.add_argument (quark); - set_qdata.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name))); - - block.add_statement (new CCodeExpressionStatement (set_qdata)); - - // TODO Replaced by g_dbus_proxy_set_interface_info() call in *_init - quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); - quark.add_argument (new CCodeConstant ("\"vala-dbus-interface-info\"")); - - set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata")); - set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null)))); - set_qdata.add_argument (quark); - set_qdata.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (sym)), "void*")); - - block.add_statement (new CCodeExpressionStatement (set_qdata)); - } -} diff --git a/src/codegen/valagdbusmodule.vala b/src/codegen/valagdbusmodule.vala deleted file mode 100644 index 59ab1de8b..000000000 --- a/src/codegen/valagdbusmodule.vala +++ /dev/null @@ -1,499 +0,0 @@ -/* valagdbusmodule.vala - * - * Copyright (C) 2010-2012 Jürg Billeter - * - * 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.1 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 - */ - -public class Vala.GDBusModule : GVariantModule { - public static string? get_dbus_name (TypeSymbol symbol) { - return symbol.get_attribute_string ("DBus", "name"); - } - - public static string get_dbus_name_for_member (Symbol symbol) { - var dbus_name = symbol.get_attribute_string ("DBus", "name"); - if (dbus_name != null) { - return dbus_name; - } - - return Symbol.lower_case_to_camel_case (symbol.name); - } - - public static int get_dbus_timeout_for_member (Symbol symbol) { - return symbol.get_attribute_integer ("DBus", "timeout", -1); - } - - public static bool is_dbus_visible (CodeNode node) { - var dbus_attribute = node.get_attribute ("DBus"); - if (dbus_attribute != null - && dbus_attribute.has_argument ("visible") - && !dbus_attribute.get_bool ("visible")) { - return false; - } - - return true; - } - - public static bool is_dbus_no_reply (Method m) { - return m.get_attribute_bool ("DBus", "no_reply"); - } - - public static string dbus_result_name (Method m) { - var dbus_name = m.get_attribute_string ("DBus", "result"); - if (dbus_name != null && dbus_name != "") { - return dbus_name; - } - - return "result"; - } - - public override void visit_error_domain (ErrorDomain edomain) { - var edomain_dbus_name = get_dbus_name (edomain); - if (edomain_dbus_name == null) { - base.visit_error_domain (edomain); - return; - } - - cfile.add_include ("gio/gio.h"); - - generate_error_domain_declaration (edomain, cfile); - - if (!edomain.is_internal_symbol ()) { - generate_error_domain_declaration (edomain, header_file); - } - if (!edomain.is_private_symbol ()) { - generate_error_domain_declaration (edomain, internal_header_file); - } - - var error_entries = new CCodeInitializerList (); - foreach (ErrorCode ecode in edomain.get_codes ()) { - var ecode_dbus_name = get_dbus_name (ecode); - if (ecode_dbus_name == null) { - ecode_dbus_name = Symbol.lower_case_to_camel_case (ecode.name.ascii_down ()); - } - - var error_entry = new CCodeInitializerList (); - error_entry.append (new CCodeIdentifier (get_ccode_name (ecode))); - error_entry.append (new CCodeConstant ("\"%s.%s\"".printf (edomain_dbus_name, ecode_dbus_name))); - error_entries.append (error_entry); - } - - var cdecl = new CCodeDeclaration ("const GDBusErrorEntry"); - cdecl.add_declarator (new CCodeVariableDeclarator (get_ccode_lower_case_name (edomain) + "_entries[]", error_entries)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - string quark_fun_name = get_ccode_lower_case_prefix (edomain) + "quark"; - - var cquark_fun = new CCodeFunction (quark_fun_name, get_ccode_name (gquark_type.type_symbol)); - push_function (cquark_fun); - - string quark_name = "%squark_volatile".printf (get_ccode_lower_case_prefix (edomain)); - - ccode.add_declaration ("gsize", new CCodeVariableDeclarator (quark_name, new CCodeConstant ("0")), CCodeModifiers.STATIC | CCodeModifiers.VOLATILE); - - var register_call = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_error_register_error_domain")); - register_call.add_argument (new CCodeConstant ("\"" + get_ccode_quark_name (edomain) + "\"")); - register_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (quark_name))); - register_call.add_argument (new CCodeIdentifier (get_ccode_lower_case_name (edomain) + "_entries")); - var nentries = new CCodeFunctionCall (new CCodeIdentifier ("G_N_ELEMENTS")); - nentries.add_argument (new CCodeIdentifier (get_ccode_lower_case_name (edomain) + "_entries")); - register_call.add_argument (nentries); - ccode.add_expression (register_call); - - ccode.add_return (new CCodeCastExpression (new CCodeIdentifier (quark_name), "GQuark")); - - pop_function (); - cfile.add_function (cquark_fun); - } - - bool is_file_descriptor (DataType type) { - if (type is ObjectType) { - if (type.type_symbol.get_full_name () == "GLib.UnixInputStream" || - type.type_symbol.get_full_name () == "GLib.UnixOutputStream" || - type.type_symbol.get_full_name () == "GLib.Socket" || - type.type_symbol.get_full_name () == "GLib.FileDescriptorBased") { - return true; - } - } - - return false; - } - - public bool dbus_method_uses_file_descriptor (Method method) { - foreach (Parameter param in method.get_parameters ()) { - if (is_file_descriptor (param.variable_type)) { - return true; - } - } - - if (is_file_descriptor (method.return_type)) { - return true; - } - - return false; - } - - CCodeExpression? get_file_descriptor (DataType type, CCodeExpression expr) { - if (type is ObjectType) { - if (type.type_symbol.get_full_name () == "GLib.UnixInputStream") { - var result = new CCodeFunctionCall (new CCodeIdentifier ("g_unix_input_stream_get_fd")); - result.add_argument (expr); - return result; - } else if (type.type_symbol.get_full_name () == "GLib.UnixOutputStream") { - var result = new CCodeFunctionCall (new CCodeIdentifier ("g_unix_output_stream_get_fd")); - result.add_argument (expr); - return result; - } else if (type.type_symbol.get_full_name () == "GLib.Socket") { - var result = new CCodeFunctionCall (new CCodeIdentifier ("g_socket_get_fd")); - result.add_argument (expr); - return result; - } else if (type.type_symbol.get_full_name () == "GLib.FileDescriptorBased") { - var result = new CCodeFunctionCall (new CCodeIdentifier ("g_file_descriptor_based_get_fd")); - result.add_argument (expr); - return result; - } - } - - return null; - } - - public void send_dbus_value (DataType type, CCodeExpression builder_expr, CCodeExpression expr, Symbol? sym) { - var fd = get_file_descriptor (type, expr); - if (fd != null) { - // add file descriptor to the file descriptor list - var fd_append = new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_append")); - fd_append.add_argument (new CCodeIdentifier ("_fd_list")); - fd_append.add_argument (fd); - fd_append.add_argument (new CCodeConstant ("NULL")); - - // add index to file descriptor to gvariant - var builder_add = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_add")); - builder_add.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, builder_expr)); - builder_add.add_argument (new CCodeConstant ("\"h\"")); - builder_add.add_argument (fd_append); - ccode.add_expression (builder_add); - } else { - write_expression (type, builder_expr, expr, sym); - } - } - - CCodeExpression? create_from_file_descriptor (DataType type, CCodeExpression expr) { - if (type is ObjectType) { - if (type.type_symbol.get_full_name () == "GLib.UnixInputStream") { - var result = new CCodeFunctionCall (new CCodeIdentifier ("g_unix_input_stream_new")); - result.add_argument (expr); - result.add_argument (new CCodeConstant ("TRUE")); - return new CCodeCastExpression (result, "GUnixInputStream *"); - } else if (type.type_symbol.get_full_name () == "GLib.UnixOutputStream") { - var result = new CCodeFunctionCall (new CCodeIdentifier ("g_unix_output_stream_new")); - result.add_argument (expr); - result.add_argument (new CCodeConstant ("TRUE")); - return new CCodeCastExpression (result, "GUnixOutputStream *"); - } else if (type.type_symbol.get_full_name () == "GLib.Socket") { - var result = new CCodeFunctionCall (new CCodeIdentifier ("g_socket_new_from_fd")); - result.add_argument (expr); - result.add_argument (new CCodeConstant ("NULL")); - return result; - } - } - - return null; - } - - public void receive_dbus_value (DataType type, CCodeExpression message_expr, CCodeExpression iter_expr, CCodeExpression target_expr, Symbol? sym, CCodeExpression? error_expr = null, out bool may_fail = null) { - var fd_list = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_get_unix_fd_list")); - fd_list.add_argument (message_expr); - - var fd_var = new CCodeIdentifier ("_fd"); - - var stream = create_from_file_descriptor (type, fd_var); - if (stream != null) { - var fd_list_var = new CCodeIdentifier ("_fd_list"); - - var fd = new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_get")); - fd.add_argument (fd_list_var); - fd.add_argument (new CCodeIdentifier ("_fd_index")); - fd.add_argument (error_expr); - - ccode.add_assignment (fd_list_var, fd_list); - ccode.open_if (fd_list_var); - - var get_fd = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_next")); - get_fd.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, iter_expr)); - get_fd.add_argument (new CCodeConstant ("\"h\"")); - get_fd.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_fd_index"))); - ccode.add_expression (get_fd); - - ccode.add_assignment (fd_var, fd); - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN_OR_EQUAL, fd_var, new CCodeConstant ("0"))); - - ccode.add_assignment (target_expr, stream); - may_fail = true; - - ccode.close (); - - ccode.add_else (); - var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error_literal")); - set_error.add_argument (error_expr); - set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR")); - set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR_FAILED")); - set_error.add_argument (new CCodeConstant ("\"FD List is NULL\"")); - ccode.add_expression (set_error); - ccode.close (); - } else { - read_expression (type, iter_expr, target_expr, sym, error_expr, out may_fail); - } - } - CCodeExpression get_method_info (ObjectTypeSymbol sym) { - var infos = new CCodeInitializerList (); - - foreach (Method m in sym.get_methods ()) { - if (m is CreationMethod || m.binding != MemberBinding.INSTANCE - || m.overrides || m.access != SymbolAccessibility.PUBLIC) { - continue; - } - if (!is_dbus_visible (m)) { - continue; - } - - var in_args_info = new CCodeInitializerList (); - var out_args_info = new CCodeInitializerList (); - - foreach (Parameter param in m.get_parameters ()) { - if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") { - continue; - } - if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") { - continue; - } - - var info = new CCodeInitializerList (); - info.append (new CCodeConstant ("-1")); - info.append (new CCodeConstant ("\"%s\"".printf (param.name))); - info.append (new CCodeConstant ("\"%s\"".printf (param.variable_type.get_type_signature (param)))); - info.append (new CCodeConstant ("NULL")); - - var cdecl = new CCodeDeclaration ("const GDBusArgInfo"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_" + param.name, info)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - if (param.direction == ParameterDirection.IN) { - in_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_" + param.name))); - } else { - out_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_" + param.name))); - } - } - - if (!(m.return_type is VoidType)) { - var info = new CCodeInitializerList (); - info.append (new CCodeConstant ("-1")); - info.append (new CCodeConstant ("\"%s\"".printf (dbus_result_name (m)))); - info.append (new CCodeConstant ("\"%s\"".printf (m.return_type.get_type_signature (m)))); - info.append (new CCodeConstant ("NULL")); - - var cdecl = new CCodeDeclaration ("const GDBusArgInfo"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_result", info)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - out_args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_result"))); - } - - in_args_info.append (new CCodeConstant ("NULL")); - out_args_info.append (new CCodeConstant ("NULL")); - - var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_in[]", in_args_info)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - cdecl = new CCodeDeclaration ("const GDBusArgInfo * const"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_out[]", out_args_info)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - var info = new CCodeInitializerList (); - info.append (new CCodeConstant ("-1")); - info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m)))); - info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_in")), "GDBusArgInfo **")); - info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + m.name + "_out")), "GDBusArgInfo **")); - info.append (new CCodeConstant ("NULL")); - - cdecl = new CCodeDeclaration ("const GDBusMethodInfo"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_method_info_" + m.name, info)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_method_info_" + m.name))); - } - - infos.append (new CCodeConstant ("NULL")); - - var cdecl = new CCodeDeclaration ("const GDBusMethodInfo * const"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_method_info[]", infos)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_method_info"); - } - - CCodeExpression get_signal_info (ObjectTypeSymbol sym) { - var infos = new CCodeInitializerList (); - - foreach (Signal sig in sym.get_signals ()) { - if (sig.access != SymbolAccessibility.PUBLIC) { - continue; - } - if (!is_dbus_visible (sig)) { - continue; - } - - var args_info = new CCodeInitializerList (); - - foreach (Parameter param in sig.get_parameters ()) { - var info = new CCodeInitializerList (); - info.append (new CCodeConstant ("-1")); - info.append (new CCodeConstant ("\"%s\"".printf (param.name))); - info.append (new CCodeConstant ("\"%s\"".printf (param.variable_type.get_type_signature (param)))); - info.append (new CCodeConstant ("NULL")); - - var cdecl = new CCodeDeclaration ("const GDBusArgInfo"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + get_ccode_lower_case_name (sig) + "_" + param.name, info)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - args_info.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + get_ccode_lower_case_name (sig) + "_" + param.name))); - } - - args_info.append (new CCodeConstant ("NULL")); - - var cdecl = new CCodeDeclaration ("const GDBusArgInfo * const"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + get_ccode_lower_case_name (sig) + "[]", args_info)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - var info = new CCodeInitializerList (); - info.append (new CCodeConstant ("-1")); - info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig)))); - info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_arg_info_" + get_ccode_lower_case_name (sig))), "GDBusArgInfo **")); - info.append (new CCodeConstant ("NULL")); - - cdecl = new CCodeDeclaration ("const GDBusSignalInfo"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_signal_info_" + get_ccode_lower_case_name (sig), info)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_signal_info_" + get_ccode_lower_case_name (sig)))); - } - - infos.append (new CCodeConstant ("NULL")); - - var cdecl = new CCodeDeclaration ("const GDBusSignalInfo * const"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_signal_info[]", infos)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_signal_info"); - } - - CCodeExpression get_property_info (ObjectTypeSymbol sym) { - var infos = new CCodeInitializerList (); - - foreach (Property prop in sym.get_properties ()) { - if (prop.binding != MemberBinding.INSTANCE - || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) { - continue; - } - if (!is_dbus_visible (prop)) { - continue; - } - - var info = new CCodeInitializerList (); - info.append (new CCodeConstant ("-1")); - info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop)))); - info.append (new CCodeConstant ("\"%s\"".printf (prop.property_type.get_type_signature (prop)))); - if (prop.get_accessor != null && prop.set_accessor != null) { - info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE | G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE")); - } else if (prop.get_accessor != null) { - info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_READABLE")); - } else if (prop.set_accessor != null) { - info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE")); - } else { - info.append (new CCodeConstant ("G_DBUS_PROPERTY_INFO_FLAGS_NONE")); - } - info.append (new CCodeConstant ("NULL")); - - var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_property_info_" + prop.name, info)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - infos.append (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_property_info_" + prop.name))); - } - - infos.append (new CCodeConstant ("NULL")); - - var cdecl = new CCodeDeclaration ("const GDBusPropertyInfo * const"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_property_info[]", infos)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_property_info"); - } - - void declare_interface_info (ObjectTypeSymbol sym) { - var info = new CCodeInitializerList (); - info.append (new CCodeConstant ("-1")); - info.append (new CCodeConstant ("\"%s\"".printf (get_dbus_name (sym)))); - info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_method_info (sym)), "GDBusMethodInfo **")); - info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_signal_info (sym)), "GDBusSignalInfo **")); - info.append (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_property_info (sym)), "GDBusPropertyInfo **")); - info.append (new CCodeConstant ("NULL")); - - var cdecl = new CCodeDeclaration ("const GDBusInterfaceInfo"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_info", info)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - } - - protected CCodeExpression get_interface_info (ObjectTypeSymbol sym) { - return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_info"); - } - - public override void visit_class (Class cl) { - base.visit_class (cl); - - visit_object_type_symbol (cl); - } - - public override void visit_interface (Interface iface) { - base.visit_interface (iface); - - visit_object_type_symbol (iface); - } - - void visit_object_type_symbol (ObjectTypeSymbol sym) { - if (get_dbus_name (sym) == null) { - return; - } - - declare_interface_info(sym); - } -} diff --git a/src/codegen/valagdbusservermodule.vala b/src/codegen/valagdbusservermodule.vala deleted file mode 100644 index 6e026b43b..000000000 --- a/src/codegen/valagdbusservermodule.vala +++ /dev/null @@ -1,1216 +0,0 @@ -/* valagdbusservermodule.vala - * - * Copyright (C) 2010-2011 Jürg Billeter - * - * 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.1 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 - */ - -public class Vala.GDBusServerModule : GDBusClientModule { - string generate_dbus_wrapper (Method m, ObjectTypeSymbol sym, bool ready = false) { - string wrapper_name = "_dbus_%s".printf (get_ccode_name (m)); - bool need_goto_label = ready; - - if (m.base_method != null) { - m = m.base_method; - } else if (m.base_interface_method != null) { - m = m.base_interface_method; - } - - if (ready) { - // async ready function - wrapper_name += "_ready"; - } - - var function = new CCodeFunction (wrapper_name); - function.modifiers = CCodeModifiers.STATIC; - - if (!ready) { - function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*")); - function.add_parameter (new CCodeParameter ("_parameters_", "GVariant*")); - function.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*")); - } else { - function.add_parameter (new CCodeParameter ("source_object", "GObject *")); - function.add_parameter (new CCodeParameter ("_res_", "GAsyncResult *")); - function.add_parameter (new CCodeParameter ("_user_data_", "gpointer")); - } - - push_function (function); - - CCodeIdentifier ready_data_expr = m.coroutine ? new CCodeIdentifier ("_ready_data") : null; - string ready_data_struct_name = Symbol.lower_case_to_camel_case (get_ccode_name (m)) + "ReadyData"; - - if (ready) { - ccode.add_declaration (ready_data_struct_name + "*", new CCodeVariableDeclarator ("_ready_data", new CCodeIdentifier ("_user_data_"))); - ccode.add_declaration ("GDBusMethodInvocation*", new CCodeVariableDeclarator ("invocation", new CCodeMemberAccess.pointer (ready_data_expr, "_invocation_"))); - } - - var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_connection")); - connection.add_argument (new CCodeIdentifier ("invocation")); - - bool no_reply = is_dbus_no_reply (m); - bool uses_fd = dbus_method_uses_file_descriptor (m); - if (uses_fd) { - cfile.add_include ("gio/gunixfdlist.h"); - ccode.add_declaration ("GUnixFDList*", new CCodeVariableDeclarator ("_fd_list")); - } - - bool uses_error = false; - - if (!m.coroutine || ready) { - ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL"))); - uses_error = true; - } - - if (!ready) { - ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_arguments_iter")); - - var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init")); - iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_iter"))); - iter_init.add_argument (new CCodeIdentifier ("_parameters_")); - ccode.add_expression (iter_init); - } - - CCodeFunctionCall ccall; - if (!ready) { - ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m))); - ccall.add_argument (new CCodeIdentifier ("self")); - } else { - ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_name (m))); - ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("source_object"), get_ccode_name (sym) + "*")); - ccall.add_argument (new CCodeIdentifier ("_res_")); - } - - if (!ready) { - if (uses_fd) { - ccode.add_declaration ("gint", new CCodeVariableDeclarator.zero ("_fd_index", new CCodeConstant ("0"))); - ccode.add_declaration ("gint", new CCodeVariableDeclarator ("_fd")); - } - - CCodeStruct? ready_data_struct = null; - - if (m.coroutine) { - ready_data_struct = new CCodeStruct ("_" + ready_data_struct_name); - ready_data_struct.add_field ("GDBusMethodInvocation*", "_invocation_"); - append_struct (ready_data_struct); - - var ready_data_alloc = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0")); - ready_data_alloc.add_argument (new CCodeIdentifier (ready_data_struct_name)); - - ccode.add_declaration (ready_data_struct_name + "*", new CCodeVariableDeclarator ("_ready_data")); - ccode.add_assignment (ready_data_expr, ready_data_alloc); - - ccode.add_assignment (new CCodeMemberAccess.pointer (ready_data_expr, "_invocation_"), new CCodeIdentifier ("invocation")); - } - - foreach (Parameter param in m.get_parameters ()) { - string param_name = get_variable_cname (param.name); - if (param.direction != ParameterDirection.IN) { - continue; - } - - if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") { - continue; - } - - if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") { - // ignore BusName sender parameters - continue; - } - - CCodeExpression param_expr; - if (ready_data_expr != null) { - param_expr = new CCodeMemberAccess.pointer (ready_data_expr, param_name); - } else { - param_expr = new CCodeIdentifier (param_name); - } - - var owned_type = param.variable_type.copy (); - owned_type.value_owned = true; - - if (ready_data_struct != null) { - ready_data_struct.add_field (get_ccode_name (owned_type), param_name); - } else { - ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true))); - } - - var array_type = param.variable_type as ArrayType; - if (array_type != null) { - var length_ctype = get_ccode_array_length_type (array_type); - for (int dim = 1; dim <= array_type.rank; dim++) { - string length_cname = get_variable_array_length_cname (param, dim); - - if (ready_data_struct != null) { - ready_data_struct.add_field (length_ctype, length_cname); - } else { - ccode.add_declaration (length_ctype, new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0"))); - } - } - } - - var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message")); - message_expr.add_argument (new CCodeIdentifier ("invocation")); - - bool may_fail; - receive_dbus_value (param.variable_type, message_expr, new CCodeIdentifier ("_arguments_iter"), param_expr, param, new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")), out may_fail); - - if (may_fail) { - if (!uses_error) { - ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("error", new CCodeConstant ("NULL"))); - uses_error = true; - } - - ccode.open_if (new CCodeIdentifier ("error")); - - var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_take_error")); - return_error.add_argument (new CCodeIdentifier ("invocation")); - return_error.add_argument (new CCodeIdentifier ("error")); - ccode.add_expression (return_error); - - if (need_goto_label || requires_destroy (owned_type)) { - ccode.add_goto ("_error"); - need_goto_label = true; - } else { - ccode.add_return (); - } - - ccode.close (); - } else if (!need_goto_label && m.tree_can_fail && requires_destroy (owned_type)) { - need_goto_label = true; - } - } - } - - foreach (Parameter param in m.get_parameters ()) { - string param_name = get_variable_cname (param.name); - - CCodeExpression param_expr; - if (ready_data_expr != null && param.direction == ParameterDirection.IN) { - param_expr = new CCodeMemberAccess.pointer (ready_data_expr, param_name); - } else { - param_expr = new CCodeIdentifier (param_name); - } - - if (param.direction == ParameterDirection.IN && !ready) { - if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") { - ccall.add_argument (new CCodeConstant ("NULL")); - continue; - } - - if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") { - // ignore BusName sender parameters - var sender = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_sender")); - sender.add_argument (new CCodeIdentifier ("invocation")); - ccall.add_argument (sender); - continue; - } - - unowned Struct? st = param.variable_type.type_symbol as Struct; - if (st != null && !st.is_simple_type ()) { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, param_expr)); - } else { - ccall.add_argument (param_expr); - } - } else if (param.direction == ParameterDirection.OUT && (!m.coroutine || ready)) { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, param_expr)); - } - - var array_type = param.variable_type as ArrayType; - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - string length_cname = get_variable_array_length_cname (param, dim); - - CCodeExpression length_expr; - if (ready_data_expr != null && param.direction == ParameterDirection.IN) - length_expr = new CCodeMemberAccess.pointer (ready_data_expr, length_cname); - else - length_expr = new CCodeIdentifier (length_cname); - - if (param.direction == ParameterDirection.IN && !ready) { - ccall.add_argument (length_expr); - } else if (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready)) { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, length_expr)); - } - } - } - } - - if (!m.coroutine || ready) { - if (!(m.return_type is VoidType)) { - if (m.return_type.is_real_non_null_struct_type ()) { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result"))); - } else { - var array_type = m.return_type as ArrayType; - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - string length_cname = get_array_length_cname ("result", dim); - - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname))); - } - } - } - } - } - - if (m.coroutine && !ready) { - ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (wrapper_name + "_ready"), "GAsyncReadyCallback")); - ccall.add_argument (ready_data_expr); - } - - if (!m.coroutine || ready) { - if (m.tree_can_fail) { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error"))); - } - } - - if (!no_reply && (!m.coroutine || ready)) { - if (m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ()) { - ccode.add_expression (ccall); - } else { - ccode.add_assignment (new CCodeIdentifier ("result"), ccall); - } - - if (m.tree_can_fail) { - ccode.open_if (new CCodeIdentifier ("error")); - - var return_error = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_take_error")); - return_error.add_argument (new CCodeIdentifier ("invocation")); - return_error.add_argument (new CCodeIdentifier ("error")); - ccode.add_expression (return_error); - - if (need_goto_label) { - ccode.add_goto ("_error"); - } else { - ccode.add_return (); - } - - ccode.close (); - } - - ccode.add_declaration ("GDBusMessage*", new CCodeVariableDeclarator.zero ("_reply_message", new CCodeConstant ("NULL"))); - - var message_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_method_invocation_get_message")); - message_expr.add_argument (new CCodeIdentifier ("invocation")); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_new_method_reply")); - ccall.add_argument (message_expr); - ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall); - - ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply")); - ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_reply_builder")); - - var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init")); - builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder"))); - builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE")); - ccode.add_expression (builder_init); - - if (uses_fd) { - ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall (new CCodeIdentifier ("g_unix_fd_list_new"))); - } - - foreach (Parameter param in m.get_parameters ()) { - if (param.direction != ParameterDirection.OUT) { - continue; - } - - string param_name = get_variable_cname (param.name); - var owned_type = param.variable_type.copy (); - owned_type.value_owned = true; - - ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero (param_name, default_value_for_type (param.variable_type, true))); - - var array_type = param.variable_type as ArrayType; - if (array_type != null) { - var length_ctype = get_ccode_array_length_type (array_type); - for (int dim = 1; dim <= array_type.rank; dim++) { - string length_cname = get_variable_array_length_cname (param, dim); - - ccode.add_declaration (length_ctype, new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0"))); - } - } - - send_dbus_value (param.variable_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier (param_name), param); - } - - if (!(m.return_type is VoidType)) { - if (m.return_type.is_real_non_null_struct_type ()) { - ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true))); - - send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m); - - if (requires_destroy (m.return_type)) { - // keep local alive (symbol_reference is weak) - var local = new LocalVariable (m.return_type, ".result"); - ccode.add_expression (destroy_local (local)); - } - } else { - ccode.add_declaration (get_ccode_name (m.return_type), new CCodeVariableDeclarator ("result")); - - var array_type = m.return_type as ArrayType; - if (array_type != null) { - var length_ctype = get_ccode_array_length_type (array_type); - for (int dim = 1; dim <= array_type.rank; dim++) { - string length_cname = get_array_length_cname ("result", dim); - - ccode.add_declaration (length_ctype, new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0"))); - } - } - - send_dbus_value (m.return_type, new CCodeIdentifier ("_reply_builder"), new CCodeIdentifier ("result"), m); - - if (requires_destroy (m.return_type)) { - // keep local alive (symbol_reference is weak) - var local = new LocalVariable (m.return_type, ".result"); - ccode.add_expression (destroy_local (local)); - } - } - } - - var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end")); - builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_builder"))); - ccode.add_assignment (new CCodeIdentifier ("_reply"), builder_end); - - var set_body = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_body")); - set_body.add_argument (new CCodeIdentifier ("_reply_message")); - set_body.add_argument (new CCodeIdentifier ("_reply")); - ccode.add_expression (set_body); - - if (uses_fd) { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_set_unix_fd_list")); - ccall.add_argument (new CCodeIdentifier ("_reply_message")); - ccall.add_argument (new CCodeIdentifier ("_fd_list")); - ccode.add_expression (ccall); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - ccall.add_argument (new CCodeIdentifier ("_fd_list")); - ccode.add_expression (ccall); - } - } else { - ccode.add_expression (ccall); - } - - if (!no_reply && (!m.coroutine || ready)) { - var return_value = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_send_message")); - return_value.add_argument (connection); - return_value.add_argument (new CCodeIdentifier ("_reply_message")); - return_value.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE")); - return_value.add_argument (new CCodeConstant ("NULL")); - return_value.add_argument (new CCodeConstant ("NULL")); - ccode.add_expression (return_value); - - // free invocation like g_dbus_method_invocation_return_* - var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - unref_call.add_argument (new CCodeIdentifier ("invocation")); - ccode.add_expression (unref_call); - - unref_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - unref_call.add_argument (new CCodeIdentifier ("_reply_message")); - ccode.add_expression (unref_call); - } - - if (need_goto_label) { - ccode.add_label ("_error"); - } - - foreach (Parameter param in m.get_parameters ()) { - if ((param.direction == ParameterDirection.IN && (ready_data_expr == null || ready)) || - (param.direction == ParameterDirection.OUT && !no_reply && (!m.coroutine || ready))) { - if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.Cancellable") { - continue; - } - - if (param.variable_type is ObjectType && param.variable_type.type_symbol.get_full_name () == "GLib.BusName") { - // ignore BusName sender parameters - continue; - } - - var owned_type = param.variable_type.copy (); - owned_type.value_owned = true; - - if (requires_destroy (owned_type)) { - if (ready_data_expr != null && param.direction == ParameterDirection.IN) { - var target = new GLibValue (owned_type, new CCodeMemberAccess.pointer (ready_data_expr, param.name), true); - - var array_type = owned_type as ArrayType; - if (array_type != null) { - for (int dim = 1; dim <= array_type.rank; dim++) { - string length_cname = get_variable_array_length_cname (param, dim); - - target.append_array_length_cvalue (new CCodeMemberAccess.pointer (ready_data_expr, length_cname)); - } - } - - ccode.add_expression (destroy_value (target)); - } else { - // keep local alive (symbol_reference is weak) - var local = new LocalVariable (owned_type, get_variable_cname (param.name)); - ccode.add_expression (destroy_local (local)); - } - } - } - } - - if (ready) { - var freecall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); - freecall.add_argument (new CCodeIdentifier (ready_data_struct_name)); - freecall.add_argument (ready_data_expr); - ccode.add_expression (freecall); - } else if (need_goto_label) { - ccode.add_statement (new CCodeEmptyStatement ()); - } - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - if (m.coroutine && !ready) { - // generate ready function - generate_dbus_wrapper (m, sym, true); - } - - return wrapper_name; - } - - string generate_dbus_signal_wrapper (Signal sig, ObjectTypeSymbol sym, string dbus_iface_name) { - string wrapper_name = "_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig)); - - var function = new CCodeFunction (wrapper_name, "void"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("_sender", "GObject*")); - - foreach (var param in sig.get_parameters ()) { - // ensure ccodenode of parameter is set - var cparam = generate_parameter (param, cfile, new HashMap (), null); - - function.add_parameter (cparam); - if (param.variable_type is ArrayType) { - var array_type = (ArrayType) param.variable_type; - var length_ctype = get_ccode_array_length_type (array_type); - for (int dim = 1; dim <= array_type.rank; dim++) { - function.add_parameter (new CCodeParameter (get_variable_array_length_cname (param, dim), length_ctype)); - } - } - } - - function.add_parameter (new CCodeParameter ("_data", "gpointer*")); - - push_function (function); - - ccode.add_declaration ("GDBusConnection *", new CCodeVariableDeclarator ("_connection", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("1")))); - ccode.add_declaration ("const gchar *", new CCodeVariableDeclarator ("_path", new CCodeElementAccess (new CCodeIdentifier ("_data"), new CCodeConstant ("2")))); - ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments")); - ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder")); - - var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init")); - builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder"))); - builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE")); - ccode.add_expression (builder_init); - - foreach (Parameter param in sig.get_parameters ()) { - string param_name = get_variable_cname (param.name); - CCodeExpression expr = new CCodeIdentifier (param_name); - if (param.variable_type.is_real_struct_type ()) { - expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, expr); - } - write_expression (param.variable_type, new CCodeIdentifier ("_arguments_builder"), expr, param); - } - - var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end")); - builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_arguments_builder"))); - ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_emit_signal")); - ccall.add_argument (new CCodeIdentifier ("_connection")); - ccall.add_argument (new CCodeConstant ("NULL")); - ccall.add_argument (new CCodeIdentifier ("_path")); - ccall.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_iface_name))); - ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (sig)))); - ccall.add_argument (new CCodeIdentifier ("_arguments")); - ccall.add_argument (new CCodeConstant ("NULL")); - ccode.add_expression (ccall); - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return wrapper_name; - } - - string generate_dbus_property_get_wrapper (Property prop, ObjectTypeSymbol sym) { - string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.get_accessor)); - - var function = new CCodeFunction (wrapper_name, "GVariant*"); - function.modifiers = CCodeModifiers.STATIC; - function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*")); - - push_function (function); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.get_accessor))); - ccall.add_argument (new CCodeIdentifier ("self")); - - if (prop.get_accessor.value_type.is_real_non_null_struct_type ()) { - ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator.zero ("result", default_value_for_type (prop.get_accessor.value_type, true))); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result"))); - - ccode.add_expression (ccall); - } else { - ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new CCodeVariableDeclarator ("result")); - ccode.add_assignment (new CCodeIdentifier ("result"), ccall); - - var array_type = prop.get_accessor.value_type as ArrayType; - if (array_type != null) { - var length_ctype = get_ccode_array_length_type (array_type); - for (int dim = 1; dim <= array_type.rank; dim++) { - string length_cname = get_array_length_cname ("result", dim); - - ccode.add_declaration (length_ctype, new CCodeVariableDeclarator.zero (length_cname, new CCodeConstant ("0"))); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (length_cname))); - } - } - } - - ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator ("_reply")); - - if (get_dbus_signature (prop) != null) { - // raw GVariant - ccode.add_assignment (new CCodeIdentifier ("_reply"), new CCodeIdentifier("result")); - } else { - var reply_expr = serialize_expression (prop.get_accessor.value_type, new CCodeIdentifier ("result")); - - ccode.add_assignment (new CCodeIdentifier ("_reply"), reply_expr); - - if (requires_destroy (prop.get_accessor.value_type)) { - // keep local alive (symbol_reference is weak) - var local = new LocalVariable (prop.get_accessor.value_type, ".result"); - ccode.add_expression (destroy_local (local)); - } - } - - ccode.add_return (new CCodeIdentifier ("_reply")); - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return wrapper_name; - } - - string generate_dbus_property_set_wrapper (Property prop, ObjectTypeSymbol sym) { - string wrapper_name = "_dbus_%s".printf (get_ccode_name (prop.set_accessor)); - - var function = new CCodeFunction (wrapper_name); - function.modifiers = CCodeModifiers.STATIC; - function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*")); - function.add_parameter (new CCodeParameter ("_value", "GVariant*")); - - push_function (function); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (prop.set_accessor))); - ccall.add_argument (new CCodeIdentifier ("self")); - - var owned_type = prop.property_type.copy (); - owned_type.value_owned = true; - - ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero ("value", default_value_for_type (prop.property_type, true))); - - unowned Struct? st = prop.property_type.type_symbol as Struct; - if (st != null && !st.is_simple_type ()) { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("value"))); - } else { - ccall.add_argument (new CCodeIdentifier ("value")); - - var array_type = prop.property_type as ArrayType; - if (array_type != null) { - var length_ctype = get_ccode_array_length_type (array_type); - for (int dim = 1; dim <= array_type.rank; dim++) { - ccode.add_declaration (length_ctype, new CCodeVariableDeclarator (get_array_length_cname ("value", dim))); - ccall.add_argument (new CCodeIdentifier (get_array_length_cname ("value", dim))); - } - } - } - - var target = new CCodeIdentifier ("value"); - - if (get_dbus_signature (prop) != null) { - ccode.add_assignment (target, new CCodeIdentifier("_value")); - ccode.add_expression (ccall); - } else { - var expr = deserialize_expression (prop.property_type, new CCodeIdentifier ("_value"), target); - ccode.add_assignment (target, expr); - ccode.add_expression (ccall); - - if (requires_destroy (owned_type)) { - // keep local alive (symbol_reference is weak) - var local = new LocalVariable (owned_type, "value"); - ccode.add_expression (destroy_local (local)); - } - } - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return wrapper_name; - } - - void handle_signals (ObjectTypeSymbol sym, bool connect) { - string dbus_iface_name = get_dbus_name (sym); - if (dbus_iface_name == null) { - return; - } - - foreach (Signal sig in sym.get_signals ()) { - if (sig.access != SymbolAccessibility.PUBLIC) { - continue; - } - if (!is_dbus_visible (sig)) { - continue; - } - - if (connect) { - var connect_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_connect")); - connect_call.add_argument (new CCodeIdentifier ("object")); - connect_call.add_argument (get_signal_canonical_constant (sig)); - connect_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_dbus_signal_wrapper (sig, sym, dbus_iface_name)), "GCallback")); - connect_call.add_argument (new CCodeIdentifier ("data")); - ccode.add_expression (connect_call); - } else { - // disconnect the signals - var disconnect_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_handlers_disconnect_by_func")); - disconnect_call.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))); - disconnect_call.add_argument (new CCodeIdentifier ("_dbus_%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig)))); - disconnect_call.add_argument (new CCodeIdentifier ("data")); - ccode.add_expression (disconnect_call); - } - } - } - - void generate_interface_method_call_function (ObjectTypeSymbol sym) { - var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_method_call", "void"); - cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*")); - cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("method_name", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*")); - cfunc.add_parameter (new CCodeParameter ("invocation", "GDBusMethodInvocation*")); - cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer")); - - cfunc.modifiers |= CCodeModifiers.STATIC; - - push_function (cfunc); - - ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data"))); - ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")))); - - bool first = true; - - foreach (Method m in sym.get_methods ()) { - if (m is CreationMethod || m.binding != MemberBinding.INSTANCE - || m.overrides || m.access != SymbolAccessibility.PUBLIC) { - continue; - } - if (!is_dbus_visible (m)) { - continue; - } - - cfile.add_include ("string.h"); - - var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); - ccheck.add_argument (new CCodeIdentifier ("method_name")); - ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (m)))); - - if (first) { - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"))); - first = false; - } else { - ccode.else_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0"))); - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_wrapper (m, sym))); - ccall.add_argument (new CCodeIdentifier ("object")); - ccall.add_argument (new CCodeIdentifier ("parameters")); - ccall.add_argument (new CCodeIdentifier ("invocation")); - ccode.add_expression (ccall); - } - - if (!first) { - ccode.add_else (); - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - ccall.add_argument (new CCodeIdentifier ("invocation")); - ccode.add_expression (ccall); - - if (!first) { - ccode.close (); - } - - pop_function (); - - cfile.add_function_declaration (cfunc); - cfile.add_function (cfunc); - } - - void generate_interface_get_property_function (ObjectTypeSymbol sym) { - var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property", "GVariant*"); - cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*")); - cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("error", "GError**")); - cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer")); - - cfunc.modifiers |= CCodeModifiers.STATIC; - - cfile.add_function_declaration (cfunc); - - push_function (cfunc); - - ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data"))); - - ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")))); - - bool firstif = true; - - foreach (Property prop in sym.get_properties ()) { - if (prop.binding != MemberBinding.INSTANCE - || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) { - continue; - } - if (!is_dbus_visible (prop)) { - continue; - } - if (prop.get_accessor == null) { - continue; - } - - cfile.add_include ("string.h"); - - var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); - ccheck.add_argument (new CCodeIdentifier ("property_name")); - ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop)))); - - var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")); - if (firstif) { - ccode.open_if (cond); - firstif = false; - } else { - ccode.else_if (cond); - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_get_wrapper (prop, sym))); - ccall.add_argument (new CCodeIdentifier ("object")); - - ccode.add_return (ccall); - } - if (!firstif) { - ccode.close (); - } - - ccode.add_return (new CCodeConstant ("NULL")); - - pop_function (); - cfile.add_function (cfunc); - } - - void generate_interface_set_property_function (ObjectTypeSymbol sym) { - var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property", "gboolean"); - cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*")); - cfunc.add_parameter (new CCodeParameter ("sender", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("object_path", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("interface_name", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("property_name", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("value", "GVariant*")); - cfunc.add_parameter (new CCodeParameter ("error", "GError**")); - cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer")); - - cfunc.modifiers |= CCodeModifiers.STATIC; - - cfile.add_function_declaration (cfunc); - - push_function (cfunc); - - ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data"))); - - ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("object", new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")))); - - bool firstif = true; - - foreach (Property prop in sym.get_properties ()) { - if (prop.binding != MemberBinding.INSTANCE - || prop.overrides || prop.access != SymbolAccessibility.PUBLIC) { - continue; - } - if (!is_dbus_visible (prop)) { - continue; - } - if (prop.set_accessor == null) { - continue; - } - - cfile.add_include ("string.h"); - - var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); - ccheck.add_argument (new CCodeIdentifier ("property_name")); - ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop)))); - - var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new CCodeConstant ("0")); - if (firstif) { - ccode.open_if (cond); - firstif = false; - } else { - ccode.else_if (cond); - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_property_set_wrapper (prop, sym))); - ccall.add_argument (new CCodeIdentifier ("object")); - ccall.add_argument (new CCodeIdentifier ("value")); - - ccode.add_expression (ccall); - ccode.add_return (new CCodeConstant ("TRUE")); - } - if (!firstif) { - ccode.close (); - } - ccode.add_return (new CCodeConstant ("FALSE")); - - pop_function (); - cfile.add_function (cfunc); - } - - CCodeExpression get_interface_vtable (ObjectTypeSymbol sym) { - var vtable = new CCodeInitializerList (); - vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_method_call")); - vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_get_property")); - vtable.append (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "dbus_interface_set_property")); - - generate_interface_method_call_function (sym); - generate_interface_get_property_function (sym); - generate_interface_set_property_function (sym); - - var cdecl = new CCodeDeclaration ("const GDBusInterfaceVTable"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_vtable", vtable)); - cdecl.modifiers = CCodeModifiers.STATIC; - cfile.add_constant_declaration (cdecl); - - return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_vtable"); - } - - string generate_register_object_function () { - string register_object_func = "_vala_g_dbus_connection_register_object"; - - if (!add_wrapper (register_object_func)) { - return register_object_func; - } - - cfile.add_include ("gio/gio.h"); - - var function = new CCodeFunction (register_object_func, "guint"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("type", "GType")); - function.add_parameter (new CCodeParameter ("object", "void*")); - function.add_parameter (new CCodeParameter ("connection", "GDBusConnection*")); - function.add_parameter (new CCodeParameter ("path", "const gchar*")); - function.add_parameter (new CCodeParameter ("error", "GError**")); - - push_function (function); - - var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); - quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\"")); - - var get_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_get_qdata")); - get_qdata.add_argument (new CCodeIdentifier ("type")); - get_qdata.add_argument (quark); - - ccode.add_declaration ("void", new CCodeVariableDeclarator ("*func")); - ccode.add_assignment (new CCodeIdentifier ("func"), get_qdata); - - ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("func"))); - // no D-Bus interface - // return error - - var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error_literal")); - set_error.add_argument (new CCodeIdentifier ("error")); - set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR")); - set_error.add_argument (new CCodeIdentifier ("G_IO_ERROR_FAILED")); - set_error.add_argument (new CCodeConstant ("\"The specified type does not support D-Bus registration\"")); - ccode.add_expression (set_error); - - ccode.add_return (new CCodeConstant ("0")); - - ccode.close (); - - var register_object = new CCodeCastExpression (new CCodeIdentifier ("func"), "guint (*) (void *, GDBusConnection *, const gchar *, GError **)"); - - var ccall = new CCodeFunctionCall (register_object); - ccall.add_argument (new CCodeIdentifier ("object")); - ccall.add_argument (new CCodeIdentifier ("connection")); - ccall.add_argument (new CCodeIdentifier ("path")); - ccall.add_argument (new CCodeIdentifier ("error")); - - ccode.add_return (ccall); - - pop_function (); - - cfile.add_function_declaration (function); - cfile.add_function (function); - - return register_object_func; - } - - public override void visit_method_call (MethodCall expr) { - var mtype = expr.call.value_type as MethodType; - if (mtype == null || get_ccode_name (mtype.method_symbol) != "g_dbus_connection_register_object") { - base.visit_method_call (expr); - return; - } - - var ma = (MemberAccess) expr.call; - var type_arg = ma.get_type_arguments ().get (0); - - CCodeFunctionCall cregister; - - var object_type = type_arg as ObjectType; - if (object_type != null) { - if (get_dbus_name (object_type.type_symbol) == null) { - Report.error (expr.source_reference, "DBusConnection.register_object requires type argument with [DBus (name = ...)] attribute"); - return; - } - - cregister = new CCodeFunctionCall (new CCodeIdentifier ("%sregister_object".printf (get_ccode_lower_case_prefix (object_type.type_symbol)))); - } else { - // use runtime type information for generic methods - cregister = new CCodeFunctionCall (new CCodeIdentifier (generate_register_object_function ())); - cregister.add_argument (get_type_id_expression (type_arg)); - } - - var args = expr.get_argument_list (); - var path_arg = args[0]; - var obj_arg = args[1]; - - // method can fail - current_method_inner_error = true; - - cregister.add_argument (get_cvalue (obj_arg)); - cregister.add_argument (get_cvalue (ma.inner)); - cregister.add_argument (get_cvalue (path_arg)); - cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ())); - - if (expr.parent_node is ExpressionStatement) { - ccode.add_expression (cregister); - } else { - var temp_var = get_temp_variable (expr.value_type, expr.value_type.value_owned); - var temp_ref = get_variable_cexpression (temp_var.name); - - emit_temp_var (temp_var); - - ccode.add_assignment (temp_ref, cregister); - set_cvalue (expr, temp_ref); - } - } - - public override void generate_class_declaration (Class cl, CCodeFile decl_space) { - base.generate_class_declaration (cl, decl_space); - - generate_object_type_symbol_declaration (cl, decl_space); - } - - public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) { - base.generate_interface_declaration (iface, decl_space); - - generate_object_type_symbol_declaration (iface, decl_space); - } - - public override void visit_class (Class cl) { - base.visit_class (cl); - - visit_object_type_symbol (cl); - } - - public override void visit_interface (Interface iface) { - base.visit_interface (iface); - - visit_object_type_symbol (iface); - } - - void generate_object_type_symbol_declaration (ObjectTypeSymbol sym, CCodeFile decl_space) { - string dbus_iface_name = get_dbus_name (sym); - if (dbus_iface_name == null) { - return; - } - - string register_object_name = "%sregister_object".printf (get_ccode_lower_case_prefix (sym)); - - if (add_symbol_declaration (decl_space, sym, register_object_name)) { - return; - } - - decl_space.add_include ("gio/gio.h"); - - // declare register_object function - var cfunc = new CCodeFunction (register_object_name, "guint"); - cfunc.add_parameter (new CCodeParameter ("object", "void*")); - cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*")); - cfunc.add_parameter (new CCodeParameter ("path", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("error", "GError**")); - if (sym.is_private_symbol ()) { - cfunc.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && sym.is_internal_symbol ()) { - cfunc.modifiers |= CCodeModifiers.INTERNAL; - } else { - cfunc.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - decl_space.add_function_declaration (cfunc); - } - - void visit_object_type_symbol (ObjectTypeSymbol sym) { - // only support registering a single D-Bus interface at a time (unlike old D-Bus support) - // however, register_object can be invoked multiple times for the same object path with different interfaces - string dbus_iface_name = get_dbus_name (sym); - if (dbus_iface_name == null) { - return; - } - - cfile.add_include ("gio/gio.h"); - - var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "register_object", "guint"); - cfunc.add_parameter (new CCodeParameter ("object", "gpointer")); - cfunc.add_parameter (new CCodeParameter ("connection", "GDBusConnection*")); - cfunc.add_parameter (new CCodeParameter ("path", "const gchar*")); - cfunc.add_parameter (new CCodeParameter ("error", "GError**")); - if (sym.is_private_symbol ()) { - cfunc.modifiers |= CCodeModifiers.STATIC; - } else if (context.hide_internal && sym.is_internal_symbol ()) { - cfunc.modifiers |= CCodeModifiers.INTERNAL; - } - - push_function (cfunc); - - ccode.add_declaration ("guint", new CCodeVariableDeclarator ("result")); - - - // data consists of 3 pointers: object, connection, path - ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("*data")); - - var alloc_data = new CCodeFunctionCall (new CCodeIdentifier ("g_new")); - alloc_data.add_argument (new CCodeIdentifier ("gpointer")); - alloc_data.add_argument (new CCodeConstant ("3")); - ccode.add_assignment (new CCodeIdentifier ("data"), alloc_data); - - var ref_function = get_ccode_ref_function (sym); - if (sym is Interface && ref_function == null) { - Report.error (sym.source_reference, "missing class prerequisite for interface `%s', add GLib.Object to interface declaration if unsure", sym.get_full_name ()); - return; - } - - var ref_object = new CCodeFunctionCall (new CCodeIdentifier (ref_function)); - ref_object.add_argument (new CCodeIdentifier ("object")); - ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0")), ref_object); - - ref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref")); - ref_object.add_argument (new CCodeIdentifier ("connection")); - ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1")), ref_object); - - var dup_path = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup")); - dup_path.add_argument (new CCodeIdentifier ("path")); - ccode.add_assignment (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2")), dup_path); - - - var cregister = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_connection_register_object")); - cregister.add_argument (new CCodeIdentifier ("connection")); - cregister.add_argument (new CCodeIdentifier ("path")); - - cregister.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_info (sym)), "GDBusInterfaceInfo *")); - cregister.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_interface_vtable (sym))); - - cregister.add_argument (new CCodeIdentifier ("data")); - cregister.add_argument (new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "unregister_object")); - cregister.add_argument (new CCodeIdentifier ("error")); - - ccode.add_assignment (new CCodeIdentifier ("result"), cregister); - - ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("result"))); - ccode.add_return (new CCodeConstant ("0")); - ccode.close (); - - handle_signals (sym, true); - - ccode.add_return (new CCodeIdentifier ("result")); - - pop_function (); - cfile.add_function (cfunc); - - - cfunc = new CCodeFunction ("_" + get_ccode_lower_case_prefix (sym) + "unregister_object"); - cfunc.add_parameter (new CCodeParameter ("user_data", "gpointer")); - cfunc.modifiers |= CCodeModifiers.STATIC; - - push_function (cfunc); - - ccode.add_declaration ("gpointer*", new CCodeVariableDeclarator ("data", new CCodeIdentifier ("user_data"))); - - handle_signals (sym, false); - - var unref_object = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (sym))); - unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("0"))); - ccode.add_expression (unref_object); - - unref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - unref_object.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("1"))); - ccode.add_expression (unref_object); - - var free_path = new CCodeFunctionCall (new CCodeIdentifier ("g_free")); - free_path.add_argument (new CCodeElementAccess (new CCodeIdentifier ("data"), new CCodeConstant ("2"))); - ccode.add_expression (free_path); - - var free_data = new CCodeFunctionCall (new CCodeIdentifier ("g_free")); - free_data.add_argument (new CCodeIdentifier ("data")); - ccode.add_expression (free_data); - - pop_function (); - cfile.add_function_declaration (cfunc); - cfile.add_function (cfunc); - } - - public override void register_dbus_info (CCodeBlock block, ObjectTypeSymbol sym) { - string dbus_iface_name = get_dbus_name (sym); - if (dbus_iface_name == null) { - return; - } - - base.register_dbus_info (block, sym); - - var quark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); - quark.add_argument (new CCodeConstant ("\"vala-dbus-register-object\"")); - - var set_qdata = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata")); - set_qdata.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (sym, null)))); - set_qdata.add_argument (quark); - set_qdata.add_argument (new CCodeCastExpression (new CCodeIdentifier (get_ccode_lower_case_prefix (sym) + "register_object"), "void*")); - - block.add_statement (new CCodeExpressionStatement (set_qdata)); - } -} diff --git a/src/codegen/valagerrormodule.vala b/src/codegen/valagerrormodule.vala deleted file mode 100644 index a559a4d00..000000000 --- a/src/codegen/valagerrormodule.vala +++ /dev/null @@ -1,408 +0,0 @@ -/* valagerrormodule.vala - * - * Copyright (C) 2008-2010 Jürg Billeter - * - * 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.1 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 - * Thijs Vermeir - */ - -using GLib; - -public class Vala.GErrorModule : CCodeDelegateModule { - private bool is_in_catch = false; - - public override void generate_error_domain_declaration (ErrorDomain edomain, CCodeFile decl_space) { - if (add_symbol_declaration (decl_space, edomain, get_ccode_name (edomain))) { - return; - } - - generate_type_declaration (gquark_type, decl_space); - - var cenum = new CCodeEnum (get_ccode_name (edomain)); - - foreach (ErrorCode ecode in edomain.get_codes ()) { - if (ecode.value == null) { - cenum.add_value (new CCodeEnumValue (get_ccode_name (ecode))); - } else { - ecode.value.emit (this); - cenum.add_value (new CCodeEnumValue (get_ccode_name (ecode), get_cvalue (ecode.value))); - } - } - - decl_space.add_type_definition (cenum); - - string quark_fun_name = get_ccode_lower_case_prefix (edomain) + "quark"; - - var error_domain_define = new CCodeMacroReplacement (get_ccode_upper_case_name (edomain), quark_fun_name + " ()"); - decl_space.add_type_definition (error_domain_define); - - var cquark_fun = new CCodeFunction (quark_fun_name, get_ccode_name (gquark_type.type_symbol)); - cquark_fun.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - - decl_space.add_function_declaration (cquark_fun); - } - - public override void visit_error_domain (ErrorDomain edomain) { - if (edomain.comment != null) { - cfile.add_type_definition (new CCodeComment (edomain.comment.content)); - } - - generate_error_domain_declaration (edomain, cfile); - - if (!edomain.is_internal_symbol ()) { - generate_error_domain_declaration (edomain, header_file); - } - if (!edomain.is_private_symbol ()) { - generate_error_domain_declaration (edomain, internal_header_file); - } - - edomain.accept_children (this); - - string quark_fun_name = get_ccode_lower_case_prefix (edomain) + "quark"; - - var cquark_fun = new CCodeFunction (quark_fun_name, get_ccode_name (gquark_type.type_symbol)); - push_function (cquark_fun); - - var cquark_call = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); - cquark_call.add_argument (new CCodeConstant ("\"" + get_ccode_quark_name (edomain) + "\"")); - - ccode.add_return (cquark_call); - - pop_function (); - cfile.add_function (cquark_fun); - } - - public override void visit_throw_statement (ThrowStatement stmt) { - // method will fail - current_method_inner_error = true; - ccode.add_assignment (get_inner_error_cexpression (), get_cvalue (stmt.error_expression)); - - add_simple_check (stmt, true); - } - - public virtual void return_with_exception (CCodeExpression error_expr) { - var cpropagate = new CCodeFunctionCall (new CCodeIdentifier ("g_propagate_error")); - cpropagate.add_argument (new CCodeIdentifier ("error")); - cpropagate.add_argument (error_expr); - - ccode.add_expression (cpropagate); - - // free local variables - append_local_free (current_symbol); - - // free possibly already assigned out-parameter - append_out_param_free (current_method); - - if (current_method is CreationMethod && current_method.parent_symbol is Class) { - var cl = (Class) current_method.parent_symbol; - ccode.add_expression (destroy_value (new GLibValue (new ObjectType (cl), new CCodeIdentifier ("self"), true))); - ccode.add_return (new CCodeConstant ("NULL")); - } else if (is_in_coroutine ()) { - ccode.add_return (new CCodeConstant ("FALSE")); - } else { - return_default_value (current_return_type, true); - } - } - - void uncaught_error_statement (CCodeExpression inner_error, bool unexpected = false, CodeNode? start_at = null) { - // free local variables - if (start_at is TryStatement) { - append_local_free (start_at.parent_node as Block); - } else { - append_local_free (current_symbol); - } - - // free possibly already assigned out-parameter - append_out_param_free (current_method); - - cfile.add_include ("glib.h"); - - var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical")); - ccritical.add_argument (new CCodeConstant (unexpected ? "\"file %s: line %d: unexpected error: %s (%s, %d)\"" : "\"file %s: line %d: uncaught error: %s (%s, %d)\"")); - ccritical.add_argument (new CCodeConstant ("__FILE__")); - ccritical.add_argument (new CCodeConstant ("__LINE__")); - ccritical.add_argument (new CCodeMemberAccess.pointer (inner_error, "message")); - var domain_name = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_to_string")); - domain_name.add_argument (new CCodeMemberAccess.pointer (inner_error, "domain")); - ccritical.add_argument (domain_name); - ccritical.add_argument (new CCodeMemberAccess.pointer (inner_error, "code")); - - var cclear = new CCodeFunctionCall (new CCodeIdentifier ("g_clear_error")); - cclear.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, inner_error)); - - // print critical message - ccode.add_expression (ccritical); - ccode.add_expression (cclear); - - if (is_in_constructor () || is_in_destructor ()) { - // just print critical, do not return prematurely - } else if (current_method is CreationMethod) { - if (current_method.parent_symbol is Struct) { - ccode.add_return (); - } else { - ccode.add_return (new CCodeConstant ("NULL")); - } - } else if (is_in_coroutine ()) { - var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref")); - unref.add_argument (get_variable_cexpression ("_async_result")); - ccode.add_expression (unref); - ccode.add_return (new CCodeConstant ("FALSE")); - } else if (current_return_type != null) { - return_default_value (current_return_type, true); - } - } - - bool in_finally_block (CodeNode node) { - var current_node = node; - while (current_node != null) { - var try_stmt = current_node.parent_node as TryStatement; - if (try_stmt != null && try_stmt.finally_body == current_node) { - return true; - } - current_node = current_node.parent_node; - } - return false; - } - - public override void add_simple_check (CodeNode node, bool always_fails = false) { - current_method_inner_error = true; - - if (always_fails) { - // inner_error is always set, avoid unnecessary if statement - // eliminates C warnings - } else { - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_inner_error_cexpression (), new CCodeConstant ("NULL")); - var unlikely = new CCodeFunctionCall (new CCodeIdentifier ("G_UNLIKELY")); - unlikely.add_argument (ccond); - ccode.open_if (unlikely); - } - - if (current_try != null) { - // surrounding try found - - // free local variables - if (is_in_catch) { - append_local_free (current_symbol, null, current_catch); - } else { - append_local_free (current_symbol, null, current_try); - } - - var error_types = new ArrayList (); - node.get_error_types (error_types); - - bool has_general_catch_clause = false; - - if (!is_in_catch) { - var handled_error_types = new ArrayList (); - foreach (CatchClause clause in current_try.get_catch_clauses ()) { - // keep track of unhandled error types - foreach (DataType node_error_type in error_types) { - if (clause.error_type == null || node_error_type.compatible (clause.error_type)) { - handled_error_types.add (node_error_type); - } - } - foreach (DataType handled_error_type in handled_error_types) { - error_types.remove (handled_error_type); - } - handled_error_types.clear (); - - if (clause.error_type.equals (gerror_type)) { - // general catch clause, this should be the last one - has_general_catch_clause = true; - ccode.add_goto (clause.get_attribute_string ("CCode", "cname")); - break; - } else { - unowned ErrorType catch_type = (ErrorType) clause.error_type; - - if (catch_type.error_code != null) { - /* catch clause specifies a specific error code */ - var error_match = new CCodeFunctionCall (new CCodeIdentifier ("g_error_matches")); - error_match.add_argument (get_inner_error_cexpression ()); - error_match.add_argument (new CCodeIdentifier (get_ccode_upper_case_name (catch_type.error_domain))); - error_match.add_argument (new CCodeIdentifier (get_ccode_name (catch_type.error_code))); - - ccode.open_if (error_match); - } else { - /* catch clause specifies a full error domain */ - var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, - new CCodeMemberAccess.pointer (get_inner_error_cexpression (), "domain"), new CCodeIdentifier - (get_ccode_upper_case_name (catch_type.error_domain))); - - ccode.open_if (ccond); - } - - // go to catch clause if error domain matches - ccode.add_goto (clause.get_attribute_string ("CCode", "cname")); - ccode.close (); - } - } - } - - if (has_general_catch_clause) { - // every possible error is already caught - // as there is a general catch clause - // no need to do anything else - } else if (error_types.size > 0) { - // go to finally clause if no catch clause matches - // and there are still unhandled error types - ccode.add_goto ("__finally%d".printf (current_try_id)); - } else if (in_finally_block (node)) { - // do not check unexpected errors happening within finally blocks - // as jump out of finally block is not supported - } else { - // should never happen with correct bindings - uncaught_error_statement (get_inner_error_cexpression (), true, current_try); - } - } else if (current_method != null && current_method.tree_can_fail) { - // current method can fail, propagate error - CCodeBinaryExpression ccond = null; - - var error_types = new ArrayList (); - current_method.get_error_types (error_types); - foreach (DataType error_type in error_types) { - // If GLib.Error is allowed we propagate everything - if (error_type.equals (gerror_type)) { - ccond = null; - break; - } - - // Check the allowed error domains to propagate - var domain_check = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeMemberAccess.pointer - (get_inner_error_cexpression (), "domain"), new CCodeIdentifier (get_ccode_upper_case_name (((ErrorType) error_type).error_domain))); - if (ccond == null) { - ccond = domain_check; - } else { - ccond = new CCodeBinaryExpression (CCodeBinaryOperator.OR, ccond, domain_check); - } - } - - if (ccond != null) { - ccode.open_if (ccond); - return_with_exception (get_inner_error_cexpression ()); - - ccode.add_else (); - uncaught_error_statement (get_inner_error_cexpression ()); - ccode.close (); - } else { - return_with_exception (get_inner_error_cexpression ()); - } - } else { - uncaught_error_statement (get_inner_error_cexpression ()); - } - - if (!always_fails) { - ccode.close (); - } - } - - public override void visit_try_statement (TryStatement stmt) { - int this_try_id = next_try_id++; - - var old_try = current_try; - var old_try_id = current_try_id; - var old_is_in_catch = is_in_catch; - var old_catch = current_catch; - current_try = stmt; - current_try_id = this_try_id; - is_in_catch = true; - - foreach (CatchClause clause in stmt.get_catch_clauses ()) { - clause.set_attribute_string ("CCode", "cname", "__catch%d_%s".printf (this_try_id, get_ccode_lower_case_name (clause.error_type))); - } - - is_in_catch = false; - stmt.body.emit (this); - is_in_catch = true; - - foreach (CatchClause clause in stmt.get_catch_clauses ()) { - current_catch = clause; - ccode.add_goto ("__finally%d".printf (this_try_id)); - clause.emit (this); - } - - current_try = old_try; - current_try_id = old_try_id; - is_in_catch = old_is_in_catch; - current_catch = old_catch; - - ccode.add_label ("__finally%d".printf (this_try_id)); - if (stmt.finally_body != null) { - // use a dedicated inner_error variable, if there - // is some error handling happening in finally-block - current_inner_error_id++; - stmt.finally_body.emit (this); - current_inner_error_id--; - } - - // check for errors not handled by this try statement - // may be handled by outer try statements or propagated - add_simple_check (stmt, !stmt.after_try_block_reachable); - } - - public override void visit_catch_clause (CatchClause clause) { - current_method_inner_error = true; - - var error_type = (ErrorType) clause.error_type; - if (error_type.error_domain != null) { - generate_error_domain_declaration (error_type.error_domain, cfile); - } - - ccode.add_label (clause.get_attribute_string ("CCode", "cname")); - - ccode.open_block (); - - if (clause.error_variable != null && clause.error_variable.used) { - visit_local_variable (clause.error_variable); - ccode.add_assignment (get_variable_cexpression (get_local_cname (clause.error_variable)), get_inner_error_cexpression ()); - ccode.add_assignment (get_inner_error_cexpression (), new CCodeConstant ("NULL")); - } else { - if (clause.error_variable != null) { - clause.error_variable.unreachable = true; - } - // error object is not used within catch statement, clear it - cfile.add_include ("glib.h"); - var cclear = new CCodeFunctionCall (new CCodeIdentifier ("g_clear_error")); - cclear.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ())); - ccode.add_expression (cclear); - } - - clause.body.emit (this); - - ccode.close (); - } - - protected override void append_scope_free (Symbol sym, CodeNode? stop_at = null) { - base.append_scope_free (sym, stop_at); - - if (!(stop_at is TryStatement || stop_at is CatchClause)) { - var finally_block = (Block) null; - if (sym.parent_node is TryStatement) { - finally_block = ((TryStatement) sym.parent_node).finally_body; - } else if (sym.parent_node is CatchClause) { - finally_block = ((TryStatement) sym.parent_node.parent_node).finally_body; - } - - if (finally_block != null && finally_block != sym) { - finally_block.emit (this); - } - } - } -} - -// vim:sw=8 noet diff --git a/src/codegen/valagirwriter.vala b/src/codegen/valagirwriter.vala deleted file mode 100644 index 696c6c8a6..000000000 --- a/src/codegen/valagirwriter.vala +++ /dev/null @@ -1,1840 +0,0 @@ -/* valagirwriter.vala - * - * Copyright (C) 2008-2012 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * Code visitor generating .gir file for the public interface. - */ -public class Vala.GIRWriter : CodeVisitor { - private CodeContext context; - private string directory; - private string gir_namespace; - private string gir_version; - private string gir_shared_library; - - protected virtual string? get_interface_comment (Interface iface) { - return null; - } - - protected virtual string? get_struct_comment (Struct st) { - return null; - } - - protected virtual string? get_enum_comment (Enum en) { - return null; - } - - protected virtual string? get_class_comment (Class c) { - return null; - } - - protected virtual string? get_error_code_comment (ErrorCode ecode) { - return null; - } - - protected virtual string? get_enum_value_comment (EnumValue ev) { - return null; - } - - protected virtual string? get_constant_comment (Constant c) { - return null; - } - - protected virtual string? get_error_domain_comment (ErrorDomain edomain) { - return null; - } - - protected virtual string? get_field_comment (Field f) { - return null; - } - - protected virtual string? get_delegate_comment (Delegate cb) { - return null; - } - - protected virtual string? get_method_comment (Method m) { - return null; - } - - protected virtual string? get_property_comment (Property prop) { - return null; - } - - protected virtual string? get_delegate_return_comment (Delegate cb) { - return null; - } - - protected virtual string? get_signal_return_comment (Signal sig) { - return null; - } - - protected virtual string? get_method_return_comment (Method m) { - return null; - } - - protected virtual string? get_signal_comment (Signal sig) { - return null; - } - - protected virtual string? get_parameter_comment (Parameter param) { - return null; - } - - StringBuilder buffer = new StringBuilder(); - FileStream stream; - Vala.HashSet unannotated_namespaces = new Vala.HashSet(); - Vala.HashSet our_namespaces = new Vala.HashSet(); - Vala.ArrayList hierarchy = new Vala.ArrayList(); - Vala.ArrayList deferred = new Vala.ArrayList(); - - int indent; - - private TypeSymbol gobject_type; - private TypeSymbol ginitiallyunowned_type; - private TypeSymbol gtypeinterface_type; - private TypeSymbol gtypeinstance_type; - private TypeSymbol gtype_type; - - private struct GIRNamespace { - public GIRNamespace (string ns, string version) { - this.ns = ns; this.version = version; - } - public string ns; - public string version; - public bool equal (GIRNamespace g) { - return ((ns == g.ns) && (version == g.version)); - } - - public static GIRNamespace for_symbol (Symbol sym) { - while (sym.parent_symbol != null && sym.parent_symbol.name != null) { - sym = sym.parent_symbol; - } - assert (sym is Namespace); - string gir_namespace = sym.get_attribute_string ("CCode", "gir_namespace"); - string gir_version = sym.get_attribute_string ("CCode", "gir_version"); - return GIRNamespace (gir_namespace, gir_version); - } - } - - private ArrayList externals = new ArrayList ((EqualFunc) GIRNamespace.equal); - - public void write_includes() { - foreach (var i in externals) { - if (i.ns != this.gir_namespace) { - write_indent_stream (); - stream.printf ("\n", i.ns, i.version); - } - } - } - - - /** - * Writes the public interface of the specified code context into the - * specified file. - * - * @param context a code context - * @param gir_filename a relative or absolute filename - */ - public void write_file (CodeContext context, string directory, string gir_filename, string gir_namespace, string gir_version, string package, string? gir_shared_library = null) { - this.context = context; - this.directory = directory; - this.gir_namespace = gir_namespace; - this.gir_version = gir_version; - this.gir_shared_library = gir_shared_library; - - var root_symbol = context.root; - var glib_ns = root_symbol.scope.lookup ("GLib"); - gobject_type = (TypeSymbol) glib_ns.scope.lookup ("Object"); - ginitiallyunowned_type = (TypeSymbol) glib_ns.scope.lookup ("InitiallyUnowned"); - gtypeinterface_type = (TypeSymbol) glib_ns.scope.lookup ("TypeInterface"); - gtypeinstance_type = (TypeSymbol) glib_ns.scope.lookup ("TypeInstance"); - gtype_type = (TypeSymbol) glib_ns.scope.lookup ("Type"); - - write_package (package); - - // Make sure to initialize external files with their gir_namespace/version - foreach (var file in context.get_source_files ()) { - file.accept (this); - } - - context.accept (this); - - indent--; - buffer.append_printf ("\n"); - - string filename = "%s%c%s".printf (directory, Path.DIR_SEPARATOR, gir_filename); - var file_exists = FileUtils.test (filename, FileTest.EXISTS); - var temp_filename = "%s.valatmp".printf (filename); - - if (file_exists) { - stream = FileStream.open (temp_filename, "w"); - } else { - stream = FileStream.open (filename, "w"); - } - - if (stream == null) { - Report.error (null, "unable to open `%s' for writing", filename); - this.context = null; - return; - } - - stream.printf ("\n"); - - var header = context.version_header ? - "".printf (Path.get_basename (filename), Environment.get_prgname (), Vala.BUILD_VERSION) : - "".printf (Path.get_basename (filename), Environment.get_prgname ()); - stream.printf ("%s\n", header); - - stream.printf ("\n"); - indent++; - - write_includes(); - indent--; - - stream.puts (buffer.str); - stream = null; - - if (file_exists) { - var changed = true; - - try { - var old_file = new MappedFile (filename, false); - var new_file = new MappedFile (temp_filename, false); - var len = old_file.get_length (); - if (len == new_file.get_length ()) { - if (Memory.cmp (old_file.get_contents (), new_file.get_contents (), len) == 0) { - changed = false; - } - } - old_file = null; - new_file = null; - } catch (FileError e) { - // assume changed if mmap comparison doesn't work - } - - if (changed) { - FileUtils.rename (temp_filename, filename); - } else { - FileUtils.unlink (temp_filename); - } - } - - foreach (var ns in unannotated_namespaces) { - if (!our_namespaces.contains(ns)) { - Report.warning (ns.source_reference, "Namespace `%s' does not have a GIR namespace and version annotation", ns.name); - } - } - foreach (var ns in our_namespaces) { - ns.source_reference.file.gir_namespace = gir_namespace; - ns.source_reference.file.gir_version = gir_version; - } - - if (our_namespaces.size == 0) { - Report.error (null, "No suitable namespace found to export for GIR"); - } - - this.context = null; - } - - private void write_doc (string? comment) { - if (comment != null) { - write_indent (); - buffer.append (""); - buffer.append (comment); - buffer.append ("\n"); - } - } - - private void write_package (string package) { - write_indent (); - buffer.append_printf ("\n", package); - } - - private void write_c_includes (Namespace ns) { - // Collect C header filenames - Set header_filenames = new HashSet (str_hash, str_equal); - foreach (unowned string c_header_filename in get_ccode_header_filenames (ns).split (",")) { - header_filenames.add (c_header_filename); - } - foreach (Symbol symbol in ns.scope.get_symbol_table ().get_values ()) { - if (symbol.external_package) { - continue; - } - foreach (unowned string c_header_filename in get_ccode_header_filenames (symbol).split (",")) { - header_filenames.add (c_header_filename); - } - } - - // Generate c:include tags - foreach (string c_header_filename in header_filenames) { - write_c_include (c_header_filename); - } - } - - private void write_c_include (string name) { - write_indent (); - buffer.append_printf ("\n", name); - } - - public override void visit_source_file (SourceFile source_file) { - if (source_file.file_type != SourceFileType.PACKAGE) { - return; - } - - // Populate gir_namespace/version of source-file like in Namespace.check() - foreach (var node in source_file.get_nodes ()) { - if (node is Namespace && ((Namespace) node).parent_symbol == context.root) { - var a = node.get_attribute ("CCode"); - if (a != null && a.has_argument ("gir_namespace")) { - var new_gir = a.get_string ("gir_namespace"); - var old_gir = source_file.gir_namespace; - if (old_gir != null && old_gir != new_gir) { - source_file.gir_ambiguous = true; - } - source_file.gir_namespace = new_gir; - } - if (a != null && a.has_argument ("gir_version")) { - source_file.gir_version = a.get_string ("gir_version"); - } - break; - } - } - } - - public override void visit_namespace (Namespace ns) { - if (ns.external_package) { - return; - } - - if (!is_visibility (ns)) { - return; - } - - if (ns.name == null) { - // global namespace - hierarchy.insert (0, ns); - ns.accept_children (this); - hierarchy.remove_at (0); - return; - } - - if (ns.parent_symbol.name != null) { - ns.accept_children (this); - return; - } - - if (our_namespaces.size > 0) { - Report.error (ns.source_reference, "Secondary top-level namespace `%s' is not supported by GIR format", ns.name); - return; - } - - // Use given gir_namespace and gir_version for our top-level namespace - var old_gir_namespace = ns.get_attribute_string ("CCode", "gir_namespace"); - var old_gir_version = ns.get_attribute_string ("CCode", "gir_version"); - if ((old_gir_namespace != null && old_gir_namespace != gir_namespace) - || (old_gir_version != null && old_gir_version != gir_version)) { - Report.warning (ns.source_reference, "Replace conflicting CCode.gir_* attributes for namespace `%s'".printf (ns.name)); - } - ns.set_attribute_string ("CCode", "gir_namespace", gir_namespace); - ns.set_attribute_string ("CCode", "gir_version", gir_version); - - write_c_includes (ns); - - write_indent (); - buffer.append_printf ("\n"); - indent++; - - hierarchy.insert (0, ns); - ns.accept_children (this); - hierarchy.remove_at (0); - - indent--; - write_indent (); - buffer.append_printf ("\n"); - our_namespaces.add(ns); - - visit_deferred (); - } - - private void write_symbol_attributes (Symbol symbol) { - if (!is_introspectable (symbol)) { - buffer.append_printf (" introspectable=\"0\""); - } - if (symbol.version.deprecated) { - buffer.append_printf (" deprecated=\"1\""); - if (symbol.version.deprecated_since != null) { - buffer.append_printf (" deprecated-version=\"%s\"", symbol.version.deprecated_since); - } - } - if (symbol.version.since != null) { - buffer.append_printf (" version=\"%s\"", symbol.version.since); - } - } - - public override void visit_class (Class cl) { - if (cl.external_package) { - return; - } - - if (!check_accessibility (cl)) { - return; - } - - if (!has_namespace (cl)) { - return; - } - - if (!(hierarchy[0] is Namespace)) { - deferred.add (cl); - return; - } - - if (!cl.is_compact) { - string gtype_struct_name = get_gir_name (cl) + "Class"; - - write_indent (); - buffer.append_printf ("\n"); - indent++; - - write_doc (get_class_comment (cl)); - - // write implemented interfaces - foreach (DataType base_type in cl.get_base_types ()) { - var object_type = (ObjectType) base_type; - if (object_type.type_symbol is Interface) { - write_indent (); - buffer.append_printf ("\n", gi_type_name (object_type.type_symbol)); - } - } - - write_indent (); - buffer.append_printf ("\n"); - indent++; - write_indent (); - if (cl.base_class == null) { - buffer.append_printf ("\n", gi_type_name (gtypeinstance_type), get_ccode_name (gtypeinstance_type)); - } else { - buffer.append_printf ("\n", gi_type_name (cl.base_class), get_ccode_name (cl.base_class)); - } - indent--; - write_indent (); - buffer.append_printf("\n"); - - if (cl.base_class == null) { - write_indent (); - buffer.append_printf ("\n"); - indent++; - write_indent (); - buffer.append_printf ("\n"); - indent--; - write_indent (); - buffer.append_printf("\n"); - } - - if (!context.abi_stability) { - write_indent (); - buffer.append_printf ("\n"); - indent++; - write_indent (); - buffer.append_printf ("\n", get_gir_name (cl), get_ccode_name (cl)); - indent--; - write_indent (); - buffer.append_printf("\n"); - } - - if (cl.base_class != null && cl.base_class.is_subtype_of (gobject_type)) { - foreach (var p in cl.get_type_parameters ()) { - write_type_parameter (p, "property"); - } - } - - hierarchy.insert (0, cl); - cl.accept_children (this); - hierarchy.remove_at (0); - - if (context.abi_stability) { - write_indent (); - buffer.append_printf ("\n"); - indent++; - write_indent (); - buffer.append_printf ("\n", get_gir_name (cl), get_ccode_name (cl)); - indent--; - write_indent (); - buffer.append_printf("\n"); - } - - indent--; - write_indent (); - buffer.append_printf ("\n"); - - write_indent (); - buffer.append_printf ("\n"); - indent++; - - write_indent (); - buffer.append_printf ("\n"); - indent++; - write_indent (); - if (cl.base_class == null) { - //FIXME GObject.TypeClass vs GType - buffer.append_printf ("\n", "GObject.Type", get_ccode_name (gtype_type)); - } else { - buffer.append_printf ("\n", gi_type_name (cl.base_class), get_ccode_name (cl.base_class)); - } - indent--; - write_indent (); - buffer.append_printf ("\n"); - - foreach (Method m in cl.get_methods ()) { - if (m.is_abstract || m.is_virtual) { - if (m.coroutine) { - string finish_name = m.name; - if (finish_name.has_suffix ("_async")) { - finish_name = finish_name.substring (0, finish_name.length - "_async".length); - } - finish_name += "_finish"; - - write_indent (); - buffer.append_printf("\n"); - indent++; - do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_async_begin_parameters (), new VoidType (), false, false, false); - indent--; - write_indent (); - buffer.append_printf ("\n"); - - write_indent (); - buffer.append_printf("\n"); - indent++; - do_write_signature (m, "callback", true, finish_name, get_ccode_finish_name (m), m.get_async_end_parameters (), m.return_type, m.tree_can_fail, false, false); - indent--; - write_indent (); - buffer.append_printf ("\n"); - } else { - write_indent (); - buffer.append_printf("\n"); - indent++; - do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, false, false); - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - } - } - - foreach (Signal sig in cl.get_signals ()) { - if (sig.default_handler != null) { - write_indent (); - buffer.append_printf ("\n"); - indent++; - write_signature (sig.default_handler, "callback", false, true, false); - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - } - - indent--; - write_indent (); - buffer.append_printf ("\n"); - - write_indent (); - buffer.append_printf ("\n", get_gir_name (cl), get_ccode_name (cl)); - } else { - write_indent (); - buffer.append_printf ("\n"); - indent++; - - write_doc (get_class_comment (cl)); - - hierarchy.insert (0, cl); - cl.accept_children (this); - hierarchy.remove_at (0); - - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - - visit_deferred (); - } - - public override void visit_struct (Struct st) { - if (st.external_package) { - return; - } - - if (!check_accessibility (st)) { - return; - } - - if (!has_namespace (st)) { - return; - } - - if (!(hierarchy[0] is Namespace)) { - deferred.add (st); - return; - } - - write_indent (); - buffer.append_printf ("\n"); - indent++; - - write_doc (get_struct_comment (st)); - - hierarchy.insert (0, st); - st.accept_children (this); - hierarchy.remove_at (0); - - indent--; - write_indent (); - buffer.append_printf ("\n"); - - visit_deferred (); - } - - public override void visit_interface (Interface iface) { - if (iface.external_package) { - return; - } - - if (!check_accessibility (iface)) { - return; - } - - if (!has_namespace (iface)) { - return; - } - - if (!(hierarchy[0] is Namespace)) { - deferred.add (iface); - return; - } - - string gtype_struct_name = get_gir_name (iface) + "Iface"; - - write_indent (); - buffer.append_printf ("\n"); - indent++; - - write_doc (get_interface_comment (iface)); - - // write prerequisites - if (iface.get_prerequisites ().size > 0) { - foreach (DataType base_type in iface.get_prerequisites ()) { - write_indent (); - buffer.append_printf ("\n", gi_type_name (((ObjectType) base_type).type_symbol)); - } - } - - hierarchy.insert (0, iface); - iface.accept_children (this); - hierarchy.remove_at (0); - - indent--; - write_indent (); - buffer.append_printf ("\n"); - - write_indent (); - buffer.append_printf ("\n"); - indent++; - - write_indent (); - buffer.append_printf ("\n"); - indent++; - write_indent (); - buffer.append_printf ("\n", gi_type_name (gtypeinterface_type), get_ccode_name (gtypeinterface_type)); - indent--; - write_indent (); - buffer.append_printf ("\n"); - - foreach (Method m in iface.get_methods ()) { - if (m.is_abstract || m.is_virtual) { - if (m.coroutine) { - string finish_name = m.name; - if (finish_name.has_suffix ("_async")) { - finish_name = finish_name.substring (0, finish_name.length - "_async".length); - } - finish_name += "_finish"; - - write_indent (); - buffer.append_printf("\n"); - indent++; - do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_async_begin_parameters (), new VoidType (), false, false, false); - indent--; - write_indent (); - buffer.append_printf ("\n"); - - write_indent (); - buffer.append_printf("\n"); - indent++; - do_write_signature (m, "callback", true, finish_name, get_ccode_finish_name (m), m.get_async_end_parameters (), m.return_type, m.tree_can_fail, false, false); - indent--; - write_indent (); - buffer.append_printf ("\n"); - } else { - write_indent (); - buffer.append_printf("\n"); - indent++; - do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, false, false); - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - } - } - - foreach (var prop in iface.get_properties ()) { - if (prop.is_abstract || prop.is_virtual) { - if (prop.get_accessor != null) { - var m = prop.get_accessor.get_method (); - write_indent (); - buffer.append_printf("\n"); - indent++; - do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, false, false); - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - - if (prop.set_accessor != null && prop.set_accessor.writable) { - var m = prop.set_accessor.get_method (); - write_indent (); - buffer.append_printf("\n"); - indent++; - do_write_signature (m, "callback", true, m.name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, false, false); - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - } - } - - indent--; - write_indent (); - buffer.append_printf ("\n"); - - visit_deferred (); - } - - private void visit_deferred () { - var nodes = this.deferred; - this.deferred = new Vala.ArrayList(); - - foreach (var node in nodes) { - node.accept (this); - } - } - - private string? get_gir_name (Symbol symbol) { - string? gir_name = null; - var h0 = hierarchy[0]; - - for (Symbol? cur_sym = symbol ; cur_sym != null ; cur_sym = cur_sym.parent_symbol) { - if (cur_sym == h0) { - break; - } - - var cur_name = cur_sym.get_attribute_string ("GIR", "name"); - if (cur_name == null) { - cur_name = cur_sym.name; - } - gir_name = cur_name.concat (gir_name); - } - - return gir_name; - } - - public override void visit_enum (Enum en) { - if (en.external_package) { - return; - } - - if (!check_accessibility (en)) { - return; - } - - if (!has_namespace (en)) { - return; - } - - if (!(hierarchy[0] is Namespace)) { - deferred.add (en); - return; - } - - string element_name = (en.is_flags) ? "bitfield" : "enumeration"; - - write_indent (); - buffer.append_printf ("<%s name=\"%s\"", element_name, get_gir_name (en)); - if (get_ccode_has_type_id (en)) { - write_gtype_attributes (en); - } else { - write_ctype_attributes (en); - } - write_symbol_attributes (en); - buffer.append_printf (">\n"); - indent++; - - write_doc (get_enum_comment (en)); - - enum_value = 0; - hierarchy.insert (0, en); - en.accept_children (this); - hierarchy.remove_at (0); - - indent--; - write_indent (); - buffer.append_printf ("\n", element_name); - - visit_deferred (); - } - - private int enum_value; - - public override void visit_enum_value (EnumValue ev) { - write_indent (); - var en = (Enum) hierarchy[0]; - buffer.append_printf ("\n"); - } else { - buffer.append_printf (">\n"); - indent++; - - write_doc (comment); - - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - } - - public override void visit_error_domain (ErrorDomain edomain) { - if (edomain.external_package) { - return; - } - - if (!check_accessibility (edomain)) { - return; - } - - if (!has_namespace (edomain)) { - return; - } - - write_indent (); - buffer.append_printf ("\n"); - indent++; - - write_doc (get_error_domain_comment (edomain)); - - enum_value = 0; - hierarchy.insert (0, edomain); - edomain.accept_children (this); - hierarchy.remove_at (0); - - indent--; - write_indent (); - buffer.append_printf ("\n"); - - visit_deferred (); - } - - public override void visit_error_code (ErrorCode ecode) { - write_indent (); - buffer.append_printf ("\n"); - } else { - buffer.append_printf (">\n"); - indent++; - - write_doc (comment); - - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - } - - public override void visit_constant (Constant c) { - if (c.external_package) { - return; - } - - if (!check_accessibility (c)) { - return; - } - - if (!has_namespace (c)) { - return; - } - - //TODO Add better constant evaluation - var initializer = c.value; - string value = literal_expression_to_value_string (initializer); - - write_indent (); - buffer.append_printf ("\n"); - indent++; - - write_doc (get_constant_comment (c)); - - write_type (initializer.value_type); - - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - - public override void visit_field (Field f) { - if (f.external_package) { - return; - } - - if (!check_accessibility (f)) { - return; - } - - if (!has_namespace (f)) { - return; - } - - write_indent (); - buffer.append_printf ("\n"); - indent++; - - write_doc (get_field_comment (f)); - - write_type (f.variable_type); - - indent--; - write_indent (); - buffer.append_printf ("\n"); - - if (f.variable_type is ArrayType && get_ccode_array_length (f)) { - var array_type = (ArrayType) f.variable_type; - if (!array_type.fixed_length) { - for (var i = 0; i < array_type.rank; i++) { - write_indent (); - buffer.append_printf ("\n"); - indent++; - write_type (array_type.length_type); - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - } - } else if (f.variable_type is DelegateType) { - var deleg_type = (DelegateType) f.variable_type; - if (deleg_type.delegate_symbol.has_target) { - write_indent (); - buffer.append_printf ("\n"); - indent++; - write_indent (); - buffer.append_printf ("\n"); - indent--; - write_indent (); - buffer.append_printf ("\n"); - if (deleg_type.is_disposable ()) { - write_indent (); - buffer.append_printf ("\n"); - indent++; - write_indent (); - buffer.append_printf ("\n"); - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - } - } - } - - private void write_implicit_params (DataType? type, ref int index, bool has_array_length, string? name, ParameterDirection direction) { - if (type is ArrayType && has_array_length) { - for (var i = 0; i < ((ArrayType) type).rank; i++) { - write_param_or_return (((ArrayType) type).length_type, "parameter", ref index, has_array_length, "%s_length%i".printf (name, i + 1), null, direction); - } - } else if (type is DelegateType) { - var deleg_type = (DelegateType) type; - if (deleg_type.delegate_symbol.has_target) { - var data_type = new PointerType (new VoidType ()); - write_param_or_return (data_type, "parameter", ref index, false, "%s_target".printf (name), null, direction); - if (deleg_type.is_disposable ()) { - var notify_type = new DelegateType (context.root.scope.lookup ("GLib").scope.lookup ("DestroyNotify") as Delegate); - write_param_or_return (notify_type, "parameter", ref index, false, "%s_target_destroy_notify".printf (name), null, direction); - } - } - } - } - - void skip_implicit_params (DataType? type, ref int index, bool has_array_length) { - if (type is ArrayType && has_array_length) { - index += ((ArrayType) type).rank; - } else if (type is DelegateType) { - index++; - var deleg_type = (DelegateType) type; - if (deleg_type.is_disposable ()) { - index++; - } - } - } - - private void write_type_parameter (TypeParameter type_parameter, string tag_type) { - write_indent (); - if (tag_type == "property") { - buffer.append_printf ("<%s name=\"%s\" writable=\"1\" construct-only=\"1\">\n", tag_type, get_ccode_type_id (type_parameter).replace ("_", "-")); - } else { - buffer.append_printf ("<%s name=\"%s\" transfer-ownership=\"none\">\n", tag_type, get_ccode_type_id (type_parameter)); - } - indent++; - write_indent (); - buffer.append_printf ("\n"); - indent--; - write_indent (); - buffer.append_printf ("\n", tag_type); - write_indent (); - if (tag_type == "property") { - buffer.append_printf ("<%s name=\"%s\" writable=\"1\" construct-only=\"1\">\n", tag_type, get_ccode_copy_function (type_parameter).replace ("_", "-")); - } else { - buffer.append_printf ("<%s name=\"%s\" transfer-ownership=\"none\">\n", tag_type, get_ccode_copy_function (type_parameter)); - } - indent++; - write_indent (); - buffer.append_printf ("\n"); - indent--; - write_indent (); - buffer.append_printf ("\n", tag_type); - write_indent (); - if (tag_type == "property") { - buffer.append_printf ("<%s name=\"%s\" writable=\"1\" construct-only=\"1\">\n", tag_type, get_ccode_destroy_function (type_parameter).replace ("_", "-")); - } else { - buffer.append_printf ("<%s name=\"%s\" transfer-ownership=\"none\">\n", tag_type, get_ccode_destroy_function (type_parameter)); - } - indent++; - write_indent (); - buffer.append_printf ("\n"); - indent--; - write_indent (); - buffer.append_printf ("\n", tag_type); - } - - private void write_params_and_return (string tag_name, List params, List? type_params, DataType? return_type, bool return_array_length, string? return_comment = null, bool constructor = false, Parameter? instance_param = null, bool user_data = false) { - int last_index = 0; - bool ret_is_struct = return_type != null && return_type.is_real_non_null_struct_type (); - - if (params.size != 0 || (return_type is ArrayType && return_array_length) || (return_type is DelegateType) || ret_is_struct) { - int index = 0; - - foreach (Parameter param in params) { - index++; - - skip_implicit_params (param.variable_type, ref index, get_ccode_array_length (param)); - } - - if (ret_is_struct) { - index++; - } else { - skip_implicit_params (return_type, ref index, return_array_length); - if (return_type is ArrayType && return_array_length) { - index -= ((ArrayType) return_type).rank - 1; - } - } - - last_index = index - 1; - } - - if (return_type != null && !ret_is_struct) { - write_param_or_return (return_type, "return-value", ref last_index, return_array_length, null, return_comment, ParameterDirection.IN, constructor); - } else if (ret_is_struct) { - write_param_or_return (new VoidType (), "return-value", ref last_index, false, null, return_comment, ParameterDirection.IN); - } - - if (params.size != 0 || (type_params != null && type_params.size > 0) || instance_param != null || (return_type is ArrayType && return_array_length) || (return_type is DelegateType) || ret_is_struct) { - write_indent (); - buffer.append_printf ("\n"); - indent++; - int index = 0; - - if (instance_param != null) { - var type = instance_param.variable_type.copy (); - unowned Struct? st = type.type_symbol as Struct; - if (st != null && !st.is_simple_type ()) { - type.nullable = true; - } - int skip = 0; - if (tag_name == "callback") { - write_param_or_return (type, "parameter", ref skip, false, "self"); - index++; - } else { - write_param_or_return (type, "instance-parameter", ref skip, false, "self"); - } - } - - if (constructor && ret_is_struct) { - // struct constructor has a caller-allocates / out-parameter as instance - write_param_or_return (return_type, "instance-parameter", ref index, false, "self", return_comment, ParameterDirection.OUT, constructor, true); - } - - if (type_params != null) { - foreach (var p in type_params) { - write_type_parameter (p, "parameter"); - index += 3; - } - } - - foreach (Parameter param in params) { - write_param_or_return (param.variable_type, "parameter", ref index, get_ccode_array_length (param), get_ccode_name (param), get_parameter_comment (param), param.direction, false, false, param.ellipsis || param.params_array); - - write_implicit_params (param.variable_type, ref index, get_ccode_array_length (param), get_ccode_name (param), param.direction); - } - - if (!constructor && ret_is_struct) { - // struct returns are converted to parameters - write_param_or_return (return_type, "parameter", ref index, false, "result", return_comment, ParameterDirection.OUT, constructor, true); - } else if (!constructor) { - write_implicit_params (return_type, ref index, return_array_length, "result", ParameterDirection.OUT); - } - - if (user_data) { - write_indent (); - buffer.append_printf ("\n", index); - indent++; - write_indent (); - buffer.append_printf ("\n"); - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - } - - public override void visit_delegate (Delegate cb) { - if (cb.external_package) { - return; - } - - if (!check_accessibility (cb)) { - return; - } - - if (!has_namespace (cb)) { - return; - } - - write_indent (); - buffer.append_printf ("\n"); - indent++; - - write_doc (get_delegate_comment (cb)); - - write_params_and_return ("callback", cb.get_parameters (), cb.get_type_parameters (), cb.return_type, get_ccode_array_length (cb), get_delegate_return_comment (cb), false, null, cb.has_target); - - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - - public override void visit_method (Method m) { - if (m.external_package) { - return; - } - - // don't write interface implementation unless it's an abstract or virtual method - if (!check_accessibility (m) || m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) { - return; - } - - if (!has_namespace (m)) { - return; - } - - string tag_name = "method"; - var parent = this.hierarchy.get (0); - if (parent is Enum) { - deferred.add (m); - return; - } - - if (parent is Namespace || m.binding == MemberBinding.STATIC || parent != m.parent_symbol) { - tag_name = "function"; - } - - if (!get_ccode_no_wrapper (m) && m.signal_reference == null) { - write_signature (m, tag_name, true); - } - - if (m.is_abstract || m.is_virtual) { - write_signature (m, "virtual-method", true, false); - } - } - - bool is_type_introspectable (DataType type) { - // gobject-introspection does not currently support va_list parameters - if (get_ccode_name (type) == "va_list") { - return false; - } - - return true; - } - - bool is_method_introspectable (Method m) { - if (!is_type_introspectable (m.return_type)) { - return false; - } - foreach (var param in m.get_parameters ()) { - if (param.ellipsis || param.params_array || !is_type_introspectable (param.variable_type)) { - return false; - } - } - return true; - } - - bool is_introspectable (Symbol sym) { - if (sym is Method && !is_method_introspectable ((Method) sym)) { - return false; - } - - return is_visibility (sym); - } - - private void write_signature (Method m, string tag_name, bool write_doc, bool instance = false, bool write_attributes = true) { - var parent = this.hierarchy.get (0); - string name; - if (m.parent_symbol != parent) { - instance = false; - name = get_ccode_name (m); - var parent_prefix = get_ccode_lower_case_prefix (parent); - if (name.has_prefix (parent_prefix)) { - name = name.substring (parent_prefix.length); - } - } else { - name = m.name; - } - - if (m.coroutine) { - string finish_name = name; - if (finish_name.has_suffix ("_async")) { - finish_name = finish_name.substring (0, finish_name.length - "_async".length); - } - finish_name += "_finish"; - do_write_signature (m, tag_name, instance, name, get_ccode_name (m), m.get_async_begin_parameters (), new VoidType (), false, true, write_attributes); - do_write_signature (m, tag_name, instance, finish_name, get_ccode_finish_name (m), m.get_async_end_parameters (), m.return_type, m.tree_can_fail, false, write_attributes); - } else { - do_write_signature (m, tag_name, instance, name, get_ccode_name (m), m.get_parameters (), m.return_type, m.tree_can_fail, true, write_attributes); - } - } - - private void do_write_signature (Method m, string tag_name, bool instance, string name, string cname, List params, DataType return_type, bool can_fail, bool write_comment, bool write_attributes = true) { - write_indent (); - buffer.append_printf ("<%s name=\"%s\"", tag_name, name); - if (tag_name == "virtual-method") { - if (!get_ccode_no_wrapper (m)) { - buffer.append_printf (" invoker=\"%s\"", name); - } - } else if (tag_name == "callback") { - /* this is only used for vfuncs */ - buffer.append_printf (" c:type=\"%s\"", name); - } else { - buffer.append_printf (" c:identifier=\"%s\"", cname); - } - if (can_fail) { - buffer.append_printf (" throws=\"1\""); - } - if (write_attributes) { - write_symbol_attributes (m); - } - buffer.append_printf (">\n"); - indent++; - - string? return_comment = null; - if (write_comment) { - return_comment = get_method_return_comment (m); - write_doc (get_method_comment (m)); - } - - write_params_and_return (tag_name, params, m.get_type_parameters (), return_type, get_ccode_array_length (m), return_comment, false, m.this_parameter); - - indent--; - write_indent (); - buffer.append_printf ("\n", tag_name); - } - - public override void visit_creation_method (CreationMethod m) { - if (m.external_package) { - return; - } - - if (!check_accessibility (m)) { - return; - } - - if (m.parent_symbol is Class && ((Class) m.parent_symbol).is_abstract) { - return; - } - - write_indent (); - - bool is_struct = m.parent_symbol is Struct; - // GI doesn't like constructors that return void type - string tag_name = is_struct ? "method" : "constructor"; - - if (m.parent_symbol is Class && m == ((Class)m.parent_symbol).default_construction_method || - m.parent_symbol is Struct && m == ((Struct)m.parent_symbol).default_construction_method) { - string m_name = is_struct ? "init" : "new"; - buffer.append_printf ("<%s name=\"%s\" c:identifier=\"%s\"", tag_name, m_name, get_ccode_name (m)); - } else if (is_struct) { - buffer.append_printf ("<%s name=\"init_%s\" c:identifier=\"%s\"", tag_name, m.name, get_ccode_name (m)); - } else { - buffer.append_printf ("<%s name=\"%s\" c:identifier=\"%s\"", tag_name, m.name, get_ccode_name (m)); - } - - if (m.tree_can_fail) { - buffer.append_printf (" throws=\"1\""); - } - write_symbol_attributes (m); - buffer.append_printf (">\n"); - indent++; - - write_doc (get_method_comment (m)); - - var datatype = SemanticAnalyzer.get_data_type_for_symbol (m.parent_symbol); - List? type_params = null; - if (m.parent_symbol is Class) { - type_params = ((Class) m.parent_symbol).get_type_parameters (); - } - write_params_and_return (tag_name, m.get_parameters (), type_params, datatype, false, get_method_return_comment (m), true); - - indent--; - write_indent (); - buffer.append_printf ("\n", tag_name); - } - - public override void visit_property (Property prop) { - if (!check_accessibility (prop) || prop.overrides || (prop.base_interface_property != null && !prop.is_abstract && !prop.is_virtual)) { - return; - } - - if (context.analyzer.is_gobject_property (prop)) { - write_indent (); - buffer.append_printf ("\n"); - indent++; - - write_doc (get_property_comment (prop)); - - write_type (prop.property_type); - - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - - if (prop.get_accessor != null) { - var m = prop.get_accessor.get_method (); - if (m != null) { - visit_method (m); - } - } - - if (prop.set_accessor != null) { - var m = prop.set_accessor.get_method (); - if (m != null) { - visit_method (m); - } - } - } - - public override void visit_signal (Signal sig) { - if (!check_accessibility (sig)) { - return; - } - - if (sig.emitter != null) { - sig.emitter.accept (this); - } - - if (sig.default_handler != null) { - sig.default_handler.accept (this); - } - - write_indent (); - buffer.append_printf ("\n"); - indent++; - - write_doc (get_signal_comment (sig)); - - write_params_and_return ("glib:signal", sig.get_parameters (), null, sig.return_type, false, get_signal_return_comment (sig)); - - indent--; - write_indent (); - buffer.append_printf ("\n"); - } - - private void write_indent () { - int i; - - for (i = 0; i < indent; i++) { - buffer.append_c ('\t'); - } - } - - private void write_indent_stream () { - int i; - - for (i = 0; i < indent; i++) { - stream.putc ('\t'); - } - } - - - private void write_param_or_return (DataType? type, string tag, ref int index, bool has_array_length, string? name = null, string? comment = null, ParameterDirection direction = ParameterDirection.IN, bool constructor = false, bool caller_allocates = false, bool ellipsis = false) { - write_indent (); - buffer.append_printf ("<%s", tag); - if (ellipsis) { - name = "..."; - } - if (name != null) { - buffer.append_printf (" name=\"%s\"", name); - } - if (direction == ParameterDirection.REF) { - buffer.append_printf (" direction=\"inout\""); - } else if (direction == ParameterDirection.OUT) { - buffer.append_printf (" direction=\"out\""); - } - - unowned DelegateType? delegate_type = type as DelegateType; - unowned ArrayType? array_type = type as ArrayType; - - if (type != null && ((type.value_owned && delegate_type == null) || (constructor - && !(type.type_symbol is Struct || type.type_symbol.is_subtype_of (ginitiallyunowned_type))))) { - var any_owned = false; - foreach (var generic_arg in type.get_type_arguments ()) { - any_owned |= generic_arg.value_owned; - } - if (type.has_type_arguments () && !any_owned) { - buffer.append_printf (" transfer-ownership=\"container\""); - } else if (array_type != null && !array_type.element_type.value_owned) { - buffer.append_printf (" transfer-ownership=\"container\""); - } else { - buffer.append_printf (" transfer-ownership=\"full\""); - } - } else { - buffer.append_printf (" transfer-ownership=\"none\""); - } - if (caller_allocates) { - buffer.append_printf (" caller-allocates=\"1\""); - } - if (type != null && type.nullable) { - if (tag == "parameter" - && (direction == ParameterDirection.OUT || direction == ParameterDirection.REF)) { - buffer.append_printf (" optional=\"1\""); - } else { - buffer.append_printf (" nullable=\"1\""); - } - } - - if (delegate_type != null && delegate_type.delegate_symbol.has_target) { - int closure_index = tag == "parameter" ? - index + 1 : (type.value_owned ? index - 1 : index); - buffer.append_printf (" closure=\"%i\"", closure_index); - if (delegate_type.is_called_once) { - buffer.append (" scope=\"async\""); - } else if (type.value_owned) { - buffer.append_printf (" scope=\"notified\" destroy=\"%i\"", closure_index + 1); - } else { - buffer.append (" scope=\"call\""); - } - } else if (delegate_type != null) { - buffer.append (" scope=\"call\""); - } - - buffer.append_printf (">\n"); - indent++; - - write_doc (comment); - - if (ellipsis) { - write_indent (); - buffer.append ("\n"); - } else if (type != null) { - int length_param_index = -1; - if (has_array_length) { - length_param_index = tag == "parameter" ? index + 1 : index; - } - write_type (type, length_param_index, direction); - } - - indent--; - write_indent (); - buffer.append_printf ("\n", tag); - index++; - } - - private void write_ctype_attributes (TypeSymbol symbol, string suffix = "", bool symbol_prefix = false) { - buffer.append_printf (" c:type=\"%s%s\"", get_ccode_name (symbol), suffix); - if (symbol_prefix) { - buffer.append_printf (" c:symbol-prefix=\"%s\"", get_ccode_lower_case_suffix (symbol)); - } - } - - private void write_gtype_attributes (TypeSymbol symbol, bool symbol_prefix = false) { - write_ctype_attributes(symbol, "", symbol_prefix); - buffer.append_printf (" glib:type-name=\"%s\"", get_ccode_name (symbol)); - buffer.append_printf (" glib:get-type=\"%sget_type\"", get_ccode_lower_case_prefix (symbol)); - } - - private void write_type (DataType type, int index = -1, ParameterDirection direction = ParameterDirection.IN) { - if (type is ArrayType) { - var array_type = (ArrayType) type; - - write_indent (); - buffer.append_printf ("\n"); - indent++; - - write_type (array_type.element_type); - - indent--; - write_indent (); - buffer.append_printf ("\n"); - } else if (type is VoidType) { - write_indent (); - buffer.append_printf ("\n"); - } else if (type is PointerType) { - write_indent (); - buffer.append_printf ("\n", get_ccode_name (type), direction == ParameterDirection.IN ? "" : "*"); - } else if (type is GenericType) { - // generic type parameters not supported in GIR - write_indent (); - buffer.append ("\n"); - } else if (type is DelegateType) { - var deleg_type = (DelegateType) type; - write_indent (); - buffer.append_printf ("\n", gi_type_name (deleg_type.delegate_symbol), get_ccode_name (type), direction == ParameterDirection.IN ? "" : "*"); - } else if (type.type_symbol != null) { - write_indent (); - string type_name = gi_type_name (type.type_symbol); - bool is_array = false; - if ((type_name == "GLib.Array") || (type_name == "GLib.PtrArray")) { - is_array = true; - } - buffer.append_printf ("<%s name=\"%s\" c:type=\"%s%s\"", is_array ? "array" : "type", gi_type_name (type.type_symbol), get_ccode_name (type), direction == ParameterDirection.IN ? "" : "*"); - - List type_arguments = type.get_type_arguments (); - if (type_arguments.size == 0) { - buffer.append_printf ("/>\n"); - } else { - buffer.append_printf (">\n"); - indent++; - - foreach (DataType type_argument in type_arguments) { - write_type (type_argument); - } - - indent--; - write_indent (); - buffer.append_printf ("\n", is_array ? "array" : "type"); - } - } else { - write_indent (); - buffer.append_printf ("\n", type.to_string ()); - } - } - - private string? get_full_gir_name (Symbol sym) { - string? gir_fullname = sym.get_attribute_string ("GIR", "fullname"); - if (gir_fullname != null) { - return gir_fullname; - } - - string? gir_name = sym.get_attribute_string ("GIR", "name"); - - if (gir_name == null && sym is Namespace) { - gir_name = sym.get_attribute_string ("CCode", "gir_namespace"); - } - if (gir_name == null) { - gir_name = sym.name; - } - - if (sym.parent_symbol == null) { - return gir_name; - } - - if (sym.name == null) { - return get_full_gir_name (sym.parent_symbol); - } - - string parent_gir_name = get_full_gir_name (sym.parent_symbol); - if (parent_gir_name == null) { - return gir_name; - } - - string self_gir_name = gir_name.has_prefix (".") ? gir_name.substring (1) : gir_name; - if ("." in parent_gir_name) { - return "%s%s".printf (parent_gir_name, self_gir_name); - } else { - return "%s.%s".printf (parent_gir_name, self_gir_name); - } - } - - private string gi_type_name (TypeSymbol type_symbol) { - Symbol parent = type_symbol.parent_symbol; - if (parent is Namespace) { - Namespace ns = parent as Namespace; - var ns_gir_name = ns.get_attribute_string ("GIR", "name") ?? ns.name; - if (ns_gir_name != null) { - unowned SourceFile source_file = type_symbol.source_reference.file; - if (source_file.gir_namespace != null) { - GIRNamespace external; - if (source_file.gir_ambiguous) { - external = GIRNamespace.for_symbol (type_symbol); - } else { - external = GIRNamespace (source_file.gir_namespace, source_file.gir_version); - } - if (!externals.contains (external)) { - externals.add (external); - } - string? gir_fullname = type_symbol.get_attribute_string ("GIR", "fullname"); - if (gir_fullname != null) { - return gir_fullname; - } - var type_name = type_symbol.get_attribute_string ("GIR", "name") ?? type_symbol.name; - return "%s.%s".printf (external.ns, type_name); - } else { - unannotated_namespaces.add(ns); - } - } - } - - return get_full_gir_name (type_symbol); - } - - private string? literal_expression_to_value_string (Expression literal) { - if (literal is StringLiteral) { - var lit = literal as StringLiteral; - if (lit != null) { - return Markup.escape_text (lit.eval ()); - } - } else if (literal is CharacterLiteral) { - return "%c".printf ((char) ((CharacterLiteral) literal).get_char ()); - } else if (literal is BooleanLiteral) { - return ((BooleanLiteral) literal).value ? "true" : "false"; - } else if (literal is RealLiteral) { - return ((RealLiteral) literal).value; - } else if (literal is IntegerLiteral) { - return ((IntegerLiteral) literal).value; - } else if (literal is UnaryExpression) { - var unary = (UnaryExpression) literal; - if (unary.operator == UnaryOperator.MINUS) { - if (unary.inner is RealLiteral) { - return "-" + ((RealLiteral) unary.inner).value; - } else if (unary.inner is IntegerLiteral) { - return "-" + ((IntegerLiteral) unary.inner).value; - } - } - } - return null; - } - - private bool check_accessibility (Symbol sym) { - if (sym.access == SymbolAccessibility.PUBLIC || - sym.access == SymbolAccessibility.PROTECTED) { - return true; - } - - // internal fields and function pointers in classes/interfaces are public API - if (sym.access == SymbolAccessibility.INTERNAL) { - unowned Symbol? parent = sym.parent_symbol; - if (parent != null - && (parent is Class || parent is Interface) - && ((sym is Field && ((Field) sym).binding == MemberBinding.INSTANCE) - || (sym is Method && ((Method) sym).binding == MemberBinding.INSTANCE && (((Method) sym).is_abstract || ((Method) sym).is_virtual)))) { - return true; - } - } - - return false; - } - - private bool is_visibility (Symbol sym) { - return sym.get_attribute_bool ("GIR", "visible", true); - } - - bool has_namespace (Symbol sym) { - if (!(sym.parent_symbol is Namespace) || sym.parent_symbol.name != null) { - return true; - } - - Report.warning (sym.source_reference, "`%s' must be part of namespace to be included in GIR", sym.name); - return false; - } -} diff --git a/src/codegen/valaglibvalue.vala b/src/codegen/valaglibvalue.vala deleted file mode 100644 index acd8ac9d7..000000000 --- a/src/codegen/valaglibvalue.vala +++ /dev/null @@ -1,183 +0,0 @@ -/* valaglibvalue.vala - * - * Copyright (C) 2010 Jürg Billeter - * Copyright (C) 2011 Luca Bruno - * - * 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.1 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 - * Luca Bruno - */ - -public class Vala.GLibValue : TargetValue { - public CCodeExpression cvalue; - public bool lvalue; - public bool non_null; - public string? ctype; - - public List array_length_cvalues; - public CCodeExpression? array_size_cvalue; - public bool array_null_terminated; - public CCodeExpression? array_length_cexpr; - - public CCodeExpression? delegate_target_cvalue; - public CCodeExpression? delegate_target_destroy_notify_cvalue; - - public GLibValue (DataType? value_type = null, CCodeExpression? cvalue = null, bool lvalue = false) { - base (value_type); - this.cvalue = cvalue; - this.lvalue = lvalue; - } - - public void append_array_length_cvalue (CCodeExpression length_cvalue) { - if (array_length_cvalues == null) { - array_length_cvalues = new ArrayList (); - } - array_length_cvalues.add (length_cvalue); - } - - public GLibValue copy () { - var result = new GLibValue (value_type.copy (), cvalue, lvalue); - result.actual_value_type = actual_value_type; - result.non_null = non_null; - result.ctype = ctype; - - if (array_length_cvalues != null) { - foreach (var cexpr in array_length_cvalues) { - result.append_array_length_cvalue (cexpr); - } - } - result.array_size_cvalue = array_size_cvalue; - result.array_null_terminated = array_null_terminated; - result.array_length_cexpr = array_length_cexpr; - - result.delegate_target_cvalue = delegate_target_cvalue; - result.delegate_target_destroy_notify_cvalue = delegate_target_destroy_notify_cvalue; - - return result; - } -} - -namespace Vala { - public static unowned CCodeExpression? get_cvalue (Expression expr) { - if (expr.target_value == null) { - return null; - } - return ((GLibValue) expr.target_value).cvalue; - } - - public static unowned CCodeExpression? get_cvalue_ (TargetValue value) { - return ((GLibValue) value).cvalue; - } - - public static void set_cvalue (Expression expr, CCodeExpression? cvalue) { - unowned GLibValue glib_value = (GLibValue) expr.target_value; - if (glib_value == null) { - expr.target_value = new GLibValue (expr.value_type); - glib_value = (GLibValue) expr.target_value; - } - glib_value.cvalue = cvalue; - } - - public static unowned CCodeExpression? get_array_size_cvalue (TargetValue value) { - return ((GLibValue) value).array_size_cvalue; - } - - public static void set_array_size_cvalue (TargetValue value, CCodeExpression? cvalue) { - ((GLibValue) value).array_size_cvalue = cvalue; - } - - public static unowned CCodeExpression? get_delegate_target (Expression expr) { - if (expr.target_value == null) { - return null; - } - return ((GLibValue) expr.target_value).delegate_target_cvalue; - } - - public static void set_delegate_target (Expression expr, CCodeExpression? delegate_target) { - unowned GLibValue? glib_value = (GLibValue) expr.target_value; - if (glib_value == null) { - expr.target_value = new GLibValue (expr.value_type); - glib_value = (GLibValue) expr.target_value; - } - glib_value.delegate_target_cvalue = delegate_target; - } - - public static unowned CCodeExpression? get_delegate_target_destroy_notify (Expression expr) { - unowned GLibValue? glib_value = (GLibValue) expr.target_value; - if (glib_value == null) { - return null; - } - return glib_value.delegate_target_destroy_notify_cvalue; - } - - public static void set_delegate_target_destroy_notify (Expression expr, CCodeExpression? destroy_notify) { - unowned GLibValue? glib_value = (GLibValue) expr.target_value; - if (glib_value == null) { - expr.target_value = new GLibValue (expr.value_type); - glib_value = (GLibValue) expr.target_value; - } - glib_value.delegate_target_destroy_notify_cvalue = destroy_notify; - } - - public static void append_array_length (Expression expr, CCodeExpression size) { - unowned GLibValue? glib_value = (GLibValue) expr.target_value; - if (glib_value == null) { - expr.target_value = new GLibValue (expr.value_type); - glib_value = (GLibValue) expr.target_value; - } - glib_value.append_array_length_cvalue (size); - } - - public static void set_array_length (Expression expr, CCodeExpression size) { - unowned GLibValue? glib_value = (GLibValue) expr.target_value; - if (glib_value == null) { - expr.target_value = new GLibValue (expr.value_type); - glib_value = (GLibValue) expr.target_value; - } else { - glib_value.array_length_cvalues = null; - } - glib_value.append_array_length_cvalue (size); - } - - public static unowned List? get_array_lengths (Expression expr) { - unowned GLibValue? glib_value = (GLibValue) expr.target_value; - if (glib_value == null) { - return null; - } - return glib_value.array_length_cvalues; - } - - public static bool get_lvalue (TargetValue value) { - return ((GLibValue) value).lvalue; - } - - public static bool get_non_null (TargetValue value) { - return ((GLibValue) value).non_null; - } - - public static unowned string? get_ctype (TargetValue value) { - return ((GLibValue) value).ctype; - } - - public static bool get_array_null_terminated (TargetValue value) { - return ((GLibValue) value).array_null_terminated; - } - - public static unowned CCodeExpression? get_array_length_cexpr (TargetValue value) { - return ((GLibValue) value).array_length_cexpr; - } -} diff --git a/src/codegen/valagobjectmodule.vala b/src/codegen/valagobjectmodule.vala deleted file mode 100644 index 638aab367..000000000 --- a/src/codegen/valagobjectmodule.vala +++ /dev/null @@ -1,719 +0,0 @@ -/* valagobjectmodule.vala - * - * Copyright (C) 2006-2011 Jürg Billeter - * Copyright (C) 2006-2008 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.1 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 - * Raffaele Sandrini - */ - - -public class Vala.GObjectModule : GTypeModule { - int signal_wrapper_id; - - public override void visit_class (Class cl) { - base.visit_class (cl); - - if (!cl.is_subtype_of (gobject_type)) { - return; - } - - push_line (cl.source_reference); - if (class_has_readable_properties (cl) || cl.has_type_parameters ()) { - add_get_property_function (cl); - } - if (class_has_writable_properties (cl) || cl.has_type_parameters ()) { - add_set_property_function (cl); - } - pop_line (); - } - - public override void generate_class_init (Class cl) { - if (!cl.is_subtype_of (gobject_type)) { - return; - } - - /* set property handlers */ - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); - ccall.add_argument (new CCodeIdentifier ("klass")); - if (class_has_readable_properties (cl) || cl.has_type_parameters ()) { - ccode.add_assignment (new CCodeMemberAccess.pointer (ccall, "get_property"), new CCodeIdentifier ("_vala_%s_get_property".printf (get_ccode_lower_case_name (cl, null)))); - } - if (class_has_writable_properties (cl) || cl.has_type_parameters ()) { - ccode.add_assignment (new CCodeMemberAccess.pointer (ccall, "set_property"), new CCodeIdentifier ("_vala_%s_set_property".printf (get_ccode_lower_case_name (cl, null)))); - } - - /* set constructor */ - if (cl.constructor != null) { - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); - ccast.add_argument (new CCodeIdentifier ("klass")); - ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "constructor"), new CCodeIdentifier ("%sconstructor".printf (get_ccode_lower_case_prefix (cl)))); - } - - /* set finalize function */ - if (cl.get_fields ().size > 0 || cl.destructor != null) { - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); - ccast.add_argument (new CCodeIdentifier ("klass")); - ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%sfinalize".printf (get_ccode_lower_case_prefix (cl)))); - } - - /* create type, dup_func, and destroy_func properties for generic types */ - foreach (TypeParameter type_param in cl.get_type_parameters ()) { - string func_name, enum_value; - CCodeConstant func_name_constant; - CCodeFunctionCall cinst, cspec; - - - func_name = get_ccode_type_id (type_param); - func_name_constant = new CCodeConstant ("\"%s\"".printf (func_name.replace ("_", "-"))); - enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up (); - cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); - cinst.add_argument (ccall); - cinst.add_argument (new CCodeConstant (enum_value)); - cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_gtype")); - cspec.add_argument (func_name_constant); - cspec.add_argument (new CCodeConstant ("\"type\"")); - cspec.add_argument (new CCodeConstant ("\"type\"")); - cspec.add_argument (new CCodeIdentifier ("G_TYPE_NONE")); - cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY")); - cinst.add_argument (cspec); - ccode.add_expression (cinst); - prop_enum.add_value (new CCodeEnumValue (enum_value)); - - - func_name = get_ccode_copy_function (type_param); - func_name_constant = new CCodeConstant ("\"%s\"".printf (func_name.replace ("_", "-"))); - enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up (); - cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); - cinst.add_argument (ccall); - cinst.add_argument (new CCodeConstant (enum_value)); - cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_pointer")); - cspec.add_argument (func_name_constant); - cspec.add_argument (new CCodeConstant ("\"dup func\"")); - cspec.add_argument (new CCodeConstant ("\"dup func\"")); - cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY")); - cinst.add_argument (cspec); - ccode.add_expression (cinst); - prop_enum.add_value (new CCodeEnumValue (enum_value)); - - - func_name = get_ccode_destroy_function (type_param); - func_name_constant = new CCodeConstant ("\"%s\"".printf (func_name.replace ("_", "-"))); - enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up (); - cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); - cinst.add_argument (ccall); - cinst.add_argument (new CCodeConstant (enum_value)); - 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_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY")); - cinst.add_argument (cspec); - ccode.add_expression (cinst); - prop_enum.add_value (new CCodeEnumValue (enum_value)); - } - - /* create properties */ - var props = cl.get_properties (); - foreach (Property prop in props) { - if (!context.analyzer.is_gobject_property (prop)) { - if (!context.analyzer.is_gobject_property_type (prop.property_type)) { - Report.warning (prop.source_reference, "Type `%s' can not be used for a GLib.Object property", prop.property_type.to_qualified_string ()); - } - continue; - } - - if (prop.comment != null) { - ccode.add_statement (new CCodeComment (prop.comment.content)); - } - - var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); - cinst.add_argument (ccall); - cinst.add_argument (new CCodeConstant ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop)))); - cinst.add_argument (get_param_spec (prop)); - - ccode.add_expression (cinst); - } - } - - private bool class_has_readable_properties (Class cl) { - foreach (Property prop in cl.get_properties ()) { - if (prop.get_accessor != null) { - return true; - } - } - return false; - } - - private bool class_has_writable_properties (Class cl) { - foreach (Property prop in cl.get_properties ()) { - if (prop.set_accessor != null) { - return true; - } - } - return false; - } - - private void add_guarded_expression (Symbol sym, CCodeExpression expression) { - // prevent deprecation warnings - if (sym.version.deprecated) { - var guard = new CCodeGGnucSection (GGnucSectionType.IGNORE_DEPRECATIONS); - ccode.add_statement (guard); - guard.append (new CCodeExpressionStatement (expression)); - } else { - ccode.add_expression (expression); - } - } - - private void add_get_property_function (Class cl) { - var get_prop = new CCodeFunction ("_vala_%s_get_property".printf (get_ccode_lower_case_name (cl, null)), "void"); - get_prop.modifiers = CCodeModifiers.STATIC; - get_prop.add_parameter (new CCodeParameter ("object", "GObject *")); - get_prop.add_parameter (new CCodeParameter ("property_id", "guint")); - get_prop.add_parameter (new CCodeParameter ("value", "GValue *")); - get_prop.add_parameter (new CCodeParameter ("pspec", "GParamSpec *")); - - push_function (get_prop); - - CCodeFunctionCall ccall = generate_instance_cast (new CCodeIdentifier ("object"), cl); - ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", ccall)); - - ccode.open_switch (new CCodeIdentifier ("property_id")); - var props = cl.get_properties (); - foreach (Property prop in props) { - if (prop.get_accessor == null || prop.is_abstract) { - continue; - } - if (!context.analyzer.is_gobject_property (prop)) { - // don't register private properties - continue; - } - - Property base_prop = prop; - CCodeExpression cself = new CCodeIdentifier ("self"); - if (prop.base_property != null) { - var base_type = (Class) prop.base_property.parent_symbol; - base_prop = prop.base_property; - cself = get_cvalue_ (transform_value (new GLibValue (new ObjectType (cl), cself, true), new ObjectType (base_type), prop)); - - generate_property_accessor_declaration (prop.base_property.get_accessor, cfile); - } else if (prop.base_interface_property != null) { - var base_type = (Interface) prop.base_interface_property.parent_symbol; - base_prop = prop.base_interface_property; - cself = get_cvalue_ (transform_value (new GLibValue (new ObjectType (cl), cself, true), new ObjectType (base_type), prop)); - - generate_property_accessor_declaration (prop.base_interface_property.get_accessor, cfile); - } - - CCodeExpression cfunc; - if (!get_ccode_no_accessor_method (base_prop) && !get_ccode_concrete_accessor (base_prop)) { - cfunc = new CCodeIdentifier (get_ccode_name (base_prop.get_accessor)); - } else { - // use the static real function as helper - cfunc = new CCodeIdentifier (get_ccode_real_name (prop.get_accessor)); - } - - ccode.add_case (new CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop)))); - if (prop.property_type.is_real_struct_type ()) { - ccode.open_block (); - ccode.add_declaration (get_ccode_name (prop.property_type), new CCodeVariableDeclarator ("boxed")); - - ccall = new CCodeFunctionCall (cfunc); - ccall.add_argument (cself); - if (prop.property_type.nullable) { - ccode.add_assignment (new CCodeIdentifier ("boxed"), ccall); - } else { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("boxed"))); - ccode.add_expression (ccall); - } - - var csetcall = new CCodeFunctionCall (); - csetcall.call = get_value_setter_function (prop.property_type); - csetcall.add_argument (new CCodeIdentifier ("value")); - if (prop.property_type.nullable) { - csetcall.add_argument (new CCodeIdentifier ("boxed")); - } else { - csetcall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("boxed"))); - } - add_guarded_expression (prop, csetcall); - - if (requires_destroy (prop.get_accessor.value_type)) { - ccode.add_expression (destroy_value (new GLibValue (prop.get_accessor.value_type, new CCodeIdentifier ("boxed"), true))); - } - ccode.close (); - } else { - ccall = new CCodeFunctionCall (cfunc); - ccall.add_argument (cself); - var array_type = prop.property_type as ArrayType; - if (array_type != null && get_ccode_array_length (prop) && array_type.element_type.type_symbol == string_type.type_symbol) { - // G_TYPE_STRV - ccode.open_block (); - ccode.add_declaration ("int", new CCodeVariableDeclarator ("length")); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("length"))); - } - var csetcall = new CCodeFunctionCall (); - if (prop.get_accessor.value_type.value_owned) { - csetcall.call = get_value_taker_function (prop.property_type); - } else { - csetcall.call = get_value_setter_function (prop.property_type); - } - csetcall.add_argument (new CCodeIdentifier ("value")); - csetcall.add_argument (ccall); - add_guarded_expression (prop, csetcall); - if (array_type != null && get_ccode_array_length (prop) && array_type.element_type.type_symbol == string_type.type_symbol) { - ccode.close (); - } - } - ccode.add_break (); - } - - /* type, dup func, and destroy func properties for generic types */ - foreach (TypeParameter type_param in cl.get_type_parameters ()) { - string func_name, enum_value; - CCodeMemberAccess cfield; - CCodeFunctionCall csetcall; - - func_name = get_ccode_type_id (type_param); - enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up (); - ccode.add_case (new CCodeIdentifier (enum_value)); - cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name); - csetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_gtype")); - csetcall.add_argument (new CCodeIdentifier ("value")); - csetcall.add_argument (cfield); - ccode.add_expression (csetcall); - ccode.add_break (); - - func_name = get_ccode_copy_function (type_param); - enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up (); - ccode.add_case (new CCodeIdentifier (enum_value)); - cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name); - csetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_pointer")); - csetcall.add_argument (new CCodeIdentifier ("value")); - csetcall.add_argument (cfield); - ccode.add_expression (csetcall); - ccode.add_break (); - - func_name = get_ccode_destroy_function (type_param); - enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up (); - ccode.add_case (new CCodeIdentifier (enum_value)); - cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name); - csetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_pointer")); - csetcall.add_argument (new CCodeIdentifier ("value")); - csetcall.add_argument (cfield); - ccode.add_expression (csetcall); - ccode.add_break (); - } - ccode.add_default (); - emit_invalid_property_id_warn (); - ccode.add_break (); - - ccode.close (); - - pop_function (); - - cfile.add_function_declaration (get_prop); - cfile.add_function (get_prop); - } - - private void add_set_property_function (Class cl) { - var set_prop = new CCodeFunction ("_vala_%s_set_property".printf (get_ccode_lower_case_name (cl, null)), "void"); - set_prop.modifiers = CCodeModifiers.STATIC; - set_prop.add_parameter (new CCodeParameter ("object", "GObject *")); - set_prop.add_parameter (new CCodeParameter ("property_id", "guint")); - set_prop.add_parameter (new CCodeParameter ("value", "const GValue *")); - set_prop.add_parameter (new CCodeParameter ("pspec", "GParamSpec *")); - - push_function (set_prop); - - CCodeFunctionCall ccall = generate_instance_cast (new CCodeIdentifier ("object"), cl); - ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", ccall)); - - ccode.open_switch (new CCodeIdentifier ("property_id")); - var props = cl.get_properties (); - foreach (Property prop in props) { - if (prop.set_accessor == null || prop.is_abstract) { - continue; - } - if (!context.analyzer.is_gobject_property (prop)) { - continue; - } - - Property base_prop = prop; - CCodeExpression cself = new CCodeIdentifier ("self"); - if (prop.base_property != null) { - var base_type = (Class) prop.base_property.parent_symbol; - base_prop = prop.base_property; - cself = get_cvalue_ (transform_value (new GLibValue (new ObjectType (cl), cself, true), new ObjectType (base_type), prop)); - - generate_property_accessor_declaration (prop.base_property.set_accessor, cfile); - } else if (prop.base_interface_property != null) { - var base_type = (Interface) prop.base_interface_property.parent_symbol; - base_prop = prop.base_interface_property; - cself = get_cvalue_ (transform_value (new GLibValue (new ObjectType (cl), cself, true), new ObjectType (base_type), prop)); - - generate_property_accessor_declaration (prop.base_interface_property.set_accessor, cfile); - } - - CCodeExpression cfunc; - if (!get_ccode_no_accessor_method (base_prop) && !get_ccode_concrete_accessor (base_prop)) { - cfunc = new CCodeIdentifier (get_ccode_name (base_prop.set_accessor)); - } else { - // use the static real function as helper - cfunc = new CCodeIdentifier (get_ccode_real_name (prop.set_accessor)); - } - - ccode.add_case (new CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop)))); - ccall = new CCodeFunctionCall (cfunc); - ccall.add_argument (cself); - if (prop.property_type is ArrayType && ((ArrayType)prop.property_type).element_type.type_symbol == string_type.type_symbol) { - ccode.open_block (); - ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("boxed")); - - var cgetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_boxed")); - cgetcall.add_argument (new CCodeIdentifier ("value")); - ccode.add_assignment (new CCodeIdentifier ("boxed"), cgetcall); - ccall.add_argument (new CCodeIdentifier ("boxed")); - - if (get_ccode_array_length (prop)) { - var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("boxed"), new CCodeConstant ("NULL")); - var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length")); - cstrvlen.add_argument (new CCodeIdentifier ("boxed")); - var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cstrvlen); - - ccall.add_argument (ccond); - } - add_guarded_expression (prop, ccall); - ccode.close (); - } else { - var cgetcall = new CCodeFunctionCall (); - if (prop.property_type.type_symbol != null) { - cgetcall.call = new CCodeIdentifier (get_ccode_get_value_function (prop.property_type.type_symbol)); - } else { - cgetcall.call = new CCodeIdentifier ("g_value_get_pointer"); - } - cgetcall.add_argument (new CCodeIdentifier ("value")); - ccall.add_argument (cgetcall); - add_guarded_expression (prop, ccall); - } - ccode.add_break (); - } - - /* type, dup func, and destroy func properties for generic types */ - foreach (TypeParameter type_param in cl.get_type_parameters ()) { - string func_name, enum_value; - CCodeMemberAccess cfield; - CCodeFunctionCall cgetcall; - - func_name = get_ccode_type_id (type_param); - enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up (); - ccode.add_case (new CCodeIdentifier (enum_value)); - cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name); - cgetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_gtype")); - cgetcall.add_argument (new CCodeIdentifier ("value")); - ccode.add_assignment (cfield, cgetcall); - ccode.add_break (); - - func_name = get_ccode_copy_function (type_param); - enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up (); - ccode.add_case (new CCodeIdentifier (enum_value)); - cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name); - cgetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer")); - cgetcall.add_argument (new CCodeIdentifier ("value")); - ccode.add_assignment (cfield, cgetcall); - ccode.add_break (); - - func_name = get_ccode_destroy_function (type_param); - enum_value = "%s_%s".printf (get_ccode_lower_case_name (cl, null), func_name).ascii_up (); - ccode.add_case (new CCodeIdentifier (enum_value)); - cfield = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name); - cgetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer")); - cgetcall.add_argument (new CCodeIdentifier ("value")); - ccode.add_assignment (cfield, cgetcall); - ccode.add_break (); - } - ccode.add_default (); - emit_invalid_property_id_warn (); - ccode.add_break (); - - ccode.close (); - - pop_function (); - - cfile.add_function_declaration (set_prop); - cfile.add_function (set_prop); - } - - private void emit_invalid_property_id_warn () { - // warn on invalid property id - var cwarn = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_WARN_INVALID_PROPERTY_ID")); - cwarn.add_argument (new CCodeIdentifier ("object")); - cwarn.add_argument (new CCodeIdentifier ("property_id")); - cwarn.add_argument (new CCodeIdentifier ("pspec")); - ccode.add_expression (cwarn); - } - - public override void visit_constructor (Constructor c) { - push_line (c.source_reference); - - var cl = (Class) c.parent_symbol; - - if (c.binding == MemberBinding.INSTANCE) { - if (!cl.is_subtype_of (gobject_type)) { - Report.error (c.source_reference, "construct blocks require GLib.Object"); - c.error = true; - return; - } - - push_context (new EmitContext (c)); - - var function = new CCodeFunction ("%sconstructor".printf (get_ccode_lower_case_prefix (cl)), "GObject *"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("type", "GType")); - function.add_parameter (new CCodeParameter ("n_construct_properties", "guint")); - function.add_parameter (new CCodeParameter ("construct_properties", "GObjectConstructParam *")); - - cfile.add_function_declaration (function); - - push_function (function); - - ccode.add_declaration ("GObject *", new CCodeVariableDeclarator ("obj")); - ccode.add_declaration ("GObjectClass *", new CCodeVariableDeclarator ("parent_class")); - - if (cl.is_singleton) { - var singleton_ref_name = "%s_singleton__ref".printf (get_ccode_name (cl)); - var singleton_lock_name = "%s_singleton__lock".printf (get_ccode_name (cl)); - var singleton_once_name = "%s_singleton__once".printf (get_ccode_name (cl)); - - var singleton_ref = new CCodeDeclaration("GObject *"); - singleton_ref.add_declarator (new CCodeVariableDeclarator (singleton_ref_name, new CCodeConstant ("NULL"))); - singleton_ref.modifiers = CCodeModifiers.STATIC; - ccode.add_statement (singleton_ref); - - var mutex_lock = new CCodeDeclaration("GMutex"); - mutex_lock.add_declarator (new CCodeVariableDeclarator (singleton_lock_name)); - mutex_lock.modifiers = CCodeModifiers.STATIC; - ccode.add_statement (mutex_lock); - - var once_lock = new CCodeDeclaration("gsize"); - once_lock.add_declarator (new CCodeVariableDeclarator (singleton_once_name, new CCodeConstant ("0"))); - if (context.require_glib_version (2, 68)) { - once_lock.modifiers = CCodeModifiers.STATIC; - } else { - once_lock.modifiers = CCodeModifiers.STATIC | CCodeModifiers.VOLATILE; - } - ccode.add_statement (once_lock); - - var once_init = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_enter")); - once_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_once_name))); - - var once_block = new CCodeBlock(); - - var singleton_mutex_init = new CCodeFunctionCall (new CCodeIdentifier ("g_mutex_init")); - singleton_mutex_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_lock_name))); - once_block.add_statement (new CCodeExpressionStatement (singleton_mutex_init)); - - var once_leave = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_leave")); - once_leave.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_once_name))); - once_leave.add_argument (new CCodeConstant ("42")); - once_block.add_statement (new CCodeExpressionStatement (once_leave)); - - var if_once = new CCodeIfStatement (once_init, once_block); - ccode.add_statement (if_once); - - var singleton_mutex_lock = new CCodeFunctionCall (new CCodeIdentifier ("g_mutex_lock")); - singleton_mutex_lock.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_lock_name))); - ccode.add_statement (new CCodeExpressionStatement (singleton_mutex_lock)); - - var check_existance = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (singleton_ref_name), new CCodeConstant ("NULL")); - var return_singleton = new CCodeBlock(); - - var ref_object = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref")); - ref_object.add_argument (new CCodeIdentifier (singleton_ref_name)); - return_singleton.add_statement (new CCodeExpressionStatement (ref_object)); - - var singleton_mutex_unlock = new CCodeFunctionCall (new CCodeIdentifier ("g_mutex_unlock")); - singleton_mutex_unlock.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_lock_name))); - return_singleton.add_statement (new CCodeExpressionStatement (singleton_mutex_unlock)); - return_singleton.add_statement (new CCodeReturnStatement (new CCodeIdentifier (singleton_ref_name))); - - var if_singleton_alive = new CCodeIfStatement (check_existance, return_singleton); - ccode.add_statement (if_singleton_alive); - } - - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); - ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null)))); - ccode.add_assignment (new CCodeIdentifier ("parent_class"), ccast); - - var 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")); - ccode.add_assignment (new CCodeIdentifier ("obj"), ccall); - - - ccall = generate_instance_cast (new CCodeIdentifier ("obj"), cl); - - ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self")); - ccode.add_assignment (new CCodeIdentifier ("self"), ccall); - - c.body.emit (this); - - if (current_method_inner_error) { - /* always separate error parameter and inner_error local variable - * as error may be set to NULL but we're always interested in inner errors - */ - ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL"))); - } - - if (cl.is_singleton) { - var singleton_ref_name = "%s_singleton__ref".printf (get_ccode_name (cl)); - var singleton_lock_name = "%s_singleton__lock".printf (get_ccode_name (cl)); - - ccode.add_assignment (new CCodeIdentifier (singleton_ref_name), new CCodeIdentifier ("obj")); - - var set_weak_ref_to_volatile = new CCodeFunctionCall (new CCodeIdentifier ("g_object_add_weak_pointer")); - set_weak_ref_to_volatile.add_argument (new CCodeIdentifier (singleton_ref_name)); - set_weak_ref_to_volatile.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_ref_name)), "gpointer")); - ccode.add_statement (new CCodeExpressionStatement (set_weak_ref_to_volatile)); - - var final_singleton_mutex_unlock = new CCodeFunctionCall (new CCodeIdentifier ("g_mutex_unlock")); - final_singleton_mutex_unlock.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (singleton_lock_name))); - ccode.add_statement (new CCodeExpressionStatement (final_singleton_mutex_unlock)); - } - - ccode.add_return (new CCodeIdentifier ("obj")); - - pop_function (); - cfile.add_function (function); - - pop_context (); - } else if (c.binding == MemberBinding.CLASS) { - // class constructor - - if (cl.is_compact) { - Report.error (c.source_reference, "class constructors are not supported in compact classes"); - c.error = true; - return; - } - - push_context (base_init_context); - - c.body.emit (this); - - if (current_method_inner_error) { - /* always separate error parameter and inner_error local variable - * as error may be set to NULL but we're always interested in inner errors - */ - ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL"))); - } - - pop_context (); - } else if (c.binding == MemberBinding.STATIC) { - // static class constructor - // add to class_init - - if (cl.is_compact) { - Report.error (c.source_reference, "static constructors are not supported in compact classes"); - c.error = true; - return; - } - - push_context (class_init_context); - - c.body.emit (this); - - if (current_method_inner_error) { - /* always separate error parameter and inner_error local variable - * as error may be set to NULL but we're always interested in inner errors - */ - ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL"))); - } - - pop_context (); - } else { - Report.error (c.source_reference, "internal error: constructors must have instance, class, or static binding"); - } - - pop_line (); - } - - public override string get_dynamic_signal_cname (DynamicSignal node) { - return "dynamic_%s%d_".printf (node.name, signal_wrapper_id++); - } - - public override void visit_property (Property prop) { - base.visit_property (prop); - - if (context.analyzer.is_gobject_property (prop) && prop.parent_symbol is Class) { - prop_enum.add_value (new CCodeEnumValue ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop)))); - } - } - - public override void visit_method_call (MethodCall expr) { - if (expr.call is MemberAccess) { - push_line (expr.source_reference); - - var ma = expr.call as MemberAccess; - if (ma.inner != null && ma.inner.symbol_reference == gobject_type && - (ma.member_name == "new" || ma.member_name == "newv" - || ma.member_name == "new_valist" || ma.member_name == "new_with_properties")) { - // Object.new (...) creation - // runtime check to ref_sink the instance if it's a floating type - base.visit_method_call (expr); - - var initiallyunowned_ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_IS_INITIALLY_UNOWNED")); - initiallyunowned_ccall.add_argument (get_cvalue (expr)); - var sink_ref_ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref_sink")); - sink_ref_ccall.add_argument (get_cvalue (expr)); - var cexpr = new CCodeConditionalExpression (initiallyunowned_ccall, sink_ref_ccall, get_cvalue (expr)); - - expr.target_value = store_temp_value (new GLibValue (expr.value_type, cexpr), expr); - return; - } else if (ma.symbol_reference == gobject_type) { - // Object (...) chain up - // check it's only used with valid properties - foreach (var arg in expr.get_argument_list ()) { - var named_argument = arg as NamedArgument; - if (named_argument == null) { - Report.error (arg.source_reference, "Named argument expected"); - break; - } - var prop = SemanticAnalyzer.symbol_lookup_inherited (current_class, named_argument.name) as Property; - if (prop == null) { - Report.error (arg.source_reference, "Property `%s' not found in `%s'", named_argument.name, current_class.get_full_name ()); - break; - } - if (!context.analyzer.is_gobject_property (prop)) { - Report.error (arg.source_reference, "Property `%s' not supported in Object (property: value) constructor chain up", named_argument.name); - break; - } - if (!arg.value_type.compatible (prop.property_type)) { - Report.error (arg.source_reference, "Cannot convert from `%s' to `%s'", arg.value_type.to_string (), prop.property_type.to_string ()); - break; - } - } - } - - pop_line (); - } - - base.visit_method_call (expr); - } -} - diff --git a/src/codegen/valagsignalmodule.vala b/src/codegen/valagsignalmodule.vala deleted file mode 100644 index 4186859cf..000000000 --- a/src/codegen/valagsignalmodule.vala +++ /dev/null @@ -1,785 +0,0 @@ -/* valagsignalmodule.vala - * - * Copyright (C) 2006-2010 Jürg Billeter - * Copyright (C) 2006-2008 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.1 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 - * Raffaele Sandrini - */ - - -public class Vala.GSignalModule : GObjectModule { - string get_marshaller_function (Signal sig, List params, DataType return_type, string? prefix = null) { - var signature = get_marshaller_signature (sig, params, return_type); - string ret; - - if (prefix == null) { - if (predefined_marshal_set.contains (signature)) { - prefix = "g_cclosure_marshal"; - } else { - prefix = "g_cclosure_user_marshal"; - } - } - - ret = "%s_%s_".printf (prefix, get_ccode_marshaller_type_name (return_type)); - - foreach (Parameter p in params) { - ret = "%s_%s".printf (ret, get_ccode_marshaller_type_name (p).replace (",", "_")); - } - if (sig.return_type.is_real_non_null_struct_type ()) { - ret = ret + "_POINTER"; - } else if (params.size == 0) { - ret = ret + "_VOID"; - } - - return ret; - } - - private string? get_value_type_name_from_type_reference (DataType t) { - if (t is PointerType || t is GenericType) { - return "gpointer"; - } else if (t is VoidType) { - return "void"; - } else if (get_ccode_type_id (t) == get_ccode_type_id (string_type)) { - return "const char*"; - } else if (t.type_symbol is Class || t.type_symbol is Interface) { - return "gpointer"; - } else if (t is ValueType && t.nullable) { - return "gpointer"; - } else if (t.type_symbol is Struct) { - unowned Struct st = (Struct) t.type_symbol; - if (st.is_simple_type ()) { - return get_ccode_name (t.type_symbol); - } else { - return "gpointer"; - } - } else if (t.type_symbol is Enum) { - unowned Enum en = (Enum) t.type_symbol; - if (en.is_flags) { - return "guint"; - } else { - return "gint"; - } - } else if (t is ArrayType) { - return "gpointer"; - } else if (t is DelegateType) { - return "gpointer"; - } else if (t is ErrorType) { - return "gpointer"; - } - - return null; - } - - private string? get_value_type_name_from_parameter (Parameter p) { - if (p.direction != ParameterDirection.IN) { - return "gpointer"; - } else { - return get_value_type_name_from_type_reference (p.variable_type); - } - } - - private string get_marshaller_signature (Signal sig, List params, DataType return_type) { - string signature; - - signature = "%s:".printf (get_ccode_marshaller_type_name (return_type)); - bool first = true; - foreach (Parameter p in params) { - if (first) { - signature = signature + get_ccode_marshaller_type_name (p); - first = false; - } else { - signature = "%s,%s".printf (signature, get_ccode_marshaller_type_name (p)); - } - } - if (sig.return_type.is_real_non_null_struct_type ()) { - signature = signature + (first ? "POINTER" : ",POINTER"); - } else if (params.size == 0) { - signature = signature + "VOID"; - } - - return signature; - } - - private CCodeExpression get_signal_name_cexpression (Signal sig, Expression? detail_expr, CodeNode node) { - if (detail_expr == null) { - return get_signal_canonical_constant (sig); - } - - if (detail_expr is StringLiteral) { - return get_signal_canonical_constant (sig, ((StringLiteral) detail_expr).eval ()); - } - - var detail_value = create_temp_value (detail_expr.value_type, false, node, true); - temp_ref_values.insert (0, detail_value); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat")); - ccall.add_argument (get_signal_canonical_constant (sig, "")); - ccall.add_argument (get_cvalue (detail_expr)); - ccall.add_argument (new CCodeConstant ("NULL")); - - ccode.add_assignment (get_cvalue_ (detail_value), ccall); - return get_cvalue_ (detail_value); - } - - private CCodeExpression get_signal_id_cexpression (Signal sig) { - var cl = (TypeSymbol) sig.parent_symbol; - var signal_array = new CCodeIdentifier ("%s_signals".printf (get_ccode_lower_case_name (cl))); - var signal_enum_value = new CCodeIdentifier ("%s_%s_SIGNAL".printf (get_ccode_upper_case_name (cl), get_ccode_upper_case_name (sig))); - - return new CCodeElementAccess (signal_array, signal_enum_value); - } - - private CCodeExpression get_detail_cexpression (Expression detail_expr, CodeNode node) { - var detail_cexpr = get_cvalue (detail_expr); - CCodeFunctionCall detail_ccall; - if (is_constant_ccode_expression (detail_cexpr)) { - detail_ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string")); - } else { - detail_ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string")); - } - detail_ccall.add_argument (detail_cexpr); - - return detail_ccall; - } - - public override void visit_signal (Signal sig) { - if (signal_enum != null && sig.parent_symbol is TypeSymbol) { - signal_enum.add_value (new CCodeEnumValue ("%s_%s_SIGNAL".printf (get_ccode_upper_case_name ((TypeSymbol) sig.parent_symbol), get_ccode_upper_case_name (sig)))); - } - - sig.accept_children (this); - - // declare parameter type - unowned List params = sig.get_parameters (); - foreach (Parameter p in params) { - generate_parameter (p, cfile, new HashMap (), null); - } - - if (sig.return_type.is_real_non_null_struct_type ()) { - generate_marshaller (sig, params, new VoidType ()); - } else { - generate_marshaller (sig, params, sig.return_type); - } - } - - void generate_marshaller (Signal sig, List params, DataType return_type) { - string signature; - int n_params, i; - - /* check whether a signal with the same signature already exists for this source file (or predefined) */ - signature = get_marshaller_signature (sig, params, return_type); - if (predefined_marshal_set.contains (signature) || user_marshal_set.contains (signature)) { - return; - } - - var signal_marshaller = new CCodeFunction (get_marshaller_function (sig, params, return_type, null), "void"); - signal_marshaller.modifiers = CCodeModifiers.STATIC; - - signal_marshaller.add_parameter (new CCodeParameter ("closure", "GClosure *")); - signal_marshaller.add_parameter (new CCodeParameter ("return_value", "GValue *")); - signal_marshaller.add_parameter (new CCodeParameter ("n_param_values", "guint")); - signal_marshaller.add_parameter (new CCodeParameter ("param_values", "const GValue *")); - signal_marshaller.add_parameter (new CCodeParameter ("invocation_hint", "gpointer")); - signal_marshaller.add_parameter (new CCodeParameter ("marshal_data", "gpointer")); - - push_function (signal_marshaller); - - var callback_decl = new CCodeFunctionDeclarator (get_marshaller_function (sig, params, return_type, "GMarshalFunc")); - callback_decl.add_parameter (new CCodeParameter ("data1", "gpointer")); - n_params = 1; - foreach (Parameter p in params) { - callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params), get_value_type_name_from_parameter (p))); - n_params++; - if (p.variable_type is ArrayType) { - var array_type = (ArrayType) p.variable_type; - var length_ctype = get_ccode_array_length_type (p); - for (var j = 0; j < array_type.rank; j++) { - callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params), length_ctype)); - n_params++; - } - } else if (p.variable_type is DelegateType) { - unowned DelegateType delegate_type = (DelegateType) p.variable_type; - if (delegate_type.delegate_symbol.has_target) { - callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params), get_ccode_name (delegate_target_type))); - n_params++; - if (delegate_type.is_disposable ()) { - callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params), get_ccode_name (delegate_target_destroy_type))); - n_params++; - } - } - } - } - if (sig.return_type.is_real_non_null_struct_type ()) { - callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params), "gpointer")); - n_params++; - } - - callback_decl.add_parameter (new CCodeParameter ("data2", "gpointer")); - ccode.add_statement (new CCodeTypeDefinition (get_value_type_name_from_type_reference (return_type), callback_decl)); - - ccode.add_declaration (get_marshaller_function (sig, params, return_type, "GMarshalFunc"), new CCodeVariableDeclarator ("callback"), CCodeModifiers.REGISTER); - - ccode.add_declaration ("GCClosure *", new CCodeVariableDeclarator ("cc", new CCodeCastExpression (new CCodeIdentifier ("closure"), "GCClosure *")), CCodeModifiers.REGISTER); - - ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("data1"), CCodeModifiers.REGISTER); - ccode.add_declaration ("gpointer", new CCodeVariableDeclarator ("data2"), CCodeModifiers.REGISTER); - - CCodeFunctionCall fc; - - if (return_type.type_symbol != null || return_type is ArrayType) { - ccode.add_declaration (get_value_type_name_from_type_reference (return_type), new CCodeVariableDeclarator ("v_return")); - - fc = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); - fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("return_value"), new CCodeConstant ("NULL"))); - ccode.add_expression (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()))); - ccode.add_expression (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")); - ccode.open_if (cond); - ccode.add_assignment (new CCodeIdentifier ("data1"), data); - ccode.add_assignment (new CCodeIdentifier ("data2"), param); - ccode.add_else (); - ccode.add_assignment (new CCodeIdentifier ("data1"), param); - ccode.add_assignment (new CCodeIdentifier ("data2"), data); - ccode.close (); - - var c_assign_rhs = new CCodeCastExpression (new CCodeConditionalExpression (new CCodeIdentifier ("marshal_data"), new CCodeIdentifier ("marshal_data"), new CCodeMemberAccess (new CCodeIdentifier ("cc"), "callback", true)), get_marshaller_function (sig, params, return_type, "GMarshalFunc")); - ccode.add_assignment (new CCodeIdentifier ("callback"), c_assign_rhs); - - fc = new CCodeFunctionCall (new CCodeIdentifier ("callback")); - fc.add_argument (new CCodeIdentifier ("data1")); - i = 1; - foreach (Parameter p in params) { - CCodeFunctionCall inner_fc; - if (p.direction != ParameterDirection.IN) { - inner_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer")); - } else if (p.variable_type is ValueType && p.variable_type.nullable) { - inner_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer")); - } else { - inner_fc = new CCodeFunctionCall (get_value_getter_function (p.variable_type)); - } - inner_fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("param_values"), new CCodeIdentifier (i.to_string ()))); - fc.add_argument (inner_fc); - i++; - if (p.variable_type is ArrayType) { - var array_type = (ArrayType) p.variable_type; - var length_value_function = get_ccode_get_value_function (array_type.length_type.type_symbol); - assert (length_value_function != null && length_value_function != ""); - for (var j = 0; j < array_type.rank; j++) { - inner_fc = new CCodeFunctionCall (new CCodeIdentifier (length_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++; - } - } else if (p.variable_type is DelegateType) { - unowned DelegateType delegate_type = (DelegateType) p.variable_type; - if (delegate_type.delegate_symbol.has_target) { - inner_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer")); - inner_fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("param_values"), new CCodeIdentifier (i.to_string ()))); - fc.add_argument (inner_fc); - i++; - if (delegate_type.is_disposable ()) { - inner_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer")); - inner_fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("param_values"), new CCodeIdentifier (i.to_string ()))); - fc.add_argument (inner_fc); - i++; - } - } - } - } - if (sig.return_type.is_real_non_null_struct_type ()) { - var inner_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer")); - 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 (return_type.type_symbol != null || return_type is ArrayType) { - ccode.add_assignment (new CCodeIdentifier ("v_return"), fc); - - CCodeFunctionCall set_fc; - if (return_type is ValueType) { - if (return_type.nullable) { - set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_pointer")); - } else { - set_fc = new CCodeFunctionCall (get_value_setter_function (return_type)); - } - } else { - set_fc = new CCodeFunctionCall (get_value_taker_function (return_type)); - } - set_fc.add_argument (new CCodeIdentifier ("return_value")); - set_fc.add_argument (new CCodeIdentifier ("v_return")); - - ccode.add_expression (set_fc); - } else { - ccode.add_expression (fc); - } - - pop_function (); - - cfile.add_function_declaration (signal_marshaller); - cfile.add_function (signal_marshaller); - user_marshal_set.add (signature); - } - - public override CCodeExpression get_signal_creation (Signal sig, ObjectTypeSymbol type) { - CCodeFunctionCall csignew; - if (sig.default_handler == null || sig.is_virtual) { - csignew = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_new")); - } else { - csignew = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_new_class_handler")); - } - csignew.add_argument (new CCodeConstant ("\"%s\"".printf (get_ccode_name (sig)))); - csignew.add_argument (new CCodeIdentifier (get_ccode_type_id (type))); - string[] flags = new string[0]; - var run_type = sig.get_attribute_string ("Signal", "run"); - if (run_type == "first") { - flags += "G_SIGNAL_RUN_FIRST"; - } else if (run_type == "cleanup") { - flags += "G_SIGNAL_RUN_CLEANUP"; - } else { - flags += "G_SIGNAL_RUN_LAST"; - } - if (sig.get_attribute_bool ("Signal", "detailed")) { - flags += "G_SIGNAL_DETAILED"; - } - - if (sig.get_attribute_bool ("Signal", "no_recurse")) { - flags += "G_SIGNAL_NO_RECURSE"; - } - - if (sig.get_attribute_bool ("Signal", "action")) { - flags += "G_SIGNAL_ACTION"; - } - - if (sig.get_attribute_bool ("Signal", "no_hooks")) { - flags += "G_SIGNAL_NO_HOOKS"; - } - - if (sig.version.deprecated) { - flags += "G_SIGNAL_DEPRECATED"; - } - - csignew.add_argument (new CCodeConstant (string.joinv (" | ", flags))); - - if (sig.default_handler == null) { - csignew.add_argument (new CCodeConstant ("0")); - } else if (sig.is_virtual) { - var struct_offset = new CCodeFunctionCall (new CCodeIdentifier ("G_STRUCT_OFFSET")); - struct_offset.add_argument (new CCodeIdentifier (get_ccode_type_name (type))); - struct_offset.add_argument (new CCodeIdentifier (get_ccode_vfunc_name (sig.default_handler))); - csignew.add_argument (struct_offset); - } else { - csignew.add_argument (new CCodeCastExpression (new CCodeIdentifier (get_ccode_real_name (sig.default_handler)), "GCallback")); - } - csignew.add_argument (new CCodeConstant ("NULL")); - csignew.add_argument (new CCodeConstant ("NULL")); - - unowned List params = sig.get_parameters (); - string marshaller; - if (sig.return_type.is_real_non_null_struct_type ()) { - marshaller = get_marshaller_function (sig, params, new VoidType ()); - } else { - marshaller = get_marshaller_function (sig, params, sig.return_type); - } - - var marshal_arg = new CCodeIdentifier (marshaller); - csignew.add_argument (marshal_arg); - - if (sig.return_type is PointerType || sig.return_type is GenericType) { - csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); - } else if (sig.return_type is ErrorType) { - csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); - } else if (sig.return_type is ValueType && sig.return_type.nullable) { - csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); - } else if (sig.return_type.type_symbol == null) { - csignew.add_argument (new CCodeConstant ("G_TYPE_NONE")); - } else if (sig.return_type.is_real_non_null_struct_type ()) { - csignew.add_argument (new CCodeConstant ("G_TYPE_NONE")); - } else { - csignew.add_argument (new CCodeConstant (get_ccode_type_id (sig.return_type.type_symbol))); - } - - int params_len = 0; - foreach (Parameter param in params) { - params_len++; - if (param.variable_type is ArrayType) { - params_len += ((ArrayType) param.variable_type).rank; - } else if (param.variable_type is DelegateType) { - unowned DelegateType delegate_type = (DelegateType) param.variable_type; - if (delegate_type.delegate_symbol.has_target) { - params_len++; - if (delegate_type.is_disposable ()) { - params_len++; - } - } - } - } - if (sig.return_type.is_real_non_null_struct_type ()) { - params_len++; - } - - csignew.add_argument (new CCodeConstant ("%d".printf (params_len))); - foreach (Parameter param in params) { - if (param.variable_type is ArrayType) { - var array_type = (ArrayType) param.variable_type; - if (array_type.element_type.type_symbol == string_type.type_symbol) { - csignew.add_argument (new CCodeConstant ("G_TYPE_STRV")); - } else { - csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); - } - assert (get_ccode_has_type_id (array_type.length_type.type_symbol)); - var length_type_id = get_ccode_type_id (array_type.length_type.type_symbol); - for (var i = 0; i < array_type.rank; i++) { - csignew.add_argument (new CCodeConstant (length_type_id)); - } - } else if (param.variable_type is DelegateType) { - unowned DelegateType delegate_type = (DelegateType) param.variable_type; - csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); - if (delegate_type.delegate_symbol.has_target) { - csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); - if (delegate_type.is_disposable ()) { - csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); - } - } - } else if (param.variable_type is PointerType || param.variable_type is GenericType || param.direction != ParameterDirection.IN) { - csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); - } else if (param.variable_type is ErrorType) { - csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); - } else if (param.variable_type is ValueType && param.variable_type.nullable) { - csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); - } else { - csignew.add_argument (new CCodeConstant (get_ccode_type_id (param.variable_type.type_symbol))); - } - } - if (sig.return_type.is_real_non_null_struct_type ()) { - csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER")); - } - - marshal_arg.name = marshaller; - - return new CCodeAssignment (get_signal_id_cexpression (sig), csignew); - } - - public override void visit_element_access (ElementAccess expr) { - if (!(expr.container is MemberAccess && expr.container.symbol_reference is Signal)) { - base.visit_element_access (expr); - return; - } - - if (expr.parent_node is MethodCall) { - // detailed signal emission - unowned Signal sig = (Signal) expr.symbol_reference; - unowned MemberAccess ma = (MemberAccess) expr.container; - var detail_expr = expr.get_indices ().get (0); - - set_cvalue (expr, emit_signal (sig, ma, detail_expr)); - } else { - // signal connect or disconnect - } - } - - bool in_gobject_instance (Method m) { - bool result = false; - if (m.binding == MemberBinding.INSTANCE) { - result = m.this_parameter.variable_type.type_symbol.is_subtype_of (gobject_type); - } - return result; - } - - public override void visit_member_access (MemberAccess expr) { - if (!(expr.symbol_reference is Signal)) { - base.visit_member_access (expr); - return; - } - - unowned Signal sig = (Signal) expr.symbol_reference; - - set_cvalue (expr, emit_signal (sig, expr)); - } - - CCodeExpression emit_signal (Signal sig, MemberAccess expr, Expression? detail_expr = null) { - CCodeExpression pub_inst = null; - - if (expr.inner != null) { - pub_inst = get_cvalue (expr.inner); - } - - if (expr.inner is BaseAccess && sig.is_virtual) { - var m = sig.default_handler; - var base_class = (Class) m.parent_symbol; - var vcast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (base_class))); - vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (current_class)))); - return new CCodeMemberAccess.pointer (vcast, m.name); - } - - if (!sig.external_package && expr.source_reference.file == sig.source_reference.file && !(sig is DynamicSignal)) { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit")); - ccall.add_argument (pub_inst); - ccall.add_argument (get_signal_id_cexpression (sig)); - if (detail_expr == null) { - ccall.add_argument (new CCodeConstant ("0")); - } else { - ccall.add_argument (get_detail_cexpression (detail_expr, expr)); - } - return ccall; - } else if (get_ccode_has_emitter (sig)) { - string emitter_func; - if (sig.emitter != null) { - if (!sig.external_package && expr.source_reference.file != sig.source_reference.file) { - generate_method_declaration (sig.emitter, cfile); - } - emitter_func = get_ccode_lower_case_name (sig.emitter); - } else { - unowned TypeSymbol sym = (TypeSymbol) sig.parent_symbol; - emitter_func = "%s_%s".printf (get_ccode_lower_case_name (sym), get_ccode_lower_case_name (sig)); - } - var ccall = new CCodeFunctionCall (new CCodeIdentifier (emitter_func)); - ccall.add_argument (pub_inst); - return ccall; - } else { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name")); - ccall.add_argument (pub_inst); - if (detail_expr == null) { - ccall.add_argument (get_signal_canonical_constant (sig)); - } else { - ccall.add_argument (get_signal_name_cexpression (sig, detail_expr, expr)); - } - return ccall; - } - } - - public override void visit_method_call (MethodCall expr) { - var method_type = expr.call.value_type as MethodType; - - if (method_type == null || !(method_type.method_symbol.parent_symbol is Signal)) { - // no signal connect/disconnect call - base.visit_method_call (expr); - return; - } - - var sig = (Signal) method_type.method_symbol.parent_symbol; - var signal_access = ((MemberAccess) expr.call).inner; - var handler = expr.get_argument_list ().get (0); - - bool disconnect = (method_type.method_symbol.name == "disconnect"); - bool after = (method_type.method_symbol.name == "connect_after"); - - var cexpr = connect_signal (sig, signal_access, handler, disconnect, after, expr); - set_cvalue (expr, cexpr); - } - - CCodeExpression? connect_signal (Signal sig, Expression signal_access, Expression handler, bool disconnect, bool after, CodeNode expr) { - string connect_func; - - DelegateType? dt = null; - if (handler.symbol_reference is Variable) { - dt = ((Variable) handler.symbol_reference).variable_type as DelegateType; - if (dt != null && !context.experimental) { - Report.warning (handler.source_reference, "Connecting delegates to signals is experimental"); - } - // Use actual lambda expression if available for proper target/destroy handling - if (((Variable) handler.symbol_reference).initializer is LambdaExpression) { - handler = ((Variable) handler.symbol_reference).initializer; - } - } - var m = handler.symbol_reference as Method; - - if (!disconnect) { - // connect - if (!(sig is DynamicSignal) && ((m != null && m.closure) || (dt != null && dt.value_owned))) { - connect_func = "g_signal_connect_data"; - } else if (m != null && in_gobject_instance (m)) { - connect_func = "g_signal_connect_object"; - } else if (!after) { - connect_func = "g_signal_connect"; - } else { - connect_func = "g_signal_connect_after"; - } - } else { - // disconnect - if (sig is DynamicSignal) { - connect_func = "VALA_UNSUPPORTED"; - } else { - connect_func = "g_signal_handlers_disconnect_matched"; - } - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (connect_func)); - - CCodeExpression signal_name_cexpr = null; - - // first argument: instance of sender - MemberAccess ma; - if (signal_access is ElementAccess) { - var ea = (ElementAccess) signal_access; - ma = (MemberAccess) ea.container; - var detail_expr = ea.get_indices ().get (0); - signal_name_cexpr = get_signal_name_cexpression (sig, detail_expr, expr); - } else { - ma = (MemberAccess) signal_access; - signal_name_cexpr = get_signal_name_cexpression (sig, null, expr); - } - if (ma.inner != null) { - ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner)); - } else { - ccall.add_argument (get_this_cexpression ()); - } - - if (sig is DynamicSignal) { - // dynamic_signal_connect or dynamic_signal_disconnect - - // second argument: signal name - ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_ccode_name (sig)))); - } else if (!disconnect) { - // g_signal_connect_object or g_signal_connect - - // second argument: signal name - ccall.add_argument (signal_name_cexpr); - } else { - // g_signal_handlers_disconnect_matched - - // second argument: mask - if (!(signal_access is ElementAccess)) { - ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA")); - } else { - ccall.add_argument (new CCodeConstant ("G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA")); - } - - // get signal id - var temp_decl = get_temp_variable (uint_type); - emit_temp_var (temp_decl); - var parse_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_parse_name")); - parse_call.add_argument (signal_name_cexpr); - var decl_type = (TypeSymbol) sig.parent_symbol; - parse_call.add_argument (new CCodeIdentifier (get_ccode_type_id (decl_type))); - parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_decl.name))); - LocalVariable? detail_temp_decl = null; - if (!(signal_access is ElementAccess)) { - parse_call.add_argument (new CCodeConstant ("NULL")); - parse_call.add_argument (new CCodeConstant ("FALSE")); - } else { - detail_temp_decl = get_temp_variable (gquark_type); - emit_temp_var (detail_temp_decl); - parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (detail_temp_decl.name))); - parse_call.add_argument (new CCodeConstant ("TRUE")); - } - ccode.add_expression (parse_call); - - // third argument: signal_id - ccall.add_argument (get_variable_cexpression (temp_decl.name)); - - // fourth argument: detail - if (detail_temp_decl == null) { - ccall.add_argument (new CCodeConstant ("0")); - } else { - ccall.add_argument (get_variable_cexpression (detail_temp_decl.name)); - } - // fifth argument: closure - ccall.add_argument (new CCodeConstant ("NULL")); - } - - // third resp. sixth argument: handler - ccall.add_argument (new CCodeCastExpression (get_cvalue (handler), "GCallback")); - - if (m != null && m.closure) { - // g_signal_connect_data - - // fourth argument: user_data - CCodeExpression handler_destroy_notify; - ccall.add_argument (get_delegate_target_cexpression (handler, out handler_destroy_notify)); - - // fifth argument: destroy_notify - ccall.add_argument (new CCodeCastExpression (handler_destroy_notify, "GClosureNotify")); - - // sixth argument: connect_flags - if (!after) - ccall.add_argument (new CCodeConstant ("0")); - else - ccall.add_argument (new CCodeConstant ("G_CONNECT_AFTER")); - } else if (m != null && m.binding == MemberBinding.INSTANCE) { - // g_signal_connect_object or g_signal_handlers_disconnect_matched - // or dynamic_signal_connect or dynamic_signal_disconnect - - // fourth resp. seventh argument: object/user_data - if (handler is MemberAccess) { - var right_ma = (MemberAccess) handler; - if (right_ma.inner != null) { - ccall.add_argument (get_cvalue (right_ma.inner)); - } else { - ccall.add_argument (get_this_cexpression ()); - } - } else if (handler is LambdaExpression) { - ccall.add_argument (get_this_cexpression ()); - } - if (!disconnect && in_gobject_instance (m)) { - // g_signal_connect_object - - // fifth argument: connect_flags - if (!after) - ccall.add_argument (new CCodeConstant ("0")); - else - ccall.add_argument (new CCodeConstant ("G_CONNECT_AFTER")); - } - } else if (dt != null && dt.delegate_symbol.has_target) { - // fourth argument: user_data - CCodeExpression handler_destroy_notify; - ccall.add_argument (get_delegate_target_cexpression (handler, out handler_destroy_notify)); - if (!disconnect && dt.value_owned) { - // fifth argument: destroy_notify - //FIXME handler_destroy_notify is NULL - ccall.add_argument (new CCodeCastExpression (handler_destroy_notify, "GClosureNotify")); - // sixth argument: connect_flags - if (!after) - ccall.add_argument (new CCodeConstant ("0")); - else - ccall.add_argument (new CCodeConstant ("G_CONNECT_AFTER")); - } - } else { - // g_signal_connect or g_signal_connect_after or g_signal_handlers_disconnect_matched - // or dynamic_signal_connect or dynamic_signal_disconnect - - // fourth resp. seventh argument: user_data - ccall.add_argument (new CCodeConstant ("NULL")); - } - - if (disconnect || expr.parent_node is ExpressionStatement) { - ccode.add_expression (ccall); - return null; - } else { - var temp_var = get_temp_variable (ulong_type); - var temp_ref = get_variable_cexpression (temp_var.name); - - emit_temp_var (temp_var); - - ccode.add_assignment (temp_ref, ccall); - - return temp_ref; - } - } -} - diff --git a/src/codegen/valagtkmodule.vala b/src/codegen/valagtkmodule.vala deleted file mode 100644 index e129fcba0..000000000 --- a/src/codegen/valagtkmodule.vala +++ /dev/null @@ -1,534 +0,0 @@ -/* valagtkmodule.vala - * - * Copyright (C) 2013 Jürg Billeter - * Copyright (C) 2013-2014 Luca Bruno - * - * 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.1 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: - * Luca Bruno - */ - - -public class Vala.GtkModule : GSignalModule { - - class InvalidClass : Class { - public InvalidClass (string name) { - base (name, null, null); - error = true; - } - public override bool check (CodeContext context) { - return false; - } - } - - class InvalidProperty : Property { - public InvalidProperty (string name) { - base (name, null, null, null); - error = true; - } - public override bool check (CodeContext context) { - return false; - } - } - - /* C type-func name to Vala class mapping */ - private HashMap type_id_to_vala_map = null; - /* C class name to Vala class mapping */ - private HashMap cclass_to_vala_map = null; - /* GResource name to real file name mapping */ - private HashMap gresource_to_file_map = null; - /* GtkBuilder xml handler set */ - private HashMap handler_map = new HashMap(str_hash, str_equal); - /* GtkBuilder xml handler to Vala property mapping */ - private HashMap current_handler_to_property_map = new HashMap(str_hash, str_equal); - /* GtkBuilder xml handler to Vala signal mapping */ - private HashMap current_handler_to_signal_map = new HashMap(str_hash, str_equal); - /* GtkBuilder xml child to Vala class mapping */ - private HashMap current_child_to_class_map = new HashMap(str_hash, str_equal); - /* Required custom application-specific gtype classes to be ref'd before initializing the template */ - private List current_required_app_classes = new ArrayList(); - - /* Stack of occuring object elements in the template */ - List current_object_stack = new ArrayList (); - Class? current_object; - - void push_object (Class cl) { - current_object_stack.add (current_object); - current_object = cl; - } - - void pop_object () { - current_object = current_object_stack.remove_at (current_object_stack.size - 1); - } - - /* Stack of occuring property elements in the template */ - List current_property_stack = new ArrayList (); - Property? current_property; - - void push_property (Property prop) { - current_property_stack.add (current_property); - current_property = prop; - } - - void pop_property () { - current_property = current_property_stack.remove_at (current_property_stack.size - 1); - } - - private void ensure_type_id_to_vala_map () { - // map C type-func name of gtypeinstance classes to Vala classes - if (type_id_to_vala_map != null) { - return; - } - type_id_to_vala_map = new HashMap(str_hash, str_equal); - recurse_type_id_to_vala_map (context.root); - } - - private void recurse_type_id_to_vala_map (Symbol sym) { - unowned List classes; - if (sym is Namespace) { - foreach (var inner in ((Namespace) sym).get_namespaces()) { - recurse_type_id_to_vala_map (inner); - } - classes = ((Namespace) sym).get_classes (); - } else if (sym is ObjectTypeSymbol) { - classes = ((ObjectTypeSymbol) sym).get_classes (); - } else { - return; - } - foreach (var cl in classes) { - if (!cl.is_compact) { - var type_id = get_ccode_type_id (cl); - if (type_id == null) - continue; - - var i = type_id.index_of_char ('('); - if (i > 0) { - type_id = type_id.substring (0, i - 1).strip (); - } else { - type_id = type_id.strip (); - } - type_id_to_vala_map.set (type_id, cl); - } - recurse_type_id_to_vala_map (cl); - } - } - - private void ensure_cclass_to_vala_map () { - // map C name of gtypeinstance classes to Vala classes - if (cclass_to_vala_map != null) { - return; - } - cclass_to_vala_map = new HashMap(str_hash, str_equal); - recurse_cclass_to_vala_map (context.root); - } - - private void recurse_cclass_to_vala_map (Symbol sym) { - unowned List classes; - if (sym is Namespace) { - foreach (var inner in ((Namespace) sym).get_namespaces()) { - recurse_cclass_to_vala_map (inner); - } - classes = ((Namespace) sym).get_classes (); - } else if (sym is ObjectTypeSymbol) { - classes = ((ObjectTypeSymbol) sym).get_classes (); - } else { - return; - } - foreach (var cl in classes) { - if (!cl.is_compact) { - cclass_to_vala_map.set (get_ccode_name (cl), cl); - } - recurse_cclass_to_vala_map (cl); - } - } - - private void ensure_gresource_to_file_map () { - // map gresource paths to real file names - if (gresource_to_file_map != null) { - return; - } - gresource_to_file_map = new HashMap(str_hash, str_equal); - foreach (var gresource in context.gresources) { - if (!FileUtils.test (gresource, FileTest.EXISTS)) { - Report.error (null, "GResources file `%s' does not exist", gresource); - continue; - } - - MarkupReader reader = new MarkupReader (gresource); - - int state = 0; - string prefix = null; - string alias = null; - - MarkupTokenType current_token = reader.read_token (null, null); - while (current_token != MarkupTokenType.EOF) { - if (current_token == MarkupTokenType.START_ELEMENT && reader.name == "gresource") { - prefix = reader.get_attribute ("prefix"); - } else if (current_token == MarkupTokenType.START_ELEMENT && reader.name == "file") { - alias = reader.get_attribute ("alias"); - state = 1; - } else if (state == 1 && current_token == MarkupTokenType.TEXT) { - var name = reader.content; - var filename = context.get_gresource_path (gresource, name); - if (alias != null) { - gresource_to_file_map.set (Path.build_filename (prefix, alias), filename); - } - gresource_to_file_map.set (Path.build_filename (prefix, name), filename); - state = 0; - } - current_token = reader.read_token (null, null); - } - } - } - - private void process_current_ui_resource (string ui_resource, CodeNode node) { - /* Scan a single gtkbuilder file for signal handlers in elements, - and save an handler string -> Vala.Signal mapping for each of them */ - ensure_type_id_to_vala_map (); - ensure_cclass_to_vala_map(); - ensure_gresource_to_file_map(); - - current_handler_to_signal_map = null; - current_child_to_class_map = null; - var ui_file = gresource_to_file_map.get (ui_resource); - if (ui_file == null || !FileUtils.test (ui_file, FileTest.EXISTS)) { - node.error = true; - Report.error (node.source_reference, "UI resource not found: `%s'. Please make sure to specify the proper GResources xml files with --gresources and alternative search locations with --gresourcesdir.", ui_resource); - return; - } - handler_map = new HashMap(str_hash, str_equal); - current_handler_to_signal_map = new HashMap(str_hash, str_equal); - current_child_to_class_map = new HashMap(str_hash, str_equal); - current_object_stack = new ArrayList (); - current_property_stack = new ArrayList (); - - MarkupReader reader = new MarkupReader (ui_file); - string? current_handler = null; - - bool template_tag_found = false; - MarkupTokenType current_token = reader.read_token (null, null); - while (current_token != MarkupTokenType.EOF) { - unowned string current_name = reader.name; - if (current_token == MarkupTokenType.START_ELEMENT && (current_name == "object" || current_name == "template")) { - Class? current_class = null; - - if (current_name == "object") { - var type_id = reader.get_attribute ("type-func"); - if (type_id != null) { - current_class = type_id_to_vala_map.get (type_id); - } - } else if (current_name == "template") { - template_tag_found = true; - } - - if (current_class == null) { - var class_name = reader.get_attribute ("class"); - if (class_name == null) { - Report.error (node.source_reference, "Invalid %s in ui file `%s'", current_name, ui_file); - current_token = reader.read_token (null, null); - continue; - } - current_class = cclass_to_vala_map.get (class_name); - - if (current_class == null) { - push_object (new InvalidClass (class_name)); - if (current_name == "template") { - Report.error (node.source_reference, "Unknown template `%s' in ui file `%s'", class_name, ui_file); - } else { - Report.warning (node.source_reference, "Unknown object `%s' in ui file `%s'", class_name, ui_file); - } - } - } - - if (current_class != null) { - var child_name = reader.get_attribute ("id"); - if (child_name != null) { - current_child_to_class_map.set (child_name, current_class); - } - push_object (current_class); - } - } else if (current_token == MarkupTokenType.END_ELEMENT && (current_name == "object" || current_name == "template")) { - pop_object (); - } else if (current_object != null && current_token == MarkupTokenType.START_ELEMENT && current_name == "signal") { - var signal_name = reader.get_attribute ("name"); - var handler_name = reader.get_attribute ("handler"); - - if (signal_name == null || handler_name == null) { - if (signal_name != null) { - Report.error (node.source_reference, "Invalid signal `%s' without handler in ui file `%s'", signal_name, ui_file); - } else if (handler_name != null) { - Report.error (node.source_reference, "Invalid signal without name in ui file `%s'", ui_file); - } else { - Report.error (node.source_reference, "Invalid signal without name and handler in ui file `%s'", ui_file); - } - current_token = reader.read_token (null, null); - continue; - } - var sep_idx = signal_name.index_of ("::"); - if (sep_idx >= 0) { - // detailed signal, we don't care about the detail - signal_name = signal_name.substring (0, sep_idx); - } - - var sig = SemanticAnalyzer.symbol_lookup_inherited (current_object, signal_name.replace ("-", "_")) as Signal; - if (sig != null) { - current_handler_to_signal_map.set (handler_name, sig); - } else { - Report.error (node.source_reference, "Unknown signal `%s::%s' in ui file `%s'", current_object.get_full_name (), signal_name, ui_file); - current_token = reader.read_token (null, null); - continue; - } - } else if (current_object != null && current_token == MarkupTokenType.START_ELEMENT && (current_name == "property" || current_name == "binding")) { - var property_name = reader.get_attribute ("name"); - if (property_name == null) { - Report.error (node.source_reference, "Invalid binding in ui file `%s'", ui_file); - current_token = reader.read_token (null, null); - continue; - } - - property_name = property_name.replace ("-", "_"); - var property = SemanticAnalyzer.symbol_lookup_inherited (current_object, property_name) as Property; - if (property != null) { - push_property (property); - } else { - push_property (new InvalidProperty (property_name)); - if (current_name == "binding") { - Report.error (node.source_reference, "Unknown property `%s:%s' for binding in ui file `%s'", current_object.get_full_name (), property_name, ui_file); - } - current_token = reader.read_token (null, null); - continue; - } - } else if (current_token == MarkupTokenType.END_ELEMENT && (current_name == "property" || current_name == "binding")) { - pop_property (); - } else if (current_object != null && current_token == MarkupTokenType.START_ELEMENT && current_name == "closure") { - var handler_name = reader.get_attribute ("function"); - - if (current_property != null) { - if (handler_name == null) { - Report.error (node.source_reference, "Invalid closure in ui file `%s'", ui_file); - current_token = reader.read_token (null, null); - continue; - } - if (current_property is InvalidProperty) { - Report.error (node.source_reference, "Unknown property `%s:%s' for binding in ui file `%s'", current_object.get_full_name (), current_property.name, ui_file); - } - - //TODO Retrieve signature declaration? c-type to vala-type? - current_handler_to_property_map.set (handler_name, current_property); - current_handler = handler_name; - } else if (current_handler != null) { - // Track nested closure elements - handler_map.set (handler_name, current_handler); - current_handler = handler_name; - } - } - current_token = reader.read_token (null, null); - } - - if (!template_tag_found) { - Report.error (node.source_reference, "ui resource `%s' does not describe a valid composite template", ui_resource); - } - } - - private bool is_gtk_template (Class cl) { - var attr = cl.get_attribute ("GtkTemplate"); - if (attr != null) { - if (gtk_widget_type == null || !cl.is_subtype_of (gtk_widget_type)) { - if (!cl.error) { - Report.error (attr.source_reference, "subclassing Gtk.Widget is required for using Gtk templates"); - cl.error = true; - } - return false; - } - return true; - } - return false; - } - - public override void generate_class_init (Class cl) { - base.generate_class_init (cl); - - if (cl.error || !is_gtk_template (cl)) { - return; - } - - /* Gtk builder widget template */ - var ui = cl.get_attribute_string ("GtkTemplate", "ui"); - if (ui == null) { - Report.error (cl.source_reference, "empty ui resource declaration for Gtk widget template"); - cl.error = true; - return; - } - - process_current_ui_resource (ui, cl); - - var call = new CCodeFunctionCall (new CCodeIdentifier ("gtk_widget_class_set_template_from_resource")); - call.add_argument (new CCodeIdentifier ("GTK_WIDGET_CLASS (klass)")); - call.add_argument (new CCodeConstant ("\"%s\"".printf (ui))); - ccode.add_expression (call); - - current_required_app_classes.clear (); - } - - public override void visit_property (Property prop) { - if (prop.get_attribute ("GtkChild") != null && prop.field == null) { - Report.error (prop.source_reference, "[GtkChild] is only allowed on automatic properties"); - } - - base.visit_property (prop); - } - - public override void visit_field (Field f) { - base.visit_field (f); - - var cl = current_class; - if (cl == null || cl.error) { - return; - } - - if (f.binding != MemberBinding.INSTANCE || f.get_attribute ("GtkChild") == null) { - return; - } - - /* If the field has a [GtkChild] attribute but its class doesn'thave a - [GtkTemplate] attribute, we throw an error */ - if (!is_gtk_template (cl)) { - Report.error (f.source_reference, "[GtkChild] is only allowed in classes with a [GtkTemplate] attribute"); - return; - } - - push_context (class_init_context); - - /* Map ui widget to a class field */ - var gtk_name = f.get_attribute_string ("GtkChild", "name", f.name); - var child_class = current_child_to_class_map.get (gtk_name); - if (child_class == null) { - Report.error (f.source_reference, "could not find child `%s'", gtk_name); - return; - } - - /* We allow Gtk child to have stricter type than class field */ - unowned Class? field_class = f.variable_type.type_symbol as Class; - if (field_class == null || !child_class.is_subtype_of (field_class)) { - Report.error (f.source_reference, "cannot convert from Gtk child type `%s' to `%s'", child_class.get_full_name(), field_class.get_full_name()); - return; - } - - var internal_child = f.get_attribute_bool ("GtkChild", "internal"); - - CCodeExpression offset; - if (f.is_private_symbol ()) { - // new glib api, we add the private struct offset to get the final field offset out of the instance - var private_field_offset = new CCodeFunctionCall (new CCodeIdentifier ("G_STRUCT_OFFSET")); - private_field_offset.add_argument (new CCodeIdentifier ("%sPrivate".printf (get_ccode_name (cl)))); - private_field_offset.add_argument (new CCodeIdentifier (get_ccode_name (f))); - offset = new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier ("%s_private_offset".printf (get_ccode_name (cl))), private_field_offset); - } else { - var offset_call = new CCodeFunctionCall (new CCodeIdentifier ("G_STRUCT_OFFSET")); - offset_call.add_argument (new CCodeIdentifier (get_ccode_name (cl))); - offset_call.add_argument (new CCodeIdentifier (get_ccode_name (f))); - offset = offset_call; - } - - var call = new CCodeFunctionCall (new CCodeIdentifier ("gtk_widget_class_bind_template_child_full")); - call.add_argument (new CCodeIdentifier ("GTK_WIDGET_CLASS (klass)")); - call.add_argument (new CCodeConstant ("\"%s\"".printf (gtk_name))); - call.add_argument (new CCodeConstant (internal_child ? "TRUE" : "FALSE")); - call.add_argument (offset); - ccode.add_expression (call); - - pop_context (); - - if (!field_class.external && !field_class.external_package) { - current_required_app_classes.add (field_class); - } - } - - public override void visit_method (Method m) { - base.visit_method (m); - - var cl = current_class; - if (cl == null || cl.error || !is_gtk_template (cl)) { - return; - } - - if (m.get_attribute ("GtkCallback") == null) { - return; - } - - /* Handler name as defined in the gtkbuilder xml */ - var handler_name = m.get_attribute_string ("GtkCallback", "name", m.name); - var callback = handler_map.get (handler_name); - var sig = current_handler_to_signal_map.get (handler_name); - var prop = current_handler_to_property_map.get (handler_name); - if (callback == null && sig == null && prop == null) { - Report.error (m.source_reference, "could not find signal or property for handler `%s'", handler_name); - return; - } - - push_context (class_init_context); - - if (sig != null) { - sig.check (context); - var method_type = new MethodType (m); - var signal_type = new SignalType (sig); - var delegate_type = signal_type.get_handler_type (); - if (!method_type.compatible (delegate_type)) { - Report.error (m.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'", method_type.to_string (), delegate_type.to_string (), delegate_type.to_prototype_string (m.name)); - } else { - var wrapper = generate_delegate_wrapper (m, signal_type.get_handler_type (), m); - - var call = new CCodeFunctionCall (new CCodeIdentifier ("gtk_widget_class_bind_template_callback_full")); - call.add_argument (new CCodeIdentifier ("GTK_WIDGET_CLASS (klass)")); - call.add_argument (new CCodeConstant ("\"%s\"".printf (handler_name))); - call.add_argument (new CCodeIdentifier ("G_CALLBACK(%s)".printf (wrapper))); - ccode.add_expression (call); - } - } - if (prop != null || callback != null) { - if (prop != null) { - prop.check (context); - } - //TODO Perform signature check - var call = new CCodeFunctionCall (new CCodeIdentifier ("gtk_widget_class_bind_template_callback_full")); - call.add_argument (new CCodeIdentifier ("GTK_WIDGET_CLASS (klass)")); - call.add_argument (new CCodeConstant ("\"%s\"".printf (handler_name))); - call.add_argument (new CCodeIdentifier ("G_CALLBACK(%s)".printf (get_ccode_name (m)))); - ccode.add_expression (call); - } - - pop_context (); - } - - - public override void end_instance_init (Class cl) { - if (cl == null || cl.error || !is_gtk_template (cl)) { - return; - } - - foreach (var req in current_required_app_classes) { - /* ensure custom application widgets are initialized */ - var call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_ensure")); - call.add_argument (get_type_id_expression (SemanticAnalyzer.get_data_type_for_symbol (req))); - ccode.add_expression (call); - } - - var call = new CCodeFunctionCall (new CCodeIdentifier ("gtk_widget_init_template")); - call.add_argument (new CCodeIdentifier ("GTK_WIDGET (self)")); - ccode.add_expression (call); - } -} - diff --git a/src/codegen/valagtypemodule.vala b/src/codegen/valagtypemodule.vala deleted file mode 100644 index 270548e72..000000000 --- a/src/codegen/valagtypemodule.vala +++ /dev/null @@ -1,2550 +0,0 @@ -/* valagtypemodule.vala - * - * Copyright (C) 2006-2010 Jürg Billeter - * Copyright (C) 2006-2008 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.1 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 - * Raffaele Sandrini - */ - - -public class Vala.GTypeModule : GErrorModule { - public override CCodeParameter generate_parameter (Parameter param, CCodeFile decl_space, Map cparam_map, Map? carg_map) { - if (!(param.variable_type is ObjectType)) { - return base.generate_parameter (param, decl_space, cparam_map, carg_map); - } - - generate_type_declaration (param.variable_type, decl_space); - - string? ctypename = get_ccode_type (param); - if (ctypename == null) { - ctypename = get_ccode_name (param.variable_type); - - if (param.direction != ParameterDirection.IN) { - ctypename = "%s*".printf (ctypename); - } - } - - var cparam = new CCodeParameter (get_ccode_name (param), ctypename); - if (param.format_arg) { - cparam.modifiers = CCodeModifiers.FORMAT_ARG; - } - - cparam_map.set (get_param_pos (get_ccode_pos (param)), cparam); - if (carg_map != null) { - carg_map.set (get_param_pos (get_ccode_pos (param)), get_parameter_cexpression (param)); - } - - return cparam; - } - - public override void generate_class_declaration (Class cl, CCodeFile decl_space) { - if (add_symbol_declaration (decl_space, cl, get_ccode_name (cl))) { - return; - } - - if (cl.base_class != null) { - // base class declaration - // necessary for ref and unref function declarations - generate_class_declaration (cl.base_class, decl_space); - } - - bool is_gtypeinstance = !cl.is_compact; - bool is_fundamental = is_gtypeinstance && cl.base_class == null; - bool is_gsource = cl.is_subtype_of (gsource_type); - - if (is_gtypeinstance) { - decl_space.add_include ("glib-object.h"); - - decl_space.add_type_declaration (new CCodeNewline ()); - var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (cl, null)); - decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (cl), macro)); - - macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_name (cl)); - decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_cast_function (cl)), macro)); - - if (!(cl.is_sealed && decl_space.file_type == CCodeFileType.PUBLIC_HEADER)) { - macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_type_name (cl)); - decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(klass)".printf (get_ccode_class_type_function (cl)), macro)); - } - - macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (cl)); - decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (cl)), macro)); - - if (!(cl.is_sealed && decl_space.file_type == CCodeFileType.PUBLIC_HEADER)) { - macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (get_ccode_type_id (cl)); - decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(klass)".printf (get_ccode_class_type_check_function (cl)), macro)); - } - - if (!(cl.is_sealed && decl_space.file_type == CCodeFileType.PUBLIC_HEADER)) { - macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %s))".printf (get_ccode_type_id (cl), get_ccode_type_name (cl)); - decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_get_function (cl)), macro)); - } - decl_space.add_type_declaration (new CCodeNewline ()); - } - - if (!(!cl.is_compact || cl.base_class == null || compact_class_has_instance_struct_member (cl))) { - decl_space.add_type_declaration (new CCodeTypeDefinition (get_ccode_name (cl.base_class), new CCodeVariableDeclarator (get_ccode_name (cl)))); - } else { - decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (cl)), new CCodeVariableDeclarator (get_ccode_name (cl)))); - } - - if (is_fundamental) { - var ref_fun = new CCodeFunction (get_ccode_ref_function (cl), "gpointer"); - var unref_fun = new CCodeFunction (get_ccode_unref_function (cl), "void"); - if (cl.is_private_symbol ()) { - ref_fun.modifiers = CCodeModifiers.STATIC; - unref_fun.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && cl.is_internal_symbol ()) { - ref_fun.modifiers = CCodeModifiers.INTERNAL; - unref_fun.modifiers = CCodeModifiers.INTERNAL; - } else { - ref_fun.modifiers = CCodeModifiers.EXTERN; - unref_fun.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - ref_fun.add_parameter (new CCodeParameter ("instance", "gpointer")); - unref_fun.add_parameter (new CCodeParameter ("instance", "gpointer")); - - decl_space.add_function_declaration (ref_fun); - decl_space.add_function_declaration (unref_fun); - - // GParamSpec and GValue functions - var function = new CCodeFunction (get_ccode_param_spec_function (cl), "GParamSpec*"); - function.add_parameter (new CCodeParameter ("name", "const gchar*")); - function.add_parameter (new CCodeParameter ("nick", "const gchar*")); - function.add_parameter (new CCodeParameter ("blurb", "const gchar*")); - function.add_parameter (new CCodeParameter ("object_type", "GType")); - function.add_parameter (new CCodeParameter ("flags", "GParamFlags")); - - if (cl.is_private_symbol ()) { - // avoid C warning as this function is not always used - function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED; - } else if (context.hide_internal && cl.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } else { - function.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - decl_space.add_function_declaration (function); - - function = new CCodeFunction (get_ccode_set_value_function (cl), "void"); - function.add_parameter (new CCodeParameter ("value", "GValue*")); - function.add_parameter (new CCodeParameter ("v_object", "gpointer")); - - if (cl.is_private_symbol ()) { - // avoid C warning as this function is not always used - function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED; - } else if (context.hide_internal && cl.is_internal_symbol ()) { - // avoid C warning as this function is not always used - function.modifiers = CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED; - } else { - function.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - decl_space.add_function_declaration (function); - - function = new CCodeFunction (get_ccode_take_value_function (cl), "void"); - function.add_parameter (new CCodeParameter ("value", "GValue*")); - function.add_parameter (new CCodeParameter ("v_object", "gpointer")); - - if (cl.is_private_symbol ()) { - // avoid C warning as this function is not always used - function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED; - } else if (context.hide_internal && cl.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } else { - function.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - decl_space.add_function_declaration (function); - - function = new CCodeFunction (get_ccode_get_value_function (cl), "gpointer"); - function.add_parameter (new CCodeParameter ("value", "const GValue*")); - - if (cl.is_private_symbol ()) { - // avoid C warning as this function is not always used - function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.UNUSED; - } else if (context.hide_internal && cl.is_internal_symbol ()) { - // avoid C warning as this function is not always used - function.modifiers = CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED; - } else { - function.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - decl_space.add_function_declaration (function); - } else if (!is_gtypeinstance && !is_gsource) { - if (cl.base_class == null) { - var function = new CCodeFunction (get_ccode_free_function (cl), "void"); - if (cl.is_private_symbol ()) { - function.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && cl.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } else { - function.modifiers = CCodeModifiers.EXTERN; - requires_vala_extern = true; - } - - function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl)))); - - decl_space.add_function_declaration (function); - } - } - - if (is_gtypeinstance && !(cl.is_sealed && decl_space.file_type == CCodeFileType.PUBLIC_HEADER)) { - decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_type_name (cl)), new CCodeVariableDeclarator (get_ccode_type_name (cl)))); - - var type_fun = new ClassRegisterFunction (cl); - type_fun.init_from_type (context, in_plugin, true); - decl_space.add_type_member_declaration (type_fun.get_declaration ()); - - requires_vala_extern = true; - } - - var base_class = cl; - while (base_class.base_class != null) { - base_class = base_class.base_class; - } - // Custom unref-methods need to be emitted before G_DEFINE_AUTOPTR_CLEANUP_FUNC, - // so we guard against that special case and handle it in generate_method_declaration. - if (!(base_class.is_compact && is_reference_counting (base_class)) - && (context.header_filename == null|| decl_space.file_type == CCodeFileType.PUBLIC_HEADER - || (decl_space.file_type == CCodeFileType.INTERNAL_HEADER && base_class.is_internal_symbol()))) { - string autoptr_cleanup_func; - if (is_reference_counting (base_class)) { - autoptr_cleanup_func = get_ccode_unref_function (base_class); - } else { - autoptr_cleanup_func = get_ccode_free_function (base_class); - } - if (autoptr_cleanup_func == null || autoptr_cleanup_func == "") { - Report.error (cl.source_reference, "internal error: autoptr_cleanup_func not available"); - } - decl_space.add_type_member_declaration (new CCodeIdentifier ("G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, %s)".printf (get_ccode_name (cl), autoptr_cleanup_func))); - decl_space.add_type_member_declaration (new CCodeNewline ()); - } - } - - public override void generate_class_struct_declaration (Class cl, CCodeFile decl_space) { - if (add_symbol_declaration (decl_space, cl, "struct _%s".printf (get_ccode_name (cl)))) { - return; - } - - if (cl.base_class != null) { - // base class declaration - generate_class_struct_declaration (cl.base_class, decl_space); - } - foreach (DataType base_type in cl.get_base_types ()) { - unowned Interface? iface = base_type.type_symbol as Interface; - if (iface != null) { - generate_interface_declaration (iface, decl_space); - } - } - - generate_class_declaration (cl, decl_space); - - if (cl.is_sealed && decl_space.file_type == CCodeFileType.PUBLIC_HEADER) { - return; - } - - bool is_gtypeinstance = !cl.is_compact; - bool is_fundamental = is_gtypeinstance && cl.base_class == null; - - var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (cl))); - var type_struct = new CCodeStruct ("_%s".printf (get_ccode_type_name (cl))); - - if (cl.base_class != null) { - instance_struct.add_field (get_ccode_name (cl.base_class), "parent_instance"); - } else if (is_fundamental) { - instance_struct.add_field ("GTypeInstance", "parent_instance"); - instance_struct.add_field ("volatile int", "ref_count"); - } - - if (is_gtypeinstance) { - decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (get_ccode_name (cl))))); - - if (!context.abi_stability) { - instance_struct.add_field ("%sPrivate *".printf (get_ccode_name (cl)), "priv"); - } - if (is_fundamental) { - type_struct.add_field ("GTypeClass", "parent_class"); - } else { - type_struct.add_field (get_ccode_type_name (cl.base_class), "parent_class"); - } - - if (is_fundamental) { - type_struct.add_field ("void", "(*finalize) (%s *self)".printf (get_ccode_name (cl))); - } - } - - if (context.abi_stability) { - foreach (Symbol s in cl.get_members ()) { - if (s is Method) { - var m = (Method) s; - generate_struct_method_declaration (cl, m, instance_struct, type_struct, decl_space); - } else if (s is Signal) { - var sig = (Signal) s; - if (sig.default_handler != null) { - if (sig.is_virtual) { - generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct); - } else { - generate_method_declaration (sig.default_handler, cfile); - } - } - } else if (s is Property) { - var prop = (Property) s; - generate_struct_property_declaration (cl, prop, instance_struct, type_struct, decl_space); - } else if (s is Field) { - if (s.access != SymbolAccessibility.PRIVATE || cl.is_opaque) { - generate_struct_field_declaration ((Field) s, instance_struct, type_struct, decl_space); - } - } else { - Report.error (s.source_reference, "internal: Unsupported symbol"); - } - } - } else { - foreach (Method m in cl.get_methods ()) { - generate_struct_method_declaration (cl, m, instance_struct, type_struct, decl_space); - } - - foreach (Signal sig in cl.get_signals ()) { - if (sig.default_handler != null) { - if (sig.is_virtual) { - generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct); - } else { - generate_method_declaration (sig.default_handler, cfile); - } - } - } - - foreach (Property prop in cl.get_properties ()) { - generate_struct_property_declaration (cl, prop, instance_struct, type_struct, decl_space); - } - - foreach (Field f in cl.get_fields ()) { - if (f.access != SymbolAccessibility.PRIVATE || cl.is_opaque) { - generate_struct_field_declaration (f, instance_struct, type_struct, decl_space); - } - } - } - - if (cl.is_compact && cl.base_class == null && !compact_class_has_instance_struct_member (cl)) { - // add dummy member, C doesn't allow empty structs - instance_struct.add_field ("int", "dummy"); - } - - if (!cl.is_compact || cl.base_class == null || compact_class_has_instance_struct_member (cl)) { - decl_space.add_type_definition (instance_struct); - } - - if (is_gtypeinstance) { - if (context.abi_stability) { - instance_struct.add_field ("%sPrivate *".printf (get_ccode_name (cl)), "priv"); - } - decl_space.add_type_definition (type_struct); - } - } - - bool compact_class_has_instance_struct_member (Class cl) { - assert (cl.is_compact); - foreach (Symbol s in cl.get_members ()) { - if (s is Method) { - unowned Method m = (Method) s; - if (m.is_abstract || m.is_virtual) { - return true; - } - } else if (s is Property) { - unowned Property prop = (Property) s; - if (prop.is_abstract || prop.is_virtual) { - return true; - } - } else if (s is Field) { - if (s.access != SymbolAccessibility.PRIVATE || cl.is_opaque) { - unowned Field f = (Field) s; - if (f.binding == MemberBinding.INSTANCE) { - return true; - } - } - } else { - Report.error (s.source_reference, "internal: Unsupported symbol"); - } - } - return false; - } - - void generate_struct_method_declaration (ObjectTypeSymbol type_sym, Method m, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space) { - unowned Class? cl = type_sym as Class; - if (type_sym is Interface || (cl != null && !cl.is_compact)) { - generate_virtual_method_declaration (m, decl_space, type_struct); - } else if (cl != null && cl.is_compact && cl.base_class == null) { - generate_virtual_method_declaration (m, decl_space, instance_struct); - } - } - - void generate_struct_property_declaration (ObjectTypeSymbol type_sym, Property prop, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space) { - if (!prop.is_abstract && !prop.is_virtual) { - return; - } - generate_type_declaration (prop.property_type, decl_space); - - unowned ObjectTypeSymbol t = (ObjectTypeSymbol) prop.parent_symbol; - unowned Class? cl = type_sym as Class; - - var this_type = new ObjectType (t); - var cselfparam = new CCodeParameter ("self", get_ccode_name (this_type)); - - if (prop.get_accessor != null) { - var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name)); - vdeclarator.add_parameter (cselfparam); - var creturn_type = get_callable_creturn_type (prop.get_accessor.get_method ()); - if (prop.property_type.is_real_non_null_struct_type ()) { - var cvalueparam = new CCodeParameter ("result", "%s *".printf (get_ccode_name (prop.get_accessor.value_type))); - vdeclarator.add_parameter (cvalueparam); - } - - var array_type = prop.property_type as ArrayType; - if (array_type != null && get_ccode_array_length (prop)) { - var length_ctype = get_ccode_array_length_type (prop) + "*"; - for (int dim = 1; dim <= array_type.rank; dim++) { - vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("result", dim), length_ctype)); - } - } else if ((prop.property_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) prop.property_type).delegate_symbol.has_target) { - vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("result"), "gpointer*")); - } - - var vdecl = new CCodeDeclaration (get_ccode_name (creturn_type)); - vdecl.add_declarator (vdeclarator); - type_struct.add_declaration (vdecl); - - if (cl != null && cl.is_compact && cl.base_class == null) { - instance_struct.add_declaration (vdecl); - } - } - if (prop.set_accessor != null) { - CCodeParameter cvalueparam; - if (prop.property_type.is_real_non_null_struct_type ()) { - cvalueparam = new CCodeParameter ("value", "%s *".printf (get_ccode_name (prop.set_accessor.value_type))); - } else { - cvalueparam = new CCodeParameter ("value", get_ccode_name (prop.set_accessor.value_type)); - } - - var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name)); - vdeclarator.add_parameter (cselfparam); - vdeclarator.add_parameter (cvalueparam); - - var array_type = prop.property_type as ArrayType; - if (array_type != null && get_ccode_array_length (prop)) { - var length_ctype = get_ccode_array_length_type (prop); - for (int dim = 1; dim <= array_type.rank; dim++) { - vdeclarator.add_parameter (new CCodeParameter (get_array_length_cname ("value", dim), length_ctype)); - } - } else if ((prop.property_type is DelegateType) && get_ccode_delegate_target (prop) && ((DelegateType) prop.property_type).delegate_symbol.has_target) { - vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_cname ("value"), "gpointer")); - if (prop.set_accessor.value_type.value_owned) { - vdeclarator.add_parameter (new CCodeParameter (get_delegate_target_destroy_notify_cname ("value"), get_ccode_name (delegate_target_destroy_type))); - } - } - - var vdecl = new CCodeDeclaration ("void"); - vdecl.add_declarator (vdeclarator); - type_struct.add_declaration (vdecl); - - if (cl != null && cl.is_compact && cl.base_class == null) { - instance_struct.add_declaration (vdecl); - } - } - } - - void generate_struct_field_declaration (Field f, CCodeStruct instance_struct, CCodeStruct type_struct, CCodeFile decl_space) { - CCodeModifiers modifiers = (f.is_volatile ? CCodeModifiers.VOLATILE : 0) | (f.version.deprecated ? CCodeModifiers.DEPRECATED : 0); - if (f.binding == MemberBinding.INSTANCE) { - append_field (instance_struct, f, decl_space); - } else if (f.binding == MemberBinding.CLASS) { - type_struct.add_field (get_ccode_name (f.variable_type), get_ccode_name (f), modifiers); - } - } - - public override bool generate_method_declaration (Method m, CCodeFile decl_space) { - if (base.generate_method_declaration (m, decl_space)) { - // Custom unref-methods need to be emitted before G_DEFINE_AUTOPTR_CLEANUP_FUNC, - // in addition to the non-ref-countable case in generate_class_declaration. - unowned Class? cl = m.parent_symbol as Class; - if (cl != null && cl.is_compact && get_ccode_unref_function (cl) == get_ccode_name (m) - && (context.header_filename == null || decl_space.file_type == CCodeFileType.PUBLIC_HEADER - || (decl_space.file_type == CCodeFileType.INTERNAL_HEADER && cl.is_internal_symbol()))) { - decl_space.add_type_member_declaration (new CCodeIdentifier ("G_DEFINE_AUTOPTR_CLEANUP_FUNC (%s, %s)".printf (get_ccode_name (cl), get_ccode_name (m)))); - decl_space.add_type_member_declaration (new CCodeNewline ()); - } - - return true; - } - - return false; - } - - public virtual void generate_virtual_method_declaration (Method m, CCodeFile decl_space, CCodeStruct type_struct) { - if (!m.is_abstract && !m.is_virtual) { - return; - } - - var creturn_type = get_callable_creturn_type (m); - - // add vfunc field to the type struct - var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m)); - var cparam_map = new HashMap (direct_hash, direct_equal); - - if (m.printf_format) { - vdeclarator.modifiers |= CCodeModifiers.PRINTF; - } else if (m.scanf_format) { - vdeclarator.modifiers |= CCodeModifiers.SCANF; - } - - if (m.version.deprecated) { - vdeclarator.modifiers |= CCodeModifiers.DEPRECATED; - } - - generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator); - - var vdecl = new CCodeDeclaration (get_ccode_name (creturn_type)); - vdecl.add_declarator (vdeclarator); - type_struct.add_declaration (vdecl); - } - - void generate_class_private_declaration (Class cl, CCodeFile decl_space) { - if (cl.is_opaque || decl_space.add_declaration ("%sPrivate".printf (get_ccode_name (cl)))) { - return; - } - - bool is_gtypeinstance = !cl.is_compact; - bool has_class_locks = false; - - var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (get_ccode_name (cl))); - var type_priv_struct = new CCodeStruct ("_%sPrivate".printf (get_ccode_type_name (cl))); - - if (is_gtypeinstance) { - /* create type, dup_func, and destroy_func fields for generic types */ - foreach (TypeParameter type_param in cl.get_type_parameters ()) { - instance_priv_struct.add_field ("GType", get_ccode_type_id (type_param)); - instance_priv_struct.add_field ("GBoxedCopyFunc", get_ccode_copy_function (type_param)); - instance_priv_struct.add_field ("GDestroyNotify", get_ccode_destroy_function (type_param)); - } - } - - foreach (Field f in cl.get_fields ()) { - if (f.access == SymbolAccessibility.PRIVATE) { - generate_struct_field_declaration (f, instance_priv_struct, type_priv_struct, decl_space); - } - if (f.lock_used) { - if (f.binding == MemberBinding.INSTANCE) { - cl.has_private_fields = true; - // add field for mutex - instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f))); - } else if (f.binding == MemberBinding.CLASS) { - has_class_locks = true; - // add field for mutex - type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (f))); - } - } - } - - foreach (Property prop in cl.get_properties ()) { - if (prop.binding == MemberBinding.INSTANCE) { - if (prop.lock_used) { - cl.has_private_fields = true; - // add field for mutex - instance_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (prop))); - } - } else if (prop.binding == MemberBinding.CLASS) { - if (prop.lock_used) { - has_class_locks = true; - // add field for mutex - type_priv_struct.add_field (get_ccode_name (mutex_type), get_symbol_lock_name (get_ccode_name (prop))); - } - } - } - - if (is_gtypeinstance) { - if (cl.has_class_private_fields || has_class_locks) { - decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (get_ccode_type_name (cl))))); - } - - /* only add the *Private struct if it is not empty, i.e. we actually have private data */ - if (cl.has_private_fields || cl.has_type_parameters ()) { - decl_space.add_type_definition (instance_priv_struct); - - var parent_decl = new CCodeDeclaration ("gint"); - var parent_var_decl = new CCodeVariableDeclarator ("%s_private_offset".printf (get_ccode_name (cl))); - parent_decl.add_declarator (parent_var_decl); - parent_decl.modifiers = CCodeModifiers.STATIC; - cfile.add_type_member_declaration (parent_decl); - - var function = new CCodeFunction ("%s_get_instance_private".printf (get_ccode_lower_case_name (cl, null)), "gpointer"); - function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.INLINE; - function.add_parameter (new CCodeParameter ("self", "%s*".printf (get_ccode_name (cl)))); - - push_function (function); - - function.block = new CCodeBlock (); - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_STRUCT_MEMBER_P")); - ccall.add_argument (new CCodeIdentifier ("self")); - ccall.add_argument (new CCodeIdentifier ("%s_private_offset".printf (get_ccode_name (cl)))); - function.block.add_statement (new CCodeReturnStatement (ccall)); - - pop_function (); - cfile.add_function (function); - } - - if (cl.has_class_private_fields || has_class_locks) { - decl_space.add_type_definition (type_priv_struct); - - string macro = "(G_TYPE_CLASS_GET_PRIVATE (klass, %s, %sPrivate))".printf (get_ccode_type_id (cl), get_ccode_type_name (cl)); - decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s(klass)".printf (get_ccode_class_get_private_function (cl)), macro)); - } - } - } - - public override void visit_class (Class cl) { - push_context (new EmitContext (cl)); - push_line (cl.source_reference); - - var old_param_spec_struct = param_spec_struct; - var old_prop_enum = prop_enum; - var old_signal_enum = signal_enum; - var old_class_init_context = class_init_context; - var old_base_init_context = base_init_context; - var old_class_finalize_context = class_finalize_context; - var old_base_finalize_context = base_finalize_context; - var old_instance_init_context = instance_init_context; - var old_instance_finalize_context = instance_finalize_context; - - bool is_gtypeinstance = !cl.is_compact; - bool is_gobject = is_gtypeinstance && cl.is_subtype_of (gobject_type); - bool is_fundamental = is_gtypeinstance && cl.base_class == null; - - if (get_ccode_name (cl).length < 3) { - cl.error = true; - Report.error (cl.source_reference, "Class name `%s' is too short", get_ccode_name (cl)); - return; - } - - prop_enum = new CCodeEnum (); - prop_enum.add_value (new CCodeEnumValue ("%s_0_PROPERTY".printf (get_ccode_upper_case_name (cl, null)))); - signal_enum = new CCodeEnum (); - class_init_context = new EmitContext (cl); - base_init_context = new EmitContext (cl); - class_finalize_context = new EmitContext (cl); - base_finalize_context = new EmitContext (cl); - instance_init_context = new EmitContext (cl); - instance_finalize_context = new EmitContext (cl); - - generate_class_struct_declaration (cl, cfile); - generate_class_private_declaration (cl, cfile); - - var last_prop = "%s_NUM_PROPERTIES".printf (get_ccode_upper_case_name (cl)); - if (is_gobject) { - cfile.add_type_declaration (prop_enum); - - var prop_array_decl = new CCodeDeclaration ("GParamSpec*"); - prop_array_decl.modifiers |= CCodeModifiers.STATIC; - prop_array_decl.add_declarator (new CCodeVariableDeclarator ("%s_properties".printf (get_ccode_lower_case_name (cl)), null, new CCodeDeclaratorSuffix.with_array (new CCodeIdentifier (last_prop)))); - cfile.add_type_declaration (prop_array_decl); - } - - if (!cl.is_internal_symbol () || cl.is_sealed) { - if (!cl.is_opaque) { - generate_class_struct_declaration (cl, header_file); - } else { - generate_class_declaration (cl, header_file); - } - } - if (!cl.is_private_symbol () || cl.is_sealed) { - generate_class_struct_declaration (cl, internal_header_file); - } - - if (is_gtypeinstance) { - begin_base_init_function (cl); - begin_class_init_function (cl); - begin_instance_init_function (cl); - - begin_base_finalize_function (cl); - begin_class_finalize_function (cl); - begin_finalize_function (cl); - } else { - if (cl.is_compact || cl.base_class == null || cl.is_subtype_of (gsource_type)) { - begin_instance_init_function (cl); - begin_finalize_function (cl); - } - } - - cl.accept_children (this); - - if (is_gtypeinstance) { - if (is_fundamental) { - param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(get_ccode_prefix (cl.parent_symbol), cl.name)); - param_spec_struct.add_field ("GParamSpec", "parent_instance"); - cfile.add_type_definition (param_spec_struct); - - cfile.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (param_spec_struct.name), new CCodeVariableDeclarator ( "%sParamSpec%s".printf(get_ccode_prefix (cl.parent_symbol), cl.name)))); - - add_type_value_table_init_function (cl); - add_type_value_table_free_function (cl); - add_type_value_table_copy_function (cl); - add_type_value_table_peek_pointer_function (cl); - add_type_value_table_collect_value_function (cl); - add_type_value_table_lcopy_value_function (cl); - add_g_param_spec_type_function (cl); - add_g_value_get_function (cl); - add_g_value_set_function (cl); - add_g_value_take_function (cl); - - var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1")); - push_context (instance_init_context); - ccode.add_expression (ref_count); - pop_context (); - } - - if (is_gobject) { - prop_enum.add_value (new CCodeEnumValue (last_prop)); - } - - if (cl.get_signals ().size > 0) { - var last_signal = "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (cl)); - signal_enum.add_value (new CCodeEnumValue (last_signal)); - cfile.add_type_declaration (signal_enum); - - var signal_array_decl = new CCodeDeclaration ("guint"); - signal_array_decl.modifiers |= CCodeModifiers.STATIC; - signal_array_decl.add_declarator (new CCodeVariableDeclarator ("%s_signals".printf (get_ccode_lower_case_name (cl)), new CCodeConstant ("{0}"), new CCodeDeclaratorSuffix.with_array (new CCodeIdentifier (last_signal)))); - cfile.add_type_declaration (signal_array_decl); - } - - - if (cl.class_constructor != null) { - add_base_init_function (cl); - } - add_class_init_function (cl); - - if (cl.class_destructor != null) { - add_base_finalize_function (cl); - } - - if (cl.static_destructor != null) { - add_class_finalize_function (cl); - } - - foreach (DataType base_type in cl.get_base_types ()) { - if (base_type.type_symbol is Interface) { - add_interface_init_function (cl, (Interface) base_type.type_symbol); - } - } - - add_instance_init_function (cl); - - if (!cl.is_compact && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) { - add_finalize_function (cl); - } - - if (cl.comment != null) { - cfile.add_type_member_definition (new CCodeComment (cl.comment.content)); - } - - var type_fun = new ClassRegisterFunction (cl); - type_fun.init_from_type (context, in_plugin, false); - cfile.add_type_member_declaration (type_fun.get_source_declaration ()); - cfile.add_type_member_definition (type_fun.get_definition ()); - - if (is_fundamental) { - var ref_count = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"); - - // ref function - var ref_fun = new CCodeFunction (get_ccode_ref_function (cl), "gpointer"); - ref_fun.add_parameter (new CCodeParameter ("instance", "gpointer")); - if (cl.is_private_symbol ()) { - ref_fun.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && cl.is_internal_symbol ()) { - ref_fun.modifiers = CCodeModifiers.INTERNAL; - } - push_function (ref_fun); - - ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance"))); - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_inc")); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count)); - ccode.add_expression (ccall); - ccode.add_return (new CCodeIdentifier ("instance")); - - pop_function (); - cfile.add_function (ref_fun); - - // unref function - var unref_fun = new CCodeFunction (get_ccode_unref_function (cl), "void"); - unref_fun.add_parameter (new CCodeParameter ("instance", "gpointer")); - if (cl.is_private_symbol ()) { - unref_fun.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && cl.is_internal_symbol ()) { - unref_fun.modifiers = CCodeModifiers.INTERNAL; - } - push_function (unref_fun); - - ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance"))); - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_dec_and_test")); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count)); - ccode.open_if (ccall); - - var get_class = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (cl))); - get_class.add_argument (new CCodeIdentifier ("self")); - - // finalize class - var ccast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_get_function (cl))); - ccast.add_argument (new CCodeIdentifier ("self")); - ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize")); - ccall.add_argument (new CCodeIdentifier ("self")); - ccode.add_expression (ccall); - - // free type instance - var free = new CCodeFunctionCall (new CCodeIdentifier ("g_type_free_instance")); - free.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GTypeInstance *")); - ccode.add_expression (free); - - ccode.close (); - pop_function (); - cfile.add_function (unref_fun); - } - } else { - if (cl.is_compact || cl.base_class == null || cl.is_subtype_of (gsource_type)) { - add_instance_init_function (cl); - add_finalize_function (cl); - } - } - - param_spec_struct = old_param_spec_struct; - prop_enum = old_prop_enum; - signal_enum = old_signal_enum; - class_init_context = old_class_init_context; - base_init_context = old_base_init_context; - class_finalize_context = old_class_finalize_context; - base_finalize_context = old_base_finalize_context; - instance_init_context = old_instance_init_context; - instance_finalize_context = old_instance_finalize_context; - - pop_line (); - pop_context (); - } - - private void add_type_value_table_init_function (Class cl) { - var function = new CCodeFunction ("%s_init".printf (get_ccode_lower_case_name (cl, "value_")), "void"); - function.add_parameter (new CCodeParameter ("value", "GValue*")); - function.modifiers = CCodeModifiers.STATIC; - - push_function (function); - ccode.add_assignment (new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer"), new CCodeConstant ("NULL")); - pop_function (); - cfile.add_function (function); - } - - private void add_type_value_table_free_function (Class cl) { - var function = new CCodeFunction ("%s_free_value".printf (get_ccode_lower_case_name (cl, "value_")), "void"); - function.add_parameter (new CCodeParameter ("value", "GValue*")); - function.modifiers = CCodeModifiers.STATIC; - - push_function (function); - - var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); - var ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl))); - ccall.add_argument (vpointer); - - ccode.open_if (vpointer); - ccode.add_expression (ccall); - ccode.close (); - - pop_function (); - cfile.add_function (function); - } - - private void add_type_value_table_copy_function (Class cl) { - var function = new CCodeFunction ("%s_copy_value".printf (get_ccode_lower_case_name (cl, "value_")), "void"); - function.add_parameter (new CCodeParameter ("src_value", "const GValue*")); - function.add_parameter (new CCodeParameter ("dest_value", "GValue*")); - function.modifiers = CCodeModifiers.STATIC; - - push_function (function); - - var dest_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest_value"), "data[0]"), "v_pointer"); - var src_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("src_value"), "data[0]"), "v_pointer"); - - var ref_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl))); - ref_ccall.add_argument ( src_vpointer ); - - ccode.open_if (src_vpointer); - ccode.add_assignment (dest_vpointer, ref_ccall); - ccode.add_else (); - ccode.add_assignment (dest_vpointer, new CCodeConstant ("NULL")); - ccode.close (); - - pop_function (); - cfile.add_function (function); - } - - private void add_type_value_table_peek_pointer_function (Class cl) { - var function = new CCodeFunction ("%s_peek_pointer".printf (get_ccode_lower_case_name (cl, "value_")), "gpointer"); - function.add_parameter (new CCodeParameter ("value", "const GValue*")); - function.modifiers = CCodeModifiers.STATIC; - - push_function (function); - - var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer"); - ccode.add_return (vpointer); - - pop_function (); - cfile.add_function (function); - } - - private void add_type_value_table_lcopy_value_function ( Class cl ) { - // Required for GTypeCValue - cfile.add_include ("gobject/gvaluecollector.h"); - - var function = new CCodeFunction ("%s_lcopy_value".printf (get_ccode_lower_case_name (cl, "value_")), "gchar*"); - function.add_parameter (new CCodeParameter ("value", "const GValue*")); - function.add_parameter (new CCodeParameter ("n_collect_values", "guint")); - function.add_parameter (new CCodeParameter ("collect_values", "GTypeCValue*")); - function.add_parameter (new CCodeParameter ("collect_flags", "guint")); - function.modifiers = CCodeModifiers.STATIC; - - var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer"); - var object_p_ptr = new CCodeIdentifier ("*object_p"); - var null_ = new CCodeConstant ("NULL"); - - push_function (function); - - ccode.add_declaration ("%s **".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("object_p", new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer"))); - - var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME")); - value_type_name_fct.add_argument (new CCodeConstant ("value")); - - var assert_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("object_p")); - ccode.open_if (assert_condition); - var assert_printf = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup_printf")); - assert_printf.add_argument (new CCodeConstant ("\"value location for `%s' passed as NULL\"")); - assert_printf.add_argument (value_type_name_fct); - ccode.add_return (assert_printf); - ccode.close (); - - var main_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, vpointer); - var main_else_if_condition = new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, new CCodeIdentifier ("collect_flags"), new CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS")); - var ref_fct = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl))); - ref_fct.add_argument (vpointer); - ccode.open_if (main_condition); - ccode.add_assignment (object_p_ptr, null_); - ccode.else_if (main_else_if_condition); - ccode.add_assignment (object_p_ptr, vpointer); - ccode.add_else (); - ccode.add_assignment (object_p_ptr, ref_fct); - ccode.close (); - - ccode.add_return (null_); - pop_function (); - cfile.add_function (function); - } - - private void add_type_value_table_collect_value_function (Class cl) { - // Required for GTypeCValue - cfile.add_include ("gobject/gvaluecollector.h"); - - var function = new CCodeFunction ("%s_collect_value".printf (get_ccode_lower_case_name (cl, "value_")), "gchar*"); - function.add_parameter (new CCodeParameter ("value", "GValue*")); - function.add_parameter (new CCodeParameter ("n_collect_values", "guint")); - function.add_parameter (new CCodeParameter ("collect_values", "GTypeCValue*")); - function.add_parameter (new CCodeParameter ("collect_flags", "guint")); - function.modifiers = CCodeModifiers.STATIC; - - var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer"); - - push_function (function); - - var collect_vpointer = new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer"); - - ccode.open_if (collect_vpointer); - ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("object", collect_vpointer)); - var obj_identifier = new CCodeIdentifier ("object"); - var l_expression = new CCodeMemberAccess (new CCodeMemberAccess.pointer (obj_identifier, "parent_instance"), "g_class"); - var sub_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, l_expression, new CCodeConstant ("NULL")); - var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME")); - value_type_name_fct.add_argument (new CCodeConstant ("value")); - - ccode.open_if (sub_condition); - var true_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat")); - true_return.add_argument (new CCodeConstant ("\"invalid unclassed object pointer for value type `\"")); - true_return.add_argument (value_type_name_fct); - true_return.add_argument (new CCodeConstant ("\"'\"")); - true_return.add_argument (new CCodeConstant ("NULL")); - ccode.add_return (true_return); - - var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible")); - var type_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE")); - type_check.add_argument (new CCodeIdentifier ("object")); - reg_call.add_argument (type_check); - var stored_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE")); - stored_type.add_argument (new CCodeIdentifier ("value")); - reg_call.add_argument (stored_type); - - ccode.else_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, reg_call)); - var false_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat")); - var type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name")); - type_name_fct.add_argument (type_check); - false_return.add_argument (new CCodeConstant ("\"invalid object type `\"")); - false_return.add_argument (type_name_fct); - false_return.add_argument (new CCodeConstant ("\"' for value type `\"")); - false_return.add_argument (value_type_name_fct); - false_return.add_argument (new CCodeConstant ("\"'\"")); - false_return.add_argument (new CCodeConstant ("NULL")); - ccode.add_return (false_return); - - ccode.close (); - - var ref_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl))); - ref_call.add_argument (new CCodeIdentifier ("object")); - ccode.add_assignment (vpointer, ref_call); - - ccode.add_else (); - ccode.add_assignment (vpointer, new CCodeConstant ("NULL")); - - ccode.close (); - - ccode.add_return (new CCodeConstant ("NULL")); - - pop_function (); - cfile.add_function (function); - } - - private void add_g_param_spec_type_function (Class cl) { - var function = new CCodeFunction (get_ccode_param_spec_function (cl), "GParamSpec*"); - function.add_parameter (new CCodeParameter ("name", "const gchar*")); - function.add_parameter (new CCodeParameter ("nick", "const gchar*")); - function.add_parameter (new CCodeParameter ("blurb", "const gchar*")); - function.add_parameter (new CCodeParameter ("object_type", "GType")); - function.add_parameter (new CCodeParameter ("flags", "GParamFlags")); - - if (cl.is_private_symbol ()) { - function.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && cl.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } - - push_function (function); - - ccode.add_declaration ("%sParamSpec%s*".printf (get_ccode_prefix (cl.parent_symbol), cl.name), new CCodeVariableDeclarator ("spec")); - - var subccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_is_a")); - subccall.add_argument (new CCodeIdentifier ("object_type")); - subccall.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) )); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail")); - ccall.add_argument (subccall); - ccall.add_argument (new CCodeConstant ("NULL")); - ccode.add_expression (ccall); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_internal")); - ccall.add_argument (new CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" )); - ccall.add_argument (new CCodeIdentifier ("name")); - ccall.add_argument (new CCodeIdentifier ("nick")); - ccall.add_argument (new CCodeIdentifier ("blurb")); - ccall.add_argument (new CCodeIdentifier ("flags")); - - ccode.add_assignment (new CCodeIdentifier ("spec"), ccall); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_PARAM_SPEC")); - ccall.add_argument (new CCodeIdentifier ("spec")); - - ccode.add_assignment (new CCodeMemberAccess.pointer (ccall, "value_type"), new CCodeIdentifier ("object_type")); - ccode.add_return (ccall); - - pop_function (); - cfile.add_function (function); - } - - private void add_g_value_set_function (Class cl) { - var function = new CCodeFunction (get_ccode_set_value_function (cl), "void"); - function.add_parameter (new CCodeParameter ("value", "GValue*")); - function.add_parameter (new CCodeParameter ("v_object", "gpointer")); - - if (cl.is_private_symbol ()) { - function.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && cl.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } - - var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer"); - - push_function (function); - - ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("old")); - - var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE")); - ccall_typecheck.add_argument (new CCodeIdentifier ( "value" )); - ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) )); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); - ccall.add_argument (ccall_typecheck); - ccode.add_expression (ccall); - - ccode.add_assignment (new CCodeConstant ("old"), vpointer); - - ccode.open_if (new CCodeIdentifier ("v_object")); - ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE")); - ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" )); - ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) )); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); - ccall.add_argument (ccall_typecheck); - ccode.add_expression (ccall); - - var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE")); - ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" )); - - var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE")); - ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" )); - - var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible")); - ccall_typecompatible.add_argument (ccall_typefrominstance); - ccall_typecompatible.add_argument (ccall_gvaluetype); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); - ccall.add_argument (ccall_typecompatible); - ccode.add_expression (ccall); - - ccode.add_assignment (vpointer, new CCodeConstant ("v_object")); - - ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_ref_function (cl))); - ccall.add_argument (vpointer); - ccode.add_expression (ccall); - - ccode.add_else (); - ccode.add_assignment (vpointer, new CCodeConstant ("NULL")); - ccode.close (); - - ccode.open_if (new CCodeIdentifier ("old")); - ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl))); - ccall.add_argument (new CCodeIdentifier ("old")); - ccode.add_expression (ccall); - ccode.close (); - - pop_function (); - cfile.add_function (function); - } - - private void add_g_value_take_function (Class cl) { - var function = new CCodeFunction (get_ccode_take_value_function (cl), "void"); - function.add_parameter (new CCodeParameter ("value", "GValue*")); - function.add_parameter (new CCodeParameter ("v_object", "gpointer")); - - if (cl.is_private_symbol ()) { - function.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && cl.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } - - var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); - - push_function (function); - - ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("old")); - - var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE")); - ccall_typecheck.add_argument (new CCodeIdentifier ( "value" )); - ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) )); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); - ccall.add_argument (ccall_typecheck); - ccode.add_expression (ccall); - - ccode.add_assignment (new CCodeConstant ("old"), vpointer); - - ccode.open_if (new CCodeIdentifier ("v_object")); - - ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE")); - ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" )); - ccall_typecheck.add_argument (new CCodeIdentifier ( get_ccode_type_id (cl) )); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); - ccall.add_argument (ccall_typecheck); - ccode.add_expression (ccall); - - var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE")); - ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" )); - - var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE")); - ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" )); - - var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible")); - ccall_typecompatible.add_argument (ccall_typefrominstance); - ccall_typecompatible.add_argument (ccall_gvaluetype); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); - ccall.add_argument (ccall_typecompatible); - ccode.add_expression (ccall); - - ccode.add_assignment (vpointer, new CCodeConstant ("v_object")); - - ccode.add_else (); - ccode.add_assignment (vpointer, new CCodeConstant ("NULL")); - ccode.close (); - - ccode.open_if (new CCodeIdentifier ("old")); - ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_unref_function (cl))); - ccall.add_argument (new CCodeIdentifier ("old")); - ccode.add_expression (ccall); - ccode.close (); - - pop_function (); - cfile.add_function (function); - } - - private void add_g_value_get_function (Class cl) { - var function = new CCodeFunction (get_ccode_get_value_function (cl), "gpointer"); - function.add_parameter (new CCodeParameter ("value", "const GValue*")); - - if (cl.is_private_symbol ()) { - function.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && cl.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } - - var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); - - push_function (function); - - var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE")); - ccall_typecheck.add_argument (new CCodeIdentifier ("value")); - ccall_typecheck.add_argument (new CCodeIdentifier (get_ccode_type_id (cl))); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail")); - ccall.add_argument (ccall_typecheck); - ccall.add_argument (new CCodeConstant ("NULL")); - ccode.add_expression (ccall); - - ccode.add_return (vpointer); - - pop_function (); - cfile.add_function (function); - } - - private void begin_base_init_function (Class cl) { - push_context (base_init_context); - - var base_init = new CCodeFunction ("%s_base_init".printf (get_ccode_lower_case_name (cl, null)), "void"); - base_init.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl)))); - base_init.modifiers = CCodeModifiers.STATIC; - - push_function (base_init); - - pop_context (); - } - - private void add_base_init_function (Class cl) { - cfile.add_function (base_init_context.ccode); - } - - public virtual void generate_class_init (Class cl) { - } - - public virtual void end_instance_init (Class cl) { - } - - private void begin_class_init_function (Class cl) { - push_context (class_init_context); - - var func = new CCodeFunction ("%s_class_init".printf (get_ccode_lower_case_name (cl, null))); - func.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl)))); - func.add_parameter (new CCodeParameter ("klass_data", "gpointer")); - func.modifiers = CCodeModifiers.STATIC; - - CCodeFunctionCall ccall; - - /* save pointer to parent class */ - var parent_decl = new CCodeDeclaration ("gpointer"); - var parent_var_decl = new CCodeVariableDeclarator ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null))); - parent_var_decl.initializer = new CCodeConstant ("NULL"); - parent_decl.add_declarator (parent_var_decl); - parent_decl.modifiers = CCodeModifiers.STATIC; - cfile.add_type_member_declaration (parent_decl); - - push_function (func); - - 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 (get_ccode_lower_case_name (cl, null))), ccall); - ccode.add_expression (parent_assignment); - - - if (!cl.is_compact && !cl.is_subtype_of (gobject_type) && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) { - // set finalize function - var fundamental_class = cl; - while (fundamental_class.base_class != null) { - fundamental_class = fundamental_class.base_class; - } - - var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%s *".printf (get_ccode_type_name (fundamental_class))); - var finalize_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%sfinalize".printf (get_ccode_lower_case_prefix (cl)))); - ccode.add_expression (finalize_assignment); - } - - /* add struct for private fields */ - if (cl.has_private_fields || cl.has_type_parameters ()) { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_adjust_private_offset")); - ccall.add_argument (new CCodeIdentifier ("klass")); - ccall.add_argument (new CCodeIdentifier ("&%s_private_offset".printf (get_ccode_name (cl)))); - ccode.add_expression (ccall); - } - - /* connect overridden methods */ - foreach (Method m in cl.get_methods ()) { - if (m.base_method == null) { - continue; - } - var base_type = (ObjectTypeSymbol) m.base_method.parent_symbol; - - // there is currently no default handler for abstract async methods - if (!m.is_abstract || !m.coroutine) { - generate_method_declaration (m.base_method, cfile); - - CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (m)); - cfunc = cast_method_pointer (m.base_method, cfunc, base_type, (m.coroutine ? 1 : 3)); - var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%s *".printf (get_ccode_type_name (base_type))); - ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (m.base_method)), cfunc); - - if (m.coroutine) { - cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m)); - cfunc = cast_method_pointer (m.base_method, cfunc, base_type, 2); - ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_finish_vfunc_name (m.base_method)), cfunc); - } - } - } - - /* connect default signal handlers */ - foreach (Signal sig in cl.get_signals ()) { - if (sig.default_handler == null || !sig.is_virtual) { - continue; - } - - var ccast = new CCodeCastExpression (new CCodeIdentifier ("klass"), "%s *".printf (get_ccode_type_name (cl))); - ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (sig.default_handler)), new CCodeIdentifier (get_ccode_real_name (sig.default_handler))); - } - - /* connect overridden properties */ - foreach (Property prop in cl.get_properties ()) { - if (prop.base_property == null) { - continue; - } - var base_type = (Class) prop.base_property.parent_symbol; - - var ccast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (base_type))); - ccast.add_argument (new CCodeIdentifier ("klass")); - - if (!get_ccode_no_accessor_method (prop.base_property) && !get_ccode_concrete_accessor (prop.base_property)) { - if (prop.get_accessor != null) { - generate_property_accessor_declaration (prop.base_property.get_accessor, cfile); - - string cname = get_ccode_real_name (prop.get_accessor); - ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname)); - } - if (prop.set_accessor != null) { - generate_property_accessor_declaration (prop.base_property.set_accessor, cfile); - - string cname = get_ccode_real_name (prop.set_accessor); - ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname)); - } - } - } - - generate_class_init (cl); - - if (!cl.is_compact) { - /* create signals */ - foreach (Signal sig in cl.get_signals ()) { - if (sig.comment != null) { - ccode.add_statement (new CCodeComment (sig.comment.content)); - } - ccode.add_expression (get_signal_creation (sig, cl)); - } - } - - pop_context (); - } - - private void add_class_init_function (Class cl) { - cfile.add_function (class_init_context.ccode); - } - - private void add_generic_accessor_function (string base_name, string return_type, CCodeExpression? expression, TypeParameter p, Class cl, Interface iface) { - string name = "%s_%s_%s".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface), base_name); - - var function = new CCodeFunction (name, return_type); - function.modifiers = CCodeModifiers.STATIC; - var this_type = SemanticAnalyzer.get_data_type_for_symbol (cl); - function.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type))); - push_function (function); - ccode.add_return (expression); - pop_function (); - cfile.add_function (function); - - CCodeExpression cfunc = new CCodeIdentifier (function.name); - string cast = "%s (*)".printf (return_type); - string cast_args = "%s *".printf (get_ccode_name (iface)); - cast = "%s (%s)".printf (cast, cast_args); - cfunc = new CCodeCastExpression (cfunc, cast); - var ciface = new CCodeIdentifier ("iface"); - ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, base_name), cfunc); - } - - private void add_interface_init_function (Class cl, Interface iface) { - var iface_init = new CCodeFunction ("%s_%s_interface_init".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface)), "void"); - iface_init.add_parameter (new CCodeParameter ("iface", "%s *".printf (get_ccode_type_name (iface)))); - iface_init.add_parameter (new CCodeParameter ("iface_data", "gpointer")); - iface_init.modifiers = CCodeModifiers.STATIC; - - push_function (iface_init); - - CCodeFunctionCall ccall; - - /* save pointer to parent vtable */ - string parent_iface_var = "%s_%s_parent_iface".printf (get_ccode_lower_case_name (cl), get_ccode_lower_case_name (iface)); - var parent_decl = new CCodeDeclaration ("%s *".printf (get_ccode_type_name (iface))); - 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; - cfile.add_type_member_declaration (parent_decl); - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent")); - ccall.add_argument (new CCodeIdentifier ("iface")); - ccode.add_assignment (new CCodeIdentifier (parent_iface_var), ccall); - - foreach (Method m in cl.get_methods ()) { - if (m.base_interface_method == null) { - continue; - } - - var base_type = m.base_interface_method.parent_symbol; - if (base_type != iface) { - continue; - } - - generate_method_declaration (m.base_interface_method, cfile); - - var ciface = new CCodeIdentifier ("iface"); - CCodeExpression cfunc; - if (m.is_abstract || m.is_virtual) { - cfunc = new CCodeIdentifier (get_ccode_name (m)); - } else { - cfunc = new CCodeIdentifier (get_ccode_real_name (m)); - } - cfunc = cast_method_pointer (m.base_interface_method, cfunc, iface, (m.coroutine ? 1 : 3)); - ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m.base_interface_method)), cfunc); - - if (m.coroutine) { - if (m.is_abstract || m.is_virtual) { - cfunc = new CCodeIdentifier (get_ccode_finish_name (m)); - } else { - cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m)); - } - cfunc = cast_method_pointer (m.base_interface_method, cfunc, iface, 2); - ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_finish_vfunc_name (m.base_interface_method)), cfunc); - } - } - - if (iface.get_attribute ("GenericAccessors") != null) { - foreach (TypeParameter p in iface.get_type_parameters ()) { - GenericType p_type = new GenericType (p); - DataType p_data_type = p_type.get_actual_type (SemanticAnalyzer.get_data_type_for_symbol (cl), null, cl); - - add_generic_accessor_function ("get_%s".printf (get_ccode_type_id (p)), - "GType", - get_type_id_expression (p_data_type), - p, cl, iface); - - add_generic_accessor_function ("get_%s".printf (get_ccode_copy_function (p)), - "GBoxedCopyFunc", - get_dup_func_expression (p_data_type, p_data_type.source_reference), - p, cl, iface); - - add_generic_accessor_function ("get_%s".printf (get_ccode_destroy_function (p)), - "GDestroyNotify", - get_destroy_func_expression (p_data_type), - p, cl, iface); - } - } - - // connect inherited implementations - var it = cl.get_implicit_implementations ().map_iterator (); - while (it.next ()) { - Method m = it.get_key (); - if (m.parent_symbol == iface) { - Method base_method = it.get_value (); - - generate_method_declaration (base_method, cfile); - - CCodeExpression cfunc = new CCodeIdentifier (get_ccode_name (base_method)); - cfunc = cast_method_pointer (m, cfunc, iface); - var ciface = new CCodeIdentifier ("iface"); - ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m)), cfunc); - } - } - - foreach (Property prop in cl.get_properties ()) { - if (prop.base_interface_property == null) { - continue; - } - - var base_type = (ObjectTypeSymbol) prop.base_interface_property.parent_symbol; - if (base_type != iface) { - continue; - } - - var ciface = new CCodeIdentifier ("iface"); - - if (!get_ccode_no_accessor_method (prop.base_interface_property) && !get_ccode_concrete_accessor (prop.base_interface_property)) { - if (prop.get_accessor != null) { - generate_property_accessor_declaration (prop.base_interface_property.get_accessor, cfile); - - string cname = get_ccode_real_name (prop.get_accessor); - if (prop.is_abstract || prop.is_virtual) { - cname = get_ccode_name (prop.get_accessor); - } - - CCodeExpression cfunc = new CCodeIdentifier (cname); - if (prop.is_abstract || prop.is_virtual) { - cfunc = cast_property_accessor_pointer (prop.get_accessor, cfunc, base_type); - } - ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc); - } - if (prop.set_accessor != null) { - generate_property_accessor_declaration (prop.base_interface_property.set_accessor, cfile); - - string cname = get_ccode_real_name (prop.set_accessor); - if (prop.is_abstract || prop.is_virtual) { - cname = get_ccode_name (prop.set_accessor); - } - - CCodeExpression cfunc = new CCodeIdentifier (cname); - if (prop.is_abstract || prop.is_virtual) { - cfunc = cast_property_accessor_pointer (prop.set_accessor, cfunc, base_type); - } - ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc); - } - } - } - - foreach (Property prop in iface.get_properties ()) { - if (!prop.is_abstract) { - continue; - } - - Property cl_prop = null; - var base_class = cl; - while (base_class != null && cl_prop == null) { - cl_prop = base_class.scope.lookup (prop.name) as Property; - base_class = base_class.base_class; - } - if (base_class != null && cl_prop.parent_symbol != cl) { - // property inherited from base class - - var base_property = cl_prop; - if (cl_prop.base_property != null) { - base_property = cl_prop.base_property; - } else if (cl_prop.base_interface_property != null) { - base_property = cl_prop.base_interface_property; - } - - // Our base class provides this interface implementation - if (prop == base_property) { - continue; - } - - var ciface = new CCodeIdentifier ("iface"); - - if (base_property.get_accessor != null && prop.get_accessor != null) { - generate_property_accessor_declaration (base_property.get_accessor, cfile); - - string cname = get_ccode_name (base_property.get_accessor); - CCodeExpression cfunc = new CCodeIdentifier (cname); - cfunc = cast_property_accessor_pointer (prop.get_accessor, cfunc, iface); - ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), cfunc); - } - if (base_property.set_accessor != null && prop.set_accessor != null) { - generate_property_accessor_declaration (base_property.set_accessor, cfile); - - string cname = get_ccode_name (base_property.set_accessor); - CCodeExpression cfunc = new CCodeIdentifier (cname); - cfunc = cast_property_accessor_pointer (prop.set_accessor, cfunc, iface); - ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), cfunc); - } - } - } - - pop_function (); - cfile.add_function (iface_init); - } - - CCodeExpression cast_property_accessor_pointer (PropertyAccessor acc, CCodeExpression cfunc, ObjectTypeSymbol base_type) { - string cast; - if (acc.readable && acc.value_type.is_real_non_null_struct_type ()) { - cast = "void (*) (%s *, %s *)".printf (get_ccode_name (base_type), get_ccode_name (acc.value_type)); - } else if (acc.readable) { - cast = "%s (*) (%s *)".printf (get_ccode_name (acc.value_type), get_ccode_name (base_type)); - } else if (acc.value_type.is_real_non_null_struct_type ()) { - cast = "void (*) (%s *, %s *)".printf (get_ccode_name (base_type), get_ccode_name (acc.value_type)); - } else { - cast = "void (*) (%s *, %s)".printf (get_ccode_name (base_type), get_ccode_name (acc.value_type)); - } - return new CCodeCastExpression (cfunc, cast); - } - - CCodeExpression cast_method_pointer (Method m, CCodeExpression cfunc, ObjectTypeSymbol base_type, int direction = 3) { - // Cast the function pointer to match the interface - string cast; - if (direction == 1 || m.return_type.is_real_non_null_struct_type ()) { - cast = "void (*)"; - } else { - cast = "%s (*)".printf (get_ccode_name (m.return_type)); - } - - var vdeclarator = new CCodeFunctionDeclarator (get_ccode_vfunc_name (m)); - var cparam_map = new HashMap (direct_hash, direct_equal); - - generate_cparameters (m, cfile, cparam_map, new CCodeFunction ("fake"), vdeclarator, null, null, direction); - - // append C arguments in the right order - int last_pos = -1; - int min_pos; - string cast_args = ""; - while (true) { - min_pos = -1; - foreach (int pos in cparam_map.get_keys ()) { - if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { - min_pos = pos; - } - } - if (min_pos == -1) { - break; - } - if (last_pos != -1) { - cast_args = "%s, ".printf (cast_args); - } - var cparam = cparam_map.get (min_pos); - if (cparam.ellipsis) { - cast_args = "%s...".printf (cast_args); - } else { - cast_args = "%s%s".printf (cast_args, cparam.type_name); - } - last_pos = min_pos; - } - cast = "%s (%s)".printf (cast, cast_args); - return new CCodeCastExpression (cfunc, cast); - } - - private void begin_instance_init_function (Class cl) { - push_context (instance_init_context); - - var func = new CCodeFunction ("%s_instance_init".printf (get_ccode_lower_case_name (cl, null))); - func.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl)))); - if (!cl.is_compact) { - func.add_parameter (new CCodeParameter ("klass", "gpointer")); - } - func.modifiers = CCodeModifiers.STATIC; - - push_function (func); - - bool is_gsource = cl.is_subtype_of (gsource_type); - - if (cl.is_compact) { - // Add declaration, since the instance_init function is explicitly called - // by the creation methods - cfile.add_function_declaration (func); - - // connect overridden methods - foreach (Method m in cl.get_methods ()) { - if (m.base_method == null || is_gsource) { - continue; - } - var base_type = (ObjectTypeSymbol) m.base_method.parent_symbol; - - // there is currently no default handler for abstract async methods - if (!m.is_abstract || !m.coroutine) { - generate_method_declaration (m.base_method, cfile); - - CCodeExpression cfunc = new CCodeIdentifier (get_ccode_real_name (m)); - cfunc = cast_method_pointer (m.base_method, cfunc, base_type, (m.coroutine ? 1 : 3)); - var ccast = new CCodeCastExpression (new CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type))); - func.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_vfunc_name (m.base_method)), cfunc); - - if (m.coroutine) { - cfunc = new CCodeIdentifier (get_ccode_finish_real_name (m)); - cfunc = cast_method_pointer (m.base_method, cfunc, base_type, 2); - ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, get_ccode_finish_vfunc_name (m.base_method)), cfunc); - } - } - } - - // connect overridden properties - foreach (Property prop in cl.get_properties ()) { - if (prop.base_property == null || is_gsource) { - continue; - } - var base_type = prop.base_property.parent_symbol; - - var ccast = new CCodeCastExpression (new CCodeIdentifier ("self"), "%s *".printf (get_ccode_name (base_type))); - - if (!get_ccode_no_accessor_method (prop.base_property) && !get_ccode_concrete_accessor (prop.base_property)) { - if (prop.get_accessor != null) { - generate_property_accessor_declaration (prop.base_property.get_accessor, cfile); - - string cname = get_ccode_real_name (prop.get_accessor); - ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname)); - } - if (prop.set_accessor != null) { - generate_property_accessor_declaration (prop.base_property.set_accessor, cfile); - - string cname = get_ccode_real_name (prop.set_accessor); - ccode.add_assignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname)); - } - } - } - } - - if (!cl.is_compact && (cl.has_private_fields || cl.has_type_parameters ())) { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_get_instance_private".printf (get_ccode_lower_case_name (cl, null)))); - ccall.add_argument (new CCodeIdentifier ("self")); - func.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall); - } - - pop_context (); - } - - private void add_instance_init_function (Class cl) { - push_context (instance_init_context); - end_instance_init (cl); - pop_context (); - - cfile.add_function (instance_init_context.ccode); - } - - private void begin_class_finalize_function (Class cl) { - push_context (class_finalize_context); - - var function = new CCodeFunction ("%s_class_finalize".printf (get_ccode_lower_case_name (cl, null)), "void"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl)))); - - push_function (function); - - if (cl.static_destructor != null) { - cl.static_destructor.body.emit (this); - - if (current_method_inner_error) { - ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL"))); - } - - if (current_method_return) { - // support return statements in destructors - ccode.add_label ("_return"); - ccode.add_statement (new CCodeEmptyStatement ()); - } - } - - pop_context (); - } - - private void add_class_finalize_function (Class cl) { - cfile.add_function_declaration (class_finalize_context.ccode); - cfile.add_function (class_finalize_context.ccode); - } - - private void begin_base_finalize_function (Class cl) { - push_context (base_finalize_context); - - var function = new CCodeFunction ("%s_base_finalize".printf (get_ccode_lower_case_name (cl, null)), "void"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeParameter ("klass", "%s *".printf (get_ccode_type_name (cl)))); - function.add_parameter (new CCodeParameter ("klass_data", "gpointer")); - - push_function (function); - - if (cl.class_destructor != null) { - cl.class_destructor.body.emit (this); - - if (current_method_inner_error) { - ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL"))); - } - - if (current_method_return) { - // support return statements in destructors - ccode.add_label ("_return"); - ccode.add_statement (new CCodeEmptyStatement ()); - } - } - - pop_context (); - } - - private void add_base_finalize_function (Class cl) { - push_context (base_finalize_context); - - cfile.add_function_declaration (ccode); - cfile.add_function (ccode); - - pop_context (); - } - - private void begin_finalize_function (Class cl) { - push_context (instance_finalize_context); - - bool is_gsource = cl.is_subtype_of (gsource_type); - - if (!cl.is_compact || is_gsource) { - var fundamental_class = cl; - while (fundamental_class.base_class != null) { - fundamental_class = fundamental_class.base_class; - } - - var func = new CCodeFunction ("%sfinalize".printf (get_ccode_lower_case_prefix (cl))); - func.add_parameter (new CCodeParameter ("obj", "%s *".printf (get_ccode_name (fundamental_class)))); - func.modifiers = CCodeModifiers.STATIC; - - push_function (func); - - if (is_gsource) { - cfile.add_function_declaration (func); - } - - CCodeExpression ccast; - if (!cl.is_compact) { - ccast = generate_instance_cast (new CCodeIdentifier ("obj"), cl); - } else { - ccast = new CCodeCastExpression (new CCodeIdentifier ("obj"), "%s *".printf (get_ccode_name (cl))); - } - - ccode.add_declaration ("%s *".printf (get_ccode_name (cl)), new CCodeVariableDeclarator ("self")); - ccode.add_assignment (new CCodeIdentifier ("self"), ccast); - - if (!cl.is_compact && cl.base_class == null) { - // non-gobject class - var call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_handlers_destroy")); - call.add_argument (new CCodeIdentifier ("self")); - ccode.add_expression (call); - } - } else if (cl.base_class == null) { - var function = new CCodeFunction (get_ccode_free_function (cl), "void"); - if (cl.is_private_symbol ()) { - function.modifiers = CCodeModifiers.STATIC; - } else if (context.hide_internal && cl.is_internal_symbol ()) { - function.modifiers = CCodeModifiers.INTERNAL; - } - - function.add_parameter (new CCodeParameter ("self", "%s *".printf (get_ccode_name (cl)))); - - push_function (function); - } - - if (cl.destructor != null) { - cl.destructor.body.emit (this); - - if (current_method_inner_error) { - ccode.add_declaration ("GError*", new CCodeVariableDeclarator.zero ("_inner_error%d_".printf (current_inner_error_id), new CCodeConstant ("NULL"))); - } - - if (current_method_return) { - // support return statements in destructors - ccode.add_label ("_return"); - } - } - - pop_context (); - } - - private void add_finalize_function (Class cl) { - if (!cl.is_compact) { - var fundamental_class = cl; - while (fundamental_class.base_class != null) { - fundamental_class = fundamental_class.base_class; - } - - // chain up to finalize function of the base class - if (cl.base_class != null) { - var ccast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (fundamental_class))); - ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (cl, null)))); - var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize")); - ccall.add_argument (new CCodeIdentifier ("obj")); - push_context (instance_finalize_context); - ccode.add_expression (ccall); - pop_context (); - } - - cfile.add_function_declaration (instance_finalize_context.ccode); - cfile.add_function (instance_finalize_context.ccode); - } else if (cl.base_class == null) { - // g_slice_free needs glib.h - cfile.add_include ("glib.h"); - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); - ccall.add_argument (new CCodeIdentifier (get_ccode_name (cl))); - ccall.add_argument (new CCodeIdentifier ("self")); - push_context (instance_finalize_context); - ccode.add_expression (ccall); - pop_context (); - - cfile.add_function (instance_finalize_context.ccode); - } else if (cl.is_subtype_of (gsource_type)) { - cfile.add_function (instance_finalize_context.ccode); - } - } - - public override CCodeExpression get_param_spec_cexpression (Property prop) { - var cl = (TypeSymbol) prop.parent_symbol; - var prop_array = new CCodeIdentifier ("%s_properties".printf (get_ccode_lower_case_name (cl))); - var prop_enum_value = new CCodeIdentifier ("%s_PROPERTY".printf (get_ccode_upper_case_name (prop))); - - return new CCodeElementAccess (prop_array, prop_enum_value); - } - - public override CCodeExpression get_param_spec (Property prop) { - var cspec = new CCodeFunctionCall (); - cspec.add_argument (get_property_canonical_cconstant (prop)); - cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.nick))); - cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.blurb))); - - unowned TypeSymbol? type_symbol = prop.property_type.type_symbol; - if (type_symbol is Class || type_symbol is Interface) { - string param_spec_name = get_ccode_param_spec_function (type_symbol); - cspec.call = new CCodeIdentifier (param_spec_name); - if (param_spec_name == "g_param_spec_string") { - cspec.add_argument (new CCodeConstant ("NULL")); - } else if (param_spec_name == "g_param_spec_variant") { - cspec.add_argument (new CCodeConstant ("G_VARIANT_TYPE_ANY")); - cspec.add_argument (new CCodeConstant ("NULL")); - } else if (param_spec_name == "gtk_param_spec_expression") { - // No additional parameter required - } else if (get_ccode_type_id (type_symbol) != "G_TYPE_POINTER") { - cspec.add_argument (new CCodeIdentifier (get_ccode_type_id (type_symbol))); - } - } else if (type_symbol is Enum) { - unowned Enum e = (Enum) type_symbol; - if (get_ccode_has_type_id (e)) { - if (e.is_flags) { - cspec.call = new CCodeIdentifier ("g_param_spec_flags"); - } else { - cspec.call = new CCodeIdentifier ("g_param_spec_enum"); - } - cspec.add_argument (new CCodeIdentifier (get_ccode_type_id (e))); - } else { - if (e.is_flags) { - cspec.call = new CCodeIdentifier ("g_param_spec_uint"); - cspec.add_argument (new CCodeConstant ("0")); - cspec.add_argument (new CCodeConstant ("G_MAXUINT")); - } else { - cspec.call = new CCodeIdentifier ("g_param_spec_int"); - cspec.add_argument (new CCodeConstant ("G_MININT")); - cspec.add_argument (new CCodeConstant ("G_MAXINT")); - } - } - - if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); - } else { - cspec.add_argument (new CCodeConstant (get_ccode_default_value (type_symbol))); - } - } else if (type_symbol is Struct) { - unowned Struct st = (Struct) type_symbol; - var type_id = get_ccode_type_id (st); - if (type_id == "G_TYPE_INT") { - cspec.call = new CCodeIdentifier ("g_param_spec_int"); - cspec.add_argument (new CCodeConstant ("G_MININT")); - cspec.add_argument (new CCodeConstant ("G_MAXINT")); - if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); - } else { - cspec.add_argument (new CCodeConstant ("0")); - } - } else if (type_id == "G_TYPE_UINT") { - cspec.call = new CCodeIdentifier ("g_param_spec_uint"); - cspec.add_argument (new CCodeConstant ("0")); - cspec.add_argument (new CCodeConstant ("G_MAXUINT")); - if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); - } else { - cspec.add_argument (new CCodeConstant ("0U")); - } - } else if (type_id == "G_TYPE_INT64") { - cspec.call = new CCodeIdentifier ("g_param_spec_int64"); - cspec.add_argument (new CCodeConstant ("G_MININT64")); - cspec.add_argument (new CCodeConstant ("G_MAXINT64")); - if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); - } else { - cspec.add_argument (new CCodeConstant ("0")); - } - } else if (type_id == "G_TYPE_UINT64") { - cspec.call = new CCodeIdentifier ("g_param_spec_uint64"); - cspec.add_argument (new CCodeConstant ("0")); - cspec.add_argument (new CCodeConstant ("G_MAXUINT64")); - if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); - } else { - cspec.add_argument (new CCodeConstant ("0U")); - } - } else if (type_id == "G_TYPE_LONG") { - cspec.call = new CCodeIdentifier ("g_param_spec_long"); - cspec.add_argument (new CCodeConstant ("G_MINLONG")); - cspec.add_argument (new CCodeConstant ("G_MAXLONG")); - if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); - } else { - cspec.add_argument (new CCodeConstant ("0L")); - } - } else if (type_id == "G_TYPE_ULONG") { - cspec.call = new CCodeIdentifier ("g_param_spec_ulong"); - cspec.add_argument (new CCodeConstant ("0")); - cspec.add_argument (new CCodeConstant ("G_MAXULONG")); - if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); - } else { - cspec.add_argument (new CCodeConstant ("0UL")); - } - } else if (type_id == "G_TYPE_BOOLEAN") { - cspec.call = new CCodeIdentifier ("g_param_spec_boolean"); - if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); - } else { - cspec.add_argument (new CCodeConstant ("FALSE")); - } - } else if (type_id == "G_TYPE_CHAR") { - cspec.call = new CCodeIdentifier ("g_param_spec_char"); - cspec.add_argument (new CCodeConstant ("G_MININT8")); - cspec.add_argument (new CCodeConstant ("G_MAXINT8")); - if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); - } else { - cspec.add_argument (new CCodeConstant ("0")); - } - } else if (type_id == "G_TYPE_UCHAR") { - cspec.call = new CCodeIdentifier ("g_param_spec_uchar"); - cspec.add_argument (new CCodeConstant ("0")); - cspec.add_argument (new CCodeConstant ("G_MAXUINT8")); - if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); - } else { - cspec.add_argument (new CCodeConstant ("0")); - } - } else if (type_id == "G_TYPE_FLOAT") { - cspec.call = new CCodeIdentifier ("g_param_spec_float"); - cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT")); - cspec.add_argument (new CCodeConstant ("G_MAXFLOAT")); - if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); - } else { - cspec.add_argument (new CCodeConstant ("0.0F")); - } - } else if (type_id == "G_TYPE_DOUBLE") { - cspec.call = new CCodeIdentifier ("g_param_spec_double"); - cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE")); - cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE")); - if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); - } else { - cspec.add_argument (new CCodeConstant ("0.0")); - } - } else if (type_id == "G_TYPE_GTYPE") { - cspec.call = new CCodeIdentifier ("g_param_spec_gtype"); - if (prop.initializer != null) { - cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer)); - } else { - cspec.add_argument (new CCodeConstant ("G_TYPE_NONE")); - } - } else { - cspec.call = new CCodeIdentifier ("g_param_spec_boxed"); - cspec.add_argument (new CCodeIdentifier (type_id)); - } - } else if (prop.property_type is ArrayType && ((ArrayType)prop.property_type).element_type.type_symbol == string_type.type_symbol) { - cspec.call = new CCodeIdentifier ("g_param_spec_boxed"); - cspec.add_argument (new CCodeIdentifier ("G_TYPE_STRV")); - } else { - cspec.call = new CCodeIdentifier ("g_param_spec_pointer"); - } - - var pflags = "G_PARAM_STATIC_STRINGS"; - if (prop.get_accessor != null && prop.get_accessor.access != SymbolAccessibility.PRIVATE) { - pflags = "%s%s".printf (pflags, " | G_PARAM_READABLE"); - } - if (prop.set_accessor != null && prop.set_accessor.access != SymbolAccessibility.PRIVATE) { - 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"); - } - } - } - if (!prop.notify) { - pflags = "%s%s".printf (pflags, " | G_PARAM_EXPLICIT_NOTIFY"); - } - if (prop.version.deprecated) { - pflags = "%s%s".printf (pflags, " | G_PARAM_DEPRECATED"); - } - cspec.add_argument (new CCodeConstant (pflags)); - - if (prop.parent_symbol is Interface) { - return cspec; - } else { - return new CCodeAssignment (get_param_spec_cexpression (prop), cspec); - } - } - - public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) { - if (add_symbol_declaration (decl_space, iface, get_ccode_name (iface))) { - return; - } - - decl_space.add_include ("glib-object.h"); - - var instance_struct = new CCodeStruct ("_%s".printf (get_ccode_name (iface))); - var type_struct = new CCodeStruct ("_%s".printf (get_ccode_type_name (iface))); - - decl_space.add_type_declaration (new CCodeNewline ()); - var macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (iface, null)); - decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (iface), macro)); - - macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (get_ccode_type_id (iface), get_ccode_name (iface)); - decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_cast_function (iface)), macro)); - - macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (get_ccode_type_id (iface)); - decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_check_function (iface)), macro)); - - macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (get_ccode_type_id (iface), get_ccode_type_name (iface)); - decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (get_ccode_type_get_function (iface)), macro)); - decl_space.add_type_declaration (new CCodeNewline ()); - - decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (get_ccode_name (iface)), new CCodeVariableDeclarator (get_ccode_name (iface)))); - decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator (get_ccode_type_name (iface)))); - - foreach (DataType prerequisite in iface.get_prerequisites ()) { - unowned Class? prereq_cl = prerequisite.type_symbol as Class; - unowned Interface? prereq_iface = prerequisite.type_symbol as Interface; - if (prereq_cl != null) { - generate_class_declaration (prereq_cl, decl_space); - } else if (prereq_iface != null) { - generate_interface_declaration (prereq_iface, decl_space); - } - } - - type_struct.add_field ("GTypeInterface", "parent_iface"); - - if (iface.get_attribute ("GenericAccessors") != null) { - foreach (TypeParameter p in iface.get_type_parameters ()) { - var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (get_ccode_type_id (p))); - var this_type = SemanticAnalyzer.get_data_type_for_symbol (iface); - vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type))); - - var vdecl = new CCodeDeclaration ("GType"); - vdecl.add_declarator (vdeclarator); - type_struct.add_declaration (vdecl); - - vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (get_ccode_copy_function (p))); - this_type = SemanticAnalyzer.get_data_type_for_symbol (iface); - vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type))); - - vdecl = new CCodeDeclaration ("GBoxedCopyFunc"); - vdecl.add_declarator (vdeclarator); - type_struct.add_declaration (vdecl); - - vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (get_ccode_destroy_function (p))); - this_type = SemanticAnalyzer.get_data_type_for_symbol (iface); - vdeclarator.add_parameter (new CCodeParameter ("self", get_ccode_name (this_type))); - - vdecl = new CCodeDeclaration ("GDestroyNotify"); - vdecl.add_declarator (vdeclarator); - type_struct.add_declaration (vdecl); - } - } - - foreach (Symbol sym in iface.get_virtuals ()) { - Method m; - Signal sig; - Property prop; - if ((m = sym as Method) != null) { - generate_struct_method_declaration (iface, m, instance_struct, type_struct, decl_space); - } else if ((sig = sym as Signal) != null) { - if (sig.default_handler != null) { - if (sig.is_virtual) { - generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct); - } else { - generate_method_declaration (sig.default_handler, cfile); - } - } - } else if ((prop = sym as Property) != null) { - generate_struct_property_declaration (iface, prop, instance_struct, type_struct, decl_space); - } else { - Report.error (sym.source_reference, "internal: Unsupported symbol"); - } - } - - decl_space.add_type_definition (type_struct); - - var type_fun = new InterfaceRegisterFunction (iface); - type_fun.init_from_type (context, in_plugin, true); - decl_space.add_type_member_declaration (type_fun.get_declaration ()); - - requires_vala_extern = true; - } - - public override void visit_interface (Interface iface) { - push_context (new EmitContext (iface)); - push_line (iface.source_reference); - - var old_signal_enum = signal_enum; - - if (get_ccode_name (iface).length < 3) { - iface.error = true; - Report.error (iface.source_reference, "Interface name `%s' is too short", get_ccode_name (iface)); - return; - } - - signal_enum = new CCodeEnum (); - - generate_interface_declaration (iface, cfile); - if (!iface.is_internal_symbol ()) { - generate_interface_declaration (iface, header_file); - } - if (!iface.is_private_symbol ()) { - generate_interface_declaration (iface, internal_header_file); - } - - iface.accept_children (this); - - if (iface.get_signals ().size > 0) { - var last_signal = "%s_NUM_SIGNALS".printf (get_ccode_upper_case_name (iface)); - signal_enum.add_value (new CCodeEnumValue (last_signal)); - cfile.add_type_declaration (signal_enum); - - var signal_array_decl = new CCodeDeclaration ("guint"); - signal_array_decl.modifiers |= CCodeModifiers.STATIC; - signal_array_decl.add_declarator (new CCodeVariableDeclarator ("%s_signals".printf (get_ccode_lower_case_name (iface)), new CCodeConstant ("{0}"), new CCodeDeclaratorSuffix.with_array (new CCodeIdentifier (last_signal)))); - cfile.add_type_declaration (signal_array_decl); - } - - add_interface_default_init_function (iface); - - if (iface.comment != null) { - cfile.add_type_member_definition (new CCodeComment (iface.comment.content)); - } - - var type_fun = new InterfaceRegisterFunction (iface); - type_fun.init_from_type (context, in_plugin, false); - cfile.add_type_member_declaration (type_fun.get_source_declaration ()); - cfile.add_type_member_definition (type_fun.get_definition ()); - - signal_enum = old_signal_enum; - - pop_line (); - pop_context (); - } - - private void add_interface_default_init_function (Interface iface) { - push_context (new EmitContext (iface)); - - var default_init = new CCodeFunction ("%s_default_init".printf (get_ccode_lower_case_name (iface, null)), "void"); - default_init.add_parameter (new CCodeParameter ("iface", "%s *".printf (get_ccode_type_name (iface)))); - default_init.add_parameter (new CCodeParameter ("iface_data", "gpointer")); - default_init.modifiers = CCodeModifiers.STATIC; - - push_function (default_init); - - if (iface.is_subtype_of (gobject_type)) { - /* create properties */ - var props = iface.get_properties (); - foreach (Property prop in props) { - if (prop.is_abstract) { - if (!context.analyzer.is_gobject_property (prop)) { - continue; - } - - if (prop.comment != null) { - ccode.add_statement (new CCodeComment (prop.comment.content)); - } - - var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_interface_install_property")); - cinst.add_argument (new CCodeIdentifier ("iface")); - cinst.add_argument (get_param_spec (prop)); - - ccode.add_expression (cinst); - } - } - } - - var ciface = new CCodeIdentifier ("iface"); - - /* connect default signal handlers */ - foreach (Signal sig in iface.get_signals ()) { - if (sig.default_handler == null || !sig.is_virtual) { - continue; - } - var cname = get_ccode_real_name (sig.default_handler); - ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (sig.default_handler)), new CCodeIdentifier (cname)); - } - - /* create signals */ - foreach (Signal sig in iface.get_signals ()) { - if (sig.comment != null) { - ccode.add_statement (new CCodeComment (sig.comment.content)); - } - ccode.add_expression (get_signal_creation (sig, iface)); - } - - // connect default implementations - foreach (Method m in iface.get_methods ()) { - if (m.is_virtual) { - var cname = get_ccode_real_name (m); - ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_vfunc_name (m)), new CCodeIdentifier (cname)); - if (m.coroutine) { - ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, get_ccode_finish_vfunc_name (m)), new CCodeIdentifier (get_ccode_finish_real_name (m))); - } - } - } - - foreach (Property prop in iface.get_properties ()) { - if (prop.is_virtual) { - if (prop.get_accessor != null) { - string cname = get_ccode_real_name (prop.get_accessor); - ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), new CCodeIdentifier (cname)); - } - if (prop.set_accessor != null) { - string cname = get_ccode_real_name (prop.set_accessor); - ccode.add_assignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), new CCodeIdentifier (cname)); - } - } - } - - pop_context (); - - cfile.add_function (default_init); - } - - public override void visit_struct (Struct st) { - // custom simple type structs cannot have a type id which depends on head-allocation - if (st.get_attribute ("SimpleType") != null && !st.has_attribute_argument ("CCode", "type_id")) { - st.set_attribute_bool ("CCode", "has_type_id", false); - } - - base.visit_struct (st); - - if (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ()) { - // Skip GType handling for these struct types, - // like in CCodeStructModule.generate_struct_declaration() - return; - } - - if (get_ccode_has_type_id (st)) { - if (get_ccode_name (st).length < 3) { - st.error = true; - Report.error (st.source_reference, "Struct name `%s' is too short", get_ccode_name (st)); - return; - } - - push_line (st.source_reference); - var type_fun = new StructRegisterFunction (st); - type_fun.init_from_type (context, false, false); - cfile.add_type_member_definition (type_fun.get_definition ()); - pop_line (); - } - } - - public override void visit_enum (Enum en) { - base.visit_enum (en); - - if (get_ccode_has_type_id (en)) { - if (get_ccode_name (en).length < 3) { - en.error = true; - Report.error (en.source_reference, "Enum name `%s' is too short", get_ccode_name (en)); - return; - } - - push_line (en.source_reference); - var type_fun = new EnumRegisterFunction (en); - type_fun.init_from_type (context, false, false); - cfile.add_type_member_definition (type_fun.get_definition ()); - pop_line (); - } - } - - public override void visit_method_call (MethodCall expr) { - var ma = expr.call as MemberAccess; - var mtype = expr.call.value_type as MethodType; - if (mtype == null || ma == null || ma.inner == null || - !(ma.inner.value_type is EnumValueType) || !get_ccode_has_type_id (ma.inner.value_type.type_symbol) || - mtype.method_symbol != ((EnumValueType) ma.inner.value_type).get_to_string_method ()) { - base.visit_method_call (expr); - return; - } - // to_string() on a gtype enum - - bool is_flags = ((Enum) ((EnumValueType) ma.inner.value_type).type_symbol).is_flags; - - push_line (expr.source_reference); - if (context.require_glib_version (2, 54)) { - var to_string = new CCodeFunctionCall (new CCodeIdentifier ((is_flags ? "g_flags_to_string" : "g_enum_to_string"))); - to_string.add_argument (new CCodeIdentifier (get_ccode_type_id (ma.inner.value_type))); - to_string.add_argument ((CCodeExpression) get_ccodenode (((MemberAccess) expr.call).inner)); - expr.value_type.value_owned = true; - set_cvalue (expr, to_string); - } else { - var temp_var = get_temp_variable (new CType (is_flags ? "GFlagsValue*" : "GEnumValue*", "NULL"), false, expr, false); - emit_temp_var (temp_var); - - var class_ref = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_ref")); - class_ref.add_argument (new CCodeIdentifier (get_ccode_type_id (ma.inner.value_type))); - var get_value = new CCodeFunctionCall (new CCodeIdentifier (is_flags ? "g_flags_get_first_value" : "g_enum_get_value")); - get_value.add_argument (class_ref); - get_value.add_argument ((CCodeExpression) get_ccodenode (((MemberAccess) expr.call).inner)); - - ccode.add_assignment (get_variable_cexpression (temp_var.name), get_value); - var is_null_value = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (temp_var.name), new CCodeConstant ("NULL")); - set_cvalue (expr, new CCodeConditionalExpression (is_null_value, new CCodeMemberAccess.pointer (get_variable_cexpression (temp_var.name), "value_name"), new CCodeConstant ("NULL"))); - } - pop_line (); - } - - public override void visit_property (Property prop) { - var cl = current_type_symbol as Class; - var st = current_type_symbol as Struct; - - var base_prop = prop; - if (prop.base_property != null) { - base_prop = prop.base_property; - } else if (prop.base_interface_property != null) { - base_prop = prop.base_interface_property; - } - - if (base_prop.get_attribute ("NoAccessorMethod") == null && - prop.name == "type" && ((cl != null && !cl.is_compact) || (st != null && get_ccode_has_type_id (st)))) { - Report.error (prop.source_reference, "Property 'type' not allowed"); - return; - } - base.visit_property (prop); - } - - public override void create_type_check_statement (CodeNode method_node, DataType ret_type, TypeSymbol t, bool non_null, string var_name) { - var ccheck = new CCodeFunctionCall (); - - if (!context.assert) { - return; - } else if (context.checking && ((t is Class && !((Class) t).is_compact) || t is Interface)) { - if (!get_ccode_has_type_id (t)) { - return; - } - - CCodeFunctionCall ctype_check; - if (t.external_package) { - ctype_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE")); - ctype_check.add_argument (new CCodeIdentifier (var_name)); - ctype_check.add_argument (new CCodeIdentifier (get_ccode_type_id (t))); - } else { - ctype_check = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_type_check_function (t))); - ctype_check.add_argument (new CCodeIdentifier (var_name)); - } - - 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 || (t is Struct && ((Struct) t).is_simple_type ())) { - return; - } else if (t == glist_type || t == gslist_type) { - // NULL is empty list - return; - } else { - var cnonnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL")); - ccheck.add_argument (cnonnull); - } - - // g_return_* needs glib.h - cfile.add_include ("glib.h"); - - var cm = method_node as CreationMethod; - if (cm != null && !cm.coroutine && cm.parent_symbol is ObjectTypeSymbol) { - ccheck.call = new CCodeIdentifier ("g_return_val_if_fail"); - ccheck.add_argument (new CCodeConstant ("NULL")); - } else if (ret_type is VoidType) { - /* void function */ - ccheck.call = new CCodeIdentifier ("g_return_if_fail"); - } else { - ccheck.call = new CCodeIdentifier ("g_return_val_if_fail"); - - var cdefault = default_value_for_type (ret_type, false); - if (cdefault != null) { - ccheck.add_argument (cdefault); - } else if (ret_type.type_symbol is Struct && !((Struct) ret_type.type_symbol).is_simple_type ()) { - ccheck.add_argument (new CCodeIdentifier ("result")); - } else { - return; - } - } - - ccode.add_expression (ccheck); - } - - public override void visit_cast_expression (CastExpression expr) { - unowned ObjectTypeSymbol? type_symbol = expr.type_reference.type_symbol as ObjectTypeSymbol; - - if (type_symbol == null || (type_symbol is Class && ((Class) type_symbol).is_compact)) { - base.visit_cast_expression (expr); - return; - } - - generate_type_declaration (expr.type_reference, cfile); - - // checked cast for strict subtypes of GTypeInstance - if (expr.is_silent_cast) { - TargetValue to_cast = expr.inner.target_value; - CCodeExpression cexpr; - if (!get_lvalue (to_cast)) { - to_cast = store_temp_value (to_cast, expr); - } - cexpr = get_cvalue_ (to_cast); - var ccheck = create_type_check (cexpr, expr.type_reference); - var ccast = new CCodeCastExpression (cexpr, get_ccode_name (expr.type_reference)); - var cnull = new CCodeConstant ("NULL"); - var cast_value = new GLibValue (expr.value_type, new CCodeConditionalExpression (ccheck, ccast, cnull)); - if (requires_destroy (expr.inner.value_type)) { - var casted = store_temp_value (cast_value, expr); - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, get_cvalue_ (casted), new CCodeConstant ("NULL"))); - ccode.add_expression (destroy_value (to_cast)); - ccode.close (); - expr.target_value = ((GLibValue) casted).copy (); - } else { - expr.target_value = cast_value; - } - } else { - set_cvalue (expr, generate_instance_cast (get_cvalue (expr.inner), expr.type_reference.type_symbol)); - } - } -} diff --git a/src/codegen/valagvaluemodule.vala b/src/codegen/valagvaluemodule.vala deleted file mode 100644 index 8b4dbbc66..000000000 --- a/src/codegen/valagvaluemodule.vala +++ /dev/null @@ -1,132 +0,0 @@ -/* valagvaluemodule.vala - * - * Copyright (C) 2019 Rico Tzschichholz - * - * 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.1 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: - * Rico Tzschichholz - */ - -public class Vala.GValueModule : GAsyncModule { - public override void visit_cast_expression (CastExpression expr) { - unowned DataType? value_type = expr.inner.value_type; - unowned DataType? target_type = expr.type_reference; - - if (expr.is_non_null_cast || value_type == null || gvalue_type == null - || value_type.type_symbol != gvalue_type || target_type.type_symbol == gvalue_type - || get_ccode_type_id (target_type) == "") { - base.visit_cast_expression (expr); - return; - } - - generate_type_declaration (expr.type_reference, cfile); - - // explicit conversion from GValue - var ccall = new CCodeFunctionCall (get_value_getter_function (target_type)); - CCodeExpression gvalue; - if (value_type.nullable) { - gvalue = get_cvalue (expr.inner); - } else { - gvalue = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue (expr.inner)); - } - ccall.add_argument (gvalue); - - if (value_type.is_disposable ()) { - var temp_var = get_temp_variable (value_type, true, expr, false); - emit_temp_var (temp_var); - var temp_ref = get_variable_cexpression (temp_var.name); - ccode.add_assignment (temp_ref, get_cvalue (expr.inner)); - - // value needs to be kept alive until the end of this block - temp_ref_values.insert (0, get_local_cvalue (temp_var)); - } - - CCodeExpression rv; - if (target_type is ArrayType) { - var temp_var = get_temp_variable (target_type, true, expr, false); - emit_temp_var (temp_var); - var temp_ref = get_variable_cexpression (temp_var.name); - ccode.add_assignment (temp_ref, ccall); - rv = temp_ref; - - // null-terminated string array - var len_call = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length")); - len_call.add_argument (rv); - append_array_length (expr, len_call); - } else if (target_type is StructValueType) { - var temp_var = get_temp_variable (new PointerType (target_type), true, expr, false); - emit_temp_var (temp_var); - var temp_ref = get_variable_cexpression (temp_var.name); - ccode.add_assignment (temp_ref, ccall); - rv = temp_ref; - - // default value to fallback to - var temp_value = create_temp_value (target_type, true, expr, true); - var ctemp = get_cvalue_ (temp_value); - - var holds = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_HOLDS")); - holds.add_argument (gvalue); - holds.add_argument (new CCodeIdentifier (get_ccode_type_id (target_type))); - var cond = new CCodeBinaryExpression (CCodeBinaryOperator.AND, holds, rv); - var warn = new CCodeFunctionCall (new CCodeIdentifier ("g_warning")); - warn.add_argument (new CCodeConstant ("\"Invalid GValue unboxing (wrong type or NULL)\"")); - var fail = new CCodeCommaExpression (); - fail.append_expression (warn); - fail.append_expression (ctemp); - rv = new CCodeConditionalExpression (cond, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, rv), fail); - } else { - rv = ccall; - } - - set_cvalue (expr, rv); - } - - public override CCodeExpression get_value_getter_function (DataType type_reference) { - var array_type = type_reference as ArrayType; - if (type_reference.type_symbol != null) { - return new CCodeIdentifier (get_ccode_get_value_function (type_reference.type_symbol)); - } else if (array_type != null && array_type.element_type.type_symbol == string_type.type_symbol) { - // G_TYPE_STRV - return new CCodeIdentifier ("g_value_get_boxed"); - } else { - return new CCodeIdentifier ("g_value_get_pointer"); - } - } - - public override CCodeExpression get_value_setter_function (DataType type_reference) { - var array_type = type_reference as ArrayType; - if (type_reference.type_symbol != null) { - return new CCodeIdentifier (get_ccode_set_value_function (type_reference.type_symbol)); - } else if (array_type != null && array_type.element_type.type_symbol == string_type.type_symbol) { - // G_TYPE_STRV - return new CCodeIdentifier ("g_value_set_boxed"); - } else { - return new CCodeIdentifier ("g_value_set_pointer"); - } - } - - public override CCodeExpression get_value_taker_function (DataType type_reference) { - var array_type = type_reference as ArrayType; - if (type_reference.type_symbol != null) { - return new CCodeIdentifier (get_ccode_take_value_function (type_reference.type_symbol)); - } else if (array_type != null && array_type.element_type.type_symbol == string_type.type_symbol) { - // G_TYPE_STRV - return new CCodeIdentifier ("g_value_take_boxed"); - } else { - return new CCodeIdentifier ("g_value_set_pointer"); - } - } -} diff --git a/src/codegen/valagvariantmodule.vala b/src/codegen/valagvariantmodule.vala deleted file mode 100644 index be13d35b9..000000000 --- a/src/codegen/valagvariantmodule.vala +++ /dev/null @@ -1,921 +0,0 @@ -/* valagvariantmodule.vala - * - * Copyright (C) 2010-2011 Jürg Billeter - * - * 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.1 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 - */ - -public class Vala.GVariantModule : GValueModule { - struct BasicTypeInfo { - public unowned string signature; - public unowned string type_name; - public bool is_string; - } - - const BasicTypeInfo[] basic_types = { - { "y", "byte", false }, - { "b", "boolean", false }, - { "n", "int16", false }, - { "q", "uint16", false }, - { "i", "int32", false }, - { "u", "uint32", false }, - { "x", "int64", false }, - { "t", "uint64", false }, - { "d", "double", false }, - { "s", "string", true }, - { "o", "object_path", true }, - { "g", "signature", true } - }; - - static bool is_string_marshalled_enum (TypeSymbol? symbol) { - if (symbol != null && symbol is Enum) { - return symbol.get_attribute_bool ("DBus", "use_string_marshalling"); - } - return false; - } - - string get_dbus_value (EnumValue value, string default_value) { - var dbus_value = value.get_attribute_string ("DBus", "value"); - if (dbus_value != null) { - return dbus_value;; - } - return default_value; - } - - public static string? get_dbus_signature (Symbol symbol) { - return symbol.get_attribute_string ("DBus", "signature"); - } - - bool get_basic_type_info (string? signature, out BasicTypeInfo basic_type) { - if (signature != null) { - foreach (BasicTypeInfo info in basic_types) { - if (info.signature == signature) { - basic_type = info; - return true; - } - } - } - basic_type = BasicTypeInfo (); - return false; - } - - public override void visit_enum (Enum en) { - base.visit_enum (en); - - if (is_string_marshalled_enum (en)) { - // strcmp - cfile.add_include ("string.h"); - - // for G_DBUS_ERROR - cfile.add_include ("gio/gio.h"); - - cfile.add_function (generate_enum_from_string_function (en)); - cfile.add_function (generate_enum_to_string_function (en)); - } - } - - public override bool generate_enum_declaration (Enum en, CCodeFile decl_space) { - if (base.generate_enum_declaration (en, decl_space)) { - if (is_string_marshalled_enum (en)) { - decl_space.add_function_declaration (generate_enum_from_string_function_declaration (en)); - decl_space.add_function_declaration (generate_enum_to_string_function_declaration (en)); - } - return true; - } - return false; - } - - int next_variant_function_id = 0; - - public override void visit_cast_expression (CastExpression expr) { - var value = expr.inner.target_value; - var target_type = expr.type_reference; - - if (expr.is_non_null_cast || value.value_type == null || gvariant_type == null || value.value_type.type_symbol != gvariant_type) { - base.visit_cast_expression (expr); - return; - } - - generate_type_declaration (expr.type_reference, cfile); - - string variant_func = "_variant_get%d".printf (++next_variant_function_id); - - var variant = value; - if (value.value_type.value_owned) { - // value leaked, destroy it - var temp_value = store_temp_value (value, expr); - temp_ref_values.insert (0, ((GLibValue) temp_value).copy ()); - variant = temp_value; - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier (variant_func)); - ccall.add_argument (get_cvalue_ (variant)); - - var needs_init = (target_type is ArrayType); - var result = create_temp_value (target_type, needs_init, expr); - - var cfunc = new CCodeFunction (variant_func); - cfunc.modifiers = CCodeModifiers.STATIC; - cfunc.add_parameter (new CCodeParameter ("value", "GVariant*")); - - if (!target_type.is_real_non_null_struct_type ()) { - cfunc.return_type = get_ccode_name (target_type); - } - - if (target_type.is_real_non_null_struct_type ()) { - // structs are returned via out parameter - cfunc.add_parameter (new CCodeParameter ("result", "%s *".printf (get_ccode_name (target_type)))); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue_ (result))); - } else if (target_type is ArrayType) { - // return array length if appropriate - // tmp = _variant_get (variant, &tmp_length); - unowned ArrayType array_type = (ArrayType) target_type; - var length_ctype = get_ccode_array_length_type (array_type); - for (int dim = 1; dim <= array_type.rank; dim++) { - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_array_length_cvalue (result, dim))); - cfunc.add_parameter (new CCodeParameter (get_array_length_cname ("result", dim), length_ctype + "*")); - } - } - - if (!target_type.is_real_non_null_struct_type ()) { - ccode.add_assignment (get_cvalue_ (result), ccall); - } else { - ccode.add_expression (ccall); - } - - push_context (new EmitContext ()); - push_function (cfunc); - - CCodeExpression type_expr = null; - BasicTypeInfo basic_type = {}; - bool is_basic_type = false; - if (expr.is_silent_cast) { - var signature = target_type.get_type_signature (); - is_basic_type = get_basic_type_info (signature, out basic_type); - var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_is_of_type")); - ccheck.add_argument (new CCodeIdentifier ("value")); - if (is_basic_type) { - type_expr = new CCodeIdentifier ("G_VARIANT_TYPE_" + basic_type.type_name.ascii_up ()); - } else { - var gvariant_type_type = new ObjectType ((Class) root_symbol.scope.lookup ("GLib").scope.lookup ("VariantType")); - var type_temp = get_temp_variable (gvariant_type_type, true, expr, true); - emit_temp_var (type_temp); - type_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_type_new")); - ((CCodeFunctionCall) type_expr).add_argument (new CCodeIdentifier ("\"%s\"".printf (signature))); - store_value (get_local_cvalue (type_temp), new GLibValue (gvariant_type_type, type_expr), expr.source_reference); - type_expr = get_variable_cexpression (type_temp.name); - } - ccheck.add_argument (type_expr); - ccode.open_if (new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("value"), ccheck)); - } - - CCodeExpression func_result = deserialize_expression (target_type, new CCodeIdentifier ("value"), new CCodeIdentifier ("*result")); - - if (expr.is_silent_cast) { - if (is_basic_type && basic_type.is_string) { - ccode.add_return (func_result); - } else { - if (!is_basic_type) { - var type_free = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_type_free")); - type_free.add_argument (type_expr); - ccode.add_expression (type_free); - } - var temp_type = expr.target_type.copy (); - if (!expr.target_type.is_real_struct_type ()) { - temp_type.nullable = false; - } - var temp_value = create_temp_value (temp_type, false, expr); - store_value (temp_value, new GLibValue (temp_type, func_result), expr.source_reference); - ccode.add_return (get_cvalue_ (transform_value (temp_value, expr.target_type, expr))); - } - ccode.add_else (); - if (!is_basic_type) { - var type_free = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_type_free")); - type_free.add_argument (type_expr); - ccode.add_expression (type_free); - } - ccode.add_return (new CCodeConstant ("NULL")); - ccode.close (); - } else if (target_type.is_real_non_null_struct_type ()) { - ccode.add_assignment (new CCodeIdentifier ("*result"), func_result); - } else { - ccode.add_return (func_result); - } - - pop_function (); - pop_context (); - - cfile.add_function_declaration (cfunc); - cfile.add_function (cfunc); - - expr.target_value = load_temp_value (result); - } - - CCodeExpression? get_array_length (CCodeExpression expr, int dim) { - var id = expr as CCodeIdentifier; - var ma = expr as CCodeMemberAccess; - if (id != null) { - return new CCodeIdentifier ("%s_length%d".printf (id.name, dim)); - } else if (ma != null) { - if (ma.is_pointer) { - return new CCodeMemberAccess.pointer (ma.inner, "%s_length%d".printf (ma.member_name, dim)); - } else { - return new CCodeMemberAccess (ma.inner, "%s_length%d".printf (ma.member_name, dim)); - } - } else { - // must be NULL-terminated - var len_call = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length")); - len_call.add_argument (expr); - return len_call; - } - } - - CCodeExpression? generate_enum_value_from_string (EnumValueType type, CCodeExpression? expr, CCodeExpression? error_expr) { - var en = type.type_symbol as Enum; - var from_string_name = "%s_from_string".printf (get_ccode_lower_case_name (en, null)); - - var from_string_call = new CCodeFunctionCall (new CCodeIdentifier (from_string_name)); - from_string_call.add_argument (expr); - from_string_call.add_argument (error_expr != null ? error_expr : new CCodeConstant ("NULL")); - - return from_string_call; - } - - public CCodeFunction generate_enum_from_string_function_declaration (Enum en) { - var from_string_name = "%s_from_string".printf (get_ccode_lower_case_name (en, null)); - - var from_string_func = new CCodeFunction (from_string_name, get_ccode_name (en)); - from_string_func.add_parameter (new CCodeParameter ("str", "const char*")); - from_string_func.add_parameter (new CCodeParameter ("error", "GError**")); - from_string_func.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - - return from_string_func; - } - - public CCodeFunction generate_enum_from_string_function (Enum en) { - var from_string_name = "%s_from_string".printf (get_ccode_lower_case_name (en, null)); - - var from_string_func = new CCodeFunction (from_string_name, get_ccode_name (en)); - from_string_func.add_parameter (new CCodeParameter ("str", "const char*")); - from_string_func.add_parameter (new CCodeParameter ("error", "GError**")); - - push_function (from_string_func); - - ccode.add_declaration (get_ccode_name (en), new CCodeVariableDeclarator.zero ("value", new CCodeConstant ("0"))); - - bool firstif = true; - foreach (EnumValue enum_value in en.get_values ()) { - string dbus_value = get_dbus_value (enum_value, enum_value.name); - var string_comparison = new CCodeFunctionCall (new CCodeIdentifier ("strcmp")); - string_comparison.add_argument (new CCodeIdentifier ("str")); - string_comparison.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_value))); - var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, string_comparison, new CCodeConstant ("0")); - if (firstif) { - ccode.open_if (cond); - firstif = false; - } else { - ccode.else_if (cond); - } - ccode.add_assignment (new CCodeIdentifier ("value"), new CCodeIdentifier (get_ccode_name (enum_value))); - } - - ccode.add_else (); - var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error")); - set_error.add_argument (new CCodeIdentifier ("error")); - set_error.add_argument (new CCodeIdentifier ("G_DBUS_ERROR")); - set_error.add_argument (new CCodeIdentifier ("G_DBUS_ERROR_INVALID_ARGS")); - set_error.add_argument (new CCodeConstant ("\"Invalid value for enum `%s'\"".printf (get_ccode_name (en)))); - ccode.add_expression (set_error); - ccode.close (); - - ccode.add_return (new CCodeIdentifier ("value")); - - pop_function (); - return from_string_func; - } - - CCodeExpression deserialize_basic (BasicTypeInfo basic_type, CCodeExpression variant_expr, bool transfer = false) { - var get_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_" + basic_type.type_name)); - get_call.add_argument (variant_expr); - - if (basic_type.is_string) { - if (transfer) { - get_call.call = new CCodeIdentifier ("g_variant_get_string"); - } else { - get_call.call = new CCodeIdentifier ("g_variant_dup_string"); - } - get_call.add_argument (new CCodeConstant ("NULL")); - } - - return get_call; - } - - CCodeExpression deserialize_array (ArrayType array_type, CCodeExpression variant_expr, CCodeExpression? expr) { - if (array_type.rank == 1 && array_type.get_type_signature () == "ay") { - return deserialize_buffer_array (array_type, variant_expr, expr); - } - - string temp_name = "_tmp%d_".printf (next_temp_var_id++); - - var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new")); - new_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - // add one extra element for NULL-termination - new_call.add_argument (new CCodeConstant ("5")); - - var length_ctype = get_ccode_array_length_type (array_type); - ccode.add_declaration (get_ccode_name (array_type), new CCodeVariableDeclarator (temp_name, new_call)); - ccode.add_declaration (length_ctype, new CCodeVariableDeclarator (temp_name + "_length", new CCodeConstant ("0"))); - ccode.add_declaration (length_ctype, new CCodeVariableDeclarator (temp_name + "_size", new CCodeConstant ("4"))); - - deserialize_array_dim (array_type, 1, temp_name, variant_expr, expr); - - if (array_type.element_type.is_reference_type_or_type_parameter ()) { - // NULL terminate array - var length = new CCodeIdentifier (temp_name + "_length"); - var element_access = new CCodeElementAccess (new CCodeIdentifier (temp_name), length); - ccode.add_assignment (element_access, new CCodeConstant ("NULL")); - } - - return new CCodeIdentifier (temp_name); - } - - void deserialize_array_dim (ArrayType array_type, int dim, string temp_name, CCodeExpression variant_expr, CCodeExpression? expr) { - string subiter_name = "_tmp%d_".printf (next_temp_var_id++); - string element_name = "_tmp%d_".printf (next_temp_var_id++); - - ccode.add_declaration (get_ccode_array_length_type (array_type), new CCodeVariableDeclarator ("%s_length%d".printf (temp_name, dim), new CCodeConstant ("0"))); - ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator (subiter_name)); - ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator (element_name)); - - var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init")); - iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name))); - iter_call.add_argument (variant_expr); - ccode.add_expression (iter_call); - - iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_next_value")); - iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name))); - - var cforcond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeAssignment (new CCodeIdentifier (element_name), iter_call), new CCodeConstant ("NULL")); - var cforiter = new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("%s_length%d".printf (temp_name, dim))); - ccode.open_for (null, cforcond, cforiter); - - if (dim < array_type.rank) { - deserialize_array_dim (array_type, dim + 1, temp_name, new CCodeIdentifier (element_name), expr); - } else { - var size_check = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (temp_name + "_size"), new CCodeIdentifier (temp_name + "_length")); - - ccode.open_if (size_check); - - // tmp_size = (2 * tmp_size); - var new_size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("2"), new CCodeIdentifier (temp_name + "_size")); - ccode.add_assignment (new CCodeIdentifier (temp_name + "_size"), new_size); - - var renew_call = new CCodeFunctionCall (new CCodeIdentifier ("g_renew")); - renew_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type))); - renew_call.add_argument (new CCodeIdentifier (temp_name)); - // add one extra element for NULL-termination - renew_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (temp_name + "_size"), new CCodeConstant ("1"))); - ccode.add_assignment (new CCodeIdentifier (temp_name), renew_call); - - ccode.close (); - - var element_access = new CCodeElementAccess (new CCodeIdentifier (temp_name), new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier (temp_name + "_length"))); - var element_expr = deserialize_expression (array_type.element_type, new CCodeIdentifier (element_name), null); - ccode.add_assignment (element_access, element_expr); - } - - var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref")); - unref.add_argument (new CCodeIdentifier (element_name)); - ccode.add_expression (unref); - - ccode.close (); - - if (expr != null) { - ccode.add_assignment (get_array_length (expr, dim), new CCodeIdentifier ("%s_length%d".printf (temp_name, dim))); - } - } - - CCodeExpression deserialize_buffer_array (ArrayType array_type, CCodeExpression variant_expr, CCodeExpression? expr) { - string temp_name = "_tmp%d_".printf (next_temp_var_id++); - - var get_data_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_data")); - get_data_call.add_argument (variant_expr); - - var get_size_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_size")); - get_size_call.add_argument (variant_expr); - ccode.add_declaration ("gsize", new CCodeVariableDeclarator (temp_name + "_length", get_size_call)); - var length = new CCodeIdentifier (temp_name + "_length"); - - CCodeFunctionCall dup_call; - if (context.require_glib_version (2, 68)) { - dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup2")); - } else { - requires_memdup2 = true; - dup_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_memdup2")); - } - dup_call.add_argument (get_data_call); - dup_call.add_argument (length); - - ccode.add_declaration (get_ccode_name (array_type), new CCodeVariableDeclarator (temp_name, dup_call)); - if (expr != null) { - ccode.add_assignment (get_array_length (expr, 1), length); - } - - return new CCodeIdentifier (temp_name); - } - - CCodeExpression? deserialize_struct (Struct st, CCodeExpression variant_expr) { - string temp_name = "_tmp%d_".printf (next_temp_var_id++); - string subiter_name = "_tmp%d_".printf (next_temp_var_id++); - - ccode.add_declaration (get_ccode_name (st), new CCodeVariableDeclarator (temp_name)); - ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator (subiter_name)); - - var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init")); - iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name))); - iter_call.add_argument (variant_expr); - ccode.add_expression (iter_call); - - bool field_found = false;; - - foreach (Field f in st.get_fields ()) { - if (f.binding != MemberBinding.INSTANCE) { - continue; - } - - field_found = true; - - read_expression (f.variable_type, new CCodeIdentifier (subiter_name), new CCodeMemberAccess (new CCodeIdentifier (temp_name), get_ccode_name (f)), f); - } - - if (!field_found) { - return null; - } - - return new CCodeIdentifier (temp_name); - } - - CCodeExpression? deserialize_hash_table (ObjectType type, CCodeExpression variant_expr) { - string temp_name = "_tmp%d_".printf (next_temp_var_id++); - string subiter_name = "_tmp%d_".printf (next_temp_var_id++); - string key_name = "_tmp%d_".printf (next_temp_var_id++); - string value_name = "_tmp%d_".printf (next_temp_var_id++); - - var type_args = type.get_type_arguments (); - if (type_args.size != 2) { - Report.error (type.source_reference, "Missing type-arguments for GVariant deserialization of `%s'", type.type_symbol.get_full_name ()); - return new CCodeInvalidExpression (); - } - var key_type = type_args.get (0); - var value_type = type_args.get (1); - - ccode.add_declaration ("GHashTable*", new CCodeVariableDeclarator (temp_name)); - ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator (subiter_name)); - ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator (key_name)); - ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator (value_name)); - - var hash_table_new = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_new_full")); - if (key_type.type_symbol.is_subtype_of (string_type.type_symbol)) { - hash_table_new.add_argument (new CCodeIdentifier ("g_str_hash")); - hash_table_new.add_argument (new CCodeIdentifier ("g_str_equal")); - } else if (key_type.type_symbol == gvariant_type) { - hash_table_new.add_argument (new CCodeIdentifier ("g_variant_hash")); - hash_table_new.add_argument (new CCodeIdentifier ("g_variant_equal")); - } else { - hash_table_new.add_argument (new CCodeIdentifier ("g_direct_hash")); - hash_table_new.add_argument (new CCodeIdentifier ("g_direct_equal")); - } - - if (key_type.type_symbol.is_subtype_of (string_type.type_symbol)) { - hash_table_new.add_argument (new CCodeIdentifier ("g_free")); - } else if (key_type.type_symbol == gvariant_type) { - hash_table_new.add_argument (new CCodeCastExpression (new CCodeIdentifier ("g_variant_unref"), "GDestroyNotify")); - } else if (key_type.type_symbol.get_full_name () == "GLib.HashTable") { - hash_table_new.add_argument (new CCodeCastExpression (new CCodeIdentifier ("g_hash_table_unref"), "GDestroyNotify")); - } else { - hash_table_new.add_argument (new CCodeConstant ("NULL")); - } - - if (value_type.type_symbol.is_subtype_of (string_type.type_symbol)) { - hash_table_new.add_argument (new CCodeIdentifier ("g_free")); - } else if (value_type.type_symbol == gvariant_type) { - hash_table_new.add_argument (new CCodeCastExpression (new CCodeIdentifier ("g_variant_unref"), "GDestroyNotify")); - } else if (value_type.type_symbol.get_full_name () == "GLib.HashTable") { - hash_table_new.add_argument (new CCodeCastExpression (new CCodeIdentifier ("g_hash_table_unref"), "GDestroyNotify")); - } else { - hash_table_new.add_argument (new CCodeConstant ("NULL")); - } - ccode.add_assignment (new CCodeIdentifier (temp_name), hash_table_new); - - var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init")); - iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name))); - iter_call.add_argument (variant_expr); - ccode.add_expression (iter_call); - - iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_loop")); - iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name))); - iter_call.add_argument (new CCodeConstant ("\"{?*}\"")); - iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (key_name))); - iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (value_name))); - - ccode.open_while (iter_call); - - var key_expr = deserialize_expression (key_type, new CCodeIdentifier (key_name), null); - var value_expr = deserialize_expression (value_type, new CCodeIdentifier (value_name), null); - if (key_expr == null || value_expr == null) { - return null; - } - - var hash_table_insert = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_insert")); - hash_table_insert.add_argument (new CCodeIdentifier (temp_name)); - hash_table_insert.add_argument (convert_to_generic_pointer (key_expr, key_type)); - hash_table_insert.add_argument (convert_to_generic_pointer (value_expr, value_type)); - ccode.add_expression (hash_table_insert); - - ccode.close (); - - return new CCodeIdentifier (temp_name); - } - - public override CCodeExpression? deserialize_expression (DataType type, CCodeExpression variant_expr, CCodeExpression? expr, CCodeExpression? error_expr = null, out bool may_fail = null) { - BasicTypeInfo basic_type; - CCodeExpression result = null; - may_fail = false; - if (is_string_marshalled_enum (type.type_symbol)) { - get_basic_type_info ("s", out basic_type); - result = deserialize_basic (basic_type, variant_expr, true); - result = generate_enum_value_from_string (type as EnumValueType, result, error_expr); - may_fail = true; - } else if (get_basic_type_info (type.get_type_signature (), out basic_type)) { - result = deserialize_basic (basic_type, variant_expr); - } else if (type is ArrayType) { - result = deserialize_array ((ArrayType) type, variant_expr, expr); - } else if (type.type_symbol is Struct) { - unowned Struct st = (Struct) type.type_symbol; - result = deserialize_struct (st, variant_expr); - if (result != null && type.nullable) { - var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof")); - csizeof.add_argument (new CCodeIdentifier (get_ccode_name (st))); - CCodeFunctionCall cdup; - if (context.require_glib_version (2, 68)) { - cdup = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup2")); - } else { - requires_memdup2 = true; - cdup = new CCodeFunctionCall (new CCodeIdentifier ("_vala_memdup2")); - } - cdup.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, result)); - cdup.add_argument (csizeof); - result = cdup; - } - } else if (type is ObjectType) { - if (type.type_symbol.get_full_name () == "GLib.Variant") { - var variant_get = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_variant")); - variant_get.add_argument (variant_expr); - result = variant_get; - } else if (type.type_symbol.get_full_name () == "GLib.HashTable") { - result = deserialize_hash_table ((ObjectType) type, variant_expr); - } - } - - if (result == null) { - Report.error (type.source_reference, "GVariant deserialization of type `%s' is not supported", type.to_string ()); - return new CCodeInvalidExpression (); - } - - return result; - } - - public void read_expression (DataType type, CCodeExpression iter_expr, CCodeExpression target_expr, Symbol? sym, CCodeExpression? error_expr = null, out bool may_fail = null) { - var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_next_value")); - iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, iter_expr)); - - if (sym != null && get_dbus_signature (sym) != null) { - // raw GVariant - ccode.add_assignment (target_expr, iter_call); - may_fail = false; - return; - } - - string temp_name = "_tmp%d_".printf (next_temp_var_id++); - - ccode.add_declaration ("GVariant*", new CCodeVariableDeclarator (temp_name)); - - var variant_expr = new CCodeIdentifier (temp_name); - - ccode.add_assignment (variant_expr, iter_call); - - var result = deserialize_expression (type, variant_expr, target_expr, error_expr, out may_fail); - if (result == null) { - // error already reported - return; - } - - ccode.add_assignment (target_expr, result); - - var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref")); - unref.add_argument (variant_expr); - ccode.add_expression (unref); - } - - CCodeExpression? generate_enum_value_to_string (EnumValueType type, CCodeExpression? expr) { - var en = type.type_symbol as Enum; - var to_string_name = "%s_to_string".printf (get_ccode_lower_case_name (en, null)); - - var to_string_call = new CCodeFunctionCall (new CCodeIdentifier (to_string_name)); - to_string_call.add_argument (expr); - - return to_string_call; - } - - public CCodeFunction generate_enum_to_string_function_declaration (Enum en) { - var to_string_name = "%s_to_string".printf (get_ccode_lower_case_name (en, null)); - - var to_string_func = new CCodeFunction (to_string_name, "const char*"); - to_string_func.add_parameter (new CCodeParameter ("value", get_ccode_name (en))); - to_string_func.modifiers |= CCodeModifiers.EXTERN; - requires_vala_extern = true; - - return to_string_func; - } - - public CCodeFunction generate_enum_to_string_function (Enum en) { - var to_string_name = "%s_to_string".printf (get_ccode_lower_case_name (en, null)); - - var to_string_func = new CCodeFunction (to_string_name, "const char*"); - to_string_func.add_parameter (new CCodeParameter ("value", get_ccode_name (en))); - - push_function (to_string_func); - - ccode.add_declaration ("const char *", new CCodeVariableDeclarator ("str")); - - ccode.open_switch (new CCodeIdentifier ("value")); - foreach (EnumValue enum_value in en.get_values ()) { - string dbus_value = get_dbus_value (enum_value, enum_value.name); - ccode.add_case (new CCodeIdentifier (get_ccode_name (enum_value))); - ccode.add_assignment (new CCodeIdentifier ("str"), new CCodeConstant ("\"%s\"".printf (dbus_value))); - ccode.add_break (); - } - - ccode.close(); - - ccode.add_return (new CCodeIdentifier ("str")); - - pop_function (); - return to_string_func; - } - - CCodeExpression? serialize_basic (BasicTypeInfo basic_type, CCodeExpression expr) { - var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_new_" + basic_type.type_name)); - new_call.add_argument (expr); - return new_call; - } - - CCodeExpression? serialize_array (ArrayType array_type, CCodeExpression array_expr) { - if (array_type.rank == 1 && array_type.get_type_signature () == "ay") { - return serialize_buffer_array (array_type, array_expr); - } - - string array_iter_name = "_tmp%d_".printf (next_temp_var_id++); - - ccode.add_declaration (get_ccode_name (array_type), new CCodeVariableDeclarator (array_iter_name)); - ccode.add_assignment (new CCodeIdentifier (array_iter_name), array_expr); - - return serialize_array_dim (array_type, 1, array_expr, new CCodeIdentifier (array_iter_name)); - } - - CCodeExpression? serialize_array_dim (ArrayType array_type, int dim, CCodeExpression array_expr, CCodeExpression array_iter_expr) { - string builder_name = "_tmp%d_".printf (next_temp_var_id++); - string index_name = "_tmp%d_".printf (next_temp_var_id++); - - ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator (builder_name)); - ccode.add_declaration (get_ccode_array_length_type (array_type), new CCodeVariableDeclarator (index_name)); - - var gvariant_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VARIANT_TYPE")); - ArrayType array_type_copy = (ArrayType) array_type.copy (); - array_type_copy.rank -= dim - 1; - gvariant_type.add_argument (new CCodeConstant ("\"%s\"".printf (array_type_copy.get_type_signature ()))); - - var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init")); - builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name))); - builder_init.add_argument (gvariant_type); - ccode.add_expression (builder_init); - - var cforinit = new CCodeAssignment (new CCodeIdentifier (index_name), new CCodeConstant ("0")); - var cforcond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (index_name), get_array_length (array_expr, dim)); - var cforiter = new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier (index_name)); - ccode.open_for (cforinit, cforcond, cforiter); - - CCodeExpression element_variant; - if (dim < array_type.rank) { - element_variant = serialize_array_dim (array_type, dim + 1, array_expr, array_iter_expr); - } else { - var element_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, array_iter_expr); - element_variant = serialize_expression (array_type.element_type, element_expr); - } - - var builder_add = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_add_value")); - builder_add.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name))); - builder_add.add_argument (element_variant); - ccode.add_expression (builder_add); - - if (dim == array_type.rank) { - var array_iter_incr = new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, array_iter_expr); - ccode.add_expression (array_iter_incr); - } - - ccode.close (); - - var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end")); - builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name))); - return builder_end; - } - - CCodeExpression serialize_buffer_array (ArrayType array_type, CCodeExpression array_expr) { - string buffer_name = "_tmp%d_".printf (next_temp_var_id++); - - var gvariant_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VARIANT_TYPE")); - gvariant_type.add_argument (new CCodeConstant ("\"%s\"".printf (array_type.get_type_signature ()))); - - CCodeFunctionCall dup_call; - if (context.require_glib_version (2, 68)) { - dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup2")); - } else { - requires_memdup2 = true; - dup_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_memdup2")); - } - dup_call.add_argument (array_expr); - dup_call.add_argument (get_array_length (array_expr, 1)); - ccode.add_declaration (get_ccode_name (array_type), new CCodeVariableDeclarator (buffer_name, dup_call)); - - var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_new_from_data")); - new_call.add_argument (gvariant_type); - new_call.add_argument (new CCodeIdentifier (buffer_name)); - new_call.add_argument (get_array_length (array_expr, 1)); - new_call.add_argument (new CCodeConstant ("TRUE")); - new_call.add_argument (new CCodeIdentifier ("g_free")); - new_call.add_argument (new CCodeIdentifier (buffer_name)); - - return new_call; - } - - CCodeExpression? serialize_struct (Struct st, CCodeExpression struct_expr) { - string builder_name = "_tmp%d_".printf (next_temp_var_id++); - - ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator (builder_name)); - - var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init")); - iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name))); - iter_call.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE")); - ccode.add_expression (iter_call); - - bool field_found = false;; - - foreach (Field f in st.get_fields ()) { - if (f.binding != MemberBinding.INSTANCE) { - continue; - } - - field_found = true; - - write_expression (f.variable_type, new CCodeIdentifier (builder_name), new CCodeMemberAccess (struct_expr, get_ccode_name (f)), f); - } - - if (!field_found) { - return null; - } - - var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end")); - builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (builder_name))); - return builder_end; - } - - CCodeExpression? serialize_hash_table (ObjectType type, CCodeExpression hash_table_expr) { - string subiter_name = "_tmp%d_".printf (next_temp_var_id++); - string tableiter_name = "_tmp%d_".printf (next_temp_var_id++); - string key_name = "_tmp%d_".printf (next_temp_var_id++); - string value_name = "_tmp%d_".printf (next_temp_var_id++); - - var type_args = type.get_type_arguments (); - if (type_args.size != 2) { - Report.error (type.source_reference, "Missing type-arguments for GVariant serialization of `%s'", type.type_symbol.get_full_name ()); - return new CCodeInvalidExpression (); - } - var key_type = type_args.get (0); - var value_type = type_args.get (1); - - ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator (subiter_name)); - ccode.add_declaration ("GHashTableIter", new CCodeVariableDeclarator (tableiter_name)); - ccode.add_declaration ("gpointer", new CCodeVariableDeclarator (key_name)); - ccode.add_declaration ("gpointer", new CCodeVariableDeclarator (value_name)); - - var iter_init_call = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_iter_init")); - iter_init_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (tableiter_name))); - iter_init_call.add_argument (hash_table_expr); - ccode.add_expression (iter_init_call); - - var gvariant_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VARIANT_TYPE")); - gvariant_type.add_argument (new CCodeConstant ("\"%s\"".printf (type.get_type_signature ()))); - - var iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init")); - iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name))); - iter_call.add_argument (gvariant_type); - ccode.add_expression (iter_call); - - var iter_next_call = new CCodeFunctionCall (new CCodeIdentifier ("g_hash_table_iter_next")); - iter_next_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (tableiter_name))); - iter_next_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (key_name))); - iter_next_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (value_name))); - - ccode.open_while (iter_next_call); - - ccode.add_declaration (get_ccode_name (key_type), new CCodeVariableDeclarator ("_key")); - ccode.add_declaration (get_ccode_name (value_type), new CCodeVariableDeclarator ("_value")); - - ccode.add_assignment (new CCodeIdentifier ("_key"), convert_from_generic_pointer (new CCodeIdentifier (key_name), key_type)); - ccode.add_assignment (new CCodeIdentifier ("_value"), convert_from_generic_pointer (new CCodeIdentifier (value_name), value_type)); - - var serialized_key = serialize_expression (key_type, new CCodeIdentifier ("_key")); - var serialized_value = serialize_expression (value_type, new CCodeIdentifier ("_value")); - if (serialized_key == null || serialized_value == null) { - return null; - } - - iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_add")); - iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name))); - iter_call.add_argument (new CCodeConstant ("\"{?*}\"")); - iter_call.add_argument (serialized_key); - iter_call.add_argument (serialized_value); - ccode.add_expression (iter_call); - - ccode.close (); - - iter_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end")); - iter_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (subiter_name))); - return iter_call; - } - - public override CCodeExpression? serialize_expression (DataType type, CCodeExpression expr) { - BasicTypeInfo basic_type; - CCodeExpression result = null; - if (is_string_marshalled_enum (type.type_symbol)) { - get_basic_type_info ("s", out basic_type); - result = generate_enum_value_to_string (type as EnumValueType, expr); - result = serialize_basic (basic_type, result); - } else if (get_basic_type_info (type.get_type_signature (), out basic_type)) { - result = serialize_basic (basic_type, expr); - } else if (type is ArrayType) { - result = serialize_array ((ArrayType) type, expr); - } else if (type.type_symbol is Struct) { - var st_expr = expr; - if (type.nullable) { - st_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, st_expr); - } - result = serialize_struct ((Struct) type.type_symbol, st_expr); - } else if (type is ObjectType) { - if (type.type_symbol.get_full_name () == "GLib.Variant") { - var variant_new = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_new_variant")); - variant_new.add_argument (expr); - result = variant_new; - } else if (type.type_symbol.get_full_name () == "GLib.HashTable") { - result = serialize_hash_table ((ObjectType) type, expr); - } - } - - if (result == null) { - Report.error (type.source_reference, "GVariant serialization of type `%s' is not supported", type.to_string ()); - return new CCodeInvalidExpression (); - } - - return result; - } - - public void write_expression (DataType type, CCodeExpression builder_expr, CCodeExpression expr, Symbol? sym) { - var variant_expr = expr; - if (sym == null || get_dbus_signature (sym) == null) { - // perform boxing - variant_expr = serialize_expression (type, expr); - } - if (variant_expr != null) { - var builder_add = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_add_value")); - builder_add.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, builder_expr)); - builder_add.add_argument (variant_expr); - ccode.add_expression (builder_add); - } - } -} diff --git a/src/codegen/valainterfaceregisterfunction.vala b/src/codegen/valainterfaceregisterfunction.vala deleted file mode 100644 index 3a35f995c..000000000 --- a/src/codegen/valainterfaceregisterfunction.vala +++ /dev/null @@ -1,94 +0,0 @@ -/* valainterfaceregisterfunction.vala - * - * Copyright (C) 2006-2011 Jürg Billeter - * Copyright (C) 2006-2007 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.1 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 - * Raffaele Sandrini - */ - -using GLib; - -/** - * C function to register an interface at runtime. - */ -public class Vala.InterfaceRegisterFunction : TypeRegisterFunction { - /** - * Specifies the interface to be registered. - */ - public weak Interface interface_reference { get; set; } - - public InterfaceRegisterFunction (Interface iface) { - interface_reference = iface; - } - - public override TypeSymbol get_type_declaration () { - return interface_reference; - } - - public override string get_type_struct_name () { - return get_ccode_type_name (interface_reference); - } - - public override string get_base_init_func_name () { - return "NULL"; - } - - public override string get_class_finalize_func_name () { - return "NULL"; - } - - public override string get_base_finalize_func_name () { - return "NULL"; - } - - public override string get_class_init_func_name () { - return "%s_default_init".printf (get_ccode_lower_case_name (interface_reference)); - } - - public override string get_instance_struct_size () { - return "0"; - } - - public override string get_instance_init_func_name () { - return "NULL"; - } - - public override string get_parent_type_name () { - return "G_TYPE_INTERFACE"; - } - - public override SymbolAccessibility get_accessibility () { - return interface_reference.access; - } - - public override void get_type_interface_init_statements (CodeContext context, CCodeBlock block, bool plugin) { - /* register all prerequisites */ - foreach (DataType prereq_ref in interface_reference.get_prerequisites ()) { - unowned TypeSymbol prereq = prereq_ref.type_symbol; - - var func = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_add_prerequisite")); - func.add_argument (new CCodeIdentifier ("%s_type_id".printf (get_ccode_lower_case_name (interface_reference)))); - func.add_argument (new CCodeIdentifier (get_ccode_type_id (prereq))); - - block.add_statement (new CCodeExpressionStatement (func)); - } - - ((CCodeBaseModule) context.codegen).register_dbus_info (block, interface_reference); - } -} diff --git a/src/codegen/valastructregisterfunction.vala b/src/codegen/valastructregisterfunction.vala deleted file mode 100644 index c210f8631..000000000 --- a/src/codegen/valastructregisterfunction.vala +++ /dev/null @@ -1,51 +0,0 @@ -/* valastructregisterfunction.vala - * - * Copyright (C) 2008 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * C function to register a struct at runtime. - */ -public class Vala.StructRegisterFunction : TypeRegisterFunction { - /** - * Specifies the struct to be registered. - */ - public weak Struct struct_reference { get; set; } - - /** - * Creates a new C function to register the specified struct at runtime. - * - * @param st a struct - * @return newly created struct register function - */ - public StructRegisterFunction (Struct st) { - struct_reference = st; - } - - public override TypeSymbol get_type_declaration () { - return struct_reference; - } - - public override SymbolAccessibility get_accessibility () { - return struct_reference.access; - } -} diff --git a/src/codegen/valatyperegisterfunction.vala b/src/codegen/valatyperegisterfunction.vala deleted file mode 100644 index a3236b94c..000000000 --- a/src/codegen/valatyperegisterfunction.vala +++ /dev/null @@ -1,465 +0,0 @@ -/* valatyperegisterfunction.vala - * - * Copyright (C) 2006-2010 Jürg Billeter - * - * 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.1 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 - */ - -using GLib; - -/** - * C function to register a type at runtime. - */ -public abstract class Vala.TypeRegisterFunction { - CCodeFragment source_declaration_fragment = new CCodeFragment (); - CCodeFragment declaration_fragment = new CCodeFragment (); - CCodeFragment definition_fragment = new CCodeFragment (); - - /** - * Constructs the C function from the specified type. - */ - public void init_from_type (CodeContext context, bool plugin, bool declaration_only) { - var type_symbol = get_type_declaration (); - - bool fundamental = false; - unowned Class? cl = type_symbol as Class; - if (cl != null && !cl.is_compact && cl.base_class == null) { - fundamental = true; - } - - string type_id_name = "%s_type_id".printf (get_ccode_lower_case_name (type_symbol)); - - var type_block = new CCodeBlock (); - var type_once_block = new CCodeBlock (); - CCodeDeclaration cdecl; - if (!plugin) { - cdecl = new CCodeDeclaration ("gsize"); - cdecl.add_declarator (new CCodeVariableDeclarator (type_id_name + "__once", new CCodeConstant ("0"))); - if (context.require_glib_version (2, 68)) { - cdecl.modifiers = CCodeModifiers.STATIC; - } else { - cdecl.modifiers = CCodeModifiers.STATIC | CCodeModifiers.VOLATILE; - } - type_block.add_statement (cdecl); - } else { - cdecl = new CCodeDeclaration ("GType"); - cdecl.add_declarator (new CCodeVariableDeclarator (type_id_name, new CCodeConstant ("0"))); - cdecl.modifiers = CCodeModifiers.STATIC; - source_declaration_fragment.append (cdecl); - } - - CCodeFunction fun; - CCodeFunction fun_once = null; - if (!plugin) { - fun = new CCodeFunction (get_ccode_type_function (type_symbol), "GType"); - fun.modifiers = CCodeModifiers.CONST; - - /* Function will not be prototyped anyway */ - if (get_accessibility () == SymbolAccessibility.PRIVATE) { - // avoid C warning as this function is not always used - fun.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.UNUSED; - } else if (context.hide_internal && get_accessibility () == SymbolAccessibility.INTERNAL) { - // avoid C warning as this function is not always used - fun.modifiers |= CCodeModifiers.INTERNAL | CCodeModifiers.UNUSED; - } else { - fun.modifiers |= CCodeModifiers.EXTERN; - } - - fun.is_declaration = true; - declaration_fragment.append (fun.copy ()); - fun.is_declaration = false; - - fun_once = new CCodeFunction ("%s_once".printf (fun.name), "GType"); - fun_once.modifiers = CCodeModifiers.STATIC; - if (context.require_glib_version (2, 58)) { - fun_once.modifiers |= CCodeModifiers.NO_INLINE; - } - - fun_once.is_declaration = true; - source_declaration_fragment.append (fun_once.copy ()); - fun_once.is_declaration = false; - } else { - fun = new CCodeFunction ("%s_register_type".printf (get_ccode_lower_case_name (type_symbol)), "GType"); - fun.add_parameter (new CCodeParameter ("module", "GTypeModule *")); - - fun.is_declaration = true; - declaration_fragment.append (fun.copy ()); - fun.is_declaration = false; - - var get_fun = new CCodeFunction (get_ccode_type_function (type_symbol), "GType"); - get_fun.modifiers = CCodeModifiers.CONST | CCodeModifiers.EXTERN; - - get_fun.is_declaration = true; - declaration_fragment.append (get_fun.copy ()); - get_fun.is_declaration = false; - - get_fun.block = new CCodeBlock (); - get_fun.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name))); - - definition_fragment.append (get_fun); - } - - string type_value_table_decl_name = null; - var type_init = new CCodeBlock (); - - if (fundamental) { - var cgtypetabledecl = new CCodeDeclaration ("const GTypeValueTable"); - cgtypetabledecl.modifiers = CCodeModifiers.STATIC; - - cgtypetabledecl.add_declarator (new CCodeVariableDeclarator ( "g_define_type_value_table", new CCodeConstant ("{ %s, %s, %s, %s, \"p\", %s, \"p\", %s }".printf (get_gtype_value_table_init_function_name (), get_gtype_value_table_free_function_name (), get_gtype_value_table_copy_function_name (), get_gtype_value_table_peek_pointer_function_name (), get_gtype_value_table_collect_value_function_name (), get_gtype_value_table_lcopy_value_function_name ())))); - type_value_table_decl_name = "&g_define_type_value_table"; - type_init.add_statement ( cgtypetabledecl ); - } - else { - type_value_table_decl_name = "NULL"; - } - - - if (type_symbol is ObjectTypeSymbol) { - var ctypedecl = new CCodeDeclaration ("const GTypeInfo"); - ctypedecl.modifiers = CCodeModifiers.STATIC; - ctypedecl.add_declarator (new CCodeVariableDeclarator ("g_define_type_info", new CCodeConstant ("{ sizeof (%s), (GBaseInitFunc) %s, (GBaseFinalizeFunc) %s, (GClassInitFunc) %s, (GClassFinalizeFunc) %s, NULL, %s, 0, (GInstanceInitFunc) %s, %s }".printf (get_type_struct_name (), get_base_init_func_name (), (plugin) ? get_base_finalize_func_name () : "NULL", get_class_init_func_name (), get_class_finalize_func_name (), get_instance_struct_size (), get_instance_init_func_name (), type_value_table_decl_name)))); - type_init.add_statement (ctypedecl); - if (fundamental) { - var ctypefundamentaldecl = new CCodeDeclaration ("const GTypeFundamentalInfo"); - ctypefundamentaldecl.modifiers = CCodeModifiers.STATIC; - ctypefundamentaldecl.add_declarator (new CCodeVariableDeclarator ("g_define_type_fundamental_info", new CCodeConstant ("{ (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }"))); - type_init.add_statement (ctypefundamentaldecl); - } - } - - type_init.add_statement (get_type_interface_init_declaration ()); - - CCodeFunctionCall reg_call; - if (type_symbol is Struct) { - reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_boxed_type_register_static")); - } else if (type_symbol is Enum) { - unowned Enum en = (Enum) type_symbol; - if (en.is_flags) { - reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_flags_register_static")); - } else { - reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_enum_register_static")); - } - } else if (fundamental) { - reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_register_fundamental")); - reg_call.add_argument (new CCodeFunctionCall (new CCodeIdentifier ("g_type_fundamental_next"))); - } else if (!plugin) { - reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_register_static")); - reg_call.add_argument (new CCodeIdentifier (get_parent_type_name ())); - } else { - reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_module_register_type")); - reg_call.add_argument (new CCodeIdentifier ("module")); - reg_call.add_argument (new CCodeIdentifier (get_parent_type_name ())); - } - reg_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_ccode_name (type_symbol)))); - if (type_symbol is Struct) { - var st = (Struct) type_symbol; - reg_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (get_ccode_dup_function (st)), "GBoxedCopyFunc")); - reg_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (get_ccode_free_function (st)), "GBoxedFreeFunc")); - } else if (type_symbol is Enum) { - unowned Enum en = (Enum) type_symbol; - var clist = new CCodeInitializerList (); /* or during visit time? */ - - CCodeInitializerList clist_ev = null; - foreach (EnumValue ev in en.get_values ()) { - clist_ev = new CCodeInitializerList (); - clist_ev.append (new CCodeConstant (get_ccode_name (ev))); - clist_ev.append (new CCodeConstant ("\"%s\"".printf (get_ccode_name (ev)))); - clist_ev.append (new CCodeConstant ("\"%s\"".printf (ev.nick))); - clist.append (clist_ev); - } - - clist_ev = new CCodeInitializerList (); - clist_ev.append (new CCodeConstant ("0")); - clist_ev.append (new CCodeConstant ("NULL")); - clist_ev.append (new CCodeConstant ("NULL")); - clist.append (clist_ev); - - var enum_decl = new CCodeVariableDeclarator ("values[]", clist); - - if (en.is_flags) { - cdecl = new CCodeDeclaration ("const GFlagsValue"); - } else { - cdecl = new CCodeDeclaration ("const GEnumValue"); - } - - cdecl.add_declarator (enum_decl); - cdecl.modifiers = CCodeModifiers.STATIC; - - type_init.add_statement (cdecl); - - reg_call.add_argument (new CCodeIdentifier ("values")); - } else { - reg_call.add_argument (new CCodeIdentifier ("&g_define_type_info")); - if (fundamental) { - reg_call.add_argument (new CCodeIdentifier ("&g_define_type_fundamental_info")); - } - reg_call.add_argument (new CCodeConstant (get_type_flags ())); - } - - var once_call_block = new CCodeBlock (); - if (!plugin) { - var temp_decl = new CCodeDeclaration ("GType"); - temp_decl.add_declarator (new CCodeVariableDeclarator (type_id_name, reg_call)); - type_init.add_statement (temp_decl); - temp_decl = new CCodeDeclaration ("GType"); - temp_decl.add_declarator (new CCodeVariableDeclarator (type_id_name, new CCodeFunctionCall (new CCodeIdentifier (fun_once.name)))); - once_call_block.add_statement (temp_decl); - } else { - type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (type_id_name), reg_call))); - } - - if (cl != null && cl.has_class_private_fields) { - CCodeFunctionCall add_class_private_call; - - add_class_private_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_add_class_private")); - add_class_private_call.add_argument (new CCodeIdentifier (type_id_name)); - add_class_private_call.add_argument (new CCodeIdentifier ("sizeof (%sPrivate)".printf (get_ccode_type_name (cl)))); - type_init.add_statement (new CCodeExpressionStatement (add_class_private_call)); - } - - if (!declaration_only) { - get_type_interface_init_statements (context, type_init, plugin); - } - - if (cl != null && (cl.has_private_fields || cl.has_type_parameters ())) { - if (!plugin) { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_add_instance_private")); - ccall.add_argument (new CCodeIdentifier (type_id_name)); - ccall.add_argument (new CCodeIdentifier ("sizeof (%sPrivate)".printf (get_ccode_name (cl)))); - type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("%s_private_offset".printf (get_ccode_name (cl))), ccall))); - } else { - type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("%s_private_offset".printf (get_ccode_name (cl))), new CCodeIdentifier ("sizeof (%sPrivate)".printf (get_ccode_name (cl)))))); - } - } - - if (!plugin) { - // the condition that guards the type initialisation - var enter = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_enter")); - enter.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (type_id_name + "__once"))); - - var leave = new CCodeFunctionCall (new CCodeIdentifier ("g_once_init_leave")); - leave.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (type_id_name + "__once"))); - leave.add_argument (new CCodeIdentifier (type_id_name)); - once_call_block.add_statement (new CCodeExpressionStatement (leave)); - - var cif = new CCodeIfStatement (enter, once_call_block); - type_block.add_statement (cif); - type_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name + "__once"))); - - type_once_block = type_init; - type_once_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name))); - } else { - type_block = type_init; - type_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier (type_id_name))); - } - - if (!plugin) { - fun_once.block = type_once_block; - definition_fragment.append (fun_once); - } - - fun.block = type_block; - definition_fragment.append (fun); - } - - /** - * Returns the data type to be registered. - * - * @return type to be registered - */ - public abstract TypeSymbol get_type_declaration (); - - /** - * Returns the name of the type struct in C code. - * - * @return C struct name - */ - public virtual string get_type_struct_name () { - assert_not_reached (); - } - /** - * Returns the name of the base_init function in C code. - * - * @return C function name - */ - public virtual string get_base_init_func_name () { - assert_not_reached (); - } - - /** - * Returns the name of the class_finalize function in C code. - * - * @return C function name - */ - public virtual string get_class_finalize_func_name () { - assert_not_reached (); - } - - /** - * Returns the name of the base_finalize function in C code. - * - * @return C function name - */ - public virtual string get_base_finalize_func_name () { - assert_not_reached (); - } - - /** - * Returns the name of the class_init function in C code. - * - * @return C function name - */ - public virtual string get_class_init_func_name () { - assert_not_reached (); - } - - /** - * Returns the size of the instance struct in C code. - * - * @return C instance struct size - */ - public virtual string get_instance_struct_size () { - assert_not_reached (); - } - - /** - * Returns the name of the instance_init function in C code. - * - * @return C function name - */ - public virtual string get_instance_init_func_name () { - assert_not_reached (); - } - - /** - * Returns the name of the parent type in C code. - * - * @return C function name - */ - public virtual string get_parent_type_name () { - assert_not_reached (); - } - - - - /** - * Returns the C-name of the new generated GTypeValueTable init function or null when not available. - * - * @return C function name - */ - public virtual string? get_gtype_value_table_init_function_name () { - return null; - } - - /** - * Returns the C-name of the new generated GTypeValueTable peek pointer function or null when not available. - * - * @return C function name - */ - public virtual string? get_gtype_value_table_peek_pointer_function_name () { - return null; - } - - /** - * Returns the C-name of the new generated GTypeValueTable free function or null when not available. - * - * @return C function name - */ - public virtual string? get_gtype_value_table_free_function_name () { - return null; - } - - /** - * Returns the C-name of the new generated GTypeValueTable copy function or null when not available. - * - * @return C function name - */ - public virtual string? get_gtype_value_table_copy_function_name () { - return null; - } - - /** - * Returns the C-name of the new generated GTypeValueTable lcopy function or null when not available. - * - * @return C function name - */ - public virtual string? get_gtype_value_table_lcopy_value_function_name () { - return null; - } - - /** - * Returns the C-name of the new generated GTypeValueTable collect value function or null when not available. - * - * @return C function name - */ - public virtual string? get_gtype_value_table_collect_value_function_name () { - return null; - } - - /** - * Returns the set of type flags to be applied when registering. - * - * @return type flags - */ - public virtual string get_type_flags () { - return "0"; - } - - /** - * Returns additional C declarations to setup interfaces. - * - * @return C declarations - */ - public virtual CCodeFragment get_type_interface_init_declaration () { - return new CCodeFragment (); - } - - /** - * Returns additional C initialization statements to setup interfaces. - */ - public virtual void get_type_interface_init_statements (CodeContext context, CCodeBlock block, bool plugin) { - } - - public CCodeFragment get_source_declaration () { - return source_declaration_fragment; - } - - /** - * Returns the declaration for this type register function in C code. - * - * @return C function declaration fragment - */ - public CCodeFragment get_declaration () { - return declaration_fragment; - } - - /** - * Returns the definition for this type register function in C code. - * - * @return C function definition fragment - */ - public CCodeFragment get_definition () { - return definition_fragment; - } - - /** - * Returns the accessibility for this type. - */ - public abstract SymbolAccessibility get_accessibility (); -}