5 public int Scope_gid = 0;
7 public class Scope : Object
13 public Gee.ArrayList<Scope> subScopes;
14 public string ident = ""; // used by the walker...
16 Gee.HashMap<string,Identifier> identifier_map; // map of identifiers to {Identifier} objects
17 Gee.ArrayList<Identifier> identifier_list;
19 Gee.HashMap<string,string> hints;
24 Gee.HashMap<string,bool> protectedVars ; // only used by to parent..
26 // lastIdent is only used on the documentation parser..
27 public Scope(int braceN, Scope? parent, int startTokN, string lastIdent, Token? token) // Identifier? lastIdent
29 if (lastIdent.length> 0 ) {
30 GLib.debug("NEW SCOPE: %s", lastIdent);
36 this.identifier_map = new Gee.HashMap<string,Identifier>();
37 this.identifier_list = new Gee.ArrayList<Identifier>();
38 this.subScopes = new Gee.ArrayList<Scope> ();
39 this.hints = new Gee.HashMap<string,string>();
40 this.protectedVars = new Gee.HashMap<string,bool>();
41 this.ident = lastIdent;
42 this.id = Scope_gid++;
44 //print("ADD SCOPE(" + this.gid + ") TO "+ (parent ? this.parent.gid : 'TOP') + ' : ' +
45 // (token ? token.toString() : ''));
48 this.parent.subScopes.add(this);
62 * dump the scope to StdOut...
65 public void dump (string indent = "")
67 //indent = indent || '';
70 var idents = this.identifier_list;
71 var iter = idents.list_iterator();
73 var identifier = iter.get();
74 str += (str.length > 0 ? ", " : "");
75 str += indent + " " + identifier.name + "=>" + identifier.mungedValue ;
79 indent + "Scope: %d\n" +
80 indent + "Started: %s\n" +
81 indent + "- idents..: %s\n",
84 this.token != null ? this.token.asString() : "TOP",
86 // " + XObject.keys(this.identifiers).join(", ") + "
88 foreach(var s in this.subScopes) {
96 public Identifier declareIdentifier(string symbol, Token token)
99 //print("SCOPE : " + this.gid + " :SYM: " + symbol + " " + token.toString()+"");
101 if (!this.identifier_map.has_key(symbol)) {
102 var nid = new Identifier(symbol, this);
103 this.identifier_list.add(nid);
104 this.identifier_map.set(symbol, nid);
108 //if (typeof(token) != 'undefined') { // shoudl this happen?
109 token.identifier = this.identifier_map.get(symbol);
112 if (this.braceN < 0) {
113 // then it's global...
114 this.identifier_map.get(symbol).toMunge = false;
118 this.addToParentScope(symbol);
119 return this.identifier_map.get(symbol);
124 public Identifier? getIdentifier(string symbol, Token token)
126 if (!this.identifier_map.has_key(symbol)) {
128 //if (['String', 'Date'].indexOf(symbol)> -1) {
132 //print("SCOPE : " + this.gid +" = SYMBOL NOT FOUND?" + token.toString());
135 //print("SCOPE : " + this.gid +" = FOUND:" + token.toString());
136 return this.identifier_map.get(symbol);
139 public void addHint(string varName, string varType) {
141 this.hints.set(varName, varType);
143 public void preventMunging () {
147 //usedsymcache : false,
149 public string[] getUsedSymbols () {
151 string[] result = {};
153 // if (this.usedsymcache !== false) {
154 // return this.usedsymcache;
157 var idents = this.identifier_list;
158 var iter = idents.list_iterator();
159 while (iter.next()) {
160 var identifier = iter.get();
161 //println('<b>'+i+'</b>='+typeof(idents[i]) +'<br/>');
162 //var identifier = this.identifier_map.get(i);
163 var mungedValue = identifier.mungedValue;
165 if (mungedValue.length < 1) {
166 //println(identifier.toSource());
167 mungedValue = identifier.name;
169 result += mungedValue;
171 //println("Symbols for ("+ this.id +"): <B>" + result.join(',') + "</B><BR/>");
172 //this.usedsymcache = result;
176 string[] getAllUsedSymbols()
178 var result = this.getUsedSymbols();
179 var scope = this.parent;
180 while (scope != null) {
181 var ps = scope.getUsedSymbols();
182 for (var i =0; i< ps.length; i++) {
185 scope = scope.parent;
187 //println("Done - addused");
190 /** - we need to register short vairalbes so they never get munged into.. */
191 public void addToParentScope(string ident)
193 if (ident.length > 2) {
196 var scope = this.parent;
197 while (scope != null) {
198 //println("addused:"+scope.id);
199 if (scope.parent != null) {
200 scope.protectedVars.set(ident, true);
202 scope = scope.parent;
206 public bool isProtectedVar(string ident)
208 //if (ident == "_this") { // not sure why we need to protect _this. as it should be calculated as protected..
212 if (ident.length > 2) {
215 var scope = this.parent;
216 while (scope != null) {
217 //println("addused:"+scope.id);
218 if (scope.parent != null) {
219 if (scope.protectedVars.has_key(ident)) {
223 scope = scope.parent;
232 * set's all the munged values on the identifiers.
241 // Stop right here if this scope was flagged as unsafe for munging.
242 // println("MUNGE: SKIP - Scope" + this.id+"</BR>");
254 // Do not munge symbols in the global scope!
255 if (this.parent == null) {
256 // same code at bottom... ?? goto::
258 //println("Doing sub scopes");
259 for (var j = 0; j < this.subScopes.size; j++) {
260 this.subScopes.get(j).munge();
268 var iter = this.identifier_list.list_iterator();
269 while (iter.next()) {
270 all += iter.get().name;
272 //print("MUNGE: %s\n", string.joinv(",", all));
274 //println("MUNGE: Building FreeSyms:" + this.id+"</BR>");
276 Gee.ArrayList<string> freeSymbols= new Gee.ArrayList<string>();
278 var sy = this.getAllUsedSymbols();
280 // we need to remove the used from the free.....
287 Scope.array_merge(freeSymbols,Scope.ones,sy);
290 //println(freeSymbols.toSource());
292 //println("MUNGE: Replacing " + this.id+"</BR>");
293 iter = this.identifier_list.list_iterator();
294 while (iter.next()) {
295 var i = iter.get().name;
297 // is the identifer in the global scope!?!!?
300 if (!this.identifier_map.get(i).toMunge) {
301 //print("SKIP toMunge==false : " + i)
305 if (this.isProtectedVar(i)) {
306 //print("SKIP PROTECTED: " + i)
312 //if (this.identifiers[i].constructor != Identifier) {
313 // print("SKIP NOT IDENTIFIER : " + i)
316 // println("IDENT:" +i+'</BR>');
318 if (repsym.length < 1) {
319 if (freeSymbols.size < 1) {
320 Scope.array_merge(freeSymbols,Scope.twos,sy);
322 repsym = freeSymbols.remove_at(0); // pop off beginngin???
325 var identifier = this.identifier_map.get(i);
326 //println(typeof(identifier.name));
327 var mungedValue = identifier.name;
329 if (mungedValue.length < 3) { // don't bother replacing 1&2 character variables..
333 //println([ repsym,mungedValue ]);
335 if (this.mungeM && repsym.length < mungedValue.length) {
336 //print("REPLACE:"+ mungedValue +" with " + repsym );
337 mungedValue = repsym;
341 identifier.mungedValue = mungedValue;
343 //println("MUNGE: Done " + this.id+"</BR>");
346 //println("Doing sub scopes");
347 for (var j = 0; j < this.subScopes.size; j++) {
348 this.subScopes.get(j).munge();
354 // ---------------------- static part... --------------------
358 static void array_merge(Gee.ArrayList<string> fs, string[] toadd, string[] ignore)
361 foreach(var i in toadd) {
363 foreach(var ig in ignore) {
376 static bool initialized = false;
377 public static Gee.ArrayList<string> builtin;
378 public static Gee.ArrayList<string> skips;
380 public static string[] ones;
381 public static string[] twos;
382 // static string[] threes : [],
385 if (Scope.initialized) {
388 Scope.initialized = true;
389 Scope.builtin = new Gee.ArrayList<string>();
390 array_merge(Scope.builtin, "NaN,top".split(","), {});
392 Scope.skips = new Gee.ArrayList<string>();
393 array_merge(Scope.skips, "as,is,do,if,in,for,int,new,try,use,var,NaN,top".split(","), {});
395 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(",");
396 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(",");
399 for(var i = 0; i < Scope.ones.length; i++) {
400 for(var j = 0; j < n.length; j++) {
401 string tw = Scope.ones[i] + n[j];
402 if (Scope.skips.index_of(tw) < 0) {
407 for(var k = 0; k < n.length; k++) {
408 var thr = a[i] + n[j] + n[k];
409 //println("thr="+ thr + ":iOf="+this.skips.indexOf(thr) );
410 if (this.skips.indexOf(thr) < 0) {
412 this.threes.push(thr);
420 //println("done creating var list");
421 //println("threes="+ this.threes.toSource());