bool ExprFuncNode::checkArg(int arg, ExprType type, ExprVarEnvBuilder& envBuilder) { ExprType childType = child(arg)->prep(type.isFP(1), envBuilder); _promote[arg] = 0; if (ExprType::valuesCompatible(type, childType) && type.isLifeCompatible(childType)) { if (type.isFP() && type.dim() > childType.dim()) { _promote[arg] = type.dim(); } return true; } child(arg)->addError("Expected " + type.toString() + " for argument, got " + childType.toString()); return false; }
ExprType ExprFuncStandard::prep(ExprFuncNode* node, bool scalarWanted, ExprVarEnvBuilder& envBuilder) const { if (_funcType < VEC) { // scalar argumented functions returning scalars // use promote protocol... bool error = false; int nonOneDim = 1; // defaults to 1, if another is seen record! bool multiInvoke = !scalarWanted; ExprType retType; for (int c = 0; c < node->numChildren(); c++) { ExprType childType = node->child(c)->prep(scalarWanted, envBuilder); int childDim = childType.dim(); node->child(c)->checkIsFP(childType, error); retType.setLifetime(childType); if (childDim != 1) { if (nonOneDim != 1 && childDim != nonOneDim) multiInvoke = false; nonOneDim = childDim; } } if (error) return retType.Error(); else if (multiInvoke && nonOneDim != 1) return retType.FP(nonOneDim); return retType.FP(1); } else { // vector argumented functions bool error = false; ExprType retType; for (int c = 0; c < node->numChildren(); c++) { ExprType childType = node->child(c)->prep(scalarWanted, envBuilder); int childDim = childType.dim(); node->child(c)->checkIsFP(childType, error); node->child(c)->checkCondition(childDim == 1 || childDim == 3, "Expected float or FP[3]", error); retType.setLifetime(childType); } if (error) return retType.Error(); else if (scalarWanted || _funcType < VECVEC) return retType.FP(1); else return retType.FP(3); } }
ExprType ExprVecNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) { bool error = false; int max_child_d = 0; for (int c = 0; c < numChildren(); c++) { ExprType childType = child(c)->prep(true, envBuilder); // TODO: add way to tell what element of vector has the type mismatch checkIsFP(childType, error); max_child_d = std::max(max_child_d, childType.dim()); } if (error) setType(ExprType().Error()); else setTypeWithChildLife(ExprType().FP(numChildren())); return _type; }