Merge remote-tracking branch 'nim-lang/devel' into emscripten-support

This commit is contained in:
Andrey Sobolev 2015-09-21 21:41:40 +06:00
commit 7321fb0c18
9 changed files with 128 additions and 60 deletions

View file

@ -32,12 +32,6 @@ type
cursorInBody: bool # only for nimsuggest cursorInBody: bool # only for nimsuggest
bracketExpr: PNode bracketExpr: PNode
template withBracketExpr(x, body: untyped) =
let old = ctx.bracketExpr
ctx.bracketExpr = x
body
ctx.bracketExpr = old
type type
TSemGenericFlag = enum TSemGenericFlag = enum
withinBind, withinTypeDesc, withinMixin withinBind, withinTypeDesc, withinMixin
@ -271,7 +265,7 @@ proc semGenericStmt(c: PContext, n: PNode,
result = newNodeI(nkCall, n.info) result = newNodeI(nkCall, n.info)
result.add newIdentNode(getIdent("[]"), n.info) result.add newIdentNode(getIdent("[]"), n.info)
for i in 0 ..< n.len: result.add(n[i]) 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) result = semGenericStmt(c, result, flags, ctx)
of nkAsgn, nkFastAsgn: of nkAsgn, nkFastAsgn:
checkSonsLen(n, 2) checkSonsLen(n, 2)
@ -291,7 +285,7 @@ proc semGenericStmt(c: PContext, n: PNode,
result.add newIdentNode(getIdent("[]="), n.info) result.add newIdentNode(getIdent("[]="), n.info)
for i in 0 ..< a.len: result.add(a[i]) for i in 0 ..< a.len: result.add(a[i])
result.add(b) result.add(b)
withBracketExpr a.sons[0]: withBracketExpr ctx, a.sons[0]:
result = semGenericStmt(c, result, flags, ctx) result = semGenericStmt(c, result, flags, ctx)
else: else:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):

View file

@ -110,6 +110,13 @@ type
toBind, toMixin, toInject: IntSet toBind, toMixin, toInject: IntSet
owner: PSym owner: PSym
cursorInBody: bool # only for nimsuggest 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 = proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
case n.kind case n.kind
@ -310,6 +317,18 @@ proc wrapInBind(c: var TemplCtx; n: PNode; opr: string): PNode =
else: else:
result = n 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 = proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
result = n result = n
semIdeForTemplateOrGenericCheck(n, c.cursorInBody) semIdeForTemplateOrGenericCheck(n, c.cursorInBody)
@ -452,10 +471,16 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
result.sons[1] = semTemplBody(c, n.sons[1]) result.sons[1] = semTemplBody(c, n.sons[1])
of nkPragma: of nkPragma:
result = onlyReplaceParams(c, n) result = onlyReplaceParams(c, n)
of nkBracketExpr, nkCurlyExpr: of nkBracketExpr:
result = newNodeI(nkCall, n.info) result = newNodeI(nkCall, n.info)
result.add newIdentNode(getIdent(if n.kind == nkBracketExpr:"[]" else:"{}"), result.add newIdentNode(getIdent("[]"), n.info)
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]) for i in 0 ..< n.len: result.add(n[i])
result = semTemplBodySons(c, result) result = semTemplBodySons(c, result)
of nkAsgn, nkFastAsgn: of nkAsgn, nkFastAsgn:
@ -465,19 +490,29 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
let k = a.kind let k = a.kind
case k case k
of nkBracketExpr, nkCurlyExpr: of nkBracketExpr:
result = newNodeI(nkCall, n.info) result = newNodeI(nkCall, n.info)
result.add newIdentNode(getIdent(if k == nkBracketExpr:"[]=" else:"{}="), result.add newIdentNode(getIdent("[]="), n.info)
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]) for i in 0 ..< a.len: result.add(a[i])
result.add(b) result.add(b)
else:
result = n
result = semTemplBodySons(c, result) result = semTemplBodySons(c, result)
else: 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', # dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
# so we use the generic code for nkDotExpr too # so we use the generic code for nkDotExpr too
if n.kind == nkDotExpr or n.kind == nkAccQuoted:
let s = qualifiedLookUp(c.c, n, {}) let s = qualifiedLookUp(c.c, n, {})
if s != nil: if s != nil:
# do not symchoice a quoted template parameter (bug #2390): # do not symchoice a quoted template parameter (bug #2390):
@ -493,6 +528,8 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
else: else:
return symChoice(c.c, n, s, scOpen) return symChoice(c.c, n, s, scOpen)
result = semTemplBodySons(c, n) result = semTemplBodySons(c, n)
else:
result = semTemplBodySons(c, n)
proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode = proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
result = n result = n

