Mercurial > repos > tabletprog
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); }