p2  0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
table.c
Go to the documentation of this file.
1 //
6 // (c) 2008 why the lucky stiff, the freelance professor
7 // (c) 2013 perl11 org
8 //
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include "p2.h"
12 #include "internal.h"
13 #include "khash.h"
14 #include "table.h"
15 
16 #define NEW_TUPLE(t, size) \
17  vPN(Tuple) t = PN_ALLOC_N(PN_TTUPLE, struct PNTuple, size * sizeof(PN)); \
18  t->alloc = t->len = size
19 
24  vPN(Table) t = (vPN(Table))potion_fwd(self);
26  PN out = potion_byte_str(P, "(");
27  unsigned k, i = 0;
28  for (k = kh_begin(t); k != kh_end(t); ++k)
29  if (kh_exist(PN, t, k)) {
30  if (i++ > 0) pn_printf(P, out, ", ");
31  potion_bytes_obj_string(P, out, kh_key(PN, t, k));
32  pn_printf(P, out, "=");
33  potion_bytes_obj_string(P, out, kh_val(PN, t, k));
34  }
35  pn_printf(P, out, ")");
36  return PN_STR_B(out);
37 }
38 
43  return (PN)PN_ALLOC_N(PN_TTABLE, struct PNTable, 0);
44 }
45 
48  if (PN_IS_TUPLE(self)) {
49  int ret; unsigned k;
50  vPN(Table) t = PN_ALLOC_N(PN_TTABLE, struct PNTable, 0);
51  PN_TUPLE_EACH(self, i, v, {
52  k = kh_put(PN, t, PN_NUM(i), &ret);
53  PN_QUICK_FWD(struct PNTable *, t);
54  kh_val(PN, t, k) = v;
55  });
56  ((struct PNFwd *)self)->fwd = POTION_FWD;
57  ((struct PNFwd *)self)->siz = potion_type_size(P, (const struct PNObject *)self);
58  ((struct PNFwd *)self)->ptr = (PN)t;
59  PN_TOUCH(self);
60  self = (PN)t;
61  }
63  return self;
64 }
65 
70 PN potion_table_at(Potion *P, PN cl, PN self, PN key) {
71  vPN(Table) t = (vPN(Table))potion_fwd(self);
73  unsigned k = kh_get(PN, t, key);
74  if (k != kh_end(t)) return kh_val(PN, t, k);
75  return PN_NIL;
76 }
77 
82 PN potion_table_each(Potion *P, PN cl, PN self, PN block) {
83  vPN(Table) t = (struct PNTable *)potion_fwd(self);
84  unsigned k;
86  for (k = kh_begin(t); k != kh_end(t); ++k)
87  if (kh_exist(PN, t, k)) {
88  PN_CLOSURE(block)->method(P, block, P->lobby, kh_key(PN, t, k), kh_val(PN, t, k));
89  }
90  return self;
91 }
92 
98 PN potion_table_put(Potion *P, PN cl, PN self, PN key, PN value) {
99  int ret;
100  vPN(Table) t = (vPN(Table))potion_fwd(self);
102  unsigned k = kh_put(PN, t, key, &ret);
103  PN_QUICK_FWD(struct PNTable * volatile, t);
104  kh_val(PN, t, k) = value;
105  PN_TOUCH(self);
106  return self;
107 }
108 
113 PN potion_table_remove(Potion *P, PN cl, PN self, PN key) {
114  vPN(Table) t = (vPN(Table))potion_fwd(self);
116  unsigned k = kh_get(PN, t, key);
117  if (k != kh_end(t)) kh_del(PN, t, k);
118  PN_TOUCH(self);
119  return self;
120 }
121 
126 PN potion_table_set(Potion *P, PN self, PN key, PN value) {
127  self = potion_fwd(self);
128  return potion_table_put(P, PN_NIL, potion_table_cast(P, self), key, value);
129 }
130 
135  vPN(Table) t = (vPN(Table))potion_fwd(self);
137  return PN_NUM(kh_size(t));
138 }
139 
140 static
142  vPN(Table) t = (vPN(Table))potion_fwd(self);
144  vPN(Table) t2 = (vPN(Table))PN_ALLOC_N(PN_TTABLE, struct PNTable, 0);
145  unsigned k; int ret;
146  t2 = kh_resize_PN(P, t2, kh_size(t));
147  for (k = kh_begin(t); k != kh_end(t); ++k)
148  if (kh_exist(PN, t, k)) {
149  unsigned key = kh_put(PN, t2, kh_key(PN, t, k), &ret);
150  PN_QUICK_FWD(struct PNTable *, t);
151  PN_QUICK_FWD(struct PNTable *, t2);
152  kh_val(PN, t2, key) = kh_val(PN, t, k);
153  }
154  PN_TOUCH(t2);
155  return (PN)t2;
156 }
157 
168 static
169 PN potion_table_slice(Potion *P, PN cl, PN self, PN keys) {
170  vPN(Table) t = (vPN(Table))potion_fwd(self);
172  if (!keys)
173  return potion_table_clone(P, cl, self);
174  else {
176  }
177  vPN(Table) t2 = (vPN(Table))PN_ALLOC_N(PN_TTABLE, struct PNTable, 0);
178  t2 = kh_resize_PN(P, t2, PN_TUPLE_LEN(keys)); //ca, could overshoot for dupl and outliers
179  PN_TUPLE_EACH(keys, i, v, {
180  DBG_vt("%d:%ld ", i, PN_INT(v));
181  unsigned k = kh_get(PN, t, v);
182  if (k != kh_end(t)) {
183  int ret;
184  unsigned k2 = kh_put(PN, t2, v, &ret);
185  PN_QUICK_FWD(struct PNTable *, t);
186  PN_QUICK_FWD(struct PNTable *, t2);
187  kh_val(PN, t2, k2) = kh_val(PN, t, k);
188  }
189  });
190  PN_TOUCH(t2);
191  return (PN)t2;
192 }
193 
199 static
200 PN potion_table_keys(Potion *P, PN cl, PN self) {
201  vPN(Table) t = (vPN(Table))potion_fwd(self);
203  NEW_TUPLE(t2, kh_size(t));
204  int i = 0; unsigned k;
205  for (k = kh_begin(t); k != kh_end(t); ++k)
206  if (kh_exist(PN, t, k)) {
207  PN_TUPLE_AT(t2, i++) = kh_key(PN, t, k);
208  }
209  PN_TOUCH(t2);
210  return (PN)t2;
211 }
212 
218 static
220  vPN(Table) t = (vPN(Table))potion_fwd(self);
222  NEW_TUPLE(t2, kh_size(t));
223  int i = 0; unsigned k;
224  for (k = kh_begin(t); k != kh_end(t); ++k)
225  if (kh_exist(PN, t, k)) {
226  PN_TUPLE_AT(t2, i++) = kh_val(PN, t, k);
227  }
228  PN_TOUCH(t2);
229  return (PN)t2;
230 }
231 
232 // TUPLE - ordered lists, i.e. arrays in consecutive memory
233 // not autovivifying
234 
236  //NEW_TUPLE(t, 0);
237  NEW_TUPLE(t, 3); // prealloc 3 elems
238  t->len = 0;
239  return (PN)t;
240 }
241 
242 PN potion_tuple_with_size(Potion *P, unsigned long size) {
243  NEW_TUPLE(t, size);
244  return (PN)t;
245 }
246 
248  NEW_TUPLE(t, 3); // overallocate by 2 elems
249  t->len = 1;
250  t->set[0] = value;
251  return (PN)t;
252 }
253 
254 PN potion_tuple_push(Potion *P, PN tuple, PN value) {
255  vPN(Tuple) t = PN_GET_TUPLE(tuple);
256  DBG_CHECK_TUPLE(t);
257  if (t->len >= t->alloc) {
258  PN_REALLOC(t, PN_TTUPLE, struct PNTuple, sizeof(PN) * (t->alloc + 3)); // overalloc by 2
259  t->alloc += 3;
260  }
261  t->set[t->len] = value;
262  t->len++;
263  PN_TOUCH(tuple);
264  return tuple;
265 }
266 
271 PN potion_tuple_append(Potion *P, PN cl, PN self, PN value) {
272  DBG_CHECK_TUPLE(self);
273  return potion_tuple_push(P, self, value);
274 }
275 
280 PN_SIZE potion_tuple_find(Potion *P, PN tuple, PN value) {
281  DBG_CHECK_TUPLE(tuple);
282  PN_TUPLE_EACH(tuple, i, v, {
283  if (v == value) return i;
284  });
285  return PN_NONE;
286 }
287 
291  DBG_CHECK_TUPLE(tuple);
292  PN_SIZE idx = potion_tuple_find(P, tuple, value);
293  if (idx != PN_NONE) return idx;
294 
295  potion_tuple_push(P, tuple, value);
296  return PN_TUPLE_LEN(tuple) - 1;
297 }
298 
309 PN potion_tuple_at(Potion *P, PN cl, PN self, PN index) {
310  DBG_CHECK_TUPLE(self);
311  long i = PN_INT(index), len = PN_TUPLE_LEN(self);
312  if (i < 0) i += len;
313  if (i >= len) return PN_NIL;
314  return PN_TUPLE_AT(self, i);
315 }
316 
320 static
322  vPN(Tuple) t1 = PN_GET_TUPLE(self);
323  DBG_CHECK_TUPLE(t1);
324  NEW_TUPLE(t2, t1->len);
325  PN_MEMCPY_N(t2->set, t1->set, PN, t1->len);
326  t2->alloc = t1->len;
327  PN_TOUCH(t2);
328  return (PN)t2;
329 }
330 
346 static
347 PN potion_tuple_slice(Potion *P, PN cl, PN self, PN start, PN end) {
348  vPN(Tuple) t1 = PN_GET_TUPLE(self);
349  long i, l;
350  DBG_CHECK_TUPLE(t1);
351  if (!start)
352  return potion_tuple_clone(P, cl, self);
353  else {
354  DBG_CHECK_INT(start);
355  i = PN_INT(start);
356  if (i < 0) i = t1->len + i;
357  }
358  if (!end)
359  l = t1->len - i;
360  else {
361  long e = PN_INT(end);
362  DBG_CHECK_INT(end);
363  if (e < 0) e = t1->len + e;
364  l = e - i;
365  if (l < 0) { i = e; l = labs(l) + 1; }
366  else l++;
367  if (l > t1->len) l = t1->len; // permit overshoots
368  }
369  DBG_vt("; splice(i=%ld,len=%ld)\n", i, l);
370  if (!l || i >= t1->len) return PN_NIL;
371  NEW_TUPLE(t2, l);
372  PN_MEMCPY_N(&t2->set[0], &t1->set[i], PN, l);
373  t2->alloc = l;
374  PN_TOUCH(t2);
375  return (PN)t2;
376 }
377 
378 
383 PN potion_tuple_each(Potion *P, PN cl, PN self, PN block) {
384  DBG_CHECK_TUPLE(self);
385  int with_index = potion_sig_arity(P, PN_CLOSURE(block)->sig) >= 2;
386  PN_TUPLE_EACH(self, i, v, {
387  if (with_index)
388  PN_CLOSURE(block)->method(P, block, P->lobby, v, PN_NUM(i));
389  else
390  PN_CLOSURE(block)->method(P, block, P->lobby, v);
391  });
392  return self;
393 }
394 
399  DBG_CHECK_TUPLE(self);
400  if (PN_TUPLE_LEN(self) < 1) return PN_NIL;
401  return PN_TUPLE_AT(self, 0);
402 }
403 
408 PN potion_tuple_join(Potion *P, PN cl, PN self, PN sep) {
409  DBG_CHECK_TUPLE(self);
410  PN out = potion_byte_str(P, "");
411  PN_TUPLE_EACH(self, i, v, {
412  if (i > 0 && sep != PN_NIL) potion_bytes_obj_string(P, out, sep);
413  potion_bytes_obj_string(P, out, v);
414  });
415  return PN_STR_B(out);
416 }
417 
421 PN potion_tuple_last(Potion *P, PN cl, PN self) {
422  DBG_CHECK_TUPLE(self);
423  long len = PN_TUPLE_LEN(self);
424  if (len < 1) return PN_NIL;
425  return PN_TUPLE_AT(self, len - 1);
426 }
427 
432  DBG_CHECK_TUPLE(self);
433  int licks = 0;
434  PN out = potion_byte_str(P, "(");
435  PN_TUPLE_EACH(self, i, v, {
436  if (i > 0) pn_printf(P, out, ", ");
437  if (PN_TYPE(v) == PN_TLICK) licks++;
438  potion_bytes_obj_string(P, out, v);
439  });
440 
441  licks = (licks > 0 && licks == PN_TUPLE_LEN(self));
442  if (licks) PN_STR_PTR(out)[0] = '[';
443  pn_printf(P, out, licks ? "]" : ")");
444  return PN_STR_B(out);
445 }
446 
450 PN potion_tuple_pop(Potion *P, PN cl, PN self) {
451  vPN(Tuple) t = PN_GET_TUPLE(self);
452  DBG_CHECK_TUPLE(t);
453  PN obj = t->set[t->len - 1];
454  PN_REALLOC(t, PN_TTUPLE, struct PNTuple, sizeof(PN) * (t->len - 1));
455  t->len--;
456  PN_TOUCH(self);
457  return obj;
458 }
459 
466 PN potion_tuple_put(Potion *P, PN cl, PN self, PN key, PN value) {
467  if (PN_IS_INT(key)) {
468  DBG_CHECK_TUPLE(self);
469  long i = PN_INT(key), len = PN_TUPLE_LEN(self);
470  if (i < 0) i += len;
471  if (i < len) {
472  PN_TUPLE_AT(self, i) = value;
473  PN_TOUCH(self);
474  return self;
475  } else if (i == len)
476  return potion_tuple_push(P, self, value);
477  }
478 #ifdef P2
479  return potion_type_error(P, key);
480 #endif
481  return potion_table_put(P, PN_NIL, potion_table_cast(P, self), key, value);
482 }
483 
488 PN potion_tuple_unshift(Potion *P, PN cl, PN self, PN value) {
489  vPN(Tuple) t = PN_GET_TUPLE(self);
490  DBG_CHECK_TUPLE(t);
491  if (t->len >= t->alloc) {
492  PN_REALLOC(t, PN_TTUPLE, struct PNTuple, sizeof(PN) * (t->alloc + 3)); // overalloc by 2
493  t->alloc += 3;
494  }
495  PN_MEMMOVE_N(&t->set[1], &t->set[0], PN, t->len);
496  t->set[0] = value;
497  t->len++;
498  PN_TOUCH(self);
499  return self;
500 }
501 
507  vPN(Tuple) t = PN_GET_TUPLE(self);
508  DBG_CHECK_TUPLE(t);
509  PN obj = t->set[0];
510  PN_MEMMOVE_N(&t->set[0], &t->set[1], PN, t->len);
511  PN_REALLOC(t, PN_TTUPLE, struct PNTuple, sizeof(PN) * (t->len - 1));
512  t->len--;
513  PN_TOUCH(self);
514  return obj;
515 }
516 
521  DBG_CHECK_TUPLE(self);
522  PN_TUPLE_EACH(self, i, v, {
523  potion_send(v, PN_print);
524  });
525  return PN_STR0;
526 }
527 
533  return PN_NUM(PN_TUPLE_LEN(self));
534 }
535 
540  DBG_CHECK_TUPLE(self);
541  unsigned long len = PN_TUPLE_LEN(self);
542  PN tuple = potion_tuple_with_size(P, len);
543  len--;
544  PN_TUPLE_EACH(self, i, x, {
545  PN_TUPLE_AT(tuple, len - i) = x;
546  });
547  return tuple;
548 }
549 
550 #define GET(i) t->set[i]
551 #define SET(i,v) t->set[i] = v
552 //xor swap
553 #define SWAP(a,b) if (a != b) { \
554  t->set[a] ^= GET(b); \
555  t->set[b] ^= GET(a); \
556  t->set[a] ^= GET(b); }
557 
562 PN potion_tuple_remove(Potion *P, PN cl, PN self, PN index) {
563  struct PNTuple *t = PN_GET_TUPLE(self);
564  DBG_CHECK_TUPLE(t);
565  if (t->len) {
566  PN_SIZE i = PN_INT(index);
567  PN data = potion_tuple_clone(P, cl, self);
568  t = PN_GET_TUPLE(data);
569  if (i < t->len)
570  PN_MEMMOVE_N(&t->set[i], &t->set[i+1], PN, t->len - i);
571  t->len--;
572  //((struct PNFwd *)data)->ptr = (PN)t;
573  PN_TOUCH(data);
574  return data;
575  }
576  return self;
577 }
578 
583 PN potion_tuple_delete(Potion *P, PN cl, PN self, PN index) {
584  struct PNTuple *t = PN_GET_TUPLE(self);
585  DBG_CHECK_TUPLE(t);
586  if (t->len) {
587  PN_SIZE i = PN_INT(index);
588  if (i < t->len)
589  PN_MEMMOVE_N(&t->set[i], &t->set[i+1], PN, t->len - i);
590  t->len--;
591  PN_TOUCH(self);
592  }
593  return self;
594 }
595 
600  struct PNTuple *t = PN_GET_TUPLE(self);
601  DBG_CHECK_TUPLE(t);
602  PN_SIZE len = t->len;
603  if (len) {
604  PN_SIZE i;
605  for (i = 0; i < (PN_SIZE)(len/2); i++) {
606  SWAP(len-i-1, i);
607  }
608  PN_TOUCH(self);
609  }
610  return self;
611 }
612 
617 PN potion_tuple_bsearch(Potion *P, PN cl, PN self, PN x) {
618  struct PNTuple *t = PN_GET_TUPLE(self);
619  DBG_CHECK_TUPLE(t);
620  PNUniq xu = PN_UNIQ(x);
621  long i = 0, j = t->len - 1;
622  while (i <= j) {
623  long m = j + ((i - j) / 2);
624  PNUniq u = PN_UNIQ(t->set[m]);
625  if (u == xu)
626  return PN_NUM(m);
627  else if (u > xu)
628  j = m - 1;
629  else
630  i = m + 1;
631  }
632  return PN_NUM(-1);
633 }
634 
636 static
637 void potion_sort_internal(Potion *P, PN cl, PN self,
638  PN_SIZE from,
639  PN_SIZE to,
640  PN cmp)
641 {
642 #ifdef DEBUG
643  if (PN_TTUPLE != PN_TYPE(self)) potion_fatal("Invalid type");
644 #endif
645  if (from < to) {
646  struct PNTuple *t = PN_GET_TUPLE(self);
647  // which pivot? first is worst case if already sorted.
648  // random, last, middle or best: median-of-3.
649  PN_SIZE i, index = from + (to - from)/2;
650  PN pivot = GET(index);
651  SWAP(index, to);
652  index = from;
653  // partition the portion of the tuple between indexes from and to,
654  // inclusively, by moving all elements less than pivot before
655  // the pivot, and the equal or greater elements after it.
656  if (cmp == PN_NIL) { // default: sort by uniq, not value
657  for (i=from; i < to-1; i++) { // from ≤ i < to
658  if (PN_UNIQ(GET(i)) <= PN_UNIQ(pivot)) { SWAP(i, index); index++; }
659  }
660  } else if (cmp == PN_TRUE) { // sort by ascending number
661  for (i=from; i < to; i++) {
662  if (GET(i) <= pivot) {
663  SWAP(i, index); index++;
664  }
665  }
666  } else if (cmp == PN_FALSE) { // sort by descending number
667  for (i=from; i < to; i++) {
668  if (GET(i) > pivot) { SWAP(i, index); index++;
669  }
670  }
671  } else {
672  vPN(Closure) c = PN_CLOSURE(cmp);
673  for (i=from; i < to; i++) { // call cmp
674  if (PN_INT(c->method(P, cl, cmp, GET(i), pivot)) > 0)
675  { SWAP(i, index); index++; }
676  }
677  }
678  SWAP(index, to); // Move pivot element back to its final place
679 
680  if (index > 0)
681  potion_sort_internal(P,cl,self, from, index-1, cmp);
682  potion_sort_internal(P,cl,self, index+1, to, cmp);
683  PN_TOUCH(self);
684  }
685 }
686 
697 static PN potion_tuple_sort(Potion *P, PN cl,
700  PN self,
701  PN cmp)
702 {
703  PN data = potion_tuple_clone(P, cl, self);
704  PN_SIZE len = PN_TUPLE_LEN(self);
705  if (cmp != PN_NIL && !PN_IS_BOOL(cmp) && !PN_IS_CLOSURE(cmp))
706  potion_fatal("sort: invalid cmp type");
707  potion_sort_internal(P, cl, data, 0, len-1, cmp);
708  return data;
709 }
710 
719 PN potion_tuple_ins_sort(Potion *P, PN cl, PN self, PN cmp) {
720  struct PNTuple *t = PN_GET_TUPLE(self);
722  unsigned long i, j;
723  vPN(Closure) c;
724  if (t->len < MAX_INS_SORT) {
725  // simple insertion sort for smaller arrays (<13)
726  if (cmp == PN_NIL) { // default: sort by uniq, not value
727  for (i = 1; i < t->len; i++) {
728  j = i;
729  while (j > 0 && PN_UNIQ(GET(j-1)) > PN_UNIQ(GET(j))) {
730  SWAP(j, j-1);
731  j--;
732  }
733  }
734  }
735  else if (PN_IS_CLOSURE(cmp)) {
736  c = PN_CLOSURE(cmp);
737  for (i = 1; i < t->len; i++) {
738  j = i;
739  while (j > 0 && PN_INT(c->method(P, cl, cmp, GET(j-1), GET(j))) > 0) {
740  SWAP(j, j-1);
741  j--;
742  }
743  }
744  }
745  else if (cmp == PN_TRUE) {
746  for (i = 1; i < t->len; i++) {
747  j = i;
748  while (j > 0 && GET(j-1) > GET(j)) {
749  SWAP(j, j-1);
750  j--;
751  }
752  }
753  }
754  else if (cmp == PN_FALSE) {
755  for (i = 1; i < t->len; i++) {
756  j = i;
757  while (j > 0 && GET(j-1) < GET(j)) {
758  SWAP(j, j-1);
759  j--;
760  }
761  }
762  }
763  else {
764  potion_fatal("sort: invalid cmp type");
765  }
766  PN_TOUCH(self);
767  }
768  else {
769  if (cmp != PN_NIL && !PN_IS_BOOL(cmp) && !PN_IS_CLOSURE(cmp))
770  potion_fatal("sort: invalid cmp type");
771  potion_sort_internal(P, cl, self, 0, t->len-1, cmp);
772  }
773  return self;
774 }
775 
776 static
777 PN potion_tuple_cmp(Potion *P, PN cl, PN self, PN value) {
779  switch (potion_type(value)) {
780  case PN_TBOOLEAN: // false < () < true
781  return value == PN_FALSE ? -1 : 1;
782  case PN_TNIL:
783  return -1; //nil < () < (...)
784  case PN_TTUPLE: // recurse
785  if(PN_TUPLE_LEN(self) && PN_TUPLE_LEN(value)) {
786  PN cmp;
787  if ((cmp = potion_send(potion_tuple_first(P,cl,self), PN_cmp,
788  potion_tuple_first(P,cl,value)))
789  == PN_ZERO)
790  {
791  PN t1 = potion_tuple_clone(P,cl,self);
792  PN t2 = potion_tuple_clone(P,cl,value);
793  potion_tuple_pop(P,cl,t1);
794  potion_tuple_pop(P,cl,t2);
795  return potion_send(t1, PN_cmp, t2);
796  }
797  else {
798  return cmp;
799  }
800  }
801  else {
802  if (PN_TUPLE_LEN(value)) return -1;
803  else if (PN_TUPLE_LEN(self)) return 1;
804  else return 0;
805  }
806  default:
807  potion_fatal("Invalid tuple cmp type");
808  return 0;
809  }
810 }
811 
812 #undef SWAP
813 #undef GET
814 #undef SET
815 
820 PN potion_lobby_list(Potion *P, PN cl, PN self, PN size) {
821  return potion_tuple_with_size(P, PN_INT(size));
822 }
823 
825  PN tbl_vt = PN_VTABLE(PN_TTABLE);
826  PN tpl_vt = PN_VTABLE(PN_TTUPLE);
827  potion_type_call_is(tbl_vt, PN_FUNC(potion_table_at, "key=o"));
828  potion_type_callset_is(tbl_vt, PN_FUNC(potion_table_put, "key=o,value=o"));
829  potion_method(tbl_vt, "at", potion_table_at, "key=o");
830  potion_method(tbl_vt, "each", potion_table_each, "block=&");
831  potion_method(tbl_vt, "length", potion_table_length, 0);
832  potion_method(tbl_vt, "put", potion_table_put, "key=o,value=o");
833  potion_method(tbl_vt, "remove", potion_table_remove, "index=o");
834  potion_method(tbl_vt, "string", potion_table_string, 0);
835  potion_method(tbl_vt, "clone", potion_table_clone, 0);
836  potion_method(tbl_vt, "slice", potion_table_slice, "|keys=u");
837  potion_method(tbl_vt, "keys", potion_table_keys, 0);
838  potion_method(tbl_vt, "values", potion_table_values, 0);
839 
840  potion_type_call_is(tpl_vt, PN_FUNC(potion_tuple_at, "index=N"));
841  potion_type_callset_is(tpl_vt, PN_FUNC(potion_tuple_put, "index=N,value=o"));
842  potion_method(tpl_vt, "append", potion_tuple_append, "value=o");
843  potion_method(tpl_vt, "at", potion_tuple_at, "index=N");
844  potion_method(tpl_vt, "each", potion_tuple_each, "block=&");
845  potion_method(tpl_vt, "clone", potion_tuple_clone, 0);
846  potion_method(tpl_vt, "first", potion_tuple_first, 0);
847  potion_method(tpl_vt, "join", potion_tuple_join, "|sep=S");
848  potion_method(tpl_vt, "last", potion_tuple_last, 0);
849  potion_method(tpl_vt, "length", potion_tuple_length, 0);
850  potion_method(tpl_vt, "print", potion_tuple_print, 0);
851  potion_method(tpl_vt, "pop", potion_tuple_pop, 0);
852  potion_method(tpl_vt, "push", potion_tuple_append, "value=o");
853  potion_method(tpl_vt, "put", potion_tuple_put, "index=N,value=o");
854  potion_method(tpl_vt, "reverse", potion_tuple_reverse, 0);
855  potion_method(tpl_vt, "nreverse", potion_tuple_nreverse, 0);
856  potion_method(tpl_vt, "remove", potion_tuple_remove, "index=N");
857  potion_method(tpl_vt, "delete", potion_tuple_delete, "index=N");
858  potion_method(tpl_vt, "slice", potion_tuple_slice, "start:=0,end:=nil");
859  potion_method(tpl_vt, "unshift", potion_tuple_unshift, "value=o");
860  potion_method(tpl_vt, "shift", potion_tuple_shift, 0);
861  potion_method(tpl_vt, "bsearch", potion_tuple_bsearch, "value=o");
862  potion_method(tpl_vt, "sort", potion_tuple_sort, "|block=&");
863  potion_method(tpl_vt, "ins_sort", potion_tuple_ins_sort, "|block=&");
864  potion_method(tpl_vt, "cmp", potion_tuple_cmp, "value=o");
865  potion_method(tpl_vt, "string", potion_tuple_string, 0);
866  potion_method(P->lobby, "list", potion_lobby_list, "length=N");
867 }
#define PN_TUPLE_AT(t, n)
Definition: potion.h:278
PN potion_tuple_ins_sort(Potion *P, PN cl, PN self, PN cmp)
Definition: table.c:719
forwarding pointer (in case of reallocation)
Definition: potion.h:313
#define DBG_vt(...)
Definition: potion.h:264
PN potion_table_remove(Potion *P, PN cl, PN self, PN key)
Definition: table.c:113
#define GET(i)
Definition: table.c:550
#define DBG_CHECK_TYPE(obj, type)
Definition: potion.h:201
klib hash table library based on double hashing http://en.wikipedia.org/wiki/Double_hashing ...
#define NEW_TUPLE(t, size)
Definition: table.c:16
a tuple is an array of PNs.
Definition: potion.h:477
#define PN_ALLOC_N(V, T, C)
Definition: internal.h:13
#define PN_CLOSURE(x)
Definition: potion.h:225
#define PN_REALLOC(X, V, T, N)
Definition: internal.h:15
PN_SIZE void potion_bytes_obj_string(Potion *, PN, PN)
Definition: string.c:384
PN PN_cmp
Definition: internal.c:18
#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 potion_byte_str(Potion *, const char *)
Definition: string.c:331
#define PN_MEMMOVE_N(DST, SRC, T, N)
Definition: internal.h:23
PN potion_tuple_at(Potion *P, PN cl, PN self, PN index)
Definition: table.c:309
#define potion_method(RCV, MSG, FN, SIG)
Definition: potion.h:789
#define PN_TUPLE_LEN(t)
Definition: potion.h:277
PN_SIZE potion_tuple_push_unless(Potion *P, PN tuple, PN value)
Definition: table.c:290
static PN potion_table_values(Potion *P, PN cl, PN self)
Definition: table.c:219
#define PN_TNIL
Definition: potion.h:107
unsigned int PNUniq
Definition: potion.h:79
PN potion_tuple_append(Potion *P, PN cl, PN self, PN value)
Definition: table.c:271
static PN potion_fwd(PN)
the potion type is the 't' in the vtable tuple (m,t)
Definition: potion.h:570
static PN potion_tuple_slice(Potion *P, PN cl, PN self, PN start, PN end)
Definition: table.c:347
#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 kh_put(name, h, k, r)
Definition: khash.h:221
void potion_table_init(Potion *P)
Definition: table.c:824
#define PN_TTUPLE
Definition: potion.h:115
static void potion_sort_internal(Potion *P, PN cl, PN self, PN_SIZE from, PN_SIZE to, PN cmp)
space-efficient but destructive and not-stable qsort
Definition: table.c:637
#define PN_INT(x)
Definition: potion.h:214
#define PN_ZERO
Definition: potion.h:140
#define PN_NUM(i)
Definition: potion.h:213
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
static PN potion_table_keys(Potion *P, PN cl, PN self)
Definition: table.c:200
static PN potion_table_slice(Potion *P, PN cl, PN self, PN keys)
Definition: table.c:169
#define PN_STR_B(x)
Definition: potion.h:224
PN potion_tuple_join(Potion *P, PN cl, PN self, PN sep)
Definition: table.c:408
PN potion_tuple_shift(Potion *P, PN cl, PN self)
Definition: table.c:506
PN lobby
root namespace
Definition: potion.h:657
PN potion_table_empty(Potion *P)
Definition: table.c:42
#define kh_size(h)
Definition: khash.h:230
PN_SIZE len
Definition: potion.h:479
PN potion_tuple_last(Potion *P, PN cl, PN self)
Definition: table.c:421
void potion_type_callset_is(PN vt, PN cl)
set default writer
Definition: objmodel.c:240
#define PN_UNIQ(x)
Definition: potion.h:247
PN potion_table_cast(Potion *P, PN self)
Definition: table.c:47
#define PN_IS_CLOSURE(v)
Definition: potion.h:177
#define MAX_INS_SORT
Definition: table.h:14
#define kh_begin(h)
Definition: khash.h:228
PN potion_tuple_unshift(Potion *P, PN cl, PN self, PN value)
Definition: table.c:488
static PN potion_tuple_cmp(Potion *P, PN cl, PN self, PN value)
Definition: table.c:777
#define PN_IS_BOOL(v)
Definition: potion.h:170
PN potion_type_error(Potion *P, PN obj)
Definition: internal.c:273
PN potion_tuple_print(Potion *P, PN cl, PN self)
Definition: table.c:520
the table class, based on khash
Definition: table.h:40
#define PN_FALSE
Definition: potion.h:141
PN potion_tuple_each(Potion *P, PN cl, PN self, PN block)
Definition: table.c:383
#define PN_NONE
Definition: potion.h:145
#define DBG_CHECK_TUPLE(obj)
Definition: potion.h:205
#define PN_TBOOLEAN
Definition: potion.h:109
static PN potion_tuple_clone(Potion *P, PN cl, PN self)
Definition: table.c:321
PN potion_tuple_put(Potion *P, PN cl, PN self, PN key, PN value)
Definition: table.c:466
#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
PN potion_tuple_string(Potion *P, PN cl, PN self)
Definition: table.c:431
#define DBG_CHECK_INT(obj)
Definition: potion.h:203
#define PN_TRUE
Definition: potion.h:142
PN potion_tuple_with_size(Potion *P, unsigned long size)
Definition: table.c:242
PN potion_table_at(Potion *P, PN cl, PN self, PN key)
Definition: table.c:70
#define kh_del(name, h, k)
Definition: khash.h:223
non-API internal parts
PN potion_lobby_list(Potion *P, PN cl, PN self, PN size)
Definition: table.c:820
#define SWAP(a, b)
Definition: table.c:553
PN potion_tuple_reverse(Potion *P, PN cl, PN self)
Definition: table.c:539
PN potion_tuple_remove(Potion *P, PN cl, PN self, PN index)
Definition: table.c:562
PN_SIZE potion_type_size(Potion *P, const struct PNObject *ptr)
Definition: gc.c:306
PN potion_table_string(Potion *P, PN cl, PN self)
Definition: table.c:23
PN potion_tuple_empty(Potion *P)
Definition: table.c:235
#define PN_GET_TUPLE(t)
Definition: potion.h:276
#define kh_val(name, h, x)
Definition: khash.h:227
PN potion_tuple_length(Potion *P, PN cl, PN self)
Definition: table.c:531
PN potion_tuple_new(Potion *P, PN value)
Definition: table.c:247
the global interpreter state P. currently singleton (not threads yet)
Definition: potion.h:653
static PN potion_tuple_sort(Potion *P, PN cl, PN self, PN cmp)
TODO: bitonic __m128 sort (SSE accelerated) for typed tuples E.g.
Definition: table.c:699
PN_SIZE pn_printf(Potion *, PN, const char *,...) __attribute__((format(printf
#define PN_TYPE(x)
Definition: potion.h:133
#define kh_key(name, h, x)
Definition: khash.h:226
The p2 API.
PN PN_print
Definition: internal.c:14
#define PN_IS_INT(v)
Definition: potion.h:171
PN potion_table_each(Potion *P, PN cl, PN self, PN block)
Definition: table.c:82
static PNType potion_type(PN obj)
either immediate (NUM,BOOL,NIL) or a fwd
Definition: potion.h:532
#define PN_QUICK_FWD(t, obj)
PN_QUICK_FWD - doing a single fwd check after a possible realloc.
Definition: potion.h:558
the central table type, based on core/khash.h
static PN potion_table_clone(Potion *P, PN cl, PN self)
Definition: table.c:141
PN potion_table_length(Potion *P, PN cl, PN self)
Definition: table.c:134
#define potion_send(RCV, MSG, ARGS...)
method caches (more great stuff from ian piumarta)
Definition: potion.h:781
int potion_sig_arity(Potion *P, PN sig)
number of args of sig tuple, implements the potion_closure_arity method.
Definition: objmodel.c:87
PN_SIZE potion_tuple_find(Potion *P, PN tuple, PN value)
Return index of found value or PN_NONE.
Definition: table.c:280
PN potion_tuple_delete(Potion *P, PN cl, PN self, PN index)
Definition: table.c:583
#define PN_TTABLE
Definition: potion.h:124
PN potion_tuple_push(Potion *P, PN tuple, PN value)
Definition: table.c:254
#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
PN potion_tuple_pop(Potion *P, PN cl, PN self)
Definition: table.c:450
#define PN_IS_TUPLE(v)
Definition: potion.h:174
PN potion_table_set(Potion *P, PN self, PN key, PN value)
helper function for potion_table_put:"put", accepts tuple or table
Definition: table.c:126
#define PN_FUNC(f, s)
Definition: potion.h:228
#define POTION_FWD
Definition: potion.h:146
PN potion_tuple_first(Potion *P, PN cl, PN self)
Definition: table.c:398
#define kh_exist(name, h, x)
Definition: khash.h:225
PN potion_tuple_nreverse(Potion *P, PN cl, PN self)
Definition: table.c:599
#define PN_TUPLE_EACH(T, I, V, B)
Definition: potion.h:288
#define PN_TOUCH(x)
Definition: potion.h:231
PN set[]
Definition: potion.h:481
void potion_fatal(char *message)
Definition: internal.c:286
#define PN_STR_PTR(x)
Definition: potion.h:222
#define PN_VTABLE(t)
Definition: potion.h:136
#define kh_get(name, h, k)
Definition: khash.h:222