@@ -183,189 +183,64 @@ void dump(const char *str, Ref node, bool pretty) {
183183 std::cerr << std::endl;
184184}
185185
186- // AST traversals
187-
188186// Traversals
189187
190188struct TraverseInfo {
191189 TraverseInfo () = default ;
192- TraverseInfo (Ref node, ArrayStorage* arr) : node(node), arr(arr), index(0 ) {}
193- Ref node;
194- ArrayStorage* arr;
195- int index;
196- };
197-
198- template <class T , int init>
199- struct StackedStack { // a stack, on the stack
200- T stackStorage[init];
201- T* storage;
202- int used = 0 ;
203- int available = init; // used amount, available amount
204- bool alloced = false ;
205-
206- StackedStack () {
207- storage = stackStorage;
208- }
209- ~StackedStack () {
210- if (alloced) free (storage);
211- }
212-
213- int size () { return used; }
214-
215- void push_back (const T& t) {
216- assert (used <= available);
217- if (used == available) {
218- available *= 2 ;
219- if (!alloced) {
220- T* old = storage;
221- storage = (T*)malloc (sizeof (T)*available);
222- memcpy (storage, old, sizeof (T)*used);
223- alloced = true ;
224- } else {
225- T *newStorage = (T*)realloc (storage, sizeof (T)*available);
226- assert (newStorage);
227- storage = newStorage;
228- }
229- }
230- assert (used < available);
231- assert (storage);
232- storage[used++] = t;
233- }
234-
235- T& back () {
236- assert (used > 0 );
237- return storage[used-1 ];
238- }
239-
240- void pop_back () {
241- assert (used > 0 );
242- used--;
243- }
244- };
245-
246- #define visitable (node ) (node->isArray () && node->size() > 0)
247-
248- #define TRAV_STACK 40
249-
250- // Traverse, calling visit before the children
251- void traversePre (Ref node, std::function<void (Ref)> visit) {
252- if (!visitable (node)) return ;
253- visit (node);
254- StackedStack<TraverseInfo, TRAV_STACK> stack;
255- int index = 0 ;
256- ArrayStorage* arr = &node->getArray ();
257- int arrsize = (int )arr->size ();
258- Ref* arrdata = &(*arr)[0 ];
259- stack.push_back (TraverseInfo (node, arr));
260- while (1 ) {
261- if (index < arrsize) {
262- Ref sub = *(arrdata+index);
263- index++;
264- if (visitable (sub)) {
265- stack.back ().index = index;
266- index = 0 ;
267- visit (sub);
268- arr = &sub->getArray ();
269- arrsize = (int )arr->size ();
270- arrdata = &(*arr)[0 ];
271- stack.push_back (TraverseInfo (sub, arr));
190+ TraverseInfo (Ref node) : node(node) {
191+ assert (node.get ());
192+ if (node->isArray ()) {
193+ for (size_t i = 0 ; i < node->size (); i++) {
194+ maybeAdd (node[i]);
272195 }
196+ } else if (node->isAssign ()) {
197+ auto assign = node->asAssign ();
198+ maybeAdd (assign->target ());
199+ maybeAdd (assign->value ());
200+ } else if (node->isAssignName ()) {
201+ auto assign = node->asAssignName ();
202+ maybeAdd (assign->value ());
273203 } else {
274- stack.pop_back ();
275- if (stack.size () == 0 ) break ;
276- TraverseInfo& back = stack.back ();
277- index = back.index ;
278- arr = back.arr ;
279- arrsize = (int )arr->size ();
280- arrdata = &(*arr)[0 ];
204+ // no children
281205 }
282206 }
283- }
207+ Ref node;
208+ size_t index = -1 ;
209+ std::vector<Ref> children;
284210
285- // Traverse, calling visitPre before the children and visitPost after
286- void traversePrePost (Ref node, std::function<void (Ref)> visitPre, std::function<void (Ref)> visitPost) {
287- if (!visitable (node)) return ;
288- visitPre (node);
289- StackedStack<TraverseInfo, TRAV_STACK> stack;
290- int index = 0 ;
291- ArrayStorage* arr = &node->getArray ();
292- int arrsize = (int )arr->size ();
293- Ref* arrdata = &(*arr)[0 ];
294- stack.push_back (TraverseInfo (node, arr));
295- while (1 ) {
296- if (index < arrsize) {
297- Ref sub = *(arrdata+index);
298- index++;
299- if (visitable (sub)) {
300- stack.back ().index = index;
301- index = 0 ;
302- visitPre (sub);
303- arr = &sub->getArray ();
304- arrsize = (int )arr->size ();
305- arrdata = &(*arr)[0 ];
306- stack.push_back (TraverseInfo (sub, arr));
307- }
308- } else {
309- visitPost (stack.back ().node );
310- stack.pop_back ();
311- if (stack.size () == 0 ) break ;
312- TraverseInfo& back = stack.back ();
313- index = back.index ;
314- arr = back.arr ;
315- arrsize = (int )arr->size ();
316- arrdata = &(*arr)[0 ];
211+ private:
212+ void maybeAdd (Ref child) {
213+ if (child.get ()) {
214+ children.push_back (child);
317215 }
318216 }
319- }
217+ };
320218
321- // Traverse, calling visitPre before the children and visitPost after. If pre returns false, do not traverse children
322- void traversePrePostConditional (Ref node, std::function<bool (Ref)> visitPre, std::function<void (Ref)> visitPost) {
323- if (!visitable (node)) return ;
324- if (!visitPre (node)) return ;
325- StackedStack<TraverseInfo, TRAV_STACK> stack;
326- int index = 0 ;
327- ArrayStorage* arr = &node->getArray ();
328- int arrsize = (int )arr->size ();
329- Ref* arrdata = &(*arr)[0 ];
330- stack.push_back (TraverseInfo (node, arr));
331- while (1 ) {
332- if (index < arrsize) {
333- Ref sub = *(arrdata+index);
334- index++;
335- if (visitable (sub)) {
336- if (visitPre (sub)) {
337- stack.back ().index = index;
338- index = 0 ;
339- arr = &sub->getArray ();
340- arrsize = (int )arr->size ();
341- arrdata = &(*arr)[0 ];
342- stack.push_back (TraverseInfo (sub, arr));
343- }
219+ // Traverse, calling visit after the children
220+ void traversePost (Ref node, std::function<void (Ref)> visit) {
221+ std::vector<TraverseInfo> stack;
222+ stack.push_back (TraverseInfo (node));
223+ while (!stack.empty ()) {
224+ TraverseInfo& back = stack.back ();
225+ if (back.index == size_t (-1 )) {
226+ // This is the first time we see this. Push its children.
227+ back.index = 0 ;
228+ for (auto child : back.children ) {
229+ stack.emplace_back (child);
344230 }
345- } else {
346- visitPost (stack.back ().node );
347- stack.pop_back ();
348- if (stack.size () == 0 ) break ;
349- TraverseInfo& back = stack.back ();
350- index = back.index ;
351- arr = back.arr ;
352- arrsize = (int )arr->size ();
353- arrdata = &(*arr)[0 ];
231+ continue ;
354232 }
355- }
356- }
357-
358- // Traverses all the top-level functions in the document
359- void traverseFunctions (Ref ast, std::function<void (Ref)> visit) {
360- if (!ast || ast->size () == 0 ) return ;
361- if (ast[0 ] == TOPLEVEL) {
362- Ref stats = ast[1 ];
363- for (size_t i = 0 ; i < stats->size (); i++) {
364- Ref curr = stats[i];
365- if (curr[0 ] == DEFUN) visit (curr);
233+ if (back.index < back.children .size ()) {
234+ // Visit this child.
235+ back.index ++;
236+ visit (back.children [back.index - 1 ]);
237+ continue ;
366238 }
367- } else if (ast[0 ] == DEFUN) {
368- visit (ast);
239+ assert (back.index == back.children .size ());
240+ // Time to visit the node itself
241+ auto node = back.node ;
242+ stack.pop_back ();
243+ visit (node);
369244 }
370245}
371246
0 commit comments