"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.or = exports.and = exports.simplifyType = exports.normalizeExpressions = void 0;
const ast_1 = require("../ast");
const simplify_1 = __importDefault(require("./simplify"));
function normalizeExpressions(node) {
    if (ast_1.TypeExpression.is(node)) {
        node = node.value;
    }
    if (ast_1.Reference.is(node)) {
        return new ast_1.BinaryExpression({
            location: node.location,
            left: new ast_1.DotExpression({}),
            operator: "is",
            right: node
        });
    }
    return node;
}
exports.normalizeExpressions = normalizeExpressions;
function simplifyType(type) {
    if (ast_1.Expression.is(type)) {
        type = simplify_1.default(type);
    }
    if (ast_1.TypeExpression.is(type)) {
        let { value } = type;
        if (ast_1.BinaryExpression.is(value) && ast_1.DotExpression.is(value.left) && value.operator === "is" && (ast_1.Reference.is(value.right) || ast_1.FunctionType.is(value.right))) {
            return value.right;
        }
    }
    else if (ast_1.Expression.is(type)) {
        type = new ast_1.TypeExpression({ value: type });
    }
    return type;
}
exports.simplifyType = simplifyType;
function and(left, right) {
    return combineTypeExpression(left, right, "&&");
}
exports.and = and;
function or(left, right) {
    return combineTypeExpression(left, right, "||");
}
exports.or = or;
function combineTypeExpression(left, right, operator) {
    if (left == null) {
        return right;
    }
    if (right == null) {
        return left;
    }
    left = simplify_1.default(normalizeExpressions(left));
    right = simplify_1.default(normalizeExpressions(right));
    return simplify_1.default(new ast_1.BinaryExpression({ left, operator, right }));
}
exports.default = combineTypeExpression;
