Unchecked arrays now have their own type (#9267)

This commit is contained in:
LemonBoy
2018-10-10 21:03:18 +02:00
committed by Andreas Rumpf
parent 0803b532f4
commit 0ead36dae6
15 changed files with 72 additions and 21 deletions

View File

@@ -363,7 +363,9 @@ type
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64,
tyOptAsRef, tySink, tyLent,
tyVarargs,
tyUnused,
tyUncheckedArray
# An array with boundaries [0,+∞]
tyProxy # used as errornous type (for idetools)
tyBuiltInTypeClass
@@ -657,7 +659,7 @@ type
mNHint, mNWarning, mNError,
mInstantiationInfo, mGetTypeInfo,
mNimvm, mIntDefine, mStrDefine, mRunnableExamples,
mException, mBuiltinType, mSymOwner
mException, mBuiltinType, mSymOwner, mUncheckedArray
# things that we can evaluate safely at compile time, even if not asked for it:
const

View File

@@ -856,6 +856,15 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
else:
genRecordField(p, e.sons[0], d)
proc genUncheckedArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
var a, b: TLoc
initLocExpr(p, x, a)
initLocExpr(p, y, b)
var ty = skipTypes(a.t, abstractVarRange + abstractPtrs + tyUserTypeClasses)
d.inheritLocation(a)
putIntoDest(p, d, n, ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)),
a.storage)
proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
var a, b: TLoc
initLocExpr(p, x, a)
@@ -949,6 +958,7 @@ proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) =
var ty = skipTypes(n.sons[0].typ, abstractVarRange + tyUserTypeClasses)
if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange)
case ty.kind
of tyUncheckedArray: genUncheckedArrayElem(p, n, n.sons[0], n.sons[1], d)
of tyArray: genArrayElem(p, n, n.sons[0], n.sons[1], d)
of tyOpenArray, tyVarargs: genOpenArrayElem(p, n, n.sons[0], n.sons[1], d)
of tySequence, tyString: genSeqElem(p, n, n.sons[0], n.sons[1], d)

View File

@@ -139,7 +139,7 @@ proc mapType(conf: ConfigRef; typ: PType): TCTypeKind =
of tyBool: result = ctBool
of tyChar: result = ctChar
of tySet: result = mapSetType(conf, typ)
of tyOpenArray, tyArray, tyVarargs: result = ctArray
of tyOpenArray, tyArray, tyVarargs, tyUncheckedArray: result = ctArray
of tyObject, tyTuple: result = ctStruct
of tyUserTypeClasses:
doAssert typ.isResolvedUserTypeClass
@@ -161,7 +161,7 @@ proc mapType(conf: ConfigRef; typ: PType): TCTypeKind =
of tyPtr, tyVar, tyLent, tyRef, tyOptAsRef:
var base = skipTypes(typ.lastSon, typedescInst)
case base.kind
of tyOpenArray, tyArray, tyVarargs: result = ctPtrToArray
of tyOpenArray, tyArray, tyVarargs, tyUncheckedArray: result = ctPtrToArray
of tySet:
if mapSetType(conf, base) == ctArray: result = ctPtrToArray
else: result = ctPtr
@@ -747,6 +747,12 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
else:
result = rope("TGenericSeq")
add(result, seqStar(m))
of tyUncheckedArray:
result = getTypeName(m, origTyp, sig)
m.typeCache[sig] = result
if not isImportedType(t):
let foo = getTypeDescAux(m, t.sons[0], check)
addf(m.s[cfsTypes], "typedef $1 $2[1];$n", [foo, result])
of tyArray:
var n: BiggestInt = lengthOrd(m.config, t)
if n <= 0: n = 1 # make an array of at least one element
@@ -1218,7 +1224,7 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope =
if m.config.selectedGC >= gcMarkAndSweep:
let markerProc = genTraverseProc(m, origType, sig)
addf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [result, markerProc])
of tyPtr, tyRange: genTypeInfoAux(m, t, t, result, info)
of tyPtr, tyRange, tyUncheckedArray: genTypeInfoAux(m, t, t, result, info)
of tyArray: genArrayInfo(m, t, result, info)
of tySet: genSetInfo(m, t, result, info)
of tyEnum: genEnumInfo(m, t, result, info)

