namespace JSDOC { public int Scope_gid = 0; public class Scope : Object { int id ; int braceN ; public Scope parent; public Gee.ArrayList subScopes; Gee.HashMap identifiers; // map of identifiers to {Identifier} objects Gee.HashMap hints; bool mungeM = true; //ident: '', bool munged = false; Gee.HashMap protectedVars ; // only used by to parent.. Token? token; public Scope(int braceN, Scope? parent, int startTokN, Token? token) // Identifier? lastIdent { //if (lastIdent.length) { // println("NEW SCOPE: " + lastIdent); //} this.braceN = braceN; this.parent = parent; this.id = startTokN; this.identifiers = new Gee.HashMap(); this.subScopes = new Gee.ArrayList (); this.hints = new Gee.HashMap(); this.protectedVars = new Gee.HashMap(); //this.ident = lastIdent; this.id = Scope_gid++; this.token = token; //print("ADD SCOPE(" + this.gid + ") TO "+ (parent ? this.parent.gid : 'TOP') + ' : ' + // (token ? token.toString() : '')); if (parent != null) { this.parent.subScopes.add(this); } Scope.init(); } /** * dump the scope to StdOut... * */ void dump (string indent) { //indent = indent || ''; print( indent + "Scope: %d\n" + indent + "Started: %d\n" + indent + "- idents..: fixme\n" , this.id, this.token != null ? this.token.line : -1 // " + XObject.keys(this.identifiers).join(", ") + " ); foreach(var s in this.subScopes) { s.dump(indent + " "); }; } public Identifier declareIdentifier(string symbol, Token token) { //print("SCOPE : " + this.gid + " :SYM: " + symbol + " " + token.toString()+""); if (!this.identifiers.has_key(symbol)) { this.identifiers.set(symbol, new Identifier(symbol, this)); } //if (typeof(token) != 'undefined') { // shoudl this happen? token.identifier = this.identifiers.get(symbol); //} if (this.braceN < 0) { // then it's global... this.identifiers[symbol].toMunge = false; } this.addToParentScope(symbol); return this.identifiers.get(symbol); } public Identifier? getIdentifier(string symbol, Token token) { if (!this.identifiers.has_key(symbol)) { return null; //if (['String', 'Date'].indexOf(symbol)> -1) { // return false; //} //print("SCOPE : " + this.gid +" = SYMBOL NOT FOUND?" + token.toString()); //return n; } //print("SCOPE : " + this.gid +" = FOUND:" + token.toString()); return this.identifiers.get(symbol); } public void addHint(string varName, string varType) { this.hints.set(varName, varType); } public void preventMunging () { this.mungeM = false; } //usedsymcache : false, public string[] getUsedSymbols () { string[] result = {}; // if (this.usedsymcache !== false) { // return this.usedsymcache; //} var idents = this.identifiers; var iter = idents.map_iterator(); while (iter.next()) { var i = iter.get_key(); //println(''+i+'='+typeof(idents[i]) +'
'); var identifier = this.identifiers.get(i); var mungedValue = identifier.mungedValue; if (mungedValue.length < 1) { //println(identifier.toSource()); mungedValue = identifier.name; } result += mungedValue; } //println("Symbols for ("+ this.id +"): " + result.join(',') + "
"); //this.usedsymcache = result; return result; } string[] getAllUsedSymbols() { var result = this.getUsedSymbols(); var scope = this.parent; while (scope != null) { var ps = scope.getUsedSymbols(); for (var i =0; i< ps.length; i++) { result += ps[i]; } scope = scope.parent; } //println("Done - addused"); return result; } /** - we need to register short vairalbes so they never get munged into.. */ public void addToParentScope(string ident) { if (ident.length > 2) { return; } var scope = this.parent; while (scope != null) { //println("addused:"+scope.id); if (scope.parent != null) { scope.protectedVars.set(ident, true); } scope = scope.parent; } } public bool isProtectedVar(string ident) { if (ident.length > 2) { return false; } var scope = this.parent; while (scope != null) { //println("addused:"+scope.id); if (scope.parent != null) { if (scope.protectedVars.has_key(ident)) { return true; } } scope = scope.parent; } return false; } /** * set's all the munged values on the identifiers. * * */ public void munge() { if (!this.mungeM) { // Stop right here if this scope was flagged as unsafe for munging. // println("MUNGE: SKIP - Scope" + this.id+"
"); return; } if (this.munged) { return; } var pickFromSet = 1; // Do not munge symbols in the global scope! if (this.parent == null) { // same code at bottom... ?? goto:: this.munged = true; //println("Doing sub scopes"); for (var j = 0; j < this.subScopes.size; j++) { this.subScopes.get(j).munge(); } return; } string[] all = {}; var iter = this.identifiers.map_iterator(); while (iter.next()) { all += iter.get_key(); } //print("MUNGE: " + all.join(', ')); //println("MUNGE: Building FreeSyms:" + this.id+"
"); Gee.ArrayList freeSymbols= new Gee.ArrayList(); var sy = this.getAllUsedSymbols(); Scope.array_merge(freeSymbols,Scope.ones); var repsym = ""; //println(freeSymbols.toSource()); //println("MUNGE: Replacing " + this.id+"
"); iter = this.identifiers.map_iterator(); while (iter.next()) { var i = iter.get_key(); // is the identifer in the global scope!?!!? if (!this.identifiers.get(i).toMunge) { //print("SKIP toMunge==false : " + i) continue; } if (this.isProtectedVar(i)) { //print("SKIP PROTECTED: " + i) continue; // } //if (this.identifiers[i].constructor != Identifier) { // print("SKIP NOT IDENTIFIER : " + i) // continue; // } // println("IDENT:" +i+'
'); if (repsym.length < 1) { if (freeSymbols.size < 1) { Scope.array_merge(freeSymbols,Scope.twos); } repsym = freeSymbols.remove_at(0); // pop off beginngin??? } var identifier = this.identifiers.get(i); //println(typeof(identifier.name)); var mungedValue = identifier.name; //println([ repsym,mungedValue ]); if (this.mungeM && repsym.length < mungedValue.length) { //print("REPLACE:"+ mungedValue +" with " + repsym ); mungedValue = repsym; repsym = ""; } identifier.mungedValue = mungedValue; } //println("MUNGE: Done " + this.id+"
"); this.munged = true; //println("Doing sub scopes"); for (var j = 0; j < this.subScopes.size; j++) { this.subScopes.get(j).munge(); } } // ---------------------- static part... -------------------- static void array_merge(Gee.ArrayList fs, string[] toadd) { foreach(var i in toadd) { fs.add(i); } } static bool initialized = false; public static Gee.ArrayList builtin; public static Gee.ArrayList skips; public static string[] ones; public static string[] twos; // static string[] threes : [], static void init () { if (Scope.initialized) { return; } Scope.initialized = true; Scope.builtin = new Gee.ArrayList(); array_merge(Scope.builtin, "NaN,top".split(",")); Scope.skips = new Gee.ArrayList(); array_merge(Scope.skips, "as,is,do,if,in,for,int,new,try,use,var,NaN,top".split(",")); Scope.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 n = "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,0,1,2,3,4,5,6,7,8,9".split(","); string[] twos = {}; for(var i = 0; i < Scope.ones.length; i++) { for(var j = 0; j < n.length; j++) { string tw = Scope.ones[i] + n[j]; if (Scope.skips.index_of(tw) < 0) { twos += 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); } } */ } } Scope.twos = twos; //println("done creating var list"); //println("threes="+ this.threes.toSource()); //throw "DONE"; } } }