added experimental .this pragma

This commit is contained in:
Andreas Rumpf 2016-02-28 03:17:20 +01:00
commit 1afdefcbe9
9 changed files with 192 additions and 117 deletions

View file

@ -298,6 +298,7 @@ const
sfWrittenTo* = sfBorrow # param is assigned to sfWrittenTo* = sfBorrow # param is assigned to
sfEscapes* = sfProcvar # param escapes sfEscapes* = sfProcvar # param escapes
sfBase* = sfDiscriminant sfBase* = sfDiscriminant
sfIsSelf* = sfOverriden # param is 'self'
const const
# getting ready for the future expr/stmt merge # getting ready for the future expr/stmt merge

View file

@ -635,7 +635,7 @@ proc reallySameIdent(a, b: string): bool {.inline.} =
else: else:
result = true result = true
proc strTableIncl*(t: var TStrTable, n: PSym): bool {.discardable.} = proc strTableIncl*(t: var TStrTable, n: PSym; onConflictKeepOld=false): bool {.discardable.} =
# returns true if n is already in the string table: # returns true if n is already in the string table:
# It is essential that `n` is written nevertheless! # It is essential that `n` is written nevertheless!
# This way the newest redefinition is picked by the semantic analyses! # This way the newest redefinition is picked by the semantic analyses!
@ -654,7 +654,8 @@ proc strTableIncl*(t: var TStrTable, n: PSym): bool {.discardable.} =
replaceSlot = h replaceSlot = h
h = nextTry(h, high(t.data)) h = nextTry(h, high(t.data))
if replaceSlot >= 0: if replaceSlot >= 0:
t.data[replaceSlot] = n # overwrite it with newer definition! if not onConflictKeepOld:
t.data[replaceSlot] = n # overwrite it with newer definition!
return true # found it return true # found it
elif mustRehash(len(t.data), t.counter): elif mustRehash(len(t.data), t.counter):
strTableEnlarge(t) strTableEnlarge(t)

View file

@ -46,7 +46,7 @@ const
wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated, wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto, wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
wInjectStmt, wDeprecated, wExperimental} wInjectStmt, wDeprecated, wExperimental, wThis}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame, wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
@ -875,6 +875,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
c.module.flags.incl sfExperimental c.module.flags.incl sfExperimental
else: else:
localError(it.info, "'experimental' pragma only valid as toplevel statement") localError(it.info, "'experimental' pragma only valid as toplevel statement")
of wThis:
if it.kind == nkExprColonExpr:
c.selfName = considerQuotedIdent(it[1])
else:
c.selfName = getIdent("self")
of wNoRewrite: of wNoRewrite:
noVal(it) noVal(it)
of wBase: of wBase:

View file

@ -39,7 +39,8 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
initialBinding: PNode, initialBinding: PNode,
filter: TSymKinds, filter: TSymKinds,
best, alt: var TCandidate, best, alt: var TCandidate,
errors: var CandidateErrors) = errors: var CandidateErrors;
fromUsingStmt: bool) =
var o: TOverloadIter var o: TOverloadIter
# thanks to the lazy semchecking for operands, we need to iterate over the # thanks to the lazy semchecking for operands, we need to iterate over the
# symbol table *before* any call to 'initCandidate' which might invoke # symbol table *before* any call to 'initCandidate' which might invoke
@ -50,7 +51,12 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
var syms: seq[tuple[a: PSym, b: int]] = @[] var syms: seq[tuple[a: PSym, b: int]] = @[]
while symx != nil: while symx != nil:
if symx.kind in filter: syms.add((symx, o.lastOverloadScope)) if symx.kind in filter:
if fromUsingStmt and (symx.typ.n.len <= 1 or
sfIsSelf notin symx.typ.n[1].sym.flags):
discard "only consider procs that have a 'self' too"
else:
syms.add((symx, o.lastOverloadScope))
symx = nextOverloadIter(o, c, headSymbol) symx = nextOverloadIter(o, c, headSymbol)
if syms.len == 0: return if syms.len == 0: return
@ -63,7 +69,6 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
let sym = syms[i][0] let sym = syms[i][0]
determineType(c, sym) determineType(c, sym)
initCandidate(c, z, sym, initialBinding, syms[i][1]) initCandidate(c, z, sym, initialBinding, syms[i][1])
z.calleeSym = sym
#if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140: #if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
# gDebug = true # gDebug = true
@ -156,28 +161,27 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
else: else:
initialBinding = nil initialBinding = nil
var usedSyms: seq[PNode] template pickBest(headSymbol, fromUsingStmt) =
template pickBest(headSymbol: expr) =
pickBestCandidate(c, headSymbol, n, orig, initialBinding, pickBestCandidate(c, headSymbol, n, orig, initialBinding,
filter, result, alt, errors) filter, result, alt, errors, fromUsingStmt)
gatherUsedSyms(c, usedSyms)
if usedSyms != nil:
var hiddenArg = if usedSyms.len > 1: newNode(nkClosedSymChoice, n.info, usedSyms)
else: usedSyms[0]
#gatherUsedSyms(c, usedSyms)
if c.p != nil and c.p.selfSym != nil:
# we need to enforce semchecking of selfSym again because it
# might need auto-deref:
var hiddenArg = newSymNode(c.p.selfSym)
hiddenArg.typ = nil
n.sons.insert(hiddenArg, 1) n.sons.insert(hiddenArg, 1)
orig.sons.insert(hiddenArg, 1) orig.sons.insert(hiddenArg, 1)
pickBest(f) pickBest(f, true)
if result.state != csMatch: if result.state != csMatch:
n.sons.delete(1) n.sons.delete(1)
orig.sons.delete(1) orig.sons.delete(1)
else: return else: return
pickBest(f) pickBest(f, false)
let overloadsState = result.state let overloadsState = result.state
if overloadsState != csMatch: if overloadsState != csMatch:
@ -194,7 +198,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
let op = newIdentNode(getIdent(x), n.info) let op = newIdentNode(getIdent(x), n.info)
n.sons[0] = op n.sons[0] = op
orig.sons[0] = op orig.sons[0] = op
pickBest(op) pickBest(op, false)
if nfExplicitCall in n.flags: if nfExplicitCall in n.flags:
tryOp ".()" tryOp ".()"
@ -209,7 +213,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
let callOp = newIdentNode(getIdent".=", n.info) let callOp = newIdentNode(getIdent".=", n.info)
n.sons[0..1] = [callOp, n[1], calleeName] n.sons[0..1] = [callOp, n[1], calleeName]
orig.sons[0..1] = [callOp, orig[1], calleeName] orig.sons[0..1] = [callOp, orig[1], calleeName]
pickBest(callOp) pickBest(callOp, false)
if overloadsState == csEmpty and result.state == csEmpty: if overloadsState == csEmpty and result.state == csEmpty:
if nfDotField in n.flags and nfExplicitCall notin n.flags: if nfDotField in n.flags and nfExplicitCall notin n.flags:
@ -228,7 +232,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
n.sons[0] = f n.sons[0] = f
errors = @[] errors = @[]
pickBest(f) pickBest(f, false)
#notFoundError(c, n, errors) #notFoundError(c, n, errors)
return return

View file

