w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

proc.c
Go to the documentation of this file.
1 /*
2 ** proc.c - Proc class
3 **
4 ** See Copyright Notice in mruby.h
5 */
6 
7 #include <mruby.h>
8 #include <mruby/class.h>
9 #include <mruby/proc.h>
10 #include <mruby/opcode.h>
11 #include <mruby/data.h>
12 #include <mruby/presym.h>
13 
14 static const mrb_code call_iseq[] = {
15  OP_CALL,
16 };
17 
18 static const mrb_irep call_irep = {
19  0, /* nlocals */
20  2, /* nregs */
21  0, /* clen */
22  MRB_ISEQ_NO_FREE | MRB_IREP_NO_FREE, /* flags */
23  call_iseq, /* iseq */
24  NULL, /* pool */
25  NULL, /* syms */
26  NULL, /* reps */
27  NULL, /* lv */
28  NULL, /* debug_info */
29  1, /* ilen */
30  0, /* plen */
31  0, /* slen */
32  1, /* rlen */
33  0, /* refcnt */
34 };
35 
36 struct RProc*
38 {
39  struct RProc *p;
40  mrb_callinfo *ci = mrb->c->ci;
41 
42  p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
43  if (ci) {
44  struct RClass *tc = NULL;
45 
46  if (ci->proc) {
47  tc = MRB_PROC_TARGET_CLASS(ci->proc);
48  }
49  if (tc == NULL) {
50  tc = mrb_vm_ci_target_class(ci);
51  }
52  p->upper = ci->proc;
53  p->e.target_class = tc;
54  }
55  p->body.irep = irep;
56  if (irep) {
57  mrb_irep_incref(mrb, (mrb_irep*)irep);
58  }
59 
60  return p;
61 }
62 
63 struct REnv*
64 mrb_env_new(mrb_state *mrb, struct mrb_context *c, mrb_callinfo *ci, int nstacks, mrb_value *stack, struct RClass *tc)
65 {
66  struct REnv *e;
67  mrb_int bidx;
68 
69  e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, tc);
70  MRB_ENV_SET_LEN(e, nstacks);
71  bidx = ci->argc;
72  if (bidx < 0) bidx = 2;
73  else bidx += 1;
74  MRB_ENV_SET_BIDX(e, bidx);
75  e->mid = ci->mid;
76  e->stack = stack;
77  e->cxt = c;
78 
79  return e;
80 }
81 
82 static void
84 {
85  mrb_callinfo *ci = mrb->c->ci;
86  const struct RProc *up = p->upper;
87  struct REnv *e = NULL;
88 
89  if (ci && (e = mrb_vm_ci_env(ci)) != NULL) {
90  /* do nothing, because e is assigned already */
91  }
92  else if (up) {
93  struct RClass *tc = MRB_PROC_TARGET_CLASS(p);
94 
95  e = mrb_env_new(mrb, mrb->c, ci, up->body.irep->nlocals, ci->stack, tc);
96  ci->u.env = e;
97  if (MRB_PROC_ENV_P(up) && MRB_PROC_ENV(up)->cxt == NULL) {
98  e->mid = MRB_PROC_ENV(up)->mid;
99  }
100  }
101  if (e) {
102  p->e.env = e;
103  p->flags |= MRB_PROC_ENVSET;
104  mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)e);
105  }
106 }
107 
108 struct RProc*
110 {
111  struct RProc *p = mrb_proc_new(mrb, irep);
112 
113  closure_setup(mrb, p);
114  return p;
115 }
116 
117 MRB_API struct RProc*
119 {
120  struct RProc *p;
121 
122  p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
123  p->body.func = func;
124  p->flags |= MRB_PROC_CFUNC_FL;
125  p->upper = 0;
126  p->e.target_class = 0;
127 
128  return p;
129 }
130 
131 MRB_API struct RProc*
133 {
134  struct RProc *p = mrb_proc_new_cfunc(mrb, func);
135  struct REnv *e;
136  int i;
137 
138  p->e.env = e = mrb_env_new(mrb, mrb->c, mrb->c->ci, 0, NULL, NULL);
139  p->flags |= MRB_PROC_ENVSET;
140  mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)e);
141  MRB_ENV_CLOSE(e);
142 
143  e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc);
145 
146  if (argv) {
147  for (i = 0; i < argc; ++i) {
148  e->stack[i] = argv[i];
149  }
150  }
151  else {
152  for (i = 0; i < argc; ++i) {
153  SET_NIL_VALUE(e->stack[i]);
154  }
155  }
156  return p;
157 }
158 
159 MRB_API struct RProc*
161 {
162  return mrb_proc_new_cfunc_with_env(mrb, func, nlocals, NULL);
163 }
164 
167 {
168  const struct RProc *p = mrb->c->ci->proc;
169  struct REnv *e;
170 
171  if (!p || !MRB_PROC_CFUNC_P(p)) {
172  mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from non-cfunc proc.");
173  }
174  e = MRB_PROC_ENV(p);
175  if (!e) {
176  mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from cfunc Proc without REnv.");
177  }
178  if (idx < 0 || MRB_ENV_LEN(e) <= idx) {
179  mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: %i (expected: 0 <= index < %i)",
180  idx, MRB_ENV_LEN(e));
181  }
182 
183  return e->stack[idx];
184 }
185 
186 void
187 mrb_proc_copy(struct RProc *a, struct RProc *b)
188 {
189  if (a->body.irep) {
190  /* already initialized proc */
191  return;
192  }
193  a->flags = b->flags;
194  a->body = b->body;
195  if (!MRB_PROC_CFUNC_P(a) && a->body.irep) {
196  mrb_irep_incref(NULL, (mrb_irep*)a->body.irep);
197  }
198  a->upper = b->upper;
199  a->e.env = b->e.env;
200  /* a->e.target_class = a->e.target_class; */
201 }
202 
203 static mrb_value
205 {
206  mrb_value blk;
207  mrb_value proc;
208  struct RProc *p;
209 
210  /* Calling Proc.new without a block is not implemented yet */
211  mrb_get_args(mrb, "&!", &blk);
212  p = (struct RProc *)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb_class_ptr(proc_class));
214  proc = mrb_obj_value(p);
216  if (!MRB_PROC_STRICT_P(p) &&
217  mrb->c->ci > mrb->c->cibase && MRB_PROC_ENV(p) == mrb->c->ci[-1].u.env) {
218  p->flags |= MRB_PROC_ORPHAN;
219  }
220  return proc;
221 }
222 
223 static mrb_value
225 {
226  mrb_value proc = mrb_get_arg1(mrb);
227 
228  if (!mrb_proc_p(proc)) {
229  mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc");
230  }
232  return self;
233 }
234 
235 /* 15.2.17.4.2 */
236 static mrb_value
238 {
239  return mrb_int_value(mrb, mrb_proc_arity(mrb_proc_ptr(self)));
240 }
241 
242 /* 15.3.1.2.6 */
243 /* 15.3.1.3.27 */
244 /*
245  * call-seq:
246  * lambda { |...| block } -> a_proc
247  *
248  * Equivalent to <code>Proc.new</code>, except the resulting Proc objects
249  * check the number of parameters passed when called.
250  */
251 static mrb_value
253 {
254  mrb_value blk;
255  struct RProc *p;
256 
257  mrb_get_args(mrb, "&", &blk);
258  if (mrb_nil_p(blk)) {
259  mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
260  }
261  if (!mrb_proc_p(blk)) {
262  mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc");
263  }
264  p = mrb_proc_ptr(blk);
265  if (!MRB_PROC_STRICT_P(p)) {
266  struct RProc *p2 = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, p->c);
267  mrb_proc_copy(p2, p);
268  p2->flags |= MRB_PROC_STRICT;
269  return mrb_obj_value(p2);
270  }
271  return blk;
272 }
273 
274 mrb_int
275 mrb_proc_arity(const struct RProc *p)
276 {
277  const mrb_irep *irep;
278  const mrb_code *pc;
279  mrb_aspec aspec;
280  int ma, op, ra, pa, arity;
281 
282  if (MRB_PROC_CFUNC_P(p)) {
283  /* TODO cfunc aspec not implemented yet */
284  return -1;
285  }
286 
287  irep = p->body.irep;
288  if (!irep) {
289  return 0;
290  }
291 
292  pc = irep->iseq;
293  /* arity is depend on OP_ENTER */
294  if (*pc != OP_ENTER) {
295  return 0;
296  }
297 
298  aspec = PEEK_W(pc+1);
299  ma = MRB_ASPEC_REQ(aspec);
300  op = MRB_ASPEC_OPT(aspec);
301  ra = MRB_ASPEC_REST(aspec);
302  pa = MRB_ASPEC_POST(aspec);
303  arity = ra || (MRB_PROC_STRICT_P(p) && op) ? -(ma + pa + 1) : ma + pa;
304 
305  return arity;
306 }
307 
308 void
310 {
311  struct RProc *p;
312  mrb_method_t m;
313 
315  mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1));
316  mrb_define_method(mrb, mrb->proc_class, "arity", proc_arity, MRB_ARGS_NONE());
317 
318  p = mrb_proc_new(mrb, &call_irep);
321  mrb_define_method_raw(mrb, mrb->proc_class, MRB_OPSYM(aref), m);
322 
323  mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); /* 15.3.1.2.6 */
324  mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); /* 15.3.1.3.27 */
325 }
#define call
Definition: aptex-macros.h:493
char * p2
Definition: bmpfont.h:62
#define SET_NIL_VALUE(r)
Definition: boxing_nan.h:114
#define mrb_nil_p(o)
Definition: boxing_word.h:146
#define mrb_proc_p(o)
Definition: boxing_word.h:163
void mrb_define_method_raw(mrb_state *, struct RClass *, mrb_sym, mrb_method_t)
Definition: class.c:725
#define mrb_class_ptr(v)
Definition: class.h:24
#define b
Definition: jpegint.h:372
#define MRB_OPSYM(name)
Definition: disable.h:14
#define MRB_SYM(name)
Definition: disable.h:20
long pc
Definition: disdvi.c:114
static void initialize(void)
Definition: dvidvi.c:542
#define c(n)
Definition: gpos-common.c:150
#define a(n)
Definition: gpos-common.c:148
#define PEEK_W(pc)
Definition: opcode.h:28
void mrb_irep_incref(mrb_state *, struct mrb_irep *)
Definition: state.c:110
#define MRB_ISEQ_NO_FREE
Definition: irep.h:82
#define MRB_IREP_NO_FREE
Definition: irep.h:83
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
FT_UInt idx
Definition: cffcmap.c:135
static luaL_Reg func[]
Definition: except.c:32
#define E_TYPE_ERROR
Definition: mruby.h:1308
struct RBasic * mrb_obj_alloc(mrb_state *, enum mrb_vtype, struct RClass *)
Definition: gc.c:535
void mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt,...)
Definition: error.c:400
#define E_INDEX_ERROR
Definition: mruby.h:1311
uint8_t mrb_code
Definition: mruby.h:122
mrb_value mrb_get_arg1(mrb_state *mrb)
Definition: class.c:840
mrb_int mrb_get_args(mrb_state *mrb, mrb_args_format format,...)
Definition: class.c:891
void mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg)
Definition: error.c:214
#define MRB_ARGS_NONE()
Definition: mruby.h:879
#define MRB_ARGS_REQ(n)
Definition: mruby.h:837
void mrb_field_write_barrier(mrb_state *, struct RBasic *, struct RBasic *)
Definition: gc.c:1345
mrb_value mrb_funcall_with_block(mrb_state *mrb, mrb_value val, mrb_sym name, mrb_int argc, const mrb_value *argv, mrb_value block)
Definition: vm.c:380
#define MRB_ARGS_BLOCK()
Definition: mruby.h:869
void * mrb_malloc(mrb_state *, size_t)
Definition: gc.c:256
uintptr_t mrb_method_t
Definition: mruby.h:206
#define E_ARGUMENT_ERROR
Definition: mruby.h:1310
mrb_value(* mrb_func_t)(struct mrb_state *mrb, mrb_value self)
Definition: mruby.h:203
struct _proc * proc
Definition: obx.h:95
#define ra
#define MRB_API
Definition: common.h:73
#define mrb_define_class_method(mrb, c, name, f, a)
Definition: scanning.h:16
#define mrb_define_method(mrb, c, name, f, a)
Definition: scanning.h:15
#define MRB_PROC_ENVSET
Definition: proc.h:70
#define MRB_ENV_LEN(e)
Definition: proc.h:27
#define MRB_ENV_SET_LEN(e, len)
Definition: proc.h:26
#define MRB_ASPEC_REST(a)
Definition: proc.h:57
#define mrb_proc_ptr(v)
Definition: proc.h:87
#define MRB_ASPEC_REQ(a)
Definition: proc.h:55
#define MRB_PROC_TARGET_CLASS(p)
Definition: proc.h:73
static struct RClass * mrb_vm_ci_target_class(const mrb_callinfo *ci)
Definition: proc.h:147
#define MRB_PROC_ORPHAN
Definition: proc.h:68
#define MRB_PROC_ENV_P(p)
Definition: proc.h:71
#define MRB_PROC_CFUNC_P(p)
Definition: proc.h:64
static struct REnv * mrb_vm_ci_env(const mrb_callinfo *ci)
Definition: proc.h:172
#define MRB_PROC_CFUNC_FL
Definition: proc.h:63
#define MRB_ENV_CLOSE(e)
Definition: proc.h:31
#define MRB_METHOD_FROM_PROC(m, pr)
Definition: proc.h:112
#define MRB_ENV_SET_BIDX(e, idx)
Definition: proc.h:37
#define MRB_ASPEC_OPT(a)
Definition: proc.h:56
#define MRB_PROC_STRICT
Definition: proc.h:66
#define MRB_PROC_ENV(p)
Definition: proc.h:72
#define MRB_ASPEC_POST(a)
Definition: proc.h:58
#define MRB_PROC_STRICT_P(p)
Definition: proc.h:67
@ OP_CALL
Definition: lopcodes.h:216
ShellFileEnvironment e
Definition: sh6.c:388
struct RProc * mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const mrb_value *argv)
Definition: proc.c:132
void mrb_init_proc(mrb_state *mrb)
Definition: proc.c:309
static mrb_value mrb_proc_init_copy(mrb_state *mrb, mrb_value self)
Definition: proc.c:224
struct RProc * mrb_proc_new_cfunc(mrb_state *mrb, mrb_func_t func)
Definition: proc.c:118
static mrb_value proc_arity(mrb_state *mrb, mrb_value self)
Definition: proc.c:237
static mrb_value proc_lambda(mrb_state *mrb, mrb_value self)
Definition: proc.c:252
static const mrb_code call_iseq[]
Definition: proc.c:14
struct RProc * mrb_closure_new(mrb_state *mrb, const mrb_irep *irep)
Definition: proc.c:109
mrb_value mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx)
Definition: proc.c:166
static void closure_setup(mrb_state *mrb, struct RProc *p)
Definition: proc.c:83
static const mrb_irep call_irep
Definition: proc.c:18
struct RProc * mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals)
Definition: proc.c:160
struct REnv * mrb_env_new(mrb_state *mrb, struct mrb_context *c, mrb_callinfo *ci, int nstacks, mrb_value *stack, struct RClass *tc)
Definition: proc.c:64
static mrb_value mrb_proc_s_new(mrb_state *mrb, mrb_value proc_class)
Definition: proc.c:204
struct RProc * mrb_proc_new(mrb_state *mrb, const mrb_irep *irep)
Definition: proc.c:37
void mrb_proc_copy(struct RProc *a, struct RProc *b)
Definition: proc.c:187
mrb_int mrb_proc_arity(const struct RProc *p)
Definition: proc.c:275
Definition: object.h:19
Definition: class.h:17
Definition: proc.h:18
Definition: proc.h:41
const mrb_irep * irep
Definition: proc.h:44
Definition: obx.h:103
mrb_sym mid
Definition: mruby.h:152
union mrb_callinfo::@1650 u
mrb_value * stack
Definition: mruby.h:156
struct REnv * env
Definition: mruby.h:159
int16_t argc
Definition: mruby.h:153
const struct RProc * proc
Definition: mruby.h:155
mrb_callinfo * cibase
Definition: mruby.h:179
mrb_callinfo * ci
Definition: mruby.h:178
Definition: irep.h:56
const mrb_code * iseq
Definition: irep.h:62
struct mrb_context * c
Definition: mruby.h:235
struct RClass * kernel_module
Definition: mruby.h:259
struct RClass * proc_class
Definition: mruby.h:245
Definition: sh.h:1226
Definition: spc_misc.c:56
up
Definition: tex4ht.c:2558
m
Definition: tex4ht.c:3990
op
Definition: tex4ht.c:3129
#define stack
Definition: stack.c:10
int32_t mrb_int
Definition: value.h:35
@ MRB_TT_PROC
Definition: value.h:121
@ MRB_TT_ENV
Definition: value.h:127
static mrb_value mrb_int_value(struct mrb_state *mrb, mrb_int i)
Definition: value.h:294
static mrb_value mrb_obj_value(void *p)
Definition: value.h:317
#define argv
Definition: xmain.c:270
#define argc
Definition: xmain.c:269