Custom pragmas in proc types (#8205)
This commit is contained in:
parent
c115090f6e
commit
dec97924a4
5 changed files with 30 additions and 14 deletions
|
|
@ -322,7 +322,8 @@ const
|
||||||
usesEffects* = 1 # read effects at position 1
|
usesEffects* = 1 # read effects at position 1
|
||||||
writeEffects* = 2 # write effects at position 2
|
writeEffects* = 2 # write effects at position 2
|
||||||
tagEffects* = 3 # user defined tag ('gc', 'time' etc.)
|
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
|
type
|
||||||
TTypeKind* = enum # order is important!
|
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
|
# XXX prove the soundness of this effect system rule
|
||||||
result = n.kind == nkSym and n.sym.kind == skParam and owner == n.sym.owner
|
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) =
|
proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
|
||||||
let a = skipConvAndClosure(n)
|
let a = skipConvAndClosure(n)
|
||||||
let op = a.typ
|
let op = a.typ
|
||||||
|
|
@ -561,7 +565,7 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
|
||||||
let s = n.skipConv
|
let s = n.skipConv
|
||||||
if s.kind == nkSym and s.sym.kind in routineKinds:
|
if s.kind == nkSym and s.sym.kind in routineKinds:
|
||||||
propagateEffects(tracked, n, s.sym)
|
propagateEffects(tracked, n, s.sym)
|
||||||
elif effectList.len == 0:
|
elif isNoEffectList(effectList):
|
||||||
if isForwardedProc(n):
|
if isForwardedProc(n):
|
||||||
# we have no explicit effects but it's a forward declaration and so it's
|
# 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:
|
# 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]
|
var effectList = op.n.sons[0]
|
||||||
if a.kind == nkSym and a.sym.kind == skMethod:
|
if a.kind == nkSym and a.sym.kind == skMethod:
|
||||||
propagateEffects(tracked, n, a.sym)
|
propagateEffects(tracked, n, a.sym)
|
||||||
elif effectList.len == 0:
|
elif isNoEffectList(effectList):
|
||||||
if isForwardedProc(a):
|
if isForwardedProc(a):
|
||||||
propagateEffects(tracked, n, a.sym)
|
propagateEffects(tracked, n, a.sym)
|
||||||
elif isIndirectCall(a, tracked.owner):
|
elif isIndirectCall(a, tracked.owner):
|
||||||
|
|
@ -897,19 +901,18 @@ proc checkMethodEffects*(g: ModuleGraph; disp, branch: PSym) =
|
||||||
[$branch.typ.lockLevel, $disp.typ.lockLevel])
|
[$branch.typ.lockLevel, $disp.typ.lockLevel])
|
||||||
|
|
||||||
proc setEffectsForProcType*(g: ModuleGraph; t: PType, n: PNode) =
|
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
|
if t.kind != tyProc or effects.kind != nkEffectList: return
|
||||||
|
if n.kind != nkEmpty:
|
||||||
let
|
|
||||||
raisesSpec = effectSpec(n, wRaises)
|
|
||||||
tagsSpec = effectSpec(n, wTags)
|
|
||||||
if not isNil(raisesSpec) or not isNil(tagsSpec):
|
|
||||||
internalAssert g.config, effects.len == 0
|
internalAssert g.config, effects.len == 0
|
||||||
newSeq(effects.sons, effectListLen)
|
newSeq(effects.sons, effectListLen)
|
||||||
|
let raisesSpec = effectSpec(n, wRaises)
|
||||||
if not isNil(raisesSpec):
|
if not isNil(raisesSpec):
|
||||||
effects.sons[exceptionEffects] = raisesSpec
|
effects[exceptionEffects] = raisesSpec
|
||||||
|
let tagsSpec = effectSpec(n, wTags)
|
||||||
if not isNil(tagsSpec):
|
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) =
|
proc initEffects(g: ModuleGraph; effects: PNode; s: PSym; t: var TEffects) =
|
||||||
newSeq(effects.sons, effectListLen)
|
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[tagEffects] = newNodeI(nkArgList, s.info)
|
||||||
effects.sons[usesEffects] = g.emptyNode
|
effects.sons[usesEffects] = g.emptyNode
|
||||||
effects.sons[writeEffects] = g.emptyNode
|
effects.sons[writeEffects] = g.emptyNode
|
||||||
|
effects.sons[pragmasEffects] = g.emptyNode
|
||||||
|
|
||||||
t.exc = effects.sons[exceptionEffects]
|
t.exc = effects.sons[exceptionEffects]
|
||||||
t.tags = effects.sons[tagEffects]
|
t.tags = effects.sons[tagEffects]
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,8 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
|
||||||
for i in 1..<t.sons.len:
|
for i in 1..<t.sons.len:
|
||||||
fp.add newIdentDefs(t.n[i], t.sons[i])
|
fp.add newIdentDefs(t.n[i], t.sons[i])
|
||||||
result.add fp
|
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:
|
else:
|
||||||
result = mapTypeToBracket("proc", mNone, t, info)
|
result = mapTypeToBracket("proc", mNone, t, info)
|
||||||
of tyOpenArray: result = mapTypeToBracket("openArray", mOpenArray, t, info)
|
of tyOpenArray: result = mapTypeToBracket("openArray", mOpenArray, t, info)
|
||||||
|
|
|
||||||
|
|
@ -1284,7 +1284,9 @@ proc customPragmaNode(n: NimNode): NimNode =
|
||||||
let
|
let
|
||||||
typ = n.getTypeInst()
|
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()
|
let impl = typ[1].getImpl()
|
||||||
if impl[0].kind == nnkPragmaExpr:
|
if impl[0].kind == nnkPragmaExpr:
|
||||||
return impl[0][1]
|
return impl[0][1]
|
||||||
|
|
|
||||||
|
|
@ -146,3 +146,11 @@ block:
|
||||||
|
|
||||||
proc generic_proc[T]() =
|
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)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue