summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure')
-rw-r--r--lib/pure/htmlparser.nim3
-rw-r--r--lib/pure/ioselects/ioselectors_epoll.nim8
-rw-r--r--lib/pure/logging.nim11
-rw-r--r--lib/pure/math.nim54
-rw-r--r--lib/pure/parsesql.nim25
-rw-r--r--lib/pure/parsexml.nim28
-rw-r--r--lib/pure/strscans.nim7
-rw-r--r--lib/pure/strutils.nim2
-rw-r--r--lib/pure/sugar.nim5
9 files changed, 116 insertions, 27 deletions
diff --git a/lib/pure/htmlparser.nim b/lib/pure/htmlparser.nim
index fbf2b8e73..2d24050f2 100644
--- a/lib/pure/htmlparser.nim
+++ b/lib/pure/htmlparser.nim
@@ -2014,7 +2014,8 @@ proc parseHtml*(s: Stream, filename: string,
   ## Parses the XML from stream `s` and returns a ``XmlNode``. Every
   ## occurred parsing error is added to the `errors` sequence.
   var x: XmlParser
-  open(x, s, filename, {reportComments, reportWhitespace})
+  open(x, s, filename, {reportComments, reportWhitespace, allowUnquotedAttribs,
+    allowEmptyAttribs})
   next(x)
   # skip the DOCTYPE:
   if x.kind == xmlSpecial: next(x)
diff --git a/lib/pure/ioselects/ioselectors_epoll.nim b/lib/pure/ioselects/ioselectors_epoll.nim
index 8b3f14f34..16d901ff0 100644
--- a/lib/pure/ioselects/ioselectors_epoll.nim
+++ b/lib/pure/ioselects/ioselectors_epoll.nim
@@ -383,14 +383,14 @@ proc selectInto*[T](s: Selector[T], timeout: int,
 
       if (pevents and EPOLLERR) != 0 or (pevents and EPOLLHUP) != 0:
         if (pevents and EPOLLHUP) != 0:
-          rkey.errorCode = ECONNRESET.OSErrorCode
+          rkey.errorCode = OSErrorCode ECONNRESET
         else:
           # Try reading SO_ERROR from fd.
           var error: cint
-          var size = sizeof(error).SockLen
-          if getsockopt(fdi.SocketHandle, SOL_SOCKET, SO_ERROR, addr(error),
+          var size = SockLen sizeof(error)
+          if getsockopt(SocketHandle fdi, SOL_SOCKET, SO_ERROR, addr(error),
                         addr(size)) == 0'i32:
-            rkey.errorCode = error.OSErrorCode
+            rkey.errorCode = OSErrorCode error
 
         rkey.events.incl(Event.Error)
       if (pevents and EPOLLOUT) != 0:
diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim
index f2f5cac9e..cd13deec3 100644
--- a/lib/pure/logging.nim
+++ b/lib/pure/logging.nim
@@ -80,6 +80,7 @@ type
 
   ConsoleLogger* = ref object of Logger ## logger that writes the messages to the
                                         ## console
+    useStderr*: bool ## will send logs into Stderr if set 
 
 when not defined(js):
   type
@@ -150,16 +151,20 @@ method log*(logger: ConsoleLogger, level: Level, args: varargs[string, `$`]) =
       {.emit: "console.log(`cln`);".}
     else:
       try:
-        writeLine(stdout, ln)
-        if level in {lvlError, lvlFatal}: flushFile(stdout)
+        var handle = stdout
+        if logger.useStderr:
+          handle = stderr 
+        writeLine(handle, ln)
+        if level in {lvlError, lvlFatal}: flushFile(handle)
       except IOError:
         discard
 
-proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr): ConsoleLogger =
+proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr, useStderr=false): ConsoleLogger =
   ## Creates a new console logger. This logger logs to the console.
   new result
   result.fmtStr = fmtStr
   result.levelThreshold = levelThreshold
+  result.useStderr = useStderr
 
 when not defined(js):
   method log*(logger: FileLogger, level: Level, args: varargs[string, `$`]) =
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index f04cb5050..e2ad626de 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -168,16 +168,19 @@ when not defined(JS): # C
   proc sqrt*(x: float32): float32 {.importc: "sqrtf", header: "<math.h>".}
   proc sqrt*(x: float64): float64 {.importc: "sqrt", header: "<math.h>".}
     ## Computes the square root of ``x``.
+    ##
     ## .. code-block:: nim
     ##  echo sqrt(1.44) ## 1.2
   proc cbrt*(x: float32): float32 {.importc: "cbrtf", header: "<math.h>".}
   proc cbrt*(x: float64): float64 {.importc: "cbrt", header: "<math.h>".}
     ## Computes the cubic root of ``x``.
+    ##
     ## .. code-block:: nim
     ##  echo cbrt(2.197) ## 1.3
   proc ln*(x: float32): float32 {.importc: "logf", header: "<math.h>".}
   proc ln*(x: float64): float64 {.importc: "log", header: "<math.h>".}
     ## Computes the `natural logarithm <https://en.wikipedia.org/wiki/Natural_logarithm>`_ of ``x``.
+    ##
     ## .. code-block:: nim
     ##  echo ln(exp(4.0)) ## 4.0
 else: # JS
@@ -189,6 +192,7 @@ else: # JS
 
 proc log*[T: SomeFloat](x, base: T): T =
   ## Computes the logarithm of ``x`` to base ``base``.
+  ##
   ## .. code-block:: nim
   ##  echo log(9.0, 3.0) ## 2.0
   ln(x) / ln(base)
@@ -197,51 +201,60 @@ when not defined(JS): # C
   proc log10*(x: float32): float32 {.importc: "log10f", header: "<math.h>".}
   proc log10*(x: float64): float64 {.importc: "log10", header: "<math.h>".}
     ## Computes the common logarithm (base 10) of ``x``.
+    ##
     ## .. code-block:: nim
     ##  echo log10(100.0) ## 2.0
   proc exp*(x: float32): float32 {.importc: "expf", header: "<math.h>".}
   proc exp*(x: float64): float64 {.importc: "exp", header: "<math.h>".}
     ## Computes the exponential function of ``x`` (pow(E, x)).
+    ##
     ## .. code-block:: nim
     ##  echo exp(1.0) ## 2.718281828459045
     ##  echo ln(exp(4.0)) ## 4.0
   proc sin*(x: float32): float32 {.importc: "sinf", header: "<math.h>".}
   proc sin*(x: float64): float64 {.importc: "sin", header: "<math.h>".}
     ## Computes the sine of ``x``.
+    ##
     ## .. code-block:: nim
     ##  echo sin(PI / 6) ## 0.4999999999999999
     ##  echo sin(degToRad(90.0)) ## 1.0
   proc cos*(x: float32): float32 {.importc: "cosf", header: "<math.h>".}
   proc cos*(x: float64): float64 {.importc: "cos", header: "<math.h>".}
     ## Computes the cosine of ``x``.
+    ##
     ## .. code-block:: nim
     ##  echo cos(2 * PI) ## 1.0
     ##  echo cos(degToRad(60.0)) ## 0.5000000000000001
   proc tan*(x: float32): float32 {.importc: "tanf", header: "<math.h>".}
   proc tan*(x: float64): float64 {.importc: "tan", header: "<math.h>".}
     ## Computes the tangent of ``x``.
+    ##
     ## .. code-block:: nim
     ##  echo tan(degToRad(45.0)) ## 0.9999999999999999
     ##  echo tan(PI / 4) ## 0.9999999999999999
   proc sinh*(x: float32): float32 {.importc: "sinhf", header: "<math.h>".}
   proc sinh*(x: float64): float64 {.importc: "sinh", header: "<math.h>".}
     ## Computes the `hyperbolic sine <https://en.wikipedia.org/wiki/Hyperbolic_function#Definitions>`_ of ``x``.
+    ##
     ## .. code-block:: nim
     ##  echo sinh(1.0) ## 1.175201193643801
   proc cosh*(x: float32): float32 {.importc: "coshf", header: "<math.h>".}
   proc cosh*(x: float64): float64 {.importc: "cosh", header: "<math.h>".}
     ## Computes the `hyperbolic cosine <https://en.wikipedia.org/wiki/Hyperbolic_function#Definitions>`_ of ``x``.
+    ##
     ## .. code-block:: nim
     ##  echo cosh(1.0) ## 1.543080634815244
   proc tanh*(x: float32): float32 {.importc: "tanhf", header: "<math.h>".}
   proc tanh*(x: float64): float64 {.importc: "tanh", header: "<math.h>".}
     ## Computes the `hyperbolic tangent <https://en.wikipedia.org/wiki/Hyperbolic_function#Definitions>`_ of ``x``.
+    ##
     ## .. code-block:: nim
     ##  echo tanh(1.0) ## 0.7615941559557649
 
   proc arccos*(x: float32): float32 {.importc: "acosf", header: "<math.h>".}
   proc arccos*(x: float64): float64 {.importc: "acos", header: "<math.h>".}
     ## Computes the arc cosine of ``x``.
+    ##
     ## .. code-block:: nim
     ##  echo arccos(1.0) ## 0.0
   proc arcsin*(x: float32): float32 {.importc: "asinf", header: "<math.h>".}
@@ -250,6 +263,7 @@ when not defined(JS): # C
   proc arctan*(x: float32): float32 {.importc: "atanf", header: "<math.h>".}
   proc arctan*(x: float64): float64 {.importc: "atan", header: "<math.h>".}
     ## Calculate the arc tangent of ``x``.
+    ##
     ## .. code-block:: nim
     ##  echo arctan(1.0) ## 0.7853981633974483
     ##  echo radToDeg(arctan(1.0)) ## 45.0
@@ -259,6 +273,7 @@ when not defined(JS): # C
     ## `arctan2` returns the arc tangent of ``y`` / ``x``; it produces correct
     ## results even when the resulting angle is near pi/2 or -pi/2
     ## (``x`` near 0).
+    ##
     ## .. code-block:: nim
     ##  echo arctan2(1.0, 0.0) ## 1.570796326794897
     ##  echo radToDeg(arctan2(1.0, 0.0)) ## 90.0
@@ -332,6 +347,7 @@ when not defined(JS): # C
   proc hypot*(x, y: float64): float64 {.importc: "hypot", header: "<math.h>".}
     ## Computes the hypotenuse of a right-angle triangle with ``x`` and
     ## ``y`` as its base and height. Equivalent to ``sqrt(x*x + y*y)``.
+    ##
     ## .. code-block:: nim
     ##  echo hypot(4.0, 3.0) ## 5.0
   proc pow*(x, y: float32): float32 {.importc: "powf", header: "<math.h>".}
@@ -339,6 +355,7 @@ when not defined(JS): # C
     ## computes x to power raised of y.
     ##
     ## To compute power between integers, use ``^`` e.g. 2 ^ 6
+    ##
     ## .. code-block:: nim
     ##  echo pow(16.0, 0.5) ## 4.0
 
@@ -361,7 +378,7 @@ when not defined(JS): # C
       ## **Deprecated since version 0.19.0**: Use ``gamma`` instead.
     proc lgamma*(x: float32): float32 {.importc: "lgammaf", header: "<math.h>".}
     proc lgamma*(x: float64): float64 {.importc: "lgamma", header: "<math.h>".}
-      ## Computes the natural log of the gamma function for ``x``. 
+      ## Computes the natural log of the gamma function for ``x``.
 
   proc floor*(x: float32): float32 {.importc: "floorf", header: "<math.h>".}
   proc floor*(x: float64): float64 {.importc: "floor", header: "<math.h>".}
@@ -456,7 +473,11 @@ when not defined(JS): # C
     ## Computes the modulo operation for float values (the remainder of ``x`` divided by ``y``).
     ##
     ## .. code-block:: nim
-    ##  echo 2.5 mod 0.3 ## 0.1
+    ##  ( 6.5 mod  2.5) ==  1.5
+    ##  (-6.5 mod  2.5) == -1.5
+    ##  ( 6.5 mod -2.5) ==  1.5
+    ##  (-6.5 mod -2.5) == -1.5
+
 else: # JS
   proc hypot*[T: float32|float64](x, y: T): T = return sqrt(x*x + y*y)
   proc pow*(x, y: float32): float32 {.importC: "Math.pow", nodecl.}
@@ -474,7 +495,10 @@ else: # JS
     ## Computes the modulo operation for float values (the remainder of ``x`` divided by ``y``).
     ##
     ## .. code-block:: nim
-    ##  echo 2.5 mod 0.3 ## 0.1
+    ##  ( 6.5 mod  2.5) ==  1.5
+    ##  (-6.5 mod  2.5) == -1.5
+    ##  ( 6.5 mod -2.5) ==  1.5
+    ##  (-6.5 mod -2.5) == -1.5
 
 proc round*[T: float32|float64](x: T, places: int): T {.deprecated: "use format instead".} =
   ## Decimal rounding on a binary floating point number.
@@ -498,19 +522,25 @@ proc floorDiv*[T: SomeInteger](x, y: T): T =
   ## This is different from the ``div`` operator, which is defined
   ## as ``trunc(x / y)``. That is, ``div`` rounds towards ``0`` and ``floorDiv``
   ## rounds down.
+  ##
   ## .. code-block:: nim
-  ##  echo floorDiv(13, 3) # 4
-  ##  echo floorDiv(-13, 3) # -5
+  ##  echo floorDiv( 13,  3) #  4
+  ##  echo floorDiv(-13,  3) # -5
+  ##  echo floorDiv( 13, -3) # -5
+  ##  echo floorDiv(-13, -3) #  4
   result = x div y
   let r = x mod y
   if (r > 0 and y < 0) or (r < 0 and y > 0): result.dec 1
 
 proc floorMod*[T: SomeNumber](x, y: T): T =
-  ## Floor modulus is conceptually defined as ``x - (floorDiv(x, y) * y).
+  ## Floor modulus is conceptually defined as ``x - (floorDiv(x, y) * y)``.
   ## This proc behaves the same as the ``%`` operator in Python.
+  ##
   ## .. code-block:: nim
-  ##  echo floorMod(13, 3) # 1
-  ##  echo floorMod(-13, 3) # 2
+  ##  echo floorMod( 13,  3) #  1
+  ##  echo floorMod(-13,  3) #  2
+  ##  echo floorMod( 13, -3) # -2
+  ##  echo floorMod(-13, -3) # -1
   result = x mod y
   if (result > 0 and y < 0) or (result < 0 and y > 0): result += y
 
@@ -525,6 +555,7 @@ when not defined(JS):
     ## and less than 1) and the integer value n such that ``x`` (the original
     ## float value) equals ``m * 2**n``. frexp stores n in `exponent` and returns
     ## m.
+    ##
     ## .. code-block:: nim
     ##  var x : int
     ##  echo frexp(5.0, x) # 0.625
@@ -579,6 +610,7 @@ proc splitDecimal*[T: float32|float64](x: T): tuple[intpart: T, floatpart: T] =
   ##
   ## Both parts have the same sign as ``x``.  Analogous to the ``modf``
   ## function in C.
+  ##
   ## .. code-block:: nim
   ##  echo splitDecimal(5.25) # (intpart: 5.0, floatpart: 0.25)
   var
@@ -594,12 +626,14 @@ proc splitDecimal*[T: float32|float64](x: T): tuple[intpart: T, floatpart: T] =
 
 proc degToRad*[T: float32|float64](d: T): T {.inline.} =
   ## Convert from degrees to radians
+  ##
   ## .. code-block:: nim
   ##  echo degToRad(180.0) # 3.141592653589793
   result = T(d) * RadPerDeg
 
 proc radToDeg*[T: float32|float64](d: T): T {.inline.} =
   ## Convert from radians to degrees
+
   ## .. code-block:: nim
   ##  echo degToRad(2 * PI) # 360.0
   result = T(d) / RadPerDeg
@@ -608,6 +642,7 @@ proc sgn*[T: SomeNumber](x: T): int {.inline.} =
   ## Sign function. Returns -1 for negative numbers and ``NegInf``, 1 for
   ## positive numbers and ``Inf``, and 0 for positive zero, negative zero and
   ## ``NaN``.
+  ##
   ## .. code-block:: nim
   ##  echo sgn(-5) # 1
   ##  echo sgn(-4.1) # -1
@@ -619,6 +654,7 @@ proc sgn*[T: SomeNumber](x: T): int {.inline.} =
 proc `^`*[T](x: T, y: Natural): T =
   ## Computes ``x`` to the power ``y``. ``x`` must be non-negative, use
   ## `pow <#pow,float,float>`_ for negative exponents.
+  ##
   ## .. code-block:: nim
   ##  echo 2 ^ 3 # 8
   when compiles(y >= T(0)):
@@ -650,6 +686,7 @@ proc gcd*[T](x, y: T): T =
 proc gcd*(x, y: SomeInteger): SomeInteger =
   ## Computes the greatest common (positive) divisor of ``x`` and ``y``.
   ## Using binary GCD (aka Stein's) algorithm.
+  ##
   ## .. code-block:: nim
   ##  echo gcd(24, 30) # 6
   when x is SomeSignedInt:
@@ -677,6 +714,7 @@ proc gcd*(x, y: SomeInteger): SomeInteger =
 
 proc lcm*[T](x, y: T): T =
   ## Computes the least common multiple of ``x`` and ``y``.
+  ##
   ## .. code-block:: nim
   ##  echo lcm(24, 30) # 120
   x div gcd(x, y) * y
diff --git a/lib/pure/parsesql.nim b/lib/pure/parsesql.nim
index 9aef43c1b..4b841b9e1 100644
--- a/lib/pure/parsesql.nim
+++ b/lib/pure/parsesql.nim
@@ -566,7 +566,6 @@ type
   SqlParser* = object of SqlLexer ## SQL parser object
     tok: Token
 
-
 {.deprecated: [EInvalidSql: SqlParseError, PSqlNode: SqlNode,
     TSqlNode: SqlNodeObj, TSqlParser: SqlParser, TSqlNodeKind: SqlNodeKind].}
 
@@ -591,6 +590,7 @@ proc len*(n: SqlNode): int =
     result = n.sons.len
 
 proc `[]`*(n: SqlNode; i: int): SqlNode = n.sons[i]
+proc `[]`*(n: SqlNode; i: BackwardsIndex): SqlNode = n.sons[n.len - int(i)]
 
 proc add*(father, n: SqlNode) =
   add(father.sons, n)
@@ -674,7 +674,7 @@ proc getPrecedence(p: SqlParser): int =
     result = 5
   elif isOpr(p, "=") or isOpr(p, "<") or isOpr(p, ">") or isOpr(p, ">=") or
        isOpr(p, "<=") or isOpr(p, "<>") or isOpr(p, "!=") or isKeyw(p, "is") or
-       isKeyw(p, "like"):
+       isKeyw(p, "like") or isKeyw(p, "in"):
     result = 4
   elif isKeyw(p, "and"):
     result = 3
@@ -717,7 +717,10 @@ proc identOrLiteral(p: var SqlParser): SqlNode =
   of tkParLe:
     getTok(p)
     result = newNode(nkPrGroup)
-    result.add(parseExpr(p))
+    while true:
+      result.add(parseExpr(p))
+      if p.tok.kind != tkComma: break
+      getTok(p)
     eat(p, tkParRi)
   else:
     if p.tok.literal == "*":
@@ -1465,6 +1468,22 @@ proc `$`*(n: SqlNode): string =
   ## an alias for `renderSQL`.
   renderSQL(n)
 
+proc treeReprAux(s: SqlNode, level: int, result: var string) =
+  result.add('\n')
+  for i in 0 ..< level: result.add("  ")
+
+  result.add($s.kind)
+  if s.kind in LiteralNodes:
+    result.add(' ')
+    result.add(s.strVal)
+  else:
+    for son in s.sons:
+      treeReprAux(son, level + 1, result)
+
+proc treeRepr*(s: SqlNode): string =
+  result = newStringOfCap(128)
+  treeReprAux(s, 0, result)
+
 when not defined(js):
   import streams
 
diff --git a/lib/pure/parsexml.nim b/lib/pure/parsexml.nim
index d8d5a7a2d..0967f7983 100644
--- a/lib/pure/parsexml.nim
+++ b/lib/pure/parsexml.nim
@@ -180,6 +180,7 @@ type
     errEqExpected,           ## ``=`` expected
     errQuoteExpected,        ## ``"`` or ``'`` expected
     errEndOfCommentExpected  ## ``-->`` expected
+    errAttributeValueExpected ## non-empty attribute value expected
 
   ParserState = enum
     stateStart, stateNormal, stateAttr, stateEmptyElementTag, stateError
@@ -187,6 +188,8 @@ type
   XmlParseOption* = enum  ## options for the XML parser
     reportWhitespace,      ## report whitespace
     reportComments         ## report comments
+    allowUnquotedAttribs   ## allow unquoted attribute values (for HTML)
+    allowEmptyAttribs      ## allow empty attributes (without explicit value)
 
   XmlParser* = object of BaseLexer ## the parser object.
     a, b, c: string
@@ -207,7 +210,8 @@ const
     "'>' expected",
     "'=' expected",
     "'\"' or \"'\" expected",
-    "'-->' expected"
+    "'-->' expected",
+    "attribute value expected"
   ]
 
 proc open*(my: var XmlParser, input: Stream, filename: string,
@@ -618,10 +622,15 @@ proc parseAttribute(my: var XmlParser) =
   if my.a.len == 0:
     markError(my, errGtExpected)
     return
+
+  let startPos = my.bufpos
   parseWhitespace(my, skip=true)
   if my.buf[my.bufpos] != '=':
-    markError(my, errEqExpected)
+    if allowEmptyAttribs notin my.options or
+        (my.buf[my.bufpos] != '>' and my.bufpos == startPos):
+      markError(my, errEqExpected)
     return
+
   inc(my.bufpos)
   parseWhitespace(my, skip=true)
 
@@ -669,6 +678,21 @@ proc parseAttribute(my: var XmlParser) =
             pendingSpace = false
           add(my.b, buf[pos])
           inc(pos)
+  elif allowUnquotedAttribs in my.options:
+    const disallowedChars = {'"', '\'', '`', '=', '<', '>', ' ',
+                             '\0', '\t', '\L', '\F', '\f'}
+    let startPos = pos
+    while (let c = buf[pos]; c notin disallowedChars):
+      if c == '&':
+        my.bufpos = pos
+        parseEntity(my, my.b)
+        my.kind = xmlAttribute # parseEntity overwrites my.kind!
+        pos = my.bufpos
+      else:
+        add(my.b, c)
+        inc(pos)
+    if pos == startPos:
+      markError(my, errAttributeValueExpected)
   else:
     markError(my, errQuoteExpected)
     # error corrections: guess what was meant
diff --git a/lib/pure/strscans.nim b/lib/pure/strscans.nim
index 77763ff43..c1c535e55 100644
--- a/lib/pure/strscans.nim
+++ b/lib/pure/strscans.nim
@@ -129,7 +129,7 @@ to use prefix instead of postfix operators.
 ``+E``           One or more
 ``?E``           Zero or One
 ``E{n,m}``       From ``n`` up to ``m`` times ``E``
-``~Ε``           Not predicate
+``~E``           Not predicate
 ``a ^* b``       Shortcut for ``?(a *(b a))``. Usually used for separators.
 ``a ^* b``       Shortcut for ``?(a +(b a))``. Usually used for separators.
 ``'a'``          Matches a single character
@@ -456,10 +456,11 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b
 
 template atom*(input: string; idx: int; c: char): bool =
   ## Used in scanp for the matching of atoms (usually chars).
-  idx < input.len and input[idx] == c
+  ## EOF is matched as ``'\0'``.
+  (idx < input.len and input[idx] == c) or (idx == input.len and c == '\0')
 
 template atom*(input: string; idx: int; s: set[char]): bool =
-  idx < input.len and input[idx] in s
+  (idx < input.len and input[idx] in s) or (idx == input.len and '\0' in s)
 
 template hasNxt*(input: string; idx: int): bool = idx < input.len
 
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 82c6dc8b9..e266275cf 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -909,7 +909,7 @@ proc toHex*(x: BiggestInt, len: Positive): string {.noSideEffect,
 proc toHex*[T: SomeInteger](x: T): string =
   ## Shortcut for ``toHex(x, T.sizeOf * 2)``
   runnableExamples:
-    doAssert toHex(1984) == "00000000000007C0"
+    doAssert toHex(1984'i64) == "00000000000007C0"
   toHex(BiggestInt(x), T.sizeOf * 2)
 
 proc toHex*(s: string): string {.noSideEffect, rtl.} =
diff --git a/lib/pure/sugar.nim b/lib/pure/sugar.nim
index 8ded552d9..53c31e8c9 100644
--- a/lib/pure/sugar.nim
+++ b/lib/pure/sugar.nim
@@ -125,6 +125,8 @@ macro `->`*(p, b: untyped): untyped =
 type ListComprehension = object
 var lc*: ListComprehension
 
+template `|`*(lc: ListComprehension, comp: untyped): untyped = lc
+
 macro `[]`*(lc: ListComprehension, comp, typ: untyped): untyped =
   ## List comprehension, returns a sequence. `comp` is the actual list
   ## comprehension, for example ``x | (x <- 1..10, x mod 2 == 0)``. `typ` is
@@ -140,8 +142,7 @@ macro `[]`*(lc: ListComprehension, comp, typ: untyped): untyped =
 
   expectLen(comp, 3)
   expectKind(comp, nnkInfix)
-  expectKind(comp[0], nnkIdent)
-  assert($comp[0].ident == "|")
+  assert($comp[0] == "|")
 
   result = newCall(
     newDotExpr(