/*
 * Copyright (C) 2013 Matthew Dawson <matthew@mjdsystems.ca>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ca.mcmaster.cas.matlab2smt;

/**
 *
 * @author Matthew Dawson <matthew@mjdsystems.ca>
 */
public class SMTLIBGenerator implements CheckerGenerator {
    @Override
    public String GenerateUnaryOperation(MatlabUnaryOperation op, String expression, VariableType usedType) {
        return "(" + SMTLIBGenerator.GetUnaryOperationSymbolFor(op) + " " + expression + ")";  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public String GenerateBinaryOperation(MatlabBinaryOperation op, String lhsExp, String rhsExp, VariableType usedType) {
        return "(" + SMTLIBGenerator.GetBinaryOperationSymbolFor(op) + " " + lhsExp + " " + rhsExp + ")";
    }

    @Override
    public String GenerateLiterlaValue(String value, VariableType requestedType) {
        if (requestedType instanceof RealVariableType) {
            if (value.contains(".")) {
                return value;
            } else {
                return value + ".0";
            }
        } else {
            throw new IllegalArgumentException("Can't cast literal to that type!");
        }
    }

    @Override
    public String GenerateVariableDecleration(Variable var) {
        return "(declare-fun " + var.name() + " () " + GenerateVariableType(var.type()) + ")";
    }

    public static String GenerateVariableType(VariableType type) {
        if (type instanceof RealVariableType) {
            return "Real";
        } else if (type instanceof BooleanVariableType) {
            return "Bool";
        } else {
            throw new IllegalArgumentException("SMT-LIB Doesn't handle this variable type (Class: " + type.getClass().getName() + ")");
        }
    }

    private static String GetBinaryOperationSymbolFor(MatlabBinaryOperation op) {
        switch (op) {
            case Addition:
                return "+";
            case Minus:
                return "-";
            case Multiplication:
                return "*";
            case Division:
                return "/";
            case GreaterThen:
                return ">";
            case GreaterThenEqual:
                return ">=";
            case LessThen:
                return "<";
            case LessThenEqual:
                return "<=";
            case Equals:
                return "=";
            case BooleanAnd:
                return "and";
            case BooleanOr:
                return "or";
        }
        throw new RuntimeException("Should never happen!  Asked for unhandled op: " + op + "!");
    }

    private static String GetUnaryOperationSymbolFor(MatlabUnaryOperation op) {
        switch (op) {
            case Negation:
                return "not";
            case Minus:
                return "-";
        }
        throw new RuntimeException("Should never happen!  Asked for unhandled op: " + op + "!");
    }
}
