/
super.pmc
143 lines (96 loc) · 2.94 KB
/
super.pmc
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
/*
Copyright (C) 2005-2007, The Perl Foundation.
$Id$
=head1 NAME
src/pmc/super.pmc - Super Class
=head1 DESCRIPTION
A Super PMC holds an object and redirects method lookup to the parent
of the object's class.
=head1 SYNOPSIS
.sub meth :method
.local pmc s
s = new 'Super', self
s."meth"()
.end
=head2 Methods
=over 4
=cut
*/
#include "parrot/parrot.h"
pmclass Super need_ext {
/*
=item C<void init(PMC *obj)>
Create an unbound super instance.
=item C<void init_pmc(PMC *obj)>
Initialize a new super instance, bound to the C<obj>.
=item C<void set_pmc(PMC *obj)>
Bind the object C<obj> to this Super instance.
=item C<PMC *get_pmc(void)>
Return the bound object.
=item C<void mark()>
Set the bound object live.
=item C<PMC *find_method(STRING *name)>
Find the method for C<*name> in the parent class of the bound object.
=cut
*/
VTABLE void init() {
PMC_pmc_val(SELF) = PMCNULL;
PMC_struct_val(SELF) = PMCNULL;
}
VTABLE void init_pmc(PMC *obj) {
PMC_struct_val(SELF) = PMCNULL;
SELF.set_pmc(obj);
}
VTABLE void set_pmc(PMC *obj) {
PMC *mro, *classobj;
PMC_pmc_val(SELF) = obj;
if (PMC_IS_NULL(obj))
return;
if (PObj_is_object_TEST(obj)) {
classobj = VTABLE_get_class(interp, obj);
if (PMC_IS_NULL(classobj))
return;
mro = VTABLE_inspect_str(interp, classobj, CONST_STRING(interp, "all_parents"));
}
else {
mro = obj->vtable->mro;
}
if (PMC_IS_NULL(mro))
return;
if (VTABLE_elements(INTERP, mro) <= 1)
real_exception(INTERP, NULL, E_TypeError, "object has no parent");
PObj_custom_mark_SET(SELF);
}
VTABLE PMC *get_pmc() {
return PMC_pmc_val(SELF);
}
VTABLE void mark() {
if (PMC_pmc_val(SELF))
pobject_lives(INTERP, (PObj *)PMC_pmc_val(SELF));
if (PMC_struct_val(SELF))
pobject_lives(INTERP, (PObj *)PMC_struct_val(SELF));
}
VTABLE PMC *find_method(STRING *name) {
PMC *mro, *classobj, *parent_class, *parent_methods;
PMC *method = PMCNULL;
PMC * const obj = PMC_pmc_val(SELF);
if (PMC_IS_NULL(obj))
real_exception(INTERP, NULL, E_TypeError,
"no object bound to super");
classobj = VTABLE_get_class(interp, obj);
mro = VTABLE_inspect_str(interp, classobj, CONST_STRING(interp, "all_parents"));
parent_class = VTABLE_get_pmc_keyed_int(INTERP, mro, 1);
parent_methods = VTABLE_inspect_str(interp, parent_class, CONST_STRING(interp, "methods"));
if (VTABLE_exists_keyed_str(interp, parent_methods, name)) {
method = VTABLE_get_pmc_keyed_str(interp, parent_methods,
name);
}
return method;
}
}
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4:
*/