Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sem: keep shape of array constructors in typed AST #1340

Merged
merged 4 commits into from
Jun 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 20 additions & 25 deletions compiler/sem/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -772,32 +772,19 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
result.sons.setLen(n.len)
for i, it in n.pairs:
# first, analyse the index expression (if one exist)
let (idx, val) =
var (idx, val) =
if i == 0: (first, firstIndex)
else: semArrayElementIndex(c, it, indexType)

# figure out the node that holds the element expression, and validate
# the index if one is provided
var e =
case idx.kind
of nkError:
let r = shallowCopy(it)
r[0] = idx
r[1] = it[1]
c.config.wrapError(r)
of nkEmpty:
it
else:
if val == lastIndex + 1:
it[1]
else:
# the specified index value doesn't match with the expected one
c.config.newError(it,
PAstDiag(kind: adSemInvalidOrderInArrayConstructor))
if idx.kind notin {nkError, nkEmpty} and val != lastIndex + 1:
# the specified index value doesn't match with the expected one
idx = c.config.newError(idx,
PAstDiag(kind: adSemInvalidOrderInArrayConstructor))

if e.kind != nkError:
e = semExprWithType(c, e, {})
e = exprNotGenericRoutine(c, e)
# always analyze the expression, even when the index expression is
# erroneous
var e = semExprWithType(c, it.skipColon, {})
e = exprNotGenericRoutine(c, e)

if typ.isNil:
# must be the first item; initialize the common type:
Expand All @@ -816,7 +803,11 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
# yet
typ = commonType(c, typ, e.typ)

result[i] = e
if it.kind == nkExprColonExpr:
result[i] = newTreeI(nkExprColonExpr, it.info, [idx, e])
else:
result[i] = e

inc lastIndex

# watch out for ``sink T``!
Expand All @@ -831,8 +822,12 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
var hasError = false
# fit all elements to be of the derived common type
for it in result.sons.mitems:
it = fitNode(c, typ, it, it.info)
hasError = hasError or it.kind == nkError
if it.kind == nkExprColonExpr:
it[1] = fitNode(c, typ, it[1], it[1].info)
hasError = hasError or nkError in {it[0].kind, it[1].kind}
else:
it = fitNode(c, typ, it, it.info)
hasError = hasError or it.kind == nkError

if hasError:
result = c.config.wrapError(result)
Expand Down
4 changes: 2 additions & 2 deletions compiler/sem/semfold.nim
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
of nkBracket, nkCurly:
result = copyNode(n)
for i, son in n.pairs:
let a = getConstExpr(m, son, idgen, g)
let a = getConstExpr(m, son.skipColon, idgen, g)
if a == nil: return nil
result.add a
incl(result.flags, nfAllConst)
Expand Down Expand Up @@ -881,7 +881,7 @@ proc foldConstExprAux(m: PSym, n: PNode, idgen: IdGenerator, g: ModuleGraph): Fo
# the last node is an expression
result.add foldConstExprAux(m, n[^1], idgen, g)
of nkExprColonExpr:
# comes here from tuple/object constructions
# comes here from array/tuple/object constructions
result.add n[0]
result.add foldConstExprAux(m, n[1], idgen, g)
return
Expand Down
5 changes: 5 additions & 0 deletions compiler/sem/transf.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1315,7 +1315,7 @@
result = transformSons(c, n)
of nkIdentDefs, nkConstDef:
result = shallowCopy(n)
result[0] = transformDefSym(c, n[0])

Check warning on line 1318 in compiler/sem/transf.nim

View workflow job for this annotation

GitHub Actions / Build release binaries (macOS (M1))

workaround for sem not sanitizing AST; transformDefSym is deprecated [Deprecated]

Check warning on line 1318 in compiler/sem/transf.nim

View workflow job for this annotation

GitHub Actions / Build release binaries (macOS)

workaround for sem not sanitizing AST; transformDefSym is deprecated [Deprecated]

Check warning on line 1318 in compiler/sem/transf.nim

View workflow job for this annotation

GitHub Actions / Build release binaries (Linux)

workaround for sem not sanitizing AST; transformDefSym is deprecated [Deprecated]

Check warning on line 1318 in compiler/sem/transf.nim

View workflow job for this annotation

GitHub Actions / Build release binaries (Windows)

workaround for sem not sanitizing AST; transformDefSym is deprecated [Deprecated]

Check warning on line 1318 in compiler/sem/transf.nim

View workflow job for this annotation

GitHub Actions / Build docs and release artifacts (macOS (M1))

workaround for sem not sanitizing AST; transformDefSym is deprecated [Deprecated]

Check warning on line 1318 in compiler/sem/transf.nim

View workflow job for this annotation

GitHub Actions / Build docs and release artifacts (macOS)

workaround for sem not sanitizing AST; transformDefSym is deprecated [Deprecated]

Check warning on line 1318 in compiler/sem/transf.nim

View workflow job for this annotation

GitHub Actions / Build docs and release artifacts (Linux)

workaround for sem not sanitizing AST; transformDefSym is deprecated [Deprecated]

Check warning on line 1318 in compiler/sem/transf.nim

View workflow job for this annotation

GitHub Actions / Build docs and release artifacts (Windows)

workaround for sem not sanitizing AST; transformDefSym is deprecated [Deprecated]
# Skip the second son since it only contains an unsemanticized copy of the
# variable type used by docgen
let last = n.len-1
Expand Down Expand Up @@ -1364,6 +1364,11 @@
of nkPragmaExpr:
# not needed in transformed AST -> drop it
result = transform(c, n.lastSon)
of nkBracket:
# replace elements where the index is specified with just the expression
result = shallowCopy(n)
for i, it in n.pairs:
result[i] = transform(c, it.skipColon)
else:
result = transformSons(c, n)
when false:
Expand Down
21 changes: 21 additions & 0 deletions tests/lang_exprs/ttyped_array_constr_expr.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
discard """
description: '''
Ensure that the shape of literal array construction expresions is
preserved in typed AST
'''
action: compile
"""

import std/macros

macro m(x: typed) =
doAssert treeRepr(x) == """Bracket
ExprColonExpr
IntLit 1
StrLit "a"
StrLit "b"
ExprColonExpr
IntLit 3
StrLit "c""""

m([1: "a", "b", 3: "c"])
Loading