Add *~ to .gitignore
[vala-lang.git] / vala / valacodewriter.vala
blob62f1d0758e3df0470cb7eea6154d6a46f14a11a7
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 && ns.parent_symbol == context.root) {
145 // Set GIR information only for the main namespace of the file.
146 if (ns.source_reference.file.gir_namespace != null) {
147 write_string (", ");
148 write_string ("gir_namespace = \"%s\"".printf (ns.source_reference.file.gir_namespace));
150 if (ns.source_reference.file.gir_version != null) {
151 write_string(", ");
152 write_string ("gir_version = \"%s\"".printf (ns.source_reference.file.gir_version));
156 write_string (")]");
157 write_newline ();
159 write_attributes (ns);
161 write_indent ();
162 write_string ("namespace ");
163 write_identifier (ns.name);
164 write_begin_block ();
166 current_scope = ns.scope;
168 visit_sorted (ns.get_namespaces ());
169 visit_sorted (ns.get_classes ());
170 visit_sorted (ns.get_interfaces ());
171 visit_sorted (ns.get_structs ());
172 visit_sorted (ns.get_enums ());
173 visit_sorted (ns.get_error_domains ());
174 visit_sorted (ns.get_delegates ());
175 visit_sorted (ns.get_fields ());
176 visit_sorted (ns.get_constants ());
177 visit_sorted (ns.get_methods ());
179 current_scope = current_scope.parent_scope;
181 write_end_block ();
182 write_newline ();
185 private string get_cheaders (Symbol cl) {
186 bool first = true;
187 string cheaders = "";
188 if (type != CodeWriterType.FAST) {
189 foreach (string cheader in cl.get_cheader_filenames ()) {
190 if (header_to_override != null &&
191 cheader == header_to_override) {
192 cheader = override_header;
194 if (first) {
195 cheaders = cheader;
196 first = false;
197 } else {
198 cheaders = "%s,%s".printf (cheaders, cheader);
202 return cheaders;
205 private void emit_deprecated_attribute (Symbol symbol) {
206 if (symbol.deprecated) {
207 write_indent ();
208 write_string ("[Deprecated");
209 var since = symbol.deprecated_since;
210 var replacement = symbol.replacement;
212 if (since != null || replacement != null) {
213 write_string (" (");
214 if (since != null) {
215 write_string ("since = \"%s\"".printf (since));
217 if (since != null && replacement != null) {
218 write_string (", ");
220 if (replacement != null) {
221 write_string ("replacement = \"%s\"".printf (replacement));
223 write_string (")");
225 write_string ("]");
229 public override void visit_class (Class cl) {
230 if (cl.external_package) {
231 return;
234 if (!check_accessibility (cl)) {
235 return;
238 if (cl.is_compact) {
239 write_indent ();
240 write_string ("[Compact]");
241 write_newline ();
244 if (cl.is_immutable) {
245 write_indent ();
246 write_string ("[Immutable]");
247 write_newline ();
250 emit_deprecated_attribute (cl);
252 write_indent ();
254 write_string ("[CCode (");
256 if (cl.is_reference_counting () && type != CodeWriterType.FAST) {
257 if (cl.base_class == null || cl.base_class.get_ref_function () == null || cl.base_class.get_ref_function () != cl.get_ref_function ()) {
258 write_string ("ref_function = \"%s\", ".printf (cl.get_ref_function ()));
259 if (cl.ref_function_void) {
260 write_string ("ref_function_void = true, ");
263 if (cl.base_class == null || cl.base_class.get_unref_function () == null || cl.base_class.get_unref_function () != cl.get_unref_function ()) {
264 write_string ("unref_function = \"%s\", ".printf (cl.get_unref_function ()));
266 } else {
267 if (cl.get_dup_function () != null) {
268 write_string ("copy_function = \"%s\", ".printf (cl.get_dup_function ()));
270 if (cl.get_free_function () != cl.get_default_free_function ()) {
271 write_string ("free_function = \"%s\", ".printf (cl.get_free_function ()));
275 if (cl.get_cname () != cl.get_default_cname ()) {
276 write_string ("cname = \"%s\", ".printf (cl.get_cname ()));
278 if (cl.const_cname != null) {
279 write_string ("const_cname = \"%s\", ".printf (cl.const_cname));
282 if (cl.type_check_function != null) {
283 write_string ("type_check_function = \"%s\", ".printf (cl.type_check_function ));
286 if (cl.get_type_id () != cl.get_default_type_id ()) {
287 write_string ("type_id = \"%s\", ".printf (cl.get_type_id ()));
290 if (cl.get_param_spec_function () != cl.get_default_param_spec_function ()) {
291 write_string ("param_spec_function = \"%s\", ".printf (cl.get_param_spec_function ()));
294 write_string ("cheader_filename = \"%s\")]".printf (get_cheaders(cl)));
295 write_newline ();
297 write_attributes (cl);
299 write_indent ();
300 write_accessibility (cl);
301 if (cl.is_abstract) {
302 write_string ("abstract ");
304 write_string ("class ");
305 write_identifier (cl.name);
307 var type_params = cl.get_type_parameters ();
308 if (type_params.size > 0) {
309 write_string ("<");
310 bool first = true;
311 foreach (TypeParameter type_param in type_params) {
312 if (first) {
313 first = false;
314 } else {
315 write_string (",");
317 write_identifier (type_param.name);
319 write_string (">");
322 var base_types = cl.get_base_types ();
323 if (base_types.size > 0) {
324 write_string (" : ");
326 bool first = true;
327 foreach (DataType base_type in base_types) {
328 if (!first) {
329 write_string (", ");
330 } else {
331 first = false;
333 write_type (base_type);
336 write_begin_block ();
338 current_scope = cl.scope;
340 visit_sorted (cl.get_classes ());
341 visit_sorted (cl.get_structs ());
342 visit_sorted (cl.get_enums ());
343 visit_sorted (cl.get_delegates ());
344 visit_sorted (cl.get_fields ());
345 visit_sorted (cl.get_constants ());
346 visit_sorted (cl.get_methods ());
347 visit_sorted (cl.get_properties ());
348 visit_sorted (cl.get_signals ());
350 if (cl.constructor != null) {
351 cl.constructor.accept (this);
354 current_scope = current_scope.parent_scope;
356 write_end_block ();
357 write_newline ();
360 void visit_sorted (List<Symbol> symbols) {
361 if (type != CodeWriterType.EXTERNAL) {
362 // order of virtual methods matters for fast vapis
363 foreach (Symbol sym in symbols) {
364 sym.accept (this);
366 return;
369 var sorted_symbols = new ArrayList<Symbol> ();
370 foreach (Symbol sym in symbols) {
371 int left = 0;
372 int right = sorted_symbols.size - 1;
373 if (left > right || sym.name < sorted_symbols[left].name) {
374 sorted_symbols.insert (0, sym);
375 } else if (sym.name > sorted_symbols[right].name) {
376 sorted_symbols.add (sym);
377 } else {
378 while (right - left > 1) {
379 int i = (right + left) / 2;
380 if (sym.name > sorted_symbols[i].name) {
381 left = i;
382 } else {
383 right = i;
386 sorted_symbols.insert (left + 1, sym);
389 foreach (Symbol sym in sorted_symbols) {
390 sym.accept (this);
394 public override void visit_struct (Struct st) {
395 if (st.external_package) {
396 return;
399 if (!check_accessibility (st)) {
400 return;
403 if (st.is_immutable) {
404 write_indent ();
405 write_string ("[Immutable]");
406 write_newline ();
409 emit_deprecated_attribute (st);
411 write_indent ();
413 write_string ("[CCode (");
415 if (st.get_cname () != st.get_default_cname ()) {
416 write_string ("cname = \"%s\", ".printf (st.get_cname ()));
419 if (!st.has_type_id) {
420 write_string ("has_type_id = false, ");
421 } else if (!st.is_simple_type () && st.get_type_id () != "G_TYPE_POINTER") {
422 write_string ("type_id = \"%s\", ".printf (st.get_type_id ()));
425 if (!st.has_copy_function) {
426 write_string ("has_copy_function = false, ");
429 if (!st.has_destroy_function) {
430 write_string ("has_destroy_function = false, ");
433 write_string ("cheader_filename = \"%s\")]".printf (get_cheaders(st)));
434 write_newline ();
436 if (st.is_simple_type ()) {
437 write_indent ();
438 write_string ("[SimpleType]");
439 write_newline ();
442 if (st.is_integer_type ()) {
443 write_indent ();
444 write_string ("[IntegerType (rank = %d)]".printf (st.get_rank ()));
445 write_newline ();
448 if (st.is_floating_type ()) {
449 write_indent ();
450 write_string ("[FloatingType (rank = %d)]".printf (st.get_rank ()));
451 write_newline ();
454 write_attributes (st);
456 write_indent ();
457 write_accessibility (st);
458 write_string ("struct ");
459 write_identifier (st.name);
461 if (st.base_type != null) {
462 write_string (" : ");
463 write_type (st.base_type);
466 write_begin_block ();
468 current_scope = st.scope;
470 foreach (Field field in st.get_fields ()) {
471 field.accept (this);
473 visit_sorted (st.get_constants ());
474 visit_sorted (st.get_methods ());
475 visit_sorted (st.get_properties ());
477 current_scope = current_scope.parent_scope;
479 write_end_block ();
480 write_newline ();
483 public override void visit_interface (Interface iface) {
484 if (iface.external_package) {
485 return;
488 if (!check_accessibility (iface)) {
489 return;
492 emit_deprecated_attribute (iface);
494 write_indent ();
496 write_string ("[CCode (cheader_filename = \"%s\"".printf (get_cheaders(iface)));
497 if (iface.get_lower_case_csuffix () != iface.get_default_lower_case_csuffix ())
498 write_string (", lower_case_csuffix = \"%s\"".printf (iface.get_lower_case_csuffix ()));
499 if (iface.get_type_cname () != iface.get_default_type_cname ())
500 write_string (", type_cname = \"%s\"".printf (iface.get_type_cname ()));
502 write_string (")]");
503 write_newline ();
505 write_attributes (iface);
507 write_indent ();
508 write_accessibility (iface);
509 write_string ("interface ");
510 write_identifier (iface.name);
512 var type_params = iface.get_type_parameters ();
513 if (type_params.size > 0) {
514 write_string ("<");
515 bool first = true;
516 foreach (TypeParameter type_param in type_params) {
517 if (first) {
518 first = false;
519 } else {
520 write_string (",");
522 write_identifier (type_param.name);
524 write_string (">");
527 var prerequisites = iface.get_prerequisites ();
528 if (prerequisites.size > 0) {
529 write_string (" : ");
531 bool first = true;
532 foreach (DataType prerequisite in prerequisites) {
533 if (!first) {
534 write_string (", ");
535 } else {
536 first = false;
538 write_type (prerequisite);
541 write_begin_block ();
543 current_scope = iface.scope;
545 visit_sorted (iface.get_classes ());
546 visit_sorted (iface.get_structs ());
547 visit_sorted (iface.get_enums ());
548 visit_sorted (iface.get_delegates ());
549 visit_sorted (iface.get_fields ());
550 visit_sorted (iface.get_constants ());
551 visit_sorted (iface.get_methods ());
552 visit_sorted (iface.get_properties ());
553 visit_sorted (iface.get_signals ());
555 current_scope = current_scope.parent_scope;
557 write_end_block ();
558 write_newline ();
561 public override void visit_enum (Enum en) {
562 if (en.external_package) {
563 return;
566 if (!check_accessibility (en)) {
567 return;
570 emit_deprecated_attribute (en);
572 write_indent ();
574 write_string ("[CCode (cprefix = \"%s\", ".printf (en.get_cprefix ()));
576 if (!en.has_type_id) {
577 write_string ("has_type_id = false, ");
580 write_string ("cheader_filename = \"%s\")]".printf (get_cheaders(en)));
582 if (en.is_flags) {
583 write_indent ();
584 write_string ("[Flags]");
587 write_attributes (en);
589 write_indent ();
590 write_accessibility (en);
591 write_string ("enum ");
592 write_identifier (en.name);
593 write_begin_block ();
595 bool first = true;
596 foreach (EnumValue ev in en.get_values ()) {
597 if (first) {
598 first = false;
599 } else {
600 write_string (",");
601 write_newline ();
604 if (ev.get_cname () != ev.get_default_cname ()) {
605 write_indent ();
606 write_string ("[CCode (cname = \"%s\")]".printf (ev.get_cname ()));
608 write_indent ();
609 write_identifier (ev.name);
611 if (type == CodeWriterType.FAST && ev.value != null) {
612 write_string(" = ");
613 ev.value.accept (this);
617 if (!first) {
618 if (en.get_methods ().size > 0 || en.get_constants ().size > 0) {
619 write_string (";");
621 write_newline ();
624 current_scope = en.scope;
625 foreach (Method m in en.get_methods ()) {
626 m.accept (this);
628 foreach (Constant c in en.get_constants ()) {
629 c.accept (this);
631 current_scope = current_scope.parent_scope;
633 write_end_block ();
634 write_newline ();
637 public override void visit_error_domain (ErrorDomain edomain) {
638 if (edomain.external_package) {
639 return;
642 if (!check_accessibility (edomain)) {
643 return;
646 emit_deprecated_attribute (edomain);
648 write_indent ();
650 write_string ("[CCode (cprefix = \"%s\", cheader_filename = \"%s\")]".printf (edomain.get_cprefix (), get_cheaders(edomain)));
652 write_attributes (edomain);
654 write_indent ();
655 write_accessibility (edomain);
656 write_string ("errordomain ");
657 write_identifier (edomain.name);
658 write_begin_block ();
660 edomain.accept_children (this);
662 write_end_block ();
663 write_newline ();
666 public override void visit_error_code (ErrorCode ecode) {
667 write_indent ();
668 write_identifier (ecode.name);
669 write_string (",");
670 write_newline ();
673 public override void visit_constant (Constant c) {
674 if (c.external_package) {
675 return;
678 if (!check_accessibility (c)) {
679 return;
682 emit_deprecated_attribute (c);
684 bool custom_cname = (c.get_cname () != c.get_default_cname ());
685 bool custom_cheaders = (c.parent_symbol is Namespace);
686 if (custom_cname || custom_cheaders) {
687 write_indent ();
688 write_string ("[CCode (");
690 if (custom_cname) {
691 write_string ("cname = \"%s\"".printf (c.get_cname ()));
694 if (custom_cheaders) {
695 if (custom_cname) {
696 write_string (", ");
699 write_string ("cheader_filename = \"%s\"".printf (get_cheaders(c)));
702 write_string (")]");
705 write_indent ();
706 write_accessibility (c);
707 write_string ("const ");
709 write_type (c.type_reference);
711 write_string (" ");
712 write_identifier (c.name);
713 if (type == CodeWriterType.FAST && c.value != null) {
714 write_string(" = ");
715 c.value.accept (this);
717 write_string (";");
718 write_newline ();
721 public override void visit_field (Field f) {
722 if (f.external_package) {
723 return;
726 if (!check_accessibility (f)) {
727 return;
730 emit_deprecated_attribute (f);
732 bool custom_cname = (f.get_cname () != f.get_default_cname ());
733 bool custom_ctype = (f.get_ctype () != null);
734 bool custom_cheaders = (f.parent_symbol is Namespace);
735 bool custom_array_length_cname = (f.get_array_length_cname () != null);
736 bool custom_array_length_type = (f.array_length_type != null);
737 if (custom_cname || custom_ctype || custom_cheaders || custom_array_length_cname || custom_array_length_type || (f.no_array_length && f.variable_type is ArrayType)) {
738 write_indent ();
739 write_string ("[CCode (");
741 if (custom_cname) {
742 write_string ("cname = \"%s\"".printf (f.get_cname ()));
745 if (custom_ctype) {
746 if (custom_cname) {
747 write_string (", ");
750 write_string ("type = \"%s\"".printf (f.get_ctype ()));
753 if (custom_cheaders) {
754 if (custom_cname || custom_ctype) {
755 write_string (", ");
758 write_string ("cheader_filename = \"%s\"".printf (get_cheaders(f)));
761 if (f.variable_type is ArrayType) {
762 if (f.no_array_length) {
763 if (custom_cname || custom_ctype || custom_cheaders) {
764 write_string (", ");
767 write_string ("array_length = false");
769 if (f.array_null_terminated) {
770 write_string (", array_null_terminated = true");
772 } else {
773 if (custom_array_length_cname) {
774 if (custom_cname || custom_ctype || custom_cheaders) {
775 write_string (", ");
778 write_string ("array_length_cname = \"%s\"".printf (f.get_array_length_cname ()));
781 if (custom_array_length_type) {
782 if (custom_cname || custom_ctype || custom_cheaders || custom_array_length_cname) {
783 write_string (", ");
786 write_string ("array_length_type = \"%s\"".printf (f.array_length_type));
791 write_string (")]");
794 write_indent ();
795 write_accessibility (f);
797 if (f.binding == MemberBinding.STATIC) {
798 write_string ("static ");
799 } else if (f.binding == MemberBinding.CLASS) {
800 write_string ("class ");
803 if (f.variable_type.is_weak ()) {
804 write_string ("weak ");
807 write_type (f.variable_type);
809 write_string (" ");
810 write_identifier (f.name);
811 write_string (";");
812 write_newline ();
815 private void write_error_domains (List<DataType> error_domains) {
816 if (error_domains.size > 0) {
817 write_string (" throws ");
819 bool first = true;
820 foreach (DataType type in error_domains) {
821 if (!first) {
822 write_string (", ");
823 } else {
824 first = false;
827 write_type (type);
832 // equality comparison with 3 digit precision
833 private bool float_equal (double d1, double d2) {
834 return ((int) (d1 * 1000)) == ((int) (d2 * 1000));
837 private void write_params (List<Parameter> params) {
838 write_string ("(");
840 int i = 1;
841 foreach (Parameter param in params) {
842 if (i > 1) {
843 write_string (", ");
846 if (param.ellipsis) {
847 write_string ("...");
848 continue;
852 var ccode_params = new StringBuilder ();
853 var separator = "";
855 if (!float_equal (param.cparameter_position, i)) {
856 ccode_params.append_printf ("%spos = %g", separator, param.cparameter_position);
857 separator = ", ";
859 if (param.ctype != null) {
860 ccode_params.append_printf ("%stype = \"%s\"", separator, param.ctype);
861 separator = ", ";
863 if (param.no_array_length && param.variable_type is ArrayType) {
864 ccode_params.append_printf ("%sarray_length = false", separator);
865 separator = ", ";
867 if (param.array_length_type != null && param.variable_type is ArrayType) {
868 ccode_params.append_printf ("%sarray_length_type = \"%s\"", separator, param.array_length_type);
869 separator = ", ";
871 if (param.get_array_length_cname () != null && param.variable_type is ArrayType) {
872 ccode_params.append_printf ("%sarray_length_cname = \"%s\"", separator, param.get_array_length_cname ());
873 separator = ", ";
875 if (!float_equal (param.carray_length_parameter_position, i + 0.1)) {
876 ccode_params.append_printf ("%sarray_length_pos = %g", separator, param.carray_length_parameter_position);
877 separator = ", ";
879 if (!float_equal (param.cdelegate_target_parameter_position, i + 0.1)) {
880 ccode_params.append_printf ("%sdelegate_target_pos = %g", separator, param.cdelegate_target_parameter_position);
881 separator = ", ";
884 if (ccode_params.len > 0) {
885 write_string ("[CCode (%s)] ".printf (ccode_params.str));
888 if (param.params_array) {
889 write_string ("params ");
892 if (param.direction == ParameterDirection.IN) {
893 if (param.variable_type.value_owned) {
894 write_string ("owned ");
896 } else {
897 if (param.direction == ParameterDirection.REF) {
898 write_string ("ref ");
899 } else if (param.direction == ParameterDirection.OUT) {
900 write_string ("out ");
902 if (param.variable_type.is_weak ()) {
903 write_string ("unowned ");
907 write_type (param.variable_type);
909 write_string (" ");
910 write_identifier (param.name);
912 if (param.initializer != null) {
913 write_string (" = ");
914 param.initializer.accept (this);
917 i++;
920 write_string (")");
923 public override void visit_delegate (Delegate cb) {
924 if (cb.external_package) {
925 return;
928 if (!check_accessibility (cb)) {
929 return;
932 emit_deprecated_attribute (cb);
934 write_indent ();
936 write_string ("[CCode (cheader_filename = \"%s\"".printf (get_cheaders(cb)));
938 if (!cb.has_target) {
939 write_string (", has_target = false");
940 } else if (!float_equal (cb.cinstance_parameter_position, -2)) {
941 write_string (", instance_pos = %g".printf (cb.cinstance_parameter_position));
944 write_string (")]");
946 write_indent ();
948 write_accessibility (cb);
949 write_string ("delegate ");
951 write_return_type (cb.return_type);
953 write_string (" ");
954 write_identifier (cb.name);
956 var type_params = cb.get_type_parameters ();
957 if (type_params.size > 0) {
958 write_string ("<");
959 bool first = true;
960 foreach (TypeParameter type_param in type_params) {
961 if (first) {
962 first = false;
963 } else {
964 write_string (",");
966 write_identifier (type_param.name);
968 write_string (">");
971 write_string (" ");
973 write_params (cb.get_parameters ());
975 write_error_domains (cb.get_error_types ());
977 write_string (";");
979 write_newline ();
982 public override void visit_constructor (Constructor c) {
983 if (type != CodeWriterType.DUMP) {
984 return;
987 write_indent ();
988 write_string ("construct");
989 write_code_block (c.body);
990 write_newline ();
993 public override void visit_method (Method m) {
994 if (m.external_package) {
995 return;
998 // don't write interface implementation unless it's an abstract or virtual method
999 if (!check_accessibility (m) || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
1000 if (type != CodeWriterType.DUMP) {
1001 return;
1005 if (m.get_attribute ("NoWrapper") != null) {
1006 write_indent ();
1007 write_string ("[NoWrapper]");
1009 if (m.get_attribute ("NoThrow") != null) {
1010 write_indent ();
1011 write_string ("[NoThrow]");
1013 if (m.returns_modified_pointer) {
1014 write_indent ();
1015 write_string ("[ReturnsModifiedPointer]");
1017 if (m.printf_format) {
1018 write_indent ();
1019 write_string ("[PrintfFormat]");
1021 if (m.scanf_format) {
1022 write_indent ();
1023 write_string ("[ScanfFormat]");
1025 if (m.get_attribute ("Print") != null) {
1026 write_indent ();
1027 write_string ("[Print]");
1029 if (m.get_attribute ("NoReturn") != null) {
1030 write_indent ();
1031 write_string ("[NoReturn]");
1034 emit_deprecated_attribute (m);
1036 var ccode_params = new StringBuilder ();
1037 var separator = "";
1039 if (m.get_cname () != m.get_default_cname ()) {
1040 ccode_params.append_printf ("%scname = \"%s\"", separator, m.get_cname ());
1041 separator = ", ";
1043 if (m.parent_symbol is Namespace) {
1044 ccode_params.append_printf ("%scheader_filename = \"%s\"", separator, get_cheaders(m));
1045 separator = ", ";
1047 if (!float_equal (m.cinstance_parameter_position, 0)) {
1048 ccode_params.append_printf ("%sinstance_pos = %g", separator, m.cinstance_parameter_position);
1049 separator = ", ";
1051 if (m.no_array_length && m.return_type is ArrayType) {
1052 ccode_params.append_printf ("%sarray_length = false", separator);
1053 separator = ", ";
1055 if (!float_equal (m.carray_length_parameter_position, -3)) {
1056 ccode_params.append_printf ("%sarray_length_pos = %g", separator, m.carray_length_parameter_position);
1057 separator = ", ";
1059 if (m.array_null_terminated && m.return_type is ArrayType) {
1060 ccode_params.append_printf ("%sarray_null_terminated = true", separator);
1061 separator = ", ";
1063 if (m.array_length_type != null && m.return_type is ArrayType) {
1064 ccode_params.append_printf ("%sarray_length_type = \"%s\"", separator, m.array_length_type);
1065 separator = ", ";
1067 if (!float_equal (m.cdelegate_target_parameter_position, -3)) {
1068 ccode_params.append_printf ("%sdelegate_target_pos = %g", separator, m.cdelegate_target_parameter_position);
1069 separator = ", ";
1071 if (m.vfunc_name != m.name) {
1072 ccode_params.append_printf ("%svfunc_name = \"%s\"", separator, m.vfunc_name);
1073 separator = ", ";
1075 if (m.coroutine && m.get_finish_cname () != m.get_default_finish_cname ()) {
1076 ccode_params.append_printf ("%sfinish_name = \"%s\"", separator, m.get_finish_cname ());
1077 separator = ", ";
1079 if (m.sentinel != m.DEFAULT_SENTINEL) {
1080 ccode_params.append_printf ("%ssentinel = \"%s\"", separator, m.sentinel);
1081 separator = ", ";
1083 var cm = m as CreationMethod;
1084 if (cm != null) {
1085 if (cm.custom_return_type_cname != null) {
1086 ccode_params.append_printf ("%stype = \"%s\"", separator, cm.custom_return_type_cname);
1087 separator = ", ";
1089 if (!m.has_new_function) {
1090 ccode_params.append_printf ("%shas_new_function = false", separator);
1091 separator = ", ";
1093 if (!m.has_construct_function) {
1094 ccode_params.append_printf ("%shas_construct_function = false", separator);
1095 separator = ", ";
1096 } else if (m.name == ".new" && m.get_real_cname () != cm.get_default_construct_function ()) {
1097 ccode_params.append_printf ("%sconstruct_function = \"%s\"", separator, m.get_real_cname ());
1098 separator = ", ";
1102 if (ccode_params.len > 0) {
1103 write_indent ();
1104 write_string ("[CCode (%s)]".printf (ccode_params.str));
1107 write_indent ();
1108 write_accessibility (m);
1110 if (m is CreationMethod) {
1111 if (m.coroutine) {
1112 write_string ("async ");
1115 var datatype = (TypeSymbol) m.parent_symbol;
1116 write_identifier (datatype.name);
1117 if (m.name != ".new") {
1118 write_string (".");
1119 write_identifier (m.name);
1121 write_string (" ");
1122 } else {
1123 if (m.binding == MemberBinding.STATIC) {
1124 write_string ("static ");
1125 } else if (m.binding == MemberBinding.CLASS) {
1126 write_string ("class ");
1127 } else if (m.is_abstract) {
1128 write_string ("abstract ");
1129 } else if (m.is_virtual) {
1130 write_string ("virtual ");
1131 } else if (m.overrides) {
1132 write_string ("override ");
1135 if (m.hides) {
1136 write_string ("new ");
1139 if (m.coroutine) {
1140 write_string ("async ");
1143 write_return_type (m.return_type);
1144 write_string (" ");
1146 write_identifier (m.name);
1148 var type_params = m.get_type_parameters ();
1149 if (type_params.size > 0) {
1150 write_string ("<");
1151 bool first = true;
1152 foreach (TypeParameter type_param in type_params) {
1153 if (first) {
1154 first = false;
1155 } else {
1156 write_string (",");
1158 write_identifier (type_param.name);
1160 write_string (">");
1163 write_string (" ");
1166 write_params (m.get_parameters ());
1168 if (context.profile != Profile.DOVA) {
1169 write_error_domains (m.get_error_types ());
1172 write_code_block (m.body);
1174 write_newline ();
1177 public override void visit_creation_method (CreationMethod m) {
1178 visit_method (m);
1181 public override void visit_property (Property prop) {
1182 if (!check_accessibility (prop) || (prop.base_interface_property != null && !prop.is_abstract && !prop.is_virtual)) {
1183 return;
1186 emit_deprecated_attribute (prop);
1188 if (prop.no_accessor_method) {
1189 write_indent ();
1190 write_string ("[NoAccessorMethod]");
1192 if (prop.property_type is ArrayType && prop.no_array_length) {
1193 write_indent ();
1194 write_string ("[CCode (array_length = false");
1196 if (prop.array_null_terminated) {
1197 write_string (", array_null_terminated = true");
1200 write_string (")]");
1203 write_indent ();
1204 write_accessibility (prop);
1206 if (prop.binding == MemberBinding.STATIC) {
1207 write_string ("static ");
1208 } else if (prop.is_abstract) {
1209 write_string ("abstract ");
1210 } else if (prop.is_virtual) {
1211 write_string ("virtual ");
1212 } else if (prop.overrides) {
1213 write_string ("override ");
1216 write_type (prop.property_type);
1218 write_string (" ");
1219 write_identifier (prop.name);
1220 write_string (" {");
1221 if (prop.get_accessor != null) {
1222 var ccode_params = new StringBuilder ();
1223 var separator = "";
1225 if (prop.get_accessor.get_cname () != prop.get_accessor.get_default_cname ()) {
1226 ccode_params.append_printf ("%scname = \"%s\"", separator, prop.get_accessor.get_cname ());
1227 separator = ", ";
1229 if (ccode_params.len > 0) {
1230 write_indent ();
1231 write_string ("[CCode (%s)]".printf (ccode_params.str));
1234 write_property_accessor_accessibility (prop.get_accessor);
1236 if (context.profile != Profile.DOVA && prop.get_accessor.value_type.is_disposable ()) {
1237 write_string (" owned");
1240 write_string (" get");
1241 write_code_block (prop.get_accessor.body);
1243 if (prop.set_accessor != null) {
1244 var ccode_params = new StringBuilder ();
1245 var separator = "";
1247 if (prop.set_accessor.get_cname () != prop.set_accessor.get_default_cname ()) {
1248 ccode_params.append_printf ("%scname = \"%s\"", separator, prop.set_accessor.get_cname ());
1249 separator = ", ";
1251 if (ccode_params.len > 0) {
1252 write_indent ();
1253 write_string ("[CCode (%s)]".printf (ccode_params.str));
1256 write_property_accessor_accessibility (prop.set_accessor);
1258 if (context.profile != Profile.DOVA && prop.set_accessor.value_type.value_owned) {
1259 write_string (" owned");
1262 if (prop.set_accessor.writable) {
1263 write_string (" set");
1265 if (prop.set_accessor.construction) {
1266 write_string (" construct");
1268 write_code_block (prop.set_accessor.body);
1270 write_string (" }");
1271 write_newline ();
1274 public override void visit_signal (Signal sig) {
1275 if (!check_accessibility (sig)) {
1276 return;
1279 if (sig.has_emitter) {
1280 write_indent ();
1281 write_string ("[HasEmitter]");
1284 emit_deprecated_attribute (sig);
1286 write_indent ();
1287 write_accessibility (sig);
1289 if (sig.is_virtual) {
1290 write_string ("virtual ");
1293 write_string ("signal ");
1295 write_return_type (sig.return_type);
1297 write_string (" ");
1298 write_identifier (sig.name);
1300 write_string (" ");
1302 write_params (sig.get_parameters ());
1304 write_string (";");
1306 write_newline ();
1309 public override void visit_block (Block b) {
1310 write_begin_block ();
1312 foreach (Statement stmt in b.get_statements ()) {
1313 stmt.accept (this);
1316 write_end_block ();
1319 public override void visit_empty_statement (EmptyStatement stmt) {
1322 public override void visit_declaration_statement (DeclarationStatement stmt) {
1323 write_indent ();
1324 stmt.declaration.accept (this);
1325 write_string (";");
1326 write_newline ();
1329 public override void visit_local_variable (LocalVariable local) {
1330 write_type (local.variable_type);
1331 write_string (" ");
1332 write_identifier (local.name);
1333 if (local.initializer != null) {
1334 write_string (" = ");
1335 local.initializer.accept (this);
1339 public override void visit_initializer_list (InitializerList list) {
1340 write_string ("{");
1342 bool first = true;
1343 foreach (Expression initializer in list.get_initializers ()) {
1344 if (!first) {
1345 write_string (", ");
1346 } else {
1347 write_string (" ");
1349 first = false;
1350 initializer.accept (this);
1352 write_string (" }");
1355 public override void visit_expression_statement (ExpressionStatement stmt) {
1356 write_indent ();
1357 stmt.expression.accept (this);
1358 write_string (";");
1359 write_newline ();
1362 public override void visit_if_statement (IfStatement stmt) {
1363 write_indent ();
1364 write_string ("if (");
1365 stmt.condition.accept (this);
1366 write_string (")");
1367 stmt.true_statement.accept (this);
1368 if (stmt.false_statement != null) {
1369 write_string (" else");
1370 stmt.false_statement.accept (this);
1372 write_newline ();
1375 public override void visit_switch_statement (SwitchStatement stmt) {
1376 write_indent ();
1377 write_string ("switch (");
1378 stmt.expression.accept (this);
1379 write_string (") {");
1380 write_newline ();
1382 foreach (SwitchSection section in stmt.get_sections ()) {
1383 section.accept (this);
1386 write_indent ();
1387 write_string ("}");
1388 write_newline ();
1391 public override void visit_switch_section (SwitchSection section) {
1392 foreach (SwitchLabel label in section.get_labels ()) {
1393 label.accept (this);
1396 visit_block (section);
1399 public override void visit_switch_label (SwitchLabel label) {
1400 if (label.expression != null) {
1401 write_indent ();
1402 write_string ("case ");
1403 label.expression.accept (this);
1404 write_string (":");
1405 write_newline ();
1406 } else {
1407 write_indent ();
1408 write_string ("default:");
1409 write_newline ();
1413 public override void visit_loop (Loop stmt) {
1414 write_indent ();
1415 write_string ("loop");
1416 stmt.body.accept (this);
1417 write_newline ();
1420 public override void visit_while_statement (WhileStatement stmt) {
1421 write_indent ();
1422 write_string ("while (");
1423 stmt.condition.accept (this);
1424 write_string (")");
1425 stmt.body.accept (this);
1426 write_newline ();
1429 public override void visit_do_statement (DoStatement stmt) {
1430 write_indent ();
1431 write_string ("do");
1432 stmt.body.accept (this);
1433 write_string ("while (");
1434 stmt.condition.accept (this);
1435 write_string (");");
1436 write_newline ();
1439 public override void visit_for_statement (ForStatement stmt) {
1440 write_indent ();
1441 write_string ("for (");
1443 bool first = true;
1444 foreach (Expression initializer in stmt.get_initializer ()) {
1445 if (!first) {
1446 write_string (", ");
1448 first = false;
1449 initializer.accept (this);
1451 write_string ("; ");
1453 stmt.condition.accept (this);
1454 write_string ("; ");
1456 first = true;
1457 foreach (Expression iterator in stmt.get_iterator ()) {
1458 if (!first) {
1459 write_string (", ");
1461 first = false;
1462 iterator.accept (this);
1465 write_string (")");
1466 stmt.body.accept (this);
1467 write_newline ();
1470 public override void visit_foreach_statement (ForeachStatement stmt) {
1473 public override void visit_break_statement (BreakStatement stmt) {
1474 write_indent ();
1475 write_string ("break;");
1476 write_newline ();
1479 public override void visit_continue_statement (ContinueStatement stmt) {
1480 write_indent ();
1481 write_string ("continue;");
1482 write_newline ();
1485 public override void visit_return_statement (ReturnStatement stmt) {
1486 write_indent ();
1487 write_string ("return");
1488 if (stmt.return_expression != null) {
1489 write_string (" ");
1490 stmt.return_expression.accept (this);
1492 write_string (";");
1493 write_newline ();
1496 public override void visit_yield_statement (YieldStatement y) {
1497 write_indent ();
1498 write_string ("yield");
1499 if (y.yield_expression != null) {
1500 write_string (" ");
1501 y.yield_expression.accept (this);
1503 write_string (";");
1504 write_newline ();
1507 public override void visit_throw_statement (ThrowStatement stmt) {
1508 write_indent ();
1509 write_string ("throw");
1510 if (stmt.error_expression != null) {
1511 write_string (" ");
1512 stmt.error_expression.accept (this);
1514 write_string (";");
1515 write_newline ();
1518 public override void visit_try_statement (TryStatement stmt) {
1519 write_indent ();
1520 write_string ("try");
1521 stmt.body.accept (this);
1522 foreach (var clause in stmt.get_catch_clauses ()) {
1523 clause.accept (this);
1525 if (stmt.finally_body != null) {
1526 write_string (" finally");
1527 stmt.finally_body.accept (this);
1529 write_newline ();
1532 public override void visit_catch_clause (CatchClause clause) {
1533 var type_name = clause.error_type == null ? "GLib.Error" : clause.error_type.to_string ();
1534 var var_name = clause.variable_name == null ? "_" : clause.variable_name;
1535 write_string (" catch (%s %s)".printf (type_name, var_name));
1536 clause.body.accept (this);
1539 public override void visit_lock_statement (LockStatement stmt) {
1540 write_indent ();
1541 write_string ("lock (");
1542 stmt.resource.accept (this);
1543 write_string (")");
1544 if (stmt.body == null) {
1545 write_string (";");
1546 } else {
1547 stmt.body.accept (this);
1549 write_newline ();
1552 public override void visit_delete_statement (DeleteStatement stmt) {
1553 write_indent ();
1554 write_string ("delete ");
1555 stmt.expression.accept (this);
1556 write_string (";");
1557 write_newline ();
1560 public override void visit_array_creation_expression (ArrayCreationExpression expr) {
1561 write_string ("new ");
1562 write_type (expr.element_type);
1563 write_string ("[");
1565 bool first = true;
1566 foreach (Expression size in expr.get_sizes ()) {
1567 if (!first) {
1568 write_string (", ");
1570 first = false;
1572 size.accept (this);
1575 write_string ("]");
1577 if (expr.initializer_list != null) {
1578 write_string (" ");
1579 expr.initializer_list.accept (this);
1583 public override void visit_boolean_literal (BooleanLiteral lit) {
1584 write_string (lit.value.to_string ());
1587 public override void visit_character_literal (CharacterLiteral lit) {
1588 write_string (lit.value);
1591 public override void visit_integer_literal (IntegerLiteral lit) {
1592 write_string (lit.value);
1595 public override void visit_real_literal (RealLiteral lit) {
1596 write_string (lit.value);
1599 public override void visit_string_literal (StringLiteral lit) {
1600 write_string (lit.value);
1603 public override void visit_null_literal (NullLiteral lit) {
1604 write_string ("null");
1607 public override void visit_member_access (MemberAccess expr) {
1608 if (expr.inner != null) {
1609 expr.inner.accept (this);
1610 write_string (".");
1612 write_identifier (expr.member_name);
1615 public override void visit_method_call (MethodCall expr) {
1616 expr.call.accept (this);
1617 write_string (" (");
1619 bool first = true;
1620 foreach (Expression arg in expr.get_argument_list ()) {
1621 if (!first) {
1622 write_string (", ");
1624 first = false;
1626 arg.accept (this);
1629 write_string (")");
1632 public override void visit_element_access (ElementAccess expr) {
1633 expr.container.accept (this);
1634 write_string ("[");
1636 bool first = true;
1637 foreach (Expression index in expr.get_indices ()) {
1638 if (!first) {
1639 write_string (", ");
1641 first = false;
1643 index.accept (this);
1646 write_string ("]");
1649 public override void visit_slice_expression (SliceExpression expr) {
1650 expr.container.accept (this);
1651 write_string ("[");
1652 expr.start.accept (this);
1653 write_string (":");
1654 expr.stop.accept (this);
1655 write_string ("]");
1658 public override void visit_base_access (BaseAccess expr) {
1659 write_string ("base");
1662 public override void visit_postfix_expression (PostfixExpression expr) {
1663 expr.inner.accept (this);
1664 if (expr.increment) {
1665 write_string ("++");
1666 } else {
1667 write_string ("--");
1671 public override void visit_object_creation_expression (ObjectCreationExpression expr) {
1672 if (!expr.struct_creation) {
1673 write_string ("new ");
1676 write_type (expr.type_reference);
1678 if (expr.symbol_reference.name != ".new") {
1679 write_string (".");
1680 write_string (expr.symbol_reference.name);
1683 write_string (" (");
1685 bool first = true;
1686 foreach (Expression arg in expr.get_argument_list ()) {
1687 if (!first) {
1688 write_string (", ");
1690 first = false;
1692 arg.accept (this);
1695 write_string (")");
1698 public override void visit_sizeof_expression (SizeofExpression expr) {
1699 write_string ("sizeof (");
1700 write_type (expr.type_reference);
1701 write_string (")");
1704 public override void visit_typeof_expression (TypeofExpression expr) {
1705 write_string ("typeof (");
1706 write_type (expr.type_reference);
1707 write_string (")");
1710 public override void visit_unary_expression (UnaryExpression expr) {
1711 switch (expr.operator) {
1712 case UnaryOperator.PLUS:
1713 write_string ("+");
1714 break;
1715 case UnaryOperator.MINUS:
1716 write_string ("-");
1717 break;
1718 case UnaryOperator.LOGICAL_NEGATION:
1719 write_string ("!");
1720 break;
1721 case UnaryOperator.BITWISE_COMPLEMENT:
1722 write_string ("~");
1723 break;
1724 case UnaryOperator.INCREMENT:
1725 write_string ("++");
1726 break;
1727 case UnaryOperator.DECREMENT:
1728 write_string ("--");
1729 break;
1730 case UnaryOperator.REF:
1731 write_string ("ref ");
1732 break;
1733 case UnaryOperator.OUT:
1734 write_string ("out ");
1735 break;
1736 default:
1737 assert_not_reached ();
1739 expr.inner.accept (this);
1742 public override void visit_cast_expression (CastExpression expr) {
1743 if (expr.is_non_null_cast) {
1744 write_string ("(!) ");
1745 expr.inner.accept (this);
1746 return;
1749 if (!expr.is_silent_cast) {
1750 write_string ("(");
1751 write_type (expr.type_reference);
1752 write_string (") ");
1755 expr.inner.accept (this);
1757 if (expr.is_silent_cast) {
1758 write_string (" as ");
1759 write_type (expr.type_reference);
1763 public override void visit_pointer_indirection (PointerIndirection expr) {
1764 write_string ("*");
1765 expr.inner.accept (this);
1768 public override void visit_addressof_expression (AddressofExpression expr) {
1769 write_string ("&");
1770 expr.inner.accept (this);
1773 public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
1774 write_string ("(owned) ");
1775 expr.inner.accept (this);
1778 public override void visit_binary_expression (BinaryExpression expr) {
1779 expr.left.accept (this);
1781 switch (expr.operator) {
1782 case BinaryOperator.PLUS:
1783 write_string (" + ");
1784 break;
1785 case BinaryOperator.MINUS:
1786 write_string (" - ");
1787 break;
1788 case BinaryOperator.MUL:
1789 write_string (" * ");
1790 break;
1791 case BinaryOperator.DIV:
1792 write_string (" / ");
1793 break;
1794 case BinaryOperator.MOD:
1795 write_string (" % ");
1796 break;
1797 case BinaryOperator.SHIFT_LEFT:
1798 write_string (" << ");
1799 break;
1800 case BinaryOperator.SHIFT_RIGHT:
1801 write_string (" >> ");
1802 break;
1803 case BinaryOperator.LESS_THAN:
1804 write_string (" < ");
1805 break;
1806 case BinaryOperator.GREATER_THAN:
1807 write_string (" > ");
1808 break;
1809 case BinaryOperator.LESS_THAN_OR_EQUAL:
1810 write_string (" <= ");
1811 break;
1812 case BinaryOperator.GREATER_THAN_OR_EQUAL:
1813 write_string (" >= ");
1814 break;
1815 case BinaryOperator.EQUALITY:
1816 write_string (" == ");
1817 break;
1818 case BinaryOperator.INEQUALITY:
1819 write_string (" != ");
1820 break;
1821 case BinaryOperator.BITWISE_AND:
1822 write_string (" & ");
1823 break;
1824 case BinaryOperator.BITWISE_OR:
1825 write_string (" | ");
1826 break;
1827 case BinaryOperator.BITWISE_XOR:
1828 write_string (" ^ ");
1829 break;
1830 case BinaryOperator.AND:
1831 write_string (" && ");
1832 break;
1833 case BinaryOperator.OR:
1834 write_string (" || ");
1835 break;
1836 case BinaryOperator.IN:
1837 write_string (" in ");
1838 break;
1839 case BinaryOperator.COALESCE:
1840 write_string (" ?? ");
1841 break;
1842 default:
1843 assert_not_reached ();
1846 expr.right.accept (this);
1849 public override void visit_type_check (TypeCheck expr) {
1850 expr.expression.accept (this);
1851 write_string (" is ");
1852 write_type (expr.type_reference);
1855 public override void visit_conditional_expression (ConditionalExpression expr) {
1856 expr.condition.accept (this);
1857 write_string ("?");
1858 expr.true_expression.accept (this);
1859 write_string (":");
1860 expr.false_expression.accept (this);
1863 public override void visit_lambda_expression (LambdaExpression expr) {
1864 write_string ("(");
1865 var params = expr.get_parameters ();
1866 if (params.size != 0) {
1867 for (var i = 0; i < params.size - 1; ++ i) {
1868 write_string (params[i]);
1869 write_string (", ");
1871 write_string (params[params.size - 1]);
1873 write_string (") =>");
1874 if (expr.statement_body != null) {
1875 expr.statement_body.accept (this);
1876 } else if (expr.expression_body != null) {
1877 expr.expression_body.accept (this);
1881 public override void visit_assignment (Assignment a) {
1882 a.left.accept (this);
1883 write_string (" = ");
1884 a.right.accept (this);
1887 private void write_indent () {
1888 int i;
1890 if (!bol) {
1891 stream.putc ('\n');
1894 for (i = 0; i < indent; i++) {
1895 stream.putc ('\t');
1898 bol = false;
1901 private void write_identifier (string s) {
1902 char* id = (char*)s;
1903 int id_length = (int)s.length;
1904 if (context.profile != Profile.DOVA &&
1905 (Vala.Scanner.get_identifier_or_keyword (id, id_length) != Vala.TokenType.IDENTIFIER ||
1906 s.get_char ().isdigit ())) {
1907 stream.putc ('@');
1909 write_string (s);
1912 private void write_return_type (DataType type) {
1913 if (type.is_weak ()) {
1914 write_string ("unowned ");
1917 write_type (type);
1920 private void write_type (DataType type) {
1921 write_string (type.to_qualified_string (current_scope));
1924 private void write_string (string s) {
1925 stream.printf ("%s", s);
1926 bol = false;
1929 private void write_newline () {
1930 stream.putc ('\n');
1931 bol = true;
1934 void write_code_block (Block? block) {
1935 if (block == null || type != CodeWriterType.DUMP) {
1936 write_string (";");
1937 return;
1940 block.accept (this);
1943 private void write_begin_block () {
1944 if (!bol) {
1945 stream.putc (' ');
1946 } else {
1947 write_indent ();
1949 stream.putc ('{');
1950 write_newline ();
1951 indent++;
1954 private void write_end_block () {
1955 indent--;
1956 write_indent ();
1957 stream.printf ("}");
1960 private bool check_accessibility (Symbol sym) {
1961 switch (type) {
1962 case CodeWriterType.EXTERNAL:
1963 return sym.access == SymbolAccessibility.PUBLIC ||
1964 sym.access == SymbolAccessibility.PROTECTED;
1966 case CodeWriterType.INTERNAL:
1967 case CodeWriterType.FAST:
1968 return sym.access == SymbolAccessibility.INTERNAL ||
1969 sym.access == SymbolAccessibility.PUBLIC ||
1970 sym.access == SymbolAccessibility.PROTECTED;
1972 case CodeWriterType.DUMP:
1973 return true;
1975 default:
1976 assert_not_reached ();
1980 private void write_attributes (CodeNode node) {
1981 foreach (Attribute attr in node.attributes) {
1982 if (!filter_attribute (attr)) {
1983 write_indent ();
1984 stream.printf ("[%s", attr.name);
1986 var keys = attr.args.get_keys ();
1987 if (keys.size != 0) {
1988 stream.printf (" (");
1990 string separator = "";
1991 foreach (string arg_name in keys) {
1992 stream.printf ("%s%s = %s", separator, arg_name, attr.args.get (arg_name));
1993 separator = ", ";
1996 stream.printf (")");
1998 stream.printf ("]");
1999 write_newline ();
2004 private bool filter_attribute (Attribute attr) {
2005 if (attr.name == "CCode"
2006 || attr.name == "Compact" || attr.name == "Immutable"
2007 || attr.name == "SimpleType" || attr.name == "IntegerType" || attr.name == "FloatingType"
2008 || attr.name == "Flags") {
2009 return true;
2011 return false;
2014 private void write_accessibility (Symbol sym) {
2015 if (sym.access == SymbolAccessibility.PUBLIC) {
2016 write_string ("public ");
2017 } else if (sym.access == SymbolAccessibility.PROTECTED) {
2018 write_string ("protected ");
2019 } else if (sym.access == SymbolAccessibility.INTERNAL) {
2020 write_string ("internal ");
2021 } else if (sym.access == SymbolAccessibility.PRIVATE) {
2022 write_string ("private ");
2025 if (type != CodeWriterType.EXTERNAL && sym.external && !sym.external_package) {
2026 write_string ("extern ");
2030 void write_property_accessor_accessibility (Symbol sym) {
2031 if (sym.access == SymbolAccessibility.PROTECTED) {
2032 write_string (" protected");
2033 } else if (sym.access == SymbolAccessibility.INTERNAL) {
2034 write_string (" internal");
2035 } else if (sym.access == SymbolAccessibility.PRIVATE) {
2036 write_string (" private");
2041 public enum Vala.CodeWriterType {
2042 EXTERNAL,
2043 INTERNAL,
2044 FAST,
2045 DUMP