Mathias Panzenböck avatar Mathias Panzenböck committed b208e14

helper ++

Comments (0)

Files changed (3)

 "use strict";
 
 var extend = require("extend");
+var esprima = require("esprima");
 
 var PrecedenceMap = {
 	'.':   { order: 1, rtl: false },
 	',':    { order: 17, rtl: false }
 };
 
+function wrap (value) {
+	if (value === undefined) {
+		return new Identifier('undefined');
+	}
+	else if (value instanceof Node) {
+		return value;
+	}
+	else if (typeof(value) === "function") {
+		return new require("./clonevisitor.js").CloneVisitor().visit(
+			esprima.parse("("+value.toString()+");").body[0].expression);
+	}
+	else if (value instanceof RegExp || value === null || typeof(value) !== "object") {
+		return new Literal(value);
+	}
+	else if (Array.isArray(value)) {
+		return new ArrayExpression(value.map(wrap));
+	}
+	else {
+		var properties = [];
+		for (var name in value) {
+			properties.push(new Property(new Identifier(name), wrap(value[name])));
+		}
+		return new ObjectExpression(properties);
+	}
+}
+
+function idwrap (name) {
+	if (name instanceof Node) {
+		return name;
+	}
+	else if (name === "this") {
+		return new ThisExpression();
+	}
+	else {
+		return new Identifier(name);
+	}
+}
+
+function blockwrap (body) {
+	if (body instanceof Expression) {
+		return new ExpressionStatement(body);
+	}
+	else if (body instanceof Node) {
+		return body;
+	}
+	return new BlockStatement(body.map(blockwrap));
+}
+
+var NodeHelper = {
+	val: wrap,
+	id: idwrap,
+	var: function () {
+		return this.decl('var',arguments);
+	},
+	let: function () {
+		return this.decl('let',arguments);
+	},
+	const: function () {
+		return this.decl('const',arguments);
+	},
+	decl: function (kind, decls) {
+		var declarators = [];
+		for (var i = 0; i < decls.length; ++ i) {
+			var decl = decls[i];
+			if (typeof decl === "object") {
+				for (var name in decl) {
+					declarations.push(new VariableDeclarator(
+						new Identifier(name),wrap(decl[name])));
+				}
+			}
+			else {
+				declarations.push(new VariableDeclarator(idwrap(decl),null));
+			}
+		}
+	},
+	funexp: function (name, args, body) {
+		return new FunctionExpression(
+			name ? idwrap(name) : null,
+			args ? args.map(idwrap) : [],
+			this.block(body));
+	},
+	fundecl: function (name, args, body) {
+		return new FunctionDeclaration(
+			idwrap(name),
+			args ? args.map(idwrap) : [],
+			this.block(body));
+	},
+	block: function (body) {
+		return new BlockStatement((body||[]).map(blockwrap));
+	},
+	program: function (body) {
+		return new Program((body||[]).map(blockwrap));
+	},
+	this: function () {
+		return new ThisExpression();
+	},
+	empty: function () {
+		return new EmptyStatement();
+	},
+	expr: function (code) {
+		if (code instanceof Expression) {
+			return code;
+		}
+		return new require("./clonevisitor.js").CloneVisitor().visit(
+			esprima.parse("("+code+");").body[0].expression);
+	},
+	stmt: function (code) {
+		if (code instanceof Expression) {
+			return code.stmt();
+		}
+		else if (code instanceof Statement) {
+			return code;
+		}
+		return new require("./clonevisitor.js").CloneVisitor().visit(
+			esprima.parse(code).body[0]);
+	},
+	neg: function (expr) {
+		return wrap(expr).neg();
+	},
+	pos: function (expr) {
+		return wrap(expr).pos();
+	},
+	not: function (expr) {
+		return wrap(expr).not();
+	},
+	bnot: function (expr) {
+		return wrap(expr).bnot();
+	},
+	typeof: function (expr) {
+		return wrap(expr).typeof();
+	},
+	void: function (expr) {
+		return wrap(expr).void();
+	},
+	delete: function (expr) {
+		return wrap(expr).delete();
+	},
+	inc: function (expr) {
+		return wrap(expr).preinc();
+	},
+	dec: function (expr) {
+		return wrap(expr).predec();
+	}
+};
+
 function Node () {}
 function Statement () {}
 function Declaration () {}
 	toString: function () {
 		return require("escodegen").generate(this);
 	}
-	// TODO: add lots of helper functions
 };
 
 Statement.prototype = new Node();
 			return !this.precedence.rtl;
 		}
 	},
