requested code review changes

This commit is contained in:
Zahary Karadjov 2017-03-29 16:15:30 +03:00
commit a74ad869e9
6 changed files with 66 additions and 49 deletions

View file

@ -99,7 +99,10 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
if cmp < 0: best = z # x is better than the best so far
elif cmp == 0: alt = z # x is as good as the best so far
elif errors != nil or z.diagnostics != nil:
errors.safeAdd((sym, int z.mutabilityProblem, z.diagnostics))
errors.safeAdd(CandidateError(
sym: sym,
unmatchedVarParam: int z.mutabilityProblem,
diagnostics: z.diagnostics))
else:
# Symbol table has been modified. Restart and pre-calculate all syms
# before any further candidate init and compare. SLOW, but rare case.
@ -126,9 +129,9 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
# we do a pre-analysis. If all types produce the same string, we will add
# module information.
let proto = describeArgs(c, n, 1, preferName)
for err, mut, diagnostics in items(errors):
for err in errors:
var errProto = ""
let n = err.typ.n
let n = err.sym.typ.n
for i in countup(1, n.len - 1):
var p = n.sons[i]
if p.kind == nkSym:
@ -140,16 +143,17 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
break
var candidates = ""
for err, mut, diagnostics in items(errors):
if err.kind in routineKinds and err.ast != nil:
add(candidates, renderTree(err.ast,
for err in errors:
if err.sym.kind in routineKinds and err.sym.ast != nil:
add(candidates, renderTree(err.sym.ast,
{renderNoBody, renderNoComments, renderNoPragmas}))
else:
add(candidates, err.getProcHeader(prefer))
add(candidates, err.sym.getProcHeader(prefer))
add(candidates, "\n")
if mut != 0 and mut < n.len:
add(candidates, "for a 'var' type a variable needs to be passed, but '" & renderTree(n[mut]) & "' is immutable\n")
for diag in diagnostics:
if err.unmatchedVarParam != 0 and err.unmatchedVarParam < n.len:
add(candidates, "for a 'var' type a variable needs to be passed, but '" &
renderTree(n[err.unmatchedVarParam]) & "' is immutable\n")
for diag in err.diagnostics:
add(candidates, diag & "\n")
result = (prefer, candidates)
@ -180,7 +184,9 @@ proc bracketNotFoundError(c: PContext; n: PNode) =
var symx = initOverloadIter(o, c, headSymbol)
while symx != nil:
if symx.kind in routineKinds:
errors.add((symx, 0, nil))
errors.add(CandidateError(sym: symx,
unmatchedVarParam: 0,
diagnostics: nil))
symx = nextOverloadIter(o, c, headSymbol)
if errors.len == 0:
localError(n.info, "could not resolve: " & $n)
@ -405,7 +411,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
n.sons[1] = n.sons[1].sons[0]
notFoundError(c, n, errors)
else:
if efExplain notin flags:
if efExplain notin flags and c.compilesContextId == 0:
# repeat the overload resolution,
# this time enabling all the diagnostic output (this should fail again)
discard semOverloadedCall(c, n, nOrig, filter, flags + {efExplain})

View file

@ -1555,9 +1555,14 @@ proc usesResult(n: PNode): bool =
for c in n:
if usesResult(c): return true
proc inferConceptStaticParam(c: PContext, typ: PType, n: PNode) =
proc inferConceptStaticParam(c: PContext, inferred, n: PNode) =
var typ = inferred.typ
let res = semConstExpr(c, n)
if not sameType(res.typ, typ.base): localError(n.info, "")
if not sameType(res.typ, typ.base):
localError(n.info,
"cannot infer the concept parameter '%s', due to a type mismatch. " &
"attempt to equate '%s' and '%s'.",
[inferred.renderTree, $res.typ, $typ.base])
typ.n = res
proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
@ -1616,12 +1621,14 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
if c.inTypeClass > 0 and expr.typ != nil:
case expr.typ.kind
of tyBool:
if expr.kind == nkInfix and expr[0].sym.name.s == "==":
if expr.kind == nkInfix and
expr[0].kind == nkSym and
expr[0].sym.name.s == "==":
if expr[1].typ.isUnresolvedStatic:
inferConceptStaticParam(c, expr[1].typ, expr[2])
inferConceptStaticParam(c, expr[1], expr[2])
continue
elif expr[2].typ.isUnresolvedStatic:
inferConceptStaticParam(c, expr[2].typ, expr[1])
inferConceptStaticParam(c, expr[2], expr[1])
continue
let verdict = semConstExpr(c, n[i])

View file

@ -1235,7 +1235,7 @@ proc symFromExpectedTypeNode(c: PContext, n: PNode): PSym =
if n.kind == nkType:
result = symFromType(n.typ, n.info)
else:
localError(n.info, "xx")
localError(n.info, errTypeExpected)
result = errorSym(c, n)
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =

View file

@ -22,10 +22,10 @@ type
TCandidateState* = enum
csEmpty, csMatch, csNoMatch
CandidateError = tuple
sym: PSym
unmatchedVarParam: int
diagnostics: seq[string]
CandidateError* = object
sym*: PSym
unmatchedVarParam*: int
diagnostics*: seq[string]
CandidateErrors* = seq[CandidateError]
@ -589,8 +589,8 @@ proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
proc matchUserTypeClass*(c: PContext, m: var TCandidate,
ff, a: PType): PType =
var
Concept = ff.skipTypes({tyUserTypeClassInst})
body = Concept.n[3]
typeClass = ff.skipTypes({tyUserTypeClassInst})
body = typeClass.n[3]
if c.inTypeClass > 4:
localError(body.info, $body & " too nested for type matching")
return nil
@ -611,7 +611,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
param: PSym
template paramSym(kind): untyped =
newSym(kind, typeParamName, Concept.sym, Concept.sym.info)
newSym(kind, typeParamName, typeClass.sym, typeClass.sym.info)
block addTypeParam:
for prev in typeParams:
@ -642,7 +642,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
addDecl(c, param)
for param in Concept.n[0]:
for param in typeClass.n[0]:
var
dummyName: PNode
dummyType: PType
@ -665,7 +665,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
internalAssert dummyName.kind == nkIdent
var dummyParam = newSym(if modifier == tyTypeDesc: skType else: skVar,
dummyName.ident, Concept.sym, Concept.sym.info)
dummyName.ident, typeClass.sym, typeClass.sym.info)
dummyParam.typ = dummyType
addDecl(c, dummyParam)
@ -675,7 +675,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
errorPrefix: string
flags: TExprFlags = {}
collectDiagnostics = m.diagnostics != nil or
sfExplain in Concept.sym.flags
sfExplain in typeClass.sym.flags
if collectDiagnostics:
oldWriteHook = writelnHook
@ -684,7 +684,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
diagnostics = @[]
flags = {efExplain}
writelnHook = proc (s: string) =
if errorPrefix == nil: errorPrefix = Concept.sym.name.s & ":"
if errorPrefix == nil: errorPrefix = typeClass.sym.name.s & ":"
let msg = s.replace("Error:", errorPrefix)
if oldWriteHook != nil: oldWriteHook msg
diagnostics.add msg
@ -704,7 +704,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
put(m, p[1], p[0].typ)
if ff.kind == tyUserTypeClassInst:
result = generateTypeInstance(c, m.bindings, Concept.sym.info, ff)
result = generateTypeInstance(c, m.bindings, typeClass.sym.info, ff)
else:
result = copyType(ff, ff.owner, true)