diff options
-rw-r--r-- | compiler/ast.nim | 3 | ||||
-rw-r--r-- | compiler/sempass2.nim | 24 | ||||
-rw-r--r-- | compiler/vmdeps.nim | 3 | ||||
-rw-r--r-- | lib/core/macros.nim | 4 | ||||
-rw-r--r-- | tests/pragmas/tcustom_pragma.nim | 10 |
5 files changed, 30 insertions, 14 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 6302c21b9..dbf1151a9 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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! diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 4d3ee0408..e7a76ec22 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -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] diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index 865ecd36e..bf2418eaf 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -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) diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 1f251b73e..8a1be3720 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -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] diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim index cd1edccf6..a5f86b54d 100644 --- a/tests/pragmas/tcustom_pragma.nim +++ b/tests/pragmas/tcustom_pragma.nim @@ -145,4 +145,12 @@ block: type Annotated {.simpleAttr.} = object proc generic_proc[T]() = - assert Annotated.hasCustomPragma(simpleAttr) \ No newline at end of file + assert Annotated.hasCustomPragma(simpleAttr) + + +#-------------------------------------------------------------------------- +# Pragma on proc type + +let a: proc(x: int) {.defaultValue(5).} = nil +static: + doAssert hasCustomPragma(a.type, defaultValue) |