changeset 43:27a2167663dd

Improve compiler error reporting. Fix operator associativity. Add some more string operations and a string ops sample
author Mike Pavone <pavone@retrodev.com>
date Thu, 12 Jul 2012 22:10:58 -0700
parents 4e983fe32047
children 9dd370530f69
files cbackend.js parser.js samples/stringops.tp tpc.js
diffstat 4 files changed, 73 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/cbackend.js	Thu Jul 12 20:14:15 2012 -0700
+++ b/cbackend.js	Thu Jul 12 22:10:58 2012 -0700
@@ -40,7 +40,7 @@
 }
 
 op.prototype.toC = function(isReceiver) {
-	var optoMeth = {'+': 'ADD_', '-': 'SUB_', '*': 'MUL_', '/': 'DIV_', '=': 'EQ_', '!=': 'NEQ_', '<': 'LT_', '>': 'GT_', '>=': 'GEQ_', '<=': 'LEQ_'};
+	var optoMeth = {'+': 'ADD_', '-': 'SUB_', '*': 'MUL_', '/': 'DIV_', '=': 'EQ_', '!=': 'NEQ_', '<': 'LT_', '>': 'GT_', '>=': 'GEQ_', '<=': 'LEQ_', '.': 'CAT_'};
 	var method = optoMeth[this.op];
 	return 'mcall(' + getMethodId(method) + ', 2, ' + this.left.toC() + ', ' + this.right.toC() + ')\n';
 };
@@ -122,7 +122,7 @@
 strlit.prototype.toC = function() {
 	if (!(this.val in declaredStrings)) {
 		//TODO: get the proper byte length
-		toplevelcode += 'string str_' + nextStringId + ' = {{&string_meta, NULL}, ' + this.val.length + ', ' + this.val.length + ', ' + this.val.length + ', "' + this.val.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') + '"};\n';
+		toplevelcode += 'string str_' + nextStringId + ' = {{&string_meta, NULL}, ' + this.val.length + ', ' + this.val.length + ', "' + this.val.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') + '"};\n';
 		declaredStrings[this.val] = nextStringId++;
 	}
 	return '((object *)&str_' + declaredStrings[this.val] + ')';
@@ -379,6 +379,16 @@
 	addCompOp(int32, 'NEQ_', '!=', 'obj_int32');
 	addCompOp(int32, 'GEQ_', '>=', 'obj_int32');
 	addCompOp(int32, 'LEQ_', '<=', 'obj_int32');
+	int32.addMessage('string', {
+		vars: {str: 'string *'},
+		lines: [
+			'str = (string *)make_object(&string_meta, NULL, 0);',
+			'str->data = malloc(12);',
+			'sprintf(str->data, "%d", self->num);',
+			'str->length = str->bytes = strlen(str->data);',
+			'return (object *)str;'
+		]
+	});
 	var array = new cObject('array');
 	array.addProperty('size', null, 'uint32_t');
 	array.addProperty('storage', null, 'uint32_t');
@@ -434,7 +444,6 @@
 	var string = new cObject('string');
 	string.addProperty('length', null, 'uint32_t');
 	string.addProperty('bytes', null, 'uint32_t');
-	string.addProperty('storage', null, 'uint32_t');
 	string.addProperty('data', null, 'char *');
 	string.addMessage('length', {
 		vars: {intret: 'obj_int32 *'},
@@ -444,6 +453,14 @@
 			'return &(intret->header);'
 		]
 	});
+	string.addMessage('byte_length', {
+		vars: {intret: 'obj_int32 *'},
+		lines: [
+			'intret = (obj_int32 *)make_object(&obj_int32_meta, NULL, 0);',
+			'intret->num = self->bytes;',
+			'return &(intret->header);'
+		]
+	});
 	string.addMessage('EQ_', {
 		vars: {argb: 'string *'},
 		lines: [
@@ -461,6 +478,24 @@
 			'return self;'
 		]
 	});
