change run to use meson/ninja and then exec. - remove libvala code from application...
[roobuilder] / src / codegen / valaccode.vala
1 /* valaccode.vala
2  *
3  * Copyright (C) 2017  Rico Tzschichholz
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
18  *
19  * Author:
20  *      Rico Tzschichholz <ricotz@ubuntu.com>
21  */
22
23 namespace Vala {
24         static int? ccode_attribute_cache_index = null;
25
26         static unowned CCodeAttribute get_ccode_attribute (CodeNode node) {
27                 if (ccode_attribute_cache_index == null) {
28                         ccode_attribute_cache_index = CodeNode.get_attribute_cache_index ();
29                 }
30
31                 unowned AttributeCache? attr = node.get_attribute_cache (ccode_attribute_cache_index);
32                 if (attr == null) {
33                         var new_attr = new CCodeAttribute (node);
34                         node.set_attribute_cache (ccode_attribute_cache_index, new_attr);
35                         attr = new_attr;
36                 }
37                 return (CCodeAttribute) attr;
38         }
39
40         public static string get_ccode_name (CodeNode node) {
41                 return get_ccode_attribute(node).name;
42         }
43
44         public static string get_ccode_const_name (CodeNode node) {
45                 return get_ccode_attribute(node).const_name;
46         }
47
48         public static string get_ccode_type_name (ObjectTypeSymbol sym) {
49                 return get_ccode_attribute (sym).type_name;
50         }
51
52         public static string get_ccode_type_cast_function (ObjectTypeSymbol sym) {
53                 assert (!(sym is Class && ((Class) sym).is_compact));
54                 return get_ccode_upper_case_name (sym);
55         }
56
57         public static string get_ccode_type_get_function (ObjectTypeSymbol sym) {
58                 var func_name = sym.get_attribute_string ("CCode", "type_get_function");
59                 if (func_name != null) {
60                         return func_name;
61                 }
62                 if (sym is Class) {
63                         assert (!((Class) sym).is_compact);
64                         return "%s_GET_CLASS".printf (get_ccode_upper_case_name (sym));
65                 } else if (sym is Interface) {
66                         return "%s_GET_INTERFACE".printf (get_ccode_upper_case_name (sym));
67                 } else {
68                         Report.error (sym.source_reference, "`CCode.type_get_function' not supported");
69                         return "";
70                 }
71         }
72
73         public static string get_ccode_class_get_private_function (Class cl) {
74                 assert (!cl.is_compact);
75                 return "%s_GET_CLASS_PRIVATE".printf (get_ccode_upper_case_name (cl));
76         }
77
78         public static string get_ccode_class_type_function (Class cl) {
79                 assert (!cl.is_compact);
80                 return "%s_CLASS".printf (get_ccode_upper_case_name (cl));
81         }
82
83         public static string get_ccode_lower_case_name (CodeNode node, string? infix = null) {
84                 unowned Symbol? sym = node as Symbol;
85                 if (sym != null) {
86                         if (infix == null) {
87                                 infix = "";
88                         }
89                         if (sym is Delegate) {
90                                 return "%s%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), infix, Symbol.camel_case_to_lower_case (sym.name));
91                         } else if (sym is Signal) {
92                                 return get_ccode_attribute (sym).name.replace ("-", "_");
93                         } else if (sym is ErrorCode) {
94                                 return get_ccode_name (sym).ascii_down ();
95                         } else {
96                                 return "%s%s%s".printf (get_ccode_lower_case_prefix (sym.parent_symbol), infix, get_ccode_lower_case_suffix (sym));
97                         }
98                 } else if (node is ErrorType) {
99                         unowned ErrorType type = (ErrorType) node;
100                         if (type.error_domain == null) {
101                                 if (infix == null) {
102                                         return "g_error";
103                                 } else {
104                                         return "g_%s_error".printf (infix);
105                                 }
106                         } else if (type.error_code == null) {
107                                 return get_ccode_lower_case_name (type.error_domain, infix);
108                         } else {
109                                 return get_ccode_lower_case_name (type.error_code, infix);
110                         }
111                 } else if (node is DelegateType) {
112                         unowned DelegateType type = (DelegateType) node;
113                         return get_ccode_lower_case_name (type.delegate_symbol, infix);
114                 } else if (node is PointerType) {
115                         unowned PointerType type = (PointerType) node;
116                         return get_ccode_lower_case_name (type.base_type, infix);
117                 } else if (node is GenericType) {
118                         return "valageneric";
119                 } else if (node is VoidType) {
120                         return "valavoid";
121                 } else {
122                         unowned DataType type = (DataType) node;
123                         return get_ccode_lower_case_name (type.type_symbol, infix);
124                 }
125         }
126
127         public static string get_ccode_upper_case_name (Symbol sym, string? infix = null) {
128                 if (sym is Property) {
129                         return "%s_%s".printf (get_ccode_lower_case_name (sym.parent_symbol), Symbol.camel_case_to_lower_case (sym.name)).ascii_up ();
130                 } else {
131                         return get_ccode_lower_case_name (sym, infix).ascii_up ();
132                 }
133         }
134
135         public static string get_ccode_header_filenames (Symbol sym) {
136                 return get_ccode_attribute(sym).header_filenames;
137         }
138
139         public static string get_ccode_feature_test_macros (Symbol sym) {
140                 return get_ccode_attribute(sym).feature_test_macros;
141         }
142
143         public static string get_ccode_prefix (Symbol sym) {
144                 return get_ccode_attribute(sym).prefix;
145         }
146
147         public static string get_ccode_lower_case_prefix (Symbol sym) {
148                 return get_ccode_attribute(sym).lower_case_prefix;
149         }
150
151         public static string get_ccode_lower_case_suffix (Symbol sym) {
152                 return get_ccode_attribute(sym).lower_case_suffix;
153         }
154
155         public static string get_ccode_ref_function (TypeSymbol sym) {
156                 return get_ccode_attribute(sym).ref_function;
157         }
158
159         public static string get_ccode_quark_name (ErrorDomain edomain) {
160                 return "%s-quark".printf (get_ccode_lower_case_name (edomain).replace ("_", "-"));
161         }
162
163         public static bool is_reference_counting (TypeSymbol sym) {
164                 if (sym is Class) {
165                         return get_ccode_ref_function (sym) != null;
166                 } else if (sym is Interface) {
167                         return true;
168                 } else {
169                         return false;
170                 }
171         }
172
173         public static bool is_ref_function_void (DataType type) {
174                 unowned Class? cl = type.type_symbol as Class;
175                 if (cl != null) {
176                         return get_ccode_ref_function_void (cl);
177                 } else {
178                         return false;
179                 }
180         }
181
182         public static bool is_free_function_address_of (DataType type) {
183                 unowned Class? cl = type.type_symbol as Class;
184                 if (cl != null) {
185                         return get_ccode_free_function_address_of (cl);
186                 } else {
187                         return false;
188                 }
189         }
190
191         public static bool get_ccode_ref_function_void (Class cl) {
192                 return get_ccode_attribute(cl).ref_function_void;
193         }
194
195         public static bool get_ccode_free_function_address_of (Class cl) {
196                 return get_ccode_attribute(cl).free_function_address_of;
197         }
198
199         public static string get_ccode_unref_function (ObjectTypeSymbol sym) {
200                 return get_ccode_attribute(sym).unref_function;
201         }
202
203         public static string get_ccode_ref_sink_function (ObjectTypeSymbol sym) {
204                 return get_ccode_attribute(sym).ref_sink_function;
205         }
206
207         public static string get_ccode_copy_function (TypeSymbol sym) {
208                 return get_ccode_attribute(sym).copy_function;
209         }
210
211         public static string get_ccode_destroy_function (TypeSymbol sym) {
212                 return get_ccode_attribute(sym).destroy_function;
213         }
214
215         public static string? get_ccode_dup_function (TypeSymbol sym) {
216                 if (sym is Struct) {
217                         return get_ccode_attribute (sym).dup_function;
218                 }
219                 return get_ccode_copy_function (sym);
220         }
221
222         public static string get_ccode_free_function (TypeSymbol sym) {
223                 return get_ccode_attribute(sym).free_function;
224         }
225
226         public static bool get_ccode_is_gboxed (TypeSymbol sym) {
227                 return get_ccode_free_function (sym) == "g_boxed_free";
228         }
229
230         public static bool get_ccode_finish_instance (Method m) {
231                 assert (m.coroutine);
232                 return get_ccode_attribute (m).finish_instance;
233         }
234
235         public static string get_ccode_type_id (CodeNode node) {
236                 return get_ccode_attribute(node).type_id;
237         }
238
239         public static string get_ccode_type_function (TypeSymbol sym) {
240                 assert (!((sym is Class && ((Class) sym).is_compact) || sym is ErrorCode || sym is ErrorDomain || sym is Delegate));
241                 return "%s_get_type".printf (get_ccode_lower_case_name (sym));
242         }
243
244         public static string get_ccode_marshaller_type_name (CodeNode node) {
245                 return get_ccode_attribute(node).marshaller_type_name;
246         }
247
248         public static string get_ccode_get_value_function (CodeNode sym) {
249                 return get_ccode_attribute(sym).get_value_function;
250         }
251
252         public static string get_ccode_set_value_function (CodeNode sym) {
253                 return get_ccode_attribute(sym).set_value_function;
254         }
255
256         public static string get_ccode_take_value_function (CodeNode sym) {
257                 return get_ccode_attribute(sym).take_value_function;
258         }
259
260         public static string get_ccode_param_spec_function (CodeNode sym) {
261                 return get_ccode_attribute(sym).param_spec_function;
262         }
263
264         public static string get_ccode_type_check_function (TypeSymbol sym) {
265                 unowned Class? cl = sym as Class;
266                 var a = sym.get_attribute_string ("CCode", "type_check_function");
267                 if (cl != null && a != null) {
268                         return a;
269                 } else if ((cl != null && cl.is_compact) || sym is Struct || sym is Enum || sym is Delegate) {
270                         return "";
271                 } else {
272                         return get_ccode_upper_case_name (sym, "IS_");
273                 }
274         }
275
276         public static string get_ccode_class_type_check_function (Class cl) {
277                 assert (!cl.is_compact);
278                 return "%s_CLASS".printf (get_ccode_type_check_function (cl));
279         }
280
281         public static string get_ccode_default_value (TypeSymbol sym) {
282                 return get_ccode_attribute(sym).default_value;
283         }
284
285         public static string get_ccode_default_value_on_error (TypeSymbol sym) {
286                 return get_ccode_attribute (sym).default_value_on_error;
287         }
288
289         public static bool get_ccode_has_copy_function (Struct st) {
290                 return st.get_attribute_bool ("CCode", "has_copy_function", true);
291         }
292
293         public static bool get_ccode_has_destroy_function (Struct st) {
294                 return st.get_attribute_bool ("CCode", "has_destroy_function", true);
295         }
296
297         public static double get_ccode_instance_pos (CodeNode node) {
298                 if (node is Delegate) {
299                         return node.get_attribute_double ("CCode", "instance_pos", -2);
300                 } else {
301                         return node.get_attribute_double ("CCode", "instance_pos", 0);
302                 }
303         }
304
305         public static double get_ccode_error_pos (Callable c) {
306                 return c.get_attribute_double ("CCode", "error_pos", -1);
307         }
308
309         public static bool get_ccode_array_length (CodeNode node) {
310                 return get_ccode_attribute(node).array_length;
311         }
312
313         public static string get_ccode_array_length_type (CodeNode node) {
314                 if (node is ArrayType) {
315                         return get_ccode_name (((ArrayType) node).length_type);
316                 } else if (node is DataType) {
317                         Report.error (node.source_reference, "`CCode.array_length_type' not supported");
318                         return "";
319                 } else {
320                         assert (node is Method || node is Parameter || node is Delegate || node is Property || node is Field);
321                         return get_ccode_attribute(node).array_length_type;
322                 }
323         }
324
325         public static bool get_ccode_array_null_terminated (CodeNode node) {
326                 return get_ccode_attribute(node).array_null_terminated;
327         }
328
329         public static string? get_ccode_array_length_name (CodeNode node) {
330                 return get_ccode_attribute(node).array_length_name;
331         }
332
333         public static string? get_ccode_array_length_expr (CodeNode node) {
334                 return get_ccode_attribute(node).array_length_expr;
335         }
336
337         public static double get_ccode_array_length_pos (CodeNode node) {
338                 var a = node.get_attribute ("CCode");
339                 if (a != null && a.has_argument ("array_length_pos")) {
340                         return a.get_double ("array_length_pos");
341                 }
342                 if (node is Parameter) {
343                         unowned Parameter param = (Parameter) node;
344                         return get_ccode_pos (param) + 0.1;
345                 } else {
346                         return -3;
347                 }
348         }
349
350         public static double get_ccode_delegate_target_pos (CodeNode node) {
351                 var a = node.get_attribute ("CCode");
352                 if (a != null && a.has_argument ("delegate_target_pos")) {
353                         return a.get_double ("delegate_target_pos");
354                 }
355                 if (node is Parameter) {
356                         unowned Parameter param = (Parameter) node;
357                         return get_ccode_pos (param) + 0.1;
358                 } else {
359                         return -3;
360                 }
361         }
362
363         public static double get_ccode_destroy_notify_pos (CodeNode node) {
364                 var a = node.get_attribute ("CCode");
365                 if (a != null && a.has_argument ("destroy_notify_pos")) {
366                         return a.get_double ("destroy_notify_pos");
367                 }
368                 return get_ccode_delegate_target_pos (node) + 0.01;
369         }
370
371         public static bool get_ccode_delegate_target (CodeNode node) {
372                 return get_ccode_attribute(node).delegate_target;
373         }
374
375         public static string get_ccode_delegate_target_name (Variable variable) {
376                 return get_ccode_attribute(variable).delegate_target_name;
377         }
378
379         public static string get_ccode_delegate_target_destroy_notify_name (Variable variable) {
380                 return get_ccode_attribute(variable).delegate_target_destroy_notify_name;
381         }
382
383         public static double get_ccode_pos (Parameter param) {
384                 return get_ccode_attribute(param).pos;
385         }
386
387         public static string? get_ccode_type (CodeNode node) {
388                 return get_ccode_attribute(node).ctype;
389         }
390
391         public static bool get_ccode_simple_generics (Method m) {
392                 return m.get_attribute_bool ("CCode", "simple_generics");
393         }
394
395         public static string get_ccode_real_name (Symbol sym) {
396                 return get_ccode_attribute(sym).real_name;
397         }
398
399         public static string get_ccode_constructv_name (CreationMethod m) {
400                 const string infix = "constructv";
401
402                 unowned Class parent = (Class) m.parent_symbol;
403
404                 if (m.name == ".new") {
405                         return "%s%s".printf (get_ccode_lower_case_prefix (parent), infix);
406                 } else {
407                         return "%s%s_%s".printf (get_ccode_lower_case_prefix (parent), infix, m.name);
408                 }
409         }
410
411         public static string get_ccode_vfunc_name (Method m) {
412                 return get_ccode_attribute(m).vfunc_name;
413         }
414
415         public static double get_ccode_async_result_pos (Method m) {
416                 assert (m.coroutine);
417                 return m.get_attribute_double ("CCode", "async_result_pos", 0.1);
418         }
419
420         public static string get_ccode_finish_name (Method m) {
421                 assert (m.coroutine);
422                 return get_ccode_attribute(m).finish_name;
423         }
424
425         public static string get_ccode_finish_vfunc_name (Method m) {
426                 assert (m.coroutine);
427                 return get_ccode_attribute(m).finish_vfunc_name;
428         }
429
430         public static string get_ccode_finish_real_name (Method m) {
431                 assert (m.coroutine);
432                 return get_ccode_attribute(m).finish_real_name;
433         }
434
435         public static bool get_ccode_no_accessor_method (Property p) {
436                 return p.get_attribute ("NoAccessorMethod") != null;
437         }
438
439         public static bool get_ccode_concrete_accessor (Property p) {
440                 return p.get_attribute ("ConcreteAccessor") != null;
441         }
442
443         public static bool get_ccode_has_emitter (Signal sig) {
444                 return sig.get_attribute ("HasEmitter") != null;
445         }
446
447         public static bool get_ccode_has_type_id (TypeSymbol sym) {
448                 return sym.get_attribute_bool ("CCode", "has_type_id", true);
449         }
450
451         public static bool get_ccode_has_new_function (Method m) {
452                 return m.get_attribute_bool ("CCode", "has_new_function", true);
453         }
454
455         public static bool get_ccode_has_generic_type_parameter (Method m) {
456                 var a = m.get_attribute ("CCode");
457                 return a != null && a.has_argument ("generic_type_pos");
458         }
459
460         public static double get_ccode_generic_type_pos (Method m) {
461                 return m.get_attribute_double ("CCode", "generic_type_pos");
462         }
463
464         public static bool get_ccode_no_wrapper (Method m) {
465                 return m.get_attribute ("NoWrapper") != null;
466         }
467
468         public static string get_ccode_sentinel (Method m) {
469                 return get_ccode_attribute(m).sentinel;
470         }
471 }