bootstraps fine with overloadable templates

This commit is contained in:
Zahary Karadjov
2011-12-15 18:39:44 +02:00
parent 1d8ff40f56
commit e5bd3b5b97
14 changed files with 230 additions and 143 deletions

View File

@@ -225,6 +225,9 @@ type
sfInnerProc, # proc is an inner proc
sfThread, # proc will run as a thread
# variable is a thread variable
sfInline # forced-inline procs
sfImmediate, # macro or template is immediately expanded without
# considering any possible overloads
sfCompileTime, # proc can be evaluated at compile time
sfMerge, # proc can be merged with itself
sfDeadCodeElim, # dead code elimination for the module is turned on
@@ -570,7 +573,8 @@ type
# the poor naming choices in the standard library.
const
OverloadableSyms* = {skProc, skMethod, skIterator, skConverter, skModule}
OverloadableSyms* = {skProc, skMethod, skIterator, skConverter,
skModule, skTemplate, skMacro}
GenericTypes*: TTypeKinds = {tyGenericInvokation, tyGenericBody,
tyGenericParam}
@@ -918,6 +922,12 @@ proc delSon(father: PNode, idx: int) =
for i in countup(idx, length - 2): father.sons[i] = father.sons[i + 1]
setlen(father.sons, length - 1)
proc hasSons*(n: PNode): bool {.inline.} =
result = n.kind notin { nkCharLit..nkInt64Lit,
nkFloatLit..nkFloat64Lit,
nkStrLit..nkTripleStrLit,
nkSym, nkIdent }
proc copyNode(src: PNode): PNode =
# does not copy its sons!
if src == nil:
@@ -949,6 +959,18 @@ proc shallowCopy*(src: PNode): PNode =
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
else: newSeq(result.sons, sonsLen(src))
proc copySons*(src: PNode): Pnode =
# copies a node and its immediate sons
if src == nil: return nil
assert src.hasSons
result = newNode(src.kind)
result.info = src.info
result.typ = src.typ
result.flags = src.flags * PersistentNodeFlags
newSeq(result.sons, src.len)
for i in countup(0, src.len - 1):
result.sons[i] = src.sons[i]
proc copyTree(src: PNode): PNode =
# copy a whole syntax tree; performs deep copying
if src == nil:

View File

@@ -10,7 +10,8 @@
proc leftAppearsOnRightSide(le, ri: PNode): bool =
if le != nil:
for i in 1 .. <ri.len:
if le.isPartOf(ri[i]) != arNo: return true
let r = ri[i]
if isPartOf(le, r) != arNo: return true
proc hasNoInit(call: PNode): bool {.inline.} =
result = call.sons[0].kind == nkSym and sfNoInit in call.sons[0].sym.flags

View File

@@ -26,8 +26,9 @@ const
wNoStackFrame, wError, wDiscardable, wNoInit}
converterPragmas* = procPragmas
methodPragmas* = procPragmas
macroPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wMagic, wNosideEffect, wCompilerProc, wDeprecated, wExtern,
templatePragmas* = {wImmediate}
macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
wNodecl, wMagic, wNosideEffect, wCompilerProc, wDeprecated, wExtern,
wImportcpp, wImportobjc, wError, wDiscardable}
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideEffect, wSideEffect,
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
@@ -450,6 +451,9 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
of wImportCompilerProc:
processImportCompilerProc(sym, getOptionalStr(c, it, sym.name.s))
of wExtern: setExternName(sym, expectStrLit(c, it))
of wImmediate:
if sym.kind notin {skTemplate, skMacro}: invalidPragma(it)
incl(sym.flags, sfImmediate)
of wImportCpp:
processImportCpp(sym, getOptionalStr(c, it, sym.name.s))
of wImportObjC:

View File

