changeset 210:d0848563f25d

Fix some bugs and allow proper access to list literals in interpreter/macro expander
author Mike Pavone <pavone@retrodev.com>
date Sat, 30 Nov 2013 15:03:47 -0800
parents 4b3b57f39f10
children 53cd9c3bcf96
files interp.js
diffstat 1 files changed, 49 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- 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";
 };