nimbuild should work again
This commit is contained in:
parent
faed98d215
commit
42d0911d6a
11 changed files with 106 additions and 31 deletions
|
|
@ -8,7 +8,8 @@
|
|||
#
|
||||
|
||||
import
|
||||
ast, astalgo, msgs, renderer, magicsys, types, idents, trees, wordrecg
|
||||
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
|
||||
wordrecg
|
||||
|
||||
# Second semantic checking pass over the AST. Necessary because the old
|
||||
# way had some inherent problems. Performs:
|
||||
|
|
@ -48,8 +49,6 @@ when false:
|
|||
proc sem2call(c: PContext, n: PNode): PNode =
|
||||
assert n.kind in nkCallKinds
|
||||
|
||||
|
||||
|
||||
proc sem2sym(c: PContext, n: PNode): PNode =
|
||||
assert n.kind == nkSym
|
||||
|
||||
|
|
@ -97,16 +96,17 @@ proc excType(n: PNode): PType =
|
|||
else: n.sons[0].typ
|
||||
result = skipTypes(t, skipPtrs)
|
||||
|
||||
proc addEffect(a: PEffects, e: PNode) =
|
||||
proc addEffect(a: PEffects, e: PNode, useLineInfo=true) =
|
||||
assert e.kind == nkRaiseStmt
|
||||
var aa = a.exc
|
||||
for i in a.bottom .. <aa.len:
|
||||
if sameType(aa[i].excType, e.excType) and aa[i].info == e.info: return
|
||||
if sameType(aa[i].excType, e.excType):
|
||||
if not useLineInfo: return
|
||||
elif aa[i].info == e.info: return
|
||||
throws(a, e)
|
||||
|
||||
proc mergeEffects(a: PEffects, b: PNode) =
|
||||
for effect in items(b):
|
||||
addEffect(a, effect)
|
||||
proc mergeEffects(a: PEffects, b: PNode, useLineInfo) =
|
||||
for effect in items(b): addEffect(a, effect, useLineInfo)
|
||||
|
||||
proc listEffects(a: PEffects) =
|
||||
var aa = a.exc
|
||||
|
|
@ -118,12 +118,13 @@ proc catches(tracked: PEffects, e: PType) =
|
|||
var L = tracked.exc.len
|
||||
var i = tracked.bottom
|
||||
while i < L:
|
||||
# e supertype of r?
|
||||
if inheritanceDiff(e, tracked.exc[i].excType) <= 0:
|
||||
# r supertype of e?
|
||||
if inheritanceDiff(tracked.exc[i].excType, e) <= 0:
|
||||
tracked.exc.sons[i] = tracked.exc.sons[L-1]
|
||||
dec L
|
||||
else:
|
||||
inc i
|
||||
setLen(tracked.exc.sons, L)
|
||||
|
||||
proc catchesAll(tracked: PEffects) =
|
||||
setLen(tracked.exc.sons, tracked.bottom)
|
||||
|
|
@ -161,6 +162,20 @@ proc trackPragmaStmt(tracked: PEffects, n: PNode) =
|
|||
# list the computed effects up to here:
|
||||
listEffects(tracked)
|
||||
|
||||
proc raisesSpec(n: PNode): PNode =
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var it = n.sons[i]
|
||||
if it.kind == nkExprColonExpr and whichPragma(it) == wRaises:
|
||||
result = it.sons[1]
|
||||
if result.kind notin {nkCurly, nkBracket}:
|
||||
result = newNodeI(nkCurly, result.info)
|
||||
result.add(it.sons[1])
|
||||
return
|
||||
|
||||
proc createRaise(n: PNode, t: PType): PNode =
|
||||
result = newNodeI(nkRaiseStmt, n.info)
|
||||
result.add(newNodeIT(nkType, n.info, t))
|
||||
|
||||
proc track(tracked: PEffects, n: PNode) =
|
||||
case n.kind
|
||||
of nkRaiseStmt: throws(tracked, n)
|
||||
|
|
@ -168,18 +183,20 @@ proc track(tracked: PEffects, n: PNode) =
|
|||
# p's effects are ours too:
|
||||
let op = n.sons[0].typ
|
||||
if op != nil and op.kind == tyProc:
|
||||
InternalAssert op.kind == tyProc and op.n.sons[0].kind == nkEffectList
|
||||
InternalAssert op.n.sons[0].kind == nkEffectList
|
||||
var effectList = op.n.sons[0]
|
||||
if effectList.len == 0:
|
||||
if isIndirectCall(n.sons[0]) or isForwardedProc(n.sons[0]):
|
||||
# assume the worst: raise of exception 'E_Base':
|
||||
var rs = newNodeI(nkRaiseStmt, n.info)
|
||||
var re = newNodeIT(nkType, n.info, sysTypeFromName"E_Base")
|
||||
rs.add(re)
|
||||
addEffect(tracked, rs)
|
||||
if isForwardedProc(n.sons[0]):
|
||||
let spec = raisesSpec(n.sons[0].sym.ast.sons[pragmasPos])
|
||||
if not isNil(spec):
|
||||
mergeEffects(tracked, spec, useLineInfo=false)
|
||||
else:
|
||||
addEffect(tracked, createRaise(n, sysTypeFromName"E_Base"))
|
||||
elif isIndirectCall(n.sons[0]):
|
||||
addEffect(tracked, createRaise(n, sysTypeFromName"E_Base"))
|
||||
else:
|
||||
effectList = effectList.sons[exceptionEffects]
|
||||
mergeEffects(tracked, effectList)
|
||||
mergeEffects(tracked, effectList, useLineInfo=true)
|
||||
of nkTryStmt:
|
||||
trackTryStmt(tracked, n)
|
||||
return
|
||||
|
|
@ -191,10 +208,45 @@ proc track(tracked: PEffects, n: PNode) =
|
|||
for i in 0 .. <safeLen(n):
|
||||
track(tracked, n.sons[i])
|
||||
|
||||
# XXX
|
||||
# - make use of 'raises' in proc types compatibility
|
||||
# - check for 'raises' consistency for multi-methods
|
||||
|
||||
proc checkRaisesSpec(spec, real: PNode) =
|
||||
# check that any real exception is listed in 'spec'; mark those as used;
|
||||
# report any unused exception
|
||||
var used = initIntSet()
|
||||
for r in items(real):
|
||||
block search:
|
||||
for s in 0 .. <spec.len:
|
||||
# r supertype of s?
|
||||
if inheritanceDiff(r.excType, spec[s].typ) <= 0:
|
||||
used.incl(s)
|
||||
break search
|
||||
# XXX call graph analysis would be nice here!
|
||||
localError(r.info, errGenerated, "can raise an unlisted exception: " &
|
||||
typeToString(r.sons[0].typ))
|
||||
# hint about unnecessarily listed exception types:
|
||||
for s in 0 .. <spec.len:
|
||||
if not used.contains(s):
|
||||
Message(spec[s].info, hintXDeclaredButNotUsed, renderTree(spec[s]))
|
||||
|
||||
proc compatibleEffects*(formal, actual: PType): bool =
|
||||
# for proc type compatibility checking:
|
||||
assert formal.kind == tyProc and actual.kind == tyProc
|
||||
InternalAssert formal.n.sons[0].kind == nkEffectList
|
||||
InternalAssert actual.n.sons[0].kind == nkEffectList
|
||||
|
||||
var effectList = formal.n.sons[0]
|
||||
if effectList.len == 0:
|
||||
# 'formal' has no restrictions :-)
|
||||
result = true
|
||||
|
||||
proc trackProc*(s: PSym, body: PNode) =
|
||||
var effects = s.typ.n.sons[0]
|
||||
InternalAssert effects.kind == nkEffectList
|
||||
# effects already computed?
|
||||
if sfForward in s.flags: return
|
||||
if effects.len == effectListLen: return
|
||||
newSeq(effects.sons, effectListLen)
|
||||
effects.sons[exceptionEffects] = newNodeI(nkArgList, body.info)
|
||||
|
|
@ -203,3 +255,6 @@ proc trackProc*(s: PSym, body: PNode) =
|
|||
t.exc = effects.sons[exceptionEffects]
|
||||
track(t, body)
|
||||
|
||||
let spec = raisesSpec(s.ast.sons[pragmasPos])
|
||||
if not isNil(spec):
|
||||
checkRaisesSpec(spec, t.exc)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue