2
0
Эх сурвалжийг харах

stb: Remove stua entirely

As per issue 634, Stua "will be deleted from stb.h" soonish. That
was 3 years ago, which should be plenty of warning, and the
language has been de-facto orphaned and undocumented for a
good while longer than that.

Fixes issue #634.
Fabian Giesen 4 жил өмнө
parent
commit
e5fd7f6ce0
1 өөрчлөгдсөн 0 нэмэгдсэн , 1350 устгасан
  1. 0 1350
      deprecated/stb.h

+ 0 - 1350
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