Merge branch 'devel' of https://github.com/Araq/Nimrod into devel

This commit is contained in:
Audun Wilhelmsen 2014-02-23 00:26:46 +01:00
commit 1250db5075
71 changed files with 1533 additions and 692 deletions

View file

@ -540,7 +540,7 @@ proc typeAtom(p: var TParser): PNode =
if p.tok.s == "unsigned":
isUnsigned = true
elif p.tok.s == "signed" or p.tok.s == "int":
nil
discard
else:
add(x, p.tok.s)
getTok(p, nil)
@ -746,7 +746,7 @@ proc directDeclarator(p: var TParser, a: PNode, ident: ptr PNode): PNode =
result = declarator(p, a, ident)
eat(p, pxParRi, result)
else:
nil
discard
return parseTypeSuffix(p, a)
proc declarator(p: var TParser, a: PNode, ident: ptr PNode): PNode =
@ -1165,7 +1165,7 @@ proc enumSpecifier(p: var TParser): PNode =
proc setBaseFlags(n: PNode, base: TNumericalBase) =
case base
of base10: nil
of base10: discard
of base2: incl(n.flags, nfBase2)
of base8: incl(n.flags, nfBase8)
of base16: incl(n.flags, nfBase16)
@ -1686,7 +1686,7 @@ proc switchStatement(p: var TParser): PNode =
break
of "case", "default":
break
else: nil
else: discard
addSon(result, statement(p))
if sonsLen(result) == 0:
# translate empty statement list to Nimrod's ``nil`` statement

View file

@ -103,7 +103,7 @@ proc parseDefBody(p: var TParser, m: var TMacro, params: seq[string]) =
m.body.add(tok)
of pxDirConc:
# just ignore this token: this implements token merging correctly
nil
discard
else:
m.body.add(p.tok)
# we do not want macro expansion here:
@ -166,7 +166,7 @@ proc parseStmtList(p: var TParser): PNode =
of pxDirectiveParLe, pxDirective:
case p.tok.s
of "else", "endif", "elif": break
else: nil
else: discard
addSon(result, statement(p))
proc eatEndif(p: var TParser) =

View file

@ -88,7 +88,8 @@ type
errTemplateInstantiationTooNested, errInstantiationFrom,
errInvalidIndexValueForTuple, errCommandExpectsFilename,
errMainModuleMustBeSpecified,
errXExpected,
errXExpected,
errTIsNotAConcreteType,
errInvalidSectionStart, errGridTableNotImplemented, errGeneralParseError,
errNewSectionExpected, errWhitespaceExpected, errXisNoValidIndexFile,
errCannotRenderX, errVarVarTypeNotAllowed, errInstantiateXExplicitely,
@ -103,6 +104,7 @@ type
errXhasSideEffects, errIteratorExpected, errLetNeedsInit,
errThreadvarCannotInit, errWrongSymbolX, errIllegalCaptureX,
errXCannotBeClosure, errXMustBeCompileTime,
errCannotInferTypeOfTheLiteral,
errUser,
warnCannotOpenFile,
warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit,
@ -312,6 +314,7 @@ const
errCommandExpectsFilename: "command expects a filename argument",
errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file",
errXExpected: "\'$1\' expected",
errTIsNotAConcreteType: "\'$1\' is not a concrete type.",
errInvalidSectionStart: "invalid section start",
errGridTableNotImplemented: "grid table is not implemented",
errGeneralParseError: "general parse error",
@ -346,6 +349,7 @@ const
errIllegalCaptureX: "illegal capture '$1'",
errXCannotBeClosure: "'$1' cannot have 'closure' calling convention",
errXMustBeCompileTime: "'$1' can only be used in compile-time context",
errCannotInferTypeOfTheLiteral: "cannot infer the type of the $1",
errUser: "$1",
warnCannotOpenFile: "cannot open \'$1\' [CannotOpenFile]",
warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored [OctalEscape]",

View file

@ -342,7 +342,7 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
h = h +% ord(c)
h = h +% h shl 10
h = h xor (h shr 6)
of '_': nil
of '_': discard
else: break
inc(pos)
h = h +% h shl 3

