From f838c1baa48a22ef74f431d9b691af179d1c632d Mon Sep 17 00:00:00 2001 From: Adam Strzelecki Date: Fri, 30 Oct 2015 00:27:33 +0100 Subject: [PATCH 001/211] fixes #3498 Previously it was not possible to use template arguments in template body as the symbols were not resolved correctly leading to Error: undeclared identifier: 'XX', eg.: template defaultOf[T](t: T): expr = (var d: T; d) echo defaultOf(1) #<- invalid identifier, but should output 0 --- compiler/evaltempl.nim | 3 ++- compiler/semtempl.nim | 5 +---- tests/generics/tgenerictmpl.nim | 25 +++++++++++++++++-------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim index c33e5be861..01233274b0 100644 --- a/compiler/evaltempl.nim +++ b/compiler/evaltempl.nim @@ -38,7 +38,8 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) = if s.owner.id == c.owner.id: if s.kind == skParam and sfGenSym notin s.flags: handleParam actual.sons[s.position] - elif s.kind == skGenericParam: + elif s.kind == skGenericParam or + s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam: handleParam actual.sons[s.owner.typ.len + s.position - 1] else: internalAssert sfGenSym in s.flags diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 2dda8276d8..0dc6009836 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -228,10 +228,7 @@ proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode = of skParam: result = n of skType: - if (s.typ != nil) and (s.typ.kind != tyGenericParam): - result = newSymNodeTypeDesc(s, n.info) - else: - result = n + result = newSymNodeTypeDesc(s, n.info) else: result = newSymNode(s, n.info) diff --git a/tests/generics/tgenerictmpl.nim b/tests/generics/tgenerictmpl.nim index a749e65708..c71ce4e2ee 100644 --- a/tests/generics/tgenerictmpl.nim +++ b/tests/generics/tgenerictmpl.nim @@ -1,12 +1,21 @@ +discard """ + output: '''0 +123''' +""" -template tmp[T](x: var seq[T]) = - #var yz: T # XXX doesn't work yet +# bug #3498 + +template defaultOf[T](t: T): expr = (var d: T; d) + +echo defaultOf(1) #<- excpected 0 + +# assignment using template + +template tassign[T](x: var seq[T]) = x = @[1, 2, 3] -macro tmp2[T](x: var seq[T]): stmt = - nil - var y: seq[int] -tmp(y) -tmp(y) -echo y.repr +tassign(y) #<- x is expected = @[1, 2, 3] +tassign(y) + +echo y[0], y[1], y[2] From 097c508897ccb53137916c431836689ba0fc0186 Mon Sep 17 00:00:00 2001 From: Matt Sullivan Date: Fri, 30 Oct 2015 23:42:29 -0500 Subject: [PATCH 002/211] Create entity nodes with xmlparser --- lib/pure/xmlparser.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/xmlparser.nim b/lib/pure/xmlparser.nim index 56b1220008..b1c6acacef 100644 --- a/lib/pure/xmlparser.nim +++ b/lib/pure/xmlparser.nim @@ -96,7 +96,7 @@ proc parse(x: var XmlParser, errors: var seq[string]): XmlNode = next(x) of xmlEntity: ## &entity; - errors.add(errorMsg(x, "unknown entity: " & x.entityName)) + result = newEntity(x.entityName) next(x) of xmlEof: discard From 8671656e6f6d8cca67054a925dfdcb8246a97bef Mon Sep 17 00:00:00 2001 From: Matt Sullivan Date: Sat, 31 Oct 2015 13:30:07 -0500 Subject: [PATCH 003/211] Add a test to xmlparser --- lib/pure/xmlparser.nim | 27 +++++++++++++++++---------- tests/testdata/doc1.xml | 1 + 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/pure/xmlparser.nim b/lib/pure/xmlparser.nim index b1c6acacef..2a2c3e1dd8 100644 --- a/lib/pure/xmlparser.nim +++ b/lib/pure/xmlparser.nim @@ -143,17 +143,24 @@ proc loadXml*(path: string): XmlNode = result = loadXml(path, errors) if errors.len > 0: raiseInvalidXml(errors) -when not defined(testing) and isMainModule: - import os +when isMainModule: + when not defined(testing): + import os - var errors: seq[string] = @[] - var x = loadXml(paramStr(1), errors) - for e in items(errors): echo e + var errors: seq[string] = @[] + var x = loadXml(paramStr(1), errors) + for e in items(errors): echo e - var f: File - if open(f, "xmltest.txt", fmWrite): - f.write($x) - f.close() + var f: File + if open(f, "xmltest.txt", fmWrite): + f.write($x) + f.close() + else: + quit("cannot write test.txt") else: - quit("cannot write test.txt") + block: # correctly parse ../../tests/testdata/doc1.xml + let filePath = "tests/testdata/doc1.xml" + var errors: seq[string] = @[] + var xml = loadXml(filePath, errors) + assert(errors.len == 0, "The file tests/testdata/doc1.xml should be parsed without errors.") diff --git a/tests/testdata/doc1.xml b/tests/testdata/doc1.xml index 4e77481aa1..07cbceeb73 100644 --- a/tests/testdata/doc1.xml +++ b/tests/testdata/doc1.xml @@ -5,6 +5,7 @@ bla ah absy hsh hsh + &woohoo; sjj bla From c0179043639ceab4f146fda2eec906fc30740b4b Mon Sep 17 00:00:00 2001 From: Anatoly Galiulin Date: Fri, 6 Nov 2015 10:24:23 +0600 Subject: [PATCH 004/211] Fixed issue 3513: wrong setupQuery realization --- lib/impure/db_postgres.nim | 8 ++------ tests/untestable/tpostgres.nim | 4 +++- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim index 7e62194653..5603d9686f 100644 --- a/lib/impure/db_postgres.nim +++ b/lib/impure/db_postgres.nim @@ -167,11 +167,7 @@ proc newRow(L: int): Row = proc setupQuery(db: DbConn, query: SqlQuery, args: varargs[string]): PPGresult = - # s is a dummy unique id str for each setupQuery query - let s = "setupQuery_Query_" & string(query) - var res = pqprepare(db, s, dbFormat(query, args), 0, nil) - result = pqexecPrepared(db, s, 0, nil, - nil, nil, 0) + result = pqexec(db, dbFormat(query, args)) if pqResultStatus(result) != PGRES_TUPLES_OK: dbError(db) proc setupQuery(db: DbConn, stmtName: SqlPrepared, @@ -380,4 +376,4 @@ proc setEncoding*(connection: DbConn, encoding: string): bool {. return pqsetClientEncoding(connection, encoding) == 0 -# Tests are in ../../tests/untestable/tpostgres. \ No newline at end of file +# Tests are in ../../tests/untestable/tpostgres. diff --git a/tests/untestable/tpostgres.nim b/tests/untestable/tpostgres.nim index 5f29da091c..81fe8bf511 100644 --- a/tests/untestable/tpostgres.nim +++ b/tests/untestable/tpostgres.nim @@ -9,5 +9,7 @@ let name = "Dom" db.exec(sql"INSERT INTO myTable (id, name) VALUES (0, ?)", name) doAssert db.getValue(sql"SELECT name FROM myTable") == name +# Check issue #3513 +doAssert db.getValue(sql"SELECT name FROM myTable") == name -db.close() \ No newline at end of file +db.close() From 03590a1c42905d7786f307ec8e3ba6930059ee83 Mon Sep 17 00:00:00 2001 From: JamesP Date: Sat, 7 Nov 2015 15:10:51 +1000 Subject: [PATCH 005/211] Removal of RunningStats ready for new stats.nim pure lib file --- lib/pure/math.nim | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 391a880aea..91877fcfa9 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -376,48 +376,6 @@ proc random*[T](a: openArray[T]): T = ## returns a random element from the openarray `a`. result = a[random(a.low..a.len)] -type - RunningStat* = object ## an accumulator for statistical data - n*: int ## number of pushed data - sum*, min*, max*, mean*: float ## self-explaining - oldM, oldS, newS: float - -{.deprecated: [TFloatClass: FloatClass, TRunningStat: RunningStat].} - -proc push*(s: var RunningStat, x: float) = - ## pushes a value `x` for processing - inc(s.n) - # See Knuth TAOCP vol 2, 3rd edition, page 232 - if s.n == 1: - s.min = x - s.max = x - s.oldM = x - s.mean = x - s.oldS = 0.0 - else: - if s.min > x: s.min = x - if s.max < x: s.max = x - s.mean = s.oldM + (x - s.oldM)/toFloat(s.n) - s.newS = s.oldS + (x - s.oldM)*(x - s.mean) - - # set up for next iteration: - s.oldM = s.mean - s.oldS = s.newS - s.sum = s.sum + x - -proc push*(s: var RunningStat, x: int) = - ## pushes a value `x` for processing. `x` is simply converted to ``float`` - ## and the other push operation is called. - push(s, toFloat(x)) - -proc variance*(s: RunningStat): float = - ## computes the current variance of `s` - if s.n > 1: result = s.newS / (toFloat(s.n - 1)) - -proc standardDeviation*(s: RunningStat): float = - ## computes the current standard deviation of `s` - result = sqrt(variance(s)) - {.pop.} {.pop.} From cdd00c4df608232c4822aed72bf7bd56e9cbd80c Mon Sep 17 00:00:00 2001 From: JamesP Date: Sat, 7 Nov 2015 15:15:30 +1000 Subject: [PATCH 006/211] Add RunningStat related statistics code removed from math lib, and add new functionality - skewness & kurtosis (3rd and 4th stat moments) - addition ops for RunningStat - RunningRegress object - slope, intercept and correlation regression procs - addition ops for RunningRegress --- lib/pure/stats.nim | 269 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 lib/pure/stats.nim diff --git a/lib/pure/stats.nim b/lib/pure/stats.nim new file mode 100644 index 0000000000..a78a2b5bf5 --- /dev/null +++ b/lib/pure/stats.nim @@ -0,0 +1,269 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2015 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# +## Statistical analysis framework for performing +## basic statistical analysis of data. +## The data is analysed in a single pass, when a data value +## is pushed to the ``RunningStat`` or ``RunningRegress`` objects +## +## ``RunningStat`` calculates for a single data set +## - n (data count) +## - min (smallest value) +## - max (largest value) +## - mean +## - variance +## - varianceS (sample var) +## - standardDeviation +## - standardDeviationS (sample stddev) +## - skewness (the third statistical moment) +## - kurtosis (the fourth statistical moment) +## +## ``RunningRegress`` calculates for two sets of data +## - n +## - slope +## - intercept +## - correlation +## +from math import FloatClass, sqrt, pow, round + +{.push debugger:off .} # the user does not want to trace a part + # of the standard library! +{.push checks:off, line_dir:off, stack_trace:off.} + +type + RunningStat* = object ## an accumulator for statistical data + n*: int ## number of pushed data + min*, max*: float ## self-explaining + mom1, mom2, mom3, mom4: float ## statistical moments, mom1 is mean + + + RunningRegress* = object ## an accumulator for regression calculations + n*: int ## number of pushed data + x_stats*: RunningStat ## stats for first set of data + y_stats*: RunningStat ## stats for second set of data + s_xy: float ## acculated data for combined xy + +{.deprecated: [TFloatClass: FloatClass, TRunningStat: RunningStat].} + +proc clear(s: var RunningStat) = + ## reset `s` + s.n = 0 + s.min = 0.0 + s.max = 0.0 + s.mom1 = 0.0 + s.mom2 = 0.0 + s.mom3 = 0.0 + s.mom4 = 0.0 + +proc push*(s: var RunningStat, x: float) = + ## pushes a value `x` for processing + inc(s.n) + # See Knuth TAOCP vol 2, 3rd edition, page 232 + if s.min > x: s.min = x + if s.max < x: s.max = x + let n = toFloat(s.n) + let delta = x - s.mom1 + let delta_n = delta / toFloat(s.n) + let delta_n2 = delta_n * delta_n + let term1 = delta * delta_n * toFloat(s.n - 1) + s.mom4 += term1 * delta_n2 * (n*n - 3*n + 3) + + 6*delta_n2*s.mom2 - 4*delta_n*s.mom3 + s.mom3 += term1 * delta_n * (n - 2) - 3*delta_n*s.mom2 + s.mom2 += term1 + s.mom1 += delta_n + +proc push*(s: var RunningStat, x: int) = + ## pushes a value `x` for processing. + ## + ## `x` is simply converted to ``float`` + ## and the other push operation is called. + s.push(toFloat(x)) + +proc push*(s: var RunningStat, x: openarray[float|int]) = + ## pushes all values of `x` for processing. + ## + ## Int values of `x` are simply converted to ``float`` and + ## the other push operation is called. + for val in x: + s.push(val) + +proc mean*(s: RunningStat): float = result = s.mom1 + ## computes the current mean of `s` + +proc variance*(s: RunningStat): float = + ## computes the current population variance of `s` + result = s.mom2 / toFloat(s.n) + +proc varianceS*(s: RunningStat): float = + ## computes the current sample variance of `s` + if s.n > 1: result = s.mom2 / toFloat(s.n - 1) + +proc standardDeviation*(s: RunningStat): float = + ## computes the current population standard deviation of `s` + result = sqrt(variance(s)) + +proc standardDeviationS*(s: RunningStat): float = + ## computes the current sample standard deviation of `s` + result = sqrt(varianceS(s)) + +proc skewness*(s: RunningStat): float = + ## computes the current population skewness of `s` + result = sqrt(toFloat(s.n)) * s.mom3 / pow(s.mom2, 1.5) + +proc skewnessS*(s: RunningStat): float = + ## computes the current sample skewness of `s` + let s2 = skewness(s) + result = sqrt(toFloat(s.n*(s.n-1)))*s2 / toFloat(s.n-2) + +proc kurtosis*(s: RunningStat): float = + ## computes the current population kurtosis of `s` + result = toFloat(s.n) * s.mom4 / (s.mom2 * s.mom2) - 3.0 + +proc kurtosisS*(s: RunningStat): float = + ## computes the current sample kurtosis of `s` + result = toFloat(s.n-1) / toFloat((s.n-2)*(s.n-3)) * + (toFloat(s.n+1)*kurtosis(s) + 6) + +proc `+`*(a, b: RunningStat): RunningStat = + ## combine two RunningStats. + ## + ## Useful if performing parallel analysis of data series + ## and need to re-combine parallel result sets + result.clear() + result.n = a.n + b.n + + let delta = b.mom1 - a.mom1 + let delta2 = delta*delta + let delta3 = delta*delta2 + let delta4 = delta2*delta2 + let n = toFloat(result.n) + + result.mom1 = (a.n.float*a.mom1 + b.n.float*b.mom1) / n + result.mom2 = a.mom2 + b.mom2 + delta2 * a.n.float * b.n.float / n + result.mom3 = a.mom3 + b.mom3 + + delta3 * a.n.float * b.n.float * (a.n.float - b.n.float)/(n*n); + result.mom3 += 3.0*delta * (a.n.float*b.mom2 - b.n.float*a.mom2) / n + result.mom4 = a.mom4 + b.mom4 + + delta4*a.n.float*b.n.float * toFloat(a.n*a.n - a.n*b.n + b.n*b.n) / + (n*n*n) + result.mom4 += 6.0*delta2 * (a.n.float*a.n.float*b.mom2 + b.n.float*b.n.float*a.mom2) / + (n*n) + + 4.0*delta*(a.n.float*b.mom3 - b.n.float*a.mom3) / n + result.max = max(a.max, b.max) + result.min = max(a.min, b.min) + +proc `+=`*(a: var RunningStat, b: RunningStat) {.inline.} = + ## add a second RunningStats `b` to `a` + a = a + b + +# ---------------------- Running Regression ----------------------------- + +proc clear*(r: var RunningRegress) = + ## reset `r` + r.x_stats.clear() + r.y_stats.clear() + r.s_xy = 0.0 + r.n = 0 + +proc push*(r: var RunningRegress, x, y: float) = + ## pushes two values `x` and `y` for processing + r.s_xy += (r.x_stats.mean() -x)*(r.y_stats.mean() - y)*toFloat(r.n)/toFloat(r.n+1) + + r.x_stats.push(x) + r.y_stats.push(y) + inc(r.n) + +proc push*(r: var RunningRegress, x, y: int) {.inline.} = + ## pushes two values `x` and `y` for processing. + ## + ## `x` and `y` are converted to ``float`` + ## and the other push operation is called. + r.push(toFloat(x), toFloat(y)) + +proc push*(r: var RunningRegress, x, y: openarray[float|int]) = + ## pushes two sets of values `x` and `y` for processing. + assert(x.len == y.len) + for i in 0.. Date: Sat, 7 Nov 2015 17:47:49 +1000 Subject: [PATCH 007/211] import the new stats lib --- examples/statcsv.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/statcsv.nim b/examples/statcsv.nim index f2cf809e20..983cd555fb 100644 --- a/examples/statcsv.nim +++ b/examples/statcsv.nim @@ -3,7 +3,7 @@ # the standard deviation of its columns. # The CSV file can have a header which is then used for the output. -import os, streams, parsecsv, strutils, math +import os, streams, parsecsv, strutils, math, stats if paramCount() < 1: quit("Usage: statcsv filename[.csv]") From 7d62b9fc1a7f8ec18c83b3800aaaecda1b085c46 Mon Sep 17 00:00:00 2001 From: JamesP Date: Sat, 7 Nov 2015 18:00:21 +1000 Subject: [PATCH 008/211] add sum back in, fix min inital value, tidy up spaces in code and comment wording, add a sum test assertion --- lib/pure/stats.nim | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/lib/pure/stats.nim b/lib/pure/stats.nim index a78a2b5bf5..50b5601e5b 100644 --- a/lib/pure/stats.nim +++ b/lib/pure/stats.nim @@ -15,6 +15,7 @@ ## - n (data count) ## - min (smallest value) ## - max (largest value) +## - sum ## - mean ## - variance ## - varianceS (sample var) @@ -36,25 +37,26 @@ from math import FloatClass, sqrt, pow, round {.push checks:off, line_dir:off, stack_trace:off.} type - RunningStat* = object ## an accumulator for statistical data - n*: int ## number of pushed data - min*, max*: float ## self-explaining - mom1, mom2, mom3, mom4: float ## statistical moments, mom1 is mean + RunningStat* = object ## an accumulator for statistical data + n*: int ## number of pushed data + min*, max*, sum*: float ## self-explaining + mom1, mom2, mom3, mom4: float ## statistical moments, mom1 is mean RunningRegress* = object ## an accumulator for regression calculations n*: int ## number of pushed data x_stats*: RunningStat ## stats for first set of data - y_stats*: RunningStat ## stats for second set of data - s_xy: float ## acculated data for combined xy + y_stats*: RunningStat ## stats for second set of data + s_xy: float ## accumulated data for combined xy {.deprecated: [TFloatClass: FloatClass, TRunningStat: RunningStat].} -proc clear(s: var RunningStat) = +proc clear*(s: var RunningStat) = ## reset `s` s.n = 0 - s.min = 0.0 + s.min = toBiggestFloat(int.high) s.max = 0.0 + s.sum = 0.0 s.mom1 = 0.0 s.mom2 = 0.0 s.mom3 = 0.0 @@ -62,10 +64,12 @@ proc clear(s: var RunningStat) = proc push*(s: var RunningStat, x: float) = ## pushes a value `x` for processing + if s.n == 0: s.min = x inc(s.n) # See Knuth TAOCP vol 2, 3rd edition, page 232 if s.min > x: s.min = x if s.max < x: s.max = x + s.sum += x let n = toFloat(s.n) let delta = x - s.mom1 let delta_n = delta / toFloat(s.n) @@ -92,8 +96,9 @@ proc push*(s: var RunningStat, x: openarray[float|int]) = for val in x: s.push(val) -proc mean*(s: RunningStat): float = result = s.mom1 +proc mean*(s: RunningStat): float = ## computes the current mean of `s` + result = s.mom1 proc variance*(s: RunningStat): float = ## computes the current population variance of `s` @@ -172,8 +177,8 @@ proc clear*(r: var RunningRegress) = proc push*(r: var RunningRegress, x, y: float) = ## pushes two values `x` and `y` for processing - r.s_xy += (r.x_stats.mean() -x)*(r.y_stats.mean() - y)*toFloat(r.n)/toFloat(r.n+1) - + r.s_xy += (r.x_stats.mean() - x)*(r.y_stats.mean() - y)* + toFloat(r.n) / toFloat(r.n + 1) r.x_stats.push(x) r.y_stats.push(y) inc(r.n) @@ -254,6 +259,10 @@ when isMainModule: doAssert(clean(rs1.mom2) == clean(rs.mom2)) doAssert(clean(rs1.mom3) == clean(rs.mom3)) doAssert(clean(rs1.mom4) == clean(rs.mom4)) + rs1.clear() + rs1.push(@[1.0, 2.2, 1.4, 4.9]) + doAssert(rs1.sum == 9.5) + doAssert(rs1.mean() == 2.375) var rr: RunningRegress rr.push(@[0.0,1.0,2.8,3.0,4.0], @[0.0,1.0,2.3,3.0,4.0]) From ab0a7303bf6ebf68f30958486346d77f929f03c9 Mon Sep 17 00:00:00 2001 From: Gour Date: Sat, 7 Nov 2015 09:33:55 +0100 Subject: [PATCH 009/211] fix docgen link --- doc/tools.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tools.txt b/doc/tools.txt index bad6039253..7c9aed7ade 100644 --- a/doc/tools.txt +++ b/doc/tools.txt @@ -4,7 +4,7 @@ Tools available with Nim The standard distribution ships with the following tools: -- | `Documentation generator `_ +- | `Documentation generator `_ | The builtin document generator ``nim doc2`` generates HTML documentation from ``.nim`` source files. From 696b89c1117a69531a861ed3980f86d6ad95acf6 Mon Sep 17 00:00:00 2001 From: wt Date: Tue, 10 Nov 2015 11:13:04 +0800 Subject: [PATCH 010/211] Fix osproc.close --- lib/pure/osproc.nim | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index de9e639094..7a1e14a577 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -937,9 +937,10 @@ elif not defined(useNimRtl): if p.inStream != nil: close(p.inStream) if p.outStream != nil: close(p.outStream) if p.errStream != nil: close(p.errStream) - discard close(p.inHandle) - discard close(p.outHandle) - discard close(p.errHandle) + if poParentStreams notin p.options: + discard close(p.inHandle) + discard close(p.outHandle) + discard close(p.errHandle) proc suspend(p: Process) = if kill(p.id, SIGSTOP) != 0'i32: raiseOsError(osLastError()) From 209a5fc1bcfdd9b474e17b4619f6361fe80c5b2e Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 10 Nov 2015 15:27:20 +0100 Subject: [PATCH 011/211] updated old links on the website --- tools/website.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/website.tmpl b/tools/website.tmpl index 7541fae4c4..1f882510c7 100644 --- a/tools/website.tmpl +++ b/tools/website.tmpl @@ -181,7 +181,7 @@ runForever() Stable Documentation Learning Resources - Issues & Requests + Issues & Requests

