Mercurial > repos > tabletprog
comparison cbackend.js @ 121:1a4446f573d3
Add isInteger? method to the int32 type in the C backend
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 01 Aug 2013 19:10:48 -0700 |
parents | 59a94f3ad56f |
children | 9820ecd4eed4 |
comparison
equal
deleted
inserted
replaced
120:d5dc9507d612 | 121:1a4446f573d3 |
---|---|
5 var methodIds = {}; | 5 var methodIds = {}; |
6 function getMethodId(methodName) | 6 function getMethodId(methodName) |
7 { | 7 { |
8 if (!(methodName in methodIds)) { | 8 if (!(methodName in methodIds)) { |
9 methodIds[methodName] = nextmethodId++; | 9 methodIds[methodName] = nextmethodId++; |
10 | 10 |
11 } | 11 } |
12 return methodIds[methodName]; | 12 return methodIds[methodName]; |
13 } | 13 } |
14 | 14 |
15 op.prototype.toC = function(isReceiver) { | 15 op.prototype.toC = function(isReceiver) { |
39 function getSymbolPrefix(info, symbols) | 39 function getSymbolPrefix(info, symbols) |
40 { | 40 { |
41 var pre = ''; | 41 var pre = ''; |
42 switch(info.type) { | 42 switch(info.type) { |
43 case 'self': | 43 case 'self': |
44 | 44 |
45 pre = (new symbol('self', symbols)).toC() + '->'; | 45 pre = (new symbol('self', symbols)).toC() + '->'; |
46 break; | 46 break; |
47 case 'parent': | 47 case 'parent': |
48 pre = (new symbol('self', symbols)).toC() + '->header.'; | 48 pre = (new symbol('self', symbols)).toC() + '->header.'; |
49 for (var i = 0; i < info.depth; ++i) { | 49 for (var i = 0; i < info.depth; ++i) { |
418 var init = this.init.slice(0, this.init.length); | 418 var init = this.init.slice(0, this.init.length); |
419 init.push('return (object *)self;'); | 419 init.push('return (object *)self;'); |
420 this.addMessage('_init', { | 420 this.addMessage('_init', { |
421 vars: {}, | 421 vars: {}, |
422 lines: init | 422 lines: init |
423 }); | 423 }); |
424 this.initmsgadded = true; | 424 this.initmsgadded = true; |
425 } | 425 } |
426 } | 426 } |
427 | 427 |
428 cObject.prototype.populateSymbols = function() {}; | 428 cObject.prototype.populateSymbols = function() {}; |
459 for (var varname in this.slotvars[i]) { | 459 for (var varname in this.slotvars[i]) { |
460 slotdefs += '\t' + this.slotvars[i][varname] + ' ' + varname + ';\n'; | 460 slotdefs += '\t' + this.slotvars[i][varname] + ' ' + varname + ';\n'; |
461 } | 461 } |
462 if (this.slots[i].length == 1) { | 462 if (this.slots[i].length == 1) { |
463 slotdefs += '\tif (method_id == ' + this.slots[i][0][0] + ') { /* ' + this.slots[i][0][2] + '*/\n' + | 463 slotdefs += '\tif (method_id == ' + this.slots[i][0][0] + ') { /* ' + this.slots[i][0][2] + '*/\n' + |
464 '\t\t' + this.slots[i][0][1] + '\n' + | 464 '\t\t' + this.slots[i][0][1] + '\n' + |
465 '\t}\n' + | 465 '\t}\n' + |
466 '\treturn no_impl(method_id, num_params, (object *)self, args);\n}\n'; | 466 '\treturn no_impl(method_id, num_params, (object *)self, args);\n}\n'; |
467 } else { | 467 } else { |
468 slotdefs += '\tswitch(method_id) {\n'; | 468 slotdefs += '\tswitch(method_id) {\n'; |
469 for (j in this.slots[i]) { | 469 for (j in this.slots[i]) { |
470 slotdefs += '\t\tcase ' + this.slots[i][j][0] + ': /* ' + this.slots[i][j][2] + '*/\n' + | 470 slotdefs += '\t\tcase ' + this.slots[i][j][0] + ': /* ' + this.slots[i][j][2] + '*/\n' + |
471 '\t\t\t' + this.slots[i][j][1] + '\n'; | 471 '\t\t\t' + this.slots[i][j][1] + '\n'; |
472 } | 472 } |
473 slotdefs += '\t\tdefault:\n' + | 473 slotdefs += '\t\tdefault:\n' + |
474 '\t\t\treturn no_impl(method_id, num_params, (object *)self, args);\n\t}\n}\n'; | 474 '\t\t\treturn no_impl(method_id, num_params, (object *)self, args);\n\t}\n}\n'; |
475 | 475 |
476 } | 476 } |
477 metadef += this.name + '_slot_' + i; | 477 metadef += this.name + '_slot_' + i; |
478 } else { | 478 } else { |
479 metadef += 'no_impl'; | 479 metadef += 'no_impl'; |
480 } | 480 } |
542 me.addMessage(msgname, { | 542 me.addMessage(msgname, { |
543 vars: vars, | 543 vars: vars, |
544 lines: messages[i].args[2].toCLines(vars, true) | 544 lines: messages[i].args[2].toCLines(vars, true) |
545 }); | 545 }); |
546 } else { | 546 } else { |
547 | 547 |
548 throw new Error('Only import and import:from calls allowed in object context. ' + messages[i].name + 'with ' + messages[i].args.length + ' arguments found instead.'); | 548 throw new Error('Only import and import:from calls allowed in object context. ' + messages[i].name + 'with ' + messages[i].args.length + ' arguments found instead.'); |
549 } | 549 } |
550 } else { | 550 } else { |
551 messages[i].toCObject(me); | 551 messages[i].toCObject(me); |
552 } | 552 } |
613 'sprintf(str->data, "%d", self->num);', | 613 'sprintf(str->data, "%d", self->num);', |
614 'str->len = str->bytes = strlen(str->data);', | 614 'str->len = str->bytes = strlen(str->data);', |
615 'return &(str->header);' | 615 'return &(str->header);' |
616 ] | 616 ] |
617 }); | 617 }); |
618 int32.addMessage('isInteger?', { | |
619 vars: {}, | |
620 lines: [ | |
621 'return ' + toplevel.moduleVar('true') + ';' | |
622 ] | |
623 }); | |
618 int32.addMessage('hash', { | 624 int32.addMessage('hash', { |
619 vars: {}, | 625 vars: {}, |
620 lines: [ | 626 lines: [ |
621 'return &(self->header);' | 627 'return &(self->header);' |
622 ] | 628 ] |
774 modulefile.prototype.toC = function(){ | 780 modulefile.prototype.toC = function(){ |
775 return this.ast.toCModuleInstance(); | 781 return this.ast.toCModuleInstance(); |
776 }; | 782 }; |
777 | 783 |
778 function processUsedToplevel(toplevel) | 784 function processUsedToplevel(toplevel) |
779 { | 785 { |
780 var alwaysused = ['true', 'false']; | 786 var alwaysused = ['true', 'false']; |
781 var ret = ''; | 787 var ret = ''; |
782 var modulenum = 0; | 788 var modulenum = 0; |
783 var visited = {}; | 789 var visited = {}; |
784 for (var i in alwaysused) { | 790 for (var i in alwaysused) { |
800 newused.push(symbol); | 806 newused.push(symbol); |
801 allused.push(symbol); | 807 allused.push(symbol); |
802 } | 808 } |
803 } | 809 } |
804 } | 810 } |
805 | 811 |
806 for (var i = allused.length-1; i >= 0; i--) { | 812 for (var i = allused.length-1; i >= 0; i--) { |
807 var symbol = allused[i]; | 813 var symbol = allused[i]; |
808 debugprint('//---module', symbol, '(' + i +')--- compile'); | 814 debugprint('//---module', symbol, '(' + i +')--- compile'); |
809 ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n'; | 815 ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n'; |
810 } | 816 } |
855 } else { | 861 } else { |
856 var offset = 0; | 862 var offset = 0; |
857 } | 863 } |
858 for (var i = 0; i < args.length; ++i) { | 864 for (var i = 0; i < args.length; ++i) { |
859 var argname = args[i].toC(); | 865 var argname = args[i].toC(); |
860 | 866 |
861 args[i] = (argname.indexOf('->') < 0 ? '\tobject * ' : '\t') + argname + ' = va_arg(args, object *);\n'; | 867 args[i] = (argname.indexOf('->') < 0 ? '\tobject * ' : '\t') + argname + ' = va_arg(args, object *);\n'; |
862 } | 868 } |
863 var compiled = [] | 869 var compiled = [] |
864 for (var i in exprs) { | 870 for (var i in exprs) { |
865 var js = exprs[i].toC(); | 871 var js = exprs[i].toC(); |
869 } | 875 } |
870 exprs = compiled; | 876 exprs = compiled; |
871 if (exprs.length) { | 877 if (exprs.length) { |
872 exprs[exprs.length-1] = 'return (object *)(' + exprs[exprs.length-1] + ');'; | 878 exprs[exprs.length-1] = 'return (object *)(' + exprs[exprs.length-1] + ');'; |
873 } | 879 } |
874 | 880 |
875 if (Object.keys(this.symbols.closedover).length) { | 881 if (Object.keys(this.symbols.closedover).length) { |
876 forwarddec += 'struct ' + this.name + '_env {\n'; | 882 forwarddec += 'struct ' + this.name + '_env {\n'; |
877 if (this.symbols.needsParentEnv) { | 883 if (this.symbols.needsParentEnv) { |
878 forwarddec += '\tstruct ' + this.symbols.parentEnvType() + ' * parent;\n'; | 884 forwarddec += '\tstruct ' + this.symbols.parentEnvType() + ' * parent;\n'; |
879 } | 885 } |
883 } else { | 889 } else { |
884 forwarddec += '\tobject * ' + escapeCName(varname) + ';\n'; | 890 forwarddec += '\tobject * ' + escapeCName(varname) + ';\n'; |
885 } | 891 } |
886 } | 892 } |
887 forwarddec += '};\n' | 893 forwarddec += '};\n' |
888 | 894 |
889 var myenvinit = '\t' + this.name + '_env * myenv = GC_MALLOC(sizeof(' + this.name + '_env));\n'; | 895 var myenvinit = '\t' + this.name + '_env * myenv = GC_MALLOC(sizeof(' + this.name + '_env));\n'; |
890 if (this.symbols.needsParentEnv) { | 896 if (this.symbols.needsParentEnv) { |
891 myenvinit += '\tmyenv->parent = env;\n'; | 897 myenvinit += '\tmyenv->parent = env;\n'; |
892 } | 898 } |
893 this.symbols.envtype = this.name + '_env'; | 899 this.symbols.envtype = this.name + '_env'; |
894 } else { | 900 } else { |
895 var myenvinit = ''; | 901 var myenvinit = ''; |
896 } | 902 } |
897 forwarddec += 'object *' + this.name + ' (' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...);\n'; | 903 forwarddec += 'object *' + this.name + ' (' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...);\n'; |
898 | 904 |
899 toplevelcode += 'object * ' + this.name + ' ( ' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...) {\n\tva_list args;\n' + myenvinit + '\tva_start(args, num_args);\n'; | 905 toplevelcode += 'object * ' + this.name + ' ( ' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...) {\n\tva_list args;\n' + myenvinit + '\tva_start(args, num_args);\n'; |
900 if (this.selftype) { | 906 if (this.selftype) { |
901 var selfvar = (new symbol('self', this.symbols)).toC(); | 907 var selfvar = (new symbol('self', this.symbols)).toC(); |
902 if (selfvar == 'self') { | 908 if (selfvar == 'self') { |
903 toplevelcode += '\t' + this.selftype + ' * self = va_arg(args, ' + this.selftype + ' *);\n'; | 909 toplevelcode += '\t' + this.selftype + ' * self = va_arg(args, ' + this.selftype + ' *);\n'; |
904 } else { | 910 } else { |
905 toplevelcode += '\t' + selfvar + ' = va_arg(args, ' + this.selftype + ' *);\n'; | 911 toplevelcode += '\t' + selfvar + ' = va_arg(args, ' + this.selftype + ' *);\n'; |
906 } | 912 } |
907 | 913 |
908 } | 914 } |
909 toplevelcode += args.join('') + '\tva_end(args);\n' + exprs.join(';\n\t') + '\n}\n'; | 915 toplevelcode += args.join('') + '\tva_end(args);\n' + exprs.join(';\n\t') + '\n}\n'; |
910 | 916 |
911 if (this.selftype) { | 917 if (this.selftype) { |
912 return this.name; | 918 return this.name; |
913 } else { | 919 } else { |
914 if (this.symbols.parentEnvType() != 'void') { | 920 if (this.symbols.parentEnvType() != 'void') { |
915 if (this.symbols.parent.passthruenv) { | 921 if (this.symbols.parent.passthruenv) { |
917 } else { | 923 } else { |
918 var envvar = 'myenv'; | 924 var envvar = 'myenv'; |
919 } | 925 } |
920 debugprint('//' + this.name, 'has envvar:', envvar, 'num vars closed over:', Object.keys(this.symbols.closedover).length); | 926 debugprint('//' + this.name, 'has envvar:', envvar, 'num vars closed over:', Object.keys(this.symbols.closedover).length); |
921 return 'make_lambda(' + envvar + ', (closure_func)' + this.name + ')'; | 927 return 'make_lambda(' + envvar + ', (closure_func)' + this.name + ')'; |
922 } else { | 928 } else { |
923 toplevelcode += 'lambda ' + this.name + '_obj = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n'; | 929 toplevelcode += 'lambda ' + this.name + '_obj = {{&lambda_meta, NULL}, NULL, lambda_' + mynum + '};\n'; |
924 return '((object *)&' + this.name + '_obj)'; | 930 return '((object *)&' + this.name + '_obj)'; |
925 } | 931 } |
926 } | 932 } |
927 }; | 933 }; |