View file

@ -335,7 +335,7 @@ proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind,
proc setBaseFlags(n: PNode, base: TNumericalBase) =
case base
of base10: nil
of base10: discard
of base2: incl(n.flags, nfBase2)
of base8: incl(n.flags, nfBase8)
of base16: incl(n.flags, nfBase16)
@ -466,7 +466,7 @@ proc lowestExprAux(p: var TParser, v: var PNode, limit: int): TTokKind =
eat(p, pxCurlyDirRi)
opNode.ident = getIdent("&")
else:
nil
discard
of pxMinus:
if p.tok.xkind == pxPer:
getTok(p)
@ -477,7 +477,7 @@ proc lowestExprAux(p: var TParser, v: var PNode, limit: int): TTokKind =
of pxNeq:
opNode.ident = getIdent("!=")
else:
nil
discard
skipCom(p, opNode) # read sub-expression with higher priority
nextop = lowestExprAux(p, v2, opPred)
addSon(node, opNode)
@ -505,7 +505,7 @@ proc fixExpr(n: PNode): PNode =
(n.sons[2].kind in {nkCharLit, nkStrLit}):
n.sons[0].ident = getIdent("&") # fix operator
else:
nil
discard
if not (n.kind in {nkEmpty..nkNilLit}):
for i in countup(0, sonsLen(n) - 1): result.sons[i] = fixExpr(n.sons[i])
@ -603,7 +603,7 @@ proc parseStmtList(p: var TParser): PNode =
of pxCurlyDirLe, pxStarDirLe:
if not isHandledDirective(p): break
else:
nil
discard
addSon(result, parseStmt(p))
if sonsLen(result) == 1: result = result.sons[0]
@ -732,7 +732,7 @@ proc parseRepeat(p: var TParser): PNode =
addSon(b, c)
addSon(a, b)
if b.sons[0].kind == nkIdent and b.sons[0].ident.id == getIdent("false").id:
nil
discard
else:
addSon(s, a)
addSon(result, s)
@ -840,7 +840,7 @@ proc parseParam(p: var TParser): PNode =
getTok(p)
v = newNodeP(nkVarTy, p)
else:
nil
discard
while true:
case p.tok.xkind
of pxSymbol: a = createIdentNodeP(p.tok.ident, p)
@ -1133,7 +1133,7 @@ proc parseRecordPart(p: var TParser): PNode =
proc exSymbol(n: var PNode) =
case n.kind
of nkPostfix:
nil
discard
of nkPragmaExpr:
exSymbol(n.sons[0])
of nkIdent, nkAccQuoted:
@ -1154,7 +1154,7 @@ proc fixRecordDef(n: var PNode) =
for i in countup(0, sonsLen(n) - 1): fixRecordDef(n.sons[i])
of nkIdentDefs:
for i in countup(0, sonsLen(n) - 3): exSymbol(n.sons[i])
of nkNilLit, nkEmpty: nil
of nkNilLit, nkEmpty: discard
else: internalError(n.info, "fixRecordDef(): " & $n.kind)
proc addPragmaToIdent(ident: var PNode, pragma: PNode) =
@ -1191,7 +1191,7 @@ proc parseRecordBody(p: var TParser, result, definition: PNode) =
if definition != nil: addPragmaToIdent(definition.sons[0], parseCommand(p))
else: internalError(result.info, "anonymous record is not supported")
else:
nil
discard
opt(p, pxSemicolon)
skipCom(p, result)
@ -1399,7 +1399,7 @@ proc fixVarSection(p: var TParser, counter: PNode) =
proc exSymbols(n: PNode) =
case n.kind
of nkEmpty..nkNilLit: nil
of nkEmpty..nkNilLit: discard
of nkProcDef..nkIteratorDef: exSymbol(n.sons[namePos])
of nkWhenStmt, nkStmtList:
for i in countup(0, sonsLen(n) - 1): exSymbols(n.sons[i])
@ -1410,7 +1410,7 @@ proc exSymbols(n: PNode) =
exSymbol(n.sons[i].sons[0])
if n.sons[i].sons[2].kind == nkObjectTy:
fixRecordDef(n.sons[i].sons[2])
else: nil
else: discard
proc parseBegin(p: var TParser, result: PNode) =
getTok(p)

