Remove immediate pragma (#11308)

* remove immediate from tests
* remove immediate from the compiler
This commit is contained in:
Arne Döring 2019-05-29 22:21:51 +02:00 • committed by Andreas Rumpf
commit 5b27b263fd
22 changed files with 53 additions and 116 deletions

View file

@ -286,10 +286,6 @@ type
const const
sfNoInit* = sfMainModule # don't generate code to init the variable sfNoInit* = sfMainModule # don't generate code to init the variable
sfImmediate* = sfDispatcher
# macro or template is immediately expanded
# without considering any possible overloads
sfCursor* = sfDispatcher sfCursor* = sfDispatcher
# local variable has been computed to be a "cursor". # local variable has been computed to be a "cursor".
# see cursors.nim for details about what that means. # see cursors.nim for details about what that means.

View file

@ -667,8 +667,6 @@ proc strTableContains*(t: TStrTable, n: PSym): bool =
proc strTableRawInsert(data: var seq[PSym], n: PSym) = proc strTableRawInsert(data: var seq[PSym], n: PSym) =
var h: Hash = n.name.h and high(data) var h: Hash = n.name.h and high(data)
if sfImmediate notin n.flags:
# fast path:
while data[h] != nil: while data[h] != nil:
if data[h] == n: if data[h] == n:
# allowed for 'export' feature: # allowed for 'export' feature:
@ -677,21 +675,6 @@ proc strTableRawInsert(data: var seq[PSym], n: PSym) =
h = nextTry(h, high(data)) h = nextTry(h, high(data))
assert(data[h] == nil) assert(data[h] == nil)
data[h] = n data[h] = n
else:
# slow path; we have to ensure immediate symbols are preferred for
# symbol lookups.
# consider the chain: foo (immediate), foo, bar, bar (immediate)
# then bar (immediate) gets replaced with foo (immediate) and the non
# immediate foo is picked! Thus we need to replace it with the first
# slot that has in fact the same identifier stored in it!
var favPos = -1
while data[h] != nil:
if data[h] == n: return
if favPos < 0 and data[h].name.id == n.name.id: favPos = h
h = nextTry(h, high(data))
assert(data[h] == nil)
data[h] = n
if favPos >= 0: swap data[h], data[favPos]
proc symTabReplaceRaw(data: var seq[PSym], prevSym: PSym, newSym: PSym) = proc symTabReplaceRaw(data: var seq[PSym], prevSym: PSym, newSym: PSym) =
assert prevSym.name.h == newSym.name.h assert prevSym.name.h == newSym.name.h

View file

@ -54,7 +54,6 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimKnowsNimvm") defineSymbol("nimKnowsNimvm")
defineSymbol("nimArrIdx") defineSymbol("nimArrIdx")
defineSymbol("nimHasalignOf") defineSymbol("nimHasalignOf")
defineSymbol("nimImmediateDeprecated")
defineSymbol("nimNewShiftOps") defineSymbol("nimNewShiftOps")
defineSymbol("nimDistros") defineSymbol("nimDistros")
defineSymbol("nimHasCppDefine") defineSymbol("nimHasCppDefine")

View file

@ -104,7 +104,7 @@ proc evalTemplateArgs(n: PNode, s: PSym; conf: ConfigRef; fromHlo: bool): PNode
# their bodies. We could try to fix this, but it may be # their bodies. We could try to fix this, but it may be
# wiser to just deprecate immediate templates and macros # wiser to just deprecate immediate templates and macros
# now that we have working untyped parameters. # now that we have working untyped parameters.
genericParams = if sfImmediate in s.flags or fromHlo: 0 genericParams = if fromHlo: 0
else: s.ast[genericParamsPos].len else: s.ast[genericParamsPos].len
expectedRegularParams = s.typ.len-1 expectedRegularParams = s.typ.len-1
givenRegularParams = totalParams - genericParams givenRegularParams = totalParams - genericParams

View file

@ -28,9 +28,9 @@ const
wConstructor, wExportNims, wUsed, wLiftLocals, wStacktrace, wLinetrace} wConstructor, wExportNims, wUsed, wLiftLocals, wStacktrace, wLinetrace}
converterPragmas* = procPragmas converterPragmas* = procPragmas
methodPragmas* = procPragmas+{wBase}-{wImportCpp} methodPragmas* = procPragmas+{wBase}-{wImportCpp}
templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty, templatePragmas* = {wDeprecated, wError, wGensym, wInject, wDirty,
wDelegator, wExportNims, wUsed, wPragma} wDelegator, wExportNims, wUsed, wPragma}
macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc, macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc,
wNodecl, wMagic, wNosideeffect, wCompilerProc, wNonReloadable, wCore, wDeprecated, wExtern, wNodecl, wMagic, wNosideeffect, wCompilerProc, wNonReloadable, wCore, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator, wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator,
wExportNims, wUsed} wExportNims, wUsed}
@ -789,12 +789,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
recordPragma(c, it, "cppdefine", name) recordPragma(c, it, "cppdefine", name)
processImportCompilerProc(c, sym, name, it.info) processImportCompilerProc(c, sym, name, it.info)
of wExtern: setExternName(c, sym, expectStrLit(c, it), it.info) of wExtern: setExternName(c, sym, expectStrLit(c, it), it.info)
of wImmediate:
if sym.kind in {skTemplate, skMacro}:
incl(sym.flags, sfImmediate)
incl(sym.flags, sfAllUntyped)
message(c.config, n.info, warnDeprecated, "use 'untyped' parameters instead; immediate is deprecated")
else: invalidPragma(c, it)
of wDirty: of wDirty:
if sym.kind == skTemplate: incl(sym.flags, sfDirty) if sym.kind == skTemplate: incl(sym.flags, sfDirty)
else: invalidPragma(c, it) else: invalidPragma(c, it)

