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 = 0;
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         print(
66             indent + "Scope: " + this.id + "\n" +
67             indent + "Started: " + ( this.token ? this.token.line  : 'TOP' ) + "\n" +
68             indent + "- " + XObject.keys(this.identifiers).join(", ") + "\n"
69         );
70         this.subScopes.forEach(function(s) {
71             s.dump(indent + ' ');
72         });
73         
74         
75     },
76     
77     
78     declareIdentifier : function(symbol, token) 
79     {
80         
81         //print("SCOPE : " + this.gid +  " :SYM: " + symbol + " " + token.toString()+"");
82         
83         if (typeof(this.identifiers[symbol])== 'undefined') {
84             
85             this.identifiers[symbol] =  new Identifier(symbol, this);
86             
87         }
88         if (typeof(token) != 'undefined') { // shoudl this happen?
89             token.identifier = this.identifiers[symbol];
90             
91         }
92         if (this.braceN < 0) {
93                 // then it's global... 
94                 this.identifiers[symbol].toMunge  = false;
95         }
96          
97         
98         this.addToParentScope(symbol);
99         return this.identifiers[symbol];
100     },
101     getIdentifier : function(symbol, token) {
102         if (typeof(this.identifiers[symbol])== 'undefined') {
103             if (['String', 'Date'].indexOf(symbol)> -1) {
104                 return false;
105             }
106             
107             //print("SCOPE : " + this.gid +" = SYMBOL NOT FOUND?" + token.toString());
108             return false;
109         }
110          //print("SCOPE : " + this.gid +" = FOUND:" + token.toString());
111         return this.identifiers[symbol];
112     },
113     
114     addHint : function(varName, varType) {
115         this.hint[varName] = varType;
116     },
117     preventMunging : function() {
118         this.mungeM = false;
119     },
120
121     usedsymcache : false,
122     
123     getUsedSymbols : function() {
124         
125         var result = [];
126        // if (this.usedsymcache !== false) {
127         //    return this.usedsymcache;
128         //}
129         
130         var idents = this.identifiers;
131         for(var i in idents) { 
132             //println('<b>'+i+'</b>='+typeof(idents[i]) +'<br/>');
133             var identifier = this.identifiers[i];
134             var mungedValue = identifier.mungedValue
135             if (!mungedValue.length) {
136                 //println(identifier.toSource());
137                 mungedValue = identifier.name;
138             }
139             result.push(mungedValue);
140         }
141         //println("Symbols for ("+ this.id +"): <B>" + result.join(',') + "</B><BR/>");
142         //this.usedsymcache = result;
143         return result;
144     },
145
146     getAllUsedSymbols :function() {
147         var result = this.getUsedSymbols();
148         var scope = this.parent;
149         while (scope !== false) {
150             //println("addused:"+scope.id);
151             result = result.concat(scope.getUsedSymbols());
152             scope = scope.parent;
153         }
154          //println("Done - addused");
155         return result;
156     },
157     /** - we need to register short vairalbes so they never get munged into.. */
158     addToParentScope: function(ident) 
159     {
160         if (ident.length > 2) {
161             return;
162         }
163         var scope = this.parent;
164         while (scope !== false) {
165             //println("addused:"+scope.id);
166             if (!scope.parent) {
167                 scope.protectedVars[ident] = true;
168             }
169             scope = scope.parent;
170         }
171         
172     },
173     isProtectedVar: function(ident)
174     {
175         if (ident.length > 2) {
176             return false;
177         }
178         var scope = this.parent;
179         while (scope !== false) {
180             //println("addused:"+scope.id);
181             if (!scope.parent) {
182                 if (typeof(scope.protectedVars[ident])  != 'undefined') return true;
183             }
184             scope = scope.parent;
185         }
186         return false;
187     },
188     
189     /**
190      * set's all the munged values on the identifiers.
191      * 
192      * 
193      */
194
195     munge :function() 
196     {
197
198         if (!this.mungeM) {
199             // Stop right here if this scope was flagged as unsafe for munging.
200            // println("MUNGE: SKIP -  Scope" + this.id+"</BR>");
201             return;
202         }
203         if (this.munged) {
204             return;
205         }
206         
207
208         
209         
210         var pickFromSet = 1;
211
212         // Do not munge symbols in the global scope!
213         if (this.parent) {
214             
215             var all = [];
216             for (var ii in this.identifiers) {
217                 all.push(ii);
218             }
219             //print("MUNGE: " + all.join(', '));
220             
221             //println("MUNGE: Building FreeSyms:" + this.id+"</BR>");
222             
223             var freeSymbols = [];
224             var sy = this.getAllUsedSymbols();
225             
226             var addSyms=function(batch)
227             {
228                 for(var i =0;i<batch.length;i++) {
229                     if (sy.indexOf(batch[i]) > -1) {
230                         continue;
231                     }
232                     freeSymbols.push(batch[i]);
233                 }
234             }
235              
236             addSyms(Scope.ones); 
237              
238             var repsym = '';
239             //println(freeSymbols.toSource());
240             
241             //println("MUNGE: Replacing " + this.id+"</BR>");
242             for (var i in  this.identifiers) {
243                 
244                 // is the identifer in the global scope!?!!?
245                 
246                 
247                 if (!this.identifiers[i].toMunge) {
248                     //print("SKIP toMunge==false : " + i)
249                     continue;
250                 }
251                 
252                 if (this.isProtectedVar(i)) {
253                     //print("SKIP PROTECTED: " + i)
254                     continue; // 
255                 }
256                 
257                 
258                 
259                 //if (this.identifiers[i].constructor !=  Identifier) {
260                 //    print("SKIP NOT IDENTIFIER : " + i)
261                 //    continue;
262                // }
263                // println("IDENT:" +i+'</BR>');
264                 
265                 if (!repsym.length) {
266                     if (!freeSymbols.length) {
267                         addSyms(Scope.twos); 
268                     }
269                     repsym = freeSymbols.shift(); // pop off beginngin???
270                 }
271                 
272                 var identifier = this.identifiers[i]; 
273                 //println(typeof(identifier.name));
274                 var mungedValue = identifier.name; 
275                 
276                 //println([     repsym,mungedValue ]);
277                 
278                 if (this.mungeM && repsym.length < mungedValue.length) {
279                     //print("REPLACE:"+ mungedValue +" with " + repsym );    
280                     mungedValue = repsym;
281                     repsym = '';
282                 }
283                 
284                 identifier.mungedValue =  mungedValue;
285             }
286             //println("MUNGE: Done " + this.id+"</BR>");
287         }
288         this.munged = true;
289         //println("Doing sub scopes");
290         for (var j = 0; j < this.subScopes.length; j++) {
291             var ss = this.subScopes[j];
292             ss.munge();
293         }
294     }
295  
296
297 };
298
299
300
301
302
303 XObject.extend(Scope, {
304     
305     builtin : ["NaN","top"],
306     skips : [  'as', 'is', 'do', 'if', 'in', 'for', 'int', 'new', 'try', 'use', 'var', "NaN","top"],
307      
308     ones : [],
309     twos : [],
310     threes : [],
311     init : function () {
312         /* cache it later?
313         if (File.exists('/tmp/var_list_ones.js')) {
314             eval("JSDOC.Scope.ones = " + File.read('/tmp/var_list_ones.js'));
315             eval("JSDOC.Scope.twos = " + File.read('/tmp/var_twos_ones.js'));
316             eval("JSDOC.Scope.threes = " + File.read('/tmp/var_threes_ones.js'));
317         }
318         */
319         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(',');
320         var a = this.ones;
321         var n = a.concat( '0,1,2,3,4,5,6,7,8,9'.split(','));
322         for(var i = 0; i < a.length; i++) {
323             for(var j = 0; j < n.length; j++) {
324                 var tw = a[i] + n[j];
325                 if (this.skips.indexOf(tw) < 0) {
326                     this.twos.push(tw);
327                 }
328                     
329                 /*
330                 for(var k = 0; k < n.length; k++) {
331                     var thr = a[i] + n[j] + n[k];
332                     //println("thr="+ thr + ":iOf="+this.skips.indexOf(thr) );
333                     if (this.skips.indexOf(thr)  < 0) {
334                         //println("+"+thr);
335                         this.threes.push(thr);
336                        }
337                     
338                 }
339                 */
340             }
341         }
342         //println("done creating var list");
343         //println("threes="+ this.threes.toSource());
344         //throw "DONE";
345         
346        
347     }
348 })
349 // init the scope constants..
350 Scope.init();
351 Scope.gid = 0;