p2  0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
objmodel.c
Go to the documentation of this file.
1 
7 // (c) 2008 why the lucky stiff, the freelance professor
8 #include <stdio.h>
9 #include <stdarg.h>
10 #include <stdlib.h>
11 #include "p2.h"
12 #include "internal.h"
13 #include "khash.h"
14 #include "table.h"
15 #include "asm.h"
16 
17 PN potion_closure_new(Potion *P, PN_F meth, PN sig, PN_SIZE extra) {
18  PN_SIZE i; PN cr;
19  vPN(Closure) c = PN_ALLOC_N(PN_TCLOSURE, struct PNClosure, extra * sizeof(PN));
20  c->method = meth;
21  if (PN_IS_TUPLE(sig) && PN_TUPLE_LEN(sig) > 0) {
22  c->sig = sig;
23  c->arity = potion_sig_arity(P, sig);
24  c->minargs = potion_sig_minargs(P, sig);
25  } else {
26  c->sig = PN_NIL;
27  c->arity = 0;
28  c->minargs = 0;
29  }
30  c->extra = extra;
31  for (i = 0; i < c->extra; i++)
32  c->data[i] = PN_NIL;
33  cr = (PN)c;
34  return cr;
35 }
36 
43  if (PN_CLOSURE(self)->extra > 0 && PN_IS_PROTO(PN_CLOSURE(self)->data[0]))
44  return PN_CLOSURE(self)->data[0];
45  return PN_NIL;
46 }
47 
52 PN potion_closure_string(Potion *P, PN cl, PN self, PN maxlen) {
53 #ifdef P2
54 # define FUNCNAME "sub"
55 #else
56 # define FUNCNAME "function"
57 #endif
58  PN out = potion_byte_str(P, FUNCNAME);
59  if (PN_CLOSURE(self)->name)
60  pn_printf(P, out, " %s", PN_STR_PTR(PN_CLOSURE(self)->name));
61  pn_printf(P, out, "(");
62  potion_bytes_obj_string(P, out, potion_sig_string(P,cl,PN_CLOSURE(self)->sig));
63  pn_printf(P, out, ")");
64  return PN_STR_B(out);
65 }
71  return PN_NUM(PN_CLOSURE(self)->arity);
72 }
78  return PN_NUM(PN_CLOSURE(self)->minargs);
79 }
80 
87 int potion_sig_arity(Potion *P, PN sig) {
88  if (PN_IS_TUPLE(sig)) {
89  //return PN_TUPLE_LEN(PN_CLOSURE(closure)->sig) / 2;
90  int count = 0;
91  struct PNTuple * volatile t = (struct PNTuple *)potion_fwd(sig);
92  if (t->len != 0) {
93  PN_SIZE i;
94  for (i = 0; i < t->len; i++) {
95  PN v = (PN)t->set[i];
96  if (PN_IS_STR(v)) count++; // names
97  // but not string default values
98  if (PN_IS_INT(v) && v == PN_NUM(':') && PN_IS_STR((PN)t->set[i+1])) count--;
99  }
100  }
101  return count;
102  }
103  else if (sig == PN_NIL)
104  return 0;
105  else {
106  potion_fatal("Invalid signature type for sig_arity");
107  return 0;
108  }
109 }
113  if (PN_IS_TUPLE(sig)) {
114  int count = 0;
115  struct PNTuple * volatile t = (struct PNTuple *)potion_fwd(sig);
116  if (t->len != 0) {
117  PN_SIZE i;
118  for (i = 0; i < t->len; i++) {
119  PN v = (PN)t->set[i];
120  if (PN_IS_STR(v)) count++; // count only names
121  if (PN_IS_INT(v) && v == PN_NUM('|')) break;
122  if (PN_IS_INT(v) && v == PN_NUM(':')) { count--; break; }
123  }
124  }
125  return count;
126  }
127  else if (sig == PN_NIL)
128  return 0;
129  else {
130  potion_fatal("wrong sig type for sig_minargs");
131  return 0;
132  }
133 }
134 
136 PN potion_sig_at(Potion *P, PN sig, int index) {
137  PN result = PN_NIL;
138  if (PN_IS_TUPLE(sig)) {
139  int count = -1;
140  struct PNTuple * volatile t = (struct PNTuple *)potion_fwd(sig);
141  if (t->len > 0) {
142  PN_SIZE i;
143  for (i = 0; i < t->len; i++) {
144  PN v = (PN)t->set[i];
145  if (PN_IS_STR(v)) count++;
146  if (PN_IS_INT(v) && v == PN_NUM(':') && PN_IS_STR((PN)t->set[i+1])) count--;
147  if (count == index) {
148  result = potion_tuple_new(P, v);
149  if (i+1 < t->len && PN_IS_INT((PN)t->set[i+1])) {
150  PN typ = (PN)t->set[i+1];
151  result = potion_tuple_push(P, result, typ);
152  if (i+2 < t->len && typ == PN_NUM(':'))
153  result = potion_tuple_push(P, result, (PN)t->set[i+2]);
154  }
155  return result;
156  }
157  }
158  }
159  return result;
160  }
161  else if (sig == PN_NIL)
162  return result;
163  else {
164  potion_fatal("wrong sig type for sig_at");
165  return 0;
166  }
167 }
168 
170 PN potion_sig_name_at(Potion *P, PN sig, int index) {
171  if (PN_IS_TUPLE(sig)) {
172  int count = -1;
173  struct PNTuple * volatile t = (struct PNTuple *)potion_fwd(sig);
174  if (t->len > 0) {
175  PN_SIZE i;
176  for (i = 0; i < t->len; i++) {
177  PN v = (PN)t->set[i];
178  if (PN_IS_STR(v)) count++;
179  if (PN_IS_INT(v) && v == PN_NUM(':') && PN_IS_STR((PN)t->set[i+1])) count--;
180  if (count == index)
181  return v;
182  }
183  }
184  return 0;
185  }
186  else if (sig == PN_NIL)
187  return 0;
188  else {
189  potion_fatal("wrong sig type for sig_at");
190  return 0;
191  }
192 }
193 
194 PN potion_no_call(Potion *P, PN cl, PN self) {
195  return self;
196 }
197 
198 void potion_add_metaclass(Potion *P, vPN(Vtable) vt) {
199  struct PNVtable *meta = vt->meta = PN_CALLOC_N(PN_TVTABLE, struct PNVtable, 0);
200  meta->type = PN_FLEX_SIZE(P->vts) + PN_TNIL;
201  PN_FLEX_NEEDS(1, P->vts, PN_TFLEX, PNFlex, TYPE_BATCH_SIZE);
202  PN_FLEX_SIZE(P->vts)++;
203  meta->name = PN_NIL;
204  meta->parent = PN_TVTABLE;
205  meta->methods = (struct PNTable *)potion_table_empty(P);
206  meta->ctor = PN_FUNC(potion_no_call, 0);
207  PN_VTABLE(meta->type) = (PN)meta;
208  meta->meta = NULL;
209  PN_TOUCH(P->vts);
210 }
213  vPN(Vtable) vt = PN_CALLOC_N(PN_TVTABLE, struct PNVtable, 0);
214  vt->type = t;
215  vt->name = PN_NIL;
216  vt->parent = self ? ((struct PNVtable *)self)->type : 0;
217  vt->methods = (struct PNTable *)potion_table_empty(P);
218  vt->ctor = PN_FUNC(potion_no_call, 0);
219  PN_VTABLE(t) = (PN)vt;
220  potion_add_metaclass(P, vt);
221  return (PN)vt;
222 }
225  vPN(Vtable) vt = (vPN(Vtable))potion_type_new(P, t, self);
226  vt->name = name;
227  return (PN)vt;
228 }
230 void potion_type_call_is(PN vt, PN cl) {
231  ((struct PNVtable *)vt)->call = cl;
232 }
235  PN cl = ((struct PNVtable *)PN_VTABLE(PN_TYPE(obj)))->call;
236  if (cl == PN_NIL) cl = P->call;
237  return cl;
238 }
241  ((struct PNVtable *)vt)->callset = cl;
242 }
245  PN cl = ((struct PNVtable *)PN_VTABLE(PN_TYPE(obj)))->callset;
246  if (cl == PN_NIL) cl = P->callset;
247  return cl;
248 }
251  ((struct PNVtable *)vt)->ctor = cl;
252 }
257 PN potion_class(Potion *P, PN cl, PN self, PN ivars) {
258  PN parent = ((!self || self == P->lobby) ? PN_VTABLE(PN_TOBJECT) : self);
259  PN pvars = ((struct PNVtable *)parent)->ivars;
260  PNType t = PN_FLEX_SIZE(P->vts) + PN_TNIL;
261  PN_FLEX_NEEDS(1, P->vts, PN_TFLEX, PNFlex, TYPE_BATCH_SIZE);
262  PN_FLEX_SIZE(P->vts)++;
263  self = potion_type_new(P, t, parent);
264  if (PN_IS_TUPLE(pvars)) {
265  if (!PN_IS_TUPLE(ivars)) ivars = PN_TUP0();
266  PN_TUPLE_EACH(pvars, i, v, {PN_PUT(ivars, v);});
267  }
268  if (PN_IS_TUPLE(ivars))
269  potion_ivars(P, PN_NIL, self, ivars);
270 
271  if (!PN_IS_CLOSURE(cl))
272  cl = ((struct PNVtable *)parent)->ctor;
273  ((struct PNVtable *)self)->ctor = cl;
274 
275  PN_TOUCH(P->vts);
276  return self;
277 }
278 
281  int i;
282  for (i=0; i < PN_FLEX_SIZE(P->vts); i++) {
283  vPN(Vtable) vt = (struct PNVtable *)PN_FLEX_AT(P->vts, i);
284  if (vt && vt->name == name)
285  return (PN)vt;
286  }
287  return PN_NIL;
288 }
291  struct PNVtable *vt = (struct PNVtable *)potion_fwd(class);
292  return vt->type;
293 }
294 
295 PN potion_ivars(Potion *P, PN cl, PN self, PN ivars) {
296  struct PNVtable *vt = (struct PNVtable *)self;
297 #ifdef POTION_JIT_TARGET
298  // TODO: allocate assembled instructions together into single pages
299  // since many times these tables are <100 bytes.
300  PNAsm * volatile asmb = potion_asm_new(P);
301  P->target.ivars(P, ivars, &asmb);
302  vt->ivfunc = (PN_IVAR_FUNC)PN_ALLOC_FUNC(asmb->len);
303  PN_MEMCPY_N(vt->ivfunc, asmb->ptr, u8, asmb->len);
304 #endif
305  vt->ivlen = PN_TUPLE_LEN(ivars);
306  vt->ivars = ivars;
307  return self;
308 }
309 
310 static inline long potion_obj_find_ivar(Potion *P, PN self, PN ivar) {
311  PNType t = PN_TYPE(self);
312  vPN(Vtable) vt = (struct PNVtable *)PN_VTABLE(t);
313  if (vt->ivfunc != NULL)
314  return vt->ivfunc(PN_UNIQ(ivar));
315 
316  if (t > PN_TUSER) {
317  PN ivars = ((struct PNVtable *)PN_VTABLE(t))->ivars;
318  if (ivars != PN_NIL) {
319  PN found = potion_tuple_bsearch(P, 0, ivars, ivar);
320  return found == PN_FALSE ? -1 : found;
321  }
322  }
323  return -1;
324 }
325 
327 PN potion_obj_get(Potion *P, PN cl, PN self, PN ivar) {
328  long i = potion_obj_find_ivar(P, self, ivar);
329  if (i >= 0)
330  return ((struct PNObject *)self)->ivars[i];
331  return PN_NIL;
332 }
334 PN potion_obj_set(Potion *P, PN cl, PN self, PN ivar, PN value) {
335  long i = potion_obj_find_ivar(P, self, ivar);
336  if (i >= 0) {
337  ((struct PNObject *)self)->ivars[i] = value;
338  PN_TOUCH(self);
339  }
340  return value;
341 }
344  return potion_vm(P, PN_CLOSURE(cl)->data[0], P->lobby, args, 0, NULL);
345 }
348  return PN_CLOSURE(cl)->data[0];
349 }
351 PN potion_def_method(Potion *P, PN closure, PN self, PN key, PN method) {
352  int ret;
353  PN cl;
354  vPN(Vtable) vt = (struct PNVtable *)self;
355  if (PN_TVTABLE != PN_TYPE(self)) return potion_type_error_want(P, "self.def_method", self, "VTable (a class)");
356  unsigned k = kh_put(PN, vt->methods, key, &ret);
357  PN_QUICK_FWD(struct PNTable *, vt->methods);
358  PN_TOUCH(vt->methods);
359 
360  if (!PN_IS_CLOSURE(method)) {
361  if (PN_IS_PROTO(method)) {
362  cl = potion_closure_new(P, (PN_F)potion_proto_method, PN_PROTO(method)->sig, 1);
363  PN_PROTO(method)->name = key;
364  }
365  else
367  PN_CLOSURE(cl)->data[0] = method;
368  PN_CLOSURE(cl)->name = key;
369  method = cl;
370  }
371  else
372  PN_CLOSURE(method)->name = key;
373 
374  kh_val(PN, vt->methods, k) = method;
375  PN_TOUCH(self);
376 
377 #ifdef JIT_MCACHE
378  // TODO: make JIT_MCACHE more flexible, store in fixed gc, see ivfunc TODO also
379  // TODO: this is disabled until method weakrefs can be stored in fixed memory
380  if (P->target.mcache != NULL) {
381  PNAsm * volatile asmb = potion_asm_new(P);
382  P->target.mcache(P, vt, &asmb);
383  if (asmb->len <= 4096) {
384  if (vt->mcache == NULL)
385  vt->mcache = PN_ALLOC_FUNC(4096);
386  PN_MEMCPY_N(vt->mcache, asmb->ptr, u8, asmb->len);
387  } else if (vt->mcache != NULL) {
388  potion_munmap(vt->mcache, 4096);
389  vt->mcache = NULL;
390  }
391  }
392 #endif
393  return method;
394 }
396 PN potion_lookup(Potion *P, PN closure, PN self, PN key) {
397  vPN(Vtable) vt = (struct PNVtable *)self;
398 #ifdef JIT_MCACHE
399  if (vt->mcache != NULL)
400  return vt->mcache(PN_UNIQ(key));
401 #endif
402  unsigned k = kh_get(PN, vt->methods, key);
403  if (k != kh_end(vt->methods)) return kh_val(PN, vt->methods, k);
404  return PN_NIL;
405 }
406 
408 PN potion_bind(Potion *P, PN rcv, PN msg) {
409  PN closure = PN_NIL;
410  PN vt = PN_NIL;
411  PNType t = PN_TYPE(rcv);
412  if (!PN_TYPECHECK(t)) return PN_NIL;
413  if (t == PN_TVTABLE && !PN_IS_METACLASS(rcv)) {
414  vt = (PN)((struct PNVtable *)rcv)->meta;
415  } else {
416  vt = PN_VTABLE(t);
417  }
418  //TODO p2: for multiple parents walk the c3 resolution
419  while (1) {
420  closure = ((msg == PN_lookup) && (t == PN_TVTABLE))
421  ? potion_lookup(P, 0, vt, msg)
422  : potion_send(vt, PN_lookup, msg);
423  if (closure || !((struct PNVtable *)vt)->parent) break;
424  vt = PN_VTABLE(((struct PNVtable *)vt)->parent);
425  }
426  return closure;
427 }
428 
429 PN potion_message(Potion *P, PN rcv, PN msg) {
430  PN cl = potion_bind(P, rcv, msg);
431  if (PN_IS_CLOSURE(cl) && PN_CLOSURE(cl)->sig == PN_NIL)
432  return PN_CLOSURE(cl)->method(P, cl, rcv, PN_NIL);
433  return cl;
434 }
435 
437  return potion_send(a, PN_add, b);
438 }
439 
441  return potion_send(a, PN_sub, b);
442 }
443 
445  return potion_send(a, PN_mult, b);
446 }
447 
449  return potion_send(a, PN_div, b);
450 }
451 
453  return potion_send(a, PN_rem, b);
454 }
455 
457  return potion_send(a, PN_bitn);
458 }
459 
461  return potion_send(a, PN_bitl, b);
462 }
463 
465  return potion_send(a, PN_bitr, b);
466 }
467 
473 PN potion_ref(Potion *P, PN data) {
474  if (PN_IS_REF(data)) return data;
475  vPN(WeakRef) ref = PN_ALLOC(PN_TWEAK, struct PNWeakRef);
476  ref->data = data;
477  return (PN)ref;
478 }
479 
483 PN potion_ref_string(Potion *P, PN cl, PN self, PN len) {
484  return potion_str(P, "<ref>");
485 }
486 
490 PN potion_object_string(Potion *P, PN cl, vPN(Object) self) {
491  struct PNVtable *vt = (struct PNVtable *)PN_VTABLE(self->vt);
492  if (vt->name != PN_NIL) {
493  PN str = potion_byte_str2(P, NULL, 0);
494  pn_printf(P, str, "<%s %lx>", PN_STR_PTR(vt->name), (PN)self);
495  return potion_send(str, PN_string);
496  }
497 
498  return potion_str(P, "<object>");
499 }
500 
504 PN potion_object_forward(Potion *P, PN cl, PN self, PN method) {
505  printf("#<object>");
506  return PN_NIL;
507 }
508 
514 PN potion_object_send(Potion *P, PN cl, PN self, PN method) {
515  return potion_send(self, method);
516 }
517 
522 PN potion_object_new(Potion *P, PN cl, PN self) {
523  vPN(Vtable) vt = (struct PNVtable *)self;
524  if (PN_IS_METACLASS(vt)) // TODO: error
525  return PN_NIL;
526  if (vt->type == PN_TVTABLE) // TODO: error
527  return PN_NIL;
528  return (PN)PN_ALLOC_N(vt->type, struct PNObject,
529  potion_type_size(P, (struct PNObject *)self) - sizeof(struct PNObject) + vt->ivlen * sizeof(PN));
530 }
534  vPN(Object) obj = (struct PNObject *)self;
535  return sizeof(struct PNObject) + (((struct PNVtable *)PN_VTABLE(obj->vt))->ivlen * sizeof(PN));
536 }
540 PN potion_lobby_isa(Potion *P, PN cl, PN self, vPN(Vtable) vtable) {
541  PNType t = PN_TYPE(self);
542  PNType t1 = vtable->type;
543  PN_CHECK_TYPE(vtable, PN_TVTABLE);
544  if (!PN_TYPECHECK(t1)) return potion_type_error(P, (PN)vtable);
545  if (PN_IS_PTR(self) && !PN_TYPECHECK(t)) return potion_type_error(P, self);
546  return t == t1 ? PN_TRUE : PN_FALSE;
547 }
552 PN potion_object_subclass(Potion *P, PN cl, PN self, vPN(Vtable) vtable) {
553  PNType t = PN_TYPE(self);
554  PNType t0, p;
555  if (potion_lobby_isa(P, cl, self, vtable) == PN_TRUE) return PN_TRUE;
556  if (!PN_IS_PTR(self))
557  return vtable->type == PN_TNUMBER
558  ? (t == PN_TINTEGER ? PN_TRUE : PN_FALSE) // Integer is a subclass of Number
559  : PN_FALSE; // other primitives have no parents
560  t0 = vtable->type;
561  while ((p = ((struct PNVtable *)PN_VTABLE(t))->parent)) {
562  if (t0 == p) return PN_TRUE;
563  t = p;
564  }
565  return PN_FALSE;
566 }
567 
570 PN potion_get_metaclass(Potion *P, PN cl, vPN(Vtable) self) {
571  return (PN)self->meta;
572 }
573 
577 static PN potion_lobby_self(Potion *P, PN cl, PN self) {
578  return self;
579 }
580 
585  PN str = ((struct PNVtable *)self)->name;
586  return (void *)str != PN_NIL ? str :
587  PN_IS_METACLASS(self) ? potion_str(P, "<metaclass>") : potion_str(P, "<class>");
588 }
589 
593 PN potion_lobby_kind(Potion *P, PN cl, PN self) {
594  PNType t = PN_TYPE(self);
595  if (!PN_TYPECHECK(t)) return PN_NIL; // TODO: error
596  return PN_VTABLE(t);
597 }
598 
602 PN potion_lobby_can(Potion *P, PN cl, PN self, PN method) {
603  return potion_bind(P, self, method) ? PN_TRUE : PN_FALSE;
604 }
605 
609  return potion_send(potion_send(self, PN_string), PN_print);
610 }
614 PN potion_lobby_say(Potion *P, PN cl, PN self) {
616  printf("\n");
617  return PN_STR0;
618 }
619 
621  char meta_str[strlen("<metaclass: >") + PN_STR_LEN(name) + 1];
622  potion_send(P->lobby, PN_def, name, vt);
623  ((struct PNVtable *)vt)->name = name;
624  sprintf(meta_str, "<metaclass: %s>", PN_STR_PTR(name));
625  ((struct PNVtable *)vt)->meta->name = potion_str(P, meta_str);
626 }
627 
629  if (PN_TYPE(val) == PN_TVTABLE && !PN_IS_METACLASS(val)) {
630  potion_init_class_reference(P, name, val);
631  } else {
632  potion_send(P->lobby, PN_def, name, val);
633  }
634 }
635 
639 PN potion_about(Potion *P, PN cl, PN self) {
640  PN about = potion_table_empty(P);
641  potion_table_put(P, PN_NIL, about, potion_str(P, "_why"),
642  potion_str(P, "“I love _why, but learning Ruby from him is like trying to learn to pole vault "
643  "by having Salvador Dali punch you in the face.” - Steven Frank"));
644  potion_table_put(P, PN_NIL, about, potion_str(P, "minimalism"),
645  potion_str(P, "“The sad thing about ‘minimalism’ is that it has a name.” "
646  "- Steve Dekorte"));
647  potion_table_put(P, PN_NIL, about, potion_str(P, "stage fright"),
648  potion_str(P, "“Recently no move on Potion. I git pull everyday.” "
649  "- matz"));
650  potion_table_put(P, PN_NIL, about, potion_str(P, "terms of use"),
651  potion_str(P, "“Setting up my new anarchist bulletin board so that during registration, if you accept "
652  "the terms and conditions, you are banned forever.” - Dr. Casey Hall"));
653  potion_table_put(P, PN_NIL, about, potion_str(P, "help"),
654  potion_str(P, "`man which` - Evan Weaver"));
655  potion_table_put(P, PN_NIL, about, potion_str(P, "ts"),
656  potion_str(P, "“pigeon%” - Guy Decoux (1955 - 2008)"));
657  potion_table_put(P, PN_NIL, about, potion_str(P, "summary"),
658  potion_str(P, "“I smell as how a leprechaun looks.” - Alana Post"));
659  return about;
660 }
661 
664 PN potion_exit(Potion *P, PN cl, PN self) {
665  potion_destroy(P);
666  exit(0);
667 }
668 
670  PN clo_vt = PN_VTABLE(PN_TCLOSURE);
671  PN ref_vt = PN_VTABLE(PN_TWEAK);
672  PN obj_vt = PN_VTABLE(PN_TOBJECT);
673  potion_method(clo_vt, "code", potion_closure_code, 0);
674  potion_method(clo_vt, "string", potion_closure_string, 0);
675  potion_method(clo_vt, "arity", potion_closure_arity, 0);
676  potion_method(clo_vt, "minargs", potion_closure_minargs, 0);
677  potion_method(ref_vt, "string", potion_ref_string, 0);
678  potion_method(obj_vt, "forward", potion_object_forward, 0);
679  potion_method(obj_vt, "send", potion_object_send, 0);
680  potion_method(obj_vt, "string", potion_object_string, 0);
681  potion_method(obj_vt, "size", potion_object_size, 0);
682  potion_method(obj_vt, "subclass?", potion_object_subclass, "value=o");
683 }
684 
685 # ifdef P2
686 # define LOBBY_NAME "P2"
687 # define BOOLEAN_NAME "Bool"
688 # define NUMBER_NAME "Num"
689 # define INTEGER_NAME "Int"
690 # define DOUBLE_NAME "Dbl"
691 # define STRING_NAME "Str"
692 # else
693 # define LOBBY_NAME "Lobby"
694 # define BOOLEAN_NAME "Boolean"
695 # define NUMBER_NAME "Number"
696 # define INTEGER_NAME "Integer"
697 # define DOUBLE_NAME "Double"
698 # define STRING_NAME "String"
699 # endif
700 
705 
724  potion_init_class_reference(P, potion_str(P, "Continuation"), PN_VTABLE(PN_TCONT));
727 
728  P->call = P->callset = PN_FUNC(potion_no_call, 0);
729 
730  PN mixin_vt = PN_VTABLE(PN_TVTABLE);
732  potion_method(mixin_vt, "meta", potion_get_metaclass, 0);
733 
734  potion_method(P->lobby, "about", potion_about, 0);
735 #ifndef DISABLE_CALLCC
736  potion_method(P->lobby, "here", potion_callcc, 0);
737 #endif
738  potion_method(P->lobby, "exit", potion_exit, 0);
739  potion_method(P->lobby, "kind", potion_lobby_kind, 0);
740  potion_method(P->lobby, "isa?", potion_lobby_isa, "value=o");
741  potion_method(P->lobby, "srand", potion_srand, "seed=N");
742  potion_method(P->lobby, "rand", potion_rand, 0);
743  potion_method(P->lobby, "self", potion_lobby_self, 0);
744  potion_method(P->lobby, "string", potion_lobby_string, 0);
745  potion_method(P->lobby, "can", potion_lobby_can, "method=S");
746  potion_method(P->lobby, "print", potion_lobby_print, 0);
747  potion_method(P->lobby, "say", potion_lobby_say, 0);
748 }
PN potion_vm(Potion *, PN, PN, PN, PN_SIZE, PN *volatile)
the bytecode run-loop
Definition: vm.c:594
#define PN_IS_STR(v)
Definition: potion.h:175
PN potion_closure_new(Potion *P, PN_F meth, PN sig, PN_SIZE extra)
Definition: objmodel.c:17
#define PN_IS_METACLASS(v)
Definition: potion.h:180
PN potion_def_method(Potion *P, PN closure, PN self, PN key, PN method)
define a method for a class
Definition: objmodel.c:351
void potion_destroy(Potion *P)
Definition: internal.c:137
PN potion_rand(Potion *P, PN cl, PN self)
Definition: mt19937ar.c:173
PN potion_no_call(Potion *P, PN cl, PN self)
Definition: objmodel.c:194
PN potion_proto_method(Potion *P, PN cl, PN self, PN args)
only used in def_method
Definition: objmodel.c:343
#define PN_FLEX_NEEDS(X, N, V, T, S)
Definition: internal.h:40
PN potion_str(Potion *, const char *)
Definition: string.c:33
PN potion_class(Potion *P, PN cl, PN self, PN ivars)
create a user-class (ie type)
Definition: objmodel.c:257
PN potion_ref_string(Potion *P, PN cl, PN self, PN len)
Definition: objmodel.c:483
PN potion_exit(Potion *P, PN cl, PN self)
Definition: objmodel.c:664
#define PN_TSTATE
Definition: potion.h:116
klib hash table library based on double hashing http://en.wikipedia.org/wiki/Double_hashing ...
#define PN_TSTRING
Definition: potion.h:112
a tuple is an array of PNs.
Definition: potion.h:477
#define PN_TCLOSURE
Definition: potion.h:114
PN potion_lobby_can(Potion *P, PN cl, PN self, PN method)
Definition: objmodel.c:602
#define PN_ALLOC_N(V, T, C)
Definition: internal.h:13
PN PN_lookup
Definition: internal.c:14
#define PN_CLOSURE(x)
Definition: potion.h:225
PN potion_bind(Potion *P, PN rcv, PN msg)
find method for given receiver and message (method lookup)
Definition: objmodel.c:408
a closure is an anonymous function, without closed values,
Definition: potion.h:381
the central vtable, see io http://www.piumarta.com/pepsi/objmodel.pdf
Definition: table.h:24
#define PN_TUSER
Definition: potion.h:130
PN potion_obj_set(Potion *P, PN cl, PN self, PN ivar, PN value)
implements OP_SETPATH
Definition: objmodel.c:334
PN_SIZE void potion_bytes_obj_string(Potion *, PN, PN)
Definition: string.c:384
PN potion_lobby_say(Potion *P, PN cl, PN self)
Definition: objmodel.c:614
#define PN_PUT(T, X)
Definition: potion.h:275
int potion_sig_minargs(Potion *P, PN sig)
number of mandatory args, without any optional arguments
Definition: objmodel.c:112
PN potion_lobby_string(Potion *P, PN cl, PN self)
Definition: objmodel.c:584
#define PN_TLICK
Definition: potion.h:125
PN potion_table_put(Potion *P, PN cl, PN self, PN key, PN value)
Definition: table.c:98
PN PN_bitn
Definition: internal.c:17
PN PN potion_byte_str(Potion *, const char *)
Definition: string.c:331
PN potion_sig_string(Potion *P, PN cl, PN sig)
Definition: compile.c:60
void potion_lobby_init(Potion *P)
Definition: objmodel.c:704
PNTarget target
the jit
Definition: potion.h:655
#define potion_method(RCV, MSG, FN, SIG)
Definition: potion.h:789
#define PN_TUPLE_LEN(t)
Definition: potion.h:277
PN potion_closure_arity(Potion *P, PN cl, PN self)
Definition: objmodel.c:69
#define PN_TFILE
Definition: potion.h:117
#define PN_TCONT
Definition: potion.h:129
PN potion_ref(Potion *P, PN data)
Definition: objmodel.c:473
PN potion_byte_str2(Potion *, const char *, size_t len)
Definition: string.c:335
#define PN_TNIL
Definition: potion.h:107
unsigned int PNType
Definition: potion.h:79
#define PN_STR_LEN(x)
Definition: potion.h:223
static PN potion_fwd(PN)
the potion type is the 't' in the vtable tuple (m,t)
Definition: potion.h:570
#define TYPE_BATCH_SIZE
Definition: internal.h:33
static long potion_obj_find_ivar(Potion *P, PN self, PN ivar)
Definition: objmodel.c:310
#define PN_TINTEGER
Definition: potion.h:111
#define kh_end(h)
Definition: khash.h:229
void potion_type_call_is(PN vt, PN cl)
sets the default call method of the PNVtable
Definition: objmodel.c:230
#define STRING_NAME
Definition: objmodel.c:698
#define FUNCNAME
Definition: potion.h:586
PN PN_add
Definition: internal.c:17
#define kh_put(name, h, k, r)
Definition: khash.h:221
#define PN_TTUPLE
Definition: potion.h:115
PN potion_obj_bitl(Potion *P, PN a, PN b)
Definition: objmodel.c:460
void potion_add_metaclass(Potion *P, vPN(Vtable) vt)
Definition: objmodel.c:198
#define PN_TYPECHECK(t)
Definition: potion.h:137
PN PN_string
Definition: internal.c:14
a weak ref is used for upvals, it acts as a memory slot, non-volatile but mutable.
Definition: potion.h:488
#define BOOLEAN_NAME
Definition: objmodel.c:694
#define PN_TFLEX
Definition: potion.h:126
#define PN_TBYTES
Definition: potion.h:121
PNType potion_class_type(Potion *P, PN class)
Definition: objmodel.c:290
#define PN_NUM(i)
Definition: potion.h:213
#define PN_IS_REF(v)
Definition: potion.h:179
PN potion_sig_at(Potion *P, PN sig, int index)
Definition: objmodel.c:136
PN potion_class_find(Potion *P, PN name)
find class by name. At first only system metaclasses (types), no user classes yet.
Definition: objmodel.c:280
static void potion_init_class_reference(Potion *P, PN name, PN vt)
Definition: objmodel.c:620
int potion_munmap(void *mem, size_t len)
Definition: contrib.c:101
unsigned int PN_SIZE
Definition: potion.h:79
standard objects act like C structs the fields are defined by the type and it's a fixed size...
Definition: potion.h:304
PN name
classes/types need to be found by name.
Definition: table.h:28
PN potion_closure_string(Potion *P, PN cl, PN self, PN maxlen)
Definition: objmodel.c:52
PN potion_about(Potion *P, PN cl, PN self)
Definition: objmodel.c:639
PN potion_get_metaclass(Potion *P, PN cl, vPN(Vtable) self)
Definition: objmodel.c:570
#define PN_STR_B(x)
Definition: potion.h:224
PN potion_getter_method(Potion *P, PN cl, PN self)
only used in def_method
Definition: objmodel.c:347
PN ctor
meta PNVtable
Definition: table.h:33
PN potion_closure_code(Potion *P, PN cl, PN self)
Definition: objmodel.c:42
#define PN_TVTABLE
Definition: potion.h:119
#define DOUBLE_NAME
Definition: objmodel.c:697
PN lobby
root namespace
Definition: potion.h:657
PN potion_table_empty(Potion *P)
Definition: table.c:42
PN_SIZE len
Definition: potion.h:479
void potion_type_callset_is(PN vt, PN cl)
set default writer
Definition: objmodel.c:240
#define PN_UNIQ(x)
Definition: potion.h:247
void(* mcache)(Potion *, struct PNVtable *volatile, PNAsm *volatile *)
Definition: potion.h:605
#define PN_TOBJECT
Definition: potion.h:118
#define PN_TSOURCE
Definition: potion.h:120
#define PN_IS_CLOSURE(v)
Definition: potion.h:177
#define PN_TDOUBLE
Definition: potion.h:110
#define PN_FLEX_SIZE(N)
Definition: potion.h:240
PN potion_type_error(Potion *P, PN obj)
Definition: internal.c:273
the table class, based on khash
Definition: table.h:40
PN_IVAR_FUNC ivfunc
Definition: table.h:36
PN potion_tuple_new(Potion *, PN)
Definition: table.c:247
PN PN_sub
Definition: internal.c:17
PN potion_obj_get(Potion *P, PN cl, PN self, PN ivar)
implements OP_GETPATH
Definition: objmodel.c:327
#define PN_FALSE
Definition: potion.h:141
PN potion_obj_get_callset(Potion *P, PN obj)
get default writer
Definition: objmodel.c:244
void potion_define_global(Potion *P, PN name, PN val)
Definition: objmodel.c:628
PN potion_obj_sub(Potion *P, PN a, PN b)
Definition: objmodel.c:440
PN potion_obj_add(Potion *P, PN a, PN b)
Definition: objmodel.c:436
#define LOBBY_NAME
Definition: objmodel.c:693
#define PN_TBOOLEAN
Definition: potion.h:109
unsigned char u8
Definition: internal.h:8
#define PN_MEMCPY_N(X, Y, T, N)
Definition: internal.h:22
PN potion_tuple_bsearch(Potion *P, PN cl, PN self, PN x)
Definition: table.c:617
#define PN_TWEAK
Definition: potion.h:113
PN potion_ivars(Potion *P, PN cl, PN self, PN ivars)
Definition: objmodel.c:295
some assembler macros
void potion_object_init(Potion *P)
Definition: objmodel.c:669
PN potion_lobby_kind(Potion *P, PN cl, PN self)
Definition: objmodel.c:593
#define PN_CHECK_TYPE(obj, type)
Definition: potion.h:193
PN callset
generic call and setter
Definition: potion.h:661
PNAsm * potion_asm_new(Potion *P)
Definition: asm.c:13
#define PN_TRUE
Definition: potion.h:142
PN potion_obj_mult(Potion *P, PN a, PN b)
Definition: objmodel.c:444
PN potion_object_string(Potion *P, PN cl, vPN(Object) self)
Definition: objmodel.c:490
PN potion_obj_get_call(Potion *P, PN obj)
get the default accessor (usually "at")
Definition: objmodel.c:234
PNType parent
parent type, default: for P->lobby: PN_VTABLE(PN_TOBJECT)
Definition: table.h:26
PN potion_tuple_push(Potion *, PN, PN)
Definition: table.c:254
PN PN_mult
Definition: internal.c:17
non-API internal parts
PNFlex *volatile vts
built in types
Definition: potion.h:658
PN potion_obj_bitr(Potion *P, PN a, PN b)
Definition: objmodel.c:464
#define PN_IS_PTR(v)
Definition: potion.h:168
PN(* PN_IVAR_FUNC)(PNUniq hash)
Definition: table.h:19
PN potion_object_send(Potion *P, PN cl, PN self, PN method)
Definition: objmodel.c:514
ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS PN potion_callcc(Potion *P, PN cl, PN self)
Definition: callcc.c:102
#define NILKIND_NAME
Definition: potion.h:150
#define PN_FLEX_AT(N, I)
Definition: potion.h:239
#define PN_ALLOC_FUNC(size)
Definition: internal.h:88
void(* ivars)(Potion *, PN, PNAsm *volatile *)
Definition: potion.h:606
PN potion_type_new(Potion *P, PNType t, PN self)
create a non-user type, derived from self
Definition: objmodel.c:212
PN_SIZE potion_type_size(Potion *P, const struct PNObject *ptr)
Definition: gc.c:306
PN potion_closure_minargs(Potion *P, PN cl, PN self)
Definition: objmodel.c:76
#define kh_val(name, h, x)
Definition: khash.h:227
#define INTEGER_NAME
Definition: objmodel.c:696
PN potion_object_size(Potion *P, PN cl, PN self)
Definition: objmodel.c:533
PN_SIZE len
Definition: potion.h:586
#define PN_IS_PROTO(v)
Definition: potion.h:178
the global interpreter state P. currently singleton (not threads yet)
Definition: potion.h:653
#define PN_ALLOC(V, T)
Definition: internal.h:12
PN PN_div
Definition: internal.c:17
PN PN_def
Definition: internal.c:14
PN_SIZE pn_printf(Potion *, PN, const char *,...) __attribute__((format(printf
PN potion_obj_rem(Potion *P, PN a, PN b)
Definition: objmodel.c:452
unsigned char ptr[]
Definition: potion.h:586
#define PN_TYPE(x)
Definition: potion.h:133
#define PN_TPROTO
Definition: potion.h:122
The p2 API.
PN PN_print
Definition: internal.c:14
static PN potion_lobby_self(Potion *P, PN cl, PN self)
Definition: objmodel.c:577
PN potion_srand(Potion *P, PN cl, PN self, PN seed)
Definition: mt19937ar.c:163
#define PN_IS_INT(v)
Definition: potion.h:171
PN potion_message(Potion *P, PN rcv, PN msg)
Definition: objmodel.c:429
#define PN_QUICK_FWD(t, obj)
PN_QUICK_FWD - doing a single fwd check after a possible realloc.
Definition: potion.h:558
PNType type
current type
Definition: table.h:27
the central table type, based on core/khash.h
PN potion_object_forward(Potion *P, PN cl, PN self, PN method)
Definition: objmodel.c:504
_PN(* PN_F)(Potion *, PN, PN,...)
Definition: potion.h:216
PN potion_obj_bitn(Potion *P, PN a)
Definition: objmodel.c:456
PN potion_lookup(Potion *P, PN closure, PN self, PN key)
used in bind and def_method
Definition: objmodel.c:396
#define potion_send(RCV, MSG, ARGS...)
method caches (more great stuff from ian piumarta)
Definition: potion.h:781
PN potion_object_subclass(Potion *P, PN cl, PN self, vPN(Vtable) vtable)
Definition: objmodel.c:552
#define NUMBER_NAME
Definition: objmodel.c:695
PN potion_type_error_want(Potion *P, const char *param, PN obj, const char *type)
Definition: internal.c:277
PN potion_type_new2(Potion *P, PNType t, PN self, PN name)
create a named type
Definition: objmodel.c:224
int potion_sig_arity(Potion *P, PN sig)
number of args of sig tuple, implements the potion_closure_arity method.
Definition: objmodel.c:87
const char * name
Definition: compile.c:30
PN PN_bitl
Definition: internal.c:17
int ivlen
PN_TUPLE_LEN(ivars)
Definition: table.h:29
#define PN_TTABLE
Definition: potion.h:124
#define vPN(t)
Definition: buffile.c:34
volatile _PN PN
Definition: potion.h:81
PN PN_STR0
Definition: internal.c:18
#define PN_NIL
Definition: potion.h:139
#define PN_TNUMBER
Definition: potion.h:108
#define PN_IS_TUPLE(v)
Definition: potion.h:174
#define PN_CALLOC_N(V, T, C)
Definition: internal.h:14
#define PN_FUNC(f, s)
Definition: potion.h:228
void potion_type_constructor_is(PN vt, PN cl)
set default constructor
Definition: objmodel.c:250
#define PN_TERROR
Definition: potion.h:128
#define PN_TUPLE_EACH(T, I, V, B)
Definition: potion.h:288
PN PN_bitr
Definition: internal.c:17
PN potion_sig_name_at(Potion *P, PN sig, int index)
Definition: objmodel.c:170
#define PN_TOUCH(x)
Definition: potion.h:231
PN set[]
Definition: potion.h:481
void potion_fatal(char *message)
Definition: internal.c:286
const u8 args
Definition: compile.c:31
#define PN_STR_PTR(x)
Definition: potion.h:222
PN ivars
PNTuple of all our or the parents inherited vars.
Definition: table.h:30
#define PN_TUP0()
Definition: potion.h:270
#define PN_VTABLE(t)
Definition: potion.h:136
PN PN_rem
Definition: internal.c:17
PN potion_object_new(Potion *P, PN cl, PN self)
Definition: objmodel.c:522
PN potion_lobby_print(Potion *P, PN cl, PN self)
Definition: objmodel.c:608
PN potion_lobby_isa(Potion *P, PN cl, PN self, vPN(Vtable) vtable)
Definition: objmodel.c:540
#define kh_get(name, h, k)
Definition: khash.h:222
PN potion_obj_div(Potion *P, PN a, PN b)
Definition: objmodel.c:448
#define PN_PROTO(x)
Definition: potion.h:227