From 36accda8aaef4bd8daaf23e3eb369c2ca540f224 Mon Sep 17 00:00:00 2001 From: Araq Date: Sat, 29 Jan 2011 14:18:43 +0100 Subject: [PATCH] unary <; countup two type parameters; --recursivePath should work now --- config/nimrod.cfg | 2 +- lib/pure/os.nim | 3 ++- lib/system.nim | 18 ++++++++++--- lib/system/sysio.nim | 10 +++++++- rod/ast.nim | 3 ++- rod/ccgexprs.nim | 3 +++ rod/commands.nim | 17 +++++++++---- rod/ecmasgen.nim | 4 +++ rod/msgs.nim | 48 +++++++---------------------------- rod/semfold.nim | 1 + tests/accept/run/spec.csv | 1 + tests/accept/run/tcountup.nim | 8 ++++++ web/news.txt | 5 ++-- 13 files changed, 69 insertions(+), 54 deletions(-) create mode 100644 tests/accept/run/tcountup.nim diff --git a/config/nimrod.cfg b/config/nimrod.cfg index 96504b483f..03963b330d 100755 --- a/config/nimrod.cfg +++ b/config/nimrod.cfg @@ -30,7 +30,7 @@ path="$lib/windows" path="$lib/posix" path="$lib/ecmas" path="$lib/pure/unidecode" -#recursivePath:"$user/.babel/lib" +#recursivePath:"$home/.babel/lib" @if release or quick: obj_checks:off diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 229fad441a..9876629759 100755 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -861,7 +861,7 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] = if y != "." and y != "..": var s: TStat y = dir / y - if stat(y, s) < 0'i32: break + if lstat(y, s) < 0'i32: break var k = pcFile if S_ISDIR(s.st_mode): k = pcDir if S_ISLNK(s.st_mode): k = succ(k) @@ -1245,3 +1245,4 @@ proc findExe*(exe: string): string = result = "" {.pop.} + diff --git a/lib/system.nim b/lib/system.nim index e6ef4fa6f7..d632b73673 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -1,7 +1,7 @@ # # # Nimrod's Runtime Library -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -247,6 +247,14 @@ proc sizeof*[T](x: T): natural {.magic: "SizeOf", noSideEffect.} ## that one never needs to know ``x``'s size. As a special semantic rule, ## ``x`` may also be a type identifier (``sizeof(int)`` is valid). +proc `<`*[T](x: ordinal[T]): T {.magic: "UnaryLt", noSideEffect.} + ## unary ``<`` that can be used for nice looking excluding ranges: + ## + ## .. code-block:: nimrod + ## for i in 0 .. <10: echo i + ## + ## Semantically this is the same as ``pred``. + proc succ*[T](x: ordinal[T], y = 1): T {.magic: "Succ", noSideEffect.} ## returns the ``y``-th successor of the value ``x``. ``T`` has to be ## an ordinal type. If such a value does not exist, ``EOutOfRange`` is raised @@ -1017,11 +1025,11 @@ iterator countdown*[T](a, b: T, step = 1): T {.inline.} = yield res dec(res, step) -iterator countup*[T](a, b: T, step = 1): T {.inline.} = +iterator countup*[S, T](a: S, b: T, step = 1): T {.inline.} = ## Counts from ordinal value `a` up to `b` with the given - ## step count. `T` may be any ordinal type, `step` may only + ## step count. `S`, `T` may be any ordinal type, `step` may only ## be positive. - var res = a + var res: T = a while res <= b: yield res inc(res, step) @@ -1459,6 +1467,8 @@ when not defined(EcmaScript) and not defined(NimrodVM): proc write*(f: TFile, r: float) proc write*(f: TFile, i: int) + proc write*(f: TFile, i: biggestInt) + proc write*(f: TFile, r: biggestFloat) proc write*(f: TFile, s: string) proc write*(f: TFile, b: Bool) proc write*(f: TFile, c: char) diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index e342296c7e..80d9b14955 100755 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -1,7 +1,7 @@ # # # Nimrod's Runtime Library -# (c) Copyright 2009 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -59,11 +59,19 @@ proc write(f: TFile, i: int) = fprintf(f, "%lld", i) else: fprintf(f, "%ld", i) + +proc write(f: TFile, i: biggestInt) = + when sizeof(biggestint) == 8: + fprintf(f, "%lld", i) + else: + fprintf(f, "%ld", i) proc write(f: TFile, b: bool) = if b: write(f, "true") else: write(f, "false") proc write(f: TFile, r: float) = fprintf(f, "%g", r) +proc write(f: TFile, r: biggestFloat) = fprintf(f, "%g", r) + proc write(f: TFile, c: Char) = putc(c, f) proc write(f: TFile, a: openArray[string]) = for x in items(a): write(f, x) diff --git a/rod/ast.nim b/rod/ast.nim index 1d689deb96..50bd00444d 100755 --- a/rod/ast.nim +++ b/rod/ast.nim @@ -300,7 +300,8 @@ type TSymKinds* = set[TSymKind] TMagic* = enum # symbols that require compiler magic: - mNone, mDefined, mDefinedInScope, mLow, mHigh, mSizeOf, mIs, mEcho, mSucc, + mNone, mDefined, mDefinedInScope, mLow, mHigh, mSizeOf, mIs, mEcho, + mUnaryLt, mSucc, mPred, mInc, mDec, mOrd, mNew, mNewFinalize, mNewSeq, mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref, mGCunref, mAddI, mSubI, mMulI, mDivI, mModI, mAddI64, mSubI64, mMulI64, diff --git a/rod/ccgexprs.nim b/rod/ccgexprs.nim index 294b3e5107..634dea8865 100755 --- a/rod/ccgexprs.nim +++ b/rod/ccgexprs.nim @@ -1369,6 +1369,9 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mAddi..mModi64: binaryArithOverflow(p, e, d, op) of mRepr: genRepr(p, e, d) of mSwap: genSwap(p, e, d) + of mUnaryLt: + if not (optOverflowCheck in p.Options): unaryExpr(p, e, d, "$1 - 1") + else: unaryExpr(p, e, d, "#subInt($1, 1)") of mPred: # XXX: range checking? if not (optOverflowCheck in p.Options): binaryExpr(p, e, d, "$1 - $2") diff --git a/rod/commands.nim b/rod/commands.nim index 7a74cac7f9..177b647d9c 100755 --- a/rod/commands.nim +++ b/rod/commands.nim @@ -274,10 +274,18 @@ proc processPath(path: string): string = result = UnixToNativePath(path % ["nimrod", getPrefixDir(), "lib", libpath, "home", removeTrailingDirSep(os.getHomeDir())]) -proc addPath(path: string) = +proc addPath(path: string, info: TLineInfo) = if not contains(options.searchPaths, path): lists.PrependStr(options.searchPaths, path) +proc addPathRec(dir: string, info: TLineInfo) = + for k,p in os.walkDir(dir): + if k == pcDir and '.' notin p: + addPathRec(p, info) + if not contains(options.searchPaths, p): + liMessage(info, hintPath, p) + lists.PrependStr(options.searchPaths, p) + proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = var theOS: TSystemOS @@ -286,13 +294,12 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = case whichKeyword(switch) of wPath, wP: expectArg(switch, arg, pass, info) - addPath(processPath(arg)) - #discard lists.IncludeStr(options.searchPaths, path) + addPath(processPath(arg), info) of wRecursivePath: expectArg(switch, arg, pass, info) var path = processPath(arg) - for p in os.walkDirRec(path, {pcDir}): addPath(p) - addPath(path) + addPathRec(path, info) + addPath(path, info) of wOut, wO: expectArg(switch, arg, pass, info) options.outFile = arg diff --git a/rod/ecmasgen.nim b/rod/ecmasgen.nim index ca3ab8ddb2..b86b5dd597 100755 --- a/rod/ecmasgen.nim +++ b/rod/ecmasgen.nim @@ -1074,6 +1074,10 @@ proc genMagic(p: var TProc, n: PNode, r: var TCompRes) = of mAnd: genAnd(p, n.sons[1], n.sons[2], r) of mAddi..mStrToStr: arith(p, n, r, op) #mRepr: genRepr(p, n, r); of mSwap: genSwap(p, n, r) + of mUnaryLt: + # XXX: range checking? + if not (optOverflowCheck in p.Options): unaryExpr(p, n, r, "", "$1 - 1") + else: unaryExpr(p, n, r, "subInt", "subInt($1, 1)") of mPred: # XXX: range checking? if not (optOverflowCheck in p.Options): binaryExpr(p, n, r, "", "$1 - $2") diff --git a/rod/msgs.nim b/rod/msgs.nim index e34631c90c..9e826e1276 100755 --- a/rod/msgs.nim +++ b/rod/msgs.nim @@ -1,46 +1,13 @@ # # # The Nimrod Compiler -# (c) Copyright 2010 Andreas Rumpf +# (c) Copyright 2011 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # -import #[[[cog - #from string import replace - #enum = "type\n TMsgKind = (\n" - #msgs = "const\n MsgKindToStr: array [TMsgKind] of string = (\n" - #warns = "const\n WarningsToStr: array [0..%d] of string = (\n" - #hints = "const\n HintsToStr: array [0..%d] of string = (\n" - #w = 0 # counts the warnings - #h = 0 # counts the hints - # - #for elem in eval(open('data/messages.yml').read()): - # for key, val in elem.items(): - # enum = enum + ' %s,\n' % key - # v = replace(val, "'", "''") - # if key[0:4] == 'warn': - # msgs = msgs + " '%s [%s]',\n" % (v, key[4:]) - # warns = warns + " '%s',\n" % key[4:] - # w = w + 1 - # elif key[0:4] == 'hint': - # msgs = msgs + " '%s [%s]',\n" % (v, key[4:]) - # hints = hints + " '%s',\n" % key[4:] - # h = h + 1 - # else: - # msgs = msgs + " '%s',\n" % v - # - #enum = enum[:-2] + ');\n\n' - #msgs = msgs[:-2] + '\n );\n' - #warns = (warns[:-2] + '\n );\n') % (w-1) - #hints = (hints[:-2] + '\n );\n') % (h-1) - # - #cog.out(enum) - #cog.out(msgs) - #cog.out(warns) - #cog.out(hints) - #]]] +import options, strutils, os type @@ -126,7 +93,7 @@ type warnXisPassedToProcVar, warnUser, hintSuccess, hintSuccessX, hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled, - hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintUser + hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, hintUser const MsgKindToStr*: array[TMsgKind, string] = ["unknown error", @@ -274,7 +241,9 @@ const "expression evaluates always to \'$1\' [ExprAlwaysX]", "quit() called [QuitCalled]", "$1 [Processing]", "generated code listing: [CodeBegin]", "end of listing [CodeEnd]", - "used config file \'$1\' [Conf]", "$1 [User]"] + "used config file \'$1\' [Conf]", + "added path: '$1' [Path]", + "$1 [User]"] const WarningsToStr*: array[0..14, string] = ["CannotOpenFile", "OctalEscape", @@ -284,10 +253,11 @@ const "CommentXIgnored", "XisPassedToProcVar", "User"] const - HintsToStr*: array[0..12, string] = ["Success", "SuccessX", "LineTooLong", + HintsToStr*: array[0..13, string] = ["Success", "SuccessX", "LineTooLong", "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf", - "User"] #[[[end]]] + "Path", + "User"] const fatalMin* = errUnknown diff --git a/rod/semfold.nim b/rod/semfold.nim index 91d6ea3bc7..a61ad0f8eb 100755 --- a/rod/semfold.nim +++ b/rod/semfold.nim @@ -95,6 +95,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode = of mToU8: result = newIntNodeT(getInt(a) and 0x000000FF, n) of mToU16: result = newIntNodeT(getInt(a) and 0x0000FFFF, n) of mToU32: result = newIntNodeT(getInt(a) and 0x00000000FFFFFFFF'i64, n) + of mUnaryLt: result = newIntNodeT(getOrdValue(a) - 1, n) of mSucc: result = newIntNodeT(getOrdValue(a) + getInt(b), n) of mPred: result = newIntNodeT(getOrdValue(a) - getInt(b), n) of mAddI, mAddI64: result = newIntNodeT(getInt(a) + getInt(b), n) diff --git a/tests/accept/run/spec.csv b/tests/accept/run/spec.csv index 09dbc40b38..e9c49ea74c 100755 --- a/tests/accept/run/spec.csv +++ b/tests/accept/run/spec.csv @@ -19,6 +19,7 @@ tcnstseq.nim;AngelikaAnneAnnaAnkaAnja tconstr2.nim;69 tcontinuexc.nim;ECcaught tcopy.nim;TEMP=C:\Programs\xyz\bin +tcountup.nim;0123456789 tcurrncy.nim;25 temit.nim;509 tenumhole;my value A1my value Bconc2valueCabc4abc diff --git a/tests/accept/run/tcountup.nim b/tests/accept/run/tcountup.nim new file mode 100644 index 0000000000..4d4c9b304d --- /dev/null +++ b/tests/accept/run/tcountup.nim @@ -0,0 +1,8 @@ + +# Test new countup and unary < + +for i in 0 .. < 10'i64: + stdout.write(i) + +#OUT 0123456789 + diff --git a/web/news.txt b/web/news.txt index 181ec706ab..0a8f01cadb 100755 --- a/web/news.txt +++ b/web/news.txt @@ -51,8 +51,9 @@ Additions ``array[TMyEnum, string]`` mapping. - Indices in array literals may be explicitly given, enhancing readability: ``[enumValueA: "a", enumValueB: "b"]``. -- Added basic thread support via the ``threads`` core module. - +- Added basic thread support via the ``threads`` core module and + the ``--threads:on`` command line switch. +- Added unary ``<`` for nice looking excluding upper bounds in ranges. 2010-10-20 Version 0.8.10 released