literal array indices (#11424)

This commit is contained in:
Jasper Jenkins
2019-06-18 05:16:33 -07:00
committed by Andreas Rumpf
parent c99ce5051e
commit 8ee0f14ab6
5 changed files with 44 additions and 4 deletions

View File

@@ -527,16 +527,24 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = newNodeI(nkBracket, n.info)
result.typ = newTypeS(tyArray, c)
rawAddSon(result.typ, nil) # index type
var
firstIndex, lastIndex: BiggestInt = 0
indexType = getSysType(c.graph, n.info, tyInt)
lastValidIndex = lastOrd(c.config, indexType)
if sonsLen(n) == 0:
rawAddSon(result.typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
lastIndex = -1
else:
var x = n.sons[0]
var lastIndex: BiggestInt = 0
var indexType = getSysType(c.graph, n.info, tyInt)
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
var idx = semConstExpr(c, x.sons[0])
lastIndex = getOrdValue(idx)
if not isOrdinalType(idx.typ):
localError(c.config, idx.info, "expected ordinal value for array " &
"index, got '$1'" % renderTree(idx))
firstIndex = getOrdValue(idx)
lastIndex = firstIndex
indexType = idx.typ
lastValidIndex = lastOrd(c.config, indexType)
x = x.sons[1]
let yy = semExprWithType(c, x)
@@ -544,6 +552,12 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
addSon(result, yy)
#var typ = skipTypes(result.sons[0].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal})
for i in 1 ..< sonsLen(n):
if lastIndex == lastValidIndex:
let validIndex = makeRangeType(c, firstIndex, lastValidIndex, n.info,
indexType)
localError(c.config, n.info, "size of array exceeds range of index " &
"type '$1' by $2 elements" % [typeToString(validIndex), $(n.len-i)])
x = n.sons[i]
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
var idx = semConstExpr(c, x.sons[0])
@@ -561,7 +575,8 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
addSonSkipIntLit(result.typ, typ)
for i in 0 ..< result.len:
result.sons[i] = fitNode(c, typ, result.sons[i], result.sons[i].info)
result.typ.sons[0] = makeRangeType(c, 0, sonsLen(result) - 1, n.info)
result.typ.sons[0] = makeRangeType(c, firstIndex, lastIndex, n.info,
indexType)
proc fixAbstractType(c: PContext, n: PNode) =
for i in 1 ..< n.len:

View File

@@ -548,3 +548,12 @@ block t3899:
x.a[i]
const c = O(a: [1.0,2.0])
echo c[2]
block arrayLiterals:
type ABC = enum A, B, C
template Idx[IdxT, ElemT](arr: array[IdxT, ElemT]): untyped = IdxT
doAssert [A: 0, B: 1].Idx is range[A..B]
doAssert [A: 0, 1, 3].Idx is ABC
doAssert [1: 2][1] == 2
doAssert [-1'i8: 2][-1] == 2
doAssert [-1'i8: 2, 3, 4, 5].Idx is range[-1'i8..2'i8]

View File

@@ -0,0 +1,6 @@
discard """
errormsg: "size of array exceeds range of index type 'range 1..2(Color)' by 3 elements"
line: 6
"""
type Color = enum Red, Green, Blue
let y = [Green: 0, 1, 2, 3, 4]

View File

@@ -0,0 +1,5 @@
discard """
errormsg: "expected ordinal value for array index, got '\"string\"'"
line: 5
"""
let x = ["string": 0, "index": 1]

View File

@@ -0,0 +1,5 @@
discard """
errormsg: "size of array exceeds range of index type 'range 2147483646..2147483647(int32)' by 1 elements"
line: 5
"""
echo [high(int32)-1: 1, 2, 3]