# # # The Nim Compiler # (c) Copyright 2013 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # # This module implements the semantic checking pass. import ast, options, astalgo, trees, wordrecg, ropes, msgs, idents, renderer, types, platform, magicsys, nversion, nimsets, semfold, modulepaths, importer, procfind, lookups, pragmas, semdata, semtypinst, sigmatch, transf, vmdef, vm, aliases, cgmeth, lambdalifting, evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity, lowerings, plugins/active, lineinfos, int128, isolation_check, typeallowed, modulegraphs, enumtostr, concepts, astmsgs, extccomp import vtables import std/[strtabs, math, tables, intsets, strutils, packedsets] when not defined(leanCompiler): import spawn when defined(nimPreviewSlimSystem): import std/[ formatfloat, assertions, ] # implementation proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode proc semExprNoType(c: PContext, n: PNode): PNode proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode proc semProcBody(c: PContext, n: PNode; expectedType: PType = nil): PNode proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode proc changeType(c: PContext; n: PNode, newType: PType, check: bool) proc semTypeNode(c: PContext, n: PNode, prev: PType): PType proc semStmt(c: PContext, n: PNode; flags: TExprFlags): PNode proc semOpAux(c: PContext, n: PNode) proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) proc addParams(c: PContext, n: PNode, kind: TSymKind) proc maybeAddResult(c: PContext, s: PSym, n: PNode) proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode proc activate(c: PContext, n: PNode) proc semQuoteAst(c: PContext, n: PNode): PNode proc finishMethod(c: PContext, s: PSym) proc evalAtCompileTime(c: PContext, n: PNode): PNode proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode proc semStaticExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode proc semStaticType(c: PContext, childNode: PNode, prev: PType): PType proc semTypeOf(c: PContext; n: PNode): PNode proc computeRequiresInit(c: PContext, t: PType): bool proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) proc hasUnresolvedArgs(c: PContext, n: PNode): bool proc isArrayConstr(n: PNode): bool {.inline.} = result = n.kind == nkBracket and n.typ.skipTypes(abstractInst).kind == tyArray template semIdeForTemplateOrGenericCheck(conf, n, requiresCheck) = # we check quickly if the node is where the cursor is when defined(nimsuggest): if n.info.fileIndex == conf.m.trackPos.fileIndex and n.info.line == conf.m.trackPos.line: requiresCheck = true template semIdeForTemplateOrGeneric(c: PContext; n: PNode; requiresCheck: bool) = # use only for idetools support; this is pretty slow so generics and # templates perform some quick check whether the cursor is actually in # the generic or template. when defined(nimsuggest): if c.config.cmd == cmdIdeTools and requiresCheck: #if optIdeDebug in gGlobalOptions: # echo "passing to safeSemExpr: ", renderTree(n) discard safeSemExpr(c, n) proc fitNodePostMatch(c: PContext, formal: PType, arg: PNode): PNode = let x = arg.skipConv if (x.kind == nkCurly and formal.kind == tySet and formal.base.kind != tyGenericParam) or (x.kind in {nkPar, nkTupleConstr}) and formal.kind notin {tyUntyped, tyBuiltInTypeClass, tyAnything}: changeType(c, x, formal, check=true) result = arg result = skipHiddenSubConv(result, c.graph, c.idgen) proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode = if arg.typ.isNil: localError(c.config, arg.info, "expression has no type: " & renderTree(arg, {renderNoComments})) # error correction: result = copyTree(arg) result.typ = formal elif arg.kind in nkS
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: package ranger.container</title>
</head><body bgcolor="#f0f0f8">

<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="ranger.html"><font color="#ffffff">ranger</font></a>.container</strong></big></big></font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/hut/ranger/ranger/container/__init__.py">/home/hut/ranger/ranger/container/__init__.py</a></font></td></tr></table>
    <p><tt>This&nbsp;package&nbsp;includes&nbsp;container-objects&nbsp;which&nbsp;are<br>
used&nbsp;to&nbsp;manage&nbsp;stored&nbsp;data</tt></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
    
