Info & Block::addMacroDef(ast::FunctionDec * dec) { TIType ty(getGVN(), TIType::MACRO); Info & i = addDefine(dec->getSymbol(), ty, false, dec); i.exp = dec; return i; }
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; }
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, ¯odef, 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); }