mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-13 06:43:52 +00:00
Custom pragmas in proc types (#8205)
This commit is contained in:
@@ -322,7 +322,8 @@ const
|
||||
usesEffects* = 1 # read effects at position 1
|
||||
writeEffects* = 2 # write effects at position 2
|
||||
tagEffects* = 3 # user defined tag ('gc', 'time' etc.)
|
||||
effectListLen* = 4 # list of effects list
|
||||
pragmasEffects* = 4 # not an effect, but a slot for pragmas in proc type
|
||||
effectListLen* = 5 # list of effects list
|
||||
|
||||
type
|
||||
TTypeKind* = enum # order is important!
|
||||
|
||||
@@ -552,6 +552,10 @@ proc isOwnedProcVar(n: PNode; owner: PSym): bool =
|
||||
# XXX prove the soundness of this effect system rule
|
||||
result = n.kind == nkSym and n.sym.kind == skParam and owner == n.sym.owner
|
||||
|
||||
proc isNoEffectList(n: PNode): bool {.inline.} =
|
||||
assert n.kind == nkEffectList
|
||||
n.len == 0 or (n[tagEffects] == nil and n[exceptionEffects] == nil)
|
||||
|
||||
proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
|
||||
let a = skipConvAndClosure(n)
|
||||
let op = a.typ
|
||||
@@ -561,7 +565,7 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
|
||||
let s = n.skipConv
|
||||
if s.kind == nkSym and s.sym.kind in routineKinds:
|
||||
propagateEffects(tracked, n, s.sym)
|
||||
elif effectList.len == 0:
|
||||
elif isNoEffectList(effectList):
|
||||
if isForwardedProc(n):
|
||||
# we have no explicit effects but it's a forward declaration and so it's
|
||||
# stated there are no additional effects, so simply propagate them:
|
||||
@@ -723,7 +727,7 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
var effectList = op.n.sons[0]
|
||||
if a.kind == nkSym and a.sym.kind == skMethod:
|
||||
propagateEffects(tracked, n, a.sym)
|
||||
elif effectList.len == 0:
|
||||
elif isNoEffectList(effectList):
|
||||
if isForwardedProc(a):
|
||||
propagateEffects(tracked, n, a.sym)
|
||||
elif isIndirectCall(a, tracked.owner):
|
||||
@@ -897,19 +901,18 @@ proc checkMethodEffects*(g: ModuleGraph; disp, branch: PSym) =
|
||||
[$branch.typ.lockLevel, $disp.typ.lockLevel])
|
||||
|
||||
proc setEffectsForProcType*(g: ModuleGraph; t: PType, n: PNode) =
|
||||
var effects = t.n.sons[0]
|
||||
var effects = t.n[0]
|
||||
if t.kind != tyProc or effects.kind != nkEffectList: return
|
||||
|
||||
let
|
||||
raisesSpec = effectSpec(n, wRaises)
|
||||
tagsSpec = effectSpec(n, wTags)
|
||||
if not isNil(raisesSpec) or not isNil(tagsSpec):
|
||||
if n.kind != nkEmpty:
|
||||
internalAssert g.config, effects.len == 0
|
||||
newSeq(effects.sons, effectListLen)
|
||||
let raisesSpec = effectSpec(n, wRaises)
|
||||
if not isNil(raisesSpec):
|
||||
effects.sons[exceptionEffects] = raisesSpec
|
||||
effects[exceptionEffects] = raisesSpec
|
||||
let tagsSpec = effectSpec(n, wTags)
|
||||
if not isNil(tagsSpec):
|
||||
effects.sons[tagEffects] = tagsSpec
|
||||
effects[tagEffects] = tagsSpec
|
||||
effects[pragmasEffects] = n
|
||||
|
||||
proc initEffects(g: ModuleGraph; effects: PNode; s: PSym; t: var TEffects) =
|
||||
newSeq(effects.sons, effectListLen)
|
||||
@@ -917,6 +920,7 @@ proc initEffects(g: ModuleGraph; effects: PNode; s: PSym; t: var TEffects) =
|
||||
effects.sons[tagEffects] = newNodeI(nkArgList, s.info)
|
||||
effects.sons[usesEffects] = g.emptyNode
|
||||
effects.sons[writeEffects] = g.emptyNode
|
||||
effects.sons[pragmasEffects] = g.emptyNode
|
||||
|
||||
t.exc = effects.sons[exceptionEffects]
|
||||
t.tags = effects.sons[tagEffects]
|
||||
|
||||
@@ -229,7 +229,8 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
|
||||
for i in 1..<t.sons.len:
|
||||
fp.add newIdentDefs(t.n[i], t.sons[i])
|
||||
result.add fp
|
||||
result.add newNodeI(nkEmpty, info) # pragmas aren't reconstructed yet
|
||||
result.add if t.n[0].len > 0: t.n[0][pragmasEffects].copyTree
|
||||
else: newNodeI(nkEmpty, info)
|
||||
else:
|
||||
result = mapTypeToBracket("proc", mNone, t, info)
|
||||
of tyOpenArray: result = mapTypeToBracket("openArray", mOpenArray, t, info)
|
||||
|
||||
@@ -1284,7 +1284,9 @@ proc customPragmaNode(n: NimNode): NimNode =
|
||||
let
|
||||
typ = n.getTypeInst()
|
||||
|
||||
if typ.typeKind == ntyTypeDesc:
|
||||
if typ.kind == nnkBracketExpr and typ.len > 1 and typ[1].kind == nnkProcTy:
|
||||
return typ[1][1]
|
||||
elif typ.typeKind == ntyTypeDesc:
|
||||
let impl = typ[1].getImpl()
|
||||
if impl[0].kind == nnkPragmaExpr:
|
||||
return impl[0][1]
|
||||
|
||||
@@ -145,4 +145,12 @@ block:
|
||||
type Annotated {.simpleAttr.} = object
|
||||
|
||||
proc generic_proc[T]() =
|
||||
assert Annotated.hasCustomPragma(simpleAttr)
|
||||
assert Annotated.hasCustomPragma(simpleAttr)
|
||||
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Pragma on proc type
|
||||
|
||||
let a: proc(x: int) {.defaultValue(5).} = nil
|
||||
static:
|
||||
doAssert hasCustomPragma(a.type, defaultValue)
|
||||
|
||||
Reference in New Issue
Block a user