comparison cbackend.js @ 87:25bc8a5ab41e

Improve llMessage a bit and move implementation of string into string.tp module using llMessage. Update TASKS list
author Mike Pavone <pavone@retrodev.com>
date Sun, 22 Jul 2012 14:18:34 -0700
parents 9811040704ac
children f23ecd4e22af
comparison
equal deleted inserted replaced
86:ce6a81b3be70 87:25bc8a5ab41e
43 var optoMeth = {'+': 'ADD_', '-': 'SUB_', '*': 'MUL_', '/': 'DIV_', '%': 'MOD_', '=': 'EQ_', '!=': 'NEQ_', '<': 'LT_', '>': 'GT_', '>=': 'GEQ_', '<=': 'LEQ_', '.': 'CAT_'}; 43 var optoMeth = {'+': 'ADD_', '-': 'SUB_', '*': 'MUL_', '/': 'DIV_', '%': 'MOD_', '=': 'EQ_', '!=': 'NEQ_', '<': 'LT_', '>': 'GT_', '>=': 'GEQ_', '<=': 'LEQ_', '.': 'CAT_'};
44 var method = optoMeth[this.op]; 44 var method = optoMeth[this.op];
45 return 'mcall(' + getMethodId(method) + '/* ' + method + ' */, 2, (object *)' + this.left.toC() + ', ' + this.right.toC() + ')\n'; 45 return 'mcall(' + getMethodId(method) + '/* ' + method + ' */, 2, (object *)' + this.left.toC() + ', ' + this.right.toC() + ')\n';
46 }; 46 };
47 op.prototype.toCLLExpr = function(vars) { 47 op.prototype.toCLLExpr = function(vars) {
48 return this.left.toCLLExpr(vars) + (this.op == '=' ? '==' : this.op) + this.right.toCLLExpr(vars); 48 var opmap = {'=': '==', 'xor': '^'};
49 return this.left.toCLLExpr(vars) + (this.op in opmap ? opmap[this.op] : this.op) + this.right.toCLLExpr(vars);
49 }; 50 };
50 op.prototype.toCLines = function(vars, needsreturn) { 51 op.prototype.toCLines = function(vars, needsreturn) {
51 return [ (needsreturn ? 'return (object *)' : '' ) + this.toCLLExpr(vars) + ';']; 52 return [ (needsreturn ? 'return (object *)' : '' ) + this.toCLLExpr(vars) + ';'];
52 }; 53 };
53 54
139 return toplevel.moduleVar(name); 140 return toplevel.moduleVar(name);
140 } else if (info.type == 'self') { 141 } else if (info.type == 'self') {
141 if (info.isll || !(info.def instanceof lambda)) { 142 if (info.isll || !(info.def instanceof lambda)) {
142 return 'self->' + name; 143 return 'self->' + name;
143 } else { 144 } else {
144 return 'mcall(' + getMethodId(name) + '/* ' + name + ' */, 1, ' + (new symbol('self', this.symbols)).toC() + ')'; 145 return 'mcall(' + getMethodId(name) + '/* ' + name + ' */, 1, self)';
145 } 146 }
146 } 147 }
147 throw new Error('Unsupported reference type ' + info.type + ' for variable ' + name); 148 throw new Error('Unsupported reference type ' + info.type + ' for variable ' + name);
148 }; 149 };
149 symbol.prototype.toCLines = function(vars, needsreturn) { 150 symbol.prototype.toCLines = function(vars, needsreturn) {
229 args.splice(0, 0, this.receiver); 230 args.splice(0, 0, this.receiver);
230 } 231 }
231 var method = false; 232 var method = false;
232 var funinfo = this.symbols.find(name); 233 var funinfo = this.symbols.find(name);
233 var start = 0; 234 var start = 0;
234 if (!funinfo || funinfo.def instanceof setter) { 235 if (!funinfo || funinfo.def instanceof setter || funinfo.type == 'toplevel') {
235 method = true; 236 method = true;
236 } else { 237 } else {
237 switch(funinfo.type) 238 switch(funinfo.type)
238 { 239 {
239 case 'self': 240 case 'self':
347 } 348 }
348 } 349 }
349 switch(name) 350 switch(name)
350 { 351 {
351 case 'if': 352 case 'if':
353 return '((' + args[0].toCLLExpr(vars) + ') ? (' + args[1].toCLLExpr(vars) + ') : 0)';
352 case 'if:else': 354 case 'if:else':
355 return '((' + args[0].toCLLExpr(vars) + ') ? (' + args[1].toCLLExpr(vars) + ') : (' + args[2].toCLLExpr(vars) + '))';
353 case 'while:do': 356 case 'while:do':
354 throw new Error('if, if:else and while:do not allow in expression context in llMessage block'); 357 throw new Error('while:do not allowed in expression context in llMessage block');
355 case 'addr_of': 358 case 'addr_of':
356 return '&(' + args[0].toCLLExpr(vars) + ')'; 359 return '&(' + args[0].toCLLExpr(vars) + ')';
357 case 'sizeof': 360 case 'sizeof':
358 return 'sizeof(' + args[0].toCTypeName() + ')'; 361 return 'sizeof(' + args[0].toCTypeName() + ')';
359 case 'get': 362 case 'get':
360 return args[0].toCLLExpr(vars) + '[' + args[1].toCLLExpr(vars) + ']'; 363 return args[0].toCLLExpr(vars) + '[' + args[1].toCLLExpr(vars) + ']';
361 case 'set': 364 case 'set':
362 return args[0].toCLLExpr(vars) + '[' + args[1].toCLLExpr(vars) + '] = ' + args[2].toCLLExpr(vars); 365 return args[0].toCLLExpr(vars) + '[' + args[1].toCLLExpr(vars) + '] = ' + args[2].toCLLExpr(vars);
363 case 'not': 366 case 'not':
364 return '!(' + args[0].toCLLExpr(vars) + ')'; 367 return '!(' + args[0].toCLLExpr(vars) + ')';
368 case 'mcall':
369 if (args[0] instanceof symbol) {
370 args[0] = new intlit(getMethodId(args[0].name));
371 }
365 default: 372 default:
366 for (var i in args) { 373 for (var i in args) {
367 args[i] = args[i].toCLLExpr(vars); 374 args[i] = args[i].toCLLExpr(vars);
368 } 375 }
369 return name + '(' + args.join(', ') + ')'; 376 return name + '(' + args.join(', ') + ')';
625 vars: {str: 'string *'}, 632 vars: {str: 'string *'},
626 lines: [ 633 lines: [
627 'str = (string *)make_object(&string_meta, NULL, 0);', 634 'str = (string *)make_object(&string_meta, NULL, 0);',
628 'str->data = GC_MALLOC(12);', 635 'str->data = GC_MALLOC(12);',
629 'sprintf(str->data, "%d", self->num);', 636 'sprintf(str->data, "%d", self->num);',
630 'str->length = str->bytes = strlen(str->data);', 637 'str->len = str->bytes = strlen(str->data);',
631 'return &(str->header);' 638 'return &(str->header);'
632 ] 639 ]
633 }); 640 });
634 int32.addMessage('hash', { 641 int32.addMessage('hash', {
635 vars: {}, 642 vars: {},
649 return ast.toCObject(); 656 return ast.toCObject();
650 } 657 }
651 658
652 function makeString() 659 function makeString()
653 { 660 {
654 var string = new cObject('string'); 661 var arrayfile = toplevel.names['string'];
655 string.addProperty('length', null, 'uint32_t'); 662 var ast = parseFile(arrayfile.path + '/' + arrayfile.file);
656 string.addProperty('bytes', null, 'uint32_t'); 663 ast.name = 'string';
657 string.addProperty('data', null, 'char *'); 664 ast.populateSymbols(toplevel);
658 string.addMessage('length', { 665 return ast.toCObject();
659 vars: {intret: 'obj_int32 *'},
660 lines: [
661 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
662 'intret->num = self->length;',
663 'return &(intret->header);'
664 ]
665 });
666 string.addMessage('byte_length', {
667 vars: {intret: 'obj_int32 *'},
668 lines: [
669 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
670 'intret->num = self->bytes;',
671 'return &(intret->header);'
672 ]
673 });
674 string.addMessage('EQ_', {
675 vars: {argb: 'string *'},
676 lines: [
677 'argb = va_arg(args, string *);',
678 'if (self->length == argb->length && self->bytes == argb->bytes && !memcmp(self->data, argb->data, self->bytes)) {',
679 ' return ' + toplevel.moduleVar('true') + ';',
680 '}',
681 'return ' + toplevel.moduleVar('false') + ';',
682 ]
683 });
684 string.addMessage('NEQ_', {
685 vars: {argb: 'string *'},
686 lines: [
687 'argb = va_arg(args, string *);',
688 'if (self->length != argb->length || self->bytes != argb->bytes || memcmp(self->data, argb->data, self->bytes)) {',
689 ' return ' + toplevel.moduleVar('true') + ';',
690 '}',
691 'return ' + toplevel.moduleVar('false') + ';',
692 ]
693 });
694 string.addMessage('print', {
695 vars: {},
696 lines: [
697 'fwrite(self->data, 1, self->bytes, stdout);',
698 'return &(self->header);'
699 ]
700 });
701 string.addMessage('string', {
702 vars: {},
703 lines: [ 'return &(self->header);' ]
704 });
705 string.addMessage('CAT_', {
706 vars: {argbo: 'object *', argb: 'string *', out: 'string *'},
707 lines: [
708 'argbo = va_arg(args, object *);',
709 'argb = (string *)mcall(' + getMethodId('string') + ', 1, argbo);',
710 'out = (string *)make_object(&string_meta, NULL, 0);',
711 'out->bytes = self->bytes + argb->bytes;',
712 'out->length = self->length + argb->length;',
713 'out->data = GC_MALLOC_ATOMIC(out->bytes+1);',
714 'memcpy(out->data, self->data, self->bytes);',
715 'memcpy(out->data + self->bytes, argb->data, argb->bytes + 1);',
716 'return &(out->header);'
717 ]
718 });
719 string.addMessage('byte', {
720 vars: {index: 'obj_int32 *', intret: 'obj_int32 *'},
721 lines: [
722 'index = va_arg(args, obj_int32 *);',
723 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
724 'intret->num = index->num < self->bytes ? self->data[index->num] : 0;',
725 'return &(intret->header);'
726 ]
727 });
728 string.addMessage('int32', {
729 vars: {intret: 'obj_int32 *'},
730 lines: [
731 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
732 'intret->num = atoi(self->data);',
733 'return &(intret->header);'
734 ]
735 });
736 string.addMessage('hash', {
737 vars: {intret: 'obj_int32 *', i: 'uint32_t'},
738 lines: [
739 'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
740 'intret->num = 0;',
741 'if (self->bytes) {',
742 ' intret->num = self->data[0] << 7;',
743 ' for (i = 0; i < self->bytes; i++) {',
744 ' intret->num = (1000003 * intret->num) ^ self->data[i];',
745 ' }',
746 ' intret->num = intret->num ^ self->bytes;',
747 '}',
748 'return &(intret->header);'
749 ]
750 });
751 return string;
752 } 666 }
753 667
754 function makelambda() 668 function makelambda()
755 { 669 {
756 var clos = new cObject('lambda'); 670 var clos = new cObject('lambda');