View File

@@ -82,6 +82,7 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimNoNilSeqs")
defineSymbol("nimNoNilSeqs2")
defineSymbol("nimHasUserErrors")
defineSymbol("nimUncheckedArrayTyp")
defineSymbol("nimHasNilSeqs")
for f in low(Feature)..high(Feature):

View File

@@ -179,7 +179,7 @@ proc mapType(typ: PType): TJSTypeKind =
of tyFloat..tyFloat128: result = etyFloat
of tySet: result = etyObject # map a set to a table
of tyString, tySequence, tyOpt: result = etySeq
of tyObject, tyArray, tyTuple, tyOpenArray, tyVarargs:
of tyObject, tyArray, tyTuple, tyOpenArray, tyVarargs, tyUncheckedArray:
result = etyObject
of tyNil: result = etyNull
of tyGenericParam, tyGenericBody, tyGenericInvocation,
@@ -195,7 +195,7 @@ proc mapType(typ: PType): TJSTypeKind =
else: result = etyNone
of tyProc: result = etyProc
of tyCString: result = etyString
of tyUnused, tyOptAsRef: doAssert(false, "mapType")
of tyOptAsRef: doAssert(false, "mapType")
proc mapType(p: PProc; typ: PType): TJSTypeKind =
result = mapType(typ)

View File

@@ -197,7 +197,7 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case t.kind
of tyNone, tyEmpty, tyVoid: discard
of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString,
tyPtr, tyRef, tyOpt:
tyPtr, tyRef, tyOpt, tyUncheckedArray:
defaultOp(c, t, body, x, y)
of tyArray:
if {tfHasAsgn, tfUncheckedArray} * t.flags == {tfHasAsgn}:
@@ -260,7 +260,7 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of tyOrdinal, tyRange, tyInferred,
tyGenericInst, tyStatic, tyVar, tyLent, tyAlias, tySink:
liftBodyAux(c, lastSon(t), body, x, y)
of tyUnused, tyOptAsRef: internalError(c.c.config, "liftBodyAux")
of tyOptAsRef: internalError(c.c.config, "liftBodyAux")
proc newProcType(info: TLineInfo; owner: PSym): PType =
result = newType(tyProc, owner)

View File

@@ -1365,7 +1365,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
case arr.kind
of tyArray, tyOpenArray, tyVarargs, tySequence, tyString,
tyCString:
tyCString, tyUncheckedArray:
if n.len != 2: return nil
n.sons[0] = makeDeref(n.sons[0])
for i in countup(1, sonsLen(n) - 1):

View File

@@ -1511,6 +1511,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
case s.magic
of mArray: result = semArray(c, n, prev)
of mOpenArray: result = semContainer(c, n, tyOpenArray, "openarray", prev)
of mUncheckedArray: result = semContainer(c, n, tyUncheckedArray, "uncheckedarray", prev)
of mRange: result = semRange(c, n, prev)
of mSet: result = semSet(c, n, prev)
of mOrdinal: result = semOrdinal(c, n, prev)
@@ -1751,6 +1752,8 @@ proc processMagicType(c: PContext, m: PSym) =
rawAddSon(m.typ, newTypeS(tyNone, c))
of mSet:
setMagicType(c.config, m, tySet, 0)
of mUncheckedArray:
setMagicType(c.config, m, tyUncheckedArray, 0)
of mSeq:
setMagicType(c.config, m, tySequence, 0)
if c.config.selectedGc == gcDestructors:

View File