View file

@ -97,8 +97,25 @@ proc makeExternImport(s: PSym, extname: string) =
incl(s.flags, sfImportc)
excl(s.flags, sfForward)
proc makeExternExport(s: PSym, extname: string) =
const invalidIdentChars = AllChars - IdentChars
proc validateExternCName(s: PSym, info: TLineInfo) =
## Validates that the symbol name in s.loc.r is a valid C identifier.
##
## Valid identifiers are those alphanumeric including the underscore not
## starting with a number. If the check fails, a generic error will be
## displayed to the user.
let target = ropeToStr(s.loc.r)
if target.len < 1 or (not (target[0] in IdentStartChars)) or
(not target.allCharsInSet(IdentChars)):
localError(info, errGenerated, "invalid exported symbol")
proc makeExternExport(s: PSym, extname: string, info: TLineInfo) =
setExternName(s, extname)
case gCmd
of cmdCompileToC, cmdCompileToCpp, cmdCompileToOC:
validateExternCName(s, info)
else: discard
incl(s.flags, sfExportc)
proc processImportCompilerProc(s: PSym, extname: string) =
@ -515,7 +532,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
if k in validPragmas:
case k
of wExportc:
makeExternExport(sym, getOptionalStr(c, it, "$1"))
makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info)
incl(sym.flags, sfUsed) # avoid wrong hints
of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1"))
of wImportCompilerProc:
@ -601,7 +618,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
processDynLib(c, it, sym)
of wCompilerproc:
noVal(it) # compilerproc may not get a string!
makeExternExport(sym, "$1")
makeExternExport(sym, "$1", it.info)
incl(sym.flags, sfCompilerProc)
incl(sym.flags, sfUsed) # suppress all those stupid warnings
registerCompilerProc(sym)

View file

@ -333,6 +333,7 @@ proc myOpen(module: PSym): PPassContext =
c.semOperand = semOperand
c.semConstBoolExpr = semConstBoolExpr
c.semOverloadedCall = semOverloadedCall
c.semInferredLambda = semInferredLambda
c.semGenerateInstance = generateInstance
c.semTypeNode = semTypeNode
pushProcCon(c, module)

View file

@ -81,6 +81,7 @@ type
semOverloadedCall*: proc (c: PContext, n, nOrig: PNode,
filter: TSymKinds): PNode {.nimcall.}
semTypeNode*: proc(c: PContext, n: PNode, prev: PType): PType {.nimcall.}
semInferredLambda*: proc(c: PContext, pt: TIdTable, n: PNode): PNode
semGenerateInstance*: proc (c: PContext, fn: PSym, pt: TIdTable,
info: TLineInfo): PSym
includedFiles*: TIntSet # used to detect recursive include files

View file

@ -1829,8 +1829,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = symChoice(c, n, s, scClosed)
if result.kind == nkSym:
markIndirect(c, result.sym)
if isGenericRoutine(result.sym):
localError(n.info, errInstantiateXExplicitely, s.name.s)
# if isGenericRoutine(result.sym):
# localError(n.info, errInstantiateXExplicitely, s.name.s)
of nkSym:
# because of the changed symbol binding, this does not mean that we
# don't have to check the symbol for semantics here again!

View file

