diff options
Diffstat (limited to 'compiler')
38 files changed, 290 insertions, 141 deletions
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index d9cd5ade1..832f8819a 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -110,14 +110,14 @@ proc iiTablePut*(t: var TIITable, key, val: int) # implementation -proc skipConvAndClosure*(n: PNode): PNode = +proc skipConvCastAndClosure*(n: PNode): PNode = result = n while true: case result.kind of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64, nkClosure: result = result[0] - of nkHiddenStdConv, nkHiddenSubConv, nkConv: + of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast: result = result[1] else: break diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 1eb6caeb3..a3fbeca5f 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2269,7 +2269,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = initLocExpr(p, e[1], a) initLocExpr(p, e[2], b) - let ranged = skipTypes(e[1].typ, {tyGenericInst, tyAlias, tySink, tyVar, tyLent}) + let ranged = skipTypes(e[1].typ, {tyGenericInst, tyAlias, tySink, tyVar, tyLent, tyDistinct}) let res = binaryArithOverflowRaw(p, ranged, a, b, if underlying.kind == tyInt64: fun64[op] else: fun[op]) diff --git a/compiler/cmdlinehelper.nim b/compiler/cmdlinehelper.nim index a415afce9..d5a26717d 100644 --- a/compiler/cmdlinehelper.nim +++ b/compiler/cmdlinehelper.nim @@ -41,7 +41,9 @@ proc initDefinesProg*(self: NimProg, conf: ConfigRef, name: string) = proc processCmdLineAndProjectPath*(self: NimProg, conf: ConfigRef) = self.processCmdLine(passCmd1, "", conf) - if self.supportsStdinFile and conf.projectName == "-": + if conf.projectIsCmd and conf.projectName in ["-", ""]: + handleCmdInput(conf) + elif self.supportsStdinFile and conf.projectName == "-": handleStdinInput(conf) elif conf.projectName != "": try: @@ -59,6 +61,8 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi graph: ModuleGraph): bool = if self.suggestMode: conf.command = "nimsuggest" + if conf.command == "e": + incl(conf.globalOptions, optWasNimscript) loadConfigs(DefaultConfig, cache, conf, graph.idgen) # load all config files if not self.suggestMode: diff --git a/compiler/commands.nim b/compiler/commands.nim index cb7517f06..7a94fb612 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -383,19 +383,33 @@ proc dynlibOverride(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, in expectArg(conf, switch, arg, pass, info) options.inclDynlibOverride(conf, arg) -proc handleStdinInput*(conf: ConfigRef) = - conf.projectName = "stdinfile" +template handleStdinOrCmdInput = conf.projectFull = conf.projectName.AbsoluteFile conf.projectPath = AbsoluteDir getCurrentDir() - conf.projectIsStdin = true if conf.outDir.isEmpty: conf.outDir = getNimcacheDir(conf) +proc handleStdinInput*(conf: ConfigRef) = + conf.projectName = "stdinfile" + conf.projectIsStdin = true + handleStdinOrCmdInput() + +proc handleCmdInput*(conf: ConfigRef) = + conf.projectName = "cmdfile" + handleStdinOrCmdInput() + proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; conf: ConfigRef) = var key, val: string case switch.normalize + of "eval": + expectArg(conf, switch, arg, pass, info) + conf.projectIsCmd = true + conf.cmdInput = arg # can be empty (a nim file with empty content is valid too) + if conf.command == "": + conf.command = "e" # better than "r" as a default + conf.implicitCmd = true of "path", "p": expectArg(conf, switch, arg, pass, info) for path in nimbleSubs(conf, arg): @@ -781,9 +795,6 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "def": expectNoArg(conf, switch, arg, pass, info) conf.ideCmd = ideDef - of "eval": - expectArg(conf, switch, arg, pass, info) - conf.evalExpr = arg of "context": expectNoArg(conf, switch, arg, pass, info) conf.ideCmd = ideCon @@ -936,6 +947,8 @@ proc processSwitch*(pass: TCmdLinePass; p: OptParser; config: ConfigRef) = proc processArgument*(pass: TCmdLinePass; p: OptParser; argsCount: var int; config: ConfigRef): bool = + if argsCount == 0 and config.implicitCmd: + argsCount.inc if argsCount == 0: # nim filename.nims is the same as "nim e filename.nims": if p.key.endsWith(".nims"): diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 7609c96ee..57fdad12a 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -127,6 +127,7 @@ template declareClosures = of meCannotOpenFile: k = errCannotOpenFile of meExpected: k = errXExpected of meGridTableNotImplemented: k = errGridTableNotImplemented + of meMarkdownIllformedTable: k = errMarkdownIllformedTable of meNewSectionExpected: k = errNewSectionExpected of meGeneralParseError: k = errGeneralParseError of meInvalidDirective: k = errInvalidDirectiveX @@ -591,8 +592,10 @@ proc getRoutineBody(n: PNode): PNode = (0 or more) doc comments and runnableExamples. ]## result = n[bodyPos] - if result.kind == nkAsgn and n.len > bodyPos+1 and n[bodyPos+1].kind == nkSym: - doAssert result[0].kind == nkSym + + # This won't be transformed: result.id = 10. Namely result[0].kind != nkSym. + if result.kind == nkAsgn and result[0].kind == nkSym and + n.len > bodyPos+1 and n[bodyPos+1].kind == nkSym: doAssert result.len == 2 result = result[1] diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 11b001f9d..e37e867da 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -627,10 +627,7 @@ proc footprint(conf: ConfigRef; cfile: Cfile): SecureHash = getCompileCFileCmd(conf, cfile)) proc externalFileChanged(conf: ConfigRef; cfile: Cfile): bool = - case conf.backend - of backendInvalid: doAssert false - of backendJs: return false # pre-existing behavior, but not sure it's good - else: discard + if conf.backend == backendJs: return false # pre-existing behavior, but not sure it's good var hashFile = toGeneratedFile(conf, conf.withPackageName(cfile.cname), "sha1") var currentHash = footprint(conf, cfile) @@ -1022,6 +1019,10 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) = lit ",\L\"stdinInput\": " lit $(%* conf.projectIsStdin) + lit ",\L\"projectIsCmd\": " + lit $(%* conf.projectIsCmd) + lit ",\L\"cmdInput\": " + lit $(%* conf.cmdInput) if optRun in conf.globalOptions or isDefined(conf, "nimBetterRun"): lit ",\L\"cmdline\": " @@ -1051,11 +1052,18 @@ proc changeDetectedViaJsonBuildInstructions*(conf: ConfigRef; projectfile: Absol return true if not data.hasKey("stdinInput"): return true let stdinInput = data["stdinInput"].getBool + let projectIsCmd = data["projectIsCmd"].getBool if conf.projectIsStdin or stdinInput: # could optimize by returning false if stdin input was the same, # but I'm not sure how to get full stding input return true + if conf.projectIsCmd or projectIsCmd: + if not (conf.projectIsCmd and projectIsCmd): return true + if not data.hasKey("cmdInput"): return true + let cmdInput = data["cmdInput"].getStr + if cmdInput != conf.cmdInput: return true + let depfilesPairs = data["depfiles"] doAssert depfilesPairs.kind == JArray for p in depfilesPairs: diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 0b893ede8..7e64ebfdc 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -824,14 +824,10 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode = of nkAsgn, nkFastAsgn: if hasDestructor(c, n[0].typ) and n[1].kind notin {nkProcDef, nkDo, nkLambda} and not isCursor(n[0], c): - # rule (self-assignment-removal): - if n[1].kind == nkSym and n[0].kind == nkSym and n[0].sym == n[1].sym: - result = newNodeI(nkEmpty, n.info) - else: - if n[0].kind in {nkDotExpr, nkCheckedFieldExpr}: - cycleCheck(n, c) - assert n[1].kind notin {nkAsgn, nkFastAsgn} - result = moveOrCopy(p(n[0], c, s, mode), n[1], c, s) + if n[0].kind in {nkDotExpr, nkCheckedFieldExpr}: + cycleCheck(n, c) + assert n[1].kind notin {nkAsgn, nkFastAsgn} + result = moveOrCopy(p(n[0], c, s, mode), n[1], c, s) elif isDiscriminantField(n[0]): result = c.genDiscriminantAsgn(s, n) else: @@ -954,8 +950,11 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, isDecl = false): PNod result = c.genSink(dest, p(ri, c, s, consumed), isDecl) of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit: result = c.genSink(dest, p(ri, c, s, consumed), isDecl) - of nkSym: - if isSinkParam(ri.sym) and isLastRead(ri, c): + of nkSym: + if dest.kind == nkSym and dest.sym == ri.sym: + # rule (self-assignment-removal): + result = newNodeI(nkEmpty, dest.info) + elif isSinkParam(ri.sym) and isLastRead(ri, c): # Rule 3: `=sink`(x, z); wasMoved(z) let snk = c.genSink(dest, ri, isDecl) result = newTree(nkStmtList, snk, c.genWasMoved(ri)) diff --git a/compiler/installer.ini b/compiler/installer.ini index 01b7b8c6b..f0756ab3e 100644 --- a/compiler/installer.ini +++ b/compiler/installer.ini @@ -9,7 +9,7 @@ Platforms: """ linux: i386;hppa;ia64;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv64 macosx: i386;amd64;powerpc64 solaris: i386;amd64;sparc;sparc64 - freebsd: i386;amd64;powerpc64;arm;arm64;riscv64;sparc64;mips;mipsel;mips64;mips64el;powerpc + freebsd: i386;amd64;powerpc64;arm;arm64;riscv64;sparc64;mips;mipsel;mips64;mips64el;powerpc;powerpc64el netbsd: i386;amd64 openbsd: i386;amd64;arm;arm64 dragonfly: i386;amd64 diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index d124ae5fe..3a1ef7fbb 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -1049,6 +1049,10 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) = var a, b: TCompRes var xtyp = mapType(p, x.typ) + # disable `[]=` for cstring + if x.kind == nkBracketExpr and x.len >= 2 and x[0].typ.skipTypes(abstractInst).kind == tyCString: + localError(p.config, x.info, "cstring doesn't support `[]=` operator") + gen(p, x, a) genLineDir(p, y) gen(p, y, b) @@ -1070,8 +1074,13 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) = lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc]) else: useMagic(p, "nimCopy") - lineF(p, "nimCopy($1, $2, $3);$n", - [a.res, b.res, genTypeInfo(p, y.typ)]) + # supports proc getF(): var T + if x.kind in {nkHiddenDeref, nkDerefExpr} and x[0].kind in nkCallKinds: + lineF(p, "nimCopy($1, $2, $3);$n", + [a.res, b.res, genTypeInfo(p, y.typ)]) + else: + lineF(p, "$1 = nimCopy($1, $2, $3);$n", + [a.res, b.res, genTypeInfo(p, y.typ)]) of etyBaseIndex: if a.typ != etyBaseIndex or b.typ != etyBaseIndex: if y.kind == nkCall: @@ -2204,11 +2213,17 @@ proc genConv(p: PProc, n: PNode, r: var TCompRes) = if dest.kind == src.kind: # no-op conversion return - case dest.kind: - of tyBool: + let toInt = (dest.kind in tyInt..tyInt32) + let fromInt = (src.kind in tyInt..tyInt32) + let toUint = (dest.kind in tyUInt..tyUInt32) + let fromUint = (src.kind in tyUInt..tyUInt32) + if toUint and (fromInt or fromUint): + let trimmer = unsignedTrimmer(dest.size) + r.res = "($1 $2)" % [r.res, trimmer] + elif dest.kind == tyBool: r.res = "(!!($1))" % [r.res] r.kind = resExpr - of tyInt: + elif toInt: r.res = "(($1)|0)" % [r.res] else: # TODO: What types must we handle here? @@ -2406,8 +2421,7 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) = r.res = "($1 $2)" % [r.res, trimmer] elif toInt: if fromInt: - let trimmer = unsignedTrimmer(dest.size) - r.res = "($1 $2)" % [r.res, trimmer] + return elif fromUint: if src.size == 4 and dest.size == 4: # XXX prevent multi evaluations diff --git a/compiler/lexer.nim b/compiler/lexer.nim index e020236b1..b55dd3585 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -10,7 +10,7 @@ # This scanner is handwritten for efficiency. I used an elegant buffering # scheme which I have not seen anywhere else: # We guarantee that a whole line is in the buffer. Thus only when scanning -# the \n or \r character we have to check wether we need to read in the next +# the \n or \r character we have to check whether we need to read in the next # chunk. (\n or \r already need special handling for incrementing the line # counter; choosing both \n and \r allows the scanner to properly read Unix, # DOS or Macintosh text files, even when it is not the native format. diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 9b6c179db..943dd074e 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -392,6 +392,16 @@ proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode = v.addVar(result, lowerings.newIntLit(c.g, body.info, first)) body.add v +proc declareTempOf(c: var TLiftCtx; body: PNode; value: PNode): PNode = + var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextId(c.idgen), c.fn, c.info) + temp.typ = value.typ + incl(temp.flags, sfFromGeneric) + + var v = newNodeI(nkVarSection, c.info) + result = newSymNode(temp) + v.addVar(result, value) + body.add v + proc addIncStmt(c: var TLiftCtx; body, i: PNode) = let incCall = genBuiltin(c.g, mInc, "inc", i) incCall.add lowerings.newIntLit(c.g, c.info, 1) @@ -508,43 +518,75 @@ proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = discard "strings are atomic and have no inner elements that are to trace" proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = + #[ bug #15753 is really subtle. Usually the classical write barrier for reference + counting looks like this:: + + incRef source # increment first; this takes care of self-assignments1 + decRef dest + dest[] = source + + However, 'decRef dest' might trigger a cycle collection and then the collector + traverses the graph. It is crucial that when it follows the pointers the assignment + 'dest[] = source' already happened so that we don't do trial deletion on a wrong + graph -- this causes premature freeing of objects! The correct barrier looks like + this:: + + let tmp = dest + incRef source + dest[] = source + decRef tmp + + ]# var actions = newNodeI(nkStmtList, c.info) let elemType = t.lastSon createTypeBoundOps(c.g, c.c, elemType, c.info, c.idgen) + let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(elemType) + + let tmp = + if isCyclic and c.kind in {attachedAsgn, attachedSink}: + declareTempOf(c, body, x) + else: + x if isFinal(elemType): - addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr)) + addDestructorCall(c, elemType, actions, genDeref(tmp, nkDerefExpr)) var alignOf = genBuiltin(c.g, mAlignOf, "alignof", newNodeIT(nkType, c.info, elemType)) alignOf.typ = getSysType(c.g, c.info, tyInt) - actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x, alignOf) + actions.add callCodegenProc(c.g, "nimRawDispose", c.info, tmp, alignOf) else: - addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr)) - actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, x) - - let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(elemType) + addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(tmp, nkDerefExpr)) + actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, tmp) var cond: PNode if isCyclic: if isFinal(elemType): let typInfo = genBuiltin(c.g, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType)) typInfo.typ = getSysType(c.g, c.info, tyPointer) - cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, x, typInfo) + cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, tmp, typInfo) else: - cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicDyn", c.info, x) + cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicDyn", c.info, tmp) else: cond = callCodegenProc(c.g, "nimDecRefIsLast", c.info, x) cond.typ = getSysType(c.g, x.info, tyBool) case c.kind of attachedSink: - body.add genIf(c, cond, actions) - body.add newAsgnStmt(x, y) + if isCyclic: + body.add newAsgnStmt(x, y) + body.add genIf(c, cond, actions) + else: + body.add genIf(c, cond, actions) + body.add newAsgnStmt(x, y) of attachedAsgn: body.add genIf(c, y, callCodegenProc(c.g, if isCyclic: "nimIncRefCyclic" else: "nimIncRef", c.info, y)) - body.add genIf(c, cond, actions) - body.add newAsgnStmt(x, y) + if isCyclic: + body.add newAsgnStmt(x, y) + body.add genIf(c, cond, actions) + else: + body.add genIf(c, cond, actions) + body.add newAsgnStmt(x, y) of attachedDestructor: body.add genIf(c, cond, actions) of attachedDeepCopy: assert(false, "cannot happen") @@ -571,19 +613,30 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = let xenv = genBuiltin(c.g, mAccessEnv, "accessEnv", x) xenv.typ = getSysType(c.g, c.info, tyPointer) + let isCyclic = c.g.config.selectedGC == gcOrc + let tmp = + if isCyclic and c.kind in {attachedAsgn, attachedSink}: + declareTempOf(c, body, xenv) + else: + xenv + var actions = newNodeI(nkStmtList, c.info) - actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, xenv) + actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, tmp) let decRefProc = - if c.g.config.selectedGC == gcOrc: "nimDecRefIsLastCyclicDyn" + if isCyclic: "nimDecRefIsLastCyclicDyn" else: "nimDecRefIsLast" - let cond = callCodegenProc(c.g, decRefProc, c.info, xenv) + let cond = callCodegenProc(c.g, decRefProc, c.info, tmp) cond.typ = getSysType(c.g, x.info, tyBool) case c.kind of attachedSink: - body.add genIf(c, cond, actions) - body.add newAsgnStmt(x, y) + if isCyclic: + body.add newAsgnStmt(x, y) + body.add genIf(c, cond, actions) + else: + body.add genIf(c, cond, actions) + body.add newAsgnStmt(x, y) of attachedAsgn: let yenv = genBuiltin(c.g, mAccessEnv, "accessEnv", y) yenv.typ = getSysType(c.g, c.info, tyPointer) @@ -591,8 +644,12 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = if c.g.config.selectedGC == gcOrc: "nimIncRefCyclic" else: "nimIncRef" body.add genIf(c, yenv, callCodegenProc(c.g, incRefProc, c.info, yenv)) - body.add genIf(c, cond, actions) - body.add newAsgnStmt(x, y) + if isCyclic: + body.add newAsgnStmt(x, y) + body.add genIf(c, cond, actions) + else: + body.add genIf(c, cond, actions) + body.add newAsgnStmt(x, y) of attachedDestructor: body.add genIf(c, cond, actions) of attachedDeepCopy: assert(false, "cannot happen") diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim index 759002312..f9ea90caf 100644 --- a/compiler/lineinfos.nim +++ b/compiler/lineinfos.nim @@ -30,42 +30,43 @@ type errUnknown, errInternal, errIllFormedAstX, errCannotOpenFile, errXExpected, errGridTableNotImplemented, + errMarkdownIllformedTable, errGeneralParseError, errNewSectionExpected, errInvalidDirectiveX, errProveInit, # deadcode errGenerated, errUser, - - warnCannotOpenFile = "CannotOpenFile", warnOctalEscape = "OctalEscape", + + warnCannotOpenFile = "CannotOpenFile", warnOctalEscape = "OctalEscape", warnXIsNeverRead = "XIsNeverRead", warnXmightNotBeenInit = "XmightNotBeenInit", warnDeprecated = "Deprecated", warnConfigDeprecated = "ConfigDeprecated", - warnSmallLshouldNotBeUsed = "SmallLshouldNotBeUsed", warnUnknownMagic = "UnknownMagic", - warnRedefinitionOfLabel = "RedefinitionOfLabel", warnUnknownSubstitutionX = "UnknownSubstitutionX", - warnLanguageXNotSupported = "LanguageXNotSupported", warnFieldXNotSupported = "FieldXNotSupported", + warnSmallLshouldNotBeUsed = "SmallLshouldNotBeUsed", warnUnknownMagic = "UnknownMagic", + warnRedefinitionOfLabel = "RedefinitionOfLabel", warnUnknownSubstitutionX = "UnknownSubstitutionX", + warnLanguageXNotSupported = "LanguageXNotSupported", warnFieldXNotSupported = "FieldXNotSupported", warnCommentXIgnored = "CommentXIgnored", warnTypelessParam = "TypelessParam", - warnUseBase = "UseBase", warnWriteToForeignHeap = "WriteToForeignHeap", + warnUseBase = "UseBase", warnWriteToForeignHeap = "WriteToForeignHeap", warnUnsafeCode = "UnsafeCode", warnUnusedImportX = "UnusedImport", warnInheritFromException = "InheritFromException", warnEachIdentIsTuple = "EachIdentIsTuple", warnUnsafeSetLen = "UnsafeSetLen", warnUnsafeDefault = "UnsafeDefault", warnProveInit = "ProveInit", warnProveField = "ProveField", warnProveIndex = "ProveIndex", warnUnreachableElse = "UnreachableElse", warnUnreachableCode = "UnreachableCode", warnStaticIndexCheck = "IndexCheck", warnGcUnsafe = "GcUnsafe", warnGcUnsafe2 = "GcUnsafe2", - warnUninit = "Uninit", warnGcMem = "GcMem", warnDestructor = "Destructor", - warnLockLevel = "LockLevel", warnResultShadowed = "ResultShadowed", - warnInconsistentSpacing = "Spacing", warnCaseTransition = "CaseTransition", - warnCycleCreated = "CycleCreated", warnObservableStores = "ObservableStores", + warnUninit = "Uninit", warnGcMem = "GcMem", warnDestructor = "Destructor", + warnLockLevel = "LockLevel", warnResultShadowed = "ResultShadowed", + warnInconsistentSpacing = "Spacing", warnCaseTransition = "CaseTransition", + warnCycleCreated = "CycleCreated", warnObservableStores = "ObservableStores", warnUser = "User", hintSuccess = "Success", hintSuccessX = "SuccessX", hintCC = "CC", hintLineTooLong = "LineTooLong", hintXDeclaredButNotUsed = "XDeclaredButNotUsed", hintXCannotRaiseY = "XCannotRaiseY", hintConvToBaseNotNeeded = "ConvToBaseNotNeeded", - hintConvFromXtoItselfNotNeeded = "ConvFromXtoItselfNotNeeded", hintExprAlwaysX = "ExprAlwaysX", - hintQuitCalled = "QuitCalled", hintProcessing = "Processing", hintCodeBegin = "CodeBegin", + hintConvFromXtoItselfNotNeeded = "ConvFromXtoItselfNotNeeded", hintExprAlwaysX = "ExprAlwaysX", + hintQuitCalled = "QuitCalled", hintProcessing = "Processing", hintCodeBegin = "CodeBegin", hintCodeEnd = "CodeEnd", hintConf = "Conf", hintPath = "Path", - hintConditionAlwaysTrue = "CondTrue", hintConditionAlwaysFalse = "CondFalse", hintName = "Name", + hintConditionAlwaysTrue = "CondTrue", hintConditionAlwaysFalse = "CondFalse", hintName = "Name", hintPattern = "Pattern", hintExecuting = "Exec", hintLinking = "Link", hintDependency = "Dependency", - hintSource = "Source", hintPerformance = "Performance", hintStackTrace = "StackTrace", + hintSource = "Source", hintPerformance = "Performance", hintStackTrace = "StackTrace", hintGCStats = "GCStats", hintGlobalVar = "GlobalVar", hintExpandMacro = "ExpandMacro", hintUser = "User", hintUserRaw = "UserRaw", hintExtendedContext = "ExtendedContext", hintMsgOrigin = "MsgOrigin", # since 1.3.5 @@ -79,6 +80,7 @@ const errCannotOpenFile: "cannot open '$1'", errXExpected: "'$1' expected", errGridTableNotImplemented: "grid table is not implemented", + errMarkdownIllformedTable: "illformed delimiter row of a markdown table", errGeneralParseError: "general parse error", errNewSectionExpected: "new section expected", errInvalidDirectiveX: "invalid directive: '$1'", diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 40d61b779..e9e704075 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -138,6 +138,7 @@ proc lowerSwap*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNod var temp = newSym(skVar, getIdent(g.cache, genPrefix), nextId(idgen), owner, n.info, owner.options) temp.typ = n[1].typ incl(temp.flags, sfFromGeneric) + incl(temp.flags, sfGenSym) var v = newNodeI(nkVarSection, n.info) let tempAsNode = newSymNode(temp) diff --git a/compiler/main.nim b/compiler/main.nim index af9102414..f9b0dd413 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -260,7 +260,7 @@ proc mainCommand*(graph: ModuleGraph) = conf.setNoteDefaults(warnLockLevel, false) # issue #13218 conf.setNoteDefaults(warnRedefinitionOfLabel, false) # issue #13218 # because currently generates lots of false positives due to conflation - # of labels links in doc comments, eg for random.rand: + # of labels links in doc comments, e.g. for random.rand: # ## * `rand proc<#rand,Rand,Natural>`_ that returns an integer # ## * `rand proc<#rand,Rand,range[]>`_ that returns a float commandDoc2(graph, false) @@ -348,11 +348,12 @@ proc mainCommand*(graph: ModuleGraph) = conf.cmd = cmdInteractive commandInteractive(graph) of "e": - if not fileExists(conf.projectFull): + if conf.projectIsCmd or conf.projectIsStdin: discard + elif not fileExists(conf.projectFull): rawMessage(conf, errGenerated, "NimScript file does not exist: " & conf.projectFull.string) elif not conf.projectFull.string.endsWith(".nims"): rawMessage(conf, errGenerated, "not a NimScript file: " & conf.projectFull.string) - # main NimScript logic handled in cmdlinehelper.nim. + # main NimScript logic handled in `loadConfigs`. of "nop", "help": # prevent the "success" message: conf.cmd = cmdDump diff --git a/compiler/modules.nim b/compiler/modules.nim index 87a6bc507..748b74953 100644 --- a/compiler/modules.nim +++ b/compiler/modules.nim @@ -82,6 +82,13 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): P var flags = flags if fileIdx == graph.config.projectMainIdx2: flags.incl sfMainModule result = graph.getModule(fileIdx) + + template processModuleAux = + var s: PLLStream + if sfMainModule in flags: + if graph.config.projectIsStdin: s = stdin.llStreamOpen + elif graph.config.projectIsCmd: s = llStreamOpen(graph.config.cmdInput) + discard processModule(graph, result, idGeneratorFromModule(result), s) if result == nil: let filename = AbsoluteFile toFullPath(graph.config, fileIdx) result = loadModuleSym(graph, fileIdx, filename) @@ -91,15 +98,13 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): P registerModule(graph, result) else: partialInitModule(result, graph, fileIdx, filename) - discard processModule(graph, result, idGeneratorFromModule(result), - if sfMainModule in flags and graph.config.projectIsStdin: stdin.llStreamOpen else: nil) + processModuleAux() elif graph.isDirty(result): result.flags.excl sfDirty # reset module fields: initStrTable(result.tab) result.ast = nil - discard processModule(graph, result, idGeneratorFromModule(result), - if sfMainModule in flags and graph.config.projectIsStdin: stdin.llStreamOpen else: nil) + processModuleAux() graph.markClientsDirty(fileIdx) proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym = diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 0f5879ff6..be3dc5ec4 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -233,11 +233,11 @@ template toFullPathConsiderDirty*(conf: ConfigRef; info: TLineInfo): string = string toFullPathConsiderDirty(conf, info.fileIndex) type FilenameOption* = enum - foAbs # absolute path, eg: /pathto/bar/foo.nim - foRelProject # relative to project path, eg: ../foo.nim + foAbs # absolute path, e.g.: /pathto/bar/foo.nim + foRelProject # relative to project path, e.g.: ../foo.nim foMagicSauce # magic sauce, shortest of (foAbs, foRelProject) - foName # lastPathPart, eg: foo.nim - foShort # foName without extension, eg: foo + foName # lastPathPart, e.g.: foo.nim + foShort # foName without extension, e.g.: foo foStacktrace # if optExcessiveStackTrace: foAbs else: foName proc toFilenameOption*(conf: ConfigRef, fileIdx: FileIndex, opt: FilenameOption): string = @@ -523,6 +523,7 @@ proc liMessage*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string, let s = if isRaw: arg else: getMessageStr(msg, arg) if not ignoreMsg: let loc = if info != unknownLineInfo: conf.toFileLineCol(info) & " " else: "" + # we could also show `conf.cmdInput` here for `projectIsCmd` var kindmsg = if kind.len > 0: KindFormat % kind else: "" if conf.structuredErrorHook != nil: conf.structuredErrorHook(conf, info, s & kindmsg, sev) diff --git a/compiler/nim.nim b/compiler/nim.nim index 15aeccb33..9ff0eedbc 100644 --- a/compiler/nim.nim +++ b/compiler/nim.nim @@ -79,7 +79,8 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) = self.processCmdLineAndProjectPath(conf) var graph = newModuleGraph(cache, conf) - if not self.loadConfigsAndRunMainCommand(cache, conf, graph): return + if not self.loadConfigsAndRunMainCommand(cache, conf, graph): + return mainCommand(graph) if conf.hasHint(hintGCStats): echo(GC_getStatistics()) #echo(GC_getStatistics()) diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim index 05f234ce6..b6ec1bbc8 100644 --- a/compiler/nimconf.nim +++ b/compiler/nimconf.nim @@ -248,11 +248,16 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef; idgen: if readConfigFile(configPath, cache, conf): configFiles.add(configPath) - template runNimScriptIfExists(path: AbsoluteFile) = + template runNimScriptIfExists(path: AbsoluteFile, isMain = false) = let p = path # eval once - if fileExists(p): + var s: PLLStream + if isMain and optWasNimscript in conf.globalOptions: + if conf.projectIsStdin: s = stdin.llStreamOpen + elif conf.projectIsCmd: s = llStreamOpen(conf.cmdInput) + if s == nil and fileExists(p): s = llStreamOpen(p, fmRead) + if s != nil: configFiles.add(p) - runNimScript(cache, p, idgen, freshDefines = false, conf) + runNimScript(cache, p, idgen, freshDefines = false, conf, s) if optSkipSystemConfigFile notin conf.globalOptions: readConfigFile(getSystemConfigPath(conf, cfg)) @@ -288,19 +293,19 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef; idgen: runNimScriptIfExists(pd / DefaultConfigNims) let scriptFile = conf.projectFull.changeFileExt("nims") - let isMain = scriptFile == conf.projectFull + let scriptIsProj = scriptFile == conf.projectFull template showHintConf = for filename in configFiles: # delayed to here so that `hintConf` is honored rawMessage(conf, hintConf, filename.string) - if isMain: + if scriptIsProj: showHintConf() configFiles.setLen 0 if conf.command != "nimsuggest": - runNimScriptIfExists(scriptFile) + runNimScriptIfExists(scriptFile, isMain = true) else: - if not isMain: - runNimScriptIfExists(scriptFile) + if not scriptIsProj: + runNimScriptIfExists(scriptFile, isMain = true) else: # 'nimsuggest foo.nims' means to just auto-complete the NimScript file discard diff --git a/compiler/options.nim b/compiler/options.nim index 872ab9582..58d09938c 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -246,11 +246,13 @@ type evalMacroCounter*: int exitcode*: int8 cmd*: TCommands # the command + cmdInput*: string # input command + projectIsCmd*: bool # whether we're compiling from a command input + implicitCmd*: bool # whether some flag triggered an implicit `command` selectedGC*: TGCMode # the selected GC (+) exc*: ExceptionSystem verbosity*: int # how verbose the compiler is numberOfProcessors*: int # number of processors - evalExpr*: string # expression for idetools --eval lastCmdTime*: float # when caas is enabled, we measure each command symbolFiles*: SymbolFilesOption @@ -418,7 +420,6 @@ proc newConfigRef*(): ConfigRef = macrosToExpand: newStringTable(modeStyleInsensitive), arcToExpand: newStringTable(modeStyleInsensitive), m: initMsgConfig(), - evalExpr: "", cppDefines: initHashSet[string](), headerFile: "", features: {}, legacyFeatures: {}, foreignPackageNotes: {hintProcessing, warnUnknownMagic, hintQuitCalled, hintExecuting}, diff --git a/compiler/packagehandling.nim b/compiler/packagehandling.nim index 9a3224de2..a781f1d51 100644 --- a/compiler/packagehandling.nim +++ b/compiler/packagehandling.nim @@ -16,7 +16,7 @@ iterator myParentDirs(p: string): string = yield current proc getNimbleFile*(conf: ConfigRef; path: string): string = - ## returns absolute path to nimble file, eg: /pathto/cligen.nimble + ## returns absolute path to nimble file, e.g.: /pathto/cligen.nimble var parents = 0 block packageSearch: for d in myParentDirs(path): @@ -35,7 +35,7 @@ proc getNimbleFile*(conf: ConfigRef; path: string): string = if parents <= 0: break proc getPackageName*(conf: ConfigRef; path: string): string = - ## returns nimble package name, eg: `cligen` + ## returns nimble package name, e.g.: `cligen` let path = getNimbleFile(conf, path) result = path.splitFile.name diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 8affccbf3..1ec0aa112 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -896,7 +896,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, of wMagic: processMagic(c, it, sym) of wCompileTime: noVal(c, it) - incl(sym.flags, sfCompileTime) + if comesFromPush: + if sym.kind in {skProc, skFunc}: + incl(sym.flags, sfCompileTime) + else: + incl(sym.flags, sfCompileTime) #incl(sym.loc.flags, lfNoDecl) of wGlobal: noVal(c, it) diff --git a/compiler/renderer.nim b/compiler/renderer.nim index a4152cf29..765bcded5 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -1226,7 +1226,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = infixArgument(g, n, 1) put(g, tkSpaces, Space) gsub(g, n, 0) # binary operator - # eg: `n1 == n2` decompses as following sum: + # e.g.: `n1 == n2` decompses as following sum: if n.len == 3 and not fits(g, oldLineLen + lsub(g, n[1]) + lsub(g, n[2]) + lsub(g, n[0]) + len(" ")): optNL(g, g.indent + longIndentWid) else: diff --git a/compiler/scriptconfig.nim b/compiler/scriptconfig.nim index ab7e5e0b5..a353278d6 100644 --- a/compiler/scriptconfig.nim +++ b/compiler/scriptconfig.nim @@ -199,7 +199,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string; proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile; idgen: IdGenerator; - freshDefines=true; conf: ConfigRef) = + freshDefines=true; conf: ConfigRef, stream: PLLStream) = let oldSymbolFiles = conf.symbolFiles conf.symbolFiles = disabledSf @@ -226,7 +226,7 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile; graph.vm = vm graph.compileSystemModule() - discard graph.processModule(m, vm.idgen, llStreamOpen(scriptName, fmRead)) + discard graph.processModule(m, vm.idgen, stream) # watch out, "newruntime" can be set within NimScript itself and then we need # to remember this: diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 0446d28c2..70a7e099c 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -326,7 +326,7 @@ proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string = var typeHint = "" if sym == nil: # Perhaps we're in a `compiles(foo.bar)` expression, or - # in a concept, eg: + # in a concept, e.g.: # ExplainedConcept {.explain.} = concept x # x.foo is int # We could use: `(c.config $ n[1].info)` to get more context. diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index b2f0207e7..cb119b3e8 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -432,7 +432,7 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode = m.diagnostics = @[] m.diagnosticsEnabled = true res = typeRel(m, t2, t1) >= isSubtype # isNone - # `res = sameType(t1, t2)` would be wrong, eg for `int is (int|float)` + # `res = sameType(t1, t2)` would be wrong, e.g. for `int is (int|float)` result = newIntNode(nkIntLit, ord(res)) result.typ = n.typ diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 5e6b4dbe2..3368bcfbf 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -527,14 +527,24 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, if n[^1].kind == nkSym and n[^1].sym.kind notin {skProc, skFunc}: localError(c.config, n.info, "finalizer must be a direct reference to a proc") elif optTinyRtti in c.config.globalOptions: - let fin = if n[^1].kind in {nkLambda, nkDo}: n[^1][namePos].sym - else: n[^1].sym - # check if we converted this finalizer into a destructor already: - let t = whereToBindTypeHook(c, fin.typ[1].skipTypes(abstractInst+{tyRef})) - if t != nil and t.attachedOps[attachedDestructor] != nil and t.attachedOps[attachedDestructor].owner == fin: - discard "already turned this one into a finalizer" - else: - bindTypeHook(c, turnFinalizerIntoDestructor(c, fin, n.info), n, attachedDestructor) + let nfin = skipConvCastAndClosure(n[^1]) + let fin = case nfin.kind + of nkSym: nfin.sym + of nkLambda, nkDo: nfin[namePos].sym + else: + localError(c.config, n.info, "finalizer must be a direct reference to a proc") + nil + if fin != nil: + if fin.kind notin {skProc, skFunc}: + # calling convention is checked in codegen + localError(c.config, n.info, "finalizer must be a direct reference to a proc") + + # check if we converted this finalizer into a destructor already: + let t = whereToBindTypeHook(c, fin.typ[1].skipTypes(abstractInst+{tyRef})) + if t != nil and t.attachedOps[attachedDestructor] != nil and t.attachedOps[attachedDestructor].owner == fin: + discard "already turned this one into a finalizer" + else: + bindTypeHook(c, turnFinalizerIntoDestructor(c, fin, n.info), n, attachedDestructor) result = n of mDestroy: result = n diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim index 64a27d1db..42529e1e5 100644 --- a/compiler/semobjconstr.nim +++ b/compiler/semobjconstr.nim @@ -355,15 +355,22 @@ proc computeRequiresInit(c: PContext, t: PType): bool = proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) = var objType = t - while objType.kind != tyObject: + while objType.kind notin {tyObject, tyDistinct}: objType = objType.lastSon assert objType != nil - var constrCtx = initConstrContext(objType, newNodeI(nkObjConstr, info)) - let initResult = semConstructTypeAux(c, constrCtx, {}) - assert constrCtx.missingFields.len > 0 - localError(c.config, info, - "The $1 type doesn't have a default value. The following fields must be initialized: $2.", - [typeToString(t), listSymbolNames(constrCtx.missingFields)]) + if objType.kind == tyObject: + var constrCtx = initConstrContext(objType, newNodeI(nkObjConstr, info)) + let initResult = semConstructTypeAux(c, constrCtx, {}) + assert constrCtx.missingFields.len > 0 + localError(c.config, info, + "The $1 type doesn't have a default value. The following fields must " & + "be initialized: $2.", + [typeToString(t), listSymbolNames(constrCtx.missingFields)]) + elif objType.kind == tyDistinct: + localError(c.config, info, + "The $1 distinct type doesn't have a default value.", [typeToString(t)]) + else: + assert false, "Must not enter here." proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = var t = semTypeNode(c, n[0], nil) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 92a896a38..39ba1b307 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -510,7 +510,7 @@ proc procVarCheck(n: PNode; conf: ConfigRef) = proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) = let n = n.skipConv if paramType.isNil or paramType.kind != tyTypeDesc: - procVarCheck skipConvAndClosure(n), tracked.config + procVarCheck skipConvCastAndClosure(n), tracked.config #elif n.kind in nkSymChoices: # echo "came here" let paramType = paramType.skipTypesOrNil(abstractInst) @@ -556,7 +556,7 @@ proc isTrival(caller: PNode): bool {.inline.} = result = caller.kind == nkSym and caller.sym.magic in {mEqProc, mIsNil, mMove, mWasMoved, mSwap} proc trackOperandForIndirectCall(tracked: PEffects, n: PNode, paramType: PType; caller: PNode) = - let a = skipConvAndClosure(n) + let a = skipConvCastAndClosure(n) let op = a.typ # assume indirect calls are taken here: if op != nil and op.kind == tyProc and n.skipConv.kind != nkNilLit and not isTrival(caller): diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 2a058eee2..f83864775 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -435,7 +435,7 @@ proc semLowerLetVarCustomPragma(c: PContext, a: PNode, n: PNode): PNode = var b = a[0] if b.kind == nkPragmaExpr: if b[1].len != 1: - # we could in future support pragmas w args eg: `var foo {.bar:"goo".} = expr` + # we could in future support pragmas w args e.g.: `var foo {.bar:"goo".} = expr` return nil let nodePragma = b[1][0] # see: `singlePragma` @@ -611,7 +611,8 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = if def.kind == nkEmpty: let actualType = v.typ.skipTypes({tyGenericInst, tyAlias, tyUserTypeClassInst}) - if actualType.kind == tyObject and actualType.requiresInit: + if actualType.kind in {tyObject, tyDistinct} and + actualType.requiresInit: defaultConstructionError(c, v.typ, v.info) else: checkNilable(c, v) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 21667895a..5feb25a59 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -159,7 +159,7 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType = var base = semTypeNode(c, n[1], nil) addSonSkipIntLit(result, base, c.idgen) if base.kind in {tyGenericInst, tyAlias, tySink}: base = lastSon(base) - if base.kind != tyGenericParam: + if base.kind notin {tyGenericParam, tyGenericInvocation}: if not isOrdinalType(base, allowEnumWithHoles = true): localError(c.config, n.info, errOrdinalTypeExpected) elif lengthOrd(c.config, base) > MaxSetElements: @@ -306,7 +306,7 @@ proc semArrayIndex(c: PContext, n: PNode): PType = result = makeRangeWithStaticExpr(c, e) if c.inGenericContext > 0: result.flags.incl tfUnresolved elif e.kind in (nkCallKinds + {nkBracketExpr}) and hasUnresolvedArgs(c, e): - if not isOrdinalType(e.typ): + if not isOrdinalType(e.typ.skipTypes({tyStatic, tyAlias, tyGenericInst, tySink})): localError(c.config, n[1].info, errOrdinalTypeExpected) # This is an int returning call, depending on an # yet unknown generic param (see tgenericshardcases). @@ -1056,7 +1056,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, # disable the bindOnce behavior for the type class result = recurse(paramType.base, true) - of tyAlias, tyOwned: + of tyAlias, tyOwned, tySink: result = recurse(paramType.base) of tySequence, tySet, tyArray, tyOpenArray, diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 2cf2846c0..2e332f105 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1079,7 +1079,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, return typeRel(c, f, lastSon(aOrig), flags) if a.kind == tyGenericInst and - skipTypes(f, {tyVar, tyLent, tySink}).kind notin { + skipTypes(f, {tyStatic, tyVar, tyLent, tySink}).kind notin { tyGenericBody, tyGenericInvocation, tyGenericInst, tyGenericParam} + tyTypeClasses: return typeRel(c, f, lastSon(a), flags) @@ -1555,7 +1555,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, for i in 1..<f.len: let x = PType(idTableGet(c.bindings, genericBody[i-1])) if x == nil: - discard "maybe fine (for eg. a==tyNil)" + discard "maybe fine (for e.g. a==tyNil)" elif x.kind in {tyGenericInvocation, tyGenericParam}: internalError(c.c.graph.config, "wrong instantiated type!") else: @@ -2489,7 +2489,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var Int container = nil else: # we end up here if the argument can be converted into the varargs - # formal (eg. seq[T] -> varargs[T]) but we have already instantiated + # formal (e.g. seq[T] -> varargs[T]) but we have already instantiated # a container #assert arg.kind == nkHiddenStdConv # for 'nim check' # this assertion can be off diff --git a/compiler/sizealignoffsetimpl.nim b/compiler/sizealignoffsetimpl.nim index 2c764fe12..b50777c9e 100644 --- a/compiler/sizealignoffsetimpl.nim +++ b/compiler/sizealignoffsetimpl.nim @@ -258,12 +258,16 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) = of tyArray: computeSizeAlign(conf, typ[1]) - let elemSize = typ[1].size + let elemSize = typ[1].size + let len = lengthOrd(conf, typ[0]) if elemSize < 0: typ.size = elemSize typ.align = int16(elemSize) + elif len < 0: + typ.size = szUnknownSize + typ.align = szUnknownSize else: - typ.size = toInt64Checked(lengthOrd(conf, typ[0]) * int32(elemSize), szTooBigSize) + typ.size = toInt64Checked(len * int32(elemSize), szTooBigSize) typ.align = typ[1].align of tyUncheckedArray: diff --git a/compiler/strutils2.nim b/compiler/strutils2.nim index 6cb50347f..f44b811c7 100644 --- a/compiler/strutils2.nim +++ b/compiler/strutils2.nim @@ -12,7 +12,7 @@ proc dataPointer*[T](a: T): pointer = ## same as C++ `data` that works with std::string, std::vector etc. ## Note: safe to use when a.len == 0 but whether the result is nil or not ## is implementation defined for performance reasons. - # this could be improved with ocmpiler support to avoid the `if`, eg in C++ + # this could be improved with ocmpiler support to avoid the `if`, e.g. in C++ # `&a[0]` is well defined even if a.size() == 0 when T is string | seq: if a.len == 0: nil else: cast[pointer](a[0].unsafeAddr) diff --git a/compiler/typeallowed.nim b/compiler/typeallowed.nim index a8210508c..e163b914a 100644 --- a/compiler/typeallowed.nim +++ b/compiler/typeallowed.nim @@ -260,4 +260,5 @@ proc directViewType*(t: PType): ViewTypeKind = result = noView proc requiresInit*(t: PType): bool = - (t.flags * {tfRequiresInit, tfNotNil} != {}) or classifyViewType(t) != noView + (t.flags * {tfRequiresInit, tfNeedsFullInit, tfNotNil} != {}) or + classifyViewType(t) != noView diff --git a/compiler/types.nim b/compiler/types.nim index 42b7de416..1f2ee9d20 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -23,7 +23,7 @@ type preferTypeName, preferResolved, # fully resolved symbols preferMixed, - # most useful, shows: symbol + resolved symbols if it differs, eg: + # most useful, shows: symbol + resolved symbols if it differs, e.g.: # tuple[a: MyInt{int}, b: float] proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string diff --git a/compiler/varpartitions.nim b/compiler/varpartitions.nim index 34a64c759..63c18d94a 100644 --- a/compiler/varpartitions.nim +++ b/compiler/varpartitions.nim @@ -45,6 +45,8 @@ proc `<`(a, b: AbstractTime): bool {.borrow.} proc inc(x: var AbstractTime; diff = 1) {.borrow.} proc dec(x: var AbstractTime; diff = 1) {.borrow.} +proc `$`(x: AbstractTime): string {.borrow.} + type SubgraphFlag = enum isMutated, # graph might be mutated @@ -397,6 +399,7 @@ proc allRoots(n: PNode; result: var seq[PSym]; followDotExpr = true) = proc destMightOwn(c: var Partitions; dest: var VarIndex; n: PNode) = ## Analyse if 'n' is an expression that owns the data, if so mark 'dest' ## with 'ownsData'. + if n.typ == nil: return case n.kind of nkEmpty, nkCharLit..nkNilLit: # primitive literals including the empty are harmless: @@ -591,33 +594,34 @@ proc deps(c: var Partitions; dest, src: PNode) = for s in sources: connect(c, t, s, dest.info) - if cursorInference in c.goals and src.kind != nkEmpty: - if dest.kind == nkSym: - let vid = variableId(c, dest.sym) + if cursorInference in c.goals and src.kind != nkEmpty: + let d = pathExpr(dest, c.owner) + if d != nil and d.kind == nkSym: + let vid = variableId(c, d.sym) if vid >= 0: destMightOwn(c, c.s[vid], src) for s in sources: - if s == dest.sym: + if s == d.sym: discard "assignments like: it = it.next are fine" elif {sfGlobal, sfThread} * s.flags != {} or hasDisabledAsgn(s.typ): # do not borrow from a global variable or from something with a # disabled assignment operator. c.s[vid].flags.incl preventCursor - when explainCursors: echo "A not a cursor: ", dest.sym, " ", s + when explainCursors: echo "A not a cursor: ", d.sym, " ", s else: let srcid = variableId(c, s) if srcid >= 0: if s.kind notin {skResult, skParam} and ( c.s[srcid].aliveEnd < c.s[vid].aliveEnd): # you cannot borrow from a local that lives shorter than 'vid': - when explainCursors: echo "B not a cursor ", dest.sym, " ", c.s[srcid].aliveEnd, " ", c.s[vid].aliveEnd + when explainCursors: echo "B not a cursor ", d.sym, " ", c.s[srcid].aliveEnd, " ", c.s[vid].aliveEnd c.s[vid].flags.incl preventCursor elif {isReassigned, preventCursor} * c.s[srcid].flags != {}: # you cannot borrow from something that is re-assigned: - when explainCursors: echo "C not a cursor ", dest.sym, " ", c.s[srcid].flags, " reassignedTo ", c.s[srcid].reassignedTo + when explainCursors: echo "C not a cursor ", d.sym, " ", c.s[srcid].flags, " reassignedTo ", c.s[srcid].reassignedTo c.s[vid].flags.incl preventCursor - elif c.s[srcid].reassignedTo != 0 and c.s[srcid].reassignedTo != dest.sym.id: - when explainCursors: echo "D not a cursor ", dest.sym, " reassignedTo ", c.s[srcid].reassignedTo + elif c.s[srcid].reassignedTo != 0 and c.s[srcid].reassignedTo != d.sym.id: + when explainCursors: echo "D not a cursor ", d.sym, " reassignedTo ", c.s[srcid].reassignedTo c.s[vid].flags.incl preventCursor const @@ -900,4 +904,4 @@ proc computeCursors*(s: PSym; n: PNode; config: ConfigRef) = discard "cannot cursor into a graph that is mutated" else: v.sym.flags.incl sfCursor - #echo "this is now a cursor ", v.sym, " ", par.s[rid].flags, " ", config $ v.sym.info + #echo "this is now a cursor ", v.sym, " ", par.s[rid].flags, " ", config $ v.sym.info \ No newline at end of file diff --git a/compiler/vm.nim b/compiler/vm.nim index 761186dc3..a6478f3f0 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -765,7 +765,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = if regs[rb].node.kind == nkRefTy: regs[ra].node = regs[rb].node[0] elif not maybeHandlePtr(regs[rb].node, regs[ra], false): - ## eg: typ.kind = tyObject + ## e.g.: typ.kind = tyObject ensureKind(rkNode) regs[ra].node = regs[rb].node else: @@ -996,7 +996,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = if nb.kind != nc.kind: discard elif (nb == nc) or (nb.kind == nkNilLit): ret = true # intentional elif sameConstant(nb, nc): ret = true - # this also takes care of procvar's, represented as nkTupleConstr, eg (nil, nil) + # this also takes care of procvar's, represented as nkTupleConstr, e.g. (nil, nil) elif nb.kind == nkIntLit and nc.kind == nkIntLit and nb.intVal == nc.intVal: # TODO: nkPtrLit let tb = nb.getTyp let tc = nc.getTyp @@ -2114,6 +2114,9 @@ proc evalStmt*(c: PCtx, n: PNode) = discard execute(c, start) proc evalExpr*(c: PCtx, n: PNode): PNode = + # deadcode + # `nim --eval:"expr"` might've used it at some point for idetools; could + # be revived for nimsuggest let n = transformExpr(c.graph, c.idgen, c.module, n) let start = genExpr(c, n) assert c.code[start].opcode != opcEof diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 61c7fefd9..bcb7faa47 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1122,7 +1122,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = c.freeTemp(d) of mSwap: unused(c, n, dest) - c.gen(lowerSwap(c.graph, n, c.idgen, if c.prc == nil: c.module else: c.prc.sym)) + c.gen(lowerSwap(c.graph, n, c.idgen, if c.prc == nil or c.prc.sym == nil: c.module else: c.prc.sym)) of mIsNil: genUnaryABC(c, n, dest, opcIsNil) of mParseBiggestFloat: if dest < 0: dest = c.getTemp(n.typ) |