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 ()));
86 write_attributes (ns
);
89 write_string ("namespace ");
90 write_identifier (ns
.name
);
93 current_scope
= ns
.scope
;
95 visit_sorted (ns
.get_namespaces ());
96 visit_sorted (ns
.get_classes ());
97 visit_sorted (ns
.get_interfaces ());
98 visit_sorted (ns
.get_structs ());
99 visit_sorted (ns
.get_enums ());
100 visit_sorted (ns
.get_error_domains ());
101 visit_sorted (ns
.get_delegates ());
102 visit_sorted (ns
.get_fields ());
103 visit_sorted (ns
.get_constants ());
104 visit_sorted (ns
.get_methods ());
106 current_scope
= current_scope
.parent_scope
;
112 public override void visit_class (Class cl
) {
113 if (cl
.external_package
) {
117 if (!check_accessibility (cl
)) {
123 write_string ("[Compact]");
127 if (cl
.is_immutable
) {
129 write_string ("[Immutable]");
135 write_string ("[CCode (");
137 if (cl
.is_reference_counting ()) {
138 if (cl
.base_class
== null || cl
.base_class
.get_ref_function () == null || cl
.base_class
.get_ref_function () != cl
.get_ref_function ()) {
139 write_string ("ref_function = \"%s\", ".printf (cl
.get_ref_function ()));
140 if (cl
.ref_function_void
) {
141 write_string ("ref_function_void = true, ");
144 if (cl
.base_class
== null || cl
.base_class
.get_unref_function () == null || cl
.base_class
.get_unref_function () != cl
.get_unref_function ()) {
145 write_string ("unref_function = \"%s\", ".printf (cl
.get_unref_function ()));
148 if (cl
.get_dup_function () != null) {
149 write_string ("copy_function = \"%s\", ".printf (cl
.get_dup_function ()));
151 if (cl
.get_free_function () != cl
.get_default_free_function ()) {
152 write_string ("free_function = \"%s\", ".printf (cl
.get_free_function ()));
156 if (cl
.get_cname () != cl
.get_default_cname ()) {
157 write_string ("cname = \"%s\", ".printf (cl
.get_cname ()));
160 if (cl
.type_check_function
!= null) {
161 write_string ("type_check_function = \"%s\", ".printf (cl
.type_check_function
));
164 if (cl
.is_compact
&& cl
.get_type_id () != "G_TYPE_POINTER") {
165 write_string ("type_id = \"%s\", ".printf (cl
.get_type_id ()));
168 if (cl
.get_param_spec_function () != null
169 && (cl
.base_class
== null || cl
.get_param_spec_function () != cl
.base_class
.get_param_spec_function ())) {
170 write_string ("param_spec_function = \"%s\", ".printf (cl
.get_param_spec_function ()));
174 string cheaders
= "";
175 foreach (string cheader
in cl
.get_cheader_filenames ()) {
180 cheaders
= "%s,%s".printf (cheaders
, cheader
);
183 write_string ("cheader_filename = \"%s\")]".printf (cheaders
));
186 write_attributes (cl
);
189 write_accessibility (cl
);
190 if (cl
.is_abstract
) {
191 write_string ("abstract ");
193 write_string ("class ");
194 write_identifier (cl
.name
);
196 var type_params
= cl
.get_type_parameters ();
197 if (type_params
.size
> 0) {
200 foreach (TypeParameter type_param
in type_params
) {
206 write_identifier (type_param
.name
);
211 var base_types
= cl
.get_base_types ();
212 if (base_types
.size
> 0) {
213 write_string (" : ");
216 foreach (DataType base_type
in base_types
) {
222 write_type (base_type
);
225 write_begin_block ();
227 current_scope
= cl
.scope
;
229 visit_sorted (cl
.get_classes ());
230 visit_sorted (cl
.get_structs ());
231 visit_sorted (cl
.get_enums ());
232 visit_sorted (cl
.get_delegates ());
233 visit_sorted (cl
.get_fields ());
234 visit_sorted (cl
.get_constants ());
235 visit_sorted (cl
.get_methods ());
236 visit_sorted (cl
.get_properties ());
237 visit_sorted (cl
.get_signals ());
239 current_scope
= current_scope
.parent_scope
;
245 void visit_sorted (Gee
.List
<Symbol
> symbols
) {
246 var sorted_symbols
= new Gee
.ArrayList
<Symbol
> ();
247 foreach (Symbol sym
in symbols
) {
249 int right
= sorted_symbols
.size
- 1;
250 if (left
> right
|| sym
.name
< sorted_symbols
[left
].name
) {
251 sorted_symbols
.insert (0, sym
);
252 } else if (sym
.name
> sorted_symbols
[right
].name
) {
253 sorted_symbols
.add (sym
);
255 while (right
- left
> 1) {
256 int i
= (right
+ left
) / 2;
257 if (sym
.name
> sorted_symbols
[i
].name
) {
263 sorted_symbols
.insert (left
+ 1, sym
);
266 foreach (Symbol sym
in sorted_symbols
) {
271 public override void visit_struct (Struct st
) {
272 if (st
.external_package
) {
276 if (!check_accessibility (st
)) {
282 write_string ("[CCode (");
284 if (st
.get_cname () != st
.get_default_cname ()) {
285 write_string ("cname = \"%s\", ".printf (st
.get_cname ()));
288 if (!st
.is_simple_type () && st
.get_type_id () != "G_TYPE_POINTER") {
289 write_string ("type_id = \"%s\", ".printf (st
.get_type_id ()));
293 write_string ("use_const = false, ");
297 string cheaders
= "";
298 foreach (string cheader
in st
.get_cheader_filenames ()) {
303 cheaders
= "%s,%s".printf (cheaders
, cheader
);
306 write_string ("cheader_filename = \"%s\")]".printf (cheaders
));
309 if (st
.is_simple_type ()) {
311 write_string ("[SimpleType]");
315 if (st
.is_integer_type ()) {
317 write_string ("[IntegerType (rank = %d)]".printf (st
.get_rank ()));
321 if (st
.is_floating_type ()) {
323 write_string ("[FloatingType (rank = %d)]".printf (st
.get_rank ()));
327 write_attributes (st
);
330 write_accessibility (st
);
331 write_string ("struct ");
332 write_identifier (st
.name
);
334 if (st
.base_type
!= null) {
335 write_string (" : ");
336 write_type (st
.base_type
);
339 write_begin_block ();
341 current_scope
= st
.scope
;
343 foreach (Field field
in st
.get_fields ()) {
346 visit_sorted (st
.get_constants ());
347 visit_sorted (st
.get_methods ());
349 current_scope
= current_scope
.parent_scope
;
355 public override void visit_interface (Interface iface
) {
356 if (iface
.external_package
) {
360 if (!check_accessibility (iface
)) {
367 string cheaders
= "";
368 foreach (string cheader
in iface
.get_cheader_filenames ()) {
373 cheaders
= "%s,%s".printf (cheaders
, cheader
);
376 write_string ("[CCode (cheader_filename = \"%s\"".printf (cheaders
));
377 if (iface
.get_lower_case_csuffix () != iface
.get_default_lower_case_csuffix ())
378 write_string (", lower_case_csuffix = \"%s\"".printf (iface
.get_lower_case_csuffix ()));
383 write_attributes (iface
);
386 write_accessibility (iface
);
387 write_string ("interface ");
388 write_identifier (iface
.name
);
390 var type_params
= iface
.get_type_parameters ();
391 if (type_params
.size
> 0) {
394 foreach (TypeParameter type_param
in type_params
) {
400 write_identifier (type_param
.name
);
405 var prerequisites
= iface
.get_prerequisites ();
406 if (prerequisites
.size
> 0) {
407 write_string (" : ");
410 foreach (DataType prerequisite
in prerequisites
) {
416 write_type (prerequisite
);
419 write_begin_block ();
421 current_scope
= iface
.scope
;
423 visit_sorted (iface
.get_classes ());
424 visit_sorted (iface
.get_structs ());
425 visit_sorted (iface
.get_enums ());
426 visit_sorted (iface
.get_delegates ());
427 visit_sorted (iface
.get_fields ());
428 visit_sorted (iface
.get_methods ());
429 visit_sorted (iface
.get_properties ());
430 visit_sorted (iface
.get_signals ());
432 current_scope
= current_scope
.parent_scope
;
438 public override void visit_enum (Enum en
) {
439 if (en
.external_package
) {
443 if (!check_accessibility (en
)) {
450 string cheaders
= "";
451 foreach (string cheader
in en
.get_cheader_filenames ()) {
456 cheaders
= "%s,%s".printf (cheaders
, cheader
);
460 write_string ("[CCode (cprefix = \"%s\", ".printf (en
.get_cprefix ()));
462 if (!en
.has_type_id
) {
463 write_string ("has_type_id = \"%d\", ".printf (en
.has_type_id ?
1 : 0));
466 write_string ("cheader_filename = \"%s\")]".printf (cheaders
));
470 write_string ("[Flags]");
473 write_attributes (en
);
476 write_accessibility (en
);
477 write_string ("enum ");
478 write_identifier (en
.name
);
479 write_begin_block ();
482 foreach (EnumValue ev
in en
.get_values ()) {
490 if (ev
.get_cname () != ev
.get_default_cname ()) {
492 write_string ("[CCode (cname = \"%s\")]".printf (ev
.get_cname ()));
495 write_identifier (ev
.name
);
499 if (en
.get_methods ().size
> 0) {
505 current_scope
= en
.scope
;
506 foreach (Method m
in en
.get_methods ()) {
509 current_scope
= current_scope
.parent_scope
;
515 public override void visit_error_domain (ErrorDomain edomain
) {
516 if (edomain
.external_package
) {
520 if (!check_accessibility (edomain
)) {
527 string cheaders
= "";
528 foreach (string cheader
in edomain
.get_cheader_filenames ()) {
533 cheaders
= "%s,%s".printf (cheaders
, cheader
);
536 write_string ("[CCode (cprefix = \"%s\", cheader_filename = \"%s\")]".printf (edomain
.get_cprefix (), cheaders
));
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
) {
584 string cheaders
= "";
585 foreach (string cheader
in c
.get_cheader_filenames ()) {
590 cheaders
= "%s,%s".printf (cheaders
, cheader
);
593 write_string ("cheader_filename = \"%s\"".printf (cheaders
));
600 write_accessibility (c
);
601 write_string ("const ");
603 write_type (c
.type_reference
);
606 write_identifier (c
.name
);
611 public override void visit_field (Field f
) {
612 if (f
.external_package
) {
616 if (!check_accessibility (f
)) {
620 bool custom_cname
= (f
.get_cname () != f
.get_default_cname ());
621 bool custom_ctype
= (f
.get_ctype () != null);
622 bool custom_cheaders
= (f
.parent_symbol is Namespace
);
623 if (custom_cname
|| custom_ctype
|| custom_cheaders
|| (f
.no_array_length
&& f
.field_type is ArrayType
)) {
625 write_string ("[CCode (");
628 write_string ("cname = \"%s\"".printf (f
.get_cname ()));
636 write_string ("type = \"%s\"".printf (f
.get_ctype ()));
639 if (custom_cheaders
) {
640 if (custom_cname
|| custom_ctype
) {
645 string cheaders
= "";
646 foreach (string cheader
in f
.get_cheader_filenames ()) {
651 cheaders
= "%s,%s".printf (cheaders
, cheader
);
654 write_string ("cheader_filename = \"%s\"".printf (cheaders
));
657 if (f
.no_array_length
&& f
.field_type is ArrayType
) {
658 if (custom_cname
|| custom_ctype
|| custom_cheaders
) {
662 write_string ("array_length = false");
669 write_accessibility (f
);
671 if (f
.binding
== MemberBinding
.STATIC
) {
672 write_string ("static ");
673 } else if (f
.binding
== MemberBinding
.CLASS
) {
674 write_string ("class ");
677 if (is_weak (f
.field_type
)) {
678 write_string ("weak ");
681 write_type (f
.field_type
);
684 write_identifier (f
.name
);
689 private void write_error_domains (Gee
.List
<DataType
> error_domains
) {
690 if (error_domains
.size
> 0) {
691 write_string (" throws ");
694 foreach (DataType type
in error_domains
) {
706 // equality comparison with 3 digit precision
707 private bool float_equal (double d1
, double d2
) {
708 return ((int) (d1
* 1000)) == ((int) (d2
* 1000));
711 private void write_params (Gee
.List
<FormalParameter
> params
) {
715 foreach (FormalParameter param
in params
) {
720 if (param
.ellipsis
) {
721 write_string ("...");
726 var ccode_params
= new
StringBuilder ();
729 if (param
.ctype
!= null) {
730 ccode_params
.append_printf ("%stype = \"%s\"", separator
, param
.ctype
);
733 if (param
.no_array_length
&& param
.parameter_type is ArrayType
) {
734 ccode_params
.append_printf ("%sarray_length = false", separator
);
737 if (!float_equal (param
.carray_length_parameter_position
, i
+ 0.1)) {
738 ccode_params
.append_printf ("%sarray_length_pos = %g", separator
, param
.carray_length_parameter_position
);
741 if (!float_equal (param
.cdelegate_target_parameter_position
, i
+ 0.1)) {
742 ccode_params
.append_printf ("%sdelegate_target_pos = %g", separator
, param
.cdelegate_target_parameter_position
);
745 if (param
.async_only
) {
746 ccode_params
.append_printf ("%sasync_only = true", separator
);
750 if (ccode_params
.len
> 0) {
751 write_string ("[CCode (%s)] ".printf (ccode_params
.str
));
754 if (param
.params_array
) {
755 write_string ("params ");
758 if (param
.direction
== ParameterDirection
.IN
) {
759 if (param
.parameter_type
.value_owned
) {
760 write_string ("owned ");
763 if (param
.direction
== ParameterDirection
.REF
) {
764 write_string ("ref ");
765 } else if (param
.direction
== ParameterDirection
.OUT
) {
766 write_string ("out ");
768 if (is_weak (param
.parameter_type
)) {
769 write_string ("unowned ");
773 write_type (param
.parameter_type
);
776 write_identifier (param
.name
);
778 if (param
.default_expression
!= null) {
779 write_string (" = ");
780 write_string (param
.default_expression
.to_string ());
789 public override void visit_delegate (Delegate cb
) {
790 if (cb
.external_package
) {
794 if (!check_accessibility (cb
)) {
801 string cheaders
= "";
802 foreach (string cheader
in cb
.get_cheader_filenames ()) {
807 cheaders
= "%s,%s".printf (cheaders
, cheader
);
810 write_string ("[CCode (cheader_filename = \"%s\")]".printf (cheaders
));
814 write_accessibility (cb
);
815 if (!cb
.has_target
) {
816 write_string ("static ");
818 write_string ("delegate ");
820 write_return_type (cb
.return_type
);
823 write_identifier (cb
.name
);
827 write_params (cb
.get_parameters ());
834 public override void visit_method (Method m
) {
835 if (m
.external_package
) {
839 // don't write interface implementation unless it's an abstract or virtual method
840 if (!check_accessibility (m
) || (m
.base_interface_method
!= null && !m
.is_abstract
&& !m
.is_virtual
)) {
846 if (m
.get_attribute ("NoWrapper") != null) {
848 write_string ("[NoWrapper]");
850 if (m
.returns_modified_pointer
) {
852 write_string ("[ReturnsModifiedPointer]");
855 var ccode_params
= new
StringBuilder ();
858 if (m
.get_cname () != m
.get_default_cname ()) {
859 ccode_params
.append_printf ("%scname = \"%s\"", separator
, m
.get_cname ());
862 if (m
.parent_symbol is Namespace
) {
864 string cheaders
= "";
865 foreach (string cheader
in m
.get_cheader_filenames ()) {
870 cheaders
= "%s,%s".printf (cheaders
, cheader
);
873 ccode_params
.append_printf ("%scheader_filename = \"%s\"", separator
, cheaders
);
876 if (!float_equal (m
.cinstance_parameter_position
, 0)) {
877 ccode_params
.append_printf ("%sinstance_pos = %g", separator
, m
.cinstance_parameter_position
);
880 if (m
.no_array_length
&& m
.return_type is ArrayType
) {
881 ccode_params
.append_printf ("%sarray_length = false", separator
);
884 if (!float_equal (m
.carray_length_parameter_position
, -3)) {
885 ccode_params
.append_printf ("%sarray_length_pos = %g", separator
, m
.carray_length_parameter_position
);
888 if (m
.array_null_terminated
&& m
.return_type is ArrayType
) {
889 ccode_params
.append_printf ("%sarray_null_terminated = true", separator
);
892 if (!float_equal (m
.cdelegate_target_parameter_position
, -3)) {
893 ccode_params
.append_printf ("%sdelegate_target_pos = %g", separator
, m
.cdelegate_target_parameter_position
);
896 if (m
.vfunc_name
!= m
.name
) {
897 ccode_params
.append_printf ("%svfunc_name = \"%s\"", separator
, m
.vfunc_name
);
900 if (m
.sentinel
!= m
.DEFAULT_SENTINEL
) {
901 ccode_params
.append_printf ("%ssentinel = \"%s\"", separator
, m
.sentinel
);
904 if (m is CreationMethod
&& ((CreationMethod
)m
).custom_return_type_cname
!= null) {
905 ccode_params
.append_printf ("%stype = \"%s\"", separator
, ((CreationMethod
)m
).custom_return_type_cname
);
908 if (m is CreationMethod
&& !m
.has_construct_function
) {
909 ccode_params
.append_printf ("%shas_construct_function = false", separator
);
913 if (ccode_params
.len
> 0) {
915 write_string ("[CCode (%s)]".printf (ccode_params
.str
));
919 write_accessibility (m
);
921 if (m is CreationMethod
) {
922 var datatype
= (TypeSymbol
) m
.parent_symbol
;
923 write_identifier (datatype
.name
);
924 if (m
.name
!= "new") {
926 write_identifier (m
.name
);
929 } else if (m
.binding
== MemberBinding
.STATIC
) {
930 write_string ("static ");
931 } else if (m
.binding
== MemberBinding
.CLASS
) {
932 write_string ("class ");
933 } else if (m
.is_abstract
) {
934 write_string ("abstract ");
935 } else if (m
.is_virtual
) {
936 write_string ("virtual ");
937 } else if (m
.overrides
) {
938 write_string ("override ");
941 if (!(m is CreationMethod
)) {
942 write_return_type (m
.return_type
);
945 write_identifier (m
.name
);
949 write_params (m
.get_parameters ());
950 write_error_domains (m
.get_error_types ());
952 write_code_block (m
.body
);
957 public override void visit_creation_method (CreationMethod m
) {
961 public override void visit_property (Property prop
) {
962 if (!check_accessibility (prop
) || (prop
.base_interface_property
!= null && !prop
.is_abstract
&& !prop
.is_virtual
)) {
966 if (prop
.no_accessor_method
) {
968 write_string ("[NoAccessorMethod]");
972 write_accessibility (prop
);
974 if (prop
.binding
== MemberBinding
.STATIC
) {
975 write_string ("static ");
976 } else if (prop
.is_abstract
) {
977 write_string ("abstract ");
978 } else if (prop
.is_virtual
) {
979 write_string ("virtual ");
980 } else if (prop
.overrides
) {
981 write_string ("override ");
984 write_type (prop
.property_type
);
987 write_identifier (prop
.name
);
989 if (prop
.get_accessor
!= null) {
990 if (prop
.get_accessor
.value_type
.is_disposable ()) {
991 write_string (" owned");
994 write_string (" get");
995 write_code_block (prop
.get_accessor
.body
);
997 if (prop
.set_accessor
!= null) {
998 if (prop
.set_accessor
.value_type
.value_owned
) {
999 write_string ("owned ");
1002 if (prop
.set_accessor
.writable
) {
1003 write_string (" set");
1005 if (prop
.set_accessor
.construction
) {
1006 write_string (" construct");
1008 write_code_block (prop
.set_accessor
.body
);
1010 write_string (" }");
1014 public override void visit_signal (Signal sig
) {
1015 if (!check_accessibility (sig
)) {
1019 if (sig
.has_emitter
) {
1021 write_string ("[HasEmitter]");
1025 write_accessibility (sig
);
1027 if (sig
.is_virtual
) {
1028 write_string ("virtual ");
1031 write_string ("signal ");
1033 write_return_type (sig
.return_type
);
1036 write_identifier (sig
.name
);
1040 write_params (sig
.get_parameters ());
1047 public override void visit_block (Block b
) {
1048 write_begin_block ();
1050 foreach (Statement stmt
in b
.get_statements ()) {
1057 public override void visit_empty_statement (EmptyStatement stmt
) {
1060 public override void visit_declaration_statement (DeclarationStatement stmt
) {
1062 stmt
.declaration
.accept (this
);
1067 public override void visit_local_variable (LocalVariable local
) {
1068 write_type (local
.variable_type
);
1070 write_identifier (local
.name
);
1071 if (local
.initializer
!= null) {
1072 write_string (" = ");
1073 local
.initializer
.accept (this
);
1077 public override void visit_initializer_list (InitializerList list
) {
1081 foreach (Expression initializer
in list
.get_initializers ()) {
1083 write_string (", ");
1088 initializer
.accept (this
);
1090 write_string (" }");
1093 public override void visit_expression_statement (ExpressionStatement stmt
) {
1095 stmt
.expression
.accept (this
);
1100 public override void visit_if_statement (IfStatement stmt
) {
1102 write_string ("if (");
1103 stmt
.condition
.accept (this
);
1105 stmt
.true_statement
.accept (this
);
1106 if (stmt
.false_statement
!= null) {
1107 write_string (" else");
1108 stmt
.false_statement
.accept (this
);
1113 public override void visit_switch_statement (SwitchStatement stmt
) {
1115 write_string ("switch (");
1116 stmt
.expression
.accept (this
);
1117 write_string (") {");
1120 foreach (SwitchSection section
in stmt
.get_sections ()) {
1121 section
.accept (this
);
1129 public override void visit_switch_section (SwitchSection section
) {
1130 foreach (SwitchLabel label
in section
.get_labels ()) {
1131 label
.accept (this
);
1134 visit_block (section
);
1137 public override void visit_switch_label (SwitchLabel label
) {
1138 if (label
.expression
!= null) {
1140 write_string ("case ");
1141 label
.expression
.accept (this
);
1146 write_string ("default:");
1151 public override void visit_while_statement (WhileStatement stmt
) {
1153 write_string ("while (");
1154 stmt
.condition
.accept (this
);
1156 stmt
.body
.accept (this
);
1160 public override void visit_do_statement (DoStatement stmt
) {
1162 write_string ("do");
1163 stmt
.body
.accept (this
);
1164 write_string ("while (");
1165 stmt
.condition
.accept (this
);
1166 write_string (");");
1170 public override void visit_for_statement (ForStatement stmt
) {
1172 write_string ("for (");
1175 foreach (Expression initializer
in stmt
.get_initializer ()) {
1177 write_string (", ");
1180 initializer
.accept (this
);
1182 write_string ("; ");
1184 stmt
.condition
.accept (this
);
1185 write_string ("; ");
1188 foreach (Expression iterator
in stmt
.get_iterator ()) {
1190 write_string (", ");
1193 iterator
.accept (this
);
1197 stmt
.body
.accept (this
);
1201 public override void visit_foreach_statement (ForeachStatement stmt
) {
1204 public override void visit_break_statement (BreakStatement stmt
) {
1206 write_string ("break;");
1210 public override void visit_continue_statement (ContinueStatement stmt
) {
1212 write_string ("continue;");
1216 public override void visit_return_statement (ReturnStatement stmt
) {
1218 write_string ("return");
1219 if (stmt
.return_expression
!= null) {
1221 stmt
.return_expression
.accept (this
);
1227 public override void visit_yield_statement (YieldStatement y
) {
1229 write_string ("yield");
1230 if (y
.yield_expression
!= null) {
1232 y
.yield_expression
.accept (this
);
1238 public override void visit_throw_statement (ThrowStatement stmt
) {
1240 write_string ("throw");
1241 if (stmt
.error_expression
!= null) {
1243 stmt
.error_expression
.accept (this
);
1249 public override void visit_try_statement (TryStatement stmt
) {
1251 write_string ("try");
1252 stmt
.body
.accept (this
);
1256 public override void visit_catch_clause (CatchClause clause
) {
1259 public override void visit_lock_statement (LockStatement stmt
) {
1262 public override void visit_delete_statement (DeleteStatement stmt
) {
1265 public override void visit_array_creation_expression (ArrayCreationExpression expr
) {
1266 write_string ("new ");
1267 write_type (expr
.element_type
);
1271 foreach (Expression size
in expr
.get_sizes ()) {
1273 write_string (", ");
1282 if (expr
.initializer_list
!= null) {
1284 expr
.initializer_list
.accept (this
);
1288 public override void visit_boolean_literal (BooleanLiteral lit
) {
1289 write_string (lit
.value
.to_string ());
1292 public override void visit_character_literal (CharacterLiteral lit
) {
1293 write_string (lit
.value
);
1296 public override void visit_integer_literal (IntegerLiteral lit
) {
1297 write_string (lit
.value
);
1300 public override void visit_real_literal (RealLiteral lit
) {
1301 write_string (lit
.value
);
1304 public override void visit_string_literal (StringLiteral lit
) {
1305 write_string (lit
.value
);
1308 public override void visit_null_literal (NullLiteral lit
) {
1309 write_string ("null");
1312 public override void visit_member_access (MemberAccess expr
) {
1313 if (expr
.inner
!= null) {
1314 expr
.inner
.accept (this
);
1317 write_identifier (expr
.member_name
);
1320 public override void visit_method_call (MethodCall expr
) {
1321 expr
.call
.accept (this
);
1322 write_string (" (");
1325 foreach (Expression arg
in expr
.get_argument_list ()) {
1327 write_string (", ");
1337 public override void visit_element_access (ElementAccess expr
) {
1338 expr
.container
.accept (this
);
1342 foreach (Expression index
in expr
.get_indices ()) {
1344 write_string (", ");
1348 index
.accept (this
);
1354 public override void visit_base_access (BaseAccess expr
) {
1355 write_string ("base");
1358 public override void visit_postfix_expression (PostfixExpression expr
) {
1359 expr
.inner
.accept (this
);
1360 if (expr
.increment
) {
1361 write_string ("++");
1363 write_string ("--");
1367 public override void visit_object_creation_expression (ObjectCreationExpression expr
) {
1368 write_string ("new ");
1369 write_type (expr
.type_reference
);
1370 write_string (" (");
1373 foreach (Expression arg
in expr
.get_argument_list ()) {
1375 write_string (", ");
1385 public override void visit_sizeof_expression (SizeofExpression expr
) {
1386 write_string ("sizeof (");
1387 write_type (expr
.type_reference
);
1391 public override void visit_typeof_expression (TypeofExpression expr
) {
1392 write_string ("typeof (");
1393 write_type (expr
.type_reference
);
1397 public override void visit_unary_expression (UnaryExpression expr
) {
1398 switch (expr
.operator
) {
1399 case UnaryOperator
.PLUS
:
1402 case UnaryOperator
.MINUS
:
1405 case UnaryOperator
.LOGICAL_NEGATION
:
1408 case UnaryOperator
.BITWISE_COMPLEMENT
:
1411 case UnaryOperator
.INCREMENT
:
1412 write_string ("++");
1414 case UnaryOperator
.DECREMENT
:
1415 write_string ("--");
1417 case UnaryOperator
.REF
:
1418 write_string ("ref ");
1420 case UnaryOperator
.OUT
:
1421 write_string ("out ");
1424 assert_not_reached ();
1426 expr
.inner
.accept (this
);
1429 public override void visit_cast_expression (CastExpression expr
) {
1430 if (!expr
.is_silent_cast
) {
1432 write_type (expr
.type_reference
);
1433 write_string (") ");
1436 expr
.inner
.accept (this
);
1438 if (expr
.is_silent_cast
) {
1439 write_string (" as ");
1440 write_type (expr
.type_reference
);
1444 public override void visit_pointer_indirection (PointerIndirection expr
) {
1446 expr
.inner
.accept (this
);
1449 public override void visit_addressof_expression (AddressofExpression expr
) {
1451 expr
.inner
.accept (this
);
1454 public override void visit_reference_transfer_expression (ReferenceTransferExpression expr
) {
1455 write_string ("(owned) ");
1456 expr
.inner
.accept (this
);
1459 public override void visit_binary_expression (BinaryExpression expr
) {
1460 expr
.left
.accept (this
);
1462 switch (expr
.operator
) {
1463 case BinaryOperator
.PLUS
:
1464 write_string (" + ");
1466 case BinaryOperator
.MINUS
:
1467 write_string (" - ");
1469 case BinaryOperator
.MUL
:
1470 write_string (" * ");
1472 case BinaryOperator
.DIV
:
1473 write_string (" / ");
1475 case BinaryOperator
.MOD
:
1476 write_string (" % ");
1478 case BinaryOperator
.SHIFT_LEFT
:
1479 write_string (" << ");
1481 case BinaryOperator
.SHIFT_RIGHT
:
1482 write_string (" >> ");
1484 case BinaryOperator
.LESS_THAN
:
1485 write_string (" < ");
1487 case BinaryOperator
.GREATER_THAN
:
1488 write_string (" > ");
1490 case BinaryOperator
.LESS_THAN_OR_EQUAL
:
1491 write_string (" <= ");
1493 case BinaryOperator
.GREATER_THAN_OR_EQUAL
:
1494 write_string (" >= ");
1496 case BinaryOperator
.EQUALITY
:
1497 write_string (" == ");
1499 case BinaryOperator
.INEQUALITY
:
1500 write_string (" != ");
1502 case BinaryOperator
.BITWISE_AND
:
1503 write_string (" & ");
1505 case BinaryOperator
.BITWISE_OR
:
1506 write_string (" | ");
1508 case BinaryOperator
.BITWISE_XOR
:
1509 write_string (" ^ ");
1511 case BinaryOperator
.AND
:
1512 write_string (" && ");
1514 case BinaryOperator
.OR
:
1515 write_string (" || ");
1517 case BinaryOperator
.IN
:
1518 write_string (" in ");
1521 assert_not_reached ();
1524 expr
.right
.accept (this
);
1527 public override void visit_type_check (TypeCheck expr
) {
1528 expr
.expression
.accept (this
);
1529 write_string (" is ");
1530 write_type (expr
.type_reference
);
1533 public override void visit_conditional_expression (ConditionalExpression expr
) {
1534 expr
.condition
.accept (this
);
1536 expr
.true_expression
.accept (this
);
1538 expr
.false_expression
.accept (this
);
1541 public override void visit_lambda_expression (LambdaExpression expr
) {
1544 public override void visit_assignment (Assignment a
) {
1545 a
.left
.accept (this
);
1546 write_string (" = ");
1547 a
.right
.accept (this
);
1550 private void write_indent () {
1557 for (i
= 0; i
< indent
; i
++) {
1564 private void write_identifier (string s
) {
1565 if (s
== "base" || s
== "break" || s
== "class" ||
1566 s
== "construct" || s
== "delegate" || s
== "delete" ||
1567 s
== "do" || s
== "dynamic" || s
== "foreach" || s
== "in" ||
1568 s
== "interface" || s
== "lock" || s
== "namespace" ||
1569 s
== "new" || s
== "out" || s
== "ref" ||
1570 s
== "signal" || s
.get_char ().isdigit ()) {
1576 private void write_return_type (DataType type
) {
1577 if (is_weak (type
)) {
1578 write_string ("unowned ");
1584 private bool is_weak (DataType type
) {
1585 if (type
.value_owned
) {
1587 } else if (type is VoidType
|| type is PointerType
) {
1589 } else if (type is ValueType
) {
1590 if (type
.nullable
) {
1591 // nullable structs are heap allocated
1595 // TODO return true for structs with destroy
1602 private void write_type (DataType type
) {
1603 write_string (type
.to_qualified_string (current_scope
));
1606 private void write_string (string s
) {
1607 stream
.printf ("%s", s
);
1611 private void write_newline () {
1616 void write_code_block (Block? block
) {
1617 if (block
== null || !dump_tree
) {
1622 block
.accept (this
);
1625 private void write_begin_block () {
1636 private void write_end_block () {
1639 stream
.printf ("}");
1642 private bool check_accessibility (Symbol sym
) {
1644 sym
.access
== SymbolAccessibility
.PUBLIC
||
1645 sym
.access
== SymbolAccessibility
.PROTECTED
) {
1652 private void write_attributes (CodeNode node
) {
1653 foreach (Attribute attr
in node
.attributes
) {
1654 if (!filter_attribute (attr
)) {
1656 stream
.printf ("[%s", attr
.name
);
1658 var keys
= attr
.args
.get_keys ();
1659 if (keys
.size
!= 0) {
1660 stream
.printf (" (");
1662 string separator
= "";
1663 foreach (string arg_name
in keys
) {
1664 stream
.printf ("%s%s = ", separator
, arg_name
);
1665 var expr
= attr
.args
.get (arg_name
);
1670 stream
.printf (")");
1672 stream
.printf ("]");
1678 private bool filter_attribute (Attribute attr
) {
1679 if (attr
.name
== "CCode"
1680 || attr
.name
== "Compact" || attr
.name
== "Immutable"
1681 || attr
.name
== "SimpleType" || attr
.name
== "IntegerType" || attr
.name
== "FloatingType"
1682 || attr
.name
== "Flags") {
1688 private void write_accessibility (Symbol sym
) {
1689 if (sym
.access
== SymbolAccessibility
.PUBLIC
) {
1690 write_string ("public ");
1691 } else if (sym
.access
== SymbolAccessibility
.PROTECTED
) {
1692 write_string ("protected ");
1693 } else if (sym
.access
== SymbolAccessibility
.INTERNAL
) {
1694 write_string ("internal ");
1695 } else if (sym
.access
== SymbolAccessibility
.PRIVATE
) {
1696 write_string ("private ");