fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / src / hll.c
blob7da0fbdd4621b077226bb8a215d3748d3569c667
1 /*
2 Copyright (C) 2005-2009, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/hll.c - High Level Language support
9 =head1 DESCRIPTION
11 The Parrot core sometimes has to create new PMCs which should map to the
12 current HLL's defaults. The current language and a typemap provides this
13 feature.
15 =head1 DATA
17 interp->HLL_info
19 @HLL_info = [
20 [ hll_name, hll_lib, { core_type => HLL_type, ... }, namespace, hll_id ],
21 ...
24 =head2 Functions
26 =over 4
28 =cut
32 #include "parrot/parrot.h"
33 #include "parrot/dynext.h"
34 #include "pmc/pmc_callcontext.h"
35 #include "hll.str"
37 /* HEADERIZER HFILE: include/parrot/hll.h */
39 /* HEADERIZER BEGIN: static */
40 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
42 PARROT_CANNOT_RETURN_NULL
43 PARROT_WARN_UNUSED_RESULT
44 static PMC* new_hll_entry(PARROT_INTERP, ARGIN_NULLOK(STRING *entry_name))
45 __attribute__nonnull__(1);
47 #define ASSERT_ARGS_new_hll_entry __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
48 PARROT_ASSERT_ARG(interp))
49 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
50 /* HEADERIZER END: static */
52 /* for shared HLL data, do COW stuff */
53 #define START_READ_HLL_INFO(interp, hll_info)
54 #define END_READ_HLL_INFO(interp, hll_info)
59 =item C<static PMC* new_hll_entry(PARROT_INTERP, STRING *entry_name)>
61 Create a new HLL information table entry.
62 Takes an interpreter name and (optional) entry name.
63 Returns a pointer to the new entry.
64 Used by Parrot_register_HLL and Parrot_register_HLL_lib.
66 =cut
70 PARROT_CANNOT_RETURN_NULL
71 PARROT_WARN_UNUSED_RESULT
72 static PMC*
73 new_hll_entry(PARROT_INTERP, ARGIN_NULLOK(STRING *entry_name))
75 ASSERT_ARGS(new_hll_entry)
76 PMC * const hll_info = interp->HLL_info;
77 const INTVAL id = VTABLE_elements(interp, hll_info);
79 PMC *entry_id;
81 PMC * const entry = Parrot_pmc_new_constant_init_int(interp,
82 enum_class_FixedPMCArray, e_HLL_MAX);
84 if (entry_name && !STRING_IS_EMPTY(entry_name)) {
85 VTABLE_set_pmc_keyed_str(interp, hll_info, entry_name, entry);
87 else
88 VTABLE_push_pmc(interp, hll_info, entry);
90 entry_id = Parrot_pmc_new_constant_init_int(interp, enum_class_Integer, id);
91 VTABLE_set_pmc_keyed_int(interp, entry, e_HLL_id, entry_id);
93 return entry;
99 =item C<void Parrot_init_HLL(PARROT_INTERP)>
101 Initialises the HLL_info and HLL_namespace fields of the interpreter structure.
102 Registers the default HLL namespace "parrot".
104 =cut
108 void
109 Parrot_init_HLL(PARROT_INTERP)
111 ASSERT_ARGS(Parrot_init_HLL)
112 interp->HLL_info =
113 Parrot_pmc_new(interp, enum_class_OrderedHash);
114 interp->HLL_namespace =
115 Parrot_pmc_new_constant(interp, enum_class_ResizablePMCArray);
117 Parrot_register_HLL(interp, CONST_STRING(interp, "parrot"));
122 =item C<INTVAL Parrot_register_HLL(PARROT_INTERP, STRING *hll_name)>
124 Register the HLL with the given STRING name C<hll_name> in the interpreter.
126 If the HLL has already been registered, the ID of the HLL is returned.
127 Otherwise the HLL is registered, a corresponding HLL namespace is created,
128 and the HLL ID is returned.
130 If there is an error, C<-1> is returned.
132 =cut
136 PARROT_EXPORT
137 INTVAL
138 Parrot_register_HLL(PARROT_INTERP, ARGIN(STRING *hll_name))
140 ASSERT_ARGS(Parrot_register_HLL)
141 PMC *entry, *name, *type_hash, *ns_hash, *hll_info;
142 INTVAL idx;
144 /* TODO LOCK or disallow in threads */
146 idx = Parrot_get_HLL_id(interp, hll_name);
148 if (idx >= 0)
149 return idx;
151 hll_info = interp->HLL_info;
153 idx = VTABLE_elements(interp, hll_info);
154 entry = new_hll_entry(interp, hll_name);
156 /* register HLL name */
157 name = Parrot_pmc_new_constant(interp, enum_class_String);
159 VTABLE_set_string_native(interp, name, hll_name);
160 VTABLE_set_pmc_keyed_int(interp, entry, e_HLL_name, name);
162 /* create HLL namespace using the *constant* name */
163 hll_name = Parrot_str_downcase(interp, VTABLE_get_string(interp, name));
165 /* HLL type mappings aren't yet created, we can't create
166 * a namespace in HLL's flavor yet - maybe promote the
167 * ns_hash to another type, if mappings provide one
168 * XXX - FIXME
170 ns_hash = Parrot_ns_make_namespace_keyed_str(interp, interp->root_namespace,
171 hll_name);
173 /* cache HLL's toplevel namespace */
174 VTABLE_set_pmc_keyed_int(interp, interp->HLL_namespace, idx, ns_hash);
176 /* create HLL typemap hash */
177 type_hash = Parrot_pmc_new_constant(interp, enum_class_Hash);
178 VTABLE_set_pointer(interp, type_hash, parrot_new_intval_hash(interp));
179 VTABLE_set_pmc_keyed_int(interp, entry, e_HLL_typemap, type_hash);
181 return idx;
186 =item C<INTVAL Parrot_register_HLL_lib(PARROT_INTERP, STRING *hll_lib)>
188 Register an HLL library.
189 Takes a pointer to a library name STRING to add. If the name has already
190 been registered the list position of the library in the HLL Info list is
191 returned. Otherwise, the library is added to the list and 0 is returned.
193 =cut
197 PARROT_EXPORT
198 INTVAL
199 Parrot_register_HLL_lib(PARROT_INTERP, ARGIN(STRING *hll_lib))
201 ASSERT_ARGS(Parrot_register_HLL_lib)
202 PMC *hll_info = interp->HLL_info;
203 const INTVAL nelements = VTABLE_elements(interp, hll_info);
204 INTVAL i;
206 for (i = 0; i < nelements; ++i) {
207 PMC * const entry = VTABLE_get_pmc_keyed_int(interp, hll_info, i);
208 PMC * const lib_name = VTABLE_get_pmc_keyed_int(interp, entry, e_HLL_lib);
210 if (!PMC_IS_NULL(lib_name)) {
211 const STRING * const lib_name_str = VTABLE_get_string(interp, lib_name);
212 if (Parrot_str_equal(interp, lib_name_str, hll_lib))
213 break;
217 if (i < nelements)
218 return i;
219 else {
220 PMC * const new_entry = new_hll_entry(interp, NULL);
221 PMC *name;
223 VTABLE_set_pmc_keyed_int(interp, new_entry, e_HLL_name, PMCNULL);
225 /* register dynlib */
226 name = Parrot_pmc_new_constant(interp, enum_class_String);
228 VTABLE_set_string_native(interp, name, hll_lib);
229 VTABLE_set_pmc_keyed_int(interp, new_entry, e_HLL_lib, name);
231 return 0;
237 =item C<INTVAL Parrot_get_HLL_id(PARROT_INTERP, STRING *hll_name)>
239 Returns the ID number of the HLL with the given name. The default HLL namespace
240 C<parrot> has an ID number of 0. On error, or if an HLL with the given name
241 does not exist, returns -1.
243 =cut
247 PARROT_EXPORT
248 PARROT_WARN_UNUSED_RESULT
249 INTVAL
250 Parrot_get_HLL_id(PARROT_INTERP, ARGIN_NULLOK(STRING *hll_name))
252 ASSERT_ARGS(Parrot_get_HLL_id)
253 PMC * entry;
254 PMC * const hll_info = interp->HLL_info;
255 INTVAL i = -1;
257 if (!hll_name)
258 return i;
260 START_READ_HLL_INFO(interp, hll_info);
262 entry = VTABLE_get_pmc_keyed_str(interp, hll_info, hll_name);
264 if (!PMC_IS_NULL(entry)) {
265 PMC * const entry_id = VTABLE_get_pmc_keyed_int(interp, entry, e_HLL_id);
266 i = VTABLE_get_integer(interp, entry_id);
269 END_READ_HLL_INFO(interp, hll_info);
271 return i;
276 =item C<STRING * Parrot_get_HLL_name(PARROT_INTERP, INTVAL id)>
278 Returns the STRING name of the HLL with the given C<id> number. If the id
279 is out of range or does not exist, the NULL value is returned instead. Note
280 that some HLLs are anonymous and so might also return NULL.
282 =cut
286 PARROT_EXPORT
287 PARROT_WARN_UNUSED_RESULT
288 PARROT_CAN_RETURN_NULL
289 STRING *
290 Parrot_get_HLL_name(PARROT_INTERP, INTVAL id)
292 ASSERT_ARGS(Parrot_get_HLL_name)
293 PMC * const hll_info = interp->HLL_info;
294 const INTVAL nelements = VTABLE_elements(interp, hll_info);
296 PMC *entry, *name_pmc;
298 if (id < 0 || id >= nelements)
299 return NULL;
301 START_READ_HLL_INFO(interp, hll_info);
303 entry = VTABLE_get_pmc_keyed_int(interp, hll_info, id);
304 name_pmc = VTABLE_get_pmc_keyed_int(interp, entry, e_HLL_name);
306 END_READ_HLL_INFO(interp, hll_info);
308 /* loadlib-created 'HLL's are nameless */
309 if (PMC_IS_NULL(name_pmc))
310 return NULL;
311 else
312 return VTABLE_get_string(interp, name_pmc);
317 =item C<void Parrot_register_HLL_type(PARROT_INTERP, INTVAL hll_id, INTVAL
318 core_type, INTVAL hll_type)>
320 Register a type mapping of C<< core_type => hll_type >> for the given HLL.
322 =cut
326 PARROT_EXPORT
327 void
328 Parrot_register_HLL_type(PARROT_INTERP, INTVAL hll_id,
329 INTVAL core_type, INTVAL hll_type)
331 ASSERT_ARGS(Parrot_register_HLL_type)
333 if (hll_id == Parrot_get_HLL_id(interp, CONST_STRING(interp, "parrot")))
334 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
335 "Cannot map without an HLL");
336 else {
337 PMC *hll_info = interp->HLL_info;
338 const INTVAL n = VTABLE_elements(interp, hll_info);
339 if (hll_id >= n)
340 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_GLOBAL_NOT_FOUND,
341 "no such HLL ID (%vd)", hll_id);
342 else {
343 PMC *type_hash;
344 PMC *entry = VTABLE_get_pmc_keyed_int(interp, hll_info, hll_id);
345 PARROT_ASSERT(!PMC_IS_NULL(entry));
346 type_hash = VTABLE_get_pmc_keyed_int(interp, entry, e_HLL_typemap);
347 PARROT_ASSERT(!PMC_IS_NULL(type_hash));
349 VTABLE_set_integer_keyed_int(interp, type_hash, core_type, hll_type);
356 =item C<INTVAL Parrot_get_HLL_type(PARROT_INTERP, INTVAL hll_id, INTVAL
357 core_type)>
359 Get an equivalent HLL type number for the language C<hll_id>. If the given HLL
360 doesn't remap the given type, or if C<hll_id> is the special value
361 C<PARROT_HLL_NONE>, returns C<core_type> unchanged.
363 =cut
367 PARROT_EXPORT
368 INTVAL
369 Parrot_get_HLL_type(PARROT_INTERP, INTVAL hll_id, INTVAL core_type)
371 ASSERT_ARGS(Parrot_get_HLL_type)
373 if (hll_id == PARROT_HLL_NONE || hll_id == 0)
374 return core_type;
376 if (hll_id < 0)
377 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_GLOBAL_NOT_FOUND,
378 "no such HLL ID (%vd)", hll_id);
379 else {
380 PMC * const hll_info = interp->HLL_info;
381 INTVAL id;
382 PMC *entry, *type_hash;
384 START_READ_HLL_INFO(interp, hll_info);
385 entry = VTABLE_get_pmc_keyed_int(interp, hll_info, hll_id);
386 END_READ_HLL_INFO(interp, hll_info);
388 if (PMC_IS_NULL(entry))
389 Parrot_ex_throw_from_c_args(interp, NULL,
390 EXCEPTION_GLOBAL_NOT_FOUND, "no such HLL ID (%vd)", hll_id);
392 type_hash = VTABLE_get_pmc_keyed_int(interp, entry, e_HLL_typemap);
394 if (PMC_IS_NULL(type_hash))
395 return core_type;
397 id = VTABLE_get_integer_keyed_int(interp, type_hash, core_type);
399 return id ? id : core_type;
405 =item C<INTVAL Parrot_get_ctx_HLL_type(PARROT_INTERP, INTVAL core_type)>
407 Return an equivalent PMC type number according to the HLL settings in
408 the current context. If no type is registered, returns C<core_type>.
410 =cut
414 PARROT_EXPORT
415 INTVAL
416 Parrot_get_ctx_HLL_type(PARROT_INTERP, INTVAL core_type)
418 ASSERT_ARGS(Parrot_get_ctx_HLL_type)
419 const INTVAL hll_id = Parrot_pcc_get_HLL(interp, CURRENT_CONTEXT(interp));
420 if (!hll_id || hll_id == PARROT_HLL_NONE)
421 return core_type;
423 return Parrot_get_HLL_type(interp, hll_id, core_type);
428 =item C<PMC* Parrot_get_ctx_HLL_namespace(PARROT_INTERP)>
430 Return root namespace of the current HLL.
432 =cut
436 PARROT_EXPORT
437 PARROT_WARN_UNUSED_RESULT
438 PARROT_CAN_RETURN_NULL
439 PMC*
440 Parrot_get_ctx_HLL_namespace(PARROT_INTERP)
442 ASSERT_ARGS(Parrot_get_ctx_HLL_namespace)
443 return Parrot_get_HLL_namespace(interp, Parrot_pcc_get_HLL(interp, CURRENT_CONTEXT(interp)));
448 =item C<PMC* Parrot_get_HLL_namespace(PARROT_INTERP, int hll_id)>
450 Return root namespace of the HLL with the ID of I<hll_id>. If C<hll_id> is the
451 special value C<PARROT_HLL_NONE>, return the global root namespace.
453 =cut
457 PARROT_EXPORT
458 PARROT_WARN_UNUSED_RESULT
459 PARROT_CAN_RETURN_NULL
460 PMC*
461 Parrot_get_HLL_namespace(PARROT_INTERP, int hll_id)
463 ASSERT_ARGS(Parrot_get_HLL_namespace)
464 if (hll_id == PARROT_HLL_NONE)
465 return interp->root_namespace;
467 return VTABLE_get_pmc_keyed_int(interp, interp->HLL_namespace, hll_id);
472 =item C<void Parrot_regenerate_HLL_namespaces(PARROT_INTERP)>
474 Create all HLL namespaces that don't already exist. This is necessary when
475 creating a new interpreter which shares an old interpreter's HLL_info.
477 =cut
481 PARROT_EXPORT
482 void
483 Parrot_regenerate_HLL_namespaces(PARROT_INTERP)
485 ASSERT_ARGS(Parrot_regenerate_HLL_namespaces)
486 const INTVAL n = VTABLE_elements(interp, interp->HLL_info);
487 INTVAL hll_id;
489 /* start at one since the 'parrot' namespace should already have been
490 * created */
492 for (hll_id = 1; hll_id < n; ++hll_id) {
493 PMC *ns_hash =
494 VTABLE_get_pmc_keyed_int(interp, interp->HLL_namespace, hll_id);
496 if (PMC_IS_NULL(ns_hash) ||
497 ns_hash->vtable->base_type == enum_class_Undef)
499 STRING * hll_name = Parrot_get_HLL_name(interp, hll_id);
500 if (!hll_name)
501 continue;
503 hll_name = Parrot_str_downcase(interp, hll_name);
505 /* XXX as in Parrot_register_HLL() this needs to be fixed to use
506 * the correct type of namespace. It's relatively easy to do that
507 * here because the typemap already exists, but it is not currently
508 * done for consistency.
510 ns_hash = Parrot_ns_make_namespace_keyed_str(interp,
511 interp->root_namespace, hll_name);
513 VTABLE_set_pmc_keyed_int(interp, interp->HLL_namespace,
514 hll_id, ns_hash);
521 =back
523 =head1 AUTHOR
525 Leopold Toetsch
527 =cut
533 * Local variables:
534 * c-file-style: "parrot"
535 * End:
536 * vim: expandtab shiftwidth=4: