1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
define.class("$system/parse/onejswalk", function(baseclass, require) {

        var jsformatter = require('$system/parse/jsformatter');

        this.toSource = function(ast) {
                if (!ast) {
                        ast = this.at;
                }

                var buf = {
                        out:'',
                        charCodeAt: function(i){return this.out.charCodeAt(i)},
                        char_count:0
                };

                jsformatter.walk(ast, buf, {}, function(str){

                        if(str === '\n'){
                                this.last_is_newline = true;
                                return
                        }
                        if(str === '\t' && this.last_is_newline){
                                str = '\n';
                                for (var i = 0; i < this.actual_indent;i++) {
                                        str += '  '
                                }
                        }
                        this.last_is_newline = false;

                        buf.char_count += str.length;
                        buf.out += str
                });

                return buf.out;
        };

        this.atConstructor = function(rootnode, astpath) {
                this._root = rootnode;
                if (astpath && !Array.isArray(astpath)) {
                        astpath = [astpath];
                }
                this._stages = astpath;
                this.reset();
                if (this._stages) {
                        this.scan()
                }
        };

        this.reset = function() {
                this._unstage();
                this.atparent = undefined;
                this.atindex = undefined;
                this.atstate = undefined;
                this.at = this._root;
                return this;
        };

        this.scan = function(newstages) {
                if (newstages) {
                        this._unstage();
                        this._stages = newstages;
                }

                while (this._prepare()) {
                        this.walk(this.at);
                }
                return this;
        };

        this._unstage = function() {
                if (this._stage) {
                        var type = this._stage.type;
                        this._stage = undefined;
                        if (type) {
//                                delete this[type];
                                this[type] = baseclass[type];
                        }
                }
        };

        this._match = function(stage, node, parent) {
                var match = !!(node);

                if (match) {
                        for (var prop in stage) {
                                if (stage.hasOwnProperty(prop) && prop[0] != '_') {
                                        var val = stage[prop];
                                        var nodeval = node[prop];
                                        if (val) {
                                                if (typeof(val) === "object") {
                                                        match = match && this._match(val, nodeval)
                                                } else {
                                                        match = match && nodeval === val
                                                }
                                        } else {
                                                // we just ignore empty keys in search term for now since onejsgen will create them regardless
                                        }
                                }
                                if (!match) {
                                        break;
                                }
                        }
                }

                return match;
        };

        this._prepare = function() {
                this._unstage();
                if (this._stages) {
                        this._stage = this._stages.shift();
                        if (this._stage) {
                                this[this._stage.type] = function(node, parent, state, index) {
                                        var stageindex = this._stage._index;
                                        if ((stageindex >= 0 && stageindex !== index) || !this._match(this._stage, node, parent)) {
                                                baseclass[node.type].call(this, node, parent, state, index)
                                        } else {
                                                this.atparent = parent;
                                                this.atindex = index;
                                                this.atstate = state;
                                                this.at = node;
                                                this.scan();
                                        }

                                }.bind(this);
                        }
                }

                return !!(this._stage);
        };

        //for (var prop in this) {
        //        if (/^[A-Z]/.test(prop)) {
        //                console.log('pp', prop)
        //                this[prop] = function(node, parent, state) {
        //          console.log('Found', node.type)
        //                        baseclass[node.type].call(this, node, parent, state)
        //                }.bind(this)
        //        }
        //}

});