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_types ());
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 ()));
139 if (cl
.base_class
== null || cl
.base_class
.get_unref_function () == null || cl
.base_class
.get_unref_function () != cl
.get_unref_function ()) {
140 write_string ("unref_function = \"%s\", ".printf (cl
.get_unref_function ()));
143 if (cl
.get_dup_function () != null) {
144 write_string ("copy_function = \"%s\", ".printf (cl
.get_dup_function ()));
146 if (cl
.get_free_function () != cl
.get_default_free_function ()) {
147 write_string ("free_function = \"%s\", ".printf (cl
.get_free_function ()));
151 if (cl
.get_cname () != cl
.get_default_cname ()) {
152 write_string ("cname = \"%s\", ".printf (cl
.get_cname ()));
155 if (cl
.type_check_function
!= null) {
156 write_string ("type_check_function = \"%s\", ".printf (cl
.type_check_function
));
159 if (cl
.get_param_spec_function () != null
160 && (cl
.base_class
== null || cl
.get_param_spec_function () != cl
.base_class
.get_param_spec_function ())) {
161 write_string ("param_spec_function = \"%s\", ".printf (cl
.get_param_spec_function ()));
165 string cheaders
= "";
166 foreach (string cheader
in cl
.get_cheader_filenames ()) {
171 cheaders
= "%s,%s".printf (cheaders
, cheader
);
174 write_string ("cheader_filename = \"%s\")]".printf (cheaders
));
178 write_accessibility (cl
);
179 if (cl
.is_abstract
) {
180 write_string ("abstract ");
182 write_string ("class ");
183 write_identifier (cl
.name
);
185 var type_params
= cl
.get_type_parameters ();
186 if (type_params
.size
> 0) {
189 foreach (TypeParameter type_param
in type_params
) {
195 write_identifier (type_param
.name
);
200 var base_types
= cl
.get_base_types ();
201 if (base_types
.size
> 0) {
202 write_string (" : ");
205 foreach (DataType base_type
in base_types
) {
211 write_type (base_type
);
214 write_begin_block ();
216 current_scope
= cl
.scope
;
218 visit_sorted (cl
.get_classes ());
219 visit_sorted (cl
.get_structs ());
220 visit_sorted (cl
.get_enums ());
221 visit_sorted (cl
.get_delegates ());
222 visit_sorted (cl
.get_fields ());
223 visit_sorted (cl
.get_constants ());
224 visit_sorted (cl
.get_methods ());
225 visit_sorted (cl
.get_properties ());
226 visit_sorted (cl
.get_signals ());
228 current_scope
= current_scope
.parent_scope
;
234 void visit_sorted (Gee
.List
<Symbol
> symbols
) {
235 var sorted_symbols
= new Gee
.ArrayList
<Symbol
> ();
236 foreach (Symbol sym
in symbols
) {
238 int right
= sorted_symbols
.size
- 1;
239 if (left
> right
|| sym
.name
< sorted_symbols
[left
].name
) {
240 sorted_symbols
.insert (0, sym
);
241 } else if (sym
.name
> sorted_symbols
[right
].name
) {
242 sorted_symbols
.add (sym
);
244 while (right
- left
> 1) {
245 int i
= (right
+ left
) / 2;
246 if (sym
.name
> sorted_symbols
[i
].name
) {
252 sorted_symbols
.insert (left
+ 1, sym
);
255 foreach (Symbol sym
in sorted_symbols
) {
260 public override void visit_struct (Struct st
) {
261 if (st
.external_package
) {
265 if (!check_accessibility (st
)) {
271 write_string ("[CCode (");
273 if (st
.get_cname () != st
.get_default_cname ()) {
274 write_string ("cname = \"%s\", ".printf (st
.get_cname ()));
277 if (!st
.is_simple_type () && st
.get_type_id () != "G_TYPE_POINTER") {
278 write_string ("type_id = \"%s\", ".printf (st
.get_type_id ()));
282 string cheaders
= "";
283 foreach (string cheader
in st
.get_cheader_filenames ()) {
288 cheaders
= "%s,%s".printf (cheaders
, cheader
);
291 write_string ("cheader_filename = \"%s\")]".printf (cheaders
));
294 if (st
.is_simple_type ()) {
296 write_string ("[SimpleType]");
300 if (st
.is_integer_type ()) {
302 write_string ("[IntegerType (rank = %d)]".printf (st
.get_rank ()));
306 if (st
.is_floating_type ()) {
308 write_string ("[FloatingType (rank = %d)]".printf (st
.get_rank ()));
313 write_accessibility (st
);
314 write_string ("struct ");
315 write_identifier (st
.name
);
317 var base_types
= st
.get_base_types ();
318 if (base_types
.size
> 0) {
319 write_string (" : ");
322 foreach (DataType base_type
in base_types
) {
328 write_type (base_type
);
332 write_begin_block ();
334 current_scope
= st
.scope
;
336 foreach (Field field
in st
.get_fields ()) {
339 visit_sorted (st
.get_constants ());
340 visit_sorted (st
.get_methods ());
342 current_scope
= current_scope
.parent_scope
;
348 public override void visit_interface (Interface iface
) {
349 if (iface
.external_package
) {
353 if (!check_accessibility (iface
)) {
360 string cheaders
= "";
361 foreach (string cheader
in iface
.get_cheader_filenames ()) {
366 cheaders
= "%s,%s".printf (cheaders
, cheader
);
369 write_string ("[CCode (cheader_filename = \"%s\"".printf (cheaders
));
370 if (iface
.get_lower_case_csuffix () != iface
.get_default_lower_case_csuffix ())
371 write_string (", lower_case_csuffix = \"%s\"".printf (iface
.get_lower_case_csuffix ()));
377 write_accessibility (iface
);
378 write_string ("interface ");
379 write_identifier (iface
.name
);
381 var type_params
= iface
.get_type_parameters ();
382 if (type_params
.size
> 0) {
385 foreach (TypeParameter type_param
in type_params
) {
391 write_identifier (type_param
.name
);
396 var prerequisites
= iface
.get_prerequisites ();
397 if (prerequisites
.size
> 0) {
398 write_string (" : ");
401 foreach (DataType prerequisite
in prerequisites
) {
407 write_type (prerequisite
);
410 write_begin_block ();
412 current_scope
= iface
.scope
;
414 visit_sorted (iface
.get_classes ());
415 visit_sorted (iface
.get_structs ());
416 visit_sorted (iface
.get_enums ());
417 visit_sorted (iface
.get_delegates ());
418 visit_sorted (iface
.get_fields ());
419 visit_sorted (iface
.get_methods ());
420 visit_sorted (iface
.get_properties ());
421 visit_sorted (iface
.get_signals ());
423 current_scope
= current_scope
.parent_scope
;
429 public override void visit_enum (Enum en
) {
430 if (en
.external_package
) {
434 if (!check_accessibility (en
)) {
441 string cheaders
= "";
442 foreach (string cheader
in en
.get_cheader_filenames ()) {
447 cheaders
= "%s,%s".printf (cheaders
, cheader
);
451 write_string ("[CCode (cprefix = \"%s\", ".printf (en
.get_cprefix ()));
453 if (!en
.has_type_id
) {
454 write_string ("has_type_id = \"%d\", ".printf (en
.has_type_id ?
1 : 0));
457 write_string ("cheader_filename = \"%s\")]".printf (cheaders
));
461 write_string ("[Flags]");
465 write_accessibility (en
);
466 write_string ("enum ");
467 write_identifier (en
.name
);
468 write_begin_block ();
471 foreach (EnumValue ev
in en
.get_values ()) {
479 if (ev
.get_cname () != ev
.get_default_cname ()) {
481 write_string ("[CCode (cname = \"%s\")]".printf (ev
.get_cname ()));
484 write_identifier (ev
.name
);
488 if (en
.get_methods ().size
> 0) {
494 current_scope
= en
.scope
;
495 foreach (Method m
in en
.get_methods ()) {
498 current_scope
= current_scope
.parent_scope
;
504 public override void visit_error_domain (ErrorDomain edomain
) {
505 if (edomain
.external_package
) {
509 if (!check_accessibility (edomain
)) {
516 string cheaders
= "";
517 foreach (string cheader
in edomain
.get_cheader_filenames ()) {
522 cheaders
= "%s,%s".printf (cheaders
, cheader
);
525 write_string ("[CCode (cprefix = \"%s\", cheader_filename = \"%s\")]".printf (edomain
.get_cprefix (), cheaders
));
528 write_accessibility (edomain
);
529 write_string ("errordomain ");
530 write_identifier (edomain
.name
);
531 write_begin_block ();
533 edomain
.accept_children (this
);
539 public override void visit_error_code (ErrorCode ecode
) {
541 write_identifier (ecode
.name
);
546 public override void visit_constant (Constant c
) {
547 if (c
.external_package
) {
551 if (!check_accessibility (c
)) {
555 bool custom_cname
= (c
.get_cname () != c
.get_default_cname ());
556 bool custom_cheaders
= (c
.parent_symbol is Namespace
);
557 if (custom_cname
|| custom_cheaders
) {
559 write_string ("[CCode (");
562 write_string ("cname = \"%s\"".printf (c
.get_cname ()));
565 if (custom_cheaders
) {
571 string cheaders
= "";
572 foreach (string cheader
in c
.get_cheader_filenames ()) {
577 cheaders
= "%s,%s".printf (cheaders
, cheader
);
580 write_string ("cheader_filename = \"%s\"".printf (cheaders
));
587 write_accessibility (c
);
588 write_string ("const ");
590 write_type (c
.type_reference
);
593 write_identifier (c
.name
);
598 public override void visit_field (Field f
) {
599 if (f
.external_package
) {
603 if (!check_accessibility (f
)) {
607 bool custom_cname
= (f
.get_cname () != f
.get_default_cname ());
608 bool custom_ctype
= (f
.get_ctype () != null);
609 bool custom_cheaders
= (f
.parent_symbol is Namespace
);
610 if (custom_cname
|| custom_ctype
|| custom_cheaders
|| (f
.no_array_length
&& f
.field_type is ArrayType
)) {
612 write_string ("[CCode (");
615 write_string ("cname = \"%s\"".printf (f
.get_cname ()));
623 write_string ("type = \"%s\"".printf (f
.get_ctype ()));
626 if (custom_cheaders
) {
627 if (custom_cname
|| custom_ctype
) {
632 string cheaders
= "";
633 foreach (string cheader
in f
.get_cheader_filenames ()) {
638 cheaders
= "%s,%s".printf (cheaders
, cheader
);
641 write_string ("cheader_filename = \"%s\"".printf (cheaders
));
644 if (f
.no_array_length
&& f
.field_type is ArrayType
) {
645 if (custom_cname
|| custom_ctype
|| custom_cheaders
) {
649 write_string ("array_length = false");
656 write_accessibility (f
);
658 if (f
.binding
== MemberBinding
.STATIC
) {
659 write_string ("static ");
660 } else if (f
.binding
== MemberBinding
.CLASS
) {
661 write_string ("class ");
664 if (is_weak (f
.field_type
)) {
665 write_string ("weak ");
668 write_type (f
.field_type
);
671 write_identifier (f
.name
);
676 private void write_error_domains (Gee
.List
<DataType
> error_domains
) {
677 if (error_domains
.size
> 0) {
678 write_string (" throws ");
681 foreach (DataType type
in error_domains
) {
693 // equality comparison with 3 digit precision
694 private bool float_equal (double d1
, double d2
) {
695 return ((int) (d1
* 1000)) == ((int) (d2
* 1000));
698 private void write_params (Gee
.List
<FormalParameter
> params
) {
702 foreach (FormalParameter param
in params
) {
707 if (param
.ellipsis
) {
708 write_string ("...");
713 var ccode_params
= new
StringBuilder ();
716 if (param
.ctype
!= null) {
717 ccode_params
.append_printf ("%stype = \"%s\"", separator
, param
.ctype
);
720 if (param
.no_array_length
&& param
.parameter_type is ArrayType
) {
721 ccode_params
.append_printf ("%sarray_length = false", separator
);
724 if (!float_equal (param
.carray_length_parameter_position
, i
+ 0.1)) {
725 ccode_params
.append_printf ("%sarray_length_pos = %g", separator
, param
.carray_length_parameter_position
);
728 if (!float_equal (param
.cdelegate_target_parameter_position
, i
+ 0.1)) {
729 ccode_params
.append_printf ("%sdelegate_target_pos = %g", separator
, param
.cdelegate_target_parameter_position
);
733 if (ccode_params
.len
> 0) {
734 write_string ("[CCode (%s)] ".printf (ccode_params
.str
));
737 if (param
.params_array
) {
738 write_string ("params ");
741 if (param
.direction
== ParameterDirection
.IN
) {
742 if (param
.parameter_type
.value_owned
) {
743 write_string ("owned ");
746 if (param
.direction
== ParameterDirection
.REF
) {
747 write_string ("ref ");
748 } else if (param
.direction
== ParameterDirection
.OUT
) {
749 write_string ("out ");
751 if (is_weak (param
.parameter_type
)) {
752 write_string ("unowned ");
756 write_type (param
.parameter_type
);
759 write_identifier (param
.name
);
761 if (param
.default_expression
!= null) {
762 write_string (" = ");
763 write_string (param
.default_expression
.to_string ());
772 public override void visit_delegate (Delegate cb
) {
773 if (cb
.external_package
) {
777 if (!check_accessibility (cb
)) {
784 string cheaders
= "";
785 foreach (string cheader
in cb
.get_cheader_filenames ()) {
790 cheaders
= "%s,%s".printf (cheaders
, cheader
);
793 write_string ("[CCode (cheader_filename = \"%s\")]".printf (cheaders
));
797 write_accessibility (cb
);
798 if (!cb
.has_target
) {
799 write_string ("static ");
801 write_string ("delegate ");
803 write_return_type (cb
.return_type
);
806 write_identifier (cb
.name
);
810 write_params (cb
.get_parameters ());
817 public override void visit_method (Method m
) {
818 if (m
.external_package
) {
822 // don't write interface implementation unless it's an abstract or virtual method
823 if (!check_accessibility (m
) || m
.overrides
|| (m
.base_interface_method
!= null && !m
.is_abstract
&& !m
.is_virtual
)) {
829 if (m
.get_attribute ("NoWrapper") != null) {
831 write_string ("[NoWrapper]");
833 if (m
.returns_modified_pointer
) {
835 write_string ("[ReturnsModifiedPointer]");
838 var ccode_params
= new
StringBuilder ();
841 if (m
.get_cname () != m
.get_default_cname ()) {
842 ccode_params
.append_printf ("%scname = \"%s\"", separator
, m
.get_cname ());
845 if (m
.parent_symbol is Namespace
) {
847 string cheaders
= "";
848 foreach (string cheader
in m
.get_cheader_filenames ()) {
853 cheaders
= "%s,%s".printf (cheaders
, cheader
);
856 ccode_params
.append_printf ("%scheader_filename = \"%s\"", separator
, cheaders
);
859 if (!float_equal (m
.cinstance_parameter_position
, 0)) {
860 ccode_params
.append_printf ("%sinstance_pos = %g", separator
, m
.cinstance_parameter_position
);
863 if (m
.no_array_length
&& m
.return_type is ArrayType
) {
864 ccode_params
.append_printf ("%sarray_length = false", separator
);
867 if (!float_equal (m
.carray_length_parameter_position
, -3)) {
868 ccode_params
.append_printf ("%sarray_length_pos = %g", separator
, m
.carray_length_parameter_position
);
871 if (m
.array_null_terminated
&& m
.return_type is ArrayType
) {
872 ccode_params
.append_printf ("%sarray_null_terminated = true", separator
);
875 if (!float_equal (m
.cdelegate_target_parameter_position
, -3)) {
876 ccode_params
.append_printf ("%sdelegate_target_pos = %g", separator
, m
.cdelegate_target_parameter_position
);
879 if (m
.sentinel
!= m
.DEFAULT_SENTINEL
) {
880 ccode_params
.append_printf ("%ssentinel = \"%s\"", separator
, m
.sentinel
);
883 if (m is CreationMethod
&& ((CreationMethod
)m
).custom_return_type_cname
!= null) {
884 ccode_params
.append_printf ("%stype = \"%s\"", separator
, ((CreationMethod
)m
).custom_return_type_cname
);
887 if (m is CreationMethod
&& !m
.has_construct_function
) {
888 ccode_params
.append_printf ("%shas_construct_function = false", separator
);
892 if (ccode_params
.len
> 0) {
894 write_string ("[CCode (%s)]".printf (ccode_params
.str
));
898 write_accessibility (m
);
900 if (m is CreationMethod
) {
901 var datatype
= (TypeSymbol
) m
.parent_symbol
;
902 write_identifier (datatype
.name
);
903 if (m
.name
!= "new") {
905 write_identifier (m
.name
);
908 } else if (m
.binding
== MemberBinding
.STATIC
) {
909 write_string ("static ");
910 } else if (m
.binding
== MemberBinding
.CLASS
) {
911 write_string ("class ");
912 } else if (m
.is_abstract
) {
913 write_string ("abstract ");
914 } else if (m
.is_virtual
) {
915 write_string ("virtual ");
918 if (!(m is CreationMethod
)) {
919 write_return_type (m
.return_type
);
922 write_identifier (m
.name
);
926 write_params (m
.get_parameters ());
927 write_error_domains (m
.get_error_types ());
929 write_code_block (m
.body
);
934 public override void visit_creation_method (CreationMethod m
) {
938 public override void visit_property (Property prop
) {
939 if (!check_accessibility (prop
) || prop
.overrides
|| (prop
.base_interface_property
!= null && !prop
.is_abstract
&& !prop
.is_virtual
)) {
943 if (prop
.no_accessor_method
) {
945 write_string ("[NoAccessorMethod]");
949 write_accessibility (prop
);
951 if (prop
.binding
== MemberBinding
.STATIC
) {
952 write_string ("static ");
953 } else if (prop
.is_abstract
) {
954 write_string ("abstract ");
955 } else if (prop
.is_virtual
) {
956 write_string ("virtual ");
959 write_type (prop
.property_type
);
962 write_identifier (prop
.name
);
964 if (prop
.get_accessor
!= null) {
965 if (prop
.get_accessor
.value_type
.is_disposable ()) {
966 write_string (" owned");
969 write_string (" get");
970 write_code_block (prop
.get_accessor
.body
);
972 if (prop
.set_accessor
!= null) {
973 if (prop
.set_accessor
.value_type
.value_owned
) {
974 write_string ("owned ");
977 if (prop
.set_accessor
.writable
) {
978 write_string (" set");
980 if (prop
.set_accessor
.construction
) {
981 write_string (" construct");
983 write_code_block (prop
.set_accessor
.body
);
989 public override void visit_signal (Signal sig
) {
990 if (!check_accessibility (sig
)) {
994 if (sig
.has_emitter
) {
996 write_string ("[HasEmitter]");
1000 write_accessibility (sig
);
1002 if (sig
.is_virtual
) {
1003 write_string ("virtual ");
1006 write_string ("signal ");
1008 write_return_type (sig
.return_type
);
1011 write_identifier (sig
.name
);
1015 write_params (sig
.get_parameters ());
1022 public override void visit_block (Block b
) {
1023 write_begin_block ();
1025 foreach (Statement stmt
in b
.get_statements ()) {
1032 public override void visit_empty_statement (EmptyStatement stmt
) {
1035 public override void visit_declaration_statement (DeclarationStatement stmt
) {
1037 stmt
.declaration
.accept (this
);
1042 public override void visit_local_variable (LocalVariable local
) {
1043 write_type (local
.variable_type
);
1045 write_identifier (local
.name
);
1046 if (local
.initializer
!= null) {
1047 write_string (" = ");
1048 local
.initializer
.accept (this
);
1052 public override void visit_initializer_list (InitializerList list
) {
1056 foreach (Expression initializer
in list
.get_initializers ()) {
1058 write_string (", ");
1063 initializer
.accept (this
);
1065 write_string (" }");
1068 public override void visit_expression_statement (ExpressionStatement stmt
) {
1070 stmt
.expression
.accept (this
);
1075 public override void visit_if_statement (IfStatement stmt
) {
1077 write_string ("if (");
1078 stmt
.condition
.accept (this
);
1080 stmt
.true_statement
.accept (this
);
1081 if (stmt
.false_statement
!= null) {
1082 write_string (" else");
1083 stmt
.false_statement
.accept (this
);
1088 public override void visit_switch_statement (SwitchStatement stmt
) {
1090 write_string ("switch (");
1091 stmt
.expression
.accept (this
);
1092 write_string (") {");
1095 foreach (SwitchSection section
in stmt
.get_sections ()) {
1096 section
.accept (this
);
1104 public override void visit_switch_section (SwitchSection section
) {
1105 foreach (SwitchLabel label
in section
.get_labels ()) {
1106 label
.accept (this
);
1109 visit_block (section
);
1112 public override void visit_switch_label (SwitchLabel label
) {
1113 if (label
.expression
!= null) {
1115 write_string ("case ");
1116 label
.expression
.accept (this
);
1121 write_string ("default:");
1126 public override void visit_while_statement (WhileStatement stmt
) {
1128 write_string ("while (");
1129 stmt
.condition
.accept (this
);
1131 stmt
.body
.accept (this
);
1135 public override void visit_do_statement (DoStatement stmt
) {
1137 write_string ("do");
1138 stmt
.body
.accept (this
);
1139 write_string ("while (");
1140 stmt
.condition
.accept (this
);
1141 write_string (");");
1145 public override void visit_for_statement (ForStatement stmt
) {
1147 write_string ("for (");
1150 foreach (Expression initializer
in stmt
.get_initializer ()) {
1152 write_string (", ");
1155 initializer
.accept (this
);
1157 write_string ("; ");
1159 stmt
.condition
.accept (this
);
1160 write_string ("; ");
1163 foreach (Expression iterator
in stmt
.get_iterator ()) {
1165 write_string (", ");
1168 iterator
.accept (this
);
1172 stmt
.body
.accept (this
);
1176 public override void visit_foreach_statement (ForeachStatement stmt
) {
1179 public override void visit_break_statement (BreakStatement stmt
) {
1181 write_string ("break;");
1185 public override void visit_continue_statement (ContinueStatement stmt
) {
1187 write_string ("continue;");
1191 public override void visit_return_statement (ReturnStatement stmt
) {
1193 write_string ("return");
1194 if (stmt
.return_expression
!= null) {
1196 stmt
.return_expression
.accept (this
);
1202 public override void visit_yield_statement (YieldStatement y
) {
1204 write_string ("yield");
1205 if (y
.yield_expression
!= null) {
1207 y
.yield_expression
.accept (this
);
1213 public override void visit_throw_statement (ThrowStatement stmt
) {
1215 write_string ("throw");
1216 if (stmt
.error_expression
!= null) {
1218 stmt
.error_expression
.accept (this
);
1224 public override void visit_try_statement (TryStatement stmt
) {
1226 write_string ("try");
1227 stmt
.body
.accept (this
);
1231 public override void visit_catch_clause (CatchClause clause
) {
1234 public override void visit_lock_statement (LockStatement stmt
) {
1237 public override void visit_delete_statement (DeleteStatement stmt
) {
1240 public override void visit_array_creation_expression (ArrayCreationExpression expr
) {
1241 write_string ("new ");
1242 write_type (expr
.element_type
);
1246 foreach (Expression size
in expr
.get_sizes ()) {
1248 write_string (", ");
1257 if (expr
.initializer_list
!= null) {
1259 expr
.initializer_list
.accept (this
);
1263 public override void visit_boolean_literal (BooleanLiteral lit
) {
1264 write_string (lit
.value
.to_string ());
1267 public override void visit_character_literal (CharacterLiteral lit
) {
1268 write_string (lit
.value
);
1271 public override void visit_integer_literal (IntegerLiteral lit
) {
1272 write_string (lit
.value
);
1275 public override void visit_real_literal (RealLiteral lit
) {
1276 write_string (lit
.value
);
1279 public override void visit_string_literal (StringLiteral lit
) {
1280 write_string (lit
.value
);
1283 public override void visit_null_literal (NullLiteral lit
) {
1284 write_string ("null");
1287 public override void visit_parenthesized_expression (ParenthesizedExpression expr
) {
1289 expr
.inner
.accept (this
);
1293 public override void visit_member_access (MemberAccess expr
) {
1294 if (expr
.inner
!= null) {
1295 expr
.inner
.accept (this
);
1298 write_identifier (expr
.member_name
);
1301 public override void visit_method_call (MethodCall expr
) {
1302 expr
.call
.accept (this
);
1303 write_string (" (");
1306 foreach (Expression arg
in expr
.get_argument_list ()) {
1308 write_string (", ");
1318 public override void visit_element_access (ElementAccess expr
) {
1319 expr
.container
.accept (this
);
1323 foreach (Expression index
in expr
.get_indices ()) {
1325 write_string (", ");
1329 index
.accept (this
);
1335 public override void visit_base_access (BaseAccess expr
) {
1336 write_string ("base");
1339 public override void visit_postfix_expression (PostfixExpression expr
) {
1340 expr
.inner
.accept (this
);
1341 if (expr
.increment
) {
1342 write_string ("++");
1344 write_string ("--");
1348 public override void visit_object_creation_expression (ObjectCreationExpression expr
) {
1349 write_string ("new ");
1350 write_type (expr
.type_reference
);
1351 write_string (" (");
1354 foreach (Expression arg
in expr
.get_argument_list ()) {
1356 write_string (", ");
1366 public override void visit_sizeof_expression (SizeofExpression expr
) {
1367 write_string ("sizeof (");
1368 write_type (expr
.type_reference
);
1372 public override void visit_typeof_expression (TypeofExpression expr
) {
1373 write_string ("typeof (");
1374 write_type (expr
.type_reference
);
1378 public override void visit_unary_expression (UnaryExpression expr
) {
1379 switch (expr
.operator
) {
1380 case UnaryOperator
.PLUS
:
1383 case UnaryOperator
.MINUS
:
1386 case UnaryOperator
.LOGICAL_NEGATION
:
1389 case UnaryOperator
.BITWISE_COMPLEMENT
:
1392 case UnaryOperator
.INCREMENT
:
1393 write_string ("++");
1395 case UnaryOperator
.DECREMENT
:
1396 write_string ("--");
1398 case UnaryOperator
.REF
:
1399 write_string ("ref ");
1401 case UnaryOperator
.OUT
:
1402 write_string ("out ");
1405 assert_not_reached ();
1407 expr
.inner
.accept (this
);
1410 public override void visit_cast_expression (CastExpression expr
) {
1411 if (!expr
.is_silent_cast
) {
1413 write_type (expr
.type_reference
);
1414 write_string (") ");
1417 expr
.inner
.accept (this
);
1419 if (expr
.is_silent_cast
) {
1420 write_string (" as ");
1421 write_type (expr
.type_reference
);
1425 public override void visit_pointer_indirection (PointerIndirection expr
) {
1427 expr
.inner
.accept (this
);
1430 public override void visit_addressof_expression (AddressofExpression expr
) {
1432 expr
.inner
.accept (this
);
1435 public override void visit_reference_transfer_expression (ReferenceTransferExpression expr
) {
1436 write_string ("(owned) ");
1437 expr
.inner
.accept (this
);
1440 public override void visit_binary_expression (BinaryExpression expr
) {
1441 expr
.left
.accept (this
);
1443 switch (expr
.operator
) {
1444 case BinaryOperator
.PLUS
:
1445 write_string (" + ");
1447 case BinaryOperator
.MINUS
:
1448 write_string (" - ");
1450 case BinaryOperator
.MUL
:
1451 write_string (" * ");
1453 case BinaryOperator
.DIV
:
1454 write_string (" / ");
1456 case BinaryOperator
.MOD
:
1457 write_string (" % ");
1459 case BinaryOperator
.SHIFT_LEFT
:
1460 write_string (" << ");
1462 case BinaryOperator
.SHIFT_RIGHT
:
1463 write_string (" >> ");
1465 case BinaryOperator
.LESS_THAN
:
1466 write_string (" < ");
1468 case BinaryOperator
.GREATER_THAN
:
1469 write_string (" > ");
1471 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
1472 write_string (" <= ");
1474 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
1475 write_string (" >= ");
1477 case BinaryOperator
.EQUALITY
:
1478 write_string (" == ");
1480 case BinaryOperator
.INEQUALITY
:
1481 write_string (" != ");
1483 case BinaryOperator
.BITWISE_AND
:
1484 write_string (" & ");
1486 case BinaryOperator
.BITWISE_OR
:
1487 write_string (" | ");
1489 case BinaryOperator
.BITWISE_XOR
:
1490 write_string (" ^ ");
1492 case BinaryOperator
.AND
:
1493 write_string (" && ");
1495 case BinaryOperator
.OR
:
1496 write_string (" || ");
1498 case BinaryOperator
.IN
:
1499 write_string (" in ");
1502 assert_not_reached ();
1505 expr
.right
.accept (this
);
1508 public override void visit_type_check (TypeCheck expr
) {
1509 expr
.expression
.accept (this
);
1510 write_string (" is ");
1511 write_type (expr
.type_reference
);
1514 public override void visit_conditional_expression (ConditionalExpression expr
) {
1515 expr
.condition
.accept (this
);
1517 expr
.true_expression
.accept (this
);
1519 expr
.false_expression
.accept (this
);
1522 public override void visit_lambda_expression (LambdaExpression expr
) {
1525 public override void visit_assignment (Assignment a
) {
1526 a
.left
.accept (this
);
1527 write_string (" = ");
1528 a
.right
.accept (this
);
1531 private void write_indent () {
1538 for (i
= 0; i
< indent
; i
++) {
1545 private void write_identifier (string s
) {
1546 if (s
== "base" || s
== "break" || s
== "class" ||
1547 s
== "construct" || s
== "delegate" || s
== "delete" ||
1548 s
== "do" || s
== "foreach" || s
== "in" ||
1549 s
== "interface" || s
== "lock" || s
== "namespace" ||
1550 s
== "new" || s
== "out" || s
== "ref" ||
1557 private void write_return_type (DataType type
) {
1558 if (is_weak (type
)) {
1559 write_string ("unowned ");
1565 private bool is_weak (DataType type
) {
1566 if (type
.value_owned
) {
1568 } else if (type is VoidType
|| type is PointerType
) {
1570 } else if (type is ValueType
) {
1571 if (type
.nullable
) {
1572 // nullable structs are heap allocated
1576 // TODO return true for structs with destroy
1583 private void write_type (DataType type
) {
1584 write_string (type
.to_qualified_string (current_scope
));
1587 private void write_string (string s
) {
1588 stream
.printf ("%s", s
);
1592 private void write_newline () {
1597 void write_code_block (Block? block
) {
1598 if (block
== null || !dump_tree
) {
1603 block
.accept (this
);
1606 private void write_begin_block () {
1617 private void write_end_block () {
1620 stream
.printf ("}");
1623 private bool check_accessibility (Symbol sym
) {
1625 sym
.access
== SymbolAccessibility
.PUBLIC
||
1626 sym
.access
== SymbolAccessibility
.PROTECTED
) {
1633 private void write_accessibility (Symbol sym
) {
1634 if (sym
.access
== SymbolAccessibility
.PUBLIC
) {
1635 write_string ("public ");
1636 } else if (sym
.access
== SymbolAccessibility
.PROTECTED
) {
1637 write_string ("protected ");
1638 } else if (sym
.access
== SymbolAccessibility
.INTERNAL
) {
1639 write_string ("internal ");
1640 } else if (sym
.access
== SymbolAccessibility
.PRIVATE
) {
1641 write_string ("private ");