comparison cbackend.js @ 42:4e983fe32047

Fix closures as methods so that private vars work
author Mike Pavone <pavone@retrodev.com>
date Thu, 12 Jul 2012 20:14:15 -0700
parents 0558dad9d061
children 27a2167663dd
comparison
equal deleted inserted replaced
41:0558dad9d061 42:4e983fe32047
53 name = name.replace("_", "UN_").replace(":", "CN_").replace("!", "EX_").replace('?', 'QS_').replace('@', 'AT_'); 53 name = name.replace("_", "UN_").replace(":", "CN_").replace("!", "EX_").replace('?', 'QS_').replace('@', 'AT_');
54 name = 'tp_' + name; 54 name = 'tp_' + name;
55 return name; 55 return name;
56 } 56 }
57 57
58 symbol.prototype.toC = function() { 58 function getSymbolPrefix(info)
59 var name = this.cleanName(); 59 {
60 var info = this.symbols.find(name);
61 if (!info) {
62 throw new Error('symbol ' + name + ' not found');
63 }
64 var pre = ''; 60 var pre = '';
65 switch(info.type) { 61 switch(info.type) {
66 case 'self': 62 case 'self':
67 pre = 'self->'; 63 pre = 'self->';
68 break; 64 break;
76 pre = 'env->'; 72 pre = 'env->';
77 for (var i = 1; i < info.depth; ++i) { 73 for (var i = 1; i < info.depth; ++i) {
78 pre += 'parent->'; 74 pre += 'parent->';
79 } 75 }
80 break; 76 break;
77 case 'recupvar':
78 if (info.subtype == 'object') {
79 pre = 'self->env->';
80 } else {
81 //TODO: fill this case in if necessary
82 }
83 pre += getSymbolPrefix(info.parent);
81 case 'toplevel': 84 case 'toplevel':
82 pre = 'modules.'; 85 pre = 'modules.';
83 modules[name] = false; 86 modules[name] = false;
84 break; 87 break;
85 case 'closedover': 88 case 'closedover':
86 pre = 'myenv->'; 89 pre = 'myenv->';
87 } 90 }
88 return pre + escapeCName(name); 91 return pre;
92 }
93
94 symbol.prototype.toC = function() {
95 var name = this.cleanName();
96 var info = this.symbols.find(name);
97 if (!info) {
98 throw new Error('symbol ' + name + ' not found');
99 }
100
101 return getSymbolPrefix(info) + escapeCName(name);
89 } 102 }
90 103
91 var declaredInts = {}; 104 var declaredInts = {};
92 105
93 intlit.prototype.toC = function() { 106 intlit.prototype.toC = function() {
144 } 157 }
145 var args = this.args.slice(0, this.args.length); 158 var args = this.args.slice(0, this.args.length);
146 if (this.receiver) { 159 if (this.receiver) {
147 args.splice(0, 0, this.receiver); 160 args.splice(0, 0, this.receiver);
148 } 161 }
149 var method = false; 162 var method = false;
150 var funinfo = this.symbols.find(name); 163 var funinfo = this.symbols.find(name);
151 if (!funinfo || funinfo.def instanceof setter) { 164 if (!funinfo || funinfo.def instanceof setter) {
152 method = true; 165 method = true;
153 } else { 166 } else {
154 switch(funinfo.type) 167 switch(funinfo.type)
155 { 168 {
156 case 'self': 169 case 'self':
157 if (args.length < funinfo.def.args.length || funinfo.def.args[0].name != 'self') { 170
171 if (args.length < funinfo.def.args.length || !funinfo.def.args.length || funinfo.def.args[0].name != 'self') {
158 args.splice(0, 0, new symbol('self', this.symbols)); 172 args.splice(0, 0, new symbol('self', this.symbols));
159 } else { 173 } else {
160 args.splice(0, 1); 174 args.splice(0, 1);
161 } 175 }
162 method = true; 176 method = true;
205 } 219 }
206 220
207 cObject.prototype.addProperty = function(propname, value, type) { 221 cObject.prototype.addProperty = function(propname, value, type) {
208 if (type != undefined) { 222 if (type != undefined) {
209 this.properties.push([propname, type]); 223 this.properties.push([propname, type]);
224 if (value !== null) {
225 this.values.push(value);
226 }
210 } else { 227 } else {
211 var escaped = escapeCName(propname); 228 var escaped = escapeCName(propname);
212 this.addMessage(propname, { 229 this.addMessage(propname, {
213 vars: {}, 230 vars: {},
214 lines: [ 231 lines: [
286 object.prototype.toC = function() { 303 object.prototype.toC = function() {
287 var messages = this.messages; 304 var messages = this.messages;
288 var values = []; 305 var values = [];
289 var imports = [] 306 var imports = []
290 var me = new cObject('object_' + nextobject++); 307 var me = new cObject('object_' + nextobject++);
308 if (this.symbols.needsenv) {
309 me.addProperty('env', this.symbols.envVar(), 'struct ' + this.symbols.getEnvType() + ' * ');
310 me.hasenv = true;
311 }
291 for (var i in messages) { 312 for (var i in messages) {
292 if (messages[i] instanceof funcall) { 313 if (messages[i] instanceof funcall) {
293 if (messages[i].name == 'import:' && messages[i].args.length == 1) { 314 if (messages[i].name == 'import:' && messages[i].args.length == 1) {
294 imports.push({symbols: false, src: messages[i].args[0]}); 315 imports.push({symbols: false, src: messages[i].args[0]});
295 } else if(messages[i].name == 'import:from:' && messages[i].args.length == 2) { 316 } else if(messages[i].name == 'import:from:' && messages[i].args.length == 2) {
306 } 327 }
307 } else { 328 } else {
308 messages[i].toCObject(me); 329 messages[i].toCObject(me);
309 } 330 }
310 } 331 }
332
311 forwarddec += me.toEarlyCDef(); 333 forwarddec += me.toEarlyCDef();
312 toplevelcode += me.toCDef(); 334 toplevelcode += me.toCDef();
313 return me.toCInstance(); 335 return me.toCInstance();
314 } 336 }
315 337
489 if (exprs.length) { 511 if (exprs.length) {
490 exprs[exprs.length-1] = 'return ' + exprs[exprs.length-1] + ';'; 512 exprs[exprs.length-1] = 'return ' + exprs[exprs.length-1] + ';';
491 } 513 }
492 514
493 if (Object.keys(this.symbols.closedover).length) { 515 if (Object.keys(this.symbols.closedover).length) {
494 forwarddec += 'typedef struct {\n'; 516 forwarddec += 'typedef struct lambda_' + mynum + '_env {\n';
495 for (var varname in this.symbols.closedover) { 517 for (var varname in this.symbols.closedover) {
496 forwarddec += '\tobject * ' + escapeCName(varname) + ';\n'; 518 forwarddec += '\tobject * ' + escapeCName(varname) + ';\n';
497 } 519 }
498 forwarddec += '} lambda_' + mynum + '_env;\n' 520 forwarddec += '} lambda_' + mynum + '_env;\n'
499 521
513 } 535 }
514 536
515 } 537 }
516 toplevelcode += args.join('') + '\tva_end(args);\n' + exprs.join(';\n\t') + '\n}\n'; 538 toplevelcode += args.join('') + '\tva_end(args);\n' + exprs.join(';\n\t') + '\n}\n';
517 539
518 if (this.symbols.parentEnvType() != 'void') { 540 if (this.selftype) {
519 if (this.symbols.passthruenv) { 541 return 'lambda_' + mynum;
520 var envvar = 'env'; 542 } else {
521 } else { 543 if (this.symbols.parentEnvType() != 'void') {
522 var envvar = 'myenv'; 544 if (this.symbols.passthruenv) {
523 } 545 var envvar = 'env';
524 return 'make_closure(' + envvar + ', lambda_' + mynum + ')'; 546 } else {
525 } else { 547 var envvar = 'myenv';
526 toplevelcode += 'closure lambda_obj_' + mynum + ' = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n'; 548 }
527 return '((object *)&lambda_obj_' + mynum + ')'; 549 return 'make_closure(' + envvar + ', lambda_' + mynum + ')';
550 } else {
551 toplevelcode += 'closure lambda_obj_' + mynum + ' = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n';
552 return '((object *)&lambda_obj_' + mynum + ')';
553 }
528 } 554 }
529 }; 555 };
530 lambda.prototype.toCObject = function(typename) { 556 lambda.prototype.toCObject = function(typename) {
531 this.selftype = typename; 557 this.selftype = typename;
532 return this.toC(); 558 return this.toC();
569 paramget += escaped + ' = va_arg(args, object *); '; 595 paramget += escaped + ' = va_arg(args, object *); ';
570 } 596 }
571 } 597 }
572 cobj.addMessage(this.symbol.name, { 598 cobj.addMessage(this.symbol.name, {
573 vars: messagevars, 599 vars: messagevars,
574 lines: [paramget + 'return ccall(' + val + ', ' + params.length + (params.length ? ', ' : '') + params.join(', ') + ');'] 600 lines: [paramget + 'return ' + val + '(' + (cobj.hasenv ? 'self->env' : 'NULL') + ', ' + params.length + (params.length ? ', ' : '') + params.join(', ') + ');']
575 }); 601 });
576 } else { 602 } else {
577 cobj.addProperty(this.symbol.name, val); 603 cobj.addProperty(this.symbol.name, val);
578 } 604 }
579 }; 605 };