Mercurial > repos > tabletprog
diff interp.js @ 208:a1b4a2bc8d72
Initial work on pattern match macrosfor the new parser
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 22 Nov 2013 19:37:25 -0800 |
parents | 60eff5f81d9a |
children | 4b3b57f39f10 |
line wrap: on
line diff
--- a/interp.js Tue Nov 19 22:02:11 2013 -0800 +++ b/interp.js Fri Nov 22 19:37:25 2013 -0800 @@ -25,6 +25,9 @@ Number.prototype['tpmeth_<='] = function(other) { return this <= other ? tptrue : tpfalse; }; +Number.prototype.tpmeth_asStringChar = function() { + return String.fromCharCode(this); +}; Number.prototype.tpmeth_string = function() { return '' + this; }; @@ -38,9 +41,33 @@ String.prototype['tpmeth_='] = function(other) { return this == other ? tptrue : tpfalse; }; +String.prototype.tpmeth_length = function() { + return this.length; +}; +String.prototype.tpmeth_byte_length = function() { + return this.length; +}; +String.prototype.tpmeth_byte = function(index) { + return this.charCodeAt(index); +}; +String.prototype['tpmeth_from:withLength'] = function(pos, length) { + return this.substr(pos, length); +}; String.prototype.tpmeth_print = function() { print(this); -} +}; + +Function.prototype['tpmeth_while:do'] = function(body) { + var ret = null; + for (;;) { + var res = this.call(null); + if (res != tptrue) { + break; + } + ret = body.call(null); + } + return ret; +}; var tptrue = null; var tpfalse = null; @@ -93,6 +120,9 @@ findMacro: function(name) { return null; }, + findQuoteTrans: function(name) { + return null; + } } function environment(parent) @@ -100,6 +130,7 @@ this.parent = parent; this.syms = {}; this.macros = {}; + this.quotetrans = {}; } environment.prototype = { @@ -150,6 +181,15 @@ } return null; }, + findQuoteTrans: function(name) { + if (name in this.quotetrans) { + return this.quotetrans[name]; + } + if (this.parent) { + return this.parent.findQuoteTrans(name); + } + return null; + }, defMacro: function(name, def) { this.syms[name] = def; this.macros[name] = true; @@ -162,7 +202,7 @@ return new intlit(val); } if (typeof val == 'string') { - return new stringlit(val); + return new strlit(val); } if (val instanceof Array) { return new arraylit(val); @@ -196,8 +236,30 @@ return this; }; +op.prototype.quote = function(env) { + var left = this.left.quote(env); + var right = this.right.quote(env); + return new op(left, this.op, right); +}; + +var quote_prefix = 0; + symbol.prototype.eval = function(env) { - return env.find(this.name); + var res = env.find(this.name); + if (res === null) { + throw new Error('Symbol ' + this.name + ' is not bound'); + } + return res; +}; + +symbol.prototype.quote = function(env) { + var val = env.find(this.name); + if (val) { + return makeASTNode(val); + } else { + var hygenic = env.findQuoteTrans(this.name); + return hygenic ? new symbol(hygenic, this.symbols) : this; + } }; intlit.prototype.eval = @@ -216,6 +278,14 @@ return this; }; +intlit.prototype.quote = + floatlit.prototype.quote = + strlit.prototype.quote = + arraylit.prototype.quote = + listlit.prototype.quote = function(env) { + return this; +}; + funcall.prototype.eval = function(env) { var args = []; var name = this.name; @@ -224,10 +294,10 @@ } if (name == 'quote') { if (this.receiver) { - return this.receiver; + return this.receiver.quote(env); } if (this.args.length) { - return this.args[0]; + return this.args[0].quote(env); } throw new Error('quote takes an argument'); } @@ -253,11 +323,11 @@ return fun.apply(null, args); } else { //if (typeof args[0]'tpmeth_'+name in args[0]) { - //try { + try { return args[0]['tpmeth_'+name].apply(args[0], args.slice(1)); - /*} catch(e) { - throw new Error('Error, \n\t' + e.message.split('\n').join('\n\t') + '\ninvoking method ' + name + ' on object ' + args[0] + ' ' + JSON.stringify(Object.keys(args[0]))); - }*/ + } catch(e) { + throw new Error('Error, \n\t' + e.message.split('\n').join('\n\t') + '\ninvoking method ' + name + ' on object ' + args[0]); + } /*} else {JSON.stringify throw new Error('No method named ' + name + ' on object ' + JSON.stringify(args[0])); }*/ @@ -289,6 +359,21 @@ return makeASTNode(macro.apply(null, args)); }; +funcall.prototype.quote = function(env) { + var receiver = this.receiver ? this.receiver.quote(env) : null; + var args = []; + for (var i = 0; i < this.args.length; i++) { + args.push(this.args[i].quote(env)); + } + var name = env.findQuoteTrans(this.name); + if (!name) { + name = this.name; + } + var ret = new funcall(name, args); + ret.receiver = receiver; + return ret; +}; + object.prototype.eval = function(parentenv) { var env = new environment(parentenv); var obj = {env: env}; @@ -369,6 +454,32 @@ return this; }; +object.prototype.quote = function(parentenv) { + var env = new environment(parentenv); + var outmessages = []; + for (var i = 0; i < this.messages.length; i++) { + var msg = this.messages[i]; + if (msg instanceof assignment) { + //Make sure method names don't get renamed for hygene + env.syms[msg.symbol.name] = null; + env.quotetrans[msg.symbol.name] = msg.symbol.name; + if (msg.expression instanceof lambda) { + env.syms[msg.symbol.name + '!'] = null; + env.quotetrans[msg.symbol.name + '!'] = msg.symbol.name + '!'; + } + } + } + for (var i = 0; i < this.messages.length; i++) { + var msg = this.messages[i]; + if (msg instanceof assignment) { + outmessages.push(new assignment(msg.symbol, msg.expression.quote(env))); + } else { + outmessages.push(msg.quote(env)); + } + } + return new object(outmessages); +}; + lambda.prototype.eval = function(parentenv) { var args = this.args; var exprs = this.expressions; @@ -380,7 +491,7 @@ } env.syms[args[j].cleanName()] = arguments[i]; } - if (this != null && (args.length == 0 || args[0].cleanName() != 'self')) { + if (this != null && !(args.length == 0 || args[0].cleanName() != 'self')) { env.syms['self'] = this; } var res = null; @@ -412,6 +523,22 @@ return this; }; +lambda.prototype.quote = function(parentenv) { + var args = []; + var expressions = []; + var env = new environment(parentenv); + for (var i = 0; i < this.args.length; i++) { + env.syms[this.args[i].cleanName()] = null; + var hygenic = '' + quote_prefix + this.args[i].cleanName(); + env.quotetrans[this.args[i].cleanName()] = hygenic; + args.push(new symbol(hygenic, this.args[i].symbols)); + } + for (var i = 0; i < this.expressions.length; i++) { + expressions.push(this.expressions[i].quote(env)); + } + return new lambda(args, expressions); +}; + assignment.prototype.eval = function(env) { var val = this.expression.eval(env); env.findSet(this.symbol.name, val); @@ -422,3 +549,11 @@ this.expression = this.expression.macroexpand(env); return this; }; + +assignment.prototype.quote = function(env) { + var name = this.symbol.cleanName(); + env.syms[name] = null; + var hygenic = '' + quote_prefix + name; + env.quotetrans[name] = hygenic; + return new assignment(new symbol(hygenic, this.symbol.symbols), this.expression.quote(env)); +};