@ -30,6 +30,7 @@ type
# statements # statements
owner*: PSym # the symbol this context belongs to owner*: PSym # the symbol this context belongs to
resultSym*: PSym # the result symbol (if we are in a proc) resultSym*: PSym # the result symbol (if we are in a proc)
selfSym*: PSym # the 'self' symbol (if available)
nestedLoopCounter*: int # whether we are in a loop or not nestedLoopCounter*: int # whether we are in a loop or not
nestedBlockCounter*: int # whether we are in a block or not nestedBlockCounter*: int # whether we are in a block or not
inTryStmt*: int # whether we are in a try statement; works also inTryStmt*: int # whether we are in a try statement; works also
@ -103,7 +104,7 @@ type
inParallelStmt*: int inParallelStmt*: int
instTypeBoundOp*: proc (c: PContext; dc: PSym; t: PType; info: TLineInfo; instTypeBoundOp*: proc (c: PContext; dc: PSym; t: PType; info: TLineInfo;
op: TTypeAttachedOp): PSym {.nimcall.} op: TTypeAttachedOp): PSym {.nimcall.}
selfName*: PIdent
proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair = proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
result.genericSym = s result.genericSym = s
@ -154,16 +155,6 @@ proc popOwner() =
proc lastOptionEntry(c: PContext): POptionEntry = proc lastOptionEntry(c: PContext): POptionEntry =
result = POptionEntry(c.optionStack.tail) result = POptionEntry(c.optionStack.tail)
proc pushProcCon*(c: PContext, owner: PSym) {.inline.} =
if owner == nil:
internalError("owner is nil")
return
var x: PProcCon
new(x)
x.owner = owner
x.next = c.p
c.p = x
proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next
proc newOptionEntry(): POptionEntry = proc newOptionEntry(): POptionEntry =

View file

