changeset 35:bf5e88f6419d

Use a function/method call strategy that actually works
author Mike Pavone <pavone@retrodev.com>
date Mon, 09 Jul 2012 21:32:28 -0700
parents a10f1b049193
children 3b0503a67165
files cbackend.js compiler.js runtime/object.c runtime/object.h runtime/progfoot.inc runtime/proghead.inc
diffstat 6 files changed, 64 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/cbackend.js	Mon Jul 09 08:57:50 2012 -0700
+++ b/cbackend.js	Mon Jul 09 21:32:28 2012 -0700
@@ -42,10 +42,7 @@
 op.prototype.toC = function(isReceiver) {
 	var optoMeth = {'+': 'ADD_', '-': 'SUB_', '*': 'MUL_', '/': 'DIV_', '=': 'EQ_', '!=': 'NEQ_', '<': 'LT_', '>': 'GT_', '>=': 'GEQ_', '<=': 'LEQ_'};
 	var method = optoMeth[this.op];
-	var ret = '(params[0] = ' + this.left.toC() + ',\n';
-	ret += 'params[1] = ' + this.right.toC() + ',\n';
-	ret += 'mcall(' + getMethodId(method) + ', 2, params))\n';
-	return ret;
+	return 'mcall(' + getMethodId(method) + ', 2, ' + this.left.toC() + ', ' + this.right.toC() + ')\n';
 };
 
 function escapeCName(name)
@@ -65,7 +62,6 @@
 		throw new Error('symbol ' + name + ' not found');
 	}
 	var pre = '';
-	console.log('symbol', info);
 	switch(info.type) {
 	case 'self':
 		pre = 'self->';
@@ -158,7 +154,7 @@
 		}
 	}
 	for (var i in args) {
-		args[i] = 'params[' + i + '] = ' + args[i].toC() + ',\n';
+		args[i] = ', ' + args[i].toC();
 	}
 	var callpart;
 	if (method) {
@@ -166,7 +162,7 @@
 	} else {
 		callpart = 'ccall(' + escapeCName(name);
 	}
-	return '(' + args.join('') + callpart + ', ' + args.length + ', ' + 'params))';
+	return callpart + ', ' + args.length + args.join('') + ')';
 }
 
 function cObject(name) {
@@ -174,6 +170,7 @@
 	this.slots = {};
 	this.properties = [];
 	this.values = [];
+	this.slotvars = {};
 }
 
 cObject.prototype.addMessage = function(msgname, implementation) {
@@ -190,13 +187,22 @@
 		this.properties.push([propname, type]);
 	} else {
 		var escaped = escapeCName(propname);
-		this.addMessage(propname, 'return self->' + escaped + ';');
-		this.addMessage(propname + '!', 'self->' + escaped + ' = params[1]; return params[0];');
+		this.addMessage(propname, 'va_end(args); return self->' + escaped + ';');
+		this.addMessageVar(propname + '!', 'setval', 'object *');
+		this.addMessage(propname + '!', 'setval = va_arg(args, object *); va_end(args); self->' + escaped + ' = setval; return (object *)self;');
 		this.properties.push(escaped);
 		this.values.push(value);
 	}
 }
 
