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

pragmas: type pragmas must follow generic params #400

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
63 changes: 33 additions & 30 deletions compiler/ast/parser.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1987,7 +1987,7 @@ proc parseObject(p: var Parser): PNode =
result = newNodeP(nkObjectTy, p)
p.getTok
result.add if p.tok.tokType == tkCurlyDotLe and p.validInd:
# Deprecated since v0.20.0
# Deprecated: type declaration syntax needs overhaul to fix this
p.localError ParserReport(kind: rparPragmaNotFollowingTypeName)
p.parsePragma
else:
Expand Down Expand Up @@ -2063,38 +2063,41 @@ proc parseTypeClass(p: var Parser): PNode =

proc parseTypeDef(p: var Parser): PNode =
#|
#| typeDef = identWithPragmaDot genericParamList? '=' optInd typeDefAux
#| indAndComment? / identVisDot genericParamList? pragma '=' optInd typeDefAux
#| typeDef = identWithPragmaDot '=' optInd typeDefAux
#| indAndComment? / identVisDot genericParamList? pragma? '=' optInd typeDefAux
#| indAndComment?
result = newNodeP(nkTypeDef, p)
let identifier = p.identVis(allowDot=true)
var identPragma = identifier
var foundPragmas = false

if p.tok.tokType == tkCurlyDotLe:
let pragma = optPragmas(p)
identPragma = newTreeI(nkPragmaExpr, p.lineInfo, [identifier, pragma])
foundPragmas = true

let genericParam = if p.validInd and p.tok.tokType == tkBracketLe:
if foundPragmas:
# Deprecated since v0.20.0
p.localError ParserReport(kind: rparPragmaBeforeGenericParameters)
parseGenericParamList(p)
else:
p.emptyNode

if not foundPragmas:
let pragma = optPragmas(p)
if pragma.kind != nkEmpty:
identPragma = newTreeI(nkPragmaExpr, p.lineInfo, [identifier, pragma])
elif p.tok.tokType == tkCurlyDotLe:
p.localError ParserReport(kind: rparPragmaAlreadyPresent)

result.add identPragma
result.add genericParam
let
identifier = p.identVis(allowDot=true)
(genericParams, pragmas) =
case p.tok.tokType
of tkBracketLe:
(
(if p.validInd: parseGenericParamList(p) else: p.emptyNode),
optPragmas(p)
)
# xxx: should the else/empty generic branch invalid indentation error?
of tkCurlyDotLe:
let res = (p.emptyNode, optPragmas(p))

if p.validInd and p.tok.tokType == tkBracketLe:
p.localError ParserReport(kind: rparPragmaBeforeGenericParameters)

res
of tkEquals:
(p.emptyNode, p.emptyNode)
# parsing for everything after the equals is shared, we do that below
else:
(p.emptyNode, p.emptyNode) # xxx: error?

result.add if p.tok.tokType == tkEquals:
result.add:
if pragmas.kind == nkEmpty:
identifier
else:
newTreeI(nkPragmaExpr, p.lineInfo, [identifier, pragmas])
result.add genericParams
result.add case p.tok.tokType
of tkEquals:
result.info = p.lineInfo
p.getTok
p.optInd(result)
Expand Down
7 changes: 4 additions & 3 deletions compiler/ast/report_enums.nim
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ type
rparPragmaAlreadyPresent
rparMisplacedExport

rparPragmaBeforeGenericParameters

# template parser `filter_tmpl.nim`
rparTemplMissingEndClose
rparTemplInvalidExpression
Expand All @@ -230,9 +232,8 @@ type

# warnings begin
rparInconsistentSpacing = "Spacing"
rparEnablePreviewDotOps = "DotLikeOps"
rparPragmaNotFollowingTypeName
rparPragmaBeforeGenericParameters
rparEnablePreviewDotOps = "DotLikeOps"
# warnings END !! add reports BEFORE the last enum !!

rparName = "Name" ## Linter report about used identifier
Expand Down Expand Up @@ -951,7 +952,7 @@ const
rparHintKinds* = {rparName}
rparErrorKinds* = {rparInvalidIndentation .. rparInvalidFilter}
rparWarningKinds* = {
rparInconsistentSpacing .. rparPragmaBeforeGenericParameters}
rparInconsistentSpacing .. rparEnablePreviewDotOps}

#--------------------------------- sem ---------------------------------#
repSemKinds* = {low(SemReportKind) .. high(SemReportKind)}
Expand Down
6 changes: 3 additions & 3 deletions compiler/front/cli_reporter.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2525,13 +2525,13 @@ proc reportBody*(conf: ConfigRef, r: ParserReport): string =
result = "Number of spaces around '$#' is not consistent"

of rparEnablePreviewDotOps:
result = "?"
result = "dot-like operators will be parsed differently with `-d:nimPreviewDotLikeOps`"

of rparPragmaNotFollowingTypeName:
result = "?"
result = "type pragmas follow the type name; this form of writing pragmas is deprecated"

of rparPragmaBeforeGenericParameters:
result = "?"
result = "pragma must come after any generic parameter list"

of rparName:
result = "?"
Expand Down
2 changes: 1 addition & 1 deletion compiler/sem/semdata.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1133,7 +1133,7 @@ proc extractPragma(s: PSym): PNode =
if s.ast[0].kind == nkPragmaExpr and s.ast[0].len > 1:
# s.ast = nkTypedef / nkPragmaExpr / [nkSym, nkPragma]
result = s.ast[0][1]
doAssert result == nil or result.kind == nkPragma
doAssert result == nil or result.kind in {nkPragma, nkEmpty}

proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) =
var pragmaNode: PNode
Expand Down
2 changes: 1 addition & 1 deletion tests/arc/tweave.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
discard """
outputsub: '''Success'''
cmd: '''nim c --gc:arc --threads:on $file'''
disabled: "bsd"
matrix: "--gc:arc --threads:on"
"""

# bug #13936
Expand Down
2 changes: 1 addition & 1 deletion tests/cpp/temitlist.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ disabled: "windows" # pending bug #18011

# bug #4730

type Vector* {.importcpp: "std::vector", header: "<vector>".}[T] = object
type Vector*[T] {.importcpp: "std::vector", header: "<vector>".} = object

template `[]=`*[T](v: var Vector[T], key: int, val: T) =
{.emit: [v, "[", key, "] = ", val, ";"].}
Expand Down
4 changes: 2 additions & 2 deletions tests/cpp/tvector_iterator.nim
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ struct Vector {
""".}

type
Vector {.importcpp: "Vector".} [T] = object
VectorIterator {.importcpp: "Vector<'0>::Iterator".} [T] = object
Vector[T] {.importcpp: "Vector".} = object
VectorIterator[T] {.importcpp: "Vector<'0>::Iterator".} = object

var x: VectorIterator[void]

2 changes: 1 addition & 1 deletion tests/errmsgs/tinvalidinout.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ tinvalidinout.nim(18, 9) Error: the 'in' modifier can be used only with imported
"""

type
Foo {.header: "foo.h", importcpp.} [in T] = object
Foo[in T] {.header: "foo.h", importcpp.} = object

Bar[out X] = object
x: int
Expand Down
2 changes: 1 addition & 1 deletion tests/exception/tcpp_imported_exc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ doAssert(getCurrentException() == nil)
# raise by pointer and also generic type

type
std_vector {.importcpp"std::vector", header"<vector>".} [T] = object
std_vector[T] {.importcpp"std::vector", header"<vector>".} = object

proc newVector[T](len: int): ptr std_vector[T] {.importcpp: "new std::vector<'1>(@)".}
proc deleteVector[T](v: ptr std_vector[T]) {.importcpp: "delete @; @ = NIM_NIL;".}
Expand Down
4 changes: 2 additions & 2 deletions tests/generics/tgeneric3.nim
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ import strutils

type
PNode[T,D] = ref TNode[T,D]
TItem {.acyclic, pure, final, shallow.} [T,D] = object
TItem[T,D] {.acyclic, pure, final, shallow.} = object
key: T
value: D
node: PNode[T,D]
when not (D is string):
val_set: bool

TItems[T,D] = seq[ref TItem[T,D]]
TNode {.acyclic, pure, final, shallow.} [T,D] = object
TNode[T,D] {.acyclic, pure, final, shallow.} = object
slots: TItems[T,D]
left: PNode[T,D]
count: int32
Expand Down
2 changes: 1 addition & 1 deletion tests/iter/titer2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type
TSlotEnum = enum seEmpty, seFilled, seDeleted
TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B]
TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]]
TTable* {.final.}[A, B] = object
TTable*[A, B] {.final.} = object
data: TKeyValuePairSeq[A, B]
counter: int

Expand Down
6 changes: 3 additions & 3 deletions tests/misc/tsimplesort.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type
TSlotEnum = enum seEmpty, seFilled, seDeleted
TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B]
TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]]
TTable* {.final, myShallow.}[A, B] = object
TTable*[A, B] {.final, myShallow.} = object
data: TKeyValuePairSeq[A, B]
counter: int

Expand Down Expand Up @@ -137,8 +137,8 @@ proc `$`*[A, B](t: TTable[A, B]): string =
# ------------------------------ count tables -------------------------------

type
TCountTable* {.final, myShallow.}[
A] = object ## table that counts the number of each key
TCountTable*[A] {.final, myShallow.} = object
## table that counts the number of each key
data: seq[tuple[key: A, val: int]]
counter: int

Expand Down
4 changes: 3 additions & 1 deletion tests/misc/tsizeof.nim
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,9 @@ proc transformObjectconfigPacked(arg: NimNode): NimNode =
result.add transformObjectconfigPacked(child)

proc removeObjectconfig(arg: NimNode): NimNode =
if arg.kind == nnkPragmaExpr and arg[1][0].eqIdent "objectconfig":
if arg.kind == nnkPragmaExpr and
arg[1].kind != nnkEmpty and
arg[1][0].eqIdent "objectconfig":
result = arg[0]
else:
result = copyNimNode(arg)
Expand Down
6 changes: 3 additions & 3 deletions tests/statictypes/tstaticimportcpp.nim
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ struct SimpleStruct {
""" .}

type
GenericIntType {.importcpp: "GenericIntType<'0, '1>".} [N: static[int]; T] = object
GenericIntType[N: static[int]; T] {.importcpp: "GenericIntType<'0, '1>".} = object
data: array[N, T]

GenericIntTypeAlt {.importcpp: "GenericIntType".} [N: static[int]; T] = object
GenericIntTypeAlt[N: static[int]; T] {.importcpp: "GenericIntType".} = object

GenericTType {.importcpp: "GenericTType<'0>".} [T] = object
GenericTType[T] {.importcpp: "GenericTType<'0>".} = object
field: T

GenInt4 = GenericIntType[4, int]
Expand Down