diff cbackend.js @ 171:869399ff7faa

Merge
author Mike Pavone <pavone@retrodev.com>
date Tue, 13 Aug 2013 22:01:00 -0700
parents 18598163e3ef 224071eed9dd
children 8d466c5a7dff
line wrap: on
line diff
--- a/cbackend.js	Tue Aug 13 21:58:03 2013 -0700
+++ b/cbackend.js	Tue Aug 13 22:01:00 2013 -0700
@@ -3,6 +3,7 @@
 
 var nextmethodId = 0;
 var methodIds = {};
+var assignNames;
 function getMethodId(methodName)
 {
 	if (!(methodName in methodIds)) {
@@ -142,7 +143,7 @@
 var declaredInts = {};
 
 intlit.prototype.toC = function() {
-	var intType = 'int' + this.bits;
+	var intType = (this.unsigned ? 'u' : '') + 'int' + this.bits;
 	var str =  intType + '_' + (this.val < 0 ? 'neg_' + (0-this.val).toString() : this.val.toString());
 	if (!(str in declaredInts)) {
 		toplevelcode += 'obj_' + intType + ' ' + str + ' = {{&obj_' + intType + '_meta, NULL}, ' + this.val.toString() + '};\n';
@@ -637,11 +638,11 @@
 	});
 }
 
-function makeInt(bits)
+function makeInt(bits, unsigned)
 {
-	var typename = 'obj_int' + bits;
+	var typename = 'obj_' + (unsigned ? 'u' : '') + 'int' + bits;
 	var intObj = new cObject(typename);
-	intObj.addProperty('num', null, 'int' + bits +'_t');
+	intObj.addProperty('num', null, (unsigned ? 'u' : '') + 'int' + bits +'_t');
 	addBinaryOp(intObj, 'ADD_', '+', typename);
 	addBinaryOp(intObj, 'SUB_', '-', typename);
 	addBinaryOp(intObj, 'MUL_', '*', typename);
@@ -666,7 +667,7 @@
 		lines: [
 			'str = (string *)make_object(&string_meta, NULL, 0);',
 			'str->data = GC_MALLOC(' + (bits == 64 ? 21 : 12) + ');',
-			'sprintf(str->data, "%' + (bits == 64 ? 'l' : '') +'d", self->num);',
+			'sprintf(str->data, "%' + (bits == 64 ? 'l' : '') + (unsigned ? 'u' : 'd') + '", self->num);',
 			'str->len = str->bytes = strlen(str->data);',
 			'return &(str->header);'
 		]
@@ -695,6 +696,37 @@
 			'return &(self->header);'
 		]
 	});
+	var sizes = [8, 16, 32, 64];
+	var destunsigned = [false, true];
+	for (var i = 0; i < sizes.length; i++) {
+		size = sizes[i];
+		for (var j = 0; j < destunsigned.length; j++) {
+			uns = destunsigned[j];
+			if (uns == unsigned && size == bits) {
+				intObj.addMessage((uns ? 'u' : '') + 'int' + size, {
+					vars: {},
+					lines: [
+						'return &(self->header);'
+					]
+				});
+			} else {
+				var retType = 'obj_' + (uns ? 'u' : '') + 'int' + size;
+				var retName = 'ret' + (uns ? 'u' : '') + size;
+				var vars = {};
+				vars[retName] = retType + ' *';
+				intObj.addMessage((uns ? 'u' : '') + 'int' + size, {
+
+					vars: vars,
+					lines: [
+						retName + ' = ('+retType+' *)make_object(&' + retType +'_meta, NULL, 0);',
+						retName + '->num = self->num;',
+						'return &(' + retName + '->header);'
+					]
+				});
+			}
+		}
+	}
+
 	return intObj;
 }
 
@@ -737,7 +769,9 @@
 
 function builtinTypes()
 {
-	return [makeInt(64), makeInt(32), makeInt(16), makeInt(8), makeArray(), makeString(), makelambda()];
+	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()];
 }
 
 function addBuiltinModules(toplevel)
@@ -745,6 +779,9 @@
 	var os = new cObject('mod_obj_os');
 	os.addInclude('<sys/stat.h>');
 	os.addInclude('<fcntl.h>');
+	os.addInclude('<stdlib.h>');
+	os.addInclude('<time.h>');
+	os.addInclude('<unistd.h>');
 	os.addMessage('write', {
 		vars: {str: 'string *', intret: 'obj_int32 *', filedes: 'obj_int32 *'},
 		lines: [
@@ -762,8 +799,8 @@
 			'size = va_arg(args, obj_int32 *);',
 			'str = (string *)make_object(&string_meta, NULL, 0);',
 			'str->data = GC_MALLOC_ATOMIC(size->num + 1);',
-			'str->length = str->bytes = read(filedes->num, str->data, size->num);',
-			'if (str->bytes < 0) { str->bytes = str->length = 0; }',
+			'str->len = str->bytes = read(filedes->num, str->data, size->num);',
+			'if (str->bytes < 0) { str->bytes = str->len = 0; }',
 			'str->data[str->bytes] = 0;',
 			'return &(str->header);'
 		]
@@ -842,6 +879,49 @@
 			'return &(intret->header);'
 		]
 	});
+	os.addMessage('rand', {
+		vars: {intret: 'obj_int32 *'},
+		lines: [
+			'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
+			'intret->num = rand();',
+			'return &(intret->header);'
+		]
+	});
+	os.addMessage('rand64', {
+		vars: {intret64: 'obj_int64 *'},
+		lines: [
+			'intret64 = (obj_int64 *)make_object(&obj_int64_meta, NULL, 0);',
+			'intret64->num = (((int64_t)rand()) << 32 ) | rand();',
+			'return &(intret64->header);'
+		]
+	});
+	os.addMessage('srand', {
+		vars: {oseed: 'object *', seed: 'obj_int32 *'},
+		lines: [
+			'oseed = va_arg(args, object *);',
+			'seed = mcall(' + getMethodId("int32") + ', 1, oseed);',
+			'srand(seed->num);',
+			'return &(seed->header);'
+		]
+	});
+	os.addMessage('time', {
+		vars: {intret64: 'obj_int64 *'},
+		lines: [
+			'intret64 = (obj_int64 *)make_object(&obj_int64_meta, NULL, 0);',
+			'intret64->num = time(NULL);',
+			'return &(intret64->header);'
+		]
+	});
+	os.addMessage('sleep', {
+		vars: {osecs: 'object *', secs: 'obj_int32 *', intret: 'obj_int32 *'},
+		lines: [
+			'osecs = va_arg(args, object *);',
+			'secs = mcall(' + getMethodId("int32") + ', 1, osecs);',
+			'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
+			'intret->num = sleep(secs->num);',
+			'return &(intret->header);'
+		]
+	});
 	toplevel.names['os'] = os;
 }
 
@@ -880,7 +960,9 @@
 	for (var i = allused.length-1; i >= 0; i--) {
 		var symbol = allused[i];
 		debugprint('//---module', symbol, '(' + i +')--- compile');
+		assignNames.push(symbol);
 		ret += '\t' + toplevel.moduleVar(symbol) + ' = ' + toplevel.names[symbol].toC() + ';\n';
+		assignNames.pop();
 	}
 	return ret;
 }
@@ -888,6 +970,7 @@
 function makeCProg(obj)
 {
 	forwarddec = toplevelcode = '';
+	assignNames = [];
 	var builtins = builtinTypes();
 	for (var i in builtins) {
 		forwarddec += builtins[i].toEarlyCDef();
@@ -917,10 +1000,13 @@
 lambda.prototype.toC = function() {
 	var args = this.args ? this.args.slice(0, this.args.length) : [];
 	var exprs = this.expressions;
-	debugprint('//', this.name);
+	var assignPath = assignNames.join('<-');
+	debugprint('//', this.name, assignPath);
+	var addedTypeDef = false;
 	if (Object.keys(this.symbols.closedover).length) {
 		this.symbols.envtype = this.name + '_env';
 		forwarddec += 'typedef struct ' + this.symbols.envtype + '  ' + this.symbols.envtype + ';\n'
+		var addedTypeDef = true;
 	}
 	if (this.selftype) {
 		this.symbols.defineVar('self', this.selftype);
@@ -949,6 +1035,12 @@
 	}
 
 	if (Object.keys(this.symbols.closedover).length) {
+		if (!addedTypeDef) {
+			for (var key in this.symbols.closedover) {
+				print(key, ": ", this.symbols.closedover[key]);
+			}
+			throw new Error('this.symbols.closedover is not empty, but it was when compilation of ' + this.name + ' "' + assignPath + '" started');
+		}
 		forwarddec += 'struct ' + this.name + '_env {\n';
 		if (this.symbols.needsParentEnv) {
 			forwarddec += '\tstruct ' + this.symbols.parentEnvType() + ' * parent;\n';
@@ -972,6 +1064,7 @@
 	}
 	forwarddec += 'object *' + this.name + ' (' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...);\n';
 
+	toplevelcode += '//' + assignPath + "\n";
 	toplevelcode +=  'object * ' + this.name + ' ( ' + this.symbols.parentEnvType() + ' * env, uint32_t num_args, ...) {\n\tva_list args;\n' + myenvinit + '\tva_start(args, num_args);\n';
 	if (this.selftype) {
 		var selfvar = (new symbol('self', this.symbols)).toC();
@@ -1042,7 +1135,9 @@
 	debugprint('//assignment', this.symbol.name);
 	var existing = this.symbols.find(this.symbol.name);
 	var prefix = '';
+	assignNames.push(this.symbol.name);
 	var val = this.expression.toC();
+	assignNames.pop(this.symbol.name);
 	if (val === null) {
 		return null;
 	}
@@ -1055,11 +1150,13 @@
 };
 assignment.prototype.toCObject = function(cobj) {
 	debugprint('//message definition', this.symbol.name);
+	assignNames.push('#' + this.symbol.name);
 	if (this.expression.toCObject) {
 		var val = this.expression.toCObject(cobj.name);
 	} else {
 		var val = this.expression.toC();
 	}
+	assignNames.pop();
 	if (val === null) {
 		return;
 	}