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)); }
