pragma blocks; fixed line information issue with user defined assertions
This commit is contained in:
parent
42dad650e0
commit
78f4aacde9
17 changed files with 133 additions and 23 deletions
|
|
@ -139,6 +139,7 @@ type
|
|||
nkMacroStmt, # a macro statement
|
||||
nkAsmStmt, # an assembler block
|
||||
nkPragma, # a pragma statement
|
||||
nkPragmaBlock, # a pragma with a block
|
||||
nkIfStmt, # an if statement
|
||||
nkWhenStmt, # a when statement
|
||||
nkForStmt, # a for statement
|
||||
|
|
@ -390,7 +391,8 @@ type
|
|||
mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal,
|
||||
mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNLineInfo,
|
||||
mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr,
|
||||
mEqIdent, mEqNimrodNode, mNHint, mNWarning, mNError, mGetTypeInfo
|
||||
mEqIdent, mEqNimrodNode, mNHint, mNWarning, mNError,
|
||||
mInstantiationInfo, mGetTypeInfo
|
||||
|
||||
type
|
||||
PNode* = ref TNode
|
||||
|
|
|
|||
|
|
@ -11,11 +11,7 @@
|
|||
|
||||
import
|
||||
ast, astalgo, ropes, lists, hashes, strutils, types, msgs, wordrecg,
|
||||
platform
|
||||
|
||||
proc whichPragma*(n: PNode): TSpecialWord =
|
||||
var key = if n.kind == nkExprColonExpr: n.sons[0] else: n
|
||||
if key.kind == nkIdent: result = whichKeyword(key.ident)
|
||||
platform, trees
|
||||
|
||||
proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
|
||||
case n.kind
|
||||
|
|
|
|||
|
|
@ -1213,6 +1213,8 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
|||
of nkMetaNode:
|
||||
result = copyTree(n.sons[0])
|
||||
result.typ = n.typ
|
||||
of nkPragmaBlock:
|
||||
result = evalAux(c, n.sons[1], flags)
|
||||
of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr,
|
||||
nkLambda, nkContinueStmt, nkIdent:
|
||||
result = raiseCannotEval(c, n.info)
|
||||
|
|
|
|||
|
|
@ -476,6 +476,12 @@ proc pushInfoContext*(info: TLineInfo) =
|
|||
proc popInfoContext*() =
|
||||
setlen(msgContext, len(msgContext) - 1)
|
||||
|
||||
proc getInfoContext*(index: int): TLineInfo =
|
||||
let L = msgContext.len
|
||||
let i = if index < 0: L + index else: index
|
||||
if i >=% L: result = UnknownLineInfo()
|
||||
else: result = msgContext[i]
|
||||
|
||||
proc ToFilename*(info: TLineInfo): string =
|
||||
if info.fileIndex < 0: result = "???"
|
||||
else: result = fileInfos[info.fileIndex].projPath
|
||||
|
|
|
|||
|
|
@ -1316,6 +1316,15 @@ proc parseBind(p: var TParser): PNode =
|
|||
optInd(p, a)
|
||||
expectNl(p)
|
||||
|
||||
proc parseStmtPragma(p: var TParser): PNode =
|
||||
result = parsePragma(p)
|
||||
if p.tok.tokType == tkColon:
|
||||
let a = result
|
||||
result = newNodeI(nkPragmaBlock, a.info)
|
||||
getTok(p)
|
||||
result.add a
|
||||
result.add parseStmt(p)
|
||||
|
||||
proc simpleStmt(p: var TParser): PNode =
|
||||
case p.tok.tokType
|
||||
of tkReturn: result = parseReturnOrRaise(p, nkReturnStmt)
|
||||
|
|
@ -1324,7 +1333,7 @@ proc simpleStmt(p: var TParser): PNode =
|
|||
of tkDiscard: result = parseYieldOrDiscard(p, nkDiscardStmt)
|
||||
of tkBreak: result = parseBreakOrContinue(p, nkBreakStmt)
|
||||
of tkContinue: result = parseBreakOrContinue(p, nkContinueStmt)
|
||||
of tkCurlyDotLe: result = parsePragma(p)
|
||||
of tkCurlyDotLe: result = parseStmtPragma(p)
|
||||
of tkImport: result = parseImportOrIncludeStmt(p, nkImportStmt)
|
||||
of tkFrom: result = parseFromStmt(p)
|
||||
of tkInclude: result = parseImportOrIncludeStmt(p, nkIncludeStmt)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ const
|
|||
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect,
|
||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
||||
wImportcpp, wImportobjc, wError, wDiscardable}
|
||||
exprPragmas* = {wLine}
|
||||
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
|
||||
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
|
||||
wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
|
||||
|
|
@ -394,6 +395,23 @@ proc PragmaUnroll(c: PContext, n: PNode) =
|
|||
proc PragmaLinearScanEnd(c: PContext, n: PNode) =
|
||||
noVal(n)
|
||||
|
||||
proc PragmaLine(c: PContext, n: PNode) =
|
||||
if n.kind == nkExprColonExpr:
|
||||
n.sons[1] = c.semConstExpr(c, n.sons[1])
|
||||
let a = n.sons[1]
|
||||
if a.kind != nkPar: GlobalError(n.info, errXExpected, "tuple")
|
||||
var x = a.sons[0]
|
||||
var y = a.sons[1]
|
||||
if x.kind == nkExprColonExpr: x = x.sons[1]
|
||||
if y.kind == nkExprColonExpr: y = y.sons[1]
|
||||
if x.kind != nkStrLit: GlobalError(n.info, errStringLiteralExpected)
|
||||
if y.kind != nkIntLit: GlobalError(n.info, errIntLiteralExpected)
|
||||
n.info.fileIndex = msgs.fileInfoIdx(x.strVal)
|
||||
n.info.line = int16(y.intVal)
|
||||
else:
|
||||
# sensible default:
|
||||
n.info = getInfoContext(-1)
|
||||
|
||||
proc processPragma(c: PContext, n: PNode, i: int) =
|
||||
var it = n.sons[i]
|
||||
if it.kind != nkExprColonExpr: invalidPragma(n)
|
||||
|
|
@ -575,6 +593,7 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
|||
noVal(it)
|
||||
if sym.typ == nil: invalidPragma(it)
|
||||
incl(sym.typ.flags, tfIncompleteStruct)
|
||||
of wLine: PragmaLine(c, it)
|
||||
else: invalidPragma(it)
|
||||
else: invalidPragma(it)
|
||||
else: processNote(c, it)
|
||||
|
|
|
|||
|
|
@ -537,6 +537,16 @@ proc gwhile(g: var TSrcGen, n: PNode) =
|
|||
gcoms(g) # a good place for comments
|
||||
gstmts(g, n.sons[1], c)
|
||||
|
||||
proc gpragmaBlock(g: var TSrcGen, n: PNode) =
|
||||
var c: TContext
|
||||
gsub(g, n.sons[0])
|
||||
putWithSpace(g, tkColon, ":")
|
||||
initContext(c)
|
||||
if longMode(n) or (lsub(n.sons[1]) + g.lineLen > maxLineLen):
|
||||
incl(c.flags, rfLongMode)
|
||||
gcoms(g) # a good place for comments
|
||||
gstmts(g, n.sons[1], c)
|
||||
|
||||
proc gtry(g: var TSrcGen, n: PNode) =
|
||||
var c: TContext
|
||||
put(g, tkTry, "try")
|
||||
|
|
@ -933,6 +943,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
|||
putWithSpace(g, tkWhen, "when")
|
||||
gif(g, n)
|
||||
of nkWhileStmt: gwhile(g, n)
|
||||
of nkPragmaBlock: gpragmaBlock(g, n)
|
||||
of nkCaseStmt, nkRecCase: gcase(g, n)
|
||||
of nkMacroStmt: gmacro(g, n)
|
||||
of nkTryStmt: gtry(g, n)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,23 @@ proc semSlurp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
except EIO:
|
||||
GlobalError(a.info, errCannotOpenFile, a.strVal)
|
||||
|
||||
proc expectIntLit(c: PContext, n: PNode): int =
|
||||
let x = c.semConstExpr(c, n)
|
||||
case x.kind
|
||||
of nkIntLit..nkInt64Lit: result = int(x.intVal)
|
||||
else: GlobalError(n.info, errIntLiteralExpected)
|
||||
|
||||
proc semInstantiationInfo(c: PContext, n: PNode): PNode =
|
||||
result = newNodeIT(nkPar, n.info, n.typ)
|
||||
let idx = expectIntLit(c, n.sons[1])
|
||||
let info = getInfoContext(idx)
|
||||
var filename = newNodeIT(nkStrLit, n.info, getSysType(tyString))
|
||||
filename.strVal = ToFilename(info)
|
||||
var line = newNodeIT(nkIntLit, n.info, getSysType(tyInt))
|
||||
line.intVal = ToLinenumber(info)
|
||||
result.add(filename)
|
||||
result.add(line)
|
||||
|
||||
proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
flags: TExprFlags): PNode =
|
||||
case n[0].sym.magic
|
||||
|
|
@ -34,5 +51,6 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
|||
of mAstToStr:
|
||||
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
|
||||
result.typ = getSysType(tyString)
|
||||
of mInstantiationInfo: result = semInstantiationInfo(c, n)
|
||||
else: result = n
|
||||
|
||||
|
|
|
|||
|
|
@ -827,6 +827,18 @@ proc evalInclude(c: PContext, n: PNode): PNode =
|
|||
addSon(result, semStmt(c, gIncludeFile(f)))
|
||||
Excl(c.includedFiles, fileIndex)
|
||||
|
||||
proc setLine(n: PNode, info: TLineInfo) =
|
||||
for i in 0 .. <safeLen(n): setLine(n.sons[i], info)
|
||||
n.info = info
|
||||
|
||||
proc semPragmaBlock(c: PContext, n: PNode): PNode =
|
||||
let pragmaList = n.sons[0]
|
||||
pragma(c, nil, pragmaList, exprPragmas)
|
||||
result = semStmt(c, n.sons[1])
|
||||
for i in 0 .. <pragmaList.len:
|
||||
if whichPragma(pragmaList.sons[i]) == wLine:
|
||||
setLine(result, pragmaList.sons[i].info)
|
||||
|
||||
proc SemStmt(c: PContext, n: PNode): PNode =
|
||||
const # must be last statements in a block:
|
||||
LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
|
||||
|
|
@ -881,6 +893,8 @@ proc SemStmt(c: PContext, n: PNode): PNode =
|
|||
of nkIncludeStmt:
|
||||
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "include")
|
||||
result = evalInclude(c, n)
|
||||
of nkPragmaBlock:
|
||||
result = semPragmaBlock(c, n)
|
||||
else:
|
||||
# in interactive mode, we embed the expression in an 'echo':
|
||||
if gCmd == cmdInteractive:
|
||||
|
|
|
|||
|
|
@ -146,3 +146,7 @@ proc IsRange*(n: PNode): bool {.inline.} =
|
|||
n[0].kind == nkSymChoice and n[0][1].sym.name.id == ord(wDotDot):
|
||||
result = true
|
||||
|
||||
proc whichPragma*(n: PNode): TSpecialWord =
|
||||
let key = if n.kind == nkExprColonExpr: n.sons[0] else: n
|
||||
if key.kind == nkIdent: result = whichKeyword(key.ident)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue