changeset 286:ddf38b66b2e2

Finish support for floating point numbers in C backend
author Michael Pavone <pavone@retrodev.com>
date Tue, 22 Jul 2014 18:31:31 -0700
parents bb1539decd62
children b01d7c1b4edd
files cbackend.js modules/json.tp parser.js
diffstat 3 files changed, 73 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/cbackend.js	Tue Jul 22 08:35:30 2014 -0700
+++ b/cbackend.js	Tue Jul 22 18:31:31 2014 -0700
@@ -164,7 +164,13 @@
 };
 
 floatlit.prototype.toC = function() {
-	return 'make_float(' + this.val.toString() + ')';
+	var floatType = this.bits == 32 ? 'float' : 'double';
+	var str =  floatType + '_' + (this.val < 0 ? 'neg_' + (0-this.val).toString() : this.val.toString()).replace('.', '_');
+	if (!(str in declaredInts)) {
+		toplevelcode += 'obj_float' + this.bits + ' ' + str + ' = {{&obj_float' + this.bits + '_meta, NULL}, ' + this.val.toString() + '};\n';
+		declaredInts[str] = true;
+	}
+	return '((object *)&' + str + ')';
 }
 floatlit.prototype.toCLLExpr = function(vars) {
 	return this.val.toString();
@@ -707,27 +713,40 @@
 	});
 }
 
+function addNumberOps(obj, typename)
+{
+	addBinaryOp(obj, '+', '+', typename);
+	addBinaryOp(obj, '-', '-', typename);
+	addBinaryOp(obj, '*', '*', typename);
+	addBinaryOp(obj, '/', '/', typename);
+	addCompOp(obj, '<', '<', typename);
+	addCompOp(obj, '>', '>', typename);
+	addCompOp(obj, '=', '==', typename);
+	addCompOp(obj, '!=', '!=', typename);
+	addCompOp(obj, '>=', '>=', typename);
+	addCompOp(obj, '<=', '<=', typename);
+
+	obj.addMessage('jsonEncode', {
+		vars: {},
+		lines: [
+			'return mcall(' + getMethodId('string') + ', 1, &self->header);'
+		]
+	});
+}
+
 function makeInt(bits, unsigned)
 {
 	var typename = 'obj_' + (unsigned ? 'u' : '') + 'int' + bits;
 	var intObj = new cObject(typename);
 	intObj.addProperty('num', null, (unsigned ? 'u' : '') + 'int' + bits +'_t');
-	addBinaryOp(intObj, '+', '+', typename);
-	addBinaryOp(intObj, '-', '-', typename);
-	addBinaryOp(intObj, '*', '*', typename);
-	addBinaryOp(intObj, '/', '/', typename);
+	addNumberOps(intObj, typename);
 	addBinaryOp(intObj, '%', '%', typename);
 	addBinaryOp(intObj, 'or', '|', typename);
 	addBinaryOp(intObj, 'xor', '^', typename);
 	addBinaryOp(intObj, 'and', '&', typename);
 	addBinaryOp(intObj, 'lshift:by', '<<', typename);
 	addBinaryOp(intObj, 'rshift:by', '>>', typename);
-	addCompOp(intObj, '<', '<', typename);
-	addCompOp(intObj, '>', '>', typename);
-	addCompOp(intObj, '=', '==', typename);
-	addCompOp(intObj, '!=', '!=', typename);
-	addCompOp(intObj, '>=', '>=', typename);
-	addCompOp(intObj, '<=', '<=', typename);
+
 	intObj.addInclude('<string.h>');
 	//-9223372036854775808
 	//01234567890123456789
@@ -741,12 +760,6 @@
 			'return &(str->header);'
 		]
 	});
-	intObj.addMessage('jsonEncode', {
-		vars: {},
-		lines: [
-			'return mcall(' + getMethodId('string') + ', 1, &self->header);'
-		]
-	});
 	//7FFFFFFFFFFFFFFF
 	//01234567890123456789
 	intObj.addMessage('hex', {
@@ -811,6 +824,43 @@
 	return intObj;
 }
 
+function makeFloat(bits)
+{
+	var typename = 'obj_float' + bits;
+	var floatObj = new cObject(typename);
+	floatObj.addProperty('num', null, bits == 32 ? 'float' : 'double');
+	addNumberOps(floatObj, typename);
+
+	floatObj.addInclude('<string.h>');
+	floatObj.addMessage('string', {
+		vars: {str: 'string *'},
+		lines: [
+			'str = (string *)make_object(&string_meta, NULL, 0);',
+			//probably overkill, but lets play it safe for now
+			'str->data = GC_MALLOC(128);',
+			'sprintf(str->data, "%f", self->num);',
+			'str->len = str->bytes = strlen(str->data);',
+			'return &(str->header);'
+		]
+	});
+	floatObj.addMessage('f' + bits, {
+		vars: {},
+		lines: [
+			'return &(self->header);'
+		]
+	});
+
+	floatObj.addMessage('f' + (bits == 32 ? 64 : 32), {
+		vars: {trans: 'obj_float' + (bits == 32 ? 64 : 32) + ' *'},
+		lines: [
+			'trans = make_object(&obj_float' + (bits == 32 ? 64 : 32) + '_meta, NULL, 0);',
+			'trans->num = self->num;',
+			'return &(trans->header);'
+		]
+	});
+	return floatObj;
+}
+
 function makeCPointer()
 {
 	var cptr = new cObject('cpointer');
@@ -875,7 +925,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(), makeCPointer()];
+	        makeFloat(32), makeFloat(64), makeArray(), makeString(), makelambda(), makeCPointer()];
 }
 
 function addBuiltinModules(toplevel)
--- a/modules/json.tp	Tue Jul 22 08:35:30 2014 -0700
+++ b/modules/json.tp	Tue Jul 22 18:31:31 2014 -0700
@@ -189,9 +189,9 @@
 				baz <- ["fizz" "buzz" "buzzzz"]
 				qux <- ((dict hash) set: "fo" "shizzle") set: "my" "nizzle"
 				arr <- #["pirate" "booty"]
-				numbers <- [1 2 3 42 (0-1337)]
+				numbers <- [1 2 3 42 (0-1337) 3.14159]
 				booleans <- [
-					true 
+					true
 					false
 				]
 			}
--- a/parser.js	Tue Jul 22 08:35:30 2014 -0700
+++ b/parser.js	Tue Jul 22 18:31:31 2014 -0700
@@ -46,9 +46,10 @@
 	return val;
 };
 
-function floatlit(val)
+function floatlit(val, bits)
 {
 	this.val = val;
+	this.bits = bits;
 }
 floatlit.prototype.valueOf = function() {
 	return '' + val;
@@ -206,7 +207,7 @@
 'muldiv = left:primlitsym pieces:(hws ("*"/"/"/"%") ws primlitsym)* { if (pieces.length) { var cur = new op(left, pieces[0][1], pieces[0][3]); for (var i = 1; i < pieces.length; i++) { cur = new op(cur, pieces[i][1], pieces[i][3]); } return cur; } else { return left; } };'+
 'primlitsym = hws val:(float / hex / binary / int / string / symbol / object / array / list / lambda / "(" ws expr:expr hws ")" { return expr; }) { return val; };' +
 'symbol = chars:[a-zA-Z_!?@]+ trailing:(":"? [a-zA-Z_!?@0-9])* ! ":" { for (var i = 0; i < trailing.length; i++) { trailing[i] = trailing[i].join(""); } return new symbol(chars.join("") + trailing.join("")); };' +
-'float = digits:[0-9]+ "." decimals:[0-9]+ { return new floatlit(parseFloat(digits.join("") + "." + decimals.join(""))); };' +
+'float = digits:[0-9]+ "." decimals:[0-9]+ size:("f" ("32" / "64"))? { var bits = size ? parseInt(size[1], 10) : 64; return new floatlit(parseFloat(digits.join("") + "." + decimals.join("")), bits); };' +
 'binary = "0b" digits:[01]+ { return new intlit(parseInt(digits.join(""), 2)); };' +
 'hex = "0x" digits:[0-9a-fA-F]+ size:([iu] ("8" / "16" / "32" / "64"))? { var bits = size ? parseInt(size[1], 10) : 0; return new intlit(parseInt(digits.join(""), 16), bits, size[0] == "u"); };' +
 'int = sign:"-"? digits:[0-9]+ size:([iu] ("8" / "16" / "32" / "64"))? { var bits = size ? parseInt(size[1], 10) : 0; return new intlit(parseInt(sign + digits.join(""), 10), bits, size[0] == "u"); };' +