new minor language feature: .noSideEffect blocks like .gcsafe blocks

This commit is contained in:
Andreas Rumpf 2018-11-26 23:28:02 +01:00
commit 413580bc04
7 changed files with 30 additions and 12 deletions

View file

@ -38,7 +38,7 @@ const
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
wTags, wLocks, wGcSafe, wExportNims, wUsed}
exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe}
exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe, wNosideeffect}
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
wBoundchecks, wOverflowchecks, wNilchecks, wMovechecks, wAssertions,
wWarnings, wHints,
@ -855,8 +855,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
sym.flags.incl sfOverriden
of wNosideeffect:
noVal(c, it)
incl(sym.flags, sfNoSideEffect)
if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect)
if sym != nil:
incl(sym.flags, sfNoSideEffect)
if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect)
of wSideeffect:
noVal(c, it)
incl(sym.flags, sfSideEffect)

View file

@ -56,6 +56,7 @@ type
guards: TModel # nested guards
locked: seq[PNode] # locked locations
gcUnsafe, isRecursive, isToplevel, hasSideEffect, inEnforcedGcSafe: bool
inEnforcedNoSideEffects: bool
maxLockLevel, currLockLevel: TLockLevel
config: ConfigRef
graph: ModuleGraph
@ -194,10 +195,10 @@ proc markGcUnsafe(a: PEffects; reason: PNode) =
when true:
template markSideEffect(a: PEffects; reason: typed) =
a.hasSideEffect = true
if not a.inEnforcedNoSideEffects: a.hasSideEffect = true
else:
template markSideEffect(a: PEffects; reason: typed) =
a.hasSideEffect = true
if not a.inEnforcedNoSideEffects: a.hasSideEffect = true
markGcUnsafe(a, reason)
proc listGcUnsafety(s: PSym; onlyWarning: bool; cycleCheck: var IntSet; conf: ConfigRef) =
@ -846,15 +847,20 @@ proc track(tracked: PEffects, n: PNode) =
let oldLocked = tracked.locked.len
let oldLockLevel = tracked.currLockLevel
var enforcedGcSafety = false
var enforceNoSideEffects = false
for i in 0 ..< pragmaList.len:
let pragma = whichPragma(pragmaList.sons[i])
if pragma == wLocks:
lockLocations(tracked, pragmaList.sons[i])
elif pragma == wGcSafe:
enforcedGcSafety = true
elif pragma == wNosideeffect:
enforceNoSideEffects = true
if enforcedGcSafety: tracked.inEnforcedGcSafe = true
if enforceNoSideEffects: tracked.inEnforcedNoSideEffects = true
track(tracked, n.lastSon)
if enforcedGcSafety: tracked.inEnforcedGcSafe = false
if enforceNoSideEffects: tracked.inEnforcedNoSideEffects = false
setLen(tracked.locked, oldLocked)
tracked.currLockLevel = oldLockLevel
of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,

View file

@ -1860,7 +1860,7 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
for i in 0 ..< pragmaList.len:
case whichPragma(pragmaList.sons[i])
of wLine: setLine(result, pragmaList.sons[i].info)
of wLocks, wGcSafe:
of wLocks, wGcSafe, wNosideeffect:
result = n
result.typ = n.sons[1].typ
of wNoRewrite:

View file

@ -1239,8 +1239,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
if dest < 0: dest = c.getTemp(n.typ)
c.gABC(n, opcCallSite, dest)
of mNGenSym: genBinaryABC(c, n, dest, opcGenSym)
of mMinI, mMaxI, mAbsF64, mMinF64, mMaxF64, mAbsI,
mDotDot:
of mMinI, mMaxI, mAbsF64, mMinF64, mMaxF64, mAbsI, mDotDot:
c.genCall(n, dest)
of mExpandToAst:
if n.len != 2: