Bump version suffix
[vala-lang.git] / vala / valacodewriter.vala
blobb6e31c27284b39e9a2fbb7e5617002ae6bb25e88
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 private void emit_experimental_attribute (Symbol symbol) {
230 if (symbol.experimental) {
231 write_indent ();
232 write_string ("[Experimental]");
233 write_newline ();
237 public override void visit_class (Class cl) {
238 if (cl.external_package) {
239 return;
242 if (!check_accessibility (cl)) {
243 return;
246 if (cl.is_compact) {
247 write_indent ();
248 write_string ("[Compact]");
249 write_newline ();
252 if (cl.is_immutable) {
253 write_indent ();
254 write_string ("[Immutable]");
255 write_newline ();
258 emit_deprecated_attribute (cl);
259 emit_experimental_attribute (cl);
261 write_indent ();
263 write_string ("[CCode (");
265 if (cl.is_reference_counting () && type != CodeWriterType.FAST) {
266 if (cl.base_class == null || cl.base_class.get_ref_function () == null || cl.base_class.get_ref_function () != cl.get_ref_function ()) {
267 write_string ("ref_function = \"%s\", ".printf (cl.get_ref_function ()));
268 if (cl.ref_function_void) {
269 write_string ("ref_function_void = true, ");
272 if (cl.base_class == null || cl.base_class.get_unref_function () == null || cl.base_class.get_unref_function () != cl.get_unref_function ()) {
273 write_string ("unref_function = \"%s\", ".printf (cl.get_unref_function ()));
275 } else {
276 if (cl.get_dup_function () != null) {
277 write_string ("copy_function = \"%s\", ".printf (cl.get_dup_function ()));
279 if (cl.get_free_function () != cl.get_default_free_function ()) {
280 write_string ("free_function = \"%s\", ".printf (cl.get_free_function ()));
284 if (cl.get_cname () != cl.get_default_cname ()) {
285 write_string ("cname = \"%s\", ".printf (cl.get_cname ()));
287 if (cl.const_cname != null) {
288 write_string ("const_cname = \"%s\", ".printf (cl.const_cname));
291 if (cl.type_check_function != null) {
292 write_string ("type_check_function = \"%s\", ".printf (cl.type_check_function ));
295 if (cl.get_type_id () != cl.get_default_type_id ()) {
296 write_string ("type_id = \"%s\", ".printf (cl.get_type_id ()));
299 if (cl.get_param_spec_function () != cl.get_default_param_spec_function ()) {
300 write_string ("param_spec_function = \"%s\", ".printf (cl.get_param_spec_function ()));
303 write_string ("cheader_filename = \"%s\")]".printf (get_cheaders(cl)));
304 write_newline ();
306 write_attributes (cl);
308 write_indent ();
309 write_accessibility (cl);
310 if (cl.is_abstract) {
311 write_string ("abstract ");
313 write_string ("class ");
314 write_identifier (cl.name);
316 var type_params = cl.get_type_parameters ();
317 if (type_params.size > 0) {
318 write_string ("<");
319 bool first = true;
320 foreach (TypeParameter type_param in type_params) {
321 if (first) {
322 first = false;
323 } else {
324 write_string (",");
326 write_identifier (type_param.name);
328 write_string (">");
331 var base_types = cl.get_base_types ();
332 if (base_types.size > 0) {
333 write_string (" : ");
335 bool first = true;
336 foreach (DataType base_type in base_types) {
337 if (!first) {
338 write_string (", ");
339 } else {
340 first = false;
342 write_type (base_type);
345 write_begin_block ();
347 current_scope = cl.scope;
349 visit_sorted (cl.get_classes ());
350 visit_sorted (cl.get_structs ());
351 visit_sorted (cl.get_enums ());
352 visit_sorted (cl.get_delegates ());
353 visit_sorted (cl.get_fields ());
354 visit_sorted (cl.get_constants ());
355 visit_sorted (cl.get_methods ());
356 visit_sorted (cl.get_properties ());
357 visit_sorted (cl.get_signals ());
359 if (cl.constructor != null) {
360 cl.constructor.accept (this);
363 current_scope = current_scope.parent_scope;
365 write_end_block ();
366 write_newline ();
369 void visit_sorted (List<Symbol> symbols) {
370 if (type != CodeWriterType.EXTERNAL) {
371 // order of virtual methods matters for fast vapis
372 foreach (Symbol sym in symbols) {
373 sym.accept (this);
375 return;
378 var sorted_symbols = new ArrayList<Symbol> ();
379 foreach (Symbol sym in symbols) {
380 int left = 0;
381 int right = sorted_symbols.size - 1;
382 if (left > right || sym.name < sorted_symbols[left].name) {
383 sorted_symbols.insert (0, sym);
384 } else if (sym.name > sorted_symbols[right].name) {
385 sorted_symbols.add (sym);
386 } else {
387 while (right - left > 1) {
388 int i = (right + left) / 2;
389 if (sym.name > sorted_symbols[i].name) {
390 left = i;
391 } else {
392 right = i;
395 sorted_symbols.insert (left + 1, sym);
398 foreach (Symbol sym in sorted_symbols) {
399 sym.accept (this);
403 public override void visit_struct (Struct st) {
404 if (st.external_package) {
405 return;
408 if (!check_accessibility (st)) {
409 return;
412 if (st.is_immutable) {
413 write_indent ();
414 write_string ("[Immutable]");
415 write_newline ();
418 emit_deprecated_attribute (st);
419 emit_experimental_attribute (st);
421 write_indent ();
423 write_string ("[CCode (");
425 if (st.get_cname () != st.get_default_cname ()) {
426 write_string ("cname = \"%s\", ".printf (st.get_cname ()));
429 if (!st.has_type_id) {
430 write_string ("has_type_id = false, ");
431 } else if (!st.is_simple_type () && st.get_type_id () != "G_TYPE_POINTER") {
432 write_string ("type_id = \"%s\", ".printf (st.get_type_id ()));
435 if (!st.has_copy_function) {
436 write_string ("has_copy_function = false, ");
439 if (!st.has_destroy_function) {
440 write_string ("has_destroy_function = false, ");
443 write_string ("cheader_filename = \"%s\")]".printf (get_cheaders(st)));
444 write_newline ();
446 if (st.is_simple_type ()) {
447 write_indent ();
448 write_string ("[SimpleType]");
449 write_newline ();
452 if (st.is_integer_type ()) {
453 write_indent ();
454 write_string ("[IntegerType (rank = %d)]".printf (st.get_rank ()));
455 write_newline ();
458 if (st.is_floating_type ()) {
459 write_indent ();
460 write_string ("[FloatingType (rank = %d)]".printf (st.get_rank ()));
461 write_newline ();
464 write_attributes (st);
466 write_indent ();
467 write_accessibility (st);
468 write_string ("struct ");
469 write_identifier (st.name);
471 if (st.base_type != null) {
472 write_string (" : ");
473 write_type (st.base_type);
476 write_begin_block ();
478 current_scope = st.scope;
480 foreach (Field field in st.get_fields ()) {
481 field.accept (this);
483 visit_sorted (st.get_constants ());
484 visit_sorted (st.get_methods ());
485 visit_sorted (st.get_properties ());
487 current_scope = current_scope.parent_scope;
489 write_end_block ();
490 write_newline ();
493 public override void visit_interface (Interface iface) {
494 if (iface.external_package) {
495 return;
498 if (!check_accessibility (iface)) {
499 return;
502 emit_deprecated_attribute (iface);
503 emit_experimental_attribute (iface);
505 write_indent ();
507 write_string ("[CCode (cheader_filename = \"%s\"".printf (get_cheaders(iface)));
508 if (iface.get_lower_case_csuffix () != iface.get_default_lower_case_csuffix ())
509 write_string (", lower_case_csuffix = \"%s\"".printf (iface.get_lower_case_csuffix ()));
510 if (iface.get_type_cname () != iface.get_default_type_cname ())
511 write_string (", type_cname = \"%s\"".printf (iface.get_type_cname ()));
513 write_string (")]");
514 write_newline ();
516 write_attributes (iface);
518 write_indent ();
519 write_accessibility (iface);
520 write_string ("interface ");
521 write_identifier (iface.name);
523 var type_params = iface.get_type_parameters ();
524 if (type_params.size > 0) {
525 write_string ("<");
526 bool first = true;
527 foreach (TypeParameter type_param in type_params) {
528 if (first) {
529 first = false;
530 } else {
531 write_string (",");
533 write_identifier (type_param.name);
535 write_string (">");
538 var prerequisites = iface.get_prerequisites ();
539 if (prerequisites.size > 0) {
540 write_string (" : ");
542 bool first = true;
543 foreach (DataType prerequisite in prerequisites) {
544 if (!first) {
545 write_string (", ");
546 } else {
547 first = false;
549 write_type (prerequisite);
552 write_begin_block ();
554 current_scope = iface.scope;
556 visit_sorted (iface.get_classes ());
557 visit_sorted (iface.get_structs ());
558 visit_sorted (iface.get_enums ());
559 visit_sorted (iface.get_delegates ());
560 visit_sorted (iface.get_fields ());
561 visit_sorted (iface.get_constants ());
562 visit_sorted (iface.get_methods ());
563 visit_sorted (iface.get_properties ());
564 visit_sorted (iface.get_signals ());
566 current_scope = current_scope.parent_scope;
568 write_end_block ();
569 write_newline ();
572 public override void visit_enum (Enum en) {
573 if (en.external_package) {
574 return;
577 if (!check_accessibility (en)) {
578 return;
581 emit_deprecated_attribute (en);
582 emit_experimental_attribute (en);
584 write_indent ();
586 write_string ("[CCode (cprefix = \"%s\", ".printf (en.get_cprefix ()));
588 if (!en.has_type_id) {
589 write_string ("has_type_id = false, ");
592 write_string ("cheader_filename = \"%s\")]".printf (get_cheaders(en)));
594 if (en.is_flags) {
595 write_indent ();
596 write_string ("[Flags]");
599 write_attributes (en);
601 write_indent ();
602 write_accessibility (en);
603 write_string ("enum ");
604 write_identifier (en.name);
605 write_begin_block ();
607 bool first = true;
608 foreach (EnumValue ev in en.get_values ()) {
609 if (first) {
610 first = false;
611 } else {
612 write_string (",");
613 write_newline ();
616 if (ev.get_cname () != ev.get_default_cname ()) {
617 write_indent ();
618 write_string ("[CCode (cname = \"%s\")]".printf (ev.get_cname ()));
620 write_indent ();
621 write_identifier (ev.name);
623 if (type == CodeWriterType.FAST && ev.value != null) {
624 write_string(" = ");
625 ev.value.accept (this);
629 if (!first) {
630 if (en.get_methods ().size > 0 || en.get_constants ().size > 0) {
631 write_string (";");
633 write_newline ();
636 current_scope = en.scope;
637 foreach (Method m in en.get_methods ()) {
638 m.accept (this);
640 foreach (Constant c in en.get_constants ()) {
641 c.accept (this);
643 current_scope = current_scope.parent_scope;
645 write_end_block ();
646 write_newline ();
649 public override void visit_error_domain (ErrorDomain edomain) {
650 if (edomain.external_package) {
651 return;
654 if (!check_accessibility (edomain)) {
655 return;
658 emit_deprecated_attribute (edomain);
659 emit_experimental_attribute (edomain);
661 write_indent ();
663 write_string ("[CCode (cprefix = \"%s\", cheader_filename = \"%s\")]".printf (edomain.get_cprefix (), get_cheaders(edomain)));
665 write_attributes (edomain);
667 write_indent ();
668 write_accessibility (edomain);
669 write_string ("errordomain ");
670 write_identifier (edomain.name);
671 write_begin_block ();
673 edomain.accept_children (this);
675 write_end_block ();
676 write_newline ();
679 public override void visit_error_code (ErrorCode ecode) {
680 write_indent ();
681 write_identifier (ecode.name);
682 write_string (",");
683 write_newline ();
686 public override void visit_constant (Constant c) {
687 if (c.external_package) {
688 return;
691 if (!check_accessibility (c)) {
692 return;
695 emit_deprecated_attribute (c);
696 emit_experimental_attribute (c);
698 bool custom_cname = (c.get_cname () != c.get_default_cname ());
699 bool custom_cheaders = (c.parent_symbol is Namespace);
700 if (custom_cname || custom_cheaders) {
701 write_indent ();
702 write_string ("[CCode (");
704 if (custom_cname) {
705 write_string ("cname = \"%s\"".printf (c.get_cname ()));
708 if (custom_cheaders) {
709 if (custom_cname) {
710 write_string (", ");
713 write_string ("cheader_filename = \"%s\"".printf (get_cheaders(c)));
716 write_string (")]");
719 write_indent ();
720 write_accessibility (c);
721 write_string ("const ");
723 write_type (c.type_reference);
725 write_string (" ");
726 write_identifier (c.name);
727 if (type == CodeWriterType.FAST && c.value != null) {
728 write_string(" = ");
729 c.value.accept (this);
731 write_string (";");
732 write_newline ();
735 public override void visit_field (Field f) {
736 if (f.external_package) {
737 return;
740 if (!check_accessibility (f)) {
741 return;
744 emit_deprecated_attribute (f);
745 emit_experimental_attribute (f);
747 bool custom_cname = (f.get_cname () != f.get_default_cname ());
748 bool custom_ctype = (f.get_ctype () != null);
749 bool custom_cheaders = (f.parent_symbol is Namespace);
750 bool custom_array_length_cname = (f.get_array_length_cname () != null);
751 bool custom_array_length_type = (f.array_length_type != null);
752 if (custom_cname || custom_ctype || custom_cheaders || custom_array_length_cname || custom_array_length_type || (f.no_array_length && f.variable_type is ArrayType)) {
753 write_indent ();
754 write_string ("[CCode (");
756 if (custom_cname) {
757 write_string ("cname = \"%s\"".printf (f.get_cname ()));
760 if (custom_ctype) {
761 if (custom_cname) {
762 write_string (", ");
765 write_string ("type = \"%s\"".printf (f.get_ctype ()));
768 if (custom_cheaders) {
769 if (custom_cname || custom_ctype) {
770 write_string (", ");
773 write_string ("cheader_filename = \"%s\"".printf (get_cheaders(f)));
776 if (f.variable_type is ArrayType) {
777 if (f.no_array_length) {
778 if (custom_cname || custom_ctype || custom_cheaders) {
779 write_string (", ");
782 write_string ("array_length = false");
784 if (f.array_null_terminated) {
785 write_string (", array_null_terminated = true");
787 } else {
788 if (custom_array_length_cname) {
789 if (custom_cname || custom_ctype || custom_cheaders) {
790 write_string (", ");
793 write_string ("array_length_cname = \"%s\"".printf (f.get_array_length_cname ()));
796 if (custom_array_length_type) {
797 if (custom_cname || custom_ctype || custom_cheaders || custom_array_length_cname) {
798 write_string (", ");
801 write_string ("array_length_type = \"%s\"".printf (f.array_length_type));
806 write_string (")]");
809 write_indent ();
810 write_accessibility (f);
812 if (f.binding == MemberBinding.STATIC) {
813 write_string ("static ");
814 } else if (f.binding == MemberBinding.CLASS) {
815 write_string ("class ");
818 if (f.variable_type.is_weak ()) {
819 write_string ("weak ");
822 write_type (f.variable_type);
824 write_string (" ");
825 write_identifier (f.name);
826 write_string (";");
827 write_newline ();
830 private void write_error_domains (List<DataType> error_domains) {
831 if (error_domains.size > 0) {
832 write_string (" throws ");
834 bool first = true;
835 foreach (DataType type in error_domains) {
836 if (!first) {
837 write_string (", ");
838 } else {
839 first = false;
842 write_type (type);
847 // equality comparison with 3 digit precision
848 private bool float_equal (double d1, double d2) {
849 return ((int) (d1 * 1000)) == ((int) (d2 * 1000));
852 private void write_params (List<Parameter> params) {
853 write_string ("(");
855 int i = 1;
856 foreach (Parameter param in params) {
857 if (i > 1) {
858 write_string (", ");
861 if (param.ellipsis) {
862 write_string ("...");
863 continue;
867 var ccode_params = new StringBuilder ();
868 var separator = "";
870 if (!float_equal (param.cparameter_position, i)) {
871 ccode_params.append_printf ("%spos = %g", separator, param.cparameter_position);
872 separator = ", ";
874 if (param.ctype != null) {
875 ccode_params.append_printf ("%stype = \"%s\"", separator, param.ctype);
876 separator = ", ";
878 if (param.no_array_length && param.variable_type is ArrayType) {
879 ccode_params.append_printf ("%sarray_length = false", separator);
880 separator = ", ";
882 if (param.array_null_terminated && param.variable_type is ArrayType) {
883 ccode_params.append_printf ("%sarray_null_terminated = true", separator);
884 separator = ", ";
886 if (param.array_length_type != null && param.variable_type is ArrayType) {
887 ccode_params.append_printf ("%sarray_length_type = \"%s\"", separator, param.array_length_type);
888 separator = ", ";
890 if (param.get_array_length_cname () != null && param.variable_type is ArrayType) {
891 ccode_params.append_printf ("%sarray_length_cname = \"%s\"", separator, param.get_array_length_cname ());
892 separator = ", ";
894 if (!float_equal (param.carray_length_parameter_position, i + 0.1)) {
895 ccode_params.append_printf ("%sarray_length_pos = %g", separator, param.carray_length_parameter_position);
896 separator = ", ";
898 if (!float_equal (param.cdelegate_target_parameter_position, i + 0.1)) {
899 ccode_params.append_printf ("%sdelegate_target_pos = %g", separator, param.cdelegate_target_parameter_position);
900 separator = ", ";
903 if (ccode_params.len > 0) {
904 write_string ("[CCode (%s)] ".printf (ccode_params.str));
907 if (param.params_array) {
908 write_string ("params ");
911 if (param.direction == ParameterDirection.IN) {
912 if (param.variable_type.value_owned) {
913 write_string ("owned ");
915 } else {
916 if (param.direction == ParameterDirection.REF) {
917 write_string ("ref ");
918 } else if (param.direction == ParameterDirection.OUT) {
919 write_string ("out ");
921 if (param.variable_type.is_weak ()) {
922 write_string ("unowned ");
926 write_type (param.variable_type);
928 write_string (" ");
929 write_identifier (param.name);
931 if (param.initializer != null) {
932 write_string (" = ");
933 param.initializer.accept (this);
936 i++;
939 write_string (")");
942 public override void visit_delegate (Delegate cb) {
943 if (cb.external_package) {
944 return;
947 if (!check_accessibility (cb)) {
948 return;
951 emit_deprecated_attribute (cb);
952 emit_experimental_attribute (cb);
954 write_indent ();
956 write_string ("[CCode (cheader_filename = \"%s\"".printf (get_cheaders(cb)));
958 if (!cb.has_target) {
959 write_string (", has_target = false");
960 } else if (!float_equal (cb.cinstance_parameter_position, -2)) {
961 write_string (", instance_pos = %g".printf (cb.cinstance_parameter_position));
964 write_string (")]");
966 write_indent ();
968 write_accessibility (cb);
969 write_string ("delegate ");
971 write_return_type (cb.return_type);
973 write_string (" ");
974 write_identifier (cb.name);
976 var type_params = cb.get_type_parameters ();
977 if (type_params.size > 0) {
978 write_string ("<");
979 bool first = true;
980 foreach (TypeParameter type_param in type_params) {
981 if (first) {
982 first = false;
983 } else {
984 write_string (",");
986 write_identifier (type_param.name);
988 write_string (">");
991 write_string (" ");
993 write_params (cb.get_parameters ());
995 write_error_domains (cb.get_error_types ());
997 write_string (";");
999 write_newline ();
1002 public override void visit_constructor (Constructor c) {
1003 if (type != CodeWriterType.DUMP) {
1004 return;
1007 write_indent ();
1008 write_string ("construct");
1009 write_code_block (c.body);
1010 write_newline ();
1013 public override void visit_method (Method m) {
1014 if (m.external_package) {
1015 return;
1018 // don't write interface implementation unless it's an abstract or virtual method
1019 if (!check_accessibility (m) || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
1020 if (type != CodeWriterType.DUMP) {
1021 return;
1025 if (m.get_attribute ("NoWrapper") != null) {
1026 write_indent ();
1027 write_string ("[NoWrapper]");
1029 if (m.get_attribute ("NoThrow") != null) {
1030 write_indent ();
1031 write_string ("[NoThrow]");
1033 if (m.returns_modified_pointer) {
1034 write_indent ();
1035 write_string ("[ReturnsModifiedPointer]");
1037 if (m.printf_format) {
1038 write_indent ();
1039 write_string ("[PrintfFormat]");
1041 if (m.scanf_format) {
1042 write_indent ();
1043 write_string ("[ScanfFormat]");
1045 if (m.get_attribute ("Print") != null) {
1046 write_indent ();
1047 write_string ("[Print]");
1049 if (m.get_attribute ("NoReturn") != null) {
1050 write_indent ();
1051 write_string ("[NoReturn]");
1053 if (m.get_attribute ("Diagnostics") != null) {
1054 write_indent ();
1055 write_string ("[Diagnostics]");
1058 emit_deprecated_attribute (m);
1059 emit_experimental_attribute (m);
1061 var ccode_params = new StringBuilder ();
1062 var separator = "";
1064 if (m.get_cname () != m.get_default_cname ()) {
1065 ccode_params.append_printf ("%scname = \"%s\"", separator, m.get_cname ());
1066 separator = ", ";
1068 if (m.parent_symbol is Namespace) {
1069 ccode_params.append_printf ("%scheader_filename = \"%s\"", separator, get_cheaders(m));
1070 separator = ", ";
1072 if (!float_equal (m.cinstance_parameter_position, 0)) {
1073 ccode_params.append_printf ("%sinstance_pos = %g", separator, m.cinstance_parameter_position);
1074 separator = ", ";
1076 if (m.no_array_length && m.return_type is ArrayType) {
1077 ccode_params.append_printf ("%sarray_length = false", separator);
1078 separator = ", ";
1080 if (!float_equal (m.carray_length_parameter_position, -3)) {
1081 ccode_params.append_printf ("%sarray_length_pos = %g", separator, m.carray_length_parameter_position);
1082 separator = ", ";
1084 if (m.array_null_terminated && m.return_type is ArrayType) {
1085 ccode_params.append_printf ("%sarray_null_terminated = true", separator);
1086 separator = ", ";
1088 if (m.array_length_type != null && m.return_type is ArrayType) {
1089 ccode_params.append_printf ("%sarray_length_type = \"%s\"", separator, m.array_length_type);
1090 separator = ", ";
1092 if (!float_equal (m.cdelegate_target_parameter_position, -3)) {
1093 ccode_params.append_printf ("%sdelegate_target_pos = %g", separator, m.cdelegate_target_parameter_position);
1094 separator = ", ";
1096 if (m.vfunc_name != m.name) {
1097 ccode_params.append_printf ("%svfunc_name = \"%s\"", separator, m.vfunc_name);
1098 separator = ", ";
1100 if (m.coroutine && m.get_finish_cname () != m.get_default_finish_cname ()) {
1101 ccode_params.append_printf ("%sfinish_name = \"%s\"", separator, m.get_finish_cname ());
1102 separator = ", ";
1104 if (m.sentinel != m.DEFAULT_SENTINEL) {
1105 ccode_params.append_printf ("%ssentinel = \"%s\"", separator, m.sentinel);
1106 separator = ", ";
1108 var cm = m as CreationMethod;
1109 if (cm != null) {
1110 if (cm.custom_return_type_cname != null) {
1111 ccode_params.append_printf ("%stype = \"%s\"", separator, cm.custom_return_type_cname);
1112 separator = ", ";
1114 if (!m.has_new_function) {
1115 ccode_params.append_printf ("%shas_new_function = false", separator);
1116 separator = ", ";
1118 if (!m.has_construct_function) {
1119 ccode_params.append_printf ("%shas_construct_function = false", separator);
1120 separator = ", ";
1121 } else if (m.name == ".new" && m.get_real_cname () != cm.get_default_construct_function ()) {
1122 ccode_params.append_printf ("%sconstruct_function = \"%s\"", separator, m.get_real_cname ());
1123 separator = ", ";
1127 if (ccode_params.len > 0) {
1128 write_indent ();
1129 write_string ("[CCode (%s)]".printf (ccode_params.str));
1132 write_indent ();
1133 write_accessibility (m);
1135 if (m is CreationMethod) {
1136 if (m.coroutine) {
1137 write_string ("async ");
1140 var datatype = (TypeSymbol) m.parent_symbol;
1141 write_identifier (datatype.name);
1142 if (m.name != ".new") {
1143 write_string (".");
1144 write_identifier (m.name);
1146 write_string (" ");
1147 } else {
1148 if (m.binding == MemberBinding.STATIC) {
1149 write_string ("static ");
1150 } else if (m.binding == MemberBinding.CLASS) {
1151 write_string ("class ");
1152 } else if (m.is_abstract) {
1153 write_string ("abstract ");
1154 } else if (m.is_virtual) {
1155 write_string ("virtual ");
1156 } else if (m.overrides) {
1157 write_string ("override ");
1160 if (m.hides) {
1161 write_string ("new ");
1164 if (m.coroutine) {
1165 write_string ("async ");
1168 write_return_type (m.return_type);
1169 write_string (" ");
1171 write_identifier (m.name);
1173 var type_params = m.get_type_parameters ();
1174 if (type_params.size > 0) {
1175 write_string ("<");
1176 bool first = true;
1177 foreach (TypeParameter type_param in type_params) {
1178 if (first) {
1179 first = false;
1180 } else {
1181 write_string (",");
1183 write_identifier (type_param.name);
1185 write_string (">");
1188 write_string (" ");
1191 write_params (m.get_parameters ());
1193 if (context.profile != Profile.DOVA) {
1194 write_error_domains (m.get_error_types ());
1197 write_code_block (m.body);
1199 write_newline ();
1202 public override void visit_creation_method (CreationMethod m) {
1203 visit_method (m);
1206 public override void visit_property (Property prop) {
1207 if (!check_accessibility (prop) || (prop.base_interface_property != null && !prop.is_abstract && !prop.is_virtual)) {
1208 return;
1211 emit_deprecated_attribute (prop);
1212 emit_experimental_attribute (prop);
1214 if (prop.no_accessor_method) {
1215 write_indent ();
1216 write_string ("[NoAccessorMethod]");
1218 if (prop.property_type is ArrayType && prop.no_array_length) {
1219 write_indent ();
1220 write_string ("[CCode (array_length = false");
1222 if (prop.array_null_terminated) {
1223 write_string (", array_null_terminated = true");
1226 write_string (")]");
1229 write_indent ();
1230 write_accessibility (prop);
1232 if (prop.binding == MemberBinding.STATIC) {
1233 write_string ("static ");
1234 } else if (prop.is_abstract) {
1235 write_string ("abstract ");
1236 } else if (prop.is_virtual) {
1237 write_string ("virtual ");
1238 } else if (prop.overrides) {
1239 write_string ("override ");
1242 write_type (prop.property_type);
1244 write_string (" ");
1245 write_identifier (prop.name);
1246 write_string (" {");
1247 if (prop.get_accessor != null) {
1248 var ccode_params = new StringBuilder ();
1249 var separator = "";
1251 if (prop.get_accessor.get_cname () != prop.get_accessor.get_default_cname ()) {
1252 ccode_params.append_printf ("%scname = \"%s\"", separator, prop.get_accessor.get_cname ());
1253 separator = ", ";
1255 if (ccode_params.len > 0) {
1256 write_indent ();
1257 write_string ("[CCode (%s)]".printf (ccode_params.str));
1260 write_property_accessor_accessibility (prop.get_accessor);
1262 if (context.profile != Profile.DOVA && prop.get_accessor.value_type.is_disposable ()) {
1263 write_string (" owned");
1266 write_string (" get");
1267 write_code_block (prop.get_accessor.body);
1269 if (prop.set_accessor != null) {
1270 var ccode_params = new StringBuilder ();
1271 var separator = "";
1273 if (prop.set_accessor.get_cname () != prop.set_accessor.get_default_cname ()) {
1274 ccode_params.append_printf ("%scname = \"%s\"", separator, prop.set_accessor.get_cname ());
1275 separator = ", ";
1277 if (ccode_params.len > 0) {
1278 write_indent ();
1279 write_string ("[CCode (%s)]".printf (ccode_params.str));
1282 write_property_accessor_accessibility (prop.set_accessor);
1284 if (context.profile != Profile.DOVA && prop.set_accessor.value_type.value_owned) {
1285 write_string (" owned");
1288 if (prop.set_accessor.writable) {
1289 write_string (" set");
1291 if (prop.set_accessor.construction) {
1292 write_string (" construct");
1294 write_code_block (prop.set_accessor.body);
1296 write_string (" }");
1297 write_newline ();
1300 public override void visit_signal (Signal sig) {
1301 if (!check_accessibility (sig)) {
1302 return;
1305 if (sig.has_emitter) {
1306 write_indent ();
1307 write_string ("[HasEmitter]");
1310 emit_deprecated_attribute (sig);
1311 emit_experimental_attribute (sig);
1313 write_indent ();
1314 write_accessibility (sig);
1316 if (sig.is_virtual) {
1317 write_string ("virtual ");
1320 write_string ("signal ");
1322 write_return_type (sig.return_type);
1324 write_string (" ");
1325 write_identifier (sig.name);
1327 write_string (" ");
1329 write_params (sig.get_parameters ());
1331 write_string (";");
1333 write_newline ();
1336 public override void visit_block (Block b) {
1337 write_begin_block ();
1339 foreach (Statement stmt in b.get_statements ()) {
1340 stmt.accept (this);
1343 write_end_block ();
1346 public override void visit_empty_statement (EmptyStatement stmt) {
1349 public override void visit_declaration_statement (DeclarationStatement stmt) {
1350 write_indent ();
1351 stmt.declaration.accept (this);
1352 write_string (";");
1353 write_newline ();
1356 public override void visit_local_variable (LocalVariable local) {
1357 write_type (local.variable_type);
1358 write_string (" ");
1359 write_identifier (local.name);
1360 if (local.initializer != null) {
1361 write_string (" = ");
1362 local.initializer.accept (this);
1366 public override void visit_initializer_list (InitializerList list) {
1367 write_string ("{");
1369 bool first = true;
1370 foreach (Expression initializer in list.get_initializers ()) {
1371 if (!first) {
1372 write_string (", ");
1373 } else {
1374 write_string (" ");
1376 first = false;
1377 initializer.accept (this);
1379 write_string (" }");
1382 public override void visit_expression_statement (ExpressionStatement stmt) {
1383 write_indent ();
1384 stmt.expression.accept (this);
1385 write_string (";");
1386 write_newline ();
1389 public override void visit_if_statement (IfStatement stmt) {
1390 write_indent ();
1391 write_string ("if (");
1392 stmt.condition.accept (this);
1393 write_string (")");
1394 stmt.true_statement.accept (this);
1395 if (stmt.false_statement != null) {
1396 write_string (" else");
1397 stmt.false_statement.accept (this);
1399 write_newline ();
1402 public override void visit_switch_statement (SwitchStatement stmt) {
1403 write_indent ();
1404 write_string ("switch (");
1405 stmt.expression.accept (this);
1406 write_string (") {");
1407 write_newline ();
1409 foreach (SwitchSection section in stmt.get_sections ()) {
1410 section.accept (this);
1413 write_indent ();
1414 write_string ("}");
1415 write_newline ();
1418 public override void visit_switch_section (SwitchSection section) {
1419 foreach (SwitchLabel label in section.get_labels ()) {
1420 label.accept (this);
1423 visit_block (section);
1426 public override void visit_switch_label (SwitchLabel label) {
1427 if (label.expression != null) {
1428 write_indent ();
1429 write_string ("case ");
1430 label.expression.accept (this);
1431 write_string (":");
1432 write_newline ();
1433 } else {
1434 write_indent ();
1435 write_string ("default:");
1436 write_newline ();
1440 public override void visit_loop (Loop stmt) {
1441 write_indent ();
1442 write_string ("loop");
1443 stmt.body.accept (this);
1444 write_newline ();
1447 public override void visit_while_statement (WhileStatement stmt) {
1448 write_indent ();
1449 write_string ("while (");
1450 stmt.condition.accept (this);
1451 write_string (")");
1452 stmt.body.accept (this);
1453 write_newline ();
1456 public override void visit_do_statement (DoStatement stmt) {
1457 write_indent ();
1458 write_string ("do");
1459 stmt.body.accept (this);
1460 write_string ("while (");
1461 stmt.condition.accept (this);
1462 write_string (");");
1463 write_newline ();
1466 public override void visit_for_statement (ForStatement stmt) {
1467 write_indent ();
1468 write_string ("for (");
1470 bool first = true;
1471 foreach (Expression initializer in stmt.get_initializer ()) {
1472 if (!first) {
1473 write_string (", ");
1475 first = false;
1476 initializer.accept (this);
1478 write_string ("; ");
1480 stmt.condition.accept (this);
1481 write_string ("; ");
1483 first = true;
1484 foreach (Expression iterator in stmt.get_iterator ()) {
1485 if (!first) {
1486 write_string (", ");
1488 first = false;
1489 iterator.accept (this);
1492 write_string (")");
1493 stmt.body.accept (this);
1494 write_newline ();
1497 public override void visit_foreach_statement (ForeachStatement stmt) {
1500 public override void visit_break_statement (BreakStatement stmt) {
1501 write_indent ();
1502 write_string ("break;");
1503 write_newline ();
1506 public override void visit_continue_statement (ContinueStatement stmt) {
1507 write_indent ();
1508 write_string ("continue;");
1509 write_newline ();
1512 public override void visit_return_statement (ReturnStatement stmt) {
1513 write_indent ();
1514 write_string ("return");
1515 if (stmt.return_expression != null) {
1516 write_string (" ");
1517 stmt.return_expression.accept (this);
1519 write_string (";");
1520 write_newline ();
1523 public override void visit_yield_statement (YieldStatement y) {
1524 write_indent ();
1525 write_string ("yield");
1526 if (y.yield_expression != null) {
1527 write_string (" ");
1528 y.yield_expression.accept (this);
1530 write_string (";");
1531 write_newline ();
1534 public override void visit_throw_statement (ThrowStatement stmt) {
1535 write_indent ();
1536 write_string ("throw");
1537 if (stmt.error_expression != null) {
1538 write_string (" ");
1539 stmt.error_expression.accept (this);
1541 write_string (";");
1542 write_newline ();
1545 public override void visit_try_statement (TryStatement stmt) {
1546 write_indent ();
1547 write_string ("try");
1548 stmt.body.accept (this);
1549 foreach (var clause in stmt.get_catch_clauses ()) {
1550 clause.accept (this);
1552 if (stmt.finally_body != null) {
1553 write_string (" finally");
1554 stmt.finally_body.accept (this);
1556 write_newline ();
1559 public override void visit_catch_clause (CatchClause clause) {
1560 var type_name = clause.error_type == null ? "GLib.Error" : clause.error_type.to_string ();
1561 var var_name = clause.variable_name == null ? "_" : clause.variable_name;
1562 write_string (" catch (%s %s)".printf (type_name, var_name));
1563 clause.body.accept (this);
1566 public override void visit_lock_statement (LockStatement stmt) {
1567 write_indent ();
1568 write_string ("lock (");
1569 stmt.resource.accept (this);
1570 write_string (")");
1571 if (stmt.body == null) {
1572 write_string (";");
1573 } else {
1574 stmt.body.accept (this);
1576 write_newline ();
1579 public override void visit_delete_statement (DeleteStatement stmt) {
1580 write_indent ();
1581 write_string ("delete ");
1582 stmt.expression.accept (this);
1583 write_string (";");
1584 write_newline ();
1587 public override void visit_array_creation_expression (ArrayCreationExpression expr) {
1588 write_string ("new ");
1589 write_type (expr.element_type);
1590 write_string ("[");
1592 bool first = true;
1593 foreach (Expression size in expr.get_sizes ()) {
1594 if (!first) {
1595 write_string (", ");
1597 first = false;
1599 size.accept (this);
1602 write_string ("]");
1604 if (expr.initializer_list != null) {
1605 write_string (" ");
1606 expr.initializer_list.accept (this);
1610 public override void visit_boolean_literal (BooleanLiteral lit) {
1611 write_string (lit.value.to_string ());
1614 public override void visit_character_literal (CharacterLiteral lit) {
1615 write_string (lit.value);
1618 public override void visit_integer_literal (IntegerLiteral lit) {
1619 write_string (lit.value);
1622 public override void visit_real_literal (RealLiteral lit) {
1623 write_string (lit.value);
1626 public override void visit_string_literal (StringLiteral lit) {
1627 write_string (lit.value);
1630 public override void visit_null_literal (NullLiteral lit) {
1631 write_string ("null");
1634 public override void visit_member_access (MemberAccess expr) {
1635 if (expr.inner != null) {
1636 expr.inner.accept (this);
1637 write_string (".");
1639 write_identifier (expr.member_name);
1642 public override void visit_method_call (MethodCall expr) {
1643 expr.call.accept (this);
1644 write_string (" (");
1646 bool first = true;
1647 foreach (Expression arg in expr.get_argument_list ()) {
1648 if (!first) {
1649 write_string (", ");
1651 first = false;
1653 arg.accept (this);
1656 write_string (")");
1659 public override void visit_element_access (ElementAccess expr) {
1660 expr.container.accept (this);
1661 write_string ("[");
1663 bool first = true;
1664 foreach (Expression index in expr.get_indices ()) {
1665 if (!first) {
1666 write_string (", ");
1668 first = false;
1670 index.accept (this);
1673 write_string ("]");
1676 public override void visit_slice_expression (SliceExpression expr) {
1677 expr.container.accept (this);
1678 write_string ("[");
1679 expr.start.accept (this);
1680 write_string (":");
1681 expr.stop.accept (this);
1682 write_string ("]");
1685 public override void visit_base_access (BaseAccess expr) {
1686 write_string ("base");
1689 public override void visit_postfix_expression (PostfixExpression expr) {
1690 expr.inner.accept (this);
1691 if (expr.increment) {
1692 write_string ("++");
1693 } else {
1694 write_string ("--");
1698 public override void visit_object_creation_expression (ObjectCreationExpression expr) {
1699 if (!expr.struct_creation) {
1700 write_string ("new ");
1703 write_type (expr.type_reference);
1705 if (expr.symbol_reference.name != ".new") {
1706 write_string (".");
1707 write_string (expr.symbol_reference.name);
1710 write_string (" (");
1712 bool first = true;
1713 foreach (Expression arg in expr.get_argument_list ()) {
1714 if (!first) {
1715 write_string (", ");
1717 first = false;
1719 arg.accept (this);
1722 write_string (")");
1725 public override void visit_sizeof_expression (SizeofExpression expr) {
1726 write_string ("sizeof (");
1727 write_type (expr.type_reference);
1728 write_string (")");
1731 public override void visit_typeof_expression (TypeofExpression expr) {
1732 write_string ("typeof (");
1733 write_type (expr.type_reference);
1734 write_string (")");
1737 public override void visit_unary_expression (UnaryExpression expr) {
1738 switch (expr.operator) {
1739 case UnaryOperator.PLUS:
1740 write_string ("+");
1741 break;
1742 case UnaryOperator.MINUS:
1743 write_string ("-");
1744 break;
1745 case UnaryOperator.LOGICAL_NEGATION:
1746 write_string ("!");
1747 break;
1748 case UnaryOperator.BITWISE_COMPLEMENT:
1749 write_string ("~");
1750 break;
1751 case UnaryOperator.INCREMENT:
1752 write_string ("++");
1753 break;
1754 case UnaryOperator.DECREMENT:
1755 write_string ("--");
1756 break;
1757 case UnaryOperator.REF:
1758 write_string ("ref ");
1759 break;
1760 case UnaryOperator.OUT:
1761 write_string ("out ");
1762 break;
1763 default:
1764 assert_not_reached ();
1766 expr.inner.accept (this);
1769 public override void visit_cast_expression (CastExpression expr) {
1770 if (expr.is_non_null_cast) {
1771 write_string ("(!) ");
1772 expr.inner.accept (this);
1773 return;
1776 if (!expr.is_silent_cast) {
1777 write_string ("(");
1778 write_type (expr.type_reference);
1779 write_string (") ");
1782 expr.inner.accept (this);
1784 if (expr.is_silent_cast) {
1785 write_string (" as ");
1786 write_type (expr.type_reference);
1790 public override void visit_pointer_indirection (PointerIndirection expr) {
1791 write_string ("*");
1792 expr.inner.accept (this);
1795 public override void visit_addressof_expression (AddressofExpression expr) {
1796 write_string ("&");
1797 expr.inner.accept (this);
1800 public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
1801 write_string ("(owned) ");
1802 expr.inner.accept (this);
1805 public override void visit_binary_expression (BinaryExpression expr) {
1806 expr.left.accept (this);
1808 switch (expr.operator) {
1809 case BinaryOperator.PLUS:
1810 write_string (" + ");
1811 break;
1812 case BinaryOperator.MINUS:
1813 write_string (" - ");
1814 break;
1815 case BinaryOperator.MUL:
1816 write_string (" * ");
1817 break;
1818 case BinaryOperator.DIV:
1819 write_string (" / ");
1820 break;
1821 case BinaryOperator.MOD:
1822 write_string (" % ");
1823 break;
1824 case BinaryOperator.SHIFT_LEFT:
1825 write_string (" << ");
1826 break;
1827 case BinaryOperator.SHIFT_RIGHT:
1828 write_string (" >> ");
1829 break;
1830 case BinaryOperator.LESS_THAN:
1831 write_string (" < ");
1832 break;
1833 case BinaryOperator.GREATER_THAN:
1834 write_string (" > ");
1835 break;
1836 case BinaryOperator.LESS_THAN_OR_EQUAL:
1837 write_string (" <= ");
1838 break;
1839 case BinaryOperator.GREATER_THAN_OR_EQUAL:
1840 write_string (" >= ");
1841 break;
1842 case BinaryOperator.EQUALITY:
1843 write_string (" == ");
1844 break;
1845 case BinaryOperator.INEQUALITY:
1846 write_string (" != ");
1847 break;
1848 case BinaryOperator.BITWISE_AND:
1849 write_string (" & ");
1850 break;
1851 case BinaryOperator.BITWISE_OR:
1852 write_string (" | ");
1853 break;
1854 case BinaryOperator.BITWISE_XOR:
1855 write_string (" ^ ");
1856 break;
1857 case BinaryOperator.AND:
1858 write_string (" && ");
1859 break;
1860 case BinaryOperator.OR:
1861 write_string (" || ");
1862 break;
1863 case BinaryOperator.IN:
1864 write_string (" in ");
1865 break;
1866 case BinaryOperator.COALESCE:
1867 write_string (" ?? ");
1868 break;
1869 default:
1870 assert_not_reached ();
1873 expr.right.accept (this);
1876 public override void visit_type_check (TypeCheck expr) {
1877 expr.expression.accept (this);
1878 write_string (" is ");
1879 write_type (expr.type_reference);
1882 public override void visit_conditional_expression (ConditionalExpression expr) {
1883 expr.condition.accept (this);
1884 write_string ("?");
1885 expr.true_expression.accept (this);
1886 write_string (":");
1887 expr.false_expression.accept (this);
1890 public override void visit_lambda_expression (LambdaExpression expr) {
1891 write_string ("(");
1892 var params = expr.get_parameters ();
1893 if (params.size != 0) {
1894 for (var i = 0; i < params.size - 1; ++ i) {
1895 write_string (params[i]);
1896 write_string (", ");
1898 write_string (params[params.size - 1]);
1900 write_string (") =>");
1901 if (expr.statement_body != null) {
1902 expr.statement_body.accept (this);
1903 } else if (expr.expression_body != null) {
1904 expr.expression_body.accept (this);
1908 public override void visit_assignment (Assignment a) {
1909 a.left.accept (this);
1910 write_string (" = ");
1911 a.right.accept (this);
1914 private void write_indent () {
1915 int i;
1917 if (!bol) {
1918 stream.putc ('\n');
1921 for (i = 0; i < indent; i++) {
1922 stream.putc ('\t');
1925 bol = false;
1928 private void write_identifier (string s) {
1929 char* id = (char*)s;
1930 int id_length = (int)s.length;
1931 if (context.profile != Profile.DOVA &&
1932 (Vala.Scanner.get_identifier_or_keyword (id, id_length) != Vala.TokenType.IDENTIFIER ||
1933 s.get_char ().isdigit ())) {
1934 stream.putc ('@');
1936 write_string (s);
1939 private void write_return_type (DataType type) {
1940 if (type.is_weak ()) {
1941 write_string ("unowned ");
1944 write_type (type);
1947 private void write_type (DataType type) {
1948 write_string (type.to_qualified_string (current_scope));
1951 private void write_string (string s) {
1952 stream.printf ("%s", s);
1953 bol = false;
1956 private void write_newline () {
1957 stream.putc ('\n');
1958 bol = true;
1961 void write_code_block (Block? block) {
1962 if (block == null || type != CodeWriterType.DUMP) {
1963 write_string (";");
1964 return;
1967 block.accept (this);
1970 private void write_begin_block () {
1971 if (!bol) {
1972 stream.putc (' ');
1973 } else {
1974 write_indent ();
1976 stream.putc ('{');
1977 write_newline ();
1978 indent++;
1981 private void write_end_block () {
1982 indent--;
1983 write_indent ();
1984 stream.printf ("}");
1987 private bool check_accessibility (Symbol sym) {
1988 switch (type) {
1989 case CodeWriterType.EXTERNAL:
1990 return sym.access == SymbolAccessibility.PUBLIC ||
1991 sym.access == SymbolAccessibility.PROTECTED;
1993 case CodeWriterType.INTERNAL:
1994 case CodeWriterType.FAST:
1995 return sym.access == SymbolAccessibility.INTERNAL ||
1996 sym.access == SymbolAccessibility.PUBLIC ||
1997 sym.access == SymbolAccessibility.PROTECTED;
1999 case CodeWriterType.DUMP:
2000 return true;
2002 default:
2003 assert_not_reached ();
2007 private void write_attributes (CodeNode node) {
2008 foreach (Attribute attr in node.attributes) {
2009 if (!filter_attribute (attr)) {
2010 write_indent ();
2011 stream.printf ("[%s", attr.name);
2013 var keys = attr.args.get_keys ();
2014 if (keys.size != 0) {
2015 stream.printf (" (");
2017 string separator = "";
2018 foreach (string arg_name in keys) {
2019 stream.printf ("%s%s = %s", separator, arg_name, attr.args.get (arg_name));
2020 separator = ", ";
2023 stream.printf (")");
2025 stream.printf ("]");
2026 write_newline ();
2031 private bool filter_attribute (Attribute attr) {
2032 if (attr.name == "CCode"
2033 || attr.name == "Compact" || attr.name == "Immutable"
2034 || attr.name == "SimpleType" || attr.name == "IntegerType" || attr.name == "FloatingType"
2035 || attr.name == "Flags") {
2036 return true;
2038 return false;
2041 private void write_accessibility (Symbol sym) {
2042 if (sym.access == SymbolAccessibility.PUBLIC) {
2043 write_string ("public ");
2044 } else if (sym.access == SymbolAccessibility.PROTECTED) {
2045 write_string ("protected ");
2046 } else if (sym.access == SymbolAccessibility.INTERNAL) {
2047 write_string ("internal ");
2048 } else if (sym.access == SymbolAccessibility.PRIVATE) {
2049 write_string ("private ");
2052 if (type != CodeWriterType.EXTERNAL && sym.external && !sym.external_package) {
2053 write_string ("extern ");
2057 void write_property_accessor_accessibility (Symbol sym) {
2058 if (sym.access == SymbolAccessibility.PROTECTED) {
2059 write_string (" protected");
2060 } else if (sym.access == SymbolAccessibility.INTERNAL) {
2061 write_string (" internal");
2062 } else if (sym.access == SymbolAccessibility.PRIVATE) {
2063 write_string (" private");
2068 public enum Vala.CodeWriterType {
2069 EXTERNAL,
2070 INTERNAL,
2071 FAST,
2072 DUMP