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>
28 * Code visitor generating Vala API file for the public interface.
30 public class Vala
.CodeWriter
: CodeVisitor
{
31 private CodeContext context
;
36 /* at begin of line */
43 public CodeWriter (bool dump_tree
= false) {
44 this
.dump_tree
= dump_tree
;
48 * Writes the public interface of the specified code context into the
51 * @param context a code context
52 * @param filename a relative or absolute filename
54 public void write_file (CodeContext context
, string filename
) {
55 this
.context
= context
;
57 stream
= FileStream
.open (filename
, "w");
59 write_string ("/* %s generated by %s, do not modify. */".printf (Path
.get_basename (filename
), Environment
.get_prgname ()));
63 current_scope
= context
.root
.scope
;
65 context
.accept (this
);
72 public override void visit_namespace (Namespace ns
) {
73 if (ns
.external_package
) {
77 if (ns
.name
== null) {
78 ns
.accept_children (this
);
83 write_string ("[CCode (cprefix = \"%s\", lower_case_cprefix = \"%s\")]".printf (ns
.get_cprefix (), ns
.get_lower_case_cprefix ()));
87 write_string ("namespace ");
88 write_identifier (ns
.name
);
91 current_scope
= ns
.scope
;
93 visit_sorted (ns
.get_namespaces ());
94 visit_sorted (ns
.get_classes ());
95 visit_sorted (ns
.get_interfaces ());
96 visit_sorted (ns
.get_structs ());
97 visit_sorted (ns
.get_enums ());
98 visit_sorted (ns
.get_error_domains ());
99 visit_sorted (ns
.get_delegates ());
100 visit_sorted (ns
.get_fields ());
101 visit_sorted (ns
.get_constants ());
102 visit_sorted (ns
.get_methods ());
104 current_scope
= current_scope
.parent_scope
;
110 public override void visit_class (Class cl
) {
111 if (cl
.external_package
) {
115 if (!check_accessibility (cl
)) {
121 write_string ("[Compact]");
125 if (cl
.is_immutable
) {
127 write_string ("[Immutable]");
133 write_string ("[CCode (");
135 if (cl
.is_reference_counting ()) {
136 if (cl
.base_class
== null || cl
.base_class
.get_ref_function () == null || cl
.base_class
.get_ref_function () != cl
.get_ref_function ()) {
137 write_string ("ref_function = \"%s\", ".printf (cl
.get_ref_function ()));
138 if (cl
.ref_function_void
) {
139 write_string ("ref_function_void = true, ");
142 if (cl
.base_class
== null || cl
.base_class
.get_unref_function () == null || cl
.base_class
.get_unref_function () != cl
.get_unref_function ()) {
143 write_string ("unref_function = \"%s\", ".printf (cl
.get_unref_function ()));
146 if (cl
.get_dup_function () != null) {
147 write_string ("copy_function = \"%s\", ".printf (cl
.get_dup_function ()));
149 if (cl
.get_free_function () != cl
.get_default_free_function ()) {
150 write_string ("free_function = \"%s\", ".printf (cl
.get_free_function ()));
154 if (cl
.get_cname () != cl
.get_default_cname ()) {
155 write_string ("cname = \"%s\", ".printf (cl
.get_cname ()));
158 if (cl
.type_check_function
!= null) {
159 write_string ("type_check_function = \"%s\", ".printf (cl
.type_check_function
));
162 if (cl
.is_compact
&& cl
.get_type_id () != "G_TYPE_POINTER") {
163 write_string ("type_id = \"%s\", ".printf (cl
.get_type_id ()));
166 if (cl
.get_param_spec_function () != null
167 && (cl
.base_class
== null || cl
.get_param_spec_function () != cl
.base_class
.get_param_spec_function ())) {
168 write_string ("param_spec_function = \"%s\", ".printf (cl
.get_param_spec_function ()));
172 string cheaders
= "";
173 foreach (string cheader
in cl
.get_cheader_filenames ()) {
178 cheaders
= "%s,%s".printf (cheaders
, cheader
);
181 write_string ("cheader_filename = \"%s\")]".printf (cheaders
));
185 write_accessibility (cl
);
186 if (cl
.is_abstract
) {
187 write_string ("abstract ");
189 write_string ("class ");
190 write_identifier (cl
.name
);
192 var type_params
= cl
.get_type_parameters ();
193 if (type_params
.size
> 0) {
196 foreach (TypeParameter type_param
in type_params
) {
202 write_identifier (type_param
.name
);
207 var base_types
= cl
.get_base_types ();
208 if (base_types
.size
> 0) {
209 write_string (" : ");
212 foreach (DataType base_type
in base_types
) {
218 write_type (base_type
);
221 write_begin_block ();
223 current_scope
= cl
.scope
;
225 visit_sorted (cl
.get_classes ());
226 visit_sorted (cl
.get_structs ());
227 visit_sorted (cl
.get_enums ());
228 visit_sorted (cl
.get_delegates ());
229 visit_sorted (cl
.get_fields ());
230 visit_sorted (cl
.get_constants ());
231 visit_sorted (cl
.get_methods ());
232 visit_sorted (cl
.get_properties ());
233 visit_sorted (cl
.get_signals ());
235 current_scope
= current_scope
.parent_scope
;
241 void visit_sorted (Gee
.List
<Symbol
> symbols
) {
242 var sorted_symbols
= new Gee
.ArrayList
<Symbol
> ();
243 foreach (Symbol sym
in symbols
) {
245 int right
= sorted_symbols
.size
- 1;
246 if (left
> right
|| sym
.name
< sorted_symbols
[left
].name
) {
247 sorted_symbols
.insert (0, sym
);
248 } else if (sym
.name
> sorted_symbols
[right
].name
) {
249 sorted_symbols
.add (sym
);
251 while (right
- left
> 1) {
252 int i
= (right
+ left
) / 2;
253 if (sym
.name
> sorted_symbols
[i
].name
) {
259 sorted_symbols
.insert (left
+ 1, sym
);
262 foreach (Symbol sym
in sorted_symbols
) {
267 public override void visit_struct (Struct st
) {
268 if (st
.external_package
) {
272 if (!check_accessibility (st
)) {
278 write_string ("[CCode (");
280 if (st
.get_cname () != st
.get_default_cname ()) {
281 write_string ("cname = \"%s\", ".printf (st
.get_cname ()));
284 if (!st
.is_simple_type () && st
.get_type_id () != "G_TYPE_POINTER") {
285 write_string ("type_id = \"%s\", ".printf (st
.get_type_id ()));
289 write_string ("use_const = false, ");
293 string cheaders
= "";
294 foreach (string cheader
in st
.get_cheader_filenames ()) {
299 cheaders
= "%s,%s".printf (cheaders
, cheader
);
302 write_string ("cheader_filename = \"%s\")]".printf (cheaders
));
305 if (st
.is_simple_type ()) {
307 write_string ("[SimpleType]");
311 if (st
.is_integer_type ()) {
313 write_string ("[IntegerType (rank = %d)]".printf (st
.get_rank ()));
317 if (st
.is_floating_type ()) {
319 write_string ("[FloatingType (rank = %d)]".printf (st
.get_rank ()));
324 write_accessibility (st
);
325 write_string ("struct ");
326 write_identifier (st
.name
);
328 if (st
.base_type
!= null) {
329 write_string (" : ");
330 write_type (st
.base_type
);
333 write_begin_block ();
335 current_scope
= st
.scope
;
337 foreach (Field field
in st
.get_fields ()) {
340 visit_sorted (st
.get_constants ());
341 visit_sorted (st
.get_methods ());
343 current_scope
= current_scope
.parent_scope
;
349 public override void visit_interface (Interface iface
) {
350 if (iface
.external_package
) {
354 if (!check_accessibility (iface
)) {
361 string cheaders
= "";
362 foreach (string cheader
in iface
.get_cheader_filenames ()) {
367 cheaders
= "%s,%s".printf (cheaders
, cheader
);
370 write_string ("[CCode (cheader_filename = \"%s\"".printf (cheaders
));
371 if (iface
.get_lower_case_csuffix () != iface
.get_default_lower_case_csuffix ())
372 write_string (", lower_case_csuffix = \"%s\"".printf (iface
.get_lower_case_csuffix ()));
378 write_accessibility (iface
);
379 write_string ("interface ");
380 write_identifier (iface
.name
);
382 var type_params
= iface
.get_type_parameters ();
383 if (type_params
.size
> 0) {
386 foreach (TypeParameter type_param
in type_params
) {
392 write_identifier (type_param
.name
);
397 var prerequisites
= iface
.get_prerequisites ();
398 if (prerequisites
.size
> 0) {
399 write_string (" : ");
402 foreach (DataType prerequisite
in prerequisites
) {
408 write_type (prerequisite
);
411 write_begin_block ();
413 current_scope
= iface
.scope
;
415 visit_sorted (iface
.get_classes ());
416 visit_sorted (iface
.get_structs ());
417 visit_sorted (iface
.get_enums ());
418 visit_sorted (iface
.get_delegates ());
419 visit_sorted (iface
.get_fields ());
420 visit_sorted (iface
.get_methods ());
421 visit_sorted (iface
.get_properties ());
422 visit_sorted (iface
.get_signals ());
424 current_scope
= current_scope
.parent_scope
;
430 public override void visit_enum (Enum en
) {
431 if (en
.external_package
) {
435 if (!check_accessibility (en
)) {
442 string cheaders
= "";
443 foreach (string cheader
in en
.get_cheader_filenames ()) {
448 cheaders
= "%s,%s".printf (cheaders
, cheader
);
452 write_string ("[CCode (cprefix = \"%s\", ".printf (en
.get_cprefix ()));
454 if (!en
.has_type_id
) {
455 write_string ("has_type_id = \"%d\", ".printf (en
.has_type_id ?
1 : 0));
458 write_string ("cheader_filename = \"%s\")]".printf (cheaders
));
462 write_string ("[Flags]");
466 write_accessibility (en
);
467 write_string ("enum ");
468 write_identifier (en
.name
);
469 write_begin_block ();
472 foreach (EnumValue ev
in en
.get_values ()) {
480 if (ev
.get_cname () != ev
.get_default_cname ()) {
482 write_string ("[CCode (cname = \"%s\")]".printf (ev
.get_cname ()));
485 write_identifier (ev
.name
);
489 if (en
.get_methods ().size
> 0) {
495 current_scope
= en
.scope
;
496 foreach (Method m
in en
.get_methods ()) {
499 current_scope
= current_scope
.parent_scope
;
505 public override void visit_error_domain (ErrorDomain edomain
) {
506 if (edomain
.external_package
) {
510 if (!check_accessibility (edomain
)) {
517 string cheaders
= "";
518 foreach (string cheader
in edomain
.get_cheader_filenames ()) {
523 cheaders
= "%s,%s".printf (cheaders
, cheader
);
526 write_string ("[CCode (cprefix = \"%s\", cheader_filename = \"%s\")]".printf (edomain
.get_cprefix (), cheaders
));
529 write_accessibility (edomain
);
530 write_string ("errordomain ");
531 write_identifier (edomain
.name
);
532 write_begin_block ();
534 edomain
.accept_children (this
);
540 public override void visit_error_code (ErrorCode ecode
) {
542 write_identifier (ecode
.name
);
547 public override void visit_constant (Constant c
) {
548 if (c
.external_package
) {
552 if (!check_accessibility (c
)) {
556 bool custom_cname
= (c
.get_cname () != c
.get_default_cname ());
557 bool custom_cheaders
= (c
.parent_symbol is Namespace
);
558 if (custom_cname
|| custom_cheaders
) {
560 write_string ("[CCode (");
563 write_string ("cname = \"%s\"".printf (c
.get_cname ()));
566 if (custom_cheaders
) {
572 string cheaders
= "";
573 foreach (string cheader
in c
.get_cheader_filenames ()) {
578 cheaders
= "%s,%s".printf (cheaders
, cheader
);
581 write_string ("cheader_filename = \"%s\"".printf (cheaders
));
588 write_accessibility (c
);
589 write_string ("const ");
591 write_type (c
.type_reference
);
594 write_identifier (c
.name
);
599 public override void visit_field (Field f
) {
600 if (f
.external_package
) {
604 if (!check_accessibility (f
)) {
608 bool custom_cname
= (f
.get_cname () != f
.get_default_cname ());
609 bool custom_ctype
= (f
.get_ctype () != null);
610 bool custom_cheaders
= (f
.parent_symbol is Namespace
);
611 if (custom_cname
|| custom_ctype
|| custom_cheaders
|| (f
.no_array_length
&& f
.field_type is ArrayType
)) {
613 write_string ("[CCode (");
616 write_string ("cname = \"%s\"".printf (f
.get_cname ()));
624 write_string ("type = \"%s\"".printf (f
.get_ctype ()));
627 if (custom_cheaders
) {
628 if (custom_cname
|| custom_ctype
) {
633 string cheaders
= "";
634 foreach (string cheader
in f
.get_cheader_filenames ()) {
639 cheaders
= "%s,%s".printf (cheaders
, cheader
);
642 write_string ("cheader_filename = \"%s\"".printf (cheaders
));
645 if (f
.no_array_length
&& f
.field_type is ArrayType
) {
646 if (custom_cname
|| custom_ctype
|| custom_cheaders
) {
650 write_string ("array_length = false");
657 write_accessibility (f
);
659 if (f
.binding
== MemberBinding
.STATIC
) {
660 write_string ("static ");
661 } else if (f
.binding
== MemberBinding
.CLASS
) {
662 write_string ("class ");
665 if (is_weak (f
.field_type
)) {
666 write_string ("weak ");
669 write_type (f
.field_type
);
672 write_identifier (f
.name
);
677 private void write_error_domains (Gee
.List
<DataType
> error_domains
) {
678 if (error_domains
.size
> 0) {
679 write_string (" throws ");
682 foreach (DataType type
in error_domains
) {
694 // equality comparison with 3 digit precision
695 private bool float_equal (double d1
, double d2
) {
696 return ((int) (d1
* 1000)) == ((int) (d2
* 1000));
699 private void write_params (Gee
.List
<FormalParameter
> params
) {
703 foreach (FormalParameter param
in params
) {
708 if (param
.ellipsis
) {
709 write_string ("...");
714 var ccode_params
= new
StringBuilder ();
717 if (param
.ctype
!= null) {
718 ccode_params
.append_printf ("%stype = \"%s\"", separator
, param
.ctype
);
721 if (param
.no_array_length
&& param
.parameter_type is ArrayType
) {
722 ccode_params
.append_printf ("%sarray_length = false", separator
);
725 if (!float_equal (param
.carray_length_parameter_position
, i
+ 0.1)) {
726 ccode_params
.append_printf ("%sarray_length_pos = %g", separator
, param
.carray_length_parameter_position
);
729 if (!float_equal (param
.cdelegate_target_parameter_position
, i
+ 0.1)) {
730 ccode_params
.append_printf ("%sdelegate_target_pos = %g", separator
, param
.cdelegate_target_parameter_position
);
733 if (param
.async_only
) {
734 ccode_params
.append_printf ("%sasync_only = true", separator
);
738 if (ccode_params
.len
> 0) {
739 write_string ("[CCode (%s)] ".printf (ccode_params
.str
));
742 if (param
.params_array
) {
743 write_string ("params ");
746 if (param
.direction
== ParameterDirection
.IN
) {
747 if (param
.parameter_type
.value_owned
) {
748 write_string ("owned ");
751 if (param
.direction
== ParameterDirection
.REF
) {
752 write_string ("ref ");
753 } else if (param
.direction
== ParameterDirection
.OUT
) {
754 write_string ("out ");
756 if (is_weak (param
.parameter_type
)) {
757 write_string ("unowned ");
761 write_type (param
.parameter_type
);
764 write_identifier (param
.name
);
766 if (param
.default_expression
!= null) {
767 write_string (" = ");
768 write_string (param
.default_expression
.to_string ());
777 public override void visit_delegate (Delegate cb
) {
778 if (cb
.external_package
) {
782 if (!check_accessibility (cb
)) {
789 string cheaders
= "";
790 foreach (string cheader
in cb
.get_cheader_filenames ()) {
795 cheaders
= "%s,%s".printf (cheaders
, cheader
);
798 write_string ("[CCode (cheader_filename = \"%s\")]".printf (cheaders
));
802 write_accessibility (cb
);
803 if (!cb
.has_target
) {
804 write_string ("static ");
806 write_string ("delegate ");
808 write_return_type (cb
.return_type
);
811 write_identifier (cb
.name
);
815 write_params (cb
.get_parameters ());
822 public override void visit_method (Method m
) {
823 if (m
.external_package
) {
827 // don't write interface implementation unless it's an abstract or virtual method
828 if (!check_accessibility (m
) || (m
.base_interface_method
!= null && !m
.is_abstract
&& !m
.is_virtual
)) {
834 if (m
.get_attribute ("NoWrapper") != null) {
836 write_string ("[NoWrapper]");
838 if (m
.returns_modified_pointer
) {
840 write_string ("[ReturnsModifiedPointer]");
843 var ccode_params
= new
StringBuilder ();
846 if (m
.get_cname () != m
.get_default_cname ()) {
847 ccode_params
.append_printf ("%scname = \"%s\"", separator
, m
.get_cname ());
850 if (m
.parent_symbol is Namespace
) {
852 string cheaders
= "";
853 foreach (string cheader
in m
.get_cheader_filenames ()) {
858 cheaders
= "%s,%s".printf (cheaders
, cheader
);
861 ccode_params
.append_printf ("%scheader_filename = \"%s\"", separator
, cheaders
);
864 if (!float_equal (m
.cinstance_parameter_position
, 0)) {
865 ccode_params
.append_printf ("%sinstance_pos = %g", separator
, m
.cinstance_parameter_position
);
868 if (m
.no_array_length
&& m
.return_type is ArrayType
) {
869 ccode_params
.append_printf ("%sarray_length = false", separator
);
872 if (!float_equal (m
.carray_length_parameter_position
, -3)) {
873 ccode_params
.append_printf ("%sarray_length_pos = %g", separator
, m
.carray_length_parameter_position
);
876 if (m
.array_null_terminated
&& m
.return_type is ArrayType
) {
877 ccode_params
.append_printf ("%sarray_null_terminated = true", separator
);
880 if (!float_equal (m
.cdelegate_target_parameter_position
, -3)) {
881 ccode_params
.append_printf ("%sdelegate_target_pos = %g", separator
, m
.cdelegate_target_parameter_position
);
884 if (m
.vfunc_name
!= m
.name
) {
885 ccode_params
.append_printf ("%svfunc_name = \"%s\"", separator
, m
.vfunc_name
);
888 if (m
.sentinel
!= m
.DEFAULT_SENTINEL
) {
889 ccode_params
.append_printf ("%ssentinel = \"%s\"", separator
, m
.sentinel
);
892 if (m is CreationMethod
&& ((CreationMethod
)m
).custom_return_type_cname
!= null) {
893 ccode_params
.append_printf ("%stype = \"%s\"", separator
, ((CreationMethod
)m
).custom_return_type_cname
);
896 if (m is CreationMethod
&& !m
.has_construct_function
) {
897 ccode_params
.append_printf ("%shas_construct_function = false", separator
);
901 if (ccode_params
.len
> 0) {
903 write_string ("[CCode (%s)]".printf (ccode_params
.str
));
907 write_accessibility (m
);
909 if (m is CreationMethod
) {
910 var datatype
= (TypeSymbol
) m
.parent_symbol
;
911 write_identifier (datatype
.name
);
912 if (m
.name
!= "new") {
914 write_identifier (m
.name
);
917 } else if (m
.binding
== MemberBinding
.STATIC
) {
918 write_string ("static ");
919 } else if (m
.binding
== MemberBinding
.CLASS
) {
920 write_string ("class ");
921 } else if (m
.is_abstract
) {
922 write_string ("abstract ");
923 } else if (m
.is_virtual
) {
924 write_string ("virtual ");
925 } else if (m
.overrides
) {
926 write_string ("override ");
929 if (!(m is CreationMethod
)) {
930 write_return_type (m
.return_type
);
933 write_identifier (m
.name
);
937 write_params (m
.get_parameters ());
938 write_error_domains (m
.get_error_types ());
940 write_code_block (m
.body
);
945 public override void visit_creation_method (CreationMethod m
) {
949 public override void visit_property (Property prop
) {
950 if (!check_accessibility (prop
) || (prop
.base_interface_property
!= null && !prop
.is_abstract
&& !prop
.is_virtual
)) {
954 if (prop
.no_accessor_method
) {
956 write_string ("[NoAccessorMethod]");
960 write_accessibility (prop
);
962 if (prop
.binding
== MemberBinding
.STATIC
) {
963 write_string ("static ");
964 } else if (prop
.is_abstract
) {
965 write_string ("abstract ");
966 } else if (prop
.is_virtual
) {
967 write_string ("virtual ");
968 } else if (prop
.overrides
) {
969 write_string ("override ");
972 write_type (prop
.property_type
);
975 write_identifier (prop
.name
);
977 if (prop
.get_accessor
!= null) {
978 if (prop
.get_accessor
.value_type
.is_disposable ()) {
979 write_string (" owned");
982 write_string (" get");
983 write_code_block (prop
.get_accessor
.body
);
985 if (prop
.set_accessor
!= null) {
986 if (prop
.set_accessor
.value_type
.value_owned
) {
987 write_string ("owned ");
990 if (prop
.set_accessor
.writable
) {
991 write_string (" set");
993 if (prop
.set_accessor
.construction
) {
994 write_string (" construct");
996 write_code_block (prop
.set_accessor
.body
);
1002 public override void visit_signal (Signal sig
) {
1003 if (!check_accessibility (sig
)) {
1007 if (sig
.has_emitter
) {
1009 write_string ("[HasEmitter]");
1013 write_accessibility (sig
);
1015 if (sig
.is_virtual
) {
1016 write_string ("virtual ");
1019 write_string ("signal ");
1021 write_return_type (sig
.return_type
);
1024 write_identifier (sig
.name
);
1028 write_params (sig
.get_parameters ());
1035 public override void visit_block (Block b
) {
1036 write_begin_block ();
1038 foreach (Statement stmt
in b
.get_statements ()) {
1045 public override void visit_empty_statement (EmptyStatement stmt
) {
1048 public override void visit_declaration_statement (DeclarationStatement stmt
) {
1050 stmt
.declaration
.accept (this
);
1055 public override void visit_local_variable (LocalVariable local
) {
1056 write_type (local
.variable_type
);
1058 write_identifier (local
.name
);
1059 if (local
.initializer
!= null) {
1060 write_string (" = ");
1061 local
.initializer
.accept (this
);
1065 public override void visit_initializer_list (InitializerList list
) {
1069 foreach (Expression initializer
in list
.get_initializers ()) {
1071 write_string (", ");
1076 initializer
.accept (this
);
1078 write_string (" }");
1081 public override void visit_expression_statement (ExpressionStatement stmt
) {
1083 stmt
.expression
.accept (this
);
1088 public override void visit_if_statement (IfStatement stmt
) {
1090 write_string ("if (");
1091 stmt
.condition
.accept (this
);
1093 stmt
.true_statement
.accept (this
);
1094 if (stmt
.false_statement
!= null) {
1095 write_string (" else");
1096 stmt
.false_statement
.accept (this
);
1101 public override void visit_switch_statement (SwitchStatement stmt
) {
1103 write_string ("switch (");
1104 stmt
.expression
.accept (this
);
1105 write_string (") {");
1108 foreach (SwitchSection section
in stmt
.get_sections ()) {
1109 section
.accept (this
);
1117 public override void visit_switch_section (SwitchSection section
) {
1118 foreach (SwitchLabel label
in section
.get_labels ()) {
1119 label
.accept (this
);
1122 visit_block (section
);
1125 public override void visit_switch_label (SwitchLabel label
) {
1126 if (label
.expression
!= null) {
1128 write_string ("case ");
1129 label
.expression
.accept (this
);
1134 write_string ("default:");
1139 public override void visit_while_statement (WhileStatement stmt
) {
1141 write_string ("while (");
1142 stmt
.condition
.accept (this
);
1144 stmt
.body
.accept (this
);
1148 public override void visit_do_statement (DoStatement stmt
) {
1150 write_string ("do");
1151 stmt
.body
.accept (this
);
1152 write_string ("while (");
1153 stmt
.condition
.accept (this
);
1154 write_string (");");
1158 public override void visit_for_statement (ForStatement stmt
) {
1160 write_string ("for (");
1163 foreach (Expression initializer
in stmt
.get_initializer ()) {
1165 write_string (", ");
1168 initializer
.accept (this
);
1170 write_string ("; ");
1172 stmt
.condition
.accept (this
);
1173 write_string ("; ");
1176 foreach (Expression iterator
in stmt
.get_iterator ()) {
1178 write_string (", ");
1181 iterator
.accept (this
);
1185 stmt
.body
.accept (this
);
1189 public override void visit_foreach_statement (ForeachStatement stmt
) {
1192 public override void visit_break_statement (BreakStatement stmt
) {
1194 write_string ("break;");
1198 public override void visit_continue_statement (ContinueStatement stmt
) {
1200 write_string ("continue;");
1204 public override void visit_return_statement (ReturnStatement stmt
) {
1206 write_string ("return");
1207 if (stmt
.return_expression
!= null) {
1209 stmt
.return_expression
.accept (this
);
1215 public override void visit_yield_statement (YieldStatement y
) {
1217 write_string ("yield");
1218 if (y
.yield_expression
!= null) {
1220 y
.yield_expression
.accept (this
);
1226 public override void visit_throw_statement (ThrowStatement stmt
) {
1228 write_string ("throw");
1229 if (stmt
.error_expression
!= null) {
1231 stmt
.error_expression
.accept (this
);
1237 public override void visit_try_statement (TryStatement stmt
) {
1239 write_string ("try");
1240 stmt
.body
.accept (this
);
1244 public override void visit_catch_clause (CatchClause clause
) {
1247 public override void visit_lock_statement (LockStatement stmt
) {
1250 public override void visit_delete_statement (DeleteStatement stmt
) {
1253 public override void visit_array_creation_expression (ArrayCreationExpression expr
) {
1254 write_string ("new ");
1255 write_type (expr
.element_type
);
1259 foreach (Expression size
in expr
.get_sizes ()) {
1261 write_string (", ");
1270 if (expr
.initializer_list
!= null) {
1272 expr
.initializer_list
.accept (this
);
1276 public override void visit_boolean_literal (BooleanLiteral lit
) {
1277 write_string (lit
.value
.to_string ());
1280 public override void visit_character_literal (CharacterLiteral lit
) {
1281 write_string (lit
.value
);
1284 public override void visit_integer_literal (IntegerLiteral lit
) {
1285 write_string (lit
.value
);
1288 public override void visit_real_literal (RealLiteral lit
) {
1289 write_string (lit
.value
);
1292 public override void visit_string_literal (StringLiteral lit
) {
1293 write_string (lit
.value
);
1296 public override void visit_null_literal (NullLiteral lit
) {
1297 write_string ("null");
1300 public override void visit_member_access (MemberAccess expr
) {
1301 if (expr
.inner
!= null) {
1302 expr
.inner
.accept (this
);
1305 write_identifier (expr
.member_name
);
1308 public override void visit_method_call (MethodCall expr
) {
1309 expr
.call
.accept (this
);
1310 write_string (" (");
1313 foreach (Expression arg
in expr
.get_argument_list ()) {
1315 write_string (", ");
1325 public override void visit_element_access (ElementAccess expr
) {
1326 expr
.container
.accept (this
);
1330 foreach (Expression index
in expr
.get_indices ()) {
1332 write_string (", ");
1336 index
.accept (this
);
1342 public override void visit_base_access (BaseAccess expr
) {
1343 write_string ("base");
1346 public override void visit_postfix_expression (PostfixExpression expr
) {
1347 expr
.inner
.accept (this
);
1348 if (expr
.increment
) {
1349 write_string ("++");
1351 write_string ("--");
1355 public override void visit_object_creation_expression (ObjectCreationExpression expr
) {
1356 write_string ("new ");
1357 write_type (expr
.type_reference
);
1358 write_string (" (");
1361 foreach (Expression arg
in expr
.get_argument_list ()) {
1363 write_string (", ");
1373 public override void visit_sizeof_expression (SizeofExpression expr
) {
1374 write_string ("sizeof (");
1375 write_type (expr
.type_reference
);
1379 public override void visit_typeof_expression (TypeofExpression expr
) {
1380 write_string ("typeof (");
1381 write_type (expr
.type_reference
);
1385 public override void visit_unary_expression (UnaryExpression expr
) {
1386 switch (expr
.operator
) {
1387 case UnaryOperator
.PLUS
:
1390 case UnaryOperator
.MINUS
:
1393 case UnaryOperator
.LOGICAL_NEGATION
:
1396 case UnaryOperator
.BITWISE_COMPLEMENT
:
1399 case UnaryOperator
.INCREMENT
:
1400 write_string ("++");
1402 case UnaryOperator
.DECREMENT
:
1403 write_string ("--");
1405 case UnaryOperator
.REF
:
1406 write_string ("ref ");
1408 case UnaryOperator
.OUT
:
1409 write_string ("out ");
1412 assert_not_reached ();
1414 expr
.inner
.accept (this
);
1417 public override void visit_cast_expression (CastExpression expr
) {
1418 if (!expr
.is_silent_cast
) {
1420 write_type (expr
.type_reference
);
1421 write_string (") ");
1424 expr
.inner
.accept (this
);
1426 if (expr
.is_silent_cast
) {
1427 write_string (" as ");
1428 write_type (expr
.type_reference
);
1432 public override void visit_pointer_indirection (PointerIndirection expr
) {
1434 expr
.inner
.accept (this
);
1437 public override void visit_addressof_expression (AddressofExpression expr
) {
1439 expr
.inner
.accept (this
);
1442 public override void visit_reference_transfer_expression (ReferenceTransferExpression expr
) {
1443 write_string ("(owned) ");
1444 expr
.inner
.accept (this
);
1447 public override void visit_binary_expression (BinaryExpression expr
) {
1448 expr
.left
.accept (this
);
1450 switch (expr
.operator
) {
1451 case BinaryOperator
.PLUS
:
1452 write_string (" + ");
1454 case BinaryOperator
.MINUS
:
1455 write_string (" - ");
1457 case BinaryOperator
.MUL
:
1458 write_string (" * ");
1460 case BinaryOperator
.DIV
:
1461 write_string (" / ");
1463 case BinaryOperator
.MOD
:
1464 write_string (" % ");
1466 case BinaryOperator
.SHIFT_LEFT
:
1467 write_string (" << ");
1469 case BinaryOperator
.SHIFT_RIGHT
:
1470 write_string (" >> ");
1472 case BinaryOperator
.LESS_THAN
:
1473 write_string (" < ");
1475 case BinaryOperator
.GREATER_THAN
:
1476 write_string (" > ");
1478 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
1479 write_string (" <= ");
1481 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
1482 write_string (" >= ");
1484 case BinaryOperator
.EQUALITY
:
1485 write_string (" == ");
1487 case BinaryOperator
.INEQUALITY
:
1488 write_string (" != ");
1490 case BinaryOperator
.BITWISE_AND
:
1491 write_string (" & ");
1493 case BinaryOperator
.BITWISE_OR
:
1494 write_string (" | ");
1496 case BinaryOperator
.BITWISE_XOR
:
1497 write_string (" ^ ");
1499 case BinaryOperator
.AND
:
1500 write_string (" && ");
1502 case BinaryOperator
.OR
:
1503 write_string (" || ");
1505 case BinaryOperator
.IN
:
1506 write_string (" in ");
1509 assert_not_reached ();
1512 expr
.right
.accept (this
);
1515 public override void visit_type_check (TypeCheck expr
) {
1516 expr
.expression
.accept (this
);
1517 write_string (" is ");
1518 write_type (expr
.type_reference
);
1521 public override void visit_conditional_expression (ConditionalExpression expr
) {
1522 expr
.condition
.accept (this
);
1524 expr
.true_expression
.accept (this
);
1526 expr
.false_expression
.accept (this
);
1529 public override void visit_lambda_expression (LambdaExpression expr
) {
1532 public override void visit_assignment (Assignment a
) {
1533 a
.left
.accept (this
);
1534 write_string (" = ");
1535 a
.right
.accept (this
);
1538 private void write_indent () {
1545 for (i
= 0; i
< indent
; i
++) {
1552 private void write_identifier (string s
) {
1553 if (s
== "base" || s
== "break" || s
== "class" ||
1554 s
== "construct" || s
== "delegate" || s
== "delete" ||
1555 s
== "do" || s
== "dynamic" || s
== "foreach" || s
== "in" ||
1556 s
== "interface" || s
== "lock" || s
== "namespace" ||
1557 s
== "new" || s
== "out" || s
== "ref" ||
1558 s
== "signal" || s
.get_char ().isdigit ()) {
1564 private void write_return_type (DataType type
) {
1565 if (is_weak (type
)) {
1566 write_string ("unowned ");
1572 private bool is_weak (DataType type
) {
1573 if (type
.value_owned
) {
1575 } else if (type is VoidType
|| type is PointerType
) {
1577 } else if (type is ValueType
) {
1578 if (type
.nullable
) {
1579 // nullable structs are heap allocated
1583 // TODO return true for structs with destroy
1590 private void write_type (DataType type
) {
1591 write_string (type
.to_qualified_string (current_scope
));
1594 private void write_string (string s
) {
1595 stream
.printf ("%s", s
);
1599 private void write_newline () {
1604 void write_code_block (Block? block
) {
1605 if (block
== null || !dump_tree
) {
1610 block
.accept (this
);
1613 private void write_begin_block () {
1624 private void write_end_block () {
1627 stream
.printf ("}");
1630 private bool check_accessibility (Symbol sym
) {
1632 sym
.access
== SymbolAccessibility
.PUBLIC
||
1633 sym
.access
== SymbolAccessibility
.PROTECTED
) {
1640 private void write_accessibility (Symbol sym
) {
1641 if (sym
.access
== SymbolAccessibility
.PUBLIC
) {
1642 write_string ("public ");
1643 } else if (sym
.access
== SymbolAccessibility
.PROTECTED
) {
1644 write_string ("protected ");
1645 } else if (sym
.access
== SymbolAccessibility
.INTERNAL
) {
1646 write_string ("internal ");
1647 } else if (sym
.access
== SymbolAccessibility
.PRIVATE
) {
1648 write_string ("private ");