implemented delegators and improved the error messages of unmatched type classes
This commit is contained in:
parent
89086a8e19
commit
28d9398de7
13 changed files with 130 additions and 93 deletions
|
|
@ -216,7 +216,7 @@ type
|
||||||
TNodeKinds* = set[TNodeKind]
|
TNodeKinds* = set[TNodeKind]
|
||||||
|
|
||||||
type
|
type
|
||||||
TSymFlag* = enum # already 30 flags!
|
TSymFlag* = enum # already 32 flags!
|
||||||
sfUsed, # read access of sym (for warnings) or simply used
|
sfUsed, # read access of sym (for warnings) or simply used
|
||||||
sfExported, # symbol is exported from module
|
sfExported, # symbol is exported from module
|
||||||
sfFromGeneric, # symbol is instantiation of a generic; this is needed
|
sfFromGeneric, # symbol is instantiation of a generic; this is needed
|
||||||
|
|
@ -353,6 +353,7 @@ type
|
||||||
# efficiency
|
# efficiency
|
||||||
nfTransf, # node has been transformed
|
nfTransf, # node has been transformed
|
||||||
nfSem # node has been checked for semantics
|
nfSem # node has been checked for semantics
|
||||||
|
nfDelegate # the call can use a delegator
|
||||||
|
|
||||||
TNodeFlags* = set[TNodeFlag]
|
TNodeFlags* = set[TNodeFlag]
|
||||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 23)
|
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 23)
|
||||||
|
|
@ -774,7 +775,8 @@ const
|
||||||
tyProc, tyString, tyError}
|
tyProc, tyString, tyError}
|
||||||
ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, skIterator,
|
ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, skIterator,
|
||||||
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub}
|
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub}
|
||||||
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, nfAllConst}
|
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
|
||||||
|
nfAllConst, nfDelegate}
|
||||||
namePos* = 0
|
namePos* = 0
|
||||||
patternPos* = 1 # empty except for term rewriting macros
|
patternPos* = 1 # empty except for term rewriting macros
|
||||||
genericParamsPos* = 2
|
genericParamsPos* = 2
|
||||||
|
|
|
||||||
|
|
@ -103,4 +103,5 @@ proc IdentEq*(id: PIdent, name: string): bool =
|
||||||
result = id.id == getIdent(name).id
|
result = id.id == getIdent(name).id
|
||||||
|
|
||||||
var idAnon* = getIdent":anonymous"
|
var idAnon* = getIdent":anonymous"
|
||||||
|
let idDelegator* = getIdent":delegator"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ type
|
||||||
errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError,
|
errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError,
|
||||||
errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile,
|
errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile,
|
||||||
errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitely,
|
errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitely,
|
||||||
|
errOnlyACallOpCanBeDelegator,
|
||||||
|
|
||||||
errXExpectsTwoArguments,
|
errXExpectsTwoArguments,
|
||||||
errXExpectsObjectTypes, errXcanNeverBeOfThisSubtype, errTooManyIterations,
|
errXExpectsObjectTypes, errXcanNeverBeOfThisSubtype, errTooManyIterations,
|
||||||
|
|
@ -316,6 +317,7 @@ const
|
||||||
errCannotRenderX: "cannot render reStructuredText element \'$1\'",
|
errCannotRenderX: "cannot render reStructuredText element \'$1\'",
|
||||||
errVarVarTypeNotAllowed: "type \'var var\' is not allowed",
|
errVarVarTypeNotAllowed: "type \'var var\' is not allowed",
|
||||||
errInstantiateXExplicitely: "instantiate '$1' explicitely",
|
errInstantiateXExplicitely: "instantiate '$1' explicitely",
|
||||||
|
errOnlyACallOpCanBeDelegator: "only a call operator can be a delegator",
|
||||||
errXExpectsTwoArguments: "\'$1\' expects two arguments",
|
errXExpectsTwoArguments: "\'$1\' expects two arguments",
|
||||||
errXExpectsObjectTypes: "\'$1\' expects object types",
|
errXExpectsObjectTypes: "\'$1\' expects object types",
|
||||||
errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype",
|
errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype",
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,14 @@ const
|
||||||
wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
wCompilerProc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
||||||
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
||||||
wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
|
wNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
|
||||||
wGenSym, wInject, wRaises, wTags, wOperator}
|
wGenSym, wInject, wRaises, wTags, wOperator, wDelegator}
|
||||||
converterPragmas* = procPragmas
|
converterPragmas* = procPragmas
|
||||||
methodPragmas* = procPragmas
|
methodPragmas* = procPragmas
|
||||||
templatePragmas* = {wImmediate, wDeprecated, wError, wGenSym, wInject, wDirty}
|
templatePragmas* = {wImmediate, wDeprecated, wError, wGenSym, wInject, wDirty,
|
||||||
|
wDelegator}
|
||||||
macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
|
macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
|
||||||
wNodecl, wMagic, wNosideEffect, wCompilerProc, wDeprecated, wExtern,
|
wNodecl, wMagic, wNosideEffect, wCompilerProc, wDeprecated, wExtern,
|
||||||
wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject}
|
wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject, wDelegator}
|
||||||
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect,
|
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect,
|
||||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
||||||
wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject, wRaises,
|
wImportcpp, wImportobjc, wError, wDiscardable, wGenSym, wInject, wRaises,
|
||||||
|
|
|
||||||
|
|
@ -34,25 +34,18 @@ proc sameMethodDispatcher(a, b: PSym): bool =
|
||||||
|
|
||||||
proc determineType(c: PContext, s: PSym)
|
proc determineType(c: PContext, s: PSym)
|
||||||
|
|
||||||
proc resolveOverloads(c: PContext, n, orig: PNode,
|
proc
|
||||||
filter: TSymKinds): TCandidate =
|
pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
var initialBinding: PNode
|
n, orig: PNode,
|
||||||
var f = n.sons[0]
|
initialBinding: PNode,
|
||||||
if f.kind == nkBracketExpr:
|
filter: TSymKinds,
|
||||||
# fill in the bindings:
|
best, alt: var TCandidate,
|
||||||
initialBinding = f
|
errors: var seq[string]) =
|
||||||
f = f.sons[0]
|
var o: TOverloadIter
|
||||||
else:
|
var sym = initOverloadIter(o, c, headSymbol)
|
||||||
initialBinding = nil
|
|
||||||
|
|
||||||
var
|
|
||||||
o: TOverloadIter
|
|
||||||
alt, z: TCandidate
|
|
||||||
|
|
||||||
template best: expr = result
|
|
||||||
#Message(n.info, warnUser, renderTree(n))
|
|
||||||
var sym = initOverloadIter(o, c, f)
|
|
||||||
var symScope = o.lastOverloadScope
|
var symScope = o.lastOverloadScope
|
||||||
|
|
||||||
|
var z: TCandidate
|
||||||
|
|
||||||
if sym == nil: return
|
if sym == nil: return
|
||||||
initCandidate(best, sym, initialBinding, symScope)
|
initCandidate(best, sym, initialBinding, symScope)
|
||||||
|
|
@ -64,6 +57,11 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
initCandidate(z, sym, initialBinding, o.lastOverloadScope)
|
initCandidate(z, sym, initialBinding, o.lastOverloadScope)
|
||||||
z.calleeSym = sym
|
z.calleeSym = sym
|
||||||
matches(c, n, orig, z)
|
matches(c, n, orig, z)
|
||||||
|
if errors != nil:
|
||||||
|
errors.safeAdd(getProcHeader(sym))
|
||||||
|
if z.errors != nil:
|
||||||
|
for err in z.errors:
|
||||||
|
errors[errors.len - 1].add("\n " & err)
|
||||||
if z.state == csMatch:
|
if z.state == csMatch:
|
||||||
# little hack so that iterators are preferred over everything else:
|
# little hack so that iterators are preferred over everything else:
|
||||||
if sym.kind == skIterator: inc(z.exactMatches, 200)
|
if sym.kind == skIterator: inc(z.exactMatches, 200)
|
||||||
|
|
@ -74,17 +72,71 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
if cmp < 0: best = z # x is better than the best so far
|
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 cmp == 0: alt = z # x is as good as the best so far
|
||||||
else: nil
|
else: nil
|
||||||
sym = nextOverloadIter(o, c, f)
|
sym = nextOverloadIter(o, c, headSymbol)
|
||||||
|
|
||||||
if best.state == csEmpty:
|
proc NotFoundError*(c: PContext, n: PNode, errors: seq[string]) =
|
||||||
# no overloaded proc found
|
# Gives a detailed error message; this is separated from semOverloadedCall,
|
||||||
# do not generate an error yet; the semantic checking will check for
|
# as semOverlodedCall is already pretty slow (and we need this information
|
||||||
# an overloaded () operator
|
# only in case of an error).
|
||||||
elif alt.state == csMatch and cmpCandidates(best, alt) == 0 and
|
if c.InCompilesContext > 0:
|
||||||
not sameMethodDispatcher(best.calleeSym, alt.calleeSym):
|
# fail fast:
|
||||||
if best.state != csMatch:
|
GlobalError(n.info, errTypeMismatch, "")
|
||||||
InternalError(n.info, "x.state is not csMatch")
|
var result = msgKindToString(errTypeMismatch)
|
||||||
#writeMatches(best)
|
add(result, describeArgs(c, n, 1 + ord(nfDelegate in n.flags)))
|
||||||
|
add(result, ')')
|
||||||
|
|
||||||
|
var candidates = ""
|
||||||
|
for err in errors:
|
||||||
|
add(candidates, err)
|
||||||
|
add(candidates, "\n")
|
||||||
|
|
||||||
|
if candidates != "":
|
||||||
|
add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
|
||||||
|
|
||||||
|
LocalError(n.Info, errGenerated, result)
|
||||||
|
|
||||||
|
proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
|
filter: TSymKinds): TCandidate =
|
||||||
|
var initialBinding: PNode
|
||||||
|
var alt: TCandidate
|
||||||
|
var f = n.sons[0]
|
||||||
|
if f.kind == nkBracketExpr:
|
||||||
|
# fill in the bindings:
|
||||||
|
initialBinding = f
|
||||||
|
f = f.sons[0]
|
||||||
|
else:
|
||||||
|
initialBinding = nil
|
||||||
|
|
||||||
|
var errors: seq[string]
|
||||||
|
|
||||||
|
template pickBest(headSymbol: expr) =
|
||||||
|
pickBestCandidate(c, headSymbol, n, orig, initialBinding,
|
||||||
|
filter, result, alt, errors)
|
||||||
|
|
||||||
|
pickBest(f)
|
||||||
|
|
||||||
|
if result.state == csEmpty:
|
||||||
|
if nfDelegate in n.flags:
|
||||||
|
InternalAssert f.kind == nkIdent
|
||||||
|
let calleeName = newStrNode(nkStrLit, f.ident.s)
|
||||||
|
calleeName.info = n.info
|
||||||
|
|
||||||
|
let callOp = newIdentNode(idDelegator, n.info)
|
||||||
|
n.sons[0..0] = [callOp, calleeName]
|
||||||
|
orig.sons[0..0] = [callOp, calleeName]
|
||||||
|
|
||||||
|
pickBest(callOp)
|
||||||
|
|
||||||
|
if result.state == csEmpty:
|
||||||
|
errors = @[]
|
||||||
|
pickBest(f)
|
||||||
|
NotFoundError(c, n, errors)
|
||||||
|
return
|
||||||
|
|
||||||
|
if alt.state == csMatch and cmpCandidates(result, alt) == 0 and
|
||||||
|
not sameMethodDispatcher(result.calleeSym, alt.calleeSym):
|
||||||
|
InternalAssert result.state == csMatch
|
||||||
|
#writeMatches(result)
|
||||||
#writeMatches(alt)
|
#writeMatches(alt)
|
||||||
if c.inCompilesContext > 0:
|
if c.inCompilesContext > 0:
|
||||||
# quick error message for performance of 'compiles' built-in:
|
# quick error message for performance of 'compiles' built-in:
|
||||||
|
|
@ -98,7 +150,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
add(args, ")")
|
add(args, ")")
|
||||||
|
|
||||||
LocalError(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
|
LocalError(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
|
||||||
getProcHeader(best.calleeSym), getProcHeader(alt.calleeSym),
|
getProcHeader(result.calleeSym), getProcHeader(alt.calleeSym),
|
||||||
args])
|
args])
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -155,6 +207,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||||
filter: TSymKinds): PNode =
|
filter: TSymKinds): PNode =
|
||||||
var r = resolveOverloads(c, n, nOrig, filter)
|
var r = resolveOverloads(c, n, nOrig, filter)
|
||||||
if r.state == csMatch: result = semResolvedCall(c, n, r)
|
if r.state == csMatch: result = semResolvedCall(c, n, r)
|
||||||
|
else: result = errorNode(c, n)
|
||||||
|
|
||||||
proc explicitGenericInstError(n: PNode): PNode =
|
proc explicitGenericInstError(n: PNode): PNode =
|
||||||
LocalError(n.info, errCannotInstantiateX, renderTree(n))
|
LocalError(n.info, errCannotInstantiateX, renderTree(n))
|
||||||
|
|
|
||||||
|
|
@ -682,7 +682,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result = n.sons[0]
|
result = n.sons[0]
|
||||||
result.kind = nkCall
|
result.kind = nkCall
|
||||||
for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i])
|
for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i])
|
||||||
return semExpr(c, result, flags)
|
return semDirectOp(c, result, flags)
|
||||||
else:
|
else:
|
||||||
n.sons[0] = semExpr(c, n.sons[0])
|
n.sons[0] = semExpr(c, n.sons[0])
|
||||||
let nOrig = n.copyTree
|
let nOrig = n.copyTree
|
||||||
|
|
@ -767,11 +767,6 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
let nOrig = n.copyTree
|
let nOrig = n.copyTree
|
||||||
#semLazyOpAux(c, n)
|
#semLazyOpAux(c, n)
|
||||||
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
|
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
|
||||||
if result == nil:
|
|
||||||
result = overloadedCallOpr(c, n)
|
|
||||||
if result == nil:
|
|
||||||
NotFoundError(c, n)
|
|
||||||
return errorNode(c, n)
|
|
||||||
result = afterCallActions(c, result, nOrig, flags)
|
result = afterCallActions(c, result, nOrig, flags)
|
||||||
|
|
||||||
proc buildStringify(c: PContext, arg: PNode): PNode =
|
proc buildStringify(c: PContext, arg: PNode): PNode =
|
||||||
|
|
@ -979,20 +974,11 @@ proc dotTransformation(c: PContext, n: PNode): PNode =
|
||||||
addSon(result, copyTree(n[0]))
|
addSon(result, copyTree(n[0]))
|
||||||
else:
|
else:
|
||||||
var i = considerAcc(n.sons[1])
|
var i = considerAcc(n.sons[1])
|
||||||
var f = searchInScopes(c, i)
|
result = newNodeI(nkDotCall, n.info)
|
||||||
# if f != nil and f.kind == skStub: loadStub(f)
|
result.flags.incl nfDelegate
|
||||||
# ``loadStub`` is not correct here as we don't care for ``f`` really
|
addSon(result, newIdentNode(i, n[1].info))
|
||||||
if f != nil:
|
addSon(result, copyTree(n[0]))
|
||||||
# BUGFIX: do not check for (f.kind in {skProc, skMethod, skIterator}) here
|
|
||||||
# This special node kind is to merge with the call handler in `semExpr`.
|
|
||||||
result = newNodeI(nkDotCall, n.info)
|
|
||||||
addSon(result, newIdentNode(i, n[1].info))
|
|
||||||
addSon(result, copyTree(n[0]))
|
|
||||||
else:
|
|
||||||
if not ContainsOrIncl(c.UnknownIdents, i.id):
|
|
||||||
LocalError(n.Info, errUndeclaredFieldX, i.s)
|
|
||||||
result = errorNode(c, n)
|
|
||||||
|
|
||||||
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
# this is difficult, because the '.' is used in many different contexts
|
# this is difficult, because the '.' is used in many different contexts
|
||||||
# in Nimrod. We first allow types in the semantic checking.
|
# in Nimrod. We first allow types in the semantic checking.
|
||||||
|
|
@ -1866,7 +1852,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
||||||
# check if it is an expression macro:
|
# check if it is an expression macro:
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
|
let mode = if nfDelegate in n.flags: {} else: {checkUndeclared}
|
||||||
|
var s = qualifiedLookup(c, n.sons[0], mode)
|
||||||
if s != nil:
|
if s != nil:
|
||||||
case s.kind
|
case s.kind
|
||||||
of skMacro:
|
of skMacro:
|
||||||
|
|
@ -1900,6 +1887,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
elif isSymChoice(n.sons[0]) or n[0].kind == nkBracketExpr and
|
elif isSymChoice(n.sons[0]) or n[0].kind == nkBracketExpr and
|
||||||
isSymChoice(n[0][0]):
|
isSymChoice(n[0][0]):
|
||||||
result = semDirectOp(c, n, flags)
|
result = semDirectOp(c, n, flags)
|
||||||
|
elif nfDelegate in n.flags:
|
||||||
|
result = semDirectOp(c, n, flags)
|
||||||
else:
|
else:
|
||||||
result = semIndirectOp(c, n, flags)
|
result = semIndirectOp(c, n, flags)
|
||||||
of nkWhen:
|
of nkWhen:
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||||
result.typ = getSysType(tyString)
|
result.typ = getSysType(tyString)
|
||||||
of mInstantiationInfo: result = semInstantiationInfo(c, n)
|
of mInstantiationInfo: result = semInstantiationInfo(c, n)
|
||||||
of mOrd: result = semOrd(c, n)
|
of mOrd: result = semOrd(c, n)
|
||||||
|
of mHigh: result = semLowHigh(c, n, mHigh)
|
||||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||||
of mNBindSym: result = semBindSym(c, n)
|
of mNBindSym: result = semBindSym(c, n)
|
||||||
of mLocals: result = semLocals(c, n)
|
of mLocals: result = semLocals(c, n)
|
||||||
|
|
|
||||||
|
|
@ -835,7 +835,14 @@ proc semProcAnnotation(c: PContext, prc: PNode): PNode =
|
||||||
var it = n.sons[i]
|
var it = n.sons[i]
|
||||||
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
|
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
|
||||||
let m = lookupMacro(c, key)
|
let m = lookupMacro(c, key)
|
||||||
if m == nil: continue
|
if m == nil:
|
||||||
|
if key.kind == nkIdent and key.ident.id == ord(wDelegator):
|
||||||
|
if considerAcc(prc.sons[namePos]).s == "()":
|
||||||
|
prc.sons[namePos] = newIdentNode(idDelegator, prc.info)
|
||||||
|
prc.sons[pragmasPos] = copyExcept(n, i)
|
||||||
|
else:
|
||||||
|
LocalError(prc.info, errOnlyACallOpCanBeDelegator)
|
||||||
|
continue
|
||||||
# we transform ``proc p {.m, rest.}`` into ``m(do: proc p {.rest.})`` and
|
# we transform ``proc p {.m, rest.}`` into ``m(do: proc p {.rest.})`` and
|
||||||
# let the semantic checker deal with it:
|
# let the semantic checker deal with it:
|
||||||
var x = newNodeI(nkCall, n.info)
|
var x = newNodeI(nkCall, n.info)
|
||||||
|
|
|
||||||
|
|
@ -608,7 +608,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
if genericParams.sons[i].sym.name.id == finalTypId.id:
|
if genericParams.sons[i].sym.name.id == finalTypId.id:
|
||||||
return genericParams.sons[i].typ
|
return genericParams.sons[i].typ
|
||||||
|
|
||||||
var s = newSym(skType, finalTypId, getCurrOwner(), info)
|
var s = newSym(skType, finalTypId, typeClass.sym, info)
|
||||||
if typId == nil: s.flags.incl(sfAnon)
|
if typId == nil: s.flags.incl(sfAnon)
|
||||||
s.linkTo(typeClass)
|
s.linkTo(typeClass)
|
||||||
s.position = genericParams.len
|
s.position = genericParams.len
|
||||||
|
|
|
||||||
|
|
@ -202,28 +202,6 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1): string =
|
||||||
add(result, argTypeToString(arg))
|
add(result, argTypeToString(arg))
|
||||||
if i != sonsLen(n) - 1: add(result, ", ")
|
if i != sonsLen(n) - 1: add(result, ", ")
|
||||||
|
|
||||||
proc NotFoundError*(c: PContext, n: PNode) =
|
|
||||||
# Gives a detailed error message; this is separated from semOverloadedCall,
|
|
||||||
# as semOverlodedCall is already pretty slow (and we need this information
|
|
||||||
# only in case of an error).
|
|
||||||
if c.InCompilesContext > 0:
|
|
||||||
# fail fast:
|
|
||||||
GlobalError(n.info, errTypeMismatch, "")
|
|
||||||
var result = msgKindToString(errTypeMismatch)
|
|
||||||
add(result, describeArgs(c, n))
|
|
||||||
add(result, ')')
|
|
||||||
var candidates = ""
|
|
||||||
var o: TOverloadIter
|
|
||||||
var sym = initOverloadIter(o, c, n.sons[0])
|
|
||||||
while sym != nil:
|
|
||||||
if sym.kind in RoutineKinds:
|
|
||||||
add(candidates, getProcHeader(sym))
|
|
||||||
add(candidates, "\n")
|
|
||||||
sym = nextOverloadIter(o, c, n.sons[0])
|
|
||||||
if candidates != "":
|
|
||||||
add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
|
|
||||||
LocalError(n.Info, errGenerated, result)
|
|
||||||
|
|
||||||
proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation
|
proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation
|
||||||
proc concreteType(c: TCandidate, t: PType): PType =
|
proc concreteType(c: TCandidate, t: PType): PType =
|
||||||
case t.kind
|
case t.kind
|
||||||
|
|
|
||||||
|
|
@ -442,6 +442,7 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
if t.len == 0: result = "typedesc"
|
if t.len == 0: result = "typedesc"
|
||||||
else: result = "typedesc[" & constraintsToStr(t) & "]"
|
else: result = "typedesc[" & constraintsToStr(t) & "]"
|
||||||
of tyTypeClass:
|
of tyTypeClass:
|
||||||
|
if t.n != nil: return t.sym.owner.name.s
|
||||||
case t.len
|
case t.len
|
||||||
of 0: result = "typeclass[]"
|
of 0: result = "typeclass[]"
|
||||||
of 1: result = "typeclass[" & consToStr(t.sons[0]) & "]"
|
of 1: result = "typeclass[" & consToStr(t.sons[0]) & "]"
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,8 @@ type
|
||||||
|
|
||||||
wDestroy,
|
wDestroy,
|
||||||
|
|
||||||
wImmediate, wDestructor, wImportCpp, wImportObjC,
|
wImmediate, wDestructor, wDelegator,
|
||||||
|
wImportCpp, wImportObjC,
|
||||||
wImportCompilerProc,
|
wImportCompilerProc,
|
||||||
wImportc, wExportc, wIncompleteStruct, wRequiresInit,
|
wImportc, wExportc, wIncompleteStruct, wRequiresInit,
|
||||||
wAlign, wNodecl, wPure, wSideeffect, wHeader,
|
wAlign, wNodecl, wPure, wSideeffect, wHeader,
|
||||||
|
|
@ -120,7 +121,8 @@ const
|
||||||
|
|
||||||
"destroy",
|
"destroy",
|
||||||
|
|
||||||
"immediate", "destructor", "importcpp", "importobjc",
|
"immediate", "destructor", "delegator",
|
||||||
|
"importcpp", "importobjc",
|
||||||
"importcompilerproc", "importc", "exportc", "incompletestruct",
|
"importcompilerproc", "importc", "exportc", "incompletestruct",
|
||||||
"requiresinit", "align", "nodecl", "pure", "sideeffect",
|
"requiresinit", "align", "nodecl", "pure", "sideeffect",
|
||||||
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",
|
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
discard """
|
discard """
|
||||||
file: "topaque.nim"
|
file: "topaque.nim"
|
||||||
line: 16
|
line: 16
|
||||||
errormsg: "undeclared field: \'buffer\'"
|
errormsg: "undeclared identifier: \'buffer\'"
|
||||||
"""
|
"""
|
||||||
# Test the new opaque types
|
# Test the new opaque types
|
||||||
|
|
||||||
import
|
import
|
||||||
mopaque
|
mopaque
|
||||||
|
|
||||||
var
|
var
|
||||||
L: TLexer
|
L: TLexer
|
||||||
|
|
||||||
L.filename = "ha"
|
L.filename = "ha"
|
||||||
L.line = 34
|
L.line = 34
|
||||||
L.buffer[0] = '\0' #ERROR_MSG undeclared field: 'buffer'
|
L.buffer[0] = '\0' #ERROR_MSG undeclared field: 'buffer'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue