comparison cbackend.js @ 171:869399ff7faa

Merge
author Mike Pavone <pavone@retrodev.com>
date Tue, 13 Aug 2013 22:01:00 -0700
parents 18598163e3ef 224071eed9dd
children 8d466c5a7dff
comparison
equal deleted inserted replaced
170:18598163e3ef 171:869399ff7faa
1 var mainModule; 1 var mainModule;
2 var modules = {}; 2 var modules = {};
3 3
4 var nextmethodId = 0; 4 var nextmethodId = 0;
5 var methodIds = {}; 5 var methodIds = {};
6 var assignNames;
6 function getMethodId(methodName) 7 function getMethodId(methodName)
7 { 8 {
8 if (!(methodName in methodIds)) { 9 if (!(methodName in methodIds)) {
9 methodIds[methodName] = nextmethodId++; 10 methodIds[methodName] = nextmethodId++;
10 11
140 }; 141 };
141 142
142 var declaredInts = {}; 143 var declaredInts = {};
143 144
144 intlit.prototype.toC = function() { 145 intlit.prototype.toC = function() {
145 var intType = 'int' + this.bits; 146 var intType = (this.unsigned ? 'u' : '') + 'int' + this.bits;
146 var str = intType + '_' + (this.val < 0 ? 'neg_' + (0-this.val).toString() : this.val.toString()); 147 var str = intType + '_' + (this.val < 0 ? 'neg_' + (0-this.val).toString() : this.val.toString());
147 if (!(str in declaredInts)) { 148 if (!(str in declaredInts)) {
148 toplevelcode += 'obj_' + intType + ' ' + str + ' = {{&obj_' + intType + '_meta, NULL}, ' + this.val.toString() + '};\n'; 149 toplevelcode += 'obj_' + intType + ' ' + str + ' = {{&obj_' + intType + '_meta, NULL}, ' + this.val.toString() + '};\n';
149 declaredInts[str] = true; 150 declaredInts[str] = true;
150 } 151 }
635 'return ' + toplevel.moduleVar('false') + ';', 636 'return ' + toplevel.moduleVar('false') + ';',
636 ] 637 ]
637 }); 638 });
638 } 639 }
639 640
640 function makeInt(bits) 641 function makeInt(bits, unsigned)
641 { 642 {
642 var typename = 'obj_int' + bits; 643 var typename = 'obj_' + (unsigned ? 'u' : '') + 'int' + bits;
643 var intObj = new cObject(typename); 644 var intObj = new cObject(typename);
644 intObj.addProperty('num', null, 'int' + bits +'_t'); 645 intObj.addProperty('num', null, (unsigned ? 'u' : '') + 'int' + bits +'_t');
645 addBinaryOp(intObj, 'ADD_', '+', typename); 646 addBinaryOp(intObj, 'ADD_', '+', typename);
646 addBinaryOp(intObj, 'SUB_', '-', typename); 647 addBinaryOp(intObj, 'SUB_', '-', typename);
647 addBinaryOp(intObj, 'MUL_', '*', typename); 648 addBinaryOp(intObj, 'MUL_', '*', typename);
648 addBinaryOp(intObj, 'DIV_', '/', typename); 649 addBinaryOp(intObj, 'DIV_', '/', typename);
649 addBinaryOp(intObj, 'MOD_', '%', typename); 650 addBinaryOp(intObj, 'MOD_', '%', typename);
664 intObj.addMessage('string', { 665 intObj.addMessage('string', {
665 vars: {str: 'string *'}, 666 vars: {str: 'string *'},
666 lines: [ 667 lines: [
667 'str = (string *)make_object(&string_meta, NULL, 0);', 668 'str = (string *)make_object(&string_meta, NULL, 0);',
668 'str->data = GC_MALLOC(' + (bits == 64 ? 21 : 12) + ');', 669 'str->data = GC_MALLOC(' + (bits == 64 ? 21 : 12) + ');',
669 'sprintf(str->data, "%' + (bits == 64 ? 'l' : '') +'d", self->num);', 670 'sprintf(str->data, "%' + (bits == 64 ? 'l' : '') + (unsigned ? 'u' : 'd') + '", self->num);',
670 'str->len = str->bytes = strlen(str->data);', 671 'str->len = str->bytes = strlen(str->data);',
671 'return &(str->header);' 672 'return &(str->header);'
672 ] 673 ]
673 }); 674 });
674 //7FFFFFFFFFFFFFFF 675 //7FFFFFFFFFFFFFFF
693 vars: {}, 694 vars: {},
694 lines: [ 695 lines: [
695 'return &(self->header);' 696 'return &(self->header);'
696 ] 697 ]
697 }); 698 });
699 var sizes = [8, 16, 32, 64];
700 var destunsigned = [false, true];
701 for (var i = 0; i < sizes.length; i++) {
702 size = sizes[i];
703 for (var j = 0; j < destunsigned.length; j++) {
704 uns = destunsigned[j];
705 if (uns == unsigned && size == bits) {
706 intObj.addMessage((uns ? 'u' : '') + 'int' + size, {
707 vars: {},
708 lines: [
709 'return &(self->header);'
710 ]
711 });
712 } else {
713 var retType = 'obj_' + (uns ? 'u' : '') + 'int' + size;
714 var retName = 'ret' + (uns ? 'u' : '') + size;
715 var vars = {};
716 vars[retName] = retType + ' *';
717 intObj.addMessage((uns ? 'u' : '') + 'int' + size, {
718
719 vars: vars,
720 lines: [
721 retName + ' = ('+retType+' *)make_object(&' + retType +'_meta, NULL, 0);',
722 retName + '->num = self->num;',
723 'return &(' + retName + '->header);'
724 ]
725 });
726 }
727 }
728 }
729
698 return intObj; 730 return intObj;
699 } 731 }
700 732
701 function makeArray() 733 function makeArray()
702 { 734 {
735 return clos; 767 return clos;
736 } 768 }
737 769
738 function builtinTypes() 770 function builtinTypes()
739 { 771 {
740 return [makeInt(64), makeInt(32), makeInt(16), makeInt(8), makeArray(), makeString(), makelambda()]; 772 return [makeInt(64, false), makeInt(32, false), makeInt(16, false), makeInt(8, false),
773 makeInt(64, true) , makeInt(32, true), makeInt(16, true), makeInt(8, true),
774 makeArray(), makeString(), makelambda()];
741 } 775 }
742 776
743 function addBuiltinModules(toplevel) 777 function addBuiltinModules(toplevel)
744 { 778 {
745 var os = new cObject('mod_obj_os'); 779 var os = new cObject('mod_obj_os');
746 os.addInclude('<sys/stat.h>'); 780 os.addInclude('<sys/stat.h>');
747 os.addInclude('<fcntl.h>'); 781 os.addInclude('<fcntl.h>');
782 os.addInclude('<stdlib.h>');
783 os.addInclude('<time.h>');
784 os.addInclude('<unistd.h>');
748 os.addMessage('write', { 785 os.addMessage('write', {
749 vars: {str: 'string *', intret: 'obj_int32 *', filedes: 'obj_int32 *'}, 786 vars: {str: 'string *', intret: 'obj_int32 *', filedes: 'obj_int32 *'},
750 lines: [ 787 lines: [
751 'filedes = va_arg(args, obj_int32 *);', 788 'filedes = va_arg(args, obj_int32 *);',
752 'str = va_arg(args, string *);', 789 'str = va_arg(args, string *);',
760 lines: [ 797 lines: [
761 'filedes = va_arg(args, obj_int32 *);', 798 'filedes = va_arg(args, obj_int32 *);',
762 'size = va_arg(args, obj_int32 *);', 799 'size = va_arg(args, obj_int32 *);',
763 'str = (string *)make_object(&string_meta, NULL, 0);', 800 'str = (string *)make_object(&string_meta, NULL, 0);',
764 'str->data = GC_MALLOC_ATOMIC(size->num + 1);', 801 'str->data = GC_MALLOC_ATOMIC(size->num + 1);',
765 'str->length = str->bytes = read(filedes->num, str->data, size->num);', 802 'str->len = str->bytes = read(filedes->num, str->data, size->num);',
766 'if (str->bytes < 0) { str->bytes = str->length = 0; }', 803 'if (str->bytes < 0) { str->bytes = str->len = 0; }',
767 'str->data[str->bytes] = 0;', 804 'str->data[str->bytes] = 0;',
768 'return &(str->header);' 805 'return &(str->header);'
769 ] 806 ]
770 }); 807 });
771 os.addMessage('open', { 808 os.addMessage('open', {
840 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);', 877 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
841 'intret->num = O_TRUNC;', 878 'intret->num = O_TRUNC;',
842 'return &(intret->header);' 879 'return &(intret->header);'
843 ] 880 ]
844 }); 881 });
882 os.addMessage('rand', {
883 vars: {intret: 'obj_int32 *'},
884 lines: [
885 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
886 'intret->num = rand();',
887 'return &(intret->header);'
888 ]
889 });
890 os.addMessage('rand64', {
891 vars: {intret64: 'obj_int64 *'},
892 lines: [
893 'intret64 = (obj_int64 *)make_object(&obj_int64_meta, NULL, 0);',
894 'intret64->num = (((int64_t)rand()) << 32 ) | rand();',
895 'return &(intret64->header);'
896 ]
897 });
898 os.addMessage('srand', {
899 vars: {oseed: 'object *', seed: 'obj_int32 *'},
900 lines: [
901 'oseed = va_arg(args, object *);',
902 'seed = mcall(' + getMethodId("int32") + ', 1, oseed);',
903 'srand(seed->num);',
904 'return &(seed->header);'
905 ]
906 });
907 os.addMessage('time', {
908 vars: {intret64: 'obj_int64 *'},
909 lines: [
910 'intret64 = (obj_int64 *)make_object(&obj_int64_meta, NULL, 0);',
911 'intret64->num = time(NULL);',
912 'return &(intret64->header);'
913 ]
914 });
915 os.addMessage('sleep', {
916 vars: {osecs: 'object *', secs: 'obj_int32 *', intret: 'obj_int32 *'},
917 lines: [
918 'osecs = va_arg(args, object *);',
919 'secs = mcall(' + getMethodId("int32") + ', 1, osecs);',
920 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
921 'intret->num = sleep(secs->num);',
922 'return &(intret->header);'
923 ]
924 });
845 toplevel.names['os'] = os; 925 toplevel.names['os'] = os;
846 } 926 }
847 927
848 modulefile.prototype.toC = function(){ 928 modulefile.prototype.toC = function(){
849 return this.ast.toCModuleInstance(); 929 return this.ast.toCModuleInstance();
878 } 958 }
879 959
880 for (var i = allused.length-1; i >= 0; i--) { 960 for (var i = allused.length-1; i >= 0; i--) {
881 var symbol = allused[i]; 961 var symbol = allused[i];
882 debugprint('//---module', symbol, '(' + i +')--- compile'); 962 debugprint('//---module', symbol, '(' + i +')--- compile');
963 assignNames.push(symbol);
883 ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n'; 964 ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n';
965 assignNames.pop();
884 } 966 }
885 return ret; 967 return ret;
886 } 968 }
887 969
888 function makeCProg(obj) 970 function makeCProg(obj)
889 { 971 {
890 forwarddec = toplevelcode = ''; 972 forwarddec = toplevelcode = '';
973 assignNames = [];
891 var builtins = builtinTypes(); 974 var builtins = builtinTypes();
892 for (var i in builtins) { 975 for (var i in builtins) {
893 forwarddec += builtins[i].toEarlyCDef(); 976 forwarddec += builtins[i].toEarlyCDef();
894 toplevelcode += builtins[i].toCDef(); 977 toplevelcode += builtins[i].toCDef();
895 } 978 }
915 } 998 }
916 999
917 lambda.prototype.toC = function() { 1000 lambda.prototype.toC = function() {
918 var args = this.args ? this.args.slice(0, this.args.length) : []; 1001 var args = this.args ? this.args.slice(0, this.args.length) : [];
919 var exprs = this.expressions; 1002 var exprs = this.expressions;
920 debugprint('//', this.name); 1003 var assignPath = assignNames.join('<-');
1004 debugprint('//', this.name, assignPath);
1005 var addedTypeDef = false;
921 if (Object.keys(this.symbols.closedover).length) { 1006 if (Object.keys(this.symbols.closedover).length) {
922 this.symbols.envtype = this.name + '_env'; 1007 this.symbols.envtype = this.name + '_env';
923 forwarddec += 'typedef struct ' + this.symbols.envtype + ' ' + this.symbols.envtype + ';\n' 1008 forwarddec += 'typedef struct ' + this.symbols.envtype + ' ' + this.symbols.envtype + ';\n'
1009 var addedTypeDef = true;
924 } 1010 }
925 if (this.selftype) { 1011 if (this.selftype) {
926 this.symbols.defineVar('self', this.selftype); 1012 this.symbols.defineVar('self', this.selftype);
927 if (args[0] && args[0].cleanName() == 'self') { 1013 if (args[0] && args[0].cleanName() == 'self') {
928 args.splice(0, 1); 1014 args.splice(0, 1);
947 if (exprs.length) { 1033 if (exprs.length) {
948 exprs[exprs.length-1] = 'return (object *)(' + exprs[exprs.length-1] + ');'; 1034 exprs[exprs.length-1] = 'return (object *)(' + exprs[exprs.length-1] + ');';
949 } 1035 }
950 1036
951 if (Object.keys(this.symbols.closedover).length) { 1037 if (Object.keys(this.symbols.closedover).length) {
1038 if (!addedTypeDef) {
1039 for (var key in this.symbols.closedover) {
1040 print(key, ": ", this.symbols.closedover[key]);
1041 }
1042 throw new Error('this.symbols.closedover is not empty, but it was when compilation of ' + this.name + ' "' + assignPath + '" started');
1043 }
952 forwarddec += 'struct ' + this.name + '_env {\n'; 1044 forwarddec += 'struct ' + this.name + '_env {\n';
953 if (this.symbols.needsParentEnv) { 1045 if (this.symbols.needsParentEnv) {
954 forwarddec += '\tstruct ' + this.symbols.parentEnvType() + ' * parent;\n'; 1046 forwarddec += '\tstruct ' + this.symbols.parentEnvType() + ' * parent;\n';
955 } 1047 }
956 for (var varname in this.symbols.closedover) { 1048 for (var varname in this.symbols.closedover) {
970 } else { 1062 } else {
971 var myenvinit = ''; 1063 var myenvinit = '';
972 } 1064 }
973 forwarddec += 'object *' + this.name + ' (' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...);\n'; 1065 forwarddec += 'object *' + this.name + ' (' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...);\n';
974 1066
1067 toplevelcode += '//' + assignPath + "\n";
975 toplevelcode += 'object * ' + this.name + ' ( ' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...) {\n\tva_list args;\n' + myenvinit + '\tva_start(args, num_args);\n'; 1068 toplevelcode += 'object * ' + this.name + ' ( ' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...) {\n\tva_list args;\n' + myenvinit + '\tva_start(args, num_args);\n';
976 if (this.selftype) { 1069 if (this.selftype) {
977 var selfvar = (new symbol('self', this.symbols)).toC(); 1070 var selfvar = (new symbol('self', this.symbols)).toC();
978 if (selfvar == 'self') { 1071 if (selfvar == 'self') {
979 toplevelcode += '\t' + this.selftype + ' * self = va_arg(args, ' + this.selftype + ' *);\n'; 1072 toplevelcode += '\t' + this.selftype + ' * self = va_arg(args, ' + this.selftype + ' *);\n';
1040 1133
1041 assignment.prototype.toC = function() { 1134 assignment.prototype.toC = function() {
1042 debugprint('//assignment', this.symbol.name); 1135 debugprint('//assignment', this.symbol.name);
1043 var existing = this.symbols.find(this.symbol.name); 1136 var existing = this.symbols.find(this.symbol.name);
1044 var prefix = ''; 1137 var prefix = '';
1138 assignNames.push(this.symbol.name);
1045 var val = this.expression.toC(); 1139 var val = this.expression.toC();
1140 assignNames.pop(this.symbol.name);
1046 if (val === null) { 1141 if (val === null) {
1047 return null; 1142 return null;
1048 } 1143 }
1049 if (existing.type == 'local' && !existing.isdeclared) { 1144 if (existing.type == 'local' && !existing.isdeclared) {
1050 prefix = 'object *'; 1145 prefix = 'object *';
1053 } 1148 }
1054 return prefix + this.symbol.toC() + ' = ' + val; 1149 return prefix + this.symbol.toC() + ' = ' + val;
1055 }; 1150 };
1056 assignment.prototype.toCObject = function(cobj) { 1151 assignment.prototype.toCObject = function(cobj) {
1057 debugprint('//message definition', this.symbol.name); 1152 debugprint('//message definition', this.symbol.name);
1153 assignNames.push('#' + this.symbol.name);
1058 if (this.expression.toCObject) { 1154 if (this.expression.toCObject) {
1059 var val = this.expression.toCObject(cobj.name); 1155 var val = this.expression.toCObject(cobj.name);
1060 } else { 1156 } else {
1061 var val = this.expression.toC(); 1157 var val = this.expression.toC();
1062 } 1158 }
1159 assignNames.pop();
1063 if (val === null) { 1160 if (val === null) {
1064 return; 1161 return;
1065 } 1162 }
1066 if (this.expression instanceof lambda) { 1163 if (this.expression instanceof lambda) {
1067 var params = ['((object *)self)']; 1164 var params = ['((object *)self)'];