posix.vapi: signal is allowed to be null (restoring the original handler)
[vala-lang.git] / vala / valacodewriter.vala
blobf6a56ea9f3c13ca727970799997c7d3e5d145fb3
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_indent ();
87 write_string ("namespace ");
88 write_identifier (ns.name);
89 write_begin_block ();
91 current_scope = ns.scope;
93 visit_sorted (ns.get_namespaces ());
94 visit_sorted (ns.get_classes ());
95 visit_sorted (ns.get_interfaces ());
96 visit_sorted (ns.get_structs ());
97 visit_sorted (ns.get_enums ());
98 visit_sorted (ns.get_error_domains ());
99 visit_sorted (ns.get_delegates ());
100 visit_sorted (ns.get_fields ());
101 visit_sorted (ns.get_constants ());
102 visit_sorted (ns.get_methods ());
104 current_scope = current_scope.parent_scope;
106 write_end_block ();
107 write_newline ();
110 public override void visit_class (Class cl) {
111 if (cl.external_package) {
112 return;
115 if (!check_accessibility (cl)) {
116 return;
119 if (cl.is_compact) {
120 write_indent ();
121 write_string ("[Compact]");
122 write_newline ();
125 if (cl.is_immutable) {
126 write_indent ();
127 write_string ("[Immutable]");
128 write_newline ();
131 write_indent ();
133 write_string ("[CCode (");
135 if (cl.is_reference_counting ()) {
136 if (cl.base_class == null || cl.base_class.get_ref_function () == null || cl.base_class.get_ref_function () != cl.get_ref_function ()) {
137 write_string ("ref_function = \"%s\", ".printf (cl.get_ref_function ()));
138 if (cl.ref_function_void) {
139 write_string ("ref_function_void = true, ");
142 if (cl.base_class == null || cl.base_class.get_unref_function () == null || cl.base_class.get_unref_function () != cl.get_unref_function ()) {
143 write_string ("unref_function = \"%s\", ".printf (cl.get_unref_function ()));
145 } else {
146 if (cl.get_dup_function () != null) {
147 write_string ("copy_function = \"%s\", ".printf (cl.get_dup_function ()));
149 if (cl.get_free_function () != cl.get_default_free_function ()) {
150 write_string ("free_function = \"%s\", ".printf (cl.get_free_function ()));
154 if (cl.get_cname () != cl.get_default_cname ()) {
155 write_string ("cname = \"%s\", ".printf (cl.get_cname ()));
158 if (cl.type_check_function != null) {
159 write_string ("type_check_function = \"%s\", ".printf (cl.type_check_function ));
162 if (cl.is_compact && cl.get_type_id () != "G_TYPE_POINTER") {
163 write_string ("type_id = \"%s\", ".printf (cl.get_type_id ()));
166 if (cl.get_param_spec_function () != null
167 && (cl.base_class == null || cl.get_param_spec_function () != cl.base_class.get_param_spec_function ())) {
168 write_string ("param_spec_function = \"%s\", ".printf (cl.get_param_spec_function ()));
171 bool first = true;
172 string cheaders = "";
173 foreach (string cheader in cl.get_cheader_filenames ()) {
174 if (first) {
175 cheaders = cheader;
176 first = false;
177 } else {
178 cheaders = "%s,%s".printf (cheaders, cheader);
181 write_string ("cheader_filename = \"%s\")]".printf (cheaders));
182 write_newline ();
184 write_indent ();
185 write_accessibility (cl);
186 if (cl.is_abstract) {
187 write_string ("abstract ");
189 write_string ("class ");
190 write_identifier (cl.name);
192 var type_params = cl.get_type_parameters ();
193 if (type_params.size > 0) {
194 write_string ("<");
195 first = true;
196 foreach (TypeParameter type_param in type_params) {
197 if (first) {
198 first = false;
199 } else {
200 write_string (",");
202 write_identifier (type_param.name);
204 write_string (">");
207 var base_types = cl.get_base_types ();
208 if (base_types.size > 0) {
209 write_string (" : ");
211 first = true;
212 foreach (DataType base_type in base_types) {
213 if (!first) {
214 write_string (", ");
215 } else {
216 first = false;
218 write_type (base_type);
221 write_begin_block ();
223 current_scope = cl.scope;
225 visit_sorted (cl.get_classes ());
226 visit_sorted (cl.get_structs ());
227 visit_sorted (cl.get_enums ());
228 visit_sorted (cl.get_delegates ());
229 visit_sorted (cl.get_fields ());
230 visit_sorted (cl.get_constants ());
231 visit_sorted (cl.get_methods ());
232 visit_sorted (cl.get_properties ());
233 visit_sorted (cl.get_signals ());
235 current_scope = current_scope.parent_scope;
237 write_end_block ();
238 write_newline ();
241 void visit_sorted (Gee.List<Symbol> symbols) {
242 var sorted_symbols = new Gee.ArrayList<Symbol> ();
243 foreach (Symbol sym in symbols) {
244 int left = 0;
245 int right = sorted_symbols.size - 1;
246 if (left > right || sym.name < sorted_symbols[left].name) {
247 sorted_symbols.insert (0, sym);
248 } else if (sym.name > sorted_symbols[right].name) {
249 sorted_symbols.add (sym);
250 } else {
251 while (right - left > 1) {
252 int i = (right + left) / 2;
253 if (sym.name > sorted_symbols[i].name) {
254 left = i;
255 } else {
256 right = i;
259 sorted_symbols.insert (left + 1, sym);
262 foreach (Symbol sym in sorted_symbols) {
263 sym.accept (this);
267 public override void visit_struct (Struct st) {
268 if (st.external_package) {
269 return;
272 if (!check_accessibility (st)) {
273 return;
276 write_indent ();
278 write_string ("[CCode (");
280 if (st.get_cname () != st.get_default_cname ()) {
281 write_string ("cname = \"%s\", ".printf (st.get_cname ()));
284 if (!st.is_simple_type () && st.get_type_id () != "G_TYPE_POINTER") {
285 write_string ("type_id = \"%s\", ".printf (st.get_type_id ()));
288 if (!st.use_const) {
289 write_string ("use_const = false, ");
292 bool first = true;
293 string cheaders = "";
294 foreach (string cheader in st.get_cheader_filenames ()) {
295 if (first) {
296 cheaders = cheader;
297 first = false;
298 } else {
299 cheaders = "%s,%s".printf (cheaders, cheader);
302 write_string ("cheader_filename = \"%s\")]".printf (cheaders));
303 write_newline ();
305 if (st.is_simple_type ()) {
306 write_indent ();
307 write_string ("[SimpleType]");
308 write_newline ();
311 if (st.is_integer_type ()) {
312 write_indent ();
313 write_string ("[IntegerType (rank = %d)]".printf (st.get_rank ()));
314 write_newline ();
317 if (st.is_floating_type ()) {
318 write_indent ();
319 write_string ("[FloatingType (rank = %d)]".printf (st.get_rank ()));
320 write_newline ();
323 write_indent ();
324 write_accessibility (st);
325 write_string ("struct ");
326 write_identifier (st.name);
328 if (st.base_type != null) {
329 write_string (" : ");
330 write_type (st.base_type);
333 write_begin_block ();
335 current_scope = st.scope;
337 foreach (Field field in st.get_fields ()) {
338 field.accept (this);
340 visit_sorted (st.get_constants ());
341 visit_sorted (st.get_methods ());
343 current_scope = current_scope.parent_scope;
345 write_end_block ();
346 write_newline ();
349 public override void visit_interface (Interface iface) {
350 if (iface.external_package) {
351 return;
354 if (!check_accessibility (iface)) {
355 return;
358 write_indent ();
360 bool first = true;
361 string cheaders = "";
362 foreach (string cheader in iface.get_cheader_filenames ()) {
363 if (first) {
364 cheaders = cheader;
365 first = false;
366 } else {
367 cheaders = "%s,%s".printf (cheaders, cheader);
370 write_string ("[CCode (cheader_filename = \"%s\"".printf (cheaders));
371 if (iface.get_lower_case_csuffix () != iface.get_default_lower_case_csuffix ())
372 write_string (", lower_case_csuffix = \"%s\"".printf (iface.get_lower_case_csuffix ()));
374 write_string (")]");
375 write_newline ();
377 write_indent ();
378 write_accessibility (iface);
379 write_string ("interface ");
380 write_identifier (iface.name);
382 var type_params = iface.get_type_parameters ();
383 if (type_params.size > 0) {
384 write_string ("<");
385 first = true;
386 foreach (TypeParameter type_param in type_params) {
387 if (first) {
388 first = false;
389 } else {
390 write_string (",");
392 write_identifier (type_param.name);
394 write_string (">");
397 var prerequisites = iface.get_prerequisites ();
398 if (prerequisites.size > 0) {
399 write_string (" : ");
401 first = true;
402 foreach (DataType prerequisite in prerequisites) {
403 if (!first) {
404 write_string (", ");
405 } else {
406 first = false;
408 write_type (prerequisite);
411 write_begin_block ();
413 current_scope = iface.scope;
415 visit_sorted (iface.get_classes ());
416 visit_sorted (iface.get_structs ());
417 visit_sorted (iface.get_enums ());
418 visit_sorted (iface.get_delegates ());
419 visit_sorted (iface.get_fields ());
420 visit_sorted (iface.get_methods ());
421 visit_sorted (iface.get_properties ());
422 visit_sorted (iface.get_signals ());
424 current_scope = current_scope.parent_scope;
426 write_end_block ();
427 write_newline ();
430 public override void visit_enum (Enum en) {
431 if (en.external_package) {
432 return;
435 if (!check_accessibility (en)) {
436 return;
439 write_indent ();
441 bool first = true;
442 string cheaders = "";
443 foreach (string cheader in en.get_cheader_filenames ()) {
444 if (first) {
445 cheaders = cheader;
446 first = false;
447 } else {
448 cheaders = "%s,%s".printf (cheaders, cheader);
452 write_string ("[CCode (cprefix = \"%s\", ".printf (en.get_cprefix ()));
454 if (!en.has_type_id) {
455 write_string ("has_type_id = \"%d\", ".printf (en.has_type_id ? 1 : 0));
458 write_string ("cheader_filename = \"%s\")]".printf (cheaders));
460 if (en.is_flags) {
461 write_indent ();
462 write_string ("[Flags]");
465 write_indent ();
466 write_accessibility (en);
467 write_string ("enum ");
468 write_identifier (en.name);
469 write_begin_block ();
471 first = true;
472 foreach (EnumValue ev in en.get_values ()) {
473 if (first) {
474 first = false;
475 } else {
476 write_string (",");
477 write_newline ();
480 if (ev.get_cname () != ev.get_default_cname ()) {
481 write_indent ();
482 write_string ("[CCode (cname = \"%s\")]".printf (ev.get_cname ()));
484 write_indent ();
485 write_identifier (ev.name);
488 if (!first) {
489 if (en.get_methods ().size > 0) {
490 write_string (";");
492 write_newline ();
495 current_scope = en.scope;
496 foreach (Method m in en.get_methods ()) {
497 m.accept (this);
499 current_scope = current_scope.parent_scope;
501 write_end_block ();
502 write_newline ();
505 public override void visit_error_domain (ErrorDomain edomain) {
506 if (edomain.external_package) {
507 return;
510 if (!check_accessibility (edomain)) {
511 return;
514 write_indent ();
516 var first = true;
517 string cheaders = "";
518 foreach (string cheader in edomain.get_cheader_filenames ()) {
519 if (first) {
520 cheaders = cheader;
521 first = false;
522 } else {
523 cheaders = "%s,%s".printf (cheaders, cheader);
526 write_string ("[CCode (cprefix = \"%s\", cheader_filename = \"%s\")]".printf (edomain.get_cprefix (), cheaders));
528 write_indent ();
529 write_accessibility (edomain);
530 write_string ("errordomain ");
531 write_identifier (edomain.name);
532 write_begin_block ();
534 edomain.accept_children (this);
536 write_end_block ();
537 write_newline ();
540 public override void visit_error_code (ErrorCode ecode) {
541 write_indent ();
542 write_identifier (ecode.name);
543 write_string (",");
544 write_newline ();
547 public override void visit_constant (Constant c) {
548 if (c.external_package) {
549 return;
552 if (!check_accessibility (c)) {
553 return;
556 bool custom_cname = (c.get_cname () != c.get_default_cname ());
557 bool custom_cheaders = (c.parent_symbol is Namespace);
558 if (custom_cname || custom_cheaders) {
559 write_indent ();
560 write_string ("[CCode (");
562 if (custom_cname) {
563 write_string ("cname = \"%s\"".printf (c.get_cname ()));
566 if (custom_cheaders) {
567 if (custom_cname) {
568 write_string (", ");
571 bool first = true;
572 string cheaders = "";
573 foreach (string cheader in c.get_cheader_filenames ()) {
574 if (first) {
575 cheaders = cheader;
576 first = false;
577 } else {
578 cheaders = "%s,%s".printf (cheaders, cheader);
581 write_string ("cheader_filename = \"%s\"".printf (cheaders));
584 write_string (")]");
587 write_indent ();
588 write_accessibility (c);
589 write_string ("const ");
591 write_type (c.type_reference);
593 write_string (" ");
594 write_identifier (c.name);
595 write_string (";");
596 write_newline ();
599 public override void visit_field (Field f) {
600 if (f.external_package) {
601 return;
604 if (!check_accessibility (f)) {
605 return;
608 bool custom_cname = (f.get_cname () != f.get_default_cname ());
609 bool custom_ctype = (f.get_ctype () != null);
610 bool custom_cheaders = (f.parent_symbol is Namespace);
611 if (custom_cname || custom_ctype || custom_cheaders || (f.no_array_length && f.field_type is ArrayType)) {
612 write_indent ();
613 write_string ("[CCode (");
615 if (custom_cname) {
616 write_string ("cname = \"%s\"".printf (f.get_cname ()));
619 if (custom_ctype) {
620 if (custom_cname) {
621 write_string (", ");
624 write_string ("type = \"%s\"".printf (f.get_ctype ()));
627 if (custom_cheaders) {
628 if (custom_cname || custom_ctype) {
629 write_string (", ");
632 bool first = true;
633 string cheaders = "";
634 foreach (string cheader in f.get_cheader_filenames ()) {
635 if (first) {
636 cheaders = cheader;
637 first = false;
638 } else {
639 cheaders = "%s,%s".printf (cheaders, cheader);
642 write_string ("cheader_filename = \"%s\"".printf (cheaders));
645 if (f.no_array_length && f.field_type is ArrayType) {
646 if (custom_cname || custom_ctype || custom_cheaders) {
647 write_string (", ");
650 write_string ("array_length = false");
653 write_string (")]");
656 write_indent ();
657 write_accessibility (f);
659 if (f.binding == MemberBinding.STATIC) {
660 write_string ("static ");
661 } else if (f.binding == MemberBinding.CLASS) {
662 write_string ("class ");
665 if (is_weak (f.field_type)) {
666 write_string ("weak ");
669 write_type (f.field_type);
671 write_string (" ");
672 write_identifier (f.name);
673 write_string (";");
674 write_newline ();
677 private void write_error_domains (Gee.List<DataType> error_domains) {
678 if (error_domains.size > 0) {
679 write_string (" throws ");
681 bool first = true;
682 foreach (DataType type in error_domains) {
683 if (!first) {
684 write_string (", ");
685 } else {
686 first = false;
689 write_type (type);
694 // equality comparison with 3 digit precision
695 private bool float_equal (double d1, double d2) {
696 return ((int) (d1 * 1000)) == ((int) (d2 * 1000));
699 private void write_params (Gee.List<FormalParameter> params) {
700 write_string ("(");
702 int i = 1;
703 foreach (FormalParameter param in params) {
704 if (i > 1) {
705 write_string (", ");
708 if (param.ellipsis) {
709 write_string ("...");
710 continue;
714 var ccode_params = new StringBuilder ();
715 var separator = "";
717 if (param.ctype != null) {
718 ccode_params.append_printf ("%stype = \"%s\"", separator, param.ctype);
719 separator = ", ";
721 if (param.no_array_length && param.parameter_type is ArrayType) {
722 ccode_params.append_printf ("%sarray_length = false", separator);
723 separator = ", ";
725 if (!float_equal (param.carray_length_parameter_position, i + 0.1)) {
726 ccode_params.append_printf ("%sarray_length_pos = %g", separator, param.carray_length_parameter_position);
727 separator = ", ";
729 if (!float_equal (param.cdelegate_target_parameter_position, i + 0.1)) {
730 ccode_params.append_printf ("%sdelegate_target_pos = %g", separator, param.cdelegate_target_parameter_position);
731 separator = ", ";
733 if (param.async_only) {
734 ccode_params.append_printf ("%sasync_only = true", separator);
735 separator = ", ";
738 if (ccode_params.len > 0) {
739 write_string ("[CCode (%s)] ".printf (ccode_params.str));
742 if (param.params_array) {
743 write_string ("params ");
746 if (param.direction == ParameterDirection.IN) {
747 if (param.parameter_type.value_owned) {
748 write_string ("owned ");
750 } else {
751 if (param.direction == ParameterDirection.REF) {
752 write_string ("ref ");
753 } else if (param.direction == ParameterDirection.OUT) {
754 write_string ("out ");
756 if (is_weak (param.parameter_type)) {
757 write_string ("unowned ");
761 write_type (param.parameter_type);
763 write_string (" ");
764 write_identifier (param.name);
766 if (param.default_expression != null) {
767 write_string (" = ");
768 write_string (param.default_expression.to_string ());
771 i++;
774 write_string (")");
777 public override void visit_delegate (Delegate cb) {
778 if (cb.external_package) {
779 return;
782 if (!check_accessibility (cb)) {
783 return;
786 write_indent ();
788 var first = true;
789 string cheaders = "";
790 foreach (string cheader in cb.get_cheader_filenames ()) {
791 if (first) {
792 cheaders = cheader;
793 first = false;
794 } else {
795 cheaders = "%s,%s".printf (cheaders, cheader);
798 write_string ("[CCode (cheader_filename = \"%s\")]".printf (cheaders));
800 write_indent ();
802 write_accessibility (cb);
803 if (!cb.has_target) {
804 write_string ("static ");
806 write_string ("delegate ");
808 write_return_type (cb.return_type);
810 write_string (" ");
811 write_identifier (cb.name);
813 write_string (" ");
815 write_params (cb.get_parameters ());
817 write_string (";");
819 write_newline ();
822 public override void visit_method (Method m) {
823 if (m.external_package) {
824 return;
827 // don't write interface implementation unless it's an abstract or virtual method
828 if (!check_accessibility (m) || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
829 if (!dump_tree) {
830 return;
834 if (m.get_attribute ("NoWrapper") != null) {
835 write_indent ();
836 write_string ("[NoWrapper]");
838 if (m.returns_modified_pointer) {
839 write_indent ();
840 write_string ("[ReturnsModifiedPointer]");
843 var ccode_params = new StringBuilder ();
844 var separator = "";
846 if (m.get_cname () != m.get_default_cname ()) {
847 ccode_params.append_printf ("%scname = \"%s\"", separator, m.get_cname ());
848 separator = ", ";
850 if (m.parent_symbol is Namespace) {
851 bool first = true;
852 string cheaders = "";
853 foreach (string cheader in m.get_cheader_filenames ()) {
854 if (first) {
855 cheaders = cheader;
856 first = false;
857 } else {
858 cheaders = "%s,%s".printf (cheaders, cheader);
861 ccode_params.append_printf ("%scheader_filename = \"%s\"", separator, cheaders);
862 separator = ", ";
864 if (!float_equal (m.cinstance_parameter_position, 0)) {
865 ccode_params.append_printf ("%sinstance_pos = %g", separator, m.cinstance_parameter_position);
866 separator = ", ";
868 if (m.no_array_length && m.return_type is ArrayType) {
869 ccode_params.append_printf ("%sarray_length = false", separator);
870 separator = ", ";
872 if (!float_equal (m.carray_length_parameter_position, -3)) {
873 ccode_params.append_printf ("%sarray_length_pos = %g", separator, m.carray_length_parameter_position);
874 separator = ", ";
876 if (m.array_null_terminated && m.return_type is ArrayType) {
877 ccode_params.append_printf ("%sarray_null_terminated = true", separator);
878 separator = ", ";
880 if (!float_equal (m.cdelegate_target_parameter_position, -3)) {
881 ccode_params.append_printf ("%sdelegate_target_pos = %g", separator, m.cdelegate_target_parameter_position);
882 separator = ", ";
884 if (m.vfunc_name != m.name) {
885 ccode_params.append_printf ("%svfunc_name = \"%s\"", separator, m.vfunc_name);
886 separator = ", ";
888 if (m.sentinel != m.DEFAULT_SENTINEL) {
889 ccode_params.append_printf ("%ssentinel = \"%s\"", separator, m.sentinel);
890 separator = ", ";
892 if (m is CreationMethod && ((CreationMethod)m).custom_return_type_cname != null) {
893 ccode_params.append_printf ("%stype = \"%s\"", separator, ((CreationMethod)m).custom_return_type_cname);
894 separator = ", ";
896 if (m is CreationMethod && !m.has_construct_function) {
897 ccode_params.append_printf ("%shas_construct_function = false", separator);
898 separator = ", ";
901 if (ccode_params.len > 0) {
902 write_indent ();
903 write_string ("[CCode (%s)]".printf (ccode_params.str));
906 write_indent ();
907 write_accessibility (m);
909 if (m is CreationMethod) {
910 var datatype = (TypeSymbol) m.parent_symbol;
911 write_identifier (datatype.name);
912 if (m.name != "new") {
913 write_string (".");
914 write_identifier (m.name);
916 write_string (" ");
917 } else if (m.binding == MemberBinding.STATIC) {
918 write_string ("static ");
919 } else if (m.binding == MemberBinding.CLASS) {
920 write_string ("class ");
921 } else if (m.is_abstract) {
922 write_string ("abstract ");
923 } else if (m.is_virtual) {
924 write_string ("virtual ");
925 } else if (m.overrides) {
926 write_string ("override ");
929 if (!(m is CreationMethod)) {
930 write_return_type (m.return_type);
931 write_string (" ");
933 write_identifier (m.name);
934 write_string (" ");
937 write_params (m.get_parameters ());
938 write_error_domains (m.get_error_types ());
940 write_code_block (m.body);
942 write_newline ();
945 public override void visit_creation_method (CreationMethod m) {
946 visit_method (m);
949 public override void visit_property (Property prop) {
950 if (!check_accessibility (prop) || (prop.base_interface_property != null && !prop.is_abstract && !prop.is_virtual)) {
951 return;
954 if (prop.no_accessor_method) {
955 write_indent ();
956 write_string ("[NoAccessorMethod]");
959 write_indent ();
960 write_accessibility (prop);
962 if (prop.binding == MemberBinding.STATIC) {
963 write_string ("static ");
964 } else if (prop.is_abstract) {
965 write_string ("abstract ");
966 } else if (prop.is_virtual) {
967 write_string ("virtual ");
968 } else if (prop.overrides) {
969 write_string ("override ");
972 write_type (prop.property_type);
974 write_string (" ");
975 write_identifier (prop.name);
976 write_string (" {");
977 if (prop.get_accessor != null) {
978 if (prop.get_accessor.value_type.is_disposable ()) {
979 write_string (" owned");
982 write_string (" get");
983 write_code_block (prop.get_accessor.body);
985 if (prop.set_accessor != null) {
986 if (prop.set_accessor.value_type.value_owned) {
987 write_string ("owned ");
990 if (prop.set_accessor.writable) {
991 write_string (" set");
993 if (prop.set_accessor.construction) {
994 write_string (" construct");
996 write_code_block (prop.set_accessor.body);
998 write_string (" }");
999 write_newline ();
1002 public override void visit_signal (Signal sig) {
1003 if (!check_accessibility (sig)) {
1004 return;
1007 if (sig.has_emitter) {
1008 write_indent ();
1009 write_string ("[HasEmitter]");
1012 write_indent ();
1013 write_accessibility (sig);
1015 if (sig.is_virtual) {
1016 write_string ("virtual ");
1019 write_string ("signal ");
1021 write_return_type (sig.return_type);
1023 write_string (" ");
1024 write_identifier (sig.name);
1026 write_string (" ");
1028 write_params (sig.get_parameters ());
1030 write_string (";");
1032 write_newline ();
1035 public override void visit_block (Block b) {
1036 write_begin_block ();
1038 foreach (Statement stmt in b.get_statements ()) {
1039 stmt.accept (this);
1042 write_end_block ();
1045 public override void visit_empty_statement (EmptyStatement stmt) {
1048 public override void visit_declaration_statement (DeclarationStatement stmt) {
1049 write_indent ();
1050 stmt.declaration.accept (this);
1051 write_string (";");
1052 write_newline ();
1055 public override void visit_local_variable (LocalVariable local) {
1056 write_type (local.variable_type);
1057 write_string (" ");
1058 write_identifier (local.name);
1059 if (local.initializer != null) {
1060 write_string (" = ");
1061 local.initializer.accept (this);
1065 public override void visit_initializer_list (InitializerList list) {
1066 write_string ("{");
1068 bool first = true;
1069 foreach (Expression initializer in list.get_initializers ()) {
1070 if (!first) {
1071 write_string (", ");
1072 } else {
1073 write_string (" ");
1075 first = false;
1076 initializer.accept (this);
1078 write_string (" }");
1081 public override void visit_expression_statement (ExpressionStatement stmt) {
1082 write_indent ();
1083 stmt.expression.accept (this);
1084 write_string (";");
1085 write_newline ();
1088 public override void visit_if_statement (IfStatement stmt) {
1089 write_indent ();
1090 write_string ("if (");
1091 stmt.condition.accept (this);
1092 write_string (")");
1093 stmt.true_statement.accept (this);
1094 if (stmt.false_statement != null) {
1095 write_string (" else");
1096 stmt.false_statement.accept (this);
1098 write_newline ();
1101 public override void visit_switch_statement (SwitchStatement stmt) {
1102 write_indent ();
1103 write_string ("switch (");
1104 stmt.expression.accept (this);
1105 write_string (") {");
1106 write_newline ();
1108 foreach (SwitchSection section in stmt.get_sections ()) {
1109 section.accept (this);
1112 write_indent ();
1113 write_string ("}");
1114 write_newline ();
1117 public override void visit_switch_section (SwitchSection section) {
1118 foreach (SwitchLabel label in section.get_labels ()) {
1119 label.accept (this);
1122 visit_block (section);
1125 public override void visit_switch_label (SwitchLabel label) {
1126 if (label.expression != null) {
1127 write_indent ();
1128 write_string ("case ");
1129 label.expression.accept (this);
1130 write_string (":");
1131 write_newline ();
1132 } else {
1133 write_indent ();
1134 write_string ("default:");
1135 write_newline ();
1139 public override void visit_while_statement (WhileStatement stmt) {
1140 write_indent ();
1141 write_string ("while (");
1142 stmt.condition.accept (this);
1143 write_string (")");
1144 stmt.body.accept (this);
1145 write_newline ();
1148 public override void visit_do_statement (DoStatement stmt) {
1149 write_indent ();
1150 write_string ("do");
1151 stmt.body.accept (this);
1152 write_string ("while (");
1153 stmt.condition.accept (this);
1154 write_string (");");
1155 write_newline ();
1158 public override void visit_for_statement (ForStatement stmt) {
1159 write_indent ();
1160 write_string ("for (");
1162 bool first = true;
1163 foreach (Expression initializer in stmt.get_initializer ()) {
1164 if (!first) {
1165 write_string (", ");
1167 first = false;
1168 initializer.accept (this);
1170 write_string ("; ");
1172 stmt.condition.accept (this);
1173 write_string ("; ");
1175 first = true;
1176 foreach (Expression iterator in stmt.get_iterator ()) {
1177 if (!first) {
1178 write_string (", ");
1180 first = false;
1181 iterator.accept (this);
1184 write_string (")");
1185 stmt.body.accept (this);
1186 write_newline ();
1189 public override void visit_foreach_statement (ForeachStatement stmt) {
1192 public override void visit_break_statement (BreakStatement stmt) {
1193 write_indent ();
1194 write_string ("break;");
1195 write_newline ();
1198 public override void visit_continue_statement (ContinueStatement stmt) {
1199 write_indent ();
1200 write_string ("continue;");
1201 write_newline ();
1204 public override void visit_return_statement (ReturnStatement stmt) {
1205 write_indent ();
1206 write_string ("return");
1207 if (stmt.return_expression != null) {
1208 write_string (" ");
1209 stmt.return_expression.accept (this);
1211 write_string (";");
1212 write_newline ();
1215 public override void visit_yield_statement (YieldStatement y) {
1216 write_indent ();
1217 write_string ("yield");
1218 if (y.yield_expression != null) {
1219 write_string (" ");
1220 y.yield_expression.accept (this);
1222 write_string (";");
1223 write_newline ();
1226 public override void visit_throw_statement (ThrowStatement stmt) {
1227 write_indent ();
1228 write_string ("throw");
1229 if (stmt.error_expression != null) {
1230 write_string (" ");
1231 stmt.error_expression.accept (this);
1233 write_string (";");
1234 write_newline ();
1237 public override void visit_try_statement (TryStatement stmt) {
1238 write_indent ();
1239 write_string ("try");
1240 stmt.body.accept (this);
1241 write_newline ();
1244 public override void visit_catch_clause (CatchClause clause) {
1247 public override void visit_lock_statement (LockStatement stmt) {
1250 public override void visit_delete_statement (DeleteStatement stmt) {
1253 public override void visit_array_creation_expression (ArrayCreationExpression expr) {
1254 write_string ("new ");
1255 write_type (expr.element_type);
1256 write_string ("[");
1258 bool first = true;
1259 foreach (Expression size in expr.get_sizes ()) {
1260 if (!first) {
1261 write_string (", ");
1263 first = false;
1265 size.accept (this);
1268 write_string ("]");
1270 if (expr.initializer_list != null) {
1271 write_string (" ");
1272 expr.initializer_list.accept (this);
1276 public override void visit_boolean_literal (BooleanLiteral lit) {
1277 write_string (lit.value.to_string ());
1280 public override void visit_character_literal (CharacterLiteral lit) {
1281 write_string (lit.value);
1284 public override void visit_integer_literal (IntegerLiteral lit) {
1285 write_string (lit.value);
1288 public override void visit_real_literal (RealLiteral lit) {
1289 write_string (lit.value);
1292 public override void visit_string_literal (StringLiteral lit) {
1293 write_string (lit.value);
1296 public override void visit_null_literal (NullLiteral lit) {
1297 write_string ("null");
1300 public override void visit_member_access (MemberAccess expr) {
1301 if (expr.inner != null) {
1302 expr.inner.accept (this);
1303 write_string (".");
1305 write_identifier (expr.member_name);
1308 public override void visit_method_call (MethodCall expr) {
1309 expr.call.accept (this);
1310 write_string (" (");
1312 bool first = true;
1313 foreach (Expression arg in expr.get_argument_list ()) {
1314 if (!first) {
1315 write_string (", ");
1317 first = false;
1319 arg.accept (this);
1322 write_string (")");
1325 public override void visit_element_access (ElementAccess expr) {
1326 expr.container.accept (this);
1327 write_string ("[");
1329 bool first = true;
1330 foreach (Expression index in expr.get_indices ()) {
1331 if (!first) {
1332 write_string (", ");
1334 first = false;
1336 index.accept (this);
1339 write_string ("]");
1342 public override void visit_base_access (BaseAccess expr) {
1343 write_string ("base");
1346 public override void visit_postfix_expression (PostfixExpression expr) {
1347 expr.inner.accept (this);
1348 if (expr.increment) {
1349 write_string ("++");
1350 } else {
1351 write_string ("--");
1355 public override void visit_object_creation_expression (ObjectCreationExpression expr) {
1356 write_string ("new ");
1357 write_type (expr.type_reference);
1358 write_string (" (");
1360 bool first = true;
1361 foreach (Expression arg in expr.get_argument_list ()) {
1362 if (!first) {
1363 write_string (", ");
1365 first = false;
1367 arg.accept (this);
1370 write_string (")");
1373 public override void visit_sizeof_expression (SizeofExpression expr) {
1374 write_string ("sizeof (");
1375 write_type (expr.type_reference);
1376 write_string (")");
1379 public override void visit_typeof_expression (TypeofExpression expr) {
1380 write_string ("typeof (");
1381 write_type (expr.type_reference);
1382 write_string (")");
1385 public override void visit_unary_expression (UnaryExpression expr) {
1386 switch (expr.operator) {
1387 case UnaryOperator.PLUS:
1388 write_string ("+");
1389 break;
1390 case UnaryOperator.MINUS:
1391 write_string ("-");
1392 break;
1393 case UnaryOperator.LOGICAL_NEGATION:
1394 write_string ("!");
1395 break;
1396 case UnaryOperator.BITWISE_COMPLEMENT:
1397 write_string ("~");
1398 break;
1399 case UnaryOperator.INCREMENT:
1400 write_string ("++");
1401 break;
1402 case UnaryOperator.DECREMENT:
1403 write_string ("--");
1404 break;
1405 case UnaryOperator.REF:
1406 write_string ("ref ");
1407 break;
1408 case UnaryOperator.OUT:
1409 write_string ("out ");
1410 break;
1411 default:
1412 assert_not_reached ();
1414 expr.inner.accept (this);
1417 public override void visit_cast_expression (CastExpression expr) {
1418 if (!expr.is_silent_cast) {
1419 write_string ("(");
1420 write_type (expr.type_reference);
1421 write_string (") ");
1424 expr.inner.accept (this);
1426 if (expr.is_silent_cast) {
1427 write_string (" as ");
1428 write_type (expr.type_reference);
1432 public override void visit_pointer_indirection (PointerIndirection expr) {
1433 write_string ("*");
1434 expr.inner.accept (this);
1437 public override void visit_addressof_expression (AddressofExpression expr) {
1438 write_string ("&");
1439 expr.inner.accept (this);
1442 public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
1443 write_string ("(owned) ");
1444 expr.inner.accept (this);
1447 public override void visit_binary_expression (BinaryExpression expr) {
1448 expr.left.accept (this);
1450 switch (expr.operator) {
1451 case BinaryOperator.PLUS:
1452 write_string (" + ");
1453 break;
1454 case BinaryOperator.MINUS:
1455 write_string (" - ");
1456 break;
1457 case BinaryOperator.MUL:
1458 write_string (" * ");
1459 break;
1460 case BinaryOperator.DIV:
1461 write_string (" / ");
1462 break;
1463 case BinaryOperator.MOD:
1464 write_string (" % ");
1465 break;
1466 case BinaryOperator.SHIFT_LEFT:
1467 write_string (" << ");
1468 break;
1469 case BinaryOperator.SHIFT_RIGHT:
1470 write_string (" >> ");
1471 break;
1472 case BinaryOperator.LESS_THAN:
1473 write_string (" < ");
1474 break;
1475 case BinaryOperator.GREATER_THAN:
1476 write_string (" > ");
1477 break;
1478 case BinaryOperator.LESS_THAN_OR_EQUAL:
1479 write_string (" <= ");
1480 break;
1481 case BinaryOperator.GREATER_THAN_OR_EQUAL:
1482 write_string (" >= ");
1483 break;
1484 case BinaryOperator.EQUALITY:
1485 write_string (" == ");
1486 break;
1487 case BinaryOperator.INEQUALITY:
1488 write_string (" != ");
1489 break;
1490 case BinaryOperator.BITWISE_AND:
1491 write_string (" & ");
1492 break;
1493 case BinaryOperator.BITWISE_OR:
1494 write_string (" | ");
1495 break;
1496 case BinaryOperator.BITWISE_XOR:
1497 write_string (" ^ ");
1498 break;
1499 case BinaryOperator.AND:
1500 write_string (" && ");
1501 break;
1502 case BinaryOperator.OR:
1503 write_string (" || ");
1504 break;
1505 case BinaryOperator.IN:
1506 write_string (" in ");
1507 break;
1508 default:
1509 assert_not_reached ();
1512 expr.right.accept (this);
1515 public override void visit_type_check (TypeCheck expr) {
1516 expr.expression.accept (this);
1517 write_string (" is ");
1518 write_type (expr.type_reference);
1521 public override void visit_conditional_expression (ConditionalExpression expr) {
1522 expr.condition.accept (this);
1523 write_string ("?");
1524 expr.true_expression.accept (this);
1525 write_string (":");
1526 expr.false_expression.accept (this);
1529 public override void visit_lambda_expression (LambdaExpression expr) {
1532 public override void visit_assignment (Assignment a) {
1533 a.left.accept (this);
1534 write_string (" = ");
1535 a.right.accept (this);
1538 private void write_indent () {
1539 int i;
1541 if (!bol) {
1542 stream.putc ('\n');
1545 for (i = 0; i < indent; i++) {
1546 stream.putc ('\t');
1549 bol = false;
1552 private void write_identifier (string s) {
1553 if (s == "base" || s == "break" || s == "class" ||
1554 s == "construct" || s == "delegate" || s == "delete" ||
1555 s == "do" || s == "dynamic" || s == "foreach" || s == "in" ||
1556 s == "interface" || s == "lock" || s == "namespace" ||
1557 s == "new" || s == "out" || s == "ref" ||
1558 s == "signal" || s.get_char ().isdigit ()) {
1559 stream.putc ('@');
1561 write_string (s);
1564 private void write_return_type (DataType type) {
1565 if (is_weak (type)) {
1566 write_string ("unowned ");
1569 write_type (type);
1572 private bool is_weak (DataType type) {
1573 if (type.value_owned) {
1574 return false;
1575 } else if (type is VoidType || type is PointerType) {
1576 return false;
1577 } else if (type is ValueType) {
1578 if (type.nullable) {
1579 // nullable structs are heap allocated
1580 return true;
1583 // TODO return true for structs with destroy
1584 return false;
1587 return true;
1590 private void write_type (DataType type) {
1591 write_string (type.to_qualified_string (current_scope));
1594 private void write_string (string s) {
1595 stream.printf ("%s", s);
1596 bol = false;
1599 private void write_newline () {
1600 stream.putc ('\n');
1601 bol = true;
1604 void write_code_block (Block? block) {
1605 if (block == null || !dump_tree) {
1606 write_string (";");
1607 return;
1610 block.accept (this);
1613 private void write_begin_block () {
1614 if (!bol) {
1615 stream.putc (' ');
1616 } else {
1617 write_indent ();
1619 stream.putc ('{');
1620 write_newline ();
1621 indent++;
1624 private void write_end_block () {
1625 indent--;
1626 write_indent ();
1627 stream.printf ("}");
1630 private bool check_accessibility (Symbol sym) {
1631 if (dump_tree ||
1632 sym.access == SymbolAccessibility.PUBLIC ||
1633 sym.access == SymbolAccessibility.PROTECTED) {
1634 return true;
1637 return false;
1640 private void write_accessibility (Symbol sym) {
1641 if (sym.access == SymbolAccessibility.PUBLIC) {
1642 write_string ("public ");
1643 } else if (sym.access == SymbolAccessibility.PROTECTED) {
1644 write_string ("protected ");
1645 } else if (sym.access == SymbolAccessibility.INTERNAL) {
1646 write_string ("internal ");
1647 } else if (sym.access == SymbolAccessibility.PRIVATE) {
1648 write_string ("private ");