mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-18 23:11:36 +00:00
Merge remote-tracking branch 'nim-lang/devel' into emscripten-support
This commit is contained in:
@@ -32,12 +32,6 @@ type
|
||||
cursorInBody: bool # only for nimsuggest
|
||||
bracketExpr: PNode
|
||||
|
||||
template withBracketExpr(x, body: untyped) =
|
||||
let old = ctx.bracketExpr
|
||||
ctx.bracketExpr = x
|
||||
body
|
||||
ctx.bracketExpr = old
|
||||
|
||||
type
|
||||
TSemGenericFlag = enum
|
||||
withinBind, withinTypeDesc, withinMixin
|
||||
@@ -271,7 +265,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add newIdentNode(getIdent("[]"), n.info)
|
||||
for i in 0 ..< n.len: result.add(n[i])
|
||||
withBracketExpr n.sons[0]:
|
||||
withBracketExpr ctx, n.sons[0]:
|
||||
result = semGenericStmt(c, result, flags, ctx)
|
||||
of nkAsgn, nkFastAsgn:
|
||||
checkSonsLen(n, 2)
|
||||
@@ -291,7 +285,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
result.add newIdentNode(getIdent("[]="), n.info)
|
||||
for i in 0 ..< a.len: result.add(a[i])
|
||||
result.add(b)
|
||||
withBracketExpr a.sons[0]:
|
||||
withBracketExpr ctx, a.sons[0]:
|
||||
result = semGenericStmt(c, result, flags, ctx)
|
||||
else:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
|
||||
@@ -110,6 +110,13 @@ type
|
||||
toBind, toMixin, toInject: IntSet
|
||||
owner: PSym
|
||||
cursorInBody: bool # only for nimsuggest
|
||||
bracketExpr: PNode
|
||||
|
||||
template withBracketExpr(ctx, x, body: untyped) =
|
||||
let old = ctx.bracketExpr
|
||||
ctx.bracketExpr = x
|
||||
body
|
||||
ctx.bracketExpr = old
|
||||
|
||||
proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
|
||||
case n.kind
|
||||
@@ -310,6 +317,18 @@ proc wrapInBind(c: var TemplCtx; n: PNode; opr: string): PNode =
|
||||
else:
|
||||
result = n
|
||||
|
||||
proc oprIsRoof(n: PNode): bool =
|
||||
const roof = "^"
|
||||
case n.kind
|
||||
of nkIdent: result = n.ident.s == roof
|
||||
of nkSym: result = n.sym.name.s == roof
|
||||
of nkAccQuoted:
|
||||
if n.len == 1:
|
||||
result = oprIsRoof(n.sons[0])
|
||||
of nkOpenSymChoice, nkClosedSymChoice:
|
||||
result = oprIsRoof(n.sons[0])
|
||||
else: discard
|
||||
|
||||
proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
result = n
|
||||
semIdeForTemplateOrGenericCheck(n, c.cursorInBody)
|
||||
@@ -452,10 +471,16 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
result.sons[1] = semTemplBody(c, n.sons[1])
|
||||
of nkPragma:
|
||||
result = onlyReplaceParams(c, n)
|
||||
of nkBracketExpr, nkCurlyExpr:
|
||||
of nkBracketExpr:
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add newIdentNode(getIdent(if n.kind == nkBracketExpr:"[]" else:"{}"),
|
||||
n.info)
|
||||
result.add newIdentNode(getIdent("[]"), n.info)
|
||||
for i in 0 ..< n.len: result.add(n[i])
|
||||
let n0 = semTemplBody(c, n.sons[0])
|
||||
withBracketExpr c, n0:
|
||||
result = semTemplBodySons(c, result)
|
||||
of nkCurlyExpr:
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add newIdentNode(getIdent("{}"), n.info)
|
||||
for i in 0 ..< n.len: result.add(n[i])
|
||||
result = semTemplBodySons(c, result)
|
||||
of nkAsgn, nkFastAsgn:
|
||||
@@ -465,33 +490,45 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
|
||||
let k = a.kind
|
||||
case k
|
||||
of nkBracketExpr, nkCurlyExpr:
|
||||
of nkBracketExpr:
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add newIdentNode(getIdent(if k == nkBracketExpr:"[]=" else:"{}="),
|
||||
n.info)
|
||||
result.add newIdentNode(getIdent("[]="), n.info)
|
||||
for i in 0 ..< a.len: result.add(a[i])
|
||||
result.add(b)
|
||||
let a0 = semTemplBody(c, a.sons[0])
|
||||
withBracketExpr c, a0:
|
||||
result = semTemplBodySons(c, result)
|
||||
of nkCurlyExpr:
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add newIdentNode(getIdent("{}="), n.info)
|
||||
for i in 0 ..< a.len: result.add(a[i])
|
||||
result.add(b)
|
||||
result = semTemplBodySons(c, result)
|
||||
else:
|
||||
result = n
|
||||
result = semTemplBodySons(c, result)
|
||||
else:
|
||||
result = semTemplBodySons(c, n)
|
||||
of nkCallKinds-{nkPostfix}:
|
||||
result = semTemplBodySons(c, n)
|
||||
if c.bracketExpr != nil and n.len == 2 and oprIsRoof(n.sons[0]):
|
||||
result.add c.bracketExpr
|
||||
of nkDotExpr, nkAccQuoted:
|
||||
# dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
|
||||
# so we use the generic code for nkDotExpr too
|
||||
if n.kind == nkDotExpr or n.kind == nkAccQuoted:
|
||||
let s = qualifiedLookUp(c.c, n, {})
|
||||
if s != nil:
|
||||
# do not symchoice a quoted template parameter (bug #2390):
|
||||
if s.owner == c.owner and s.kind == skParam and
|
||||
n.kind == nkAccQuoted and n.len == 1:
|
||||
incl(s.flags, sfUsed)
|
||||
styleCheckUse(n.info, s)
|
||||
return newSymNode(s, n.info)
|
||||
elif contains(c.toBind, s.id):
|
||||
return symChoice(c.c, n, s, scClosed)
|
||||
elif contains(c.toMixin, s.name.id):
|
||||
return symChoice(c.c, n, s, scForceOpen)
|
||||
else:
|
||||
return symChoice(c.c, n, s, scOpen)
|
||||
let s = qualifiedLookUp(c.c, n, {})
|
||||
if s != nil:
|
||||
# do not symchoice a quoted template parameter (bug #2390):
|
||||
if s.owner == c.owner and s.kind == skParam and
|
||||
n.kind == nkAccQuoted and n.len == 1:
|
||||
incl(s.flags, sfUsed)
|
||||
styleCheckUse(n.info, s)
|
||||
return newSymNode(s, n.info)
|
||||
elif contains(c.toBind, s.id):
|
||||
return symChoice(c.c, n, s, scClosed)
|
||||
elif contains(c.toMixin, s.name.id):
|
||||
return symChoice(c.c, n, s, scForceOpen)
|
||||
else:
|
||||
return symChoice(c.c, n, s, scOpen)
|
||||
result = semTemplBodySons(c, n)
|
||||
else:
|
||||
result = semTemplBodySons(c, n)
|
||||
|
||||
proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
|
||||
|
||||
@@ -139,23 +139,26 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
|
||||
if it.kind == nkCommentStmt:
|
||||
result[i] = PTransNode(it)
|
||||
elif it.kind == nkIdentDefs:
|
||||
if it.sons[0].kind != nkSym: internalError(it.info, "transformVarSection")
|
||||
internalAssert(it.len == 3)
|
||||
var newVar = copySym(it.sons[0].sym)
|
||||
incl(newVar.flags, sfFromGeneric)
|
||||
# fixes a strange bug for rodgen:
|
||||
#include(it.sons[0].sym.flags, sfFromGeneric);
|
||||
newVar.owner = getCurrOwner(c)
|
||||
idNodeTablePut(c.transCon.mapping, it.sons[0].sym, newSymNode(newVar))
|
||||
var defs = newTransNode(nkIdentDefs, it.info, 3)
|
||||
if importantComments():
|
||||
# keep documentation information:
|
||||
PNode(defs).comment = it.comment
|
||||
defs[0] = newSymNode(newVar).PTransNode
|
||||
defs[1] = it.sons[1].PTransNode
|
||||
defs[2] = transform(c, it.sons[2])
|
||||
newVar.ast = defs[2].PNode
|
||||
result[i] = defs
|
||||
if it.sons[0].kind == nkSym:
|
||||
internalAssert(it.len == 3)
|
||||
var newVar = copySym(it.sons[0].sym)
|
||||
incl(newVar.flags, sfFromGeneric)
|
||||
# fixes a strange bug for rodgen:
|
||||
#include(it.sons[0].sym.flags, sfFromGeneric);
|
||||
newVar.owner = getCurrOwner(c)
|
||||
idNodeTablePut(c.transCon.mapping, it.sons[0].sym, newSymNode(newVar))
|
||||
var defs = newTransNode(nkIdentDefs, it.info, 3)
|
||||
if importantComments():
|
||||
# keep documentation information:
|
||||
PNode(defs).comment = it.comment
|
||||
defs[0] = newSymNode(newVar).PTransNode
|
||||
defs[1] = it.sons[1].PTransNode
|
||||
defs[2] = transform(c, it.sons[2])
|
||||
newVar.ast = defs[2].PNode
|
||||
result[i] = defs
|
||||
else:
|
||||
# has been transformed into 'param.x' for closure iterators, so keep it:
|
||||
result[i] = PTransNode(it)
|
||||
else:
|
||||
if it.kind != nkVarTuple:
|
||||
internalError(it.info, "transformVarSection: not nkVarTuple")
|
||||
|
||||
@@ -122,7 +122,7 @@ String handling
|
||||
This module contains various string matchers for email addresses, etc.
|
||||
|
||||
* `subexes <subexes.html>`_
|
||||
This module implements advanted string substitution operations.
|
||||
This module implements advanced string substitution operations.
|
||||
|
||||
|
||||
Generic Operating System Services
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Substitution Expressions (subex)
|
||||
================================
|
||||
|
||||
A *subex* (*Substitution Expression*) represents an advanted string
|
||||
A *subex* (*Substitution Expression*) represents an advanced string
|
||||
substitution. In contrast to a `regex`:idx: which deals with string analysis, a
|
||||
*subex* deals with string synthesis.
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ import strutils
|
||||
##
|
||||
## Quick start example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## # Create a matrix which first rotates, then scales and at last translates
|
||||
##
|
||||
## var m:Matrix2d=rotate(DEG90) & scale(2.0) & move(100.0,200.0)
|
||||
@@ -93,11 +95,11 @@ let
|
||||
IDMATRIX*:Matrix2d=matrix2d(1.0,0.0,0.0,1.0,0.0,0.0)
|
||||
## Quick access to an identity matrix
|
||||
ORIGO*:Point2d=point2d(0.0,0.0)
|
||||
## Quick acces to point (0,0)
|
||||
## Quick access to point (0,0)
|
||||
XAXIS*:Vector2d=vector2d(1.0,0.0)
|
||||
## Quick acces to an 2d x-axis unit vector
|
||||
## Quick access to an 2d x-axis unit vector
|
||||
YAXIS*:Vector2d=vector2d(0.0,1.0)
|
||||
## Quick acces to an 2d y-axis unit vector
|
||||
## Quick access to an 2d y-axis unit vector
|
||||
|
||||
|
||||
# ***************************************
|
||||
|
||||
@@ -23,6 +23,8 @@ import times
|
||||
##
|
||||
## Quick start example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## # Create a matrix which first rotates, then scales and at last translates
|
||||
##
|
||||
## var m:Matrix3d=rotate(PI,vector3d(1,1,2.5)) & scale(2.0) & move(100.0,200.0,300.0)
|
||||
|
||||
@@ -1319,15 +1319,44 @@ proc reversed*(s: string): string =
|
||||
|
||||
reverseUntil(len(s))
|
||||
|
||||
proc graphemeLen*(s: string; i: Natural): Natural =
|
||||
## The number of bytes belonging to 's[i]' including following combining
|
||||
## characters.
|
||||
var j = i.int
|
||||
var r, r2: Rune
|
||||
if j < s.len:
|
||||
fastRuneAt(s, j, r, true)
|
||||
result = j-i
|
||||
while j < s.len:
|
||||
fastRuneAt(s, j, r2, true)
|
||||
if not isCombining(r2): break
|
||||
result = j-i
|
||||
|
||||
proc lastRune*(s: string; last: int): (Rune, int) =
|
||||
## length of the last rune in 's[0..last]'. Returns the rune and its length
|
||||
## in bytes.
|
||||
if s[last] <= chr(127):
|
||||
result = (Rune(s[last]), 1)
|
||||
else:
|
||||
var L = 0
|
||||
while last-L >= 0 and ord(s[last-L]) shr 6 == 0b10: inc(L)
|
||||
inc(L)
|
||||
var r: Rune
|
||||
fastRuneAt(s, last-L, r, false)
|
||||
result = (r, L)
|
||||
|
||||
when isMainModule:
|
||||
let
|
||||
someString = "öÑ"
|
||||
someRunes = @[runeAt(someString, 0), runeAt(someString, 2)]
|
||||
compared = (someString == $someRunes)
|
||||
assert compared == true
|
||||
doAssert compared == true
|
||||
|
||||
assert reversed("Reverse this!") == "!siht esreveR"
|
||||
assert reversed("先秦兩漢") == "漢兩秦先"
|
||||
assert reversed("as⃝df̅") == "f̅ds⃝a"
|
||||
assert reversed("a⃞b⃞c⃞") == "c⃞b⃞a⃞"
|
||||
assert len(toRunes("as⃝df̅")) == runeLen("as⃝df̅")
|
||||
doAssert reversed("Reverse this!") == "!siht esreveR"
|
||||
doAssert reversed("先秦兩漢") == "漢兩秦先"
|
||||
doAssert reversed("as⃝df̅") == "f̅ds⃝a"
|
||||
doAssert reversed("a⃞b⃞c⃞") == "c⃞b⃞a⃞"
|
||||
doAssert len(toRunes("as⃝df̅")) == runeLen("as⃝df̅")
|
||||
const test = "as⃝"
|
||||
doAssert lastRune(test, test.len-1)[1] == 3
|
||||
doAssert graphemeLen("è", 0) == 2
|
||||
|
||||
@@ -97,6 +97,7 @@ News
|
||||
to benchmark it.
|
||||
- ``strutils.formatFloat`` and ``formatBiggestFloat`` do not depend on the C
|
||||
locale anymore and now take an optional ``decimalSep = '.'`` parameter.
|
||||
- Added ``unicode.lastRune``, ``unicode.graphemeLen``.
|
||||
|
||||
|
||||
Compiler Additions
|
||||
|
||||
Reference in New Issue
Block a user