Unified · Split
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | #include <libc.h> |
| 3 | 3 | #include <bio.h> |
| 4 | 4 | #include "aa.h" |
| 5 | +#include "qp.h" | |
| 5 | 6 | |
| 6 | 7 | #define CAR(x) ( (x)->car.o ) |
| 7 | 8 | #define CDR(x) ( (x)->cdr.o ) |
| @@ -257,7 +258,7 @@ aa_mark(aaContext *ctx, aaObject *obj) · 249 unmodified lines | ||
| 257 | 258 | aaObject *car; |
| 258 | 259 | |
| 259 | 260 | begin: |
| 260 | − if((TAG(obj) & GCMARKBIT) != 0 || ISNULL(obj)) | |
| 261 | + if(ISNULL(obj) || (TAG(obj) & GCMARKBIT) != 0) | |
| 261 | 262 | return; |
| 262 | 263 | car = CAR(obj); /* store car before modifying it with GCMARKBIT */ |
| 263 | 264 | TAG(obj) |= GCMARKBIT; |
| @@ -290,6 +291,7 @@ collectgarbage(aaContext *ctx) · 26 unmodified lines | ||
| 290 | 291 | /* mark */ |
| 291 | 292 | for(i = 0; i < ctx->gcstack_idx; i++) |
| 292 | 293 | aa_mark(ctx, ctx->gcstack[i]); |
| 294 | + | |
| 293 | 295 | aa_mark(ctx, ctx->symlist); |
| 294 | 296 | |
| 295 | 297 | /* sweep and unmark */ |
| @@ -442,13 +444,12 @@ aaObject * · 146 unmodified lines | ||
| 442 | 444 | aa_symbol_find(aaContext *ctx, const char *name) |
| 443 | 445 | { |
| 444 | 446 | aaObject *obj; |
| 447 | + char *pk; | |
| 445 | 448 | |
| 446 | − for(obj = ctx->symlist; !ISNULL(obj); obj = CDR(obj)){ | |
| 447 | − if(streq(CAR(CDR(CAR(obj))), name)) | |
| 448 | − return CAR(obj); | |
| 449 | − } | |
| 449 | + obj = nil; | |
| 450 | + qpget(ctx->symtrie, name, 0, &pk, &obj); | |
| 450 | 451 | |
| 451 | − return nil; | |
| 452 | + return obj; | |
| 452 | 453 | } |
| 453 | 454 | |
| 454 | 455 | aaObject * |
| @@ -465,6 +466,7 @@ aa_symbol(aaContext *ctx, const char *name) · 10 unmodified lines | ||
| 465 | 466 | SETTYPE(obj, AA_TSYMBOL); |
| 466 | 467 | CDR(obj) = aa_cons(ctx, aa_string(ctx, name), nil); /* nil not &Null, because it's unbound */ |
| 467 | 468 | ctx->symlist = aa_cons(ctx, obj, ctx->symlist); |
| 469 | + ctx->symtrie = qpset(ctx->symtrie, strdup(name), 0, obj); | |
| 468 | 470 | |
| 469 | 471 | return obj; |
| 470 | 472 | } |
| @@ -1,5 +1,8 @@ | ||
| 1 | 1 | #define GCSTACKSIZE 256 |
| 2 | 2 | |
| 3 | +typedef union Trie Trie; | |
| 4 | +#pragma incomplete Trie | |
| 5 | + | |
| 3 | 6 | typedef struct aaContext aaContext; |
| 4 | 7 | typedef struct aaHandlers aaHandlers; |
| 5 | 8 | typedef struct aaNumber aaNumber; |
| @@ -13,8 +16,10 @@ typedef char (*aaReadFn)(aaContext *ctx, void *udata); · 7 unmodified lines | ||
| 13 | 16 | |
| 14 | 17 | struct aaNumber { |
| 15 | 18 | double r; |
| 16 | − double i; | |
| 19 | + //double i; | |
| 17 | 20 | }; |
| 21 | +//#define aNumber(r,i) (aaNumber){r, i} | |
| 22 | +#define aNumber(r,i) (aaNumber){r} | |
| 18 | 23 | |
| 19 | 24 | union aaValue { |
| 20 | 25 | Biobuf *port; |
| @@ -44,6 +49,7 @@ struct aaContext { · 23 unmodified lines | ||
| 44 | 49 | aaObject *calllist; |
| 45 | 50 | aaObject *freelist; |
| 46 | 51 | aaObject *symlist; |
| 52 | + Trie *symtrie; | |
| 47 | 53 | aaObject *t; |
| 48 | 54 | Rune nextrune; |
| 49 | 55 | |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | cf_##func(aaContext *ctx, aaObject *arg) \ |
| 10 | 10 | { \ |
| 11 | 11 | aaNumber x = aa_tonumber(ctx, aa_nextarg(ctx, &arg, 0)); \ |
| 12 | − return aa_number(ctx, (aaNumber){func(x.r), 0.0}); \ | |
| 12 | + return aa_number(ctx, aNumber(func(x.r), 0.0)); \ | |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | 15 | #define CFUNC2(func) \ |
| @@ -18,7 +18,7 @@ · 2 unmodified lines | ||
| 18 | 18 | { \ |
| 19 | 19 | aaNumber x = aa_tonumber(ctx, aa_nextarg(ctx, &arg, 0)); \ |
| 20 | 20 | aaNumber y = aa_tonumber(ctx, aa_nextarg(ctx, &arg, 0)); \ |
| 21 | − return aa_number(ctx, (aaNumber){func(x.r, y.r), 0.0}); \ | |
| 21 | + return aa_number(ctx, aNumber(func(x.r, y.r), 0.0)); \ | |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | 24 | #define FUNCS \ |
| @@ -46,8 +46,8 @@ cf_atan2(aaContext *ctx, aaObject *arg) · 21 unmodified lines | ||
| 46 | 46 | { |
| 47 | 47 | aaNumber x = aa_tonumber(ctx, aa_nextarg(ctx, &arg, 0)); |
| 48 | 48 | aaObject *yo = aa_nextarg(ctx, &arg, 1); |
| 49 | − aaNumber y = yo != nil ? aa_tonumber(ctx, yo) : (aaNumber){1.0, 0.0}; | |
| 50 | − return aa_number(ctx, (aaNumber){atan2(x.r, y.r), 0.0}); | |
| 49 | + aaNumber y = yo != nil ? aa_tonumber(ctx, yo) : aNumber(1.0, 0.0); | |
| 50 | + return aa_number(ctx, aNumber(atan2(x.r, y.r), 0.0)); | |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | 53 | static aaObject * |
| @@ -6,10 +6,13 @@ CFLAGS=$CFLAGS -p · 5 unmodified lines | ||
| 6 | 6 | |
| 7 | 7 | HFILES=\ |
| 8 | 8 | aa.h\ |
| 9 | + aa_math.h\ | |
| 10 | + qp.h\ | |
| 9 | 11 | |
| 10 | 12 | OFILES=\ |
| 11 | 13 | aa.$O\ |
| 12 | 14 | aa_math.$O\ |
| 15 | + qp.$O\ | |
| 13 | 16 | repl.$O\ |
| 14 | 17 | |
| 15 | 18 | default:V: all |
| @@ -0,0 +1,180 @@ | ||
| 1 | +#include <u.h> | |
| 2 | +#include <libc.h> | |
| 3 | +#include "qp.h" | |
| 4 | + | |
| 5 | +typedef u16int Tbitmap; | |
| 6 | +typedef struct Tbranch Tbranch; | |
| 7 | +typedef struct Tleaf Tleaf; | |
| 8 | + | |
| 9 | +struct Tleaf { | |
| 10 | + char *k; | |
| 11 | + void *v; | |
| 12 | +}; | |
| 13 | + | |
| 14 | +struct Tbranch { | |
| 15 | + Trie *twigs; | |
| 16 | + u64int x; | |
| 17 | +}; | |
| 18 | + | |
| 19 | +union Trie { | |
| 20 | + Tleaf leaf; | |
| 21 | + Tbranch branch; | |
| 22 | +}; | |
| 23 | + | |
| 24 | +#define x_flags(x) ((x)>>62) | |
| 25 | +#define x_index(x) ((x)>>16 & ((1ULL<<46)-1ULL)) | |
| 26 | +#define x_bitmap(x) ((x) & 0xffff) | |
| 27 | + | |
| 28 | +#define isbranch(t) (x_flags((t)->branch.x) != 0) | |
| 29 | +#define hastwig(t, b) (x_bitmap((t)->branch.x) & (b)) | |
| 30 | +#define twigoff(t, b) popcount(x_bitmap((t)->branch.x) & ((b)-1)) | |
| 31 | +#define twig(t, i) (&(t)->branch.twigs[(i)]) | |
| 32 | +#define twigoffmax(off, max, t, b) do{ off = twigoff(t, b); max = popcount(x_bitmap((t)->branch.x)); }while(0) | |
| 33 | +#define nibbit(k, f) (1 << (((k) & (((f)-2) ^ 0x0f) & 0xff) >> ((2-(f))<<2))) | |
| 34 | +#define twigbit(t, k, len) \ | |
| 35 | + (x_index((t)->branch.x) >= (len) ? \ | |
| 36 | + 1 : \ | |
| 37 | + nibbit((u8int)(k)[x_index((t)->branch.x)], x_flags((t)->branch.x))) | |
| 38 | + | |
| 39 | +/* | |
| 40 | +// need some speed? just say no. | |
| 41 | +#define POPCNT BYTE $0xf3; BYTE $0x0f; BYTE $0xb8 | |
| 42 | + | |
| 43 | +TEXT popcount(SB),$0 | |
| 44 | + MOVL b+0(FP), AX | |
| 45 | + POPCNT | |
| 46 | + RET | |
| 47 | +*/ | |
| 48 | +static u16int | |
| 49 | +popcount(u16int b) | |
| 50 | +{ | |
| 51 | + b -= b>>1 & 0x5555; | |
| 52 | + b = (b & 0x3333) + ((b>>2) & 0x3333); | |
| 53 | + b = (b + (b>>4)) & 0x0f0f; | |
| 54 | + b = (b + (b>>8)) & 0x00ff; | |
| 55 | + return b; | |
| 56 | +} | |
| 57 | + | |
| 58 | +int | |
| 59 | +qpget(Trie *t, char *k, int len, char **pk, void **pv) | |
| 60 | +{ | |
| 61 | + Tbitmap b; | |
| 62 | + | |
| 63 | + assert(k != nil && pk != nil && pv != nil); | |
| 64 | + | |
| 65 | + if(len < 1) | |
| 66 | + len = strlen(k); | |
| 67 | + if(t == nil) | |
| 68 | + return -1; | |
| 69 | + for(; isbranch(t); t = twig(t, twigoff(t, b))){ | |
| 70 | + b = twigbit(t, k, len); | |
| 71 | + if(!hastwig(t, b)) | |
| 72 | + return -1; | |
| 73 | + } | |
| 74 | + if(strncmp(k, t->leaf.k, len) != 0) | |
| 75 | + return -1; | |
| 76 | + *pk = t->leaf.k; | |
| 77 | + *pv = t->leaf.v; | |
| 78 | + | |
| 79 | + return 0; | |
| 80 | +} | |
| 81 | + | |
| 82 | +int | |
| 83 | +qpnext(Trie *t, char **pk, int *plen, void **pv) | |
| 84 | +{ | |
| 85 | + Tbitmap b; | |
| 86 | + uint s, m; | |
| 87 | + | |
| 88 | + assert(pk != nil && plen != nil && pv != nil); | |
| 89 | + | |
| 90 | + if(isbranch(t)){ | |
| 91 | + b = twigbit(t, *pk, *plen); | |
| 92 | + twigoffmax(s, m, t, b); | |
| 93 | + for(; s < m; s++){ | |
| 94 | + if(qpnext(twig(t, s), pk, plen, pv) == 0) | |
| 95 | + return 0; | |
| 96 | + } | |
| 97 | + return -1; | |
| 98 | + } | |
| 99 | + | |
| 100 | + if(*pk == nil){ | |
| 101 | + *pk = t->leaf.k; | |
| 102 | + *plen = strlen(*pk); | |
| 103 | + *pv = t->leaf.v; | |
| 104 | + return 0; | |
| 105 | + } | |
| 106 | + | |
| 107 | + return -1; | |
| 108 | +} | |
| 109 | + | |
| 110 | +Trie * | |
| 111 | +qpset(Trie *t, char *k, int len, void *v) | |
| 112 | +{ | |
| 113 | + Trie *t0, t1, t2; | |
| 114 | + uint i, s, m; | |
| 115 | + u8int f; | |
| 116 | + Tbitmap b, b1, b2; | |
| 117 | + u8int k2; | |
| 118 | + | |
| 119 | + assert(k != nil && v != nil); | |
| 120 | + if(len < 1) | |
| 121 | + len = strlen(k); | |
| 122 | + assert(len > 0); | |
| 123 | + | |
| 124 | + if(t == nil){ | |
| 125 | + t = malloc(sizeof(*t)); | |
| 126 | + assert(t != nil); | |
| 127 | + t->leaf.k = k; | |
| 128 | + t->leaf.v = v; | |
| 129 | + return t; | |
| 130 | + } | |
| 131 | + | |
| 132 | + t0 = t; | |
| 133 | + for(; isbranch(t); t = twig(t, i)){ | |
| 134 | + b = twigbit(t, k, len); | |
| 135 | + i = hastwig(t, b) ? twigoff(t, b) : 0; | |
| 136 | + } | |
| 137 | + for(i = 0; i <= len && k[i] == t->leaf.k[i]; i++); | |
| 138 | + if(i == len+1){ | |
| 139 | + t->leaf.v = v; | |
| 140 | + return t0; | |
| 141 | + } | |
| 142 | + | |
| 143 | + k2 = (u8int)t->leaf.k[i]; | |
| 144 | + f = (((u8int)k[i] ^ k2) & 0xf0) ? 1 : 2; | |
| 145 | + b1 = nibbit(k[i], f); | |
| 146 | + t1.leaf.k = k; | |
| 147 | + t1.leaf.v = v; | |
| 148 | + for(t = t0; isbranch(t); t = twig(t, twigoff(t, b))){ | |
| 149 | + if(i == x_index(t->branch.x)){ | |
| 150 | + if(f == x_flags(t->branch.x)) | |
| 151 | + goto growbranch; | |
| 152 | + if(f < x_flags(t->branch.x)) | |
| 153 | + break; | |
| 154 | + }else if(i < x_index(t->branch.x)){ | |
| 155 | + break; | |
| 156 | + } | |
| 157 | + b = twigbit(t, k, len); | |
| 158 | + assert(hastwig(t, b)); | |
| 159 | + } | |
| 160 | + | |
| 161 | + t2 = *t; | |
| 162 | + b2 = nibbit(k2, f); | |
| 163 | + t->branch.twigs = malloc(sizeof(*t)*2); | |
| 164 | + assert(t->branch.twigs != nil); | |
| 165 | + t->branch.x = (uvlong)f<<62 | (uvlong)i<<16 | b1 | b2; | |
| 166 | + *twig(t, twigoff(t, b1)) = t1; | |
| 167 | + *twig(t, twigoff(t, b2)) = t2; | |
| 168 | + | |
| 169 | + return t0; | |
| 170 | + | |
| 171 | +growbranch: | |
| 172 | + assert(!hastwig(t, b1)); | |
| 173 | + twigoffmax(s, m, t, b1); | |
| 174 | + t->branch.twigs = realloc(t->branch.twigs, sizeof(*t)*(m+1)); | |
| 175 | + memmove(t->branch.twigs+s+1, t->branch.twigs+s, sizeof(*t)*(m-s)); | |
| 176 | + memmove(t->branch.twigs+s, &t1, sizeof(t1)); | |
| 177 | + t->branch.x |= b1; | |
| 178 | + | |
| 179 | + return t0; | |
| 180 | +} | |
| @@ -0,0 +1,6 @@ | ||
| 1 | +typedef union Trie Trie; | |
| 2 | +#pragma incomplete Trie | |
| 3 | + | |
| 4 | +int qpget(Trie *t, char *k, int len, char **pk, void **pv); | |
| 5 | +int qpnext(Trie *t, char **pk, int *plen, void **pv); | |
| 6 | +Trie *qpset(Trie *t, char *k, int len, void *v); | |