pragma blocks; fixed line information issue with user defined assertions

This commit is contained in:
Araq 2012-01-17 23:58:18 +01:00
commit 78f4aacde9
17 changed files with 133 additions and 23 deletions

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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:

View file

@ -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)