comparison compiler.js @ 126:a2d2d8e09291

Merge
author Mike Pavone <pavone@retrodev.com>
date Mon, 05 Aug 2013 23:37:17 -0700
parents d715fb3c39ab
children d6e79885bd3b 18598163e3ef
comparison
equal deleted inserted replaced
125:6f8d868e8da0 126:a2d2d8e09291
7 7
8 function modulefile(path, file) 8 function modulefile(path, file)
9 { 9 {
10 this.path = path; 10 this.path = path;
11 this.file = file; 11 this.file = file;
12 }
13
14 modulefile.prototype.populateSymbols = function (toplevel) {
15 if (!this.ast) {
16 this.ast = parseFile(this.path + '/' + this.file);
17 this.ast.populateSymbols(toplevel);
18 }
19 };
20
21 modulefile.prototype.popuplateSymbolsAsync = function(toplevel, whenDone) {
22 if (!this.ast) {
23 var self = this;
24 get(this.path + '/' + this.file, function(data) {
25 self.ast = parser.parse(data.responseText);
26 self.ast.populateSymbols(toplevel);
27 whenDone();
28 });
29 } else {
30 whenDone();
31 }
32 };
33
34 function getfileshtml(path, data, names)
35 {
36 var fakeEl = newEl("div", {
37 innerHTML: data.response
38 });
39 each(qall('a', fakeEl), function(idx, a) {
40 var tpidx = a.textContent.indexOf('.tp');
41 var modname = a.textContent.substr(0, tpidx);
42 if (tpidx > -1) {
43 names[modname] = new modulefile(path, modname + '.tp');
44 }
45 });
12 } 46 }
13 47
14 var toplevel = new topsymbols([]); 48 var toplevel = new topsymbols([]);
15 function topsymbols(moduledirs) 49 function topsymbols(moduledirs)
16 { 50 {
17 this.names = null; 51 this.names = null;
18 this.used = {}; 52 this.used = {};
19 this.nextmodulenum = 0; 53 this.nextmodulenum = 0;
54 this.onready = null;
20 var self = this; 55 var self = this;
21 if (typeof window === "object") { 56 if (typeof window === "object") {
22 get('/src/', function(data) { 57 get('/modules/', function(data) {
23 self.names = {}; 58 var names = {}
24 var fakeEl = newEl("div", { 59 getfileshtml('/modules', data, names);
25 innerHTML: data.response 60 get('/src/', function(data) {
26 }); 61 getfileshtml('/src', data, names);
27 each(qall('a', fakeEl), function(idx, a) { 62 self.names = names;
28 var tpidx = a.textContent.indexOf('.tp'); 63 if (self.onready) {
29 if (tpidx > -1) { 64 self.onready();
30 self.names[a.textContent.substr(0, tpidx)] = true;
31 } 65 }
32 }); 66 });
33 }); 67 });
34 } else { 68 } else {
35 this.names = {}; 69 this.names = {};
55 type: 'toplevel', 89 type: 'toplevel',
56 def: this.names[name] 90 def: this.names[name]
57 }; 91 };
58 } 92 }
59 return null; 93 return null;
60 } 94 };
61 topsymbols.prototype.getEnvType = function() { 95 topsymbols.prototype.getEnvType = function() {
62 return 'void'; 96 return 'void';
63 } 97 };
64 topsymbols.prototype.moduleVar = function(name) { 98 topsymbols.prototype.moduleVar = function(name) {
65 if (!(name in this.names)) { 99 if (!(name in this.names)) {
66 throw new Error('symbol ' + name + ' not found at toplevel'); 100 throw new Error('symbol ' + name + ' not found at toplevel');
67 } 101 }
68 if (name == 'true' || name == 'false') { 102 if (name == 'true' || name == 'false') {
70 } 104 }
71 if (!this.names[name].modulevar) { 105 if (!this.names[name].modulevar) {
72 this.names[name].modulevar = 'module_' + this.nextmodulenum++ 106 this.names[name].modulevar = 'module_' + this.nextmodulenum++
73 } 107 }
74 return this.names[name].modulevar; 108 return this.names[name].modulevar;
75 } 109 };
110 topsymbols.prototype.onReady = function(fun) {
111 if (this.names) {
112 fun();
113 return;
114 }
115 if (!this.onready) {
116 this.onready = fun;
117 } else {
118 var oldready = this.onready;
119 this.onready = function() {
120 oldready();
121 fun();
122 };
123 }
124 };
76 125
77 function osymbols(parent) 126 function osymbols(parent)
78 { 127 {
79 this.parent = parent; 128 this.parent = parent;
80 this.names = {}; 129 this.names = {};
130 this.llnames = {};
81 this.needsenv = false; 131 this.needsenv = false;
82 this.typename = null; 132 this.typename = null;
83 this.needsparent = false; 133 this.needsparent = false;
84 } 134 }
85 osymbols.prototype.find = function(name, nestedcall) { 135 osymbols.prototype.find = function(name, nestedcall, allowll) {
86 debugprint('//osymbols.find', name + ', exists?:', name in this.names, ', nested?:', nestedcall); 136 debugprint('//osymbols.find', name + ', exists?:', name in this.names, ', nested?:', nestedcall);
87 if (name in this.names) { 137 if (name in this.names) {
88 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') { 138 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') {
89 return { 139 return {
90 type: 'foreign', 140 type: 'foreign',
91 def: this.names[name] 141 def: this.names[name]
92 }; 142 };
93 } 143 }
94 var ret = { 144 var ret = {
95 type: 'self', 145 type: 'self',
146 isll: false,
96 def: this.names[name], 147 def: this.names[name],
97 selftype: this.typename 148 selftype: this.typename
98 }; 149 };
150 } else if(allowll && name in this.llnames) {
151 return {
152 type: 'self',
153 isll: true,
154 selftype: this.typename
155 };
99 } else if(this.parent) { 156 } else if(this.parent) {
100 var ret = this.parent.find(name, nestedcall); 157 var ret = this.parent.find(name, nestedcall, allowll);
101 if (ret) { 158 if (ret) {
102 if(ret.type == 'self') { 159 if(ret.type == 'self') {
103 ret.type = 'parent'; 160 ret.type = 'parent';
104 ret.depth = 1; 161 ret.depth = 1;
105 this.needsparent = true; 162 this.needsparent = true;
117 return ret; 174 return ret;
118 }; 175 };
119 osymbols.prototype.defineMsg = function(name, def) { 176 osymbols.prototype.defineMsg = function(name, def) {
120 this.names[name] = def; 177 this.names[name] = def;
121 } 178 }
179 osymbols.prototype.defineLLProperty = function(name) {
180 this.llnames[name] = true;
181 }
122 osymbols.prototype.parentObject = function() { 182 osymbols.prototype.parentObject = function() {
123 if (!this.parent) { 183 if (!this.parent) {
124 return 'null'; 184 return 'null';
125 } 185 }
126 return 'this'; 186 return 'this';
158 this.needsSelfVar = false; 218 this.needsSelfVar = false;
159 this.passthruenv = false; 219 this.passthruenv = false;
160 this.envtype = 'void'; 220 this.envtype = 'void';
161 this.needsParentEnv = false; 221 this.needsParentEnv = false;
162 } 222 }
163 lsymbols.prototype.find = function(name, nestedcall) { 223 lsymbols.prototype.find = function(name, nestedcall, allowll) {
164 debugprint('//lsymbols.find', name + ', exists?:', name in this.names, ', nested?:', nestedcall); 224 debugprint('//lsymbols.find', name + ', exists?:', name in this.names, ', nested?:', nestedcall);
165 if (name in this.names) { 225 if (name in this.names) {
166 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') { 226 if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') {
167 var ret = { 227 var ret = {
168 type: 'foreign', 228 type: 'foreign',
185 isdeclared: (name in this.declared) 245 isdeclared: (name in this.declared)
186 }; 246 };
187 } 247 }
188 } 248 }
189 } else if(this.parent) { 249 } else if(this.parent) {
190 var ret = this.parent.find(name, true); 250 var ret = this.parent.find(name, true, allowll);
191 if (ret) { 251 if (ret) {
192 if (ret.type == 'closedover') { 252 if (ret.type == 'closedover') {
193 ret.type = 'upvar'; 253 ret.type = 'upvar';
194 ret.depth = 0; 254 ret.depth = 0;
195 } 255 }
260 320
261 var mainModule; 321 var mainModule;
262 322
263 function toobj(val) 323 function toobj(val)
264 { 324 {
265 switch(typeof val) 325 return (typeof val == "boolean") ? (val ? module_true : module_false) : val;
266 {
267 case 'boolean':
268 if(val) {
269 return mainModule.strue;
270 } else {
271 return mainModule.sfalse;
272 }
273 case 'number':
274 return mainModule.snumber(val);
275 }
276 throw new Error("can't make val into object");
277 } 326 }
278 327
279 op.prototype.populateSymbols = function(symbols, isReceiver) { 328 op.prototype.populateSymbols = function(symbols, isReceiver) {
280 this.left.populateSymbols(symbols); 329 this.left.populateSymbols(symbols);
330 if (this.op == '&&' || this.op == '||') {
331 //&& and || are syntactic sugar for if and ifnot with
332 //the second argument transformed into a lambda to
333 //achieve short-circuit evalutation
334 this.right = new lambda([], [this.right]);
335 }
281 this.right.populateSymbols(symbols); 336 this.right.populateSymbols(symbols);
282 }; 337 };
283 338
284 symbol.prototype.populateSymbols = function(symbols) { 339 symbol.prototype.populateSymbols = function(symbols) {
285 this.symbols = symbols; 340 this.symbols = symbols;
309 this.val[i].populateSymbols(symbols); 364 this.val[i].populateSymbols(symbols);
310 } 365 }
311 } 366 }
312 367
313 funcall.prototype.populateSymbols = function(symbols) { 368 funcall.prototype.populateSymbols = function(symbols) {
369 var isll = false;
314 if (this.name == 'foreign:') { 370 if (this.name == 'foreign:') {
315 if ((this.args[0] instanceof lambda) || (this.args[0] instanceof object) || (this.args[0] instanceof symbol)) { 371 if ((this.args[0] instanceof lambda) || (this.args[0] instanceof object) || (this.args[0] instanceof symbol)) {
316 return; 372 return;
317 } else { 373 } else {
318 throw new Error("Unexpected AST type for foreign:"); 374 throw new Error("Unexpected AST type for foreign:");
319 } 375 }
376 } else if (this.name == 'llProperty:withType:') {
377 if (this.args[0] instanceof symbol) {
378 if ((this.args[1] instanceof symbol) || (this.args[1] instanceof funcall)) {
379 symbols.defineLLProperty(this.args[0].name);
380 return;
381 } else {
382 throw new Error("Second argument to llProperty:withType: must be a symbol or funcall");
383 }
384 } else {
385 throw new Error("First argument to llProperty:withType: must be a symbol");
386 }
387 } else if (this.name == 'llMessage:withVars:andCode:') {
388 if (this.args[0] instanceof symbol) {
389 if (this.args[1] instanceof lambda) {
390 if (this.args[2] instanceof lambda) {
391 symbols.defineMsg(this.args[0].name, this.args[2]);
392 isll = true;
393 } else {
394 throw new Error("Third argument to llMessage:withVars:andCode: must be a lambda");
395 }
396 } else {
397 throw new Error("Second argument to llMessage:withVars:andCode: must be a lambda");
398 }
399 } else {
400 throw new Error("First argument to llMessage:withVars:andCode: must be a symbol");
401 }
320 } 402 }
321 this.symbols = symbols; 403 this.symbols = symbols;
322 var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name; 404 var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name;
323 var funinfo = symbols.find(name); 405 var funinfo = symbols.find(name);
324 if (funinfo && (funinfo.type == 'self' || funinfo.type == 'parent')) { 406 if (funinfo && (funinfo.type == 'self' || funinfo.type == 'parent')) {
325 symbols.find('self'); 407 symbols.find('self');
326 } 408 }
327 for (var i in this.args) { 409 for (var i in this.args) {
328 this.args[i].populateSymbols(symbols); 410 this.args[i].populateSymbols(symbols, undefined, isll);
329 } 411 }
330 if (this.receiver) { 412 if (this.receiver) {
331 this.receiver.populateSymbols(symbols); 413 this.receiver.populateSymbols(symbols, undefined, isll);
332 } 414 }
333 } 415 }
334 416
335 funcall.prototype.populateSymbolsObject = function(symbols) { 417 funcall.prototype.populateSymbolsObject = function(symbols) {
336 this.populateSymbols(symbols.parent); 418 this.populateSymbols(symbols);
337 } 419 }
338 420
339 object.prototype.populateSymbols = function(symbols) { 421 object.prototype.populateSymbols = function(symbols) {
340 symbols = new osymbols(symbols); 422 var symbols = new osymbols(symbols);
341 for (var i in this.messages) { 423 for (var i in this.messages) {
342 this.messages[i].populateSymbolsObject(symbols); 424 this.messages[i].populateSymbolsObject(symbols);
343 } 425 }
344 this.symbols = symbols; 426 this.symbols = symbols;
345 } 427 }
346 428 var lambdanum = 0;
347 lambda.prototype.populateSymbols = function(symbols, isobject) { 429 lambda.prototype.populateSymbols = function(symbols, isobject, isll) {
430 if (!isll) {
431 this.name = 'lambda_' + lambdanum++;
432 }
348 var args = this.args ? this.args.slice(0, this.args.length) : []; 433 var args = this.args ? this.args.slice(0, this.args.length) : [];
349 var exprs = this.expressions; 434 var exprs = this.expressions;
350 var symbols = new lsymbols(symbols); 435 var symbols = new lsymbols(symbols);
351 for (var i in args) { 436 for (var i in args) {
352 symbols.defineVar(args[i].cleanName(), null); 437 symbols.defineVar(args[i].cleanName(), null);
392 function getter(fun) 477 function getter(fun)
393 { 478 {
394 this.fun = fun; 479 this.fun = fun;
395 } 480 }
396 getter.prototype.args = [new symbol('self')]; 481 getter.prototype.args = [new symbol('self')];
482