Community

@@ -193,7 +193,7 @@ runForever()
From e9313dd3621f41ce6be875462769636ab67c2032 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 10 Nov 2015 15:28:34 +0100 Subject: [PATCH 012/211] added prefix matching to critbits.nim --- lib/pure/collections/critbits.nim | 40 ++++++++++++++++++------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim index 8c507d4fbf..bb234565ba 100644 --- a/lib/pure/collections/critbits.nim +++ b/lib/pure/collections/critbits.nim @@ -232,7 +232,7 @@ iterator mpairs*[T](c: var CritBitTree[T]): tuple[key: string, val: var T] = ## yields all (key, value)-pairs of `c`. The yielded values can be modified. for x in leaves(c.root): yield (x.key, x.val) -proc allprefixedAux[T](c: CritBitTree[T], key: string): Node[T] = +proc allprefixedAux[T](c: CritBitTree[T], key: string; longestMatch: bool): Node[T] = var p = c.root var top = p if p != nil: @@ -242,43 +242,51 @@ proc allprefixedAux[T](c: CritBitTree[T], key: string): Node[T] = let dir = (1 + (ch.ord or p.otherBits.ord)) shr 8 p = p.child[dir] if q.byte < key.len: top = p - for i in 0 .. Date: Tue, 10 Nov 2015 15:29:01 +0100 Subject: [PATCH 013/211] added newTree to ast.nim --- compiler/ast.nim | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/ast.nim b/compiler/ast.nim index e073ce3e1b..8054e9248c 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1013,6 +1013,10 @@ proc newNode*(kind: TNodeKind): PNode = writeStackTrace() inc gNodeId +proc newTree*(kind: TNodeKind; children: varargs[PNode]): PNode = + result = newNode(kind) + result.sons = @children + proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode = result = newNode(kind) result.intVal = intVal From 2aff71613464a27558c9e90cf85f038c240babb2 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 10 Nov 2015 15:29:53 +0100 Subject: [PATCH 014/211] os.walkDir is available at compile time --- compiler/vmgen.nim | 6 ++-- compiler/vmhooks.nim | 7 ++++ compiler/vmops.nim | 10 +++++- lib/pure/os.nim | 86 ++++++++++++++++++++++++-------------------- 4 files changed, 67 insertions(+), 42 deletions(-) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 97c6a55804..2a16406e7f 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1604,7 +1604,8 @@ proc matches(s: PSym; x: string): bool = var s = s var L = y.len-1 while L >= 0: - if s == nil or y[L].cmpIgnoreStyle(s.name.s) != 0: return false + if s == nil or (y[L].cmpIgnoreStyle(s.name.s) != 0 and y[L] != "*"): + return false s = s.owner dec L result = true @@ -1613,7 +1614,8 @@ proc matches(s: PSym; y: varargs[string]): bool = var s = s var L = y.len-1 while L >= 0: - if s == nil or y[L].cmpIgnoreStyle(s.name.s) != 0: return false + if s == nil or (y[L].cmpIgnoreStyle(s.name.s) != 0 and y[L] != "*"): + return false s = if sfFromGeneric in s.flags: s.owner.owner else: s.owner dec L result = true diff --git a/compiler/vmhooks.nim b/compiler/vmhooks.nim index 576b0565fe..3456e893b6 100644 --- a/compiler/vmhooks.nim +++ b/compiler/vmhooks.nim @@ -55,9 +55,16 @@ template getX(k, field) {.immediate, dirty.} = result = s[i+a.rb+1].field proc getInt*(a: VmArgs; i: Natural): BiggestInt = getX(rkInt, intVal) +proc getBool*(a: VmArgs; i: Natural): bool = getInt(a, i) != 0 proc getFloat*(a: VmArgs; i: Natural): BiggestFloat = getX(rkFloat, floatVal) proc getString*(a: VmArgs; i: Natural): string = doAssert i < a.rc-1 let s = cast[seq[TFullReg]](a.slots) doAssert s[i+a.rb+1].kind == rkNode result = s[i+a.rb+1].node.strVal + +proc getNode*(a: VmArgs; i: Natural): PNode = + doAssert i < a.rc-1 + let s = cast[seq[TFullReg]](a.slots) + doAssert s[i+a.rb+1].kind == rkNode + result = s[i+a.rb+1].node diff --git a/compiler/vmops.nim b/compiler/vmops.nim index e1a0dfef81..e40e05effa 100644 --- a/compiler/vmops.nim +++ b/compiler/vmops.nim @@ -13,7 +13,7 @@ from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin, arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc, floor, ceil, fmod -from os import getEnv, existsEnv, dirExists, fileExists +from os import getEnv, existsEnv, dirExists, fileExists, walkDir template mathop(op) {.immediate, dirty.} = registerCallback(c, "stdlib.math." & astToStr(op), `op Wrapper`) @@ -48,6 +48,12 @@ proc getCurrentExceptionMsgWrapper(a: VmArgs) {.nimcall.} = setResult(a, if a.currentException.isNil: "" else: a.currentException.sons[3].skipColon.strVal) +proc staticWalkDirImpl(path: string, relative: bool): PNode = + result = newNode(nkBracket) + for k, f in walkDir(path, relative): + result.add newTree(nkPar, newIntNode(nkIntLit, k.ord), + newStrNode(nkStrLit, f)) + proc registerAdditionalOps*(c: PCtx) = wrap1f(sqrt) wrap1f(ln) @@ -78,3 +84,5 @@ proc registerAdditionalOps*(c: PCtx) = wrap1s(fileExists) wrap2svoid(writeFile) systemop getCurrentExceptionMsg + registerCallback c, "stdlib.*.staticWalkDir", proc (a: VmArgs) {.nimcall.} = + setResult(a, staticWalkDirImpl(getString(a, 0), getBool(a, 1))) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index c012285630..7c14c46cfe 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -810,6 +810,10 @@ type {.deprecated: [TPathComponent: PathComponent].} +proc staticWalkDir(dir: string; relative: bool): seq[ + tuple[kind: PathComponent, path: string]] = + discard + iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: string] {. tags: [ReadDirEffect].} = ## walks over the directory `dir` and yields for each directory or file in @@ -833,49 +837,53 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: ## dirA/dirC ## dirA/fileA1.txt ## dirA/fileA2.txt - when defined(windows): - var f: WIN32_FIND_DATA - var h = findFirstFile(dir / "*", f) - if h != -1: - while true: - var k = pcFile - if not skipFindData(f): - if (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32: - k = pcDir - if (f.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32: - k = succ(k) - let xx = if relative: extractFilename(getFilename(f)) - else: dir / extractFilename(getFilename(f)) - yield (k, xx) - if findNextFile(h, f) == 0'i32: break - findClose(h) + when nimvm: + for k, v in items(staticWalkDir(dir, relative)): + yield (k, v) else: - var d = opendir(dir) - if d != nil: - while true: - var x = readdir(d) - if x == nil: break - var y = $x.d_name - if y != "." and y != "..": - var s: Stat - if not relative: - y = dir / y + when defined(windows): + var f: WIN32_FIND_DATA + var h = findFirstFile(dir / "*", f) + if h != -1: + while true: var k = pcFile + if not skipFindData(f): + if (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32: + k = pcDir + if (f.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32: + k = succ(k) + let xx = if relative: extractFilename(getFilename(f)) + else: dir / extractFilename(getFilename(f)) + yield (k, xx) + if findNextFile(h, f) == 0'i32: break + findClose(h) + else: + var d = opendir(dir) + if d != nil: + while true: + var x = readdir(d) + if x == nil: break + var y = $x.d_name + if y != "." and y != "..": + var s: Stat + if not relative: + y = dir / y + var k = pcFile - when defined(linux) or defined(macosx) or defined(bsd): - if x.d_type != DT_UNKNOWN: - if x.d_type == DT_DIR: k = pcDir - if x.d_type == DT_LNK: - if dirExists(y): k = pcLinkToDir - else: k = succ(k) - yield (k, y) - continue + when defined(linux) or defined(macosx) or defined(bsd): + if x.d_type != DT_UNKNOWN: + if x.d_type == DT_DIR: k = pcDir + if x.d_type == DT_LNK: + if dirExists(y): k = pcLinkToDir + else: k = succ(k) + yield (k, y) + continue - if lstat(y, s) < 0'i32: break - if S_ISDIR(s.st_mode): k = pcDir - if S_ISLNK(s.st_mode): k = succ(k) - yield (k, y) - discard closedir(d) + if lstat(y, s) < 0'i32: break + if S_ISDIR(s.st_mode): k = pcDir + if S_ISLNK(s.st_mode): k = succ(k) + yield (k, y) + discard closedir(d) iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {. tags: [ReadDirEffect].} = From 7578d580e0167bcfbd77fe7fd1393cfa7a6f1ede Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 10 Nov 2015 15:35:02 +0100 Subject: [PATCH 015/211] added oswalkdir.nim for the JS target --- lib/pure/oswalkdir.nim | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 lib/pure/oswalkdir.nim diff --git a/lib/pure/oswalkdir.nim b/lib/pure/oswalkdir.nim new file mode 100644 index 0000000000..a27b12a78d --- /dev/null +++ b/lib/pure/oswalkdir.nim @@ -0,0 +1,16 @@ + +type + PathComponent* = enum ## Enumeration specifying a path component. + pcFile, ## path refers to a file + pcLinkToFile, ## path refers to a symbolic link to a file + pcDir, ## path refers to a directory + pcLinkToDir ## path refers to a symbolic link to a directory + +proc staticWalkDir(dir: string; relative: bool): seq[ + tuple[kind: PathComponent, path: string]] = + discard + +iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: string] {. + tags: [ReadDirEffect], compiletime.} = + for k, v in staticWalkDir(dir, relative)): + yield (k, v) From b6374f1f68d899e7eed65c553f3e8b71e688c61c Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 10 Nov 2015 15:56:17 +0100 Subject: [PATCH 016/211] fixes newly introduced oswalkdir module --- lib/pure/oswalkdir.nim | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/pure/oswalkdir.nim b/lib/pure/oswalkdir.nim index a27b12a78d..000fe25a39 100644 --- a/lib/pure/oswalkdir.nim +++ b/lib/pure/oswalkdir.nim @@ -1,4 +1,7 @@ +## Compile-time only version for walkDir if you need it at compile-time +## for JavaScript. + type PathComponent* = enum ## Enumeration specifying a path component. pcFile, ## path refers to a file @@ -10,7 +13,15 @@ proc staticWalkDir(dir: string; relative: bool): seq[ tuple[kind: PathComponent, path: string]] = discard -iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: string] {. - tags: [ReadDirEffect], compiletime.} = - for k, v in staticWalkDir(dir, relative)): +iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path: string] = + for k, v in items(staticWalkDir(dir, relative)): yield (k, v) + +iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string = + var stack = @[dir] + while stack.len > 0: + for k,p in walkDir(stack.pop()): + if k in filter: + case k + of pcFile, pcLinkToFile: yield p + of pcDir, pcLinkToDir: stack.add(p) From f9ad735e55d45d6a3ed7e9e7da7abd31065f99ac Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 10 Nov 2015 22:51:03 +0100 Subject: [PATCH 017/211] documented untyped/typed meta-types --- doc/manual/modules.txt | 2 + doc/manual/templates.txt | 118 ++++++++++++++++++++++++++++++--------- 2 files changed, 93 insertions(+), 27 deletions(-) diff --git a/doc/manual/modules.txt b/doc/manual/modules.txt index e6a08b5ce1..ac47d89dd1 100644 --- a/doc/manual/modules.txt +++ b/doc/manual/modules.txt @@ -152,9 +152,11 @@ In module related statements, if any part of the module name / path begins with a number, you may have to quote it in double quotes. In the following example, it would be seen as a literal number '3.0' of type 'float64' if not quoted, if uncertain - quote it: + .. code-block:: nim import "gfx/3d/somemodule" + Scope rules ----------- Identifiers are valid from the point of their declaration until the end of diff --git a/doc/manual/templates.txt b/doc/manual/templates.txt index 092d65ea23..b60fe632ec 100644 --- a/doc/manual/templates.txt +++ b/doc/manual/templates.txt @@ -10,7 +10,7 @@ The syntax to *invoke* a template is the same as calling a procedure. Example: .. code-block:: nim - template `!=` (a, b: expr): expr = + template `!=` (a, b: untyped): untyped = # this definition exists in the System module not (a == b) @@ -23,50 +23,56 @@ templates: | ``a in b`` is transformed into ``contains(b, a)``. | ``notin`` and ``isnot`` have the obvious meanings. -The "types" of templates can be the symbols ``expr`` (stands for *expression*), -``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type +The "types" of templates can be the symbols ``untyped``, +``typed`` or ``typedesc`` (stands for *type description*). These are "meta types", they can only be used in certain -contexts. Real types can be used too; this implies that expressions are -expected. +contexts. Real types can be used too; this implies that ``typed`` expressions +are expected. -Ordinary vs immediate templates -------------------------------- +Typed vs untyped parameters +--------------------------- -There are two different kinds of templates: immediate templates and -ordinary templates. Ordinary templates take part in overloading resolution. As -such their arguments need to be type checked before the template is invoked. -So ordinary templates cannot receive undeclared identifiers: +An ``untyped`` parameter means that symbol lookups and type resolution is not +performed before the expression is passed to the template. This means that for +example *undeclared* identifiers can be passed to the template: .. code-block:: nim - template declareInt(x: expr) = - var x: int - - declareInt(x) # error: unknown identifier: 'x' - -An ``immediate`` template does not participate in overload resolution and so -its arguments are not checked for semantics before invocation. So they can -receive undeclared identifiers: - -.. code-block:: nim - - template declareInt(x: expr) {.immediate.} = + template declareInt(x: untyped) = var x: int declareInt(x) # valid + x = 3 + + +.. code-block:: nim + + template declareInt(x: typed) = + var x: int + + declareInt(x) # invalid, because x has not been declared and so has no type + +A template where every parameter is ``untyped`` is called an `immediate`:idx: +template. For historical reasons templates can be explicitly annotated with +an ``immediate`` pragma and then these templates do not take part in +overloading resolution and the parameters' types are *ignored* by the +compiler. Explicit immediate templates are about to be deprecated in later +versions of the compiler. + +**Note**: For historical reasons ``stmt`` is an alias for ``typed`` and +``expr`` an alias for ``untyped``, but new code should use the newer, +clearer names. Passing a code block to a template ---------------------------------- -If there is a ``stmt`` parameter it should be the last in the template -declaration, because statements are passed to a template via a +You can pass a block of statements as a last parameter to a template via a special ``:`` syntax: .. code-block:: nim - - template withFile(f, fn, mode: expr, actions: stmt): stmt {.immediate.} = + template withFile(f, fn, mode, actions: untyped): untyped = var f: File if open(f, fn, mode): try: @@ -84,6 +90,64 @@ In the example the two ``writeLine`` statements are bound to the ``actions`` parameter. +Usually to pass a block of code to a template the parameter that accepts +the block needs to be of type ``untyped``. Because symbol lookups are then +delayed until template instantiation time: + +.. code-block:: nim + template t(body: typed) = + block: + body + + t: + var i = 1 + echo i + + t: + var i = 2 # fails with 'attempt to redeclare i' + echo i + +The above code fails with the mysterious error message that ``i`` has already +been declared. The reason for this is that the ``var i = ...`` bodies need to +be type-checked before they are passed to the ``body`` parameter and type +checking in Nim implies symbol lookups. For the symbol lookups to succeed +``i`` needs to be added to the current (i.e. outer) scope. After type checking +these additions to the symbol table are not rolled back (for better or worse). +The same code works with ``untyped`` as the passed body is not required to be +type-checked: + +.. code-block:: nim + template t(body: untyped) = + block: + body + + t: + var i = 1 + echo i + + t: + var i = 2 # compiles + echo i + + +Varargs of untyped +------------------ + +In addition to the ``untyped`` meta-type that prevents type checking there is +also ``varargs[untyped]`` so that not even the number of parameters is fixed: + +.. code-block:: nim + template hideIdentifiers(x: varargs[untyped]) = discard + + hideIdentifiers(undeclared1, undeclared2) + +However, since a template cannot iterate over varargs, this feature is +generally much more useful for macros. + +**Note**: For historical reasons ``varargs[expr]`` is not equivalent +to ``varargs[untyped]``. + + Symbol binding in templates --------------------------- From 0cf4e2603f7dee5f29148deaa134f6560b68353b Mon Sep 17 00:00:00 2001 From: JamesP Date: Wed, 11 Nov 2015 08:56:12 +1000 Subject: [PATCH 018/211] Removal of stats procs for openarray (use the RunningStat methodology) --- lib/pure/math.nim | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 91877fcfa9..b0104336e1 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -118,26 +118,6 @@ proc sum*[T](x: openArray[T]): T {.noSideEffect.} = ## If `x` is empty, 0 is returned. for i in items(x): result = result + i -template toFloat(f: float): float = f - -proc mean*[T](x: openArray[T]): float {.noSideEffect.} = - ## Computes the mean of the elements in `x`, which are first converted to floats. - ## If `x` is empty, NaN is returned. - ## ``toFloat(x: T): float`` must be defined. - for i in items(x): result = result + toFloat(i) - result = result / toFloat(len(x)) - -proc variance*[T](x: openArray[T]): float {.noSideEffect.} = - ## Computes the variance of the elements in `x`. - ## If `x` is empty, NaN is returned. - ## ``toFloat(x: T): float`` must be defined. - result = 0.0 - var m = mean(x) - for i in items(x): - var diff = toFloat(i) - m - result = result + diff*diff - result = result / toFloat(len(x)) - proc random*(max: int): int {.benign.} ## Returns a random number in the range 0..max-1. The sequence of ## random number is always the same, unless `randomize` is called From 4cefbc2914c5ca470b1214cc1b77bf263aebd35a Mon Sep 17 00:00:00 2001 From: JamesP Date: Wed, 11 Nov 2015 08:56:51 +1000 Subject: [PATCH 019/211] add comment to identify where RunningStat code resides --- lib/pure/stats.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pure/stats.nim b/lib/pure/stats.nim index 50b5601e5b..5811e141e6 100644 --- a/lib/pure/stats.nim +++ b/lib/pure/stats.nim @@ -51,6 +51,7 @@ type {.deprecated: [TFloatClass: FloatClass, TRunningStat: RunningStat].} +# ----------- RunningStat -------------------------- proc clear*(s: var RunningStat) = ## reset `s` s.n = 0 From 67e62302b4791f68830c32e63b2cee0842e6882f Mon Sep 17 00:00:00 2001 From: Reimer Behrends Date: Wed, 11 Nov 2015 14:19:09 +0100 Subject: [PATCH 020/211] Avoid signed shifts and bit operations for sets. Set operations used "1<>3] &(1U<<((NU)($2)&7U)))!=0)") proc binaryStmtInExcl(p: BProc, e: PNode, d: var TLoc, frmt: string) = var a, b: TLoc @@ -1500,8 +1500,8 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = else: internalError(e.info, "genSetOp()") else: case op - of mIncl: binaryStmtInExcl(p, e, d, "$1[$2/8] |=(1<<($2%8));$n") - of mExcl: binaryStmtInExcl(p, e, d, "$1[$2/8] &= ~(1<<($2%8));$n") + of mIncl: binaryStmtInExcl(p, e, d, "$1[(NU)($2)>>3] |=(1U<<($2&7U));$n") + of mExcl: binaryStmtInExcl(p, e, d, "$1[(NU)($2)>>3]] &= ~(1U<<($2&7U));$n") of mCard: unaryExprChar(p, e, d, "#cardSet($1, " & $size & ')') of mLtSet, mLeSet: getTemp(p, getSysType(tyInt), i) # our counter @@ -1788,11 +1788,11 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, e.sons[i].sons[0], a) initLocExpr(p, e.sons[i].sons[1], b) lineF(p, cpsStmts, "for ($1 = $3; $1 <= $4; $1++) $n" & - "$2[$1/8] |=(1<<($1%8));$n", [rdLoc(idx), rdLoc(d), + "$2[(NU)($1)>>3] |=(1U<<((NU)($1)&7U));$n", [rdLoc(idx), rdLoc(d), rdSetElemLoc(a, e.typ), rdSetElemLoc(b, e.typ)]) else: initLocExpr(p, e.sons[i], a) - lineF(p, cpsStmts, "$1[$2/8] |=(1<<($2%8));$n", + lineF(p, cpsStmts, "$1[(NU)($2)>>3] |=(1U<<((NU)($2)&7U));$n", [rdLoc(d), rdSetElemLoc(a, e.typ)]) else: # small set From 3832ea078511ba3b0575669969563cb6ef1ea368 Mon Sep 17 00:00:00 2001 From: Varriount Date: Wed, 11 Nov 2015 15:18:13 -0500 Subject: [PATCH 021/211] Prevent Exported C procedure collisions Prevents collisions between those C externalized procedures in parseopt and parseopt2. --- lib/pure/parseopt2.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pure/parseopt2.nim b/lib/pure/parseopt2.nim index 73b498fe02..7fd9c60fec 100644 --- a/lib/pure/parseopt2.nim +++ b/lib/pure/parseopt2.nim @@ -70,7 +70,7 @@ when not defined(createNimRtl): ## Initializes option parser from current command line arguments. return initOptParser(commandLineParams()) -proc next*(p: var OptParser) {.rtl, extern: "npo$1".} +proc next*(p: var OptParser) {.rtl, extern: "npo2$1".} proc nextOption(p: var OptParser, token: string, allowEmpty: bool) = for splitchar in [':', '=']: @@ -113,7 +113,7 @@ proc next(p: var OptParser) = p.key = token p.val = "" -proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo$1", deprecated.} = +proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo2$1", deprecated.} = ## Returns part of command line string that has not been parsed yet. ## Do not use - does not correctly handle whitespace. return p.cmd[p.pos..p.cmd.len-1].join(" ") From 52e40995b7adfec8c1a837bed5a84d475f394602 Mon Sep 17 00:00:00 2001 From: JamesP Date: Thu, 12 Nov 2015 06:33:26 +1000 Subject: [PATCH 022/211] added helper procs for standalone calc of stats for array/seq Changed derivation to use runningstats, so there is a single point of truth for the calculations, and provides more stats functions --- lib/pure/stats.nim | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/lib/pure/stats.nim b/lib/pure/stats.nim index 5811e141e6..43d9c35f63 100644 --- a/lib/pure/stats.nim +++ b/lib/pure/stats.nim @@ -166,6 +166,51 @@ proc `+`*(a, b: RunningStat): RunningStat = proc `+=`*(a: var RunningStat, b: RunningStat) {.inline.} = ## add a second RunningStats `b` to `a` a = a + b +# ---------------------- standalone array/seq stats --------------------- +proc mean*[T](x: openArray[T]): float = + var rs: RunningStat + rs.push(x) + result = rs.mean() + +proc variance*[T](x: openArray[T]): float = + var rs: RunningStat + rs.push(x) + result = rs.variance() + +proc varianceS*[T](x: openArray[T]): float = + var rs: RunningStat + rs.push(x) + result = rs.varianceS() + +proc standardDeviation*[T](x: openArray[T]): float = + var rs: RunningStat + rs.push(x) + result = rs.standardDeviation() + +proc standardDeviationS*[T](x: openArray[T]): float = + var rs: RunningStat + rs.push(x) + result = rs.standardDeviationS() + +proc skewness*[T](x: openArray[T]): float = + var rs: RunningStat + rs.push(x) + result = rs.skewness() + +proc skewnessS*[T](x: openArray[T]): float = + var rs: RunningStat + rs.push(x) + result = rs.skewnessS() + +proc kurtosis*[T](x: openArray[T]): float = + var rs: RunningStat + rs.push(x) + result = rs.kurtosis() + +proc kurtosisS*[T](x: openArray[T]): float = + var rs: RunningStat + rs.push(x) + result = rs.kurtosisS() # ---------------------- Running Regression ----------------------------- From 41861711c81f189646222547e938778a2600d91e Mon Sep 17 00:00:00 2001 From: JamesP Date: Thu, 12 Nov 2015 07:03:16 +1000 Subject: [PATCH 023/211] add doco for array/seq helper procs --- lib/pure/stats.nim | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/pure/stats.nim b/lib/pure/stats.nim index 43d9c35f63..ec4cd182bc 100644 --- a/lib/pure/stats.nim +++ b/lib/pure/stats.nim @@ -30,6 +30,21 @@ ## - intercept ## - correlation ## +## Procs have been provided to calculate statistics on arrays and sequences. +## +## However, if more than a single statistical calculation is required, it is more +## efficient to push the data once to the RunningStat object, and +## call the numerous statistical procs for the RunningStat object. +## +## .. code-block:: Nim +## +## var rs: RunningStat +## rs.push(MySeqOfData) +## rs.mean() +## rs.variance() +## rs.skewness() +## rs.kurtosis() + from math import FloatClass, sqrt, pow, round {.push debugger:off .} # the user does not want to trace a part @@ -168,46 +183,55 @@ proc `+=`*(a: var RunningStat, b: RunningStat) {.inline.} = a = a + b # ---------------------- standalone array/seq stats --------------------- proc mean*[T](x: openArray[T]): float = + ## computes the mean of `x` var rs: RunningStat rs.push(x) result = rs.mean() proc variance*[T](x: openArray[T]): float = + ## computes the population variance of `x` var rs: RunningStat rs.push(x) result = rs.variance() proc varianceS*[T](x: openArray[T]): float = + ## computes the sample variance of `x` var rs: RunningStat rs.push(x) result = rs.varianceS() proc standardDeviation*[T](x: openArray[T]): float = + ## computes the population standardDeviation of `x` var rs: RunningStat rs.push(x) result = rs.standardDeviation() proc standardDeviationS*[T](x: openArray[T]): float = + ## computes the sanple standardDeviation of `x` var rs: RunningStat rs.push(x) result = rs.standardDeviationS() proc skewness*[T](x: openArray[T]): float = + ## computes the population skewness of `x` var rs: RunningStat rs.push(x) result = rs.skewness() proc skewnessS*[T](x: openArray[T]): float = + ## computes the sample skewness of `x` var rs: RunningStat rs.push(x) result = rs.skewnessS() proc kurtosis*[T](x: openArray[T]): float = + ## computes the population kurtosis of `x` var rs: RunningStat rs.push(x) result = rs.kurtosis() proc kurtosisS*[T](x: openArray[T]): float = + ## computes the sample kurtosis of `x` var rs: RunningStat rs.push(x) result = rs.kurtosisS() From e8bc19f79c23d3bda57e2a9d1a68e653656b80a9 Mon Sep 17 00:00:00 2001 From: jyelon Date: Wed, 11 Nov 2015 21:55:33 -0500 Subject: [PATCH 024/211] Add 'auto-decoration' to nimGetProcAddr Maintainers of win32 DLLs can opt to provide libraries with 'decorated' function names (Google "stdcall name decoration"). To pull a function pointer out of one of these DLLs, you have to pass a decorated name to getProcAddress. This is painful for the authors of NIM DLL wrappers - they have to pass manually-decorated strings to "importc", but only on win32. This commit adds auto-decoration to nimGetProcAddress. This function will probe the DLL for the undecorated name, and if that fails, it will automatically add decoration and try again. That way, the author of the wrapper doesn't have to deal with it. --- lib/system/dyncalls.nim | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim index 908aa551b2..4043c87141 100644 --- a/lib/system/dyncalls.nim +++ b/lib/system/dyncalls.nim @@ -105,7 +105,12 @@ elif defined(windows) or defined(dos): proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr = result = getProcAddress(cast[THINSTANCE](lib), name) - if result == nil: procAddrError(name) + if result != nil: return + for i in countup(0, 50): + var decorated = "_" & $name & "@" & $(i * 4) + result = getProcAddress(cast[THINSTANCE](lib), cstring(decorated)) + if result != nil: return + procAddrError(name) else: {.error: "no implementation for dyncalls".} From edb495a6b36cd3a943a00a00652bf7a71b831e6f Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 18 Nov 2015 11:18:56 +0100 Subject: [PATCH 025/211] fixes a critical error handling bug for nimsuggest --- compiler/lexer.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/lexer.nim b/compiler/lexer.nim index cea42ad1e1..9a69ede3e5 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -662,6 +662,7 @@ proc getString(L: var TLexer, tok: var TToken, rawMode: bool) = L.lineNumber = line lexMessagePos(L, errClosingTripleQuoteExpected, L.lineStart) L.lineNumber = line2 + L.bufpos = pos break else: add(tok.literal, buf[pos]) From aad4ed776b56144a993bcb104d887ff69c9d3177 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 18 Nov 2015 11:19:43 +0100 Subject: [PATCH 026/211] allows macros to access documentation comments --- compiler/vm.nim | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/vm.nim b/compiler/vm.nim index 495b0c7475..afc0034521 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1190,6 +1190,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = createStr regs[ra] let a = regs[rb].node if a.kind in {nkStrLit..nkTripleStrLit}: regs[ra].node.strVal = a.strVal + elif a.kind == nkCommentStmt: regs[ra].node.strVal = a.comment else: stackTrace(c, tos, pc, errFieldXNotFound, "strVal") of opcSlurp: decodeB(rkNode) From 698b1fc954fe7e8f2dd6869f6aa1a11bbe0c2ef5 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 18 Nov 2015 12:32:46 +0100 Subject: [PATCH 027/211] fixes #3550 --- compiler/cgmeth.nim | 7 ++++++- todo.txt | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim index 3c2c51b76a..de26a43904 100644 --- a/compiler/cgmeth.nim +++ b/compiler/cgmeth.nim @@ -18,7 +18,12 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode = var source = skipTypes(n.typ, abstractPtrs) if (source.kind == tyObject) and (dest.kind == tyObject): var diff = inheritanceDiff(dest, source) - if diff == high(int): internalError(n.info, "cgmeth.genConv") + if diff == high(int): + # see bug #3550 which triggers it. XXX This is a hack but I don't know yet + # how the real fix looks like: + localError(n.info, "there is no subtype relation between " & + typeToString(d) & " and " & typeToString(n.typ)) + #internalError(n.info, "cgmeth.genConv") if diff < 0: result = newNodeIT(nkObjUpConv, n.info, d) addSon(result, n) diff --git a/todo.txt b/todo.txt index 62ffdbd8ad..afc3776a6d 100644 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,7 @@ essential for 1.0 ================= -- document special cased varargs[untyped] and varargs[typed] +- introduce newSeqOfCap(10) - The remaining bugs of the lambda lifting pass that is responsible to enable closures and closure iterators need to be fixed. - ``concept`` needs to be refined, a nice name for the feature is not enough. From 528cf3eae4eead9b91527f8d79523a4e55936753 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 18 Nov 2015 13:32:16 +0100 Subject: [PATCH 028/211] better error handling for bug #3550 --- compiler/cgmeth.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim index de26a43904..ade202dc1a 100644 --- a/compiler/cgmeth.nim +++ b/compiler/cgmeth.nim @@ -23,8 +23,8 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode = # how the real fix looks like: localError(n.info, "there is no subtype relation between " & typeToString(d) & " and " & typeToString(n.typ)) - #internalError(n.info, "cgmeth.genConv") - if diff < 0: + result = n + elif diff < 0: result = newNodeIT(nkObjUpConv, n.info, d) addSon(result, n) if downcast: internalError(n.info, "cgmeth.genConv: no upcast allowed") From 2f07ac785f1f61b3f5b51a4d4476627108d93831 Mon Sep 17 00:00:00 2001 From: Araq Date: Wed, 18 Nov 2015 13:32:29 +0100 Subject: [PATCH 029/211] website updated --- tools/website.tmpl | 25 ++----------------------- web/documentation.txt | 17 ++++++++++------- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/tools/website.tmpl b/tools/website.tmpl index 1f882510c7..d2fcb0afdd 100644 --- a/tools/website.tmpl +++ b/tools/website.tmpl @@ -49,26 +49,7 @@ # if currentTab == "index":
-
- - First Nim workshop in Ukraine! - -
-
-

Why should I be excited?

- Nim is the only language that leverages automated proof technology to perform a disjoint check for your parallel code. Working on disjoint data means no locking is required and yet data races are impossible:

-
-parallel:
-  var i = 0
-  while i <= a.high:
-    spawn f(a[i])
-    spawn f(a[i+1])
-    # ERROR: cannot prove a[i] is disjoint from a[i+1]
-    # BUT: replace 'i += 1' with 'i += 2' and the code compiles!
-    i += 1
-
-
-
+

Nim is simple..

@@ -102,7 +83,7 @@ p.greet() # or greet(p)
 
-
+

C FFI is easy in Nim..

@@ -138,8 +119,6 @@ runForever()
         
-
-
# end