@ -77,88 +77,6 @@ proc inlineConst(n: PNode, s: PSym): PNode {.inline.} =
result.typ = s.typ result.typ = s.typ
result.info = n.info result.info = n.info
proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
case s.kind
of skConst:
markUsed(n.info, s)
styleCheckUse(n.info, s)
case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind
of tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
tyTuple, tySet, tyUInt..tyUInt64:
if s.magic == mNone: result = inlineConst(n, s)
else: result = newSymNode(s, n.info)
of tyArrayConstr, tySequence:
# Consider::
# const x = []
# proc p(a: openarray[int])
# proc q(a: openarray[char])
# p(x)
# q(x)
#
# It is clear that ``[]`` means two totally different things. Thus, we
# copy `x`'s AST into each context, so that the type fixup phase can
# deal with two different ``[]``.
if s.ast.len == 0: result = inlineConst(n, s)
else: result = newSymNode(s, n.info)
else:
result = newSymNode(s, n.info)
of skMacro: result = semMacroExpr(c, n, n, s, flags)
of skTemplate: result = semTemplateExpr(c, n, s, flags)
of skParam:
markUsed(n.info, s)
styleCheckUse(n.info, s)
if s.typ.kind == tyStatic and s.typ.n != nil:
# XXX see the hack in sigmatch.nim ...
return s.typ.n
elif sfGenSym in s.flags:
if c.p.wasForwarded:
# gensym'ed parameters that nevertheless have been forward declared
# need a special fixup:
let realParam = c.p.owner.typ.n[s.position+1]
internalAssert realParam.kind == nkSym and realParam.sym.kind == skParam
return newSymNode(c.p.owner.typ.n[s.position+1].sym, n.info)
elif c.p.owner.kind == skMacro:
# gensym'ed macro parameters need a similar hack (see bug #1944):
var u = searchInScopes(c, s.name)
internalAssert u != nil and u.kind == skParam and u.owner == s.owner
return newSymNode(u, n.info)
result = newSymNode(s, n.info)
of skVar, skLet, skResult, skForVar:
if s.magic == mNimvm:
localError(n.info, "illegal context for 'nimvm' magic")
markUsed(n.info, s)
styleCheckUse(n.info, s)
# if a proc accesses a global variable, it is not side effect free:
if sfGlobal in s.flags:
incl(c.p.owner.flags, sfSideEffect)
result = newSymNode(s, n.info)
# We cannot check for access to outer vars for example because it's still
# not sure the symbol really ends up being used:
# var len = 0 # but won't be called
# genericThatUsesLen(x) # marked as taking a closure?
of skGenericParam:
styleCheckUse(n.info, s)
if s.typ.kind == tyStatic:
result = newSymNode(s, n.info)
result.typ = s.typ
elif s.ast != nil:
result = semExpr(c, s.ast)
else:
n.typ = s.typ
return n
of skType:
markUsed(n.info, s)
styleCheckUse(n.info, s)
if s.typ.kind == tyStatic and s.typ.n != nil:
return s.typ.n
result = newSymNode(s, n.info)
result.typ = makeTypeDesc(c, s.typ)
else:
markUsed(n.info, s)
styleCheckUse(n.info, s)
result = newSymNode(s, n.info)
type type
TConvStatus = enum TConvStatus = enum
convOK, convOK,
@ -1015,6 +933,116 @@ proc readTypeParameter(c: PContext, typ: PType,
return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info) return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
#echo "came here: returned nil" #echo "came here: returned nil"
proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
case s.kind
of skConst:
markUsed(n.info, s)
styleCheckUse(n.info, s)
case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind
of tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
tyTuple, tySet, tyUInt..tyUInt64:
if s.magic == mNone: result = inlineConst(n, s)
else: result = newSymNode(s, n.info)
of tyArrayConstr, tySequence:
# Consider::
# const x = []
# proc p(a: openarray[int])
# proc q(a: openarray[char])
# p(x)
# q(x)
#
# It is clear that ``[]`` means two totally different things. Thus, we
# copy `x`'s AST into each context, so that the type fixup phase can
# deal with two different ``[]``.
if s.ast.len == 0: result = inlineConst(n, s)
else: result = newSymNode(s, n.info)
else:
result = newSymNode(s, n.info)
of skMacro: result = semMacroExpr(c, n, n, s, flags)
of skTemplate: result = semTemplateExpr(c, n, s, flags)
of skParam:
markUsed(n.info, s)
styleCheckUse(n.info, s)
if s.typ.kind == tyStatic and s.typ.n != nil:
# XXX see the hack in sigmatch.nim ...
return s.typ.n
elif sfGenSym in s.flags:
if c.p.wasForwarded:
# gensym'ed parameters that nevertheless have been forward declared
# need a special fixup:
let realParam = c.p.owner.typ.n[s.position+1]
internalAssert realParam.kind == nkSym and realParam.sym.kind == skParam
return newSymNode(c.p.owner.typ.n[s.position+1].sym, n.info)
elif c.p.owner.kind == skMacro:
# gensym'ed macro parameters need a similar hack (see bug #1944):
var u = searchInScopes(c, s.name)
internalAssert u != nil and u.kind == skParam and u.owner == s.owner
return newSymNode(u, n.info)
result = newSymNode(s, n.info)
of skVar, skLet, skResult, skForVar:
if s.magic == mNimvm:
localError(n.info, "illegal context for 'nimvm' magic")
markUsed(n.info, s)
styleCheckUse(n.info, s)
# if a proc accesses a global variable, it is not side effect free:
if sfGlobal in s.flags:
incl(c.p.owner.flags, sfSideEffect)
result = newSymNode(s, n.info)
# We cannot check for access to outer vars for example because it's still
# not sure the symbol really ends up being used:
# var len = 0 # but won't be called
# genericThatUsesLen(x) # marked as taking a closure?
of skGenericParam:
styleCheckUse(n.info, s)
if s.typ.kind == tyStatic:
result = newSymNode(s, n.info)
result.typ = s.typ
elif s.ast != nil:
result = semExpr(c, s.ast)
else:
n.typ = s.typ
return n
of skType:
markUsed(n.info, s)
styleCheckUse(n.info, s)
if s.typ.kind == tyStatic and s.typ.n != nil:
return s.typ.n
result = newSymNode(s, n.info)
result.typ = makeTypeDesc(c, s.typ)
of skField:
if c.p != nil and c.p.selfSym != nil:
var ty = skipTypes(c.p.selfSym.typ, {tyGenericInst, tyVar, tyPtr, tyRef})
while tfBorrowDot in ty.flags: ty = ty.skipTypes({tyDistinct})
var check: PNode = nil
if ty.kind == tyObject:
while true:
check = nil
let f = lookupInRecordAndBuildCheck(c, n, ty.n, s.name, check)
if f != nil and fieldVisible(c, f):
# is the access to a public field or in the same module or in a friend?
doAssert f == s
markUsed(n.info, f)
styleCheckUse(n.info, f)
result = newNodeIT(nkDotExpr, n.info, f.typ)
result.add makeDeref(newSymNode(c.p.selfSym))
result.add newSymNode(f) # we now have the correct field
if check != nil:
check.sons[0] = result
check.typ = result.typ
result = check
return result
if ty.sons[0] == nil: break
ty = skipTypes(ty.sons[0], {tyGenericInst})
# old code, not sure if it's live code:
markUsed(n.info, s)
styleCheckUse(n.info, s)
result = newSymNode(s, n.info)
else:
markUsed(n.info, s)
styleCheckUse(n.info, s)
result = newSymNode(s, n.info)
proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
## returns nil if it's not a built-in field access ## returns nil if it's not a built-in field access
checkSonsLen(n, 2) checkSonsLen(n, 2)