-	precedence: {order: 0, rtl: false}
+	precedence: {order: 0, rtl: false},
+
+	// Helpers:
+	get: function (key, computed) {
+		return new MemberExpression(this, computed ? wrap(key) : idwrap(key), !!computed);
+	},
+	set: function (key, value, computed) {
+		return this.get(key,computed).assign('=', value);
+	},
+	assign: function (operator, value) {
+		if (arguments.length === 1) {
+			value = operator;
+			operator = '=';
+		}
+		return new AssignmentExpression(operator, this, wrap(value));
+	},
+	op: function (operator, value) {
+		if (arguments.length === 1) {
+			if (operator === '++' || operator === '--') {
+				return this.update(operator, null);
+			}
+			else {
+				return this.unary(operator);
+			}
+		}
+		else if (operator === '&&' || operator === '||') {
+			return this.logical(operator, value);
+		}
+		else if (operator === '++' || operator === '--') {
+			return this.update(operator, value);
+		}
+		else {
+			return this.binary(operator, this, value);
+		}
+	},
+	unary: function (operator) {
+		return new UnaryExpression(operator, this);
+	},
+	binary: function (operator, value) {
+		return new BinaryExpression(operator, this, wrap(value));
+	},
+	logical: function (operator, value) {
+		return new LogicalExpression(operator, this, wrap(value));
+	},
+	update: function (operator, prefix) {
+		return new UpdateExpression(operator, this, !!prefix);
+	},
+	preinc: function () {
+		return this.update('++', true);
+	},
+	predec: function () {
+		return this.update('--', true);
+	},
+	suffinc: function () {
+		return this.update('++', false);
+	},
+	suffdec: function () {
+		return this.update('--', false);
+	},
+	inc: function (prefix) {
+		return this.update('++', prefix);
+	},
+	dec: function (prefix) {
+		return this.update('--', prefix);
+	},
+	neg: function () {
+		return this.unary('-');
+	},
+	pos: function () {
+		return this.unary('+');
+	},
+	not: function () {
+		return this.unary('!');
+	},
+	bnot: function () {
+		return this.unary('~');
+	},
+	typeof: function () {
+		return this.unary('typeof');
+	},
+	void: function () {
+		return this.unary('void');
+	},
+	delete: function () {
+		return this.unary('delete');
+	},
+	eq: function (value) {
+		return this.binary('==', value);
+	},
+	neq: function (value) {
+		return this.binary('!=', value);
+	},
+	seq: function (value) {
+		return this.binary('===', value);
+	},
+	sneq: function (value) {
+		return this.binary('!==', value);
+	},
+	lt: function (value) {
+		return this.binary('<', value);
+	},
+	gt: function (value) {
+		return this.binary('>', value);
+	},
+	le: function (value) {
+		return this.binary('<=', value);
+	},
+	ge: function (value) {
+		return this.binary('>=', value);
+	},
+	lshift: function (value) {
+		return this.binary('<<', value);
+	},
+	rshift: function (value) {
+		return this.binary('>>', value);
+	},
+	zrshift: function (value) {
+		return this.binary('>>>', value);
+	},
+	add: function (value) {
+		return this.binary('+', value);
+	},
+	sub: function (value) {
+		return this.binary('-', value);
+	},
+	mul: function (value) {
+		return this.binary('*', value);
+	},
+	div: function (value) {
+		return this.binary('/', value);
+	},
+	mod: function (value) {
+		return this.binary('%', value);
+	},
+	bor: function (value) {
+		return this.binary('|', value);
+	},
+	band: function (value) {
+		return this.binary('&', value);
+	},
+	xor: function (value) {
+		return this.binary('^', value);
+	},
+	in: function (value) {
+		return this.binary('in', value);
+	},
+	instanceof: function (value) {
+		return this.binary('instanceof', value);
+	},
+	and: function (value) {
+		return this.logical('&&', value);
+	},
+	or: function (value) {
+		return this.logical('||', value);
+	},
+	new: function () {
+		return new NewExpression(this, Array.prototype.map.call(arguments,wrap));
+	},
+	call: function () {
+		return new CallExpression(this, Array.prototype.map.call(arguments,wrap));
+	},
+	stmt: function () {
+		return new ExpressionStatement(this);
+	}
 });
 Expression.prototype.hasPrecedence = Expression.prototype.hasRightPrecedence;
 Declaration.prototype = new Statement();
 Literal.prototype = new Expression();
 Property.prototype = new Expression();
 
+exports.NodeHelper = NodeHelper;
 exports.Node = Node;
 exports.Expression = Expression;
 exports.Declaration = Declaration;
 	},
 	object: function (value) {
 		// TODO
+	},
+	pos: function (expr) {
+		return wrap(expr).pos();
+	},
+	not: function (expr) {
+		return wrap(expr).not();
+	},
+	bnot: function (expr) {
+		return wrap(expr).bnot();
+	},
+	typeof: function (expr) {
+		return wrap(expr).typeof();
+	},
+	void: function (expr) {
+		return wrap(expr).void();
+	},
+	delete: function (expr) {
+		return wrap(expr).delete();
+	},
+	inc: function (expr) {
+		return wrap(expr).preinc();
+	},
+	dec: function (expr) {
+		return wrap(expr).predec();
 	}
 	// TODO: label, if, while, do while, for, for in, with, return, break,
 	//       continue, try, throw, catch, switch, case, block, program
 		return new MemberPattern(this, wrap(key), computed === null ? null : !!computed);
 	},
 	set: function (key, value, computed) {
-		return this.get(wrap(key), computed).assign(wrap(value));
+		return this.get(key, computed).assign(value);
 	},
 	assign: function (operator, value) {
 		if (arguments.length === 1) {
 	suffdec: function () {
 		return this.update('--', false);
 	},
+	inc: function (prefix) {
+		return this.update('++', prefix);
+	},
+	dec: function (prefix) {
+		return this.update('--', prefix);
+	},
 	neg: function () {
 		return this.unary('-');
 	},
 
 function test (code) {
 var match = patterns.PatternHelper;
+var make = nodes.NodeHelper;
 if (!code) code = "a._('foo'); _('bar'); _(x); _(12); _(); function f () { var _; _('baz'); } _('bar'); function g () { _('egg'+' '+'bacon', a, b); }";
 var MinVisitor = require("./minvisitor.js").MinVisitor;
 var tbl = {};
 		id = '_'+(nextid++);
 		tbl[s] = id;
 	}
-	return new nodes.MemberExpression(new nodes.Identifier('_'),new nodes.Identifier(id),false);
+	return make.id('_').get(id);
 }).transform(code,{optimizeBefore:true});
 console.log("result:", new MinVisitor().visit(node));
 console.log("tbl:", tbl);
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.