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