girparser: Guess virtual method wrapper variant when possible
[vala-lang.git] / vala / valacodewriter.vala
blob8b3bf7d9f7e9d71cba021a01347937d2124dd154
1 /* valacodewriter.vala
3 * Copyright (C) 2006-2010 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>
26 /**
27 * Code visitor generating Vala API file for the public interface.
29 public class Vala.CodeWriter : CodeVisitor {
30 private CodeContext context;
32 FileStream stream;
34 int indent;
35 /* at begin of line */
36 bool bol = true;
38 Scope current_scope;
40 CodeWriterType type;
42 string? override_header = null;
43 string? header_to_override = null;
45 public CodeWriter (CodeWriterType type = CodeWriterType.EXTERNAL) {
46 this.type = type;
49 /**
50 * Allows overriding of a specific cheader in the output
51 * @param original orignal cheader to override
52 * @param replacement cheader to replace original with
54 public void set_cheader_override (string original, string replacement)
56 header_to_override = original;
57 override_header = replacement;
60 /**
61 * Writes the public interface of the specified code context into the
62 * specified file.
64 * @param context a code context
65 * @param filename a relative or absolute filename
67 public void write_file (CodeContext context, string filename) {
68 var file_exists = FileUtils.test (filename, FileTest.EXISTS);
69 var temp_filename = filename + ".valatmp";
70 this.context = context;
72 if (file_exists) {
73 stream = FileStream.open (temp_filename, "w");
74 } else {
75 stream = FileStream.open (filename, "w");
78 if (stream == null) {
79 Report.error (null, "unable to open `%s' for writing".printf (filename));
80 return;
83 var header = context.version_header ?
84 "/* %s generated by %s %s, do not modify. */".printf (Path.get_basename (filename), Environment.get_prgname (), Config.BUILD_VERSION) :
85 "/* %s generated by %s, do not modify. */".printf (Path.get_basename (filename), Environment.get_prgname ());
86 write_string (header);
87 write_newline ();
88 write_newline ();
90 current_scope = context.root.scope;
92 context.accept (this);
94 current_scope = null;
96 stream = null;
98 if (file_exists) {
99 var changed = true;
101 try {
102 var old_file = new MappedFile (filename, false);
103 var new_file = new MappedFile (temp_filename, false);
104 var len = old_file.get_length ();
105 if (len == new_file.get_length ()) {
106 if (Memory.cmp (old_file.get_contents (), new_file.get_contents (), len) == 0) {
107 changed = false;
110 old_file = null;
111 new_file = null;
112 } catch (FileError e) {
113 // assume changed if mmap comparison doesn't work
116 if (changed) {
117 FileUtils.rename (temp_filename, filename);
118 } else {
119 FileUtils.unlink (temp_filename);
125 public override void visit_using_directive (UsingDirective ns) {
126 if (type == CodeWriterType.FAST) {
127 write_string ("using %s;\n".printf (ns.namespace_symbol.name));
131 public override void visit_namespace (Namespace ns) {
132 if (ns.external_package) {
133 return;
136 if (ns.name == null) {
137 ns.accept_children (this);
138 return;
141 write_indent ();
142 write_string ("[CCode (cprefix = \"%s\", lower_case_cprefix = \"%s\"".printf (ns.get_cprefix (), ns.get_lower_case_cprefix ()));
144 if (ns.source_reference != null) {
145 if (ns.source_reference.file.gir_namespace != null) {
146 write_string (", ");
147 write_string ("gir_namespace = \"%s\"".printf (ns.source_reference.file.gir_namespace));
149 if (ns.source_reference.file.gir_version != null) {
150 write_string(", ");
151 write_string ("gir_version = \"%s\"".printf (ns.source_reference.file.gir_version));
155 write_string (")]");
156 write_newline ();
158 write_attributes (ns);
160 write_indent ();
161 write_string ("namespace ");
162 write_identifier (ns.name);
163 write_begin_block ();
165 current_scope = ns.scope;
167 visit_sorted (ns.get_namespaces ());
168 visit_sorted (ns.get_classes ());
169 visit_sorted (ns.get_interfaces ());
170 visit_sorted (ns.get_structs ());
171 visit_sorted (ns.get_enums ());
172 visit_sorted (ns.get_error_domains ());
173 visit_sorted (ns.get_delegates ());
174 visit_sorted (ns.get_fields ());
175 visit_sorted (ns.get_constants ());
176 visit_sorted (ns.get_methods ());
178 current_scope = current_scope.parent_scope;
180 write_end_block ();
181 write_newline ();
184 private string get_cheaders (Symbol cl) {
185 bool first = true;
186 string cheaders = "";
187 if (type != CodeWriterType.FAST) {
188 foreach (string cheader in cl.get_cheader_filenames ()) {
189 if (header_to_override != null &&
190 cheader == header_to_override) {
191 cheader = override_header;
193 if (first) {
194 cheaders = cheader;
195 first = false;
196 } else {
197 cheaders = "%s,%s".printf (cheaders, cheader);
201 return cheaders;
204 private void emit_deprecated_attribute (Symbol symbol) {
205 if (symbol.deprecated) {
206 write_indent ();
207 write_string ("[Deprecated");
208 var since = symbol.deprecated_since;
209 var replacement = symbol.replacement;
211 if (since != null || replacement != null) {
212 write_string (" (");
213 if (since != null) {
214 write_string ("since = \"%s\"".printf (since));
216 if (since != null && replacement != null) {
217 write_string (", ");
219 if (replacement != null) {
220 write_string ("replacement = \"%s\"".printf (replacement));
222 write_string (")");
224 write_string ("]");
228 public override void visit_class (Class cl) {
229 if (cl.external_package) {
230 return;
233 if (!check_accessibility (cl)) {
234 return;
237 if (cl.is_compact) {
238 write_indent ();
239 write_string ("[Compact]");
240 write_newline ();
243 if (cl.is_immutable) {
244 write_indent ();
245 write_string ("[Immutable]");
246 write_newline ();
249 emit_deprecated_attribute (cl);
251 write_indent ();
253 write_string ("[CCode (");
255 if (cl.is_reference_counting () && type != CodeWriterType.FAST) {
256 if (cl.base_class == null || cl.base_class.get_ref_function () == null || cl.base_class.get_ref_function () != cl.get_ref_function ()) {
257 write_string ("ref_function = \"%s\", ".printf (cl.get_ref_function ()));
258 if (cl.ref_function_void) {
259 write_string ("ref_function_void = true, ");
262 if (cl.base_class == null || cl.base_class.get_unref_function () == null || cl.base_class.get_unref_function () != cl.get_unref_function ()) {
263 write_string ("unref_function = \"%s\", ".printf (cl.get_unref_function ()));
265 } else {
266 if (cl.get_dup_function () != null) {
267 write_string ("copy_function = \"%s\", ".printf (cl.get_dup_function ()));
269 if (cl.get_free_function () != cl.get_default_free_function ()) {
270 write_string ("free_function = \"%s\", ".printf (cl.get_free_function ()));
274 if (cl.get_cname () != cl.get_default_cname ()) {
275 write_string ("cname = \"%s\", ".printf (cl.get_cname ()));
277 if (cl.const_cname != null) {
278 write_string ("const_cname = \"%s\", ".printf (cl.const_cname));
281 if (cl.type_check_function != null) {
282 write_string ("type_check_function = \"%s\", ".printf (cl.type_check_function ));
285 if (cl.get_type_id () != cl.get_default_type_id ()) {
286 write_string ("type_id = \"%s\", ".printf (cl.get_type_id ()));
289 if (cl.get_param_spec_function () != cl.get_default_param_spec_function ()) {
290 write_string ("param_spec_function = \"%s\", ".printf (cl.get_param_spec_function ()));
293 write_string ("cheader_filename = \"%s\")]".printf (get_cheaders(cl)));
294 write_newline ();
296 write_attributes (cl);
298 write_indent ();
299 write_accessibility (cl);
300 if (cl.is_abstract) {
301 write_string ("abstract ");
303 write_string ("class ");
304 write_identifier (cl.name);
306 var type_params = cl.get_type_parameters ();
307 if (type_params.size > 0) {
308 write_string ("<");
309 bool first = true;
310 foreach (TypeParameter type_param in type_params) {
311 if (first) {
312 first = false;
313 } else {
314 write_string (",");
316 write_identifier (type_param.name);
318 write_string (">");
321 var base_types = cl.get_base_types ();
322 if (base_types.size > 0) {
323 write_string (" : ");
325 bool first = true;
326 foreach (DataType base_type in base_types) {
327 if (!first) {
328 write_string (", ");
329 } else {
330 first = false;
332 write_type (base_type);
335 write_begin_block ();
337 current_scope = cl.scope;
339 visit_sorted (cl.get_classes ());
340 visit_sorted (cl.get_structs ());
341 visit_sorted (cl.get_enums ());
342 visit_sorted (cl.get_delegates ());
343 visit_sorted (cl.get_fields ());
344 visit_sorted (cl.get_constants ());
345 visit_sorted (cl.get_methods ());
346 visit_sorted (cl.get_properties ());
347 visit_sorted (cl.get_signals ());
349 if (cl.constructor != null) {
350 cl.constructor.accept (this);
353 current_scope = current_scope.parent_scope;
355 write_end_block ();
356 write_newline ();
359 void visit_sorted (List<Symbol> symbols) {
360 if (type != CodeWriterType.EXTERNAL) {
361 // order of virtual methods matters for fast vapis
362 foreach (Symbol sym in symbols) {
363 sym.accept (this);
365 return;
368 var sorted_symbols = new ArrayList<Symbol> ();
369 foreach (Symbol sym in symbols) {
370 int left = 0;
371 int right = sorted_symbols.size - 1;
372 if (left > right || sym.name < sorted_symbols[left].name) {
373 sorted_symbols.insert (0, sym);
374 } else if (sym.name > sorted_symbols[right].name) {
375 sorted_symbols.add (sym);
376 } else {
377 while (right - left > 1) {
378 int i = (right + left) / 2;
379 if (sym.name > sorted_symbols[i].name) {
380 left = i;
381 } else {
382 right = i;
385 sorted_symbols.insert (left + 1, sym);
388 foreach (Symbol sym in sorted_symbols) {
389 sym.accept (this);
393 public override void visit_struct (Struct st) {
394 if (st.external_package) {
395 return;
398 if (!check_accessibility (st)) {
399 return;
402 if (st.is_immutable) {
403 write_indent ();
404 write_string ("[Immutable]");
405 write_newline ();
408 emit_deprecated_attribute (st);
410 write_indent ();
412 write_string ("[CCode (");
414 if (st.get_cname () != st.get_default_cname ()) {
415 write_string ("cname = \"%s\", ".printf (st.get_cname ()));
418 if (!st.has_type_id) {
419 write_string ("has_type_id = false, ");
420 } else if (!st.is_simple_type () && st.get_type_id () != "G_TYPE_POINTER") {
421 write_string ("type_id = \"%s\", ".printf (st.get_type_id ()));
424 if (!st.has_copy_function) {
425 write_string ("has_copy_function = false, ");
428 if (!st.has_destroy_function) {
429 write_string ("has_destroy_function = false, ");
432 write_string ("cheader_filename = \"%s\")]".printf (get_cheaders(st)));
433 write_newline ();
435 if (st.is_simple_type ()) {
436 write_indent ();
437 write_string ("[SimpleType]");
438 write_newline ();
441 if (st.is_integer_type ()) {
442 write_indent ();
443 write_string ("[IntegerType (rank = %d)]".printf (st.get_rank ()));
444 write_newline ();
447 if (st.is_floating_type ()) {
448 write_indent ();
449 write_string ("[FloatingType (rank = %d)]".printf (st.get_rank ()));
450 write_newline ();
453 write_attributes (st);
455 write_indent ();
456 write_accessibility (st);
457 write_string ("struct ");
458 write_identifier (st.name);
460 if (st.base_type != null) {
461 write_string (" : ");
462 write_type (st.base_type);
465 write_begin_block ();
467 current_scope = st.scope;
469 foreach (Field field in st.get_fields ()) {
470 field.accept (this);
472 visit_sorted (st.get_constants ());
473 visit_sorted (st.get_methods ());
474 visit_sorted (st.get_properties ());
476 current_scope = current_scope.parent_scope;
478 write_end_block ();
479 write_newline ();
482 public override void visit_interface (Interface iface) {
483 if (iface.external_package) {
484 return;
487 if (!check_accessibility (iface)) {
488 return;
491 emit_deprecated_attribute (iface);
493 write_indent ();
495 write_string ("[CCode (cheader_filename = \"%s\"".printf (get_cheaders(iface)));
496 if (iface.get_lower_case_csuffix () != iface.get_default_lower_case_csuffix ())
497 write_string (", lower_case_csuffix = \"%s\"".printf (iface.get_lower_case_csuffix ()));
499 write_string (")]");
500 write_newline ();
502 write_attributes (iface);
504 write_indent ();
505 write_accessibility (iface);
506 write_string ("interface ");
507 write_identifier (iface.name);
509 var type_params = iface.get_type_parameters ();
510 if (type_params.size > 0) {
511 write_string ("<");
512 bool first = true;
513 foreach (TypeParameter type_param in type_params) {
514 if (first) {
515 first = false;
516 } else {
517 write_string (",");
519 write_identifier (type_param.name);
521 write_string (">");
524 var prerequisites = iface.get_prerequisites ();
525 if (prerequisites.size > 0) {
526 write_string (" : ");
528 bool first = true;
529 foreach (DataType prerequisite in prerequisites) {
530 if (!first) {
531 write_string (", ");
532 } else {
533 first = false;
535 write_type (prerequisite);
538 write_begin_block ();
540 current_scope = iface.scope;
542 visit_sorted (iface.get_classes ());
543 visit_sorted (iface.get_structs ());
544 visit_sorted (iface.get_enums ());
545 visit_sorted (iface.get_delegates ());
546 visit_sorted (iface.get_fields ());
547 visit_sorted (iface.get_constants ());
548 visit_sorted (iface.get_methods ());
549 visit_sorted (iface.get_properties ());
550 visit_sorted (iface.get_signals ());
552 current_scope = current_scope.parent_scope;
554 write_end_block ();
555 write_newline ();
558 public override void visit_enum (Enum en) {
559 if (en.external_package) {
560 return;
563 if (!check_accessibility (en)) {
564 return;
567 emit_deprecated_attribute (en);
569 write_indent ();
571 write_string ("[CCode (cprefix = \"%s\", ".printf (en.get_cprefix ()));
573 if (!en.has_type_id) {
574 write_string ("has_type_id = false, ");
577 write_string ("cheader_filename = \"%s\")]".printf (get_cheaders(en)));
579 if (en.is_flags) {
580 write_indent ();
581 write_string ("[Flags]");
584 write_attributes (en);
586 write_indent ();
587 write_accessibility (en);
588 write_string ("enum ");
589 write_identifier (en.name);
590 write_begin_block ();
592 bool first = true;
593 foreach (EnumValue ev in en.get_values ()) {
594 if (first) {
595 first = false;
596 } else {
597 write_string (",");
598 write_newline ();
601 if (ev.get_cname () != ev.get_default_cname ()) {
602 write_indent ();
603 write_string ("[CCode (cname = \"%s\")]".printf (ev.get_cname ()));
605 write_indent ();
606 write_identifier (ev.name);
608 if (type == CodeWriterType.FAST && ev.value != null) {
609 write_string(" = ");
610 ev.value.accept (this);
614 if (!first) {
615 if (en.get_methods ().size > 0 || en.get_constants ().size > 0) {
616 write_string (";");
618 write_newline ();
621 current_scope = en.scope;
622 foreach (Method m in en.get_methods ()) {
623 m.accept (this);
625 foreach (Constant c in en.get_constants ()) {
626 c.accept (this);
628 current_scope = current_scope.parent_scope;
630 write_end_block ();
631 write_newline ();
634 public override void visit_error_domain (ErrorDomain edomain) {
635 if (edomain.external_package) {
636 return;
639 if (!check_accessibility (edomain)) {
640 return;
643 emit_deprecated_attribute (edomain);
645 write_indent ();
647 write_string ("[CCode (cprefix = \"%s\", cheader_filename = \"%s\")]".printf (edomain.get_cprefix (), get_cheaders(edomain)));
649 write_attributes (edomain);
651 write_indent ();
652 write_accessibility (edomain);
653 write_string ("errordomain ");
654 write_identifier (edomain.name);
655 write_begin_block ();
657 edomain.accept_children (this);
659 write_end_block ();
660 write_newline ();
663 public override void visit_error_code (ErrorCode ecode) {
664 write_indent ();
665 write_identifier (ecode.name);
666 write_string (",");
667 write_newline ();
670 public override void visit_constant (Constant c) {
671 if (c.external_package) {
672 return;
675 if (!check_accessibility (c)) {
676 return;
679 emit_deprecated_attribute (c);
681 bool custom_cname = (c.get_cname () != c.get_default_cname ());
682 bool custom_cheaders = (c.parent_symbol is Namespace);
683 if (custom_cname || custom_cheaders) {
684 write_indent ();
685 write_string ("[CCode (");
687 if (custom_cname) {
688 write_string ("cname = \"%s\"".printf (c.get_cname ()));
691 if (custom_cheaders) {
692 if (custom_cname) {
693 write_string (", ");
696 write_string ("cheader_filename = \"%s\"".printf (get_cheaders(c)));
699 write_string (")]");
702 write_indent ();
703 write_accessibility (c);
704 write_string ("const ");
706 write_type (c.type_reference);
708 write_string (" ");
709 write_identifier (c.name);
710 if (type == CodeWriterType.FAST && c.value != null) {
711 write_string(" = ");
712 c.value.accept (this);
714 write_string (";");
715 write_newline ();
718 public override void visit_field (Field f) {
719 if (f.external_package) {
720 return;
723 if (!check_accessibility (f)) {
724 return;
727 emit_deprecated_attribute (f);
729 bool custom_cname = (f.get_cname () != f.get_default_cname ());
730 bool custom_ctype = (f.get_ctype () != null);
731 bool custom_cheaders = (f.parent_symbol is Namespace);
732 bool custom_array_length_cname = (f.get_array_length_cname () != null);
733 bool custom_array_length_type = (f.array_length_type != null);
734 if (custom_cname || custom_ctype || custom_cheaders || custom_array_length_cname || custom_array_length_type || (f.no_array_length && f.variable_type is ArrayType)) {
735 write_indent ();
736 write_string ("[CCode (");
738 if (custom_cname) {
739 write_string ("cname = \"%s\"".printf (f.get_cname ()));
742 if (custom_ctype) {
743 if (custom_cname) {
744 write_string (", ");
747 write_string ("type = \"%s\"".printf (f.get_ctype ()));
750 if (custom_cheaders) {
751 if (custom_cname || custom_ctype) {
752 write_string (", ");
755 write_string ("cheader_filename = \"%s\"".printf (get_cheaders(f)));
758 if (f.variable_type is ArrayType) {
759 if (f.no_array_length) {
760 if (custom_cname || custom_ctype || custom_cheaders) {
761 write_string (", ");
764 write_string ("array_length = false");
766 if (f.array_null_terminated) {
767 write_string (", array_null_terminated = true");
769 } else {
770 if (custom_array_length_cname) {
771 if (custom_cname || custom_ctype || custom_cheaders) {
772 write_string (", ");
775 write_string ("array_length_cname = \"%s\"".printf (f.get_array_length_cname ()));
778 if (custom_array_length_type) {
779 if (custom_cname || custom_ctype || custom_cheaders || custom_array_length_cname) {
780 write_string (", ");
783 write_string ("array_length_type = \"%s\"".printf (f.array_length_type));
788 write_string (")]");
791 write_indent ();
792 write_accessibility (f);
794 if (f.binding == MemberBinding.STATIC) {
795 write_string ("static ");
796 } else if (f.binding == MemberBinding.CLASS) {
797 write_string ("class ");
800 if (f.variable_type.is_weak ()) {
801 write_string ("weak ");
804 write_type (f.variable_type);
806 write_string (" ");
807 write_identifier (f.name);
808 write_string (";");
809 write_newline ();
812 private void write_error_domains (List<DataType> error_domains) {
813 if (error_domains.size > 0) {
814 write_string (" throws ");
816 bool first = true;
817 foreach (DataType type in error_domains) {
818 if (!first) {
819 write_string (", ");
820 } else {
821 first = false;
824 write_type (type);
829 // equality comparison with 3 digit precision
830 private bool float_equal (double d1, double d2) {
831 return ((int) (d1 * 1000)) == ((int) (d2 * 1000));
834 private void write_params (List<Parameter> params) {
835 write_string ("(");
837 int i = 1;
838 foreach (Parameter param in params) {
839 if (i > 1) {
840 write_string (", ");
843 if (param.ellipsis) {
844 write_string ("...");
845 continue;
849 var ccode_params = new StringBuilder ();
850 var separator = "";
852 if (!float_equal (param.cparameter_position, i)) {
853 ccode_params.append_printf ("%spos = %g", separator, param.cparameter_position);
854 separator = ", ";
856 if (param.ctype != null) {
857 ccode_params.append_printf ("%stype = \"%s\"", separator, param.ctype);
858 separator = ", ";
860 if (param.no_array_length && param.variable_type is ArrayType) {
861 ccode_params.append_printf ("%sarray_length = false", separator);
862 separator = ", ";
864 if (param.array_length_type != null && param.variable_type is ArrayType) {
865 ccode_params.append_printf ("%sarray_length_type = \"%s\"", separator, param.array_length_type);
866 separator = ", ";
868 if (param.get_array_length_cname () != null && param.variable_type is ArrayType) {
869 ccode_params.append_printf ("%sarray_length_cname = \"%s\"", separator, param.get_array_length_cname ());
870 separator = ", ";
872 if (!float_equal (param.carray_length_parameter_position, i + 0.1)) {
873 ccode_params.append_printf ("%sarray_length_pos = %g", separator, param.carray_length_parameter_position);
874 separator = ", ";
876 if (!float_equal (param.cdelegate_target_parameter_position, i + 0.1)) {
877 ccode_params.append_printf ("%sdelegate_target_pos = %g", separator, param.cdelegate_target_parameter_position);
878 separator = ", ";
881 if (ccode_params.len > 0) {
882 write_string ("[CCode (%s)] ".printf (ccode_params.str));
885 if (param.params_array) {
886 write_string ("params ");
889 if (param.direction == ParameterDirection.IN) {
890 if (param.variable_type.value_owned) {
891 write_string ("owned ");
893 } else {
894 if (param.direction == ParameterDirection.REF) {
895 write_string ("ref ");
896 } else if (param.direction == ParameterDirection.OUT) {
897 write_string ("out ");
899 if (param.variable_type.is_weak ()) {
900 write_string ("unowned ");
904 write_type (param.variable_type);
906 write_string (" ");
907 write_identifier (param.name);
909 if (param.initializer != null) {
910 write_string (" = ");
911 param.initializer.accept (this);
914 i++;
917 write_string (")");
920 public override void visit_delegate (Delegate cb) {
921 if (cb.external_package) {
922 return;
925 if (!check_accessibility (cb)) {
926 return;
929 emit_deprecated_attribute (cb);
931 write_indent ();
933 write_string ("[CCode (cheader_filename = \"%s\"".printf (get_cheaders(cb)));
935 if (!cb.has_target) {
936 write_string (", has_target = false");
937 } else if (!float_equal (cb.cinstance_parameter_position, -2)) {
938 write_string (", instance_pos = %g".printf (cb.cinstance_parameter_position));
941 write_string (")]");
943 write_indent ();
945 write_accessibility (cb);
946 write_string ("delegate ");
948 write_return_type (cb.return_type);
950 write_string (" ");
951 write_identifier (cb.name);
953 var type_params = cb.get_type_parameters ();
954 if (type_params.size > 0) {
955 write_string ("<");
956 bool first = true;
957 foreach (TypeParameter type_param in type_params) {
958 if (first) {
959 first = false;
960 } else {
961 write_string (",");
963 write_identifier (type_param.name);
965 write_string (">");
968 write_string (" ");
970 write_params (cb.get_parameters ());
972 write_error_domains (cb.get_error_types ());
974 write_string (";");
976 write_newline ();
979 public override void visit_constructor (Constructor c) {
980 if (type != CodeWriterType.DUMP) {
981 return;
984 write_indent ();
985 write_string ("construct");
986 write_code_block (c.body);
987 write_newline ();
990 public override void visit_method (Method m) {
991 if (m.external_package) {
992 return;
995 // don't write interface implementation unless it's an abstract or virtual method
996 if (!check_accessibility (m) || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
997 if (type != CodeWriterType.DUMP) {
998 return;
1002 if (m.get_attribute ("NoWrapper") != null) {
1003 write_indent ();
1004 write_string ("[NoWrapper]");
1006 if (m.get_attribute ("NoThrow") != null) {
1007 write_indent ();
1008 write_string ("[NoThrow]");
1010 if (m.returns_modified_pointer) {
1011 write_indent ();
1012 write_string ("[ReturnsModifiedPointer]");
1014 if (m.printf_format) {
1015 write_indent ();
1016 write_string ("[PrintfFormat]");
1018 if (m.scanf_format) {
1019 write_indent ();
1020 write_string ("[ScanfFormat]");
1022 if (m.get_attribute ("Print") != null) {
1023 write_indent ();
1024 write_string ("[Print]");
1026 if (m.get_attribute ("NoReturn") != null) {
1027 write_indent ();
1028 write_string ("[NoReturn]");
1031 emit_deprecated_attribute (m);
1033 var ccode_params = new StringBuilder ();
1034 var separator = "";
1036 if (m.get_cname () != m.get_default_cname ()) {
1037 ccode_params.append_printf ("%scname = \"%s\"", separator, m.get_cname ());
1038 separator = ", ";
1040 if (m.parent_symbol is Namespace) {
1041 ccode_params.append_printf ("%scheader_filename = \"%s\"", separator, get_cheaders(m));
1042 separator = ", ";
1044 if (!float_equal (m.cinstance_parameter_position, 0)) {
1045 ccode_params.append_printf ("%sinstance_pos = %g", separator, m.cinstance_parameter_position);
1046 separator = ", ";
1048 if (m.no_array_length && m.return_type is ArrayType) {
1049 ccode_params.append_printf ("%sarray_length = false", separator);
1050 separator = ", ";
1052 if (!float_equal (m.carray_length_parameter_position, -3)) {
1053 ccode_params.append_printf ("%sarray_length_pos = %g", separator, m.carray_length_parameter_position);
1054 separator = ", ";
1056 if (m.array_null_terminated && m.return_type is ArrayType) {
1057 ccode_params.append_printf ("%sarray_null_terminated = true", separator);
1058 separator = ", ";
1060 if (m.array_length_type != null && m.return_type is ArrayType) {
1061 ccode_params.append_printf ("%sarray_length_type = \"%s\"", separator, m.array_length_type);
1062 separator = ", ";
1064 if (!float_equal (m.cdelegate_target_parameter_position, -3)) {
1065 ccode_params.append_printf ("%sdelegate_target_pos = %g", separator, m.cdelegate_target_parameter_position);
1066 separator = ", ";
1068 if (m.vfunc_name != m.name) {
1069 ccode_params.append_printf ("%svfunc_name = \"%s\"", separator, m.vfunc_name);
1070 separator = ", ";
1072 if (m.coroutine && m.get_finish_cname () != m.get_default_finish_cname ()) {
1073 ccode_params.append_printf ("%sfinish_name = \"%s\"", separator, m.get_finish_cname ());
1074 separator = ", ";
1076 if (m.sentinel != m.DEFAULT_SENTINEL) {
1077 ccode_params.append_printf ("%ssentinel = \"%s\"", separator, m.sentinel);
1078 separator = ", ";
1080 var cm = m as CreationMethod;
1081 if (cm != null) {
1082 if (cm.custom_return_type_cname != null) {
1083 ccode_params.append_printf ("%stype = \"%s\"", separator, cm.custom_return_type_cname);
1084 separator = ", ";
1086 if (!m.has_new_function) {
1087 ccode_params.append_printf ("%shas_new_function = false", separator);
1088 separator = ", ";
1090 if (!m.has_construct_function) {
1091 ccode_params.append_printf ("%shas_construct_function = false", separator);
1092 separator = ", ";
1093 } else if (m.name == ".new" && m.get_real_cname () != cm.get_default_construct_function ()) {
1094 ccode_params.append_printf ("%sconstruct_function = \"%s\"", separator, m.get_real_cname ());
1095 separator = ", ";
1099 if (ccode_params.len > 0) {
1100 write_indent ();
1101 write_string ("[CCode (%s)]".printf (ccode_params.str));
1104 write_indent ();
1105 write_accessibility (m);
1107 if (m is CreationMethod) {
1108 if (m.coroutine) {
1109 write_string ("async ");
1112 var datatype = (TypeSymbol) m.parent_symbol;
1113 write_identifier (datatype.name);
1114 if (m.name != ".new") {
1115 write_string (".");
1116 write_identifier (m.name);
1118 write_string (" ");
1119 } else {
1120 if (m.binding == MemberBinding.STATIC) {
1121 write_string ("static ");
1122 } else if (m.binding == MemberBinding.CLASS) {
1123 write_string ("class ");
1124 } else if (m.is_abstract) {
1125 write_string ("abstract ");
1126 } else if (m.is_virtual) {
1127 write_string ("virtual ");
1128 } else if (m.overrides) {
1129 write_string ("override ");
1132 if (m.hides) {
1133 write_string ("new ");
1136 if (m.coroutine) {
1137 write_string ("async ");
1140 write_return_type (m.return_type);
1141 write_string (" ");
1143 write_identifier (m.name);
1145 var type_params = m.get_type_parameters ();
1146 if (type_params.size > 0) {
1147 write_string ("<");
1148 bool first = true;
1149 foreach (TypeParameter type_param in type_params) {
1150 if (first) {
1151 first = false;
1152 } else {
1153 write_string (",");
1155 write_identifier (type_param.name);
1157 write_string (">");
1160 write_string (" ");
1163 write_params (m.get_parameters ());
1165 if (context.profile != Profile.DOVA) {
1166 write_error_domains (m.get_error_types ());
1169 write_code_block (m.body);
1171 write_newline ();
1174 public override void visit_creation_method (CreationMethod m) {
1175 visit_method (m);
1178 public override void visit_property (Property prop) {
1179 if (!check_accessibility (prop) || (prop.base_interface_property != null && !prop.is_abstract && !prop.is_virtual)) {
1180 return;
1183 emit_deprecated_attribute (prop);
1185 if (prop.no_accessor_method) {
1186 write_indent ();
1187 write_string ("[NoAccessorMethod]");
1189 if (prop.property_type is ArrayType && prop.no_array_length) {
1190 write_indent ();
1191 write_string ("[CCode (array_length = false");
1193 if (prop.array_null_terminated) {
1194 write_string (", array_null_terminated = true");
1197 write_string (")]");
1200 write_indent ();
1201 write_accessibility (prop);
1203 if (prop.binding == MemberBinding.STATIC) {
1204 write_string ("static ");
1205 } else if (prop.is_abstract) {
1206 write_string ("abstract ");
1207 } else if (prop.is_virtual) {
1208 write_string ("virtual ");
1209 } else if (prop.overrides) {
1210 write_string ("override ");
1213 write_type (prop.property_type);
1215 write_string (" ");
1216 write_identifier (prop.name);
1217 write_string (" {");
1218 if (prop.get_accessor != null) {
1219 var ccode_params = new StringBuilder ();
1220 var separator = "";
1222 if (prop.get_accessor.get_cname () != prop.get_accessor.get_default_cname ()) {
1223 ccode_params.append_printf ("%scname = \"%s\"", separator, prop.get_accessor.get_cname ());
1224 separator = ", ";
1226 if (ccode_params.len > 0) {
1227 write_indent ();
1228 write_string ("[CCode (%s)]".printf (ccode_params.str));
1231 write_property_accessor_accessibility (prop.get_accessor);
1233 if (context.profile != Profile.DOVA && prop.get_accessor.value_type.is_disposable ()) {
1234 write_string (" owned");
1237 write_string (" get");
1238 write_code_block (prop.get_accessor.body);
1240 if (prop.set_accessor != null) {
1241 var ccode_params = new StringBuilder ();
1242 var separator = "";
1244 if (prop.set_accessor.get_cname () != prop.set_accessor.get_default_cname ()) {
1245 ccode_params.append_printf ("%scname = \"%s\"", separator, prop.set_accessor.get_cname ());
1246 separator = ", ";
1248 if (ccode_params.len > 0) {
1249 write_indent ();
1250 write_string ("[CCode (%s)]".printf (ccode_params.str));
1253 write_property_accessor_accessibility (prop.set_accessor);
1255 if (context.profile != Profile.DOVA && prop.set_accessor.value_type.value_owned) {
1256 write_string (" owned");
1259 if (prop.set_accessor.writable) {
1260 write_string (" set");
1262 if (prop.set_accessor.construction) {
1263 write_string (" construct");
1265 write_code_block (prop.set_accessor.body);
1267 write_string (" }");
1268 write_newline ();
1271 public override void visit_signal (Signal sig) {
1272 if (!check_accessibility (sig)) {
1273 return;
1276 if (sig.has_emitter) {
1277 write_indent ();
1278 write_string ("[HasEmitter]");
1281 emit_deprecated_attribute (sig);
1283 write_indent ();
1284 write_accessibility (sig);
1286 if (sig.is_virtual) {
1287 write_string ("virtual ");
1290 write_string ("signal ");
1292 write_return_type (sig.return_type);
1294 write_string (" ");
1295 write_identifier (sig.name);
1297 write_string (" ");
1299 write_params (sig.get_parameters ());
1301 write_string (";");
1303 write_newline ();
1306 public override void visit_block (Block b) {
1307 write_begin_block ();
1309 foreach (Statement stmt in b.get_statements ()) {
1310 stmt.accept (this);
1313 write_end_block ();
1316 public override void visit_empty_statement (EmptyStatement stmt) {
1319 public override void visit_declaration_statement (DeclarationStatement stmt) {
1320 write_indent ();
1321 stmt.declaration.accept (this);
1322 write_string (";");
1323 write_newline ();
1326 public override void visit_local_variable (LocalVariable local) {
1327 write_type (local.variable_type);
1328 write_string (" ");
1329 write_identifier (local.name);
1330 if (local.initializer != null) {
1331 write_string (" = ");
1332 local.initializer.accept (this);
1336 public override void visit_initializer_list (InitializerList list) {
1337 write_string ("{");
1339 bool first = true;
1340 foreach (Expression initializer in list.get_initializers ()) {
1341 if (!first) {
1342 write_string (", ");
1343 } else {
1344 write_string (" ");
1346 first = false;
1347 initializer.accept (this);
1349 write_string (" }");
1352 public override void visit_expression_statement (ExpressionStatement stmt) {
1353 write_indent ();
1354 stmt.expression.accept (this);
1355 write_string (";");
1356 write_newline ();
1359 public override void visit_if_statement (IfStatement stmt) {
1360 write_indent ();
1361 write_string ("if (");
1362 stmt.condition.accept (this);
1363 write_string (")");
1364 stmt.true_statement.accept (this);
1365 if (stmt.false_statement != null) {
1366 write_string (" else");
1367 stmt.false_statement.accept (this);
1369 write_newline ();
1372 public override void visit_switch_statement (SwitchStatement stmt) {
1373 write_indent ();
1374 write_string ("switch (");
1375 stmt.expression.accept (this);
1376 write_string (") {");
1377 write_newline ();
1379 foreach (SwitchSection section in stmt.get_sections ()) {
1380 section.accept (this);
1383 write_indent ();
1384 write_string ("}");
1385 write_newline ();
1388 public override void visit_switch_section (SwitchSection section) {
1389 foreach (SwitchLabel label in section.get_labels ()) {
1390 label.accept (this);
1393 visit_block (section);
1396 public override void visit_switch_label (SwitchLabel label) {
1397 if (label.expression != null) {
1398 write_indent ();
1399 write_string ("case ");
1400 label.expression.accept (this);
1401 write_string (":");
1402 write_newline ();
1403 } else {
1404 write_indent ();
1405 write_string ("default:");
1406 write_newline ();
1410 public override void visit_loop (Loop stmt) {
1411 write_indent ();
1412 write_string ("loop");
1413 stmt.body.accept (this);
1414 write_newline ();
1417 public override void visit_while_statement (WhileStatement stmt) {
1418 write_indent ();
1419 write_string ("while (");
1420 stmt.condition.accept (this);
1421 write_string (")");
1422 stmt.body.accept (this);
1423 write_newline ();
1426 public override void visit_do_statement (DoStatement stmt) {
1427 write_indent ();
1428 write_string ("do");
1429 stmt.body.accept (this);
1430 write_string ("while (");
1431 stmt.condition.accept (this);
1432 write_string (");");
1433 write_newline ();
1436 public override void visit_for_statement (ForStatement stmt) {
1437 write_indent ();
1438 write_string ("for (");
1440 bool first = true;
1441 foreach (Expression initializer in stmt.get_initializer ()) {
1442 if (!first) {
1443 write_string (", ");
1445 first = false;
1446 initializer.accept (this);
1448 write_string ("; ");
1450 stmt.condition.accept (this);
1451 write_string ("; ");
1453 first = true;
1454 foreach (Expression iterator in stmt.get_iterator ()) {
1455 if (!first) {
1456 write_string (", ");
1458 first = false;
1459 iterator.accept (this);
1462 write_string (")");
1463 stmt.body.accept (this);
1464 write_newline ();
1467 public override void visit_foreach_statement (ForeachStatement stmt) {
1470 public override void visit_break_statement (BreakStatement stmt) {
1471 write_indent ();
1472 write_string ("break;");
1473 write_newline ();
1476 public override void visit_continue_statement (ContinueStatement stmt) {
1477 write_indent ();
1478 write_string ("continue;");
1479 write_newline ();
1482 public override void visit_return_statement (ReturnStatement stmt) {
1483 write_indent ();
1484 write_string ("return");
1485 if (stmt.return_expression != null) {
1486 write_string (" ");
1487 stmt.return_expression.accept (this);
1489 write_string (";");
1490 write_newline ();
1493 public override void visit_yield_statement (YieldStatement y) {
1494 write_indent ();
1495 write_string ("yield");
1496 if (y.yield_expression != null) {
1497 write_string (" ");
1498 y.yield_expression.accept (this);
1500 write_string (";");
1501 write_newline ();
1504 public override void visit_throw_statement (ThrowStatement stmt) {
1505 write_indent ();
1506 write_string ("throw");
1507 if (stmt.error_expression != null) {
1508 write_string (" ");
1509 stmt.error_expression.accept (this);
1511 write_string (";");
1512 write_newline ();
1515 public override void visit_try_statement (TryStatement stmt) {
1516 write_indent ();
1517 write_string ("try");
1518 stmt.body.accept (this);
1519 foreach (var clause in stmt.get_catch_clauses ()) {
1520 clause.accept (this);
1522 if (stmt.finally_body != null) {
1523 write_string (" finally");
1524 stmt.finally_body.accept (this);
1526 write_newline ();
1529 public override void visit_catch_clause (CatchClause clause) {
1530 var type_name = clause.error_type == null ? "GLib.Error" : clause.error_type.to_string ();
1531 var var_name = clause.variable_name == null ? "_" : clause.variable_name;
1532 write_string (" catch (%s %s)".printf (type_name, var_name));
1533 clause.body.accept (this);
1536 public override void visit_lock_statement (LockStatement stmt) {
1537 write_indent ();
1538 write_string ("lock (");
1539 stmt.resource.accept (this);
1540 write_string (")");
1541 if (stmt.body == null) {
1542 write_string (";");
1543 } else {
1544 stmt.body.accept (this);
1546 write_newline ();
1549 public override void visit_delete_statement (DeleteStatement stmt) {
1550 write_indent ();
1551 write_string ("delete ");
1552 stmt.expression.accept (this);
1553 write_string (";");
1554 write_newline ();
1557 public override void visit_array_creation_expression (ArrayCreationExpression expr) {
1558 write_string ("new ");
1559 write_type (expr.element_type);
1560 write_string ("[");
1562 bool first = true;
1563 foreach (Expression size in expr.get_sizes ()) {
1564 if (!first) {
1565 write_string (", ");
1567 first = false;
1569 size.accept (this);
1572 write_string ("]");
1574 if (expr.initializer_list != null) {
1575 write_string (" ");
1576 expr.initializer_list.accept (this);
1580 public override void visit_boolean_literal (BooleanLiteral lit) {
1581 write_string (lit.value.to_string ());
1584 public override void visit_character_literal (CharacterLiteral lit) {
1585 write_string (lit.value);
1588 public override void visit_integer_literal (IntegerLiteral lit) {
1589 write_string (lit.value);
1592 public override void visit_real_literal (RealLiteral lit) {
1593 write_string (lit.value);
1596 public override void visit_string_literal (StringLiteral lit) {
1597 write_string (lit.value);
1600 public override void visit_null_literal (NullLiteral lit) {
1601 write_string ("null");
1604 public override void visit_member_access (MemberAccess expr) {
1605 if (expr.inner != null) {
1606 expr.inner.accept (this);
1607 write_string (".");
1609 write_identifier (expr.member_name);
1612 public override void visit_method_call (MethodCall expr) {
1613 expr.call.accept (this);
1614 write_string (" (");
1616 bool first = true;
1617 foreach (Expression arg in expr.get_argument_list ()) {
1618 if (!first) {
1619 write_string (", ");
1621 first = false;
1623 arg.accept (this);
1626 write_string (")");
1629 public override void visit_element_access (ElementAccess expr) {
1630 expr.container.accept (this);
1631 write_string ("[");
1633 bool first = true;
1634 foreach (Expression index in expr.get_indices ()) {
1635 if (!first) {
1636 write_string (", ");
1638 first = false;
1640 index.accept (this);
1643 write_string ("]");
1646 public override void visit_slice_expression (SliceExpression expr) {
1647 expr.container.accept (this);
1648 write_string ("[");
1649 expr.start.accept (this);
1650 write_string (":");
1651 expr.stop.accept (this);
1652 write_string ("]");
1655 public override void visit_base_access (BaseAccess expr) {
1656 write_string ("base");
1659 public override void visit_postfix_expression (PostfixExpression expr) {
1660 expr.inner.accept (this);
1661 if (expr.increment) {
1662 write_string ("++");
1663 } else {
1664 write_string ("--");
1668 public override void visit_object_creation_expression (ObjectCreationExpression expr) {
1669 if (!expr.struct_creation) {
1670 write_string ("new ");
1673 write_type (expr.type_reference);
1675 if (expr.symbol_reference.name != ".new") {
1676 write_string (".");
1677 write_string (expr.symbol_reference.name);
1680 write_string (" (");
1682 bool first = true;
1683 foreach (Expression arg in expr.get_argument_list ()) {
1684 if (!first) {
1685 write_string (", ");
1687 first = false;
1689 arg.accept (this);
1692 write_string (")");
1695 public override void visit_sizeof_expression (SizeofExpression expr) {
1696 write_string ("sizeof (");
1697 write_type (expr.type_reference);
1698 write_string (")");
1701 public override void visit_typeof_expression (TypeofExpression expr) {
1702 write_string ("typeof (");
1703 write_type (expr.type_reference);
1704 write_string (")");
1707 public override void visit_unary_expression (UnaryExpression expr) {
1708 switch (expr.operator) {
1709 case UnaryOperator.PLUS:
1710 write_string ("+");
1711 break;
1712 case UnaryOperator.MINUS:
1713 write_string ("-");
1714 break;
1715 case UnaryOperator.LOGICAL_NEGATION:
1716 write_string ("!");
1717 break;
1718 case UnaryOperator.BITWISE_COMPLEMENT:
1719 write_string ("~");
1720 break;
1721 case UnaryOperator.INCREMENT:
1722 write_string ("++");
1723 break;
1724 case UnaryOperator.DECREMENT:
1725 write_string ("--");
1726 break;
1727 case UnaryOperator.REF:
1728 write_string ("ref ");
1729 break;
1730 case UnaryOperator.OUT:
1731 write_string ("out ");
1732 break;
1733 default:
1734 assert_not_reached ();
1736 expr.inner.accept (this);
1739 public override void visit_cast_expression (CastExpression expr) {
1740 if (expr.is_non_null_cast) {
1741 write_string ("(!) ");
1742 expr.inner.accept (this);
1743 return;
1746 if (!expr.is_silent_cast) {
1747 write_string ("(");
1748 write_type (expr.type_reference);
1749 write_string (") ");
1752 expr.inner.accept (this);
1754 if (expr.is_silent_cast) {
1755 write_string (" as ");
1756 write_type (expr.type_reference);
1760 public override void visit_pointer_indirection (PointerIndirection expr) {
1761 write_string ("*");
1762 expr.inner.accept (this);
1765 public override void visit_addressof_expression (AddressofExpression expr) {
1766 write_string ("&");
1767 expr.inner.accept (this);
1770 public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
1771 write_string ("(owned) ");
1772 expr.inner.accept (this);
1775 public override void visit_binary_expression (BinaryExpression expr) {
1776 expr.left.accept (this);
1778 switch (expr.operator) {
1779 case BinaryOperator.PLUS:
1780 write_string (" + ");
1781 break;
1782 case BinaryOperator.MINUS:
1783 write_string (" - ");
1784 break;
1785 case BinaryOperator.MUL:
1786 write_string (" * ");
1787 break;
1788 case BinaryOperator.DIV:
1789 write_string (" / ");
1790 break;
1791 case BinaryOperator.MOD:
1792 write_string (" % ");
1793 break;
1794 case BinaryOperator.SHIFT_LEFT:
1795 write_string (" << ");
1796 break;
1797 case BinaryOperator.SHIFT_RIGHT:
1798 write_string (" >> ");
1799 break;
1800 case BinaryOperator.LESS_THAN:
1801 write_string (" < ");
1802 break;
1803 case BinaryOperator.GREATER_THAN:
1804 write_string (" > ");
1805 break;
1806 case BinaryOperator.LESS_THAN_OR_EQUAL:
1807 write_string (" <= ");
1808 break;
1809 case BinaryOperator.GREATER_THAN_OR_EQUAL:
1810 write_string (" >= ");
1811 break;
1812 case BinaryOperator.EQUALITY:
1813 write_string (" == ");
1814 break;
1815 case BinaryOperator.INEQUALITY:
1816 write_string (" != ");
1817 break;
1818 case BinaryOperator.BITWISE_AND:
1819 write_string (" & ");
1820 break;
1821 case BinaryOperator.BITWISE_OR:
1822 write_string (" | ");
1823 break;
1824 case BinaryOperator.BITWISE_XOR:
1825 write_string (" ^ ");
1826 break;
1827 case BinaryOperator.AND:
1828 write_string (" && ");
1829 break;
1830 case BinaryOperator.OR:
1831 write_string (" || ");
1832 break;
1833 case BinaryOperator.IN:
1834 write_string (" in ");
1835 break;
1836 case BinaryOperator.COALESCE:
1837 write_string (" ?? ");
1838 break;
1839 default:
1840 assert_not_reached ();
1843 expr.right.accept (this);
1846 public override void visit_type_check (TypeCheck expr) {
1847 expr.expression.accept (this);
1848 write_string (" is ");
1849 write_type (expr.type_reference);
1852 public override void visit_conditional_expression (ConditionalExpression expr) {
1853 expr.condition.accept (this);
1854 write_string ("?");
1855 expr.true_expression.accept (this);
1856 write_string (":");
1857 expr.false_expression.accept (this);
1860 public override void visit_lambda_expression (LambdaExpression expr) {
1861 write_string ("(");
1862 var params = expr.get_parameters ();
1863 if (params.size != 0) {
1864 for (var i = 0; i < params.size - 1; ++ i) {
1865 write_string (params[i]);
1866 write_string (", ");
1868 write_string (params[params.size - 1]);
1870 write_string (") =>");
1871 if (expr.statement_body != null) {
1872 expr.statement_body.accept (this);
1873 } else if (expr.expression_body != null) {
1874 expr.expression_body.accept (this);
1878 public override void visit_assignment (Assignment a) {
1879 a.left.accept (this);
1880 write_string (" = ");
1881 a.right.accept (this);
1884 private void write_indent () {
1885 int i;
1887 if (!bol) {
1888 stream.putc ('\n');
1891 for (i = 0; i < indent; i++) {
1892 stream.putc ('\t');
1895 bol = false;
1898 private void write_identifier (string s) {
1899 char* id = (char*)s;
1900 int id_length = (int)s.length;
1901 if (context.profile != Profile.DOVA &&
1902 (Vala.Scanner.get_identifier_or_keyword (id, id_length) != Vala.TokenType.IDENTIFIER ||
1903 s.get_char ().isdigit ())) {
1904 stream.putc ('@');
1906 write_string (s);
1909 private void write_return_type (DataType type) {
1910 if (type.is_weak ()) {
1911 write_string ("unowned ");
1914 write_type (type);
1917 private void write_type (DataType type) {
1918 write_string (type.to_qualified_string (current_scope));
1921 private void write_string (string s) {
1922 stream.printf ("%s", s);
1923 bol = false;
1926 private void write_newline () {
1927 stream.putc ('\n');
1928 bol = true;
1931 void write_code_block (Block? block) {
1932 if (block == null || type != CodeWriterType.DUMP) {
1933 write_string (";");
1934 return;
1937 block.accept (this);
1940 private void write_begin_block () {
1941 if (!bol) {
1942 stream.putc (' ');
1943 } else {
1944 write_indent ();
1946 stream.putc ('{');
1947 write_newline ();
1948 indent++;
1951 private void write_end_block () {
1952 indent--;
1953 write_indent ();
1954 stream.printf ("}");
1957 private bool check_accessibility (Symbol sym) {
1958 switch (type) {
1959 case CodeWriterType.EXTERNAL:
1960 return sym.access == SymbolAccessibility.PUBLIC ||
1961 sym.access == SymbolAccessibility.PROTECTED;
1963 case CodeWriterType.INTERNAL:
1964 case CodeWriterType.FAST:
1965 return sym.access == SymbolAccessibility.INTERNAL ||
1966 sym.access == SymbolAccessibility.PUBLIC ||
1967 sym.access == SymbolAccessibility.PROTECTED;
1969 case CodeWriterType.DUMP:
1970 return true;
1972 default:
1973 assert_not_reached ();
1977 private void write_attributes (CodeNode node) {
1978 foreach (Attribute attr in node.attributes) {
1979 if (!filter_attribute (attr)) {
1980 write_indent ();
1981 stream.printf ("[%s", attr.name);
1983 var keys = attr.args.get_keys ();
1984 if (keys.size != 0) {
1985 stream.printf (" (");
1987 string separator = "";
1988 foreach (string arg_name in keys) {
1989 stream.printf ("%s%s = %s", separator, arg_name, attr.args.get (arg_name));
1990 separator = ", ";
1993 stream.printf (")");
1995 stream.printf ("]");
1996 write_newline ();
2001 private bool filter_attribute (Attribute attr) {
2002 if (attr.name == "CCode"
2003 || attr.name == "Compact" || attr.name == "Immutable"
2004 || attr.name == "SimpleType" || attr.name == "IntegerType" || attr.name == "FloatingType"
2005 || attr.name == "Flags") {
2006 return true;
2008 return false;
2011 private void write_accessibility (Symbol sym) {
2012 if (sym.access == SymbolAccessibility.PUBLIC) {
2013 write_string ("public ");
2014 } else if (sym.access == SymbolAccessibility.PROTECTED) {
2015 write_string ("protected ");
2016 } else if (sym.access == SymbolAccessibility.INTERNAL) {
2017 write_string ("internal ");
2018 } else if (sym.access == SymbolAccessibility.PRIVATE) {
2019 write_string ("private ");
2022 if (type != CodeWriterType.EXTERNAL && sym.external && !sym.external_package) {
2023 write_string ("extern ");
2027 void write_property_accessor_accessibility (Symbol sym) {
2028 if (sym.access == SymbolAccessibility.PROTECTED) {
2029 write_string (" protected");
2030 } else if (sym.access == SymbolAccessibility.INTERNAL) {
2031 write_string (" internal");
2032 } else if (sym.access == SymbolAccessibility.PRIVATE) {
2033 write_string (" private");
2038 public enum Vala.CodeWriterType {
2039 EXTERNAL,
2040 INTERNAL,
2041 FAST,
2042 DUMP