@ -143,10 +143,11 @@ proc discardCheck(c: PContext, result: PNode) =
while n.kind in skipForDiscardable:
n = n.lastSon
n.typ = nil
elif c.inTypeClass > 0 and result.typ.kind == tyBool:
let verdict = semConstExpr(c, result)
if verdict.intVal == 0:
localError(result.info, "type class predicate failed")
elif c.inTypeClass > 0:
if result.typ.kind == tyBool:
let verdict = semConstExpr(c, result)
if verdict.intVal == 0:
localError(result.info, "type class predicate failed")
elif result.typ.kind != tyError and gCmd != cmdInteractive:
if result.typ.kind == tyNil:
fixNilType(result)
@ -349,7 +350,12 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
# BUGFIX: ``fitNode`` is needed here!
# check type compability between def.typ and typ:
if typ != nil: def = fitNode(c, typ, def)
else: typ = skipIntLit(def.typ)
else:
typ = skipIntLit(def.typ)
if typ.kind in {tySequence, tyArray, tySet} and
typ.lastSon.kind == tyEmpty:
localError(def.info, errCannotInferTypeOfTheLiteral,
($typ.kind).substr(2).toLower)
else:
def = ast.emptyNode
if symkind == skLet: localError(a.info, errLetNeedsInit)
@ -764,6 +770,29 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
s.ast = a
popOwner()
proc checkForMetaFields(n: PNode) =
template checkMeta(t) =
if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags:
localError(n.info, errTIsNotAConcreteType, t.typeToString)
case n.kind
of nkRecList, nkRecCase:
for s in n: checkForMetaFields(s)
of nkOfBranch, nkElse:
checkForMetaFields(n.lastSon)
of nkSym:
let t = n.sym.typ
case t.kind
of tySequence, tySet, tyArray, tyOpenArray, tyVar, tyPtr, tyRef,
tyProc, tyGenericInvokation, tyGenericInst:
let start = ord(t.kind in {tyGenericInvokation, tyGenericInst})
for i in start .. <t.sons.len:
checkMeta(t.sons[i])
else:
checkMeta(t)
else:
internalAssert false
proc typeSectionFinalPass(c: PContext, n: PNode) =
for i in countup(0, sonsLen(n) - 1):
var a = n.sons[i]
@ -780,6 +809,8 @@ proc typeSectionFinalPass(c: PContext, n: PNode) =
assignType(s.typ, t)
s.typ.id = t.id # same id
checkConstructedType(s.info, s.typ)
if s.typ.kind in {tyObject, tyTuple}:
checkForMetaFields(s.typ.n)
let aa = a.sons[2]
if aa.kind in {nkRefTy, nkPtrTy} and aa.len == 1 and
aa.sons[0].kind == nkObjectTy:
@ -883,12 +914,19 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
s = n[namePos].sym
pushOwner(s)
openScope(c)
if n.sons[genericParamsPos].kind != nkEmpty:
illFormedAst(n) # process parameters:
var gp: PNode
if n.sons[genericParamsPos].kind != nkEmpty:
n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos])
gp = n.sons[genericParamsPos]
else:
gp = newNodeI(nkGenericParams, n.info)
if n.sons[paramsPos].kind != nkEmpty:
var gp = newNodeI(nkGenericParams, n.info)
semParamList(c, n.sons[paramsPos], gp, s)
paramsTypeCheck(c, s.typ)
# paramsTypeCheck(c, s.typ)
if sonsLen(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty:
# we have a list of implicit type parameters:
n.sons[genericParamsPos] = gp
else:
s.typ = newTypeS(tyProc, c)
rawAddSon(s.typ, nil)
@ -900,12 +938,13 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
localError(n.sons[bodyPos].info, errImplOfXNotAllowed, s.name.s)
#if efDetermineType notin flags:
# XXX not good enough; see tnamedparamanonproc.nim
pushProcCon(c, s)
addResult(c, s.typ.sons[0], n.info, skProc)
let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
n.sons[bodyPos] = transformBody(c.module, semBody, s)
addResultNode(c, n)
popProcCon(c)
if n.sons[genericParamsPos].kind == nkEmpty:
pushProcCon(c, s)
addResult(c, s.typ.sons[0], n.info, skProc)
let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
n.sons[bodyPos] = transformBody(c.module, semBody, s)
addResultNode(c, n)
popProcCon(c)
sideEffectsCheck(c, s)
else:
localError(n.info, errImplOfXexpected, s.name.s)
@ -913,6 +952,34 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
popOwner()
result.typ = s.typ
proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
var n = n
n = replaceTypesInBody(c, pt, n)
result = n
n.sons[genericParamsPos] = emptyNode
n.sons[paramsPos] = n.typ.n
openScope(c)
var s = n.sons[namePos].sym
addParams(c, n.typ.n, skProc)
pushProcCon(c, s)
addResult(c, n.typ.sons[0], n.info, skProc)
let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
n.sons[bodyPos] = transformBody(c.module, semBody, n.sons[namePos].sym)
addResultNode(c, n)
popProcCon(c)
closeScope(c)
s.ast = result
# alternative variant (not quite working):
# var prc = arg[0].sym
# let inferred = c.semGenerateInstance(c, prc, m.bindings, arg.info)
# result = inferred.ast
# result.kind = arg.kind
proc activate(c: PContext, n: PNode) =
# XXX: This proc is part of my plan for getting rid of
# forward declarations. stay tuned.
@ -1263,8 +1330,8 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
let (outer, inner) = insertDestructors(c, n.sons[i])
if outer != nil:
n.sons[i] = outer
for j in countup(i+1, length-1):
inner.addSon(semStmt(c, n.sons[j]))
var rest = newNode(nkStmtList, n.info, n.sons[i+1 .. length-1])
inner.addSon(semStmtList(c, rest, flags))
n.sons.setLen(i+1)
return
of LastBlockStmts:

View file

@ -669,7 +669,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
of tyTypeDesc:
if tfUnresolved notin paramType.flags:
# naked typedescs are not bindOnce types
if paramType.sonsLen == 0 and paramTypId != nil and
if paramType.base.kind == tyNone and paramTypId != nil and
paramTypId.id == typedescId.id: paramTypId = nil
result = addImplicitGeneric(c.newTypeWithSons(tyTypeDesc, paramType.sons))
@ -705,7 +705,6 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
# result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true))
result = instGenericContainer(c, paramType.sym.info, result,
allowMetaTypes = true)
result.lastSon.shouldHaveMeta
result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, result])
result = addImplicitGeneric(result)
@ -1011,7 +1010,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of mOrdinal: result = semOrdinal(c, n, prev)
of mSeq: result = semContainer(c, n, tySequence, "seq", prev)
of mVarargs: result = semVarargs(c, n, prev)
of mExpr, mTypeDesc:
of mTypeDesc: result = makeTypeDesc(c, semTypeNode(c, n[1], nil))
of mExpr:
result = semTypeNode(c, n.sons[0], nil)
if result != nil:
result = copyType(result, getCurrOwner(), false)

