# HG changeset patch # User Mike Pavone # Date 1385852627 28800 # Node ID d0848563f25de94d6ee1507a62cb41f36a6f04eb # Parent 4b3b57f39f10ab97a9bf4e45099feccfd7f271de Fix some bugs and allow proper access to list literals in interpreter/macro expander diff -r 4b3b57f39f10 -r d0848563f25d interp.js --- a/interp.js Wed Nov 27 23:36:24 2013 -0800 +++ b/interp.js Sat Nov 30 15:03:47 2013 -0800 @@ -77,6 +77,7 @@ var tptrue = null; var tpfalse = null; +var tplist = null; function topenv(moduledirs) { @@ -103,6 +104,12 @@ return false; }; } + if (!tplist) { + tplist = this.find('list'); + if (tplist instanceof Function) { + tplist = tplist.call(null); + } + } } topenv.prototype = { @@ -315,9 +322,16 @@ symbol.prototype.macroexpand = intlit.prototype.macroexpand = floatlit.prototype.macroexpand = - strlit.prototype.macroexpand = - arraylit.prototype.macroexpand = + strlit.prototype.macroexpand = function(env) { + return this; +}; + + +arraylit.prototype.macroexpand = listlit.prototype.macroexpand = function(env) { + for (var i = 0; i < this.val.length; i++) { + this.val[i] = this.val[i].macroexpand(env); + } return this; }; @@ -352,10 +366,17 @@ intlit.prototype.tpmeth_value = floatlit.prototype.tpmeth_value = strlit.prototype.tpmeth_value = - arraylit.prototype.tpmeth_value = - listlit.prototype.tpmeth_value = function() { + arraylit.prototype.tpmeth_value = function() { return this.val; -} +}; + +listlit.prototype.tpmeth_value = function() { + var cur = tplist.tpmeth_empty(); + for (var idx = this.val.length - 1; idx >= 0; --idx) { + cur = tplist['tpmeth_node:withTail'](this.val[idx], cur); + } + return cur; +}; funcall.prototype.eval = function(env) { var args = []; @@ -391,14 +412,18 @@ return args[1].call(null, res); } var fun = env.findNoTop(name); - if (fun) { + if (fun && (fun.numargs === undefined || fun.numargs == args.length)) { return fun.apply(null, args); } else { //if (typeof args[0]'tpmeth_'+name in args[0]) { 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]); + var msg = 'Error, \n\t' + e.message.split('\n').join('\n\t') + '\ninvoking method ' + name + ' on object ' + args[0]; + if (typeof args[0] == 'object') { + msg += ' with keys ' + JSON.stringify(Object.keys(args[0]) + ' and constructor ' + args[0].constructor.name); + } + throw new Error(msg); } /*} else {JSON.stringify throw new Error('No method named ' + name + ' on object ' + JSON.stringify(args[0])); @@ -474,19 +499,20 @@ obj['tpmeth_' + msg.symbol.name] = msg.expression.eval(env); (function(name) { env.syms[name] = function() { - return obj['tpmeth_' + name].apply(obj, arguments); + var ret = obj['tpmeth_' + name].apply(obj, arguments); + return ret; }; + env.syms[name].numargs = msg.expression.numArgs(); })(msg.symbol.name); } else { var makeProp = function(obj, name) { obj['tprop_' + name] = msg.expression.eval(env); - name = 'tpmeth_' + name; - obj[name] = function() { - return this[name]; + obj['tpmeth_' + name] = function() { + return this['tprop_'+name]; }; var setname = name+'!'; - obj[setname] = function(val) { - this[setname] = val; + obj['tpmeth_' + setname] = function(val) { + this['tprop_'+name] = val; return this; }; }; @@ -514,6 +540,7 @@ } return obj['tpmeth_' + name].apply(obj, arguments); }; + env.syms[name].numargs = expr.numArgs(); })(msg.symbol.name, msg.expression); outmessages.push(msg); } else if (msg.expression instanceof funcall && msg.expression.name == 'macro:') { @@ -585,7 +612,7 @@ } env.syms[args[j].cleanName()] = arguments[i]; } - if (this != null && !(args.length == 0 || args[0].cleanName() != 'self')) { + if (this != null) { env.syms['self'] = this; } var res = null; @@ -633,6 +660,14 @@ return new lambda(args, expressions); }; +lambda.prototype.numArgs = function() { + var num = this.args.length; + if (num && (this.args[0].cleanName() == 'self')) { + --num; + } + return num; +}; + lambda.prototype.tpmeth_nodeType = function() { return "lambda"; };