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