diff cbackend.js @ 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 a6bf4869fcbe
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);
 	}