View file

@ -29,6 +29,7 @@ proc checkConstructedType*(info: TLineInfo, typ: PType) =
localError(info, errVarVarTypeNotAllowed)
elif computeSize(t) == szIllegalRecursion:
localError(info, errIllegalRecursionInTypeX, typeToString(t))
when false:
if t.kind == tyObject and t.sons[0] != nil:
if t.sons[0].kind != tyObject or tfFinal in t.sons[0].flags:
@ -219,7 +220,7 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
# is difficult to handle:
var body = t.sons[0]
if body.kind != tyGenericBody: internalError(cl.info, "no generic body")
var header: PType = nil
var header: PType = t
# search for some instantiation here:
if cl.allowMetaTypes:
result = PType(idTableGet(cl.localCache, t))
@ -231,11 +232,13 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
if x.kind == tyGenericParam:
x = lookupTypeVar(cl, x)
if x != nil:
if header == nil: header = instCopyType(cl, t)
if header == t: header = instCopyType(cl, t)
header.sons[i] = x
propagateToOwner(header, x)
else:
propagateToOwner(header, x)
if header != nil:
if header != t:
# search again after first pass:
result = searchInstTypes(header)
if result != nil: return
@ -243,6 +246,7 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
header = instCopyType(cl, t)
result = newType(tyGenericInst, t.sons[0].owner)
result.flags = header.flags
# be careful not to propagate unnecessary flags here (don't use rawAddSon)
result.sons = @[header.sons[0]]
# ugh need another pass for deeply recursive generic types (e.g. PActor)
@ -409,14 +413,22 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
else: discard
proc initTypeVars(p: PContext, pt: TIdTable, info: TLineInfo): TReplTypeVars =
initIdTable(result.symMap)
copyIdTable(result.typeMap, pt)
initIdTable(result.localCache)
result.info = info
result.c = p
proc replaceTypesInBody*(p: PContext, pt: TIdTable, n: PNode): PNode =
var cl = initTypeVars(p, pt, n.info)
pushInfoContext(n.info)
result = replaceTypeVarsN(cl, n)
popInfoContext()
proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo,
t: PType): PType =
var cl: TReplTypeVars
initIdTable(cl.symMap)
copyIdTable(cl.typeMap, pt)
initIdTable(cl.localCache)
cl.info = info
cl.c = p
var cl = initTypeVars(p, pt, info)
pushInfoContext(info)
result = replaceTypeVarsT(cl, t)
popInfoContext()

