diff --git a/deprecated/stb.h b/deprecated/stb.h index 03aec96..cd715e7 100644 --- a/deprecated/stb.h +++ b/deprecated/stb.h @@ -13058,1356 +13058,6 @@ char * stb__string_constant(char *file, int line, char *x) #endif // STB_DEFINE #endif // !STB_DEBUG && !STB_ALWAYS_H - -#ifdef STB_STUA -#error "STUA is no longer supported" -////////////////////////////////////////////////////////////////////////// -// -// stua: little scripting language -// -// define STB_STUA to compile it -// -// see http://nothings.org/stb/stb_stua.html for documentation -// -// basic parsing model: -// -// lexical analysis -// use stb_lex() to parse tokens; keywords get their own tokens -// -// parsing: -// recursive descent parser. too much of a hassle to make an unambiguous -// LR(1) grammar, and one-pass generation is clumsier (recursive descent -// makes it easier to e.g. compile nested functions). on the other hand, -// dictionary syntax required hackery to get extra lookahead. -// -// codegen: -// output into an evaluation tree, using array indices as 'pointers' -// -// run: -// traverse the tree; support for 'break/continue/return' is tricky -// -// garbage collection: -// stu__mark and sweep; explicit stack with non-stu__compile_global_scope roots - -typedef stb_int32 stua_obj; - -typedef stb_idict stua_dict; - -STB_EXTERN void stua_run_script(char *s); -STB_EXTERN void stua_uninit(void); - -extern stua_obj stua_globals; - -STB_EXTERN double stua_number(stua_obj z); - -STB_EXTERN stua_obj stua_getnil(void); -STB_EXTERN stua_obj stua_getfalse(void); -STB_EXTERN stua_obj stua_gettrue(void); -STB_EXTERN stua_obj stua_string(char *z); -STB_EXTERN stua_obj stua_make_number(double d); -STB_EXTERN stua_obj stua_box(int type, void *data, int size); - -enum -{ - STUA_op_negate=129, - STUA_op_shl, STUA_op_ge, - STUA_op_shr, STUA_op_le, - STUA_op_shru, - STUA_op_last -}; - -#define STUA_NO_VALUE 2 // equivalent to a tagged NULL -STB_EXTERN stua_obj (*stua_overload)(int op, stua_obj a, stua_obj b, stua_obj c); - -STB_EXTERN stua_obj stua_error(char *err, ...); - -STB_EXTERN stua_obj stua_pushroot(stua_obj o); -STB_EXTERN void stua_poproot ( void ); - - -#ifdef STB_DEFINE -// INTERPRETER - -// 31-bit floating point implementation -// force the (1 << 30) bit (2nd highest bit) to be zero by re-biasing the exponent; -// then shift and set the bottom bit - -static stua_obj stu__floatp(float *f) -{ - unsigned int n = *(unsigned int *) f; - unsigned int e = n & (0xff << 23); - - assert(sizeof(int) == 4 && sizeof(float) == 4); - - if (!e) // zero? - n = n; // no change - else if (e < (64 << 23)) // underflow of the packed encoding? - n = (n & 0x80000000); // signed 0 - else if (e > (190 << 23)) // overflow of the encoding? (or INF or NAN) - n = (n & 0x80000000) + (127 << 23); // new INF encoding - else - n -= 0x20000000; - - // now we need to shuffle the bits so that the spare bit is at the bottom - assert((n & 0x40000000) == 0); - return (n & 0x80000000) + (n << 1) + 1; -} - -static unsigned char stu__getfloat_addend[256]; -static float stu__getfloat(stua_obj v) -{ - unsigned int n; - unsigned int e = ((unsigned int) v) >> 24; - - n = (int) v >> 1; // preserve high bit - n += stu__getfloat_addend[e] << 24; - return *(float *) &n; -} - -stua_obj stua_float(float f) -{ - return stu__floatp(&f); -} - -static void stu__float_init(void) -{ - int i; - stu__getfloat_addend[0] = 0; // do nothing to biased exponent of 0 - for (i=1; i < 127; ++i) - stu__getfloat_addend[i] = 32; // undo the -0x20000000 - stu__getfloat_addend[127] = 64; // convert packed INF to INF (0x3f -> 0x7f) - - for (i=0; i < 128; ++i) // for signed floats, remove the bit we just shifted down - stu__getfloat_addend[128+i] = stu__getfloat_addend[i] - 64; -} - -// Tagged data type implementation - - // TAGS: -#define stu__int_tag 0 // of 2 bits // 00 int -#define stu__float_tag 1 // of 1 bit // 01 float -#define stu__ptr_tag 2 // of 2 bits // 10 boxed - // 11 float - -#define stu__tag(x) ((x) & 3) -#define stu__number(x) (stu__tag(x) != stu__ptr_tag) -#define stu__isint(x) (stu__tag(x) == stu__int_tag) - -#define stu__int(x) ((x) >> 2) -#define stu__float(x) (stu__getfloat(x)) - -#define stu__makeint(v) ((v)*4+stu__int_tag) - -// boxed data, and tag support for boxed data - -enum -{ - STU___float = 1, STU___int = 2, - STU___number = 3, STU___string = 4, - STU___function = 5, STU___dict = 6, - STU___boolean = 7, STU___error = 8, -}; - -// boxed data -#define STU__BOX short type, stua_gc -typedef struct stu__box { STU__BOX; } stu__box; - -stu__box stu__nil = { 0, 1 }; -stu__box stu__true = { STU___boolean, 1, }; -stu__box stu__false = { STU___boolean, 1, }; - -#define stu__makeptr(v) ((stua_obj) (v) + stu__ptr_tag) - -#define stua_nil stu__makeptr(&stu__nil) -#define stua_true stu__makeptr(&stu__true) -#define stua_false stu__makeptr(&stu__false) - -stua_obj stua_getnil(void) { return stua_nil; } -stua_obj stua_getfalse(void) { return stua_false; } -stua_obj stua_gettrue(void) { return stua_true; } - -#define stu__ptr(x) ((stu__box *) ((x) - stu__ptr_tag)) - -#define stu__checkt(t,x) ((t) == STU___float ? ((x) & 1) == stu__float_tag : \ - (t) == STU___int ? stu__isint(x) : \ - (t) == STU___number ? stu__number(x) : \ - stu__tag(x) == stu__ptr_tag && stu__ptr(x)->type == (t)) - -typedef struct -{ - STU__BOX; - void *ptr; -} stu__wrapper; - -// implementation of a 'function' or function + closure - -typedef struct stu__func -{ - STU__BOX; - stua_obj closure_source; // 0 - regular function; 4 - C function - // if closure, pointer to source function - union { - stua_obj closure_data; // partial-application data - void *store; // pointer to free that holds 'code' - stua_obj (*func)(stua_dict *context); - } f; - // closure ends here - short *code; - int num_param; - stua_obj *param; // list of parameter strings -} stu__func; - -// apply this to 'short *code' to get at data -#define stu__const(f) ((stua_obj *) (f)) - -static void stu__free_func(stu__func *f) -{ - if (f->closure_source == 0) free(f->f.store); - if ((stb_uint) f->closure_source <= 4) free(f->param); - free(f); -} - -#define stu__pd(x) ((stua_dict *) stu__ptr(x)) -#define stu__pw(x) ((stu__wrapper *) stu__ptr(x)) -#define stu__pf(x) ((stu__func *) stu__ptr(x)) - - -// garbage-collection - - -static stu__box ** stu__gc_ptrlist; -static stua_obj * stu__gc_root_stack; - -stua_obj stua_pushroot(stua_obj o) { stb_arr_push(stu__gc_root_stack, o); return o; } -void stua_poproot ( void ) { stb_arr_pop(stu__gc_root_stack); } - -static stb_sdict *stu__strings; -static void stu__mark(stua_obj z) -{ - int i; - stu__box *p = stu__ptr(z); - if (p->stua_gc == 1) return; // already marked - assert(p->stua_gc == 0); - p->stua_gc = 1; - switch(p->type) { - case STU___function: { - stu__func *f = (stu__func *) p; - if ((stb_uint) f->closure_source <= 4) { - if (f->closure_source == 0) { - for (i=1; i <= f->code[0]; ++i) - if (!stu__number(((stua_obj *) f->code)[-i])) - stu__mark(((stua_obj *) f->code)[-i]); - } - for (i=0; i < f->num_param; ++i) - stu__mark(f->param[i]); - } else { - stu__mark(f->closure_source); - stu__mark(f->f.closure_data); - } - break; - } - case STU___dict: { - stua_dict *e = (stua_dict *) p; - for (i=0; i < e->limit; ++i) - if (e->table[i].k != STB_IEMPTY && e->table[i].k != STB_IDEL) { - if (!stu__number(e->table[i].k)) stu__mark((int) e->table[i].k); - if (!stu__number(e->table[i].v)) stu__mark((int) e->table[i].v); - } - break; - } - } -} - -static int stu__num_allocs, stu__size_allocs; -static stua_obj stu__flow_val = stua_nil; // used for break & return - -static void stua_gc(int force) -{ - int i; - if (!force && stu__num_allocs == 0 && stu__size_allocs == 0) return; - stu__num_allocs = stu__size_allocs = 0; - //printf("[gc]\n"); - - // clear marks - for (i=0; i < stb_arr_len(stu__gc_ptrlist); ++i) - stu__gc_ptrlist[i]->stua_gc = 0; - - // stu__mark everything reachable - stu__nil.stua_gc = stu__true.stua_gc = stu__false.stua_gc = 1; - stu__mark(stua_globals); - if (!stu__number(stu__flow_val)) - stu__mark(stu__flow_val); - for (i=0; i < stb_arr_len(stu__gc_root_stack); ++i) - if (!stu__number(stu__gc_root_stack[i])) - stu__mark(stu__gc_root_stack[i]); - - // sweep unreachables - for (i=0; i < stb_arr_len(stu__gc_ptrlist);) { - stu__box *z = stu__gc_ptrlist[i]; - if (!z->stua_gc) { - switch (z->type) { - case STU___dict: stb_idict_destroy((stua_dict *) z); break; - case STU___error: free(((stu__wrapper *) z)->ptr); break; - case STU___string: stb_sdict_remove(stu__strings, (char*) ((stu__wrapper *) z)->ptr, NULL); free(z); break; - case STU___function: stu__free_func((stu__func *) z); break; - } - // swap in the last item over this, and repeat - z = stb_arr_pop(stu__gc_ptrlist); - stu__gc_ptrlist[i] = z; - } else - ++i; - } -} - -static void stu__consider_gc(stua_obj x) -{ - if (stu__size_allocs < 100000) return; - if (stu__num_allocs < 10 && stu__size_allocs < 1000000) return; - stb_arr_push(stu__gc_root_stack, x); - stua_gc(0); - stb_arr_pop(stu__gc_root_stack); -} - -static stua_obj stu__makeobj(int type, void *data, int size, int safe_to_gc) -{ - stua_obj x = stu__makeptr(data); - ((stu__box *) data)->type = type; - stb_arr_push(stu__gc_ptrlist, (stu__box *) data); - stu__num_allocs += 1; - stu__size_allocs += size; - if (safe_to_gc) stu__consider_gc(x); - return x; -} - -stua_obj stua_box(int type, void *data, int size) -{ - stu__wrapper *p = (stu__wrapper *) malloc(sizeof(*p)); - p->ptr = data; - return stu__makeobj(type, p, size, 0); -} - -// a stu string can be directly compared for equality, because -// they go into a hash table -stua_obj stua_string(char *z) -{ - stu__wrapper *b = (stu__wrapper *) stb_sdict_get(stu__strings, z); - if (b == NULL) { - int o = stua_box(STU___string, NULL, strlen(z) + sizeof(*b)); - b = stu__pw(o); - stb_sdict_add(stu__strings, z, b); - stb_sdict_getkey(stu__strings, z, (char **) &b->ptr); - } - return stu__makeptr(b); -} - -// stb_obj dictionary is just an stb_idict -static void stu__set(stua_dict *d, stua_obj k, stua_obj v) -{ if (stb_idict_set(d, k, v)) stu__size_allocs += 8; } - -static stua_obj stu__get(stua_dict *d, stua_obj k, stua_obj res) -{ - stb_idict_get_flag(d, k, &res); - return res; -} - -static stua_obj make_string(char *z, int len) -{ - stua_obj s; - char temp[256], *q = (char *) stb_temp(temp, len+1), *p = q; - while (len > 0) { - if (*z == '\\') { - if (z[1] == 'n') *p = '\n'; - else if (z[1] == 'r') *p = '\r'; - else if (z[1] == 't') *p = '\t'; - else *p = z[1]; - p += 1; z += 2; len -= 2; - } else { - *p++ = *z++; len -= 1; - } - } - *p = 0; - s = stua_string(q); - stb_tempfree(temp, q); - return s; -} - -enum token_names -{ - T__none=128, - ST_shl = STUA_op_shl, ST_ge = STUA_op_ge, - ST_shr = STUA_op_shr, ST_le = STUA_op_le, - ST_shru = STUA_op_shru, STU__negate = STUA_op_negate, - ST__reset_numbering = STUA_op_last, - ST_white, - ST_id, ST_float, ST_decimal, ST_hex, ST_char,ST_string, ST_number, - // make sure the keywords come _AFTER_ ST_id, so stb_lex prefer them - ST_if, ST_while, ST_for, ST_eq, ST_nil, - ST_then, ST_do, ST_in, ST_ne, ST_true, - ST_else, ST_break, ST_let, ST_and, ST_false, - ST_elseif, ST_continue, ST_into, ST_or, ST_repeat, - ST_end, ST_as, ST_return, ST_var, ST_func, - ST_catch, ST__frame, - ST__max_terminals, - - STU__defaultparm, STU__seq, -}; - -static stua_dict * stu__globaldict; - stua_obj stua_globals; - -static enum -{ - FLOW_normal, FLOW_continue, FLOW_break, FLOW_return, FLOW_error, -} stu__flow; - -stua_obj stua_error(char *z, ...) -{ - stua_obj a; - char temp[4096], *x; - va_list v; va_start(v,z); vsprintf(temp, z, v); va_end(v); - x = stb_p_strdup(temp); - a = stua_box(STU___error, x, strlen(x)); - stu__flow = FLOW_error; - stu__flow_val = a; - return stua_nil; -} - -double stua_number(stua_obj z) -{ - return stu__tag(z) == stu__int_tag ? stu__int(z) : stu__float(z); -} - -stua_obj stua_make_number(double d) -{ - double e = floor(d); - if (e == d && e < (1 << 29) && e >= -(1 << 29)) - return stu__makeint((int) e); - else - return stua_float((float) d); -} - -stua_obj (*stua_overload)(int op, stua_obj a, stua_obj b, stua_obj c) = NULL; - -static stua_obj stu__op(int op, stua_obj a, stua_obj b, stua_obj c) -{ - stua_obj r = STUA_NO_VALUE; - if (op == '+') { - if (stu__checkt(STU___string, a) && stu__checkt(STU___string, b)) { - ;// @TODO: string concatenation - } else if (stu__checkt(STU___function, a) && stu__checkt(STU___dict, b)) { - stu__func *f = (stu__func *) malloc(12); - assert(offsetof(stu__func, code)==12); - f->closure_source = a; - f->f.closure_data = b; - return stu__makeobj(STU___function, f, 16, 1); - } - } - if (stua_overload) r = stua_overload(op,a,b,c); - if (stu__flow != FLOW_error && r == STUA_NO_VALUE) - stua_error("Typecheck for operator %d", op), r=stua_nil; - return r; -} - -#define STU__EVAL2(a,b) \ - a = stu__eval(stu__f[n+1]); if (stu__flow) break; stua_pushroot(a); \ - b = stu__eval(stu__f[n+2]); stua_poproot(); if (stu__flow) break; - -#define STU__FB(op) \ - STU__EVAL2(a,b) \ - if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) \ - return ((a) op (b)); \ - if (stu__number(a) && stu__number(b)) \ - return stua_make_number(stua_number(a) op stua_number(b)); \ - return stu__op(stu__f[n], a,b, stua_nil) - -#define STU__F(op) \ - STU__EVAL2(a,b) \ - if (stu__number(a) && stu__number(b)) \ - return stua_make_number(stua_number(a) op stua_number(b)); \ - return stu__op(stu__f[n], a,b, stua_nil) - -#define STU__I(op) \ - STU__EVAL2(a,b) \ - if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) \ - return stu__makeint(stu__int(a) op stu__int(b)); \ - return stu__op(stu__f[n], a,b, stua_nil) - -#define STU__C(op) \ - STU__EVAL2(a,b) \ - if (stu__number(a) && stu__number(b)) \ - return (stua_number(a) op stua_number(b)) ? stua_true : stua_false; \ - return stu__op(stu__f[n], a,b, stua_nil) - -#define STU__CE(op) \ - STU__EVAL2(a,b) \ - return (a op b) ? stua_true : stua_false - -static short *stu__f; -static stua_obj stu__f_obj; -static stua_dict *stu__c; -static stua_obj stu__funceval(stua_obj fo, stua_obj co); - -static int stu__cond(stua_obj x) -{ - if (stu__flow) return 0; - if (!stu__checkt(STU___boolean, x)) - x = stu__op('!', x, stua_nil, stua_nil); - if (x == stua_true ) return 1; - if (x == stua_false) return 0; - stu__flow = FLOW_error; - return 0; -} - -// had to manually eliminate tailcall recursion for debugging complex stuff -#define TAILCALL(x) n = (x); goto top; -static stua_obj stu__eval(int n) -{ -top: - if (stu__flow >= FLOW_return) return stua_nil; // is this needed? - if (n < 0) return stu__const(stu__f)[n]; - assert(n != 0 && n != 1); - switch (stu__f[n]) { - stua_obj a,b,c; - case ST_catch: a = stu__eval(stu__f[n+1]); - if (stu__flow == FLOW_error) { a=stu__flow_val; stu__flow = FLOW_normal; } - return a; - case ST_var: b = stu__eval(stu__f[n+2]); if (stu__flow) break; - stu__set(stu__c, stu__const(stu__f)[stu__f[n+1]], b); - return b; - case STU__seq: stu__eval(stu__f[n+1]); if (stu__flow) break; - TAILCALL(stu__f[n+2]); - case ST_if: if (!stu__cond(stu__eval(stu__f[n+1]))) return stua_nil; - TAILCALL(stu__f[n+2]); - case ST_else: a = stu__cond(stu__eval(stu__f[n+1])); - TAILCALL(stu__f[n + 2 + !a]); - #define STU__HANDLE_BREAK \ - if (stu__flow >= FLOW_break) { \ - if (stu__flow == FLOW_break) { \ - a = stu__flow_val; \ - stu__flow = FLOW_normal; \ - stu__flow_val = stua_nil; \ - return a; \ - } \ - return stua_nil; \ - } - case ST_as: stu__eval(stu__f[n+3]); - STU__HANDLE_BREAK - // fallthrough! - case ST_while: a = stua_nil; stua_pushroot(a); - while (stu__cond(stu__eval(stu__f[n+1]))) { - stua_poproot(); - a = stu__eval(stu__f[n+2]); - STU__HANDLE_BREAK - stu__flow = FLOW_normal; // clear 'continue' flag - stua_pushroot(a); - if (stu__f[n+3]) stu__eval(stu__f[n+3]); - STU__HANDLE_BREAK - stu__flow = FLOW_normal; // clear 'continue' flag - } - stua_poproot(); - return a; - case ST_break: stu__flow = FLOW_break; stu__flow_val = stu__eval(stu__f[n+1]); break; - case ST_continue:stu__flow = FLOW_continue; break; - case ST_return: stu__flow = FLOW_return; stu__flow_val = stu__eval(stu__f[n+1]); break; - case ST__frame: return stu__f_obj; - case '[': STU__EVAL2(a,b); - if (stu__checkt(STU___dict, a)) - return stu__get(stu__pd(a), b, stua_nil); - return stu__op(stu__f[n], a, b, stua_nil); - case '=': a = stu__eval(stu__f[n+2]); if (stu__flow) break; - n = stu__f[n+1]; - if (stu__f[n] == ST_id) { - if (!stb_idict_update(stu__c, stu__const(stu__f)[stu__f[n+1]], a)) - if (!stb_idict_update(stu__globaldict, stu__const(stu__f)[stu__f[n+1]], a)) - return stua_error("Assignment to undefined variable"); - } else if (stu__f[n] == '[') { - stua_pushroot(a); - b = stu__eval(stu__f[n+1]); if (stu__flow) { stua_poproot(); break; } - stua_pushroot(b); - c = stu__eval(stu__f[n+2]); stua_poproot(); stua_poproot(); - if (stu__flow) break; - if (!stu__checkt(STU___dict, b)) return stua_nil; - stu__set(stu__pd(b), c, a); - } else { - return stu__op(stu__f[n], stu__eval(n), a, stua_nil); - } - return a; - case STU__defaultparm: - a = stu__eval(stu__f[n+2]); - stu__flow = FLOW_normal; - if (stb_idict_add(stu__c, stu__const(stu__f)[stu__f[n+1]], a)) - stu__size_allocs += 8; - return stua_nil; - case ST_id: a = stu__get(stu__c, stu__const(stu__f)[stu__f[n+1]], STUA_NO_VALUE); // try local variable - return a != STUA_NO_VALUE // else try stu__compile_global_scope variable - ? a : stu__get(stu__globaldict, stu__const(stu__f)[stu__f[n+1]], stua_nil); - case STU__negate:a = stu__eval(stu__f[n+1]); if (stu__flow) break; - return stu__isint(a) ? -a : stu__op(stu__f[n], a, stua_nil, stua_nil); - case '~': a = stu__eval(stu__f[n+1]); if (stu__flow) break; - return stu__isint(a) ? (~a)&~3 : stu__op(stu__f[n], a, stua_nil, stua_nil); - case '!': a = stu__eval(stu__f[n+1]); if (stu__flow) break; - a = stu__cond(a); if (stu__flow) break; - return a ? stua_true : stua_false; - case ST_eq: STU__CE(==); case ST_le: STU__C(<=); case '<': STU__C(<); - case ST_ne: STU__CE(!=); case ST_ge: STU__C(>=); case '>': STU__C(>); - case '+' : STU__FB(+); case '*': STU__F(*); case '&': STU__I(&); case ST_shl: STU__I(<<); - case '-' : STU__FB(-); case '/': STU__F(/); case '|': STU__I(|); case ST_shr: STU__I(>>); - case '%': STU__I(%); case '^': STU__I(^); - case ST_shru: STU__EVAL2(a,b); - if (stu__tag(a) == stu__int_tag && stu__tag(b) == stu__int_tag) - return stu__makeint((unsigned) stu__int(a) >> stu__int(b)); - return stu__op(stu__f[n], a,b, stua_nil); - case ST_and: a = stu__eval(stu__f[n+1]); b = stu__cond(a); if (stu__flow) break; - return a ? stu__eval(stu__f[n+2]) : a; - case ST_or : a = stu__eval(stu__f[n+1]); b = stu__cond(a); if (stu__flow) break; - return a ? b : stu__eval(stu__f[n+2]); - case'(':case':': STU__EVAL2(a,b); - if (!stu__checkt(STU___function, a)) - return stu__op(stu__f[n], a,b, stua_nil); - if (!stu__checkt(STU___dict, b)) - return stua_nil; - if (stu__f[n] == ':') - b = stu__makeobj(STU___dict, stb_idict_copy(stu__pd(b)), stb_idict_memory_usage(stu__pd(b)), 0); - a = stu__funceval(a,b); - return a; - case '{' : { - stua_dict *d; - d = stb_idict_new_size(stu__f[n+1] > 40 ? 64 : 16); - if (d == NULL) - return stua_nil; // breakpoint fodder - c = stu__makeobj(STU___dict, d, 32, 1); - stua_pushroot(c); - a = stu__f[n+1]; - for (b=0; b < a; ++b) { - stua_obj x = stua_pushroot(stu__eval(stu__f[n+2 + b*2 + 0])); - stua_obj y = stu__eval(stu__f[n+2 + b*2 + 1]); - stua_poproot(); - if (stu__flow) { stua_poproot(); return stua_nil; } - stu__set(d, x, y); - } - stua_poproot(); - return c; - } - default: if (stu__f[n] < 0) return stu__const(stu__f)[stu__f[n]]; - assert(0); /* NOTREACHED */ // internal error! - } - return stua_nil; -} - -int stb__stua_nesting; -static stua_obj stu__funceval(stua_obj fo, stua_obj co) -{ - stu__func *f = stu__pf(fo); - stua_dict *context = stu__pd(co); - int i,j; - stua_obj p; - short *tf = stu__f; // save previous function - stua_dict *tc = stu__c; - - if (stu__flow == FLOW_error) return stua_nil; - assert(stu__flow == FLOW_normal); - - stua_pushroot(fo); - stua_pushroot(co); - stu__consider_gc(stua_nil); - - while ((stb_uint) f->closure_source > 4) { - // add data from closure to context - stua_dict *e = (stua_dict *) stu__pd(f->f.closure_data); - for (i=0; i < e->limit; ++i) - if (e->table[i].k != STB_IEMPTY && e->table[i].k != STB_IDEL) - if (stb_idict_add(context, e->table[i].k, e->table[i].v)) - stu__size_allocs += 8; - // use add so if it's already defined, we don't override it; that way - // explicit parameters win over applied ones, and most recent applications - // win over previous ones - f = stu__pf(f->closure_source); - } - - for (j=0, i=0; i < f->num_param; ++i) - // if it doesn't already exist, add it from the numbered parameters - if (stb_idict_add(context, f->param[i], stu__get(context, stu__int(j), stua_nil))) - ++j; - - // @TODO: if (stu__get(context, stu__int(f->num_param+1)) != STUA_NO_VALUE) // error: too many parameters - // @TODO: ditto too few parameters - - if (f->closure_source == 4) - p = f->f.func(context); - else { - stu__f = f->code, stu__c = context; - stu__f_obj = co; - ++stb__stua_nesting; - if (stu__f[1]) - p = stu__eval(stu__f[1]); - else - p = stua_nil; - --stb__stua_nesting; - stu__f = tf, stu__c = tc; // restore previous function - if (stu__flow == FLOW_return) { - stu__flow = FLOW_normal; - p = stu__flow_val; - stu__flow_val = stua_nil; - } - } - - stua_poproot(); - stua_poproot(); - - return p; -} - -// Parser - -static int stu__tok; -static stua_obj stu__tokval; - -static char *stu__curbuf, *stu__bufstart; - -static stb_matcher *stu__lex_matcher; - -static unsigned char stu__prec[ST__max_terminals], stu__end[ST__max_terminals]; - -static void stu__nexttoken(void) -{ - int len; - -retry: - stu__tok = stb_lex(stu__lex_matcher, stu__curbuf, &len); - if (stu__tok == 0) - return; - switch(stu__tok) { - case ST_white : stu__curbuf += len; goto retry; - case T__none : stu__tok = *stu__curbuf; break; - case ST_string: stu__tokval = make_string(stu__curbuf+1, len-2); break; - case ST_id : stu__tokval = make_string(stu__curbuf, len); break; - case ST_hex : stu__tokval = stu__makeint(strtol(stu__curbuf+2,NULL,16)); stu__tok = ST_number; break; - case ST_decimal: stu__tokval = stu__makeint(strtol(stu__curbuf ,NULL,10)); stu__tok = ST_number; break; - case ST_float : stu__tokval = stua_float((float) atof(stu__curbuf)) ; stu__tok = ST_number; break; - case ST_char : stu__tokval = stu__curbuf[2] == '\\' ? stu__curbuf[3] : stu__curbuf[2]; - if (stu__curbuf[3] == 't') stu__tokval = '\t'; - if (stu__curbuf[3] == 'n') stu__tokval = '\n'; - if (stu__curbuf[3] == 'r') stu__tokval = '\r'; - stu__tokval = stu__makeint(stu__tokval); - stu__tok = ST_number; - break; - } - stu__curbuf += len; -} - -static struct { int stu__tok; char *regex; } stu__lexemes[] = -{ - ST_white , "([ \t\n\r]|/\\*(.|\n)*\\*/|//[^\r\n]*([\r\n]|$))+", - ST_id , "[_a-zA-Z][_a-zA-Z0-9]*", - ST_hex , "0x[0-9a-fA-F]+", - ST_decimal, "[0-9]+[0-9]*", - ST_float , "[0-9]+\\.?[0-9]*([eE][-+]?[0-9]+)?", - ST_float , "\\.[0-9]+([eE][-+]?[0-9]+)?", - ST_char , "c'(\\\\.|[^\\'])'", - ST_string , "\"(\\\\.|[^\\\"\n\r])*\"", - ST_string , "\'(\\\\.|[^\\\'\n\r])*\'", - - #define stua_key4(a,b,c,d) ST_##a, #a, ST_##b, #b, ST_##c, #c, ST_##d, #d, - stua_key4(if,then,else,elseif) stua_key4(while,do,for,in) - stua_key4(func,var,let,break) stua_key4(nil,true,false,end) - stua_key4(return,continue,as,repeat) stua_key4(_frame,catch,catch,catch) - - ST_shl, "<<", ST_and, "&&", ST_eq, "==", ST_ge, ">=", - ST_shr, ">>", ST_or , "||", ST_ne, "!=", ST_le, "<=", - ST_shru,">>>", ST_into, "=>", - T__none, ".", -}; - -typedef struct -{ - stua_obj *data; // constants being compiled - short *code; // code being compiled - stua_dict *locals; - short *non_local_refs; -} stu__comp_func; - -static stu__comp_func stu__pfunc; -static stu__comp_func *func_stack = NULL; -static void stu__push_func_comp(void) -{ - stb_arr_push(func_stack, stu__pfunc); - stu__pfunc.data = NULL; - stu__pfunc.code = NULL; - stu__pfunc.locals = stb_idict_new_size(16); - stu__pfunc.non_local_refs = NULL; - stb_arr_push(stu__pfunc.code, 0); // number of data items - stb_arr_push(stu__pfunc.code, 1); // starting execution address -} - -static void stu__pop_func_comp(void) -{ - stb_arr_free(stu__pfunc.code); - stb_arr_free(stu__pfunc.data); - stb_idict_destroy(stu__pfunc.locals); - stb_arr_free(stu__pfunc.non_local_refs); - stu__pfunc = stb_arr_pop(func_stack); -} - -// if an id is a reference to an outer lexical scope, this -// function returns the "name" of it, and updates the stack -// structures to make sure the names are propagated in. -static int stu__nonlocal_id(stua_obj var_obj) -{ - stua_obj dummy, var = var_obj; - int i, n = stb_arr_len(func_stack), j,k; - if (stb_idict_get_flag(stu__pfunc.locals, var, &dummy)) return 0; - for (i=n-1; i > 1; --i) { - if (stb_idict_get_flag(func_stack[i].locals, var, &dummy)) - break; - } - if (i <= 1) return 0; // stu__compile_global_scope - j = i; // need to access variable from j'th frame - for (i=0; i < stb_arr_len(stu__pfunc.non_local_refs); ++i) - if (stu__pfunc.non_local_refs[i] == j) return j-n; - stb_arr_push(stu__pfunc.non_local_refs, j-n); - // now make sure all the parents propagate it down - for (k=n-1; k > 1; --k) { - if (j-k >= 0) return j-n; // comes direct from this parent - for(i=0; i < stb_arr_len(func_stack[k].non_local_refs); ++i) - if (func_stack[k].non_local_refs[i] == j-k) - return j-n; - stb_arr_push(func_stack[k].non_local_refs, j-k); - } - assert (k != 1); - - return j-n; -} - -static int stu__off(void) { return stb_arr_len(stu__pfunc.code); } -static void stu__cc(int a) -{ - assert(a >= -2000 && a < 5000); - stb_arr_push(stu__pfunc.code, a); -} -static int stu__cc1(int a) { stu__cc(a); return stu__off()-1; } -static int stu__cc2(int a, int b) { stu__cc(a); stu__cc(b); return stu__off()-2; } -static int stu__cc3(int a, int b, int c) { - if (a == '=') assert(c != 0); - stu__cc(a); stu__cc(b); stu__cc(c); return stu__off()-3; } -static int stu__cc4(int a, int b, int c, int d) { stu__cc(a); stu__cc(b); stu__cc(c); stu__cc(d); return stu__off()-4; } - -static int stu__cdv(stua_obj p) -{ - int i; - assert(p != STUA_NO_VALUE); - for (i=0; i < stb_arr_len(stu__pfunc.data); ++i) - if (stu__pfunc.data[i] == p) - break; - if (i == stb_arr_len(stu__pfunc.data)) - stb_arr_push(stu__pfunc.data, p); - return ~i; -} - -static int stu__cdt(void) -{ - int z = stu__cdv(stu__tokval); - stu__nexttoken(); - return z; -} - -static int stu__seq(int a, int b) -{ - return !a ? b : !b ? a : stu__cc3(STU__seq, a,b); -} - -static char stu__comp_err_str[1024]; -static int stu__comp_err_line; -static int stu__err(char *str, ...) -{ - va_list v; - char *s = stu__bufstart; - stu__comp_err_line = 1; - while (s < stu__curbuf) { - if (s[0] == '\n' || s[0] == '\r') { - if (s[0]+s[1] == '\n' + '\r') ++s; - ++stu__comp_err_line; - } - ++s; - } - va_start(v, str); - vsprintf(stu__comp_err_str, str, v); - va_end(v); - return 0; -} - -static int stu__accept(int p) -{ - if (stu__tok != p) return 0; - stu__nexttoken(); - return 1; -} - -static int stu__demand(int p) -{ - if (stu__accept(p)) return 1; - return stu__err("Didn't find expected stu__tok"); -} - -static int stu__demandv(int p, stua_obj *val) -{ - if (stu__tok == p || p==0) { - *val = stu__tokval; - stu__nexttoken(); - return 1; - } else - return 0; -} - -static int stu__expr(int p); -int stu__nexpr(int p) { stu__nexttoken(); return stu__expr(p); } -static int stu__statements(int once, int as); - -static int stu__parse_if(void) // parse both ST_if and ST_elseif -{ - int b,c,a; - a = stu__nexpr(1); if (!a) return 0; - if (!stu__demand(ST_then)) return stu__err("expecting THEN"); - b = stu__statements(0,0); if (!b) return 0; - if (b == 1) b = -1; - - if (stu__tok == ST_elseif) { - return stu__parse_if(); - } else if (stu__accept(ST_else)) { - c = stu__statements(0,0); if (!c) return 0; - if (!stu__demand(ST_end)) return stu__err("expecting END after else clause"); - return stu__cc4(ST_else, a, b, c); - } else { - if (!stu__demand(ST_end)) return stu__err("expecting END in if statement"); - return stu__cc3(ST_if, a, b); - } -} - -int stu__varinit(int z, int in_globals) -{ - int a,b; - stu__nexttoken(); - while (stu__demandv(ST_id, &b)) { - if (!stb_idict_add(stu__pfunc.locals, b, 1)) - if (!in_globals) return stu__err("Redefined variable %s.", stu__pw(b)->ptr); - if (stu__accept('=')) { - a = stu__expr(1); if (!a) return 0; - } else - a = stu__cdv(stua_nil); - z = stu__seq(z, stu__cc3(ST_var, stu__cdv(b), a)); - if (!stu__accept(',')) break; - } - return z; -} - -static int stu__compile_unary(int z, int outparm, int require_inparm) -{ - int op = stu__tok, a, b; - stu__nexttoken(); - if (outparm) { - if (require_inparm || (stu__tok && stu__tok != ST_end && stu__tok != ST_else && stu__tok != ST_elseif && stu__tok !=';')) { - a = stu__expr(1); if (!a) return 0; - } else - a = stu__cdv(stua_nil); - b = stu__cc2(op, a); - } else - b = stu__cc1(op); - return stu__seq(z,b); -} - -static int stu__assign(void) -{ - int z; - stu__accept(ST_let); - z = stu__expr(1); if (!z) return 0; - if (stu__accept('=')) { - int y,p = (z >= 0 ? stu__pfunc.code[z] : 0); - if (z < 0 || (p != ST_id && p != '[')) return stu__err("Invalid lvalue in assignment"); - y = stu__assign(); if (!y) return 0; - z = stu__cc3('=', z, y); - } - return z; -} - -static int stu__statements(int once, int stop_while) -{ - int a,b, c, z=0; - for(;;) { - switch (stu__tok) { - case ST_if : a = stu__parse_if(); if (!a) return 0; - z = stu__seq(z, a); - break; - case ST_while : if (stop_while) return (z ? z:1); - a = stu__nexpr(1); if (!a) return 0; - if (stu__accept(ST_as)) c = stu__statements(0,0); else c = 0; - if (!stu__demand(ST_do)) return stu__err("expecting DO"); - b = stu__statements(0,0); if (!b) return 0; - if (!stu__demand(ST_end)) return stu__err("expecting END"); - if (b == 1) b = -1; - z = stu__seq(z, stu__cc4(ST_while, a, b, c)); - break; - case ST_repeat : stu__nexttoken(); - c = stu__statements(0,1); if (!c) return 0; - if (!stu__demand(ST_while)) return stu__err("expecting WHILE"); - a = stu__expr(1); if (!a) return 0; - if (!stu__demand(ST_do)) return stu__err("expecting DO"); - b = stu__statements(0,0); if (!b) return 0; - if (!stu__demand(ST_end)) return stu__err("expecting END"); - if (b == 1) b = -1; - z = stu__seq(z, stu__cc4(ST_as, a, b, c)); - break; - case ST_catch : a = stu__nexpr(1); if (!a) return 0; - z = stu__seq(z, stu__cc2(ST_catch, a)); - break; - case ST_var : z = stu__varinit(z,0); break; - case ST_return : z = stu__compile_unary(z,1,1); break; - case ST_continue:z = stu__compile_unary(z,0,0); break; - case ST_break : z = stu__compile_unary(z,1,0); break; - case ST_into : if (z == 0 && !once) return stu__err("=> cannot be first statement in block"); - a = stu__nexpr(99); - b = (a >= 0? stu__pfunc.code[a] : 0); - if (a < 0 || (b != ST_id && b != '[')) return stu__err("Invalid lvalue on right side of =>"); - z = stu__cc3('=', a, z); - break; - default : if (stu__end[stu__tok]) return once ? 0 : (z ? z:1); - a = stu__assign(); if (!a) return 0; - stu__accept(';'); - if (stu__tok && !stu__end[stu__tok]) { - if (a < 0) - return stu__err("Constant has no effect"); - if (stu__pfunc.code[a] != '(' && stu__pfunc.code[a] != '=') - return stu__err("Expression has no effect"); - } - z = stu__seq(z, a); - break; - } - if (!z) return 0; - stu__accept(';'); - if (once && stu__tok != ST_into) return z; - } -} - -static int stu__postexpr(int z, int p); -static int stu__dictdef(int end, int *count) -{ - int z,n=0,i,flags=0; - short *dict=NULL; - stu__nexttoken(); - while (stu__tok != end) { - if (stu__tok == ST_id) { - stua_obj id = stu__tokval; - stu__nexttoken(); - if (stu__tok == '=') { - flags |= 1; - stb_arr_push(dict, stu__cdv(id)); - z = stu__nexpr(1); if (!z) return 0; - } else { - z = stu__cc2(ST_id, stu__cdv(id)); - z = stu__postexpr(z,1); if (!z) return 0; - flags |= 2; - stb_arr_push(dict, stu__cdv(stu__makeint(n++))); - } - } else { - z = stu__expr(1); if (!z) return 0; - flags |= 2; - stb_arr_push(dict, stu__cdv(stu__makeint(n++))); - } - if (end != ')' && flags == 3) { z=stu__err("can't mix initialized and uninitialized defs"); goto done;} - stb_arr_push(dict, z); - if (!stu__accept(',')) break; - } - if (!stu__demand(end)) - return stu__err(end == ')' ? "Expecting ) at end of function call" - : "Expecting } at end of dictionary definition"); - z = stu__cc2('{', stb_arr_len(dict)/2); - for (i=0; i < stb_arr_len(dict); ++i) - stu__cc(dict[i]); - if (count) *count = n; -done: - stb_arr_free(dict); - return z; -} - -static int stu__comp_id(void) -{ - int z,d; - d = stu__nonlocal_id(stu__tokval); - if (d == 0) - return z = stu__cc2(ST_id, stu__cdt()); - // access a non-local frame by naming it with the appropriate int - assert(d < 0); - z = stu__cdv(d); // relative frame # is the 'variable' in our local frame - z = stu__cc2(ST_id, z); // now access that dictionary - return stu__cc3('[', z, stu__cdt()); // now access the variable from that dir -} - -static stua_obj stu__funcdef(stua_obj *id, stua_obj *func); -static int stu__expr(int p) -{ - int z; - // unary - switch (stu__tok) { - case ST_number: z = stu__cdt(); break; - case ST_string: z = stu__cdt(); break; // @TODO - string concatenation like C - case ST_id : z = stu__comp_id(); break; - case ST__frame: z = stu__cc1(ST__frame); stu__nexttoken(); break; - case ST_func : z = stu__funcdef(NULL,NULL); break; - case ST_if : z = stu__parse_if(); break; - case ST_nil : z = stu__cdv(stua_nil); stu__nexttoken(); break; - case ST_true : z = stu__cdv(stua_true); stu__nexttoken(); break; - case ST_false : z = stu__cdv(stua_false); stu__nexttoken(); break; - case '-' : z = stu__nexpr(99); if (z) z=stu__cc2(STU__negate,z); else return z; break; - case '!' : z = stu__nexpr(99); if (z) z=stu__cc2('!',z); else return z; break; - case '~' : z = stu__nexpr(99); if (z) z=stu__cc2('~',z); else return z; break; - case '{' : z = stu__dictdef('}', NULL); break; - default : return stu__err("Unexpected token"); - case '(' : stu__nexttoken(); z = stu__statements(0,0); if (!stu__demand(')')) return stu__err("Expecting )"); - } - return stu__postexpr(z,p); -} - -static int stu__postexpr(int z, int p) -{ - int q; - // postfix - while (stu__tok == '(' || stu__tok == '[' || stu__tok == '.') { - if (stu__accept('.')) { - // MUST be followed by a plain identifier! use [] for other stuff - if (stu__tok != ST_id) return stu__err("Must follow . with plain name; try [] instead"); - z = stu__cc3('[', z, stu__cdv(stu__tokval)); - stu__nexttoken(); - } else if (stu__accept('[')) { - while (stu__tok != ']') { - int r = stu__expr(1); if (!r) return 0; - z = stu__cc3('[', z, r); - if (!stu__accept(',')) break; - } - if (!stu__demand(']')) return stu__err("Expecting ]"); - } else { - int n, p = stu__dictdef(')', &n); if (!p) return 0; - #if 0 // this is incorrect! - if (z > 0 && stu__pfunc.code[z] == ST_id) { - stua_obj q = stu__get(stu__globaldict, stu__pfunc.data[-stu__pfunc.code[z+1]-1], stua_nil); - if (stu__checkt(STU___function, q)) - if ((stu__pf(q))->num_param != n) - return stu__err("Incorrect number of parameters"); - } - #endif - z = stu__cc3('(', z, p); - } - } - // binop - this implementation taken from lcc - for (q=stu__prec[stu__tok]; q >= p; --q) { - while (stu__prec[stu__tok] == q) { - int o = stu__tok, y = stu__nexpr(p+1); if (!y) return 0; - z = stu__cc3(o,z,y); - } - } - return z; -} - -static stua_obj stu__finish_func(stua_obj *param, int start) -{ - int n, size; - stu__func *f = (stu__func *) malloc(sizeof(*f)); - f->closure_source = 0; - f->num_param = stb_arr_len(param); - f->param = (int *) stb_copy(param, f->num_param * sizeof(*f->param)); - size = stb_arr_storage(stu__pfunc.code) + stb_arr_storage(stu__pfunc.data) + sizeof(*f) + 8; - f->f.store = malloc(stb_arr_storage(stu__pfunc.code) + stb_arr_storage(stu__pfunc.data)); - f->code = (short *) ((char *) f->f.store + stb_arr_storage(stu__pfunc.data)); - memcpy(f->code, stu__pfunc.code, stb_arr_storage(stu__pfunc.code)); - f->code[1] = start; - f->code[0] = stb_arr_len(stu__pfunc.data); - for (n=0; n < f->code[0]; ++n) - ((stua_obj *) f->code)[-1-n] = stu__pfunc.data[n]; - return stu__makeobj(STU___function, f, size, 0); -} - -static int stu__funcdef(stua_obj *id, stua_obj *result) -{ - int n,z=0,i,q; - stua_obj *param = NULL; - short *nonlocal; - stua_obj v,f=stua_nil; - assert(stu__tok == ST_func); - stu__nexttoken(); - if (id) { - if (!stu__demandv(ST_id, id)) return stu__err("Expecting function name"); - } else - stu__accept(ST_id); - if (!stu__demand('(')) return stu__err("Expecting ( for function parameter"); - stu__push_func_comp(); - while (stu__tok != ')') { - if (!stu__demandv(ST_id, &v)) { z=stu__err("Expecting parameter name"); goto done; } - stb_idict_add(stu__pfunc.locals, v, 1); - if (stu__tok == '=') { - n = stu__nexpr(1); if (!n) { z=0; goto done; } - z = stu__seq(z, stu__cc3(STU__defaultparm, stu__cdv(v), n)); - } else - stb_arr_push(param, v); - if (!stu__accept(',')) break; - } - if (!stu__demand(')')) { z=stu__err("Expecting ) at end of parameter list"); goto done; } - n = stu__statements(0,0); if (!n) { z=0; goto done; } - if (!stu__demand(ST_end)) { z=stu__err("Expecting END at end of function"); goto done; } - if (n == 1) n = 0; - n = stu__seq(z,n); - f = stu__finish_func(param, n); - if (result) { *result = f; z=1; stu__pop_func_comp(); } - else { - nonlocal = stu__pfunc.non_local_refs; - stu__pfunc.non_local_refs = NULL; - stu__pop_func_comp(); - z = stu__cdv(f); - if (nonlocal) { // build a closure with references to the needed frames - short *initcode = NULL; - for (i=0; i < stb_arr_len(nonlocal); ++i) { - int k = nonlocal[i], p; - stb_arr_push(initcode, stu__cdv(k)); - if (k == -1) p = stu__cc1(ST__frame); - else { p = stu__cdv(stu__makeint(k+1)); p = stu__cc2(ST_id, p); } - stb_arr_push(initcode, p); - } - q = stu__cc2('{', stb_arr_len(nonlocal)); - for (i=0; i < stb_arr_len(initcode); ++i) - stu__cc(initcode[i]); - z = stu__cc3('+', z, q); - stb_arr_free(initcode); - } - stb_arr_free(nonlocal); - } -done: - stb_arr_free(param); - if (!z) stu__pop_func_comp(); - return z; -} - -static int stu__compile_global_scope(void) -{ - stua_obj o; - int z=0; - - stu__push_func_comp(); - while (stu__tok != 0) { - if (stu__tok == ST_func) { - stua_obj id, f; - if (!stu__funcdef(&id,&f)) - goto error; - stu__set(stu__globaldict, id, f); - } else if (stu__tok == ST_var) { - z = stu__varinit(z,1); if (!z) goto error; - } else { - int y = stu__statements(1,0); if (!y) goto error; - z = stu__seq(z,y); - } - stu__accept(';'); - } - o = stu__finish_func(NULL, z); - stu__pop_func_comp(); - - o = stu__funceval(o, stua_globals); // initialize stu__globaldict - if (stu__flow == FLOW_error) - printf("Error: %s\n", ((stu__wrapper *) stu__ptr(stu__flow_val))->ptr); - return 1; -error: - stu__pop_func_comp(); - return 0; -} - -stua_obj stu__myprint(stua_dict *context) -{ - stua_obj x = stu__get(context, stua_string("x"), stua_nil); - if ((x & 1) == stu__float_tag) printf("%f", stu__getfloat(x)); - else if (stu__tag(x) == stu__int_tag) printf("%d", stu__int(x)); - else { - stu__wrapper *s = stu__pw(x); - if (s->type == STU___string || s->type == STU___error) - printf("%s", s->ptr); - else if (s->type == STU___dict) printf("{{dictionary}}"); - else if (s->type == STU___function) printf("[[function]]"); - else - printf("[[ERROR:%s]]", s->ptr); - } - return x; -} - -void stua_init(void) -{ - if (!stu__globaldict) { - int i; - stua_obj s; - stu__func *f; - - stu__prec[ST_and] = stu__prec[ST_or] = 1; - stu__prec[ST_eq ] = stu__prec[ST_ne] = stu__prec[ST_le] = - stu__prec[ST_ge] = stu__prec['>' ] = stu__prec['<'] = 2; - stu__prec[':'] = 3; - stu__prec['&'] = stu__prec['|'] = stu__prec['^'] = 4; - stu__prec['+'] = stu__prec['-'] = 5; - stu__prec['*'] = stu__prec['/'] = stu__prec['%'] = - stu__prec[ST_shl]= stu__prec[ST_shr]= stu__prec[ST_shru]= 6; - - stu__end[')'] = stu__end[ST_end] = stu__end[ST_else] = 1; - stu__end[ST_do] = stu__end[ST_elseif] = 1; - - stu__float_init(); - stu__lex_matcher = stb_lex_matcher(); - for (i=0; i < sizeof(stu__lexemes)/sizeof(stu__lexemes[0]); ++i) - stb_lex_item(stu__lex_matcher, stu__lexemes[i].regex, stu__lexemes[i].stu__tok); - - stu__globaldict = stb_idict_new_size(64); - stua_globals = stu__makeobj(STU___dict, stu__globaldict, 0,0); - stu__strings = stb_sdict_new(0); - - stu__curbuf = stu__bufstart = "func _print(x) end\n" - "func print()\n var x=0 while _frame[x] != nil as x=x+1 do _print(_frame[x]) end end\n"; - stu__nexttoken(); - if (!stu__compile_global_scope()) - printf("Compile error in line %d: %s\n", stu__comp_err_line, stu__comp_err_str); - - s = stu__get(stu__globaldict, stua_string("_print"), stua_nil); - if (stu__tag(s) == stu__ptr_tag && stu__ptr(s)->type == STU___function) { - f = stu__pf(s); - free(f->f.store); - f->closure_source = 4; - f->f.func = stu__myprint; - f->code = NULL; - } - } -} - -void stua_uninit(void) -{ - if (stu__globaldict) { - stb_idict_remove_all(stu__globaldict); - stb_arr_setlen(stu__gc_root_stack, 0); - stua_gc(1); - stb_idict_destroy(stu__globaldict); - stb_sdict_delete(stu__strings); - stb_matcher_free(stu__lex_matcher); - stb_arr_free(stu__gc_ptrlist); - stb_arr_free(func_stack); - stb_arr_free(stu__gc_root_stack); - stu__globaldict = NULL; - } -} - -void stua_run_script(char *s) -{ - stua_init(); - - stu__curbuf = stu__bufstart = s; - stu__nexttoken(); - - stu__flow = FLOW_normal; - - if (!stu__compile_global_scope()) - printf("Compile error in line %d: %s\n", stu__comp_err_line, stu__comp_err_str); - stua_gc(1); -} -#endif // STB_DEFINE -#endif // STB_STUA - #undef STB_EXTERN #endif // STB_INCLUDE_STB_H