3 * Copyright (C) 2006-2009 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
27 * Code visitor generating Vala API file for the public interface.
29 public class Vala
.CodeWriter
: CodeVisitor
{
30 private CodeContext context
;
35 /* at begin of line */
43 string? override_header
= null;
44 string? header_to_override
= null;
46 public CodeWriter (bool dump_tree
= false, bool emit_internal
= false) {
47 this
.dump_tree
= dump_tree
;
48 this
.emit_internal
= emit_internal
;
52 * Allows overriding of a specific cheader in the output
53 * @param original orignal cheader to override
54 * @param replacement cheader to replace original with
56 public void set_cheader_override (string original
, string replacement
)
58 header_to_override
= original
;
59 override_header
= replacement
;
63 * Writes the public interface of the specified code context into the
66 * @param context a code context
67 * @param filename a relative or absolute filename
69 public void write_file (CodeContext context
, string filename
) {
70 this
.context
= context
;
72 stream
= FileStream
.open (filename
, "w");
74 write_string ("/* %s generated by %s, do not modify. */".printf (Path
.get_basename (filename
), Environment
.get_prgname ()));
78 current_scope
= context
.root
.scope
;
80 context
.accept (this
);
87 public override void visit_namespace (Namespace ns
) {
88 if (ns
.external_package
) {
92 if (ns
.name
== null) {
93 ns
.accept_children (this
);
98 write_string ("[CCode (cprefix = \"%s\", lower_case_cprefix = \"%s\")]".printf (ns
.get_cprefix (), ns
.get_lower_case_cprefix ()));
101 write_attributes (ns
);
104 write_string ("namespace ");
105 write_identifier (ns
.name
);
106 write_begin_block ();
108 current_scope
= ns
.scope
;
110 visit_sorted (ns
.get_namespaces ());
111 visit_sorted (ns
.get_classes ());
112 visit_sorted (ns
.get_interfaces ());
113 visit_sorted (ns
.get_structs ());
114 visit_sorted (ns
.get_enums ());
115 visit_sorted (ns
.get_error_domains ());
116 visit_sorted (ns
.get_delegates ());
117 visit_sorted (ns
.get_fields ());
118 visit_sorted (ns
.get_constants ());
119 visit_sorted (ns
.get_methods ());
121 current_scope
= current_scope
.parent_scope
;
127 private string get_cheaders (Symbol cl
) {
129 string cheaders
= "";
130 foreach (string cheader
in cl
.get_cheader_filenames ()) {
131 if (header_to_override
!= null &&
132 cheader
== header_to_override
) {
133 cheader
= override_header
;
139 cheaders
= "%s,%s".printf (cheaders
, cheader
);
145 public override void visit_class (Class cl
) {
146 if (cl
.external_package
) {
150 if (!check_accessibility (cl
)) {
156 write_string ("[Compact]");
160 if (cl
.is_immutable
) {
162 write_string ("[Immutable]");
168 write_string ("[CCode (");
170 if (cl
.is_reference_counting ()) {
171 if (cl
.base_class
== null || cl
.base_class
.get_ref_function () == null || cl
.base_class
.get_ref_function () != cl
.get_ref_function ()) {
172 write_string ("ref_function = \"%s\", ".printf (cl
.get_ref_function ()));
173 if (cl
.ref_function_void
) {
174 write_string ("ref_function_void = true, ");
177 if (cl
.base_class
== null || cl
.base_class
.get_unref_function () == null || cl
.base_class
.get_unref_function () != cl
.get_unref_function ()) {
178 write_string ("unref_function = \"%s\", ".printf (cl
.get_unref_function ()));
181 if (cl
.get_dup_function () != null) {
182 write_string ("copy_function = \"%s\", ".printf (cl
.get_dup_function ()));
184 if (cl
.get_free_function () != cl
.get_default_free_function ()) {
185 write_string ("free_function = \"%s\", ".printf (cl
.get_free_function ()));
189 if (cl
.get_cname () != cl
.get_default_cname ()) {
190 write_string ("cname = \"%s\", ".printf (cl
.get_cname ()));
192 if (cl
.const_cname
!= null) {
193 write_string ("const_cname = \"%s\", ".printf (cl
.const_cname
));
196 if (cl
.type_check_function
!= null) {
197 write_string ("type_check_function = \"%s\", ".printf (cl
.type_check_function
));
200 if (cl
.is_compact
&& cl
.get_type_id () != "G_TYPE_POINTER") {
201 write_string ("type_id = \"%s\", ".printf (cl
.get_type_id ()));
204 if (cl
.get_param_spec_function () != cl
.get_default_param_spec_function ()) {
205 write_string ("param_spec_function = \"%s\", ".printf (cl
.get_param_spec_function ()));
208 write_string ("cheader_filename = \"%s\")]".printf (get_cheaders(cl
)));
211 write_attributes (cl
);
214 write_accessibility (cl
);
215 if (cl
.is_abstract
) {
216 write_string ("abstract ");
218 write_string ("class ");
219 write_identifier (cl
.name
);
221 var type_params
= cl
.get_type_parameters ();
222 if (type_params
.size
> 0) {
225 foreach (TypeParameter type_param
in type_params
) {
231 write_identifier (type_param
.name
);
236 var base_types
= cl
.get_base_types ();
237 if (base_types
.size
> 0) {
238 write_string (" : ");
241 foreach (DataType base_type
in base_types
) {
247 write_type (base_type
);
250 write_begin_block ();
252 current_scope
= cl
.scope
;
254 visit_sorted (cl
.get_classes ());
255 visit_sorted (cl
.get_structs ());
256 visit_sorted (cl
.get_enums ());
257 visit_sorted (cl
.get_delegates ());
258 visit_sorted (cl
.get_fields ());
259 visit_sorted (cl
.get_constants ());
260 visit_sorted (cl
.get_methods ());
261 visit_sorted (cl
.get_properties ());
262 visit_sorted (cl
.get_signals ());
264 if (cl
.constructor
!= null) {
265 cl
.constructor
.accept (this
);
268 current_scope
= current_scope
.parent_scope
;
274 void visit_sorted (List
<Symbol
> symbols
) {
275 var sorted_symbols
= new ArrayList
<Symbol
> ();
276 foreach (Symbol sym
in symbols
) {
278 int right
= sorted_symbols
.size
- 1;
279 if (left
> right
|| sym
.name
< sorted_symbols
[left
].name
) {
280 sorted_symbols
.insert (0, sym
);
281 } else if (sym
.name
> sorted_symbols
[right
].name
) {
282 sorted_symbols
.add (sym
);
284 while (right
- left
> 1) {
285 int i
= (right
+ left
) / 2;
286 if (sym
.name
> sorted_symbols
[i
].name
) {
292 sorted_symbols
.insert (left
+ 1, sym
);
295 foreach (Symbol sym
in sorted_symbols
) {
300 public override void visit_struct (Struct st
) {
301 if (st
.external_package
) {
305 if (!check_accessibility (st
)) {
309 if (st
.is_immutable
) {
311 write_string ("[Immutable]");
317 write_string ("[CCode (");
319 if (st
.get_cname () != st
.get_default_cname ()) {
320 write_string ("cname = \"%s\", ".printf (st
.get_cname ()));
323 if (!st
.is_simple_type () && st
.get_type_id () != "G_TYPE_POINTER") {
324 write_string ("type_id = \"%s\", ".printf (st
.get_type_id ()));
327 if (!st
.has_copy_function
) {
328 write_string ("has_copy_function = false, ");
331 if (!st
.has_destroy_function
) {
332 write_string ("has_destroy_function = false, ");
335 write_string ("cheader_filename = \"%s\")]".printf (get_cheaders(st
)));
338 if (st
.is_simple_type ()) {
340 write_string ("[SimpleType]");
344 if (st
.is_integer_type ()) {
346 write_string ("[IntegerType (rank = %d)]".printf (st
.get_rank ()));
350 if (st
.is_floating_type ()) {
352 write_string ("[FloatingType (rank = %d)]".printf (st
.get_rank ()));
356 write_attributes (st
);
359 write_accessibility (st
);
360 write_string ("struct ");
361 write_identifier (st
.name
);
363 if (st
.base_type
!= null) {
364 write_string (" : ");
365 write_type (st
.base_type
);
368 write_begin_block ();
370 current_scope
= st
.scope
;
372 foreach (Field field
in st
.get_fields ()) {
375 visit_sorted (st
.get_constants ());
376 visit_sorted (st
.get_methods ());
377 visit_sorted (st
.get_properties ());
379 current_scope
= current_scope
.parent_scope
;
385 public override void visit_interface (Interface iface
) {
386 if (iface
.external_package
) {
390 if (!check_accessibility (iface
)) {
396 write_string ("[CCode (cheader_filename = \"%s\"".printf (get_cheaders(iface
)));
397 if (iface
.get_lower_case_csuffix () != iface
.get_default_lower_case_csuffix ())
398 write_string (", lower_case_csuffix = \"%s\"".printf (iface
.get_lower_case_csuffix ()));
403 write_attributes (iface
);
406 write_accessibility (iface
);
407 write_string ("interface ");
408 write_identifier (iface
.name
);
410 var type_params
= iface
.get_type_parameters ();
411 if (type_params
.size
> 0) {
414 foreach (TypeParameter type_param
in type_params
) {
420 write_identifier (type_param
.name
);
425 var prerequisites
= iface
.get_prerequisites ();
426 if (prerequisites
.size
> 0) {
427 write_string (" : ");
430 foreach (DataType prerequisite
in prerequisites
) {
436 write_type (prerequisite
);
439 write_begin_block ();
441 current_scope
= iface
.scope
;
443 visit_sorted (iface
.get_classes ());
444 visit_sorted (iface
.get_structs ());
445 visit_sorted (iface
.get_enums ());
446 visit_sorted (iface
.get_delegates ());
447 visit_sorted (iface
.get_fields ());
448 visit_sorted (iface
.get_constants ());
449 visit_sorted (iface
.get_methods ());
450 visit_sorted (iface
.get_properties ());
451 visit_sorted (iface
.get_signals ());
453 current_scope
= current_scope
.parent_scope
;
459 public override void visit_enum (Enum en
) {
460 if (en
.external_package
) {
464 if (!check_accessibility (en
)) {
470 write_string ("[CCode (cprefix = \"%s\", ".printf (en
.get_cprefix ()));
472 if (!en
.has_type_id
) {
473 write_string ("has_type_id = \"%d\", ".printf (en
.has_type_id ?
1 : 0));
476 write_string ("cheader_filename = \"%s\")]".printf (get_cheaders(en
)));
480 write_string ("[Flags]");
483 write_attributes (en
);
486 write_accessibility (en
);
487 write_string ("enum ");
488 write_identifier (en
.name
);
489 write_begin_block ();
492 foreach (EnumValue ev
in en
.get_values ()) {
500 if (ev
.get_cname () != ev
.get_default_cname ()) {
502 write_string ("[CCode (cname = \"%s\")]".printf (ev
.get_cname ()));
505 write_identifier (ev
.name
);
509 if (en
.get_methods ().size
> 0) {
515 current_scope
= en
.scope
;
516 foreach (Method m
in en
.get_methods ()) {
519 current_scope
= current_scope
.parent_scope
;
525 public override void visit_error_domain (ErrorDomain edomain
) {
526 if (edomain
.external_package
) {
530 if (!check_accessibility (edomain
)) {
536 write_string ("[CCode (cprefix = \"%s\", cheader_filename = \"%s\")]".printf (edomain
.get_cprefix (), get_cheaders(edomain
)));
538 write_attributes (edomain
);
541 write_accessibility (edomain
);
542 write_string ("errordomain ");
543 write_identifier (edomain
.name
);
544 write_begin_block ();
546 edomain
.accept_children (this
);
552 public override void visit_error_code (ErrorCode ecode
) {
554 write_identifier (ecode
.name
);
559 public override void visit_constant (Constant c
) {
560 if (c
.external_package
) {
564 if (!check_accessibility (c
)) {
568 bool custom_cname
= (c
.get_cname () != c
.get_default_cname ());
569 bool custom_cheaders
= (c
.parent_symbol is Namespace
);
570 if (custom_cname
|| custom_cheaders
) {
572 write_string ("[CCode (");
575 write_string ("cname = \"%s\"".printf (c
.get_cname ()));
578 if (custom_cheaders
) {
583 write_string ("cheader_filename = \"%s\"".printf (get_cheaders(c
)));
590 write_accessibility (c
);
591 write_string ("const ");
593 write_type (c
.type_reference
);
596 write_identifier (c
.name
);
601 public override void visit_field (Field f
) {
602 if (f
.external_package
) {
606 if (!check_accessibility (f
)) {
610 bool custom_cname
= (f
.get_cname () != f
.get_default_cname ());
611 bool custom_ctype
= (f
.get_ctype () != null);
612 bool custom_cheaders
= (f
.parent_symbol is Namespace
);
613 if (custom_cname
|| custom_ctype
|| custom_cheaders
|| (f
.no_array_length
&& f
.field_type is ArrayType
)) {
615 write_string ("[CCode (");
618 write_string ("cname = \"%s\"".printf (f
.get_cname ()));
626 write_string ("type = \"%s\"".printf (f
.get_ctype ()));
629 if (custom_cheaders
) {
630 if (custom_cname
|| custom_ctype
) {
634 write_string ("cheader_filename = \"%s\"".printf (get_cheaders(f
)));
637 if (f
.no_array_length
&& f
.field_type is ArrayType
) {
638 if (custom_cname
|| custom_ctype
|| custom_cheaders
) {
642 write_string ("array_length = false");
644 if (f
.array_null_terminated
) {
645 write_string (", array_null_terminated = true");
653 write_accessibility (f
);
655 if (f
.binding
== MemberBinding
.STATIC
) {
656 write_string ("static ");
657 } else if (f
.binding
== MemberBinding
.CLASS
) {
658 write_string ("class ");
661 if (is_weak (f
.field_type
)) {
662 write_string ("weak ");
665 write_type (f
.field_type
);
668 write_identifier (f
.name
);
673 private void write_error_domains (List
<DataType
> error_domains
) {
674 if (error_domains
.size
> 0) {
675 write_string (" throws ");
678 foreach (DataType type
in error_domains
) {
690 // equality comparison with 3 digit precision
691 private bool float_equal (double d1
, double d2
) {
692 return ((int) (d1
* 1000)) == ((int) (d2
* 1000));
695 private void write_params (List
<FormalParameter
> params
) {
699 foreach (FormalParameter param
in params
) {
704 if (param
.ellipsis
) {
705 write_string ("...");
710 var ccode_params
= new
StringBuilder ();
713 if (param
.ctype
!= null) {
714 ccode_params
.append_printf ("%stype = \"%s\"", separator
, param
.ctype
);
717 if (param
.no_array_length
&& param
.parameter_type is ArrayType
) {
718 ccode_params
.append_printf ("%sarray_length = false", separator
);
721 if (!float_equal (param
.carray_length_parameter_position
, i
+ 0.1)) {
722 ccode_params
.append_printf ("%sarray_length_pos = %g", separator
, param
.carray_length_parameter_position
);
725 if (!float_equal (param
.cdelegate_target_parameter_position
, i
+ 0.1)) {
726 ccode_params
.append_printf ("%sdelegate_target_pos = %g", separator
, param
.cdelegate_target_parameter_position
);
730 if (ccode_params
.len
> 0) {
731 write_string ("[CCode (%s)] ".printf (ccode_params
.str
));
734 if (param
.params_array
) {
735 write_string ("params ");
738 if (param
.direction
== ParameterDirection
.IN
) {
739 if (param
.parameter_type
.value_owned
) {
740 write_string ("owned ");
743 if (param
.direction
== ParameterDirection
.REF
) {
744 write_string ("ref ");
745 } else if (param
.direction
== ParameterDirection
.OUT
) {
746 write_string ("out ");
748 if (is_weak (param
.parameter_type
)) {
749 write_string ("unowned ");
753 write_type (param
.parameter_type
);
756 write_identifier (param
.name
);
758 if (param
.default_expression
!= null) {
759 write_string (" = ");
760 write_string (param
.default_expression
.to_string ());
769 public override void visit_delegate (Delegate cb
) {
770 if (cb
.external_package
) {
774 if (!check_accessibility (cb
)) {
780 write_string ("[CCode (cheader_filename = \"%s\"".printf (get_cheaders(cb
)));
782 if (!cb
.has_target
) {
783 write_string (", has_target = false");
790 write_accessibility (cb
);
791 write_string ("delegate ");
793 write_return_type (cb
.return_type
);
796 write_identifier (cb
.name
);
800 write_params (cb
.get_parameters ());
807 public override void visit_constructor (Constructor c
) {
813 write_string ("construct");
814 write_code_block (c
.body
);
818 public override void visit_method (Method m
) {
819 if (m
.external_package
) {
823 // don't write interface implementation unless it's an abstract or virtual method
824 if (!check_accessibility (m
) || (m
.base_interface_method
!= null && !m
.is_abstract
&& !m
.is_virtual
)) {
830 if (m
.get_attribute ("NoWrapper") != null) {
832 write_string ("[NoWrapper]");
834 if (m
.returns_modified_pointer
) {
836 write_string ("[ReturnsModifiedPointer]");
838 if (m
.printf_format
) {
840 write_string ("[PrintfFormat]");
842 if (m
.scanf_format
) {
844 write_string ("[ScanfFormat]");
847 var ccode_params
= new
StringBuilder ();
850 if (m
.get_cname () != m
.get_default_cname ()) {
851 ccode_params
.append_printf ("%scname = \"%s\"", separator
, m
.get_cname ());
854 if (m
.parent_symbol is Namespace
) {
855 ccode_params
.append_printf ("%scheader_filename = \"%s\"", separator
, get_cheaders(m
));
858 if (!float_equal (m
.cinstance_parameter_position
, 0)) {
859 ccode_params
.append_printf ("%sinstance_pos = %g", separator
, m
.cinstance_parameter_position
);
862 if (m
.no_array_length
&& m
.return_type is ArrayType
) {
863 ccode_params
.append_printf ("%sarray_length = false", separator
);
866 if (!float_equal (m
.carray_length_parameter_position
, -3)) {
867 ccode_params
.append_printf ("%sarray_length_pos = %g", separator
, m
.carray_length_parameter_position
);
870 if (m
.array_null_terminated
&& m
.return_type is ArrayType
) {
871 ccode_params
.append_printf ("%sarray_null_terminated = true", separator
);
874 if (!float_equal (m
.cdelegate_target_parameter_position
, -3)) {
875 ccode_params
.append_printf ("%sdelegate_target_pos = %g", separator
, m
.cdelegate_target_parameter_position
);
878 if (m
.vfunc_name
!= m
.name
) {
879 ccode_params
.append_printf ("%svfunc_name = \"%s\"", separator
, m
.vfunc_name
);
882 if (m
.sentinel
!= m
.DEFAULT_SENTINEL
) {
883 ccode_params
.append_printf ("%ssentinel = \"%s\"", separator
, m
.sentinel
);
886 if (m is CreationMethod
&& ((CreationMethod
)m
).custom_return_type_cname
!= null) {
887 ccode_params
.append_printf ("%stype = \"%s\"", separator
, ((CreationMethod
)m
).custom_return_type_cname
);
890 if (m is CreationMethod
&& !m
.has_construct_function
) {
891 ccode_params
.append_printf ("%shas_construct_function = false", separator
);
895 if (ccode_params
.len
> 0) {
897 write_string ("[CCode (%s)]".printf (ccode_params
.str
));
901 write_accessibility (m
);
903 if (m is CreationMethod
) {
904 var datatype
= (TypeSymbol
) m
.parent_symbol
;
905 write_identifier (datatype
.name
);
906 if (m
.name
!= ".new") {
908 write_identifier (m
.name
);
911 } else if (m
.binding
== MemberBinding
.STATIC
) {
912 write_string ("static ");
913 } else if (m
.binding
== MemberBinding
.CLASS
) {
914 write_string ("class ");
915 } else if (m
.is_abstract
) {
916 write_string ("abstract ");
917 } else if (m
.is_virtual
) {
918 write_string ("virtual ");
919 } else if (m
.overrides
) {
920 write_string ("override ");
924 write_string ("async ");
927 if (!(m is CreationMethod
)) {
928 write_return_type (m
.return_type
);
931 write_identifier (m
.name
);
933 var type_params
= m
.get_type_parameters ();
934 if (type_params
.size
> 0) {
937 foreach (TypeParameter type_param
in type_params
) {
943 write_identifier (type_param
.name
);
951 write_params (m
.get_parameters ());
952 write_error_domains (m
.get_error_types ());
954 write_code_block (m
.body
);
959 public override void visit_creation_method (CreationMethod m
) {
963 public override void visit_property (Property prop
) {
964 if (!check_accessibility (prop
) || (prop
.base_interface_property
!= null && !prop
.is_abstract
&& !prop
.is_virtual
)) {
968 if (prop
.no_accessor_method
) {
970 write_string ("[NoAccessorMethod]");
972 if (prop
.property_type is ArrayType
&& prop
.no_array_length
) {
974 write_string ("[CCode (array_length = false");
976 if (prop
.array_null_terminated
) {
977 write_string (", array_null_terminated = true");
984 write_accessibility (prop
);
986 if (prop
.binding
== MemberBinding
.STATIC
) {
987 write_string ("static ");
988 } else if (prop
.is_abstract
) {
989 write_string ("abstract ");
990 } else if (prop
.is_virtual
) {
991 write_string ("virtual ");
992 } else if (prop
.overrides
) {
993 write_string ("override ");
996 write_type (prop
.property_type
);
999 write_identifier (prop
.name
);
1000 write_string (" {");
1001 if (prop
.get_accessor
!= null) {
1002 if (prop
.get_accessor
.value_type
.is_disposable ()) {
1003 write_string (" owned");
1006 write_string (" get");
1007 write_code_block (prop
.get_accessor
.body
);
1009 if (prop
.set_accessor
!= null) {
1010 if (prop
.set_accessor
.value_type
.value_owned
) {
1011 write_string ("owned ");
1014 if (prop
.set_accessor
.writable
) {
1015 write_string (" set");
1017 if (prop
.set_accessor
.construction
) {
1018 write_string (" construct");
1020 write_code_block (prop
.set_accessor
.body
);
1022 write_string (" }");
1026 public override void visit_signal (Signal sig
) {
1027 if (!check_accessibility (sig
)) {
1031 if (sig
.has_emitter
) {
1033 write_string ("[HasEmitter]");
1037 write_accessibility (sig
);
1039 if (sig
.is_virtual
) {
1040 write_string ("virtual ");
1043 write_string ("signal ");
1045 write_return_type (sig
.return_type
);
1048 write_identifier (sig
.name
);
1052 write_params (sig
.get_parameters ());
1059 public override void visit_block (Block b
) {
1060 write_begin_block ();
1062 foreach (Statement stmt
in b
.get_statements ()) {
1069 public override void visit_empty_statement (EmptyStatement stmt
) {
1072 public override void visit_declaration_statement (DeclarationStatement stmt
) {
1074 stmt
.declaration
.accept (this
);
1079 public override void visit_local_variable (LocalVariable local
) {
1080 write_type (local
.variable_type
);
1082 write_identifier (local
.name
);
1083 if (local
.initializer
!= null) {
1084 write_string (" = ");
1085 local
.initializer
.accept (this
);
1089 public override void visit_initializer_list (InitializerList list
) {
1093 foreach (Expression initializer
in list
.get_initializers ()) {
1095 write_string (", ");
1100 initializer
.accept (this
);
1102 write_string (" }");
1105 public override void visit_expression_statement (ExpressionStatement stmt
) {
1107 stmt
.expression
.accept (this
);
1112 public override void visit_if_statement (IfStatement stmt
) {
1114 write_string ("if (");
1115 stmt
.condition
.accept (this
);
1117 stmt
.true_statement
.accept (this
);
1118 if (stmt
.false_statement
!= null) {
1119 write_string (" else");
1120 stmt
.false_statement
.accept (this
);
1125 public override void visit_switch_statement (SwitchStatement stmt
) {
1127 write_string ("switch (");
1128 stmt
.expression
.accept (this
);
1129 write_string (") {");
1132 foreach (SwitchSection section
in stmt
.get_sections ()) {
1133 section
.accept (this
);
1141 public override void visit_switch_section (SwitchSection section
) {
1142 foreach (SwitchLabel label
in section
.get_labels ()) {
1143 label
.accept (this
);
1146 visit_block (section
);
1149 public override void visit_switch_label (SwitchLabel label
) {
1150 if (label
.expression
!= null) {
1152 write_string ("case ");
1153 label
.expression
.accept (this
);
1158 write_string ("default:");
1163 public override void visit_loop (Loop stmt
) {
1165 write_string ("loop");
1166 stmt
.body
.accept (this
);
1170 public override void visit_while_statement (WhileStatement stmt
) {
1172 write_string ("while (");
1173 stmt
.condition
.accept (this
);
1175 stmt
.body
.accept (this
);
1179 public override void visit_do_statement (DoStatement stmt
) {
1181 write_string ("do");
1182 stmt
.body
.accept (this
);
1183 write_string ("while (");
1184 stmt
.condition
.accept (this
);
1185 write_string (");");
1189 public override void visit_for_statement (ForStatement stmt
) {
1191 write_string ("for (");
1194 foreach (Expression initializer
in stmt
.get_initializer ()) {
1196 write_string (", ");
1199 initializer
.accept (this
);
1201 write_string ("; ");
1203 stmt
.condition
.accept (this
);
1204 write_string ("; ");
1207 foreach (Expression iterator
in stmt
.get_iterator ()) {
1209 write_string (", ");
1212 iterator
.accept (this
);
1216 stmt
.body
.accept (this
);
1220 public override void visit_foreach_statement (ForeachStatement stmt
) {
1223 public override void visit_break_statement (BreakStatement stmt
) {
1225 write_string ("break;");
1229 public override void visit_continue_statement (ContinueStatement stmt
) {
1231 write_string ("continue;");
1235 public override void visit_return_statement (ReturnStatement stmt
) {
1237 write_string ("return");
1238 if (stmt
.return_expression
!= null) {
1240 stmt
.return_expression
.accept (this
);
1246 public override void visit_yield_statement (YieldStatement y
) {
1248 write_string ("yield");
1249 if (y
.yield_expression
!= null) {
1251 y
.yield_expression
.accept (this
);
1257 public override void visit_throw_statement (ThrowStatement stmt
) {
1259 write_string ("throw");
1260 if (stmt
.error_expression
!= null) {
1262 stmt
.error_expression
.accept (this
);
1268 public override void visit_try_statement (TryStatement stmt
) {
1270 write_string ("try");
1271 stmt
.body
.accept (this
);
1275 public override void visit_catch_clause (CatchClause clause
) {
1278 public override void visit_lock_statement (LockStatement stmt
) {
1281 public override void visit_delete_statement (DeleteStatement stmt
) {
1284 public override void visit_array_creation_expression (ArrayCreationExpression expr
) {
1285 write_string ("new ");
1286 write_type (expr
.element_type
);
1290 foreach (Expression size
in expr
.get_sizes ()) {
1292 write_string (", ");
1301 if (expr
.initializer_list
!= null) {
1303 expr
.initializer_list
.accept (this
);
1307 public override void visit_boolean_literal (BooleanLiteral lit
) {
1308 write_string (lit
.value
.to_string ());
1311 public override void visit_character_literal (CharacterLiteral lit
) {
1312 write_string (lit
.value
);
1315 public override void visit_integer_literal (IntegerLiteral lit
) {
1316 write_string (lit
.value
);
1319 public override void visit_real_literal (RealLiteral lit
) {
1320 write_string (lit
.value
);
1323 public override void visit_string_literal (StringLiteral lit
) {
1324 write_string (lit
.value
);
1327 public override void visit_null_literal (NullLiteral lit
) {
1328 write_string ("null");
1331 public override void visit_member_access (MemberAccess expr
) {
1332 if (expr
.inner
!= null) {
1333 expr
.inner
.accept (this
);
1336 write_identifier (expr
.member_name
);
1339 public override void visit_method_call (MethodCall expr
) {
1340 expr
.call
.accept (this
);
1341 write_string (" (");
1344 foreach (Expression arg
in expr
.get_argument_list ()) {
1346 write_string (", ");
1356 public override void visit_element_access (ElementAccess expr
) {
1357 expr
.container
.accept (this
);
1361 foreach (Expression index
in expr
.get_indices ()) {
1363 write_string (", ");
1367 index
.accept (this
);
1373 public override void visit_base_access (BaseAccess expr
) {
1374 write_string ("base");
1377 public override void visit_postfix_expression (PostfixExpression expr
) {
1378 expr
.inner
.accept (this
);
1379 if (expr
.increment
) {
1380 write_string ("++");
1382 write_string ("--");
1386 public override void visit_object_creation_expression (ObjectCreationExpression expr
) {
1387 write_string ("new ");
1388 write_type (expr
.type_reference
);
1389 write_string (" (");
1392 foreach (Expression arg
in expr
.get_argument_list ()) {
1394 write_string (", ");
1404 public override void visit_sizeof_expression (SizeofExpression expr
) {
1405 write_string ("sizeof (");
1406 write_type (expr
.type_reference
);
1410 public override void visit_typeof_expression (TypeofExpression expr
) {
1411 write_string ("typeof (");
1412 write_type (expr
.type_reference
);
1416 public override void visit_unary_expression (UnaryExpression expr
) {
1417 switch (expr
.operator
) {
1418 case UnaryOperator
.PLUS
:
1421 case UnaryOperator
.MINUS
:
1424 case UnaryOperator
.LOGICAL_NEGATION
:
1427 case UnaryOperator
.BITWISE_COMPLEMENT
:
1430 case UnaryOperator
.INCREMENT
:
1431 write_string ("++");
1433 case UnaryOperator
.DECREMENT
:
1434 write_string ("--");
1436 case UnaryOperator
.REF
:
1437 write_string ("ref ");
1439 case UnaryOperator
.OUT
:
1440 write_string ("out ");
1443 assert_not_reached ();
1445 expr
.inner
.accept (this
);
1448 public override void visit_cast_expression (CastExpression expr
) {
1449 if (expr
.is_non_null_cast
) {
1450 write_string ("(!) ");
1451 expr
.inner
.accept (this
);
1455 if (!expr
.is_silent_cast
) {
1457 write_type (expr
.type_reference
);
1458 write_string (") ");
1461 expr
.inner
.accept (this
);
1463 if (expr
.is_silent_cast
) {
1464 write_string (" as ");
1465 write_type (expr
.type_reference
);
1469 public override void visit_pointer_indirection (PointerIndirection expr
) {
1471 expr
.inner
.accept (this
);
1474 public override void visit_addressof_expression (AddressofExpression expr
) {
1476 expr
.inner
.accept (this
);
1479 public override void visit_reference_transfer_expression (ReferenceTransferExpression expr
) {
1480 write_string ("(owned) ");
1481 expr
.inner
.accept (this
);
1484 public override void visit_binary_expression (BinaryExpression expr
) {
1485 expr
.left
.accept (this
);
1487 switch (expr
.operator
) {
1488 case BinaryOperator
.PLUS
:
1489 write_string (" + ");
1491 case BinaryOperator
.MINUS
:
1492 write_string (" - ");
1494 case BinaryOperator
.MUL
:
1495 write_string (" * ");
1497 case BinaryOperator
.DIV
:
1498 write_string (" / ");
1500 case BinaryOperator
.MOD
:
1501 write_string (" % ");
1503 case BinaryOperator
.SHIFT_LEFT
:
1504 write_string (" << ");
1506 case BinaryOperator
.SHIFT_RIGHT
:
1507 write_string (" >> ");
1509 case BinaryOperator
.LESS_THAN
:
1510 write_string (" < ");
1512 case BinaryOperator
.GREATER_THAN
:
1513 write_string (" > ");
1515 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
1516 write_string (" <= ");
1518 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
1519 write_string (" >= ");
1521 case BinaryOperator
.EQUALITY
:
1522 write_string (" == ");
1524 case BinaryOperator
.INEQUALITY
:
1525 write_string (" != ");
1527 case BinaryOperator
.BITWISE_AND
:
1528 write_string (" & ");
1530 case BinaryOperator
.BITWISE_OR
:
1531 write_string (" | ");
1533 case BinaryOperator
.BITWISE_XOR
:
1534 write_string (" ^ ");
1536 case BinaryOperator
.AND
:
1537 write_string (" && ");
1539 case BinaryOperator
.OR
:
1540 write_string (" || ");
1542 case BinaryOperator
.IN
:
1543 write_string (" in ");
1546 assert_not_reached ();
1549 expr
.right
.accept (this
);
1552 public override void visit_type_check (TypeCheck expr
) {
1553 expr
.expression
.accept (this
);
1554 write_string (" is ");
1555 write_type (expr
.type_reference
);
1558 public override void visit_conditional_expression (ConditionalExpression expr
) {
1559 expr
.condition
.accept (this
);
1561 expr
.true_expression
.accept (this
);
1563 expr
.false_expression
.accept (this
);
1566 public override void visit_lambda_expression (LambdaExpression expr
) {
1569 public override void visit_assignment (Assignment a
) {
1570 a
.left
.accept (this
);
1571 write_string (" = ");
1572 a
.right
.accept (this
);
1575 private void write_indent () {
1582 for (i
= 0; i
< indent
; i
++) {
1589 private void write_identifier (string s
) {
1590 char* id
= (char*)s
;
1591 int id_length
= (int)s
.length
;
1592 if ( Vala
.Scanner
.get_identifier_or_keyword (id
, id_length
) != Vala
.TokenType
.IDENTIFIER
||
1593 s
.get_char ().isdigit ()) {
1599 private void write_return_type (DataType type
) {
1600 if (is_weak (type
)) {
1601 write_string ("unowned ");
1607 private bool is_weak (DataType type
) {
1608 if (type
.value_owned
) {
1610 } else if (type is VoidType
|| type is PointerType
) {
1612 } else if (type is ValueType
) {
1613 if (type
.nullable
) {
1614 // nullable structs are heap allocated
1618 // TODO return true for structs with destroy
1625 private void write_type (DataType type
) {
1626 write_string (type
.to_qualified_string (current_scope
));
1629 private void write_string (string s
) {
1630 stream
.printf ("%s", s
);
1634 private void write_newline () {
1639 void write_code_block (Block? block
) {
1640 if (block
== null || !dump_tree
) {
1645 block
.accept (this
);
1648 private void write_begin_block () {
1659 private void write_end_block () {
1662 stream
.printf ("}");
1665 private bool check_accessibility (Symbol sym
) {
1669 if (!emit_internal
&&
1670 ( sym
.access
== SymbolAccessibility
.PUBLIC
||
1671 sym
.access
== SymbolAccessibility
.PROTECTED
)) {
1673 } else if (emit_internal
&&
1674 ( sym
.access
== SymbolAccessibility
.INTERNAL
||
1675 sym
.access
== SymbolAccessibility
.PUBLIC
||
1676 sym
.access
== SymbolAccessibility
.PROTECTED
)) {
1684 private void write_attributes (CodeNode node
) {
1685 foreach (Attribute attr
in node
.attributes
) {
1686 if (!filter_attribute (attr
)) {
1688 stream
.printf ("[%s", attr
.name
);
1690 var keys
= attr
.args
.get_keys ();
1691 if (keys
.size
!= 0) {
1692 stream
.printf (" (");
1694 string separator
= "";
1695 foreach (string arg_name
in keys
) {
1696 stream
.printf ("%s%s = ", separator
, arg_name
);
1697 var expr
= attr
.args
.get (arg_name
);
1702 stream
.printf (")");
1704 stream
.printf ("]");
1710 private bool filter_attribute (Attribute attr
) {
1711 if (attr
.name
== "CCode"
1712 || attr
.name
== "Compact" || attr
.name
== "Immutable"
1713 || attr
.name
== "SimpleType" || attr
.name
== "IntegerType" || attr
.name
== "FloatingType"
1714 || attr
.name
== "Flags") {
1720 private void write_accessibility (Symbol sym
) {
1721 if (sym
.access
== SymbolAccessibility
.PUBLIC
) {
1722 write_string ("public ");
1723 } else if (sym
.access
== SymbolAccessibility
.PROTECTED
) {
1724 write_string ("protected ");
1725 } else if (sym
.access
== SymbolAccessibility
.INTERNAL
) {
1726 write_string ("internal ");
1727 } else if (sym
.access
== SymbolAccessibility
.PRIVATE
) {
1728 write_string ("private ");