<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="ranger.container.bookmarks.html">bookmarks</a><br>
<a href="ranger.container.commandlist.html">commandlist</a><br>
</td><td width="25%" valign=top><a href="ranger.container.history.html">history</a><br>
<a href="ranger.container.keybuffer.html">keybuffer</a><br>
</td><td width="25%" valign=top><a href="ranger.container.tags.html">tags</a><br>
</td><td width="25%" valign=top></td></tr></table></td></tr></table>
</body></html>
localError(c.config, n.info, errConstExprExpected) proc semConceptBody(c: PContext, n: PNode): PNode include semtypes proc setGenericParamsMisc(c: PContext; n: PNode) = ## used by call defs (procs, templates, macros, ...) to analyse their generic ## params, and store the originals in miscPos for better error reporting. let orig = n[genericParamsPos] doAssert orig.kind in {nkEmpty, nkGenericParams} if n[genericParamsPos].kind == nkEmpty: n[genericParamsPos] = newNodeI(nkGenericParams, n.info) else: # we keep the original params around for better error messages, see # issue https://github.com/nim-lang/Nim/issues/1713 n[genericParamsPos] = semGenericParamList(c, orig) if n[miscPos].kind == nkEmpty: n[miscPos] = newTree(nkBracket, c.graph.emptyNode, orig) else: n[miscPos][1] = orig proc caseBranchMatchesExpr(branch, matched: PNode): bool = result = false for i in 0 ..< branch.len-1: if branch[i].kind == nkRange: if overlap(branch[i], matched): return true elif exprStructuralEquivalent(branch[i], matched): return true proc pickCaseBranchIndex(caseExpr, matched: PNode): int = result = 0 let endsWithElse = caseExpr[^1].kind == nkElse for i in 1.. 0: var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTyp)) asgnExpr.typ = aTyp asgnExpr.sons.add child result = semExpr(c, asgnExpr) else: result = nil of tyArray: let child = defaultNodeField(c, a, aTypSkip[1], checkDefault) if child != nil: let node = newNode(nkIntLit) node.intVal = toInt64(lengthOrd(c.graph.config, aTypSkip)) result = semExpr(c, newTree(nkCall, newSymNode(getSysSym(c.graph, a.info, "arrayWith"), a.info), semExprWithType(c, child), node )) result.typ = aTyp else: result = nil of tyTuple: var hasDefault = false if aTypSkip.n != nil: let children = defaultFieldsForTuple(c, aTypSkip.n, hasDefault, checkDefault) if hasDefault and children.len > 0: result = newNodeI(nkTupleConstr, a.info) result.typ = aTyp result.sons.add children result = semExpr(c, result) else: result = nil else: result = nil of tyRange: if c.graph.config.isDefined("nimPreviewRangeDefault"): result = firstRange(c.config, aTypSkip) else: result = nil else: result = nil proc defaultNodeField(c: PContext, a: PNode, checkDefault: bool): PNode = result = defaultNodeField(c, a, a.typ, checkDefault) include semtempl, semgnrc, semstmts, semexprs proc addCodeForGenerics(c: PContext, n: PNode) = for i in c.lastGenericIdx.. 0: # a generic has been added to `a`: if result.kind != nkEmpty: a.add result result = a result = hloStmt(c, result) if c.config.cmd == cmdInteractive and not isEmptyType(result.typ): result = buildEchoStmt(c, result) if c.config.cmd == cmdIdeTools: appendToModule(c.module, result) trackStmt(c, c.module, result, isTopLevel = true) if optMultiMethods notin c.config.globalOptions and c.config.selectedGC in {gcArc, gcOrc, gcAtomicArc} and Feature.vtables in c.config.features: sortVTableDispatchers(c.graph) if sfMainModule in c.module.flags: collectVTableDispatchers(c.graph) proc recoverContext(c: PContext) = # clean up in case of a semantic error: We clean up the stacks, etc. This is # faster than wrapping every stack operation in a 'try finally' block and # requires far less code. c.currentScope = c.topLevelScope while getCurrOwner(c).kind != skModule: popOwner(c) while c.p != nil and c.p.owner.kind != skModule: c.p = c.p.next proc semWithPContext*(c: PContext, n: PNode): PNode = # no need for an expensive 'try' if we stop after the first error anyway: if c.config.errorMax <= 1: result = semStmtAndGenerateGenerics(c, n) else: let oldContextLen = msgs.getInfoContextLen(c.config) let oldInGenericInst = c.inGenericInst try: result = semStmtAndGenerateGenerics(c, n) except ERecoverableError, ESuggestDone: recoverContext(c) c.inGenericInst = oldInGenericInst msgs.setInfoContextLen(c.config, oldContextLen) if getCurrentException() of ESuggestDone: c.suggestionsMade = true result = nil else: result = newNodeI(nkEmpty, n.info) #if c.config.cmd == cmdIdeTools: findSuggest(c, n) storeRodNode(c, result) proc reportUnusedModules(c: PContext) = if c.config.cmd == cmdM: return for i in 0..high(c.unusedImports): if sfUsed notin c.unusedImports[i][0].flags: message(c.config, c.unusedImports[i][1], warnUnusedImportX, c.unusedImports[i][0].name.s) proc closePContext*(graph: ModuleGraph; c: PContext, n: PNode): PNode = if c.config.cmd == cmdIdeTools and not c.suggestionsMade: suggestSentinel(c) closeScope(c) # close module's scope rawCloseScope(c) # imported symbols; don't check for unused ones! reportUnusedModules(c) result = newNode(nkStmtList) if n != nil: internalError(c.config, n.info, "n is not nil") #result := n; addCodeForGenerics(c, result) if c.module.ast != nil: result.add(c.module.ast) popOwner(c) popProcCon(c) sealRodFile(c)