The following are checked here: Variant Key Mismatch Duplicate Variant Missing Fallback Variant (called NonexhaustivePattern here) Missing Selector Annotation Duplicate Declaration - Most duplicate declaration errors are checked by the parser, but the checker checks for declarations of input variables that were previously implicitly declared (Duplicate option names and duplicate declarations are checked by the parser)
*/
// Returns true if `var` was either previously used (implicit declaration), // or is in scope by an explicit declaration bool TypeEnvironment::known(const VariableName& var) const { return has(*annotated, var) || has(*unannotated, var) || has(*freeVars, var);
}
TypeEnvironment::Type TypeEnvironment::get(const VariableName& var) const {
U_ASSERT(annotated.isValid()); if (has(*annotated, var)) { return Annotated;
}
U_ASSERT(unannotated.isValid()); if (has(*unannotated, var)) { return Unannotated;
}
U_ASSERT(freeVars.isValid()); if (has(*freeVars, var)) { return FreeVariable;
} // This case is a "free variable without an implicit declaration", // i.e. one used only in a selector expression and not in a declaration RHS return Unannotated;
}
void TypeEnvironment::extend(const VariableName& var, TypeEnvironment::Type t, UErrorCode& status) { if (t == Unannotated) {
U_ASSERT(unannotated.isValid()); // See comment below
unannotated->addElement(const_cast<void*>(static_cast<constvoid*>(&var)), status); return;
}
if (t == FreeVariable) {
U_ASSERT(freeVars.isValid()); // See comment below
freeVars->addElement(const_cast<void*>(static_cast<constvoid*>(&var)), status); return;
}
U_ASSERT(annotated.isValid()); // This is safe because elements of `annotated` are never written // and the lifetime of `var` is guaranteed to include the lifetime of // `annotated`
annotated->addElement(const_cast<void*>(static_cast<constvoid*>(&var)), status);
}
TypeEnvironment::~TypeEnvironment() {}
// ---------------------
staticbool areDefaultKeys(const Key* keys, int32_t len) {
U_ASSERT(len > 0); for (int32_t i = 0; i < len; i++) { if (!keys[i].isWildcard()) { returnfalse;
}
} returntrue;
}
// Check that each variant has a key list with size // equal to the number of selectors const Variant* variants = dataModel.getVariantsInternal();
// Check that one variant includes only wildcards bool defaultExists = false; bool duplicatesExist = false;
for (int32_t i = 0; i < dataModel.numVariants(); i++) { const SelectorKeys& k = variants[i].getKeys(); const Key* keys = k.getKeysInternal();
int32_t len = k.len; if (len != dataModel.numSelectors()) { // Variant key mismatch
errors.addError(StaticErrorType::VariantKeyMismatchError, status); return;
}
defaultExists |= areDefaultKeys(keys, len);
// Check if this variant's keys are duplicated by any other variant's keys if (!duplicatesExist) { // This check takes quadratic time, but it can be optimized if checking // this property turns out to be a bottleneck. for (int32_t j = 0; j < i; j++) { const SelectorKeys& k1 = variants[j].getKeys(); const Key* keys1 = k1.getKeysInternal(); bool allEqual = true; // This variant was already checked, // so we know keys1.len == len for (int32_t kk = 0; kk < len; kk++) { if (!(keys[kk] == keys1[kk])) {
allEqual = false; break;
}
} if (allEqual) {
duplicatesExist = true;
}
}
}
}
if (duplicatesExist) {
errors.addError(StaticErrorType::DuplicateVariant, status);
} if (!defaultExists) {
errors.addError(StaticErrorType::NonexhaustivePattern, status);
}
}
if (selectorExpr.isFunctionCall()) { return; // No error
} const Operand& rand = selectorExpr.getOperand(); if (rand.isVariable()) { if (t.get(rand.asVariable()) == TypeEnvironment::Type::Annotated) { return; // No error
}
} // If this code is reached, an error was detected
errors.addError(StaticErrorType::MissingSelectorAnnotation, status);
}
// Check each selector; if it's not annotated, emit a // "missing selector annotation" error const Expression* selectors = dataModel.getSelectorsInternal(); for (int32_t i = 0; i < dataModel.numSelectors(); i++) {
requireAnnotated(t, selectors[i], status);
}
}
// For each declaration, extend the type environment with its type // Only a very simple type system is necessary: variables // have the type "annotated", "unannotated", or "free". // For "missing selector annotation" checking, free variables // (message arguments) are treated as unannotated. // Free variables are also used for checking duplicate declarations. const Binding* env = dataModel.getLocalVariablesInternal(); for (int32_t i = 0; i < dataModel.bindingsLen; i++) { const Binding& b = env[i]; const VariableName& lhs = b.getVariable(); const Expression& rhs = b.getValue();
// First, add free variables from the RHS of b // This must be done first so we can catch: // .local $foo = {$foo} // (where the RHS is the first use of $foo) if (b.isLocal()) {
addFreeVars(t, rhs, status);
// Next, check if the LHS equals any free variables // whose implicit declarations are in scope if (t.known(lhs) && t.get(lhs) == TypeEnvironment::Type::FreeVariable) {
errors.addError(StaticErrorType::DuplicateDeclarationError, status);
}
} else { // Input declaration; if b has no annotation, there's nothing to check if (!b.isLocal() && b.hasAnnotation()) { const OptionMap& opts = b.getOptionsInternal(); // For .input declarations, we just need to add any variables // referenced in the options
addFreeVars(t, opts, status);
} // Next, check if the LHS equals any free variables // whose implicit declarations are in scope if (t.known(lhs) && t.get(lhs) == TypeEnvironment::Type::FreeVariable) {
errors.addError(StaticErrorType::DuplicateDeclarationError, status);
}
} // Next, extend the type environment with a binding from lhs to its type
t.extend(lhs, typeOf(t, rhs), status);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.