Exemple #1
0
Info & Block::addMacroDef(ast::FunctionDec * dec)
{
    TIType ty(getGVN(), TIType::MACRO);
    Info & i = addDefine(dec->getSymbol(), ty, false, dec);
    i.exp = dec;

    return i;
}
Exemple #2
0
Info & Block::setDefaultData(const symbol::Symbol & sym)
{
    Info & i = addSym(sym, new Data(false, sym));
    i.local = Info::Local::INFO_FALSE;
    i.type = DataManager::getSymInScilabContext(getGVN(), sym, i.exists);
    addGlobal(sym);
    dm->registerData(i.data);//, __LINE__, __FILE__);

    return i;
}
Exemple #3
0
std::vector<TIType> Block::addCall(AnalysisVisitor & visitor, const unsigned int lhs, const symbol::Symbol & sym, std::vector<TIType> & in, ast::CallExp * callexp)
{
    tools::SymbolMap<Info>::iterator it;
    Block * block = getDefBlock(sym, it, false);
    types::InternalType * pIT = nullptr;
    std::vector<TIType> out(lhs, TIType(visitor.getGVN()));
    TIType type;

    if (block)
    {
        type = it->second.type;
    }
    else
    {
        type = DataManager::getSymInScilabContext(getGVN(), sym, pIT);
    }

    switch (type.type)
    {
        case TIType::FUNCTION:
        {
            if (lhs > 0)
            {
                TIType ty = Checkers::check(getGVN(), sym.getName(), in);
                if (ty.type != TIType::UNKNOWN && ty.hasInvalidDims())
                {
                    out[0] = ty.asUnknownMatrix();
                }
                else
                {
                    out[0] = ty;
                }
            }
            break;
        }
        case TIType::MACRO:
        {
            if (pIT)
            {
                visitor.getPMC().getOutTypes(visitor, dm->getMacroDef(static_cast<types::Macro *>(pIT)), in, out);
            }
            else
            {
                if (it->second.exp && it->second.exp->isFunctionDec())
                {
                    DeclaredMacroDef macrodef(static_cast<ast::FunctionDec *>(it->second.exp));
                    visitor.getPMC().getOutTypes(visitor, &macrodef, in, out);
                }
                else
                {
                    DataManager::getSymInScilabContext(getGVN(), sym, pIT);
                    visitor.getPMC().getOutTypes(visitor, dm->getMacroDef(static_cast<types::Macro *>(pIT)), in, out);
                }
            }
            break;
        }
        case TIType::MACROFILE:
        {
            DataManager::getSymInScilabContext(getGVN(), sym, pIT);
            visitor.getPMC().getOutTypes(visitor, dm->getMacroDef(static_cast<types::MacroFile *>(pIT)->getMacro()), in, out);
            break;
        }
        default:
        {
        }
    }

    return out;
}
bool AnalysisVisitor::getDimension(SymbolicDimension & dim, ast::Exp & arg, bool & safe, SymbolicDimension & out)
{
    switch (arg.getType())
    {
        case ast::Exp::COLONVAR :
        {
            out = dim;
            safe = true;
            arg.getDecorator().setDollarInfo(argIndices.top());
            return true;
        }
        case ast::Exp::DOLLARVAR : // a($)
        {
            out = SymbolicDimension(getGVN(), 1.);
            safe = true;
            arg.getDecorator().setDollarInfo(argIndices.top());
            return true;
        }
        case ast::Exp::DOUBLEEXP : // a(12) or a([1 2])
        {
            ast::DoubleExp & de = static_cast<ast::DoubleExp &>(arg);
            if (types::InternalType * const pIT = de.getConstant())
            {
                if (pIT->isDouble())
                {
                    types::Double * const pDbl = static_cast<types::Double *>(pIT);
                    if (pDbl->isEmpty())
                    {
                        out = SymbolicDimension(getGVN(), 0.);
                        safe = true;
                        return true;
                    }

                    const double * real = pDbl->getReal();
                    const int size = pDbl->getSize();
                    int64_t max;
                    if (tools::asInteger(real[0], max))
                    {
                        int64_t min = max;
                        if (!pDbl->isComplex())
                        {
                            for (int i = 0; i < size; ++i)
                            {
                                int64_t _real;
                                if (tools::asInteger(real[i], _real))
                                {
                                    if (_real < min)
                                    {
                                        min = _real;
                                    }
                                    else if (_real > max)
                                    {
                                        max = _real;
                                    }
                                }
                                else
                                {
                                    return false;
                                }
                            }

                            out = SymbolicDimension(getGVN(), size);
                            safe = (min >= 1) && getCM().check(ConstraintManager::GREATER, dim.getValue(), getGVN().getValue(max));
                            return true;
                        }
                        else
                        {
                            const double * imag = pDbl->getImg();
                            int i;
                            for (i = 0; i < size; ++i)
                            {
                                if (imag[i])
                                {
                                    break;
                                }
                                int64_t _real;
                                if (tools::asInteger(real[i], _real))
                                {
                                    if (_real < min)
                                    {
                                        min = _real;
                                    }
                                    else if (_real > max)
                                    {
                                        max = _real;
                                    }
                                }
                            }

                            if (i == size)
                            {
                                out = SymbolicDimension(getGVN(), size);
                                safe = (min >= 1) && getCM().check(ConstraintManager::GREATER, dim.getValue(), getGVN().getValue(max));
                                return true;
                            }
                            else
                            {
                                return false;
                            }
                        }
                    }
                    else
                    {
                        return false;
                    }
                }
                else if (pIT->isImplicitList())
                {
                    types::ImplicitList * const pIL = static_cast<types::ImplicitList *>(pIT);
                    double start, step, end;
                    if (AnalysisVisitor::asDouble(pIL->getStart(), start) && AnalysisVisitor::asDouble(pIL->getStep(), step) && AnalysisVisitor::asDouble(pIL->getEnd(), end))
                    {
                        double single;
                        const int type = ForList64::checkList(start, end, step, single);

                        switch (type)
                        {
                            case 0 :
                            {
                                out = SymbolicDimension(getGVN(), 0.);
                                safe = true;
                                return true;
                            }
                            case 1 :
                            {
                                out = SymbolicDimension(getGVN(), 1.);
                                safe = false;
                                return true;
                            }
                            case 2 :
                            {
                                const uint64_t N = ForList64::size(start, end, step);
                                uint64_t max, min;
                                if (step > 0)
                                {
                                    min = start;
                                    max = (uint64_t)(start + (N - 1) * step);
                                }
                                else
                                {
                                    max = start;
                                    min = (uint64_t)(start + (N - 1) * step);
                                }

                                out = SymbolicDimension(getGVN(), N);
                                safe = (min >= 1) && getCM().check(ConstraintManager::GREATER, dim.getValue(), getGVN().getValue((int64_t)max));
                                return true;
                            }
                        }
                    }
                }
            }
            else
            {
                out = SymbolicDimension(getGVN(), 1.);
                safe = (de.getValue() >= 1) && getCM().check(ConstraintManager::GREATER, dim.getValue(), getGVN().getValue(de.getValue()));
                return true;
            }
            return false;
        }
        case ast::Exp::BOOLEXP : // a(a > 1) => a([%f %t %t]) => a([2 3])
        {
            ast::BoolExp & be = static_cast<ast::BoolExp &>(arg);
            if (types::InternalType * const pIT = be.getConstant())
            {
                if (pIT->isBool())
                {
                    types::Bool * const pBool = static_cast<types::Bool *>(pIT);
                    const int size = pBool->getSize();
                    const int * data = pBool->get();
                    int64_t max = -1;
                    int64_t count = 0;
                    for (int i = 0; i < size; ++i)
                    {
                        if (data[i])
                        {
                            ++count;
                            max = i;
                        }
                    }

                    out = SymbolicDimension(getGVN(), count);
                    safe = getCM().check(ConstraintManager::GREATER, dim.getValue(), getGVN().getValue(max));
                    return true;
                }
            }
            else
            {
                if (be.getValue())
                {
                    out = SymbolicDimension(getGVN(), int64_t(1));
                }
                else
                {
                    out = SymbolicDimension(getGVN(), int64_t(0));
                }
                safe = true;
                return true;
            }
            return false;
        }
        case ast::Exp::LISTEXP :
        {
            ast::ListExp & le = static_cast<ast::ListExp &>(arg);
            SymbolicList sl;
            if (SymbolicList::get(*this, le, sl))
            {
                if (sl.isSymbolic())
                {
                    sl.evalDollar(getGVN(), dim.getValue());
                }
                TIType typ;
                if (sl.getType(getGVN(), typ))
                {
                    out = SymbolicDimension(getGVN(), typ.cols.getValue());
                    safe = false;//getCM().check(ConstraintManager::GREATER, dim.getValue(), getGVN().getValue(max));
                    return true;
                }
            }
            return false;
        }
        default :
        {
            arg.accept(*this);
            Result & _res = getResult();
            SymbolicRange & range = _res.getRange();
            if (range.isValid())
            {
                //std::wcerr << *range.getStart()->poly << ":" << *range.getEnd()->poly << ",," << *dim.getValue()->poly << std::endl;
                safe = getCM().check(ConstraintManager::VALID_RANGE, range.getStart(), range.getEnd(), getGVN().getValue(int64_t(1)), dim.getValue());
                out = _res.getType().rows * _res.getType().cols;

                return true;
            }

            if (GVN::Value * const v = _res.getConstant().getGVNValue())
            {
                GVN::Value * w = v;
                if (GVN::Value * const dollar = getGVN().getExistingValue(symbol::Symbol(L"$")))
                {
                    if (GVN::Value * const x = SymbolicList::evalDollar(getGVN(), v, dollar, dim.getValue()))
                    {
                        w = x;
                    }
                }
                bool b = getCM().check(ConstraintManager::GREATER, dim.getValue(), w);
                if (b)
                {
                    safe = getCM().check(ConstraintManager::STRICT_POSITIVE, w);
                }
                else
                {
                    safe = false;
                }
                out = SymbolicDimension(getGVN(), 1);
                return true;
            }

            // To use with find
            // e.g. a(find(a > 0)): find(a > 0) return a matrix where the max index is rc(a) so the extraction is safe
            if (_res.getType().ismatrix() && _res.getType().type != TIType::BOOLEAN)
            {
                out = _res.getType().rows * _res.getType().cols;
                SymbolicDimension & maxIndex = _res.getMaxIndex();
                if (maxIndex.isValid())
                {
                    safe = getCM().check(ConstraintManager::GREATER, dim.getValue(), maxIndex.getValue());
                }
                else
                {
                    safe = false;
                }
                return true;
            }
            return false;
        }
    }
}
bool AnalysisVisitor::analyzeIndices(TIType & type, ast::CallExp & ce)
{
    const ast::exps_t args = ce.getArgs();
    const unsigned int size = args.size();

    if (size >= 3)
    {
        // Not handle yet...
        // TODO
        return false;
    }

    if (size == 0)
    {
        Result & res = ce.getDecorator().setResult(type);
        setResult(res);
        return true;
    }

    SymbolicDimension first, second;
    bool safe, ret;

    argIndices.emplace(static_cast<ast::SimpleVar &>(ce.getName()), size, 1);
    if (size == 1)
    {
        // when there is one argument, a(?) is equivalent to A(?,1)
        // where A = matrix(a, r_a * c_a, 1)

        SymbolicDimension rows(type.rows);
        second = SymbolicDimension(getGVN(), 1);
        if (type.cols != 1)
        {
            rows *= type.cols;
        }
        ret = getDimension(rows, *args.front(), safe, first);
    }
    else
    {
        bool _safe;
        ret = getDimension(type.rows, *args.front(), _safe, first);
        if (ret)
        {
            argIndices.top().getIndex() = 2;
            ret = getDimension(type.cols, *args.back(), safe, second);
            safe = safe && _safe;
        }
        else
        {
            safe = _safe;
        }
    }
    argIndices.pop();

    if (ret)
    {
        TIType typ(getGVN(), type.type, first, second);
        Result & _res = ce.getDecorator().setResult(typ);
        setResult(_res);
        ce.getDecorator().safe = safe;
    }

    return ret;
}
void AnalysisVisitor::visit(ast::ListExp & e)
{
    logger.log(L"ListExp", e.getLocation());
    if (e.getParent()->isVarDec())
    {
        visitInVarDecCtxt(e);
        return;
    }

    e.getStart().accept(*this);
    Result & Rstart = e.getStart().getDecorator().getResult();
    e.getEnd().accept(*this);
    Result & Rend = e.getEnd().getDecorator().getResult();
    e.getStep().accept(*this);
    Result & Rstep = e.getStep().getDecorator().getResult();

    double start = 1;
    double step = 1;
    double end = 1;
    if (Rstart.getConstant().getDblValue(start) && Rstep.getConstant().getDblValue(step) && Rend.getConstant().getDblValue(end))
    {
        // Start, Step & End are constant !
        double out;
        int type = ForList64::checkList(start, end, step, out);

        switch (type)
        {
            case 0:
                e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
                break;
            case 1:
                e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::DOUBLE), -1));
                break;
            case 2:
            {
                const uint64_t N = ForList64::size(start, end, step);
                TIType T(dm.getGVN(), TIType::DOUBLE, 1, N);
                if (N == 1)
                {
                    out = start;
                }
                e.getDecorator().setResult(Result(T, dm.getTmpId(T, false)));
                break;
            }
            default:
                break;
        }
        e.setValues(start, step, end, out);
        setResult(e.getDecorator().res);

        return;
    }

    if (step == 0 || tools::isNaN(step) || !tools::isFinite(step)
            || tools::isNaN(start) || !tools::isFinite(start)
            ||  tools::isNaN(end) || !tools::isFinite(end))
    {
        e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
        return;
    }

    if (!Rstep.getConstant().getDblValue(step) || (step != -1 && step != 1))
    {
        Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
        setResult(res);
        return;
    }

    if (!Rstart.getType().isscalar() || !Rend.getType().isscalar())
    {
        Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
        setResult(res);
        return;
    }

    GVN::Value * gvnStart;
    if (Rstart.getConstant().getDblValue(start))
    {
        if (tools::getIntType(start) == tools::NOTANINT)
        {
            gvnStart = getGVN().getValue((double)tools::cast<int>(start + step));
        }
        else
        {
            gvnStart = getGVN().getValue((double)tools::cast<int>(start));
        }
    }
    else
    {
        gvnStart = Rstart.getConstant().getGVNValue();
        if (!gvnStart)
        {
            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
            setResult(res);
            return;
        }
    }

    GVN::Value * gvnEnd;

    if (Rend.getConstant().getDblValue(end))
    {
        if (tools::getIntType(end) == tools::NOTANINT)
        {
            gvnEnd = getGVN().getValue((double)tools::cast<int>(end - step));
        }
        else
        {
            gvnEnd = getGVN().getValue((double)tools::cast<int>(end));
        }
    }
    else
    {
        gvnEnd = Rend.getConstant().getGVNValue();
        if (!gvnEnd)
        {
            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
            setResult(res);
            return;
        }
    }

    GVN::Value * ONEValue = getGVN().getValue(int64_t(1));
    SymbolicDimension ONE(getGVN(), ONEValue);
    GVN::Value * v;

    if (gvnStart->value == gvnEnd->value)
    {
        Result & res = e.getDecorator().setResult(Result(TIType(getGVN(), TIType::DOUBLE, ONE, ONE)));
        setResult(res);
        return;
    }

    if (step == 1)
    {
        v = getGVN().getValue(OpValue::Kind::MINUS, *gvnEnd, *gvnStart);
    }
    else
    {
        v = getGVN().getValue(OpValue::Kind::MINUS, *gvnStart, *gvnEnd);
    }
    v = getGVN().getValue(OpValue::Kind::PLUS, *v, *ONEValue);

    if (v->poly->constant < 0 && v->poly->isCoeffNegative(false))
    {
        TIType type(getGVN(), TIType::EMPTY);
        e.getDecorator().res = Result(type);
    }
    else
    {
        bool res = getCM().check(ConstraintManager::POSITIVE, v);
        if (res)
        {
            TIType type(getGVN(), TIType::DOUBLE, ONE, SymbolicDimension(getGVN(), v));
            e.getDecorator().setResult(type);
        }
        else
        {
            Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), Rstart.getType().type, false), -1));
            setResult(res);
            return;
        }
    }

    setResult(e.getDecorator().res);
}
void AnalysisVisitor::visitInVarDecCtxt(ast::ListExp & e)
{
    e.getStart().accept(*this);
    Result & Rstart = e.getStart().getDecorator().getResult();
    e.getEnd().accept(*this);
    Result & Rend = e.getEnd().getDecorator().getResult();
    e.getStep().accept(*this);
    Result & Rstep = e.getStep().getDecorator().getResult();

    double start = 1;
    double step = 1;
    double end = 1;
    if ((Rstart.getConstant().getDblValue(start) || Rstep.getConstant().getDblValue(step)
            || Rend.getConstant().getDblValue(end)) &&
            (step == 0 || tools::isNaN(step) || !tools::isFinite(step)
             || tools::isNaN(start) || !tools::isFinite(start)
             ||  tools::isNaN(end) || !tools::isFinite(end)))
    {
        // We have an invalid list
        e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::EMPTY), -1));
        return;
    }

    ast::VarDec & vd = *static_cast<ast::VarDec *>(e.getParent());
    const symbol::Symbol & sym = vd.getSymbol();
    GVN::Value * startRange = nullptr;
    GVN::Value * endRange = nullptr;
    Result & res = e.getDecorator().setResult(Result(TIType(dm.getGVN(), TIType::DOUBLE), -1));

    if (Rstart.getConstant().getGVNValue(getGVN(), startRange) && Rend.getConstant().getGVNValue(getGVN(), endRange))
    {
        // Start & End are GVN values
        res.setRange(SymbolicRange(getGVN(), startRange, endRange));
    }
    else
    {
        SymbolicRange & rangeStart = Rstart.getRange();
        if (rangeStart.isValid())
        {
            // Start is an iterator: for i=1:N, for j=i:N, ... in the second for "i" in "i:n" is an iterator
            if (endRange || Rend.getConstant().getGVNValue(getGVN(), endRange))
            {
                // Start is an iterator and End is GVN value
                res.setRange(SymbolicRange(getGVN(), rangeStart.getStart(), endRange));
            }
            else
            {
                SymbolicRange & rangeEnd = Rend.getRange();
                if (rangeEnd.isValid())
                {
                    // Start & End are iterators
                    res.setRange(SymbolicRange(getGVN(), rangeStart.getStart(), rangeEnd.getEnd()));
                }
            }
        }
        else if (startRange || Rstart.getConstant().getGVNValue(getGVN(), startRange))
        {
            // Start is a GVN value
            SymbolicRange & rangeEnd = Rend.getRange();
            if (rangeEnd.isValid())
            {
                // Start is a GVN value and End is an iterator
                res.setRange(SymbolicRange(getGVN(), startRange, rangeEnd.getEnd()));
            }
        }
    }

    setResult(res);
}