@@ -10,11 +10,11 @@
# This module implements the semantic checking pass.
import
strutils, hashes, lists, options, lexer, ast, astalgo, trees, treetab,
ast, strutils, hashes, lists, options, lexer, astalgo, trees, treetab,
wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math,
magicsys, parser, nversion, semdata, nimsets, semfold, importer,
procfind, lookups, rodread, pragmas, passes, semtypinst, sigmatch, suggest,
semthreads, intsets, transf, evals, idgen, aliases
magicsys, parser, nversion, nimsets, semfold, importer,
procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch,
suggest, semthreads, intsets, transf, evals, idgen, aliases
proc semPass*(): TPass
# implementation
@@ -75,24 +75,27 @@ proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
include semtempl
proc semConstExpr(c: PContext, n: PNode): PNode =
var e = semExprWithType(c, n)
if e == nil:
GlobalError(n.info, errConstExprExpected)
return nil
proc evalTypedExpr(c: PContext, e: PNode): PNode =
result = getConstExpr(c.module, e)
if result == nil:
result = evalConstExpr(c.module, e)
if result == nil or result.kind == nkEmpty:
GlobalError(n.info, errConstExprExpected)
if result == nil or result.kind == nkEmpty:
GlobalError(e.info, errConstExprExpected)
when false:
result = semExprWithType(c, n)
if result == nil:
if result == nil:
GlobalError(n.info, errConstExprExpected)
return
result = getConstExpr(c.module, result)
if result == nil: GlobalError(n.info, errConstExprExpected)
proc semConstExpr(c: PContext, n: PNode): PNode =
var e = semExprWithType(c, n)
if e == nil:
GlobalError(n.info, errConstExprExpected)
return nil
result = evalTypedExpr(c, e)
proc semAndEvalConstExpr(c: PContext, n: PNode): PNode =
result = semConstExpr(c, n)

View File

@@ -8,6 +8,7 @@
#
## This module implements semantic checking for calls.
# included from sem.nim
proc sameMethodDispatcher(a, b: PSym): bool =
result = false
@@ -17,70 +18,77 @@ proc sameMethodDispatcher(a, b: PSym): bool =
if aa.kind == nkSym and bb.kind == nkSym and aa.sym == bb.sym:
result = true
proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds,
initialBinding: PNode): PNode =
var
o: TOverloadIter
x, y, z: TCandidate
#Message(n.info, warnUser, renderTree(n))
var sym = initOverloadIter(o, c, f)
result = nil
if sym == nil: return
initCandidate(x, sym, initialBinding)
initCandidate(y, sym, initialBinding)
while sym != nil:
if sym.kind in filter:
initCandidate(z, sym, initialBinding)
z.calleeSym = sym
matches(c, n, z)
if z.state == csMatch:
# little hack so that iterators are preferred over everything else:
if sym.kind == skIterator: inc(z.exactMatches, 200)
case x.state
of csEmpty, csNoMatch: x = z
of csMatch:
var cmp = cmpCandidates(x, z)
if cmp < 0: x = z # z is better than x
elif cmp == 0: y = z # z is as good as x
else: nil
sym = nextOverloadIter(o, c, f)
if x.state == csEmpty:
# no overloaded proc found
# do not generate an error yet; the semantic checking will check for
# an overloaded () operator
elif y.state == csMatch and cmpCandidates(x, y) == 0 and
not sameMethodDispatcher(x.calleeSym, y.calleeSym):
if x.state != csMatch:
InternalError(n.info, "x.state is not csMatch")
LocalError(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
getProcHeader(x.calleeSym), getProcHeader(y.calleeSym),
x.calleeSym.Name.s])
else:
# only one valid interpretation found:
markUsed(n, x.calleeSym)
if x.calleeSym.ast == nil:
internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
if x.calleeSym.ast.sons[genericParamsPos].kind != nkEmpty:
# a generic proc!
x.calleeSym = generateInstance(c, x.calleeSym, x.bindings, n.info)
x.callee = x.calleeSym.typ
result = x.call
result.sons[0] = newSymNode(x.calleeSym)
result.typ = x.callee.sons[0]
proc semDirectCall(c: PContext, n: PNode, filter: TSymKinds): PNode =
# process the bindings once:
proc resolveOverloads(c: PContext, n, orig: PNode,
filter: TSymKinds): TCandidate =
var initialBinding: PNode
var f = n.sons[0]
if f.kind == nkBracketExpr:
# fill in the bindings:
initialBinding = f
f = f.sons[0]
else:
else:
initialBinding = nil
result = semDirectCallWithBinding(c, n, f, filter, initialBinding)
var
o: TOverloadIter
alt, z: TCandidate
template best: expr = result
#Message(n.info, warnUser, renderTree(n))
var sym = initOverloadIter(o, c, f)
if sym == nil: return
initCandidate(best, sym, initialBinding)
initCandidate(alt, sym, initialBinding)
while sym != nil:
if sym.kind in filter:
initCandidate(z, sym, initialBinding)
z.calleeSym = sym
matches(c, n, orig, z)
if z.state == csMatch:
# little hack so that iterators are preferred over everything else:
if sym.kind == skIterator: inc(z.exactMatches, 200)
case best.state
of csEmpty, csNoMatch: best = z
of csMatch:
var cmp = cmpCandidates(best, z)
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
else: nil
sym = nextOverloadIter(o, c, f)
if best.state == csEmpty:
# no overloaded proc found
# do not generate an error yet; the semantic checking will check for
# an overloaded () operator
elif alt.state == csMatch and cmpCandidates(best, alt) == 0 and
not sameMethodDispatcher(best.calleeSym, alt.calleeSym):
if best.state != csMatch:
InternalError(n.info, "x.state is not csMatch")
LocalError(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
getProcHeader(best.calleeSym), getProcHeader(alt.calleeSym),
best.calleeSym.Name.s])
proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
assert x.state == csMatch
var finalCallee = x.calleeSym
markUsed(n, finalCallee)
if finalCallee.ast == nil:
internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty:
# a generic proc!
finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
result = x.call
result.sons[0] = newSymNode(finalCallee)
result.typ = finalCallee.typ.sons[0]
proc semOverloadedCall(c: PContext, n, nOrig: PNode,
filter: TSymKinds): PNode =
var r = resolveOverloads(c, n, nOrig, filter)
if r.state == csMatch: result = semResolvedCall(c, n, r)
proc explicitGenericInstError(n: PNode): PNode =
LocalError(n.info, errCannotInstantiateX, renderTree(n))
result = n

