# HG changeset patch # User Mike Pavone # Date 1342156258 25200 # Node ID 27a2167663dd2da5d6cdbef9dfc4c24c02e27c5c # Parent 4e983fe32047cce4dc6e9a509d71dcf541b0260a Improve compiler error reporting. Fix operator associativity. Add some more string operations and a string ops sample diff -r 4e983fe32047 -r 27a2167663dd cbackend.js --- 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(); diff -r 4e983fe32047 -r 27a2167663dd parser.js --- 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(""))); };' + diff -r 4e983fe32047 -r 27a2167663dd samples/stringops.tp --- /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" + } +} diff -r 4e983fe32047 -r 27a2167663dd tpc.js --- 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]]); + } + } + } }