diff --git a/compiler/commands.nim b/compiler/commands.nim index f7de0978ed..a37cb348ae 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -930,7 +930,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; if m.len == 0: localError(conf, info, "Cannot resolve filename: " & arg) else: - conf.implicitImports.add m + conf.implicitImports.add(if arg.startsWith(stdPrefix): arg else: m) of "include": expectArg(conf, switch, arg, pass, info) if pass in {passCmd2, passPP}: diff --git a/compiler/importer.nim b/compiler/importer.nim index a02a5e96a1..ac10720f90 100644 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -13,7 +13,7 @@ import ast, msgs, options, idents, lookups, semdata, modulepaths, sigmatch, lineinfos, modulegraphs, wordrecg -from std/strutils import `%`, startsWith +from std/strutils import `%`, startsWith, replace from std/sequtils import addUnique import std/[sets, tables, intsets] @@ -304,9 +304,9 @@ proc myImportModule(c: PContext, n: var PNode, importStmtResult: PNode): PSym = var prefix = "" if realModule.constraint != nil: prefix = realModule.constraint.strVal & "; " message(c.config, n.info, warnDeprecated, prefix & realModule.name.s & " is deprecated") - let moduleName = getModuleName(c.config, n) - if belongsToStdlib(c.graph, result) and not startsWith(moduleName, stdPrefix) and - not startsWith(moduleName, "system/") and not startsWith(moduleName, "packages/"): + let moduleNameNorm = getModuleName(c.config, n).replace("\\", "/") + if belongsToStdlib(c.graph, result) and not startsWith(moduleNameNorm, stdPrefix) and + not startsWith(moduleNameNorm, "system/") and not startsWith(moduleNameNorm, "packages/"): message(c.config, n.info, warnStdPrefix, realModule.name.s) proc suggestMod(n: PNode; s: PSym) = diff --git a/compiler/lexer.nim b/compiler/lexer.nim index 9ebec89be5..9c0b803602 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -1349,7 +1349,7 @@ proc rawGetTok*(L: var Lexer, tok: var Token) = lexMessage(L, errGenerated, "invalid token: no whitespace between number and identifier") of '-': if L.buf[L.bufpos+1] in {'0'..'9'} and - (L.bufpos-1 == 0 or L.buf[L.bufpos-1] in UnaryMinusWhitelist): + (L.bufpos == 0 or L.buf[L.bufpos-1] in UnaryMinusWhitelist): # x)-23 # binary minus # ,-23 # unary minus # \n-78 # unary minus? Yes. diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 15d8b14fe7..32c98cdb31 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -637,6 +637,11 @@ proc renderNotLValue*(n: PNode): string = elif n.kind in {nkHiddenStdConv, nkHiddenSubConv} and n.len == 2: result = typeToString(n.typ.skipTypes(abstractVar)) & "(" & result & ")" +proc isSsoStringIndex*(conf: ConfigRef; n: PNode): bool = + result = conf.usesSso() and n.kind == nkBracketExpr and n.len >= 1 and + n[0].typ != nil and + n[0].typ.skipTypes(abstractVar + abstractInst - {tyTypeDesc}).kind == tyString + proc isAssignable(c: PContext, n: PNode): TAssignableResult = result = parampatterns.isAssignable(c.p.owner, n) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 35901ed960..9c84b721ad 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -809,6 +809,10 @@ proc trackOperandForIndirectCall(tracked: PEffects, n: PNode, formals: PType; ar markSideEffect(tracked, a, n.info) let paramType = if formals != nil and argIndex < formals.signatureLen: formals[argIndex] else: nil if paramType != nil and paramType.kind in {tyVar}: + let arg = n.skipAddr() + if isSsoStringIndex(tracked.config, arg): + localError(tracked.config, arg.info, + "expression '$1' is immutable, not 'var'" % renderNotLValue(arg)) invalidateFacts(tracked.guards, n) if n.kind == nkSym and isLocalSym(tracked, n.sym): makeVolatile(tracked, n.sym) diff --git a/doc/manual.md b/doc/manual.md index 40897ac108..0970d0f5b8 100644 --- a/doc/manual.md +++ b/doc/manual.md @@ -34,10 +34,10 @@ To learn how to compile Nim programs and generate documentation see the [Compiler User Guide](nimc.html) and the [DocGen Tools Guide](docgen.html). The language constructs are explained using an extended BNF, in which `(a)*` -means 0 or more `a`'s, `a+` means 1 or more `a`'s, and `(a)?` means an +means 0 or more *a*'s, `a+` means 1 or more *a*'s, and `(a)?` means an optional *a*. Parentheses may be used to group elements. -`&` is the lookahead operator; `&a` means that an `a` is expected but +`&` is the lookahead operator; `&a` means that an *a* is expected but not consumed. It will be consumed in the following rule. The `|`, `/` symbols are used to mark alternatives and have the lowest @@ -8874,7 +8874,7 @@ Byref pragma The `byref` pragma can be applied to an object or tuple type or a proc param. When applied to a type it instructs the compiler to pass the type by reference (hidden pointer) to procs. When applied to a param it will take precedence, even -if the the type was marked as `bycopy`. When an `importc` type has a `byref` pragma or +if the type was marked as `bycopy`. When an `importc` type has a `byref` pragma or parameters are marked as `byref` in an `importc` proc, these params translate to pointers. When an `importcpp` type has a `byref` pragma, these params translate to C++ references `&`. diff --git a/doc/tut1.md b/doc/tut1.md index 072d8f3ba6..be13f8fbb5 100644 --- a/doc/tut1.md +++ b/doc/tut1.md @@ -1144,7 +1144,7 @@ there is a difference between the `$` and `repr` outputs: echo myCharacter, ":", repr(myCharacter) # --> n:'n' echo myString, ":", repr(myString) - # --> nim:0x10fa8c050"nim" + # --> nim:"nim" echo myInteger, ":", repr(myInteger) # --> 42:42 echo myFloat, ":", repr(myFloat) diff --git a/lib/system.nim b/lib/system.nim index c76d096426..63989b1502 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2694,7 +2694,9 @@ when hasAlloc or defined(nimscript): setLen(x, xl+item.len) var j = xl-1 while j >= i: - when defined(gcArc) or defined(gcOrc) or defined(gcYrc) or defined(gcAtomicArc): + when defined(nimsso): + x[j+item.len] = x[j] + elif defined(gcArc) or defined(gcOrc) or defined(gcYrc) or defined(gcAtomicArc): x[j+item.len] = move x[j] else: shallowCopy(x[j+item.len], x[j]) diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 925f20d906..256c8afd80 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -691,7 +691,7 @@ proc getBigChunk(a: var MemRegion, size: int): PBigChunk = removeChunkFromMatrix2(a, result, fl, sl) if result.size >= size + PageSize: splitChunk(a, result, size) - # set 'used' to to true: + # set 'used' to true: result.prevSize = 1 track("setUsedToFalse", addr result.size, sizeof(int)) sysAssert result.owner == addr a, "getBigChunk: No owner set!" @@ -708,7 +708,7 @@ proc getHugeChunk(a: var MemRegion; size: int): PBigChunk = result.next = nil result.prev = nil result.size = size - # set 'used' to to true: + # set 'used' to true: result.prevSize = 1 result.owner = addr a incl(a, a.chunkStarts, pageIndex(result)) diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim index 08e8798b08..1569d12e14 100644 --- a/lib/system/gc_common.nim +++ b/lib/system/gc_common.nim @@ -143,7 +143,7 @@ when nimCoroutines: proc find(first: var GcStack, bottom: pointer): ptr GcStack = ## Find stack struct based on bottom pointer. If `bottom` is nil then main - ## thread stack is is returned. + ## thread stack is returned. if bottom == nil: return addr(gch.stack) diff --git a/lib/system/indices.nim b/lib/system/indices.nim index 6230b36788..8f20af5ec5 100644 --- a/lib/system/indices.nim +++ b/lib/system/indices.nim @@ -59,16 +59,35 @@ template `[]=`*(s: string; i: int; val: char) = arrPut(s, i, val) template `^^`(s, i: untyped): untyped = (when i is BackwardsIndex: s.len - int(i) else: int(i)) -template spliceImpl(s, a, L, b: typed): untyped = +template spliceStringImpl(s, a, L, b: typed): untyped = # make room for additional elements or cut: var shift = b.len - max(0,L) # ignore negative slice size var newLen = s.len + shift if shift > 0: # enlarge: setLen(s, newLen) - for i in countdown(newLen-1, a+b.len): movingCopy(s[i], s[i-shift]) + for i in countdown(newLen-1, a+b.len): + s[i] = s[i-shift] else: - for i in countup(a+b.len, newLen-1): movingCopy(s[i], s[i-shift]) + for i in countup(a+b.len, newLen-1): + s[i] = s[i-shift] + # cut down: + setLen(s, newLen) + # fill the hole: + for i in 0 ..< b.len: s[a+i] = b[i] + +template spliceSeqImpl(s, a, L, b: typed): untyped = + # make room for additional elements or cut: + var shift = b.len - max(0,L) # ignore negative slice size + var newLen = s.len + shift + if shift > 0: + # enlarge: + setLen(s, newLen) + for i in countdown(newLen-1, a+b.len): + movingCopy(s[i], s[i-shift]) + else: + for i in countup(a+b.len, newLen-1): + movingCopy(s[i], s[i-shift]) # cut down: setLen(s, newLen) # fill the hole: @@ -102,7 +121,7 @@ proc `[]=`*[T, U: Ordinal](s: var string, x: HSlice[T, U], b: string) {.systemRa if L == b.len: for i in 0.. PayloadSize: a.more.fullLen else: aslen let lb = if bslen > PayloadSize: b.more.fullLen else: bslen let minLen = min(la, lb) + let pfxLen = min(minLen, AlwaysAvail) + result = cmpInlineBytes(inlinePtrOf(a), inlinePtrOf(b), pfxLen) + if result != 0: return if minLen <= AlwaysAvail: result = la - lb return diff --git a/tests/compiler/tcmdline_import_std_prefix.nim b/tests/compiler/tcmdline_import_std_prefix.nim new file mode 100644 index 0000000000..9b9eca776f --- /dev/null +++ b/tests/compiler/tcmdline_import_std_prefix.nim @@ -0,0 +1,10 @@ +discard """ + matrix: "-d:nimPreviewSlimSystem --warning:StdPrefix:on --warningAsError:StdPrefix:on --import:std/objectdollar" + output: "(a: 23, b: 45)" +""" + +type Foo = object + a, b: int + +let x = Foo(a: 23, b: 45) +echo x diff --git a/tests/errmsgs/tsso_string_index_var.nim b/tests/errmsgs/tsso_string_index_var.nim new file mode 100644 index 0000000000..401491e0a5 --- /dev/null +++ b/tests/errmsgs/tsso_string_index_var.nim @@ -0,0 +1,13 @@ +discard """ + cmd: "nim check --strings:sso --mm:orc --hints:off $file" + action: "reject" + nimout: ''' +tsso_string_index_var.nim(13, 12) Error: expression 's[0]' is immutable, not 'var' +''' +""" + +proc passByVar(c: var char) = + c = 'x' + +var s = "abc" +passByVar(s[0]) diff --git a/tests/stdlib/tstrformat.nim b/tests/stdlib/tstrformat.nim index 74f23b953b..258c190a1d 100644 --- a/tests/stdlib/tstrformat.nim +++ b/tests/stdlib/tstrformat.nim @@ -544,6 +544,12 @@ proc main() = var x = 5 doAssert fmt"{(x=7;123.456)=:13e}" == "(x=7;123.456)= 1.234560e+02" doAssert x==7 + + block: # binary operators in interpolated expressions + let n = 1 + doAssert &"{n-1}" == "0" + doAssert fmt"{n-1}" == "0" + block: #curly bracket expressions and tuples proc formatValue(result: var string; value:Table|bool|JsonNode; specifier:string) = result.add $value