+	string.addMessage('string', {
+		vars: {},
+		lines: [ 'return self;' ]
+	});
+	string.addMessage('CAT_', {
+		vars: {argbo: 'object *', argb: 'string *', out: 'string *'},
+		lines: [
+			'argbo = va_arg(args, object *);',
+			'argb = mcall(' + getMethodId('string') + ', 1, argbo);',
+			'out = (string *)make_object(&string_meta, NULL, 0);',
+			'out->bytes = self->bytes + argb->bytes;',
+			'out->length = self->length + argb->length;',
+			'out->data = malloc(out->bytes+1);',
+			'memcpy(out->data, self->data, self->bytes);',
+			'memcpy(out->data + self->bytes, argb->data, argb->bytes + 1);',
+			'return out;'
+		]
+	});
 	forwarddec = toplevelcode = '';
 	forwarddec += int32.toEarlyCDef() + array.toEarlyCDef() + string.toEarlyCDef();
 	toplevelcode += int32.toCDef() + array.toCDef() + string.toCDef();
--- a/parser.js	Thu Jul 12 20:14:15 2012 -0700
+++ b/parser.js	Thu Jul 12 22:10:58 2012 -0700
@@ -74,9 +74,9 @@
 'ws = ([ \\t\\n\\r] / "//" [^\\n]* "\\n")*;' +
 'hws = ([ \\t] / "/*" ([^*] / "*" ! "/")* "*/" )*;' +
 'expr = e:(funcall / methcall / opexpr) ws { return e; };' +
-'opexpr = left:addsub hws opn:("<=" / ">=" / "<" / ">" / "=") hws right:opexpr { return new op(left, opn, right); } / addsub;' +
-'addsub = left:muldiv hws opn:("+"/"-") hws right:addsub { return new op(left, opn, right); } / muldiv;'+
-'muldiv = left:primlitsym hws opn:("*"/"/") hws right:muldiv { return new op(left, opn, right); } / primlitsym;'+
+'opexpr = left:addsub pieces:(hws ("<=" / ">=" / "<" / ">" / "=") hws addsub)* { 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; } };'+
+'addsub = left:muldiv pieces:(hws ("+"/"-"/".") hws muldiv)* { 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; } };'+
+'muldiv = left:primlitsym pieces:(hws ("*"/"/") hws 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 / int / string / symbol / object / array / list / lambda / "(" expr:expr hws ")" { return expr; }) { return val; };' +
 'symbol = chars:[a-zA-Z_!?@]+ trailing:(":"? [a-zA-Z_!?@0-9])* ! ":" { for (var i in trailing) { 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(""))); };' +
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/stringops.tp	Thu Jul 12 22:10:58 2012 -0700
@@ -0,0 +1,6 @@
+#{
+	main <- {
+		print: "foo: " . 42 . "\n"
+		print: (string: (length: "foo" . "bar")) . "\n"
+	}
+}
--- a/tpc.js	Thu Jul 12 20:14:15 2012 -0700
+++ b/tpc.js	Thu Jul 12 22:10:58 2012 -0700
@@ -16,7 +16,30 @@
 	load('parser.js');
 	load('compiler.js');
 	load('cbackend.js');
-	var parsed = parser.parse(text);
-	var c = parsed.toCModule();
-	print(c);
+	try {
+		var parsed = parser.parse(text);
+		var c = parsed.toCModule();
+		print(c);
+	} catch(error) {
+		if (error.name == 'SyntaxError') {
+			print('SyntaxError on at', error.line, ',', error.column, ':', error.message);
+			var lines = text.split('\n');
+			print(lines[error.line-1]);
+			var spacer = '';
+			for (var i = 1; i < error.column; i++) {
+				if (lines[error.line-1].charAt(i-1) == '\t') {
+					spacer += '    ';
+				} else {
+					spacer += ' ';
+				}
+			}
+			print(spacer + '^');
+		} else {
+			print("Exception:");
+			var keys = Object.keys(error);
+			for (var i = 0; i < keys.length; ++i) {
+				print('\t', keys[i], error[keys[i]]);
+			}
+		}
+	}
 }