Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add API functions to get a class from an array, and to instantiate a …

…PMC given a class.
  • Loading branch information...
commit 6f90f7de3aaa345504537aed376fc5a48197dcd6 1 parent 778020f
@nol888 nol888 authored
View
21 include/parrot/api.h
@@ -178,6 +178,14 @@ Parrot_Int Parrot_api_load_language(
Parrot_String lang);
PARROT_API
+Parrot_Int Parrot_api_lookup_class(
+ Parrot_PMC interp_pmc,
+ Parrot_PMC key,
+ ARGOUT(Parrot_PMC * p_class))
+ __attribute__nonnull__(3)
+ FUNC_MODIFIES(* p_class);
+
+PARROT_API
Parrot_Int Parrot_api_make_interpreter(
Parrot_PMC parent,
Parrot_Int flags,
@@ -288,6 +296,8 @@ Parrot_Int Parrot_api_wrap_imcc_hack(
PARROT_ASSERT_ARG(filename) \
, PARROT_ASSERT_ARG(pbc))
#define ASSERT_ARGS_Parrot_api_load_language __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+#define ASSERT_ARGS_Parrot_api_lookup_class __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(p_class))
#define ASSERT_ARGS_Parrot_api_make_interpreter __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp))
#define ASSERT_ARGS_Parrot_api_ready_bytecode __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
@@ -475,6 +485,15 @@ Parrot_Int Parrot_api_pmc_get_string(
FUNC_MODIFIES(* str);
PARROT_API
+Parrot_Int Parrot_api_pmc_new_from_class(
+ Parrot_PMC interp_pmc,
+ Parrot_PMC p_class,
+ Parrot_PMC init,
+ ARGOUT(Parrot_PMC * pmc))
+ __attribute__nonnull__(4)
+ FUNC_MODIFIES(* pmc);
+
+PARROT_API
Parrot_Int Parrot_api_pmc_null(
Parrot_PMC interp_pmc,
ARGMOD(Parrot_PMC *pmctonull))
@@ -533,6 +552,8 @@ Parrot_Int Parrot_api_pmc_set_string(
PARROT_ASSERT_ARG(value))
#define ASSERT_ARGS_Parrot_api_pmc_get_string __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(str))
+#define ASSERT_ARGS_Parrot_api_pmc_new_from_class __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(pmc))
#define ASSERT_ARGS_Parrot_api_pmc_null __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(pmctonull))
#define ASSERT_ARGS_Parrot_api_pmc_set_float __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
View
84 src/embed/api.c
@@ -525,6 +525,90 @@ Parrot_api_set_compiler(Parrot_PMC interp_pmc, Parrot_String type,
/*
+=item C<Parrot_Int Parrot_api_lookup_class(Parrot_PMC interp_pmc, Parrot_PMC
+key, Parrot_PMC * p_class)>
+
+=cut
+
+*/
+
+PARROT_API
+Parrot_Int
+Parrot_api_lookup_class(Parrot_PMC interp_pmc, Parrot_PMC key, ARGOUT(Parrot_PMC * p_class))
+{
+ EMBED_API_CALLIN(interp_pmc, interp)
+ *p_class = PMCNULL;
+
+ if(PMC_IS_NULL(key))
+ Parrot_ex_throw_from_c_args(interp, NULL, 1, "Null key passed to get_class");
+
+ if (PObj_is_class_TEST(key))
+ *p_class = key;
+ else {
+ /* Fast select of behavior based on type of the lookup key */
+ switch (key->vtable->base_type) {
+ case enum_class_NameSpace:
+ *p_class = VTABLE_get_class(interp, key);
+ break;
+ case enum_class_String:
+ case enum_class_Key:
+ case enum_class_ResizableStringArray:
+ {
+ PMC * const hll_ns = VTABLE_get_pmc_keyed_int(interp, interp->HLL_namespace, Parrot_pcc_get_HLL(interp, CURRENT_CONTEXT(interp)));
+ PMC * const ns = Parrot_ns_get_namespace_keyed(interp, hll_ns, key);
+
+ if (!PMC_IS_NULL(ns))
+ *p_class = VTABLE_get_class(interp, ns);
+ }
+ default:
+ break;
+ }
+ }
+
+ /* If the PMCProxy doesn't exist yet for the given key, we look up the
+ type ID here and create a new one */
+ if (PMC_IS_NULL(*p_class)) {
+ INTVAL type;
+ const INTVAL base_type = key->vtable->base_type;
+ Parrot_PMC type_class;
+
+ /* This is a hack! All PMCs should be able to be handled through
+ a single codepath, and all of them should be able to avoid
+ stringification because it's so imprecise. */
+ if (base_type == enum_class_Key
+ || base_type == enum_class_ResizableStringArray
+ || base_type == enum_class_String)
+ type = Parrot_pmc_get_type(interp, key);
+ else
+ type = Parrot_pmc_get_type_str(interp, VTABLE_get_string(interp, key));
+
+ /* Check if not a PMC or invalid type number */
+ if (type > interp->n_vtable_max || type <= 0)
+ Parrot_ex_throw_from_c_args(interp, NULL, 1, "Could not find PMC, or invalid type.");
+
+ type_class = interp->vtables[type]->pmc_class;
+ if (type != enum_class_Class && type_class->vtable->base_type == enum_class_Class) {
+ *p_class = type_class;
+ }
+ else {
+ PMC * const parrot_hll = Parrot_ns_get_namespace_keyed_str(interp, interp->root_namespace, Parrot_str_new_constant(interp, "parrot"));
+ PMC * const pmc_ns = Parrot_ns_make_namespace_keyed_str(interp, parrot_hll, interp->vtables[type]->whoami);
+ PMC * proxy = VTABLE_get_class(interp, pmc_ns);
+
+ /* Create proxy if not found */
+ if (PMC_IS_NULL(proxy)) {
+ proxy = Parrot_pmc_new_init_int(interp, enum_class_PMCProxy, type);
+ Parrot_pcc_invoke_method_from_c_args(interp, pmc_ns, Parrot_str_new_constant(interp, "set_class"), "P->", proxy);
+ }
+ *p_class = proxy;
+ }
+ }
+
+ EMBED_API_CALLOUT(interp_pmc, interp)
+}
+
+/*
+
=back
=cut
View
9 src/embed/pmc.c
@@ -6,6 +6,15 @@
PARROT_API
Parrot_Int
+Parrot_api_pmc_new_from_class(Parrot_PMC interp_pmc, Parrot_PMC p_class, Parrot_PMC init, ARGOUT(Parrot_PMC * pmc))
+{
+ EMBED_API_CALLIN(interp_pmc, interp)
+ *pmc = VTABLE_instantiate(interp, p_class, init);
+ EMBED_API_CALLOUT(interp_pmc, interp)
+}
+
+PARROT_API
+Parrot_Int
Parrot_api_pmc_deserialize(Parrot_PMC interp_pmc, Parrot_String fpmc,
ARGOUT(Parrot_PMC * pmc))
{
View
79 t/src/embed/pmc.t
@@ -24,7 +24,7 @@ Tests PMC API support.
=cut
-plan tests => 2;
+plan tests => 3;
c_output_is( <<'CODE', <<'OUTPUT', "get/set_keyed_int" );
@@ -38,13 +38,13 @@ int main(int argc, char* argv[])
Parrot_Interp interp = Parrot_new(NULL);
Parrot_PMC interpmc = Parrot_pmc_new(interp, enum_class_ParrotInterpreter);
- Parrot_PMC p_str = Parrot_pmc_new(interp, enum_class_String), p_keyedstr = NULL;
+ Parrot_PMC p_pmc = Parrot_pmc_new(interp, enum_class_String), p_keyedstr = NULL;
Parrot_String s_teststr = NULL, s_outstr = NULL;
Parrot_api_string_import_ascii(interpmc, "I am a string.", &s_teststr);
- Parrot_api_pmc_set_string(interpmc, p_str, s_teststr);
+ Parrot_api_pmc_set_string(interpmc, p_pmc, s_teststr);
- Parrot_api_pmc_get_keyed_int(interpmc, p_str, 0, &p_keyedstr);
+ Parrot_api_pmc_get_keyed_int(interpmc, p_pmc, 0, &p_keyedstr);
Parrot_api_pmc_get_string(interpmc, p_keyedstr, &s_outstr);
if (strcmp(Parrot_str_to_cstring(interp, s_outstr), "I") != 0) {
printf("Failed indexing a String PMC\n");
@@ -56,8 +56,8 @@ int main(int argc, char* argv[])
Parrot_api_string_import_ascii(interpmc, "i", &s_teststr);
Parrot_api_pmc_set_string(interpmc, p_keyedstr, s_teststr);
- Parrot_api_pmc_set_keyed_int(interpmc, p_str, 0, p_keyedstr);
- Parrot_api_pmc_get_string(interpmc, p_str, &s_outstr);
+ Parrot_api_pmc_set_keyed_int(interpmc, p_pmc, 0, p_keyedstr);
+ Parrot_api_pmc_get_string(interpmc, p_pmc, &s_outstr);
if (strcmp(Parrot_str_to_cstring(interp, s_outstr), "i am a string.") != 0) {
printf("Failed int-index setting a String PMC\n");
@@ -66,7 +66,7 @@ int main(int argc, char* argv[])
printf("ok 2\n");
- Parrot_pmc_destroy(interp, p_str);
+ Parrot_pmc_destroy(interp, p_pmc);
Parrot_pmc_destroy(interp, p_keyedstr);
Parrot_pmc_destroy(interp, interpmc);
@@ -90,15 +90,15 @@ int main(int argc, char* argv[])
Parrot_Interp interp = Parrot_new(NULL);
Parrot_PMC interpmc = Parrot_pmc_new(interp, enum_class_ParrotInterpreter);
- Parrot_PMC p_str = Parrot_pmc_new(interp, enum_class_String), p_keyedstr = NULL, p_idx = Parrot_pmc_new(interp, enum_class_Integer);
+ Parrot_PMC p_pmc = Parrot_pmc_new(interp, enum_class_String), p_keyedstr = NULL, p_idx = Parrot_pmc_new(interp, enum_class_Integer);
Parrot_String s_teststr = NULL, s_outstr = NULL;
Parrot_api_string_import_ascii(interpmc, "I am a string.", &s_teststr);
- Parrot_api_pmc_set_string(interpmc, p_str, s_teststr);
+ Parrot_api_pmc_set_string(interpmc, p_pmc, s_teststr);
Parrot_api_pmc_set_integer(interpmc, p_idx, 1);
- Parrot_api_pmc_get_keyed(interpmc, p_str, p_idx, &p_keyedstr);
+ Parrot_api_pmc_get_keyed(interpmc, p_pmc, p_idx, &p_keyedstr);
Parrot_api_pmc_get_string(interpmc, p_keyedstr, &s_outstr);
if (strcmp(Parrot_str_to_cstring(interp, s_outstr), " ") != 0) {
printf("Failed indexing a String PMC\n");
@@ -112,8 +112,8 @@ int main(int argc, char* argv[])
Parrot_api_pmc_set_integer(interpmc, p_idx, 3);
- Parrot_api_pmc_set_keyed(interpmc, p_str, p_idx, p_keyedstr);
- Parrot_api_pmc_get_string(interpmc, p_str, &s_outstr);
+ Parrot_api_pmc_set_keyed(interpmc, p_pmc, p_idx, p_keyedstr);
+ Parrot_api_pmc_get_string(interpmc, p_pmc, &s_outstr);
if (strcmp(Parrot_str_to_cstring(interp, s_outstr), "I an a string.") != 0) {
printf("Failed PMC-index setting a String PMC\n");
@@ -122,7 +122,7 @@ int main(int argc, char* argv[])
printf("ok 2\n");
- Parrot_pmc_destroy(interp, p_str);
+ Parrot_pmc_destroy(interp, p_pmc);
Parrot_pmc_destroy(interp, p_keyedstr);
Parrot_pmc_destroy(interp, p_idx);
Parrot_pmc_destroy(interp, interpmc);
@@ -135,6 +135,59 @@ ok 1
ok 2
OUTPUT
+c_output_is( <<'CODE', <<'OUTPUT', "PMC lookup/instantiation" );
+
+#include <parrot/parrot.h>
+#include <parrot/embed.h>
+#include <parrot/api.h>
+#include <stdio.h>
+
+int main(int argc, char* argv[])
+{
+ Parrot_Interp interp = Parrot_new(NULL);
+ Parrot_PMC interpmc = Parrot_pmc_new(interp, enum_class_ParrotInterpreter);
+ Parrot_String s_str, s_str2;
+ Parrot_PMC p_key, p_class, p_pmc;
+
+ char* string_class[] = { "String" };
+ Parrot_api_build_argv_array(interpmc, 1, string_class, &p_key);
+
+ Parrot_api_lookup_class(interpmc, p_key, &p_class);
+ Parrot_api_pmc_new_from_class(interpmc, p_class, PMCNULL, &p_pmc);
+
+ Parrot_api_string_import_ascii(interpmc, "This is a string!", &s_str);
+ Parrot_api_pmc_set_string(interpmc, p_pmc, s_str);
+ Parrot_api_pmc_get_string(interpmc, p_pmc, &s_str2);
+ if (strcmp(Parrot_str_to_cstring(interp, s_str2), "This is a string!") != 0) {
+ printf("Failed instantiating, setting, and getting a String PMC\n");
+ return EXIT_FAILURE;
+ }
+
+ printf("ok 1\n");
+
+ char* float_class[] = { "Float" };
+ Parrot_api_build_argv_array(interpmc, 1, float_class, &p_key);
+
+ Parrot_api_lookup_class(interpmc, p_key, &p_class);
+ Parrot_api_pmc_new_from_class(interpmc, p_class, PMCNULL, &p_pmc);
+
+ Parrot_api_pmc_set_float(interpmc, p_pmc, 3.1415);
+ Parrot_api_pmc_get_string(interpmc, p_pmc, &s_str2);
+ if (strcmp(Parrot_str_to_cstring(interp, s_str2), "3.1415") != 0) {
+ printf("Failed instantiating, setting, and getting a Float PMC\n");
+ return EXIT_FAILURE;
+ }
+
+ Parrot_pmc_destroy(interp, p_key);
+ Parrot_pmc_destroy(interp, p_class);
+ Parrot_pmc_destroy(interp, p_pmc);
+
+ return 0;
+}
+CODE
+ok 1
+OUTPUT
+
# Local Variables:
# mode: cperl
# cperl-indent-level: 4
Please sign in to comment.
Something went wrong with that request. Please try again.