View file

@ -343,53 +343,57 @@ proc allowsNil(f: PType): TTypeRelation {.inline.} =
proc inconsistentVarTypes(f, a: PType): bool {.inline.} =
result = f.kind != a.kind and (f.kind == tyVar or a.kind == tyVar)
proc procParamTypeRel(c: var TCandidate, f, a: PType,
result: var TTypeRelation) =
var
m: TTypeRelation
f = f
proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
var f = f
if a.isMetaType:
if f.isMetaType:
# we are matching a generic proc (as proc param)
# We are matching a generic proc (as proc param)
# to another generic type appearing in the proc
# sigunature. there is a change that the target
# signature. There is a change that the target
# type is already fully-determined, so we are
# going to try resolve it
f = generateTypeInstance(c.c, c.bindings, c.call.info, f)
if f == nil or f.isMetaType:
# no luck resolving the type, so the inference fails
result = isNone
return
return isNone
let reverseRel = typeRel(c, a, f)
if reverseRel == isGeneric:
m = isInferred
result = isInferred
inc c.genericMatches
else:
m = typeRel(c, f, a)
result = typeRel(c, f, a)
if m <= isSubtype or inconsistentVarTypes(f, a):
if result <= isSubtype or inconsistentVarTypes(f, a):
result = isNone
return
else:
result = minRel(m, result)
if result == isEqual:
inc c.exactMatches
proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
case a.kind
of tyProc:
if sonsLen(f) != sonsLen(a): return
# Note: We have to do unification for the parameters before the
# return type!
result = isEqual # start with maximum; also correct for no
# params at all
for i in countup(1, sonsLen(f)-1):
procParamTypeRel(c, f.sons[i], a.sons[i], result)
template checkParam(f, a) =
result = minRel(result, procParamTypeRel(c, f, a))
if result == isNone: return
# Note: We have to do unification for the parameters before the
# return type!
for i in 1 .. <f.sonsLen:
checkParam(f.sons[i], a.sons[i])
if f.sons[0] != nil:
if a.sons[0] != nil:
procParamTypeRel(c, f.sons[0], a.sons[0], result)
checkParam(f.sons[0], a.sons[0])
else:
return isNone
elif a.sons[0] != nil:
return isNone
if tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags:
return isNone
elif tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {}:
@ -896,20 +900,27 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
result = isNone
of tyTypeDesc:
if a.kind != tyTypeDesc: return isNone
var prev = PType(idTableGet(c.bindings, f))
if prev == nil:
# proc foo(T: typedesc, x: T)
# when `f` is an unresolved typedesc, `a` could be any
# type, so we should not perform this check earlier
if a.kind != tyTypeDesc: return isNone
if f.base.kind == tyNone:
result = isGeneric
else:
result = typeRel(c, f.base, a.base)
if result != isNone:
put(c.bindings, f, a)
else:
let toMatch = if tfUnresolved in f.flags: a
else: a.base
result = typeRel(c, prev.base, toMatch)
if tfUnresolved in f.flags:
result = typeRel(c, prev.base, a)
elif a.kind == tyTypeDesc:
result = typeRel(c, prev.base, a.base)
else:
result = isNone
of tyStmt:
result = isGeneric
@ -1035,10 +1046,11 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
#result = copyTree(arg)
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
of isInferred, isInferredConvertible:
var prc = if arg.kind in nkLambdaKinds: arg[0].sym
else: arg.sym
let inferred = c.semGenerateInstance(c, prc, m.bindings, arg.info)
result = newSymNode(inferred, arg.info)
if arg.kind in {nkProcDef, nkIteratorDef} + nkLambdaKinds:
result = c.semInferredLambda(c, m.bindings, arg)
else:
let inferred = c.semGenerateInstance(c, arg.sym, m.bindings, arg.info)
result = newSymNode(inferred, arg.info)
if r == isInferredConvertible:
result = implicitConv(nkHiddenStdConv, f, result, m, c)
of isGeneric:
@ -1101,6 +1113,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
# incorrect to simply use the first fitting match. However, to implement
# this correctly is inefficient. We have to copy `m` here to be able to
# roll back the side effects of the unification algorithm.
let c = m.c
var x, y, z: TCandidate
initCandidate(c, x, m.callee)
@ -1122,10 +1135,10 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
x.state = csMatch
of csMatch:
var cmp = cmpCandidates(x, z)
if cmp < 0:
if cmp < 0:
best = i
x = z
elif cmp == 0:
elif cmp == 0:
y = z # z is as good as x
if x.state == csEmpty:
result = nil

