diff 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
line wrap: on
line diff
--- a/cbackend.js	Sat Jul 19 20:18:34 2014 -0700
+++ b/cbackend.js	Sun Jul 20 00:12:43 2014 -0700
@@ -106,6 +106,13 @@
 symbol.prototype.toCTypeName = function() {
 	return this.cleanName();
 };
+symbol.prototype.cSafeName = function() {
+	var name = this.cleanName();
+	if (name[0] >= "0" && name[0] <= "9") {
+		name = '_tp_' + name;
+	}
+	return name;
+};
 symbol.prototype.toCLLExpr = function(vars) {
 	var name = this.cleanName();
 	if (name in vars) {
@@ -121,13 +128,13 @@
 		info = symbols.find(name, false, true);
 	}
 	if (!info) {
-		return name;
+		return this.cSafeName();
 	}
 	if (info.type == 'toplevel') {
 		return toplevel.moduleVar(name);
 	} else if (info.type == 'self') {
 		if (info.isll || !(info.def instanceof lambda)) {
-			return 'self->' + name;
+			return 'self->' + this.cSafeName();
 		} else {
 			return 'mcall(' + getMethodId(name) + '/* ' + name + ' */, 1, self)';
 		}
@@ -417,6 +424,7 @@
 	this.parent = 'NULL';
 	this.init = [];
 	this.initmsgadded = false;
+	this.imported = [];
 }
 
 cObject.prototype.addInclude = function(includefile) {
@@ -467,14 +475,19 @@
 };
 
 cObject.prototype.addImport = function(symbols, source) {
-	this.imported.push(source);
-	var importNum = imported.length - 1;
+	var importNum = this.imported.indexOf(source);
+	if (importNum < 0) {
+		var importNum = this.imported.length;
+		this.imported.push(source);
+		this.addInit('self->import_' + importNum + ' = ' + source.toC() + ';');
+	}
 	if (symbols) {
+		var self = this;
 		each(symbols, function(i, sym) {
-			this.addMessage(sym.name, {
+			self.addMessage(sym.name, {
 				vars: {},
 				lines: [
-					'return self->import_' + importNum + '->meta->meth_lookup[method_id & 0xF](method_id, num_args, self->import_' + importNum + ', args);'
+					'return self->import_' + importNum + '->meta->meth_lookup[method_id & 0xF](method_id, num_params, self->import_' + importNum + ', args);'
 				]
 			});
 		});
@@ -515,6 +528,9 @@
 			objdef += '\tobject * ' + this.properties[i] + ';\n'
 		}
 	}
+	for (var i in this.imported) {
+		objdef += '\tobject * import_' + i + ';\n';
+	}
 	objdef += '} ' + this.name + ';\nobj_meta ' + this.name + '_meta;\n';
 	return includes + objdef;
 }
@@ -604,9 +620,13 @@
 	}
 	for (var i in messages) {
 		if (messages[i] instanceof funcall) {
-			if (messages[i].name == 'import:' && messages[i].args.length == 1) {
+			var msgname = messages[i].name;
+			if (msgname[msgname.length-1] == ':') {
+				msgname = msgname.substr(0, msgname.length-1);
+			}
+			if (msgname == 'import' && messages[i].args.length == 1) {
 				me.addImport(false, messages[i].args[0]);
-			} else if(messages[i].name == 'import:from:' && messages[i].args.length == 2) {
+			} else if(msgname == 'import:from' && messages[i].args.length == 2) {
 				var importsyms = [];
 				each(messages[i].args[0].val, function(i, el) {
 					if (!(el instanceof symbol)) {
@@ -615,9 +635,9 @@
 					importsyms.push(el);
 				});
 				me.addImport(importsyms, messages[i].args[1]);
-			} else if(messages[i].name == 'llProperty:withType:' && messages[i].args.length == 2) {
+			} else if(msgname == 'llProperty:withType' && messages[i].args.length == 2) {
 				me.addProperty(messages[i].args[0].name, null, messages[i].args[1].toCTypeName());
-			} else if(messages[i].name == 'llMessage:withVars:andCode:' && messages[i].args.length == 3) {
+			} else if(msgname == 'llMessage:withVars:andCode' && messages[i].args.length == 3) {
 				if (messages[i].args[0] instanceof symbol) {
 					var msgname = messages[i].args[0].name;
 				} else if (messages[i].args[0] instanceof strlit) {
@@ -628,13 +648,13 @@
 				var rawvars = messages[i].args[1].expressions;
 				var vars = {};
 				for(var v in rawvars) {
-					vars[rawvars[v].symbol.name] = rawvars[v].expression.toCTypeName();
+					vars[rawvars[v].symbol.cSafeName()] = rawvars[v].expression.toCTypeName();
 				}
 				me.addMessage(msgname, {
 					vars: vars,
 					lines: messages[i].args[2].toCLines(vars, true)
 				});
-			} else if(messages[i].name == 'includeSystemHeader:' && messages[i].args.length == 1) {
+			} else if(msgname == 'includeSystemHeader' && messages[i].args.length == 1) {
 				me.addInclude("<" + messages[i].args[0].val + ">");
 			} else {
 
@@ -786,6 +806,29 @@
 	return intObj;
 }
 
+function makeCPointer()
+{	
+	var cptr = new cObject('cpointer');
+	cptr.addProperty('val', null, 'void *');
+	//cpointer: 
+	//1234567890
+	cptr.addMessage('string', {
+		vars: {ret: 'string *'},
+		lines: [
+			'ret = make_object(&string_meta, NULL, 0);',
+			//22 digits for worst case sensible representation
+			//10 chars for prefix
+			//4 for slop
+			//1 for null terminator
+			'ret->data = GC_MALLOC_ATOMIC(22+10+4+1);',
+			'snprintf(ret->data, 22+10+4, "cpointer: %p", self->val);',
+			'ret->data[22+10+4] = 0;',
+			'return (object *)ret;'
+		]
+	});
+	return cptr;
+}
+
 function makeArray()
 {
 	var arrayfile = toplevel.names['array'];
@@ -827,7 +870,7 @@
 {
 	return [makeInt(64, false), makeInt(32, false), makeInt(16, false), makeInt(8, false),
 	        makeInt(64, true) , makeInt(32, true),  makeInt(16, true),  makeInt(8, true),
-	        makeArray(), makeString(), makelambda()];
+	        makeArray(), makeString(), makelambda(), makeCPointer()];
 }
 
 function addBuiltinModules(toplevel)