From 2d20feb8f1c2f44ba492989f1d05cee915c76edd Mon Sep 17 00:00:00 2001 From: def Date: Mon, 29 Dec 2014 22:27:31 +0100 Subject: [PATCH 01/25] Add imports to asynchttpserver example --- lib/pure/asynchttpserver.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index 0b18e6bcc..4c48350aa 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -17,6 +17,8 @@ ## as the response body. ## ## .. code-block::nim +## import asynchttpserver, asyncdispatch +## ## var server = newAsyncHttpServer() ## proc cb(req: Request) {.async.} = ## await req.respond(Http200, "Hello World") From 99a1530c6c4a2501f0f8305f012e616241545d44 Mon Sep 17 00:00:00 2001 From: Adel Qalieh Date: Wed, 31 Dec 2014 21:41:07 -0500 Subject: [PATCH 02/25] Update tutorial to use RootObj TObject has been deprecated --- doc/tut2.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/tut2.txt b/doc/tut2.txt index 6e239d681..9d3409164 100644 --- a/doc/tut2.txt +++ b/doc/tut2.txt @@ -56,7 +56,7 @@ Objects have access to their type at runtime. There is an .. code-block:: nim type - TPerson = object of TObject + TPerson = object of RootObj name*: string # the * means that `name` is accessible from other modules age: int # no * means that the field is hidden from other modules @@ -76,10 +76,10 @@ never *equivalent*. New object types can only be defined within a type section. Inheritance is done with the ``object of`` syntax. Multiple inheritance is -currently not supported. If an object type has no suitable ancestor, ``TObject`` +currently not supported. If an object type has no suitable ancestor, ``RootObj`` can be used as its ancestor, but this is only a convention. Objects that have no ancestor are implicitly ``final``. You can use the ``inheritable`` pragma -to introduce new object roots apart from ``system.TObject``. (This is used +to introduce new object roots apart from ``system.RootObj``. (This is used in the GTK wrapper for instance.) @@ -228,7 +228,7 @@ is needed: .. code-block:: nim type - TSocket* = object of TObject + TSocket* = object of RootObj FHost: int # cannot be accessed from the outside of the module # the `F` prefix is a convention to avoid clashes since # the accessors are named `host` @@ -284,7 +284,7 @@ Procedures always use static dispatch. For dynamic dispatch replace the .. code-block:: nim type - PExpr = ref object of TObject ## abstract base class for an expression + PExpr = ref object of RootObj ## abstract base class for an expression PLiteral = ref object of PExpr x: int PPlusExpr = ref object of PExpr @@ -313,7 +313,7 @@ dispatching: .. code-block:: nim type - TThing = object of TObject + TThing = object of RootObj TUnit = object of TThing x: int From e2d2203779ed17174542e2ae4b64132cc8a5c7f0 Mon Sep 17 00:00:00 2001 From: Konstantin Molchanov Date: Thu, 1 Jan 2015 21:43:14 +0300 Subject: [PATCH 03/25] Docs: Tutorial 1: Typo fixed. --- doc/tut1.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tut1.txt b/doc/tut1.txt index 46eda7ae3..472017563 100644 --- a/doc/tut1.txt +++ b/doc/tut1.txt @@ -169,7 +169,7 @@ Numbers Numerical literals are written as in most other languages. As a special twist, underscores are allowed for better readability: ``1_000_000`` (one million). A number that contains a dot (or 'e' or 'E') is a floating point literal: -``1.0e9`` (one million). Hexadecimal literals are prefixed with ``0x``, +``1.0e9`` (one billion). Hexadecimal literals are prefixed with ``0x``, binary literals with ``0b`` and octal literals with ``0o``. A leading zero alone does not produce an octal. From b7187dc4950c244c831711c1cb34593bbc83e869 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 2 Jan 2015 03:21:46 +0100 Subject: [PATCH 04/25] fixed wrong code snippet --- tools/website.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/website.tmpl b/tools/website.tmpl index 6f7a216a5..fed52ac15 100644 --- a/tools/website.tmpl +++ b/tools/website.tmpl @@ -63,7 +63,7 @@ count += 1 echo("Average line length: ", - if count: sum / count else: 0) + if count > 0: sum / count else: 0)
From 194b14a1827e5c812e5a149070ddebc27a2966f2 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 2 Jan 2015 03:32:45 +0100 Subject: [PATCH 05/25] fixes #1816 --- lib/system/channels.nim | 7 ++++--- tests/threads/ttryrecv.nim | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 tests/threads/ttryrecv.nim diff --git a/lib/system/channels.nim b/lib/system/channels.nim index 3e5ca0795..d07d6eae1 100644 --- a/lib/system/channels.nim +++ b/lib/system/channels.nim @@ -232,9 +232,10 @@ proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvailable: bool, ## it returns ``(false, default(msg))``. var q = cast[PRawChannel](addr(c)) if q.mask != ChannelDeadMask: - if tryAcquireSys(q.lock): - llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg))) - result.dataAvailable = true + if tryAcquireSys(q.lock): + if q.count > 0: + llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg))) + result.dataAvailable = true releaseSys(q.lock) proc peek*[TMsg](c: var TChannel[TMsg]): int = diff --git a/tests/threads/ttryrecv.nim b/tests/threads/ttryrecv.nim new file mode 100644 index 000000000..acccf182c --- /dev/null +++ b/tests/threads/ttryrecv.nim @@ -0,0 +1,35 @@ +discard """ + outputsub: "channel is empty" +""" + +# bug #1816 + +from math import random +from os import sleep + +type PComm = ptr TChannel[int] + +proc doAction(outC: PComm) {.thread.} = + for i in 0.. <5: + sleep(random(100)) + send(outC[], i) + +var + thr: TThread[PComm] + chan: TChannel[int] + +open(chan) +createThread[PComm](thr, doAction, addr(chan)) + +while true: + let (flag, x) = tryRecv(chan) + if flag: + echo("received from chan: " & $x) + else: + echo "channel is empty" + break + +echo "Finished listening" + +joinThread(thr) +close(chan) From d15d9f41110a245b2b5a13bd8a882eeb79311acd Mon Sep 17 00:00:00 2001 From: Joseph Poirier Date: Fri, 2 Jan 2015 03:36:40 -0600 Subject: [PATCH 06/25] clarify single letter option requirements --- doc/basicopt.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/basicopt.txt b/doc/basicopt.txt index ffb374f18..e366b2718 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -37,4 +37,4 @@ Options: --advanced show advanced command line switches -h, --help show this help -Note: Even single letter options require the colon: -p:PATH. +Note, single letter options that take an argument require a colon. E.g. -p:PATH. From c9fc300f2df14d2db236689176d11d66b4368242 Mon Sep 17 00:00:00 2001 From: Arthur Liao Date: Fri, 2 Jan 2015 20:20:55 +0800 Subject: [PATCH 07/25] Fix typo --- doc/tut1.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tut1.txt b/doc/tut1.txt index 4c32fa0ae..324a38b0a 100644 --- a/doc/tut1.txt +++ b/doc/tut1.txt @@ -1070,7 +1070,7 @@ Operation Comment ``dec(x, n)`` decrements `x` by `n`; `n` is an integer ``succ(x)`` returns the successor of `x` ``succ(x, n)`` returns the `n`'th successor of `x` -``prec(x)`` returns the predecessor of `x` +``pred(x)`` returns the predecessor of `x` ``pred(x, n)`` returns the `n`'th predecessor of `x` ----------------- -------------------------------------------------------- From 66c05e56d8a7d6dfadd8baa85c6d882bb2d670da Mon Sep 17 00:00:00 2001 From: Jochen Kupperschmidt Date: Fri, 2 Jan 2015 13:47:33 +0100 Subject: [PATCH 08/25] Tutorial: Fixed slices example code. This is likely a remainder of the name change from "Nimrod" to "Nim". --- doc/tut1.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tut1.txt b/doc/tut1.txt index 4c32fa0ae..e961ea11b 100644 --- a/doc/tut1.txt +++ b/doc/tut1.txt @@ -1323,7 +1323,7 @@ define operators which accept TSlice objects to define ranges. a = "Nim is a progamming language" b = "Slices are useless." - echo a[10..15] # --> 'a prog' + echo a[7..12] # --> 'a prog' b[11.. -2] = "useful" echo b # --> 'Slices are useful.' From ad65a2039177b706d6dc5d3c0c7657da9e202a23 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Wed, 31 Dec 2014 12:31:02 +0200 Subject: [PATCH 09/25] fix #419 --- compiler/sigmatch.nim | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index b58818a29..6d6e26b2d 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -109,9 +109,12 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym, for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1): var formalTypeParam = typeParams.sons[i-1].typ var bound = binding[i].typ - if bound != nil and formalTypeParam.kind != tyTypeDesc: + internalAssert bound != nil + if formalTypeParam.kind == tyTypeDesc: + if bound.kind != tyTypeDesc: + bound = makeTypeDesc(ctx, bound) + else: bound = bound.skipTypes({tyTypeDesc}) - assert bound != nil put(c.bindings, formalTypeParam, bound) proc newCandidate*(ctx: PContext, callee: PSym, From 1d55fd8d1249acacb07ffcf85e307cb80d5d4e5d Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Wed, 31 Dec 2014 12:56:55 +0200 Subject: [PATCH 10/25] use unix line endings --- tests/misc/tvarious.nim | 86 ++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/tests/misc/tvarious.nim b/tests/misc/tvarious.nim index 434d25e48..0daa019a9 100644 --- a/tests/misc/tvarious.nim +++ b/tests/misc/tvarious.nim @@ -1,54 +1,54 @@ -# Test various aspects +# Test various aspects # bug #572 var a=12345678901'u64 - + var x = (x: 42, y: (a: 8, z: 10)) echo x.y - -import - mvarious - -type - PA = ref TA - PB = ref TB - - TB = object - a: PA - - TA = object - b: TB - x: int - -proc getPA(): PA = - var - b: bool - b = not false - return nil + +import + mvarious + +type + PA = ref TA + PB = ref TB + + TB = object + a: PA + + TA = object + b: TB + x: int + +proc getPA(): PA = + var + b: bool + b = not false + return nil # bug #501 proc f(): int = 54 - -var - global: int - -var - s: string - i: int - r: TA - -r.b.a.x = 0 -global = global + 1 -exportme() -write(stdout, "Hallo wie heißt du? ") -write(stdout, getPA().x) -s = readLine(stdin) -i = 0 -while i < s.len: - if s[i] == 'c': write(stdout, "'c' in deinem Namen gefunden\n") - i = i + 1 - -write(stdout, "Du heißt " & s) + +var + global: int + +var + s: string + i: int + r: TA + +r.b.a.x = 0 +global = global + 1 +exportme() +write(stdout, "Hallo wie heißt du? ") +write(stdout, getPA().x) +s = readLine(stdin) +i = 0 +while i < s.len: + if s[i] == 'c': write(stdout, "'c' in deinem Namen gefunden\n") + i = i + 1 + +write(stdout, "Du heißt " & s) # bug #544 when false: From 70b5efa98de87bd7684b7258cb95fb2b9892b6df Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Wed, 31 Dec 2014 12:58:22 +0200 Subject: [PATCH 11/25] fix #544 --- compiler/sigmatch.nim | 3 ++- tests/misc/tvarious.nim | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 6d6e26b2d..8fea81bee 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -629,6 +629,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = elif skipTypes(a, {tyRange}).kind == f.kind: result = isSubtype of tyRange: if a.kind == f.kind: + if f.base.kind == tyNone: return isGeneric result = typeRel(c, base(f), base(a)) # bugfix: accept integer conversions here #if result < isGeneric: result = isNone @@ -948,7 +949,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = else: internalAssert a.sons != nil and a.sons.len > 0 c.typedescMatched = true - result = typeRel(c, f.base, a.base) + result = typeRel(c, f.base, a.skipTypes({tyGenericParam, tyTypeDesc})) else: result = isNone else: diff --git a/tests/misc/tvarious.nim b/tests/misc/tvarious.nim index 0daa019a9..8124b3fc7 100644 --- a/tests/misc/tvarious.nim +++ b/tests/misc/tvarious.nim @@ -51,17 +51,17 @@ while i < s.len: write(stdout, "Du heißt " & s) # bug #544 -when false: - # yay, fails again - type Bar [T; I:range] = array[I, T] - proc foo*[T; I:range](a, b: Bar[T, I]): Bar[T, I] = - when len(a) != 3: - # Error: constant expression expected - {.fatal:"Dimensions have to be 3".} - #... - block: - var a, b: Bar[int, 0..2] - discard foo(a, b) + +# yay, fails again +type Bar [T; I:range] = array[I, T] +proc foo*[T; I:range](a, b: Bar[T, I]): Bar[T, I] = + when len(a) != 3: + # Error: constant expression expected + {.fatal:"Dimensions have to be 3".} + #... +block: + var a, b: Bar[int, range[0..2]] + discard foo(a, b) # bug #1788 From b21b72dc14e389cb2d31646dc25a5ae0808a43a1 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Fri, 2 Jan 2015 17:51:08 +0200 Subject: [PATCH 12/25] fix #1049 --- compiler/semdata.nim | 2 +- compiler/sigmatch.nim | 47 ++++++++++++++++++-------------- tests/metatype/tstaticparams.nim | 18 ++++++++++++ 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/compiler/semdata.nim b/compiler/semdata.nim index f876770c0..623f9b633 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -268,7 +268,7 @@ proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType = template rangeHasStaticIf*(t: PType): bool = # this accepts the ranges's node - t.n[1].kind == nkStaticExpr + t.n != nil and t.n.len > 1 and t.n[1].kind == nkStaticExpr template getStaticTypeFromRange*(t: PType): PType = t.n[1][0][1].typ diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 8fea81bee..ff90bde69 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -676,22 +676,27 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = else: fRange = prev result = typeRel(c, f.sons[1], a.sons[1]) - if result < isGeneric: - result = isNone - elif tfUnresolved in fRange.flags and - rangeHasStaticIf(fRange): - # This is a range from an array instantiated with a generic - # static param. We must extract the static param here and bind - # it to the size of the currently supplied array. - var - rangeStaticT = fRange.getStaticTypeFromRange - replacementT = newTypeWithSons(c.c, tyStatic, @[tyInt.getSysType]) - inputUpperBound = a.sons[0].n[1].intVal - # we must correct for the off-by-one discrepancy between - # ranges and static params: - replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1) - put(c.bindings, rangeStaticT, replacementT) - result = isGeneric + if result < isGeneric: return isNone + if rangeHasStaticIf(fRange): + if tfUnresolved in fRange.flags: + # This is a range from an array instantiated with a generic + # static param. We must extract the static param here and bind + # it to the size of the currently supplied array. + var + rangeStaticT = fRange.getStaticTypeFromRange + replacementT = newTypeWithSons(c.c, tyStatic, @[tyInt.getSysType]) + inputUpperBound = a.sons[0].n[1].intVal + # we must correct for the off-by-one discrepancy between + # ranges and static params: + replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1) + put(c.bindings, rangeStaticT, replacementT) + return isGeneric + + let len = tryResolvingStaticExpr(c, fRange.n[1]) + if len.kind == nkIntLit and len.intVal+1 == lengthOrd(a): + return # if we get this far, the result is already good + else: + return isNone elif lengthOrd(fRange) != lengthOrd(a): result = isNone else: discard @@ -1049,10 +1054,10 @@ proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation = initCandidate(c, m, f) result = typeRel(m, f, a) -proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate, - f: PType): PType = +proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate, + f: PType): PType = result = PType(idTableGet(m.bindings, f)) - if result == nil: + if result == nil: result = generateTypeInstance(c, m.bindings, arg, f) if result == nil: internalError(arg.info, "getInstantiatedType") @@ -1134,7 +1139,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType, arg = argSemantized argType = argType c = m.c - + if tfHasStatic in fMaybeStatic.flags: # XXX: When implicit statics are the default # this will be done earlier - we just have to @@ -1148,7 +1153,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType, return argSemantized if argType.kind == tyStatic: - if m.callee.kind == tyGenericBody: + if m.callee.kind == tyGenericBody and tfGenericTypeParam notin argType.flags: result = newNodeI(nkType, argOrig.info) result.typ = makeTypeFromExpr(c, arg) return diff --git a/tests/metatype/tstaticparams.nim b/tests/metatype/tstaticparams.nim index 6d7c569e0..b34eaa211 100644 --- a/tests/metatype/tstaticparams.nim +++ b/tests/metatype/tstaticparams.nim @@ -56,3 +56,21 @@ type TTestSub[N: static[int]] = TTest[1, N] var z: TTestSub[2] echo z.high + +# issue 1049 +proc matrix_1*[M, N, T](mat: Matrix[M,N,T], a: array[N, int]) = discard +proc matrix_2*[M, N, T](mat: Matrix[M,N,T], a: array[N+1, int]) = discard + +proc matrix_3*[M, N: static[int]; T](mat: Matrix[M,N,T], a: array[N, int]) = discard +proc matrix_4*[M, N: static[int]; T](mat: Matrix[M,N,T], a: array[N+1, int]) = discard + +var + tmat: TMatrix[4,4,int] + ar1: array[4, int] + ar2: array[5, int] + +matrix_1(tmat, ar1) +matrix_2(tmat, ar2) +matrix_3(tmat, ar1) +matrix_4(tmat, ar2) + From 5b32fb1791899a86afbb19a0c4e8d0ded0c362eb Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Fri, 2 Jan 2015 17:51:52 +0200 Subject: [PATCH 13/25] re-enable semistatic[T] as a test case --- tests/metatype/tsemistatic.nim | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/metatype/tsemistatic.nim b/tests/metatype/tsemistatic.nim index 0a003be03..a13175ba8 100644 --- a/tests/metatype/tsemistatic.nim +++ b/tests/metatype/tsemistatic.nim @@ -1,9 +1,15 @@ discard """ msg: "static 10\ndynamic\nstatic 20\n" output: "s\nd\nd\ns" - disabled: "true" """ +type + semistatic[T] = + static[T] or T + +template isStatic*(x): expr = + compiles(static(x)) + proc foo(x: semistatic[int]) = when isStatic(x): static: echo "static ", x From aa69a8a09f990f485e4ae7058b15067c70e70e28 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Fri, 2 Jan 2015 19:00:08 +0200 Subject: [PATCH 14/25] expand the test case for bug 1049 --- compiler/semtypes.nim | 3 +-- tests/metatype/tstaticparams.nim | 11 ++++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index eb15c3809..14ab7e6ba 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -225,11 +225,10 @@ proc semArrayIndex(c: PContext, n: PNode): PType = elif e.kind == nkSym and e.typ.kind == tyStatic: if e.sym.ast != nil: return semArrayIndex(c, e.sym.ast) - internalAssert c.inGenericContext > 0 if not isOrdinalType(e.typ.lastSon): localError(n[1].info, errOrdinalTypeExpected) result = makeRangeWithStaticExpr(c, e) - result.flags.incl tfUnresolved + if c.inGenericContext >0: result.flags.incl tfUnresolved elif e.kind in nkCallKinds and hasGenericArguments(e): if not isOrdinalType(e.typ): localError(n[1].info, errOrdinalTypeExpected) diff --git a/tests/metatype/tstaticparams.nim b/tests/metatype/tstaticparams.nim index b34eaa211..e53e478f0 100644 --- a/tests/metatype/tstaticparams.nim +++ b/tests/metatype/tstaticparams.nim @@ -65,7 +65,7 @@ proc matrix_3*[M, N: static[int]; T](mat: Matrix[M,N,T], a: array[N, int]) = dis proc matrix_4*[M, N: static[int]; T](mat: Matrix[M,N,T], a: array[N+1, int]) = discard var - tmat: TMatrix[4,4,int] + tmat: Matrix[4,4,int] ar1: array[4, int] ar2: array[5, int] @@ -74,3 +74,12 @@ matrix_2(tmat, ar2) matrix_3(tmat, ar1) matrix_4(tmat, ar2) +template reject(x): stmt = + static: assert(not compiles(x)) + +# test with arrays of wrong size +reject matrix_1(tmat, ar2) +reject matrix_2(tmat, ar1) +reject matrix_3(tmat, ar2) +reject matrix_4(tmat, ar1) + From 1d5ecc0deac508e7ebb3bf9df01aa34d5025d83d Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Fri, 2 Jan 2015 19:19:18 +0200 Subject: [PATCH 15/25] fix #1050 --- compiler/semexprs.nim | 4 +--- tests/generics/t1050.nim | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 tests/generics/t1050.nim diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 89110a479..68921a15a 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -229,7 +229,7 @@ proc semConv(c: PContext, n: PNode): PNode = return n result = newNodeI(nkConv, n.info) - var targetType = semTypeNode(c, n.sons[0], nil) + var targetType = semTypeNode(c, n.sons[0], nil).skipTypes({tyTypeDesc}) maybeLiftType(targetType, c, n[0].info) result.addSon copyTree(n.sons[0]) var op = semExprWithType(c, n.sons[1]) @@ -780,7 +780,6 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect) elif t != nil and t.kind == tyTypeDesc: if n.len == 1: return semObjConstr(c, n, flags) - let destType = t.skipTypes({tyTypeDesc, tyGenericInst}) return semConv(c, n) else: result = overloadedCallOpr(c, n) @@ -928,7 +927,6 @@ proc readTypeParameter(c: PContext, typ: PType, let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias else: (internalAssert(typ.kind == tyCompositeTypeClass); typ.sons[1].skipGenericAlias) - #debug ty let tbody = ty.sons[0] for s in countup(0, tbody.len-2): let tParam = tbody.sons[s] diff --git a/tests/generics/t1050.nim b/tests/generics/t1050.nim new file mode 100644 index 000000000..a6f9a2482 --- /dev/null +++ b/tests/generics/t1050.nim @@ -0,0 +1,16 @@ +discard """ + msg: "int" + output: "4" +""" + +import typetraits + +type ArrayType[T] = distinct T + +proc arrayItem(a: ArrayType): auto = + static: echo(name(type(a).T)) + result = (type(a).T)(4) + +var arr: ArrayType[int] +echo arrayItem(arr) + From 2f90be13e2be9224c2760b98f6949bdfafc7992a Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Fri, 2 Jan 2015 21:25:16 +0200 Subject: [PATCH 16/25] fix #1820 --- compiler/sigmatch.nim | 2 +- tests/metatype/tstaticparams.nim | 38 +++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index ff90bde69..ce7af1dab 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -989,7 +989,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = if aOrig.kind == tyStatic: result = typeRel(c, f.lastSon, a) if result != isNone and f.n != nil: - if not exprStructuralEquivalent(f.n, a.n): + if not exprStructuralEquivalent(f.n, aOrig.n): result = isNone if result != isNone: put(c.bindings, f, aOrig) else: diff --git a/tests/metatype/tstaticparams.nim b/tests/metatype/tstaticparams.nim index e53e478f0..e98a2871f 100644 --- a/tests/metatype/tstaticparams.nim +++ b/tests/metatype/tstaticparams.nim @@ -1,6 +1,6 @@ discard """ file: "tstaticparams.nim" - output: "abracadabra\ntest\n3\n15\n4\n2" + output: "abracadabra\ntest\n3\n15\n4\n2\nfloat\n3\nfloat\nyin\nyang" """ type @@ -83,3 +83,39 @@ reject matrix_2(tmat, ar1) reject matrix_3(tmat, ar2) reject matrix_4(tmat, ar1) +# bug 1820 + +type + T1820_1[T; Y: static[int]] = object + bar: T + +proc intOrFloat*[Y](f: T1820_1[int, Y]) = echo "int" +proc intOrFloat*[Y](f: T1820_1[float, Y]) = echo "float" +proc threeOrFour*[T](f: T1820_1[T, 3]) = echo "3" +proc threeOrFour*[T](f: T1820_1[T, 4]) = echo "4" + +var foo_1: T1820_1[float, 3] + +foo_1.intOrFloat +foo_1.threeOrFour + +type + YinAndYang = enum + Yin, + Yang + + T1820_2[T; Y: static[YinAndYang]] = object + bar: T + +proc intOrFloat*[Y](f: T1820_2[int, Y]) = echo "int" +proc intOrFloat*[Y](f: T1820_2[float, Y]) = echo "float" +proc yinOrYang*[T](f: T1820_2[T, YinAndYang.Yin]) = echo "yin" +proc yinOrYang*[T](f: T1820_2[T, Yang]) = echo "yang" + +var foo_2: T1820_2[float, Yin] +var foo_3: T1820_2[float, YinAndYang.Yang] + +foo_2.intOrFloat +foo_2.yinOrYang +foo_3.yinOrYang + From 05cbbac4e56b07b902b21f1e9a3f270f450b5d04 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Fri, 2 Jan 2015 23:57:55 +0200 Subject: [PATCH 17/25] support for static params in the user defined type classes --- compiler/ast.nim | 1 + compiler/semcall.nim | 16 ++++++-------- compiler/semstmts.nim | 12 ++++++---- compiler/semtypes.nim | 8 ++++--- compiler/sigmatch.nim | 34 ++++++++++++++++++++++------- tests/metatype/tusertypeclasses.nim | 27 ++++++++++++++++++++++- 6 files changed, 73 insertions(+), 25 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index d85dbf42c..883b68d71 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -399,6 +399,7 @@ const tyPureObject* = tyTuple GcTypeKinds* = {tyRef, tySequence, tyString} tyError* = tyProxy # as an errornous node should match everything + tyUnknown* = tyFromExpr tyUnknownTypes* = {tyError, tyFromExpr} diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 3971b8ff5..a712cc195 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -277,16 +277,14 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode = styleCheckUse(n.sons[0].info, finalCallee) if finalCallee.ast == nil: internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check! + if x.hasFauxMatch: + result = x.call + result.sons[0] = newSymNode(finalCallee, result.sons[0].info) + if containsGenericType(result.typ) or x.fauxMatch == tyUnknown: + result.typ = newTypeS(x.fauxMatch, c) + return if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty: - # a generic proc! - if not x.proxyMatch: - finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info) - else: - result = x.call - result.sons[0] = newSymNode(finalCallee, result.sons[0].info) - result.typ = finalCallee.typ.sons[0] - if containsGenericType(result.typ): result.typ = errorType(c) - return + finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info) result = x.call instGenericConvertersSons(c, result, x) result.sons[0] = newSymNode(finalCallee, result.sons[0].info) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 3b0332939..1396ef374 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1262,10 +1262,14 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode = return else: n.sons[i] = semExpr(c, n.sons[i]) - if c.inTypeClass > 0 and n[i].typ != nil and n[i].typ.kind == tyBool: - let verdict = semConstExpr(c, n[i]) - if verdict.intVal == 0: - localError(result.info, "type class predicate failed") + if c.inTypeClass > 0 and n[i].typ != nil: + case n[i].typ.kind + of tyBool: + let verdict = semConstExpr(c, n[i]) + if verdict.intVal == 0: + localError(result.info, "type class predicate failed") + of tyUnknown: continue + else: discard if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]): voidContext = true n.typ = enforceVoidContext diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 14ab7e6ba..deb4b1288 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -781,10 +781,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, of tyGenericBody: result = newTypeS(tyGenericInvokation, c) result.rawAddSon(paramType) + for i in 0 .. paramType.sonsLen - 2: - result.rawAddSon newTypeS(tyAnything, c) - # result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true)) - + let dummyType = if paramType.sons[i].kind == tyStatic: tyUnknown + else: tyAnything + result.rawAddSon newTypeS(dummyType, c) + if paramType.lastSon.kind == tyUserTypeClass: result.kind = tyUserTypeClassInst result.rawAddSon paramType.lastSon diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index ce7af1dab..0182cb555 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -39,7 +39,9 @@ type bindings*: TIdTable # maps types to types baseTypeMatch: bool # needed for conversions from T to openarray[T] # for example - proxyMatch*: bool # to prevent instantiations + fauxMatch*: TTypeKind # the match was successful only due to the use + # of error or wildcard (unknown) types. + # this is used to prevent instantiations. genericConverter*: bool # true if a generic converter needs to # be instantiated coerceDistincts*: bool # this is an explicit coercion that can strip away @@ -66,6 +68,8 @@ const proc markUsed*(info: TLineInfo, s: PSym) +template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone + proc initCandidateAux(ctx: PContext, c: var TCandidate, callee: PType) {.inline.} = c.c = ctx @@ -465,9 +469,23 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate, var typeParamName = ff.base.sons[i-1].sym.name typ = ff.sons[i] - param = newSym(skType, typeParamName, body.sym, body.sym.info) - - param.typ = makeTypeDesc(c, typ) + param: PSym + + template paramSym(kind): expr = + newSym(kind, typeParamName, body.sym, body.sym.info) + + case typ.kind + of tyStatic: + param = paramSym skConst + param.typ = typ.base + param.ast = typ.n + of tyUnknown: + param = paramSym skVar + param.typ = typ + else: + param = paramSym skType + param.typ = makeTypeDesc(c, typ) + addDecl(c, param) for param in body.n[0]: @@ -1067,7 +1085,7 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate, c: PContext): PNode = result = newNodeI(kind, arg.info) if containsGenericType(f): - if not m.proxyMatch: + if not m.hasFauxMatch: result.typ = getInstantiatedType(c, arg, m, f) else: result.typ = errorType(c) @@ -1139,7 +1157,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType, arg = argSemantized argType = argType c = m.c - + if tfHasStatic in fMaybeStatic.flags: # XXX: When implicit statics are the default # this will be done earlier - we just have to @@ -1246,9 +1264,9 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType, result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) of isNone: # do not do this in ``typeRel`` as it then can't infere T in ``ref T``: - if a.kind == tyProxy: + if a.kind in {tyProxy, tyUnknown}: inc(m.genericMatches) - m.proxyMatch = true + m.fauxMatch = a.kind return copyTree(arg) result = userConvMatch(c, m, f, a, arg) # check for a base type match, which supports varargs[T] without [] diff --git a/tests/metatype/tusertypeclasses.nim b/tests/metatype/tusertypeclasses.nim index 6e9e4934b..4e5e6221c 100644 --- a/tests/metatype/tusertypeclasses.nim +++ b/tests/metatype/tusertypeclasses.nim @@ -1,5 +1,13 @@ discard """ - output: "Sortable\nSortable\nContainer" + output: '''Sortable +Sortable +Container +true +true +false +false +false +''' """ import typetraits @@ -41,3 +49,20 @@ proc y(x: TObj): int = 10 proc testFoo(x: TFoo) = discard testFoo(TObj(x: 10)) +type + Matrix[Rows, Cols: static[int]; T] = generic M + M.M == Rows + M.N == Cols + M.T is T + + MyMatrix[M, N: static[int]; T] = object + data: array[M*N, T] + +var x: MyMatrix[3, 3, int] + +echo x is Matrix +echo x is Matrix[3, 3, int] +echo x is Matrix[3, 3, float] +echo x is Matrix[4, 3, int] +echo x is Matrix[3, 4, int] + From 7343aa0e9dd9aa7602ac504c601affe8d18c5fd1 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 3 Jan 2015 14:21:26 +0100 Subject: [PATCH 18/25] Translate md5 module to unsigned numbers Fixes the bug that files > 256 MB get wrong md5 sum calculated --- lib/pure/md5.nim | 270 +++++++++++++++++++++++------------------------ 1 file changed, 135 insertions(+), 135 deletions(-) diff --git a/lib/pure/md5.nim b/lib/pure/md5.nim index 3b5453957..c6228af50 100644 --- a/lib/pure/md5.nim +++ b/lib/pure/md5.nim @@ -9,18 +9,20 @@ ## Module for computing MD5 checksums. -type - MD5State = array[0..3, int32] - MD5Block = array[0..15, int32] - MD5CBits = array[0..7, int8] - MD5Digest* = array[0..15, int8] - MD5Buffer = array[0..63, int8] - MD5Context* {.final.} = object +import unsigned + +type + MD5State = array[0..3, uint32] + MD5Block = array[0..15, uint32] + MD5CBits = array[0..7, uint8] + MD5Digest* = array[0..15, uint8] + MD5Buffer = array[0..63, uint8] + MD5Context* {.final.} = object state: MD5State - count: array[0..1, int32] + count: array[0..1, uint32] buffer: MD5Buffer -const +const padding: cstring = "\x80\0\0\0" & "\0\0\0\0\0\0\0\0" & "\0\0\0\0\0\0\0\0" & @@ -31,60 +33,60 @@ const "\0\0\0\0\0\0\0\0" & "\0\0\0\0" -proc F(x, y, z: int32): int32 {.inline.} = +proc F(x, y, z: uint32): uint32 {.inline.} = result = (x and y) or ((not x) and z) -proc G(x, y, z: int32): int32 {.inline.} = +proc G(x, y, z: uint32): uint32 {.inline.} = result = (x and z) or (y and (not z)) -proc H(x, y, z: int32): int32 {.inline.} = +proc H(x, y, z: uint32): uint32 {.inline.} = result = x xor y xor z -proc I(x, y, z: int32): int32 {.inline.} = +proc I(x, y, z: uint32): uint32 {.inline.} = result = y xor (x or (not z)) -proc rot(x: var int32, n: int8) {.inline.} = - x = toU32(x shl ze(n)) or (x shr toU32(32 -% ze(n))) +proc rot(x: var uint32, n: uint8) {.inline.} = + x = (x shl n) or (x shr (32'u32 - n)) -proc FF(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = - a = a +% F(b, c, d) +% x +% ac +proc FF(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) = + a = a + F(b, c, d) + x + ac rot(a, s) - a = a +% b + a = a + b -proc GG(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = - a = a +% G(b, c, d) +% x +% ac +proc GG(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) = + a = a + G(b, c, d) + x + ac rot(a, s) - a = a +% b + a = a + b -proc HH(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = - a = a +% H(b, c, d) +% x +% ac +proc HH(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) = + a = a + H(b, c, d) + x + ac rot(a, s) - a = a +% b + a = a + b -proc II(a: var int32, b, c, d, x: int32, s: int8, ac: int32) = - a = a +% I(b, c, d) +% x +% ac +proc II(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) = + a = a + I(b, c, d) + x + ac rot(a, s) - a = a +% b + a = a + b -proc encode(dest: var MD5Block, src: cstring) = +proc encode(dest: var MD5Block, src: cstring) = var j = 0 for i in 0..high(dest): - dest[i] = toU32(ord(src[j]) or - ord(src[j+1]) shl 8 or - ord(src[j+2]) shl 16 or - ord(src[j+3]) shl 24) + dest[i] = uint32(ord(src[j])) or + uint32(ord(src[j+1])) shl 8 or + uint32(ord(src[j+2])) shl 16 or + uint32(ord(src[j+3])) shl 24 inc(j, 4) -proc decode(dest: var openArray[int8], src: openArray[int32]) = +proc decode(dest: var openArray[uint8], src: openArray[uint32]) = var i = 0 for j in 0..high(src): - dest[i] = toU8(src[j] and 0xff'i32) - dest[i+1] = toU8(src[j] shr 8'i32 and 0xff'i32) - dest[i+2] = toU8(src[j] shr 16'i32 and 0xff'i32) - dest[i+3] = toU8(src[j] shr 24'i32 and 0xff'i32) + dest[i] = src[j] and 0xff'u32 + dest[i+1] = src[j] shr 8 and 0xff'u32 + dest[i+2] = src[j] shr 16 and 0xff'u32 + dest[i+3] = src[j] shr 24 and 0xff'u32 inc(i, 4) -proc transform(buffer: pointer, state: var MD5State) = +proc transform(buffer: pointer, state: var MD5State) = var myBlock: MD5Block encode(myBlock, cast[cstring](buffer)) @@ -92,111 +94,111 @@ proc transform(buffer: pointer, state: var MD5State) = var b = state[1] var c = state[2] var d = state[3] - FF(a, b, c, d, myBlock[0], 7'i8, 0xD76AA478'i32) - FF(d, a, b, c, myBlock[1], 12'i8, 0xE8C7B756'i32) - FF(c, d, a, b, myBlock[2], 17'i8, 0x242070DB'i32) - FF(b, c, d, a, myBlock[3], 22'i8, 0xC1BDCEEE'i32) - FF(a, b, c, d, myBlock[4], 7'i8, 0xF57C0FAF'i32) - FF(d, a, b, c, myBlock[5], 12'i8, 0x4787C62A'i32) - FF(c, d, a, b, myBlock[6], 17'i8, 0xA8304613'i32) - FF(b, c, d, a, myBlock[7], 22'i8, 0xFD469501'i32) - FF(a, b, c, d, myBlock[8], 7'i8, 0x698098D8'i32) - FF(d, a, b, c, myBlock[9], 12'i8, 0x8B44F7AF'i32) - FF(c, d, a, b, myBlock[10], 17'i8, 0xFFFF5BB1'i32) - FF(b, c, d, a, myBlock[11], 22'i8, 0x895CD7BE'i32) - FF(a, b, c, d, myBlock[12], 7'i8, 0x6B901122'i32) - FF(d, a, b, c, myBlock[13], 12'i8, 0xFD987193'i32) - FF(c, d, a, b, myBlock[14], 17'i8, 0xA679438E'i32) - FF(b, c, d, a, myBlock[15], 22'i8, 0x49B40821'i32) - GG(a, b, c, d, myBlock[1], 5'i8, 0xF61E2562'i32) - GG(d, a, b, c, myBlock[6], 9'i8, 0xC040B340'i32) - GG(c, d, a, b, myBlock[11], 14'i8, 0x265E5A51'i32) - GG(b, c, d, a, myBlock[0], 20'i8, 0xE9B6C7AA'i32) - GG(a, b, c, d, myBlock[5], 5'i8, 0xD62F105D'i32) - GG(d, a, b, c, myBlock[10], 9'i8, 0x02441453'i32) - GG(c, d, a, b, myBlock[15], 14'i8, 0xD8A1E681'i32) - GG(b, c, d, a, myBlock[4], 20'i8, 0xE7D3FBC8'i32) - GG(a, b, c, d, myBlock[9], 5'i8, 0x21E1CDE6'i32) - GG(d, a, b, c, myBlock[14], 9'i8, 0xC33707D6'i32) - GG(c, d, a, b, myBlock[3], 14'i8, 0xF4D50D87'i32) - GG(b, c, d, a, myBlock[8], 20'i8, 0x455A14ED'i32) - GG(a, b, c, d, myBlock[13], 5'i8, 0xA9E3E905'i32) - GG(d, a, b, c, myBlock[2], 9'i8, 0xFCEFA3F8'i32) - GG(c, d, a, b, myBlock[7], 14'i8, 0x676F02D9'i32) - GG(b, c, d, a, myBlock[12], 20'i8, 0x8D2A4C8A'i32) - HH(a, b, c, d, myBlock[5], 4'i8, 0xFFFA3942'i32) - HH(d, a, b, c, myBlock[8], 11'i8, 0x8771F681'i32) - HH(c, d, a, b, myBlock[11], 16'i8, 0x6D9D6122'i32) - HH(b, c, d, a, myBlock[14], 23'i8, 0xFDE5380C'i32) - HH(a, b, c, d, myBlock[1], 4'i8, 0xA4BEEA44'i32) - HH(d, a, b, c, myBlock[4], 11'i8, 0x4BDECFA9'i32) - HH(c, d, a, b, myBlock[7], 16'i8, 0xF6BB4B60'i32) - HH(b, c, d, a, myBlock[10], 23'i8, 0xBEBFBC70'i32) - HH(a, b, c, d, myBlock[13], 4'i8, 0x289B7EC6'i32) - HH(d, a, b, c, myBlock[0], 11'i8, 0xEAA127FA'i32) - HH(c, d, a, b, myBlock[3], 16'i8, 0xD4EF3085'i32) - HH(b, c, d, a, myBlock[6], 23'i8, 0x04881D05'i32) - HH(a, b, c, d, myBlock[9], 4'i8, 0xD9D4D039'i32) - HH(d, a, b, c, myBlock[12], 11'i8, 0xE6DB99E5'i32) - HH(c, d, a, b, myBlock[15], 16'i8, 0x1FA27CF8'i32) - HH(b, c, d, a, myBlock[2], 23'i8, 0xC4AC5665'i32) - II(a, b, c, d, myBlock[0], 6'i8, 0xF4292244'i32) - II(d, a, b, c, myBlock[7], 10'i8, 0x432AFF97'i32) - II(c, d, a, b, myBlock[14], 15'i8, 0xAB9423A7'i32) - II(b, c, d, a, myBlock[5], 21'i8, 0xFC93A039'i32) - II(a, b, c, d, myBlock[12], 6'i8, 0x655B59C3'i32) - II(d, a, b, c, myBlock[3], 10'i8, 0x8F0CCC92'i32) - II(c, d, a, b, myBlock[10], 15'i8, 0xFFEFF47D'i32) - II(b, c, d, a, myBlock[1], 21'i8, 0x85845DD1'i32) - II(a, b, c, d, myBlock[8], 6'i8, 0x6FA87E4F'i32) - II(d, a, b, c, myBlock[15], 10'i8, 0xFE2CE6E0'i32) - II(c, d, a, b, myBlock[6], 15'i8, 0xA3014314'i32) - II(b, c, d, a, myBlock[13], 21'i8, 0x4E0811A1'i32) - II(a, b, c, d, myBlock[4], 6'i8, 0xF7537E82'i32) - II(d, a, b, c, myBlock[11], 10'i8, 0xBD3AF235'i32) - II(c, d, a, b, myBlock[2], 15'i8, 0x2AD7D2BB'i32) - II(b, c, d, a, myBlock[9], 21'i8, 0xEB86D391'i32) - state[0] = state[0] +% a - state[1] = state[1] +% b - state[2] = state[2] +% c - state[3] = state[3] +% d - -proc md5Init*(c: var MD5Context) = - ## initializes a MD5Context - c.state[0] = 0x67452301'i32 - c.state[1] = 0xEFCDAB89'i32 - c.state[2] = 0x98BADCFE'i32 - c.state[3] = 0x10325476'i32 - c.count[0] = 0'i32 - c.count[1] = 0'i32 + FF(a, b, c, d, myBlock[0], 7'u8, 0xD76AA478'u32) + FF(d, a, b, c, myBlock[1], 12'u8, 0xE8C7B756'u32) + FF(c, d, a, b, myBlock[2], 17'u8, 0x242070DB'u32) + FF(b, c, d, a, myBlock[3], 22'u8, 0xC1BDCEEE'u32) + FF(a, b, c, d, myBlock[4], 7'u8, 0xF57C0FAF'u32) + FF(d, a, b, c, myBlock[5], 12'u8, 0x4787C62A'u32) + FF(c, d, a, b, myBlock[6], 17'u8, 0xA8304613'u32) + FF(b, c, d, a, myBlock[7], 22'u8, 0xFD469501'u32) + FF(a, b, c, d, myBlock[8], 7'u8, 0x698098D8'u32) + FF(d, a, b, c, myBlock[9], 12'u8, 0x8B44F7AF'u32) + FF(c, d, a, b, myBlock[10], 17'u8, 0xFFFF5BB1'u32) + FF(b, c, d, a, myBlock[11], 22'u8, 0x895CD7BE'u32) + FF(a, b, c, d, myBlock[12], 7'u8, 0x6B901122'u32) + FF(d, a, b, c, myBlock[13], 12'u8, 0xFD987193'u32) + FF(c, d, a, b, myBlock[14], 17'u8, 0xA679438E'u32) + FF(b, c, d, a, myBlock[15], 22'u8, 0x49B40821'u32) + GG(a, b, c, d, myBlock[1], 5'u8, 0xF61E2562'u32) + GG(d, a, b, c, myBlock[6], 9'u8, 0xC040B340'u32) + GG(c, d, a, b, myBlock[11], 14'u8, 0x265E5A51'u32) + GG(b, c, d, a, myBlock[0], 20'u8, 0xE9B6C7AA'u32) + GG(a, b, c, d, myBlock[5], 5'u8, 0xD62F105D'u32) + GG(d, a, b, c, myBlock[10], 9'u8, 0x02441453'u32) + GG(c, d, a, b, myBlock[15], 14'u8, 0xD8A1E681'u32) + GG(b, c, d, a, myBlock[4], 20'u8, 0xE7D3FBC8'u32) + GG(a, b, c, d, myBlock[9], 5'u8, 0x21E1CDE6'u32) + GG(d, a, b, c, myBlock[14], 9'u8, 0xC33707D6'u32) + GG(c, d, a, b, myBlock[3], 14'u8, 0xF4D50D87'u32) + GG(b, c, d, a, myBlock[8], 20'u8, 0x455A14ED'u32) + GG(a, b, c, d, myBlock[13], 5'u8, 0xA9E3E905'u32) + GG(d, a, b, c, myBlock[2], 9'u8, 0xFCEFA3F8'u32) + GG(c, d, a, b, myBlock[7], 14'u8, 0x676F02D9'u32) + GG(b, c, d, a, myBlock[12], 20'u8, 0x8D2A4C8A'u32) + HH(a, b, c, d, myBlock[5], 4'u8, 0xFFFA3942'u32) + HH(d, a, b, c, myBlock[8], 11'u8, 0x8771F681'u32) + HH(c, d, a, b, myBlock[11], 16'u8, 0x6D9D6122'u32) + HH(b, c, d, a, myBlock[14], 23'u8, 0xFDE5380C'u32) + HH(a, b, c, d, myBlock[1], 4'u8, 0xA4BEEA44'u32) + HH(d, a, b, c, myBlock[4], 11'u8, 0x4BDECFA9'u32) + HH(c, d, a, b, myBlock[7], 16'u8, 0xF6BB4B60'u32) + HH(b, c, d, a, myBlock[10], 23'u8, 0xBEBFBC70'u32) + HH(a, b, c, d, myBlock[13], 4'u8, 0x289B7EC6'u32) + HH(d, a, b, c, myBlock[0], 11'u8, 0xEAA127FA'u32) + HH(c, d, a, b, myBlock[3], 16'u8, 0xD4EF3085'u32) + HH(b, c, d, a, myBlock[6], 23'u8, 0x04881D05'u32) + HH(a, b, c, d, myBlock[9], 4'u8, 0xD9D4D039'u32) + HH(d, a, b, c, myBlock[12], 11'u8, 0xE6DB99E5'u32) + HH(c, d, a, b, myBlock[15], 16'u8, 0x1FA27CF8'u32) + HH(b, c, d, a, myBlock[2], 23'u8, 0xC4AC5665'u32) + II(a, b, c, d, myBlock[0], 6'u8, 0xF4292244'u32) + II(d, a, b, c, myBlock[7], 10'u8, 0x432AFF97'u32) + II(c, d, a, b, myBlock[14], 15'u8, 0xAB9423A7'u32) + II(b, c, d, a, myBlock[5], 21'u8, 0xFC93A039'u32) + II(a, b, c, d, myBlock[12], 6'u8, 0x655B59C3'u32) + II(d, a, b, c, myBlock[3], 10'u8, 0x8F0CCC92'u32) + II(c, d, a, b, myBlock[10], 15'u8, 0xFFEFF47D'u32) + II(b, c, d, a, myBlock[1], 21'u8, 0x85845DD1'u32) + II(a, b, c, d, myBlock[8], 6'u8, 0x6FA87E4F'u32) + II(d, a, b, c, myBlock[15], 10'u8, 0xFE2CE6E0'u32) + II(c, d, a, b, myBlock[6], 15'u8, 0xA3014314'u32) + II(b, c, d, a, myBlock[13], 21'u8, 0x4E0811A1'u32) + II(a, b, c, d, myBlock[4], 6'u8, 0xF7537E82'u32) + II(d, a, b, c, myBlock[11], 10'u8, 0xBD3AF235'u32) + II(c, d, a, b, myBlock[2], 15'u8, 0x2AD7D2BB'u32) + II(b, c, d, a, myBlock[9], 21'u8, 0xEB86D391'u32) + state[0] = state[0] + a + state[1] = state[1] + b + state[2] = state[2] + c + state[3] = state[3] + d + +proc md5Init*(c: var MD5Context) = + ## initializes a MD5Context + c.state[0] = 0x67452301'u32 + c.state[1] = 0xEFCDAB89'u32 + c.state[2] = 0x98BADCFE'u32 + c.state[3] = 0x10325476'u32 + c.count[0] = 0'u32 + c.count[1] = 0'u32 zeroMem(addr(c.buffer), sizeof(MD5buffer)) -proc md5Update*(c: var MD5Context, input: cstring, len: int) = +proc md5Update*(c: var MD5Context, input: cstring, len: int) = ## updates the MD5Context with the `input` data of length `len` var input = input - var Index = (c.count[0] shr 3) and 0x3F - c.count[0] = c.count[0] +% toU32(len shl 3) - if c.count[0] < (len shl 3): c.count[1] = c.count[1] +% 1'i32 - c.count[1] = c.count[1] +% toU32(len shr 29) + var Index = int((c.count[0] shr 3) and 0x3F) + c.count[0] = c.count[0] + (uint32(len) shl 3) + if c.count[0] < (uint32(len) shl 3): c.count[1] = c.count[1] + 1'u32 + c.count[1] = c.count[1] + (uint32(len) shr 29) var PartLen = 64 - Index - if len >= PartLen: + if len >= PartLen: copyMem(addr(c.buffer[Index]), input, PartLen) transform(addr(c.buffer), c.state) var i = PartLen - while i + 63 < len: + while i + 63 < len: transform(addr(input[i]), c.state) inc(i, 64) copyMem(addr(c.buffer[0]), addr(input[i]), len-i) else: copyMem(addr(c.buffer[Index]), addr(input[0]), len) -proc md5Final*(c: var MD5Context, digest: var MD5Digest) = +proc md5Final*(c: var MD5Context, digest: var MD5Digest) = ## finishes the MD5Context and stores the result in `digest` var Bits: MD5CBits PadLen: int decode(Bits, c.count) - var Index = (c.count[0] shr 3) and 0x3F + var Index = int((c.count[0] shr 3) and 0x3F) if Index < 56: PadLen = 56 - Index else: PadLen = 120 - Index md5Update(c, padding, PadLen) @@ -204,34 +206,34 @@ proc md5Final*(c: var MD5Context, digest: var MD5Digest) = decode(digest, c.state) zeroMem(addr(c), sizeof(MD5Context)) -proc toMD5*(s: string): MD5Digest = +proc toMD5*(s: string): MD5Digest = ## computes the MD5Digest value for a string `s` var c: MD5Context md5Init(c) md5Update(c, cstring(s), len(s)) md5Final(c, result) - -proc `$`*(D: MD5Digest): string = + +proc `$`*(D: MD5Digest): string = ## converts a MD5Digest value into its string representation const digits = "0123456789abcdef" result = "" - for i in 0..15: + for i in 0..15: add(result, digits[(D[i] shr 4) and 0xF]) add(result, digits[D[i] and 0xF]) -proc getMD5*(s: string): string = +proc getMD5*(s: string): string = ## computes an MD5 value of `s` and returns its string representation - var + var c: MD5Context d: MD5Digest md5Init(c) md5Update(c, cstring(s), len(s)) md5Final(c, d) result = $d - -proc `==`*(D1, D2: MD5Digest): bool = + +proc `==`*(D1, D2: MD5Digest): bool = ## checks if two MD5Digest values are identical - for i in 0..15: + for i in 0..15: if D1[i] != D2[i]: return false return true @@ -241,5 +243,3 @@ when isMainModule: assert(getMD5("Frank jagt im komplett verwahrlosten Taxi quer durch Bayern") == "7e716d0e702df0505fc72e2b89467910") assert($toMD5("") == "d41d8cd98f00b204e9800998ecf8427e") - - From dd82f0c8298666e2de779c518e6fab14e4d13ab4 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 3 Jan 2015 17:21:54 +0100 Subject: [PATCH 19/25] Fix httpclient to properly encode queries (path?queries) --- lib/pure/httpclient.nim | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 3afb625ee..479d9a54d 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -294,7 +294,10 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", var r = if proxy == nil: parseUri(url) else: proxy.url var headers = substr($httpMethod, len("http")) if proxy == nil: - headers.add(" /" & r.path & r.query) + var pathQuery = " /" & r.path + if r.query.len > 0: + pathQuery.add("?" & r.query) + headers.add(pathQuery) else: headers.add(" " & url) @@ -442,7 +445,9 @@ proc generateHeaders(r: Uri, httpMethod: HttpMethod, headers: StringTableRef): string = result = substr($httpMethod, len("http")) # TODO: Proxies - result.add(" /" & r.path & r.query) + result.add(" /" & r.path) + if r.query.len > 0: + result.add("?" & r.query) result.add(" HTTP/1.1\c\L") add(result, "Host: " & r.hostname & "\c\L") From 76dbce275a2c009a8a93bff9b7a3e44029f215b8 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 3 Jan 2015 17:23:13 +0100 Subject: [PATCH 20/25] Fix (u: Uri), add test cases and make it work for opaque URIs --- lib/pure/uri.nim | 49 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim index 368802dc2..edc690aec 100644 --- a/lib/pure/uri.nim +++ b/lib/pure/uri.nim @@ -16,6 +16,7 @@ type Uri* = object scheme*, username*, password*: string hostname*, port*, path*, query*, anchor*: string + opaque*: bool {.deprecated: [TUrl: Url, TUri: Uri].} @@ -115,6 +116,8 @@ proc parseUri*(uri: string): Uri = if authority == "": raise newException(ValueError, "Expected authority got nothing.") parseAuthority(authority, result) + else: + result.opaque = true # Path parsePath(uri, i, result) @@ -256,7 +259,10 @@ proc `$`*(u: Uri): string = result = "" if u.scheme.len > 0: result.add(u.scheme) - result.add("://") + if u.opaque: + result.add(":") + else: + result.add("://") if u.username.len > 0: result.add(u.username) if u.password.len > 0: @@ -268,22 +274,28 @@ proc `$`*(u: Uri): string = result.add(":") result.add(u.port) if u.path.len > 0: - if u.path[0] != '/': result.add("/") result.add(u.path) - result.add(u.query) - result.add(u.anchor) + if u.query.len > 0: + result.add("?") + result.add(u.query) + if u.anchor.len > 0: + result.add("#") + result.add(u.anchor) when isMainModule: block: - let test = parseUri("http://localhost:8080/test") + let str = "http://localhost:8080/test" + let test = parseUri(str) doAssert test.scheme == "http" doAssert test.port == "8080" doAssert test.path == "/test" doAssert test.hostname == "localhost" + doAssert($test == str) block: - let test = parseUri("foo://username:password@example.com:8042/over/there" & - "/index.dtb?type=animal&name=narwhal#nose") + let str = "foo://username:password@example.com:8042/over/there" & + "/index.dtb?type=animal&name=narwhal#nose" + let test = parseUri(str) doAssert test.scheme == "foo" doAssert test.username == "username" doAssert test.password == "password" @@ -292,34 +304,45 @@ when isMainModule: doAssert test.path == "/over/there/index.dtb" doAssert test.query == "type=animal&name=narwhal" doAssert test.anchor == "nose" + doAssert($test == str) block: - let test = parseUri("urn:example:animal:ferret:nose") + let str = "urn:example:animal:ferret:nose" + let test = parseUri(str) doAssert test.scheme == "urn" doAssert test.path == "example:animal:ferret:nose" + doAssert($test == str) block: - let test = parseUri("mailto:username@example.com?subject=Topic") + let str = "mailto:username@example.com?subject=Topic" + let test = parseUri(str) doAssert test.scheme == "mailto" doAssert test.username == "username" doAssert test.hostname == "example.com" doAssert test.query == "subject=Topic" + doAssert($test == str) block: - let test = parseUri("magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar") + let str = "magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar" + let test = parseUri(str) doAssert test.scheme == "magnet" doAssert test.query == "xt=urn:sha1:72hsga62ba515sbd62&dn=foobar" + doAssert($test == str) block: - let test = parseUri("/test/foo/bar?q=2#asdf") + let str = "/test/foo/bar?q=2#asdf" + let test = parseUri(str) doAssert test.scheme == "" doAssert test.path == "/test/foo/bar" doAssert test.query == "q=2" doAssert test.anchor == "asdf" + doAssert($test == str) block: - let test = parseUri("test/no/slash") + let str = "test/no/slash" + let test = parseUri(str) doAssert test.path == "test/no/slash" + doAssert($test == str) # Remove dot segments tests block: @@ -371,5 +394,3 @@ when isMainModule: block: let test = parseUri("http://example.com/foo/") / "/bar/asd" doAssert test.path == "/foo/bar/asd" - - From 387d598cfb95aa8c62f2186ed6a25ef142a5c27e Mon Sep 17 00:00:00 2001 From: def Date: Sat, 3 Jan 2015 17:40:33 +0100 Subject: [PATCH 21/25] Minor cleanup --- lib/pure/httpclient.nim | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 479d9a54d..f77be0231 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -294,10 +294,9 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", var r = if proxy == nil: parseUri(url) else: proxy.url var headers = substr($httpMethod, len("http")) if proxy == nil: - var pathQuery = " /" & r.path + headers.add(" /" & r.path) if r.query.len > 0: - pathQuery.add("?" & r.query) - headers.add(pathQuery) + headers.add("?" & r.query) else: headers.add(" " & url) From ee62d56cadb9b05d65b01cd8489de2975604c9c9 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 3 Jan 2015 17:44:30 +0100 Subject: [PATCH 22/25] Apply #1824 to fix #1823 --- lib/pure/httpclient.nim | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index f77be0231..acc80cfdb 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -294,9 +294,11 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", var r = if proxy == nil: parseUri(url) else: proxy.url var headers = substr($httpMethod, len("http")) if proxy == nil: - headers.add(" /" & r.path) + echo url + headers.add(" " & r.path) if r.query.len > 0: headers.add("?" & r.query) + echo headers else: headers.add(" " & url) @@ -444,7 +446,7 @@ proc generateHeaders(r: Uri, httpMethod: HttpMethod, headers: StringTableRef): string = result = substr($httpMethod, len("http")) # TODO: Proxies - result.add(" /" & r.path) + result.add(" " & r.path) if r.query.len > 0: result.add("?" & r.query) result.add(" HTTP/1.1\c\L") From ad1945f102a1f2c7e5213e01911649dab6338346 Mon Sep 17 00:00:00 2001 From: Robert Gieseke Date: Sat, 3 Jan 2015 18:06:57 +0100 Subject: [PATCH 23/25] Fix typo --- doc/idetools.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/idetools.txt b/doc/idetools.txt index 5429d0c07..e04f530f4 100644 --- a/doc/idetools.txt +++ b/doc/idetools.txt @@ -145,7 +145,7 @@ The ``--usages`` idetools switch lists all usages of the symbol at a position. IDEs can use this to find all the places in the file where the symbol is used and offer the user to rename it in all places at the same time. Again, a pure string based search and -replace may catch symbols out of the scope of a funcion/loop. +replace may catch symbols out of the scope of a function/loop. For this kind of query the IDE will most likely ignore all the type/signature info provided by idetools and concentrate on the From cd73b3b12bd4fe05e342fe9c9e1dba2413ca6485 Mon Sep 17 00:00:00 2001 From: Joseph Poirier Date: Sat, 3 Jan 2015 14:24:02 -0600 Subject: [PATCH 24/25] fix a couple of typos, grammar, and removal of whitespace --- doc/manual/types.txt | 130 +++++++++++++++++++++---------------------- doc/tut2.txt | 42 +++++++------- web/index.txt | 34 +++++------ 3 files changed, 103 insertions(+), 103 deletions(-) diff --git a/doc/manual/types.txt b/doc/manual/types.txt index b028752e8..94611bbbb 100644 --- a/doc/manual/types.txt +++ b/doc/manual/types.txt @@ -40,7 +40,7 @@ These integer types are pre-defined: ``int`` the generic signed integer type; its size is platform dependent and has the - same size as a pointer. This type should be used in general. An integer + same size as a pointer. This type should be used in general. An integer literal that has no type suffix is of this type. intXX @@ -51,7 +51,7 @@ intXX ``uint`` the generic `unsigned integer`:idx: type; its size is platform dependent and - has the same size as a pointer. An integer literal with the type + has the same size as a pointer. An integer literal with the type suffix ``'u`` is of this type. uintXX @@ -59,15 +59,15 @@ uintXX (example: uint16 is a 16 bit wide unsigned integer). The current implementation supports ``uint8``, ``uint16``, ``uint32``, ``uint64``. Literals of these types have the suffix 'uXX. - Unsigned operations all wrap around; they cannot lead to over- or + Unsigned operations all wrap around; they cannot lead to over- or underflow errors. In addition to the usual arithmetic operators for signed and unsigned integers -(``+ - *`` etc.) there are also operators that formally work on *signed* -integers but treat their arguments as *unsigned*: They are mostly provided -for backwards compatibility with older versions of the language that lacked -unsigned integer types. These unsigned operations for signed integers use +(``+ - *`` etc.) there are also operators that formally work on *signed* +integers but treat their arguments as *unsigned*: They are mostly provided +for backwards compatibility with older versions of the language that lacked +unsigned integer types. These unsigned operations for signed integers use the ``%`` suffix as convention: @@ -98,7 +98,7 @@ operation meaning kinds of integer types are used: the smaller type is converted to the larger. A `narrowing type conversion`:idx: converts a larger to a smaller type (for -example ``int32 -> int16``. A `widening type conversion`:idx: converts a +example ``int32 -> int16``. A `widening type conversion`:idx: converts a smaller type to a larger type (for example ``int16 -> int32``). In Nim only widening type conversions are *implicit*: @@ -111,7 +111,7 @@ widening type conversions are *implicit*: However, ``int`` literals are implicitly convertible to a smaller integer type if the literal's value fits this smaller type and such a conversion is less -expensive than other implicit conversions, so ``myInt16 + 34`` produces +expensive than other implicit conversions, so ``myInt16 + 34`` produces an ``int16`` result. For further details, see `Convertible relation`_. @@ -137,12 +137,12 @@ determined). Assignments from the base type to one of its subrange types A subrange type has the same size as its base type (``int`` in the example). Nim requires `interval arithmetic`:idx: for subrange types over a set -of built-in operators that involve constants: ``x %% 3`` is of -type ``range[0..2]``. The following built-in operators for integers are +of built-in operators that involve constants: ``x %% 3`` is of +type ``range[0..2]``. The following built-in operators for integers are affected by this rule: ``-``, ``+``, ``*``, ``min``, ``max``, ``succ``, ``pred``, ``mod``, ``div``, ``%%``, ``and`` (bitwise ``and``). -Bitwise ``and`` only produces a ``range`` if one of its operands is a +Bitwise ``and`` only produces a ``range`` if one of its operands is a constant *x* so that (x+1) is a number of two. (Bitwise ``and`` is then a ``%%`` operation.) @@ -155,7 +155,7 @@ This means that the following code is accepted: of 9: echo "C" of 10: echo "D" # note: no ``else`` required as (x and 3) + 7 has the type: range[7..10] - + Pre-defined floating point types -------------------------------- @@ -186,17 +186,17 @@ The IEEE standard defines five types of floating-point exceptions: for example 0.0/0.0, sqrt(-1.0), and log(-37.8). * Division by zero: divisor is zero and dividend is a finite nonzero number, for example 1.0/0.0. -* Overflow: operation produces a result that exceeds the range of the exponent, +* Overflow: operation produces a result that exceeds the range of the exponent, for example MAXDOUBLE+0.0000000000001e308. -* Underflow: operation produces a result that is too small to be represented +* Underflow: operation produces a result that is too small to be represented as a normal number, for example, MINDOUBLE * MINDOUBLE. -* Inexact: operation produces a result that cannot be represented with infinite +* Inexact: operation produces a result that cannot be represented with infinite precision, for example, 2.0 / 3.0, log(1.1) and 0.1 in input. -The IEEE exceptions are either ignored at runtime or mapped to the +The IEEE exceptions are either ignored at runtime or mapped to the Nim exceptions: `FloatInvalidOpError`:idx:, `FloatDivByZeroError`:idx:, `FloatOverflowError`:idx:, `FloatUnderflowError`:idx:, -and `FloatInexactError`:idx:. +and `FloatInexactError`:idx:. These exceptions inherit from the `FloatingPointError`:idx: base class. Nim provides the pragmas `NaNChecks`:idx: and `InfChecks`:idx: to control @@ -212,7 +212,7 @@ whether the IEEE exceptions are ignored or trap a Nim exception: In the current implementation ``FloatDivByZeroError`` and ``FloatInexactError`` are never raised. ``FloatOverflowError`` is raised instead of ``FloatDivByZeroError``. -There is also a `floatChecks`:idx: pragma that is a short-cut for the +There is also a `floatChecks`:idx: pragma that is a short-cut for the combination of ``NaNChecks`` and ``InfChecks`` pragmas. ``floatChecks`` are turned off as default. @@ -303,7 +303,7 @@ and ``pred`` are not available for them either. The compiler supports the built-in stringify operator ``$`` for enumerations. -The stringify's result can be controlled by explicitly giving the string +The stringify's result can be controlled by explicitly giving the string values to use: .. code-block:: nim @@ -315,12 +315,12 @@ values to use: valueC = 2, valueD = (3, "abc") -As can be seen from the example, it is possible to both specify a field's +As can be seen from the example, it is possible to both specify a field's ordinal value and its string value by using a tuple. It is also possible to only specify one of them. An enum can be marked with the ``pure`` pragma so that it's fields are not -added to the current scope, so they always need to be accessed +added to the current scope, so they always need to be accessed via ``MyEnum.value``: .. code-block:: nim @@ -328,7 +328,7 @@ via ``MyEnum.value``: type MyEnum {.pure.} = enum valueA, valueB, valueC, valueD - + echo valueA # error: Unknown identifier echo MyEnum.valueA # works @@ -364,22 +364,22 @@ cstring type ------------ The ``cstring`` type represents a pointer to a zero-terminated char array compatible to the type ``char*`` in Ansi C. Its primary purpose lies in easy -interfacing with C. The index operation ``s[i]`` means the i-th *char* of +interfacing with C. The index operation ``s[i]`` means the i-th *char* of ``s``; however no bounds checking for ``cstring`` is performed making the index operation unsafe. -A Nim ``string`` is implicitly convertible +A Nim ``string`` is implicitly convertible to ``cstring`` for convenience. If a Nim string is passed to a C-style variadic proc, it is implicitly converted to ``cstring`` too: .. code-block:: nim - proc printf(formatstr: cstring) {.importc: "printf", varargs, + proc printf(formatstr: cstring) {.importc: "printf", varargs, header: "".} - + printf("This works %s", "as expected") Even though the conversion is implicit, it is not *safe*: The garbage collector -does not consider a ``cstring`` to be a root and may collect the underlying +does not consider a ``cstring`` to be a root and may collect the underlying memory. However in practice this almost never happens as the GC considers stack roots conservatively. One can use the builtin procs ``GC_ref`` and ``GC_unref`` to keep the string data alive for the rare cases where it does @@ -390,7 +390,7 @@ string from a cstring: .. code-block:: nim var str: string = "Hello!" - var cstr: cstring = s + var cstr: cstring = str var newstr: string = $cstr @@ -410,9 +410,9 @@ integers from 0 to ``len(A)-1``. An array expression may be constructed by the array constructor ``[]``. Sequences are similar to arrays but of dynamic length which may change -during runtime (like strings). Sequences are implemented as growable arrays, +during runtime (like strings). Sequences are implemented as growable arrays, allocating pieces of memory as items are added. A sequence ``S`` is always -indexed by integers from 0 to ``len(S)-1`` and its bounds are checked. +indexed by integers from 0 to ``len(S)-1`` and its bounds are checked. Sequences can be constructed by the array constructor ``[]`` in conjunction with the array to sequence operator ``@``. Another way to allocate space for a sequence is to call the built-in ``newSeq`` procedure. @@ -452,11 +452,11 @@ Open arrays Often fixed size arrays turn out to be too inflexible; procedures should be able to deal with arrays of different sizes. The `openarray`:idx: type -allows this; it can only be used for parameters. Openarrays are always -indexed with an ``int`` starting at position 0. The ``len``, ``low`` -and ``high`` operations are available for open arrays too. Any array with -a compatible base type can be passed to an openarray parameter, the index -type does not matter. In addition to arrays sequences can also be passed +allows this; it can only be used for parameters. Openarrays are always +indexed with an ``int`` starting at position 0. The ``len``, ``low`` +and ``high`` operations are available for open arrays too. Any array with +a compatible base type can be passed to an openarray parameter, the index +type does not matter. In addition to arrays sequences can also be passed to an open array parameter. The openarray type cannot be nested: multidimensional openarrays are not @@ -467,7 +467,7 @@ Varargs ------- A ``varargs`` parameter is an openarray parameter that additionally -allows to pass a variable number of arguments to a procedure. The compiler +allows to pass a variable number of arguments to a procedure. The compiler converts the list of arguments to an array implicitly: .. code-block:: nim @@ -494,7 +494,7 @@ type conversions in this context: # is transformed to: myWriteln(stdout, [$123, $"def", $4.0]) -In this example ``$`` is applied to any argument that is passed to the +In this example ``$`` is applied to any argument that is passed to the parameter ``a``. (Note that ``$`` applied to strings is a nop.) @@ -531,7 +531,7 @@ in future versions of the compiler. person = (creditCard: "Peter", id: 20) The implementation aligns the fields for best access performance. The alignment -is compatible with the way the C compiler does it. +is compatible with the way the C compiler does it. For consistency with ``object`` declarations, tuples in a ``type`` section can also be defined with indentation instead of ``[]``: @@ -571,7 +571,7 @@ Object construction ------------------- Objects can also be created with an `object construction expression`:idx: that -has the syntax ``T(fieldA: valueA, fieldB: valueB, ...)`` where ``T`` is +has the syntax ``T(fieldA: valueA, fieldB: valueB, ...)`` where ``T`` is an ``object`` type or a ``ref object`` type: .. code-block:: nim @@ -617,10 +617,10 @@ An example: # the following statement raises an `EInvalidField` exception, because # n.kind's value does not fit and the ``nkString`` branch is not active: n.strVal = "" - + # invalid: would change the active object branch: n.kind = nkInt - + var x = PNode(kind: nkAdd, leftOp: PNode(kind: nkInt, intVal: 4), rightOp: PNode(kind: nkInt, intVal: 2)) # valid: does not change the active object branch: @@ -660,8 +660,8 @@ untraced references are *unsafe*. However for certain low-level operations Traced references are declared with the **ref** keyword, untraced references are declared with the **ptr** keyword. -An empty subscript ``[]`` notation can be used to derefer a reference, -the ``addr`` procedure returns the address of an item. An address is always +An empty subscript ``[]`` notation can be used to derefer a reference, +the ``addr`` procedure returns the address of an item. An address is always an untraced reference. Thus the usage of ``addr`` is an *unsafe* feature. @@ -680,7 +680,7 @@ dereferencing operations for reference types: var n: PNode new(n) - n.data = 9 + n.data = 9 # no need to write n[].data; in fact n[].data is highly discouraged! In order to simplify structural type checking, recursive tuples are not valid: @@ -751,20 +751,20 @@ details like this when mixing garbage collected data with unmanaged memory. Not nil annotation ------------------ -All types for that ``nil`` is a valid value can be annotated to +All types for that ``nil`` is a valid value can be annotated to exclude ``nil`` as a valid value with the ``not nil`` annotation: .. code-block:: nim type PObject = ref TObj not nil TProc = (proc (x, y: int)) not nil - + proc p(x: PObject) = echo "not nil" - + # compiler catches this: p(nil) - + # and also this: var x: PObject p(x) @@ -851,22 +851,22 @@ Examples: forEach(printItem) # this will NOT compile because calling conventions differ - + .. code-block:: nim type TOnMouseMove = proc (x, y: int) {.closure.} - + proc onMouseMove(mouseX, mouseY: int) = # has default calling convention echo "x: ", mouseX, " y: ", mouseY - + proc setOnMouseMove(mouseMoveEvent: TOnMouseMove) = discard - + # ok, 'onMouseMove' has the default calling convention, which is compatible # to 'closure': setOnMouseMove(onMouseMove) - + A subtle issue with procedural types is that the calling convention of the procedure influences the type compatibility: procedural types are only @@ -932,7 +932,7 @@ of the following conditions hold: 3) The procedure has a calling convention that differs from ``nimcall``. 4) The procedure is anonymous. -The rules' purpose is to prevent the case that extending a non-``procvar`` +The rules' purpose is to prevent the case that extending a non-``procvar`` procedure with default parameters breaks client code. The default calling convention is ``nimcall``, unless it is an inner proc (a @@ -964,7 +964,7 @@ types are a perfect tool to model different currencies: type TDollar = distinct int TEuro = distinct int - + var d: TDollar e: TEuro @@ -989,7 +989,7 @@ number without unit; and the same holds for division: proc `*` (x: int, y: TDollar): TDollar = result = TDollar(x * int(y)) - + proc `div` ... This quickly gets tedious. The implementations are trivial and the compiler @@ -1014,7 +1014,7 @@ currency. This can be solved with templates_. template additive(typ: typedesc): stmt = proc `+` *(x, y: typ): typ {.borrow.} proc `-` *(x, y: typ): typ {.borrow.} - + # unary operators: proc `+` *(x: typ): typ {.borrow.} proc `-` *(x: typ): typ {.borrow.} @@ -1036,7 +1036,7 @@ currency. This can be solved with templates_. additive(typ) multiplicative(typ, base) comparable(typ) - + defineCurrency(TDollar, int) defineCurrency(TEuro, int) @@ -1127,21 +1127,21 @@ modules like `db_sqlite `_. Void type --------- -The ``void`` type denotes the absense of any type. Parameters of +The ``void`` type denotes the absense of any type. Parameters of type ``void`` are treated as non-existent, ``void`` as a return type means that the procedure does not return a value: .. code-block:: nim proc nothing(x, y: void): void = echo "ha" - + nothing() # writes "ha" to stdout The ``void`` type is particularly useful for generic code: .. code-block:: nim proc callProc[T](p: proc (x: T), x: T) = - when T is void: + when T is void: p() else: p(x) @@ -1151,13 +1151,13 @@ The ``void`` type is particularly useful for generic code: callProc[int](intProc, 12) callProc[void](emptyProc) - + However, a ``void`` type cannot be inferred in generic code: .. code-block:: nim - callProc(emptyProc) + callProc(emptyProc) # Error: type mismatch: got (proc ()) - # but expected one of: + # but expected one of: # callProc(p: proc (T), x: T) The ``void`` type is only valid for parameters and return types; other symbols diff --git a/doc/tut2.txt b/doc/tut2.txt index 9d3409164..2ae0f18f6 100644 --- a/doc/tut2.txt +++ b/doc/tut2.txt @@ -35,7 +35,7 @@ Object Oriented Programming =========================== While Nim's support for object oriented programming (OOP) is minimalistic, -powerful OOP technics can be used. OOP is seen as *one* way to design a +powerful OOP techniques can be used. OOP is seen as *one* way to design a program, not *the only* way. Often a procedural approach leads to simpler and more efficient code. In particular, prefering composition over inheritance is often the better design. @@ -77,8 +77,8 @@ section. Inheritance is done with the ``object of`` syntax. Multiple inheritance is currently not supported. If an object type has no suitable ancestor, ``RootObj`` -can be used as its ancestor, but this is only a convention. Objects that have -no ancestor are implicitly ``final``. You can use the ``inheritable`` pragma +can be used as its ancestor, but this is only a convention. Objects that have +no ancestor are implicitly ``final``. You can use the ``inheritable`` pragma to introduce new object roots apart from ``system.RootObj``. (This is used in the GTK wrapper for instance.) @@ -199,7 +199,7 @@ This method call syntax is not restricted to objects, it can be used for any type: .. code-block:: nim - + echo("abc".len) # is the same as echo(len("abc")) echo("abc".toUpper()) echo({'a', 'b', 'c'}.card) @@ -212,7 +212,7 @@ So "pure object oriented" code is easy to write: .. code-block:: nim import strutils - + stdout.writeln("Give a list of numbers (separated by spaces): ") stdout.write(stdin.readLine.split.map(parseInt).max.`$`) stdout.writeln(" is the maximum!") @@ -226,7 +226,7 @@ the same. But setting a value is different; for this a special setter syntax is needed: .. code-block:: nim - + type TSocket* = object of RootObj FHost: int # cannot be accessed from the outside of the module @@ -236,7 +236,7 @@ is needed: proc `host=`*(s: var TSocket, value: int) {.inline.} = ## setter of hostAddr s.FHost = value - + proc host*(s: TSocket): int {.inline.} = ## getter of hostAddr s.FHost @@ -294,15 +294,15 @@ Procedures always use static dispatch. For dynamic dispatch replace the method eval(e: PExpr): int = # override this base method quit "to override!" - + method eval(e: PLiteral): int = e.x method eval(e: PPlusExpr): int = eval(e.a) + eval(e.b) - + proc newLit(x: int): PLiteral = PLiteral(x: x) proc newPlus(a, b: PExpr): PPlusExpr = PPlusExpr(a: a, b: b) - + echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4))) - + Note that in the example the constructors ``newLit`` and ``newPlus`` are procs because they should use static binding, but ``eval`` is a method because it requires dynamic binding. @@ -316,16 +316,16 @@ dispatching: TThing = object of RootObj TUnit = object of TThing x: int - + method collide(a, b: TThing) {.inline.} = quit "to override!" - + method collide(a: TThing, b: TUnit) {.inline.} = echo "1" - + method collide(a: TUnit, b: TThing) {.inline.} = echo "2" - + var a, b: TUnit collide(a, b) # output: 2 @@ -526,7 +526,7 @@ containers: yield n.data add(stack, n.ri) # push right subtree onto the stack n = n.le # and follow the left pointer - + var root: PBinaryTree[string] # instantiate a PBinaryTree with ``string`` add(root, newNode("hello")) # instantiates ``newNode`` and ``add`` @@ -578,7 +578,7 @@ simple proc for logging: proc log(msg: string) {.inline.} = if debug: stdout.writeln(msg) - + var x = 4 log("x has the value: " & $x) @@ -595,7 +595,7 @@ Turning the ``log`` proc into a template solves this problem: template log(msg: string) = if debug: stdout.writeln(msg) - + var x = 4 log("x has the value: " & $x) @@ -622,11 +622,11 @@ via a special ``:`` syntax: close(f) else: quit("cannot open: " & fn) - + withFile(txt, "ttempl3.txt", fmWrite): txt.writeln("line 1") txt.writeln("line 2") - + In the example the two ``writeln`` statements are bound to the ``body`` parameter. The ``withFile`` template contains boilerplate code and helps to avoid a common bug: to forget to close the file. Note how the @@ -739,7 +739,7 @@ Term rewriting macros --------------------- Term rewriting macros can be used to enhance the compilation process -with user defined optimizations; see this `document `_ for +with user defined optimizations; see this `document `_ for further information. diff --git a/web/index.txt b/web/index.txt index b6d4f8e8f..95cac9316 100644 --- a/web/index.txt +++ b/web/index.txt @@ -5,16 +5,16 @@ Home Welcome to Nim -------------- -**Nim** (formerly known as "Nimrod") is a statically typed, imperative -programming language that tries to give the programmer ultimate power without +**Nim** (formerly known as "Nimrod") is a statically typed, imperative +programming language that tries to give the programmer ultimate power without compromises on runtime efficiency. This means it focuses on compile-time mechanisms in all their various forms. -Beneath a nice infix/indentation based syntax with a -powerful (AST based, hygienic) macro system lies a semantic model that supports -a soft realtime GC on thread local heaps. Asynchronous message passing is used -between threads, so no "stop the world" mechanism is necessary. An unsafe -shared memory heap is also provided for the increased efficiency that results +Beneath a nice infix/indentation based syntax with a +powerful (AST based, hygienic) macro system lies a semantic model that supports +a soft realtime GC on thread local heaps. Asynchronous message passing is used +between threads, so no "stop the world" mechanism is necessary. An unsafe +shared memory heap is also provided for the increased efficiency that results from that model. @@ -24,7 +24,7 @@ Nim is efficient * Native code generation (currently via compilation to C), not dependent on a virtual machine: **Nim produces small executables without dependencies for easy redistribution.** -* A fast **non-tracing** garbage collector that supports soft +* A fast **non-tracing** garbage collector that supports soft real-time systems (like games). * System programming features: Ability to manage your own memory and access the hardware directly. Pointers to garbage collected memory are distinguished @@ -33,22 +33,22 @@ Nim is efficient * Cross-module inlining. * Dynamic method binding with inlining and without virtual method table. * Compile time evaluation of user-defined functions. -* Whole program dead code elimination: Only *used functions* are included in +* Whole program dead code elimination: Only *used functions* are included in the executable. -* Value-based datatypes: For instance, objects and arrays can be allocated on +* Value-based datatypes: For instance, objects and arrays can be allocated on the stack. Nim is expressive ================= -* **The Nim compiler and all of the standard library are implemented in +* **The Nim compiler and all of the standard libraries are implemented in Nim.** * Built-in high level datatypes: strings, sets, sequences, etc. -* Modern type system with local type inference, tuples, variants, +* Modern type system with local type inference, tuples, variants, generics, etc. * User-defineable operators; code with new operators is often easier to read - than code which overloads built-in operators. For example, a + than code which overloads built-in operators. For example, a ``=~`` operator is defined in the ``re`` module. * Macros can modify the abstract syntax tree at compile time. @@ -58,7 +58,7 @@ Nim is elegant * Macros can use the imperative paradigm to construct parse trees. Nim does not require a different coding style for meta programming. -* Macros cannot change Nim's syntax because there is no need for it. +* Macros cannot change Nim's syntax because there is no need for it. Nim's syntax is flexible enough. * Statements are grouped by indentation but can span multiple lines. Indentation must not contain tabulators so the compiler always sees @@ -72,12 +72,12 @@ Nim plays nice with others Porting to other platforms is easy. * **The Nim Compiler can also generate C++ or Objective C for easier interfacing.** -* There are lots of bindings: for example, bindings to GTK2, the Windows API, - the POSIX API, OpenGL, SDL, Cairo, Python, Lua, TCL, X11, libzip, PCRE, +* There are lots of bindings: for example, bindings to GTK2, the Windows API, + the POSIX API, OpenGL, SDL, Cairo, Python, Lua, TCL, X11, libzip, PCRE, libcurl, mySQL and SQLite are included in the standard distribution or can easily be obtained via the `Nimble package manager `_. -* A C to Nim conversion utility: New bindings to C libraries are easily +* A C to Nim conversion utility: New bindings to C libraries are easily generated by ``c2nim``. From c7fac03abed7c4bf6c438635c4b353fff0af051d Mon Sep 17 00:00:00 2001 From: def Date: Sat, 3 Jan 2015 21:53:40 +0100 Subject: [PATCH 25/25] Remove debug messages --- lib/pure/httpclient.nim | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index acc80cfdb..a4b8bbedb 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -294,11 +294,9 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", var r = if proxy == nil: parseUri(url) else: proxy.url var headers = substr($httpMethod, len("http")) if proxy == nil: - echo url headers.add(" " & r.path) if r.query.len > 0: headers.add("?" & r.query) - echo headers else: headers.add(" " & url)