///|
/// Why a module is not well formed.
///
/// One arm per class in the reference's `reasons.py`, carrying the same
/// fields, and `message` reproduces the Python f-strings character for
/// character: these are the `.error.expected` files of the conformance suite's
/// static buckets, so the wording is fixed by the oracle and not by taste.
pub(all) enum Reason {
DuplicateFieldName(name~ : String, cls~ : String)
UnknownBaseClass(base~ : String)
InheritedFieldClash(field~ : String, base~ : String)
DuplicateClassName(name~ : String, in_module~ : String)
UnassignedVariable(name~ : String)
CapturedReassignment(name~ : String)
SelfCaptureAssignment(name~ : String)
CapturedGeneratorVariable(name~ : String)
UnreachableStatement
ConstructorArityMismatch(cls~ : String, expected~ : Int, got~ : Int)
UnknownConstructorKeyword(cls~ : String, expected_fields~ : Array[String])
PatternArityMismatch(cls~ : String, expected~ : Int, got~ : Int)
UnknownClassInPattern(cls~ : String)
UnknownFieldInPattern(cls~ : String, expected_fields~ : Array[String])
DuplicatePatternKeyword(cls~ : String)
DuplicateDictKey(key~ : String)
NonlinearPattern(index~ : Int)
UnreachableCase(index~ : Int, subsumed_by~ : Int)
DuplicateMutualName(name~ : String)
NonTopLevelImport
ImportAfterStatement
SubmoduleNameClash(name~ : String, submodule~ : String)
SubmoduleNotImported(q~ : String)
UnassignedMember(x~ : String, q~ : String)
TopLevelReturn
EmptyFromImport
UnknownModule(q~ : String)
UnknownMember(x~ : String, q~ : String)
ModuleAsValue(name~ : String)
OwnDescendantImport(q~ : String, q0~ : String)
ClassAsValue(name~ : String)
} derive(Eq, Debug)
///|
/// The message, exactly as `reasons.py` writes it.
pub fn Reason::message(self : Reason) -> String {
match self {
DuplicateFieldName(name~, cls~) =>
"duplicate field name '\{name}' in class '\{cls}'"
UnknownBaseClass(base~) =>
"base class '\{base}' is not declared in this module"
InheritedFieldClash(field~, base~) =>
"field '\{field}' clashes with inherited field from '\{base}'"
DuplicateClassName(name~, in_module~) =>
"duplicate class name '\{name}' in module '\{in_module}'"
UnassignedVariable(name~) => "'\{name}' is not definitely assigned"
CapturedReassignment(name~) =>
"'\{name}' captured by previous statement, reassigned here"
SelfCaptureAssignment(name~) => "'\{name}' captured by right-hand side"
CapturedGeneratorVariable(name~) =>
"'\{name}' bound by a generator, captured by a lambda"
UnreachableStatement => "unreachable statement"
ConstructorArityMismatch(cls~, expected~, got~) =>
"constructor for '\{cls}' expects \{expected} arguments, got \{got}"
UnknownConstructorKeyword(cls~, expected_fields~) =>
"constructor keywords for '\{cls}' must be " + expected_fields.join(", ")
PatternArityMismatch(cls~, expected~, got~) =>
"pattern for '\{cls}' expects \{expected} sub-patterns, got \{got}"
UnknownClassInPattern(cls~) => "'\{cls}' is not a declared class"
UnknownFieldInPattern(cls~, expected_fields~) =>
"pattern keywords for '\{cls}' must be " + expected_fields.join(", ")
DuplicatePatternKeyword(cls~) => "duplicate keyword in pattern for '\{cls}'"
DuplicateDictKey(key~) => "duplicate key '\{key}' in dict pattern"
NonlinearPattern(index~) => "repeated variable in pattern \{index}"
UnreachableCase(index~, subsumed_by~) =>
"case \{index} unreachable: subsumed by case \{subsumed_by}"
DuplicateMutualName(name~) => "duplicate name '\{name}' in mutual region"
NonTopLevelImport => "import only allowed at module top level"
ImportAfterStatement => "imports must precede all other statements"
SubmoduleNameClash(name~, submodule~) =>
"binding '\{name}' clashes with submodule '\{submodule}'"
SubmoduleNotImported(q~) => "submodule '\{q}' is not imported"
UnassignedMember(x~, q~) =>
"member '\{x}' of module '\{q}' is not definitely assigned"
TopLevelReturn =>
"top-level return not allowed (module body must not return)"
EmptyFromImport => "empty name list"
// Python's `repr` of the name, which is what `{q!r}` writes.
UnknownModule(q~) => "unknown module " + @basic.py_repr(q)
UnknownMember(x~, q~) =>
"module " + @basic.py_repr(q) + " has no member " + @basic.py_repr(x)
ModuleAsValue(name~) =>
"'\{name}' refers to a module; modules are not first-class values"
OwnDescendantImport(q~, q0~) =>
"'\{q}' is a descendant of the importing module '\{q0}'; import it with a from-import"
ClassAsValue(name~) =>
"'\{name}' refers to a class; classes are not first-class values"
}
}
///|
/// A short, stable code for a reason, for `--error-format json` and for a
/// person searching: `purepy::unassigned-variable`.
pub fn Reason::code(self : Reason) -> String {
let name = match self {
DuplicateFieldName(..) => "duplicate-field-name"
UnknownBaseClass(..) => "unknown-base-class"
InheritedFieldClash(..) => "inherited-field-clash"
DuplicateClassName(..) => "duplicate-class-name"
UnassignedVariable(..) => "unassigned-variable"
CapturedReassignment(..) => "captured-reassignment"
SelfCaptureAssignment(..) => "self-capture-assignment"
CapturedGeneratorVariable(..) => "captured-generator-variable"
UnreachableStatement => "unreachable-statement"
ConstructorArityMismatch(..) => "constructor-arity-mismatch"
UnknownConstructorKeyword(..) => "unknown-constructor-keyword"
PatternArityMismatch(..) => "pattern-arity-mismatch"
UnknownClassInPattern(..) => "unknown-class-in-pattern"
UnknownFieldInPattern(..) => "unknown-field-in-pattern"
DuplicatePatternKeyword(..) => "duplicate-pattern-keyword"
DuplicateDictKey(..) => "duplicate-dict-key"
NonlinearPattern(..) => "nonlinear-pattern"
UnreachableCase(..) => "unreachable-case"
DuplicateMutualName(..) => "duplicate-mutual-name"
NonTopLevelImport => "non-top-level-import"
ImportAfterStatement => "import-after-statement"
SubmoduleNameClash(..) => "submodule-name-clash"
SubmoduleNotImported(..) => "submodule-not-imported"
UnassignedMember(..) => "unassigned-member"
TopLevelReturn => "top-level-return"
EmptyFromImport => "empty-from-import"
UnknownModule(..) => "unknown-module"
UnknownMember(..) => "unknown-member"
ModuleAsValue(..) => "module-as-value"
OwnDescendantImport(..) => "own-descendant-import"
ClassAsValue(..) => "class-as-value"
}
"purepy::" + name
}