View file

@ -10,6 +10,47 @@
# This module implements the instantiation of generic procs. # This module implements the instantiation of generic procs.
# included from sem.nim # included from sem.nim
proc addObjFieldsToLocalScope(c: PContext; n: PNode) =
template rec(n) = addObjFieldsToLocalScope(c, n)
case n.kind
of nkRecList:
for i in countup(0, len(n)-1):
rec n[i]
of nkRecCase:
if n.len > 0: rec n.sons[0]
for i in countup(1, len(n)-1):
if n[i].kind in {nkOfBranch, nkElse}: rec lastSon(n[i])
of nkSym:
let f = n.sym
if f.kind == skField and fieldVisible(c, f):
c.currentScope.symbols.strTableIncl(f, onConflictKeepOld=true)
incl(f.flags, sfUsed)
# it is not an error to shadow fields via parameters
else: discard
proc rawPushProcCon(c: PContext, owner: PSym) =
var x: PProcCon
new(x)
x.owner = owner
x.next = c.p
c.p = x
proc rawHandleSelf(c: PContext; owner: PSym) =
if c.selfName != nil and owner.kind in {skProc, skMethod, skConverter, skIterator, skMacro} and owner.typ != nil:
let params = owner.typ.n
if params.len > 1:
let arg = params[1].sym
if arg.name.id == c.selfName.id:
c.p.selfSym = arg
arg.flags.incl sfIsSelf
let t = c.p.selfSym.typ.skipTypes(abstractPtrs)
if t.kind == tyObject:
addObjFieldsToLocalScope(c, t.n)
proc pushProcCon*(c: PContext; owner: PSym) =
rawPushProcCon(c, owner)
rawHandleSelf(c, owner)
iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym = iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym =
internalAssert n.kind == nkGenericParams internalAssert n.kind == nkGenericParams
for i, a in n.pairs: for i, a in n.pairs:
@ -248,7 +289,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
addDecl(c, s) addDecl(c, s)
entry.concreteTypes[i] = s.typ entry.concreteTypes[i] = s.typ
inc i inc i
pushProcCon(c, result) rawPushProcCon(c, result)
instantiateProcType(c, pt, result, info) instantiateProcType(c, pt, result, info)
for j in 1 .. result.typ.len-1: for j in 1 .. result.typ.len-1:
entry.concreteTypes[i] = result.typ.sons[j] entry.concreteTypes[i] = result.typ.sons[j]
@ -263,6 +304,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
# a ``compiles`` context but this is the lesser evil. See # a ``compiles`` context but this is the lesser evil. See
# bug #1055 (tevilcompiles). # bug #1055 (tevilcompiles).
#if c.compilesContextId == 0: #if c.compilesContextId == 0:
rawHandleSelf(c, result)
entry.compilesId = c.compilesContextId entry.compilesId = c.compilesContextId
fn.procInstCache.safeAdd(entry) fn.procInstCache.safeAdd(entry)
c.generics.add(makeInstPair(fn, entry)) c.generics.add(makeInstPair(fn, entry))

