diff --git a/.gitignore b/.gitignore
index 462df4efc7..d804fb8f54 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,4 @@ xcuserdata/
/testresults.html
/testresults.json
testament.db
+/csources/
diff --git a/compiler/ast.nim b/compiler/ast.nim
index d85dbf42c4..a071060d40 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -399,6 +399,7 @@ const
tyPureObject* = tyTuple
GcTypeKinds* = {tyRef, tySequence, tyString}
tyError* = tyProxy # as an errornous node should match everything
+ tyUnknown* = tyFromExpr
tyUnknownTypes* = {tyError, tyFromExpr}
@@ -1340,6 +1341,10 @@ proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
result = t
while result.kind in kinds: result = lastSon(result)
+proc safeSkipTypes*(t: PType, kinds: TTypeKinds): PType =
+ result = if t != nil: t.skipTypes(kinds)
+ else: nil
+
proc isGCedMem*(t: PType): bool {.inline.} =
result = t.kind in {tyString, tyRef, tySequence} or
t.kind == tyProc and t.callConv == ccClosure
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index 35acf1379f..3f4f39c279 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -23,6 +23,7 @@ type
id: int # for generating IDs
toc, section: TSections
indexValFilename: string
+ analytics: string # Google Analytics javascript, "" if doesn't exist
seenSymbols: StringTableRef # avoids duplicate symbol generation for HTML.
PDoc* = ref TDocumentor ## Alias to type less.
@@ -61,6 +62,23 @@ proc newDocumentor*(filename: string, config: StringTableRef): PDoc =
initRstGenerator(result[], (if gCmd != cmdRst2tex: outHtml else: outLatex),
options.gConfigVars, filename, {roSupportRawDirective},
docgenFindFile, compilerMsgHandler)
+
+ if config.hasKey("doc.googleAnalytics"):
+ result.analytics = """
+
+ """ % [config["doc.googleAnalytics"]]
+ else:
+ result.analytics = ""
+
result.seenSymbols = newStringTable(modeCaseInsensitive)
result.id = 100
@@ -562,10 +580,10 @@ proc genOutFile(d: PDoc): PRope =
# XXX what is this hack doing here? 'optCompileOnly' means raw output!?
code = ropeFormatNamedVars(getConfigVar("doc.file"), ["title",
"tableofcontents", "moduledesc", "date", "time",
- "content", "author", "version"],
+ "content", "author", "version", "analytics"],
[title.toRope, toc, d.modDesc, toRope(getDateStr()),
toRope(getClockStr()), content, d.meta[metaAuthor].toRope,
- d.meta[metaVersion].toRope])
+ d.meta[metaVersion].toRope, d.analytics.toRope])
else:
code = content
result = code
@@ -630,7 +648,8 @@ proc commandBuildIndex*() =
let code = ropeFormatNamedVars(getConfigVar("doc.file"), ["title",
"tableofcontents", "moduledesc", "date", "time",
- "content", "author", "version"],
+ "content", "author", "version", "analytics"],
["Index".toRope, nil, nil, toRope(getDateStr()),
- toRope(getClockStr()), content, nil, nil])
+ toRope(getClockStr()), content, nil, nil, nil])
+ # no analytics because context is not available
writeRope(code, getOutFile("theindex", HtmlExt))
diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim
index 78cc691c06..ecb898d8ac 100644
--- a/compiler/evaltempl.nim
+++ b/compiler/evaltempl.nim
@@ -25,16 +25,22 @@ proc copyNode(ctx: TemplCtx, a, b: PNode): PNode =
if ctx.instLines: result.info = b.info
proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
+ template handleParam(param) =
+ let x = param
+ if x.kind == nkArgList:
+ for y in items(x): result.add(y)
+ else:
+ result.add copyTree(x)
+
case templ.kind
of nkSym:
var s = templ.sym
if s.owner.id == c.owner.id:
- if s.kind == skParam:
- let x = actual.sons[s.position]
- if x.kind == nkArgList:
- for y in items(x): result.add(y)
- else:
- result.add copyTree(x)
+ case s.kind
+ of skParam:
+ handleParam actual.sons[s.position]
+ of skGenericParam:
+ handleParam actual.sons[s.owner.typ.len + s.position - 1]
else:
internalAssert sfGenSym in s.flags
var x = PSym(idTableGet(c.mapping, s))
@@ -56,21 +62,31 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
proc evalTemplateArgs(n: PNode, s: PSym): PNode =
# if the template has zero arguments, it can be called without ``()``
# `n` is then a nkSym or something similar
- var a: int
- case n.kind
- of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
- a = sonsLen(n)
- else: a = 0
- var f = s.typ.sonsLen
- if a > f: globalError(n.info, errWrongNumberOfArguments)
+ var totalParams = case n.kind
+ of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: expectedRegularParams + genericParams:
+ globalError(n.info, errWrongNumberOfArguments)
result = newNodeI(nkArgList, n.info)
- for i in countup(1, f - 1):
- var arg = if i < a: n.sons[i] else: copyTree(s.typ.n.sons[i].sym.ast)
- if arg == nil or arg.kind == nkEmpty:
- localError(n.info, errWrongNumberOfArguments)
- addSon(result, arg)
+ for i in 1 .. givenRegularParams:
+ result.addSon n.sons[i]
+ for i in givenRegularParams+1 .. expectedRegularParams:
+ let default = s.typ.n.sons[i].sym.ast
+ if default.kind == nkEmpty:
+ localError(n.info, errWrongNumberOfArguments)
+ result.addSon default.copyTree
+
+ for i in 1 .. genericParams:
+ result.addSon n.sons[givenRegularParams + i]
+
var evalTemplateCounter* = 0
# to prevent endless recursion in templates instantiation
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 3971b8ff59..961c61c57a 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -277,16 +277,27 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
styleCheckUse(n.sons[0].info, 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!
- if not x.proxyMatch:
+ if x.hasFauxMatch:
+ result = x.call
+ result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
+ if containsGenericType(result.typ) or x.fauxMatch == tyUnknown:
+ result.typ = newTypeS(x.fauxMatch, c)
+ return
+ let gp = finalCallee.ast.sons[genericParamsPos]
+ if gp.kind != nkEmpty:
+ if x.calleeSym.kind notin {skMacro, skTemplate}:
finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
else:
- result = x.call
- result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
- result.typ = finalCallee.typ.sons[0]
- if containsGenericType(result.typ): result.typ = errorType(c)
- return
+ # For macros and templates, the resolved generic params
+ # are added as normal params.
+ for s in instantiateGenericParamList(c, gp, x.bindings):
+ case s.kind
+ of skConst:
+ x.call.add s.ast
+ of skType:
+ x.call.add newSymNode(s, n.info)
+ else:
+ internalAssert false
result = x.call
instGenericConvertersSons(c, result, x)
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index f876770c09..623f9b6339 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -268,7 +268,7 @@ proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
template rangeHasStaticIf*(t: PType): bool =
# this accepts the ranges's node
- t.n[1].kind == nkStaticExpr
+ t.n != nil and t.n.len > 1 and t.n[1].kind == nkStaticExpr
template getStaticTypeFromRange*(t: PType): PType =
t.n[1][0][1].typ
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 9bf04c955e..5e61c4a0ba 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -229,7 +229,7 @@ proc semConv(c: PContext, n: PNode): PNode =
return n
result = newNodeI(nkConv, n.info)
- var targetType = semTypeNode(c, n.sons[0], nil)
+ var targetType = semTypeNode(c, n.sons[0], nil).skipTypes({tyTypeDesc})
maybeLiftType(targetType, c, n[0].info)
result.addSon copyTree(n.sons[0])
var op = semExprWithType(c, n.sons[1])
@@ -780,7 +780,6 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect)
elif t != nil and t.kind == tyTypeDesc:
if n.len == 1: return semObjConstr(c, n, flags)
- let destType = t.skipTypes({tyTypeDesc, tyGenericInst})
return semConv(c, n)
else:
result = overloadedCallOpr(c, n)
@@ -926,8 +925,8 @@ const
proc readTypeParameter(c: PContext, typ: PType,
paramName: PIdent, info: TLineInfo): PNode =
let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias
- else: (internalAssert(typ.kind == tyCompositeTypeClass); typ.sons[1])
- #debug ty
+ else: (internalAssert(typ.kind == tyCompositeTypeClass);
+ typ.sons[1].skipGenericAlias)
let tbody = ty.sons[0]
for s in countup(0, tbody.len-2):
let tParam = tbody.sons[s]
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 81a4465c59..dd60e08810 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -10,14 +10,10 @@
# This module implements the instantiation of generic procs.
# included from sem.nim
-proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
- entry: var TInstantiation) =
- if n.kind != nkGenericParams:
- internalError(n.info, "instantiateGenericParamList; no generic params")
- newSeq(entry.concreteTypes, n.len)
+iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym =
+ internalAssert n.kind == nkGenericParams
for i, a in n.pairs:
- if a.kind != nkSym:
- internalError(a.info, "instantiateGenericParamList; no symbol")
+ internalAssert a.kind == nkSym
var q = a.sym
if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic, tyIter}+tyTypeClasses:
continue
@@ -42,8 +38,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
#t = ReplaceTypeVarsT(cl, t)
s.typ = t
if t.kind == tyStatic: s.ast = t.n
- addDecl(c, s)
- entry.concreteTypes[i] = t
+ yield s
proc sameInstantiation(a, b: TInstantiation): bool =
if a.concreteTypes.len == b.concreteTypes.len:
@@ -196,7 +191,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
## The `pt` parameter is a type-unsafe mapping table used to link generic
## parameters to their concrete types within the generic instance.
# no need to instantiate generic templates/macros:
- if fn.kind in {skTemplate, skMacro}: return fn
+ internalAssert fn.kind notin {skMacro, skTemplate}
# generates an instantiated proc
if c.instCounter > 1000: internalError(fn.ast.info, "nesting too deep")
inc(c.instCounter)
@@ -213,12 +208,18 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
result.ast = n
pushOwner(result)
openScope(c)
- internalAssert n.sons[genericParamsPos].kind != nkEmpty
+ let gp = n.sons[genericParamsPos]
+ internalAssert gp.kind != nkEmpty
n.sons[namePos] = newSymNode(result)
pushInfoContext(info)
var entry = TInstantiation.new
entry.sym = result
- instantiateGenericParamList(c, n.sons[genericParamsPos], pt, entry[])
+ newSeq(entry.concreteTypes, gp.len)
+ var i = 0
+ for s in instantiateGenericParamList(c, gp, pt):
+ addDecl(c, s)
+ entry.concreteTypes[i] = s.typ
+ inc i
pushProcCon(c, result)
instantiateProcType(c, pt, result, info)
n.sons[genericParamsPos] = ast.emptyNode
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 3b03329396..1396ef3747 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1262,10 +1262,14 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
return
else:
n.sons[i] = semExpr(c, n.sons[i])
- if c.inTypeClass > 0 and n[i].typ != nil and n[i].typ.kind == tyBool:
- let verdict = semConstExpr(c, n[i])
- if verdict.intVal == 0:
- localError(result.info, "type class predicate failed")
+ if c.inTypeClass > 0 and n[i].typ != nil:
+ case n[i].typ.kind
+ of tyBool:
+ let verdict = semConstExpr(c, n[i])
+ if verdict.intVal == 0:
+ localError(result.info, "type class predicate failed")
+ of tyUnknown: continue
+ else: discard
if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]):
voidContext = true
n.typ = enforceVoidContext
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index eb15c3809c..deb4b12887 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -225,11 +225,10 @@ proc semArrayIndex(c: PContext, n: PNode): PType =
elif e.kind == nkSym and e.typ.kind == tyStatic:
if e.sym.ast != nil:
return semArrayIndex(c, e.sym.ast)
- internalAssert c.inGenericContext > 0
if not isOrdinalType(e.typ.lastSon):
localError(n[1].info, errOrdinalTypeExpected)
result = makeRangeWithStaticExpr(c, e)
- result.flags.incl tfUnresolved
+ if c.inGenericContext >0: result.flags.incl tfUnresolved
elif e.kind in nkCallKinds and hasGenericArguments(e):
if not isOrdinalType(e.typ):
localError(n[1].info, errOrdinalTypeExpected)
@@ -782,10 +781,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
of tyGenericBody:
result = newTypeS(tyGenericInvokation, c)
result.rawAddSon(paramType)
+
for i in 0 .. paramType.sonsLen - 2:
- result.rawAddSon newTypeS(tyAnything, c)
- # result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true))
-
+ let dummyType = if paramType.sons[i].kind == tyStatic: tyUnknown
+ else: tyAnything
+ result.rawAddSon newTypeS(dummyType, c)
+
if paramType.lastSon.kind == tyUserTypeClass:
result.kind = tyUserTypeClassInst
result.rawAddSon paramType.lastSon
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index b58818a298..721f7e3187 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -39,7 +39,9 @@ type
bindings*: TIdTable # maps types to types
baseTypeMatch: bool # needed for conversions from T to openarray[T]
# for example
- proxyMatch*: bool # to prevent instantiations
+ fauxMatch*: TTypeKind # the match was successful only due to the use
+ # of error or wildcard (unknown) types.
+ # this is used to prevent instantiations.
genericConverter*: bool # true if a generic converter needs to
# be instantiated
coerceDistincts*: bool # this is an explicit coercion that can strip away
@@ -66,6 +68,8 @@ const
proc markUsed*(info: TLineInfo, s: PSym)
+template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone
+
proc initCandidateAux(ctx: PContext,
c: var TCandidate, callee: PType) {.inline.} =
c.c = ctx
@@ -109,9 +113,12 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
var formalTypeParam = typeParams.sons[i-1].typ
var bound = binding[i].typ
- if bound != nil and formalTypeParam.kind != tyTypeDesc:
+ internalAssert bound != nil
+ if formalTypeParam.kind == tyTypeDesc:
+ if bound.kind != tyTypeDesc:
+ bound = makeTypeDesc(ctx, bound)
+ else:
bound = bound.skipTypes({tyTypeDesc})
- assert bound != nil
put(c.bindings, formalTypeParam, bound)
proc newCandidate*(ctx: PContext, callee: PSym,
@@ -462,9 +469,23 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
var
typeParamName = ff.base.sons[i-1].sym.name
typ = ff.sons[i]
- param = newSym(skType, typeParamName, body.sym, body.sym.info)
-
- param.typ = makeTypeDesc(c, typ)
+ param: PSym
+
+ template paramSym(kind): expr =
+ newSym(kind, typeParamName, body.sym, body.sym.info)
+
+ case typ.kind
+ of tyStatic:
+ param = paramSym skConst
+ param.typ = typ.base
+ param.ast = typ.n
+ of tyUnknown:
+ param = paramSym skVar
+ param.typ = typ
+ else:
+ param = paramSym skType
+ param.typ = makeTypeDesc(c, typ)
+
addDecl(c, param)
for param in body.n[0]:
@@ -626,6 +647,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
elif skipTypes(a, {tyRange}).kind == f.kind: result = isSubtype
of tyRange:
if a.kind == f.kind:
+ if f.base.kind == tyNone: return isGeneric
result = typeRel(c, base(f), base(a))
# bugfix: accept integer conversions here
#if result < isGeneric: result = isNone
@@ -672,22 +694,27 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
else:
fRange = prev
result = typeRel(c, f.sons[1], a.sons[1])
- if result < isGeneric:
- result = isNone
- elif tfUnresolved in fRange.flags and
- rangeHasStaticIf(fRange):
- # This is a range from an array instantiated with a generic
- # static param. We must extract the static param here and bind
- # it to the size of the currently supplied array.
- var
- rangeStaticT = fRange.getStaticTypeFromRange
- replacementT = newTypeWithSons(c.c, tyStatic, @[tyInt.getSysType])
- inputUpperBound = a.sons[0].n[1].intVal
- # we must correct for the off-by-one discrepancy between
- # ranges and static params:
- replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1)
- put(c.bindings, rangeStaticT, replacementT)
- result = isGeneric
+ if result < isGeneric: return isNone
+ if rangeHasStaticIf(fRange):
+ if tfUnresolved in fRange.flags:
+ # This is a range from an array instantiated with a generic
+ # static param. We must extract the static param here and bind
+ # it to the size of the currently supplied array.
+ var
+ rangeStaticT = fRange.getStaticTypeFromRange
+ replacementT = newTypeWithSons(c.c, tyStatic, @[tyInt.getSysType])
+ inputUpperBound = a.sons[0].n[1].intVal
+ # we must correct for the off-by-one discrepancy between
+ # ranges and static params:
+ replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1)
+ put(c.bindings, rangeStaticT, replacementT)
+ return isGeneric
+
+ let len = tryResolvingStaticExpr(c, fRange.n[1])
+ if len.kind == nkIntLit and len.intVal+1 == lengthOrd(a):
+ return # if we get this far, the result is already good
+ else:
+ return isNone
elif lengthOrd(fRange) != lengthOrd(a):
result = isNone
else: discard
@@ -945,7 +972,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
else:
internalAssert a.sons != nil and a.sons.len > 0
c.typedescMatched = true
- result = typeRel(c, f.base, a.base)
+ result = typeRel(c, f.base, a.skipTypes({tyGenericParam, tyTypeDesc}))
else:
result = isNone
else:
@@ -977,15 +1004,19 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
result = typeRel(c, x, a) # check if it fits
of tyStatic:
- if aOrig.kind == tyStatic:
- result = typeRel(c, f.lastSon, a)
- if result != isNone and f.n != nil:
- if not exprStructuralEquivalent(f.n, a.n):
- result = isNone
- if result != isNone: put(c.bindings, f, aOrig)
+ let prev = PType(idTableGet(c.bindings, f))
+ if prev == nil:
+ if aOrig.kind == tyStatic:
+ result = typeRel(c, f.lastSon, a)
+ if result != isNone and f.n != nil:
+ if not exprStructuralEquivalent(f.n, aOrig.n):
+ result = isNone
+ if result != isNone: put(c.bindings, f, aOrig)
+ else:
+ result = isNone
else:
- result = isNone
-
+ result = typeRel(c, prev, aOrig)
+
of tyTypeDesc:
var prev = PType(idTableGet(c.bindings, f))
if prev == nil:
@@ -1024,6 +1055,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
of tyFromExpr:
# fix the expression, so it contains the already instantiated types
+ if f.n == nil: return isGeneric
let reevaluated = tryResolvingStaticExpr(c, f.n)
case reevaluated.typ.kind
of tyTypeDesc:
@@ -1045,10 +1077,10 @@ proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation =
initCandidate(c, m, f)
result = typeRel(m, f, a)
-proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
- f: PType): PType =
+proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
+ f: PType): PType =
result = PType(idTableGet(m.bindings, f))
- if result == nil:
+ if result == nil:
result = generateTypeInstance(c, m.bindings, arg, f)
if result == nil:
internalError(arg.info, "getInstantiatedType")
@@ -1058,7 +1090,7 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
c: PContext): PNode =
result = newNodeI(kind, arg.info)
if containsGenericType(f):
- if not m.proxyMatch:
+ if not m.hasFauxMatch:
result.typ = getInstantiatedType(c, arg, m, f)
else:
result.typ = errorType(c)
@@ -1130,7 +1162,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
arg = argSemantized
argType = argType
c = m.c
-
+
if tfHasStatic in fMaybeStatic.flags:
# XXX: When implicit statics are the default
# this will be done earlier - we just have to
@@ -1144,7 +1176,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
return argSemantized
if argType.kind == tyStatic:
- if m.callee.kind == tyGenericBody:
+ if m.callee.kind == tyGenericBody and tfGenericTypeParam notin argType.flags:
result = newNodeI(nkType, argOrig.info)
result.typ = makeTypeFromExpr(c, arg)
return
@@ -1237,9 +1269,9 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
of isNone:
# do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
- if a.kind == tyProxy:
+ if a.kind in {tyProxy, tyUnknown}:
inc(m.genericMatches)
- m.proxyMatch = true
+ m.fauxMatch = a.kind
return copyTree(arg)
result = userConvMatch(c, m, f, a, arg)
# check for a base type match, which supports varargs[T] without []
diff --git a/compiler/vm.nim b/compiler/vm.nim
index ad0d3b0a17..4072ed7659 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -1417,12 +1417,20 @@ proc evalStaticStmt*(module: PSym, e: PNode, prc: PSym) =
proc setupCompileTimeVar*(module: PSym, n: PNode) =
discard evalConstExprAux(module, nil, n, emStaticStmt)
-proc setupMacroParam(x: PNode): PNode =
- result = x
- if result.kind in {nkHiddenSubConv, nkHiddenStdConv}: result = result.sons[1]
- result = canonValue(result)
- result.flags.incl nfIsRef
- result.typ = x.typ
+proc setupMacroParam(x: PNode, typ: PType): TFullReg =
+ case typ.kind
+ of tyStatic:
+ putIntoReg(result, x)
+ of tyTypeDesc:
+ putIntoReg(result, x)
+ else:
+ result.kind = rkNode
+ var n = x
+ if n.kind in {nkHiddenSubConv, nkHiddenStdConv}: n = n.sons[1]
+ n = n.canonValue
+ n.flags.incl nfIsRef
+ n.typ = x.typ
+ result.node = n
var evalMacroCounter: int
@@ -1442,6 +1450,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
c.callsite = nOrig
let start = genProc(c, sym)
+ # c.echoCode start
var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
let maxSlots = sym.offset
@@ -1457,9 +1466,14 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
tos.slots[0].kind = rkNode
tos.slots[0].node = newNodeIT(nkEmpty, n.info, sym.typ.sons[0])
# setup parameters:
- for i in 1 .. < min(tos.slots.len, L):
- tos.slots[i].kind = rkNode
- tos.slots[i].node = setupMacroParam(n.sons[i])
+ for i in 1.. tags
doc.file = """
@@ -1243,6 +1244,7 @@ dt pre > span.Operator ~ span.Identifier, dt pre > span.Operator ~ span.Operator
+$analytics