Unified · Split
| @@ -2,6 +2,7 @@ · 1 unmodified line | |||
| 2 | #include <libc.h> | 2 | #include <libc.h> |
| 3 | #include <bio.h> | 3 | #include <bio.h> |
| 4 | #include "aa.h" | 4 | #include "aa.h" |
| 5 | #include "qp.h" | ||
| 5 | 6 | ||
| 6 | #define CAR(x) ( (x)->car.o ) | 7 | #define CAR(x) ( (x)->car.o ) |
| 7 | #define CDR(x) ( (x)->cdr.o ) | 8 | #define CDR(x) ( (x)->cdr.o ) |
| @@ -257,7 +258,7 @@ aa_mark(aaContext *ctx, aaObject *obj) · 249 unmodified lines | |||
| 257 | aaObject *car; | 258 | aaObject *car; |
| 258 | 259 | ||
| 259 | begin: | 260 | begin: |
| 260 | if((TAG(obj) & GCMARKBIT) != 0 || ISNULL(obj)) | 261 | if(ISNULL(obj) || (TAG(obj) & GCMARKBIT) != 0) |
| 261 | return; | 262 | return; |
| 262 | car = CAR(obj); /* store car before modifying it with GCMARKBIT */ | 263 | car = CAR(obj); /* store car before modifying it with GCMARKBIT */ |
| 263 | TAG(obj) |= GCMARKBIT; | 264 | TAG(obj) |= GCMARKBIT; |
| @@ -290,6 +291,7 @@ collectgarbage(aaContext *ctx) · 26 unmodified lines | |||
| 290 | /* mark */ | 291 | /* mark */ |
| 291 | for(i = 0; i < ctx->gcstack_idx; i++) | 292 | for(i = 0; i < ctx->gcstack_idx; i++) |
| 292 | aa_mark(ctx, ctx->gcstack[i]); | 293 | aa_mark(ctx, ctx->gcstack[i]); |
| 294 | |||
| 293 | aa_mark(ctx, ctx->symlist); | 295 | aa_mark(ctx, ctx->symlist); |
| 294 | 296 | ||
| 295 | /* sweep and unmark */ | 297 | /* sweep and unmark */ |
| @@ -442,13 +444,12 @@ aaObject * · 146 unmodified lines | |||
| 442 | aa_symbol_find(aaContext *ctx, const char *name) | 444 | aa_symbol_find(aaContext *ctx, const char *name) |
| 443 | { | 445 | { |
| 444 | aaObject *obj; | 446 | aaObject *obj; |
| 447 | char *pk; | ||
| 445 | 448 | ||
| 446 | for(obj = ctx->symlist; !ISNULL(obj); obj = CDR(obj)){ | 449 | obj = nil; |
| 447 | if(streq(CAR(CDR(CAR(obj))), name)) | 450 | qpget(ctx->symtrie, name, 0, &pk, &obj); |
| 448 | return CAR(obj); | ||
| 449 | } | ||
| 450 | 451 | ||
| 451 | return nil; | 452 | return obj; |
| 452 | } | 453 | } |
| 453 | 454 | ||
| 454 | aaObject * | 455 | aaObject * |
| @@ -465,6 +466,7 @@ aa_symbol(aaContext *ctx, const char *name) · 10 unmodified lines | |||
| 465 | SETTYPE(obj, AA_TSYMBOL); | 466 | SETTYPE(obj, AA_TSYMBOL); |
| 466 | CDR(obj) = aa_cons(ctx, aa_string(ctx, name), nil); /* nil not &Null, because it's unbound */ | 467 | CDR(obj) = aa_cons(ctx, aa_string(ctx, name), nil); /* nil not &Null, because it's unbound */ |
| 467 | ctx->symlist = aa_cons(ctx, obj, ctx->symlist); | 468 | ctx->symlist = aa_cons(ctx, obj, ctx->symlist); |
| 469 | ctx->symtrie = qpset(ctx->symtrie, strdup(name), 0, obj); | ||
| 468 | 470 | ||
| 469 | return obj; | 471 | return obj; |
| 470 | } | 472 | } |
| @@ -1,5 +1,8 @@ | |||
| 1 | #define GCSTACKSIZE 256 | 1 | #define GCSTACKSIZE 256 |
| 2 | 2 | ||
| 3 | typedef union Trie Trie; | ||
| 4 | #pragma incomplete Trie | ||
| 5 | |||
| 3 | typedef struct aaContext aaContext; | 6 | typedef struct aaContext aaContext; |
| 4 | typedef struct aaHandlers aaHandlers; | 7 | typedef struct aaHandlers aaHandlers; |
| 5 | typedef struct aaNumber aaNumber; | 8 | typedef struct aaNumber aaNumber; |
| @@ -13,8 +16,10 @@ typedef char (*aaReadFn)(aaContext *ctx, void *udata); · 7 unmodified lines | |||
| 13 | 16 | ||
| 14 | struct aaNumber { | 17 | struct aaNumber { |
| 15 | double r; | 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 | union aaValue { | 24 | union aaValue { |
| 20 | Biobuf *port; | 25 | Biobuf *port; |
| @@ -44,6 +49,7 @@ struct aaContext { · 23 unmodified lines | |||
| 44 | aaObject *calllist; | 49 | aaObject *calllist; |
| 45 | aaObject *freelist; | 50 | aaObject *freelist; |
| 46 | aaObject *symlist; | 51 | aaObject *symlist; |
| 52 | Trie *symtrie; | ||
| 47 | aaObject *t; | 53 | aaObject *t; |
| 48 | Rune nextrune; | 54 | Rune nextrune; |
| 49 | 55 | ||
| @@ -9,7 +9,7 @@ · 8 unmodified lines | |||
| 9 | cf_##func(aaContext *ctx, aaObject *arg) \ | 9 | cf_##func(aaContext *ctx, aaObject *arg) \ |
| 10 | { \ | 10 | { \ |
| 11 | aaNumber x = aa_tonumber(ctx, aa_nextarg(ctx, &arg, 0)); \ | 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 | #define CFUNC2(func) \ | 15 | #define CFUNC2(func) \ |
| @@ -18,7 +18,7 @@ · 2 unmodified lines | |||
| 18 | { \ | 18 | { \ |
| 19 | aaNumber x = aa_tonumber(ctx, aa_nextarg(ctx, &arg, 0)); \ | 19 | aaNumber x = aa_tonumber(ctx, aa_nextarg(ctx, &arg, 0)); \ |
| 20 | aaNumber y = aa_tonumber(ctx, aa_nextarg(ctx, &arg, 0)); \ | 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 | #define FUNCS \ | 24 | #define FUNCS \ |
| @@ -46,8 +46,8 @@ cf_atan2(aaContext *ctx, aaObject *arg) · 21 unmodified lines | |||
| 46 | { | 46 | { |
| 47 | aaNumber x = aa_tonumber(ctx, aa_nextarg(ctx, &arg, 0)); | 47 | aaNumber x = aa_tonumber(ctx, aa_nextarg(ctx, &arg, 0)); |
| 48 | aaObject *yo = aa_nextarg(ctx, &arg, 1); | 48 | aaObject *yo = aa_nextarg(ctx, &arg, 1); |
| 49 | aaNumber y = yo != nil ? aa_tonumber(ctx, yo) : (aaNumber){1.0, 0.0}; | 49 | aaNumber y = yo != nil ? aa_tonumber(ctx, yo) : aNumber(1.0, 0.0); |
| 50 | return aa_number(ctx, (aaNumber){atan2(x.r, y.r), 0.0}); | 50 | return aa_number(ctx, aNumber(atan2(x.r, y.r), 0.0)); |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | static aaObject * | 53 | static aaObject * |
| @@ -6,10 +6,13 @@ CFLAGS=$CFLAGS -p · 5 unmodified lines | |||
| 6 | 6 | ||
| 7 | HFILES=\ | 7 | HFILES=\ |
| 8 | aa.h\ | 8 | aa.h\ |
| 9 | aa_math.h\ | ||
| 10 | qp.h\ | ||
| 9 | 11 | ||
| 10 | OFILES=\ | 12 | OFILES=\ |
| 11 | aa.$O\ | 13 | aa.$O\ |
| 12 | aa_math.$O\ | 14 | aa_math.$O\ |
| 15 | qp.$O\ | ||
| 13 | repl.$O\ | 16 | repl.$O\ |
| 14 | 17 | ||
| 15 | default:V: all | 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); | ||