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