comparison cbackend.js @ 68:3a169ebb3224

Change strategy for handling true and false to avoid some initialization order problems and improve performance. Add support for negative integer literals. Update samples to reflect true/false change.
author Mike Pavone <pavone@retrodev.com>
date Sat, 14 Jul 2012 16:14:01 -0700
parents 42d5660b30b4
children ba032565c7a5
comparison
equal deleted inserted replaced
67:42d5660b30b4 68:3a169ebb3224
94 var info = this.symbols.find(name); 94 var info = this.symbols.find(name);
95 if (!info) { 95 if (!info) {
96 throw new Error('symbol ' + name + ' not found'); 96 throw new Error('symbol ' + name + ' not found');
97 } 97 }
98 if (info.type == 'toplevel') { 98 if (info.type == 'toplevel') {
99 return info.def.modulevar; 99
100 return toplevel.moduleVar(name);
100 } 101 }
101 return getSymbolPrefix(info, this.symbols) + escapeCName(name); 102 return getSymbolPrefix(info, this.symbols) + escapeCName(name);
102 } 103 }
103 104
104 var declaredInts = {}; 105 var declaredInts = {};
105 106
106 intlit.prototype.toC = function() { 107 intlit.prototype.toC = function() {
107 var str = this.val.toString(); 108 var str = this.val < 0 ? 'neg_' + (0-this.val).toString() : this.val.toString();
108 if (!(this.val in declaredInts)) { 109 if (!(this.val in declaredInts)) {
109 toplevelcode += 'obj_int32 int32_' + str + ' = {{&obj_int32_meta, NULL}, ' + str + '};\n'; 110 toplevelcode += 'obj_int32 int32_' + str + ' = {{&obj_int32_meta, NULL}, ' + this.val.toString() + '};\n';
110 declaredInts[this.val] = true; 111 declaredInts[this.val] = true;
111 } 112 }
112 return '((object *)&int32_' + str + ')'; 113 return '((object *)&int32_' + str + ')';
113 } 114 }
114 115
264 }); 265 });
265 this.initmsgadded = true; 266 this.initmsgadded = true;
266 } 267 }
267 } 268 }
268 269
270 cObject.prototype.populateSymbols = function() {};
269 271
270 cObject.prototype.toEarlyCDef = function() { 272 cObject.prototype.toEarlyCDef = function() {
271 this.checkInitMsg(); 273 this.checkInitMsg();
272 var includes = ''; 274 var includes = '';
273 for (var file in this.includes) { 275 for (var file in this.includes) {
398 cobject.addMessage(opname, { 400 cobject.addMessage(opname, {
399 vars: {argb: objtype + ' *'}, 401 vars: {argb: objtype + ' *'},
400 lines: [ 402 lines: [
401 'argb = va_arg(args, ' + objtype + ' *);', 403 'argb = va_arg(args, ' + objtype + ' *);',
402 'if (self->num ' + cop + ' argb->num) {', 404 'if (self->num ' + cop + ' argb->num) {',
403 ' return mcall(METHOD_ID_TRUE, 1, main_module);', 405 ' return ' + toplevel.moduleVar('true') + ';',
404 '}', 406 '}',
405 'return mcall(METHOD_ID_FALSE, 1, main_module);' 407 'return ' + toplevel.moduleVar('false') + ';',
406 ] 408 ]
407 }); 409 });
408 } 410 }
409 411
410 function makeInt32() 412 function makeInt32()
447 lines: [ 449 lines: [
448 'index = va_arg(args, obj_int32 *);', 450 'index = va_arg(args, obj_int32 *);',
449 'if (index->num >= 0 && index->num < self->size) {', 451 'if (index->num >= 0 && index->num < self->size) {',
450 ' return self->data[index->num];', 452 ' return self->data[index->num];',
451 '}', 453 '}',
452 'return mcall(METHOD_ID_FALSE, 1, main_module);' 454 'return ' + toplevel.moduleVar('false') + ';'
453 ] 455 ]
454 }); 456 });
455 array.addMessage('set', { 457 array.addMessage('set', {
456 vars: {index: 'obj_int32 *'}, 458 vars: {index: 'obj_int32 *'},
457 lines: [ 459 lines: [
526 string.addMessage('EQ_', { 528 string.addMessage('EQ_', {
527 vars: {argb: 'string *'}, 529 vars: {argb: 'string *'},
528 lines: [ 530 lines: [
529 'argb = va_arg(args, string *);', 531 'argb = va_arg(args, string *);',
530 'if (self->length == argb->length && self->bytes == argb->bytes && !memcmp(self->data, argb->data, self->bytes)) {', 532 'if (self->length == argb->length && self->bytes == argb->bytes && !memcmp(self->data, argb->data, self->bytes)) {',
531 ' return mcall(METHOD_ID_TRUE, 1, main_module);', 533 ' return ' + toplevel.moduleVar('true') + ';',
532 '}', 534 '}',
533 'return mcall(METHOD_ID_FALSE, 1, main_module);' 535 'return ' + toplevel.moduleVar('false') + ';',
534 ] 536 ]
535 }); 537 });
536 string.addMessage('NEQ_', { 538 string.addMessage('NEQ_', {
537 vars: {argb: 'string *'}, 539 vars: {argb: 'string *'},
538 lines: [ 540 lines: [
539 'argb = va_arg(args, string *);', 541 'argb = va_arg(args, string *);',
540 'if (self->length != argb->length || self->bytes != argb->bytes || memcmp(self->data, argb->data, self->bytes)) {', 542 'if (self->length != argb->length || self->bytes != argb->bytes || memcmp(self->data, argb->data, self->bytes)) {',
541 ' return mcall(METHOD_ID_TRUE, 1, main_module);', 543 ' return ' + toplevel.moduleVar('true') + ';',
542 '}', 544 '}',
543 'return mcall(METHOD_ID_FALSE, 1, main_module);' 545 'return ' + toplevel.moduleVar('false') + ';',
544 ] 546 ]
545 }); 547 });
546 string.addMessage('print', { 548 string.addMessage('print', {
547 vars: {}, 549 vars: {},
548 lines: [ 550 lines: [
584 { 586 {
585 var clos = new cObject('lambda'); 587 var clos = new cObject('lambda');
586 clos.addProperty('env', null, 'void *'); 588 clos.addProperty('env', null, 'void *');
587 clos.addProperty('func', null, 'closure_func'); 589 clos.addProperty('func', null, 'closure_func');
588 clos.addMessage('while:do', { 590 clos.addMessage('while:do', {
589 vars: {action: 'lambda *', valtrue: 'object *', ret: 'object *'}, 591 vars: {action: 'lambda *', ret: 'object *'},
590 lines: [ 592 lines: [
591 'action = va_arg(args, lambda *);', 593 'action = va_arg(args, lambda *);',
592 'valtrue = mcall(METHOD_ID_TRUE, 1, main_module);', 594 'ret = ' + toplevel.moduleVar('true') + ';',
593 'ret = valtrue;', 595 'while(' + toplevel.moduleVar('true') + ' == ccall(self, 0)) {',
594 'while(valtrue == ccall(self, 0)) {',
595 ' ccall(action, 0);', 596 ' ccall(action, 0);',
596 '}', 597 '}',
597 'return ret;' 598 'return ret;'
598 ] 599 ]
599 }); 600 });
708 ] 709 ]
709 }); 710 });
710 toplevel.names['os'] = os; 711 toplevel.names['os'] = os;
711 } 712 }
712 713
714 modulefile.prototype.populateSymbols = function (toplevel) {
715 if (!this.ast) {
716 this.ast = parseFile(this.path + '/' + this.file);
717 this.ast.populateSymbols(toplevel);
718 }
719 };
720
713 modulefile.prototype.toC = function(){ 721 modulefile.prototype.toC = function(){
714 var ast = parseFile(this.path + '/' + this.file); 722 this.populateSymbols(toplevel);
715 ast.populateSymbols(toplevel); 723 return this.ast.toCModuleInstance();
716 return ast.toCModuleInstance();
717 }; 724 };
718 725
719 function processUsedToplevel(toplevel) 726 function processUsedToplevel(toplevel)
720 { 727 {
728 var alwaysused = ['true', 'false'];
721 var ret = ''; 729 var ret = '';
722 var modulenum = 0; 730 var modulenum = 0;
723 for (var symbol in toplevel.used) { 731 var newused = Object.keys(toplevel.used);
724 toplevel.names[symbol].modulevar = 'module_' + (modulenum++); 732 var allused = newused;
725 toplevelcode += 'object * ' + toplevel.names[symbol].modulevar + ';\n'; 733 var visited = {};
726 } 734 for (var i in alwaysused) {
727 for (var symbol in toplevel.used) { 735 forwarddec += 'object * ' + toplevel.moduleVar(alwaysused[i]) + ';\n';
728 ret += '\t' + toplevel.names[symbol].modulevar + ' = ' + toplevel.names[symbol].toC() + ';\n'; 736 toplevel.names[alwaysused[i]].populateSymbols(toplevel);
737 visited[alwaysused[i]] = true;
738 }
739 while (newused.length) {
740 for (var i in newused) {
741 debugprint('//---module', newused[i], '--- populate symbols');
742 forwarddec += 'object * ' + toplevel.moduleVar(newused[i]) + ';\n';
743 toplevel.names[newused[i]].populateSymbols(toplevel);
744 visited[newused[i]] = true;
745 }
746 newused = [];
747 for (var symbol in toplevel.used) {
748 if (!(symbol in visited)) {
749 debugprint('//found new usage of module', symbol);
750 newused.push(symbol);
751 allused.push(symbol);
752 }
753 }
754 }
755 for (var i in alwaysused) {
756 allused.push(alwaysused[i]);
757 }
758
759 for (var i = allused.length-1; i >= 0; i--) {
760 var symbol = allused[i];
761 debugprint('//---module', symbol, '--- compile');
762 ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n';
729 } 763 }
730 return ret; 764 return ret;
731 } 765 }
732 766
733 function makeCProg(obj) 767 function makeCProg(obj)
744 var moduleinit = processUsedToplevel(toplevel); 778 var moduleinit = processUsedToplevel(toplevel);
745 debugprint('//------COMPILING AST-----'); 779 debugprint('//------COMPILING AST-----');
746 var rest = 'object * mainModule() {\n' + moduleinit + '\tmain_module = ' + obj.toCModuleInstance() + ';\n\treturn main_module;\n}\n'; 780 var rest = 'object * mainModule() {\n' + moduleinit + '\tmain_module = ' + obj.toCModuleInstance() + ';\n\treturn main_module;\n}\n';
747 return '#include "runtime/proghead.inc"\n' + 781 return '#include "runtime/proghead.inc"\n' +
748 '#define METHOD_ID_MAIN ' + getMethodId('main') + '\n' + 782 '#define METHOD_ID_MAIN ' + getMethodId('main') + '\n' +
749 '#define METHOD_ID_TRUE ' + getMethodId('true') + '\n' +
750 '#define METHOD_ID_FALSE ' + getMethodId('false') + '\n' +
751 forwarddec + toplevelcode + rest + '#include "runtime/progfoot.inc"\n'; 783 forwarddec + toplevelcode + rest + '#include "runtime/progfoot.inc"\n';
752 } 784 }
753 785
754 object.prototype.toCModule = function() { 786 object.prototype.toCModule = function() {
755 return makeCProg(this); 787 return makeCProg(this);