@@ -186,7 +186,7 @@ proc sumGeneric(t: PType): int =
var isvar = 1
while true:
case t.kind
of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct,
of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct, tyUncheckedArray,
tyOpenArray, tyVarargs, tySet, tyRange, tySequence, tyGenericBody,
tyLent:
t = t.lastSon
@@ -1199,6 +1199,11 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
if lengthOrd(c.c.config, fRange) != lengthOrd(c.c.config, aRange):
result = isNone
else: discard
of tyUncheckedArray:
if a.kind == tyUncheckedArray:
result = typeRel(c, base(f), base(a))
if result < isGeneric: result = isNone
else: discard
of tyOpenArray, tyVarargs:
# varargs[expr] is special too but handled earlier. So we only need to
# handle varargs[stmt] which is the same as varargs[typed]:
@@ -1362,6 +1367,8 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
if a.len == 1:
let pointsTo = a.sons[0].skipTypes(abstractInst)
if pointsTo.kind == tyChar: result = isConvertible
elif pointsTo.kind == tyUncheckedArray and pointsTo.sons[0].kind == tyChar:
result = isConvertible
elif pointsTo.kind == tyArray and firstOrd(nil, pointsTo.sons[0]) == 0 and
skipTypes(pointsTo.sons[0], {tyRange}).kind in {tyInt..tyInt64} and
pointsTo.sons[1].kind == tyChar:

View File

@@ -396,7 +396,7 @@ const
"float", "float32", "float64", "float128",
"uint", "uint8", "uint16", "uint32", "uint64",
"opt", "sink",
"lent", "varargs[$1]", "unused", "Error Type",
"lent", "varargs[$1]", "UncheckedArray[$1]", "Error Type",
"BuiltInTypeClass", "UserTypeClass",
"UserTypeClassInst", "CompositeTypeClass", "inferred",
"and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor",
@@ -526,6 +526,8 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
else:
result = "array[" & typeToString(t.sons[0]) & ", " &
typeToString(t.sons[1]) & ']'
of tyUncheckedArray:
result = "uncheckedArray[" & typeToString(t.sons[0]) & ']'
of tySequence:
result = "seq[" & typeToString(t.sons[0]) & ']'
of tyOpt:
@@ -638,6 +640,8 @@ proc firstOrd*(conf: ConfigRef; t: PType): BiggestInt =
of tyOrdinal:
if t.len > 0: result = firstOrd(conf, lastSon(t))
else: internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')')
of tyUncheckedArray:
result = 0
else:
internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')')
result = 0
@@ -695,6 +699,8 @@ proc lastOrd*(conf: ConfigRef; t: PType; fixedUnsigned = false): BiggestInt =
of tyOrdinal:
if t.len > 0: result = lastOrd(conf, lastSon(t))
else: internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')')
of tyUncheckedArray:
result = high(BiggestInt)
else:
internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')')
result = 0
@@ -1030,7 +1036,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
if result and {ExactGenericParams, ExactTypeDescValues} * c.flags != {}:
result = a.sym.position == b.sym.position
of tyGenericInvocation, tyGenericBody, tySequence,
tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyLent, tySink,
tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyLent, tySink, tyUncheckedArray,
tyArray, tyProc, tyVarargs, tyOrdinal, tyTypeClasses, tyOpt:
cycleCheck()
if a.kind == tyUserTypeClass and a.n != nil: return a.n == b.n
@@ -1054,7 +1060,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
cycleCheck()
result = sameTypeAux(a.lastSon, b.lastSon, c)
of tyNone: result = false
of tyUnused, tyOptAsRef: result = false
of tyOptAsRef: result = false
proc sameBackendType*(x, y: PType): bool =
var c = initSameTypeClosure()
@@ -1210,7 +1216,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
result = nil
of tyOrdinal:
if kind != skParam: result = t
of tyGenericInst, tyDistinct, tyAlias, tyInferred:
of tyGenericInst, tyDistinct, tyAlias, tyInferred, tyUncheckedArray:
result = typeAllowedAux(marker, lastSon(t), kind, flags)
of tyRange:
if skipTypes(t.sons[0], abstractInst-{tyTypeDesc}).kind notin
@@ -1252,7 +1258,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
# for now same as error node; we say it's a valid type as it should
# prevent cascading errors:
result = nil
of tyUnused, tyOptAsRef: result = t
of tyOptAsRef: result = t
proc typeAllowed*(t: PType, kind: TSymKind; flags: TTypeAllowedFlags = {}): PType =
# returns 'nil' on success and otherwise the part of the type that is
@@ -1430,6 +1436,8 @@ proc computeSizeAux(conf: ConfigRef; typ: PType, a: var BiggestInt): BiggestInt
of tyStatic:
result = if typ.n != nil: computeSizeAux(conf, typ.lastSon, a)
else: szUnknownSize
of tyUncheckedArray:
result = 0
else:
#internalError("computeSizeAux()")
result = szUnknownSize

