/
bound_nci.pmc
132 lines (93 loc) · 2.96 KB
/
bound_nci.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
/*
Copyright (C) 2001-2008, Parrot Foundation.
$Id$
=head1 NAME
src/pmc/bound_nci.pmc - Bound internal method
=head1 DESCRIPTION
A bound internal method is a NCI method call, where the object is
bound to this call instance.
=head2 Methods
=over 4
=cut
*/
#include "parrot/parrot.h"
pmclass Bound_NCI extends NCI need_ext {
/*
=item C<void set_pmc(PMC *obj)>
Bind the object C<obj> to this call instance.
=item C<PMC *get_pmc(void)>
Return the bound object.
=item C<opcode_t *invoke(void *next)>
Calls the associated C method, returning C<*next>.
=item C<void mark()>
Set the bound object live.
=cut
*/
VTABLE void set_pmc(PMC *obj) {
PMC_pmc_val(SELF) = obj;
if (!PMC_IS_NULL(obj))
PObj_custom_mark_SET(SELF);
}
VTABLE PMC *get_pmc() {
return PMC_pmc_val(SELF);
}
VTABLE opcode_t *invoke(void *next) {
if (PObj_get_FLAGS(SELF) & PObj_private0_FLAG) {
/* bound multi sub
* XXX maybe create separate PMC class
* see also src/pmc/default.pmc:get_attr_str()
* */
PMC *multi = (PMC *)PMC_struct_val(SELF);
next = VTABLE_invoke(INTERP, multi, next);
}
else {
/* Locate register holding invocant. */
int sig_const = interp->current_args[1];
PMC *sig = CONTEXT(interp)->constants[sig_const]->u.key;
if (PMC_IS_NULL(sig))
Parrot_ex_throw_from_c_args(interp, NULL,
EXCEPTION_INVALID_OPERATION,
"Bound NCI call made, but no current signature found.");
ASSERT_SIG_PMC(sig);
/* Get invocant register. */
if (VTABLE_elements(INTERP, sig) > 0 &&
VTABLE_get_integer_keyed_int(INTERP, sig, 0) &
PARROT_ARG_PMC) {
int invocant_reg = interp->current_args[2];
PMC *p2 = REG_PMC(interp, invocant_reg);
INTERP->current_object = REG_PMC(interp, invocant_reg)
= PMC_pmc_val(SELF);
SUPER(next);
REG_PMC(interp, invocant_reg) = p2;
}
else {
Parrot_ex_throw_from_c_args(interp, NULL,
EXCEPTION_INVALID_OPERATION, "Bound NCI call made, "
"but the current call has no invocant.");
}
}
return (opcode_t *)next;
}
VTABLE void mark() {
if (PMC_pmc_val(SELF))
pobject_lives(INTERP, (PObj *)PMC_pmc_val(SELF));
if (PObj_get_FLAGS(SELF) & PObj_private0_FLAG) {
if (PMC_struct_val(SELF))
pobject_lives(INTERP, (PObj *)PMC_struct_val(SELF));
}
}
}
/*
=back
=head1 SEE ALSO
F<src/pmc/nci.pmc>
=head1 HISTORY
Initial revision by leo 2005.01.31.
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4:
*/