Subject: CVS commit: pkgsrc/lang/nim
From: Ryo ONODERA
Date: 2021-11-21 17:40:02
Message id: 20211121164002.DE9F8FAEC@cvs.NetBSD.org

Log Message:
nim: Update to 1.6.0

Changelog:
Nim version 1.6 is now officially released!

A year in the making, 1.6 is the latest stable release and by far the largest
yet. We're proud of what we --- the core team and dedicated volunteers --- have
accomplished with this milestone:

  * 1667 PRs merged (1760 commits)
  * 893 issues closed
  * 15 new stdlib modules
  * new features in more than 40 stdlib modules, including major improvements
    to 10 commonly used modules
  * documentation and minor improvements to 170 modules, including 312 new
    runnable examples
  * 280 new nimble packages

Nim made its first entry in TIOBE index in 2017 at position 129, last year it
entered the top-100, and for 2 months the top-50 (link). We hope this release
will reinforce this trend, building on Nim's core strengths: a practical,
compiled systems programming language offering C++-like performance and
portability, Python-like syntax, Lisp-like flexibility, strong C, C++, JS,
Python interop, and best-in-class metaprogramming.

This release includes improvements in the following areas:

  * new language features (iterable[T], user-defined literals, private imports,
    strict effects, dot-like operators, block arguments with optional
    parameters)
  * new compiler features (nim --eval:cmd, custom nimscript extensions,
    customizable compiler messages)
  * major improvements to --gc:arc and --gc:orc
  * correctness and performance of integer and float parsing and rendering in
    all backends
  * significant improvements in error messages, showing useful context
  * documentation generation logic and documentation, in particular
    runnableExamples now works in more contexts
  * JS, VM and nimscript backend are more consistent with the C backend,
    allowing more modules to work with those backends, including the imports
    from std/prelude; the test suite now standardizes on testing stdlib modules
    on each major backend (C, JS, VM)
  * support for Apple silicon/M1, 32-bit RISC-V, armv8l, CROSSOS, improved
    support for NodeJS backend
  * major improvements to the following modules: system, math, random, json,
    jsonutils, os, typetraits, wrapnils, lists, hashes including performance
    improvements
  * deprecated a number of error prone or redundant features

Why use Nim?

  * One language to rule them all: from shell scripting to web frontend and
    backend, scientific computing, deep learning, blockchain client, gamedev,
    embedded, see also some companies using Nim.
  * Concise, readable and convenient: echo "hello world" is a 1-liner.
  * Small binaries: echo "hello world" generates a 73K binary (or 5K with
    further options), optimized for embedded devices (Go: 2MB, Rust: 377K, C++:
    56K) [1].
  * Fast compile times: a full compiler rebuild takes ~12s (Rust: 15min, gcc:
    30min+, clang: 1hr+, Go: 90s) [2].
  * Native performance: see Web Frameworks Benchmark, ray tracing, primes.
  * No need for makefiles, cmake, configure or other build scripts, thanks to
    compile-time function evaluation (CTFE) and dependency tracking [3].
  * Target any platform with a C compiler: Android and iOS, embedded systems,
    micro-controllers, WASM, Nintendo Switch, Game Boy Advance.
  * Zero-overhead interop lets you reuse code in C, C++ (including templates,
    C++ STL), JS, Objective-C, Python (via nimpy).
  * Built-in documentation generator that understands Nim code and runnable
    examples that stay in sync.

Last but not least, macros let you manipulate/generate code at compile time
instead of relying on code generators, enabling writing DSLs and language
extensions in user code. Typical examples include implementing Python-like
f-strings, optional chaining, command line generators, React-like Single Page
Apps, protobuf serialization and binding generators.

Installing Nim 1.6

We recommend everyone to upgrade to 1.6:

New users

Check out if your package manager already ships version 1.6 or install it as
described here.

Note: earlier this year researchers spotted malware written in Nim programming
language which supposedly led to antivirus vendors falsely tagging all software
written in Nim as a potential threat, including the Nim compiler, nimble (Nim'
s package manager) and so on (core Nim tooling is written entirely in Nim).
This has been an ongoing issue ever since - if you have any issues related to
this, please report the Nim compiler and associated tooling as false detection
to the respective antivirus vendors.

Existing users

If you have installed a previous version of Nim using choosenim, getting Nim
1.6 is as easy as:

choosenim update self
choosenim update stable

If you don't have choosenim, you can follow the same install link as above.

Building from source

git clone https://github.com/nim-lang/Nim
cd Nim
sh build_all.sh

