comparison cbackend.js @ 34:a10f1b049193

Working closures, but need to rethink method call strategy
author Mike Pavone <pavone@retrodev.com>
date Mon, 09 Jul 2012 08:57:50 -0700
parents 64f1d516fbfd
children bf5e88f6419d
comparison
equal deleted inserted replaced
33:96e21f525b78 34:a10f1b049193
48 return ret; 48 return ret;
49 }; 49 };
50 50
51 function escapeCName(name) 51 function escapeCName(name)
52 { 52 {
53 if (name == 'self') {
54 return name;
55 }
53 name = name.replace("_", "UN_").replace(":", "CN_").replace("!", "EX_").replace('?', 'QS_').replace('@', 'AT_'); 56 name = name.replace("_", "UN_").replace(":", "CN_").replace("!", "EX_").replace('?', 'QS_').replace('@', 'AT_');
54 name = 'tp_' + name; 57 name = 'tp_' + name;
55 return name; 58 return name;
56 } 59 }
57 60
58 symbol.prototype.toC = function() { 61 symbol.prototype.toC = function() {
59 var name = this.cleanName(); 62 var name = this.cleanName();
60 if (name == 'self') {
61 return name;
62 }
63 var info = this.symbols.find(name); 63 var info = this.symbols.find(name);
64 if (!info) { 64 if (!info) {
65 throw new Error('symbol ' + name + ' not found'); 65 throw new Error('symbol ' + name + ' not found');
66 } 66 }
67 var pre = ''; 67 var pre = '';
68 if (info.type == 'self') { 68 console.log('symbol', info);
69 pre = this.symbols.selfVar() + '->'; 69 switch(info.type) {
70 } else if(info.type == 'parent') { 70 case 'self':
71 pre = this.symbols.selfVar() + '->'; 71 pre = 'self->';
72 break;
73 case 'parent':
74 pre = 'self->';
72 for (var i = 0; i < info.depth; ++i) { 75 for (var i = 0; i < info.depth; ++i) {
73 pre += 'parent->'; 76 pre += 'parent->';
74 } 77 }
75 } else if(info.type == 'upvar') { 78 break;
79 case 'upvar':
76 pre = 'env->'; 80 pre = 'env->';
77 for (var i = 1; i < info.depth; ++i) { 81 for (var i = 1; i < info.depth; ++i) {
78 pre += 'parent->'; 82 pre += 'parent->';
79 } 83 }
80 } else if (info.type == 'toplevel') { 84 break;
85 case 'toplevel':
81 pre = 'modules.'; 86 pre = 'modules.';
82 modules[name] = false; 87 modules[name] = false;
88 break;
89 case 'closedover':
90 pre = 'myenv->';
83 } 91 }
84 return pre + escapeCName(name); 92 return pre + escapeCName(name);
85 } 93 }
94
95 var declaredInts = {};
86 96
87 intlit.prototype.toC = function() { 97 intlit.prototype.toC = function() {
88 var str = this.val.toString(); 98 var str = this.val.toString();
89 toplevelcode += 'obj_int32 int32_' + str + ' = {{&obj_int32_meta, NULL}, ' + str + '};\n'; 99 if (!(this.val in declaredInts)) {
100 toplevelcode += 'obj_int32 int32_' + str + ' = {{&obj_int32_meta, NULL}, ' + str + '};\n';
101 declaredInts[this.val] = true;
102 }
90 return '((object *)&int32_' + str + ')'; 103 return '((object *)&int32_' + str + ')';
91 } 104 }
92 105
93 floatlit.prototype.toC = function() { 106 floatlit.prototype.toC = function() {
94 return 'make_float(' + this.val.toString() + ')'; 107 return 'make_float(' + this.val.toString() + ')';
272 { 285 {
273 var int32 = new cObject('obj_int32'); 286 var int32 = new cObject('obj_int32');
274 int32.addProperty('num', null, 'int32_t'); 287 int32.addProperty('num', null, 'int32_t');
275 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];'); 288 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];');
276 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];'); 289 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];');
290 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);');
277 forwarddec = toplevelcode = ''; 291 forwarddec = toplevelcode = '';
278 forwarddec += int32.toEarlyCDef(); 292 forwarddec += int32.toEarlyCDef();
279 toplevelcode += int32.toCDef(); 293 toplevelcode += int32.toCDef();
280 obj.populateSymbols(toplevel); 294 obj.populateSymbols(toplevel);
281 var rest = 'object * mainModule() {\n\treturn ' + obj.toC() + ';\n}\n'; 295 var rest = 'object * mainModule() {\n\tmain_module = ' + obj.toC() + ';\n\treturn main_module;\n}\n';
282 return '#include "runtime/proghead.inc"\n#define METHOD_ID_MAIN ' + getMethodId('main') + '\n' + forwarddec + toplevelcode + rest + '#include "runtime/progfoot.inc"\n'; 296 return '#include "runtime/proghead.inc"\n' +
297 '#define METHOD_ID_MAIN ' + getMethodId('main') + '\n' +
298 '#define METHOD_ID_TRUE ' + getMethodId('true') + '\n' +
299 '#define METHOD_ID_FALSE ' + getMethodId('false') + '\n' +
300 forwarddec + toplevelcode + rest + '#include "runtime/progfoot.inc"\n';
283 } 301 }
284 302
285 object.prototype.toCModule = function() { 303 object.prototype.toCModule = function() {
286 return makeCProg(this); 304 return makeCProg(this);
287 } 305 }
289 var lambdanum = 0; 307 var lambdanum = 0;
290 308
291 lambda.prototype.toC = function() { 309 lambda.prototype.toC = function() {
292 var args = this.args ? this.args.slice(0, this.args.length) : []; 310 var args = this.args ? this.args.slice(0, this.args.length) : [];
293 var exprs = this.expressions; 311 var exprs = this.expressions;
312 var mynum = lambdanum++;
313 if (Object.keys(this.symbols.closedover).length) {
314 this.symbols.envtype = 'lambda_' + mynum + '_env';
315 }
294 if (this.selftype) { 316 if (this.selftype) {
317 this.symbols.defineVar('self', this.selftype);
295 if (args[0] && args[0].cleanName() == 'self') { 318 if (args[0] && args[0].cleanName() == 'self') {
296 args.splice(0, 1); 319 args.splice(0, 1);
297 } 320 }
298 var offset = 1; 321 var offset = 1;
299 } else { 322 } else {
300 var offset = 0; 323 var offset = 0;
301 } 324 }
302 for (var i = 0; i < args.length; ++i) { 325 for (var i = 0; i < args.length; ++i) {
303 args[i] = '\tobject * ' + args[i].toC() + ' = params[' + (offset + i) + '];\n'; 326 var argname = args[i].toC();
327
328 args[i] = (argname.indexOf('->') < 0 ? '\tobject * ' : '\t') + argname + ' = params[' + (offset + i) + '];\n';
304 } 329 }
305 var compiled = [] 330 var compiled = []
306 for (var i in exprs) { 331 for (var i in exprs) {
307 var js = exprs[i].toC(); 332 var js = exprs[i].toC();
308 if (js) { 333 if (js) {
311 } 336 }
312 exprs = compiled; 337 exprs = compiled;
313 if (exprs.length) { 338 if (exprs.length) {
314 exprs[exprs.length-1] = 'return ' + exprs[exprs.length-1] + ';'; 339 exprs[exprs.length-1] = 'return ' + exprs[exprs.length-1] + ';';
315 } 340 }
316 var mynum = lambdanum++; 341
317 toplevelcode += 'object * lambda_' + mynum + ' (void * env, uint32_t num_args, object ** params) {\n'; 342 if (Object.keys(this.symbols.closedover).length) {
343 forwarddec += 'typedef struct {\n';
344 for (var varname in this.symbols.closedover) {
345 forwarddec += '\tobject * ' + escapeCName(varname) + ';\n';
346 }
347 forwarddec += '} lambda_' + mynum + '_env;\n'
348
349 var myenvinit = '\tlambda_' + mynum + '_env * myenv = malloc(sizeof(lambda_' + mynum + '_env));\n';
350 this.symbols.envtype = 'lambda_' + mynum + '_env';
351 } else {
352 var myenvinit = '';
353 }
354
355 toplevelcode += 'object * lambda_' + mynum + ' (' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, object ** params) {\n' + myenvinit;
318 if (this.selftype) { 356 if (this.selftype) {
319 toplevelcode += '\t' + this.selftype + ' * self = (' + this.selftype + ' *)params[0];\n'; 357 var selfvar = (new symbol('self', this.symbols)).toC();
358 if (selfvar == 'self') {
359 toplevelcode += '\t' + this.selftype + ' * self = (' + this.selftype + ' *)params[0];\n';
360 } else {
361 toplevelcode += '\t' + selfvar + ' = (' + this.selftype + ' *)params[0];\n';
362 }
363
320 } 364 }
321 toplevelcode += args.join('') + exprs.join(';\n\t') + '\n}\n'; 365 toplevelcode += args.join('') + exprs.join(';\n\t') + '\n}\n';
322 366
323 toplevelcode += 'closure lambda_obj_' + mynum + ' = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n'; 367 if (this.symbols.parentEnvType() != 'void') {
324 return '((object *)&lambda_obj_' + mynum + ')'; 368 if (this.symbols.passthruenv) {
369 var envvar = 'env';
370 } else {
371 var envvar = 'myenv';
372 }
373 return 'make_closure(' + envvar + ', lambda_' + mynum + ')';
374 } else {
375 toplevelcode += 'closure lambda_obj_' + mynum + ' = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n';
376 return '((object *)&lambda_obj_' + mynum + ')';
377 }
325 }; 378 };
326 lambda.prototype.toCObject = function(typename) { 379 lambda.prototype.toCObject = function(typename) {
327 this.selftype = typename; 380 this.selftype = typename;
328 return this.toC(); 381 return this.toC();
329 }; 382 };
334 assignment.prototype.toC = function() { 387 assignment.prototype.toC = function() {
335 var existing = this.symbols.find(this.symbol.name); 388 var existing = this.symbols.find(this.symbol.name);
336 var prefix = ''; 389 var prefix = '';
337 if (!existing) { 390 if (!existing) {
338 prefix = 'object * '; 391 prefix = 'object * ';
339 } else {
340 switch (existing.type)
341 {
342 case 'self':
343 prefix = 'self->';
344 break;
345 case 'parent':
346 prefix = 'self->header.';
347 for (var i = 0; i < existing.depth; ++i) {
348 prefix += 'parent->';
349 }
350 break;
351 }
352 } 392 }
353 var val = this.expression.toC(); 393 var val = this.expression.toC();
354 if (val === null) { 394 if (val === null) {
355 return null; 395 return null;
356 } 396 }