JSDOC/Scope.js
authoralan <alan@alanfast.akbkhome.com>
Mon, 19 Apr 2010 03:45:22 +0000 (11:45 +0800)
committeralan <alan@alanfast.akbkhome.com>
Mon, 19 Apr 2010 03:45:22 +0000 (11:45 +0800)
JSDOC/Scope.js

index e69de29..49d6cbd 100644 (file)
@@ -0,0 +1,321 @@
+//<Script type="text/javascript">
+
+/**
+* Scope stuff
+* 
+* // FIXME - I need this to do next() without doccomments..
+*/
+
+Identifier = imports['JSDOC/Identifier.js'].Identifier
+XObject = imports.XObject.XObject; 
+
+
+function Scope(braceN, parent, startTokN, lastIdent)
+{
+    if (lastIdent.length) {
+       //  println("NEW SCOPE: " + lastIdent);
+    }
+    
+    this.braceN = braceN
+    this.parent = parent;
+    this.id = startTokN;
+    this.identifiers = { };
+    this.subScopes = [];
+    this.hints = { };
+    this.ident = lastIdent;
+    
+    
+    //println("ADD SCOPE(" + this.id + ") TO "+ (parent ? this.parent.id : 'TOP') + "<BR/>");
+    
+    if (parent) {
+        this.parent.subScopes.push(this);
+    } 
+    
+}
+
+
+
+
+
+
+
+Scope.prototype = {
+    
+    id : 0,
+    braceN : -1,
+    parent : false,
+    subScopes : false,
+    identifiers : false, 
+    hints: false, 
+    mungeM : true, 
+    ident: '',
+    
+    munged : false,
+    protectedVars : {}, // only used by to parent..
+    declareIdentifier : function(symbol, token) {
+        
+        //println("ADD IDENT(" + this.id + "):<B>" + symbol+"</B><BR/>");
+        
+        if (typeof(this.identifiers[symbol])== 'undefined') {
+            
+            this.identifiers[symbol] =  new Identifier(symbol, this);
+            
+        }
+        if (typeof(token) != 'undefined') { // shoudl this happen?
+            token.identifier = this.identifiers[symbol];
+            
+        }
+        if (this.braceN < 0) {
+                // then it's global... 
+                this.identifiers[symbol].toMunge  = false;
+        }
+        this.addToParentScope(symbol);
+        return this.identifiers[symbol];
+    },
+    getIdentifier : function(symbol) {
+        return (typeof(this.identifiers[symbol])== 'undefined') ? false : this.identifiers[symbol];
+    },
+    
+    addHint : function(varName, varType) {
+        this.hint[varName] = varType;
+    },
+    preventMunging : function() {
+        this.mungeM = false;
+    },
+
+    usedsymcache : false,
+    
+    getUsedSymbols : function() {
+        
+        var result = [];
+       // if (this.usedsymcache !== false) {
+        //    return this.usedsymcache;
+        //}
+        
+        var idents = this.identifiers;
+        for(var i in idents) { 
+            //println('<b>'+i+'</b>='+typeof(idents[i]) +'<br/>');
+            var identifier = this.identifiers[i];
+            var mungedValue = identifier.mungedValue
+            if (!mungedValue.length) {
+                //println(identifier.toSource());
+                mungedValue = identifier.name;
+            }
+            result.push(mungedValue);
+        }
+        //println("Symbols for ("+ this.id +"): <B>" + result.join(',') + "</B><BR/>");
+        //this.usedsymcache = result;
+        return result;
+    },
+
+    getAllUsedSymbols :function() {
+        var result = this.getUsedSymbols();
+        var scope = this.parent;
+        while (scope !== false) {
+            //println("addused:"+scope.id);
+            result = result.concat(scope.getUsedSymbols());
+            scope = scope.parent;
+        }
+         //println("Done - addused");
+        return result;
+    },
+    /** - we need to register short vairalbes so they never get munged into.. */
+    addToParentScope: function(ident) {
+        if (ident.length > 2) {
+            return;
+        }
+        var scope = this.parent;
+        while (scope !== false) {
+            //println("addused:"+scope.id);
+            if (!scope.parent) {
+                scope.protectedVars[ident] = true;
+            }
+            scope = scope.parent;
+        }
+        
+    },
+    isProtectedVar: function(ident) {
+        if (ident.length > 2) {
+            return false;
+        }
+        var scope = this.parent;
+        while (scope !== false) {
+            //println("addused:"+scope.id);
+            if (!scope.parent) {
+                if (typeof(scope.protectedVars[ident])  != 'undefined') return true;
+            }
+            scope = scope.parent;
+        }
+        return false;
+    },
+    
+    
+
+    munge :function() {
+
+        if (!this.mungeM) {
+            // Stop right here if this scope was flagged as unsafe for munging.
+           // println("MUNGE: SKIP -  Scope" + this.id+"</BR>");
+            return;
+        }
+        if (this.munged) {
+            return;
+        }
+        
+
+        //println("MUNGE: Scope:" + this.id+"</BR>");
+        
+        var pickFromSet = 1;
+
+        // Do not munge symbols in the global scope!
+        if (this.parent) {
+
+            
+            //println("MUNGE: Building FreeSyms:" + this.id+"</BR>");
+            
+            var freeSymbols = [];
+            var sy = this.getAllUsedSymbols();
+            
+            var addSyms=function(batch)
+            {
+                for(var i =0;i<batch.length;i++) {
+                    if (sy.indexOf(batch[i]) > -1) {
+                        continue;
+                    }
+                    freeSymbols.push(batch[i]);
+                }
+            }
+            /*
+            var exsymbols  = function(n) {
+                if (sy.indexOf(n) > -1) {
+                    return;
+                }
+                freeSymbols.push(n);
+            }
+            */
+            addSyms(JSDOC.Scope.ones); 
+            
+            //if (freeSymbols.length == 0) {
+            //    pickFromSet = 2;
+               // JSDOC.Scope.twos.filter(exsymbols);
+                
+            //}
+            //if (freeSymbols.length == 0) {
+            //    pickFromSet = 3;
+            //    throw "disabled  threes!"
+            //    JSDOC.Scope.threes.filter(exsymbols);
+            //    
+            //}
+            //if (freeSymbols.length == 0) {
+            //    throw  "The Compressor ran out of symbols. Aborting...???? ";
+           // }
+            var repsym = '';
+            //println(freeSymbols.toSource());
+            
+            //println("MUNGE: Replacing " + this.id+"</BR>");
+            for (var i in  this.identifiers) {
+                
+                // is the identifer in the global scope!?!!?
+                
+                
+                if (!this.identifiers[i].toMunge) {
+                    continue;
+                }
+                
+                if (this.isProtectedVar(i)) {
+                    continue; // 
+                }
+                
+                
+                
+                if (this.identifiers[i].constructor != JSDOC.Identifier) {
+                    continue;
+                }
+               // println("IDENT:" +i+'</BR>');
+                
+                if (!repsym.length) {
+                    if (!freeSymbols.length) {
+                        addSyms(JSDOC.Scope.twos); 
+                    }
+                    repsym = freeSymbols.shift(); // pop off beginngin???
+                }
+                
+                var identifier = this.identifiers[i]; 
+                //println(typeof(identifier.name));
+                var mungedValue = identifier.name; 
+                
+                //println([     repsym,mungedValue ]);
+                
+                if (this.mungeM && repsym.length < mungedValue.length) {
+                    //println("REPLACE:"+ mungedValue +" with " + repsym + "<BR>");
+                    mungedValue = repsym;
+                    repsym = '';
+                }
+                identifier.mungedValue =  mungedValue;
+            }
+            //println("MUNGE: Done " + this.id+"</BR>");
+        }
+        this.munged = true;
+        //println("Doing sub scopes");
+        for (var i = 0; i < this.subScopes.length; i++) {
+            var ss = this.subScopes[i];
+            ss.munge();
+        }
+    }
+
+});
+
+
+
+
+
+XObject.extend(Scope, {
+    
+    builtin : ["NaN","top"],
+    skips : [  'as', 'is', 'do', 'if', 'in', 'for', 'int', 'new', 'try', 'use', 'var', "NaN","top"],
+     
+    ones : [],
+    twos : [],
+    threes : [],
+    init : function () {
+        /* cache it later?
+        if (File.exists('/tmp/var_list_ones.js')) {
+            eval("JSDOC.Scope.ones = " + File.read('/tmp/var_list_ones.js'));
+            eval("JSDOC.Scope.twos = " + File.read('/tmp/var_twos_ones.js'));
+            eval("JSDOC.Scope.threes = " + File.read('/tmp/var_threes_ones.js'));
+        }
+        */
+        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(',');
+        var a = this.ones;
+        var n = a.concat( '0,1,2,3,4,5,6,7,8,9'.split(','));
+        for(var i = 0; i < a.length; i++) {
+            for(var j = 0; j < n.length; j++) {
+                var tw = a[i] + n[j];
+                if (this.skips.indexOf(tw) < 0) {
+                    this.twos.push(tw);
+                }
+                    
+                /*
+                for(var k = 0; k < n.length; k++) {
+                    var thr = a[i] + n[j] + n[k];
+                    //println("thr="+ thr + ":iOf="+this.skips.indexOf(thr) );
+                    if (this.skips.indexOf(thr)  < 0) {
+                        //println("+"+thr);
+                        this.threes.push(thr);
+                       }
+                    
+                }
+                */
+            }
+        }
+        //println("done creating var list");
+        //println("threes="+ this.threes.toSource());
+        //throw "DONE";
+        
+       
+    }
+})
+// init the scope constants..
+Scope.init();
\ No newline at end of file