View File

@@ -73,7 +73,7 @@ type
userPragmas*: TStrTable
evalContext*: PEvalContext
slurpedFiles*: seq[string]
var
gGenericsCache: PGenericsCache # save for modularity

View File

@@ -8,6 +8,7 @@
#
# this module does the semantic checking for expressions
# included from sem.nim
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode =
markUsed(n, s)
@@ -103,7 +104,8 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
if s.ast == nil: InternalError(n.info, "no default for")
result = semExpr(c, s.ast)
of skType:
if efAllowType notin flags: GlobalError(n.info, errATypeHasNoValue)
if efAllowType notin flags:
GlobalError(n.info, errATypeHasNoValue)
markUsed(n, s)
result = newSymNode(s, n.info)
else:
@@ -245,17 +247,31 @@ proc semIs(c: PContext, n: PNode): PNode =
else:
GlobalError(n.info, errXExpectsTwoArguments, "is")
proc semOpAux(c: PContext, n: PNode) =
for i in countup(1, sonsLen(n) - 1):
proc semOpAux2(c: PContext, n: PNode): PNode =
result = n.shallowCopy
result.sons[0] = n.sons[0]
for i in countup(1, n.len - 1):
let a = n.sons[i]
if a.kind == nkExprEqExpr and a.len == 2:
var arg = a.shallowCopy
arg.sons[0] = newIdentNode(considerAcc(a.sons[0]), a.sons[0].info)
arg.sons[1] = semExprWithType(c, a.sons[1])
arg.typ = a.sons[1].typ
result.sons[i] = arg
else:
result.sons[i] = semExprWithType(c, a)
proc semOpAux(c: PContext, n: PNode) =
for i in countup(1, sonsLen(n) - 1):
var a = n.sons[i]
if a.kind == nkExprEqExpr and sonsLen(a) == 2:
var info = a.sons[0].info
a.sons[0] = newIdentNode(considerAcc(a.sons[0]), info)
a.sons[1] = semExprWithType(c, a.sons[1])
a.sons[1] = semExprWithType(c, a.sons[1], {efAllowType})
a.typ = a.sons[1].typ
else:
n.sons[i] = semExprWithType(c, a)
else:
n.sons[i] = semExprWithType(c, a, {efAllowType})
proc overloadedCallOpr(c: PContext, n: PNode): PNode =
# quick check if there is *any* () operator overloaded:
var par = getIdent("()")
@@ -475,25 +491,32 @@ proc expectStringArg(c: PContext, n: PNode, i: int): PNode =
include semmagic
proc semDirectCallAnalyseEffects(c: PContext, n: PNode,
flags: TExprFlags): PNode =
proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, orig: PNode,
flags: TExprFlags): PNode =
if efWantIterator in flags:
result = semDirectCall(c, n, {skIterator})
result = semOverloadedCall(c, n, orig, {skIterator})
elif efInTypeOf in flags:
# for ``type(countup(1,3))``, see ``tests/ttoseq``.
result = semDirectCall(c, n, {skIterator, skProc, skMethod, skConverter})
result = semOverloadedCall(c, n, orig, {skIterator, skProc, skMethod, skConverter, skMacro, skTemplate})
else:
result = semDirectCall(c, n, {skProc, skMethod, skConverter})
result = semOverloadedCall(c, n, orig, {skProc, skMethod, skConverter, skMacro, skTemplate})
if result != nil:
if result.sons[0].kind != nkSym:
InternalError("semDirectCallAnalyseEffects")
var callee = result.sons[0].sym
if (callee.kind == skIterator) and (callee.id == c.p.owner.id):
GlobalError(n.info, errRecursiveDependencyX, callee.name.s)
if sfNoSideEffect notin callee.flags:
if {sfImportc, sfSideEffect} * callee.flags != {}:
incl(c.p.owner.flags, sfSideEffect)
let callee = result.sons[0].sym
case callee.kind
of skMacro, skTemplate: nil
else:
if (callee.kind == skIterator) and (callee.id == c.p.owner.id):
GlobalError(n.info, errRecursiveDependencyX, callee.name.s)
if sfNoSideEffect notin callee.flags:
if {sfImportc, sfSideEffect} * callee.flags != {}:
incl(c.p.owner.flags, sfSideEffect)
proc semDirectCallAnalyseEffects(c: PContext, n: PNode, orig: PNode,
flags: TExprFlags): PNode =
result = semOverloadedCallAnalyseEffects(c, n, orig, flags)
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = nil
var prc = n.sons[0]
@@ -509,13 +532,14 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
return semExpr(c, result, flags)
else:
n.sons[0] = semExpr(c, n.sons[0])
let orig = n.copySons
semOpAux(c, n)
var t: PType = nil
if (n.sons[0].typ != nil): t = skipTypes(n.sons[0].typ, abstractInst)
if (t != nil) and (t.kind == tyProc):
var m: TCandidate
initCandidate(m, t)
matches(c, n, m)
matches(c, n, orig, m)
if m.state != csMatch:
var msg = msgKindToString(errTypeMismatch)
for i in countup(1, sonsLen(n) - 1):
@@ -536,7 +560,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
# the old ``prc`` (which is likely an nkIdent) has to be restored:
if result == nil:
n.sons[0] = prc
result = semDirectCallAnalyseEffects(c, n, flags)
result = semOverloadedCallAnalyseEffects(c, n, orig, flags)
if result == nil:
GlobalError(n.info, errExprXCannotBeCalled,
renderTree(n, {renderNoComments}))
@@ -547,15 +571,21 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
# this seems to be a hotspot in the compiler!
let nOrig = n.copySons
semOpAux(c, n)
result = semDirectCallAnalyseEffects(c, n, flags)
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
if result == nil:
result = overloadedCallOpr(c, n)
if result == nil: GlobalError(n.Info, errGenerated, getNotFoundError(c, n))
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
if result.sons[0].sym.magic != mNone:
result = magicsAfterOverloadResolution(c, result, flags)
let callee = result.sons[0].sym
case callee.kind
of skMacro: result = semMacroExpr(c, nOrig, callee)
of skTemplate: result = semTemplateExpr(c, nOrig, callee)
else:
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
if callee.magic != mNone:
result = magicsAfterOverloadResolution(c, result, flags)
proc buildStringify(c: PContext, arg: PNode): PNode =
if arg.typ != nil and skipTypes(arg.typ, abstractInst).kind == tyString:
@@ -693,7 +723,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
result.typ = ty
markUsed(n, f)
return
elif efAllowType notin flags:
elif efAllowType notin flags:
GlobalError(n.sons[0].info, errATypeHasNoValue)
return
# reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
@@ -820,7 +850,11 @@ proc propertyWriteAccess(c: PContext, n, a: PNode): PNode =
# nodes?
addSon(result, a[0])
addSon(result, semExpr(c, n[1]))
result = semDirectCallAnalyseEffects(c, result, {})
# XXX: @@ Revisit this
var orig = newNodeI(nkCall, n.info)
orig.addSon(a[0])
orig.addSon(n[1])
result = semDirectCallAnalyseEffects(c, result, result, {})
if result != nil:
fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result)
@@ -1234,8 +1268,18 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
if s != nil:
case s.kind
of skMacro: result = semMacroExpr(c, n, s)
of skTemplate: result = semTemplateExpr(c, n, s)
of skMacro:
echo c.filename
if c.filename.endsWith("hello.nim") and sfImmediate notin s.flags:
result = semDirectOp(c, n, flags)
else:
result = semMacroExpr(c, n, s)
of skTemplate:
var hello = c.filename.endsWith("hello.nim")
if sfImmediate notin s.flags:
result = semDirectOp(c, n, flags)
else:
result = semTemplateExpr(c, n, s)
of skType:
# XXX think about this more (``set`` procs)
if n.len == 2:

View File

@@ -168,8 +168,8 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
pushOwner(s)
openScope(c.tab)
n.sons[namePos] = newSymNode(s) # check that no pragmas exist:
if n.sons[pragmasPos].kind != nkEmpty:
LocalError(n.info, errNoPragmasAllowedForX, "template")
if n.sons[pragmasPos].kind != nkEmpty:
pragma(c, s, n.sons[pragmasPos], templatePragmas)
# check that no generic parameters exist:
if n.sons[genericParamsPos].kind != nkEmpty:
LocalError(n.info, errNoGenericParamsAllowedForX, "template")

View File

@@ -8,6 +8,7 @@
#
# this module does the semantic checking of type declarations
# included from sem.nim
proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
if prev == nil:

View File

@@ -17,6 +17,7 @@ import
type
TCandidateState* = enum
csEmpty, csMatch, csNoMatch
TCandidate* {.final.} = object
exactMatches*: int
subtypeMatches: int
@@ -35,7 +36,7 @@ type
isNone, isConvertible, isIntConv, isSubtype,
isGeneric,
isEqual
proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} =
c.exactMatches = 0
c.subtypeMatches = 0
@@ -101,10 +102,10 @@ proc writeMatches(c: TCandidate) =
Writeln(stdout, "intconv matches: " & $c.intConvMatches)
Writeln(stdout, "generic matches: " & $c.genericMatches)
proc getNotFoundError*(c: PContext, n: PNode): string =
# Gives a detailed error message; this is separated from semDirectCall,
# as semDirectCall is already pretty slow (and we need this information only
# in case of an error).
proc getNotFoundError*(c: PContext, n: PNode): string =
# 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).
result = msgKindToString(errTypeMismatch)
for i in countup(1, sonsLen(n) - 1):
#debug(n.sons[i].typ)
@@ -507,7 +508,10 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
return
proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
arg: PNode): PNode =
arg, argOrig: PNode): PNode =
if m.calleeSym != nil and m.calleeSym.kind in {skMacro, skTemplate} and
f.kind in {tyExpr, tyStmt, tyTypeDesc}:
return argOrig
var r = typeRel(m.bindings, f, a)
case r
of isConvertible:
@@ -547,9 +551,9 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
result = userConvMatch(c, m, base(f), a, arg)
proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType,
arg: PNode): PNode =
arg, argOrig: PNode): PNode =
if arg == nil or arg.kind != nkSymChoice:
result = ParamTypesMatchAux(c, m, f, a, arg)
result = ParamTypesMatchAux(c, m, f, a, arg, argOrig)
else:
# CAUTION: The order depends on the used hashing scheme. Thus it is
# incorrect to simply use the first fitting match. However, to implement
@@ -591,29 +595,29 @@ proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType,
else:
# only one valid interpretation found:
markUsed(arg, arg.sons[best].sym)
result = ParamTypesMatchAux(c, m, f, arg.sons[best].typ, arg.sons[best])
result = ParamTypesMatchAux(c, m, f, arg.sons[best].typ, arg.sons[best], argOrig)
proc IndexTypesMatch*(c: PContext, f, a: PType, arg: PNode): PNode =
var m: TCandidate
initCandidate(m, f)
result = paramTypesMatch(c, m, f, a, arg)
result = paramTypesMatch(c, m, f, a, arg, nil)
proc ConvertTo*(c: PContext, f: PType, n: PNode): PNode =
var m: TCandidate
initCandidate(m, f)
result = paramTypesMatch(c, m, f, n.typ, n)
result = paramTypesMatch(c, m, f, n.typ, n, nil)
proc argtypeMatches*(c: PContext, f, a: PType): bool =
var m: TCandidate
initCandidate(m, f)
result = paramTypesMatch(c, m, f, a, ast.emptyNode) != nil
result = paramTypesMatch(c, m, f, a, ast.emptyNode, nil) != nil
proc setSon(father: PNode, at: int, son: PNode) =
if sonsLen(father) <= at: setlen(father.sons, at + 1)
father.sons[at] = son
proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
marker: var TIntSet) =
proc matchesAux*(c: PContext, n, nOrig: PNode,
m: var TCandidate, marker: var TIntSet) =
var f = 1 # iterates over formal parameters
var a = 1 # iterates over the actual given arguments
m.state = csMatch # until proven otherwise
@@ -623,7 +627,7 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
addSon(m.call, copyTree(n.sons[0]))
var container: PNode = nil # constructed container
var formal: PSym = nil
while a < sonsLen(n):
while a < n.len:
if n.sons[a].kind == nkExprEqExpr:
# named param
# check if m.callee has such a param:
@@ -642,8 +646,8 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
m.state = csNoMatch
return
m.baseTypeMatch = false
var arg = ParamTypesMatch(c, m, formal.typ,
n.sons[a].typ, n.sons[a].sons[1])
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
n.sons[a].sons[1], nOrig.sons[a].sons[1])
if arg == nil:
m.state = csNoMatch
return
@@ -666,9 +670,10 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
copyTree(n.sons[a]), m, c))
else:
addSon(m.call, copyTree(n.sons[a]))
elif formal != nil:
elif formal != nil:
m.baseTypeMatch = false
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, n.sons[a])
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
n.sons[a], nOrig.sons[a])
if (arg != nil) and m.baseTypeMatch and (container != nil):
addSon(container, arg)
else:
@@ -687,7 +692,8 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
m.state = csNoMatch
return
m.baseTypeMatch = false
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ, n.sons[a])
var arg = ParamTypesMatch(c, m, formal.typ, n.sons[a].typ,
n.sons[a], nOrig.sons[a])
if arg == nil:
m.state = csNoMatch
return
@@ -703,14 +709,14 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
inc(a)
inc(f)
proc partialMatch*(c: PContext, n: PNode, m: var TCandidate) =
proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
# for 'suggest' support:
var marker = initIntSet()
matchesAux(c, n, m, marker)
matchesAux(c, n, nOrig, m, marker)
proc matches*(c: PContext, n: PNode, m: var TCandidate) =
proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
var marker = initIntSet()
matchesAux(c, n, m, marker)
matchesAux(c, n, nOrig, m, marker)
if m.state == csNoMatch: return
# check that every formal parameter got a value:
var f = 1

