tagged release 0.7.1
[parrot.git] / include / parrot / sub.h
blob96e7d44f12ca5dbd5248d473cff0b41a9155149f
1 /* sub.h
2 * Copyright (C) 2001-2008, The Perl Foundation.
3 * SVN Info
4 * $Id$
5 * Overview:
6 * Data Structure and Algorithms:
7 * Subroutine, coroutine, closure and continuation structures
8 * and related routines.
9 * History:
10 * Initial version by Melvin on on 2002/06/6
11 * Notes:
12 * References:
15 #ifndef PARROT_SUB_H_GUARD
16 #define PARROT_SUB_H_GUARD
18 #include "parrot/parrot.h"
21 * Subroutine flags
23 typedef enum {
24 /* runtime usage flags */
25 SUB_FLAG_CORO_FF = PObj_private0_FLAG,
26 SUB_FLAG_C_HANDLER = PObj_private0_FLAG, /* C exceptions only */
27 SUB_FLAG_TAILCALL = PObj_private2_FLAG,
28 SUB_FLAG_GENERATOR = PObj_private3_FLAG, /* unused old python pmcs */
30 /* compile/loadtime usage flags */
31 /* from packfile */
32 SUB_FLAG_IS_OUTER = PObj_private1_FLAG,
33 SUB_FLAG_PF_ANON = PObj_private3_FLAG,
34 SUB_FLAG_PF_MAIN = PObj_private4_FLAG,
35 SUB_FLAG_PF_LOAD = PObj_private5_FLAG,
36 SUB_FLAG_PF_IMMEDIATE = PObj_private6_FLAG,
37 SUB_FLAG_PF_POSTCOMP = PObj_private7_FLAG,
39 /* [temporary expedient. -- rgr, 13-Jul-08.] */
40 SUB_FLAG_NEWCLOSURE = SUB_FLAG_PF_IMMEDIATE,
42 SUB_FLAG_PF_MASK = 0xfa /* anon ... postcomp, is_outer*/
43 } sub_flags_enum;
45 #define SUB_FLAG_get_FLAGS(o) (PObj_get_FLAGS(o))
46 #define SUB_FLAG_flag_TEST(flag, o) (SUB_FLAG_get_FLAGS(o) & SUB_FLAG_ ## flag)
47 #define SUB_FLAG_flag_SET(flag, o) (SUB_FLAG_get_FLAGS(o) |= SUB_FLAG_ ## flag)
48 #define SUB_FLAG_flag_CLEAR(flag, o) (SUB_FLAG_get_FLAGS(o) &= ~(UINTVAL)(SUB_FLAG_ ## flag))
50 #define SUB_FLAG_flags_SETTO(o, f) SUB_FLAG_get_FLAGS(o) = (f)
51 #define SUB_FLAG_flags_CLEARALL(o) SUB_FLAG_flags_SETTO((o), 0)
53 #define SUB_FLAG_TAILCALL_TEST(o) SUB_FLAG_flag_TEST(TAILCALL, (o))
54 #define SUB_FLAG_TAILCALL_ISSET(o) SUB_FLAG_flag_TEST(TAILCALL, (o))
55 #define SUB_FLAG_TAILCALL_NOTSET(o) (!SUB_FLAG_flag_TEST(TAILCALL, (o)))
56 #define SUB_FLAG_TAILCALL_SET(o) SUB_FLAG_flag_SET(TAILCALL, (o))
57 #define SUB_FLAG_TAILCALL_CLEAR(o) SUB_FLAG_flag_CLEAR(TAILCALL, (o))
59 #define SUB_FLAG(n) ((UINTVAL)1 << (n))
60 typedef enum {
61 SUB_COMP_FLAG_BIT_0 = SUB_FLAG(0),
62 SUB_COMP_FLAG_BIT_1 = SUB_FLAG(1),
63 SUB_COMP_FLAG_BIT_2 = SUB_FLAG(2),
64 SUB_COMP_FLAG_METHOD = SUB_COMP_FLAG_BIT_2,
65 SUB_COMP_FLAG_BIT_3 = SUB_FLAG(3),
66 SUB_COMP_FLAG_BIT_4 = SUB_FLAG(4),
67 SUB_COMP_FLAG_BIT_5 = SUB_FLAG(5),
68 SUB_COMP_FLAG_BIT_6 = SUB_FLAG(6),
69 SUB_COMP_FLAG_BIT_7 = SUB_FLAG(7),
70 SUB_COMP_FLAG_BIT_8 = SUB_FLAG(8),
71 SUB_COMP_FLAG_BIT_9 = SUB_FLAG(9),
72 SUB_COMP_FLAG_BIT_10 = SUB_FLAG(10),
73 SUB_COMP_FLAG_PF_INIT = SUB_COMP_FLAG_BIT_10,
74 SUB_COMP_FLAG_BIT_11 = SUB_FLAG(11),
75 SUB_COMP_FLAG_BIT_12 = SUB_FLAG(12),
76 SUB_COMP_FLAG_BIT_13 = SUB_FLAG(13),
77 SUB_COMP_FLAG_BIT_14 = SUB_FLAG(14),
78 SUB_COMP_FLAG_BIT_15 = SUB_FLAG(15),
79 SUB_COMP_FLAG_BIT_16 = SUB_FLAG(16),
80 SUB_COMP_FLAG_BIT_17 = SUB_FLAG(17),
81 SUB_COMP_FLAG_BIT_18 = SUB_FLAG(18),
82 SUB_COMP_FLAG_BIT_19 = SUB_FLAG(19),
83 SUB_COMP_FLAG_BIT_20 = SUB_FLAG(20),
84 SUB_COMP_FLAG_BIT_21 = SUB_FLAG(21),
85 SUB_COMP_FLAG_BIT_22 = SUB_FLAG(22),
86 SUB_COMP_FLAG_BIT_23 = SUB_FLAG(23),
87 SUB_COMP_FLAG_BIT_24 = SUB_FLAG(24),
88 SUB_COMP_FLAG_BIT_25 = SUB_FLAG(25),
89 SUB_COMP_FLAG_BIT_26 = SUB_FLAG(26),
90 SUB_COMP_FLAG_BIT_27 = SUB_FLAG(27),
91 SUB_COMP_FLAG_BIT_28 = SUB_FLAG(28),
92 SUB_COMP_FLAG_BIT_29 = SUB_FLAG(29),
93 SUB_COMP_FLAG_BIT_30 = SUB_FLAG(30),
94 SUB_COMP_FLAG_MASK = 0x00000404
95 } sub_comp_flags_enum;
96 #undef SUB_FLAG
98 #define Sub_comp_get_FLAGS(o) ((PMC_sub(o))->comp_flags)
99 #define Sub_comp_flag_TEST(flag, o) (Sub_comp_get_FLAGS(o) & SUB_COMP_FLAG_ ## flag)
100 #define Sub_comp_flag_SET(flag, o) (Sub_comp_get_FLAGS(o) |= SUB_COMP_FLAG_ ## flag)
101 #define Sub_comp_flag_CLEAR(flag, o) (Sub_comp_get_FLAGS(o) &= ~(UINTVAL)(SUB_COMP_FLAG_ ## flag))
103 #define Sub_comp_flags_SETTO(o, f) Sub_comp_get_FLAGS(o) = (f)
104 #define Sub_comp_flags_CLEARALL(o) Sub_comp_flags_SETTO((o), 0)
106 #define Sub_comp_INIT_TEST(o) Sub_comp_flag_TEST(PF_INIT, o)
107 #define Sub_comp_INIT_SET(o) Sub_comp_flag_SET(PF_INIT, o)
108 #define Sub_comp_INIT_CLEAR(o) Sub_comp_flag_CLEAR(PF_INIT, o)
111 * a flag to signal a Sub that a new RetContinuation should be created
114 #define NEED_CONTINUATION ((PMC *)1)
117 * maximum sub recursion depth
120 #define RECURSION_LIMIT 1000
124 * Counts and flags describing the arguments.
126 typedef struct Parrot_sub_arginfo {
127 Parrot_UInt2 pos_required;
128 Parrot_UInt2 pos_optional;
129 Parrot_UInt2 named_required;
130 Parrot_UInt2 named_optional;
131 Parrot_UInt1 pos_slurpy;
132 Parrot_UInt1 named_slurpy;
133 } Parrot_sub_arginfo;
137 * Sub and Closure share a Parrot_sub structure.
138 * Closures have additionally an 'outer_ctx'
140 typedef struct Parrot_sub {
141 struct PackFile_ByteCode *seg; /* bytecode segment */
142 size_t start_offs; /* sub entry in ops from seg->base.data */
143 size_t end_offs;
145 INTVAL HLL_id; /* see src/hll.c XXX or per segment? */
146 PMC *namespace_name; /* where this Sub is in - this is either
147 * a String or a [Key] and describes
148 * the relative path in the NameSpace
150 PMC *namespace_stash; /* the actual hash, HLL::namespace */
151 STRING *name; /* name of the sub */
152 STRING *lexid; /* The lexical ID of the sub. */
153 INTVAL vtable_index; /* index in Parrot_vtable_slot_names */
154 PMC *multi_signature; /* list of types for MMD */
155 INTVAL n_regs_used[4]; /* INSP in PBC */
157 PMC *lex_info; /* LexInfo PMC */
158 PMC *outer_sub; /* :outer for closures */
159 PMC *eval_pmc; /* eval container / NULL */
160 parrot_context_t *ctx; /* the context this sub is in */
161 UINTVAL comp_flags; /* compile time and additional flags */
162 Parrot_sub_arginfo *arg_info;/* Argument counts and flags. */
164 /* - end common */
165 struct Parrot_Context *outer_ctx; /* outer context, if a closure */
166 } Parrot_sub;
168 #define PMC_sub(pmc) ((Parrot_sub *)PMC_struct_val(pmc))
170 /* the first entries must match Parrot_sub, so we can cast
171 * these two to the other type
173 typedef struct Parrot_coro {
174 struct PackFile_ByteCode *seg; /* bytecode segment */
175 size_t start_offs; /* sub entry in ops from seg->base.data */
176 size_t end_offs;
178 INTVAL HLL_id; /* see src/hll.c XXX or per segment? */
179 PMC *_namespace; /* where this Sub is in - this is either
180 * a String or a [Key] and describes
181 * the relative path in the NameSpace
183 PMC *namespace_stash; /* the actual hash, HLL::namespace */
184 STRING *name; /* name of the sub */
185 STRING *lexid; /* The lexical ID of the sub. */
186 INTVAL vtable_index; /* index in Parrot_vtable_slot_names */
187 PMC *multi_signature; /* list of types for MMD */
188 INTVAL n_regs_used[4]; /* INSP in PBC */
190 PMC *lex_info; /* LexInfo PMC */
191 PMC *outer_sub; /* :outer for closures */
192 PMC *eval_pmc; /* eval container / NULL */
193 struct Parrot_Context *ctx; /* coroutine context */
194 UINTVAL comp_flags; /* compile time and additional flags */
195 Parrot_sub_arginfo arg_info; /* Argument counts and flags. */
197 /* - end common */
199 struct PackFile_ByteCode *caller_seg; /* bytecode segment */
200 opcode_t *address; /* next address to run - toggled each time */
201 struct Stack_Chunk *dynamic_state; /* next dynamic state */
202 } Parrot_coro;
204 #define PMC_coro(pmc) ((Parrot_coro *)PMC_struct_val(pmc))
206 typedef struct Parrot_cont {
207 /* continuation destination */
208 struct PackFile_ByteCode *seg; /* bytecode segment */
209 opcode_t *address; /* start of bytecode, addr to continue */
210 struct Parrot_Context *to_ctx; /* pointer to dest context */
211 struct Stack_Chunk *dynamic_state; /* dest dynamic state */
212 /* a Continuation keeps the from_ctx alive */
213 struct Parrot_Context *from_ctx; /* sub, this cont is returning from */
214 opcode_t *current_results; /* ptr into code with get_results opcode
215 full continuation only */
216 int runloop_id; /* id of the creating runloop. */
217 int invoked; /* flag when a handler has been invoked. */
218 } Parrot_cont;
220 #define PMC_cont(pmc) ((Parrot_cont *)PMC_struct_val(pmc))
222 typedef struct Parrot_Context_info {
223 STRING *subname;
224 STRING *nsname;
225 STRING *fullname;
226 STRING *file;
227 opcode_t *address;
228 int pc;
229 int line;
230 } Parrot_Context_info;
232 /* HEADERIZER BEGIN: src/sub.c */
233 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
235 PARROT_API
236 PARROT_MALLOC
237 PARROT_CANNOT_RETURN_NULL
238 PMC * new_ret_continuation_pmc(PARROT_INTERP,
239 ARGIN_NULLOK(opcode_t *address))
240 __attribute__nonnull__(1);
242 PARROT_API
243 int Parrot_Context_get_info(PARROT_INTERP,
244 ARGIN(const parrot_context_t *ctx),
245 ARGOUT(Parrot_Context_info *info))
246 __attribute__nonnull__(1)
247 __attribute__nonnull__(2)
248 __attribute__nonnull__(3)
249 FUNC_MODIFIES(*info);
251 PARROT_API
252 PARROT_CAN_RETURN_NULL
253 PARROT_WARN_UNUSED_RESULT
254 STRING* Parrot_Context_infostr(PARROT_INTERP,
255 ARGIN(const parrot_context_t *ctx))
256 __attribute__nonnull__(1)
257 __attribute__nonnull__(2);
259 PARROT_API
260 PARROT_CAN_RETURN_NULL
261 PARROT_WARN_UNUSED_RESULT
262 STRING* Parrot_full_sub_name(PARROT_INTERP, ARGIN_NULLOK(PMC* sub))
263 __attribute__nonnull__(1);
265 PARROT_API
266 PARROT_CANNOT_RETURN_NULL
267 PARROT_WARN_UNUSED_RESULT
268 PMC* parrot_new_closure(PARROT_INTERP, ARGIN(PMC *sub_pmc))
269 __attribute__nonnull__(1)
270 __attribute__nonnull__(2);
272 void invalidate_retc_context(PARROT_INTERP, ARGMOD(PMC *cont))
273 __attribute__nonnull__(1)
274 __attribute__nonnull__(2)
275 FUNC_MODIFIES(*cont);
277 void mark_context(PARROT_INTERP, ARGMOD(parrot_context_t* ctx))
278 __attribute__nonnull__(1)
279 __attribute__nonnull__(2)
280 FUNC_MODIFIES(* ctx);
282 PARROT_MALLOC
283 PARROT_CANNOT_RETURN_NULL
284 Parrot_sub * new_closure(PARROT_INTERP)
285 __attribute__nonnull__(1);
287 PARROT_MALLOC
288 PARROT_CANNOT_RETURN_NULL
289 Parrot_cont * new_continuation(PARROT_INTERP,
290 ARGIN_NULLOK(const Parrot_cont *to))
291 __attribute__nonnull__(1);
293 PARROT_MALLOC
294 PARROT_CANNOT_RETURN_NULL
295 Parrot_coro * new_coroutine(PARROT_INTERP)
296 __attribute__nonnull__(1);
298 PARROT_MALLOC
299 PARROT_CANNOT_RETURN_NULL
300 Parrot_cont * new_ret_continuation(PARROT_INTERP)
301 __attribute__nonnull__(1);
303 PARROT_MALLOC
304 PARROT_CANNOT_RETURN_NULL
305 Parrot_sub * new_sub(PARROT_INTERP)
306 __attribute__nonnull__(1);
308 void Parrot_continuation_check(PARROT_INTERP,
309 ARGIN(PMC *pmc),
310 ARGIN(Parrot_cont *cc))
311 __attribute__nonnull__(1)
312 __attribute__nonnull__(2)
313 __attribute__nonnull__(3);
315 void Parrot_continuation_rewind_environment(PARROT_INTERP,
316 ARGIN(PMC *pmc),
317 ARGIN(Parrot_cont *cc))
318 __attribute__nonnull__(1)
319 __attribute__nonnull__(2)
320 __attribute__nonnull__(3);
322 PARROT_CAN_RETURN_NULL
323 PARROT_WARN_UNUSED_RESULT
324 PMC* Parrot_find_pad(PARROT_INTERP,
325 ARGIN(STRING *lex_name),
326 ARGIN(const parrot_context_t *ctx))
327 __attribute__nonnull__(1)
328 __attribute__nonnull__(2)
329 __attribute__nonnull__(3);
331 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
332 /* HEADERIZER END: src/sub.c */
334 #endif /* PARROT_SUB_H_GUARD */
337 * Local variables:
338 * c-file-style: "parrot"
339 * End:
340 * vim: expandtab shiftwidth=4: