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