// 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);
}
// 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 (!(normalizeNFC(keys[kk]) == normalizeNFC(keys1[kk]))) {
allEqual = false; break;
}
} if (allEqual) {
duplicatesExist = true;
}
}
}
}
if (duplicatesExist) {
errors.addError(StaticErrorType::DuplicateVariant, status);
} if (!defaultExists) {
errors.addError(StaticErrorType::NonexhaustivePattern, status);
}
}
if (t.get(selectorVar) == 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 VariableName* 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.