diff parser.js @ 217:adad61ea2f3a

Switched to a less hacky implementation of hygiene and exposed more AST properties to macros
author Michael Pavone <pavone@retrodev.com>
date Sat, 21 Dec 2013 12:07:51 -0800
parents e01137a97654
children 7435367a932a
line wrap: on
line diff
--- a/parser.js	Sat Dec 21 12:07:00 2013 -0800
+++ b/parser.js	Sat Dec 21 12:07:51 2013 -0800
@@ -2,18 +2,28 @@
 function op(left, op, right)
 {
 	this.left = left;
+	if (op instanceof Array) {
+		op = op[0];
+	}
 	this.op = op;
 	this.right = right;
 }
+op.prototype.valueOf = function(indent) {
+	return this.left.valueOf(indent) + ' ' + this.op.valueOf(indent) + ' ' + this.right.valueOf(indent);
+};
 
 function symbol(name, symbols)
 {
 	this.name = name;
 	this.symbols = symbols;
+	this.dirty = false;
 }
 symbol.prototype.cleanName = function() {
 	return this.name[0] == ':' ? this.name.substr(1) : this.name;
 }
+symbol.prototype.valueOf = function() {
+	return this.name;
+};
 
 function intlit(val, bits, unsigned)
 {
@@ -27,51 +37,156 @@
 	this.bits = bits;
 	this.val = val;
 }
+intlit.prototype.valueOf = function() {
+	var val = '' + this.val;
+	if (this.bits != 32 || this.unsigned) {
+		val += this.unsigned ? 'u' : 'i'
+		val += this.bits;
+	}
+	return val;
+};
 
 function floatlit(val)
 {
 	this.val = val;
 }
+floatlit.prototype.valueOf = function() {
+	return '' + val;
+};
 
 function strlit(val)
 {
 	this.val = val;
 }
+strlit.prototype.valueOf = function() {
+	return '"'+this.val+'"';
+};
 
 function listlit(val)
 {
 	this.val = val;
 }
+listlit.prototype.valueOf = function(indent) {
+	if (indent === undefined) {
+		indent = '';
+	}
+	var nextindent = indent + '\t';
+	var val = '['
+	for (var i = 0; i < this.val.length; i++) {
+		val += '\n' + nextindent + this.val[i].valueOf(nextindent);
+	}
+	if (this.val.length) {
+		val += '\n' + indent;
+	}
+	val += ']';
+	return val;
+};
 
 function arraylit(val)
 {
 	this.val = val;
 }
+arraylit.prototype.valueOf = function(indent) {
+	if (indent === undefined) {
+		indent = '';
+	}
+	var nextindent = indent + '\t';
+	var val = '#['
+	for (var i = 0; i < this.val.length; i++) {
+		val += '\n' + nextindent + this.val[i].valueOf(nextindent);
+	}
+	if (this.val.length) {
+		val += '\n' + indent;
+	}
+	val += ']';
+	return val;
+};
 
 function funcall(name, args)
 {
 	this.name = name;
 	this.args = args;
 	this.receiver = null;
+	this.dirty = false;
 }
+funcall.prototype.valueOf = function(indent) {
+	var parts = this.name.split(':');
+	var val = '';
+	if (this.receiver) {
+		val += this.receiver.valueOf(indent);
+	}
+	var curarg = 0;
+	for (var i = 0; i < parts.length; i++) {
+		if (val) {
+			val += ' ';
+		}
+		if (parts[i]) {
+			val += parts[i] + ': ';
+		}
+		if (curarg < this.args.length) {
+			val += this.args[curarg++].valueOf(indent);
+		}
+	}
+	while (curarg < this.args.length) {
+		val += ' ' + this.args[curarg++].valueOf(indent);
+	}
+	return val;
+};
 
 function object(messages)
 {
 	this.messages = messages;
 	this.name = null;
 }
+object.prototype.valueOf = function(indent) {
+	if (indent === undefined) {
+		indent = '';
+	}
+	var nextindent = indent + '\t';
+	var val = '#{';
+	for (var i = 0; i < this.messages.length; i++) {
+		val += '\n' + nextindent +  this.messages[i].valueOf(nextindent);
+	}
+	if (val.length > 2) {
+		val += '\n' + indent;
+	}
+	val += '}';
+	return val;
+};
 
 function lambda(args, expressions)
 {
 	this.args = args ? args : [];
 	this.expressions = expressions;
 }
+lambda.prototype.valueOf = function(indent) {
+	if (indent === undefined) {
+		indent = '';
+	}
+	var nextindent = indent + '\t';
+	var val = '';
+	for (var i = 0; i < this.args.length; i++) {
+		val += this.args[i].valueOf(indent) + ' ';
+	}
+	val += '{';
+	for (var i = 0; i < this.expressions.length; i++) {
+		val += '\n' + nextindent + this.expressions[i].valueOf(nextindent);
+	}
+	if (this.expressions.length) {
+		val += '\n' + indent;
+	}
+	val += '}';
+	return val;
+};
 
 function assignment(sym, expr)
 {
 	this.symbol = sym;
 	this.expression = expr;
 }
+assignment.prototype.valueOf = function(indent) {
+	return this.symbol.valueOf(indent) + ' <- ' + this.expression.valueOf(indent);
+};
 
 function isLambda(node)
 {
@@ -87,7 +202,7 @@
 'compareop = left:maybecons pieces:(hws ("<=" / ">=" / "<" / ">" / "=" / "!=") hws maybecons)* { 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; } };'+
 'maybecons = consop / addsub;' +
 'consop = left:addsub hws "|" hws right:maybecons { return new op(left, "|", right); };'+
-'addsub = left:muldiv pieces:(hws ("+"/"-"/"xor"/"and"/"or"/".") 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; } };'+
+'addsub = left:muldiv pieces:(hws ((("xor"/"and"/"or") ! [a-zA-Z_!?@0-9])/("+"/"-"/".")) 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 / 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("")); };' +