potion  0.2
 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 "potion.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  PN out = potion_byte_str(P, "function");
54  if (PN_CLOSURE(self)->name)
55  pn_printf(P, out, " %s", PN_STR_PTR(PN_CLOSURE(self)->name));
56  pn_printf(P, out, "(");
57  potion_bytes_obj_string(P, out, potion_sig_string(P,cl,PN_CLOSURE(self)->sig));
58  pn_printf(P, out, ")");
59  return PN_STR_B(out);
60 }
66  return PN_NUM(PN_CLOSURE(self)->arity);
67 }
73  return PN_NUM(PN_CLOSURE(self)->minargs);
74 }
75 
82 int potion_sig_arity(Potion *P, PN sig) {
83  if (PN_IS_TUPLE(sig)) {
84  //return PN_TUPLE_LEN(PN_CLOSURE(closure)->sig) / 2;
85  int count = 0;
86  struct PNTuple * volatile t = (struct PNTuple *)potion_fwd(sig);
87  if (t->len != 0) {
88  PN_SIZE i;
89  for (i = 0; i < t->len; i++) {
90  PN v = (PN)t->set[i];
91  if (PN_IS_STR(v)) count++; // names
92  // but not string default values
93  if (PN_IS_INT(v) && v == PN_NUM(':') && PN_IS_STR((PN)t->set[i+1])) count--;
94  }
95  }
96  return count;
97  }
98  else if (sig == PN_NIL)
99  return 0;
100  else {
101  potion_fatal("Invalid signature type for sig_arity");
102  return 0;
103  }
104 }
108  if (PN_IS_TUPLE(sig)) {
109  int count = 0;
110  struct PNTuple * volatile t = (struct PNTuple *)potion_fwd(sig);
111  if (t->len != 0) {
112  PN_SIZE i;
113  for (i = 0; i < t->len; i++) {
114  PN v = (PN)t->set[i];
115  if (PN_IS_STR(v)) count++; // count only names
116  if (PN_IS_INT(v) && v == PN_NUM('|')) break;
117  if (PN_IS_INT(v) && v == PN_NUM(':')) { count--; break; }
118  }
119  }
120  return count;
121  }
122  else if (sig == PN_NIL)
123  return 0;
124  else {
125  potion_fatal("wrong sig type for sig_minargs");
126  return 0;
127  }
128 }
129 
131 PN potion_sig_at(Potion *P, PN sig, int index) {
132  PN result = PN_NIL;
133  if (PN_IS_TUPLE(sig)) {
134  int count = -1;
135  struct PNTuple * volatile t = (struct PNTuple *)potion_fwd(sig);
136  if (t->len > 0) {
137  PN_SIZE i;
138  for (i = 0; i < t->len; i++) {
139  PN v = (PN)t->set[i];
140  if (PN_IS_STR(v)) count++;
141  if (PN_IS_INT(v) && v == PN_NUM(':') && PN_IS_STR((PN)t->set[i+1])) count--;
142  if (count == index) {
143  result = potion_tuple_new(P, v);
144  if (i+1 < t->len && PN_IS_INT((PN)t->set[i+1])) {
145  PN typ = (PN)t->set[i+1];
146  result = potion_tuple_push(P, result, typ);
147  if (i+2 < t->len && typ == PN_NUM(':'))
148  result = potion_tuple_push(P, result, (PN)t->set[i+2]);
149  }
150  return result;
151  }
152  }
153  }
154  return result;
155  }
156  else if (sig == PN_NIL)
157  return result;
158  else {
159  potion_fatal("wrong sig type for sig_at");
160  return 0;
161  }
162 }
163 
165 PN potion_sig_name_at(Potion *P, PN sig, int index) {
166  if (PN_IS_TUPLE(sig)) {
167  int count = -1;
168  struct PNTuple * volatile t = (struct PNTuple *)potion_fwd(sig);
169  if (t->len > 0) {
170  PN_SIZE i;
171  for (i = 0; i < t->len; i++) {
172  PN v = (PN)t->set[i];
173  if (PN_IS_STR(v)) count++;
174  if (PN_IS_INT(v) && v == PN_NUM(':') && PN_IS_STR((PN)t->set[i+1])) count--;
175  if (count == index)
176  return v;
177  }
178  }
179  return 0;
180  }
181  else if (sig == PN_NIL)
182  return 0;
183  else {
184  potion_fatal("wrong sig type for sig_at");
185  return 0;
186  }
187 }
188 
189 PN potion_no_call(Potion *P, PN cl, PN self) {
190  return self;
191 }
192 
193 void potion_add_metaclass(Potion *P, vPN(Vtable) vt) {
194  struct PNVtable *meta = vt->meta = PN_CALLOC_N(PN_TVTABLE, struct PNVtable, 0);
195  meta->type = PN_FLEX_SIZE(P->vts) + PN_TNIL;
196  PN_FLEX_NEEDS(1, P->vts, PN_TFLEX, PNFlex, TYPE_BATCH_SIZE);
197  PN_FLEX_SIZE(P->vts)++;
198  meta->name = PN_NIL;
199  meta->parent = PN_TVTABLE;
200  meta->methods = (struct PNTable *)potion_table_empty(P);
201  meta->ctor = PN_FUNC(potion_no_call, 0);
202  PN_VTABLE(meta->type) = (PN)meta;
203  meta->meta = NULL;
204  PN_TOUCH(P->vts);
205 }
208  vPN(Vtable) vt = PN_CALLOC_N(PN_TVTABLE, struct PNVtable, 0);
209  vt->type = t;
210  vt->name = PN_NIL;
211  vt->parent = self ? ((struct PNVtable *)self)->type : 0;
212  vt->methods = (struct PNTable *)potion_table_empty(P);
213  vt->ctor = PN_FUNC(potion_no_call, 0);
214  PN_VTABLE(t) = (PN)vt;
215  potion_add_metaclass(P, vt);
216  return (PN)vt;
217 }
220  vPN(Vtable) vt = (vPN(Vtable))potion_type_new(P, t, self);
221  vt->name = name;
222  return (PN)vt;
223 }
225 void potion_type_call_is(PN vt, PN cl) {
226  ((struct PNVtable *)vt)->call = cl;
227 }
230  PN cl = ((struct PNVtable *)PN_VTABLE(PN_TYPE(obj)))->call;
231  if (cl == PN_NIL) cl = P->call;
232  return cl;
233 }
236  ((struct PNVtable *)vt)->callset = cl;
237 }
240  PN cl = ((struct PNVtable *)PN_VTABLE(PN_TYPE(obj)))->callset;
241  if (cl == PN_NIL) cl = P->callset;
242  return cl;
243 }
246  ((struct PNVtable *)vt)->ctor = cl;
247 }
252 PN potion_class(Potion *P, PN cl, PN self, PN ivars) {
253  PN parent = ((!self || self == P->lobby) ? PN_VTABLE(PN_TOBJECT) : self);
254  PN pvars = ((struct PNVtable *)parent)->ivars;
255  PNType t = PN_FLEX_SIZE(P->vts) + PN_TNIL;
256  PN_FLEX_NEEDS(1, P->vts, PN_TFLEX, PNFlex, TYPE_BATCH_SIZE);
257  PN_FLEX_SIZE(P->vts)++;
258  self = potion_type_new(P, t, parent);
259  if (PN_IS_TUPLE(pvars)) {
260  if (!PN_IS_TUPLE(ivars)) ivars = PN_TUP0();
261  PN_TUPLE_EACH(pvars, i, v, {PN_PUT(ivars, v);});
262  }
263  if (PN_IS_TUPLE(ivars))
264  potion_ivars(P, PN_NIL, self, ivars);
265 
266  if (!PN_IS_CLOSURE(cl))
267  cl = ((struct PNVtable *)parent)->ctor;
268  ((struct PNVtable *)self)->ctor = cl;
269 
270  PN_TOUCH(P->vts);
271  return self;
272 }
273 
276  int i;
277  for (i=0; i < PN_FLEX_SIZE(P->vts); i++) {
278  vPN(Vtable) vt = (struct PNVtable *)PN_FLEX_AT(P->vts, i);
279  if (vt && vt->name == name)
280  return (PN)vt;
281  }
282  return PN_NIL;
283 }
286  struct PNVtable *vt = (struct PNVtable *)potion_fwd(class);
287  return vt->type;
288 }
289 
290 PN potion_ivars(Potion *P, PN cl, PN self, PN ivars) {
291  struct PNVtable *vt = (struct PNVtable *)self;
292 #ifdef POTION_JIT_TARGET
293  // TODO: allocate assembled instructions together into single pages
294  // since many times these tables are <100 bytes.
295  PNAsm * volatile asmb = potion_asm_new(P);
296  P->target.ivars(P, ivars, &asmb);
297  vt->ivfunc = (PN_IVAR_FUNC)PN_ALLOC_FUNC(asmb->len);
298  PN_MEMCPY_N(vt->ivfunc, asmb->ptr, u8, asmb->len);
299 #endif
300  vt->ivlen = PN_TUPLE_LEN(ivars);
301  vt->ivars = ivars;
302  return self;
303 }
304 
305 static inline long potion_obj_find_ivar(Potion *P, PN self, PN ivar) {
306  PNType t = PN_TYPE(self);
307  vPN(Vtable) vt = (struct PNVtable *)PN_VTABLE(t);
308  if (vt->ivfunc != NULL)
309  return vt->ivfunc(PN_UNIQ(ivar));
310 
311  if (t > PN_TUSER) {
312  PN ivars = ((struct PNVtable *)PN_VTABLE(t))->ivars;
313  if (ivars != PN_NIL) {
314  PN found = potion_tuple_bsearch(P, 0, ivars, ivar);
315  return found == PN_FALSE ? -1 : found;
316  }
317  }
318  return -1;
319 }
320 
322 PN potion_obj_get(Potion *P, PN cl, PN self, PN ivar) {
323  long i = potion_obj_find_ivar(P, self, ivar);
324  if (i >= 0)
325  return ((struct PNObject *)self)->ivars[i];
326  return PN_NIL;
327 }
329 PN potion_obj_set(Potion *P, PN cl, PN self, PN ivar, PN value) {
330  long i = potion_obj_find_ivar(P, self, ivar);
331  if (i >= 0) {
332  ((struct PNObject *)self)->ivars[i] = value;
333  PN_TOUCH(self);
334  }
335  return value;
336 }
339  return potion_vm(P, PN_CLOSURE(cl)->data[0], P->lobby, args, 0, NULL);
340 }
343  return PN_CLOSURE(cl)->data[0];
344 }
346 PN potion_def_method(Potion *P, PN closure, PN self, PN key, PN method) {
347  int ret;
348  PN cl;
349  vPN(Vtable) vt = (struct PNVtable *)self;
350  if (PN_TVTABLE != PN_TYPE(self)) return potion_type_error_want(P, "self.def_method", self, "VTable (a class)");
351  unsigned k = kh_put(PN, vt->methods, key, &ret);
352  PN_QUICK_FWD(struct PNTable *, vt->methods);
353  PN_TOUCH(vt->methods);
354 
355  if (!PN_IS_CLOSURE(method)) {
356  if (PN_IS_PROTO(method)) {
357  cl = potion_closure_new(P, (PN_F)potion_proto_method, PN_PROTO(method)->sig, 1);
358  PN_PROTO(method)->name = key;
359  }
360  else
362  PN_CLOSURE(cl)->data[0] = method;
363  PN_CLOSURE(cl)->name = key;
364  method = cl;
365  }
366  else
367  PN_CLOSURE(method)->name = key;
368 
369  kh_val(PN, vt->methods, k) = method;
370  PN_TOUCH(self);
371 
372 #ifdef JIT_MCACHE
373  // TODO: make JIT_MCACHE more flexible, store in fixed gc, see ivfunc TODO also
374  // TODO: this is disabled until method weakrefs can be stored in fixed memory
375  if (P->target.mcache != NULL) {
376  PNAsm * volatile asmb = potion_asm_new(P);
377  P->target.mcache(P, vt, &asmb);
378  if (asmb->len <= 4096) {
379  if (vt->mcache == NULL)
380  vt->mcache = PN_ALLOC_FUNC(4096);
381  PN_MEMCPY_N(vt->mcache, asmb->ptr, u8, asmb->len);
382  } else if (vt->mcache != NULL) {
383  potion_munmap(vt->mcache, 4096);
384  vt->mcache = NULL;
385  }
386  }
387 #endif
388  return method;
389 }
391 PN potion_lookup(Potion *P, PN closure, PN self, PN key) {
392  vPN(Vtable) vt = (struct PNVtable *)self;
393 #ifdef JIT_MCACHE
394  if (vt->mcache != NULL)
395  return vt->mcache(PN_UNIQ(key));
396 #endif
397  unsigned k = kh_get(PN, vt->methods, key);
398  if (k != kh_end(vt->methods)) return kh_val(PN, vt->methods, k);
399  return PN_NIL;
400 }
401 
403 PN potion_bind(Potion *P, PN rcv, PN msg) {
404  PN closure = PN_NIL;
405  PN vt = PN_NIL;
406  PNType t = PN_TYPE(rcv);
407  if (!PN_TYPECHECK(t)) return PN_NIL;
408  if (t == PN_TVTABLE && !PN_IS_METACLASS(rcv)) {
409  vt = (PN)((struct PNVtable *)rcv)->meta;
410  } else {
411  vt = PN_VTABLE(t);
412  }
413  while (1) {
414  closure = ((msg == PN_lookup) && (t == PN_TVTABLE))
415  ? potion_lookup(P, 0, vt, msg)
416  : potion_send(vt, PN_lookup, msg);
417  if (closure || !((struct PNVtable *)vt)->parent) break;
418  vt = PN_VTABLE(((struct PNVtable *)vt)->parent);
419  }
420  return closure;
421 }
422 
423 PN potion_message(Potion *P, PN rcv, PN msg) {
424  PN cl = potion_bind(P, rcv, msg);
425  if (PN_IS_CLOSURE(cl) && PN_CLOSURE(cl)->sig == PN_NIL)
426  return PN_CLOSURE(cl)->method(P, cl, rcv, PN_NIL);
427  return cl;
428 }
429 
431  return potion_send(a, PN_add, b);
432 }
433 
435  return potion_send(a, PN_sub, b);
436 }
437 
439  return potion_send(a, PN_mult, b);
440 }
441 
443  return potion_send(a, PN_div, b);
444 }
445 
447  return potion_send(a, PN_rem, b);
448 }
449 
451  return potion_send(a, PN_bitn);
452 }
453 
455  return potion_send(a, PN_bitl, b);
456 }
457 
459  return potion_send(a, PN_bitr, b);
460 }
461 
467 PN potion_ref(Potion *P, PN data) {
468  if (PN_IS_REF(data)) return data;
469  vPN(WeakRef) ref = PN_ALLOC(PN_TWEAK, struct PNWeakRef);
470  ref->data = data;
471  return (PN)ref;
472 }
473 
477 PN potion_ref_string(Potion *P, PN cl, PN self, PN len) {
478  return potion_str(P, "<ref>");
479 }
480 
484 PN potion_object_string(Potion *P, PN cl, vPN(Object) self) {
485  struct PNVtable *vt = (struct PNVtable *)PN_VTABLE(self->vt);
486  if (vt->name != PN_NIL) {
487  PN str = potion_byte_str2(P, NULL, 0);
488  pn_printf(P, str, "<%s %lx>", PN_STR_PTR(vt->name), (PN)self);
489  return potion_send(str, PN_string);
490  }
491 
492  return potion_str(P, "<object>");
493 }
494 
498 PN potion_object_forward(Potion *P, PN cl, PN self, PN method) {
499  printf("#<object>");
500  return PN_NIL;
501 }
502 
508 PN potion_object_send(Potion *P, PN cl, PN self, PN method) {
509  return potion_send(self, method);
510 }
511 
516 PN potion_object_new(Potion *P, PN cl, PN self) {
517  vPN(Vtable) vt = (struct PNVtable *)self;
518  if (PN_IS_METACLASS(vt)) // TODO: error
519  return PN_NIL;
520  if (vt->type == PN_TVTABLE) // TODO: error
521  return PN_NIL;
522  return (PN)PN_ALLOC_N(vt->type, struct PNObject,
523  potion_type_size(P, (struct PNObject *)self) - sizeof(struct PNObject) + vt->ivlen * sizeof(PN));
524 }
528  vPN(Object) obj = (struct PNObject *)self;
529  return sizeof(struct PNObject) + (((struct PNVtable *)PN_VTABLE(obj->vt))->ivlen * sizeof(PN));
530 }
534 PN potion_lobby_isa(Potion *P, PN cl, PN self, vPN(Vtable) vtable) {
535  PNType t = PN_TYPE(self);
536  PNType t1 = vtable->type;
537  PN_CHECK_TYPE(vtable, PN_TVTABLE);
538  if (!PN_TYPECHECK(t1)) return potion_type_error(P, (PN)vtable);
539  if (PN_IS_PTR(self) && !PN_TYPECHECK(t)) return potion_type_error(P, self);
540  return t == t1 ? PN_TRUE : PN_FALSE;
541 }
546 PN potion_object_subclass(Potion *P, PN cl, PN self, vPN(Vtable) vtable) {
547  PNType t = PN_TYPE(self);
548  PNType t0, p;
549  if (potion_lobby_isa(P, cl, self, vtable) == PN_TRUE) return PN_TRUE;
550  if (!PN_IS_PTR(self))
551  return vtable->type == PN_TNUMBER
552  ? (t == PN_TINTEGER ? PN_TRUE : PN_FALSE) // Integer is a subclass of Number
553  : PN_FALSE; // other primitives have no parents
554  t0 = vtable->type;
555  while ((p = ((struct PNVtable *)PN_VTABLE(t))->parent)) {
556  if (t0 == p) return PN_TRUE;
557  t = p;
558  }
559  return PN_FALSE;
560 }
561 
564 PN potion_get_metaclass(Potion *P, PN cl, vPN(Vtable) self) {
565  return (PN)self->meta;
566 }
567 
571 static PN potion_lobby_self(Potion *P, PN cl, PN self) {
572  return self;
573 }
574 
579  PN str = ((struct PNVtable *)self)->name;
580  return (void *)str != PN_NIL ? str :
581  PN_IS_METACLASS(self) ? potion_str(P, "<metaclass>") : potion_str(P, "<class>");
582 }
583 
587 PN potion_lobby_kind(Potion *P, PN cl, PN self) {
588  PNType t = PN_TYPE(self);
589  if (!PN_TYPECHECK(t)) return PN_NIL; // TODO: error
590  return PN_VTABLE(t);
591 }
592 
596 PN potion_lobby_can(Potion *P, PN cl, PN self, PN method) {
597  return potion_bind(P, self, method) ? PN_TRUE : PN_FALSE;
598 }
599 
603  return potion_send(potion_send(self, PN_string), PN_print);
604 }
608 PN potion_lobby_say(Potion *P, PN cl, PN self) {
610  printf("\n");
611  return PN_STR0;
612 }
613 
615  char meta_str[strlen("<metaclass: >") + PN_STR_LEN(name) + 1];
616  potion_send(P->lobby, PN_def, name, vt);
617  ((struct PNVtable *)vt)->name = name;
618  sprintf(meta_str, "<metaclass: %s>", PN_STR_PTR(name));
619  ((struct PNVtable *)vt)->meta->name = potion_str(P, meta_str);
620 }
621 
623  if (PN_TYPE(val) == PN_TVTABLE && !PN_IS_METACLASS(val)) {
624  potion_init_class_reference(P, name, val);
625  } else {
626  potion_send(P->lobby, PN_def, name, val);
627  }
628 }
629 
633 PN potion_about(Potion *P, PN cl, PN self) {
634  PN about = potion_table_empty(P);
635  potion_table_put(P, PN_NIL, about, potion_str(P, "_why"),
636  potion_str(P, "“I love _why, but learning Ruby from him is like trying to learn to pole vault "
637  "by having Salvador Dali punch you in the face.” - Steven Frank"));
638  potion_table_put(P, PN_NIL, about, potion_str(P, "minimalism"),
639  potion_str(P, "“The sad thing about ‘minimalism’ is that it has a name.” "
640  "- Steve Dekorte"));
641  potion_table_put(P, PN_NIL, about, potion_str(P, "stage fright"),
642  potion_str(P, "“Recently no move on Potion. I git pull everyday.” "
643  "- matz"));
644  potion_table_put(P, PN_NIL, about, potion_str(P, "terms of use"),
645  potion_str(P, "“Setting up my new anarchist bulletin board so that during registration, if you accept "
646  "the terms and conditions, you are banned forever.” - Dr. Casey Hall"));
647  potion_table_put(P, PN_NIL, about, potion_str(P, "help"),
648  potion_str(P, "`man which` - Evan Weaver"));
649  potion_table_put(P, PN_NIL, about, potion_str(P, "ts"),
650  potion_str(P, "“pigeon%” - Guy Decoux (1955 - 2008)"));
651  potion_table_put(P, PN_NIL, about, potion_str(P, "summary"),
652  potion_str(P, "“I smell as how a leprechaun looks.” - Alana Post"));
653  return about;
654 }
655 
658 PN potion_exit(Potion *P, PN cl, PN self) {
659  potion_destroy(P);
660  exit(0);
661 }
662 
664  PN clo_vt = PN_VTABLE(PN_TCLOSURE);
665  PN ref_vt = PN_VTABLE(PN_TWEAK);
666  PN obj_vt = PN_VTABLE(PN_TOBJECT);
667  potion_method(clo_vt, "code", potion_closure_code, 0);
668  potion_method(clo_vt, "string", potion_closure_string, 0);
669  potion_method(clo_vt, "arity", potion_closure_arity, 0);
670  potion_method(clo_vt, "minargs", potion_closure_minargs, 0);
671  potion_method(ref_vt, "string", potion_ref_string, 0);
672  potion_method(obj_vt, "forward", potion_object_forward, 0);
673  potion_method(obj_vt, "send", potion_object_send, 0);
674  potion_method(obj_vt, "string", potion_object_string, 0);
675  potion_method(obj_vt, "size", potion_object_size, 0);
676  potion_method(obj_vt, "subclass?", potion_object_subclass, "value=o");
677 }
678 
683  potion_init_class_reference(P, potion_str(P, "Lobby"), P->lobby);
701  potion_init_class_reference(P, potion_str(P, "Continuation"), PN_VTABLE(PN_TCONT));
704 
705  P->call = P->callset = PN_FUNC(potion_no_call, 0);
706 
707  PN mixin_vt = PN_VTABLE(PN_TVTABLE);
709  potion_method(mixin_vt, "meta", potion_get_metaclass, 0);
710 
711  potion_method(P->lobby, "about", potion_about, 0);
712 #ifndef DISABLE_CALLCC
713  potion_method(P->lobby, "here", potion_callcc, 0);
714 #endif
715  potion_method(P->lobby, "exit", potion_exit, 0);
716  potion_method(P->lobby, "kind", potion_lobby_kind, 0);
717  potion_method(P->lobby, "isa?", potion_lobby_isa, "value=o");
718  potion_method(P->lobby, "srand", potion_srand, "seed=N");
719  potion_method(P->lobby, "rand", potion_rand, 0);
720  potion_method(P->lobby, "self", potion_lobby_self, 0);
721  potion_method(P->lobby, "string", potion_lobby_string, 0);
722  potion_method(P->lobby, "can", potion_lobby_can, "method=S");
723  potion_method(P->lobby, "print", potion_lobby_print, 0);
724  potion_method(P->lobby, "say", potion_lobby_say, 0);
725 }
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:166
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:171
PN potion_def_method(Potion *P, PN closure, PN self, PN key, PN method)
define a method for a class
Definition: objmodel.c:346
void potion_destroy(Potion *P)
Definition: internal.c:133
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:189
PN potion_proto_method(Potion *P, PN cl, PN self, PN args)
only used in def_method
Definition: objmodel.c:338
#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:252
PN potion_ref_string(Potion *P, PN cl, PN self, PN len)
Definition: objmodel.c:477
PN potion_exit(Potion *P, PN cl, PN self)
Definition: objmodel.c:658
#define vPN(t)
Definition: potion.h:132
#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:468
#define PN_TCLOSURE
Definition: potion.h:114
PN potion_lobby_can(Potion *P, PN cl, PN self, PN method)
Definition: objmodel.c:596
#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:216
PN potion_bind(Potion *P, PN rcv, PN msg)
find method for given receiver and message (method lookup)
Definition: objmodel.c:403
a closure is an anonymous function, without closed values,
Definition: potion.h:372
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:329
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:608
#define PN_PUT(T, X)
Definition: potion.h:266
int potion_sig_minargs(Potion *P, PN sig)
number of mandatory args, without any optional arguments
Definition: objmodel.c:107
PN potion_lobby_string(Potion *P, PN cl, PN self)
Definition: objmodel.c:578
#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:682
PNTarget target
the jit
Definition: potion.h:646
#define potion_method(RCV, MSG, FN, SIG)
Definition: potion.h:780
#define PN_TUPLE_LEN(t)
Definition: potion.h:268
PN potion_closure_arity(Potion *P, PN cl, PN self)
Definition: objmodel.c:64
#define PN_TFILE
Definition: potion.h:117
#define PN_TCONT
Definition: potion.h:129
PN potion_ref(Potion *P, PN data)
Definition: objmodel.c:467
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:214
static PN potion_fwd(PN)
the potion type is the 't' in the vtable tuple (m,t)
Definition: potion.h:561
#define TYPE_BATCH_SIZE
Definition: internal.h:33
static long potion_obj_find_ivar(Potion *P, PN self, PN ivar)
Definition: objmodel.c:305
#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:225
Definition: potion.h:577
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:454
void potion_add_metaclass(Potion *P, vPN(Vtable) vt)
Definition: objmodel.c:193
#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:479
#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:285
#define PN_NUM(i)
Definition: potion.h:204
#define PN_IS_REF(v)
Definition: potion.h:170
PN potion_sig_at(Potion *P, PN sig, int index)
Definition: objmodel.c:131
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:275
static void potion_init_class_reference(Potion *P, PN name, PN vt)
Definition: objmodel.c:614
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:295
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:633
PN potion_get_metaclass(Potion *P, PN cl, vPN(Vtable) self)
Definition: objmodel.c:564
#define PN_STR_B(x)
Definition: potion.h:215
PN potion_getter_method(Potion *P, PN cl, PN self)
only used in def_method
Definition: objmodel.c:342
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
PN lobby
root namespace
Definition: potion.h:648
PN potion_table_empty(Potion *P)
Definition: table.c:42
PN_SIZE len
Definition: potion.h:470
void potion_type_callset_is(PN vt, PN cl)
set default writer
Definition: objmodel.c:235
#define PN_UNIQ(x)
Definition: potion.h:238
void(* mcache)(Potion *, struct PNVtable *volatile, PNAsm *volatile *)
Definition: potion.h:596
#define PN_TOBJECT
Definition: potion.h:118
#define PN_TSOURCE
Definition: potion.h:120
#define PN_IS_CLOSURE(v)
Definition: potion.h:168
#define PN_TDOUBLE
Definition: potion.h:110
#define PN_FLEX_SIZE(N)
Definition: potion.h:231
PN potion_type_error(Potion *P, PN obj)
Definition: internal.c:269
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:322
#define PN_FALSE
Definition: potion.h:141
PN potion_obj_get_callset(Potion *P, PN obj)
get default writer
Definition: objmodel.c:239
void potion_define_global(Potion *P, PN name, PN val)
Definition: objmodel.c:622
PN potion_obj_sub(Potion *P, PN a, PN b)
Definition: objmodel.c:434
PN potion_obj_add(Potion *P, PN a, PN b)
Definition: objmodel.c:430
#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:614
#define PN_TWEAK
Definition: potion.h:113
PN potion_ivars(Potion *P, PN cl, PN self, PN ivars)
Definition: objmodel.c:290
some assembler macros
void potion_object_init(Potion *P)
Definition: objmodel.c:663
PN potion_lobby_kind(Potion *P, PN cl, PN self)
Definition: objmodel.c:587
#define PN_CHECK_TYPE(obj, type)
Definition: potion.h:184
PN callset
generic call and setter
Definition: potion.h:652
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:438
PN potion_object_string(Potion *P, PN cl, vPN(Object) self)
Definition: objmodel.c:484
PN potion_obj_get_call(Potion *P, PN obj)
get the default accessor (usually "at")
Definition: objmodel.c:229
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:649
PN potion_obj_bitr(Potion *P, PN a, PN b)
Definition: objmodel.c:458
#define PN_IS_PTR(v)
Definition: potion.h:159
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:508
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:230
#define PN_ALLOC_FUNC(size)
Definition: internal.h:88
void(* ivars)(Potion *, PN, PNAsm *volatile *)
Definition: potion.h:597
PN potion_type_new(Potion *P, PNType t, PN self)
create a non-user type, derived from self
Definition: objmodel.c:207
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:71
#define kh_val(name, h, x)
Definition: khash.h:227
PN potion_object_size(Potion *P, PN cl, PN self)
Definition: objmodel.c:527
PN_SIZE len
Definition: potion.h:577
#define PN_IS_PROTO(v)
Definition: potion.h:169
the global interpreter state P. currently singleton (not threads yet)
Definition: potion.h:644
#define PN_ALLOC(V, T)
Definition: internal.h:12
PN PN_div
Definition: internal.c:17
The potion API.
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:446
unsigned char ptr[]
Definition: potion.h:577
#define PN_TYPE(x)
Definition: potion.h:133
#define PN_TPROTO
Definition: potion.h:122
PN PN_print
Definition: internal.c:14
static PN potion_lobby_self(Potion *P, PN cl, PN self)
Definition: objmodel.c:571
PN potion_srand(Potion *P, PN cl, PN self, PN seed)
Definition: mt19937ar.c:163
#define PN_IS_INT(v)
Definition: potion.h:162
PN potion_message(Potion *P, PN rcv, PN msg)
Definition: objmodel.c:423
#define PN_QUICK_FWD(t, obj)
PN_QUICK_FWD - doing a single fwd check after a possible realloc.
Definition: potion.h:549
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:498
_PN(* PN_F)(Potion *, PN, PN,...)
Definition: potion.h:207
PN potion_obj_bitn(Potion *P, PN a)
Definition: objmodel.c:450
PN potion_lookup(Potion *P, PN closure, PN self, PN key)
used in bind and def_method
Definition: objmodel.c:391
#define potion_send(RCV, MSG, ARGS...)
method caches (more great stuff from ian piumarta)
Definition: potion.h:772
PN potion_object_subclass(Potion *P, PN cl, PN self, vPN(Vtable) vtable)
Definition: objmodel.c:546
PN potion_type_error_want(Potion *P, const char *param, PN obj, const char *type)
Definition: internal.c:273
PN potion_type_new2(Potion *P, PNType t, PN self, PN name)
create a named type
Definition: objmodel.c:219
int potion_sig_arity(Potion *P, PN sig)
number of args of sig tuple, implements the potion_closure_arity method.
Definition: objmodel.c:82
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
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:165
#define PN_CALLOC_N(V, T, C)
Definition: internal.h:14
#define PN_FUNC(f, s)
Definition: potion.h:219
void potion_type_constructor_is(PN vt, PN cl)
set default constructor
Definition: objmodel.c:245
#define PN_TERROR
Definition: potion.h:128
#define PN_TUPLE_EACH(T, I, V, B)
Definition: potion.h:279
PN PN_bitr
Definition: internal.c:17
PN potion_sig_name_at(Potion *P, PN sig, int index)
Definition: objmodel.c:165
#define PN_TOUCH(x)
Definition: potion.h:222
PN set[]
Definition: potion.h:472
void potion_fatal(char *message)
Definition: internal.c:282
const u8 args
Definition: compile.c:31
#define PN_STR_PTR(x)
Definition: potion.h:213
PN ivars
PNTuple of all our or the parents inherited vars.
Definition: table.h:30
#define PN_TUP0()
Definition: potion.h:261
#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:516
PN potion_lobby_print(Potion *P, PN cl, PN self)
Definition: objmodel.c:602
PN potion_lobby_isa(Potion *P, PN cl, PN self, vPN(Vtable) vtable)
Definition: objmodel.c:534
#define kh_get(name, h, k)
Definition: khash.h:222
PN potion_obj_div(Potion *P, PN a, PN b)
Definition: objmodel.c:442
#define PN_PROTO(x)
Definition: potion.h:218