comparison cbackend.js @ 273:0dc7322590da

Make import:from actually work. Fix some macro bugs. Add a cpointer primitive type for storing an opaque pointer to a C object.
author Michael Pavone <pavone@retrodev.com>
date Sun, 20 Jul 2014 00:12:43 -0700
parents bb2b4613fdc8
children 361a449a7235
comparison
equal deleted inserted replaced
272:bb2b4613fdc8 273:0dc7322590da
104 return getSymbolPrefix(info, this.symbols) + escapeCName(name); 104 return getSymbolPrefix(info, this.symbols) + escapeCName(name);
105 } 105 }
106 symbol.prototype.toCTypeName = function() { 106 symbol.prototype.toCTypeName = function() {
107 return this.cleanName(); 107 return this.cleanName();
108 }; 108 };
109 symbol.prototype.cSafeName = function() {
110 var name = this.cleanName();
111 if (name[0] >= "0" && name[0] <= "9") {
112 name = '_tp_' + name;
113 }
114 return name;
115 };
109 symbol.prototype.toCLLExpr = function(vars) { 116 symbol.prototype.toCLLExpr = function(vars) {
110 var name = this.cleanName(); 117 var name = this.cleanName();
111 if (name in vars) { 118 if (name in vars) {
112 return name; 119 return name;
113 } 120 }
119 while (info && info.type == 'local') { 126 while (info && info.type == 'local') {
120 symbols = symbols.parent; 127 symbols = symbols.parent;
121 info = symbols.find(name, false, true); 128 info = symbols.find(name, false, true);
122 } 129 }
123 if (!info) { 130 if (!info) {
124 return name; 131 return this.cSafeName();
125 } 132 }
126 if (info.type == 'toplevel') { 133 if (info.type == 'toplevel') {
127 return toplevel.moduleVar(name); 134 return toplevel.moduleVar(name);
128 } else if (info.type == 'self') { 135 } else if (info.type == 'self') {
129 if (info.isll || !(info.def instanceof lambda)) { 136 if (info.isll || !(info.def instanceof lambda)) {
130 return 'self->' + name; 137 return 'self->' + this.cSafeName();
131 } else { 138 } else {
132 return 'mcall(' + getMethodId(name) + '/* ' + name + ' */, 1, self)'; 139 return 'mcall(' + getMethodId(name) + '/* ' + name + ' */, 1, self)';
133 } 140 }
134 } 141 }
135 throw new Error('Unsupported reference type ' + info.type + ' for variable ' + name); 142 throw new Error('Unsupported reference type ' + info.type + ' for variable ' + name);
415 this.slotvars = {}; 422 this.slotvars = {};
416 this.includes = {}; 423 this.includes = {};
417 this.parent = 'NULL'; 424 this.parent = 'NULL';
418 this.init = []; 425 this.init = [];
419 this.initmsgadded = false; 426 this.initmsgadded = false;
427 this.imported = [];
420 } 428 }
421 429
422 cObject.prototype.addInclude = function(includefile) { 430 cObject.prototype.addInclude = function(includefile) {
423 this.includes[includefile] = true; 431 this.includes[includefile] = true;
424 } 432 }
465 cObject.prototype.addInit = function(statement) { 473 cObject.prototype.addInit = function(statement) {
466 this.init.push(statement); 474 this.init.push(statement);
467 }; 475 };
468 476
469 cObject.prototype.addImport = function(symbols, source) { 477 cObject.prototype.addImport = function(symbols, source) {
470 this.imported.push(source); 478 var importNum = this.imported.indexOf(source);
471 var importNum = imported.length - 1; 479 if (importNum < 0) {
480 var importNum = this.imported.length;
481 this.imported.push(source);
482 this.addInit('self->import_' + importNum + ' = ' + source.toC() + ';');
483 }
472 if (symbols) { 484 if (symbols) {
485 var self = this;
473 each(symbols, function(i, sym) { 486 each(symbols, function(i, sym) {
474 this.addMessage(sym.name, { 487 self.addMessage(sym.name, {
475 vars: {}, 488 vars: {},
476 lines: [ 489 lines: [
477 'return self->import_' + importNum + '->meta->meth_lookup[method_id & 0xF](method_id, num_args, self->import_' + importNum + ', args);' 490 'return self->import_' + importNum + '->meta->meth_lookup[method_id & 0xF](method_id, num_params, self->import_' + importNum + ', args);'
478 ] 491 ]
479 }); 492 });
480 }); 493 });
481 } else { 494 } else {
482 //TODO: handle proxying for unimplemented methods 495 //TODO: handle proxying for unimplemented methods
512 objdef += '\t' + this.properties[i][1] + ' ' + this.properties[i][0] + ';\n'; 525 objdef += '\t' + this.properties[i][1] + ' ' + this.properties[i][0] + ';\n';
513 } 526 }
514 } else { 527 } else {
515 objdef += '\tobject * ' + this.properties[i] + ';\n' 528 objdef += '\tobject * ' + this.properties[i] + ';\n'
516 } 529 }
530 }
531 for (var i in this.imported) {
532 objdef += '\tobject * import_' + i + ';\n';
517 } 533 }
518 objdef += '} ' + this.name + ';\nobj_meta ' + this.name + '_meta;\n'; 534 objdef += '} ' + this.name + ';\nobj_meta ' + this.name + '_meta;\n';
519 return includes + objdef; 535 return includes + objdef;
520 } 536 }
521 537
602 if (this.symbols.needsparent && !(this.symbols.parent instanceof osymbols)) { 618 if (this.symbols.needsparent && !(this.symbols.parent instanceof osymbols)) {
603 me.parent = '(object *)(' + (new symbol('self', this.symbols.parent)).toC() + ')'; 619 me.parent = '(object *)(' + (new symbol('self', this.symbols.parent)).toC() + ')';
604 } 620 }
605 for (var i in messages) { 621 for (var i in messages) {
606 if (messages[i] instanceof funcall) { 622 if (messages[i] instanceof funcall) {
607 if (messages[i].name == 'import:' && messages[i].args.length == 1) { 623 var msgname = messages[i].name;
624 if (msgname[msgname.length-1] == ':') {
625 msgname = msgname.substr(0, msgname.length-1);
626 }
627 if (msgname == 'import' && messages[i].args.length == 1) {
608 me.addImport(false, messages[i].args[0]); 628 me.addImport(false, messages[i].args[0]);
609 } else if(messages[i].name == 'import:from:' && messages[i].args.length == 2) { 629 } else if(msgname == 'import:from' && messages[i].args.length == 2) {
610 var importsyms = []; 630 var importsyms = [];
611 each(messages[i].args[0].val, function(i, el) { 631 each(messages[i].args[0].val, function(i, el) {
612 if (!(el instanceof symbol)) { 632 if (!(el instanceof symbol)) {
613 throw new Error('Names in import:from statement must be symbols'); 633 throw new Error('Names in import:from statement must be symbols');
614 } 634 }
615 importsyms.push(el); 635 importsyms.push(el);
616 }); 636 });
617 me.addImport(importsyms, messages[i].args[1]); 637 me.addImport(importsyms, messages[i].args[1]);
618 } else if(messages[i].name == 'llProperty:withType:' && messages[i].args.length == 2) { 638 } else if(msgname == 'llProperty:withType' && messages[i].args.length == 2) {
619 me.addProperty(messages[i].args[0].name, null, messages[i].args[1].toCTypeName()); 639 me.addProperty(messages[i].args[0].name, null, messages[i].args[1].toCTypeName());
620 } else if(messages[i].name == 'llMessage:withVars:andCode:' && messages[i].args.length == 3) { 640 } else if(msgname == 'llMessage:withVars:andCode' && messages[i].args.length == 3) {
621 if (messages[i].args[0] instanceof symbol) { 641 if (messages[i].args[0] instanceof symbol) {
622 var msgname = messages[i].args[0].name; 642 var msgname = messages[i].args[0].name;
623 } else if (messages[i].args[0] instanceof strlit) { 643 } else if (messages[i].args[0] instanceof strlit) {
624 var msgname = messages[i].args[0].val; 644 var msgname = messages[i].args[0].val;
625 } else { 645 } else {
626 throw new Error('First argument to llMessage:withVars:andCode must be a symbol or string'); 646 throw new Error('First argument to llMessage:withVars:andCode must be a symbol or string');
627 } 647 }
628 var rawvars = messages[i].args[1].expressions; 648 var rawvars = messages[i].args[1].expressions;
629 var vars = {}; 649 var vars = {};
630 for(var v in rawvars) { 650 for(var v in rawvars) {
631 vars[rawvars[v].symbol.name] = rawvars[v].expression.toCTypeName(); 651 vars[rawvars[v].symbol.cSafeName()] = rawvars[v].expression.toCTypeName();
632 } 652 }
633 me.addMessage(msgname, { 653 me.addMessage(msgname, {
634 vars: vars, 654 vars: vars,
635 lines: messages[i].args[2].toCLines(vars, true) 655 lines: messages[i].args[2].toCLines(vars, true)
636 }); 656 });
637 } else if(messages[i].name == 'includeSystemHeader:' && messages[i].args.length == 1) { 657 } else if(msgname == 'includeSystemHeader' && messages[i].args.length == 1) {
638 me.addInclude("<" + messages[i].args[0].val + ">"); 658 me.addInclude("<" + messages[i].args[0].val + ">");
639 } else { 659 } else {
640 660
641 throw new Error('Only import and import:from calls allowed in object context. ' + messages[i].name + 'with ' + messages[i].args.length + ' arguments found instead.'); 661 throw new Error('Only import and import:from calls allowed in object context. ' + messages[i].name + 'with ' + messages[i].args.length + ' arguments found instead.');
642 } 662 }
784 } 804 }
785 805
786 return intObj; 806 return intObj;
787 } 807 }
788 808
809 function makeCPointer()
810 {
811 var cptr = new cObject('cpointer');
812 cptr.addProperty('val', null, 'void *');
813 //cpointer:
814 //1234567890
815 cptr.addMessage('string', {
816 vars: {ret: 'string *'},
817 lines: [
818 'ret = make_object(&string_meta, NULL, 0);',
819 //22 digits for worst case sensible representation
820 //10 chars for prefix
821 //4 for slop
822 //1 for null terminator
823 'ret->data = GC_MALLOC_ATOMIC(22+10+4+1);',
824 'snprintf(ret->data, 22+10+4, "cpointer: %p", self->val);',
825 'ret->data[22+10+4] = 0;',
826 'return (object *)ret;'
827 ]
828 });
829 return cptr;
830 }
831
789 function makeArray() 832 function makeArray()
790 { 833 {
791 var arrayfile = toplevel.names['array']; 834 var arrayfile = toplevel.names['array'];
792 var ast = parseFile(arrayfile.path + '/' + arrayfile.file); 835 var ast = parseFile(arrayfile.path + '/' + arrayfile.file);
793 ast.name = 'array'; 836 ast.name = 'array';
825 868
826 function builtinTypes() 869 function builtinTypes()
827 { 870 {
828 return [makeInt(64, false), makeInt(32, false), makeInt(16, false), makeInt(8, false), 871 return [makeInt(64, false), makeInt(32, false), makeInt(16, false), makeInt(8, false),
829 makeInt(64, true) , makeInt(32, true), makeInt(16, true), makeInt(8, true), 872 makeInt(64, true) , makeInt(32, true), makeInt(16, true), makeInt(8, true),
830 makeArray(), makeString(), makelambda()]; 873 makeArray(), makeString(), makelambda(), makeCPointer()];
831 } 874 }
832 875
833 function addBuiltinModules(toplevel) 876 function addBuiltinModules(toplevel)
834 { 877 {
835 var os = new cObject('mod_obj_os'); 878 var os = new cObject('mod_obj_os');