From 412cd61dabe160708c502e37a48b9c3c7c2c6017 Mon Sep 17 00:00:00 2001 From: Dmitry Atamanov Date: Mon, 16 Apr 2018 20:37:08 +0300 Subject: Fixes #7595 (#7623) * Fixes #7595 * Add brackets * Fix for treeRepr and lispRepr too --- lib/core/macros.nim | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 993756b28..b050eb6c8 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -706,8 +706,7 @@ proc treeRepr*(n: NimNode): string {.compileTime, benign.} = res.add(($n.kind).substr(3)) case n.kind - of nnkEmpty: discard # same as nil node in this representation - of nnkNilLit: res.add(" nil") + of nnkEmpty, nnkNilLit: discard # same as nil node in this representation of nnkCharLit..nnkInt64Lit: res.add(" " & $n.intVal) of nnkFloatLit..nnkFloat64Lit: res.add(" " & $n.floatVal) of nnkStrLit..nnkTripleStrLit, nnkIdent, nnkSym: @@ -730,8 +729,7 @@ proc lispRepr*(n: NimNode): string {.compileTime, benign.} = add(result, "(") case n.kind - of nnkEmpty: discard # same as nil node in this representation - of nnkNilLit: add(result, "nil") + of nnkEmpty, nnkNilLit: discard # same as nil node in this representation of nnkCharLit..nnkInt64Lit: add(result, $n.intVal) of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal) of nnkStrLit..nnkTripleStrLit, nnkCommentStmt, nnkident, nnkSym: @@ -766,7 +764,7 @@ proc astGenRepr*(n: NimNode): string {.compileTime, benign.} = ## See also `repr`, `treeRepr`, and `lispRepr`. const - NodeKinds = {nnkEmpty, nnkNilLit, nnkIdent, nnkSym, nnkNone, nnkCommentStmt} + NodeKinds = {nnkEmpty, nnkIdent, nnkSym, nnkNone, nnkCommentStmt} LitKinds = {nnkCharLit..nnkInt64Lit, nnkFloatLit..nnkFloat64Lit, nnkStrLit..nnkTripleStrLit} proc traverse(res: var string, level: int, n: NimNode) {.benign.} = @@ -775,12 +773,13 @@ proc astGenRepr*(n: NimNode): string {.compileTime, benign.} = res.add("new" & ($n.kind).substr(3) & "Node(") elif n.kind in LitKinds: res.add("newLit(") + elif n.kind == nnkNilLit: + res.add("newNilLit()") else: res.add($n.kind) case n.kind - of nnkEmpty: discard - of nnkNilLit: res.add("nil") + of nnkEmpty, nnkNilLit: discard of nnkCharLit: res.add("'" & $chr(n.intVal) & "'") of nnkIntLit..nnkInt64Lit: res.add($n.intVal) of nnkFloatLit..nnkFloat64Lit: res.add($n.floatVal) -- cgit 1.4.1-2-gfad0 From b2060acbc49ccface03a2350bf1c2e9ad456a75d Mon Sep 17 00:00:00 2001 From: Michał Zieliński Date: Mon, 16 Apr 2018 20:02:26 +0200 Subject: osproc: fix double close on POSIX (#5724) Calling close() in some cases issued two close() syscalls to one FD, which is incorrect in multithreaded programs. --- lib/pure/osproc.nim | 20 ++++++++++++++------ tests/osproc/tclose.nim | 24 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 tests/osproc/tclose.nim diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 555626514..a51b1f5ab 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -1001,13 +1001,21 @@ elif not defined(useNimRtl): {.pop} proc close(p: Process) = - if p.inStream != nil: close(p.inStream) - if p.outStream != nil: close(p.outStream) - if p.errStream != nil: close(p.errStream) if poParentStreams notin p.options: - discard close(p.inHandle) - discard close(p.outHandle) - discard close(p.errHandle) + if p.inStream != nil: + close(p.inStream) + else: + discard close(p.inHandle) + + if p.outStream != nil: + close(p.outStream) + else: + discard close(p.outHandle) + + if p.errStream != nil: + close(p.errStream) + else: + discard close(p.errHandle) proc suspend(p: Process) = if kill(p.id, SIGSTOP) != 0'i32: raiseOsError(osLastError()) diff --git a/tests/osproc/tclose.nim b/tests/osproc/tclose.nim new file mode 100644 index 000000000..d466b466a --- /dev/null +++ b/tests/osproc/tclose.nim @@ -0,0 +1,24 @@ +discard """ + exitcode: 0 +""" + +when defined(linux): + import osproc, os + + proc countFds(): int = + result = 0 + for i in walkDir("/proc/self/fd"): + result += 1 + + let initCount = countFds() + + let p = osproc.startProcess("echo", options={poUsePath}) + assert countFds() == initCount + 3 + p.close + assert countFds() == initCount + + let p1 = osproc.startProcess("echo", options={poUsePath}) + discard p1.inputStream + assert countFds() == initCount + 3 + p.close + assert countFds() == initCount -- cgit 1.4.1-2-gfad0 From 38b2596ff9935e417df6165038c59840352e6a60 Mon Sep 17 00:00:00 2001 From: hlaaf Date: Mon, 16 Apr 2018 22:01:37 +0300 Subject: Add none[T]() as alias to none(T) (#7512) * Add none[T]() as alias to none(T) * Add tests for none[T] * this test shouldn't work anyway --- lib/pure/options.nim | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/pure/options.nim b/lib/pure/options.nim index 8a771be71..aaffb57ca 100644 --- a/lib/pure/options.nim +++ b/lib/pure/options.nim @@ -104,6 +104,10 @@ proc none*(T: typedesc): Option[T] = # the default is the none type discard +proc none*[T]: Option[T] = + ## Alias for ``none(T)``. + none(T) + proc isSome*[T](self: Option[T]): bool {.inline.} = when T is SomePointer: self.val != nil @@ -290,3 +294,7 @@ when isMainModule: let tmp = option(intref) check(sizeof(tmp) == sizeof(ptr int)) + + test "none[T]": + check(none[int]().isNone) + check(none(int) == none[int]()) -- cgit 1.4.1-2-gfad0 From c4d7cc3da0e127b54deb29fa70e225ffa1899dc2 Mon Sep 17 00:00:00 2001 From: Oscar Nihlgård Date: Mon, 16 Apr 2018 21:52:27 +0200 Subject: Generate populationCount const at compile time (#7583) --- compiler/bitsets.nim | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/compiler/bitsets.nim b/compiler/bitsets.nim index 6afd1bd78..e38732877 100644 --- a/compiler/bitsets.nim +++ b/compiler/bitsets.nim @@ -72,24 +72,25 @@ proc bitSetContains(x, y: TBitSet): bool = result = true # Number of set bits for all values of int8 -const populationCount: array[low(int8)..high(int8), int8] = [ - 1.int8, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, - 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7 -] +const populationCount: array[low(int8)..high(int8), int8] = block: + var arr: array[low(int8)..high(int8), int8] + + proc countSetBits(x: int8): int8 = + return + ( x and 0b00000001'i8) + + ((x and 0b00000010'i8) shr 1) + + ((x and 0b00000100'i8) shr 2) + + ((x and 0b00001000'i8) shr 3) + + ((x and 0b00010000'i8) shr 4) + + ((x and 0b00100000'i8) shr 5) + + ((x and 0b01000000'i8) shr 6) + + ((x and 0b10000000'i8) shr 7) + + + for it in low(int8)..high(int8): + arr[it] = countSetBits(it) + + arr proc bitSetCard(x: TBitSet): BiggestInt = for it in x: -- cgit 1.4.1-2-gfad0 From b1b517128e9ab4d1c1e8e16543008cbdecef0468 Mon Sep 17 00:00:00 2001 From: Hendrik Date: Mon, 16 Apr 2018 22:03:24 +0200 Subject: os.setLastModificationTime*(file: string, t: times.Time) (#7543) * add proc toFILETIME to winlean * add proc toWinTime to times * add proc setFileTime to winlean * openHandle with write access * add proc setLastModificationTime to os * moved epochDiff,rateDiff constants and proc toWinTime The constants were moved out of the when defined(JS) block so that they are alsways available in proc toWinTime. proc toWinTime was moved above the # Deprecated procs comment. Best new location seemed to be with the toUnix proc. --- lib/pure/os.nim | 22 +++++++++++++++++++--- lib/pure/times.nim | 8 +++++--- lib/windows/winlean.nim | 11 +++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index a77bee99d..255a9a8de 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -329,20 +329,21 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1", c_free(cast[pointer](r)) when defined(Windows): - proc openHandle(path: string, followSymlink=true): Handle = + proc openHandle(path: string, followSymlink=true, writeAccess=false): Handle = var flags = FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL if not followSymlink: flags = flags or FILE_FLAG_OPEN_REPARSE_POINT + let access = if writeAccess: GENERIC_WRITE else: 0'i32 when useWinUnicode: result = createFileW( - newWideCString(path), 0'i32, + newWideCString(path), access, FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, flags, 0 ) else: result = createFileA( - path, 0'i32, + path, access, FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, flags, 0 ) @@ -1654,3 +1655,18 @@ proc isHidden*(path: string): bool = result = (fileName[0] == '.') and (fileName[3] != '.') {.pop.} + +proc setLastModificationTime*(file: string, t: times.Time) = + ## Sets the `file`'s last modification time. `OSError` is raised in case of + ## an error. + when defined(posix): + let unixt = t.toUnix.int + var timevals = [Timeval(tv_sec: unixt), Timeval(tv_sec: unixt)] # [last access, last modification] + if utimes(file, timevals.addr) != 0: raiseOSError(osLastError()) + else: + let h = openHandle(path = file, writeAccess = true) + if h == INVALID_HANDLE_VALUE: raiseOSError(osLastError()) + var ft = t.toWinTime.toFILETIME + let res = setFileTime(h, nil, nil, ft.addr) + discard h.closeHandle + if res == 0'i32: raiseOSError(osLastError()) \ No newline at end of file diff --git a/lib/pure/times.nim b/lib/pure/times.nim index dc216477b..673f0b030 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -191,6 +191,7 @@ const secondsInHour = 60*60 secondsInDay = 60*60*24 minutesInHour = 60 + rateDiff = 10000000'i64 # 100 nsecs # The number of hectonanoseconds between 1601/01/01 (windows epoch) # and 1970/01/01 (unix epoch). epochDiff = 116444736000000000'i64 @@ -371,6 +372,10 @@ proc toUnix*(t: Time): int64 {.benign, tags: [], raises: [], noSideEffect.} = ## Convert ``t`` to a unix timestamp (seconds since ``1970-01-01T00:00:00Z``). t.seconds +proc toWinTime*(t: Time): int64 = + ## Convert ``t`` to a Windows file time (100-nanosecond intervals since ``1601-01-01T00:00:00Z``). + result = t.seconds * rateDiff + epochDiff + proc isLeapYear*(year: int): bool = ## Returns true if ``year`` is a leap year. year mod 4 == 0 and (year mod 100 != 0 or year mod 400 == 0) @@ -1713,9 +1718,6 @@ when not defined(JS): var clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int - const - rateDiff = 10000000'i64 # 100 nsecs - proc unixTimeToWinTime*(time: CTime): int64 = ## converts a UNIX `Time` (``time_t``) to a Windows file time result = int64(time) * rateDiff + epochDiff diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index f40344396..62bc38da9 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -1086,3 +1086,14 @@ proc ConvertThreadToFiberEx*(param: pointer, flags: int32): pointer {.stdcall, d proc DeleteFiber*(fiber: pointer): void {.stdcall, discardable, dynlib: "kernel32", importc.} proc SwitchToFiber*(fiber: pointer): void {.stdcall, discardable, dynlib: "kernel32", importc.} proc GetCurrentFiber*(): pointer {.stdcall, importc, header: "Windows.h".} + +proc toFILETIME*(t: int64): FILETIME = + ## Convert the Windows file time timestamp ``t`` to ``FILETIME``. + result = FILETIME(dwLowDateTime: cast[DWORD](t), dwHighDateTime: DWORD(t shr 32)) + +type + LPFILETIME* = ptr FILETIME + +proc setFileTime*(hFile: HANDLE, lpCreationTime: LPFILETIME, + lpLastAccessTime: LPFILETIME, lpLastWriteTime: LPFILETIME): WINBOOL + {.stdcall, dynlib: "kernel32", importc: "SetFileTime".} -- cgit 1.4.1-2-gfad0 From 9d4fd1f1bbc0d8a2327699dd07283260d85a5245 Mon Sep 17 00:00:00 2001 From: Arne Döring Date: Tue, 17 Apr 2018 01:23:38 +0200 Subject: eqIdent new returns false on non identifier types (#7629) --- compiler/vm.nim | 18 +++++++++++++----- tests/macros/tmacro1.nim | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/compiler/vm.nim b/compiler/vm.nim index 09226988a..5ef782abd 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1397,8 +1397,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let bNode = regs[rc].node # these are cstring to prevent string copy, and cmpIgnoreStyle from # takes cstring arguments - var aStrVal: cstring - var bStrVal: cstring + var aStrVal: cstring = nil + var bStrVal: cstring = nil # extract strVal from argument ``a`` case aNode.kind of {nkStrLit..nkTripleStrLit}: @@ -1407,8 +1407,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = aStrVal = aNode.ident.s.cstring of nkSym: aStrVal = aNode.sym.name.s.cstring + of nkOpenSymChoice, nkClosedSymChoice: + aStrVal = aNode[0].sym.name.s.cstring else: - stackTrace(c, tos, pc, errFieldXNotFound, "strVal") + discard # extract strVal from argument ``b`` case bNode.kind of {nkStrLit..nkTripleStrLit}: @@ -1417,11 +1419,17 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = bStrVal = bNode.ident.s.cstring of nkSym: bStrVal = bNode.sym.name.s.cstring + of nkOpenSymChoice, nkClosedSymChoice: + bStrVal = bNode[0].sym.name.s.cstring else: - stackTrace(c, tos, pc, errFieldXNotFound, "strVal") + discard # set result regs[ra].intVal = - ord(idents.cmpIgnoreStyle(aStrVal,bStrVal,high(int)) == 0) + if aStrVal != nil and bStrVal != nil: + ord(idents.cmpIgnoreStyle(aStrVal,bStrVal,high(int)) == 0) + else: + 0 + of opcStrToIdent: decodeB(rkNode) if regs[rb].node.kind notin {nkStrLit..nkTripleStrLit}: diff --git a/tests/macros/tmacro1.nim b/tests/macros/tmacro1.nim index 0b83345a1..ac2bf9094 100644 --- a/tests/macros/tmacro1.nim +++ b/tests/macros/tmacro1.nim @@ -27,11 +27,19 @@ import strutils template assertNot(arg: untyped): untyped = assert(not(arg)) + +proc foo(arg: int): void = + discard + +proc foo(arg: float): void = + discard + static: ## test eqIdent let a = "abc_def" let b = "abcDef" let c = "AbcDef" + let d = nnkBracketExpr.newTree() # not an identifier at all assert eqIdent( a , b ) assert eqIdent(newIdentNode(a), b ) @@ -62,3 +70,12 @@ static: assertNot eqIdent(genSym(nskLet, c), newIdentNode( b)) assertNot eqIdent(newIdentNode( c), genSym(nskLet, b)) assertNot eqIdent(genSym(nskLet, c), genSym(nskLet, b)) + + # eqIdent on non identifier at all + assertNot eqIdent(a,d) + + # eqIdent on sym choice + let fooSym = bindSym"foo" + assert fooSym.kind in {nnkOpenSymChoice, nnkClosedSymChoice} + assert fooSym.eqIdent("fOO") + assertNot fooSym.eqIdent("bar") -- cgit 1.4.1-2-gfad0 From a708fda733cb6605ef122ac3be44df59929a6473 Mon Sep 17 00:00:00 2001 From: skilchen Date: Wed, 18 Apr 2018 13:22:05 +0200 Subject: allow stringification of DurationZero (#7625) --- lib/pure/times.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 673f0b030..29492379d 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -353,7 +353,9 @@ proc `$`*(dur: Duration): string = parts.add $quantity & " " & unitStrings[unit] & "s" result = "" - if parts.len == 1: + if parts.len == 0: + result.add "0 nanoseconds" + elif parts.len == 1: result = parts[0] elif parts.len == 2: result = parts[0] & " and " & parts[1] -- cgit 1.4.1-2-gfad0 From 35b0cc67e89a929270e77c07ecbf06f7cced3668 Mon Sep 17 00:00:00 2001 From: treeform Date: Wed, 18 Apr 2018 11:40:11 -0700 Subject: Remove PHP backend. (#7606) * remove php * fix * keep nimphpext * remove targetJS enum --- compiler/jsgen.nim | 562 +++++++++++++-------------------------------- compiler/jstypes.nim | 19 -- compiler/lambdalifting.nim | 4 +- compiler/main.nim | 4 - compiler/nim.nim | 8 - compiler/options.nim | 1 - compiler/rodread.nim | 2 +- lib/system.nim | 21 +- lib/system/jssys.nim | 487 +++++++++++++-------------------------- 9 files changed, 330 insertions(+), 778 deletions(-) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index da5267b93..475508946 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -8,7 +8,6 @@ # # This is the JavaScript code generator. -# Also a PHP code generator. ;-) discard """ The JS code generator contains only 2 tricks: @@ -38,11 +37,8 @@ import from modulegraphs import ModuleGraph type - TTarget = enum - targetJS, targetPHP TJSGen = object of TPassContext module: PSym - target: TTarget sigConflicts: CountTable[SigHash] BModule = ref TJSGen @@ -92,16 +88,12 @@ type module: BModule g: PGlobals beforeRetNeeded: bool - target: TTarget # duplicated here for faster dispatching unique: int # for temp identifier generation blocks: seq[TBlock] extraIndent: int up: PProc # up the call chain; required for closure support declaredGlobals: IntSet -template `|`(a, b: untyped): untyped {.dirty.} = - (if p.target == targetJS: a else: b) - var indent = "\t".rope proc indentLine(p: PProc, r: Rope): Rope = @@ -157,11 +149,8 @@ proc newProc(globals: PGlobals, module: BModule, procDef: PNode, module: module, procDef: procDef, g: globals, - target: module.target, extraIndent: int(procDef != nil)) if procDef != nil: result.prc = procDef.sons[namePos].sym - if result.target == targetPHP: - result.declaredGlobals = initIntSet() proc declareGlobal(p: PProc; id: int; r: Rope) = if p.prc != nil and not p.declaredGlobals.containsOrIncl(id): @@ -208,8 +197,7 @@ proc mapType(typ: PType): TJSTypeKind = of tyUnused, tyOptAsRef: internalError("mapType") proc mapType(p: PProc; typ: PType): TJSTypeKind = - if p.target == targetPHP: result = etyObject - else: result = mapType(typ) + result = mapType(typ) proc mangleName(m: BModule, s: PSym): Rope = proc validJsName(name: string): bool = @@ -236,7 +224,7 @@ proc mangleName(m: BModule, s: PSym): Rope = if result == nil: if s.kind == skField and s.name.s.validJsName: result = rope(s.name.s) - elif m.target == targetJS or s.kind == skTemp: + elif s.kind == skTemp: result = rope(mangle(s.name.s)) else: var x = newStringOfCap(s.name.s.len) @@ -314,7 +302,7 @@ proc useMagic(p: PProc, name: string) = proc isSimpleExpr(p: PProc; n: PNode): bool = # calls all the way down --> can stay expression based if n.kind in nkCallKinds+{nkBracketExpr, nkDotExpr, nkPar, nkTupleConstr} or - (p.target == targetJS and n.kind in {nkObjConstr, nkBracket, nkCurly}): + (n.kind in {nkObjConstr, nkBracket, nkCurly}): for c in n: if not p.isSimpleExpr(c): return false result = true @@ -323,12 +311,9 @@ proc isSimpleExpr(p: PProc; n: PNode): bool = proc getTemp(p: PProc, defineInLocals: bool = true): Rope = inc(p.unique) - if p.target == targetJS: - result = "Tmp$1" % [rope(p.unique)] - if defineInLocals: - add(p.locals, p.indentLine("var $1;$n" % [result])) - else: - result = "$$Tmp$1" % [rope(p.unique)] + result = "Tmp$1" % [rope(p.unique)] + if defineInLocals: + add(p.locals, p.indentLine("var $1;$n" % [result])) proc genAnd(p: PProc, a, b: PNode, r: var TCompRes) = assert r.kind == resNone @@ -477,15 +462,9 @@ proc unsignedTrimmerJS(size: BiggestInt): Rope = of 4: rope">>> 0" else: rope"" -proc unsignedTrimmerPHP(size: BiggestInt): Rope = - case size - of 1: rope"& 0xff" - of 2: rope"& 0xffff" - of 4: rope"& 0xffffffff" - else: rope"" template unsignedTrimmer(size: BiggestInt): Rope = - size.unsignedTrimmerJS | size.unsignedTrimmerPHP + size.unsignedTrimmerJS proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string, reassign = false) = @@ -533,46 +512,18 @@ proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) = of mMulU: binaryUintExpr(p, n, r, "*") of mDivU: binaryUintExpr(p, n, r, "/") of mDivI: - if p.target == targetPHP: - var x, y: TCompRes - gen(p, n.sons[1], x) - gen(p, n.sons[2], y) - r.res = "intval($1 / $2)" % [x.rdLoc, y.rdLoc] - else: - arithAux(p, n, r, op) + arithAux(p, n, r, op) of mModI: - if p.target == targetPHP: - var x, y: TCompRes - gen(p, n.sons[1], x) - gen(p, n.sons[2], y) - r.res = "($1 % $2)" % [x.rdLoc, y.rdLoc] - else: - arithAux(p, n, r, op) + arithAux(p, n, r, op) of mShrI: var x, y: TCompRes gen(p, n.sons[1], x) gen(p, n.sons[2], y) let trimmer = unsignedTrimmer(n[1].typ.skipTypes(abstractRange).size) - if p.target == targetPHP: - # XXX prevent multi evaluations - r.res = "(($1 $2) >= 0) ? (($1 $2) >> $3) : ((($1 $2) & 0x7fffffff) >> $3) | (0x40000000 >> ($3 - 1))" % [x.rdLoc, trimmer, y.rdLoc] - else: - r.res = "(($1 $2) >>> $3)" % [x.rdLoc, trimmer, y.rdLoc] + r.res = "(($1 $2) >>> $3)" % [x.rdLoc, trimmer, y.rdLoc] of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr: - if p.target == targetPHP: - if op == mEnumToStr: - var x: TCompRes - gen(p, n.sons[1], x) - r.res = "$#[$#]" % [genEnumInfoPHP(p, n.sons[1].typ), x.rdLoc] - elif op == mCharToStr: - var x: TCompRes - gen(p, n.sons[1], x) - r.res = "chr($#)" % [x.rdLoc] - else: - gen(p, n.sons[1], r) - else: - arithAux(p, n, r, op) + arithAux(p, n, r, op) else: arithAux(p, n, r, op) r.kind = resExpr @@ -591,7 +542,7 @@ proc genLineDir(p: PProc, n: PNode) = useMagic(p, "endb") lineF(p, "endb($1);$n", [rope(line)]) elif hasFrameInfo(p): - lineF(p, "F.line = $1;$n" | "$$F['line'] = $1;$n", [rope(line)]) + lineF(p, "F.line = $1;$n", [rope(line)]) proc genWhileStmt(p: PProc, n: PNode) = var @@ -604,12 +555,12 @@ proc genWhileStmt(p: PProc, n: PNode) = p.blocks[length].id = -p.unique p.blocks[length].isLoop = true let labl = p.unique.rope - lineF(p, "L$1: while (true) {$n" | "while (true) {$n", [labl]) + lineF(p, "L$1: while (true) {$n", [labl]) p.nested: gen(p, n.sons[0], cond) - lineF(p, "if (!$1) break L$2;$n" | "if (!$1) goto L$2;$n", + lineF(p, "if (!$1) break L$2;$n", [cond.res, labl]) p.nested: genStmt(p, n.sons[1]) - lineF(p, "}$n" | "}L$#:;$n", [labl]) + lineF(p, "}$n", [labl]) setLen(p.blocks, length) proc moveInto(p: PProc, src: var TCompRes, dest: TCompRes) = @@ -653,26 +604,22 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = var i = 1 var length = sonsLen(n) var catchBranchesExist = length > 1 and n.sons[i].kind == nkExceptBranch - if catchBranchesExist and p.target == targetJS: + if catchBranchesExist: add(p.body, "++excHandler;" & tnl) var tmpFramePtr = rope"F" if optStackTrace notin p.options: tmpFramePtr = p.getTemp(true) line(p, tmpFramePtr & " = framePtr;" & tnl) lineF(p, "try {$n", []) - if p.target == targetPHP and p.globals == nil: - p.globals = "global $lastJSError; global $prevJSError;".rope var a: TCompRes gen(p, n.sons[0], a) moveInto(p, a, r) var generalCatchBranchExists = false - let dollar = rope(if p.target == targetJS: "" else: "$") - if p.target == targetJS and catchBranchesExist: + let dollar = rope("") + if catchBranchesExist: addf(p.body, "--excHandler;$n} catch (EXC) {$n var prevJSError = lastJSError;$n" & " lastJSError = EXC;$n --excHandler;$n", []) line(p, "framePtr = $1;$n" % [tmpFramePtr]) - elif p.target == targetPHP: - lineF(p, "} catch (Exception $$EXC) {$n $$prevJSError = $$lastJSError;$n $$lastJSError = $$EXC;$n", []) while i < length and n.sons[i].kind == nkExceptBranch: let blen = sonsLen(n.sons[i]) if blen == 1: @@ -704,19 +651,11 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) = line(p, indent & "reraiseException();" & tnl) line(p, "}" & tnl) addf(p.body, "$1lastJSError = $1prevJSError;$n", [dollar]) - if p.target == targetJS: - line(p, "} finally {" & tnl) - line(p, "framePtr = $1;$n" % [tmpFramePtr]) - if p.target == targetPHP: - # XXX ugly hack for PHP codegen - line(p, "}" & tnl) + line(p, "} finally {" & tnl) + line(p, "framePtr = $1;$n" % [tmpFramePtr]) if i < length and n.sons[i].kind == nkFinally: genStmt(p, n.sons[i].sons[0]) - if p.target == targetPHP: - # XXX ugly hack for PHP codegen - line(p, "if($lastJSError) throw($lastJSError);" & tnl) - if p.target == targetJS: - line(p, "}" & tnl) + line(p, "}" & tnl) proc genRaiseStmt(p: PProc, n: PNode) = genLineDir(p, n) @@ -737,7 +676,7 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) = genLineDir(p, n) gen(p, n.sons[0], cond) let stringSwitch = skipTypes(n.sons[0].typ, abstractVar).kind == tyString - if stringSwitch and p.target == targetJS: + if stringSwitch: useMagic(p, "toJSStr") lineF(p, "switch (toJSStr($1)) {$n", [cond.rdLoc]) else: @@ -789,12 +728,12 @@ proc genBlock(p: PProc, n: PNode, r: var TCompRes) = sym.loc.k = locOther sym.position = idx+1 let labl = p.unique - lineF(p, "L$1: do {$n" | "", [labl.rope]) + lineF(p, "L$1: do {$n", [labl.rope]) setLen(p.blocks, idx + 1) p.blocks[idx].id = - p.unique # negative because it isn't used yet gen(p, n.sons[1], r) setLen(p.blocks, idx) - lineF(p, "} while(false);$n" | "$nL$#:;$n", [labl.rope]) + lineF(p, "} while(false);$n", [labl.rope]) proc genBreakStmt(p: PProc, n: PNode) = var idx: int @@ -812,7 +751,7 @@ proc genBreakStmt(p: PProc, n: PNode) = if idx < 0 or not p.blocks[idx].isLoop: internalError(n.info, "no loop to break") p.blocks[idx].id = abs(p.blocks[idx].id) # label is used - lineF(p, "break L$1;$n" | "goto L$1;$n", [rope(p.blocks[idx].id)]) + lineF(p, "break L$1;$n", [rope(p.blocks[idx].id)]) proc genAsmOrEmitStmt(p: PProc, n: PNode) = genLineDir(p, n) @@ -826,7 +765,6 @@ proc genAsmOrEmitStmt(p: PProc, n: PNode) = let v = it.sym # for backwards compatibility we don't deref syms here :-( if v.kind in {skVar, skLet, skTemp, skConst, skResult, skParam, skForVar}: - if p.target == targetPHP: p.body.add "$" p.body.add mangleName(p.module, v) else: var r: TCompRes @@ -869,24 +807,11 @@ proc generateHeader(p: PProc, typ: PType): Rope = if isCompileTimeOnly(param.typ): continue if result != nil: add(result, ", ") var name = mangleName(p.module, param) - if p.target == targetJS: - add(result, name) - if mapType(param.typ) == etyBaseIndex: - add(result, ", ") - add(result, name) - add(result, "_Idx") - elif not (i == 1 and param.name.s == "this"): - let k = param.typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind - if k in {tyVar, tyRef, tyPtr, tyLent, tyPointer}: - add(result, "&") - add(result, "$") + add(result, name) + if mapType(param.typ) == etyBaseIndex: + add(result, ", ") add(result, name) - # XXX I think something like this is needed for PHP to really support - # ptr "inside" strings and seq - #if mapType(param.typ) == etyBaseIndex: - # add(result, ", $") - # add(result, name) - # add(result, "_Idx") + add(result, "_Idx") proc countJsParams(typ: PType): int = for i in countup(1, sonsLen(typ.n) - 1): @@ -906,21 +831,10 @@ const proc needsNoCopy(p: PProc; y: PNode): bool = result = (y.kind in nodeKindsNeedNoCopy) or - (skipTypes(y.typ, abstractInst).kind in {tyRef, tyPtr, tyLent, tyVar}) or - p.target == targetPHP + (skipTypes(y.typ, abstractInst).kind in {tyRef, tyPtr, tyLent, tyVar}) proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) = var a, b: TCompRes - - if p.target == targetPHP and x.kind == nkBracketExpr and - x[0].typ.skipTypes(abstractVar).kind in {tyString, tyCString}: - var c: TCompRes - gen(p, x[0], a) - gen(p, x[1], b) - gen(p, y, c) - lineF(p, "$#[$#] = chr($#);$n", [a.rdLoc, b.rdLoc, c.rdLoc]) - return - var xtyp = mapType(p, x.typ) if x.kind == nkHiddenDeref and x.sons[0].kind == nkCall and xtyp != etyObject: @@ -968,7 +882,7 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) = proc genAsgn(p: PProc, n: PNode) = genLineDir(p, n) - genAsgnAux(p, n.sons[0], n.sons[1], noCopyNeeded=p.target == targetPHP) + genAsgnAux(p, n.sons[0], n.sons[1], noCopyNeeded=false) proc genFastAsgn(p: PProc, n: PNode) = genLineDir(p, n) @@ -991,12 +905,10 @@ proc genSwap(p: PProc, n: PNode) = let tmp2 = p.getTemp(false) if a.typ != etyBaseIndex or b.typ != etyBaseIndex: internalError(n.info, "genSwap") - lineF(p, "var $1 = $2; $2 = $3; $3 = $1;$n" | - "$1 = $2; $2 = $3; $3 = $1;$n", + lineF(p, "var $1 = $2; $2 = $3; $3 = $1;$n", [tmp, a.address, b.address]) tmp = tmp2 - lineF(p, "var $1 = $2; $2 = $3; $3 = $1;" | - "$1 = $2; $2 = $3; $3 = $1;", + lineF(p, "var $1 = $2; $2 = $3; $3 = $1;", [tmp, a.res, b.res]) proc getFieldPosition(f: PNode): int = @@ -1011,10 +923,7 @@ proc genFieldAddr(p: PProc, n: PNode, r: var TCompRes) = let b = if n.kind == nkHiddenAddr: n.sons[0] else: n gen(p, b.sons[0], a) if skipTypes(b.sons[0].typ, abstractVarRange).kind == tyTuple: - if p.target == targetJS: - r.res = makeJSString( "Field" & $getFieldPosition(b.sons[1]) ) - else: - r.res = getFieldPosition(b.sons[1]).rope + r.res = makeJSString("Field" & $getFieldPosition(b.sons[1])) else: if b.sons[1].kind != nkSym: internalError(b.sons[1].info, "genFieldAddr") var f = b.sons[1].sym @@ -1029,19 +938,13 @@ proc genFieldAccess(p: PProc, n: PNode, r: var TCompRes) = gen(p, n.sons[0], r) let otyp = skipTypes(n.sons[0].typ, abstractVarRange) if otyp.kind == tyTuple: - r.res = ("$1.Field$2" | "$1[$2]") % + r.res = ("$1.Field$2") % [r.res, getFieldPosition(n.sons[1]).rope] else: if n.sons[1].kind != nkSym: internalError(n.sons[1].info, "genFieldAccess") var f = n.sons[1].sym if f.loc.r == nil: f.loc.r = mangleName(p.module, f) - if p.target == targetJS: - r.res = "$1.$2" % [r.res, f.loc.r] - else: - if {sfImportc, sfExportc} * f.flags != {}: - r.res = "$1->$2" % [r.res, f.loc.r] - else: - r.res = "$1['$2']" % [r.res, f.loc.r] + r.res = "$1.$2" % [r.res, f.loc.r] r.kind = resExpr proc genAddr(p: PProc, n: PNode, r: var TCompRes) @@ -1069,13 +972,7 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) = else: first = 0 if optBoundsCheck in p.options: useMagic(p, "chckIndx") - if p.target == targetPHP: - if typ.kind != tyString: - r.res = "chckIndx($1, $2, count($3)-1)-$2" % [b.res, rope(first), a.res] - else: - r.res = "chckIndx($1, $2, strlen($3))-$2" % [b.res, rope(first), a.res] - else: - r.res = "chckIndx($1, $2, $3.length+$2-1)-$2" % [b.res, rope(first), a.res] + r.res = "chckIndx($1, $2, $3.length+$2-1)-$2" % [b.res, rope(first), a.res] elif first != 0: r.res = "($1)-$2" % [b.res, rope(first)] else: @@ -1089,27 +986,11 @@ proc genArrayAccess(p: PProc, n: PNode, r: var TCompRes) = of tyArray, tyOpenArray, tySequence, tyString, tyCString, tyVarargs: genArrayAddr(p, n, r) of tyTuple: - if p.target == targetPHP: - genFieldAccess(p, n, r) - return genFieldAddr(p, n, r) else: internalError(n.info, "expr(nkBracketExpr, " & $ty.kind & ')') r.typ = etyNone if r.res == nil: internalError(n.info, "genArrayAccess") - if p.target == targetPHP: - if n.sons[0].kind in nkCallKinds+{nkStrLit..nkTripleStrLit}: - useMagic(p, "nimAt") - if ty.kind in {tyString, tyCString}: - # XXX this needs to be more like substr($1,$2) - r.res = "ord(nimAt($1, $2))" % [r.address, r.res] - else: - r.res = "nimAt($1, $2)" % [r.address, r.res] - elif ty.kind in {tyString, tyCString}: - # XXX this needs to be more like substr($1,$2) - r.res = "ord(@$1[$2])" % [r.address, r.res] - else: - r.res = "$1[$2]" % [r.address, r.res] - elif ty.kind == tyCString: + if ty.kind == tyCString: r.res = "$1.charCodeAt($2)" % [r.address, r.res] else: r.res = "$1[$2]" % [r.address, r.res] @@ -1122,7 +1003,7 @@ template isIndirect(x: PSym): bool = #(mapType(v.typ) != etyObject) and {sfImportc, sfVolatile, sfExportc} * v.flags == {} and v.kind notin {skProc, skFunc, skConverter, skMethod, skIterator, - skConst, skTemp, skLet} and p.target == targetJS) + skConst, skTemp, skLet}) proc genAddr(p: PProc, n: PNode, r: var TCompRes) = case n.sons[0].kind @@ -1138,8 +1019,6 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) = r.typ = etyNone if isIndirect(s): r.res = s.loc.r & "[0]" - elif p.target == targetPHP: - r.res = "&" & s.loc.r else: r.res = s.loc.r r.address = nil @@ -1180,15 +1059,7 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) = else: internalError(n.sons[0].info, "genAddr: " & $n.sons[0].kind) proc thisParam(p: PProc; typ: PType): PType = - if p.target == targetPHP: - # XXX Might be very useful for the JS backend too? - let typ = skipTypes(typ, abstractInst) - assert(typ.kind == tyProc) - if 1 < sonsLen(typ.n): - assert(typ.n.sons[1].kind == nkSym) - let param = typ.n.sons[1].sym - if param.name.s == "this": - result = param.typ.skipTypes(abstractVar) + discard proc attachProc(p: PProc; content: Rope; s: PSym) = let otyp = thisParam(p, s.typ) @@ -1220,39 +1091,27 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) = of skVar, skLet, skParam, skTemp, skResult, skForVar: if s.loc.r == nil: internalError(n.info, "symbol has no generated name: " & s.name.s) - if p.target == targetJS: - let k = mapType(p, s.typ) - if k == etyBaseIndex: - r.typ = etyBaseIndex - if {sfAddrTaken, sfGlobal} * s.flags != {}: - r.address = "$1[0]" % [s.loc.r] - r.res = "$1[1]" % [s.loc.r] - else: - r.address = s.loc.r - r.res = s.loc.r & "_Idx" - elif isIndirect(s): - r.res = "$1[0]" % [s.loc.r] + let k = mapType(p, s.typ) + if k == etyBaseIndex: + r.typ = etyBaseIndex + if {sfAddrTaken, sfGlobal} * s.flags != {}: + r.address = "$1[0]" % [s.loc.r] + r.res = "$1[1]" % [s.loc.r] else: - r.res = s.loc.r + r.address = s.loc.r + r.res = s.loc.r & "_Idx" + elif isIndirect(s): + r.res = "$1[0]" % [s.loc.r] else: - r.res = "$" & s.loc.r - if sfGlobal in s.flags: - p.declareGlobal(s.id, r.res) + r.res = s.loc.r of skConst: genConstant(p, s) if s.loc.r == nil: internalError(n.info, "symbol has no generated name: " & s.name.s) - if p.target == targetJS: - r.res = s.loc.r - else: - r.res = "$" & s.loc.r - p.declareGlobal(s.id, r.res) + r.res = s.loc.r of skProc, skFunc, skConverter, skMethod: discard mangleName(p.module, s) - if p.target == targetPHP and r.kind != resCallee: - r.res = makeJsString($s.loc.r) - else: - r.res = s.loc.r + r.res = s.loc.r if lfNoDecl in s.loc.flags or s.magic != mNone or {sfImportc, sfInfixCall} * s.flags != {}: discard @@ -1421,10 +1280,8 @@ proc genInfixCall(p: PProc, n: PNode, r: var TCompRes) = r.res = "$1[$2]" % [r.address, r.res] r.address = nil r.typ = etyNone - add(r.res, "." | "->") + add(r.res, ".") var op: TCompRes - if p.target == targetPHP: - op.kind = resCallee gen(p, n.sons[0], op) add(r.res, op.res) genArgs(p, n, r, 2) @@ -1433,28 +1290,21 @@ proc genCall(p: PProc, n: PNode, r: var TCompRes) = if n.sons[0].kind == nkSym and thisParam(p, n.sons[0].typ) != nil: genInfixCall(p, n, r) return - if p.target == targetPHP: - r.kind = resCallee gen(p, n.sons[0], r) genArgs(p, n, r) proc genEcho(p: PProc, n: PNode, r: var TCompRes) = let n = n[1].skipConv internalAssert n.kind == nkBracket - if p.target == targetJS: - useMagic(p, "toJSStr") # Used in rawEcho - useMagic(p, "rawEcho") - elif n.len == 0: - r.kind = resExpr - add(r.res, """print("\n")""") - return - add(r.res, "rawEcho(" | "print(") + useMagic(p, "toJSStr") # Used in rawEcho + useMagic(p, "rawEcho") + add(r.res, "rawEcho(") for i in countup(0, sonsLen(n) - 1): let it = n.sons[i] if it.typ.isCompileTimeOnly: continue - if i > 0: add(r.res, ", " | ".") + if i > 0: add(r.res, ", ") genArgNoParam(p, it, r) - add(r.res, ")" | """."\n")""") + add(r.res, ")") r.kind = resExpr proc putToSeq(s: string, indirect: bool): Rope = @@ -1474,10 +1324,7 @@ proc createRecordVarAux(p: PProc, rec: PNode, excludedFieldIDs: IntSet, output: of nkSym: if rec.sym.id notin excludedFieldIDs: if output.len > 0: output.add(", ") - if p.target == targetJS: - output.addf("$#: ", [mangleName(p.module, rec.sym)]) - else: - output.addf("'$#' => ", [mangleName(p.module, rec.sym)]) + output.addf("$#: ", [mangleName(p.module, rec.sym)]) output.add(createVar(p, rec.sym.typ, false)) else: internalError(rec.info, "createRecordVarAux") @@ -1485,7 +1332,7 @@ proc createObjInitList(p: PProc, typ: PType, excludedFieldIDs: IntSet, output: v var t = typ if objHasTypeField(t): if output.len > 0: output.add(", ") - addf(output, "m_type: $1" | "'m_type' => $#", [genTypeInfo(p, t)]) + addf(output, "m_type: $1", [genTypeInfo(p, t)]) while t != nil: t = t.skipTypes(skipPtrs) createRecordVarAux(p, t.n, excludedFieldIDs, output) @@ -1514,49 +1361,42 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope = of tyRange, tyGenericInst, tyAlias, tySink: result = createVar(p, lastSon(typ), indirect) of tySet: - result = putToSeq("{}" | "array()", indirect) + result = putToSeq("{}", indirect) of tyBool: result = putToSeq("false", indirect) of tyArray: let length = int(lengthOrd(t)) let e = elemType(t) let jsTyp = arrayTypeForElemType(e) - if not jsTyp.isNil and p.target == targetJS: + if not jsTyp.isNil: result = "new $1($2)" % [rope(jsTyp), rope(length)] elif length > 32: useMagic(p, "arrayConstr") # XXX: arrayConstr depends on nimCopy. This line shouldn't be necessary. - if p.target == targetJS: useMagic(p, "nimCopy") + useMagic(p, "nimCopy") result = "arrayConstr($1, $2, $3)" % [rope(length), createVar(p, e, false), genTypeInfo(p, e)] else: - result = rope("[" | "array(") + result = rope("[") var i = 0 while i < length: if i > 0: add(result, ", ") add(result, createVar(p, e, false)) inc(i) - add(result, "]" | ")") + add(result, "]") if indirect: result = "[$1]" % [result] of tyTuple: - if p.target == targetJS: - result = rope("{") - for i in 0.. 0: add(result, ", ") - addf(result, "Field$1: $2", [i.rope, - createVar(p, t.sons[i], false)]) - add(result, "}") - if indirect: result = "[$1]" % [result] - else: - result = rope("array(") - for i in 0.. 0: add(result, ", ") - add(result, createVar(p, t.sons[i], false)) - add(result, ")") + result = rope("{") + for i in 0.. 0: add(result, ", ") + addf(result, "Field$1: $2", [i.rope, + createVar(p, t.sons[i], false)]) + add(result, "}") + if indirect: result = "[$1]" % [result] of tyObject: var initList: Rope createObjInitList(p, t, initIntSet(), initList) - result = ("{$1}" | "array($#)") % [initList] + result = ("{$1}") % [initList] if indirect: result = "[$1]" % [result] of tyVar, tyPtr, tyLent, tyRef: if mapType(p, t) == etyBaseIndex: @@ -1597,7 +1437,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) = varCode = v.constraint.strVal if n.kind == nkEmpty: - lineF(p, varCode & " = $3;$n" | "$$$2 = $3;$n", + lineF(p, varCode & " = $3;$n", [returnType, varName, createVar(p, v.typ, isIndirect(v))]) if v.typ.kind in {tyVar, tyPtr, tyLent, tyRef} and mapType(p, v.typ) == etyBaseIndex: lineF(p, "var $1_Idx = 0;$n", [varName]) @@ -1632,7 +1472,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) = if isIndirect(v): lineF(p, varCode & " = [$3];$n", [returnType, v.loc.r, s]) else: - lineF(p, varCode & " = $3;$n" | "$$$2 = $3;$n", [returnType, v.loc.r, s]) + lineF(p, varCode & " = $3;$n", [returnType, v.loc.r, s]) if useReloadingGuard: lineF(p, "}$n") @@ -1665,18 +1505,14 @@ proc genNew(p: PProc, n: PNode) = var a: TCompRes gen(p, n.sons[1], a) var t = skipTypes(n.sons[1].typ, abstractVar).sons[0] - if p.target == targetJS: - lineF(p, "$1 = $2;$n", [a.res, createVar(p, t, false)]) - else: - lineF(p, "$3 = $2; $1 = &$3;$n", [a.res, createVar(p, t, false), getTemp(p)]) + lineF(p, "$1 = $2;$n", [a.res, createVar(p, t, false)]) proc genNewSeq(p: PProc, n: PNode) = var x, y: TCompRes gen(p, n.sons[1], x) gen(p, n.sons[2], y) let t = skipTypes(n.sons[1].typ, abstractVar).sons[0] - lineF(p, "$1 = new Array($2); for (var i=0;i<$2;++i) {$1[i]=$3;}" | - "$1 = array(); for ($$i=0;$$i<$2;++$$i) {$1[]=$3;}", [ + lineF(p, "$1 = new Array($2); for (var i=0;i<$2;++i) {$1[i]=$3;}", [ x.rdLoc, y.rdLoc, createVar(p, t, false)]) proc genOrd(p: PProc, n: PNode, r: var TCompRes) = @@ -1708,21 +1544,6 @@ proc genConStrStr(p: PProc, n: PNode, r: var TCompRes) = else: r.res.add("$1)" % [a.res]) -proc genConStrStrPHP(p: PProc, n: PNode, r: var TCompRes) = - var a: TCompRes - gen(p, n.sons[1], a) - r.kind = resExpr - if skipTypes(n.sons[1].typ, abstractVarRange).kind == tyChar: - r.res.add("chr($1)" % [a.res]) - else: - r.res.add(a.res) - for i in countup(2, sonsLen(n) - 1): - gen(p, n.sons[i], a) - if skipTypes(n.sons[i].typ, abstractVarRange).kind == tyChar: - r.res.add(".chr($1)" % [a.res]) - else: - r.res.add(".$1" % [a.res]) - proc genToArray(p: PProc; n: PNode; r: var TCompRes) = # we map mArray to PHP's array constructor, a mild hack: var a, b: TCompRes @@ -1766,9 +1587,6 @@ proc genReprAux(p: PProc, n: PNode, r: var TCompRes, magic: string, typ: Rope = add(r.res, ")") proc genRepr(p: PProc, n: PNode, r: var TCompRes) = - if p.target == targetPHP: - localError(n.info, "'repr' not available for PHP backend") - return let t = skipTypes(n.sons[1].typ, abstractVarRange) case t.kind: of tyInt..tyInt64, tyUInt..tyUInt64: @@ -1828,57 +1646,36 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = if not (optOverflowCheck in p.options): unaryExpr(p, n, r, "", "$1 - 1") else: unaryExpr(p, n, r, "subInt", "subInt($1, 1)") of mAppendStrCh: - if p.target == targetJS: - binaryExpr(p, n, r, "addChar", - "if ($1 != null) { addChar($1, $2); } else { $1 = [$2, 0]; }") - else: - binaryExpr(p, n, r, "", "$1 .= chr($2)") + binaryExpr(p, n, r, "addChar", + "if ($1 != null) { addChar($1, $2); } else { $1 = [$2, 0]; }") of mAppendStrStr: - if p.target == targetJS: - if skipTypes(n.sons[1].typ, abstractVarRange).kind == tyCString: - binaryExpr(p, n, r, "", "if ($1 != null) { $1 += $2; } else { $1 = $2; }") - else: - binaryExpr(p, n, r, "", - "if ($1 != null) { $1 = ($1.slice(0, -1)).concat($2); } else { $1 = $2;}") - # XXX: make a copy of $2, because of Javascript's sucking semantics + if skipTypes(n.sons[1].typ, abstractVarRange).kind == tyCString: + binaryExpr(p, n, r, "", "if ($1 != null) { $1 += $2; } else { $1 = $2; }") else: - binaryExpr(p, n, r, "", "$1 .= $2;") + binaryExpr(p, n, r, "", + "if ($1 != null) { $1 = ($1.slice(0, -1)).concat($2); } else { $1 = $2;}") + # XXX: make a copy of $2, because of Javascript's sucking semantics of mAppendSeqElem: - if p.target == targetJS: - var x, y: TCompRes - gen(p, n.sons[1], x) - gen(p, n.sons[2], y) - if needsNoCopy(p, n[2]): - r.res = "if ($1 != null) { $1.push($2); } else { $1 = [$2]; }" % [x.rdLoc, y.rdLoc] - else: - useMagic(p, "nimCopy") - let c = getTemp(p, defineInLocals=false) - lineF(p, "var $1 = nimCopy(null, $2, $3);$n", - [c, y.rdLoc, genTypeInfo(p, n[2].typ)]) - r.res = "if ($1 != null) { $1.push($2); } else { $1 = [$2]; }" % [x.rdLoc, c] - r.kind = resExpr + var x, y: TCompRes + gen(p, n.sons[1], x) + gen(p, n.sons[2], y) + if needsNoCopy(p, n[2]): + r.res = "if ($1 != null) { $1.push($2); } else { $1 = [$2]; }" % [x.rdLoc, y.rdLoc] else: - binaryExpr(p, n, r, "", "$1[] = $2") + useMagic(p, "nimCopy") + let c = getTemp(p, defineInLocals=false) + lineF(p, "var $1 = nimCopy(null, $2, $3);$n", + [c, y.rdLoc, genTypeInfo(p, n[2].typ)]) + r.res = "if ($1 != null) { $1.push($2); } else { $1 = [$2]; }" % [x.rdLoc, c] + r.kind = resExpr of mConStrStr: - if p.target == targetJS: - genConStrStr(p, n, r) - else: - genConStrStrPHP(p, n, r) + genConStrStr(p, n, r) of mEqStr: - if p.target == targetJS: - binaryExpr(p, n, r, "eqStrings", "eqStrings($1, $2)") - else: - binaryExpr(p, n, r, "", "($1 == $2)") + binaryExpr(p, n, r, "eqStrings", "eqStrings($1, $2)") of mLeStr: - if p.target == targetJS: - binaryExpr(p, n, r, "cmpStrings", "(cmpStrings($1, $2) <= 0)") - else: - binaryExpr(p, n, r, "", "($1 <= $2)") + binaryExpr(p, n, r, "cmpStrings", "(cmpStrings($1, $2) <= 0)") of mLtStr: - if p.target == targetJS: - binaryExpr(p, n, r, "cmpStrings", "(cmpStrings($1, $2) < 0)") - else: - binaryExpr(p, n, r, "", "($1 < $2)") + binaryExpr(p, n, r, "cmpStrings", "(cmpStrings($1, $2) < 0)") of mIsNil: unaryExpr(p, n, r, "", "($1 === null)") of mEnumToStr: genRepr(p, n, r) of mNew, mNewFinalize: genNew(p, n) @@ -1886,24 +1683,20 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = of mChr, mArrToSeq: gen(p, n.sons[1], r) # nothing to do of mOrd: genOrd(p, n, r) of mLengthStr: - if p.target == targetJS and n.sons[1].typ.skipTypes(abstractInst).kind == tyCString: + if n.sons[1].typ.skipTypes(abstractInst).kind == tyCString: unaryExpr(p, n, r, "", "($1 != null ? $1.length : 0)") else: - unaryExpr(p, n, r, "", "($1 != null ? $1.length-1 : 0)" | - "strlen($1)") - of mXLenStr: unaryExpr(p, n, r, "", "$1.length-1" | "strlen($1)") + unaryExpr(p, n, r, "", "($1 != null ? $1.length-1 : 0)") + of mXLenStr: unaryExpr(p, n, r, "", "$1.length-1") of mLengthSeq, mLengthOpenArray, mLengthArray: - unaryExpr(p, n, r, "", "($1 != null ? $1.length : 0)" | - "count($1)") + unaryExpr(p, n, r, "", "($1 != null ? $1.length : 0)") of mXLenSeq: - unaryExpr(p, n, r, "", "$1.length" | "count($1)") + unaryExpr(p, n, r, "", "$1.length") of mHigh: if skipTypes(n.sons[1].typ, abstractVar).kind == tyString: - unaryExpr(p, n, r, "", "($1 != null ? ($1.length-2) : -1)" | - "(strlen($1)-1)") + unaryExpr(p, n, r, "", "($1 != null ? ($1.length-2) : -1)") else: - unaryExpr(p, n, r, "", "($1 != null ? ($1.length-1) : -1)" | - "(count($1)-1)") + unaryExpr(p, n, r, "", "($1 != null ? ($1.length-1) : -1)") of mInc: if n[1].typ.skipTypes(abstractRange).kind in tyUInt .. tyUInt64: binaryUintExpr(p, n, r, "+", true) @@ -1917,7 +1710,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2") else: binaryExpr(p, n, r, "subInt", "$1 = subInt($1, $2)") of mSetLengthStr: - binaryExpr(p, n, r, "", "$1.length = $2+1; $1[$1.length-1] = 0" | "$1 = substr($1, 0, $2)") + binaryExpr(p, n, r, "", "$1.length = $2+1; $1[$1.length-1] = 0") of mSetLengthSeq: var x, y: TCompRes gen(p, n.sons[1], x) @@ -1934,50 +1727,23 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = of mPlusSet: binaryExpr(p, n, r, "SetPlus", "SetPlus($1, $2)") of mMinusSet: binaryExpr(p, n, r, "SetMinus", "SetMinus($1, $2)") of mIncl: binaryExpr(p, n, r, "", "$1[$2] = true") - of mExcl: binaryExpr(p, n, r, "", "delete $1[$2]" | "unset $1[$2]") + of mExcl: binaryExpr(p, n, r, "", "delete $1[$2]") of mInSet: - if p.target == targetJS: - binaryExpr(p, n, r, "", "($1[$2] != undefined)") - else: - let s = n.sons[1] - if s.kind == nkCurly: - var a, b, x: TCompRes - gen(p, n.sons[2], x) - r.res = rope("(") - r.kind = resExpr - for i in countup(0, sonsLen(s) - 1): - if i > 0: add(r.res, " || ") - var it = s.sons[i] - if it.kind == nkRange: - gen(p, it.sons[0], a) - gen(p, it.sons[1], b) - addf(r.res, "($1 >= $2 && $1 <= $3)", [x.res, a.res, b.res,]) - else: - gen(p, it, a) - addf(r.res, "($1 == $2)", [x.res, a.res]) - add(r.res, ")") - else: - binaryExpr(p, n, r, "", "isset($1[$2])") + binaryExpr(p, n, r, "", "($1[$2] != undefined)") of mNewSeq: genNewSeq(p, n) - of mNewSeqOfCap: unaryExpr(p, n, r, "", "[]" | "array()") + of mNewSeqOfCap: unaryExpr(p, n, r, "", "[]") of mOf: genOf(p, n, r) of mReset: genReset(p, n) of mEcho: genEcho(p, n, r) of mNLen..mNError, mSlurp, mStaticExec: localError(n.info, errXMustBeCompileTime, n.sons[0].sym.name.s) of mCopyStr: - binaryExpr(p, n, r, "", "($1.slice($2))" | "substr($1, $2)") + binaryExpr(p, n, r, "", "($1.slice($2))") of mCopyStrLast: - if p.target == targetJS: - ternaryExpr(p, n, r, "", "($1.slice($2, ($3)+1).concat(0))") - else: - ternaryExpr(p, n, r, "nimSubstr", "nimSubstr($#, $#, $#)") + ternaryExpr(p, n, r, "", "($1.slice($2, ($3)+1).concat(0))") of mNewString: unaryExpr(p, n, r, "mnewString", "mnewString($1)") of mNewStringOfCap: - if p.target == targetJS: - unaryExpr(p, n, r, "mnewString", "mnewString(0)") - else: - unaryExpr(p, n, r, "", "''") + unaryExpr(p, n, r, "mnewString", "mnewString(0)") of mDotDot: genProcForSymIfNeeded(p, n.sons[0].sym) genCall(p, n, r) @@ -1985,8 +1751,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) = useMagic(p, "nimParseBiggestFloat") genCall(p, n, r) of mArray: - if p.target == targetPHP: genToArray(p, n, r) - else: genCall(p, n, r) + genCall(p, n, r) else: genCall(p, n, r) #else internalError(e.info, 'genMagic: ' + magicToStr[op]); @@ -2003,13 +1768,13 @@ proc genSetConstr(p: PProc, n: PNode, r: var TCompRes) = if it.kind == nkRange: gen(p, it.sons[0], a) gen(p, it.sons[1], b) - addf(r.res, "[$1, $2]" | "array($#,$#)", [a.res, b.res]) + addf(r.res, "[$1, $2]", [a.res, b.res]) else: gen(p, it, a) add(r.res, a.res) add(r.res, ")") # emit better code for constant sets: - if p.target == targetJS and isDeepConstExpr(n): + if isDeepConstExpr(n): inc(p.g.unique) let tmp = rope("ConstSet") & rope(p.g.unique) addf(p.g.constants, "var $1 = $2;$n", [tmp, r.res]) @@ -2017,25 +1782,25 @@ proc genSetConstr(p: PProc, n: PNode, r: var TCompRes) = proc genArrayConstr(p: PProc, n: PNode, r: var TCompRes) = var a: TCompRes - r.res = rope("[" | "array(") + r.res = rope("[") r.kind = resExpr for i in countup(0, sonsLen(n) - 1): if i > 0: add(r.res, ", ") gen(p, n.sons[i], a) add(r.res, a.res) - add(r.res, "]" | ")") + add(r.res, "]") proc genTupleConstr(p: PProc, n: PNode, r: var TCompRes) = var a: TCompRes - r.res = rope("{" | "array(") + r.res = rope("{") r.kind = resExpr for i in countup(0, sonsLen(n) - 1): if i > 0: add(r.res, ", ") var it = n.sons[i] if it.kind == nkExprColonExpr: it = it.sons[1] gen(p, it, a) - addf(r.res, "Field$#: $#" | "$2", [i.rope, a.res]) - r.res.add("}" | ")") + addf(r.res, "Field$#: $#", [i.rope, a.res]) + r.res.add("}") proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) = var a: TCompRes @@ -2059,10 +1824,10 @@ proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) = else: useMagic(p, "nimCopy") a.res = "nimCopy(null, $1, $2)" % [a.rdLoc, genTypeInfo(p, typ)] - addf(initList, "$#: $#" | "'$#' => $#" , [f.loc.r, a.res]) + addf(initList, "$#: $#", [f.loc.r, a.res]) let t = skipTypes(n.typ, abstractInst + skipPtrs) createObjInitList(p, t, fieldIDs, initList) - r.res = ("{$1}" | "array($#)") % [initList] + r.res = ("{$1}") % [initList] proc genConv(p: PProc, n: PNode, r: var TCompRes) = var dest = skipTypes(n.typ, abstractVarRange) @@ -2125,18 +1890,17 @@ proc genReturnStmt(p: PProc, n: PNode) = genStmt(p, n.sons[0]) else: genLineDir(p, n) - lineF(p, "break BeforeRet;$n" | "goto BeforeRet;$n", []) + lineF(p, "break BeforeRet;$n", []) proc frameCreate(p: PProc; procname, filename: Rope): Rope = let frameFmt = - "var F={procname:$1,prev:framePtr,filename:$2,line:0};$n" | - "global $$framePtr; $$F=array('procname'=>$#,'prev'=>$$framePtr,'filename'=>$#,'line'=>0);$n" + "var F={procname:$1,prev:framePtr,filename:$2,line:0};$n" result = p.indentLine(frameFmt % [procname, filename]) - result.add p.indentLine(ropes.`%`("framePtr = F;$n" | "$$framePtr = &$$F;$n", [])) + result.add p.indentLine(ropes.`%`("framePtr = F;$n", [])) proc frameDestroy(p: PProc): Rope = - result = p.indentLine rope(("framePtr = F.prev;" | "$framePtr = $F['prev'];") & tnl) + result = p.indentLine rope(("framePtr = F.prev;") & tnl) proc genProcBody(p: PProc, prc: PSym): Rope = if hasFrameInfo(p): @@ -2146,15 +1910,12 @@ proc genProcBody(p: PProc, prc: PSym): Rope = else: result = nil if p.beforeRetNeeded: - if p.target == targetJS: - result.add p.indentLine(~"BeforeRet: do {$n") - result.add p.body - result.add p.indentLine(~"} while (false);$n") - else: - addF(result, "$# BeforeRet:;$n", [p.body]) + result.add p.indentLine(~"BeforeRet: do {$n") + result.add p.body + result.add p.indentLine(~"} while (false);$n") else: add(result, p.body) - if prc.typ.callConv == ccSysCall and p.target == targetJS: + if prc.typ.callConv == ccSysCall: result = ("try {$n$1} catch (e) {$n" & " alert(\"Unhandled exception:\\n\" + e.message + \"\\n\"$n}") % [result] if hasFrameInfo(p): @@ -2182,7 +1943,7 @@ proc genProc(oldProc: PProc, prc: PSym): Rope = resultSym = prc.ast.sons[resultPos].sym let mname = mangleName(p.module, resultSym) let resVar = createVar(p, resultSym.typ, isIndirect(resultSym)) - resultAsgn = p.indentLine(("var $# = $#;$n" | "$$$# = $#;$n") % [mname, resVar]) + resultAsgn = p.indentLine(("var $# = $#;$n") % [mname, resVar]) if resultSym.typ.kind in {tyVar, tyPtr, tyLent, tyRef} and mapType(p, resultSym.typ) == etyBaseIndex: resultAsgn.add p.indentLine("var $#_Idx = 0;$n" % [mname]) @@ -2267,8 +2028,7 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) = elif fromUint: if src.size == 4 and dest.size == 4: # XXX prevent multi evaluations - r.res = "($1|0)" % [r.res] | - "($1>(float)2147483647?(int)$1-4294967296:$1)" % [r.res] + r.res = "($1|0)" % [r.res] else: let trimmer = unsignedTrimmer(dest.size) let minuend = case dest.size @@ -2304,8 +2064,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = r.res = rope"null" r.kind = resExpr of nkStrLit..nkTripleStrLit: - if skipTypes(n.typ, abstractVarRange).kind == tyString and - p.target == targetJS: + if skipTypes(n.typ, abstractVarRange).kind == tyString: useMagic(p, "makeNimstrLit") r.res = "makeNimstrLit($1)" % [makeJSString(n.strVal)] else: @@ -2342,10 +2101,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = of nkObjConstr: genObjConstr(p, n, r) of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r) of nkAddr, nkHiddenAddr: - if p.target == targetJS: - genAddr(p, n, r) - else: - gen(p, n.sons[0], r) + genAddr(p, n, r) of nkDerefExpr, nkHiddenDeref: genDeref(p, n, r) of nkBracketExpr: genArrayAccess(p, n, r) of nkDotExpr: genFieldAccess(p, n, r) @@ -2422,31 +2178,22 @@ proc newModule(module: PSym): BModule = if globals == nil: globals = newGlobals() -proc genHeader(target: TTarget): Rope = - if target == targetJS: - result = ( - "/* Generated by the Nim Compiler v$1 */$n" & - "/* (c) " & copyrightYear & " Andreas Rumpf */$n$n" & - "var framePtr = null;$n" & - "var excHandler = 0;$n" & - "var lastJSError = null;$n" & - "if (typeof Int8Array === 'undefined') Int8Array = Array;$n" & - "if (typeof Int16Array === 'undefined') Int16Array = Array;$n" & - "if (typeof Int32Array === 'undefined') Int32Array = Array;$n" & - "if (typeof Uint8Array === 'undefined') Uint8Array = Array;$n" & - "if (typeof Uint16Array === 'undefined') Uint16Array = Array;$n" & - "if (typeof Uint32Array === 'undefined') Uint32Array = Array;$n" & - "if (typeof Float32Array === 'undefined') Float32Array = Array;$n" & - "if (typeof Float64Array === 'undefined') Float64Array = Array;$n") % - [rope(VersionAsString)] - else: - result = (" 0: add(s, ", " & tnl) - let extName = if field.ast == nil: field.name.s else: field.ast.strVal - addf(s, "$# => $#$n", - [rope(field.position), makeJSString(extName)]) - prepend(p.g.typeInfo, "$$$# = $#;$n" % [result, s]) - proc genTypeInfo(p: PProc, typ: PType): Rope = - if p.target == targetPHP: - return makeJSString(typeToString(typ, preferModuleInfo)) let t = typ.skipTypes({tyGenericInst, tyDistinct, tyAlias, tySink}) result = "NTI$1" % [rope(t.id)] if containsOrIncl(p.g.typeInfoGenerated, t.id): return diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index d881df5e9..775748425 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -230,7 +230,7 @@ template isIterator*(owner: PSym): bool = proc liftingHarmful(owner: PSym): bool {.inline.} = ## lambda lifting can be harmful for JS-like code generators. let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro - result = gCmd in {cmdCompileToPHP, cmdCompileToJS} and not isCompileTime + result = gCmd == cmdCompileToJS and not isCompileTime proc liftIterSym*(n: PNode; owner: PSym): PNode = # transforms (iter) to (let env = newClosure[iter](); (iter, env)) @@ -813,7 +813,7 @@ proc liftLambdas*(fn: PSym, body: PNode; tooEarly: var bool): PNode = let isCompileTime = sfCompileTime in fn.flags or fn.kind == skMacro if body.kind == nkEmpty or ( - gCmd in {cmdCompileToPHP, cmdCompileToJS} and not isCompileTime) or + gCmd == cmdCompileToJS and not isCompileTime) or fn.skipGenericOwner.kind != skModule: # ignore forward declaration: result = body diff --git a/compiler/main.nim b/compiler/main.nim index 20a715886..c928c81cd 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -94,7 +94,6 @@ proc commandCompileToJS(graph: ModuleGraph; cache: IdentCache) = defineSymbol("nimrod") # 'nimrod' is always defined defineSymbol("ecmascript") # For backward compatibility defineSymbol("js") - if gCmd == cmdCompileToPHP: defineSymbol("nimphp") semanticPasses() registerPass(JSgenPass) compileProject(graph, cache) @@ -189,9 +188,6 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) = of "js", "compiletojs": gCmd = cmdCompileToJS commandCompileToJS(graph, cache) - of "php": - gCmd = cmdCompileToPHP - commandCompileToJS(graph, cache) of "doc0": wantMainModule() gCmd = cmdDoc diff --git a/compiler/nim.nim b/compiler/nim.nim index 89225a5e0..8f3463be9 100644 --- a/compiler/nim.nim +++ b/compiler/nim.nim @@ -90,14 +90,6 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) = ex = quoteShell( completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir)) execExternalProgram(findNodeJs() & " " & ex & ' ' & commands.arguments) - elif gCmd == cmdCompileToPHP: - var ex: string - if options.outFile.len > 0: - ex = options.outFile.prependCurDir.quoteShell - else: - ex = quoteShell( - completeCFilePath(changeFileExt(gProjectFull, "php").prependCurDir)) - execExternalProgram("php " & ex & ' ' & commands.arguments) else: var binPath: string if options.outFile.len > 0: diff --git a/compiler/options.nim b/compiler/options.nim index 69a555b3f..93a3f1796 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -81,7 +81,6 @@ type # **keep binary compatible** cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToJS, - cmdCompileToPHP, cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc, cmdGenDepend, cmdDump, cmdCheck, # semantic checking for whole project diff --git a/compiler/rodread.nim b/compiler/rodread.nim index 84f175cb5..4ada148c5 100644 --- a/compiler/rodread.nim +++ b/compiler/rodread.nim @@ -586,7 +586,7 @@ proc cmdChangeTriggersRecompilation(old, new: TCommands): bool = # new command forces us to consider it here :-) case old of cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, - cmdCompileToJS, cmdCompileToPHP, cmdCompileToLLVM: + cmdCompileToJS, cmdCompileToLLVM: if new in {cmdDoc, cmdCheck, cmdIdeTools, cmdPretty, cmdDef, cmdInteractive}: return false diff --git a/lib/system.nim b/lib/system.nim index 3761a35f8..9f0b11597 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2404,7 +2404,7 @@ proc `==` *[T](x, y: seq[T]): bool {.noSideEffect.} = if x.isNil and y.isNil: return true else: - when not defined(JS) or defined(nimphp): + when not defined(JS): proc seqToPtr[T](x: seq[T]): pointer {.inline, nosideeffect.} = result = cast[pointer](x) else: @@ -2766,17 +2766,14 @@ type when defined(JS): proc add*(x: var string, y: cstring) {.asmNoStackFrame.} = - when defined(nimphp): - asm """`x` .= `y`;""" - else: - asm """ - var len = `x`[0].length-1; - for (var i = 0; i < `y`.length; ++i) { - `x`[0][len] = `y`.charCodeAt(i); - ++len; - } - `x`[0][len] = 0 - """ + asm """ + var len = `x`[0].length-1; + for (var i = 0; i < `y`.length; ++i) { + `x`[0][len] = `y`.charCodeAt(i); + ++len; + } + `x`[0][len] = 0 + """ proc add*(x: var cstring, y: cstring) {.magic: "AppendStrStr".} elif hasAlloc: diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index 8c3175eac..56a9f6575 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -48,10 +48,7 @@ proc nimCharToStr(x: char): string {.compilerproc.} = result[0] = x proc isNimException(): bool {.asmNoStackFrame.} = - when defined(nimphp): - asm "return isset(`lastJSError`['m_type']);" - else: - asm "return `lastJSError`.m_type;" + asm "return `lastJSError`.m_type;" proc getCurrentException*(): ref Exception {.compilerRtl, benign.} = if isNimException(): result = cast[ref Exception](lastJSError) @@ -61,15 +58,14 @@ proc getCurrentExceptionMsg*(): string = if isNimException(): return cast[Exception](lastJSError).msg else: - when not defined(nimphp): - var msg: cstring - {.emit: """ - if (`lastJSError`.message !== undefined) { - `msg` = `lastJSError`.message; - } - """.} - if not msg.isNil: - return $msg + var msg: cstring + {.emit: """ + if (`lastJSError`.message !== undefined) { + `msg` = `lastJSError`.message; + } + """.} + if not msg.isNil: + return $msg return "" proc auxWriteStackTrace(f: PCallFrame): string = @@ -140,12 +136,9 @@ proc raiseException(e: ref Exception, ename: cstring) {. e.name = ename if excHandler == 0: unhandledException(e) - when defined(nimphp): - asm """throw new Exception($`e`["message"]);""" - else: - when NimStackTrace: - e.trace = rawWriteStackTrace() - asm "throw `e`;" + when NimStackTrace: + e.trace = rawWriteStackTrace() + asm "throw `e`;" proc reraiseException() {.compilerproc, asmNoStackFrame.} = if lastJSError == nil: @@ -173,57 +166,35 @@ proc raiseFieldError(f: string) {.compilerproc, noreturn.} = raise newException(FieldError, f & " is not accessible") proc setConstr() {.varargs, asmNoStackFrame, compilerproc.} = - when defined(nimphp): - asm """ - $args = func_get_args(); - $result = array(); - foreach ($args as $x) { - if (is_array($x)) { - for ($j = $x[0]; $j <= $x[1]; $j++) { - $result[$j] = true; - } - } else { - $result[$x] = true; - } - } - return $result; - """ - else: - asm """ - var result = {}; - for (var i = 0; i < arguments.length; ++i) { - var x = arguments[i]; - if (typeof(x) == "object") { - for (var j = x[0]; j <= x[1]; ++j) { - result[j] = true; - } - } else { - result[x] = true; + asm """ + var result = {}; + for (var i = 0; i < arguments.length; ++i) { + var x = arguments[i]; + if (typeof(x) == "object") { + for (var j = x[0]; j <= x[1]; ++j) { + result[j] = true; } + } else { + result[x] = true; } - return result; - """ - -proc makeNimstrLit(c: cstring): string {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - {.emit: """return `c`;""".} - else: - {.emit: """ - var ln = `c`.length; - var result = new Array(ln + 1); - var i = 0; - for (; i < ln; ++i) { - result[i] = `c`.charCodeAt(i); } - result[i] = 0; // terminating zero return result; - """.} + """ + +proc makeNimstrLit(c: cstring): string {.asmNoStackFrame, compilerproc.} = + {.emit: """ + var ln = `c`.length; + var result = new Array(ln + 1); + var i = 0; + for (; i < ln; ++i) { + result[i] = `c`.charCodeAt(i); + } + result[i] = 0; // terminating zero + return result; + """.} proc cstrToNimstr(c: cstring): string {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - {.emit: """return `c`;""".} - else: - {.emit: """ + {.emit: """ var ln = `c`.length; var result = new Array(ln); var r = 0; @@ -261,156 +232,93 @@ proc cstrToNimstr(c: cstring): string {.asmNoStackFrame, compilerproc.} = """.} proc toJSStr(s: string): cstring {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - {.emit: """return `s`;""".} - else: - asm """ - var len = `s`.length-1; - var asciiPart = new Array(len); - var fcc = String.fromCharCode; - var nonAsciiPart = null; - var nonAsciiOffset = 0; - for (var i = 0; i < len; ++i) { - if (nonAsciiPart !== null) { - var offset = (i - nonAsciiOffset) * 2; - var code = `s`[i].toString(16); - if (code.length == 1) { - code = "0"+code; - } - nonAsciiPart[offset] = "%"; - nonAsciiPart[offset + 1] = code; - } - else if (`s`[i] < 128) - asciiPart[i] = fcc(`s`[i]); - else { - asciiPart.length = i; - nonAsciiOffset = i; - nonAsciiPart = new Array((len - i) * 2); - --i; + asm """ + var len = `s`.length-1; + var asciiPart = new Array(len); + var fcc = String.fromCharCode; + var nonAsciiPart = null; + var nonAsciiOffset = 0; + for (var i = 0; i < len; ++i) { + if (nonAsciiPart !== null) { + var offset = (i - nonAsciiOffset) * 2; + var code = `s`[i].toString(16); + if (code.length == 1) { + code = "0"+code; } + nonAsciiPart[offset] = "%"; + nonAsciiPart[offset + 1] = code; } - asciiPart = asciiPart.join(""); - return (nonAsciiPart === null) ? - asciiPart : asciiPart + decodeURIComponent(nonAsciiPart.join("")); + else if (`s`[i] < 128) + asciiPart[i] = fcc(`s`[i]); + else { + asciiPart.length = i; + nonAsciiOffset = i; + nonAsciiPart = new Array((len - i) * 2); + --i; + } + } + asciiPart = asciiPart.join(""); + return (nonAsciiPart === null) ? + asciiPart : asciiPart + decodeURIComponent(nonAsciiPart.join("")); """ proc mnewString(len: int): string {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - asm """ - return str_repeat(chr(0),`len`); - """ - else: - asm """ - var result = new Array(`len`+1); - result[0] = 0; - result[`len`] = 0; - return result; - """ - -when defined(nimphp): - proc nimAt(x: string; i: int): string {.asmNoStackFrame, compilerproc.} = - asm """ - return `x`[`i`]; - """ - -when defined(nimphp): - proc nimSubstr(s: string; a, b: int): string {. - asmNoStackFrame, compilerproc.} = - asm """return substr(`s`,`a`,`b`-`a`+1);""" + asm """ + var result = new Array(`len`+1); + result[0] = 0; + result[`len`] = 0; + return result; + """ proc SetCard(a: int): int {.compilerproc, asmNoStackFrame.} = # argument type is a fake - when defined(nimphp): - asm """ - return count(`a`); - """ - else: - asm """ - var result = 0; - for (var elem in `a`) { ++result; } - return result; - """ + asm """ + var result = 0; + for (var elem in `a`) { ++result; } + return result; + """ proc SetEq(a, b: int): bool {.compilerproc, asmNoStackFrame.} = - when defined(nimphp): - asm """ - foreach (`a` as $elem=>$_) { if (!isset(`b`[$elem])) return false; } - foreach (`b` as $elem=>$_) { if (!isset(`a`[$elem])) return false; } - return true; - """ - else: - asm """ - for (var elem in `a`) { if (!`b`[elem]) return false; } - for (var elem in `b`) { if (!`a`[elem]) return false; } - return true; - """ + asm """ + for (var elem in `a`) { if (!`b`[elem]) return false; } + for (var elem in `b`) { if (!`a`[elem]) return false; } + return true; + """ proc SetLe(a, b: int): bool {.compilerproc, asmNoStackFrame.} = - when defined(nimphp): - asm """ - foreach (`a` as $elem=>$_) { if (!isset(`b`[$elem])) return false; } - return true; - """ - else: - asm """ - for (var elem in `a`) { if (!`b`[elem]) return false; } - return true; - """ + asm """ + for (var elem in `a`) { if (!`b`[elem]) return false; } + return true; + """ proc SetLt(a, b: int): bool {.compilerproc.} = result = SetLe(a, b) and not SetEq(a, b) proc SetMul(a, b: int): int {.compilerproc, asmNoStackFrame.} = - when defined(nimphp): - asm """ - var $result = array(); - foreach (`a` as $elem=>$_) { - if (isset(`b`[$elem])) { $result[$elem] = true; } - } - return $result; - """ - else: - asm """ - var result = {}; - for (var elem in `a`) { - if (`b`[elem]) { result[elem] = true; } - } - return result; - """ + asm """ + var result = {}; + for (var elem in `a`) { + if (`b`[elem]) { result[elem] = true; } + } + return result; + """ proc SetPlus(a, b: int): int {.compilerproc, asmNoStackFrame.} = - when defined(nimphp): - asm """ - var $result = array(); - foreach (`a` as $elem=>$_) { $result[$elem] = true; } - foreach (`b` as $elem=>$_) { $result[$elem] = true; } - return $result; - """ - else: - asm """ - var result = {}; - for (var elem in `a`) { result[elem] = true; } - for (var elem in `b`) { result[elem] = true; } - return result; - """ + asm """ + var result = {}; + for (var elem in `a`) { result[elem] = true; } + for (var elem in `b`) { result[elem] = true; } + return result; + """ proc SetMinus(a, b: int): int {.compilerproc, asmNoStackFrame.} = - when defined(nimphp): - asm """ - $result = array(); - foreach (`a` as $elem=>$_) { - if (!isset(`b`[$elem])) { $result[$elem] = true; } - } - return $result; - """ - else: - asm """ - var result = {}; - for (var elem in `a`) { - if (!`b`[elem]) { result[elem] = true; } - } - return result; - """ + asm """ + var result = {}; + for (var elem in `a`) { + if (!`b`[elem]) { result[elem] = true; } + } + return result; + """ proc cmpStrings(a, b: string): int {.asmNoStackFrame, compilerProc.} = asm """ @@ -424,15 +332,8 @@ proc cmpStrings(a, b: string): int {.asmNoStackFrame, compilerProc.} = return `a`.length - `b`.length; """ -proc cmp(x, y: string): int = - when defined(nimphp): - asm """ - if(`x` < `y`) `result` = -1; - elseif (`x` > `y`) `result` = 1; - else `result` = 0; - """ - else: - return cmpStrings(x, y) +proc cmp(x, y: string): int = + return cmpStrings(x, y) proc eqStrings(a, b: string): bool {.asmNoStackFrame, compilerProc.} = asm """ @@ -467,7 +368,7 @@ elif not defined(nimOldEcho): console.log(buf); """ -elif not defined(nimphp): +else: proc ewriteln(x: cstring) = var node : JSRef {.emit: "`node` = document.getElementsByTagName('body')[0];".} @@ -493,127 +394,77 @@ elif not defined(nimphp): # Arithmetic: proc addInt(a, b: int): int {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - asm """ - return `a` + `b`; - """ - else: - asm """ - var result = `a` + `b`; - if (result > 2147483647 || result < -2147483648) `raiseOverflow`(); - return result; - """ + asm """ + var result = `a` + `b`; + if (result > 2147483647 || result < -2147483648) `raiseOverflow`(); + return result; + """ proc subInt(a, b: int): int {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - asm """ - return `a` - `b`; - """ - else: - asm """ - var result = `a` - `b`; - if (result > 2147483647 || result < -2147483648) `raiseOverflow`(); - return result; - """ + asm """ + var result = `a` - `b`; + if (result > 2147483647 || result < -2147483648) `raiseOverflow`(); + return result; + """ proc mulInt(a, b: int): int {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - asm """ - return `a` * `b`; - """ - else: - asm """ - var result = `a` * `b`; - if (result > 2147483647 || result < -2147483648) `raiseOverflow`(); - return result; - """ + asm """ + var result = `a` * `b`; + if (result > 2147483647 || result < -2147483648) `raiseOverflow`(); + return result; + """ proc divInt(a, b: int): int {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - asm """ - return trunc(`a` / `b`); - """ - else: - asm """ - if (`b` == 0) `raiseDivByZero`(); - if (`b` == -1 && `a` == 2147483647) `raiseOverflow`(); - return Math.trunc(`a` / `b`); - """ + asm """ + if (`b` == 0) `raiseDivByZero`(); + if (`b` == -1 && `a` == 2147483647) `raiseOverflow`(); + return Math.trunc(`a` / `b`); + """ proc modInt(a, b: int): int {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - asm """ - return `a` % `b`; - """ - else: - asm """ - if (`b` == 0) `raiseDivByZero`(); - if (`b` == -1 && `a` == 2147483647) `raiseOverflow`(); - return Math.trunc(`a` % `b`); - """ + asm """ + if (`b` == 0) `raiseDivByZero`(); + if (`b` == -1 && `a` == 2147483647) `raiseOverflow`(); + return Math.trunc(`a` % `b`); + """ proc addInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - asm """ - return `a` + `b`; - """ - else: - asm """ - var result = `a` + `b`; - if (result > 9223372036854775807 - || result < -9223372036854775808) `raiseOverflow`(); - return result; - """ + asm """ + var result = `a` + `b`; + if (result > 9223372036854775807 + || result < -9223372036854775808) `raiseOverflow`(); + return result; + """ proc subInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - asm """ - return `a` - `b`; - """ - else: - asm """ - var result = `a` - `b`; - if (result > 9223372036854775807 - || result < -9223372036854775808) `raiseOverflow`(); - return result; - """ + asm """ + var result = `a` - `b`; + if (result > 9223372036854775807 + || result < -9223372036854775808) `raiseOverflow`(); + return result; + """ proc mulInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - asm """ - return `a` * `b`; - """ - else: - asm """ - var result = `a` * `b`; - if (result > 9223372036854775807 - || result < -9223372036854775808) `raiseOverflow`(); - return result; - """ + asm """ + var result = `a` * `b`; + if (result > 9223372036854775807 + || result < -9223372036854775808) `raiseOverflow`(); + return result; + """ proc divInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - asm """ - return trunc(`a` / `b`); - """ - else: - asm """ - if (`b` == 0) `raiseDivByZero`(); - if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`(); - return Math.trunc(`a` / `b`); - """ + asm """ + if (`b` == 0) `raiseDivByZero`(); + if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`(); + return Math.trunc(`a` / `b`); + """ proc modInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} = - when defined(nimphp): - asm """ - return `a` % `b`; - """ - else: - asm """ - if (`b` == 0) `raiseDivByZero`(); - if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`(); - return Math.trunc(`a` % `b`); - """ + asm """ + if (`b` == 0) `raiseDivByZero`(); + if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`(); + return Math.trunc(`a` % `b`); + """ proc negInt(a: int): int {.compilerproc.} = result = a*(-1) @@ -767,24 +618,14 @@ proc genericReset(x: JSRef, ti: PNimType): JSRef {.compilerproc.} = else: discard -when defined(nimphp): - proc arrayConstr(len: int, value: string, typ: string): JSRef {. - asmNoStackFrame, compilerproc.} = - # types are fake - asm """ - $result = array(); - for ($i = 0; $i < `len`; $i++) $result[] = `value`; - return $result; - """ -else: - proc arrayConstr(len: int, value: JSRef, typ: PNimType): JSRef {. - asmNoStackFrame, compilerproc.} = +proc arrayConstr(len: int, value: JSRef, typ: PNimType): JSRef {. + asmNoStackFrame, compilerproc.} = # types are fake - asm """ - var result = new Array(`len`); - for (var i = 0; i < `len`; ++i) result[i] = nimCopy(null, `value`, `typ`); - return result; - """ + asm """ + var result = new Array(`len`); + for (var i = 0; i < `len`; ++i) result[i] = nimCopy(null, `value`, `typ`); + return result; + """ proc chckIndx(i, a, b: int): int {.compilerproc.} = if i >= a and i <= b: return i -- cgit 1.4.1-2-gfad0 From 0448d3f6ea3516bee9816320fefc62bc9c7d23fc Mon Sep 17 00:00:00 2001 From: genotrance Date: Wed, 18 Apr 2018 14:19:23 -0500 Subject: test case for #2416 (#7649) --- tests/template/i2416.nim | 1 + tests/template/t2416.nim | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 tests/template/i2416.nim create mode 100644 tests/template/t2416.nim diff --git a/tests/template/i2416.nim b/tests/template/i2416.nim new file mode 100644 index 000000000..4b53cd0ca --- /dev/null +++ b/tests/template/i2416.nim @@ -0,0 +1 @@ +template i2416*() = echo "i2416" diff --git a/tests/template/t2416.nim b/tests/template/t2416.nim new file mode 100644 index 000000000..f73880718 --- /dev/null +++ b/tests/template/t2416.nim @@ -0,0 +1,2 @@ +import i2416 +i2416() -- cgit 1.4.1-2-gfad0 From b9cafe5752f0772b6c05b78c45cd72b8c0932de2 Mon Sep 17 00:00:00 2001 From: genotrance Date: Wed, 18 Apr 2018 14:19:48 -0500 Subject: test case for #1154 (#7648) --- tests/errmsgs/t1154.nim | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/errmsgs/t1154.nim diff --git a/tests/errmsgs/t1154.nim b/tests/errmsgs/t1154.nim new file mode 100644 index 000000000..7fcbf8a27 --- /dev/null +++ b/tests/errmsgs/t1154.nim @@ -0,0 +1,11 @@ +discard """ +errormsg: "invalid type: 'expr' in this context: 'proc (a: varargs[expr])' for proc" +line: 8 +""" + +import typetraits + +proc foo(a:varargs[expr]) = + echo a[0].type.name + +foo(1) -- cgit 1.4.1-2-gfad0 From fdf1d123804df3325211384e1c438295ea23bbd3 Mon Sep 17 00:00:00 2001 From: Oscar Nihlgård Date: Wed, 18 Apr 2018 21:24:28 +0200 Subject: Change type of `Timeval.tv_sec` to `posix.Time` (#7646) --- changelog.md | 1 + lib/deprecated/pure/asyncio.nim | 12 ++++++++---- lib/deprecated/pure/sockets.nim | 8 ++++++-- lib/posix/posix_linux_amd64.nim | 4 ++-- lib/posix/posix_other.nim | 4 ++-- lib/pure/nativesockets.nim | 8 ++++++-- lib/pure/os.nim | 2 +- lib/pure/osproc.nim | 2 +- lib/pure/times.nim | 2 +- 9 files changed, 28 insertions(+), 15 deletions(-) diff --git a/changelog.md b/changelog.md index f39dc2678..e6d1f6b47 100644 --- a/changelog.md +++ b/changelog.md @@ -27,6 +27,7 @@ - ``proc `-`*(a, b: Time): int64`` in the ``times`` module has changed return type to ``times.Duration`` in order to support higher time resolutions. The proc is no longer deprecated. +- ``posix.Timeval.tv_sec`` has changed type to ``posix.Time``. #### Breaking changes in the compiler diff --git a/lib/deprecated/pure/asyncio.nim b/lib/deprecated/pure/asyncio.nim index 5fd45b215..34cabefb0 100644 --- a/lib/deprecated/pure/asyncio.nim +++ b/lib/deprecated/pure/asyncio.nim @@ -101,8 +101,8 @@ when defined(windows): from winlean import TimeVal, SocketHandle, FD_SET, FD_ZERO, TFdSet, FD_ISSET, select else: - from posix import TimeVal, SocketHandle, FD_SET, FD_ZERO, TFdSet, - FD_ISSET, select + from posix import TimeVal, Time, Suseconds, SocketHandle, FD_SET, FD_ZERO, + TFdSet, FD_ISSET, select type DelegateObj* = object @@ -556,8 +556,12 @@ proc send*(sock: AsyncSocket, data: string) = proc timeValFromMilliseconds(timeout = 500): Timeval = if timeout != -1: var seconds = timeout div 1000 - result.tv_sec = seconds.int32 - result.tv_usec = ((timeout - seconds * 1000) * 1000).int32 + when defined(posix): + result.tv_sec = seconds.Time + result.tv_usec = ((timeout - seconds * 1000) * 1000).Suseconds + else: + result.tv_sec = seconds.int32 + result.tv_usec = ((timeout - seconds * 1000) * 1000).int32 proc createFdSet(fd: var TFdSet, s: seq[Delegate], m: var int) = FD_ZERO(fd) diff --git a/lib/deprecated/pure/sockets.nim b/lib/deprecated/pure/sockets.nim index f068c7d56..f0568366a 100644 --- a/lib/deprecated/pure/sockets.nim +++ b/lib/deprecated/pure/sockets.nim @@ -953,8 +953,12 @@ when defined(ssl): proc timeValFromMilliseconds(timeout = 500): Timeval = if timeout != -1: var seconds = timeout div 1000 - result.tv_sec = seconds.int32 - result.tv_usec = ((timeout - seconds * 1000) * 1000).int32 + when defined(posix): + result.tv_sec = seconds.Time + result.tv_usec = ((timeout - seconds * 1000) * 1000).Suseconds + else: + result.tv_sec = seconds.int32 + result.tv_usec = ((timeout - seconds * 1000) * 1000).int32 proc createFdSet(fd: var TFdSet, s: seq[Socket], m: var int) = FD_ZERO(fd) diff --git a/lib/posix/posix_linux_amd64.nim b/lib/posix/posix_linux_amd64.nim index 9e6211b63..4f114d394 100644 --- a/lib/posix/posix_linux_amd64.nim +++ b/lib/posix/posix_linux_amd64.nim @@ -351,8 +351,8 @@ type Timeval* {.importc: "struct timeval", header: "", final, pure.} = object ## struct timeval - tv_sec*: clong ## Seconds. - tv_usec*: clong ## Microseconds. + tv_sec*: Time ## Seconds. + tv_usec*: Suseconds ## Microseconds. TFdSet* {.importc: "fd_set", header: "", final, pure.} = object abi: array[1024 div (8 * sizeof(clong)), clong] diff --git a/lib/posix/posix_other.nim b/lib/posix/posix_other.nim index 01bc1c1e5..ae41263e8 100644 --- a/lib/posix/posix_other.nim +++ b/lib/posix/posix_other.nim @@ -335,8 +335,8 @@ type Timeval* {.importc: "struct timeval", header: "", final, pure.} = object ## struct timeval - tv_sec*: int ## Seconds. - tv_usec*: int ## Microseconds. + tv_sec*: Time ## Seconds. + tv_usec*: Suseconds ## Microseconds. TFdSet* {.importc: "fd_set", header: "", final, pure.} = object Mcontext* {.importc: "mcontext_t", header: "", diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim index 74b2c9741..09fa253f1 100644 --- a/lib/pure/nativesockets.nim +++ b/lib/pure/nativesockets.nim @@ -616,8 +616,12 @@ proc setBlocking*(s: SocketHandle, blocking: bool) = proc timeValFromMilliseconds(timeout = 500): Timeval = if timeout != -1: var seconds = timeout div 1000 - result.tv_sec = seconds.int32 - result.tv_usec = ((timeout - seconds * 1000) * 1000).int32 + when useWinVersion: + result.tv_sec = seconds.int32 + result.tv_usec = ((timeout - seconds * 1000) * 1000).int32 + else: + result.tv_sec = seconds.Time + result.tv_usec = ((timeout - seconds * 1000) * 1000).Suseconds proc createFdSet(fd: var TFdSet, s: seq[SocketHandle], m: var int) = FD_ZERO(fd) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 255a9a8de..8298024d6 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1660,7 +1660,7 @@ proc setLastModificationTime*(file: string, t: times.Time) = ## Sets the `file`'s last modification time. `OSError` is raised in case of ## an error. when defined(posix): - let unixt = t.toUnix.int + let unixt = posix.Time(t.toUnix) var timevals = [Timeval(tv_sec: unixt), Timeval(tv_sec: unixt)] # [last access, last modification] if utimes(file, timevals.addr) != 0: raiseOSError(osLastError()) else: diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index a51b1f5ab..bcab5ad3a 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -1289,7 +1289,7 @@ elif not defined(useNimRtl): proc select(readfds: var seq[Process], timeout = 500): int = var tv: Timeval - tv.tv_sec = 0 + tv.tv_sec = posix.Time(0) tv.tv_usec = timeout * 1000 var rd: TFdSet diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 29492379d..cad32b51a 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -1752,7 +1752,7 @@ when not defined(JS): when defined(posix): var a: Timeval gettimeofday(a) - result = toFloat(a.tv_sec) + toFloat(a.tv_usec)*0.00_0001 + result = toBiggestFloat(a.tv_sec.int64) + toFloat(a.tv_usec)*0.00_0001 elif defined(windows): var f: winlean.FILETIME getSystemTimeAsFileTime(f) -- cgit 1.4.1-2-gfad0 From a230307b48f2cfa2fc2688ff5d706dbe9c5de154 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 12 Apr 2018 10:57:47 +0200 Subject: little progress on nimpretty --- compiler/lexer.nim | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/compiler/lexer.nim b/compiler/lexer.nim index e55da2f35..1d9279d02 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -1003,6 +1003,10 @@ proc skip(L: var TLexer, tok: var TToken) = var buf = L.buf tokenBegin(tok, pos) tok.strongSpaceA = 0 + when defined(nimpretty): + var hasComment = false + tok.commentOffsetA = L.offsetBase + pos + tok.commentOffsetB = tok.commentOffsetA while true: case buf[pos] of ' ': @@ -1021,6 +1025,7 @@ proc skip(L: var TLexer, tok: var TToken) = inc(pos) inc(indent) elif buf[pos] == '#' and buf[pos+1] == '[': + when defined(nimpretty): hasComment = true skipMultiLineComment(L, tok, pos+2, false) pos = L.bufpos buf = L.buf @@ -1034,14 +1039,11 @@ proc skip(L: var TLexer, tok: var TToken) = of '#': # do not skip documentation comment: if buf[pos+1] == '#': break - when defined(nimpretty): - tok.commentOffsetA = L.offsetBase + pos + when defined(nimpretty): hasComment = true if buf[pos+1] == '[': skipMultiLineComment(L, tok, pos+2, false) pos = L.bufpos buf = L.buf - when defined(nimpretty): - tok.commentOffsetB = L.offsetBase + pos else: tokenBegin(tok, pos) while buf[pos] notin {CR, LF, nimlexbase.EndOfFile}: inc(pos) @@ -1053,6 +1055,9 @@ proc skip(L: var TLexer, tok: var TToken) = tokenEndPrevious(tok, pos-1) L.bufpos = pos when defined(nimpretty): + if hasComment: + tok.commentOffsetB = L.offsetBase + pos + tok.tokType = tkComment if gIndentationWidth <= 0: gIndentationWidth = tok.indent @@ -1074,6 +1079,8 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) = else: tok.indent = -1 skip(L, tok) + when defined(nimpretty): + if tok.tokType == tkComment: return var c = L.buf[L.bufpos] tok.line = L.lineNumber tok.col = getColNumber(L, L.bufpos) -- cgit 1.4.1-2-gfad0 From 9bc963508f29de8dd785a02b01f3159530a0ee2e Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 17 Apr 2018 11:09:23 +0200 Subject: nimpretty: next steps --- compiler/lexer.nim | 4 +++- compiler/msgs.nim | 18 ++++++++++++++++-- compiler/parser.nim | 8 +++++++- compiler/renderer.nim | 17 ++++++----------- tools/nimpretty.nim | 4 ++-- 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/compiler/lexer.nim b/compiler/lexer.nim index 1d9279d02..a4a2615bd 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -1080,7 +1080,9 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) = tok.indent = -1 skip(L, tok) when defined(nimpretty): - if tok.tokType == tkComment: return + if tok.tokType == tkComment: + L.indentAhead = L.currLineIndent + return var c = L.buf[L.bufpos] tok.line = L.lineNumber tok.col = getColNumber(L, L.bufpos) diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 70504cfc9..818ab0c05 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -495,7 +495,9 @@ type # and parsed; usually 'nil' but is used # for 'nimsuggest' hash*: string # the checksum of the file - + when defined(nimpretty): + fullContent*: string + FileIndex* = int32 # XXX will make this 'distinct' later TLineInfo* = object # This is designed to be as small as possible, # because it is used # in syntax nodes. We save space here by using @@ -503,7 +505,7 @@ type # On 64 bit and on 32 bit systems this is # only 8 bytes. line*, col*: int16 - fileIndex*: int32 + fileIndex*: FileIndex when defined(nimpretty): offsetA*, offsetB*: int commentOffsetA*, commentOffsetB*: int @@ -583,6 +585,18 @@ proc newFileInfo(fullPath, projPath: string): TFileInfo = result.quotedFullName = fullPath.makeCString if optEmbedOrigSrc in gGlobalOptions or true: result.lines = @[] + when defined(nimpretty): + if result.fullPath.len > 0: + try: + result.fullContent = readFile(result.fullPath) + except IOError: + #rawMessage(errCannotOpenFile, result.fullPath) + # XXX fixme + result.fullContent = "" + +when defined(nimpretty): + proc fileSection*(fid: FileIndex; a, b: int): string = + substr(fileInfos[fid].fullContent, a, b) proc fileInfoKnown*(filename: string): bool = var diff --git a/compiler/parser.nim b/compiler/parser.nim index 0019b7acb..3bf75c6f7 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -125,7 +125,13 @@ proc rawSkipComment(p: var TParser, node: PNode) = if p.tok.tokType == tkComment: if node != nil: if node.comment == nil: node.comment = "" - add(node.comment, p.tok.literal) + when defined(nimpretty): + if p.tok.commentOffsetB > p.tok.commentOffsetA: + add node.comment, fileSection(p.lex.fileIdx, p.tok.commentOffsetA, p.tok.commentOffsetB) + else: + add node.comment, p.tok.literal + else: + add(node.comment, p.tok.literal) else: parMessage(p, errInternal, "skipComment") getTok(p) diff --git a/compiler/renderer.nim b/compiler/renderer.nim index 7d513afb1..0e631a898 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -39,8 +39,7 @@ type inPragma: int when defined(nimpretty): pendingNewlineCount: int - origContent: string - + fid*: FileIndex # We render the source code in a two phases: The first # determines how long the subtree will likely be, the second @@ -354,13 +353,13 @@ proc ulitAux(g: TSrcGen; n: PNode, x: BiggestInt, size: int): string = proc atom(g: TSrcGen; n: PNode): string = when defined(nimpretty): let comment = if n.info.commentOffsetA < n.info.commentOffsetB: - " " & substr(g.origContent, n.info.commentOffsetA, n.info.commentOffsetB) + " " & fileSection(g.fid, n.info.commentOffsetA, n.info.commentOffsetB) else: "" if n.info.offsetA <= n.info.offsetB: # for some constructed tokens this can not be the case and we're better # off to not mess with the offset then. - return substr(g.origContent, n.info.offsetA, n.info.offsetB) & comment + return fileSection(g.fid, n.info.offsetA, n.info.offsetB) & comment var f: float32 case n.kind of nkEmpty: result = "" @@ -1460,17 +1459,13 @@ proc renderTree*(n: PNode, renderFlags: TRenderFlags = {}): string = proc `$`*(n: PNode): string = n.renderTree proc renderModule*(n: PNode, infile, outfile: string, - renderFlags: TRenderFlags = {}) = + renderFlags: TRenderFlags = {}; + fid = FileIndex(-1)) = var f: File g: TSrcGen initSrcGen(g, renderFlags) - when defined(nimpretty): - try: - g.origContent = readFile(infile) - except IOError: - rawMessage(errCannotOpenFile, infile) - + g.fid = fid for i in countup(0, sonsLen(n) - 1): gsub(g, n.sons[i]) optNL(g) diff --git a/tools/nimpretty.nim b/tools/nimpretty.nim index 36d1382cf..396f17b0b 100644 --- a/tools/nimpretty.nim +++ b/tools/nimpretty.nim @@ -24,7 +24,7 @@ const Usage: nimpretty [options] file.nim Options: - --backup:ON|OFF create a backup file before overwritting (default: ON) + --backup:on|off create a backup file before overwritting (default: ON) --version show the version --help show this help """ @@ -43,7 +43,7 @@ proc prettyPrint(infile: string) = let fileIdx = fileInfoIdx(infile) let tree = parseFile(fileIdx, newIdentCache()) let outfile = changeFileExt(infile, ".pretty.nim") - renderModule(tree, infile, outfile, {}) + renderModule(tree, infile, outfile, {}, fileIdx) proc main = var infile: string -- cgit 1.4.1-2-gfad0 From 4a9f6f00adb3234e604faa40cca52bc15ede9769 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 18 Apr 2018 21:30:28 +0200 Subject: fixes system.doAssertRaises --- lib/system.nim | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 9f0b11597..5e08dadc0 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -4136,17 +4136,18 @@ template doAssertRaises*(exception, code: untyped): typed = runnableExamples: doAssertRaises(ValueError): raise newException(ValueError, "Hello World") - + var wrong = false try: - block: - code - raiseAssert(astToStr(exception) & " wasn't raised by:\n" & astToStr(code)) + code + wrong = true except exception: discard except Exception as exc: raiseAssert(astToStr(exception) & " wasn't raised, another error was raised instead by:\n"& astToStr(code)) + if wrong: + raiseAssert(astToStr(exception) & " wasn't raised by:\n" & astToStr(code)) when defined(cpp) and appType != "lib" and not defined(js) and not defined(nimscript) and hostOS != "standalone": -- cgit 1.4.1-2-gfad0 From e237428d424ad18e03d4ffa6d036afb175d28bff Mon Sep 17 00:00:00 2001 From: WhiteDuke Date: Wed, 18 Apr 2018 23:29:10 +0200 Subject: Fix bright option (#7622) Setting the option to true, then to false would not turn off bright attribute. --- lib/pure/terminal.nim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index 4f2f73ba7..002181a6f 100644 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -557,8 +557,8 @@ proc setForegroundColor*(f: File, fg: ForegroundColor, bright=false) = when defined(windows): let h = conHandle(f) var old = getAttributes(h) and not FOREGROUND_RGB - if bright: - old = old or FOREGROUND_INTENSITY + old = if bright: old or FOREGROUND_INTENSITY + else: old and not(FOREGROUND_INTENSITY) const lookup: array[ForegroundColor, int] = [ 0, (FOREGROUND_RED), @@ -579,8 +579,8 @@ proc setBackgroundColor*(f: File, bg: BackgroundColor, bright=false) = when defined(windows): let h = conHandle(f) var old = getAttributes(h) and not BACKGROUND_RGB - if bright: - old = old or BACKGROUND_INTENSITY + old = if bright: old or BACKGROUND_INTENSITY + else: old and not(BACKGROUND_INTENSITY) const lookup: array[BackgroundColor, int] = [ 0, (BACKGROUND_RED), -- cgit 1.4.1-2-gfad0 From 5d13e3f28bf479cd1d59fdec7f34847df988416c Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 19 Apr 2018 00:09:36 +0200 Subject: fixes #7507 --- lib/pure/strutils.nim | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index d772b066c..54fdcb4d0 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -1647,11 +1647,15 @@ proc replace*(s, sub: string, by = ""): string {.noSideEffect, let last = s.high var i = 0 while true: - var j = find(a, s, sub, i, last) + let j = find(a, s, sub, i, last) if j < 0: break add result, substr(s, i, j - 1) add result, by - i = j + len(sub) + if sub.len == 0: + if i < s.len: add result, s[i] + i = j + 1 + else: + i = j + sub.len # copy the rest: add result, substr(s, i) @@ -1680,6 +1684,7 @@ proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect, initSkipTable(a, sub) var i = 0 let last = s.high + let sublen = max(sub.len, 1) while true: var j = find(a, s, sub, i, last) if j < 0: break @@ -1688,7 +1693,7 @@ proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect, (j+sub.len >= s.len or s[j+sub.len] notin wordChars): add result, substr(s, i, j - 1) add result, by - i = j + len(sub) + i = j + sublen else: add result, substr(s, i, j) i = j + 1 @@ -2546,6 +2551,9 @@ when isMainModule: doAssert "-ld a-ldz -ld".replaceWord("-ld") == " a-ldz " doAssert "-lda-ldz -ld abc".replaceWord("-ld") == "-lda-ldz abc" + doAssert "-lda-ldz -ld abc".replaceWord("") == "lda-ldz ld abc" + doAssert "oo".replace("", "abc") == "abcoabcoabc" + type MyEnum = enum enA, enB, enC, enuD, enE doAssert parseEnum[MyEnum]("enu_D") == enuD -- cgit 1.4.1-2-gfad0 From 17cb2f2d4c23b2c7760b8a846dcc5884d5d40c89 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Wed, 18 Apr 2018 17:12:47 +0200 Subject: threadpool: minor documentation improvement --- lib/pure/concurrency/threadpool.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index a5eaec86e..b01f8fc0d 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -245,7 +245,7 @@ proc `^`*[T](fv: FlowVar[T]): T = proc awaitAny*(flowVars: openArray[FlowVarBase]): int = ## awaits any of the given flowVars. Returns the index of one flowVar for ## which a value arrived. A flowVar only supports one call to 'awaitAny' at - ## the same time. That means if you await([a,b]) and await([b,c]) the second + ## the same time. That means if you awaitAny([a,b]) and awaitAny([b,c]) the second ## call will only await 'c'. If there is no flowVar left to be able to wait ## on, -1 is returned. ## **Note**: This results in non-deterministic behaviour and so should be -- cgit 1.4.1-2-gfad0 From cb03ae2c9fcbb459b58bee90aa0759dcea6be878 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Wed, 18 Apr 2018 17:13:29 +0200 Subject: semstmts: fewer empty lines --- compiler/semstmts.nim | 5 ----- 1 file changed, 5 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index f90e5c5f9..75d8cc2e0 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -779,20 +779,15 @@ proc semRaise(c: PContext, n: PNode): PNode = result = n checkSonsLen(n, 1) if n[0].kind != nkEmpty: - n[0] = semExprWithType(c, n[0]) let typ = n[0].typ - if not isImportedException(typ): - if typ.kind != tyRef or typ.lastSon.kind != tyObject: localError(n.info, errExprCannotBeRaised) - if not isException(typ.lastSon): localError(n.info, "raised object of type $1 does not inherit from Exception", [typeToString(typ)]) - proc addGenericParamListToScope(c: PContext, n: PNode) = if n.kind != nkGenericParams: illFormedAst(n) for i in countup(0, sonsLen(n)-1): -- cgit 1.4.1-2-gfad0 From 0dc4d6dcc28a6e35f36caaa5bcc801b4acac61b4 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Thu, 19 Apr 2018 08:54:16 +0200 Subject: fixes #7638; awaitAny blocks if the flow vars all have been complete already --- lib/pure/concurrency/threadpool.nim | 24 +++++++++++++++++------- tests/parallel/twaitany.nim | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 tests/parallel/twaitany.nim diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index b01f8fc0d..ca4f80f2a 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -168,6 +168,15 @@ proc wakeupWorkerToProcessQueue(w: ptr Worker) = signal(w.q.empty) signal(w.taskArrived) +proc attach(fv: FlowVarBase; i: int): bool = + acquire(fv.cv.L) + if fv.cv.counter <= 0: + fv.idx = i + result = true + else: + result = false + release(fv.cv.L) + proc finished(fv: FlowVarBase) = doAssert fv.ai.isNil, "flowVar is still attached to an 'awaitAny'" # we have to protect against the rare cases where the owner of the flowVar @@ -248,23 +257,24 @@ proc awaitAny*(flowVars: openArray[FlowVarBase]): int = ## the same time. That means if you awaitAny([a,b]) and awaitAny([b,c]) the second ## call will only await 'c'. If there is no flowVar left to be able to wait ## on, -1 is returned. - ## **Note**: This results in non-deterministic behaviour and so should be - ## avoided. + ## **Note**: This results in non-deterministic behaviour and should be avoided. var ai: AwaitInfo ai.cv.initSemaphore() var conflicts = 0 + result = -1 for i in 0 .. flowVars.high: if cas(addr flowVars[i].ai, nil, addr ai): - flowVars[i].idx = i + if not attach(flowVars[i], i): + result = i + break else: inc conflicts if conflicts < flowVars.len: - await(ai.cv) - result = ai.idx + if result < 0: + await(ai.cv) + result = ai.idx for i in 0 .. flowVars.high: discard cas(addr flowVars[i].ai, addr ai, nil) - else: - result = -1 destroySemaphore(ai.cv) proc isReady*(fv: FlowVarBase): bool = diff --git a/tests/parallel/twaitany.nim b/tests/parallel/twaitany.nim new file mode 100644 index 000000000..69136a3b6 --- /dev/null +++ b/tests/parallel/twaitany.nim @@ -0,0 +1,35 @@ +discard """ + output: '''true''' +""" + +# bug #7638 +import threadpool, os, strformat + +proc timer(d: int): int = + #echo fmt"sleeping {d}" + sleep(d) + #echo fmt"done {d}" + return d + +var durations = [1000, 2000, 3000, 4000, 5000] +var tasks: seq[FlowVarBase] = @[] +var results: seq[int] = @[] + +for i in 0 .. durations.high: + tasks.add spawn timer(durations[i]) + +var index = awaitAny(tasks) +while index != -1: + results.add ^cast[FlowVar[int]](tasks[index]) + tasks.del(index) + #echo repr results + index = awaitAny(tasks) + +doAssert results.len == 5 +doAssert 1000 in results +doAssert 2000 in results +doAssert 3000 in results +doAssert 4000 in results +doAssert 5000 in results +sync() +echo "true" -- cgit 1.4.1-2-gfad0 From 34029263725ef931863ea73966dc08588758dada Mon Sep 17 00:00:00 2001 From: RSDuck Date: Thu, 19 Apr 2018 11:07:45 +0200 Subject: hasCustomPragma/getCustomPragmaVal: small fix (#7650) * fix hasCustomPragma/getCustomPragmaVal for types without pragma * fix pragma on pointer test * removed trailing spaces --- lib/core/macros.nim | 6 +++++- tests/pragmas/tcustom_pragma.nim | 10 +++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/core/macros.nim b/lib/core/macros.nim index b050eb6c8..1dc067e1a 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -1288,7 +1288,11 @@ proc customPragmaNode(n: NimNode): NimNode = typ = n.getTypeInst() if typ.typeKind == ntyTypeDesc: - return typ[1].getImpl()[0][1] + let impl = typ[1].getImpl() + if impl[0].kind == nnkPragmaExpr: + return impl[0][1] + else: + return impl[0] # handle types which don't have macro at all if n.kind == nnkSym: # either an variable or a proc let impl = n.getImpl() diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim index 28a8713ce..33a4a7e65 100644 --- a/tests/pragmas/tcustom_pragma.nim +++ b/tests/pragmas/tcustom_pragma.nim @@ -51,6 +51,9 @@ block: # A bit more advanced case static: assert(hasCustomPragma(myproc, alternativeKey)) + const hasFieldCustomPragma = s.field.hasCustomPragma(defaultValue) + static: assert(hasFieldCustomPragma == false) + # pragma on an object static: assert Subfield.hasCustomPragma(defaultValue) @@ -71,6 +74,8 @@ block: # ref types MyFile {.defaultValue: "closed".} = ref object path {.defaultValue: "invalid".}: string + TypeWithoutPragma = object + var s = NodeRef() const @@ -91,7 +96,7 @@ block: # ref types var ptrS = NodePtr(nil) const - ptrRightSerKey = getCustomPragmaVal(s.right, serializationKey) + ptrRightSerKey = getCustomPragmaVal(ptrS.right, serializationKey) static: assert ptrRightSerKey == "r" @@ -103,6 +108,9 @@ block: # ref types assert fileDefVal == "closed" assert filePathDefVal == "invalid" + static: + assert TypeWithoutPragma.hasCustomPragma(defaultValue) == false + block: type VariantKind = enum -- cgit 1.4.1-2-gfad0 From 7e15d5134bb4c98a96307d16621eb836543bb083 Mon Sep 17 00:00:00 2001 From: jcosborn Date: Thu, 19 Apr 2018 15:39:18 -0500 Subject: allow setting template/macro recursive evaluation limits (#7652) * allow setting template/macro recursive evaluation limits * revert setting template/macro eval limits set them to 1000 --- compiler/commands.nim | 1 - compiler/evaltempl.nim | 5 +++-- compiler/hlo.nim | 2 +- compiler/msgs.nim | 6 ++++-- compiler/sem.nim | 2 +- compiler/vm.nim | 6 ++++-- doc/advopt.txt | 2 +- 7 files changed, 14 insertions(+), 10 deletions(-) diff --git a/compiler/commands.nim b/compiler/commands.nim index 820cb7e1a..7274004a9 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -702,7 +702,6 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; expectNoArg(switch, arg, pass, info) useNimNamespace = true defineSymbol("cppCompileToNamespace") - else: if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg) else: invalidCmdLineOption(pass, switch, info) diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim index 704ff819c..fbb7eb2e6 100644 --- a/compiler/evaltempl.nim +++ b/compiler/evaltempl.nim @@ -106,8 +106,9 @@ proc evalTemplateArgs(n: PNode, s: PSym; fromHlo: bool): PNode = for i in 1 .. genericParams: result.addSon n.sons[givenRegularParams + i] +# to prevent endless recursion in template instantiation +const evalTemplateLimit* = 1000 var evalTemplateCounter* = 0 - # to prevent endless recursion in templates instantiation proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode = when true: @@ -133,7 +134,7 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode = proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; fromHlo=false): PNode = inc(evalTemplateCounter) - if evalTemplateCounter > 100: + if evalTemplateCounter > evalTemplateLimit: globalError(n.info, errTemplateInstantiationTooNested) result = n diff --git a/compiler/hlo.nim b/compiler/hlo.nim index 2bffaa173..c4288c362 100644 --- a/compiler/hlo.nim +++ b/compiler/hlo.nim @@ -44,7 +44,7 @@ proc applyPatterns(c: PContext, n: PNode): PNode = assert x.kind in {nkStmtList, nkCall} # better be safe than sorry, so check evalTemplateCounter too: inc(evalTemplateCounter) - if evalTemplateCounter > 100: + if evalTemplateCounter > evalTemplateLimit: globalError(n.info, errTemplateInstantiationTooNested) # deactivate this pattern: c.patterns[i] = nil diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 818ab0c05..749d29b55 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -87,7 +87,8 @@ type errNoReturnTypeDeclared, errNoCommand, errInvalidCommandX, errXOnlyAtModuleScope, errXNeedsParamObjectType, - errTemplateInstantiationTooNested, errInstantiationFrom, + errTemplateInstantiationTooNested, errMacroInstantiationTooNested, + errInstantiationFrom, errInvalidIndexValueForTuple, errCommandExpectsFilename, errMainModuleMustBeSpecified, errXExpected, @@ -329,7 +330,8 @@ const errInvalidCommandX: "invalid command: \'$1\'", errXOnlyAtModuleScope: "\'$1\' is only allowed at top level", errXNeedsParamObjectType: "'$1' needs a parameter that has an object type", - errTemplateInstantiationTooNested: "template/macro instantiation too nested", + errTemplateInstantiationTooNested: "template instantiation too nested, try --evalTemplateLimit:N", + errMacroInstantiationTooNested: "macro instantiation too nested, try --evalMacroLimit:N", errInstantiationFrom: "template/generic instantiation from here", errInvalidIndexValueForTuple: "invalid index value for tuple subscript", errCommandExpectsFilename: "command expects a filename argument", diff --git a/compiler/sem.nim b/compiler/sem.nim index 4fef1bc60..041f2e127 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -377,7 +377,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode, ## reassigned, and binding the unbound identifiers that the macro output ## contains. inc(evalTemplateCounter) - if evalTemplateCounter > 100: + if evalTemplateCounter > evalTemplateLimit: globalError(s.info, errTemplateInstantiationTooNested) c.friendModules.add(s.owner.getModule) diff --git a/compiler/vm.nim b/compiler/vm.nim index 5ef782abd..5b5ccdce4 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1729,14 +1729,16 @@ iterator genericParamsInMacroCall*(macroSym: PSym, call: PNode): (PSym, PNode) = let posInCall = macroSym.typ.len + i yield (genericParam, call[posInCall]) +# to prevent endless recursion in macro instantiation +const evalMacroLimit = 1000 var evalMacroCounter: int proc evalMacroCall*(module: PSym; cache: IdentCache, n, nOrig: PNode, sym: PSym): PNode = # XXX globalError() is ugly here, but I don't know a better solution for now inc(evalMacroCounter) - if evalMacroCounter > 100: - globalError(n.info, errTemplateInstantiationTooNested) + if evalMacroCounter > evalMacroLimit: + globalError(n.info, errMacroInstantiationTooNested) # immediate macros can bypass any type and arity checking so we check the # arity here too: diff --git a/doc/advopt.txt b/doc/advopt.txt index 214ac8dd2..bf7dd7fb4 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -76,7 +76,7 @@ Advanced options: --NimblePath:PATH add a path for Nimble support --noNimblePath deactivate the Nimble path --noCppExceptions use default exception handling with C++ backend - --cppCompileToNamespace use namespace "Nim" for the generated C++ code + --cppCompileToNamespace use namespace "Nim" for the generated C++ code --excludePath:PATH exclude a path from the list of search paths --dynlibOverride:SYMBOL marks SYMBOL so that dynlib:SYMBOL has no effect and can be statically linked instead; -- cgit 1.4.1-2-gfad0 From 7d034d7b6a1e566c72c762c9e1576afa8d455410 Mon Sep 17 00:00:00 2001 From: Oscar Nihlgård Date: Thu, 19 Apr 2018 22:41:06 +0200 Subject: Add `fromWinTime` and deprecate `unixTimeToWinTime`/`winTimeToUnixTime` (#7641) --- lib/pure/os.nim | 14 ++++++-------- lib/pure/times.nim | 39 ++++++++++++++++++++++++++------------- tests/stdlib/ttimes.nim | 9 ++++++++- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 8298024d6..ddeee2c6b 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -188,7 +188,7 @@ proc getLastModificationTime*(file: string): times.Time {.rtl, extern: "nos$1".} var f: WIN32_FIND_DATA var h = findFirstFile(file, f) if h == -1'i32: raiseOSError(osLastError()) - result = fromUnix(winTimeToUnixTime(rdFileTime(f.ftLastWriteTime)).int64) + result = fromWinTime(rdFileTime(f.ftLastWriteTime)) findClose(h) proc getLastAccessTime*(file: string): times.Time {.rtl, extern: "nos$1".} = @@ -201,7 +201,7 @@ proc getLastAccessTime*(file: string): times.Time {.rtl, extern: "nos$1".} = var f: WIN32_FIND_DATA var h = findFirstFile(file, f) if h == -1'i32: raiseOSError(osLastError()) - result = fromUnix(winTimeToUnixTime(rdFileTime(f.ftLastAccessTime)).int64) + result = fromWinTime(rdFileTime(f.ftLastAccessTime)) findClose(h) proc getCreationTime*(file: string): times.Time {.rtl, extern: "nos$1".} = @@ -218,7 +218,7 @@ proc getCreationTime*(file: string): times.Time {.rtl, extern: "nos$1".} = var f: WIN32_FIND_DATA var h = findFirstFile(file, f) if h == -1'i32: raiseOSError(osLastError()) - result = fromUnix(winTimeToUnixTime(rdFileTime(f.ftCreationTime)).int64) + result = fromWinTime(rdFileTime(f.ftCreationTime)) findClose(h) proc fileNewer*(a, b: string): bool {.rtl, extern: "nos$1".} = @@ -1512,16 +1512,14 @@ template rawToFormalFileInfo(rawInfo, path, formalInfo): untyped = ## 'rawInfo' is either a 'TBY_HANDLE_FILE_INFORMATION' structure on Windows, ## or a 'Stat' structure on posix when defined(Windows): - template toTime(e: FILETIME): untyped {.gensym.} = - fromUnix(winTimeToUnixTime(rdFileTime(e)).int64) # local templates default to bind semantics template merge(a, b): untyped = a or (b shl 32) formalInfo.id.device = rawInfo.dwVolumeSerialNumber formalInfo.id.file = merge(rawInfo.nFileIndexLow, rawInfo.nFileIndexHigh) formalInfo.size = merge(rawInfo.nFileSizeLow, rawInfo.nFileSizeHigh) formalInfo.linkCount = rawInfo.nNumberOfLinks - formalInfo.lastAccessTime = toTime(rawInfo.ftLastAccessTime) - formalInfo.lastWriteTime = toTime(rawInfo.ftLastWriteTime) - formalInfo.creationTime = toTime(rawInfo.ftCreationTime) + formalInfo.lastAccessTime = fromWinTime(rdFileTime(rawInfo.ftLastAccessTime)) + formalInfo.lastWriteTime = fromWinTime(rdFileTime(rawInfo.ftLastWriteTime)) + formalInfo.creationTime = fromWinTime(rdFileTime(rawInfo.ftCreationTime)) # Retrieve basic permissions if (rawInfo.dwFileAttributes and FILE_ATTRIBUTE_READONLY) != 0'i32: diff --git a/lib/pure/times.nim b/lib/pure/times.nim index cad32b51a..bf63ed344 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -374,9 +374,20 @@ proc toUnix*(t: Time): int64 {.benign, tags: [], raises: [], noSideEffect.} = ## Convert ``t`` to a unix timestamp (seconds since ``1970-01-01T00:00:00Z``). t.seconds +proc fromWinTime*(win: int64): Time = + ## Convert a Windows file time (100-nanosecond intervals since ``1601-01-01T00:00:00Z``) + ## to a ``Time``. + let hnsecsSinceEpoch = (win - epochDiff) + var seconds = hnsecsSinceEpoch div rateDiff + var nanos = ((hnsecsSinceEpoch mod rateDiff) * 100).int + if nanos < 0: + nanos += convert(Seconds, Nanoseconds, 1) + seconds -= 1 + result = initTime(seconds, nanos) + proc toWinTime*(t: Time): int64 = ## Convert ``t`` to a Windows file time (100-nanosecond intervals since ``1601-01-01T00:00:00Z``). - result = t.seconds * rateDiff + epochDiff + result = t.seconds * rateDiff + epochDiff + t.nanoseconds div 100 proc isLeapYear*(year: int): bool = ## Returns true if ``year`` is a leap year. @@ -860,10 +871,7 @@ proc getTime*(): Time {.tags: [TimeEffect], benign.} = elif defined(windows): var f: FILETIME getSystemTimeAsFileTime(f) - let nanosSinceEpoch = (rdFileTime(f) - epochDiff) * 100 - let seconds = convert(Nanoseconds, Seconds, nanosSinceEpoch) - let nanos = (nanosSinceEpoch mod convert(Seconds, Nanoseconds, 1)).int - result = initTime(seconds, nanos) + result = fromWinTime(rdFileTime(f)) proc now*(): DateTime {.tags: [TimeEffect], benign.} = ## Get the current time as a ``DateTime`` in the local timezone. @@ -1720,14 +1728,6 @@ when not defined(JS): var clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int - proc unixTimeToWinTime*(time: CTime): int64 = - ## converts a UNIX `Time` (``time_t``) to a Windows file time - result = int64(time) * rateDiff + epochDiff - - proc winTimeToUnixTime*(time: int64): CTime = - ## converts a Windows time to a UNIX `Time` (``time_t``) - result = CTime((time - epochDiff) div rateDiff) - when not defined(useNimRtl): proc cpuTime*(): float {.rtl, extern: "nt$1", tags: [TimeEffect].} = ## gets time spent that the CPU spent to run the current process in @@ -1769,6 +1769,19 @@ when defined(JS): # Deprecated procs +when not defined(JS): + proc unixTimeToWinTime*(time: CTime): int64 {.deprecated: "Use toWinTime instead".} = + ## Converts a UNIX `Time` (``time_t``) to a Windows file time + ## + ## **Deprecated:** use ``toWinTime`` instead. + result = int64(time) * rateDiff + epochDiff + + proc winTimeToUnixTime*(time: int64): CTime {.deprecated: "Use fromWinTime instead".} = + ## Converts a Windows time to a UNIX `Time` (``time_t``) + ## + ## **Deprecated:** use ``fromWinTime`` instead. + result = CTime((time - epochDiff) div rateDiff) + proc initInterval*(seconds, minutes, hours, days, months, years: int = 0): TimeInterval {.deprecated.} = ## **Deprecated since v0.18.0:** use ``initTimeInterval`` instead. diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim index f35965286..945d7ba3d 100644 --- a/tests/stdlib/ttimes.nim +++ b/tests/stdlib/ttimes.nim @@ -409,4 +409,11 @@ suite "ttimes": # Bug with adding a day to a Time let day = 24.hours let tomorrow = now + day - check tomorrow - now == initDuration(days = 1) \ No newline at end of file + check tomorrow - now == initDuration(days = 1) + + test "fromWinTime/toWinTime": + check 0.fromUnix.toWinTime.fromWinTime.toUnix == 0 + check (-1).fromWinTime.nanoseconds == convert(Seconds, Nanoseconds, 1) - 100 + check -1.fromWinTime.toWinTime == -1 + # One nanosecond is discarded due to differences in time resolution + check initTime(0, 101).toWinTime.fromWinTime.nanoseconds == 100 \ No newline at end of file -- cgit 1.4.1-2-gfad0 From 262aafa0a915fc5c769824f7f7d63f9dc9e649c7 Mon Sep 17 00:00:00 2001 From: tersec Date: Fri, 20 Apr 2018 05:04:50 +0000 Subject: https://reproducible-builds.org/ support via SOURCE_DATE_EPOCH (#7644) (#7661) --- compiler/semfold.nim | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 096fc19e0..6fcc9a0a4 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -483,6 +483,19 @@ proc newSymNodeTypeDesc*(s: PSym; info: TLineInfo): PNode = proc getConstExpr(m: PSym, n: PNode): PNode = result = nil + + proc getSrcTimestamp(): DateTime = + try: + result = utc(fromUnix(parseInt(getEnv("SOURCE_DATE_EPOCH", + "not a number")))) + except ValueError: + # Environment variable malformed. + # https://reproducible-builds.org/specs/source-date-epoch/: "If the + # value is malformed, the build process SHOULD exit with a non-zero + # error code", which this doesn't do. This uses local time, because + # that maintains compatibility with existing usage. + result = local(getTime()) + case n.kind of nkSym: var s = n.sym @@ -492,8 +505,10 @@ proc getConstExpr(m: PSym, n: PNode): PNode = of skConst: case s.magic of mIsMainModule: result = newIntNodeT(ord(sfMainModule in m.flags), n) - of mCompileDate: result = newStrNodeT(times.getDateStr(), n) - of mCompileTime: result = newStrNodeT(times.getClockStr(), n) + of mCompileDate: result = newStrNodeT(format(getSrcTimestamp(), + "yyyy-MM-dd"), n) + of mCompileTime: result = newStrNodeT(format(getSrcTimestamp(), + "HH:mm:ss"), n) of mCpuEndian: result = newIntNodeT(ord(CPU[targetCPU].endian), n) of mHostOS: result = newStrNodeT(toLowerAscii(platform.OS[targetOS].name), n) of mHostCPU: result = newStrNodeT(platform.CPU[targetCPU].name.toLowerAscii, n) -- cgit 1.4.1-2-gfad0 From 9cc8fec370867d2f75b16c3ec85a38a5c379909a Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 20 Apr 2018 08:45:03 +0200 Subject: replace --advanced by --fullhelp; refs #7621 --- compiler/commands.nim | 11 +++++++++++ doc/basicopt.txt | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/commands.nim b/compiler/commands.nim index 7274004a9..ec58706f3 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -77,6 +77,14 @@ proc writeAdvancedUsage(pass: TCmdLinePass) = {msgStdout}) msgQuit(0) +proc writeFullhelp(pass: TCmdLinePass) = + if pass == passCmd1: + msgWriteln(`%`(HelpMessage, [VersionAsString, + platform.OS[platform.hostOS].name, + CPU[platform.hostCPU].name]) & Usage & AdvancedUsage, + {msgStdout}) + msgQuit(0) + proc writeVersionInfo(pass: TCmdLinePass) = if pass == passCmd1: msgWriteln(`%`(HelpMessage, [VersionAsString, @@ -611,6 +619,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "advanced": expectNoArg(switch, arg, pass, info) writeAdvancedUsage(pass) + of "fullhelp": + expectNoArg(switch, arg, pass, info) + writeFullhelp(pass) of "help", "h": expectNoArg(switch, arg, pass, info) helpOnError(pass) diff --git a/doc/basicopt.txt b/doc/basicopt.txt index 4db2d5af7..4c11cc767 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -36,7 +36,7 @@ Options: --app:console|gui|lib|staticlib generate a console app|GUI app|DLL|static library -r, --run run the compiled program with given arguments - --advanced show advanced command line switches + --fullhelp show all command line switches -h, --help show this help Note, single letter options that take an argument require a colon. E.g. -p:PATH. -- cgit 1.4.1-2-gfad0 From 6667362c2f1cd0fc1fdb1dacb486528b928470d5 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 20 Apr 2018 08:54:56 +0200 Subject: refs #7586; show surounding source also for hints and warnsings --- compiler/msgs.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 749d29b55..35be5e772 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -1048,7 +1048,7 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string, KindColor, `%`(KindFormat, kind)) else: styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s) - if msg in errMin..errMax and hintSource in gNotes: + if hintSource in gNotes: info.writeSurroundingSrc handleError(msg, eh, s) -- cgit 1.4.1-2-gfad0 From 33b69f0ed0272a4792322d9a0fbaffd5bef2f6e9 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 21 Apr 2018 08:13:37 +0200 Subject: refactoring: make FileIndex a distinct type; make line information an uint16; fixes #7654 --- compiler/ast.nim | 10 ++-- compiler/ccgexprs.nim | 2 +- compiler/cgen.nim | 12 ++--- compiler/commands.nim | 2 +- compiler/docgen.nim | 10 ++-- compiler/filter_tmpl.nim | 6 +-- compiler/jsgen.nim | 2 +- compiler/lexer.nim | 18 +++---- compiler/main.nim | 4 +- compiler/modulegraphs.nim | 40 ++++++++------- compiler/modulepaths.nim | 2 +- compiler/modules.nim | 20 ++++---- compiler/msgs.nim | 107 ++++++++++++++++++++------------------- compiler/nimfix/pretty.nim | 10 ++-- compiler/nimfix/prettybase.nim | 16 +++--- compiler/parampatterns.nim | 3 +- compiler/parser.nim | 2 +- compiler/passes.nim | 24 ++------- compiler/pbraces.nim | 2 +- compiler/pragmas.nim | 2 +- compiler/reorder.nim | 20 ++++---- compiler/rod.nim | 112 ++--------------------------------------- compiler/rodread.nim | 47 +++++++++-------- compiler/rodwrite.nim | 10 ++-- compiler/semdata.nim | 2 +- compiler/semstmts.nim | 8 +-- compiler/suggest.nim | 4 +- compiler/syntaxes.nim | 4 +- compiler/vm.nim | 6 +-- 29 files changed, 196 insertions(+), 311 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index da7e828f2..4a0a9a20b 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1042,9 +1042,9 @@ proc newNode*(kind: TNodeKind): PNode = new(result) result.kind = kind #result.info = UnknownLineInfo() inlined: - result.info.fileIndex = int32(-1) + result.info.fileIndex = InvalidFileIdx result.info.col = int16(-1) - result.info.line = int16(-1) + result.info.line = uint16(0) when defined(useNodeIds): result.id = gNodeId if result.id == nodeIdToDebug: @@ -1116,13 +1116,13 @@ proc linkTo*(s: PSym, t: PType): PSym {.discardable.} = s.typ = t result = s -template fileIdx*(c: PSym): int32 = +template fileIdx*(c: PSym): FileIndex = # XXX: this should be used only on module symbols - c.position.int32 + c.position.FileIndex template filename*(c: PSym): string = # XXX: this should be used only on module symbols - c.position.int32.toFilename + c.position.FileIndex.toFilename proc appendToModule*(m: PSym, n: PNode) = ## The compiler will use this internally to add nodes that will be diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 7e3c2632a..461a86298 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2023,7 +2023,7 @@ template genStmtListExprImpl(exprOrStmt) {.dirty.} = let theMacro = it[0].sym add p.s(cpsStmts), initFrameNoDebug(p, frameName, makeCString theMacro.name.s, - theMacro.info.quotedFilename, it.info.line) + theMacro.info.quotedFilename, it.info.line.int) else: genStmts(p, it) if n.len > 0: exprOrStmt diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 4d3cabd3a..9e1f9349f 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -223,7 +223,7 @@ proc genLineDir(p: BProc, t: PNode) = line.rope, makeCString(toFilename(tt.info))) elif ({optLineTrace, optStackTrace} * p.options == {optLineTrace, optStackTrace}) and - (p.prc == nil or sfPure notin p.prc.flags) and tt.info.fileIndex >= 0: + (p.prc == nil or sfPure notin p.prc.flags) and tt.info.fileIndex != InvalidFileIDX: if freshLineInfo(p, tt.info): linefmt(p, cpsStmts, "nimln_($1, $2);$n", line.rope, tt.info.quotedFilename) @@ -678,7 +678,7 @@ proc generateHeaders(m: BModule) = proc openNamespaceNim(): Rope = result.add("namespace Nim {" & tnl) - + proc closeNamespaceNim(): Rope = result.add("}" & tnl) @@ -1090,7 +1090,7 @@ proc genMainProc(m: BModule) = appcg(m, m.s[cfsProcs], nimMain, [m.g.mainModInit, initStackBottomCall, rope(m.labels)]) if optNoMain notin gGlobalOptions: - if useNimNamespace: + if useNimNamespace: m.s[cfsProcs].add closeNamespaceNim() & "using namespace Nim;" & tnl appcg(m, m.s[cfsProcs], otherMain, []) @@ -1202,7 +1202,7 @@ proc genModule(m: BModule, cfile: Cfile): Rope = add(result, genSectionStart(i)) add(result, m.s[i]) add(result, genSectionEnd(i)) - if useNimNamespace and i == cfsHeaders: result.add openNamespaceNim() + if useNimNamespace and i == cfsHeaders: result.add openNamespaceNim() add(result, m.s[cfsInitProc]) if useNimNamespace: result.add closeNamespaceNim() @@ -1301,7 +1301,7 @@ proc resetCgenModules*(g: BModuleList) = for m in cgenModules(g): resetModule(m) proc rawNewModule(g: BModuleList; module: PSym): BModule = - result = rawNewModule(g, module, module.position.int32.toFullPath) + result = rawNewModule(g, module, module.position.FileIndex.toFullPath) proc newModule(g: BModuleList; module: PSym): BModule = # we should create only one cgen module for each module sym @@ -1311,7 +1311,7 @@ proc newModule(g: BModuleList; module: PSym): BModule = if (optDeadCodeElim in gGlobalOptions): if (sfDeadCodeElim in module.flags): - internalError("added pending module twice: " & module.filename) + internalError("added pending module twice: " & toFilename(FileIndex module.position)) template injectG(config) {.dirty.} = if graph.backend == nil: diff --git a/compiler/commands.nim b/compiler/commands.nim index ec58706f3..e1dc1aacf 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -319,7 +319,7 @@ proc trackDirty(arg: string, info: TLineInfo) = localError(info, errInvalidNumber, a[2]) let dirtyOriginalIdx = a[1].fileInfoIdx - if dirtyOriginalIdx >= 0: + if dirtyOriginalIdx.int32 >= 0: msgs.setDirtyFile(dirtyOriginalIdx, a[0]) gTrackPos = newLineInfo(dirtyOriginalIdx, line, column) diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 74fb305ac..6f3dcde8b 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -544,7 +544,7 @@ proc genJsonItem(d: PDoc, n, nameNode: PNode, k: TSymKind): JsonNode = initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments}) - result = %{ "name": %name, "type": %($k), "line": %n.info.line, + result = %{ "name": %name, "type": %($k), "line": %n.info.line.int, "col": %n.info.col} if comm != nil and comm != "": result["description"] = %comm @@ -618,7 +618,7 @@ proc generateJson*(d: PDoc, n: PNode) = of nkCommentStmt: if n.comment != nil and startsWith(n.comment, "##"): let stripped = n.comment.substr(2).strip - d.add %{ "comment": %stripped, "line": %n.info.line, + d.add %{ "comment": %stripped, "line": %n.info.line.int, "col": %n.info.col } of nkProcDef: when useEffectSystem: documentRaises(n) @@ -790,7 +790,7 @@ proc writeOutputJson*(d: PDoc, filename, outExt: string, discard "fixme: error report" proc commandDoc*() = - var ast = parseFile(gProjectMainIdx, newIdentCache()) + var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache()) if ast == nil: return var d = newDocumentor(gProjectFull, options.gConfigVars) d.hasToc = true @@ -840,7 +840,7 @@ proc commandRst2TeX*() = commandRstAux(gProjectFull, TexExt) proc commandJson*() = - var ast = parseFile(gProjectMainIdx, newIdentCache()) + var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache()) if ast == nil: return var d = newDocumentor(gProjectFull, options.gConfigVars) d.hasToc = true @@ -855,7 +855,7 @@ proc commandJson*() = writeRope(content, getOutFile(gProjectFull, JsonExt), useWarning = false) proc commandTags*() = - var ast = parseFile(gProjectMainIdx, newIdentCache()) + var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache()) if ast == nil: return var d = newDocumentor(gProjectFull, options.gConfigVars) d.hasToc = true diff --git a/compiler/filter_tmpl.nim b/compiler/filter_tmpl.nim index ca9a3a801..a1ba9113c 100644 --- a/compiler/filter_tmpl.nim +++ b/compiler/filter_tmpl.nim @@ -35,7 +35,7 @@ const proc newLine(p: var TTmplParser) = llStreamWrite(p.outp, repeat(')', p.emitPar)) p.emitPar = 0 - if p.info.line > int16(1): llStreamWrite(p.outp, "\n") + if p.info.line > uint16(1): llStreamWrite(p.outp, "\n") if p.pendingExprLine: llStreamWrite(p.outp, spaces(2)) p.pendingExprLine = false @@ -212,9 +212,9 @@ proc filterTmpl*(stdin: PLLStream, filename: string, call: PNode): PLLStream = p.x = newStringOfCap(120) # do not process the first line which contains the directive: if llStreamReadLine(p.inp, p.x): - p.info.line = p.info.line + int16(1) + p.info.line = p.info.line + 1'u16 while llStreamReadLine(p.inp, p.x): - p.info.line = p.info.line + int16(1) + p.info.line = p.info.line + 1'u16 parseLine(p) newLine(p) result = p.outp diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 475508946..2ae3426ab 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -2261,7 +2261,7 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode = var m = BModule(b) if sfMainModule in m.module.flags: let ext = "js" - let f = if globals.classes.len == 0: m.module.filename + let f = if globals.classes.len == 0: toFilename(FileIndex m.module.position) else: "nimsystem" let code = wholeCode(graph, m) let outfile = diff --git a/compiler/lexer.nim b/compiler/lexer.nim index a4a2615bd..0b1090bb1 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -133,7 +133,7 @@ type TErrorHandler* = proc (info: TLineInfo; msg: TMsgKind; arg: string) TLexer* = object of TBaseLexer - fileIdx*: int32 + fileIdx*: FileIndex indentAhead*: int # if > 0 an indendation has already been read # this is needed because scanning comments # needs so much look-ahead @@ -222,7 +222,7 @@ proc fillToken(L: var TToken) = L.commentOffsetA = 0 L.commentOffsetB = 0 -proc openLexer*(lex: var TLexer, fileIdx: int32, inputstream: PLLStream; +proc openLexer*(lex: var TLexer, fileIdx: FileIndex, inputstream: PLLStream; cache: IdentCache) = openBaseLexer(lex, inputstream) lex.fileIdx = fileidx @@ -274,7 +274,7 @@ template tokenEnd(tok, pos) {.dirty.} = when defined(nimsuggest): let colB = getColNumber(L, pos)+1 if L.fileIdx == gTrackPos.fileIndex and gTrackPos.col in colA..colB and - L.lineNumber == gTrackPos.line and gIdeCmd in {ideSug, ideCon}: + L.lineNumber == gTrackPos.line.int and gIdeCmd in {ideSug, ideCon}: L.cursor = CursorPosition.InToken gTrackPos.col = colA.int16 colA = 0 @@ -285,9 +285,9 @@ template tokenEndIgnore(tok, pos) = when defined(nimsuggest): let colB = getColNumber(L, pos) if L.fileIdx == gTrackPos.fileIndex and gTrackPos.col in colA..colB and - L.lineNumber == gTrackPos.line and gIdeCmd in {ideSug, ideCon}: + L.lineNumber == gTrackPos.line.int and gIdeCmd in {ideSug, ideCon}: gTrackPos.fileIndex = trackPosInvalidFileIdx - gTrackPos.line = -1 + gTrackPos.line = 0'u16 colA = 0 when defined(nimpretty): tok.offsetB = L.offsetBase + pos @@ -299,7 +299,7 @@ template tokenEndPrevious(tok, pos) = # the cursor in a string literal or comment: let colB = getColNumber(L, pos) if L.fileIdx == gTrackPos.fileIndex and gTrackPos.col in colA..colB and - L.lineNumber == gTrackPos.line and gIdeCmd in {ideSug, ideCon}: + L.lineNumber == gTrackPos.line.int and gIdeCmd in {ideSug, ideCon}: L.cursor = CursorPosition.BeforeToken gTrackPos = L.previousToken gTrackPosAttached = true @@ -1066,7 +1066,7 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) = when defined(nimsuggest): # we attach the cursor to the last *strong* token if tok.tokType notin weakTokens: - L.previousToken.line = tok.line.int16 + L.previousToken.line = tok.line.uint16 L.previousToken.col = tok.col.int16 when defined(nimsuggest): @@ -1118,7 +1118,7 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) = tok.tokType = tkParLe when defined(nimsuggest): if L.fileIdx == gTrackPos.fileIndex and tok.col < gTrackPos.col and - tok.line == gTrackPos.line and gIdeCmd == ideCon: + tok.line == gTrackPos.line.int and gIdeCmd == ideCon: gTrackPos.col = tok.col.int16 of ')': tok.tokType = tkParRi @@ -1139,7 +1139,7 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) = of '.': when defined(nimsuggest): if L.fileIdx == gTrackPos.fileIndex and tok.col+1 == gTrackPos.col and - tok.line == gTrackPos.line and gIdeCmd == ideSug: + tok.line == gTrackPos.line.int and gIdeCmd == ideSug: tok.tokType = tkDot L.cursor = CursorPosition.InToken gTrackPos.col = tok.col.int16 diff --git a/compiler/main.nim b/compiler/main.nim index c928c81cd..401099fc3 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -35,7 +35,7 @@ proc writeDepsFile(g: ModuleGraph; project: string) = let f = open(changeFileExt(project, "deps"), fmWrite) for m in g.modules: if m != nil: - f.writeLine(toFullPath(m.position.int32)) + f.writeLine(toFullPath(m.position.FileIndex)) for k in g.inclToMod.keys: if g.getModule(k).isNil: # don't repeat includes which are also modules f.writeLine(k.toFullPath) @@ -265,7 +265,7 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) = of "parse": gCmd = cmdParse wantMainModule() - discard parseFile(gProjectMainIdx, cache) + discard parseFile(FileIndex gProjectMainIdx, cache) of "scan": gCmd = cmdScan wantMainModule() diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index 2c59a9097..6c14a46e8 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -25,7 +25,7 @@ ## - Its dependent module stays the same. ## -import ast, intsets, tables, options, rod +import ast, intsets, tables, options, rod, msgs, hashes type ModuleGraph* = ref object @@ -34,10 +34,10 @@ type deps*: IntSet # the dependency graph or potentially its transitive closure. suggestMode*: bool # whether we are in nimsuggest mode or not. invalidTransitiveClosure: bool - inclToMod*: Table[int32, int32] # mapping of include file to the - # first module that included it - importStack*: seq[int32] # The current import stack. Used for detecting recursive - # module dependencies. + inclToMod*: Table[FileIndex, FileIndex] # mapping of include file to the + # first module that included it + importStack*: seq[FileIndex] # The current import stack. Used for detecting recursive + # module dependencies. backend*: RootRef # minor hack so that a backend can extend this easily config*: ConfigRef doStopCompile*: proc(): bool {.closure.} @@ -45,6 +45,8 @@ type owners*: seq[PSym] methods*: seq[tuple[methods: TSymSeq, dispatcher: PSym]] +proc hash*(x: FileIndex): Hash {.borrow.} + {.this: g.} proc stopCompile*(g: ModuleGraph): bool {.inline.} = @@ -56,7 +58,7 @@ proc newModuleGraph*(config: ConfigRef = nil): ModuleGraph = result.deps = initIntSet() result.modules = @[] result.importStack = @[] - result.inclToMod = initTable[int32, int32]() + result.inclToMod = initTable[FileIndex, FileIndex]() if config.isNil: result.config = newConfigRef() else: @@ -69,35 +71,35 @@ proc resetAllModules*(g: ModuleGraph) = deps = initIntSet() modules = @[] importStack = @[] - inclToMod = initTable[int32, int32]() + inclToMod = initTable[FileIndex, FileIndex]() usageSym = nil owners = @[] methods = @[] -proc getModule*(g: ModuleGraph; fileIdx: int32): PSym = - if fileIdx >= 0 and fileIdx < modules.len: - result = modules[fileIdx] +proc getModule*(g: ModuleGraph; fileIdx: FileIndex): PSym = + if fileIdx.int32 >= 0 and fileIdx.int32 < modules.len: + result = modules[fileIdx.int32] proc dependsOn(a, b: int): int {.inline.} = (a shl 15) + b -proc addDep*(g: ModuleGraph; m: PSym, dep: int32) = - assert m.position == m.info.fileIndex +proc addDep*(g: ModuleGraph; m: PSym, dep: FileIndex) = + assert m.position == m.info.fileIndex.int32 addModuleDep(m.info.fileIndex, dep, isIncludeFile = false) if suggestMode: - deps.incl m.position.dependsOn(dep) + deps.incl m.position.dependsOn(dep.int) # we compute the transitive closure later when quering the graph lazily. # this improve efficiency quite a lot: #invalidTransitiveClosure = true -proc addIncludeDep*(g: ModuleGraph; module, includeFile: int32) = +proc addIncludeDep*(g: ModuleGraph; module, includeFile: FileIndex) = addModuleDep(module, includeFile, isIncludeFile = true) discard hasKeyOrPut(inclToMod, includeFile, module) -proc parentModule*(g: ModuleGraph; fileIdx: int32): int32 = +proc parentModule*(g: ModuleGraph; fileIdx: FileIndex): FileIndex = ## returns 'fileIdx' if the file belonging to this index is ## directly used as a module or else the module that first ## references this include file. - if fileIdx >= 0 and fileIdx < modules.len and modules[fileIdx] != nil: + if fileIdx.int32 >= 0 and fileIdx.int32 < modules.len and modules[fileIdx.int32] != nil: result = fileIdx else: result = inclToMod.getOrDefault(fileIdx) @@ -111,11 +113,11 @@ proc transitiveClosure(g: var IntSet; n: int) = if g.contains(i.dependsOn(k)) and g.contains(k.dependsOn(j)): g.incl i.dependsOn(j) -proc markDirty*(g: ModuleGraph; fileIdx: int32) = +proc markDirty*(g: ModuleGraph; fileIdx: FileIndex) = let m = getModule fileIdx if m != nil: incl m.flags, sfDirty -proc markClientsDirty*(g: ModuleGraph; fileIdx: int32) = +proc markClientsDirty*(g: ModuleGraph; fileIdx: FileIndex) = # we need to mark its dependent modules D as dirty right away because after # nimsuggest is done with this module, the module's dirty flag will be # cleared but D still needs to be remembered as 'dirty'. @@ -126,7 +128,7 @@ proc markClientsDirty*(g: ModuleGraph; fileIdx: int32) = # every module that *depends* on this file is also dirty: for i in 0i32..=% L: result = unknownLineInfo() else: result = msgContext[i] -template toFilename*(fileIdx: int32): string = - (if fileIdx < 0: "???" else: fileInfos[fileIdx].projPath) +template toFilename*(fileIdx: FileIndex): string = + (if fileIdx.int32 < 0: "???" else: fileInfos[fileIdx.int32].projPath) -proc toFullPath*(fileIdx: int32): string = - if fileIdx < 0: result = "???" - else: result = fileInfos[fileIdx].fullPath +proc toFullPath*(fileIdx: FileIndex): string = + if fileIdx.int32 < 0: result = "???" + else: result = fileInfos[fileIdx.int32].fullPath -proc setDirtyFile*(fileIdx: int32; filename: string) = - assert fileIdx >= 0 - fileInfos[fileIdx].dirtyFile = filename +proc setDirtyFile*(fileIdx: FileIndex; filename: string) = + assert fileIdx.int32 >= 0 + fileInfos[fileIdx.int32].dirtyFile = filename -proc setHash*(fileIdx: int32; hash: string) = - assert fileIdx >= 0 - shallowCopy(fileInfos[fileIdx].hash, hash) +proc setHash*(fileIdx: FileIndex; hash: string) = + assert fileIdx.int32 >= 0 + shallowCopy(fileInfos[fileIdx.int32].hash, hash) -proc getHash*(fileIdx: int32): string = - assert fileIdx >= 0 - shallowCopy(result, fileInfos[fileIdx].hash) +proc getHash*(fileIdx: FileIndex): string = + assert fileIdx.int32 >= 0 + shallowCopy(result, fileInfos[fileIdx.int32].hash) -proc toFullPathConsiderDirty*(fileIdx: int32): string = - if fileIdx < 0: +proc toFullPathConsiderDirty*(fileIdx: FileIndex): string = + if fileIdx.int32 < 0: result = "???" - elif not fileInfos[fileIdx].dirtyFile.isNil: - result = fileInfos[fileIdx].dirtyFile + elif not fileInfos[fileIdx.int32].dirtyFile.isNil: + result = fileInfos[fileIdx.int32].dirtyFile else: - result = fileInfos[fileIdx].fullPath + result = fileInfos[fileIdx.int32].fullPath template toFilename*(info: TLineInfo): string = info.fileIndex.toFilename @@ -762,15 +765,15 @@ template toFullPath*(info: TLineInfo): string = info.fileIndex.toFullPath proc toMsgFilename*(info: TLineInfo): string = - if info.fileIndex < 0: + if info.fileIndex.int32 < 0: result = "???" elif gListFullPaths: - result = fileInfos[info.fileIndex].fullPath + result = fileInfos[info.fileIndex.int32].fullPath else: - result = fileInfos[info.fileIndex].projPath + result = fileInfos[info.fileIndex.int32].projPath proc toLinenumber*(info: TLineInfo): int {.inline.} = - result = info.line + result = int info.line proc toColumn*(info: TLineInfo): int {.inline.} = result = info.col @@ -787,7 +790,7 @@ proc `??`* (info: TLineInfo, filename: string): bool = # only for debugging purposes result = filename in info.toFilename -const trackPosInvalidFileIdx* = -2 # special marker so that no suggestions +const trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions # are produced within comments and string literals var gTrackPos*: TLineInfo var gTrackPosAttached*: bool ## whether the tracking position was attached to some @@ -926,7 +929,7 @@ proc writeContext(lastinfo: TLineInfo) = else: styledMsgWriteln(styleBright, PosFormat % [toMsgFilename(msgContext[i]), - coordToStr(msgContext[i].line), + coordToStr(msgContext[i].line.int), coordToStr(msgContext[i].col+1)], resetStyle, getMessageStr(errInstantiationFrom, "")) @@ -994,7 +997,7 @@ proc formatMsg*(info: TLineInfo, msg: TMsgKind, arg: string): string = of warnMin..warnMax: WarningTitle of hintMin..hintMax: HintTitle else: ErrorTitle - result = PosFormat % [toMsgFilename(info), coordToStr(info.line), + result = PosFormat % [toMsgFilename(info), coordToStr(info.line.int), coordToStr(info.col+1)] & title & getMessageStr(msg, arg) @@ -1035,7 +1038,7 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string, # NOTE: currently line info line numbers start with 1, # but column numbers start with 0, however most editors expect # first column to be 1, so we need to +1 here - let x = PosFormat % [toMsgFilename(info), coordToStr(info.line), + let x = PosFormat % [toMsgFilename(info), coordToStr(info.line.int), coordToStr(info.col+1)] let s = getMessageStr(msg, arg) @@ -1093,30 +1096,30 @@ template assertNotNil*(e): untyped = template internalAssert*(e: bool) = if not e: internalError($instantiationInfo()) -proc addSourceLine*(fileIdx: int32, line: string) = - fileInfos[fileIdx].lines.add line.rope +proc addSourceLine*(fileIdx: FileIndex, line: string) = + fileInfos[fileIdx.int32].lines.add line.rope proc sourceLine*(i: TLineInfo): Rope = - if i.fileIndex < 0: return nil + if i.fileIndex.int32 < 0: return nil - if not optPreserveOrigSource and fileInfos[i.fileIndex].lines.len == 0: + if not optPreserveOrigSource and fileInfos[i.fileIndex.int32].lines.len == 0: try: for line in lines(i.toFullPath): addSourceLine i.fileIndex, line.string except IOError: discard - internalAssert i.fileIndex < fileInfos.len + internalAssert i.fileIndex.int32 < fileInfos.len # can happen if the error points to EOF: - if i.line > fileInfos[i.fileIndex].lines.len: return nil + if i.line.int > fileInfos[i.fileIndex.int32].lines.len: return nil - result = fileInfos[i.fileIndex].lines[i.line-1] + result = fileInfos[i.fileIndex.int32].lines[i.line.int-1] proc quotedFilename*(i: TLineInfo): Rope = - internalAssert i.fileIndex >= 0 + internalAssert i.fileIndex.int32 >= 0 if optExcessiveStackTrace in gGlobalOptions: - result = fileInfos[i.fileIndex].quotedFullName + result = fileInfos[i.fileIndex.int32].quotedFullName else: - result = fileInfos[i.fileIndex].quotedName + result = fileInfos[i.fileIndex.int32].quotedName ropes.errorHandler = proc (err: RopesError, msg: string, useWarning: bool) = case err diff --git a/compiler/nimfix/pretty.nim b/compiler/nimfix/pretty.nim index 55603f4cd..4627264dc 100644 --- a/compiler/nimfix/pretty.nim +++ b/compiler/nimfix/pretty.nim @@ -28,7 +28,7 @@ proc overwriteFiles*() = let doStrip = options.getConfigVar("pretty.strip").normalize == "on" for i in 0 .. high(gSourceFiles): if gSourceFiles[i].dirty and not gSourceFiles[i].isNimfixFile and - (not gOnlyMainfile or gSourceFiles[i].fileIdx == gProjectMainIdx): + (not gOnlyMainfile or gSourceFiles[i].fileIdx == gProjectMainIdx.FileIndex): let newFile = if gOverWrite: gSourceFiles[i].fullpath else: gSourceFiles[i].fullpath.changeFileExt(".pretty.nim") try: @@ -95,7 +95,7 @@ proc beautifyName(s: string, k: TSymKind): string = proc replaceInFile(info: TLineInfo; newName: string) = loadFile(info) - let line = gSourceFiles[info.fileIndex].lines[info.line-1] + let line = gSourceFiles[info.fileIndex.int].lines[info.line.int-1] var first = min(info.col.int, line.len) if first < 0: return #inc first, skipIgnoreCase(line, "proc ", first) @@ -107,8 +107,8 @@ proc replaceInFile(info: TLineInfo; newName: string) = if differ(line, first, last, newName): # last-first+1 != newName.len or var x = line.substr(0, first-1) & newName & line.substr(last+1) - system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) - gSourceFiles[info.fileIndex].dirty = true + system.shallowCopy(gSourceFiles[info.fileIndex.int].lines[info.line.int-1], x) + gSourceFiles[info.fileIndex.int].dirty = true proc checkStyle(info: TLineInfo, s: string, k: TSymKind; sym: PSym) = let beau = beautifyName(s, k) @@ -136,7 +136,7 @@ template styleCheckDef*(s: PSym) = styleCheckDef(s.info, s, s.kind) proc styleCheckUseImpl(info: TLineInfo; s: PSym) = - if info.fileIndex < 0: return + if info.fileIndex.int < 0: return # we simply convert it to what it looks like in the definition # for consistency diff --git a/compiler/nimfix/prettybase.nim b/compiler/nimfix/prettybase.nim index f1d24183b..ecb4b0093 100644 --- a/compiler/nimfix/prettybase.nim +++ b/compiler/nimfix/prettybase.nim @@ -16,13 +16,13 @@ type lines*: seq[string] dirty*, isNimfixFile*: bool fullpath*, newline*: string - fileIdx*: int32 + fileIdx*: FileIndex var gSourceFiles*: seq[TSourceFile] = @[] proc loadFile*(info: TLineInfo) = - let i = info.fileIndex + let i = info.fileIndex.int if i >= gSourceFiles.len: gSourceFiles.setLen(i+1) if gSourceFiles[i].lines.isNil: @@ -64,7 +64,7 @@ proc differ*(line: string, a, b: int, x: string): bool = proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PIdent) = loadFile(info) - let line = gSourceFiles[info.fileIndex].lines[info.line-1] + let line = gSourceFiles[info.fileIndex.int32].lines[info.line.int-1] var first = min(info.col.int, line.len) if first < 0: return #inc first, skipIgnoreCase(line, "proc ", first) @@ -75,8 +75,8 @@ proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PIdent) = let last = first+identLen(line, first)-1 if cmpIgnoreStyle(line[first..last], oldSym.s) == 0: var x = line.substr(0, first-1) & newSym.s & line.substr(last+1) - system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) - gSourceFiles[info.fileIndex].dirty = true + system.shallowCopy(gSourceFiles[info.fileIndex.int32].lines[info.line.int-1], x) + gSourceFiles[info.fileIndex.int32].dirty = true #if newSym.s == "File": writeStackTrace() proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PSym) = @@ -85,10 +85,10 @@ proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PSym) = proc replaceComment*(info: TLineInfo) = loadFile(info) - let line = gSourceFiles[info.fileIndex].lines[info.line-1] + let line = gSourceFiles[info.fileIndex.int32].lines[info.line.int-1] var first = info.col.int if line[first] != '#': inc first var x = line.substr(0, first-1) & "discard " & line.substr(first+1).escape - system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) - gSourceFiles[info.fileIndex].dirty = true + system.shallowCopy(gSourceFiles[info.fileIndex.int32].lines[info.line.int-1], x) + gSourceFiles[info.fileIndex.int32].dirty = true diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim index 8540f1b32..02c48c16d 100644 --- a/compiler/parampatterns.nim +++ b/compiler/parampatterns.nim @@ -235,7 +235,8 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult result = arLValue else: result = isAssignable(owner, n.sons[0], isUnsafeAddr) - if result != arNone and sfDiscriminant in n.sons[1].sym.flags: + if result != arNone and n[1].kind == nkSym and + sfDiscriminant in n[1].sym.flags: result = arDiscriminant of nkBracketExpr: if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in diff --git a/compiler/parser.nim b/compiler/parser.nim index 3bf75c6f7..ac0a57770 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -83,7 +83,7 @@ proc getTok(p: var TParser) = rawGetTok(p.lex, p.tok) p.hasProgress = true -proc openParser*(p: var TParser, fileIdx: int32, inputStream: PLLStream, +proc openParser*(p: var TParser, fileIdx: FileIndex, inputStream: PLLStream, cache: IdentCache; strongSpaces=false) = ## Open a parser, using the given arguments to set up its internal state. diff --git a/compiler/passes.nim b/compiler/passes.nim index f079100ea..d7c181676 100644 --- a/compiler/passes.nim +++ b/compiler/passes.nim @@ -52,8 +52,8 @@ proc makePass*(open: TPassOpen = nil, # the semantic checker needs these: var - gImportModule*: proc (graph: ModuleGraph; m: PSym, fileIdx: int32; cache: IdentCache): PSym {.nimcall.} - gIncludeFile*: proc (graph: ModuleGraph; m: PSym, fileIdx: int32; cache: IdentCache): PNode {.nimcall.} + gImportModule*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex; cache: IdentCache): PSym {.nimcall.} + gIncludeFile*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex; cache: IdentCache): PNode {.nimcall.} # implementation @@ -63,20 +63,6 @@ proc skipCodegen*(n: PNode): bool {.inline.} = # error count instead. result = msgs.gErrorCounter > 0 -proc astNeeded*(s: PSym): bool = - # The ``rodwrite`` module uses this to determine if the body of a proc - # needs to be stored. The passes manager frees s.sons[codePos] when - # appropriate to free the procedure body's memory. This is important - # to keep memory usage down. - if (s.kind in {skMethod, skProc, skFunc}) and - ({sfCompilerProc, sfCompileTime} * s.flags == {}) and - (s.typ.callConv != ccInline) and - (s.ast.sons[genericParamsPos].kind == nkEmpty): - result = false - # XXX this doesn't really make sense with excessive CTFE - else: - result = true - const maxPasses = 10 @@ -153,7 +139,7 @@ proc closePassesCached(graph: ModuleGraph; a: var TPassContextArray) = m = gPasses[i].close(graph, a[i], m) a[i] = nil # free the memory here -proc resolveMod(module, relativeTo: string): int32 = +proc resolveMod(module, relativeTo: string): FileIndex = let fullPath = findModule(module, relativeTo) if fullPath.len == 0: result = InvalidFileIDX @@ -166,7 +152,7 @@ proc processImplicits(implicits: seq[string], nodeKind: TNodeKind, let relativeTo = m.info.toFullPath for module in items(implicits): # implicit imports should not lead to a module importing itself - if m.position != resolveMod(module, relativeTo): + if m.position != resolveMod(module, relativeTo).int32: var importStmt = newNodeI(nodeKind, gCmdLineInfo) var str = newStrNode(nkStrLit, module) str.info = gCmdLineInfo @@ -180,7 +166,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream, p: TParsers a: TPassContextArray s: PLLStream - fileIdx = module.fileIdx + fileIdx = FileIndex module.fileIdx if module.id < 0: # new module caching mechanism: for i in 0..= gMods.len: setLen(gMods, fileIdx+1) - gMods[fileIdx].hash = result + if fileIdx.int32 >= gMods.len: setLen(gMods, fileIdx.int32+1) + gMods[fileIdx.int32].hash = result template growCache*(cache, pos) = if cache.len <= pos: cache.setLen(pos+1) -proc checkDep(fileIdx: int32; cache: IdentCache): TReasonForRecompile = +proc checkDep(fileIdx: FileIndex; cache: IdentCache): TReasonForRecompile = assert fileIdx != InvalidFileIDX - growCache gMods, fileIdx - if gMods[fileIdx].reason != rrEmpty: + growCache gMods, fileIdx.int32 + if gMods[fileIdx.int32].reason != rrEmpty: # reason has already been computed for this module: - return gMods[fileIdx].reason + return gMods[fileIdx.int32].reason let filename = fileIdx.toFilename var hash = getHash(fileIdx) - gMods[fileIdx].reason = rrNone # we need to set it here to avoid cycles + gMods[fileIdx.int32].reason = rrNone # we need to set it here to avoid cycles result = rrNone var rodfile = toGeneratedFile(filename.withPackageName, RodExt) - var r = newRodReader(rodfile, hash, fileIdx, cache) + var r = newRodReader(rodfile, hash, fileIdx.int32, cache) if r == nil: result = (if existsFile(rodfile): rrRodInvalid else: rrRodDoesNotExist) else: @@ -907,19 +907,18 @@ proc checkDep(fileIdx: int32; cache: IdentCache): TReasonForRecompile = # recompilation is necessary: if r != nil: memfiles.close(r.memfile) r = nil - gMods[fileIdx].rd = r - gMods[fileIdx].reason = result # now we know better + gMods[fileIdx.int32].rd = r + gMods[fileIdx.int32].reason = result # now we know better proc handleSymbolFile*(module: PSym; cache: IdentCache): PRodReader = - let fileIdx = module.fileIdx if gSymbolFiles in {disabledSf, writeOnlySf, v2Sf}: module.id = getID() return nil idgen.loadMaxIds(options.gProjectPath / options.gProjectName) - + let fileIdx = FileIndex module.fileIdx discard checkDep(fileIdx, cache) - if gMods[fileIdx].reason == rrEmpty: internalError("handleSymbolFile") - result = gMods[fileIdx].rd + if gMods[fileIdx.int32].reason == rrEmpty: internalError("handleSymbolFile") + result = gMods[fileIdx.int32].rd if result != nil: module.id = result.moduleID result.syms[module.id] = module @@ -1153,7 +1152,7 @@ proc viewFile(rodfile: string) = if r.s[r.pos] == '\x0A': inc(r.pos) inc(r.line) - outf.write(w, " ", inclHash, "\n") + outf.write(w.int32, " ", inclHash, "\n") if r.s[r.pos] == ')': inc(r.pos) outf.write(")\n") of "DEPS": @@ -1163,7 +1162,7 @@ proc viewFile(rodfile: string) = let v = int32(decodeVInt(r.s, r.pos)) r.modDeps.add(r.files[v]) if r.s[r.pos] == ' ': inc(r.pos) - outf.write(" ", r.files[v]) + outf.write(" ", r.files[v].int32) outf.write("\n") of "INTERF", "COMPILERPROCS": inc r.pos, 2 diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim index 96deb1d5a..0ae687268 100644 --- a/compiler/rodwrite.nim +++ b/compiler/rodwrite.nim @@ -55,7 +55,7 @@ proc fileIdx(w: PRodWriter, filename: string): int = w.files[result] = filename template filename*(w: PRodWriter): string = - w.module.filename + toFilename(FileIndex w.module.position) proc newRodWriter(hash: SecureHash, module: PSym; cache: IdentCache): PRodWriter = new(result) @@ -125,14 +125,14 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode, result.add('?') encodeVInt(n.info.col, result) result.add(',') - encodeVInt(n.info.line, result) + encodeVInt(int n.info.line, result) result.add(',') encodeVInt(fileIdx(w, toFullPath(n.info)), result) elif fInfo.line != n.info.line: result.add('?') encodeVInt(n.info.col, result) result.add(',') - encodeVInt(n.info.line, result) + encodeVInt(int n.info.line, result) elif fInfo.col != n.info.col: result.add('?') encodeVInt(n.info.col, result) @@ -303,7 +303,7 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) = result.add('?') if s.info.col != -1'i16: encodeVInt(s.info.col, result) result.add(',') - if s.info.line != -1'i16: encodeVInt(s.info.line, result) + if s.info.line != 0'u16: encodeVInt(int s.info.line, result) result.add(',') encodeVInt(fileIdx(w, toFullPath(s.info)), result) if s.owner != nil: @@ -642,7 +642,7 @@ proc process(c: PPassContext, n: PNode): PNode = proc myOpen(g: ModuleGraph; module: PSym; cache: IdentCache): PPassContext = if module.id < 0: internalError("rodwrite: module ID not set") - var w = newRodWriter(rodread.getHash module.fileIdx, module, cache) + var w = newRodWriter(rodread.getHash FileIndex module.position, module, cache) rawAddInterfaceSym(w, module) result = w diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 3996188dc..bcc1bba15 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -144,7 +144,7 @@ proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair = proc filename*(c: PContext): string = # the module's filename - return c.module.filename + return toFilename(FileIndex c.module.position) proc scopeDepth*(c: PContext): int {.inline.} = result = if c.currentScope != nil: c.currentScope.depthLevel diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 75d8cc2e0..8d7747fb4 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1095,12 +1095,12 @@ proc semAllTypeSections(c: PContext; n: PNode): PNode = for i in 0.. 0: suggestQuit() proc suggestSentinel*(c: PContext) = - if gIdeCmd != ideSug or c.module.position != gTrackPos.fileIndex: return + if gIdeCmd != ideSug or c.module.position != gTrackPos.fileIndex.int32: return if c.compilesContextId > 0: return inc(c.compilesContextId) var outputs: Suggestions = @[] diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim index 4745b1ac7..4014d4c58 100644 --- a/compiler/syntaxes.nim +++ b/compiler/syntaxes.nim @@ -138,7 +138,7 @@ proc evalPipe(p: var TParsers, n: PNode, filename: string, else: result = applyFilter(p, n, filename, result) -proc openParsers*(p: var TParsers, fileIdx: int32, inputstream: PLLStream; +proc openParsers*(p: var TParsers, fileIdx: FileIndex, inputstream: PLLStream; cache: IdentCache) = var s: PLLStream p.skin = skinStandard @@ -155,7 +155,7 @@ proc openParsers*(p: var TParsers, fileIdx: int32, inputstream: PLLStream; proc closeParsers*(p: var TParsers) = parser.closeParser(p.parser) -proc parseFile*(fileIdx: int32; cache: IdentCache): PNode {.procvar.} = +proc parseFile*(fileIdx: FileIndex; cache: IdentCache): PNode {.procvar.} = var p: TParsers f: File diff --git a/compiler/vm.nim b/compiler/vm.nim index 5b5ccdce4..70f79c433 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1381,7 +1381,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcNGetLine: decodeB(rkNode) let n = regs[rb].node - regs[ra].node = newIntNode(nkIntLit, n.info.line) + regs[ra].node = newIntNode(nkIntLit, n.info.line.int) regs[ra].node.info = n.info regs[ra].node.typ = n.typ of opcNGetColumn: @@ -1521,7 +1521,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let x = newNodeI(TNodeKind(int(k)), if cc.kind != nkNilLit: cc.info - elif c.comesFromHeuristic.line > -1: + elif c.comesFromHeuristic.line != 0'u16: c.comesFromHeuristic elif c.callsite != nil and c.callsite.safeLen > 1: c.callsite[1].info @@ -1748,7 +1748,7 @@ proc evalMacroCall*(module: PSym; cache: IdentCache, n, nOrig: PNode, setupGlobalCtx(module, cache) var c = globalCtx - c.comesFromHeuristic.line = -1 + c.comesFromHeuristic.line = 0'u16 c.callsite = nOrig let start = genProc(c, sym) -- cgit 1.4.1-2-gfad0 From 516ce7306660a183b3e81d6c2622a84b9396f3e1 Mon Sep 17 00:00:00 2001 From: Arne Döring Date: Sat, 21 Apr 2018 08:15:41 +0200 Subject: macro manual improvements (#7666) * macro manual improvements * fixes a typo * Small fixes --- doc/manual.rst | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/doc/manual.rst b/doc/manual.rst index b114f0a8a..9f9206e5c 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -5241,15 +5241,21 @@ chance to convert it into a sequence. Macros ====== -A macro is a special kind of low level template. Macros can be used -to implement `domain specific languages`:idx:. +A macro is a special function that is executed at compile-time. +Normally the input for a macro is an abstract syntax +tree (AST) of the code that is passed to it. The macro can then do +transformations on it and return the transformed AST. The +transformed AST is then passed to the compiler as if the macro +invocation would have been replaced by its result in the source +code. This can be used to implement `domain specific +languages`:idx:. While macros enable advanced compile-time code transformations, they cannot change Nim's syntax. However, this is no real restriction because Nim's syntax is flexible enough anyway. To write macros, one needs to know how the Nim concrete syntax is converted -to an abstract syntax tree. +to an AST. There are two ways to invoke a macro: (1) invoking a macro like a procedure call (`expression macros`) @@ -5269,19 +5275,21 @@ variable number of arguments: # ``macros`` module: import macros - macro debug(n: varargs[untyped]): untyped = - # `n` is a Nim AST that contains the whole macro invocation - # this macro returns a list of statements: - result = newNimNode(nnkStmtList, n) + macro debug(args: varargs[untyped]): untyped = + # `args` is a collection of `NimNode` values that each contain the + # AST for an argument of the macro. A macro always has to + # return a `NimNode`. A node of kind `nnkStmtList` is suitable for + # this use case. + result = nnkStmtList.newTree() # iterate over any argument that is passed to this macro: - for i in 0..n.len-1: + for n in args: # add a call to the statement list that writes the expression; # `toStrLit` converts an AST to its string representation: - add(result, newCall("write", newIdentNode("stdout"), toStrLit(n[i]))) + result.add newCall("write", newIdentNode("stdout"), newLit(n.repr)) # add a call to the statement list that writes ": " - add(result, newCall("write", newIdentNode("stdout"), newStrLitNode(": "))) + result.add newCall("write", newIdentNode("stdout"), newLit(": ")) # add a call to the statement list that writes the expressions value: - add(result, newCall("writeLine", newIdentNode("stdout"), n[i])) + result.add newCall("writeLine", newIdentNode("stdout"), n) var a: array[0..10, int] @@ -8187,5 +8195,3 @@ validation errors: If the taint mode is turned off, ``TaintedString`` is simply an alias for ``string``. - - -- cgit 1.4.1-2-gfad0 From e44c6d833799d42fac0445cfcbf4b2e75e70358f Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 21 Apr 2018 16:32:54 +0200 Subject: refactoring: remove dead code --- compiler/modules.nim | 105 --------------------------------------------------- 1 file changed, 105 deletions(-) diff --git a/compiler/modules.nim b/compiler/modules.nim index 52a6f2fdd..56bfdf662 100644 --- a/compiler/modules.nim +++ b/compiler/modules.nim @@ -13,111 +13,6 @@ import ast, astalgo, magicsys, std / sha1, rodread, msgs, cgendata, sigmatch, options, idents, os, lexer, idgen, passes, syntaxes, llstream, modulegraphs, rod -when false: - type - TNeedRecompile* = enum Maybe, No, Yes, Probing, Recompiled - THashStatus* = enum hashNotTaken, hashCached, hashHasChanged, hashNotChanged - - TModuleInMemory* = object - hash*: SecureHash - deps*: seq[int32] ## XXX: slurped files are currently not tracked - - needsRecompile*: TNeedRecompile - hashStatus*: THashStatus - - var - gCompiledModules: seq[PSym] = @[] - gMemCacheData*: seq[TModuleInMemory] = @[] - ## XXX: we should implement recycling of file IDs - ## if the user keeps renaming modules, the file IDs will keep growing - gFuzzyGraphChecking*: bool # nimsuggest uses this. XXX figure out why. - - proc hashChanged(fileIdx: int32): bool = - internalAssert fileIdx >= 0 and fileIdx < gMemCacheData.len - - template updateStatus = - gMemCacheData[fileIdx].hashStatus = if result: hashHasChanged - else: hashNotChanged - # echo "TESTING Hash: ", fileIdx.toFilename, " ", result - - case gMemCacheData[fileIdx].hashStatus - of hashHasChanged: - result = true - of hashNotChanged: - result = false - of hashCached: - let newHash = secureHashFile(fileIdx.toFullPath) - result = newHash != gMemCacheData[fileIdx].hash - gMemCacheData[fileIdx].hash = newHash - updateStatus() - of hashNotTaken: - gMemCacheData[fileIdx].hash = secureHashFile(fileIdx.toFullPath) - result = true - updateStatus() - - proc doHash(fileIdx: int32) = - if gMemCacheData[fileIdx].hashStatus == hashNotTaken: - # echo "FIRST Hash: ", fileIdx.ToFilename - gMemCacheData[fileIdx].hash = secureHashFile(fileIdx.toFullPath) - - proc resetModule*(fileIdx: int32) = - # echo "HARD RESETTING ", fileIdx.toFilename - if fileIdx <% gMemCacheData.len: - gMemCacheData[fileIdx].needsRecompile = Yes - if fileIdx <% gCompiledModules.len: - gCompiledModules[fileIdx] = nil - if fileIdx <% cgendata.gModules.len: - cgendata.gModules[fileIdx] = nil - - proc resetModule*(module: PSym) = - let conflict = getModule(module.position.int32) - if conflict == nil: return - doAssert conflict == module - resetModule(module.position.int32) - initStrTable(module.tab) - - proc resetAllModules* = - for i in 0..gCompiledModules.high: - if gCompiledModules[i] != nil: - resetModule(i.int32) - resetPackageCache() - # for m in cgenModules(): echo "CGEN MODULE FOUND" - - proc resetAllModulesHard* = - resetPackageCache() - gCompiledModules.setLen 0 - gMemCacheData.setLen 0 - magicsys.resetSysTypes() - # XXX - #gOwners = @[] - - proc checkDepMem(fileIdx: int32): TNeedRecompile = - template markDirty = - resetModule(fileIdx) - return Yes - - if gFuzzyGraphChecking: - if gMemCacheData[fileIdx].needsRecompile != Maybe: - return gMemCacheData[fileIdx].needsRecompile - else: - # cycle detection: We claim that a cycle does no harm. - if gMemCacheData[fileIdx].needsRecompile == Probing: - return No - - if optForceFullMake in gGlobalOptions or hashChanged(fileIdx): - markDirty() - - if gMemCacheData[fileIdx].deps != nil: - gMemCacheData[fileIdx].needsRecompile = Probing - for dep in gMemCacheData[fileIdx].deps: - let d = checkDepMem(dep) - if d in {Yes, Recompiled}: - # echo fileIdx.toFilename, " depends on ", dep.toFilename, " ", d - markDirty() - - gMemCacheData[fileIdx].needsRecompile = No - return No - proc resetSystemArtifacts*() = magicsys.resetSysTypes() -- cgit 1.4.1-2-gfad0 From 4f10b5edb6a6e51da5a3f8b0156a456d6eba8727 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 21 Apr 2018 16:41:35 +0200 Subject: improve documentation for 'var T return values'; refs #7373 --- doc/manual.rst | 24 +++++++++++++++++++++--- doc/manual/var_t_return.rst | 20 ++++++++++++++++++++ web/website.ini | 2 +- 3 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 doc/manual/var_t_return.rst diff --git a/doc/manual.rst b/doc/manual.rst index 9f9206e5c..fbd043020 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -3487,17 +3487,17 @@ returned value is an l-value and can be modified by the caller: .. code-block:: nim var g = 0 - proc WriteAccessToG(): var int = + proc writeAccessToG(): var int = result = g - WriteAccessToG() = 6 + writeAccessToG() = 6 assert g == 6 It is a compile time error if the implicitly introduced pointer could be used to access a location beyond its lifetime: .. code-block:: nim - proc WriteAccessToG(): var int = + proc writeAccessToG(): var int = var g = 0 result = g # Error! @@ -3512,6 +3512,24 @@ In the standard library every name of a routine that returns a ``var`` type starts with the prefix ``m`` per convention. +.. include:: manual/var_t_return.rst + +Future directions +~~~~~~~~~~~~~~~~~ + +Later versions of Nim can be more precise about the borrowing rule with +a syntax like: + +.. code-block:: nim + proc foo(other: Y; container: var X): var T from container + +Here ``var T from container`` explicitly exposes that the +location is deviated from the second parameter (called +'container' in this case). The syntax ``var T from p`` specifies a type +``varTy[T, 2]`` which is incompatible with ``varTy[T, 1]``. + + + Overloading of the subscript operator ------------------------------------- diff --git a/doc/manual/var_t_return.rst b/doc/manual/var_t_return.rst new file mode 100644 index 000000000..b9ff1d892 --- /dev/null +++ b/doc/manual/var_t_return.rst @@ -0,0 +1,20 @@ +Memory safety for returning by ``var T`` is ensured by a simple borrowing +rule: If ``result`` does not refer to a location pointing to the heap +(that is in ``result = X`` the ``X`` involves a ``ptr`` or ``ref`` access) +then it has to be deviated by the routine's first parameter: + +.. code-block:: nim + proc forward[T](x: var T): var T = + result = x # ok, deviated from the first parameter. + + proc p(param: var int): var int = + var x: int + # we know 'forward' provides a view into the location deviated by + # its first argument 'x'. + result = forward(x) # Error: location is derived from ``x`` + # which is not p's first parameter and lives + # on the stack. + +In other words, the lifetime of what ``result`` points to is attached to the +lifetime of the first parameter and that is enough knowledge to verify +memory safety at the callsite. diff --git a/web/website.ini b/web/website.ini index 56b7c436f..18e7bf2cb 100644 --- a/web/website.ini +++ b/web/website.ini @@ -31,7 +31,7 @@ file: ticker.html [Documentation] doc: "endb.rst;intern.txt;apis.txt;lib.rst;manual.rst;tut1.rst;tut2.rst;nimc.rst;overview.rst;filters.rst" doc: "tools.txt;niminst.rst;nimgrep.rst;gc.rst;estp.rst;idetools.rst;docgen.rst;koch.rst;backends.txt" -doc: "nimfix.rst;nimsuggest.rst;nep1.rst;nims.rst;contributing.rst" +doc: "nimfix.rst;nimsuggest.rst;nep1.rst;nims.rst;contributing.rst;manual/*.rst" pdf: "manual.rst;lib.rst;tut1.rst;tut2.rst;nimc.rst;niminst.rst;gc.rst" srcdoc2: "system.nim;system/nimscript;pure/ospaths" srcdoc2: "core/macros;pure/marshal;core/typeinfo" -- cgit 1.4.1-2-gfad0 From 14046d975dd0c5a5195dea7d6bdcb3daa8e69eca Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 21 Apr 2018 17:01:27 +0200 Subject: make tests green again --- compiler/vm.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/vm.nim b/compiler/vm.nim index 70f79c433..32db8f378 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1693,7 +1693,7 @@ proc evalConstExprAux(module: PSym; cache: IdentCache; prc: PSym, n: PNode, newSeq(tos.slots, c.prc.maxSlots) #for i in 0 ..< c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty) result = rawExecute(c, start, tos).regToNode - if result.info.line < 0: result.info = n.info + if result.info.col < 0: result.info = n.info proc evalConstExpr*(module: PSym; cache: IdentCache, e: PNode): PNode = result = evalConstExprAux(module, cache, nil, e, emConst) -- cgit 1.4.1-2-gfad0 From 85ea9593b38351e69fedac61ff0c2b958bac4b7f Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 21 Apr 2018 21:22:36 +0200 Subject: fixes #7637; assignments are not allowed to slice object; minor breaking change --- changelog.md | 4 ++++ lib/system/assign.nim | 10 ++++++++-- tests/objects/tinherentedvalues.nim | 16 +++++++--------- tests/objects/tobj_asgn_dont_slice.nim | 24 ++++++++++++++++++++++++ tests/objects/tobjconstr.nim | 7 +++---- 5 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 tests/objects/tobj_asgn_dont_slice.nim diff --git a/changelog.md b/changelog.md index e6d1f6b47..a3332789a 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,10 @@ to deal with! - Indexing into a ``cstring`` for the JS target is now mapped to ``charCodeAt``. +- Assignments that would "slice" an object into its supertype are not prevented + at runtime. Use ``ref object`` with inheritance rather than ``object`` with + inheritance to prevent this issue. + #### Breaking changes in the standard library diff --git a/lib/system/assign.nim b/lib/system/assign.nim index f061c89cf..ff1ef31d2 100644 --- a/lib/system/assign.nim +++ b/lib/system/assign.nim @@ -79,8 +79,12 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) = GenericSeqSize), mt.base, shallow) of tyObject: - if mt.base != nil: - genericAssignAux(dest, src, mt.base, shallow) + var it = mt.base + # don't use recursion here on the PNimType because the subtype + # check should only be done at the very end: + while it != nil: + genericAssignAux(dest, src, it.node, shallow) + it = it.base genericAssignAux(dest, src, mt.node, shallow) # we need to copy m_type field for tyObject, as it could be empty for # sequence reallocations: @@ -89,6 +93,8 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) = # if p of TB: # var tbObj = TB(p) # tbObj of TC # needs to be false! + #c_fprintf(stdout, "%s %s\n", pint[].name, mt.name) + chckObjAsgn(cast[ptr PNimType](src)[], mt) pint[] = mt # cast[ptr PNimType](src)[] of tyTuple: genericAssignAux(dest, src, mt.node, shallow) diff --git a/tests/objects/tinherentedvalues.nim b/tests/objects/tinherentedvalues.nim index c96a0fd6d..ad7b5f326 100644 --- a/tests/objects/tinherentedvalues.nim +++ b/tests/objects/tinherentedvalues.nim @@ -1,9 +1,7 @@ discard """ - output: '''tbObj of TC false -false + output: '''tbObj of TC true true -5 -false''' +5''' """ # bug #1053 @@ -20,10 +18,10 @@ type proc test(p: TA) = #echo "p of TB ", p of TB if p of TB: - var tbObj = TB(p) + #var tbObj = TB(p) # tbObj is actually no longer compatible with TC: - echo "tbObj of TC ", tbObj of TC + echo "tbObj of TC ", p of TC var v = TC() v.a = 1 @@ -48,8 +46,8 @@ proc isMyObject(obj: TObject) = asd.x = 5 -var asdCopy = TObject(asd) -echo asdCopy of MyObject +#var asdCopy = TObject(asd) +#echo asdCopy of MyObject isMyObject(asd) -isMyObject(asdCopy) +#isMyObject(asdCopy) diff --git a/tests/objects/tobj_asgn_dont_slice.nim b/tests/objects/tobj_asgn_dont_slice.nim new file mode 100644 index 000000000..866b5aecc --- /dev/null +++ b/tests/objects/tobj_asgn_dont_slice.nim @@ -0,0 +1,24 @@ +discard """ + outputsub: '''ObjectAssignmentError''' + exitcode: "1" +""" + +# bug #7637 +type + Fruit = object of RootObj + name*: string + Apple = object of Fruit + Pear = object of Fruit + +method eat(f: Fruit) {.base.} = + raise newException(Exception, "PURE VIRTUAL CALL") + +method eat(f: Apple) = + echo "fruity" + +method eat(f: Pear) = + echo "juicy" + +let basket = [Apple(name:"a"), Pear(name:"b")] + +eat(basket[0]) diff --git a/tests/objects/tobjconstr.nim b/tests/objects/tobjconstr.nim index d1f3c8bdb..7238d10c7 100644 --- a/tests/objects/tobjconstr.nim +++ b/tests/objects/tobjconstr.nim @@ -9,8 +9,8 @@ discard """ (k: kindA, a: (x: "abc", z: [1, 8, 3]), method: ()) (k: kindA, a: (x: "abc", z: [1, 9, 3]), method: ()) (k: kindA, a: (x: "abc", z: [1, 10, 3]), method: ()) -(x: 123) -(x: 123) +(y: 0, x: 123) +(y: 678, x: 123) (z: 89, y: 0, x: 128) (y: 678, x: 123) (y: 678, x: 123) @@ -33,7 +33,6 @@ type `method`: TEmpty # bug #1791 proc `$`[T](s: seq[T]): string = - # XXX why is that not in the stdlib? result = "[" for i, x in s: if i > 0: result.add(", ") @@ -59,7 +58,7 @@ type # inherited fields are ignored, so no fields are set when true: var - o: A + o: B o = B(x: 123) echo o o = B(y: 678, x: 123) -- cgit 1.4.1-2-gfad0 From 14e496fab0d42eb54be38ccfb40b65f6c1d2cdf4 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 21 Apr 2018 22:49:15 +0200 Subject: fixes #6393 --- compiler/procfind.nim | 7 +------ compiler/types.nim | 4 ++-- tests/errmsgs/tcant_overload_by_return_type.nim | 9 +++++++++ 3 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 tests/errmsgs/tcant_overload_by_return_type.nim diff --git a/compiler/procfind.nim b/compiler/procfind.nim index 137765ddb..f7d86aaef 100644 --- a/compiler/procfind.nim +++ b/compiler/procfind.nim @@ -66,12 +66,10 @@ proc searchForProcOld*(c: PContext, scope: PScope, fn: PSym): PSym = proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym = const flags = {ExactGenericParams, ExactTypeDescValues, ExactConstraints, IgnoreCC} - var it: TIdentIter - result = initIdentIter(it, scope.symbols, fn.name) while result != nil: - if result.kind == fn.kind and sameType(result.typ, fn.typ, flags): + if result.kind == fn.kind: #and sameType(result.typ, fn.typ, flags): case equalParams(result.typ.n, fn.typ.n) of paramsEqual: if (sfExported notin result.flags) and (sfExported in fn.flags): @@ -85,11 +83,8 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym = return of paramsNotEqual: discard - result = nextIdentIter(it, scope.symbols) - return nil - proc searchForProc*(c: PContext, scope: PScope, fn: PSym): PSym = result = searchForProcNew(c, scope, fn) when false: diff --git a/compiler/types.nim b/compiler/types.nim index a930779bf..4d55ac7a9 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -777,8 +777,8 @@ proc equalParams(a, b: PNode): TParamsEquality = return paramsNotEqual # paramsIncompatible; # continue traversal! If not equal, we can return immediately; else # it stays incompatible - if not sameTypeOrNil(a.sons[0].typ, b.sons[0].typ, {ExactTypeDescValues}): - if (a.sons[0].typ == nil) or (b.sons[0].typ == nil): + if not sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}): + if (a.typ == nil) or (b.typ == nil): result = paramsNotEqual # one proc has a result, the other not is OK else: result = paramsIncompatible # overloading by different diff --git a/tests/errmsgs/tcant_overload_by_return_type.nim b/tests/errmsgs/tcant_overload_by_return_type.nim new file mode 100644 index 000000000..613a896b4 --- /dev/null +++ b/tests/errmsgs/tcant_overload_by_return_type.nim @@ -0,0 +1,9 @@ +discard """ +errormsg: "overloaded 'x' leads to ambiguous calls" +line: 9 +""" + +# bug #6393 + +proc x(): int = 7 +proc x(): string = "strange" -- cgit 1.4.1-2-gfad0 From b43025b754395cc0db632fa759e78ed9098c8add Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 21 Apr 2018 23:58:24 +0200 Subject: fixes #5113 --- compiler/semexprs.nim | 8 ++++++++ tests/varres/tnewseq_on_result_vart.nim | 9 +++++++++ 2 files changed, 17 insertions(+) create mode 100644 tests/varres/tnewseq_on_result_vart.nim diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 4256e0aa6..8e223ed90 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -526,6 +526,14 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) = if isAssignable(c, it) notin {arLValue, arLocalLValue}: if it.kind != nkHiddenAddr: localError(it.info, errVarForOutParamNeededX, $it) + # bug #5113: disallow newSeq(result) where result is a 'var T': + if n[0].sym.magic in {mNew, mNewFinalize, mNewSeq}: + var arg = n[1] #.skipAddr + if arg.kind == nkHiddenDeref: arg = arg[0] + if arg.kind == nkSym and arg.sym.kind == skResult and + arg.typ.skipTypes(abstractInst).kind in {tyVar, tyLent}: + localError(n.info, errXStackEscape, renderTree(n[1], {renderNoComments})) + return for i in countup(1, sonsLen(n) - 1): if n.sons[i].kind == nkHiddenCallConv: diff --git a/tests/varres/tnewseq_on_result_vart.nim b/tests/varres/tnewseq_on_result_vart.nim new file mode 100644 index 000000000..18935a1d1 --- /dev/null +++ b/tests/varres/tnewseq_on_result_vart.nim @@ -0,0 +1,9 @@ + +discard """ + line: 9 + errormsg: "address of 'result' may not escape its stack frame" +""" +# bug #5113 + +proc makeSeqVar(size: Natural): var seq[int] = + newSeq(result, size) -- cgit 1.4.1-2-gfad0 From 07f4e8a4ed2624b92a6cb5fc578e80619b947919 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 22 Apr 2018 00:12:43 +0200 Subject: new 'var T' error messages with hyperlinks; closes #7373 --- compiler/msgs.nim | 3 +++ compiler/semexprs.nim | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 06f333cef..f08d2d2af 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -10,6 +10,9 @@ import options, strutils, os, tables, ropes, platform, terminal, macros +const + explanationsBaseUrl* = "https://nim-lang.org/docs/manual" + type TMsgKind* = enum errUnknown, errInternal, errIllFormedAstX, errCannotOpenFile, errGenerated, diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 8e223ed90..279b6cc57 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1342,11 +1342,11 @@ proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode = let root = exprRoot(n) if root != nil and root.owner == c.p.owner: if root.kind in {skLet, skVar, skTemp} and sfGlobal notin root.flags: - localError(n.info, "'$1' escapes its stack frame; context: '$2'" % [ - root.name.s, renderTree(n, {renderNoComments})]) + localError(n.info, "'$1' escapes its stack frame; context: '$2'; see $3/var_t_return.html" % [ + root.name.s, renderTree(n, {renderNoComments}), explanationsBaseUrl]) elif root.kind == skParam and root.position != 0: - localError(n.info, "'$1' is not the first parameter; context: '$2'" % [ - root.name.s, renderTree(n, {renderNoComments})]) + localError(n.info, "'$1' is not the first parameter; context: '$2'; see $3/var_t_return.html" % [ + root.name.s, renderTree(n, {renderNoComments}), explanationsBaseUrl]) case n.kind of nkHiddenAddr, nkAddr: return n of nkHiddenDeref, nkDerefExpr: return n.sons[0] -- cgit 1.4.1-2-gfad0 From 0ba50f98909b862e813da558e297ec1681fd7e7d Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 22 Apr 2018 00:19:41 +0200 Subject: make tests green again --- tests/cpp/tcovariancerules.nim | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/tests/cpp/tcovariancerules.nim b/tests/cpp/tcovariancerules.nim index f81d67a50..acde1b288 100644 --- a/tests/cpp/tcovariancerules.nim +++ b/tests/cpp/tcovariancerules.nim @@ -13,14 +13,8 @@ cat cat dog dog -dog value -cat value -dog value -cat value dog dog -dog value -cat value dog 1 dog 2 ''' @@ -243,11 +237,12 @@ reject modifiesCovariantArray(dogRefsArray.addr) var dogValues = @[vdog, vdog] var dogValuesArray = [vdog, vdog] -var animalValues = @[Animal(vdog), Animal(vcat)] -var animalValuesArray = [Animal(vdog), Animal(vcat)] +when false: + var animalValues = @[Animal(vdog), Animal(vcat)] + var animalValuesArray = [Animal(vdog), Animal(vcat)] -wantsNonCovariantSeq animalValues -wantsNonCovariantArray animalValuesArray + wantsNonCovariantSeq animalValues + wantsNonCovariantArray animalValuesArray reject wantsNonCovariantSeq(dogRefs) reject modifiesCovariantOperArray(dogRefs) @@ -260,7 +255,6 @@ modifiesDerivedOperArray dogRefs reject modifiesDerivedOperArray(dogValues) reject modifiesDerivedOperArray(animalRefs) -wantsNonCovariantOperArray animalValues reject wantsNonCovariantOperArray(animalRefs) reject wantsNonCovariantOperArray(dogRefs) reject wantsNonCovariantOperArray(dogValues) -- cgit 1.4.1-2-gfad0 From 34b333b1403128b84b93b6ede6f0b1378d7e67df Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 22 Apr 2018 07:10:55 +0200 Subject: make tests green again --- compiler/types.nim | 2 +- tests/overload/toverprc.nim | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/types.nim b/compiler/types.nim index 4d55ac7a9..5d60fa9b4 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -970,7 +970,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool = result = sameFlags(a, b) of tyGenericParam: result = sameChildrenAux(a, b, c) and sameFlags(a, b) - if result and ExactGenericParams in c.flags: + if result and {ExactGenericParams, ExactTypeDescValues} * c.flags != {}: result = a.sym.position == b.sym.position of tyGenericInvocation, tyGenericBody, tySequence, tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyLent, tySink, diff --git a/tests/overload/toverprc.nim b/tests/overload/toverprc.nim index 112eae096..9be2203f6 100644 --- a/tests/overload/toverprc.nim +++ b/tests/overload/toverprc.nim @@ -11,7 +11,7 @@ proc parseInt(x: float): int {.noSideEffect.} = discard proc parseInt(x: bool): int {.noSideEffect.} = discard proc parseInt(x: float32): int {.noSideEffect.} = discard proc parseInt(x: int8): int {.noSideEffect.} = discard -proc parseInt(x: TFile): int {.noSideEffect.} = discard +proc parseInt(x: File): int {.noSideEffect.} = discard proc parseInt(x: char): int {.noSideEffect.} = discard proc parseInt(x: int16): int {.noSideEffect.} = discard -- cgit 1.4.1-2-gfad0 From a8b70c550083e432f0028e6582c97d8310a48c8a Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 22 Apr 2018 23:16:14 +0200 Subject: remove unused error messages --- compiler/msgs.nim | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/compiler/msgs.nim b/compiler/msgs.nim index f08d2d2af..5ae2c4970 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -16,18 +16,18 @@ const type TMsgKind* = enum errUnknown, errInternal, errIllFormedAstX, errCannotOpenFile, errGenerated, - errXCompilerDoesNotSupportCpp, errStringLiteralExpected, + errStringLiteralExpected, errIntLiteralExpected, errInvalidCharacterConstant, errClosingTripleQuoteExpected, errClosingQuoteExpected, - errTabulatorsAreNotAllowed, errInvalidToken, errLineTooLong, + errTabulatorsAreNotAllowed, errInvalidToken, errInvalidNumber, errInvalidNumberOctalCode, errNumberOutOfRange, errNnotAllowedInCharacter, errClosingBracketExpected, errMissingFinalQuote, errIdentifierExpected, errNewlineExpected, errInvalidModuleName, - errOperatorExpected, errTokenExpected, errStringAfterIncludeExpected, + errOperatorExpected, errTokenExpected, errRecursiveDependencyX, errOnOrOffExpected, errNoneSpeedOrSizeExpected, errInvalidPragma, errUnknownPragma, errInvalidDirectiveX, errAtPopWithoutPush, errEmptyAsm, errInvalidIndentation, - errExceptionExpected, errExceptionAlreadyHandled, + errExceptionAlreadyHandled, errYieldNotAllowedHere, errYieldNotAllowedInTryStmt, errInvalidNumberOfYieldExpr, errCannotReturnExpr, errNoReturnWithReturnTypeNotAllowed, errAttemptToRedefine, @@ -71,7 +71,7 @@ type errWrongNumberOfArgumentsInCall, errMissingGenericParamsForTemplate, errXCannotBePassedToProcVar, - errXCannotBeInParamDecl, errPragmaOnlyInHeaderOfProcX, errImplOfXNotAllowed, + errPragmaOnlyInHeaderOfProcX, errImplOfXNotAllowed, errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValueX, errInvalidDiscard, errIllegalConvFromXtoY, errCannotBindXTwice, errInvalidOrderInArrayConstructor, @@ -148,7 +148,6 @@ const errIllFormedAstX: "illformed AST: $1", errCannotOpenFile: "cannot open \'$1\'", errGenerated: "$1", - errXCompilerDoesNotSupportCpp: "\'$1\' compiler does not support C++", errStringLiteralExpected: "string literal expected", errIntLiteralExpected: "integer literal expected", errInvalidCharacterConstant: "invalid character constant", @@ -156,7 +155,6 @@ const errClosingQuoteExpected: "closing \" expected", errTabulatorsAreNotAllowed: "tabulators are not allowed", errInvalidToken: "invalid token: $1", - errLineTooLong: "line too long", errInvalidNumber: "$1 is not a valid number", errInvalidNumberOctalCode: "$1 is not a valid number; did you mean octal? Then use one of '0o', '0c' or '0C'.", errNumberOutOfRange: "number $1 out of valid range", @@ -168,7 +166,6 @@ const errInvalidModuleName: "invalid module name: '$1'", errOperatorExpected: "operator expected, but found \'$1\'", errTokenExpected: "\'$1\' expected", - errStringAfterIncludeExpected: "string after \'include\' expected", errRecursiveDependencyX: "recursive dependency: \'$1\'", errOnOrOffExpected: "\'on\' or \'off\' expected", errNoneSpeedOrSizeExpected: "\'none\', \'speed\' or \'size\' expected", @@ -178,7 +175,6 @@ const errAtPopWithoutPush: "\'pop\' without a \'push\' pragma", errEmptyAsm: "empty asm statement", errInvalidIndentation: "invalid indentation", - errExceptionExpected: "exception expected", errExceptionAlreadyHandled: "exception already handled", errYieldNotAllowedHere: "'yield' only allowed in an iterator", errYieldNotAllowedInTryStmt: "'yield' cannot be used within 'try' in a non-inlined iterator", @@ -284,7 +280,6 @@ const errWrongNumberOfArgumentsInCall: "wrong number of arguments in call to '$1'", errMissingGenericParamsForTemplate: "'$1' has unspecified generic parameters", errXCannotBePassedToProcVar: "\'$1\' cannot be passed to a procvar", - errXCannotBeInParamDecl: "$1 cannot be declared in parameter declaration", errPragmaOnlyInHeaderOfProcX: "pragmas are only allowed in the header of a proc; redefinition of $1", errImplOfXNotAllowed: "implementation of \'$1\' is not allowed", errImplOfXexpected: "implementation of \'$1\' expected", -- cgit 1.4.1-2-gfad0