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