View file

@ -1206,9 +1206,10 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
# Macros and Templates can have generic parameters, but they are # Macros and Templates can have generic parameters, but they are
# only used for overload resolution (there is no instantiation of # only used for overload resolution (there is no instantiation of
# the symbol, so we must process the body now) # the symbol, so we must process the body now)
pushProcCon(c, s)
if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics: if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
if not usePseudoGenerics: paramsTypeCheck(c, s.typ) if not usePseudoGenerics: paramsTypeCheck(c, s.typ)
pushProcCon(c, s)
c.p.wasForwarded = proto != nil c.p.wasForwarded = proto != nil
maybeAddResult(c, s, n) maybeAddResult(c, s, n)
if sfImportc notin s.flags: if sfImportc notin s.flags:
@ -1217,7 +1218,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
# unfortunately we cannot skip this step when in 'system.compiles' # unfortunately we cannot skip this step when in 'system.compiles'
# context as it may even be evaluated in 'system.compiles': # context as it may even be evaluated in 'system.compiles':
n.sons[bodyPos] = transformBody(c.module, semBody, s) n.sons[bodyPos] = transformBody(c.module, semBody, s)
popProcCon(c)
else: else:
if s.typ.sons[0] != nil and kind != skIterator: if s.typ.sons[0] != nil and kind != skIterator:
addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info)) addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info))
@ -1228,6 +1228,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if sfImportc in s.flags: if sfImportc in s.flags:
# so we just ignore the body after semantic checking for importc: # so we just ignore the body after semantic checking for importc:
n.sons[bodyPos] = ast.emptyNode n.sons[bodyPos] = ast.emptyNode
popProcCon(c)
else: else:
if proto != nil: localError(n.info, errImplOfXexpected, proto.name.s) if proto != nil: localError(n.info, errImplOfXexpected, proto.name.s)
if {sfImportc, sfBorrow} * s.flags == {} and s.magic == mNone: if {sfImportc, sfBorrow} * s.flags == {} and s.magic == mNone:

View file

@ -37,6 +37,7 @@ type
# is this a top-level symbol or a nested proc? # is this a top-level symbol or a nested proc?
call*: PNode # modified call call*: PNode # modified call
bindings*: TIdTable # maps types to types bindings*: TIdTable # maps types to types
magic*: TMagic # magic of operation
baseTypeMatch: bool # needed for conversions from T to openarray[T] baseTypeMatch: bool # needed for conversions from T to openarray[T]
# for example # for example
fauxMatch*: TTypeKind # the match was successful only due to the use fauxMatch*: TTypeKind # the match was successful only due to the use
@ -114,6 +115,7 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
c.calleeScope = 1 c.calleeScope = 1
else: else:
c.calleeScope = calleeScope c.calleeScope = calleeScope
c.magic = c.calleeSym.magic
initIdTable(c.bindings) initIdTable(c.bindings)
c.errors = nil c.errors = nil
if binding != nil and callee.kind in routineKinds: if binding != nil and callee.kind in routineKinds:
@ -1691,7 +1693,7 @@ proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
matchesAux(c, n, nOrig, m, marker) matchesAux(c, n, nOrig, m, marker)
proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) = proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
if m.calleeSym != nil and m.calleeSym.magic in {mArrGet, mArrPut}: if m.magic in {mArrGet, mArrPut}:
m.state = csMatch m.state = csMatch
m.call = n m.call = n
return return