View File

@@ -46,7 +46,7 @@ proc suggestField(s: PSym) =
if filterSym(s):
OutWriteln(SymToStr(s, isLocal=true, sectionSuggest))
template wholeSymTab(cond, section: expr) =
template wholeSymTab(cond, section: expr) {.immediate.} =
for i in countdown(c.tab.tos-1, 0):
for it in items(c.tab.stack[i]):
if cond:
@@ -79,20 +79,18 @@ proc nameFits(c: PContext, s: PSym, n: PNode): bool =
else: return false
result = opr.id == s.name.id
proc argsFit(c: PContext, candidate: PSym, n: PNode): bool =
proc argsFit(c: PContext, candidate: PSym, n, nOrig: PNode): bool =
case candidate.kind
of skProc, skIterator, skMethod:
of OverloadableSyms:
var m: TCandidate
initCandidate(m, candidate, nil)
sigmatch.partialMatch(c, n, m)
sigmatch.partialMatch(c, n, nOrig, m)
result = m.state != csNoMatch
of skTemplate, skMacro:
result = true
else:
result = false
proc suggestCall(c: PContext, n: PNode) =
wholeSymTab(filterSym(it) and nameFits(c, it, n) and argsFit(c, it, n),
proc suggestCall(c: PContext, n, nOrig: PNode) =
wholeSymTab(filterSym(it) and nameFits(c, it, n) and argsFit(c, it, n, nOrig),
sectionContext)
proc typeFits(c: PContext, s: PSym, firstArg: PType): bool {.inline.} =
@@ -227,7 +225,7 @@ proc suggestExpr*(c: PContext, node: PNode) =
var x = safeSemExpr(c, n.sons[i])
if x.kind == nkEmpty or x.typ == nil: break
addSon(a, x)
suggestCall(c, a)
suggestCall(c, a, n)
if optDef in gGlobalOptions:
var n = findClosestSym(fuzzySemCheck(c, node))

View File

@@ -36,7 +36,7 @@ type
wColon, wColonColon, wEquals, wDot, wDotDot,
wStar, wMinus,
wMagic, wThread, wFinal, wProfiler, wObjChecks,
wImportCpp, wImportObjC,
wImmediate, wImportCpp, wImportObjC,
wImportCompilerProc,
wImportc, wExportc, wExtern, wIncompleteStruct,
wAlign, wNodecl, wPure, wVolatile, wRegister, wSideeffect, wHeader,
@@ -83,7 +83,7 @@ const
"*", "-",
"magic", "thread", "final", "profiler", "objchecks",
"importcpp", "importobjc",
"immediate", "importcpp", "importobjc",
"importcompilerproc", "importc", "exportc", "extern", "incompletestruct",
"align", "nodecl", "pure", "volatile", "register", "sideeffect",
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",

View File

@@ -251,7 +251,7 @@ when defined(endb):
dbgAborting: bool # whether the debugger wants to abort
proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
template processSignal(s, action: expr) =
template processSignal(s, action: expr) {.immediate.} =
if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n")
elif s == SIGSEGV:
action("SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n")

View File

@@ -170,7 +170,7 @@ when traceGC:
cfprintf(cstdout, "Allocations: %ld; ZCT freed: %ld; CYC freed: %ld\n",
e, z, y)
template gcTrace(cell, state: expr): stmt =
template gcTrace(cell, state: expr): stmt {.immediate.} =
when traceGC: traceCell(cell, state)
# -----------------------------------------------------------------------------