minor improvements to follow up recent PRs (#20342)
put mOpenArrayToSeq in compile-time evaluation whitelist (it was mNone before which was whitelisted), homogenize "ordinal type expected" errors, put overloadable enums in non-experimental manual
This commit is contained in:
parent
2140d05f34
commit
a73ae3e066
8 changed files with 45 additions and 51 deletions
|
|
@ -738,7 +738,7 @@ const
|
||||||
mEqStr, mLeStr, mLtStr,
|
mEqStr, mLeStr, mLtStr,
|
||||||
mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet,
|
mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet,
|
||||||
mConStrStr, mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
mConStrStr, mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
||||||
mInSet, mRepr}
|
mInSet, mRepr, mOpenArrayToSeq}
|
||||||
|
|
||||||
generatedMagics* = {mNone, mIsolate, mFinished, mOpenArrayToSeq}
|
generatedMagics* = {mNone, mIsolate, mFinished, mOpenArrayToSeq}
|
||||||
## magics that are generated as normal procs in the backend
|
## magics that are generated as normal procs in the backend
|
||||||
|
|
|
||||||
|
|
@ -2504,7 +2504,7 @@ proc semSetConstr(c: PContext, n: PNode, expectedType: PType = nil): PNode =
|
||||||
if expectedElementType == nil:
|
if expectedElementType == nil:
|
||||||
expectedElementType = typ
|
expectedElementType = typ
|
||||||
if not isOrdinalType(typ, allowEnumWithHoles=true):
|
if not isOrdinalType(typ, allowEnumWithHoles=true):
|
||||||
localError(c.config, n.info, errOrdinalTypeExpected)
|
localError(c.config, n.info, errOrdinalTypeExpected % typeToString(typ, preferDesc))
|
||||||
typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
|
typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
|
||||||
elif lengthOrd(c.config, typ) > MaxSetElements:
|
elif lengthOrd(c.config, typ) > MaxSetElements:
|
||||||
typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
|
typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,7 @@ proc semOrd(c: PContext, n: PNode): PNode =
|
||||||
if isOrdinalType(parType, allowEnumWithHoles=true):
|
if isOrdinalType(parType, allowEnumWithHoles=true):
|
||||||
discard
|
discard
|
||||||
else:
|
else:
|
||||||
localError(c.config, n.info, errOrdinalTypeExpected)
|
localError(c.config, n.info, errOrdinalTypeExpected % typeToString(parType, preferDesc))
|
||||||
result.typ = errorType(c)
|
result.typ = errorType(c)
|
||||||
|
|
||||||
proc semBindSym(c: PContext, n: PNode): PNode =
|
proc semBindSym(c: PContext, n: PNode): PNode =
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ const
|
||||||
errIntLiteralExpected = "integer literal expected"
|
errIntLiteralExpected = "integer literal expected"
|
||||||
errWrongNumberOfVariables = "wrong number of variables"
|
errWrongNumberOfVariables = "wrong number of variables"
|
||||||
errInvalidOrderInEnumX = "invalid order in enum '$1'"
|
errInvalidOrderInEnumX = "invalid order in enum '$1'"
|
||||||
errOrdinalTypeExpected = "ordinal type expected"
|
errOrdinalTypeExpected = "ordinal type expected; given: $1"
|
||||||
errSetTooBig = "set is too large; use `std/sets` for ordinal types with more than 2^16 elements"
|
errSetTooBig = "set is too large; use `std/sets` for ordinal types with more than 2^16 elements"
|
||||||
errBaseTypeMustBeOrdinal = "base type of a set must be an ordinal"
|
errBaseTypeMustBeOrdinal = "base type of a set must be an ordinal"
|
||||||
errInheritanceOnlyWithNonFinalObjects = "inheritance only works with non-final objects"
|
errInheritanceOnlyWithNonFinalObjects = "inheritance only works with non-final objects"
|
||||||
|
|
@ -95,7 +95,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||||
strVal = v[1] # second tuple part is the string value
|
strVal = v[1] # second tuple part is the string value
|
||||||
if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCstring}:
|
if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCstring}:
|
||||||
if not isOrdinalType(v[0].typ, allowEnumWithHoles=true):
|
if not isOrdinalType(v[0].typ, allowEnumWithHoles=true):
|
||||||
localError(c.config, v[0].info, errOrdinalTypeExpected & "; given: " & typeToString(v[0].typ, preferDesc))
|
localError(c.config, v[0].info, errOrdinalTypeExpected % typeToString(v[0].typ, preferDesc))
|
||||||
x = toInt64(getOrdValue(v[0])) # first tuple part is the ordinal
|
x = toInt64(getOrdValue(v[0])) # first tuple part is the ordinal
|
||||||
n[i][1][0] = newIntTypeNode(x, getSysType(c.graph, unknownLineInfo, tyInt))
|
n[i][1][0] = newIntTypeNode(x, getSysType(c.graph, unknownLineInfo, tyInt))
|
||||||
else:
|
else:
|
||||||
|
|
@ -107,7 +107,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||||
x = counter
|
x = counter
|
||||||
else:
|
else:
|
||||||
if not isOrdinalType(v.typ, allowEnumWithHoles=true):
|
if not isOrdinalType(v.typ, allowEnumWithHoles=true):
|
||||||
localError(c.config, v.info, errOrdinalTypeExpected & "; given: " & typeToString(v.typ, preferDesc))
|
localError(c.config, v.info, errOrdinalTypeExpected % typeToString(v.typ, preferDesc))
|
||||||
x = toInt64(getOrdValue(v))
|
x = toInt64(getOrdValue(v))
|
||||||
n[i][1] = newIntTypeNode(x, getSysType(c.graph, unknownLineInfo, tyInt))
|
n[i][1] = newIntTypeNode(x, getSysType(c.graph, unknownLineInfo, tyInt))
|
||||||
if i != 1:
|
if i != 1:
|
||||||
|
|
@ -163,7 +163,7 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
|
||||||
if base.kind in {tyGenericInst, tyAlias, tySink}: base = lastSon(base)
|
if base.kind in {tyGenericInst, tyAlias, tySink}: base = lastSon(base)
|
||||||
if base.kind notin {tyGenericParam, tyGenericInvocation}:
|
if base.kind notin {tyGenericParam, tyGenericInvocation}:
|
||||||
if not isOrdinalType(base, allowEnumWithHoles = true):
|
if not isOrdinalType(base, allowEnumWithHoles = true):
|
||||||
localError(c.config, n.info, errOrdinalTypeExpected)
|
localError(c.config, n.info, errOrdinalTypeExpected % typeToString(base, preferDesc))
|
||||||
elif lengthOrd(c.config, base) > MaxSetElements:
|
elif lengthOrd(c.config, base) > MaxSetElements:
|
||||||
localError(c.config, n.info, errSetTooBig)
|
localError(c.config, n.info, errSetTooBig)
|
||||||
else:
|
else:
|
||||||
|
|
@ -331,12 +331,12 @@ proc semArrayIndex(c: PContext, n: PNode): PType =
|
||||||
return semArrayIndex(c, e.sym.ast)
|
return semArrayIndex(c, e.sym.ast)
|
||||||
if not isOrdinalType(e.typ.lastSon):
|
if not isOrdinalType(e.typ.lastSon):
|
||||||
let info = if n.safeLen > 1: n[1].info else: n.info
|
let info = if n.safeLen > 1: n[1].info else: n.info
|
||||||
localError(c.config, info, errOrdinalTypeExpected)
|
localError(c.config, info, errOrdinalTypeExpected % typeToString(e.typ, preferDesc))
|
||||||
result = makeRangeWithStaticExpr(c, e)
|
result = makeRangeWithStaticExpr(c, e)
|
||||||
if c.inGenericContext > 0: result.flags.incl tfUnresolved
|
if c.inGenericContext > 0: result.flags.incl tfUnresolved
|
||||||
elif e.kind in (nkCallKinds + {nkBracketExpr}) and hasUnresolvedArgs(c, e):
|
elif e.kind in (nkCallKinds + {nkBracketExpr}) and hasUnresolvedArgs(c, e):
|
||||||
if not isOrdinalType(e.typ.skipTypes({tyStatic, tyAlias, tyGenericInst, tySink})):
|
if not isOrdinalType(e.typ.skipTypes({tyStatic, tyAlias, tyGenericInst, tySink})):
|
||||||
localError(c.config, n[1].info, errOrdinalTypeExpected)
|
localError(c.config, n[1].info, errOrdinalTypeExpected % typeToString(e.typ, preferDesc))
|
||||||
# This is an int returning call, depending on an
|
# This is an int returning call, depending on an
|
||||||
# yet unknown generic param (see tgenericshardcases).
|
# yet unknown generic param (see tgenericshardcases).
|
||||||
# We are going to construct a range type that will be
|
# We are going to construct a range type that will be
|
||||||
|
|
@ -365,7 +365,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||||
if indxB.skipTypes({tyRange}).kind in {tyUInt, tyUInt64}:
|
if indxB.skipTypes({tyRange}).kind in {tyUInt, tyUInt64}:
|
||||||
discard
|
discard
|
||||||
elif not isOrdinalType(indxB):
|
elif not isOrdinalType(indxB):
|
||||||
localError(c.config, n[1].info, errOrdinalTypeExpected)
|
localError(c.config, n[1].info, errOrdinalTypeExpected % typeToString(indxB, preferDesc))
|
||||||
elif enumHasHoles(indxB):
|
elif enumHasHoles(indxB):
|
||||||
localError(c.config, n[1].info, "enum '$1' has holes" %
|
localError(c.config, n[1].info, "enum '$1' has holes" %
|
||||||
typeToString(indxB.skipTypes({tyRange})))
|
typeToString(indxB.skipTypes({tyRange})))
|
||||||
|
|
@ -395,7 +395,7 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
|
||||||
var base = semTypeNode(c, n[1], nil)
|
var base = semTypeNode(c, n[1], nil)
|
||||||
if base.kind != tyGenericParam:
|
if base.kind != tyGenericParam:
|
||||||
if not isOrdinalType(base):
|
if not isOrdinalType(base):
|
||||||
localError(c.config, n[1].info, errOrdinalTypeExpected)
|
localError(c.config, n[1].info, errOrdinalTypeExpected % typeToString(base, preferDesc))
|
||||||
addSonSkipIntLit(result, base, c.idgen)
|
addSonSkipIntLit(result, base, c.idgen)
|
||||||
else:
|
else:
|
||||||
localError(c.config, n.info, errXExpectsOneTypeParam % "ordinal")
|
localError(c.config, n.info, errXExpectsOneTypeParam % "ordinal")
|
||||||
|
|
|
||||||
|
|
@ -1313,6 +1313,38 @@ as `MyEnum.value`:
|
||||||
echo MyEnum.amb # OK.
|
echo MyEnum.amb # OK.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Enum value names are overloadable, much like routines. If both of the enums
|
||||||
|
`T` and `U` have a member named `foo`, then the identifier `foo` corresponds
|
||||||
|
to a choice between `T.foo` and `U.foo`. During overload resolution,
|
||||||
|
the correct type of `foo` is decided from the context. If the type of `foo` is
|
||||||
|
ambiguous, a static error will be produced.
|
||||||
|
|
||||||
|
```nim test = "nim c $1"
|
||||||
|
|
||||||
|
type
|
||||||
|
E1 = enum
|
||||||
|
value1,
|
||||||
|
value2
|
||||||
|
E2 = enum
|
||||||
|
value1,
|
||||||
|
value2 = 4
|
||||||
|
|
||||||
|
const
|
||||||
|
Lookuptable = [
|
||||||
|
E1.value1: "1",
|
||||||
|
# no need to qualify value2, known to be E1.value2
|
||||||
|
value2: "2"
|
||||||
|
]
|
||||||
|
|
||||||
|
proc p(e: E1) =
|
||||||
|
# disambiguation in 'case' statements:
|
||||||
|
case e
|
||||||
|
of value1: echo "A"
|
||||||
|
of value2: echo "B"
|
||||||
|
|
||||||
|
p value2
|
||||||
|
```
|
||||||
|
|
||||||
To implement bit fields with enums see [Bit fields].
|
To implement bit fields with enums see [Bit fields].
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,44 +86,6 @@ No Unicode normalization step is performed.
|
||||||
pragma `{.experimental: "unicodeOperators".}` reliably.
|
pragma `{.experimental: "unicodeOperators".}` reliably.
|
||||||
|
|
||||||
|
|
||||||
Overloadable enum value names
|
|
||||||
=============================
|
|
||||||
|
|
||||||
Enum value names are overloadable, much like routines. If both of the enums
|
|
||||||
`T` and `U` have a member named `foo`, then the identifier `foo` corresponds
|
|
||||||
to a choice between `T.foo` and `U.foo`. During overload resolution,
|
|
||||||
the correct type of `foo` is decided from the context. If the type of `foo` is
|
|
||||||
ambiguous, a static error will be produced.
|
|
||||||
|
|
||||||
```nim test = "nim c $1"
|
|
||||||
|
|
||||||
type
|
|
||||||
E1 = enum
|
|
||||||
value1,
|
|
||||||
value2
|
|
||||||
E2 = enum
|
|
||||||
value1,
|
|
||||||
value2 = 4
|
|
||||||
|
|
||||||
const
|
|
||||||
Lookuptable = [
|
|
||||||
E1.value1: "1",
|
|
||||||
# no need to qualify value2, known to be E1.value2
|
|
||||||
value2: "2"
|
|
||||||
]
|
|
||||||
|
|
||||||
proc p(e: E1) =
|
|
||||||
# disambiguation in 'case' statements:
|
|
||||||
case e
|
|
||||||
of value1: echo "A"
|
|
||||||
of value2: echo "B"
|
|
||||||
|
|
||||||
p value2
|
|
||||||
```
|
|
||||||
|
|
||||||
Previously required `{.experimental: "overloadableEnums".}` to enable,
|
|
||||||
now always enabled.
|
|
||||||
|
|
||||||
Top-down type inference
|
Top-down type inference
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
errormsg: "ordinal type expected"
|
errormsg: "ordinal type expected; given: string"
|
||||||
line: 10
|
line: 10
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
errormsg: "ordinal type expected"
|
errormsg: "ordinal type expected; given: float"
|
||||||
line: 10
|
line: 10
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue