Mercurial > repos > tabletprog
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 { |