JSDOC/Scope.js
[gnome.introspection-doc-generator] / JSDOC / Scope.js
1 //<Script type="text/javascript">
2
3 /**
4 * Scope stuff
5
6 * // FIXME - I need this to do next() without doccomments..
7 */
8
9 const Identifier = imports.Identifier.Identifier
10 const XObject = imports.XObject.XObject; 
11
12 Scope.id = 1;
13
14 function Scope(braceN, parent, startTokN, lastIdent, token)
15 {
16     if (lastIdent.length) {
17        //  println("NEW SCOPE: " + lastIdent);
18     }
19     
20     this.braceN = braceN
21     this.parent = parent;
22     this.id = Scope.id++;
23     this.identifiers = { };
24     this.subScopes = [];
25     this.hints = { };
26     this.ident = lastIdent;
27     this.gid = Scope.gid++;
28     this.token = token;
29     //print("ADD SCOPE(" + this.gid + ") TO "+ (parent ? this.parent.gid : 'TOP') + ' : ' + 
30     //    (token ? token.toString() : ''));
31     
32     if (parent) {
33         this.parent.subScopes.push(this);
34     } 
35     
36 }
37
38
39
40
41
42
43
44 Scope.prototype = {
45     
46     id : 0,
47     braceN : -1,
48     parent : false,
49     subScopes : false,
50     identifiers : false,  // map of identifiers to {Identifier} objects
51     hints: false, 
52     mungeM : true, 
53     ident: '',
54     
55     munged : false,
56     protectedVars : {}, // only used by to parent..
57     
58     /**
59      * dump the scope to StdOut...
60      * 
61      */
62     dump : function(indent) 
63     {
64         indent = indent || '';
65         var str = '';
66         for (var k in this.identifiers) {
67             str += str.length ? ", " : "";
68             str += k + '=>' + this.identifiers[k].mungedValue;
69         }
70         
71         print(
72             indent + "Scope: " + this.id + "\n" +
73             
74             indent + "Started: " + ( this.token ? this.token.toString(): 'TOP' ) + "\n" +
75             indent + "- " + str + "\n"
76         );
77         this.subScopes.forEach(function(s) {
78             s.dump(indent + ' ');
79         });
80         
81         
82     },
83     
84     
85     declareIdentifier : function(symbol, token) 
86     {
87         
88         //print("SCOPE : " + this.gid +  " :SYM: " + symbol + " " + token.toString()+"");
89         
90         if (typeof(this.identifiers[symbol])== 'undefined') {
91             
92             this.identifiers[symbol] =  new Identifier(symbol, this);
93             
94         }
95         if (typeof(token) != 'undefined') { // shoudl this happen?
96             token.identifier = this.identifiers[symbol];
97             
98         }
99         if (this.braceN < 0) {
100                 // then it's global... 
101                 this.identifiers[symbol].toMunge  = false;
102         }
103          
104         
105         this.addToParentScope(symbol);
106         return this.identifiers[symbol];
107     },
108     getIdentifier : function(symbol, token) {
109         if (typeof(this.identifiers[symbol])== 'undefined') {
110             if (['String', 'Date'].indexOf(symbol)> -1) {
111                 return false;
112             }
113             
114             //print("SCOPE : " + this.gid +" = SYMBOL NOT FOUND?" + token.toString());
115             return false;
116         }
117          //print("SCOPE : " + this.gid +" = FOUND:" + token.toString());
118         return this.identifiers[symbol];
119     },
120     
121     addHint : function(varName, varType) {
122         this.hint[varName] = varType;
123     },
124     preventMunging : function() {
125         this.mungeM = false;
126     },
127
128     usedsymcache : false,
129     
130     getUsedSymbols : function() {
131         
132         var result = [];
133        // if (this.usedsymcache !== false) {
134         //    return this.usedsymcache;
135         //}
136         
137         var idents = this.identifiers;
138         for(var i in idents) { 
139             //println('<b>'+i+'</b>='+typeof(idents[i]) +'<br/>');
140             var identifier = this.identifiers[i];
141             var mungedValue = identifier.mungedValue
142             if (!mungedValue.length) {
143                 //println(identifier.toSource());
144                 mungedValue = identifier.name;
145             }
146             result.push(mungedValue);
147         }
148         //println("Symbols for ("+ this.id +"): <B>" + result.join(',') + "</B><BR/>");
149         //this.usedsymcache = result;
150         return result;
151     },
152
153     getAllUsedSymbols :function() {
154         var result = this.getUsedSymbols();
155         var scope = this.parent;
156         while (scope !== false) {
157             //println("addused:"+scope.id);
158             result = result.concat(scope.getUsedSymbols());
159             scope = scope.parent;
160         }
161          //println("Done - addused");
162         return result;
163     },
164     /** - we need to register short vairalbes so they never get munged into.. */
165     addToParentScope: function(ident) 
166     {
167         if (ident.length > 2) {
168             return;
169         }
170         var scope = this.parent;
171         while (scope !== false) {
172             //println("addused:"+scope.id);
173             if (!scope.parent) {
174                 scope.protectedVars[ident] = true;
175             }
176             scope = scope.parent;
177         }
178         
179     },
180     isProtectedVar: function(ident)
181     {
182         if (ident.length > 2) {
183             return false;
184         }
185         var scope = this.parent;
186         while (scope !== false) {
187             //println("addused:"+scope.id);
188             if (!scope.parent) {
189                 if (typeof(scope.protectedVars[ident])  != 'undefined') return true;
190             }
191             scope = scope.parent;
192         }
193         return false;
194     },
195     
196     /**
197      * set's all the munged values on the identifiers.
198      * 
199      * 
200      */
201
202     munge :function() 
203     {
204
205         if (!this.mungeM) {
206             // Stop right here if this scope was flagged as unsafe for munging.
207            // println("MUNGE: SKIP -  Scope" + this.id+"</BR>");
208             return;
209         }
210         if (this.munged) {
211             return;
212         }
213         
214
215         
216         
217         var pickFromSet = 1;
218
219         // Do not munge symbols in the global scope!
220         if (this.parent) {
221             
222             var all = [];
223             for (var ii in this.identifiers) {
224                 all.push(ii);
225             }
226             //print("MUNGE: " + all.join(', '));
227             
228             //println("MUNGE: Building FreeSyms:" + this.id+"</BR>");
229             
230             var freeSymbols = [];
231             var sy = this.getAllUsedSymbols();
232             
233             var addSyms=function(batch)
234             {
235                 for(var i =0;i<batch.length;i++) {
236                     if (sy.indexOf(batch[i]) > -1) {
237                         continue;
238                     }
239                     freeSymbols.push(batch[i]);
240                 }
241             }
242              
243             addSyms(Scope.ones); 
244              
245             var repsym = '';
246             //println(freeSymbols.toSource());
247             
248             //println("MUNGE: Replacing " + this.id+"</BR>");
249             for (var i in  this.identifiers) {
250                 
251                 // is the identifer in the global scope!?!!?
252                 
253                 
254                 if (!this.identifiers[i].toMunge) {
255                     //print("SKIP toMunge==false : " + i)
256                     continue;
257                 }
258                 
259                 if (this.isProtectedVar(i)) {
260                     //print("SKIP PROTECTED: " + i)
261                     continue; // 
262                 }
263                 
264                 
265                 
266                 //if (this.identifiers[i].constructor !=  Identifier) {
267                 //    print("SKIP NOT IDENTIFIER : " + i)
268                 //    continue;
269                // }
270                // println("IDENT:" +i+'</BR>');
271                 
272                 if (!repsym.length) {
273                     if (!freeSymbols.length) {
274                         addSyms(Scope.twos); 
275                     }
276                     repsym = freeSymbols.shift(); // pop off beginngin???
277                 }
278                 
279                 var identifier = this.identifiers[i]; 
280                 //println(typeof(identifier.name));
281                 var mungedValue = identifier.name; 
282                 
283                 //println([     repsym,mungedValue ]);
284                 
285                 if (this.mungeM && repsym.length < mungedValue.length) {
286                     //print("REPLACE:"+ mungedValue +" with " + repsym );    
287                     mungedValue = repsym;
288                     repsym = '';
289                 }
290                 
291                 identifier.mungedValue =  mungedValue;
292             }
293             //println("MUNGE: Done " + this.id+"</BR>");
294         }
295         this.munged = true;
296         //println("Doing sub scopes");
297         for (var j = 0; j < this.subScopes.length; j++) {
298             var ss = this.subScopes[j];
299             ss.munge();
300         }
301     }
302  
303
304 };
305
306
307
308
309
310 XObject.extend(Scope, {
311     
312     builtin : ["NaN","top"],
313     skips : [  'as', 'is', 'do', 'if', 'in', 'for', 'int', 'new', 'try', 'use', 'var', "NaN","top"],
314      
315     ones : [],
316     twos : [],
317     threes : [],
318     init : function () {
319         /* cache it later?
320         if (File.exists('/tmp/var_list_ones.js')) {
321             eval("JSDOC.Scope.ones = " + File.read('/tmp/var_list_ones.js'));
322             eval("JSDOC.Scope.twos = " + File.read('/tmp/var_twos_ones.js'));
323             eval("JSDOC.Scope.threes = " + File.read('/tmp/var_threes_ones.js'));
324         }
325         */
326         this.ones = 'A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z'.split(',');
327         var a = this.ones;
328         var n = a.concat( '0,1,2,3,4,5,6,7,8,9'.split(','));
329         for(var i = 0; i < a.length; i++) {
330             for(var j = 0; j < n.length; j++) {
331                 var tw = a[i] + n[j];
332                 if (this.skips.indexOf(tw) < 0) {
333                     this.twos.push(tw);
334                 }
335                     
336                 /*
337                 for(var k = 0; k < n.length; k++) {
338                     var thr = a[i] + n[j] + n[k];
339                     //println("thr="+ thr + ":iOf="+this.skips.indexOf(thr) );
340                     if (this.skips.indexOf(thr)  < 0) {
341                         //println("+"+thr);
342                         this.threes.push(thr);
343                        }
344                     
345                 }
346                 */
347             }
348         }
349         //println("done creating var list");
350         //println("threes="+ this.threes.toSource());
351         //throw "DONE";
352         
353        
354     }
355 })
356 // init the scope constants..
357 Scope.init();
358 Scope.gid = 0;