gstreamer-pbutils-0.10: Ownership transfer fixes
[vala-lang.git] / vala / valacodewriter.vala
blob9e72baab2c8c889426287abbbe54b905ad9aa3d8
1 /* valacodewriter.vala
3 * Copyright (C) 2006-2009 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Author:
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
25 using Gee;
27 /**
28 * Code visitor generating Vala API file for the public interface.
30 public class Vala.CodeWriter : CodeVisitor {
31 private CodeContext context;
33 FileStream stream;
35 int indent;
36 /* at begin of line */
37 bool bol = true;
39 Scope current_scope;
41 bool dump_tree;
43 public CodeWriter (bool dump_tree = false) {
44 this.dump_tree = dump_tree;
47 /**
48 * Writes the public interface of the specified code context into the
49 * specified file.
51 * @param context a code context
52 * @param filename a relative or absolute filename
54 public void write_file (CodeContext context, string filename) {
55 this.context = context;
57 stream = FileStream.open (filename, "w");
59 write_string ("/* %s generated by %s, do not modify. */".printf (Path.get_basename (filename), Environment.get_prgname ()));
60 write_newline ();
61 write_newline ();
63 current_scope = context.root.scope;
65 context.accept (this);
67 current_scope = null;
69 stream = null;
72 public override void visit_namespace (Namespace ns) {
73 if (ns.external_package) {
74 return;
77 if (ns.name == null) {
78 ns.accept_children (this);
79 return;
82 write_indent ();
83 write_string ("[CCode (cprefix = \"%s\", lower_case_cprefix = \"%s\")]".printf (ns.get_cprefix (), ns.get_lower_case_cprefix ()));
84 write_newline ();
86 write_attributes (ns);
88 write_indent ();
89 write_string ("namespace ");
90 write_identifier (ns.name);
91 write_begin_block ();
93 current_scope = ns.scope;
95 visit_sorted (ns.get_namespaces ());
96 visit_sorted (ns.get_classes ());
97 visit_sorted (ns.get_interfaces ());
98 visit_sorted (ns.get_structs ());
99 visit_sorted (ns.get_enums ());
100 visit_sorted (ns.get_error_domains ());
101 visit_sorted (ns.get_delegates ());
102 visit_sorted (ns.get_fields ());
103 visit_sorted (ns.get_constants ());
104 visit_sorted (ns.get_methods ());
106 current_scope = current_scope.parent_scope;
108 write_end_block ();
109 write_newline ();
112 public override void visit_class (Class cl) {
113 if (cl.external_package) {
114 return;
117 if (!check_accessibility (cl)) {
118 return;
121 if (cl.is_compact) {
122 write_indent ();
123 write_string ("[Compact]");
124 write_newline ();
127 if (cl.is_immutable) {
128 write_indent ();
129 write_string ("[Immutable]");
130 write_newline ();
133 write_indent ();
135 write_string ("[CCode (");
137 if (cl.is_reference_counting ()) {
138 if (cl.base_class == null || cl.base_class.get_ref_function () == null || cl.base_class.get_ref_function () != cl.get_ref_function ()) {
139 write_string ("ref_function = \"%s\", ".printf (cl.get_ref_function ()));
140 if (cl.ref_function_void) {
141 write_string ("ref_function_void = true, ");
144 if (cl.base_class == null || cl.base_class.get_unref_function () == null || cl.base_class.get_unref_function () != cl.get_unref_function ()) {
145 write_string ("unref_function = \"%s\", ".printf (cl.get_unref_function ()));
147 } else {
148 if (cl.get_dup_function () != null) {
149 write_string ("copy_function = \"%s\", ".printf (cl.get_dup_function ()));
151 if (cl.get_free_function () != cl.get_default_free_function ()) {
152 write_string ("free_function = \"%s\", ".printf (cl.get_free_function ()));
156 if (cl.get_cname () != cl.get_default_cname ()) {
157 write_string ("cname = \"%s\", ".printf (cl.get_cname ()));
160 if (cl.type_check_function != null) {
161 write_string ("type_check_function = \"%s\", ".printf (cl.type_check_function ));
164 if (cl.is_compact && cl.get_type_id () != "G_TYPE_POINTER") {
165 write_string ("type_id = \"%s\", ".printf (cl.get_type_id ()));
168 if (cl.get_param_spec_function () != null
169 && (cl.base_class == null || cl.get_param_spec_function () != cl.base_class.get_param_spec_function ())) {
170 write_string ("param_spec_function = \"%s\", ".printf (cl.get_param_spec_function ()));
173 bool first = true;
174 string cheaders = "";
175 foreach (string cheader in cl.get_cheader_filenames ()) {
176 if (first) {
177 cheaders = cheader;
178 first = false;
179 } else {
180 cheaders = "%s,%s".printf (cheaders, cheader);
183 write_string ("cheader_filename = \"%s\")]".printf (cheaders));
184 write_newline ();
186 write_attributes (cl);
188 write_indent ();
189 write_accessibility (cl);
190 if (cl.is_abstract) {
191 write_string ("abstract ");
193 write_string ("class ");
194 write_identifier (cl.name);
196 var type_params = cl.get_type_parameters ();
197 if (type_params.size > 0) {
198 write_string ("<");
199 first = true;
200 foreach (TypeParameter type_param in type_params) {
201 if (first) {
202 first = false;
203 } else {
204 write_string (",");
206 write_identifier (type_param.name);
208 write_string (">");
211 var base_types = cl.get_base_types ();
212 if (base_types.size > 0) {
213 write_string (" : ");
215 first = true;
216 foreach (DataType base_type in base_types) {
217 if (!first) {
218 write_string (", ");
219 } else {
220 first = false;
222 write_type (base_type);
225 write_begin_block ();
227 current_scope = cl.scope;
229 visit_sorted (cl.get_classes ());
230 visit_sorted (cl.get_structs ());
231 visit_sorted (cl.get_enums ());
232 visit_sorted (cl.get_delegates ());
233 visit_sorted (cl.get_fields ());
234 visit_sorted (cl.get_constants ());
235 visit_sorted (cl.get_methods ());
236 visit_sorted (cl.get_properties ());
237 visit_sorted (cl.get_signals ());
239 current_scope = current_scope.parent_scope;
241 write_end_block ();
242 write_newline ();
245 void visit_sorted (Gee.List<Symbol> symbols) {
246 var sorted_symbols = new Gee.ArrayList<Symbol> ();
247 foreach (Symbol sym in symbols) {
248 int left = 0;
249 int right = sorted_symbols.size - 1;
250 if (left > right || sym.name < sorted_symbols[left].name) {
251 sorted_symbols.insert (0, sym);
252 } else if (sym.name > sorted_symbols[right].name) {
253 sorted_symbols.add (sym);
254 } else {
255 while (right - left > 1) {
256 int i = (right + left) / 2;
257 if (sym.name > sorted_symbols[i].name) {
258 left = i;
259 } else {
260 right = i;
263 sorted_symbols.insert (left + 1, sym);
266 foreach (Symbol sym in sorted_symbols) {
267 sym.accept (this);
271 public override void visit_struct (Struct st) {
272 if (st.external_package) {
273 return;
276 if (!check_accessibility (st)) {
277 return;
280 write_indent ();
282 write_string ("[CCode (");
284 if (st.get_cname () != st.get_default_cname ()) {
285 write_string ("cname = \"%s\", ".printf (st.get_cname ()));
288 if (!st.is_simple_type () && st.get_type_id () != "G_TYPE_POINTER") {
289 write_string ("type_id = \"%s\", ".printf (st.get_type_id ()));
292 if (!st.use_const) {
293 write_string ("use_const = false, ");
296 bool first = true;
297 string cheaders = "";
298 foreach (string cheader in st.get_cheader_filenames ()) {
299 if (first) {
300 cheaders = cheader;
301 first = false;
302 } else {
303 cheaders = "%s,%s".printf (cheaders, cheader);
306 write_string ("cheader_filename = \"%s\")]".printf (cheaders));
307 write_newline ();
309 if (st.is_simple_type ()) {
310 write_indent ();
311 write_string ("[SimpleType]");
312 write_newline ();
315 if (st.is_integer_type ()) {
316 write_indent ();
317 write_string ("[IntegerType (rank = %d)]".printf (st.get_rank ()));
318 write_newline ();
321 if (st.is_floating_type ()) {
322 write_indent ();
323 write_string ("[FloatingType (rank = %d)]".printf (st.get_rank ()));
324 write_newline ();
327 write_attributes (st);
329 write_indent ();
330 write_accessibility (st);
331 write_string ("struct ");
332 write_identifier (st.name);
334 if (st.base_type != null) {
335 write_string (" : ");
336 write_type (st.base_type);
339 write_begin_block ();
341 current_scope = st.scope;
343 foreach (Field field in st.get_fields ()) {
344 field.accept (this);
346 visit_sorted (st.get_constants ());
347 visit_sorted (st.get_methods ());
349 current_scope = current_scope.parent_scope;
351 write_end_block ();
352 write_newline ();
355 public override void visit_interface (Interface iface) {
356 if (iface.external_package) {
357 return;
360 if (!check_accessibility (iface)) {
361 return;
364 write_indent ();
366 bool first = true;
367 string cheaders = "";
368 foreach (string cheader in iface.get_cheader_filenames ()) {
369 if (first) {
370 cheaders = cheader;
371 first = false;
372 } else {
373 cheaders = "%s,%s".printf (cheaders, cheader);
376 write_string ("[CCode (cheader_filename = \"%s\"".printf (cheaders));
377 if (iface.get_lower_case_csuffix () != iface.get_default_lower_case_csuffix ())
378 write_string (", lower_case_csuffix = \"%s\"".printf (iface.get_lower_case_csuffix ()));
380 write_string (")]");
381 write_newline ();
383 write_attributes (iface);
385 write_indent ();
386 write_accessibility (iface);
387 write_string ("interface ");
388 write_identifier (iface.name);
390 var type_params = iface.get_type_parameters ();
391 if (type_params.size > 0) {
392 write_string ("<");
393 first = true;
394 foreach (TypeParameter type_param in type_params) {
395 if (first) {
396 first = false;
397 } else {
398 write_string (",");
400 write_identifier (type_param.name);
402 write_string (">");
405 var prerequisites = iface.get_prerequisites ();
406 if (prerequisites.size > 0) {
407 write_string (" : ");
409 first = true;
410 foreach (DataType prerequisite in prerequisites) {
411 if (!first) {
412 write_string (", ");
413 } else {
414 first = false;
416 write_type (prerequisite);
419 write_begin_block ();
421 current_scope = iface.scope;
423 visit_sorted (iface.get_classes ());
424 visit_sorted (iface.get_structs ());
425 visit_sorted (iface.get_enums ());
426 visit_sorted (iface.get_delegates ());
427 visit_sorted (iface.get_fields ());
428 visit_sorted (iface.get_methods ());
429 visit_sorted (iface.get_properties ());
430 visit_sorted (iface.get_signals ());
432 current_scope = current_scope.parent_scope;
434 write_end_block ();
435 write_newline ();
438 public override void visit_enum (Enum en) {
439 if (en.external_package) {
440 return;
443 if (!check_accessibility (en)) {
444 return;
447 write_indent ();
449 bool first = true;
450 string cheaders = "";
451 foreach (string cheader in en.get_cheader_filenames ()) {
452 if (first) {
453 cheaders = cheader;
454 first = false;
455 } else {
456 cheaders = "%s,%s".printf (cheaders, cheader);
460 write_string ("[CCode (cprefix = \"%s\", ".printf (en.get_cprefix ()));
462 if (!en.has_type_id) {
463 write_string ("has_type_id = \"%d\", ".printf (en.has_type_id ? 1 : 0));
466 write_string ("cheader_filename = \"%s\")]".printf (cheaders));
468 if (en.is_flags) {
469 write_indent ();
470 write_string ("[Flags]");
473 write_attributes (en);
475 write_indent ();
476 write_accessibility (en);
477 write_string ("enum ");
478 write_identifier (en.name);
479 write_begin_block ();
481 first = true;
482 foreach (EnumValue ev in en.get_values ()) {
483 if (first) {
484 first = false;
485 } else {
486 write_string (",");
487 write_newline ();
490 if (ev.get_cname () != ev.get_default_cname ()) {
491 write_indent ();
492 write_string ("[CCode (cname = \"%s\")]".printf (ev.get_cname ()));
494 write_indent ();
495 write_identifier (ev.name);
498 if (!first) {
499 if (en.get_methods ().size > 0) {
500 write_string (";");
502 write_newline ();
505 current_scope = en.scope;
506 foreach (Method m in en.get_methods ()) {
507 m.accept (this);
509 current_scope = current_scope.parent_scope;
511 write_end_block ();
512 write_newline ();
515 public override void visit_error_domain (ErrorDomain edomain) {
516 if (edomain.external_package) {
517 return;
520 if (!check_accessibility (edomain)) {
521 return;
524 write_indent ();
526 var first = true;
527 string cheaders = "";
528 foreach (string cheader in edomain.get_cheader_filenames ()) {
529 if (first) {
530 cheaders = cheader;
531 first = false;
532 } else {
533 cheaders = "%s,%s".printf (cheaders, cheader);
536 write_string ("[CCode (cprefix = \"%s\", cheader_filename = \"%s\")]".printf (edomain.get_cprefix (), cheaders));
538 write_attributes (edomain);
540 write_indent ();
541 write_accessibility (edomain);
542 write_string ("errordomain ");
543 write_identifier (edomain.name);
544 write_begin_block ();
546 edomain.accept_children (this);
548 write_end_block ();
549 write_newline ();
552 public override void visit_error_code (ErrorCode ecode) {
553 write_indent ();
554 write_identifier (ecode.name);
555 write_string (",");
556 write_newline ();
559 public override void visit_constant (Constant c) {
560 if (c.external_package) {
561 return;
564 if (!check_accessibility (c)) {
565 return;
568 bool custom_cname = (c.get_cname () != c.get_default_cname ());
569 bool custom_cheaders = (c.parent_symbol is Namespace);
570 if (custom_cname || custom_cheaders) {
571 write_indent ();
572 write_string ("[CCode (");
574 if (custom_cname) {
575 write_string ("cname = \"%s\"".printf (c.get_cname ()));
578 if (custom_cheaders) {
579 if (custom_cname) {
580 write_string (", ");
583 bool first = true;
584 string cheaders = "";
585 foreach (string cheader in c.get_cheader_filenames ()) {
586 if (first) {
587 cheaders = cheader;
588 first = false;
589 } else {
590 cheaders = "%s,%s".printf (cheaders, cheader);
593 write_string ("cheader_filename = \"%s\"".printf (cheaders));
596 write_string (")]");
599 write_indent ();
600 write_accessibility (c);
601 write_string ("const ");
603 write_type (c.type_reference);
605 write_string (" ");
606 write_identifier (c.name);
607 write_string (";");
608 write_newline ();
611 public override void visit_field (Field f) {
612 if (f.external_package) {
613 return;
616 if (!check_accessibility (f)) {
617 return;
620 bool custom_cname = (f.get_cname () != f.get_default_cname ());
621 bool custom_ctype = (f.get_ctype () != null);
622 bool custom_cheaders = (f.parent_symbol is Namespace);
623 if (custom_cname || custom_ctype || custom_cheaders || (f.no_array_length && f.field_type is ArrayType)) {
624 write_indent ();
625 write_string ("[CCode (");
627 if (custom_cname) {
628 write_string ("cname = \"%s\"".printf (f.get_cname ()));
631 if (custom_ctype) {
632 if (custom_cname) {
633 write_string (", ");
636 write_string ("type = \"%s\"".printf (f.get_ctype ()));
639 if (custom_cheaders) {
640 if (custom_cname || custom_ctype) {
641 write_string (", ");
644 bool first = true;
645 string cheaders = "";
646 foreach (string cheader in f.get_cheader_filenames ()) {
647 if (first) {
648 cheaders = cheader;
649 first = false;
650 } else {
651 cheaders = "%s,%s".printf (cheaders, cheader);
654 write_string ("cheader_filename = \"%s\"".printf (cheaders));
657 if (f.no_array_length && f.field_type is ArrayType) {
658 if (custom_cname || custom_ctype || custom_cheaders) {
659 write_string (", ");
662 write_string ("array_length = false");
665 write_string (")]");
668 write_indent ();
669 write_accessibility (f);
671 if (f.binding == MemberBinding.STATIC) {
672 write_string ("static ");
673 } else if (f.binding == MemberBinding.CLASS) {
674 write_string ("class ");
677 if (is_weak (f.field_type)) {
678 write_string ("weak ");
681 write_type (f.field_type);
683 write_string (" ");
684 write_identifier (f.name);
685 write_string (";");
686 write_newline ();
689 private void write_error_domains (Gee.List<DataType> error_domains) {
690 if (error_domains.size > 0) {
691 write_string (" throws ");
693 bool first = true;
694 foreach (DataType type in error_domains) {
695 if (!first) {
696 write_string (", ");
697 } else {
698 first = false;
701 write_type (type);
706 // equality comparison with 3 digit precision
707 private bool float_equal (double d1, double d2) {
708 return ((int) (d1 * 1000)) == ((int) (d2 * 1000));
711 private void write_params (Gee.List<FormalParameter> params) {
712 write_string ("(");
714 int i = 1;
715 foreach (FormalParameter param in params) {
716 if (i > 1) {
717 write_string (", ");
720 if (param.ellipsis) {
721 write_string ("...");
722 continue;
726 var ccode_params = new StringBuilder ();
727 var separator = "";
729 if (param.ctype != null) {
730 ccode_params.append_printf ("%stype = \"%s\"", separator, param.ctype);
731 separator = ", ";
733 if (param.no_array_length && param.parameter_type is ArrayType) {
734 ccode_params.append_printf ("%sarray_length = false", separator);
735 separator = ", ";
737 if (!float_equal (param.carray_length_parameter_position, i + 0.1)) {
738 ccode_params.append_printf ("%sarray_length_pos = %g", separator, param.carray_length_parameter_position);
739 separator = ", ";
741 if (!float_equal (param.cdelegate_target_parameter_position, i + 0.1)) {
742 ccode_params.append_printf ("%sdelegate_target_pos = %g", separator, param.cdelegate_target_parameter_position);
743 separator = ", ";
745 if (param.async_only) {
746 ccode_params.append_printf ("%sasync_only = true", separator);
747 separator = ", ";
750 if (ccode_params.len > 0) {
751 write_string ("[CCode (%s)] ".printf (ccode_params.str));
754 if (param.params_array) {
755 write_string ("params ");
758 if (param.direction == ParameterDirection.IN) {
759 if (param.parameter_type.value_owned) {
760 write_string ("owned ");
762 } else {
763 if (param.direction == ParameterDirection.REF) {
764 write_string ("ref ");
765 } else if (param.direction == ParameterDirection.OUT) {
766 write_string ("out ");
768 if (is_weak (param.parameter_type)) {
769 write_string ("unowned ");
773 write_type (param.parameter_type);
775 write_string (" ");
776 write_identifier (param.name);
778 if (param.default_expression != null) {
779 write_string (" = ");
780 write_string (param.default_expression.to_string ());
783 i++;
786 write_string (")");
789 public override void visit_delegate (Delegate cb) {
790 if (cb.external_package) {
791 return;
794 if (!check_accessibility (cb)) {
795 return;
798 write_indent ();
800 var first = true;
801 string cheaders = "";
802 foreach (string cheader in cb.get_cheader_filenames ()) {
803 if (first) {
804 cheaders = cheader;
805 first = false;
806 } else {
807 cheaders = "%s,%s".printf (cheaders, cheader);
810 write_string ("[CCode (cheader_filename = \"%s\")]".printf (cheaders));
812 write_indent ();
814 write_accessibility (cb);
815 if (!cb.has_target) {
816 write_string ("static ");
818 write_string ("delegate ");
820 write_return_type (cb.return_type);
822 write_string (" ");
823 write_identifier (cb.name);
825 write_string (" ");
827 write_params (cb.get_parameters ());
829 write_string (";");
831 write_newline ();
834 public override void visit_method (Method m) {
835 if (m.external_package) {
836 return;
839 // don't write interface implementation unless it's an abstract or virtual method
840 if (!check_accessibility (m) || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
841 if (!dump_tree) {
842 return;
846 if (m.get_attribute ("NoWrapper") != null) {
847 write_indent ();
848 write_string ("[NoWrapper]");
850 if (m.returns_modified_pointer) {
851 write_indent ();
852 write_string ("[ReturnsModifiedPointer]");
855 var ccode_params = new StringBuilder ();
856 var separator = "";
858 if (m.get_cname () != m.get_default_cname ()) {
859 ccode_params.append_printf ("%scname = \"%s\"", separator, m.get_cname ());
860 separator = ", ";
862 if (m.parent_symbol is Namespace) {
863 bool first = true;
864 string cheaders = "";
865 foreach (string cheader in m.get_cheader_filenames ()) {
866 if (first) {
867 cheaders = cheader;
868 first = false;
869 } else {
870 cheaders = "%s,%s".printf (cheaders, cheader);
873 ccode_params.append_printf ("%scheader_filename = \"%s\"", separator, cheaders);
874 separator = ", ";
876 if (!float_equal (m.cinstance_parameter_position, 0)) {
877 ccode_params.append_printf ("%sinstance_pos = %g", separator, m.cinstance_parameter_position);
878 separator = ", ";
880 if (m.no_array_length && m.return_type is ArrayType) {
881 ccode_params.append_printf ("%sarray_length = false", separator);
882 separator = ", ";
884 if (!float_equal (m.carray_length_parameter_position, -3)) {
885 ccode_params.append_printf ("%sarray_length_pos = %g", separator, m.carray_length_parameter_position);
886 separator = ", ";
888 if (m.array_null_terminated && m.return_type is ArrayType) {
889 ccode_params.append_printf ("%sarray_null_terminated = true", separator);
890 separator = ", ";
892 if (!float_equal (m.cdelegate_target_parameter_position, -3)) {
893 ccode_params.append_printf ("%sdelegate_target_pos = %g", separator, m.cdelegate_target_parameter_position);
894 separator = ", ";
896 if (m.vfunc_name != m.name) {
897 ccode_params.append_printf ("%svfunc_name = \"%s\"", separator, m.vfunc_name);
898 separator = ", ";
900 if (m.sentinel != m.DEFAULT_SENTINEL) {
901 ccode_params.append_printf ("%ssentinel = \"%s\"", separator, m.sentinel);
902 separator = ", ";
904 if (m is CreationMethod && ((CreationMethod)m).custom_return_type_cname != null) {
905 ccode_params.append_printf ("%stype = \"%s\"", separator, ((CreationMethod)m).custom_return_type_cname);
906 separator = ", ";
908 if (m is CreationMethod && !m.has_construct_function) {
909 ccode_params.append_printf ("%shas_construct_function = false", separator);
910 separator = ", ";
913 if (ccode_params.len > 0) {
914 write_indent ();
915 write_string ("[CCode (%s)]".printf (ccode_params.str));
918 write_indent ();
919 write_accessibility (m);
921 if (m is CreationMethod) {
922 var datatype = (TypeSymbol) m.parent_symbol;
923 write_identifier (datatype.name);
924 if (m.name != "new") {
925 write_string (".");
926 write_identifier (m.name);
928 write_string (" ");
929 } else if (m.binding == MemberBinding.STATIC) {
930 write_string ("static ");
931 } else if (m.binding == MemberBinding.CLASS) {
932 write_string ("class ");
933 } else if (m.is_abstract) {
934 write_string ("abstract ");
935 } else if (m.is_virtual) {
936 write_string ("virtual ");
937 } else if (m.overrides) {
938 write_string ("override ");
941 if (!(m is CreationMethod)) {
942 write_return_type (m.return_type);
943 write_string (" ");
945 write_identifier (m.name);
946 write_string (" ");
949 write_params (m.get_parameters ());
950 write_error_domains (m.get_error_types ());
952 write_code_block (m.body);
954 write_newline ();
957 public override void visit_creation_method (CreationMethod m) {
958 visit_method (m);
961 public override void visit_property (Property prop) {
962 if (!check_accessibility (prop) || (prop.base_interface_property != null && !prop.is_abstract && !prop.is_virtual)) {
963 return;
966 if (prop.no_accessor_method) {
967 write_indent ();
968 write_string ("[NoAccessorMethod]");
971 write_indent ();
972 write_accessibility (prop);
974 if (prop.binding == MemberBinding.STATIC) {
975 write_string ("static ");
976 } else if (prop.is_abstract) {
977 write_string ("abstract ");
978 } else if (prop.is_virtual) {
979 write_string ("virtual ");
980 } else if (prop.overrides) {
981 write_string ("override ");
984 write_type (prop.property_type);
986 write_string (" ");
987 write_identifier (prop.name);
988 write_string (" {");
989 if (prop.get_accessor != null) {
990 if (prop.get_accessor.value_type.is_disposable ()) {
991 write_string (" owned");
994 write_string (" get");
995 write_code_block (prop.get_accessor.body);
997 if (prop.set_accessor != null) {
998 if (prop.set_accessor.value_type.value_owned) {
999 write_string ("owned ");
1002 if (prop.set_accessor.writable) {
1003 write_string (" set");
1005 if (prop.set_accessor.construction) {
1006 write_string (" construct");
1008 write_code_block (prop.set_accessor.body);
1010 write_string (" }");
1011 write_newline ();
1014 public override void visit_signal (Signal sig) {
1015 if (!check_accessibility (sig)) {
1016 return;
1019 if (sig.has_emitter) {
1020 write_indent ();
1021 write_string ("[HasEmitter]");
1024 write_indent ();
1025 write_accessibility (sig);
1027 if (sig.is_virtual) {
1028 write_string ("virtual ");
1031 write_string ("signal ");
1033 write_return_type (sig.return_type);
1035 write_string (" ");
1036 write_identifier (sig.name);
1038 write_string (" ");
1040 write_params (sig.get_parameters ());
1042 write_string (";");
1044 write_newline ();
1047 public override void visit_block (Block b) {
1048 write_begin_block ();
1050 foreach (Statement stmt in b.get_statements ()) {
1051 stmt.accept (this);
1054 write_end_block ();
1057 public override void visit_empty_statement (EmptyStatement stmt) {
1060 public override void visit_declaration_statement (DeclarationStatement stmt) {
1061 write_indent ();
1062 stmt.declaration.accept (this);
1063 write_string (";");
1064 write_newline ();
1067 public override void visit_local_variable (LocalVariable local) {
1068 write_type (local.variable_type);
1069 write_string (" ");
1070 write_identifier (local.name);
1071 if (local.initializer != null) {
1072 write_string (" = ");
1073 local.initializer.accept (this);
1077 public override void visit_initializer_list (InitializerList list) {
1078 write_string ("{");
1080 bool first = true;
1081 foreach (Expression initializer in list.get_initializers ()) {
1082 if (!first) {
1083 write_string (", ");
1084 } else {
1085 write_string (" ");
1087 first = false;
1088 initializer.accept (this);
1090 write_string (" }");
1093 public override void visit_expression_statement (ExpressionStatement stmt) {
1094 write_indent ();
1095 stmt.expression.accept (this);
1096 write_string (";");
1097 write_newline ();
1100 public override void visit_if_statement (IfStatement stmt) {
1101 write_indent ();
1102 write_string ("if (");
1103 stmt.condition.accept (this);
1104 write_string (")");
1105 stmt.true_statement.accept (this);
1106 if (stmt.false_statement != null) {
1107 write_string (" else");
1108 stmt.false_statement.accept (this);
1110 write_newline ();
1113 public override void visit_switch_statement (SwitchStatement stmt) {
1114 write_indent ();
1115 write_string ("switch (");
1116 stmt.expression.accept (this);
1117 write_string (") {");
1118 write_newline ();
1120 foreach (SwitchSection section in stmt.get_sections ()) {
1121 section.accept (this);
1124 write_indent ();
1125 write_string ("}");
1126 write_newline ();
1129 public override void visit_switch_section (SwitchSection section) {
1130 foreach (SwitchLabel label in section.get_labels ()) {
1131 label.accept (this);
1134 visit_block (section);
1137 public override void visit_switch_label (SwitchLabel label) {
1138 if (label.expression != null) {
1139 write_indent ();
1140 write_string ("case ");
1141 label.expression.accept (this);
1142 write_string (":");
1143 write_newline ();
1144 } else {
1145 write_indent ();
1146 write_string ("default:");
1147 write_newline ();
1151 public override void visit_while_statement (WhileStatement stmt) {
1152 write_indent ();
1153 write_string ("while (");
1154 stmt.condition.accept (this);
1155 write_string (")");
1156 stmt.body.accept (this);
1157 write_newline ();
1160 public override void visit_do_statement (DoStatement stmt) {
1161 write_indent ();
1162 write_string ("do");
1163 stmt.body.accept (this);
1164 write_string ("while (");
1165 stmt.condition.accept (this);
1166 write_string (");");
1167 write_newline ();
1170 public override void visit_for_statement (ForStatement stmt) {
1171 write_indent ();
1172 write_string ("for (");
1174 bool first = true;
1175 foreach (Expression initializer in stmt.get_initializer ()) {
1176 if (!first) {
1177 write_string (", ");
1179 first = false;
1180 initializer.accept (this);
1182 write_string ("; ");
1184 stmt.condition.accept (this);
1185 write_string ("; ");
1187 first = true;
1188 foreach (Expression iterator in stmt.get_iterator ()) {
1189 if (!first) {
1190 write_string (", ");
1192 first = false;
1193 iterator.accept (this);
1196 write_string (")");
1197 stmt.body.accept (this);
1198 write_newline ();
1201 public override void visit_foreach_statement (ForeachStatement stmt) {
1204 public override void visit_break_statement (BreakStatement stmt) {
1205 write_indent ();
1206 write_string ("break;");
1207 write_newline ();
1210 public override void visit_continue_statement (ContinueStatement stmt) {
1211 write_indent ();
1212 write_string ("continue;");
1213 write_newline ();
1216 public override void visit_return_statement (ReturnStatement stmt) {
1217 write_indent ();
1218 write_string ("return");
1219 if (stmt.return_expression != null) {
1220 write_string (" ");
1221 stmt.return_expression.accept (this);
1223 write_string (";");
1224 write_newline ();
1227 public override void visit_yield_statement (YieldStatement y) {
1228 write_indent ();
1229 write_string ("yield");
1230 if (y.yield_expression != null) {
1231 write_string (" ");
1232 y.yield_expression.accept (this);
1234 write_string (";");
1235 write_newline ();
1238 public override void visit_throw_statement (ThrowStatement stmt) {
1239 write_indent ();
1240 write_string ("throw");
1241 if (stmt.error_expression != null) {
1242 write_string (" ");
1243 stmt.error_expression.accept (this);
1245 write_string (";");
1246 write_newline ();
1249 public override void visit_try_statement (TryStatement stmt) {
1250 write_indent ();
1251 write_string ("try");
1252 stmt.body.accept (this);
1253 write_newline ();
1256 public override void visit_catch_clause (CatchClause clause) {
1259 public override void visit_lock_statement (LockStatement stmt) {
1262 public override void visit_delete_statement (DeleteStatement stmt) {
1265 public override void visit_array_creation_expression (ArrayCreationExpression expr) {
1266 write_string ("new ");
1267 write_type (expr.element_type);
1268 write_string ("[");
1270 bool first = true;
1271 foreach (Expression size in expr.get_sizes ()) {
1272 if (!first) {
1273 write_string (", ");
1275 first = false;
1277 size.accept (this);
1280 write_string ("]");
1282 if (expr.initializer_list != null) {
1283 write_string (" ");
1284 expr.initializer_list.accept (this);
1288 public override void visit_boolean_literal (BooleanLiteral lit) {
1289 write_string (lit.value.to_string ());
1292 public override void visit_character_literal (CharacterLiteral lit) {
1293 write_string (lit.value);
1296 public override void visit_integer_literal (IntegerLiteral lit) {
1297 write_string (lit.value);
1300 public override void visit_real_literal (RealLiteral lit) {
1301 write_string (lit.value);
1304 public override void visit_string_literal (StringLiteral lit) {
1305 write_string (lit.value);
1308 public override void visit_null_literal (NullLiteral lit) {
1309 write_string ("null");
1312 public override void visit_member_access (MemberAccess expr) {
1313 if (expr.inner != null) {
1314 expr.inner.accept (this);
1315 write_string (".");
1317 write_identifier (expr.member_name);
1320 public override void visit_method_call (MethodCall expr) {
1321 expr.call.accept (this);
1322 write_string (" (");
1324 bool first = true;
1325 foreach (Expression arg in expr.get_argument_list ()) {
1326 if (!first) {
1327 write_string (", ");
1329 first = false;
1331 arg.accept (this);
1334 write_string (")");
1337 public override void visit_element_access (ElementAccess expr) {
1338 expr.container.accept (this);
1339 write_string ("[");
1341 bool first = true;
1342 foreach (Expression index in expr.get_indices ()) {
1343 if (!first) {
1344 write_string (", ");
1346 first = false;
1348 index.accept (this);
1351 write_string ("]");
1354 public override void visit_base_access (BaseAccess expr) {
1355 write_string ("base");
1358 public override void visit_postfix_expression (PostfixExpression expr) {
1359 expr.inner.accept (this);
1360 if (expr.increment) {
1361 write_string ("++");
1362 } else {
1363 write_string ("--");
1367 public override void visit_object_creation_expression (ObjectCreationExpression expr) {
1368 write_string ("new ");
1369 write_type (expr.type_reference);
1370 write_string (" (");
1372 bool first = true;
1373 foreach (Expression arg in expr.get_argument_list ()) {
1374 if (!first) {
1375 write_string (", ");
1377 first = false;
1379 arg.accept (this);
1382 write_string (")");
1385 public override void visit_sizeof_expression (SizeofExpression expr) {
1386 write_string ("sizeof (");
1387 write_type (expr.type_reference);
1388 write_string (")");
1391 public override void visit_typeof_expression (TypeofExpression expr) {
1392 write_string ("typeof (");
1393 write_type (expr.type_reference);
1394 write_string (")");
1397 public override void visit_unary_expression (UnaryExpression expr) {
1398 switch (expr.operator) {
1399 case UnaryOperator.PLUS:
1400 write_string ("+");
1401 break;
1402 case UnaryOperator.MINUS:
1403 write_string ("-");
1404 break;
1405 case UnaryOperator.LOGICAL_NEGATION:
1406 write_string ("!");
1407 break;
1408 case UnaryOperator.BITWISE_COMPLEMENT:
1409 write_string ("~");
1410 break;
1411 case UnaryOperator.INCREMENT:
1412 write_string ("++");
1413 break;
1414 case UnaryOperator.DECREMENT:
1415 write_string ("--");
1416 break;
1417 case UnaryOperator.REF:
1418 write_string ("ref ");
1419 break;
1420 case UnaryOperator.OUT:
1421 write_string ("out ");
1422 break;
1423 default:
1424 assert_not_reached ();
1426 expr.inner.accept (this);
1429 public override void visit_cast_expression (CastExpression expr) {
1430 if (!expr.is_silent_cast) {
1431 write_string ("(");
1432 write_type (expr.type_reference);
1433 write_string (") ");
1436 expr.inner.accept (this);
1438 if (expr.is_silent_cast) {
1439 write_string (" as ");
1440 write_type (expr.type_reference);
1444 public override void visit_pointer_indirection (PointerIndirection expr) {
1445 write_string ("*");
1446 expr.inner.accept (this);
1449 public override void visit_addressof_expression (AddressofExpression expr) {
1450 write_string ("&");
1451 expr.inner.accept (this);
1454 public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
1455 write_string ("(owned) ");
1456 expr.inner.accept (this);
1459 public override void visit_binary_expression (BinaryExpression expr) {
1460 expr.left.accept (this);
1462 switch (expr.operator) {
1463 case BinaryOperator.PLUS:
1464 write_string (" + ");
1465 break;
1466 case BinaryOperator.MINUS:
1467 write_string (" - ");
1468 break;
1469 case BinaryOperator.MUL:
1470 write_string (" * ");
1471 break;
1472 case BinaryOperator.DIV:
1473 write_string (" / ");
1474 break;
1475 case BinaryOperator.MOD:
1476 write_string (" % ");
1477 break;
1478 case BinaryOperator.SHIFT_LEFT:
1479 write_string (" << ");
1480 break;
1481 case BinaryOperator.SHIFT_RIGHT:
1482 write_string (" >> ");
1483 break;
1484 case BinaryOperator.LESS_THAN:
1485 write_string (" < ");
1486 break;
1487 case BinaryOperator.GREATER_THAN:
1488 write_string (" > ");
1489 break;
1490 case BinaryOperator.LESS_THAN_OR_EQUAL:
1491 write_string (" <= ");
1492 break;
1493 case BinaryOperator.GREATER_THAN_OR_EQUAL:
1494 write_string (" >= ");
1495 break;
1496 case BinaryOperator.EQUALITY:
1497 write_string (" == ");
1498 break;
1499 case BinaryOperator.INEQUALITY:
1500 write_string (" != ");
1501 break;
1502 case BinaryOperator.BITWISE_AND:
1503 write_string (" & ");
1504 break;
1505 case BinaryOperator.BITWISE_OR:
1506 write_string (" | ");
1507 break;
1508 case BinaryOperator.BITWISE_XOR:
1509 write_string (" ^ ");
1510 break;
1511 case BinaryOperator.AND:
1512 write_string (" && ");
1513 break;
1514 case BinaryOperator.OR:
1515 write_string (" || ");
1516 break;
1517 case BinaryOperator.IN:
1518 write_string (" in ");
1519 break;
1520 default:
1521 assert_not_reached ();
1524 expr.right.accept (this);
1527 public override void visit_type_check (TypeCheck expr) {
1528 expr.expression.accept (this);
1529 write_string (" is ");
1530 write_type (expr.type_reference);
1533 public override void visit_conditional_expression (ConditionalExpression expr) {
1534 expr.condition.accept (this);
1535 write_string ("?");
1536 expr.true_expression.accept (this);
1537 write_string (":");
1538 expr.false_expression.accept (this);
1541 public override void visit_lambda_expression (LambdaExpression expr) {
1544 public override void visit_assignment (Assignment a) {
1545 a.left.accept (this);
1546 write_string (" = ");
1547 a.right.accept (this);
1550 private void write_indent () {
1551 int i;
1553 if (!bol) {
1554 stream.putc ('\n');
1557 for (i = 0; i < indent; i++) {
1558 stream.putc ('\t');
1561 bol = false;
1564 private void write_identifier (string s) {
1565 if (s == "base" || s == "break" || s == "class" ||
1566 s == "construct" || s == "delegate" || s == "delete" ||
1567 s == "do" || s == "dynamic" || s == "foreach" || s == "in" ||
1568 s == "interface" || s == "lock" || s == "namespace" ||
1569 s == "new" || s == "out" || s == "ref" ||
1570 s == "signal" || s.get_char ().isdigit ()) {
1571 stream.putc ('@');
1573 write_string (s);
1576 private void write_return_type (DataType type) {
1577 if (is_weak (type)) {
1578 write_string ("unowned ");
1581 write_type (type);
1584 private bool is_weak (DataType type) {
1585 if (type.value_owned) {
1586 return false;
1587 } else if (type is VoidType || type is PointerType) {
1588 return false;
1589 } else if (type is ValueType) {
1590 if (type.nullable) {
1591 // nullable structs are heap allocated
1592 return true;
1595 // TODO return true for structs with destroy
1596 return false;
1599 return true;
1602 private void write_type (DataType type) {
1603 write_string (type.to_qualified_string (current_scope));
1606 private void write_string (string s) {
1607 stream.printf ("%s", s);
1608 bol = false;
1611 private void write_newline () {
1612 stream.putc ('\n');
1613 bol = true;
1616 void write_code_block (Block? block) {
1617 if (block == null || !dump_tree) {
1618 write_string (";");
1619 return;
1622 block.accept (this);
1625 private void write_begin_block () {
1626 if (!bol) {
1627 stream.putc (' ');
1628 } else {
1629 write_indent ();
1631 stream.putc ('{');
1632 write_newline ();
1633 indent++;
1636 private void write_end_block () {
1637 indent--;
1638 write_indent ();
1639 stream.printf ("}");
1642 private bool check_accessibility (Symbol sym) {
1643 if (dump_tree ||
1644 sym.access == SymbolAccessibility.PUBLIC ||
1645 sym.access == SymbolAccessibility.PROTECTED) {
1646 return true;
1649 return false;
1652 private void write_attributes (CodeNode node) {
1653 foreach (Attribute attr in node.attributes) {
1654 if (!filter_attribute (attr)) {
1655 write_indent ();
1656 stream.printf ("[%s", attr.name);
1658 var keys = attr.args.get_keys ();
1659 if (keys.size != 0) {
1660 stream.printf (" (");
1662 string separator = "";
1663 foreach (string arg_name in keys) {
1664 stream.printf ("%s%s = ", separator, arg_name);
1665 var expr = attr.args.get (arg_name);
1666 expr.accept (this);
1667 separator = ", ";
1670 stream.printf (")");
1672 stream.printf ("]");
1673 write_newline ();
1678 private bool filter_attribute (Attribute attr) {
1679 if (attr.name == "CCode"
1680 || attr.name == "Compact" || attr.name == "Immutable"
1681 || attr.name == "SimpleType" || attr.name == "IntegerType" || attr.name == "FloatingType"
1682 || attr.name == "Flags") {
1683 return true;
1685 return false;
1688 private void write_accessibility (Symbol sym) {
1689 if (sym.access == SymbolAccessibility.PUBLIC) {
1690 write_string ("public ");
1691 } else if (sym.access == SymbolAccessibility.PROTECTED) {
1692 write_string ("protected ");
1693 } else if (sym.access == SymbolAccessibility.INTERNAL) {
1694 write_string ("internal ");
1695 } else if (sym.access == SymbolAccessibility.PRIVATE) {
1696 write_string ("private ");