theScript = Script.Make(Script.The.asString) result = theScript.DoIt( { ... arguments ...} )
The first routine was simple to solve because only one call was made per iteration:
int locate_endpoint(v, vo, r) point_t *v; point_t *vo; int r; { node_t *rptr = &qs[r]; switch (rptr->nodetype) { case T_SINK: return rptr->trnum; case T_Y: if (_greater_than(v, &rptr->yval)) /* above */ return locate_endpoint(v, vo, rptr->right); else if (_equal_to(v, &rptr->yval)) /* the point is already */ { /* inserted. */ if (_greater_than(vo, &rptr->yval)) /* above */ return locate_endpoint(v, vo, rptr->right); else return locate_endpoint(v, vo, rptr->left); /* below */ } else return locate_endpoint(v, vo, rptr->left); /* below */ ... }The approach I took was to set up an infinite loop, reassigning the value of variable "r" as necessary:
v = SELF.Get(0) vo = SELF.Get(1) r = SELF.Get(2) while (TRUE) rptr = _qs.Get(r) nt = rptr.Get(0) if (nt = "T_SINK") then return rptr.Get(3) elseif (nt = "T_Y") then if (av.Run("P.GT",{v,rptr.Get(2)})) then r = rptr.Get(6) elseif (v = rptr.Get(2)) then if (av.Run("P.GT",{vo,rptr.Get(2)})) then r = rptr.Get(6) else r = rptr.Get(5) end else r = rptr.Get(5) end ... endThe other routine was more difficult to solve because it made multiple calls per iteration:
static int traverse_polygon(mcur, trnum, from, dir) int mcur; int trnum; int from; int dir; { ... int do_switch = FALSE; if ((trnum <= 0) || visited[trnum]) return 0; visited[trnum] = TRUE; if ((t->u0 <= 0) && (t->u1 <= 0)) { if ((t->d0 > 0) && (t->d1 > 0)) /* downward opening triangle */ { v0 = tr[t->d1].lseg; v1 = t->lseg; if (from == t->d1) { do_switch = TRUE; mnew = make_new_monotone_poly(mcur, v1, v0); traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP); traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP); } ... }I solved the problem by using a Stack object to store arguments:
'**** initialize stack theStack = Stack.Make theStack.Push({SELF.Get(0),SELF.Get(1),SELF.Get(2),SELF.GET(3)}) retval = "" ... while (TRUE) if (theStack.IsEmpty) then return retval end arglist = theStack.Pop mcur = arglist.Get(0) trnum = arglist.Get(1) from = arglist.Get(2) dir = arglist.Get(3) do_switch = FALSE cond = FALSE if (trnum <= 0) then cond = TRUE elseif (visited.Get(trnum)) then cond = TRUE else t = _tr.Get(trnum) end if (cond) then retval = 0 continue end visited.Set(trnum,TRUE) sn = sn + 1 av.SetStatus(100*sn/sd) if ((t.Get(4) <= 0) and (t.Get(5) <= 0)) then if ((t.Get(6) > 0) and (t.Get(7) > 0)) then '**** downward opening triangle v0 = _tr.Get(t.Get(7)).Get(0) v1 = t.Get(0) if (from = t.Get(7)) then do_switch = TRUE mnew = av.Run("P.NewMonotone",{mcur, v1, v0}) theStack.Push({mnew,t.Get(6),trnum,"TR_FROM_UP"}) theStack.Push({mcur,t.Get(7),trnum,"TR_FROM_UP"}) ... endNote that because of the nature of Stacks (Last-In-First-Out), the order of the Push requests is reversed.
If you want to take a better look at the routines, you can access them via the Web. The original C code may be downloaded at:
http://www.cs.unc.edu/~dm/CODE/GEM/chapter.html
and the Avenue code may be downloaded at:
http://www.pierssen.com/arcview/esoteric.htm