Mercurial > repos > tabletprog
comparison compiler.js @ 84:9811040704ac
Add support for llMessage:withVars:andCode and llProperty:withType for specifying low level code without having to stick C inside the compiler. Redo array built-in type to use this feature.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 21 Jul 2012 22:30:21 -0700 |
parents | 8a9b96888b7d |
children | 926b65fe92b4 |
comparison
equal
deleted
inserted
replaced
83:fdb9785d2c93 | 84:9811040704ac |
---|---|
76 | 76 |
77 function osymbols(parent) | 77 function osymbols(parent) |
78 { | 78 { |
79 this.parent = parent; | 79 this.parent = parent; |
80 this.names = {}; | 80 this.names = {}; |
81 this.llnames = {}; | |
81 this.needsenv = false; | 82 this.needsenv = false; |
82 this.typename = null; | 83 this.typename = null; |
83 this.needsparent = false; | 84 this.needsparent = false; |
84 } | 85 } |
85 osymbols.prototype.find = function(name, nestedcall) { | 86 osymbols.prototype.find = function(name, nestedcall, allowll) { |
86 debugprint('//osymbols.find', name + ', exists?:', name in this.names, ', nested?:', nestedcall); | 87 debugprint('//osymbols.find', name + ', exists?:', name in this.names, ', nested?:', nestedcall); |
87 if (name in this.names) { | 88 if (name in this.names) { |
88 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') { | 89 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') { |
89 return { | 90 return { |
90 type: 'foreign', | 91 type: 'foreign', |
91 def: this.names[name] | 92 def: this.names[name] |
92 }; | 93 }; |
93 } | 94 } |
94 var ret = { | 95 var ret = { |
95 type: 'self', | 96 type: 'self', |
97 isll: false, | |
96 def: this.names[name], | 98 def: this.names[name], |
97 selftype: this.typename | 99 selftype: this.typename |
98 }; | 100 }; |
101 } else if(allowll && name in this.llnames) { | |
102 return { | |
103 type: 'self', | |
104 isll: true, | |
105 selftype: this.typename | |
106 }; | |
99 } else if(this.parent) { | 107 } else if(this.parent) { |
100 var ret = this.parent.find(name, nestedcall); | 108 var ret = this.parent.find(name, nestedcall, allowll); |
101 if (ret) { | 109 if (ret) { |
102 if(ret.type == 'self') { | 110 if(ret.type == 'self') { |
103 ret.type = 'parent'; | 111 ret.type = 'parent'; |
104 ret.depth = 1; | 112 ret.depth = 1; |
105 this.needsparent = true; | 113 this.needsparent = true; |
117 return ret; | 125 return ret; |
118 }; | 126 }; |
119 osymbols.prototype.defineMsg = function(name, def) { | 127 osymbols.prototype.defineMsg = function(name, def) { |
120 this.names[name] = def; | 128 this.names[name] = def; |
121 } | 129 } |
130 osymbols.prototype.defineLLProperty = function(name) { | |
131 this.llnames[name] = true; | |
132 } | |
122 osymbols.prototype.parentObject = function() { | 133 osymbols.prototype.parentObject = function() { |
123 if (!this.parent) { | 134 if (!this.parent) { |
124 return 'null'; | 135 return 'null'; |
125 } | 136 } |
126 return 'this'; | 137 return 'this'; |
158 this.needsSelfVar = false; | 169 this.needsSelfVar = false; |
159 this.passthruenv = false; | 170 this.passthruenv = false; |
160 this.envtype = 'void'; | 171 this.envtype = 'void'; |
161 this.needsParentEnv = false; | 172 this.needsParentEnv = false; |
162 } | 173 } |
163 lsymbols.prototype.find = function(name, nestedcall) { | 174 lsymbols.prototype.find = function(name, nestedcall, allowll) { |
164 debugprint('//lsymbols.find', name + ', exists?:', name in this.names, ', nested?:', nestedcall); | 175 debugprint('//lsymbols.find', name + ', exists?:', name in this.names, ', nested?:', nestedcall); |
165 if (name in this.names) { | 176 if (name in this.names) { |
166 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') { | 177 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') { |
167 var ret = { | 178 var ret = { |
168 type: 'foreign', | 179 type: 'foreign', |
185 isdeclared: (name in this.declared) | 196 isdeclared: (name in this.declared) |
186 }; | 197 }; |
187 } | 198 } |
188 } | 199 } |
189 } else if(this.parent) { | 200 } else if(this.parent) { |
190 var ret = this.parent.find(name, true); | 201 var ret = this.parent.find(name, true, allowll); |
191 if (ret) { | 202 if (ret) { |
192 if (ret.type == 'closedover') { | 203 if (ret.type == 'closedover') { |
193 ret.type = 'upvar'; | 204 ret.type = 'upvar'; |
194 ret.depth = 0; | 205 ret.depth = 0; |
195 } | 206 } |
315 if ((this.args[0] instanceof lambda) || (this.args[0] instanceof object) || (this.args[0] instanceof symbol)) { | 326 if ((this.args[0] instanceof lambda) || (this.args[0] instanceof object) || (this.args[0] instanceof symbol)) { |
316 return; | 327 return; |
317 } else { | 328 } else { |
318 throw new Error("Unexpected AST type for foreign:"); | 329 throw new Error("Unexpected AST type for foreign:"); |
319 } | 330 } |
331 } else if (this.name == 'llProperty:withType:') { | |
332 if (this.args[0] instanceof symbol) { | |
333 if ((this.args[1] instanceof symbol) || (this.args[1] instanceof funcall)) { | |
334 symbols.defineLLProperty(this.args[0].name); | |
335 return; | |
336 } else { | |
337 throw new Error("Second argument to llProperty:withType: must be a symbol or funcall"); | |
338 } | |
339 } else { | |
340 throw new Error("First argument to llProperty:withType: must be a symbol"); | |
341 } | |
342 } else if (this.name == 'llMessage:withVars:andCode:') { | |
343 if (this.args[0] instanceof symbol) { | |
344 if (this.args[1] instanceof lambda) { | |
345 if (this.args[2] instanceof lambda) { | |
346 symbols.defineMsg(this.args[0].name, this.args[2]); | |
347 } else { | |
348 throw new Error("Third argument to llMessage:withVars:andCode: must be a lambda"); | |
349 } | |
350 } else { | |
351 throw new Error("Second argument to llMessage:withVars:andCode: must be a lambda"); | |
352 } | |
353 } else { | |
354 throw new Error("First argument to llMessage:withVars:andCode: must be a symbol"); | |
355 } | |
320 } | 356 } |
321 this.symbols = symbols; | 357 this.symbols = symbols; |
322 var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name; | 358 var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name; |
323 var funinfo = symbols.find(name); | 359 var funinfo = symbols.find(name); |
324 if (funinfo && (funinfo.type == 'self' || funinfo.type == 'parent')) { | 360 if (funinfo && (funinfo.type == 'self' || funinfo.type == 'parent')) { |
331 this.receiver.populateSymbols(symbols); | 367 this.receiver.populateSymbols(symbols); |
332 } | 368 } |
333 } | 369 } |
334 | 370 |
335 funcall.prototype.populateSymbolsObject = function(symbols) { | 371 funcall.prototype.populateSymbolsObject = function(symbols) { |
336 this.populateSymbols(symbols.parent); | 372 this.populateSymbols(symbols); |
337 } | 373 } |
338 | 374 |
339 object.prototype.populateSymbols = function(symbols) { | 375 object.prototype.populateSymbols = function(symbols) { |
340 symbols = new osymbols(symbols); | 376 var symbols = new osymbols(symbols); |
341 for (var i in this.messages) { | 377 for (var i in this.messages) { |
342 this.messages[i].populateSymbolsObject(symbols); | 378 this.messages[i].populateSymbolsObject(symbols); |
343 } | 379 } |
344 this.symbols = symbols; | 380 this.symbols = symbols; |
345 } | 381 } |