View File

@@ -98,6 +98,10 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
of tyStmt: result = atomicType("stmt", mStmt)
of tyVoid: result = atomicType("void", mVoid)
of tyEmpty: result = atomicType("empty", mNone)
of tyUncheckedArray:
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
result.add atomicType("uncheckedArray", mUncheckedArray)
result.add mapTypeToAst(t.sons[0], info)
of tyArray:
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t)
result.add atomicType("array", mArray)
@@ -289,7 +293,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
result.add atomicType("static", mNone)
if t.n != nil:
result.add t.n.copyTree
of tyUnused, tyOptAsRef: assert(false, "mapTypeToAstX")
of tyOptAsRef: assert(false, "mapTypeToAstX")
proc opMapTypeToAst*(cache: IdentCache; t: PType; info: TLineInfo): PNode =
result = mapTypeToAstX(cache, t, info, false, true)

View File

@@ -84,7 +84,7 @@ type
wStdIn, wStdOut, wStdErr,
wInOut, wByCopy, wByRef, wOneWay,
wBitsize,
wBitsize
TSpecialWords* = set[TSpecialWord]
@@ -173,7 +173,7 @@ const
"stdin", "stdout", "stderr",
"inout", "bycopy", "byref", "oneway",
"bitsize",
"bitsize"
]
proc findStr*(a: openArray[string], s: string): int =

View File

@@ -98,7 +98,7 @@ type
ntyUInt, ntyUInt8, ntyUInt16, ntyUInt32, ntyUInt64,
ntyUnused0, ntyUnused1, ntyUnused2,
ntyVarargs,
ntyUnused,
ntyUncheckedArray,
ntyError,
ntyBuiltinTypeClass, ntyUserTypeClass, ntyUserTypeClassInst,
ntyCompositeTypeClass, ntyInferred, ntyAnd, ntyOr, ntyNot,

View File

@@ -253,7 +253,13 @@ type
seq*{.magic: "Seq".}[T] ## Generic type to construct sequences.
set*{.magic: "Set".}[T] ## Generic type to construct bit sets.
UncheckedArray* {.unchecked.}[T] = array[0, T]
when defined(nimUncheckedArrayTyp):
type
UncheckedArray*{.magic: "UncheckedArray".}[T]
## Array with no bounds checking
else:
type
UncheckedArray*{.unchecked.}[T] = array[0,T]
## Array with no bounds checking
when defined(nimHasOpt):

View File

@@ -2,6 +2,7 @@ discard """
nimout: '''proc (x: int): string => typeDesc[proc[string, int]]
proc (x: int): void => typeDesc[proc[void, int]]
proc (x: int) => typeDesc[proc[void, int]]'''
x => uncheckedArray[int]
"""
#2211
@@ -15,3 +16,6 @@ macro showType(t:typed): untyped =
showType(proc(x:int): string)
showType(proc(x:int): void)
showType(proc(x:int))
var x: UncheckedArray[int]
showType(x)