var assert = require("assert");
var n = require("./types").namedTypes;

function Path(node, parent) {
    assert.ok(this instanceof Path);
    n.Node.assert(node);
    if (parent) {
        assert.ok(parent instanceof Path);
    } else {
        parent = null;
    }

    Object.defineProperties(this, {
        node: { value: node },
        parent: { value: parent }
    });
}

var Pp = Path.prototype;

Pp.cons = function(child) {
    return new Path(child, this);
};

Pp.needsParens = function() {
    if (!this.parent)
        return false;

    var node = this.node;
    var parent = this.parent.node;

    if (n.UnaryExpression.check(node))
        return n.MemberExpression.check(parent)
            && parent.object === node;

    if (isBinary(node)) {
        if (n.CallExpression.check(parent) &&
            parent.callee === node)
            return true;

        if (n.UnaryExpression.check(parent))
            return true;

        if (n.MemberExpression.check(parent) &&
            parent.object === node)
            return true;
    }

    return false; // TODO
};

function isBinary(node) {
    return n.BinaryExpression.check(node)
        || n.LogicalExpression.check(node);
}

exports.Path = Path;

@@ -1046,24 +1046,585 @@
 rue;%0A    %7D%0A%0A
+    if (n.AssignmentExpression.check(node) %7C%7C%0A        n.ConditionalExpression.check(node))%0A    %7B%0A        if (n.UnaryExpression.check(parent))%0A            return true;%0A%0A        if (isBinary(parent))%0A            return true;%0A%0A        if (n.CallExpression.check(parent) &&%0A            parent.callee === node)%0A            return true;%0A%0A        if (n.ConditionalExpression.check(parent) &&%0A            parent.test === node)%0A            return true;%0A%0A        if (n.MemberExpression.check(parent) &&%0A            parent.object === node)%0A            return true;%0A    %7D%0A%0A
     return f

Handle {Assignment,Conditional}Expression in Path.prototype.needsParens.