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