The last command can be re-run after pulling new commits. Note that the
csources repo used was changed to csources_v1, the new setup is designed to be
forward and backward compatible.

Building from a CI setup

We now have bash APIs to (re-)build Nim from source which hide implementation
details, for example: . ci/funs.sh && nimBuildCsourcesIfNeeded. This can be
useful for CI when alternatives (using nightly builds or a Docker image) are
not suitable; in fact all the existing CI pipelines have been refactored to use
this, see #17815.

Contributors to Nim 1.6

Many thanks to our recurring and new contributors. Nim is a community driven
collaborative effort that welcomes all contributions, big or small.

Backward compatibility and preview flags

Starting with this release, we've introduced preview flags of the form
-d:nimPreviewX (e.g. -d:nimPreviewFloatRoundtrip), which allow users to opt-in
to new stdlib/compiler behavior that will likely become the default in the next
or a future release. These staging flags aim to minimize backward compatibility
issues.

We also introduced opt-out flags of the form -d:nimLegacyX, e.g.
-d:nimLegacyCopyFile, for cases where the default was changed to the new
behavior. For a transition period, these flags can be used to get the old
behavior.

Here's the list of these flags introduced in this release, refer to the text
below for explanations:

  * -d:nimLegacyCopyFile
  * -d:nimLegacyJsRound
  * -d:nimLegacyMacrosCollapseSymChoice
  * -d:nimLegacyParseQueryStrict
  * -d:nimLegacyRandomInitRand
  * -d:nimLegacyReprWithNewline
  * -d:nimLegacySigpipeHandler
  * -d:nimLegacyTypeMismatch
  * -d:nimPreviewDotLikeOps
  * -d:nimPreviewFloatRoundtrip
  * -d:nimPreviewHashRef
  * -d:nimPreviewJsonutilsHoleyEnum

Major new features

With so many new features, pinpointing the most salient ones is a subjective
exercise, but here are a select few:

iterable[T]

The iterable[T] type class was added to match called iterators, which solves a
number of long-standing issues related to iterators. Example:

iterator iota(n: int): int =
  for i in 0..<n: yield i

# previously, you'd need `untyped`, which caused other problems such as lack
# of type inference, overloading issues, and MCS.
template sumOld(a: untyped): untyped = # no type inference possible
  var result: typeof(block:(for ai in a: ai))
  for ai in a: result += ai
  result

assert sumOld(iota(3)) == 0 + 1 + 2

# now, you can write:
template sum[T](a: iterable[T]): T =
  # `template sum(a: iterable): auto =` would also be possible
  var result: T
  for ai in a: result += ai
  result

assert sum(iota(3)) == 0 + 1 + 2 # or `iota(3).sum`

In particular iterable arguments can now be used with the method call syntax.
For example:

import std/[sequtils, os]
echo walkFiles("*").toSeq # now works

See PR #17196 for additional details.

Strict effects

The effect system was refined and there is a new .effectsOf annotation that
does explicitly what was previously done implicitly. See the manual for more
details. To write code that is portable with older Nim versions, use this
idiom:

when defined(nimHasEffectsOf):
  {.experimental: "strictEffects".}
else:
  {.pragma: effectsOf.}

proc mysort(s: seq; cmp: proc(a, b: T): int) {.effectsOf: cmp.}

To enable the new effect system, compile with --experimental:strictEffects. See
also #18777 and RFC #408.

Private imports and private field access

A new import syntax import foo {.all.} now allows importing all symbols (public
or private) from foo. This can be useful for testing purposes or for more
flexibility in project organization.

Example:

from system {.all.} as system2 import nil
echo system2.ThisIsSystem # ThisIsSystem is private in `system`
import os {.all.} # weirdTarget is private in `os`
echo weirdTarget # or `os.weirdTarget`

Added a new module std/importutils, and an API privateAccess, which allows
access to private fields for an object type in the current scope.

Example:

import times
from std/importutils import privateAccess
block:
  let t = now()
  # echo t.monthdayZero # Error: undeclared field: 'monthdayZero' for type \ 
times.DateTime
  privateAccess(typeof(t)) # enables private access in this scope
  echo t.monthdayZero # ok

See PR #17706 for additional details.

nim --eval:cmd

Added nim --eval:cmd to evaluate a command directly, e.g.: nim --eval:"echo \ 
1".
It defaults to e (nimscript) but can also work with other commands, e.g.:

find . | nim r --eval:'import strutils; for a in stdin.lines: echo a.toUpper'