View file

@ -455,8 +455,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
if sym == c.p.owner: if sym == c.p.owner:
globalError(c.config, info, "recursive dependency: '$1'" % sym.name.s) globalError(c.config, info, "recursive dependency: '$1'" % sym.name.s)
let genericParams = if sfImmediate in sym.flags: 0 let genericParams = sym.ast[genericParamsPos].len
else: sym.ast[genericParamsPos].len
let suppliedParams = max(n.safeLen - 1, 0) let suppliedParams = max(n.safeLen - 1, 0)
if suppliedParams < genericParams: if suppliedParams < genericParams:

View file

@ -2586,16 +2586,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
#if c.config.cmd == cmdPretty and n.sons[0].kind == nkDotExpr: #if c.config.cmd == cmdPretty and n.sons[0].kind == nkDotExpr:
# pretty.checkUse(n.sons[0].sons[1].info, s) # pretty.checkUse(n.sons[0].sons[1].info, s)
case s.kind case s.kind
of skMacro: of skMacro, skTemplate:
if sfImmediate notin s.flags:
result = semDirectOp(c, n, flags) result = semDirectOp(c, n, flags)
else:
result = semMacroExpr(c, n, n, s, flags)
of skTemplate:
if sfImmediate notin s.flags:
result = semDirectOp(c, n, flags)
else:
result = semTemplateExpr(c, n, s, flags)
of skType: of skType:
# XXX think about this more (``set`` procs) # XXX think about this more (``set`` procs)
let ambig = contains(c.ambiguousSymbols, s.id) let ambig = contains(c.ambiguousSymbols, s.id)

View file

