Index: array.c =================================================================== RCS file: /home/danw/nawm/repository/nawm/array.c,v retrieving revision 1.16 diff -c -r1.16 array.c *** array.c 1999/11/26 22:03:49 1.16 --- array.c 1999/11/27 14:53:05 *************** *** 254,278 **** free(arr); } ! nawmval array_first(array *arr, arrayiter *ai) { ! ai->ind = 0; ! ai->chain = arr->elts[ai->ind]; ! return ai->chain->data; } ! nawmval array_next(array *arr, arrayiter *ai) { ! ai->chain = ai->chain->next; if (!ai->chain) { ai->ind++; ! if (ai->ind >= arr->size) ! return 0; ! ai->chain = arr->elts[ai->ind]; } - - return ai->chain->data; } --- 254,298 ---- free(arr); } ! ! iterator arrayiter = { T_ARRAY, arrayiter_init, arrayiter_next, free }; ! ! struct _arrayiter { ! int ind; ! struct _achain *chain; ! }; ! ! void initarrays(void) { ! define_iterator(&arrayiter); ! } ! ! static void arrayiter_init(void **iter) ! { ! struct _arrayiter **ai = iter; ! ! *ai = malloc(sizeof(struct _arrayiter)) ! (*ai)->ind = 0; ! (*ai)->chain = arr->elts[ai->ind]; } ! static nawmval arrayiter_next(void *val, void *iter) { ! array *arr = val; ! struct _arrayiter *ai = iter; ! nawmval val; ! ! if (!ai->chain) ! return 0; + val = ai->chain->data; + + ai->chain = ai->chain->next; if (!ai->chain) { ai->ind++; ! if (ai->ind < arr->size) ! ai->chain = arr->elts[ai->ind]; } } Index: dtype.c =================================================================== RCS file: /home/danw/nawm/repository/nawm/dtype.c,v retrieving revision 1.3 diff -c -r1.3 dtype.c *** dtype.c 1999/11/26 20:32:54 1.3 --- dtype.c 1999/11/27 14:56:21 *************** *** 66,71 **** --- 66,73 ---- } + /* Run-time defined typecasts */ + static int ncasts, castssize; struct cast { dtype from, to; *************** *** 92,97 **** --- 94,127 ---- { if (casts[i].from == from && casts[i].to == to) return casts[i].func; + } + return NULL; + } + + + /* Iterable types */ + int numits, itssize; + iterator *its; + + void define_iterable(iterator i) + { + if (numits == itssize) + { + itssize = 2 * (itssize + 1); + its = xrealloc(its, itssize * sizeof(iterator)); + } + + its[numits++] = i; + } + + iterator *lookup_iterable(dtype type) + { + int i; + + for (i = 0; i < numits; i++) + { + if (its[i].type == type) /* XXX basetype */ + return &its[i]; } return NULL; } Index: eval.c =================================================================== RCS file: /home/danw/nawm/repository/nawm/eval.c,v retrieving revision 1.27 diff -c -r1.27 eval.c *** eval.c 1999/11/26 22:03:51 1.27 --- eval.c 1999/11/27 15:03:13 *************** *** 211,227 **** } else { ! arrayiter ai; ! array *arr = (array *)eval_expr(cmd->vals[0]->vals[1]); nawmval val; ! val = assignval(cmd->vals[0]->vals[0], array_first(arr, &ai)); ! while (val) { if (eval_cmd(cmd->vals[1]) == BREAK) break; - val = assignval(cmd->vals[0]->vals[0], array_next(arr, &ai)); } } break; --- 211,232 ---- } else { ! void *container = (void *)eval_expr(cmd->vals[0]->vals[1]); ! iterator *iter = dtype_iterator(cmd->vals[0]->vals[1]->etype); ! void *idata; nawmval val; ! idata = iter->init(container); ! while (1) { + val = iter->next(container, idata); + if (!val) + break; + assignval(cmd->vals[0]->vals[0], val); if (eval_cmd(cmd->vals[1]) == BREAK) break; } + iter->dispose(idata); } break; Index: lang.h =================================================================== RCS file: /home/danw/nawm/repository/nawm/lang.h,v retrieving revision 1.25 diff -c -r1.25 lang.h *** lang.h 1999/11/26 22:03:52 1.25 --- lang.h 1999/11/26 22:16:36 *************** *** 72,81 **** struct _varbinding *next; } varbinding; ! typedef struct _arrayiter { ! int ind; ! struct _achain *chain; ! } arrayiter; typedef struct _event_handler { void (*handler)(XEvent *); --- 72,83 ---- struct _varbinding *next; } varbinding; ! typedef struct { ! dtype type; ! int (*init)(void **, node *); ! nawmval (*next)(void **, node *); ! void (*dispose)(void **); ! } iterator; typedef struct _event_handler { void (*handler)(XEvent *); Index: parser.y =================================================================== RCS file: /home/danw/nawm/repository/nawm/parser.y,v retrieving revision 1.32 diff -c -r1.32 parser.y *** parser.y 1999/11/26 22:03:54 1.32 --- parser.y 1999/11/26 22:08:05 *************** *** 199,205 **** | error ';' { die("while parsing commands."); } ; ! forexpr : VAR IN expr { arraycheck($3); $$ = mknode(IN, 0, 2, typecheck(mknode(VAR, $1->type, 1, $1), array_basetype($3->etype)), $3); } | expr ';' expr ';' expr { $$ = mknode(FOR, 0, 3, $1, typecheck($3, T_INT), $5); } ; --- 199,205 ---- | error ';' { die("while parsing commands."); } ; ! forexpr : VAR IN expr { $$ = mknode(IN, 0, 2, typecheck(mknode(VAR, $1->type, 1, $1), iterable_rettype($3->etype)), $3); } | expr ';' expr ';' expr { $$ = mknode(FOR, 0, 3, $1, typecheck($3, T_INT), $5); } ; *************** *** 233,239 **** ; memb_expr : add_expr ! | memb_expr IN add_expr { arraycheck($3); $$ = mknode(IN, T_INT, 2, typecheck($1, array_basetype($3->etype)), $3); } add_expr : mult_expr | add_expr ADDOP mult_expr { $$ = apply_op(opname[$2], chain($3, $1)); } --- 233,239 ---- ; memb_expr : add_expr ! | memb_expr IN add_expr { $$ = mknode(IN, T_INT, 2, typecheck($1, iterable_rettype($3->etype)), $3); } add_expr : mult_expr | add_expr ADDOP mult_expr { $$ = apply_op(opname[$2], chain($3, $1)); }