mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-25 04:15:09 +00:00
Remove immediate pragma (#11308)
* remove immediate from tests * remove immediate from the compiler
This commit is contained in:
committed by
Andreas Rumpf
parent
eb471acffb
commit
5b27b263fd
@@ -286,10 +286,6 @@ type
|
||||
const
|
||||
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
|
||||
# local variable has been computed to be a "cursor".
|
||||
# see cursors.nim for details about what that means.
|
||||
|
||||
@@ -667,31 +667,14 @@ proc strTableContains*(t: TStrTable, n: PSym): bool =
|
||||
|
||||
proc strTableRawInsert(data: var seq[PSym], n: PSym) =
|
||||
var h: Hash = n.name.h and high(data)
|
||||
if sfImmediate notin n.flags:
|
||||
# fast path:
|
||||
while data[h] != nil:
|
||||
if data[h] == n:
|
||||
# allowed for 'export' feature:
|
||||
#InternalError(n.info, "StrTableRawInsert: " & n.name.s)
|
||||
return
|
||||
h = nextTry(h, high(data))
|
||||
assert(data[h] == nil)
|
||||
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]
|
||||
while data[h] != nil:
|
||||
if data[h] == n:
|
||||
# allowed for 'export' feature:
|
||||
#InternalError(n.info, "StrTableRawInsert: " & n.name.s)
|
||||
return
|
||||
h = nextTry(h, high(data))
|
||||
assert(data[h] == nil)
|
||||
data[h] = n
|
||||
|
||||
proc symTabReplaceRaw(data: var seq[PSym], prevSym: PSym, newSym: PSym) =
|
||||
assert prevSym.name.h == newSym.name.h
|
||||
|
||||
@@ -54,7 +54,6 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
defineSymbol("nimKnowsNimvm")
|
||||
defineSymbol("nimArrIdx")
|
||||
defineSymbol("nimHasalignOf")
|
||||
defineSymbol("nimImmediateDeprecated")
|
||||
defineSymbol("nimNewShiftOps")
|
||||
defineSymbol("nimDistros")
|
||||
defineSymbol("nimHasCppDefine")
|
||||
|
||||
@@ -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
|
||||
# wiser to just deprecate immediate templates and macros
|
||||
# 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
|
||||
expectedRegularParams = s.typ.len-1
|
||||
givenRegularParams = totalParams - genericParams
|
||||
|
||||
@@ -28,9 +28,9 @@ const
|
||||
wConstructor, wExportNims, wUsed, wLiftLocals, wStacktrace, wLinetrace}
|
||||
converterPragmas* = procPragmas
|
||||
methodPragmas* = procPragmas+{wBase}-{wImportCpp}
|
||||
templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
|
||||
templatePragmas* = {wDeprecated, wError, wGensym, wInject, wDirty,
|
||||
wDelegator, wExportNims, wUsed, wPragma}
|
||||
macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
|
||||
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc,
|
||||
wNodecl, wMagic, wNosideeffect, wCompilerProc, wNonReloadable, wCore, wDeprecated, wExtern,
|
||||
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator,
|
||||
wExportNims, wUsed}
|
||||
@@ -789,12 +789,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||
recordPragma(c, it, "cppdefine", name)
|
||||
processImportCompilerProc(c, sym, name, 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:
|
||||
if sym.kind == skTemplate: incl(sym.flags, sfDirty)
|
||||
else: invalidPragma(c, it)
|
||||
|
||||
@@ -455,8 +455,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||
if sym == c.p.owner:
|
||||
globalError(c.config, info, "recursive dependency: '$1'" % sym.name.s)
|
||||
|
||||
let genericParams = if sfImmediate in sym.flags: 0
|
||||
else: sym.ast[genericParamsPos].len
|
||||
let genericParams = sym.ast[genericParamsPos].len
|
||||
let suppliedParams = max(n.safeLen - 1, 0)
|
||||
|
||||
if suppliedParams < genericParams:
|
||||
|
||||
@@ -2586,16 +2586,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
#if c.config.cmd == cmdPretty and n.sons[0].kind == nkDotExpr:
|
||||
# pretty.checkUse(n.sons[0].sons[1].info, s)
|
||||
case s.kind
|
||||
of skMacro:
|
||||
if sfImmediate notin s.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 skMacro, skTemplate:
|
||||
result = semDirectOp(c, n, flags)
|
||||
of skType:
|
||||
# XXX think about this more (``set`` procs)
|
||||
let ambig = contains(c.ambiguousSymbols, s.id)
|
||||
|
||||
@@ -2089,19 +2089,14 @@ proc evalMacroCall*(module: PSym; g: ModuleGraph;
|
||||
|
||||
let gp = sym.ast[genericParamsPos]
|
||||
for i in 0 ..< gp.len:
|
||||
if sfImmediate notin sym.flags:
|
||||
let idx = sym.typ.len + i
|
||||
if idx < n.len:
|
||||
tos.slots[idx] = setupMacroParam(n.sons[idx], gp[i].sym.typ)
|
||||
else:
|
||||
dec(g.config.evalMacroCounter)
|
||||
c.callsite = nil
|
||||
localError(c.config, n.info, "expected " & $gp.len &
|
||||
" generic parameter(s)")
|
||||
elif gp[i].sym.typ.kind in {tyStatic, tyTypeDesc}:
|
||||
let idx = sym.typ.len + i
|
||||
if idx < n.len:
|
||||
tos.slots[idx] = setupMacroParam(n.sons[idx], gp[i].sym.typ)
|
||||
else:
|
||||
dec(g.config.evalMacroCounter)
|
||||
c.callsite = nil
|
||||
globalError(c.config, n.info, "static[T] or typedesc nor supported for .immediate macros")
|
||||
localError(c.config, n.info, "expected " & $gp.len &
|
||||
" generic parameter(s)")
|
||||
# temporary storage:
|
||||
#for i in L ..< maxSlots: tos.slots[i] = newNode(nkEmpty)
|
||||
result = rawExecute(c, start, tos).regToNode
|
||||
|
||||
@@ -2242,9 +2242,7 @@ proc genProc(c: PCtx; s: PSym): int =
|
||||
genParams(c, s.typ.n)
|
||||
|
||||
# allocate additional space for any generically bound parameters
|
||||
if s.kind == skMacro and
|
||||
sfImmediate notin s.flags and
|
||||
s.ast[genericParamsPos].kind != nkEmpty:
|
||||
if s.kind == skMacro and s.ast[genericParamsPos].kind != nkEmpty:
|
||||
genGenericParams(c, s.ast[genericParamsPos])
|
||||
|
||||
if tfCapturesEnv in s.typ.flags:
|
||||
|
||||
@@ -4209,9 +4209,9 @@ proc addQuoted*[T](s: var string, x: T) =
|
||||
s.addEscapedChar(x)
|
||||
s.add("'")
|
||||
# prevent temporary string allocation
|
||||
elif T is int and not defined(JS):
|
||||
elif T is SomeSignedInt and not defined(JS):
|
||||
s.addInt(x)
|
||||
elif T is float and not defined(JS):
|
||||
elif T is SomeFloat and not defined(JS):
|
||||
s.addFloat(x)
|
||||
elif compiles(s.add(x)):
|
||||
s.add(x)
|
||||
|
||||
@@ -1063,8 +1063,7 @@ template instantiateForRegion(allocator: untyped) =
|
||||
result = realloc(p, newSize)
|
||||
|
||||
when hasThreadSupport:
|
||||
|
||||
template sharedMemStatsShared(v: int) {.immediate.} =
|
||||
template sharedMemStatsShared(v: int) =
|
||||
acquireSys(heapLock)
|
||||
result = v
|
||||
releaseSys(heapLock)
|
||||
|
||||
@@ -19,11 +19,6 @@
|
||||
when not defined(nimNewShared):
|
||||
{.pragma: gcsafe.}
|
||||
|
||||
when not defined(nimImmediateDeprecated):
|
||||
{.pragma: oldimmediate, immediate.}
|
||||
else:
|
||||
{.pragma: oldimmediate.}
|
||||
|
||||
when defined(createNimRtl):
|
||||
when defined(useNimRtl):
|
||||
{.error: "Cannot create and use nimrtl at the same time!".}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import macros
|
||||
|
||||
macro macro_bug*(s: stmt): stmt {.immediate.} =
|
||||
macro macro_bug*(s: untyped) =
|
||||
echo s.treeRepr
|
||||
s.expectKind({nnkProcDef, nnkMethodDef})
|
||||
|
||||
var params = s.params
|
||||
@@ -9,9 +10,9 @@ macro macro_bug*(s: stmt): stmt {.immediate.} =
|
||||
result = newNimNode(nnkProcDef).add(
|
||||
s.name, s[1], genericParams, params, pragma(s), newEmptyNode())
|
||||
|
||||
# don't really do anything
|
||||
var body = body(s)
|
||||
|
||||
# Fails here.
|
||||
var call = newCall("macro_bug", s.params[1][0])
|
||||
body.insert(0, call)
|
||||
result.add(body)
|
||||
|
||||
echo "result:"
|
||||
echo result.repr
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
discard """
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
import macro_bug
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ macro macrotest(n: varargs[untyped]): untyped =
|
||||
result.add(newCall("write", n[1], n[i]))
|
||||
result.add(newCall("writeLine", n[1], newStrLitNode("")))
|
||||
|
||||
macro debug(n: untyped): untyped {.immediate.} =
|
||||
macro debug(n: untyped): untyped =
|
||||
let n = callsite()
|
||||
result = newNimNode(nnkStmtList, n)
|
||||
for i in 1..n.len-1:
|
||||
|
||||
@@ -34,7 +34,7 @@ proc init(my: var TRectangle) =
|
||||
my.height = 10
|
||||
my.draw = cast[proc (my: var TFigure) {.nimcall.}](drawRectangle)
|
||||
|
||||
macro `!` (n: untyped): typed {.immediate.}=
|
||||
macro `!` (n: varargs[untyped]): typed =
|
||||
let n = callsite()
|
||||
result = newNimNode(nnkCall, n)
|
||||
var dot = newNimNode(nnkDotExpr, n)
|
||||
|
||||
@@ -3,7 +3,7 @@ discard """
|
||||
"""
|
||||
# Test operator precedence:
|
||||
|
||||
template `@` (x: untyped): untyped {.immediate.} =
|
||||
template `@@` (x: untyped): untyped =
|
||||
`self`.x
|
||||
|
||||
template `@!` (x: untyped): untyped = x
|
||||
@@ -15,11 +15,11 @@ type
|
||||
TA = tuple[a, b: int, obj: TO]
|
||||
|
||||
proc init(self: var TA): string =
|
||||
@a = 3
|
||||
=== @b = 4
|
||||
@obj.x = 4
|
||||
@@a = 3
|
||||
=== @@b = 4
|
||||
@@obj.x = 4
|
||||
@! === result = "abc"
|
||||
result = @b.`$`
|
||||
result = @@b.`$`
|
||||
|
||||
assert 3+5*5-2 == 28- -26-28
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ foo55
|
||||
foo8.0
|
||||
fooaha
|
||||
bar7
|
||||
immediate
|
||||
10
|
||||
4true
|
||||
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:
|
||||
template something(name: untyped) =
|
||||
|
||||
@@ -3,10 +3,10 @@ discard """
|
||||
file: "ttempl2.nim"
|
||||
line: 18
|
||||
"""
|
||||
template declareInScope(x: untyped, t: typeDesc): untyped {.immediate.} =
|
||||
template declareInScope(x: untyped, t: typeDesc): untyped =
|
||||
var x: t
|
||||
|
||||
template declareInNewScope(x: untyped, t: typeDesc): untyped {.immediate.} =
|
||||
template declareInNewScope(x: untyped, t: typeDesc): untyped =
|
||||
# open a new scope:
|
||||
block:
|
||||
var x: t
|
||||
|
||||
@@ -37,7 +37,7 @@ var `hu "XYZ"` = "yay"
|
||||
|
||||
echo prefix(XYZ)
|
||||
|
||||
template typedef(name: untyped, typ: typeDesc) {.immediate, dirty.} =
|
||||
template typedef(name: untyped, typ: typeDesc) {.dirty.} =
|
||||
type
|
||||
`T name`* = typ
|
||||
`P name`* = ref `T name`
|
||||
|
||||
@@ -8,10 +8,10 @@ discard """
|
||||
type Foo* {.pure, final.} = object
|
||||
elt: float
|
||||
|
||||
template defineOpAssign(T, op: untyped) {.immediate.} =
|
||||
proc op*(v: var T, w: T) {.inline.} =
|
||||
template defineOpAssign(T, op: untyped) =
|
||||
proc `op`*(v: var T, w: T) {.inline.} =
|
||||
for i in 0..1:
|
||||
op(v.elt, w.elt)
|
||||
`op`(v.elt, w.elt)
|
||||
|
||||
const ATTEMPT = 0
|
||||
|
||||
|
||||
@@ -18,14 +18,19 @@ test "previous definitions can be further overloaded or hidden in local scopes":
|
||||
check t("test") == "string"
|
||||
|
||||
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)
|
||||
|
||||
template assertion_failed(body: typed) {.immediate, dirty.} =
|
||||
template fail(msg: string): typed = body
|
||||
template assertionFailed(body: untyped) {.dirty.} =
|
||||
template fail(msg: string): typed =
|
||||
body
|
||||
|
||||
assertionFailed:
|
||||
check(msg == "first fail path")
|
||||
|
||||
assertion_failed: check msg == "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"
|
||||
|
||||
Reference in New Issue
Block a user