View file

@ -1042,7 +1042,8 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind,
of tyEmpty:
result = taField in flags
of tyTypeClasses:
result = true
result = tfGenericTypeParam in t.flags or
taField notin flags
of tyGenericBody, tyGenericParam, tyGenericInvokation,
tyNone, tyForward, tyFromExpr, tyFieldAccessor:
result = false

View file

@ -1025,7 +1025,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
regs[ra].sons[0].flags.incl nfIsRef
of opcNCopyNimNode:
decodeB(nkMetaNode)
setMeta(regs[ra], copyNode(regs[rb]))
setMeta(regs[ra], copyNode(regs[rb].skipMeta))
of opcNCopyNimTree:
decodeB(nkMetaNode)
setMeta(regs[ra], copyTree(regs[rb]))

View file

@ -321,9 +321,18 @@ proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
c.gen(n.sons[2], dest)
c.patch(L1)
proc nilLiteral(n: PNode): PNode =
if n.kind == nkNilLit and n.typ.sym != nil and
n.typ.sym.magic == mPNimrodNode:
let nilo = newNodeIT(nkNilLit, n.info, n.typ)
result = newNodeIT(nkMetaNode, n.info, n.typ)
result.add nilo
else:
result = n
proc rawGenLiteral(c: PCtx; n: PNode): int =
result = c.constants.len
c.constants.add n
c.constants.add n.nilLiteral
internalAssert result < 0x7fff
proc sameConstant*(a, b: PNode): bool =
@ -907,17 +916,20 @@ proc requiresCopy(n: PNode): bool =
proc unneededIndirection(n: PNode): bool =
n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind == tyRef
proc skipDeref(n: PNode): PNode =
if n.kind in {nkDerefExpr, nkHiddenDeref} and unneededIndirection(n.sons[0]):
result = n.sons[0]
else:
result = n
proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
flags: TGenFlags) =
# a nop for certain types
let flags = if opc == opcAddr: flags+{gfAddrOf} else: flags
if unneededIndirection(n.sons[0]):
# consider:
# proc foo(f: var ref int) =
# f = new(int)
# proc blah() =
# var x: ref int
# foo x
#
# The type of 'f' is 'var ref int' and of 'x' is 'ref int'. Hence for
# nkAddr we must not use 'unneededIndirection', but for deref we use it.
if opc != opcAddr and unneededIndirection(n.sons[0]):
gen(c, n.sons[0], dest, flags)
else:
let tmp = c.genx(n.sons[0], flags)
@ -1109,7 +1121,12 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
result = newNodeIT(nkFloatLit, info, t)
of tyVar, tyPointer, tyPtr, tyCString, tySequence, tyString, tyExpr,
tyStmt, tyTypeDesc, tyStatic, tyRef:
result = newNodeIT(nkNilLit, info, t)
if t.sym != nil and t.sym.magic == mPNimrodNode:
let nilo = newNodeIT(nkNilLit, info, t)
result = newNodeIT(nkMetaNode, info, t)
result.add nilo
else:
result = newNodeIT(nkNilLit, info, t)
of tyProc:
if t.callConv != ccClosure:
result = newNodeIT(nkNilLit, info, t)