comparison compiler.js @ 54:976a0924e1d4

Fix closure over self var
author Mike Pavone <pavone@retrodev.com>
date Fri, 13 Jul 2012 19:22:39 -0700
parents 18ab96287c3a
children 93ddb4ad6fcb
comparison
equal deleted inserted replaced
53:9482a0afe07c 54:976a0924e1d4
1 var debugprint = function() {};
2
1 function indent(str) 3 function indent(str)
2 { 4 {
3 return str.split('\n').join('\n\t'); 5 return str.split('\n').join('\n\t');
4 } 6 }
5 7
40 } 42 }
41 } 43 }
42 } 44 }
43 } 45 }
44 topsymbols.prototype.find = function(name) { 46 topsymbols.prototype.find = function(name) {
47 debugprint('//topsymbols.find', name, name in this.names);
45 if (!this.names) { 48 if (!this.names) {
46 throw new Error('data not ready'); 49 throw new Error('data not ready');
47 } 50 }
48 if (name in this.names) { 51 if (name in this.names) {
49 this.used[name] = true; 52 this.used[name] = true;
63 this.parent = parent; 66 this.parent = parent;
64 this.names = {}; 67 this.names = {};
65 this.needsenv = false; 68 this.needsenv = false;
66 } 69 }
67 osymbols.prototype.find = function(name, nestedcall) { 70 osymbols.prototype.find = function(name, nestedcall) {
71 debugprint('//osymbols.find', name + ', exists?:', name in this.names, ', nested?:', nestedcall);
68 if (name in this.names) { 72 if (name in this.names) {
69 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') { 73 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') {
70 return { 74 return {
71 type: 'foreign', 75 type: 'foreign',
72 def: this.names[name] 76 def: this.names[name]
73 }; 77 };
74 } 78 }
75 return { 79 var ret = {
76 type: 'self', 80 type: 'self',
77 def: this.names[name], 81 def: this.names[name],
78 }; 82 };
79 } else if(this.parent) { 83 } else if(this.parent) {
80 var ret = this.parent.find(name, nestedcall); 84 var ret = this.parent.find(name, nestedcall);
86 ret.depth++; 90 ret.depth++;
87 } else if(ret.type == 'closedover' || ret.type == 'upvar') { 91 } else if(ret.type == 'closedover' || ret.type == 'upvar') {
88 this.needsenv = true; 92 this.needsenv = true;
89 } 93 }
90 } 94 }
91 return ret; 95 } else {
92 } 96 return null;
93 return null; 97 }
98 debugprint('\t//symbol type:', ret ? ret.type : 'null');
99 return ret;
94 }; 100 };
95 osymbols.prototype.defineMsg = function(name, def) { 101 osymbols.prototype.defineMsg = function(name, def) {
96 this.names[name] = def; 102 this.names[name] = def;
97 } 103 }
98 osymbols.prototype.parentObject = function() { 104 osymbols.prototype.parentObject = function() {
134 this.needsSelfVar = false; 140 this.needsSelfVar = false;
135 this.passthruenv = false; 141 this.passthruenv = false;
136 this.envtype = 'void'; 142 this.envtype = 'void';
137 } 143 }
138 lsymbols.prototype.find = function(name, nestedcall) { 144 lsymbols.prototype.find = function(name, nestedcall) {
145 debugprint('//lsymbols.find', name + ', exists?:', name in this.names, ', nested?:', nestedcall);
139 if (name in this.names) { 146 if (name in this.names) {
140 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') { 147 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') {
141 return { 148 var ret = {
142 type: 'foreign', 149 type: 'foreign',
143 def: this.names[name] 150 def: this.names[name]
144 }; 151 };
145 } 152 } else {
146 if (nestedcall) { 153 if (nestedcall) {
147 this.closedover[name] = true; 154 this.closedover[name] = true;
148 } 155 }
149 if (name in this.closedover) { 156 if (name in this.closedover) {
150 return { 157 var ret = {
151 type: 'closedover', 158 type: 'closedover',
152 def: this.names[name] 159 def: this.names[name]
153 }; 160 };
154 } 161 } else {
155 return { 162 var ret = {
156 type: 'local', 163 type: 'local',
157 def: this.names[name], 164 def: this.names[name],
158 isdeclared: (name in this.declared) 165 isdeclared: (name in this.declared)
159 }; 166 };
167 }
168 }
160 } else if(this.parent) { 169 } else if(this.parent) {
161 var ret = this.parent.find(name, true); 170 var ret = this.parent.find(name, true);
162 if (ret) { 171 if (ret) {
163 if (ret.type == 'closedover') { 172 if (ret.type == 'closedover') {
164 ret.type = 'upvar'; 173 ret.type = 'upvar';
169 } else { 178 } else {
170 this.passthruenv = true; 179 this.passthruenv = true;
171 } 180 }
172 } 181 }
173 } 182 }
174 return ret; 183 } else {
175 } 184 return null;
176 return null; 185 }
186 debugprint('\t//symbol type:', ret ? ret.type : 'null');
187 return ret;
177 }; 188 };
178 lsymbols.prototype.defineVar = function(name, def) { 189 lsymbols.prototype.defineVar = function(name, def) {
179 this.names[name] = def; 190 this.names[name] = def;
180 }; 191 };
181 lsymbols.prototype.declareVar = function(name) { 192 lsymbols.prototype.declareVar = function(name) {
242 this.right.populateSymbols(symbols); 253 this.right.populateSymbols(symbols);
243 }; 254 };
244 255
245 symbol.prototype.populateSymbols = function(symbols) { 256 symbol.prototype.populateSymbols = function(symbols) {
246 this.symbols = symbols; 257 this.symbols = symbols;
247 symbols.find(this.cleanName()); 258 var ret = symbols.find(this.cleanName());
259 if (ret.type == 'self') {
260 symbols.find('self');
261 }
248 } 262 }
249 263
250 intlit.prototype.populateSymbols = function(symbols) { 264 intlit.prototype.populateSymbols = function(symbols) {
251 } 265 }
252 266
295 this.messages[i].populateSymbolsObject(symbols); 309 this.messages[i].populateSymbolsObject(symbols);
296 } 310 }
297 this.symbols = symbols; 311 this.symbols = symbols;
298 } 312 }
299 313
300 lambda.prototype.populateSymbols = function(symbols) { 314 lambda.prototype.populateSymbols = function(symbols, isobject) {
301 var args = this.args ? this.args.slice(0, this.args.length) : []; 315 var args = this.args ? this.args.slice(0, this.args.length) : [];
302 if (args.length && args[0].cleanName() == 'self') {
303 args.splice(0, 1);
304 }
305 var exprs = this.expressions; 316 var exprs = this.expressions;
306 symbols = new lsymbols(symbols); 317 var symbols = new lsymbols(symbols);
307 for (var i in args) { 318 for (var i in args) {
308 symbols.defineVar(args[i].cleanName(), null); 319 symbols.defineVar(args[i].cleanName(), null);
309 args[i].populateSymbols(symbols); 320 args[i].populateSymbols(symbols);
321 }
322 if (isobject && (!args.length || args[0].cleanName() != 'self')) {
323 symbols.defineVar('self', null);
310 } 324 }
311 for (var i in exprs) { 325 for (var i in exprs) {
312 exprs[i].populateSymbols(symbols); 326 exprs[i].populateSymbols(symbols);
313 } 327 }
314 this.symbols = symbols; 328 this.symbols = symbols;
329 } else { 343 } else {
330 symbols.defineMsg(this.symbol.name, new getter(null)); 344 symbols.defineMsg(this.symbol.name, new getter(null));
331 symbols.defineMsg(this.symbol.name + '!', new setter(null)); 345 symbols.defineMsg(this.symbol.name + '!', new setter(null));
332 } 346 }
333 this.symbol.populateSymbols(symbols); 347 this.symbol.populateSymbols(symbols);
334 this.expression.populateSymbols(symbols); 348 this.expression.populateSymbols(symbols, true);
335 this.symbols = symbols; 349 this.symbols = symbols;
336 }; 350 };
337 351
338 function setter(fun) 352 function setter(fun)
339 { 353 {