This repository has been archived by the owner on Feb 3, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
knowhow_bootstrapper.c
145 lines (124 loc) · 6.58 KB
/
knowhow_bootstrapper.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* Contains the logic that bootstraps KnowHOW, the foundation for implementing
* the various other bits of the object model. Works in conjunction with
* KnowHOWREPR. */
#define PARROT_IN_EXTENSION
#include "parrot/parrot.h"
#include "parrot/extend.h"
#include "rakudoobject.h"
#include "repr_registry.h"
#include "reprs/KnowHOWREPR.h"
/* Cached string constants. */
static STRING *repr_str = NULL;
static STRING *p6opaque_str = NULL;
/* Creates a new type with this HOW as its meta-object. */
static void new_type(PARROT_INTERP, PMC *nci) {
/* We first create a new HOW instance. */
PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
PMC *self = VTABLE_get_pmc_keyed_int(interp, capture, 0);
PMC *HOW = REPR(self)->instance_of(interp, REPR_PMC(self), STABLE(self)->WHAT);
/* See if we have a representation name; if not default to P6opaque. */
STRING *repr_name = VTABLE_exists_keyed_str(interp, capture, repr_str) ?
VTABLE_get_string_keyed_str(interp, capture, repr_str) :
p6opaque_str;
/* Create a new type object of the desired REPR. (Note that we can't
* default to KnowHOWREPR here, since it doesn't know how to actually
* store attributes, it's just for bootstrapping knowhow's. */
PMC *repr_to_use = REPR_get_by_name(interp, repr_name);
PMC *type_object = REPR_STRUCT(repr_to_use)->type_object_for(interp, repr_to_use, HOW);
/* Put it into capture to act as return value. */
Parrot_pcc_build_call_from_c_args(interp, capture, "P", type_object);
}
/* Adds a method. */
static void add_method(PARROT_INTERP, PMC *nci) {
/* Get methods table out of meta-object. */
PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
PMC *self = VTABLE_get_pmc_keyed_int(interp, capture, 0);
PMC *methods = ((KnowHOWREPRInstance *)PMC_data(self))->methods;
/* Get name and method to add. */
STRING *name = VTABLE_get_string_keyed_int(interp, capture, 2);
PMC *method = VTABLE_get_pmc_keyed_int(interp, capture, 3);
/* Add it, and return added method as result. */
VTABLE_set_pmc_keyed_str(interp, methods, name, method);
Parrot_pcc_build_call_from_c_args(interp, capture, "P", method);
}
/* Finds a method. */
static void find_method(PARROT_INTERP, PMC *nci) {
/* Get methods table out of meta-object and look up method. */
PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
PMC *self = VTABLE_get_pmc_keyed_int(interp, capture, 0);
PMC *methods = ((KnowHOWREPRInstance *)PMC_data(self))->methods;
STRING *name = VTABLE_get_string_keyed_int(interp, capture, 2);
PMC *method = VTABLE_get_pmc_keyed_str(interp, methods, name);
if (PMC_IS_NULL(method))
/* XXX Awesomeize. */
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"Could not find method '%Ss'", name);
/* Put into capture to act as return value. */
Parrot_pcc_build_call_from_c_args(interp, capture, "P", method);
}
/* Composes the meta-object. */
static void compose(PARROT_INTERP, PMC *nci) {
PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
PMC *obj = VTABLE_get_pmc_keyed_int(interp, capture, 1);
Parrot_pcc_build_call_from_c_args(interp, capture, "P", obj);
}
/* Wraps up a C function as a raw NCI method. */
static PMC * wrap_c(PARROT_INTERP, void *func) {
PMC * const wrapped = Parrot_pmc_new(interp, enum_class_NativePCCMethod);
VTABLE_set_pointer_keyed_str(interp, wrapped, Parrot_str_new_constant(interp, "->"), func);
return wrapped;
}
/* This is the find_method where things eventually bottom out. */
static PMC * bottom_find_method(PARROT_INTERP, PMC *obj, STRING *name, INTVAL hint) {
PMC *methods = ((KnowHOWREPRInstance *)PMC_data(obj))->methods;
PMC *method = VTABLE_get_pmc_keyed_str(interp, methods, name);
if (PMC_IS_NULL(method))
/* XXX Awesomeize. */
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"Could not find method '%Ss'", name);
return method;
}
/* Bootstraps the KnowHOW. This is were things "bottom out" in the meta-model
* so it's a tad loopy. Basically, we create a KnowHOW type object. We then
* create an instance from that and add a bunch of methods to it. */
void RakudoObject_bootstrap_knowhow(PARROT_INTERP) {
/* Create our KnowHOW type object. Note we don't have a HOW just yet, so
* pass in null. */
PMC *REPR = REPR_get_by_name(interp, Parrot_str_new_constant(interp, "KnowHOWREPR"));
PMC *knowhow_pmc = REPR_STRUCT(REPR)->type_object_for(interp, REPR, PMCNULL);
/* We create a KnowHOW instance that can describe itself. This means
* .HOW.HOW.HOW.HOW etc will always return that, which closes the model
* up. Also pull out its underlying struct. */
PMC *knowhow_how_pmc = REPR_STRUCT(REPR)->instance_of(interp, REPR, knowhow_pmc);
KnowHOWREPRInstance *knowhow_how = (KnowHOWREPRInstance *)PMC_data(knowhow_how_pmc);
/* Need to give the knowhow_how a twiddled STable with a different
* dispatcher, so things bottom out. */
PMC *st_copy = create_stable(interp, REPR, knowhow_how_pmc);
STABLE_STRUCT(st_copy)->WHAT = knowhow_pmc;
STABLE_STRUCT(st_copy)->find_method = bottom_find_method;
knowhow_how->common.stable = st_copy;
/* Add various methods to the KnowHOW's HOW. */
VTABLE_set_pmc_keyed_str(interp, knowhow_how->methods,
Parrot_str_new_constant(interp, "new_type"),
wrap_c(interp, F2DPTR(new_type)));
VTABLE_set_pmc_keyed_str(interp, knowhow_how->methods,
Parrot_str_new_constant(interp, "find_method"),
wrap_c(interp, F2DPTR(find_method)));
VTABLE_set_pmc_keyed_str(interp, knowhow_how->methods,
Parrot_str_new_constant(interp, "add_method"),
wrap_c(interp, F2DPTR(add_method)));
VTABLE_set_pmc_keyed_str(interp, knowhow_how->methods,
Parrot_str_new_constant(interp, "compose"),
wrap_c(interp, F2DPTR(compose)));
/* Set this built up HOW as the KnowHOW's HOW. */
STABLE(knowhow_pmc)->HOW = knowhow_how_pmc;
/* Set up some string constants that the methods here use. */
repr_str = Parrot_str_new_constant(interp, "repr");
p6opaque_str = Parrot_str_new_constant(interp, "P6opaque");
/* Install KnowHOW into the root Parrot namespace, since that's where NQP
* lives.
* XXX We'll likely want to change this in the future. */
Parrot_ns_set_global(interp, Parrot_get_ctx_HLL_namespace(interp),
Parrot_str_new_constant(interp, "KnowHOW"),
knowhow_pmc);
}