View file

@ -139,7 +139,7 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
if it.kind == nkCommentStmt: if it.kind == nkCommentStmt:
result[i] = PTransNode(it) result[i] = PTransNode(it)
elif it.kind == nkIdentDefs: elif it.kind == nkIdentDefs:
if it.sons[0].kind != nkSym: internalError(it.info, "transformVarSection") if it.sons[0].kind == nkSym:
internalAssert(it.len == 3) internalAssert(it.len == 3)
var newVar = copySym(it.sons[0].sym) var newVar = copySym(it.sons[0].sym)
incl(newVar.flags, sfFromGeneric) incl(newVar.flags, sfFromGeneric)
@ -156,6 +156,9 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
defs[2] = transform(c, it.sons[2]) defs[2] = transform(c, it.sons[2])
newVar.ast = defs[2].PNode newVar.ast = defs[2].PNode
result[i] = defs result[i] = defs
else:
# has been transformed into 'param.x' for closure iterators, so keep it:
result[i] = PTransNode(it)
else: else:
if it.kind != nkVarTuple: if it.kind != nkVarTuple:
internalError(it.info, "transformVarSection: not nkVarTuple") internalError(it.info, "transformVarSection: not nkVarTuple")

View file

@ -122,7 +122,7 @@ String handling
This module contains various string matchers for email addresses, etc. This module contains various string matchers for email addresses, etc.
* `subexes <subexes.html>`_ * `subexes <subexes.html>`_
This module implements advanted string substitution operations. This module implements advanced string substitution operations.
Generic Operating System Services Generic Operating System Services

View file

@ -1,7 +1,7 @@
Substitution Expressions (subex) 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 substitution. In contrast to a `regex`:idx: which deals with string analysis, a
*subex* deals with string synthesis. *subex* deals with string synthesis.

View file

@ -18,6 +18,8 @@ import strutils
## ##
## Quick start example: ## Quick start example:
## ##
## .. code-block:: nim
##
## # Create a matrix which first rotates, then scales and at last translates ## # 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) ## 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) IDMATRIX*:Matrix2d=matrix2d(1.0,0.0,0.0,1.0,0.0,0.0)
## Quick access to an identity matrix ## Quick access to an identity matrix
ORIGO*:Point2d=point2d(0.0,0.0) 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) 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) 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
# *************************************** # ***************************************

View file

@ -23,6 +23,8 @@ import times
## ##
## Quick start example: ## Quick start example:
## ##
## .. code-block:: nim
##
## # Create a matrix which first rotates, then scales and at last translates ## # 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) ## var m:Matrix3d=rotate(PI,vector3d(1,1,2.5)) & scale(2.0) & move(100.0,200.0,300.0)

View file

@ -1319,15 +1319,44 @@ proc reversed*(s: string): string =
reverseUntil(len(s)) 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: when isMainModule:
let let
someString = "öÑ" someString = "öÑ"
someRunes = @[runeAt(someString, 0), runeAt(someString, 2)] someRunes = @[runeAt(someString, 0), runeAt(someString, 2)]
compared = (someString == $someRunes) compared = (someString == $someRunes)
assert compared == true doAssert compared == true
assert reversed("Reverse this!") == "!siht esreveR" doAssert reversed("Reverse this!") == "!siht esreveR"
assert reversed("先秦兩漢") == "漢兩秦先" doAssert reversed("先秦兩漢") == "漢兩秦先"
assert reversed("as⃝df̅") == "f̅ds⃝a" doAssert reversed("as⃝df̅") == "f̅ds⃝a"
assert reversed("a⃞b⃞c⃞") == "c⃞b⃞a⃞" doAssert reversed("a⃞b⃞c⃞") == "c⃞b⃞a⃞"
assert len(toRunes("as⃝df̅")) == runeLen("as⃝df̅") doAssert len(toRunes("as⃝df̅")) == runeLen("as⃝df̅")
const test = "as⃝"
doAssert lastRune(test, test.len-1)[1] == 3
doAssert graphemeLen("è", 0) == 2

View file

@ -97,6 +97,7 @@ News
to benchmark it. to benchmark it.
- ``strutils.formatFloat`` and ``formatBiggestFloat`` do not depend on the C - ``strutils.formatFloat`` and ``formatBiggestFloat`` do not depend on the C
locale anymore and now take an optional ``decimalSep = '.'`` parameter. locale anymore and now take an optional ``decimalSep = '.'`` parameter.
- Added ``unicode.lastRune``, ``unicode.graphemeLen``.
Compiler Additions Compiler Additions