potion  0.2
 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 "potion.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  return potion_table_put(P, PN_NIL, potion_table_cast(P, self), key, value);
479 }
480 
485 PN potion_tuple_unshift(Potion *P, PN cl, PN self, PN value) {
486  vPN(Tuple) t = PN_GET_TUPLE(self);
487  DBG_CHECK_TUPLE(t);
488  if (t->len >= t->alloc) {
489  PN_REALLOC(t, PN_TTUPLE, struct PNTuple, sizeof(PN) * (t->alloc + 3)); // overalloc by 2
490  t->alloc += 3;
491  }
492  PN_MEMMOVE_N(&t->set[1], &t->set[0], PN, t->len);
493  t->set[0] = value;
494  t->len++;
495  PN_TOUCH(self);
496  return self;
497 }
498 
504  vPN(Tuple) t = PN_GET_TUPLE(self);
505  DBG_CHECK_TUPLE(t);
506  PN obj = t->set[0];
507  PN_MEMMOVE_N(&t->set[0], &t->set[1], PN, t->len);
508  PN_REALLOC(t, PN_TTUPLE, struct PNTuple, sizeof(PN) * (t->len - 1));
509  t->len--;
510  PN_TOUCH(self);
511  return obj;
512 }
513 
518  DBG_CHECK_TUPLE(self);
519  PN_TUPLE_EACH(self, i, v, {
520  potion_send(v, PN_print);
521  });
522  return PN_STR0;
523 }
524 
530  return PN_NUM(PN_TUPLE_LEN(self));
531 }
532 
537  DBG_CHECK_TUPLE(self);
538  unsigned long len = PN_TUPLE_LEN(self);
539  PN tuple = potion_tuple_with_size(P, len);
540  len--;
541  PN_TUPLE_EACH(self, i, x, {
542  PN_TUPLE_AT(tuple, len - i) = x;
543  });
544  return tuple;
545 }
546 
547 #define GET(i) t->set[i]
548 #define SET(i,v) t->set[i] = v
549 //xor swap
550 #define SWAP(a,b) if (a != b) { \
551  t->set[a] ^= GET(b); \
552  t->set[b] ^= GET(a); \
553  t->set[a] ^= GET(b); }
554 
559 PN potion_tuple_remove(Potion *P, PN cl, PN self, PN index) {
560  struct PNTuple *t = PN_GET_TUPLE(self);
561  DBG_CHECK_TUPLE(t);
562  if (t->len) {
563  PN_SIZE i = PN_INT(index);
564  PN data = potion_tuple_clone(P, cl, self);
565  t = PN_GET_TUPLE(data);
566  if (i < t->len)
567  PN_MEMMOVE_N(&t->set[i], &t->set[i+1], PN, t->len - i);
568  t->len--;
569  //((struct PNFwd *)data)->ptr = (PN)t;
570  PN_TOUCH(data);
571  return data;
572  }
573  return self;
574 }
575 
580 PN potion_tuple_delete(Potion *P, PN cl, PN self, PN index) {
581  struct PNTuple *t = PN_GET_TUPLE(self);
582  DBG_CHECK_TUPLE(t);
583  if (t->len) {
584  PN_SIZE i = PN_INT(index);
585  if (i < t->len)
586  PN_MEMMOVE_N(&t->set[i], &t->set[i+1], PN, t->len - i);
587  t->len--;
588  PN_TOUCH(self);
589  }
590  return self;
591 }
592 
597  struct PNTuple *t = PN_GET_TUPLE(self);
598  DBG_CHECK_TUPLE(t);
599  PN_SIZE len = t->len;
600  if (len) {
601  PN_SIZE i;
602  for (i = 0; i < (PN_SIZE)(len/2); i++) {
603  SWAP(len-i-1, i);
604  }
605  PN_TOUCH(self);
606  }
607  return self;
608 }
609 
614 PN potion_tuple_bsearch(Potion *P, PN cl, PN self, PN x) {
615  struct PNTuple *t = PN_GET_TUPLE(self);
616  DBG_CHECK_TUPLE(t);
617  PNUniq xu = PN_UNIQ(x);
618  long i = 0, j = t->len - 1;
619  while (i <= j) {
620  long m = j + ((i - j) / 2);
621  PNUniq u = PN_UNIQ(t->set[m]);
622  if (u == xu)
623  return PN_NUM(m);
624  else if (u > xu)
625  j = m - 1;
626  else
627  i = m + 1;
628  }
629  return PN_NUM(-1);
630 }
631 
633 static
634 void potion_sort_internal(Potion *P, PN cl, PN self,
635  PN_SIZE from,
636  PN_SIZE to,
637  PN cmp)
638 {
639 #ifdef DEBUG
640  if (PN_TTUPLE != PN_TYPE(self)) potion_fatal("Invalid type");
641 #endif
642  if (from < to) {
643  struct PNTuple *t = PN_GET_TUPLE(self);
644  // which pivot? first is worst case if already sorted.
645  // random, last, middle or best: median-of-3.
646  PN_SIZE i, index = from + (to - from)/2;
647  PN pivot = GET(index);
648  SWAP(index, to);
649  index = from;
650  // partition the portion of the tuple between indexes from and to,
651  // inclusively, by moving all elements less than pivot before
652  // the pivot, and the equal or greater elements after it.
653  if (cmp == PN_NIL) { // default: sort by uniq, not value
654  for (i=from; i < to-1; i++) { // from ≤ i < to
655  if (PN_UNIQ(GET(i)) <= PN_UNIQ(pivot)) { SWAP(i, index); index++; }
656  }
657  } else if (cmp == PN_TRUE) { // sort by ascending number
658  for (i=from; i < to; i++) {
659  if (GET(i) <= pivot) {
660  SWAP(i, index); index++;
661  }
662  }
663  } else if (cmp == PN_FALSE) { // sort by descending number
664  for (i=from; i < to; i++) {
665  if (GET(i) > pivot) { SWAP(i, index); index++;
666  }
667  }
668  } else {
669  vPN(Closure) c = PN_CLOSURE(cmp);
670  for (i=from; i < to; i++) { // call cmp
671  if (PN_INT(c->method(P, cl, cmp, GET(i), pivot)) > 0)
672  { SWAP(i, index); index++; }
673  }
674  }
675  SWAP(index, to); // Move pivot element back to its final place
676 
677  if (index > 0)
678  potion_sort_internal(P,cl,self, from, index-1, cmp);
679  potion_sort_internal(P,cl,self, index+1, to, cmp);
680  PN_TOUCH(self);
681  }
682 }
683 
694 static PN potion_tuple_sort(Potion *P, PN cl,
697  PN self,
698  PN cmp)
699 {
700  PN data = potion_tuple_clone(P, cl, self);
701  PN_SIZE len = PN_TUPLE_LEN(self);
702  if (cmp != PN_NIL && !PN_IS_BOOL(cmp) && !PN_IS_CLOSURE(cmp))
703  potion_fatal("sort: invalid cmp type");
704  potion_sort_internal(P, cl, data, 0, len-1, cmp);
705  return data;
706 }
707 
716 PN potion_tuple_ins_sort(Potion *P, PN cl, PN self, PN cmp) {
717  struct PNTuple *t = PN_GET_TUPLE(self);
719  unsigned long i, j;
720  vPN(Closure) c;
721  if (t->len < MAX_INS_SORT) {
722  // simple insertion sort for smaller arrays (<13)
723  if (cmp == PN_NIL) { // default: sort by uniq, not value
724  for (i = 1; i < t->len; i++) {
725  j = i;
726  while (j > 0 && PN_UNIQ(GET(j-1)) > PN_UNIQ(GET(j))) {
727  SWAP(j, j-1);
728  j--;
729  }
730  }
731  }
732  else if (PN_IS_CLOSURE(cmp)) {
733  c = PN_CLOSURE(cmp);
734  for (i = 1; i < t->len; i++) {
735  j = i;
736  while (j > 0 && PN_INT(c->method(P, cl, cmp, GET(j-1), GET(j))) > 0) {
737  SWAP(j, j-1);
738  j--;
739  }
740  }
741  }
742  else if (cmp == PN_TRUE) {
743  for (i = 1; i < t->len; i++) {
744  j = i;
745  while (j > 0 && GET(j-1) > GET(j)) {
746  SWAP(j, j-1);
747  j--;
748  }
749  }
750  }
751  else if (cmp == PN_FALSE) {
752  for (i = 1; i < t->len; i++) {
753  j = i;
754  while (j > 0 && GET(j-1) < GET(j)) {
755  SWAP(j, j-1);
756  j--;
757  }
758  }
759  }
760  else {
761  potion_fatal("sort: invalid cmp type");
762  }
763  PN_TOUCH(self);
764  }
765  else {
766  if (cmp != PN_NIL && !PN_IS_BOOL(cmp) && !PN_IS_CLOSURE(cmp))
767  potion_fatal("sort: invalid cmp type");
768  potion_sort_internal(P, cl, self, 0, t->len-1, cmp);
769  }
770  return self;
771 }
772 
773 static
774 PN potion_tuple_cmp(Potion *P, PN cl, PN self, PN value) {
776  switch (potion_type(value)) {
777  case PN_TBOOLEAN: // false < () < true
778  return value == PN_FALSE ? -1 : 1;
779  case PN_TNIL:
780  return -1; //nil < () < (...)
781  case PN_TTUPLE: // recurse
782  if(PN_TUPLE_LEN(self) && PN_TUPLE_LEN(value)) {
783  PN cmp;
784  if ((cmp = potion_send(potion_tuple_first(P,cl,self), PN_cmp,
785  potion_tuple_first(P,cl,value)))
786  == PN_ZERO)
787  {
788  PN t1 = potion_tuple_clone(P,cl,self);
789  PN t2 = potion_tuple_clone(P,cl,value);
790  potion_tuple_pop(P,cl,t1);
791  potion_tuple_pop(P,cl,t2);
792  return potion_send(t1, PN_cmp, t2);
793  }
794  else {
795  return cmp;
796  }
797  }
798  else {
799  if (PN_TUPLE_LEN(value)) return -1;
800  else if (PN_TUPLE_LEN(self)) return 1;
801  else return 0;
802  }
803  default:
804  potion_fatal("Invalid tuple cmp type");
805  return 0;
806  }
807 }
808 
809 #undef SWAP
810 #undef GET
811 #undef SET
812 
817 PN potion_lobby_list(Potion *P, PN cl, PN self, PN size) {
818  return potion_tuple_with_size(P, PN_INT(size));
819 }
820 
822  PN tbl_vt = PN_VTABLE(PN_TTABLE);
823  PN tpl_vt = PN_VTABLE(PN_TTUPLE);
824  potion_type_call_is(tbl_vt, PN_FUNC(potion_table_at, "key=o"));
825  potion_type_callset_is(tbl_vt, PN_FUNC(potion_table_put, "key=o,value=o"));
826  potion_method(tbl_vt, "at", potion_table_at, "key=o");
827  potion_method(tbl_vt, "each", potion_table_each, "block=&");
828  potion_method(tbl_vt, "length", potion_table_length, 0);
829  potion_method(tbl_vt, "put", potion_table_put, "key=o,value=o");
830  potion_method(tbl_vt, "remove", potion_table_remove, "index=o");
831  potion_method(tbl_vt, "string", potion_table_string, 0);
832  potion_method(tbl_vt, "clone", potion_table_clone, 0);
833  potion_method(tbl_vt, "slice", potion_table_slice, "|keys=u");
834  potion_method(tbl_vt, "keys", potion_table_keys, 0);
835  potion_method(tbl_vt, "values", potion_table_values, 0);
836 
837  potion_type_call_is(tpl_vt, PN_FUNC(potion_tuple_at, "index=N"));
838  potion_type_callset_is(tpl_vt, PN_FUNC(potion_tuple_put, "index=N,value=o"));
839  potion_method(tpl_vt, "append", potion_tuple_append, "value=o");
840  potion_method(tpl_vt, "at", potion_tuple_at, "index=N");
841  potion_method(tpl_vt, "each", potion_tuple_each, "block=&");
842  potion_method(tpl_vt, "clone", potion_tuple_clone, 0);
843  potion_method(tpl_vt, "first", potion_tuple_first, 0);
844  potion_method(tpl_vt, "join", potion_tuple_join, "|sep=S");
845  potion_method(tpl_vt, "last", potion_tuple_last, 0);
846  potion_method(tpl_vt, "length", potion_tuple_length, 0);
847  potion_method(tpl_vt, "print", potion_tuple_print, 0);
848  potion_method(tpl_vt, "pop", potion_tuple_pop, 0);
849  potion_method(tpl_vt, "push", potion_tuple_append, "value=o");
850  potion_method(tpl_vt, "put", potion_tuple_put, "index=N,value=o");
851  potion_method(tpl_vt, "reverse", potion_tuple_reverse, 0);
852  potion_method(tpl_vt, "nreverse", potion_tuple_nreverse, 0);
853  potion_method(tpl_vt, "remove", potion_tuple_remove, "index=N");
854  potion_method(tpl_vt, "delete", potion_tuple_delete, "index=N");
855  potion_method(tpl_vt, "slice", potion_tuple_slice, "start:=0,end:=nil");
856  potion_method(tpl_vt, "unshift", potion_tuple_unshift, "value=o");
857  potion_method(tpl_vt, "shift", potion_tuple_shift, 0);
858  potion_method(tpl_vt, "bsearch", potion_tuple_bsearch, "value=o");
859  potion_method(tpl_vt, "sort", potion_tuple_sort, "|block=&");
860  potion_method(tpl_vt, "ins_sort", potion_tuple_ins_sort, "|block=&");
861  potion_method(tpl_vt, "cmp", potion_tuple_cmp, "value=o");
862  potion_method(tpl_vt, "string", potion_tuple_string, 0);
863  potion_method(P->lobby, "list", potion_lobby_list, "length=N");
864 }
#define PN_TUPLE_AT(t, n)
Definition: potion.h:269
PN potion_tuple_ins_sort(Potion *P, PN cl, PN self, PN cmp)
Definition: table.c:716
forwarding pointer (in case of reallocation)
Definition: potion.h:304
#define DBG_vt(...)
Definition: potion.h:246
PN potion_table_remove(Potion *P, PN cl, PN self, PN key)
Definition: table.c:113
#define GET(i)
Definition: table.c:547
#define DBG_CHECK_TYPE(obj, type)
Definition: potion.h:186
#define vPN(t)
Definition: potion.h:132
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:468
#define PN_ALLOC_N(V, T, C)
Definition: internal.h:13
#define PN_CLOSURE(x)
Definition: potion.h:216
#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:780
#define PN_TUPLE_LEN(t)
Definition: potion.h:268
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:561
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:225
#define kh_put(name, h, k, r)
Definition: khash.h:221
void potion_table_init(Potion *P)
Definition: table.c:821
#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:634
#define PN_INT(x)
Definition: potion.h:205
#define PN_ZERO
Definition: potion.h:140
#define PN_NUM(i)
Definition: potion.h:204
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
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:215
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:503
PN lobby
root namespace
Definition: potion.h:648
PN potion_table_empty(Potion *P)
Definition: table.c:42
#define kh_size(h)
Definition: khash.h:230
PN_SIZE len
Definition: potion.h:470
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:235
#define PN_UNIQ(x)
Definition: potion.h:238
PN potion_table_cast(Potion *P, PN self)
Definition: table.c:47
#define PN_IS_CLOSURE(v)
Definition: potion.h:168
#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:485
static PN potion_tuple_cmp(Potion *P, PN cl, PN self, PN value)
Definition: table.c:774
#define PN_IS_BOOL(v)
Definition: potion.h:161
PN potion_tuple_print(Potion *P, PN cl, PN self)
Definition: table.c:517
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:190
#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:614
PN potion_tuple_string(Potion *P, PN cl, PN self)
Definition: table.c:431
#define DBG_CHECK_INT(obj)
Definition: potion.h:188
#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:817
#define SWAP(a, b)
Definition: table.c:550
PN potion_tuple_reverse(Potion *P, PN cl, PN self)
Definition: table.c:536
PN potion_tuple_remove(Potion *P, PN cl, PN self, PN index)
Definition: table.c:559
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:267
#define kh_val(name, h, x)
Definition: khash.h:227
PN potion_tuple_length(Potion *P, PN cl, PN self)
Definition: table.c:528
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:644
The potion API.
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:696
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
PN PN_print
Definition: internal.c:14
#define PN_IS_INT(v)
Definition: potion.h:162
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:523
#define PN_QUICK_FWD(t, obj)
PN_QUICK_FWD - doing a single fwd check after a possible realloc.
Definition: potion.h:549
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:772
int potion_sig_arity(Potion *P, PN sig)
number of args of sig tuple, implements the potion_closure_arity method.
Definition: objmodel.c:82
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:580
#define PN_TTABLE
Definition: potion.h:124
PN potion_tuple_push(Potion *P, PN tuple, PN value)
Definition: table.c:254
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:165
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:219
#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:596
#define PN_TUPLE_EACH(T, I, V, B)
Definition: potion.h:279
#define PN_TOUCH(x)
Definition: potion.h:222
PN set[]
Definition: potion.h:472
void potion_fatal(char *message)
Definition: internal.c:282
#define PN_STR_PTR(x)
Definition: potion.h:213
#define PN_VTABLE(t)
Definition: potion.h:136
#define kh_get(name, h, k)
Definition: khash.h:222