@ -2089,7 +2089,6 @@ proc evalMacroCall*(module: PSym; g: ModuleGraph;
let gp = sym.ast[genericParamsPos] let gp = sym.ast[genericParamsPos]
for i in 0 ..< gp.len: for i in 0 ..< gp.len:
if sfImmediate notin sym.flags:
let idx = sym.typ.len + i let idx = sym.typ.len + i
if idx < n.len: if idx < n.len:
tos.slots[idx] = setupMacroParam(n.sons[idx], gp[i].sym.typ) tos.slots[idx] = setupMacroParam(n.sons[idx], gp[i].sym.typ)
@ -2098,10 +2097,6 @@ proc evalMacroCall*(module: PSym; g: ModuleGraph;
c.callsite = nil c.callsite = nil
localError(c.config, n.info, "expected " & $gp.len & localError(c.config, n.info, "expected " & $gp.len &
" generic parameter(s)") " generic parameter(s)")
elif gp[i].sym.typ.kind in {tyStatic, tyTypeDesc}:
dec(g.config.evalMacroCounter)
c.callsite = nil
globalError(c.config, n.info, "static[T] or typedesc nor supported for .immediate macros")
# temporary storage: # temporary storage:
#for i in L ..< maxSlots: tos.slots[i] = newNode(nkEmpty) #for i in L ..< maxSlots: tos.slots[i] = newNode(nkEmpty)
result = rawExecute(c, start, tos).regToNode result = rawExecute(c, start, tos).regToNode

View file

@ -2242,9 +2242,7 @@ proc genProc(c: PCtx; s: PSym): int =
genParams(c, s.typ.n) genParams(c, s.typ.n)
# allocate additional space for any generically bound parameters # allocate additional space for any generically bound parameters
if s.kind == skMacro and if s.kind == skMacro and s.ast[genericParamsPos].kind != nkEmpty:
sfImmediate notin s.flags and
s.ast[genericParamsPos].kind != nkEmpty:
genGenericParams(c, s.ast[genericParamsPos]) genGenericParams(c, s.ast[genericParamsPos])
if tfCapturesEnv in s.typ.flags: if tfCapturesEnv in s.typ.flags:

View file

@ -4209,9 +4209,9 @@ proc addQuoted*[T](s: var string, x: T) =
s.addEscapedChar(x) s.addEscapedChar(x)
s.add("'") s.add("'")
# prevent temporary string allocation # prevent temporary string allocation
elif T is int and not defined(JS): elif T is SomeSignedInt and not defined(JS):
s.addInt(x) s.addInt(x)
elif T is float and not defined(JS): elif T is SomeFloat and not defined(JS):
s.addFloat(x) s.addFloat(x)
elif compiles(s.add(x)): elif compiles(s.add(x)):
s.add(x) s.add(x)

View file

@ -1063,8 +1063,7 @@ template instantiateForRegion(allocator: untyped) =
result = realloc(p, newSize) result = realloc(p, newSize)
when hasThreadSupport: when hasThreadSupport:
template sharedMemStatsShared(v: int) =
template sharedMemStatsShared(v: int) {.immediate.} =
acquireSys(heapLock) acquireSys(heapLock)
result = v result = v
releaseSys(heapLock) releaseSys(heapLock)

View file

@ -19,11 +19,6 @@
when not defined(nimNewShared): when not defined(nimNewShared):
{.pragma: gcsafe.} {.pragma: gcsafe.}
when not defined(nimImmediateDeprecated):
{.pragma: oldimmediate, immediate.}
else:
{.pragma: oldimmediate.}
when defined(createNimRtl): when defined(createNimRtl):
when defined(useNimRtl): when defined(useNimRtl):
{.error: "Cannot create and use nimrtl at the same time!".} {.error: "Cannot create and use nimrtl at the same time!".}

View file

@ -1,6 +1,7 @@
import macros import macros
macro macro_bug*(s: stmt): stmt {.immediate.} = macro macro_bug*(s: untyped) =
echo s.treeRepr
s.expectKind({nnkProcDef, nnkMethodDef}) s.expectKind({nnkProcDef, nnkMethodDef})
var params = s.params var params = s.params
@ -9,9 +10,9 @@ macro macro_bug*(s: stmt): stmt {.immediate.} =
result = newNimNode(nnkProcDef).add( result = newNimNode(nnkProcDef).add(
s.name, s[1], genericParams, params, pragma(s), newEmptyNode()) s.name, s[1], genericParams, params, pragma(s), newEmptyNode())
# don't really do anything
var body = body(s) var body = body(s)
# Fails here.
var call = newCall("macro_bug", s.params[1][0])
body.insert(0, call)
result.add(body) result.add(body)
echo "result:"
echo result.repr

View file

@ -1,6 +1,3 @@
discard """
disabled: true
"""
import macro_bug import macro_bug

View file

@ -28,7 +28,7 @@ macro macrotest(n: varargs[untyped]): untyped =
result.add(newCall("write", n[1], n[i])) result.add(newCall("write", n[1], n[i]))
result.add(newCall("writeLine", n[1], newStrLitNode(""))) result.add(newCall("writeLine", n[1], newStrLitNode("")))
macro debug(n: untyped): untyped {.immediate.} = macro debug(n: untyped): untyped =
let n = callsite() let n = callsite()
result = newNimNode(nnkStmtList, n) result = newNimNode(nnkStmtList, n)
for i in 1..n.len-1: for i in 1..n.len-1:

View file

@ -34,7 +34,7 @@ proc init(my: var TRectangle) =
my.height = 10 my.height = 10
my.draw = cast[proc (my: var TFigure) {.nimcall.}](drawRectangle) my.draw = cast[proc (my: var TFigure) {.nimcall.}](drawRectangle)
macro `!` (n: untyped): typed {.immediate.}= macro `!` (n: varargs[untyped]): typed =
let n = callsite() let n = callsite()
result = newNimNode(nnkCall, n) result = newNimNode(nnkCall, n)
var dot = newNimNode(nnkDotExpr, n) var dot = newNimNode(nnkDotExpr, n)

View file

@ -3,7 +3,7 @@ discard """
""" """
# Test operator precedence: # Test operator precedence:
template `@` (x: untyped): untyped {.immediate.} = template `@@` (x: untyped): untyped =
`self`.x `self`.x
template `@!` (x: untyped): untyped = x template `@!` (x: untyped): untyped = x
@ -15,11 +15,11 @@ type
TA = tuple[a, b: int, obj: TO] TA = tuple[a, b: int, obj: TO]
proc init(self: var TA): string = proc init(self: var TA): string =
@a = 3 @@a = 3
=== @b = 4 === @@b = 4
@obj.x = 4 @@obj.x = 4
@! === result = "abc" @! === result = "abc"
result = @b.`$` result = @@b.`$`
assert 3+5*5-2 == 28- -26-28 assert 3+5*5-2 == 28- -26-28

View file

@ -6,7 +6,6 @@ foo55
foo8.0 foo8.0
fooaha fooaha
bar7 bar7
immediate
10 10
4true 4true
132 132
@ -123,21 +122,6 @@ block pattern_with_converter:
block prefer_immediate:
# Test that immediate templates are preferred over non-immediate templates
template foo(a, b: untyped) = echo "foo expr"
template foo(a, b: int) = echo "foo int"
template foo(a, b: float) = echo "foo float"
template foo(a, b: string) = echo "foo string"
template foo(a, b: untyped) {.immediate.} = echo "immediate"
template foo(a, b: bool) = echo "foo bool"
template foo(a, b: char) = echo "foo char"
foo(undeclaredIdentifier, undeclaredIdentifier2)
block procparshadow: block procparshadow:
template something(name: untyped) = template something(name: untyped) =

View file

@ -3,10 +3,10 @@ discard """
file: "ttempl2.nim" file: "ttempl2.nim"
line: 18 line: 18
""" """
template declareInScope(x: untyped, t: typeDesc): untyped {.immediate.} = template declareInScope(x: untyped, t: typeDesc): untyped =
var x: t var x: t
template declareInNewScope(x: untyped, t: typeDesc): untyped {.immediate.} = template declareInNewScope(x: untyped, t: typeDesc): untyped =
# open a new scope: # open a new scope:
block: block:
var x: t var x: t

View file

@ -37,7 +37,7 @@ var `hu "XYZ"` = "yay"
echo prefix(XYZ) echo prefix(XYZ)
template typedef(name: untyped, typ: typeDesc) {.immediate, dirty.} = template typedef(name: untyped, typ: typeDesc) {.dirty.} =
type type
`T name`* = typ `T name`* = typ
`P name`* = ref `T name` `P name`* = ref `T name`

View file

@ -8,10 +8,10 @@ discard """
type Foo* {.pure, final.} = object type Foo* {.pure, final.} = object
elt: float elt: float
template defineOpAssign(T, op: untyped) {.immediate.} = template defineOpAssign(T, op: untyped) =
proc op*(v: var T, w: T) {.inline.} = proc `op`*(v: var T, w: T) {.inline.} =
for i in 0..1: for i in 0..1:
op(v.elt, w.elt) `op`(v.elt, w.elt)
const ATTEMPT = 0 const ATTEMPT = 0

View file

@ -18,14 +18,19 @@ test "previous definitions can be further overloaded or hidden in local scopes":
check t("test") == "string" check t("test") == "string"
test "templates can be redefined multiple times": test "templates can be redefined multiple times":
template customAssert(cond: bool, msg: string): typed {.immediate, dirty.} = template customAssert(cond: bool, msg: string): typed {.dirty.} =
if not cond: fail(msg) if not cond: fail(msg)
template assertion_failed(body: typed) {.immediate, dirty.} = template assertionFailed(body: untyped) {.dirty.} =
template fail(msg: string): typed = body template fail(msg: string): typed =
body
assertionFailed:
check(msg == "first fail path")
assertion_failed: check msg == "first fail path"
customAssert false, "first fail path" customAssert false, "first fail path"
assertion_failed: check msg == "second fail path" assertionFailed:
check(msg == "second fail path")
customAssert false, "second fail path" customAssert false, "second fail path"