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 }