Mercurial > repos > tabletprog
comparison interp.js @ 209:4b3b57f39f10
Implement zeroPlus macro
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 27 Nov 2013 23:36:24 -0800 |
parents | a1b4a2bc8d72 |
children | d0848563f25d |
comparison
equal
deleted
inserted
replaced
208:a1b4a2bc8d72 | 209:4b3b57f39f10 |
---|---|
26 return this <= other ? tptrue : tpfalse; | 26 return this <= other ? tptrue : tpfalse; |
27 }; | 27 }; |
28 Number.prototype.tpmeth_asStringChar = function() { | 28 Number.prototype.tpmeth_asStringChar = function() { |
29 return String.fromCharCode(this); | 29 return String.fromCharCode(this); |
30 }; | 30 }; |
31 Number.prototype['tpmeth_isString?'] = function() { | |
32 return false; | |
33 }; | |
31 Number.prototype.tpmeth_string = function() { | 34 Number.prototype.tpmeth_string = function() { |
32 return '' + this; | 35 return '' + this; |
33 }; | 36 }; |
34 Number.prototype.tpmeth_print = function() { | 37 Number.prototype.tpmeth_print = function() { |
35 print(this); | 38 print(this); |
50 String.prototype.tpmeth_byte = function(index) { | 53 String.prototype.tpmeth_byte = function(index) { |
51 return this.charCodeAt(index); | 54 return this.charCodeAt(index); |
52 }; | 55 }; |
53 String.prototype['tpmeth_from:withLength'] = function(pos, length) { | 56 String.prototype['tpmeth_from:withLength'] = function(pos, length) { |
54 return this.substr(pos, length); | 57 return this.substr(pos, length); |
58 }; | |
59 String.prototype['tpmeth_isString?'] = function() { | |
60 return true; | |
55 }; | 61 }; |
56 String.prototype.tpmeth_print = function() { | 62 String.prototype.tpmeth_print = function() { |
57 print(this); | 63 print(this); |
58 }; | 64 }; |
59 | 65 |
216 return val; | 222 return val; |
217 } | 223 } |
218 | 224 |
219 op.prototype.eval = function(env) { | 225 op.prototype.eval = function(env) { |
220 var l = this.left.eval(env); | 226 var l = this.left.eval(env); |
221 var r = this.right.eval(env); | |
222 var name = this.op; | 227 var name = this.op; |
228 if (name == '&&' || name == '||') { | |
229 var r = (new lambda([], [this.right])).eval(env); | |
230 } else { | |
231 var r = this.right.eval(env); | |
232 } | |
223 var fun = env.findNoTop(name); | 233 var fun = env.findNoTop(name); |
224 var ret; | 234 var ret; |
225 if (fun) { | 235 if (fun) { |
226 ret = fun(l,r) | 236 ret = fun(l,r) |
227 } else { | 237 } else { |
238 if (name == '&&') { | |
239 name = 'if' | |
240 } else if (name == '||') { | |
241 name = 'ifnot' | |
242 } | |
228 ret = l['tpmeth_'+name](r); | 243 ret = l['tpmeth_'+name](r); |
229 } | 244 } |
230 return ret; | 245 return ret; |
231 }; | 246 }; |
232 | 247 |
240 var left = this.left.quote(env); | 255 var left = this.left.quote(env); |
241 var right = this.right.quote(env); | 256 var right = this.right.quote(env); |
242 return new op(left, this.op, right); | 257 return new op(left, this.op, right); |
243 }; | 258 }; |
244 | 259 |
260 op.prototype.tpmeth_nodeType = function() { | |
261 return "op"; | |
262 }; | |
263 | |
264 op.prototype.tpmeth_left = function() { | |
265 return this.left; | |
266 }; | |
267 | |
268 op.prototype.tpmeth_right = function() { | |
269 return this.right; | |
270 }; | |
271 | |
272 op.prototype.tpmeth_opName = function() { | |
273 return this.op; | |
274 }; | |
275 | |
245 var quote_prefix = 0; | 276 var quote_prefix = 0; |
246 | 277 |
247 symbol.prototype.eval = function(env) { | 278 symbol.prototype.eval = function(env) { |
248 var res = env.find(this.name); | 279 var res = env.find(this.name); |
249 if (res === null) { | 280 if (res === null) { |
253 }; | 284 }; |
254 | 285 |
255 symbol.prototype.quote = function(env) { | 286 symbol.prototype.quote = function(env) { |
256 var val = env.find(this.name); | 287 var val = env.find(this.name); |
257 if (val) { | 288 if (val) { |
258 return makeASTNode(val); | 289 var newnode = makeASTNode(val); |
290 if (!(newnode instanceof symbol)) { | |
291 newnode = newnode.quote(env); | |
292 } | |
293 return newnode; | |
259 } else { | 294 } else { |
260 var hygenic = env.findQuoteTrans(this.name); | 295 var hygenic = env.findQuoteTrans(this.name); |
261 return hygenic ? new symbol(hygenic, this.symbols) : this; | 296 return hygenic ? new symbol(hygenic, this.symbols) : this; |
262 } | 297 } |
298 }; | |
299 | |
300 symbol.prototype.tpmeth_nodeType = function() { | |
301 return "symbol"; | |
302 }; | |
303 | |
304 symbol.prototype.tpmeth_name = function() { | |
305 return this.cleanName(); | |
263 }; | 306 }; |
264 | 307 |
265 intlit.prototype.eval = | 308 intlit.prototype.eval = |
266 floatlit.prototype.eval = | 309 floatlit.prototype.eval = |
267 strlit.prototype.eval = | 310 strlit.prototype.eval = |
284 arraylit.prototype.quote = | 327 arraylit.prototype.quote = |
285 listlit.prototype.quote = function(env) { | 328 listlit.prototype.quote = function(env) { |
286 return this; | 329 return this; |
287 }; | 330 }; |
288 | 331 |
332 intlit.prototype.tpmeth_nodeType = function() { | |
333 return "intlit"; | |
334 }; | |
335 | |
336 floatlit.prototype.tpmeth_nodeType = function() { | |
337 return "floatlit"; | |
338 }; | |
339 | |
340 strlit.prototype.tpmeth_nodeType = function() { | |
341 return "strlit"; | |
342 }; | |
343 | |
344 arraylit.prototype.tpmeth_nodeType = function() { | |
345 return "arraylit"; | |
346 }; | |
347 | |
348 listlit.prototype.tpmeth_nodeType = function() { | |
349 return "strlit"; | |
350 }; | |
351 | |
352 intlit.prototype.tpmeth_value = | |
353 floatlit.prototype.tpmeth_value = | |
354 strlit.prototype.tpmeth_value = | |
355 arraylit.prototype.tpmeth_value = | |
356 listlit.prototype.tpmeth_value = function() { | |
357 return this.val; | |
358 } | |
359 | |
289 funcall.prototype.eval = function(env) { | 360 funcall.prototype.eval = function(env) { |
290 var args = []; | 361 var args = []; |
291 var name = this.name; | 362 var name = this.name; |
292 if (name[name.length-1] == ":") { | 363 if (name[name.length-1] == ":") { |
293 name = name.substr(0, name.length-1); | 364 name = name.substr(0, name.length-1); |
295 if (name == 'quote') { | 366 if (name == 'quote') { |
296 if (this.receiver) { | 367 if (this.receiver) { |
297 return this.receiver.quote(env); | 368 return this.receiver.quote(env); |
298 } | 369 } |
299 if (this.args.length) { | 370 if (this.args.length) { |
371 var cur = env; | |
300 return this.args[0].quote(env); | 372 return this.args[0].quote(env); |
301 } | 373 } |
302 throw new Error('quote takes an argument'); | 374 throw new Error('quote takes an argument'); |
303 } | 375 } |
304 if (name == 'macro') { | 376 if (name == 'macro') { |
363 var receiver = this.receiver ? this.receiver.quote(env) : null; | 435 var receiver = this.receiver ? this.receiver.quote(env) : null; |
364 var args = []; | 436 var args = []; |
365 for (var i = 0; i < this.args.length; i++) { | 437 for (var i = 0; i < this.args.length; i++) { |
366 args.push(this.args[i].quote(env)); | 438 args.push(this.args[i].quote(env)); |
367 } | 439 } |
368 var name = env.findQuoteTrans(this.name); | 440 var name = this.name; |
369 if (!name) { | 441 if (name[name.length-1] == ":") { |
370 name = this.name; | 442 name = name.substr(0, name.length-1); |
443 } | |
444 var fun = env.find(name); | |
445 if (fun) { | |
446 fun = makeASTNode(fun); | |
447 if (fun instanceof symbol) { | |
448 name = fun.cleanName(); | |
449 } else if (fun instanceof lambda) { | |
450 throw new Error('FIXME'); | |
451 } | |
452 } else { | |
453 var hygenic = env.findQuoteTrans(this.name); | |
454 if (hygenic) { | |
455 name = hygenic; | |
456 } | |
371 } | 457 } |
372 var ret = new funcall(name, args); | 458 var ret = new funcall(name, args); |
373 ret.receiver = receiver; | 459 ret.receiver = receiver; |
374 return ret; | 460 return ret; |
461 }; | |
462 | |
463 funcall.prototype.tpmeth_nodeType = function() { | |
464 return "funcall"; | |
375 }; | 465 }; |
376 | 466 |
377 object.prototype.eval = function(parentenv) { | 467 object.prototype.eval = function(parentenv) { |
378 var env = new environment(parentenv); | 468 var env = new environment(parentenv); |
379 var obj = {env: env}; | 469 var obj = {env: env}; |
478 } | 568 } |
479 } | 569 } |
480 return new object(outmessages); | 570 return new object(outmessages); |
481 }; | 571 }; |
482 | 572 |
573 object.prototype.tpmeth_nodeType = function() { | |
574 return "object"; | |
575 }; | |
576 | |
483 lambda.prototype.eval = function(parentenv) { | 577 lambda.prototype.eval = function(parentenv) { |
484 var args = this.args; | 578 var args = this.args; |
485 var exprs = this.expressions; | 579 var exprs = this.expressions; |
486 return function() { | 580 return function() { |
487 var env = new environment(parentenv); | 581 var env = new environment(parentenv); |
537 expressions.push(this.expressions[i].quote(env)); | 631 expressions.push(this.expressions[i].quote(env)); |
538 } | 632 } |
539 return new lambda(args, expressions); | 633 return new lambda(args, expressions); |
540 }; | 634 }; |
541 | 635 |
636 lambda.prototype.tpmeth_nodeType = function() { | |
637 return "lambda"; | |
638 }; | |
639 | |
542 assignment.prototype.eval = function(env) { | 640 assignment.prototype.eval = function(env) { |
543 var val = this.expression.eval(env); | 641 var val = this.expression.eval(env); |
544 env.findSet(this.symbol.name, val); | 642 env.findSet(this.symbol.name, val); |
545 return val; | 643 return val; |
546 }; | 644 }; |
555 env.syms[name] = null; | 653 env.syms[name] = null; |
556 var hygenic = '' + quote_prefix + name; | 654 var hygenic = '' + quote_prefix + name; |
557 env.quotetrans[name] = hygenic; | 655 env.quotetrans[name] = hygenic; |
558 return new assignment(new symbol(hygenic, this.symbol.symbols), this.expression.quote(env)); | 656 return new assignment(new symbol(hygenic, this.symbol.symbols), this.expression.quote(env)); |
559 }; | 657 }; |
658 | |
659 assignment.prototype.tpmeth_nodeType = function() { | |
660 return "assignment"; | |
661 }; |