2 Copyright (C) 2005-2009, Parrot Foundation.
7 src/hll.c - High Level Language support
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
20 [ hll_name, hll_lib, { core_type => HLL_type, ... }, namespace, hll_id ],
32 #include "parrot/parrot.h"
33 #include "parrot/dynext.h"
34 #include "pmc/pmc_context.h"
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)
55 #define START_WRITE_HLL_INFO(interp, hll_info) \
57 if (PObj_is_PMC_shared_TEST(hll_info) && PMC_sync((interp)->HLL_info)) { \
58 (hll_info) = (interp)->HLL_info = \
59 Parrot_clone((interp), (interp)->HLL_info); \
60 if (PMC_sync((interp)->HLL_info)) \
61 mem_internal_free(PMC_sync((interp)->HLL_info)); \
64 #define END_WRITE_HLL_INFO(interp, hll_info)
69 =item C<static PMC* new_hll_entry(PARROT_INTERP, STRING *entry_name)>
71 Create a new HLL information table entry.
72 Takes an interpreter name and (optional) entry name.
73 Returns a pointer to the new entry.
74 Used by Parrot_register_HLL and Parrot_register_HLL_lib.
80 PARROT_CANNOT_RETURN_NULL
81 PARROT_WARN_UNUSED_RESULT
83 new_hll_entry(PARROT_INTERP
, ARGIN_NULLOK(STRING
*entry_name
))
85 ASSERT_ARGS(new_hll_entry
)
86 PMC
* const hll_info
= interp
->HLL_info
;
87 const INTVAL id
= VTABLE_elements(interp
, hll_info
);
91 PMC
* const entry
= constant_pmc_new(interp
, enum_class_FixedPMCArray
);
93 if (entry_name
&& !STRING_IS_EMPTY(entry_name
)) {
94 VTABLE_set_pmc_keyed_str(interp
, hll_info
, entry_name
, entry
);
97 VTABLE_push_pmc(interp
, hll_info
, entry
);
99 VTABLE_set_integer_native(interp
, entry
, e_HLL_MAX
);
101 entry_id
= constant_pmc_new(interp
, enum_class_Integer
);
102 VTABLE_set_integer_native(interp
, entry_id
, id
);
103 VTABLE_set_pmc_keyed_int(interp
, entry
, e_HLL_id
, entry_id
);
111 =item C<void Parrot_init_HLL(PARROT_INTERP)>
113 Initialises the HLL_info and HLL_namespace fields of the interpreter structure.
114 Registers the default HLL namespace "parrot".
121 Parrot_init_HLL(PARROT_INTERP
)
123 ASSERT_ARGS(Parrot_init_HLL
)
125 pmc_new(interp
, enum_class_OrderedHash
);
126 interp
->HLL_namespace
=
127 constant_pmc_new(interp
, enum_class_ResizablePMCArray
);
129 Parrot_register_HLL(interp
, CONST_STRING(interp
, "parrot"));
134 =item C<INTVAL Parrot_register_HLL(PARROT_INTERP, STRING *hll_name)>
136 Register the HLL with the given STRING name C<hll_name> in the interpreter.
138 If the HLL has already been registered, the ID of the HLL is returned.
139 Otherwise the HLL is registered, a corresponding HLL namespace is created,
140 and the HLL ID is returned.
142 If there is an error, C<-1> is returned.
150 Parrot_register_HLL(PARROT_INTERP
, ARGIN(STRING
*hll_name
))
152 ASSERT_ARGS(Parrot_register_HLL
)
153 PMC
*entry
, *name
, *type_hash
, *ns_hash
, *hll_info
;
156 /* TODO LOCK or disallow in threads */
158 idx
= Parrot_get_HLL_id(interp
, hll_name
);
163 hll_info
= interp
->HLL_info
;
165 START_WRITE_HLL_INFO(interp
, hll_info
);
167 idx
= VTABLE_elements(interp
, hll_info
);
168 entry
= new_hll_entry(interp
, hll_name
);
170 /* register HLL name */
171 name
= constant_pmc_new(interp
, enum_class_String
);
173 VTABLE_set_string_native(interp
, name
, hll_name
);
174 VTABLE_set_pmc_keyed_int(interp
, entry
, e_HLL_name
, name
);
176 /* create HLL namespace using the *constant* name */
177 hll_name
= Parrot_str_downcase(interp
, VTABLE_get_string(interp
, name
));
179 /* HLL type mappings aren't yet created, we can't create
180 * a namespace in HLL's flavor yet - maybe promote the
181 * ns_hash to another type, if mappings provide one
184 ns_hash
= Parrot_make_namespace_keyed_str(interp
, interp
->root_namespace
,
187 /* cache HLL's toplevel namespace */
188 VTABLE_set_pmc_keyed_int(interp
, interp
->HLL_namespace
, idx
, ns_hash
);
190 /* create HLL typemap hash */
191 type_hash
= constant_pmc_new(interp
, enum_class_Hash
);
192 VTABLE_set_pointer(interp
, type_hash
, parrot_new_intval_hash(interp
));
193 VTABLE_set_pmc_keyed_int(interp
, entry
, e_HLL_typemap
, type_hash
);
196 END_WRITE_HLL_INFO(interp
, hll_info
);
203 =item C<INTVAL Parrot_register_HLL_lib(PARROT_INTERP, STRING *hll_lib)>
205 Register an HLL library.
206 Takes a pointer to a library name STRING to add. If the name has already
207 been registered the list position of the library in the HLL Info list is
208 returned. Otherwise, the library is added to the list and 0 is returned.
216 Parrot_register_HLL_lib(PARROT_INTERP
, ARGIN(STRING
*hll_lib
))
218 ASSERT_ARGS(Parrot_register_HLL_lib
)
219 PMC
*hll_info
= interp
->HLL_info
;
223 START_WRITE_HLL_INFO(interp
, hll_info
);
225 nelements
= VTABLE_elements(interp
, hll_info
);
227 for (i
= 0; i
< nelements
; ++i
) {
228 PMC
* const entry
= VTABLE_get_pmc_keyed_int(interp
, hll_info
, i
);
229 PMC
* const lib_name
= VTABLE_get_pmc_keyed_int(interp
, entry
, e_HLL_lib
);
231 if (!PMC_IS_NULL(lib_name
)) {
232 const STRING
* const name
= VTABLE_get_string(interp
, lib_name
);
233 if (Parrot_str_equal(interp
, name
, hll_lib
))
241 entry
= new_hll_entry(interp
, NULL
);
243 VTABLE_set_pmc_keyed_int(interp
, entry
, e_HLL_name
, PMCNULL
);
245 /* register dynlib */
246 name
= constant_pmc_new(interp
, enum_class_String
);
248 VTABLE_set_string_native(interp
, name
, hll_lib
);
249 VTABLE_set_pmc_keyed_int(interp
, entry
, e_HLL_lib
, name
);
251 END_WRITE_HLL_INFO(interp
, hll_info
);
258 =item C<INTVAL Parrot_get_HLL_id(PARROT_INTERP, STRING *hll_name)>
260 Returns the ID number of the HLL with the given name. The default HLL namespace
261 C<parrot> has an ID number of 0. On error, or if an HLL with the given name
262 does not exist, returns -1.
269 PARROT_WARN_UNUSED_RESULT
271 Parrot_get_HLL_id(PARROT_INTERP
, ARGIN_NULLOK(STRING
*hll_name
))
273 ASSERT_ARGS(Parrot_get_HLL_id
)
274 PMC
* const hll_info
= interp
->HLL_info
;
277 START_READ_HLL_INFO(interp
, hll_info
);
279 if (!hll_name
|| !VTABLE_exists_keyed_str(interp
, hll_info
, hll_name
))
282 PMC
* const entry
= VTABLE_get_pmc_keyed_str(interp
, hll_info
, hll_name
);
283 PMC
* const entry_id
= VTABLE_get_pmc_keyed_int(interp
, entry
, e_HLL_id
);
284 i
= VTABLE_get_integer(interp
, entry_id
);
287 END_READ_HLL_INFO(interp
, hll_info
);
294 =item C<STRING * Parrot_get_HLL_name(PARROT_INTERP, INTVAL id)>
296 Returns the STRING name of the HLL with the given C<id> number. If the id
297 is out of range or does not exist, the NULL value is returned instead. Note
298 that some HLLs are anonymous and so might also return NULL.
305 PARROT_WARN_UNUSED_RESULT
306 PARROT_CAN_RETURN_NULL
308 Parrot_get_HLL_name(PARROT_INTERP
, INTVAL id
)
310 ASSERT_ARGS(Parrot_get_HLL_name
)
311 PMC
* const hll_info
= interp
->HLL_info
;
312 const INTVAL nelements
= VTABLE_elements(interp
, hll_info
);
314 PMC
*entry
, *name_pmc
;
316 if (id
< 0 || id
>= nelements
)
319 START_READ_HLL_INFO(interp
, hll_info
);
321 entry
= VTABLE_get_pmc_keyed_int(interp
, hll_info
, id
);
322 name_pmc
= VTABLE_get_pmc_keyed_int(interp
, entry
, e_HLL_name
);
324 END_READ_HLL_INFO(interp
, hll_info
);
326 /* loadlib-created 'HLL's are nameless */
327 if (PMC_IS_NULL(name_pmc
))
330 return VTABLE_get_string(interp
, name_pmc
);
335 =item C<void Parrot_register_HLL_type(PARROT_INTERP, INTVAL hll_id, INTVAL
336 core_type, INTVAL hll_type)>
338 Register a type mapping of C<< core_type => hll_type >> for the given HLL.
346 Parrot_register_HLL_type(PARROT_INTERP
, INTVAL hll_id
,
347 INTVAL core_type
, INTVAL hll_type
)
349 ASSERT_ARGS(Parrot_register_HLL_type
)
350 PMC
*entry
, *type_hash
;
351 PMC
*hll_info
= interp
->HLL_info
;
352 const INTVAL n
= VTABLE_elements(interp
, hll_info
);
355 Parrot_ex_throw_from_c_args(interp
, NULL
, EXCEPTION_GLOBAL_NOT_FOUND
,
356 "no such HLL ID (%vd)", hll_id
);
358 /* the type might already be registered in a non-conflicting way, in which
359 * ca se we can avoid copying */
360 if (PObj_is_PMC_shared_TEST(hll_info
) && PMC_sync(hll_info
)) {
361 if (hll_type
== Parrot_get_HLL_type(interp
, hll_id
, core_type
))
365 START_WRITE_HLL_INFO(interp
, hll_info
);
367 entry
= VTABLE_get_pmc_keyed_int(interp
, hll_info
, hll_id
);
368 PARROT_ASSERT(!PMC_IS_NULL(entry
));
370 type_hash
= VTABLE_get_pmc_keyed_int(interp
, entry
, e_HLL_typemap
);
371 PARROT_ASSERT(!PMC_IS_NULL(type_hash
));
373 VTABLE_set_integer_keyed_int(interp
, type_hash
, core_type
, hll_type
);
375 END_WRITE_HLL_INFO(interp
, hll_info
);
380 =item C<INTVAL Parrot_get_HLL_type(PARROT_INTERP, INTVAL hll_id, INTVAL
383 Get an equivalent HLL type number for the language C<hll_id>. If the given HLL
384 doesn't remap the given type, or if C<hll_id> is the special value
385 C<PARROT_HLL_NONE>, returns C<core_type> unchanged.
393 Parrot_get_HLL_type(PARROT_INTERP
, INTVAL hll_id
, INTVAL core_type
)
395 ASSERT_ARGS(Parrot_get_HLL_type
)
396 PMC
*entry
, *type_hash
, *hll_info
;
399 if (hll_id
== PARROT_HLL_NONE
|| hll_id
== 0)
403 Parrot_ex_throw_from_c_args(interp
, NULL
, EXCEPTION_GLOBAL_NOT_FOUND
,
404 "no such HLL ID (%vd)", hll_id
);
406 hll_info
= interp
->HLL_info
;
407 n
= VTABLE_elements(interp
, hll_info
);
410 Parrot_ex_throw_from_c_args(interp
, NULL
, EXCEPTION_GLOBAL_NOT_FOUND
,
411 "no such HLL ID (%vd)", hll_id
);
413 START_READ_HLL_INFO(interp
, hll_info
);
414 entry
= VTABLE_get_pmc_keyed_int(interp
, hll_info
, hll_id
);
415 END_READ_HLL_INFO(interp
, hll_info
);
417 type_hash
= VTABLE_get_pmc_keyed_int(interp
, entry
, e_HLL_typemap
);
419 if (PMC_IS_NULL(type_hash
))
422 id
= VTABLE_get_integer_keyed_int(interp
, type_hash
, core_type
);
424 return id
? id
: core_type
;
429 =item C<INTVAL Parrot_get_ctx_HLL_type(PARROT_INTERP, INTVAL core_type)>
431 Return an equivalent PMC type number according to the HLL settings in
432 the current context. If no type is registered, returns C<core_type>.
440 Parrot_get_ctx_HLL_type(PARROT_INTERP
, INTVAL core_type
)
442 ASSERT_ARGS(Parrot_get_ctx_HLL_type
)
443 const INTVAL hll_id
= Parrot_pcc_get_HLL(interp
, CURRENT_CONTEXT(interp
));
445 return Parrot_get_HLL_type(interp
, hll_id
, core_type
);
450 =item C<PMC* Parrot_get_ctx_HLL_namespace(PARROT_INTERP)>
452 Return root namespace of the current HLL.
459 PARROT_WARN_UNUSED_RESULT
460 PARROT_CAN_RETURN_NULL
462 Parrot_get_ctx_HLL_namespace(PARROT_INTERP
)
464 ASSERT_ARGS(Parrot_get_ctx_HLL_namespace
)
465 return Parrot_get_HLL_namespace(interp
, Parrot_pcc_get_HLL(interp
, CURRENT_CONTEXT(interp
)));
470 =item C<PMC* Parrot_get_HLL_namespace(PARROT_INTERP, int hll_id)>
472 Return root namespace of the HLL with the ID of I<hll_id>. If C<hll_id> is the
473 special value C<PARROT_HLL_NONE>, return the global root namespace.
480 PARROT_WARN_UNUSED_RESULT
481 PARROT_CAN_RETURN_NULL
483 Parrot_get_HLL_namespace(PARROT_INTERP
, int hll_id
)
485 ASSERT_ARGS(Parrot_get_HLL_namespace
)
486 if (hll_id
== PARROT_HLL_NONE
)
487 return interp
->root_namespace
;
489 return VTABLE_get_pmc_keyed_int(interp
, interp
->HLL_namespace
, hll_id
);
494 =item C<void Parrot_regenerate_HLL_namespaces(PARROT_INTERP)>
496 Create all HLL namespaces that don't already exist. This is necessary when
497 creating a new interpreter which shares an old interpreter's HLL_info.
505 Parrot_regenerate_HLL_namespaces(PARROT_INTERP
)
507 ASSERT_ARGS(Parrot_regenerate_HLL_namespaces
)
508 const INTVAL n
= VTABLE_elements(interp
, interp
->HLL_info
);
511 /* start at one since the 'parrot' namespace should already have been
514 for (hll_id
= 1; hll_id
< n
; ++hll_id
) {
516 VTABLE_get_pmc_keyed_int(interp
, interp
->HLL_namespace
, hll_id
);
518 if (PMC_IS_NULL(ns_hash
) ||
519 ns_hash
->vtable
->base_type
== enum_class_Undef
)
521 STRING
* const hll_name
= Parrot_get_HLL_name(interp
, hll_id
);
525 Parrot_str_downcase_inplace(interp
, hll_name
);
527 /* XXX as in Parrot_register_HLL() this needs to be fixed to use
528 * the correct type of namespace. It's relatively easy to do that
529 * here because the typemap already exists, but it is not currently
530 * done for consistency.
532 ns_hash
= Parrot_make_namespace_keyed_str(interp
,
533 interp
->root_namespace
, hll_name
);
535 VTABLE_set_pmc_keyed_int(interp
, interp
->HLL_namespace
,
556 * c-file-style: "parrot"
558 * vim: expandtab shiftwidth=4: