1 /* sub.h
2  *  Copyright (C) 2001-2008, Parrot Foundation.
3  *  Data Structure and Algorithms:
4  *     Subroutine, coroutine, closure and continuation structures
5  *     and related routines.
6  */
7 
8 #ifndef PARROT_SUB_H_GUARD
9 #define PARROT_SUB_H_GUARD
10 
11 #include "parrot/parrot.h"
12 
13 /*
14  * Subroutine flags
15  */
16 typedef enum {
17     /* runtime usage flags */
18     SUB_FLAG_CORO_FF      = PObj_private0_FLAG,
19     SUB_FLAG_C_HANDLER    = PObj_private0_FLAG, /* C exceptions only */
20     SUB_FLAG_TAILCALL     = PObj_private2_FLAG,
21     SUB_FLAG_GENERATOR    = PObj_private3_FLAG, /* unused old python pmcs */
22 
23     /* compile/loadtime usage flags */
24     /* from packfile */
25     SUB_FLAG_IS_OUTER     = PObj_private1_FLAG,
26     SUB_FLAG_PF_ANON      = PObj_private3_FLAG,
27     SUB_FLAG_PF_MAIN      = PObj_private4_FLAG,
28     SUB_FLAG_PF_LOAD      = PObj_private5_FLAG,
29     SUB_FLAG_PF_IMMEDIATE = PObj_private6_FLAG,
30     SUB_FLAG_PF_POSTCOMP  = PObj_private7_FLAG,
31 
32     SUB_FLAG_PF_MASK      = SUB_FLAG_PF_ANON
33                           | SUB_FLAG_PF_LOAD
34                           | SUB_FLAG_PF_IMMEDIATE
35                           | SUB_FLAG_PF_POSTCOMP
36 } sub_flags_enum;
37 
38 #define SUB_FLAG_get_FLAGS(o) (PObj_get_FLAGS(o))
39 #define SUB_FLAG_flag_TEST(flag, o) (SUB_FLAG_get_FLAGS(o) & SUB_FLAG_ ## flag)
40 #define SUB_FLAG_flag_SET(flag, o) (SUB_FLAG_get_FLAGS(o) |= SUB_FLAG_ ## flag)
41 #define SUB_FLAG_flag_CLEAR(flag, o) (SUB_FLAG_get_FLAGS(o) &= ~(UINTVAL)(SUB_FLAG_ ## flag))
42 
43 #define SUB_FLAG_flags_SETTO(o, f) SUB_FLAG_get_FLAGS(o) = (f)
44 #define SUB_FLAG_flags_CLEARALL(o) SUB_FLAG_flags_SETTO((o), 0)
45 
46 #define SUB_FLAG_TAILCALL_TEST(o)   SUB_FLAG_flag_TEST(TAILCALL, (o))
47 #define SUB_FLAG_TAILCALL_ISSET(o)  SUB_FLAG_flag_TEST(TAILCALL, (o))
48 #define SUB_FLAG_TAILCALL_NOTSET(o) (!SUB_FLAG_flag_TEST(TAILCALL, (o)))
49 #define SUB_FLAG_TAILCALL_SET(o)    SUB_FLAG_flag_SET(TAILCALL, (o))
50 #define SUB_FLAG_TAILCALL_CLEAR(o)  SUB_FLAG_flag_CLEAR(TAILCALL, (o))
51 
52 #define SUB_FLAG(n) ((UINTVAL)1 << (n))
53 typedef enum {
54     SUB_COMP_FLAG_BIT_0     = SUB_FLAG(0),
55     SUB_COMP_FLAG_BIT_1     = SUB_FLAG(1),
56     SUB_COMP_FLAG_VTABLE    = SUB_COMP_FLAG_BIT_1,
57     SUB_COMP_FLAG_BIT_2     = SUB_FLAG(2),
58     SUB_COMP_FLAG_METHOD    = SUB_COMP_FLAG_BIT_2,
59     SUB_COMP_FLAG_BIT_3     = SUB_FLAG(3),
60     SUB_COMP_FLAG_BIT_4     = SUB_FLAG(4),
61     SUB_COMP_FLAG_BIT_5     = SUB_FLAG(5),
62     SUB_COMP_FLAG_BIT_6     = SUB_FLAG(6),
63     SUB_COMP_FLAG_BIT_7     = SUB_FLAG(7),
64     SUB_COMP_FLAG_BIT_8     = SUB_FLAG(8),
65     SUB_COMP_FLAG_BIT_9     = SUB_FLAG(9),
66     SUB_COMP_FLAG_BIT_10    = SUB_FLAG(10),
67     SUB_COMP_FLAG_PF_INIT   = SUB_COMP_FLAG_BIT_10,
68     SUB_COMP_FLAG_BIT_11    = SUB_FLAG(11),
69     SUB_COMP_FLAG_NSENTRY   = SUB_COMP_FLAG_BIT_11,
70     SUB_COMP_FLAG_BIT_12    = SUB_FLAG(12),
71     SUB_COMP_FLAG_BIT_13    = SUB_FLAG(13),
72     SUB_COMP_FLAG_BIT_14    = SUB_FLAG(14),
73     SUB_COMP_FLAG_BIT_15    = SUB_FLAG(15),
74     SUB_COMP_FLAG_BIT_16    = SUB_FLAG(16),
75     SUB_COMP_FLAG_BIT_17    = SUB_FLAG(17),
76     SUB_COMP_FLAG_BIT_18    = SUB_FLAG(18),
77     SUB_COMP_FLAG_BIT_19    = SUB_FLAG(19),
78     SUB_COMP_FLAG_BIT_20    = SUB_FLAG(20),
79     SUB_COMP_FLAG_BIT_21    = SUB_FLAG(21),
80     SUB_COMP_FLAG_BIT_22    = SUB_FLAG(22),
81     SUB_COMP_FLAG_BIT_23    = SUB_FLAG(23),
82     SUB_COMP_FLAG_BIT_24    = SUB_FLAG(24),
83     SUB_COMP_FLAG_BIT_25    = SUB_FLAG(25),
84     SUB_COMP_FLAG_BIT_26    = SUB_FLAG(26),
85     SUB_COMP_FLAG_BIT_27    = SUB_FLAG(27),
86     SUB_COMP_FLAG_BIT_28    = SUB_FLAG(28),
87     SUB_COMP_FLAG_BIT_29    = SUB_FLAG(29),
88     SUB_COMP_FLAG_BIT_30    = SUB_FLAG(30),
89     SUB_COMP_FLAG_MASK      = SUB_COMP_FLAG_VTABLE | SUB_COMP_FLAG_METHOD
90                                 | SUB_COMP_FLAG_NSENTRY | SUB_COMP_FLAG_PF_INIT
91 } sub_comp_flags_enum;
92 #undef SUB_FLAG
93 
94 #define Sub_comp_get_FLAGS(o) ((o)->comp_flags)
95 #define Sub_comp_flag_TEST(flag, o) (Sub_comp_get_FLAGS(o) & SUB_COMP_FLAG_ ## flag)
96 #define Sub_comp_flag_SET(flag, o) (Sub_comp_get_FLAGS(o) |= SUB_COMP_FLAG_ ## flag)
97 #define Sub_comp_flag_CLEAR(flag, o) (Sub_comp_get_FLAGS(o) &= ~(UINTVAL)(SUB_COMP_FLAG_ ## flag))
98 
99 #define Sub_comp_flags_SETTO(o, f) Sub_comp_get_FLAGS(o) = (f)
100 #define Sub_comp_flags_CLEARALL(o) Sub_comp_flags_SETTO((o), 0)
101 
102 #define Sub_comp_INIT_TEST(o) Sub_comp_flag_TEST(PF_INIT, o)
103 #define Sub_comp_INIT_SET(o) Sub_comp_flag_SET(PF_INIT, o)
104 #define Sub_comp_INIT_CLEAR(o) Sub_comp_flag_CLEAR(PF_INIT, o)
105 
106 /*
107  * maximum sub recursion depth
108  */
109 
110 #define RECURSION_LIMIT 1000
111 
112 
113 /*
114  * Counts and flags describing the arguments.
115  */
116 typedef struct Parrot_sub_arginfo {
117     Parrot_UInt2 pos_required;
118     Parrot_UInt2 pos_optional;
119     Parrot_UInt2 named_required;
120     Parrot_UInt2 named_optional;
121     Parrot_UInt1 pos_slurpy;
122     Parrot_UInt1 named_slurpy;
123 } Parrot_sub_arginfo;
124 
125 #define PMC_get_sub(interp, pmc, sub) \
126     do { \
127         const INTVAL type = (pmc)->vtable->base_type; \
128         if (type == enum_class_Sub || \
129             type == enum_class_Coroutine) \
130         {\
131             (sub) = PARROT_SUB((pmc)); \
132         } \
133         else { \
134             (sub) = (Parrot_Sub_attributes*)Parrot_get_sub_pmc_from_subclass((interp), (pmc)); \
135         } \
136     } while (0)
137 
138 typedef struct Parrot_Sub_attributes Parrot_sub;
139 typedef struct Parrot_Coroutine_attributes Parrot_coro;
140 typedef struct Parrot_Continuation_attributes Parrot_cont;
141 
142 #define PMC_cont(pmc) PARROT_CONTINUATION(pmc)
143 
144 typedef struct Parrot_Context_info {
145     STRING   *subname;
146     STRING   *nsname;
147     STRING   *fullname;
148     STRING   *file;
149     opcode_t *address;
150     int       pc;
151     int       line;
152 } Parrot_Context_info;
153 
154 /* HEADERIZER BEGIN: src/sub.c */
155 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
156 
157 PARROT_EXPORT
158 PARROT_CANNOT_RETURN_NULL
159 void * Parrot_get_sub_pmc_from_subclass(PARROT_INTERP, ARGIN(PMC *subclass))
160         __attribute__nonnull__(1)
161         __attribute__nonnull__(2);
162 
163 PARROT_EXPORT
164 void Parrot_sub_capture_lex(PARROT_INTERP, ARGMOD(PMC *sub_pmc))
165         __attribute__nonnull__(1)
166         __attribute__nonnull__(2)
167         FUNC_MODIFIES(*sub_pmc);
168 
169 PARROT_EXPORT
170 int Parrot_sub_context_get_info(PARROT_INTERP,
171     ARGIN(PMC *ctx),
172     ARGOUT(Parrot_Context_info *info))
173         __attribute__nonnull__(1)
174         __attribute__nonnull__(2)
175         __attribute__nonnull__(3)
176         FUNC_MODIFIES(*info);
177 
178 PARROT_EXPORT
179 PARROT_CAN_RETURN_NULL
180 PARROT_WARN_UNUSED_RESULT
181 STRING* Parrot_sub_Context_infostr(PARROT_INTERP,
182     ARGIN(PMC *ctx),
183     int is_top)
184         __attribute__nonnull__(1)
185         __attribute__nonnull__(2);
186 
187 PARROT_EXPORT
188 PARROT_CAN_RETURN_NULL
189 PARROT_WARN_UNUSED_RESULT
190 STRING* Parrot_sub_full_sub_name(PARROT_INTERP, ARGIN_NULLOK(PMC* sub_pmc))
191         __attribute__nonnull__(1);
192 
193 PARROT_EXPORT
194 PARROT_CANNOT_RETURN_NULL
195 PARROT_WARN_UNUSED_RESULT
196 PMC* Parrot_sub_new_closure(PARROT_INTERP, ARGIN(PMC *sub_pmc))
197         __attribute__nonnull__(1)
198         __attribute__nonnull__(2);
199 
200 void Parrot_sub_continuation_check(PARROT_INTERP, ARGIN(const PMC *pmc))
201         __attribute__nonnull__(1)
202         __attribute__nonnull__(2);
203 
204 void Parrot_sub_continuation_rewind_environment(PARROT_INTERP,
205     ARGIN(PMC *pmc))
206         __attribute__nonnull__(1)
207         __attribute__nonnull__(2);
208 
209 PARROT_CAN_RETURN_NULL
210 PARROT_WARN_UNUSED_RESULT
211 PMC* Parrot_sub_find_dynamic_pad(PARROT_INTERP,
212     ARGIN(STRING *lex_name),
213     ARGIN(PMC *ctx))
214         __attribute__nonnull__(1)
215         __attribute__nonnull__(2)
216         __attribute__nonnull__(3);
217 
218 PARROT_CAN_RETURN_NULL
219 PARROT_WARN_UNUSED_RESULT
220 PMC* Parrot_sub_find_pad(PARROT_INTERP,
221     ARGIN(STRING *lex_name),
222     ARGIN(PMC *ctx))
223         __attribute__nonnull__(1)
224         __attribute__nonnull__(2)
225         __attribute__nonnull__(3);
226 
227 PARROT_CANNOT_RETURN_NULL
228 STRING * Parrot_sub_get_filename_from_pc(PARROT_INTERP,
229     ARGIN_NULLOK(PMC *subpmc),
230     ARGIN_NULLOK(opcode_t *pc))
231         __attribute__nonnull__(1);
232 
233 INTVAL Parrot_sub_get_line_from_pc(PARROT_INTERP,
234     ARGIN_NULLOK(PMC *subpmc),
235     ARGIN_NULLOK(opcode_t *pc))
236         __attribute__nonnull__(1);
237 
238 #define ASSERT_ARGS_Parrot_get_sub_pmc_from_subclass \
239      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
240        PARROT_ASSERT_ARG(interp) \
241     , PARROT_ASSERT_ARG(subclass))
242 #define ASSERT_ARGS_Parrot_sub_capture_lex __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
243        PARROT_ASSERT_ARG(interp) \
244     , PARROT_ASSERT_ARG(sub_pmc))
245 #define ASSERT_ARGS_Parrot_sub_context_get_info __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
246        PARROT_ASSERT_ARG(interp) \
247     , PARROT_ASSERT_ARG(ctx) \
248     , PARROT_ASSERT_ARG(info))
249 #define ASSERT_ARGS_Parrot_sub_Context_infostr __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
250        PARROT_ASSERT_ARG(interp) \
251     , PARROT_ASSERT_ARG(ctx))
252 #define ASSERT_ARGS_Parrot_sub_full_sub_name __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
253        PARROT_ASSERT_ARG(interp))
254 #define ASSERT_ARGS_Parrot_sub_new_closure __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
255        PARROT_ASSERT_ARG(interp) \
256     , PARROT_ASSERT_ARG(sub_pmc))
257 #define ASSERT_ARGS_Parrot_sub_continuation_check __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
258        PARROT_ASSERT_ARG(interp) \
259     , PARROT_ASSERT_ARG(pmc))
260 #define ASSERT_ARGS_Parrot_sub_continuation_rewind_environment \
261      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
262        PARROT_ASSERT_ARG(interp) \
263     , PARROT_ASSERT_ARG(pmc))
264 #define ASSERT_ARGS_Parrot_sub_find_dynamic_pad __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
265        PARROT_ASSERT_ARG(interp) \
266     , PARROT_ASSERT_ARG(lex_name) \
267     , PARROT_ASSERT_ARG(ctx))
268 #define ASSERT_ARGS_Parrot_sub_find_pad __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
269        PARROT_ASSERT_ARG(interp) \
270     , PARROT_ASSERT_ARG(lex_name) \
271     , PARROT_ASSERT_ARG(ctx))
272 #define ASSERT_ARGS_Parrot_sub_get_filename_from_pc \
273      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
274        PARROT_ASSERT_ARG(interp))
275 #define ASSERT_ARGS_Parrot_sub_get_line_from_pc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
276        PARROT_ASSERT_ARG(interp))
277 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
278 /* HEADERIZER END: src/sub.c */
279 
280 #endif /* PARROT_SUB_H_GUARD */
281 
282 /*
283  * Local variables:
284  *   c-file-style: "parrot"
285  * End:
286  * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
287  */
288