# use as a calculator:
nim --eval:'echo 3.1 / (1.2+7)'
# explore a module's APIs, including private symbols:
nim --eval:'import os {.all.}; echo weirdTarget'
# use a custom backend:
nim r -b:js --eval:"import std/jsbigints; echo 2'big ** 64'big"

See PR #15687 for more details.

Round-trip float to string

system.addFloat and system.$ now can produce string representations of floating
point numbers that are minimal in size and possess round-trip and correct
rounding guarantees (via the Dragonbox algorithm). This currently has to be
enabled via -d:nimPreviewFloatRoundtrip. It is expected that this behavior
becomes the new default in upcoming versions, as with other nimPreviewX define
flags.

Example:

from math import round
let a = round(9.779999999999999, 2)
assert a == 9.78
echo a # with `-d:nimPreviewFloatRoundtrip`: 9.78, like in python3 (instead of  \ 
9.779999999999999)

New std/jsbigints module

Provides arbitrary precision integers for the JS target. See PR #16409.
Example:

import std/jsbigints
assert 2'big ** 65'big == 36893488147419103232'big
echo 0xdeadbeef'big shl 4'big # 59774856944n

New std/sysrand module

Cryptographically secure pseudorandom number generator, allows generating
random numbers from a secure source provided by the operating system. Example:

import std/sysrand
assert urandom(1234) != urandom(1234) # unlikely to fail in practice

See PR #16459.

New module: std/tempfiles

Allows creating temporary files and directories, see PR #17361 and followups.

import std/tempfiles
let tmpPath = genTempPath("prefix", "suffix.log", \ 
"/tmp/")
# tmpPath looks like: /tmp/prefixpmW1P2KLsuffix.log

let dir = createTempDir("tmpprefix_", "_end")
# created dir looks like: getTempDir() / "tmpprefix_YEl9VuVj_end"

let (cfile, path) = createTempFile("tmpprefix_", "_end.tmp")
# path looks like: getTempDir() / "tmpprefix_FDCIRZA0_end.tmp"
cfile.write "foo"
cfile.setFilePos 0
assert readAll(cfile) == "foo"
close cfile
assert readFile(path) == "foo"

User-defined literals

Custom numeric literals (e.g. -128'bignum) are now supported. Additionally, the
unary minus in -1 is now part of the integer literal, i.e. it is now parsed as
a single token. This implies that edge cases like -128'i8 finally work
correctly. Example:

func `'big`*(num: cstring): JsBigInt {.importjs: "BigInt(#)".}
assert 0xffffffffffffffff'big == (1'big shl 64'big) - 1'big

Dot-like operators

With -d:nimPreviewDotLikeOps, dot-like operators (operators starting with .,
but not with ..) now have the same precedence as ., so that a.?b.c is now
parsed as (a.?b).c instead of a.?(b.c). A warning is generated when a dot-like
operator is used without -d:nimPreviewDotLikeOps.

An important use case is to enable dynamic fields without affecting the
built-in . operator, e.g. for std/jsffi, std/json, pkg/nimpy. Example:

import std/json
template `.?`(a: JsonNode, b: untyped{ident}): JsonNode =
  a[astToStr(b)]
let j = %*{"a1": {"a2": 10}}
assert j.?a1.?a2.getInt == 10

Block arguments now support optional parameters

This solves a major pain point for routines accepting block parameters, see PR
#18631 for details:

template fn(a = 1, b = 2, body) = discard
fn(1, 2): # already works
  bar
fn(a = 1): # now works
  bar

Likewise with multiple block arguments via do:

template fn(a = 1, b = 2, body1, body2) = discard
fn(a = 1): # now works
  bar1
do:
  bar2

Other features

For full changelog, see here.

Footnotes

Tested on a 2.3 GHz 8-Core Intel Core i9, 2019 macOS 11.5 with 64GB RAM.

  * [1] command used: nim c -d:danger. The binary size can be further reduced
    to 49K with stripping (--passL:-s) and link-time optimization
    (--passC:-flto). Statically linking against musl brings it under 5K - see
    here for more details.
  * [2] commands used:
      + for Nim: nim c --forceBuild compiler/nim
      + for Rust: ./x.py build, details
      + for GCC: see 1 2
      + for Clang: details
      + for Go: ./make.bash
  * [3] a separate nimscript file can be used if needed to execute code at
    compile time before compiling the main program but it's in the same
    language

Files:
RevisionActionfile
1.23modifypkgsrc/lang/nim/Makefile
1.14modifypkgsrc/lang/nim/PLIST
1.20modifypkgsrc/lang/nim/distinfo