+cObject.prototype.addMessageVar = function(msgname, varname, type) {
+	var trunc = getMethodId(msgname) & 0xF;
+	if (!(trunc in this.slotvars)) {
+		this.slotvars[trunc] = {};
+	}
+	this.slotvars[trunc][varname] = type;
+}
+
 cObject.prototype.toEarlyCDef = function() {
 	var objdef =  'typedef struct {\n\tobject header;\n';
 	for (var i in this.properties) {
@@ -218,20 +224,24 @@
 			metadef += ', ';
 		}
 		if (i in this.slots) {
-			slotdefs += 'object * ' + this.name + '_slot_' + i + '(uint32_t method_id, uint32_t num_params, object ** params) {\n\t' +
-				this.name + ' *self = (' + this.name + ' *)params[0];';
+			slotdefs += 'object * ' + this.name + '_slot_' + i + '(uint32_t method_id, uint32_t num_params, object * oself, va_list args) {\n\t' +
+				this.name + ' *self = (' + this.name + ' *)oself;\n';
+			for (var varname in this.slotvars[i]) {
+				slotdefs += '\t' + this.slotvars[i][varname] + ' ' + varname + ';\n';
+			}
 			if (this.slots[i].length == 1) {
 				slotdefs += '\tif (method_id == ' + this.slots[i][0][0] + ') { /* ' + this.slots[i][0][2] + '*/\n' +
 					'\t\t' + this.slots[i][0][1] + '\n' + 
 					'\t}\n' +
-					'\treturn no_impl(method_id, num_params, params);\n}\n';
+					'\treturn no_impl(method_id, num_params, (object *)self, args);\n}\n';
 			} else {
 				slotdefs += '\tswitch(method_id) {\n';
 				for (j in this.slots[i]) {
 					slotdefs += '\t\tcase ' + this.slots[i][j][0] + ': /* ' + this.slots[i][j][2] + '*/\n' +
 						'\t\t\t' + this.slots[i][j][1] + '\n';
 				}
-				slotdefs += '\t\tdefault:\n\treturn no_impl(method_id, num_params, params);\n}\n';
+				slotdefs += '\t\tdefault:\n' +
+					'\treturn no_impl(method_id, num_params, params, args);\n}\n';
 			}
 			metadef += this.name + '_slot_' + i;
 		} else {
@@ -285,9 +295,14 @@
 {
 	var int32 = new cObject('obj_int32');
 	int32.addProperty('num', null, 'int32_t');
-	int32.addMessage('ADD_', 'params[0] = make_object(&obj_int32_meta, NULL, 0); ((obj_int32 *)params[0])->num = self->num + ((obj_int32 *)params[1])->num; return params[0];');
-	int32.addMessage('SUB_', 'params[0] = make_object(&obj_int32_meta, NULL, 0); ((obj_int32 *)params[0])->num = self->num - ((obj_int32 *)params[1])->num; return params[0];');
-	int32.addMessage('LT_', 'params[0] = main_module; if (self->num < ((obj_int32 *)params[1])->num) { return mcall(METHOD_ID_TRUE, 1, params); } return mcall(METHOD_ID_FALSE, 1, params);');
+	int32.addMessageVar('ADD_', 'ret', 'obj_int32 *');
+	int32.addMessageVar('ADD_', 'argb', 'obj_int32 *');
+	int32.addMessage('ADD_', 'argb = va_arg(args, obj_int32 *); ret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0); ret->num = self->num + argb->num; return ret;');
+	int32.addMessageVar('SUB_', 'ret', 'obj_int32 *');
+	int32.addMessageVar('SUB_', 'argb', 'obj_int32 *');
+	int32.addMessage('SUB_', 'argb = va_arg(args, obj_int32 *); ret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0); ret->num = self->num - argb->num; return ret;');
+	int32.addMessageVar('LT_', 'argb', 'obj_int32 *');
+	int32.addMessage('LT_', 'argb = va_arg(args, obj_int32 *); if (self->num < argb->num) { return mcall(METHOD_ID_TRUE, 1, main_module); } return mcall(METHOD_ID_FALSE, 1, main_module);');
 	forwarddec = toplevelcode = '';
 	forwarddec += int32.toEarlyCDef();
 	toplevelcode += int32.toCDef();
@@ -325,7 +340,7 @@
 	for (var i = 0; i < args.length; ++i) {
 		var argname = args[i].toC();
 		
-		args[i] = (argname.indexOf('->') < 0 ? '\tobject * ' : '\t') + argname + ' = params[' + (offset + i) + '];\n';
+		args[i] = (argname.indexOf('->') < 0 ? '\tobject * ' : '\t') + argname + ' = va_arg(args, object *);\n';
 	}
 	var compiled = []
 	for (var i in exprs) {
@@ -352,17 +367,17 @@
 		var myenvinit = '';
 	}
 	
-	toplevelcode +=  'object * lambda_' + mynum + ' (' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, object ** params) {\n' + myenvinit;
+	toplevelcode +=  'object * lambda_' + mynum + ' (' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...) {\n\tva_list args;\n' + myenvinit + '\tva_start(args, num_args);\n';
 	if (this.selftype) {
 		var selfvar = (new symbol('self', this.symbols)).toC();
 		if (selfvar == 'self') {
-			toplevelcode += '\t' + this.selftype + ' * self = (' + this.selftype + ' *)params[0];\n';
+			toplevelcode += '\t' + this.selftype + ' * self = va_arg(args, ' + this.selftype + ' *);\n';
 		} else {
-			toplevelcode += '\t' + selfvar  + ' = (' + this.selftype + ' *)params[0];\n';
+			toplevelcode += '\t' + selfvar  + ' = va_arg(args, ' + this.selftype + ' *);\n';
 		}
 		
 	}
-	toplevelcode += args.join('') + exprs.join(';\n\t') + '\n}\n';
+	toplevelcode += args.join('') + '\tva_end(args);\n' + exprs.join(';\n\t') + '\n}\n';
 	
 	if (this.symbols.parentEnvType() != 'void') {
 		if (this.symbols.passthruenv) {
@@ -406,7 +421,17 @@
 		return;
 	}
 	if (this.expression instanceof lambda) {
-		cobj.addMessage(this.symbol.name, 'return ccall(' + val + ', num_params, params);');
+		var params = ['((object *)self)'];
+		var paramget = '';
+		for (var i in this.expression.args) {
+			var escaped = escapeCName(this.expression.args[i].cleanName());
+			if (escaped != 'self') {
+				cobj.addMessageVar(this.symbol.name, escaped, 'object *');
+				params.push(escaped);
+				paramget += escaped + ' =  va_arg(args, object *); ';
+			}
+		}
+		cobj.addMessage(this.symbol.name, paramget + 'return ccall(' + val + ', ' + params.length + (params.length ? ', ' : '') + params.join(', ') + ');');
 	} else {
 		cobj.addProperty(this.symbol.name, val);
 	}
--- a/compiler.js	Mon Jul 09 08:57:50 2012 -0700
+++ b/compiler.js	Mon Jul 09 21:32:28 2012 -0700
@@ -9,12 +9,10 @@
 	this.names = null;
 	var self = this;
 	get('/src/', function(data) {
-		console.log(data);
 		self.names = {};
 		var fakeEl = newEl("div", {
 			innerHTML: data.response
 		});
-		console.log(fakeEl);
 		each(qall('a', fakeEl), function(idx, a) {
 			var tpidx = a.textContent.indexOf('.tp');
 			if (tpidx > -1) {
@@ -24,11 +22,9 @@
 	});
 }
 topsymbols.prototype.find = function(name) {
-	console.log(this.names);
 	if (!this.names) {
 		throw new Error('data not ready');
 	}
-	console.log('toplevel', name);
 	if (name in this.names) {
 		return {
 			type: 'toplevel',
@@ -99,7 +95,6 @@
 	return curlist;
 }
 osymbols.prototype.getEnvType = function() {
-	console.log('osymbol parent', this.parent);
 	return this.parent.getEnvType();
 }
 
@@ -113,7 +108,6 @@
 	this.envtype = 'void';
 }
 lsymbols.prototype.find = function(name, nestedcall) {
-	console.log('find', name, nestedcall);
 	if (name in this.names) {
 		if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') {
 			return {
@@ -122,7 +116,6 @@
 			};
 		}
 		if (nestedcall) {
-			console.log('closedover', name);
 			this.closedover[name] = true;
 		} 
 		if (name in this.closedover) {
@@ -180,7 +173,6 @@
 };
 lsymbols.prototype.getEnvType = function() {
 	if (this.passthruenv) {
-		console.log('lsymbol parent', this.parent);
 		return this.parent.getEnvType();
 	} else {
 		return this.envtype;
--- a/runtime/object.c	Mon Jul 09 08:57:50 2012 -0700
+++ b/runtime/object.c	Mon Jul 09 21:32:28 2012 -0700
@@ -30,3 +30,12 @@
 	ret->func = func;
 	return (object *) ret;
 }
+
+object * mcall(uint32_t method_id, uint32_t num_args, object * self, ...)
+{
+	va_list args;
+	va_start(args, self);
+	object * ret = self->meta->meth_lookup[method_id & 0xF](method_id, num_args, self, args);
+	va_end(args);
+	return ret;
+}
--- a/runtime/object.h	Mon Jul 09 08:57:50 2012 -0700
+++ b/runtime/object.h	Mon Jul 09 21:32:28 2012 -0700
@@ -2,6 +2,7 @@
 #define OBJECT_H_
 
 #include <stdint.h>
+#include <stdarg.h>
 
 typedef struct obj_meta obj_meta;
 
@@ -11,9 +12,9 @@
 	struct object * parent;
 } object;
 
-typedef object * (*method)(uint32_t method_id, uint32_t num_args, object **);
+typedef object * (*method)(uint32_t method_id, uint32_t num_args, object * self, va_list args);
 
-typedef object * (*closure_func)(void *, uint32_t, object **);
+typedef object * (*closure_func)(void *, uint32_t, ...);
 
 typedef struct closure
 {
@@ -30,8 +31,8 @@
 
 extern obj_meta lambda_meta;
 
-#define mcall(method_id, num_args, args) (args[0])->meta->meth_lookup[method_id & 0xF](method_id, num_args, args)
-#define ccall(clos, num_args, args) (((closure *)clos)->func(((closure *)clos)->env, num_args, args))
+object * mcall(uint32_t method_id, uint32_t num_args, object * self, ...);
+#define ccall(clos, num_args, ...) (((closure *)clos)->func(((closure *)clos)->env, num_args,##__VA_ARGS__))
 
 object * make_object(obj_meta * meta, void * parent, int num_props, ...);
 object * make_closure(void * env, closure_func func);
--- a/runtime/progfoot.inc	Mon Jul 09 08:57:50 2012 -0700
+++ b/runtime/progfoot.inc	Mon Jul 09 21:32:28 2012 -0700
@@ -1,10 +1,7 @@
 
 int main(int argc, char ** argv)
 {
-	object * params[64];
-	params[0] = mainModule();
-	object * ret = mcall(METHOD_ID_MAIN, 1, params);
-	printf("%p:%p\n", ret->meta, &obj_int32_meta);
+	object * ret = mcall(METHOD_ID_MAIN, 1, mainModule());
 	if (ret->meta == &obj_int32_meta) {
 		obj_int32 * reti32 = (obj_int32 *) ret;
 		printf("%d\n", reti32->num);
--- a/runtime/proghead.inc	Mon Jul 09 08:57:50 2012 -0700
+++ b/runtime/proghead.inc	Mon Jul 09 21:32:28 2012 -0700
@@ -5,9 +5,9 @@
 
 object * main_module;
 
-object * no_impl(uint32_t method_id, uint32_t num_args, object ** params)
+object * no_impl(uint32_t method_id, uint32_t num_args, object * self, va_list args)
 {
-	printf("method %d is not implemented on object %p\n", method_id, params[0]);
+	printf("method %d is not implemented on object %p\n", method_id, self);
 	printf("main_module %p\n", main_module);
 	exit(0);
 	return NULL;