Skip to content

Commit

Permalink
Merge pull request #1 from nim-lang/devel
Browse files Browse the repository at this point in the history
upstream
  • Loading branch information
Daniil Yarancev authored Jan 7, 2018
2 parents ccf99fa + e23ea64 commit fb44c52
Show file tree
Hide file tree
Showing 819 changed files with 89,401 additions and 42,046 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,7 @@ dist/
# Private directories and files (IDEs)
.*/
~*

# testament cruft
testresults/
test.txt
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,7 @@ script:
- tests/testament/tester --pedantic all -d:nimCoroutines
- ./koch web
- ./koch csource
- ./koch nimsuggest
# - nim c -r nimsuggest/tester
- ( ! grep -F '.. code-block' -l -r --include '*.html' --exclude contributing.html --exclude docgen.html --exclude tut2.html )
- ( ! grep -F '..code-block' -l -r --include '*.html' --exclude contributing.html --exclude docgen.html --exclude tut2.html )
190 changes: 185 additions & 5 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,191 @@

### Changes affecting backwards compatibility

- Removed basic2d/basic3d out of the stdlib and into Nimble packages.
These packages deprecated however, use the ``glm``, ``arraymancer``, ``neo``
or another package.

- Arrays of char cannot be converted to ``cstring`` anymore, pointers to
arrays of char can! This means ``$`` for arrays can finally exist
in ``system.nim`` and do the right thing.
- JSON: Deprecated `getBVal`, `getFNum`, and `getNum` in favour to
`getBool`, `getFloat`, `getBiggestInt`. Also `getInt` procedure was added.
- ``echo`` now works with strings that contain ``\0`` (the binary zero is not
shown) and ``nil`` strings are equal to empty strings.
- JSON: Deprecated `getBVal`, `getFNum`, and `getNum` in favour to
`getBool`, `getFloat`, `getBiggestInt`. Also `getInt` procedure was added.
- `reExtended` is no longer default for the `re` constructor in the `re`
module.
- The overloading rules changed slightly so that constrained generics are
preferred over unconstrained generics. (Bug #6526)
- It is now possible to forward declare object types so that mutually
recursive types can be created across module boundaries. See
[package level objects](https://nim-lang.org/docs/manual.html#package-level-objects)
for more information.
- The **unary** ``<`` is now deprecated, for ``.. <`` use ``..<`` for other usages
use the ``pred`` proc.
- We changed how array accesses "from backwards" like ``a[^1]`` or ``a[0..^1]`` are
implemented. These are now implemented purely in ``system.nim`` without compiler
support. There is a new "heterogenous" slice type ``system.HSlice`` that takes 2
generic parameters which can be ``BackwardsIndex`` indices. ``BackwardsIndex`` is
produced by ``system.^``.
This means if you overload ``[]`` or ``[]=`` you need to ensure they also work
with ``system.BackwardsIndex`` (if applicable for the accessors).
- ``mod`` and bitwise ``and`` do not produce ``range`` subtypes anymore. This
turned out to be more harmful than helpful and the language is simpler
without this special typing rule.
- Added ``algorithm.rotateLeft``.
- ``rationals.toRational`` now uses an algorithm based on continued fractions.
This means its results are more precise and it can't run into an infinite loop
anymore.
- Added ``typetraits.$`` as an alias for ``typetraits.name``.
- ``os.getEnv`` now takes an optional ``default`` parameter that tells ``getEnv``
what to return if the environment variable does not exist.
- Bodies of ``for`` loops now get their own scope:

```nim
# now compiles:
for i in 0..4:
let i = i + 1
echo i
```

- The parsing rules of ``if`` expressions were changed so that multiple
statements are allowed in the branches. We found few code examples that
now fail because of this change, but here is one:

```nim
t[ti] = if exp_negative: '-' else: '+'; inc(ti)
```

This now needs to be written as:

```nim
t[ti] = (if exp_negative: '-' else: '+'); inc(ti)
```

- To make Nim even more robust the system iterators ``..`` and ``countup``
now only accept a single generic type ``T``. This means the following code
doesn't die with an "out of range" error anymore:

```nim
var b = 5.Natural
var a = -5
for i in a..b:
echo i
```

- ``formatFloat``/``formatBiggestFloat`` now support formatting floats with zero
precision digits. The previous ``precision = 0`` behavior (default formatting)
is now available via ``precision = -1``.
- The ``nim doc`` command is now an alias for ``nim doc2``, the second version of
the documentation generator. The old version 1 can still be accessed
via the new ``nim doc0`` command.
- Added ``system.getStackTraceEntries`` that allows you to access the stack
trace in a structured manner without string parsing.
- Added ``sequtils.mapLiterals`` for easier construction of array and tuple
literals.
- Added ``parseutils.parseSaturatedNatural``.
- ``atomic`` and ``generic`` are no longer keywords in Nim. ``generic`` used to be
an alias for ``concept``, ``atomic`` was not used for anything.
- Moved from stdlib into Nimble packages:
- [``basic2d``](https://github.com/nim-lang/basic2d)
_deprecated: use ``glm``, ``arraymancer``, ``neo``, or another package instead_
- [``basic3d``](https://github.com/nim-lang/basic3d)
_deprecated: use ``glm``, ``arraymancer``, ``neo``, or another package instead_
- [``gentabs``](https://github.com/lcrees/gentabs)
- [``libuv``](https://github.com/lcrees/libuv)
- [``numeric``](https://github.com/lcrees/polynumeric)
- [``poly``](https://github.com/lcrees/polynumeric)
- [``pdcurses``](https://github.com/lcrees/pdcurses)
- [``romans``](https://github.com/lcrees/romans)

- Added ``system.runnableExamples`` to make examples in Nim's documentation easier
to write and test. The examples are tested as the last step of
``nim doc``.
- Nim's ``rst2html`` command now supports the testing of code snippets via an RST
extension that we called ``:test:``::

```rst
.. code-block:: nim
:test:
# shows how the 'if' statement works
if true: echo "yes"
```
- The ``[]`` proc for strings now raises an ``IndexError`` exception when
the specified slice is out of bounds. See issue
[#6223](https://github.com/nim-lang/Nim/issues/6223) for more details.
You can use ``substr(str, start, finish)`` to get the old behaviour back,
see [this commit](https://github.com/nim-lang/nimbot/commit/98cc031a27ea89947daa7f0bb536bcf86462941f) for an example.
- ``strutils.split`` and ``strutils.rsplit`` with an empty string and a
separator now returns that empty string.
See issue [#4377](https://github.com/nim-lang/Nim/issues/4377).
- The experimental overloading of the dot ``.`` operators now take
an ``untyped``` parameter as the field name, it used to be
a ``static[string]``. You can use ``when defined(nimNewDot)`` to make
your code work with both old and new Nim versions.
See [special-operators](https://nim-lang.org/docs/manual.html#special-operators)
for more information.
- Added ``macros.unpackVarargs``.
- The memory manager now uses a variant of the TLSF algorithm that has much
better memory fragmentation behaviour. According
to [http://www.gii.upv.es/tlsf/](http://www.gii.upv.es/tlsf/) the maximum
fragmentation measured is lower than 25%. As a nice bonus ``alloc`` and
``dealloc`` became O(1) operations.
- The behavior of ``$`` has been changed for all standard library collections. The
collection-to-string implementations now perform proper quoting and escaping of
strings and chars.
- The ``random`` procs in ``random.nim`` have all been deprecated. Instead use
the new ``rand`` procs. The module now exports the state of the random
number generator as type ``Rand`` so multiple threads can easily use their
own random number generators that do not require locking. For more information
about this rename see issue [#6934](https://github.com/nim-lang/Nim/issues/6934)
- The compiler is now more consistent in its treatment of ambiguous symbols:
Types that shadow procs and vice versa are marked as ambiguous (bug #6693).
- ``yield`` (or ``await`` which is mapped to ``yield``) never worked reliably
in an array, seq or object constructor and is now prevented at compile-time.
- For string formatting / interpolation a new module
called [strformat](https://nim-lang.org/docs/strformat.html) has been added
to the stdlib.
- codegenDecl pragma now works for the JavaScript backend. It returns an empty string for
function return type placeholders.
- Asynchronous programming for the JavaScript backend using the `asyncjs` module.
- Extra semantic checks for procs with noreturn pragma: return type is not allowed,
statements after call to noreturn procs are no longer allowed.
- Noreturn proc calls and raising exceptions branches are now skipped during common type
deduction in if and case expressions. The following code snippets now compile:
```nim
import strutils
let str = "Y"
let a = case str:
of "Y": true
of "N": false
else: raise newException(ValueError, "Invalid boolean")
let b = case str:
of nil, "": raise newException(ValueError, "Invalid boolean")
elif str.startsWith("Y"): true
elif str.startsWith("N"): false
else: false
let c = if str == "Y": true
elif str == "N": false
else:
echo "invalid bool"
quit("this is the end")
```
- Proc [toCountTable](https://nim-lang.org/docs/tables.html#toCountTable,openArray[A]) now produces a `CountTable` with values correspoding to the number of occurrences of the key in the input. It used to produce a table with all values set to `1`.

Counting occurrences in a sequence used to be:

```nim
let mySeq = @[1, 2, 1, 3, 1, 4]
var myCounter = initCountTable[int]()
for item in mySeq:
myCounter.inc item
```

Now, you can simply do:

```nim
let
mySeq = @[1, 2, 1, 3, 1, 4]
myCounter = mySeq.toCountTable()
```

- Added support for casting between integers of same bitsize in VM (compile time and nimscript).
This allow to among other things to reinterpret signed integers as unsigned.
8 changes: 7 additions & 1 deletion compiler/aliases.nim
Original file line number Diff line number Diff line change
Expand Up @@ -179,5 +179,11 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
result = isPartOf(a[0], b)
if result == arNo: result = arMaybe
else: discard
of nkObjConstr:
result = arNo
for i in 1..<b.len:
let res = isPartOf(a, b[i][1])
if res != arNo:
result = res
if res == arYes: break
else: discard

59 changes: 37 additions & 22 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ type
nkTripleStrLit, # a triple string literal """
nkNilLit, # the nil literal
# end of atoms
nkMetaNode_Obsolete, # difficult to explain; represents itself
# (used for macros)
nkComesFrom, # "comes from" template/macro information for
# better stack trace generation
nkDotCall, # used to temporarily flag a nkCall node;
# this is used
# for transforming ``s.len`` to ``len(s)``
Expand Down Expand Up @@ -639,7 +639,8 @@ type
mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl,
mNHint, mNWarning, mNError,
mInstantiationInfo, mGetTypeInfo, mNGenSym,
mNimvm, mIntDefine, mStrDefine
mNimvm, mIntDefine, mStrDefine, mRunnableExamples,
mException

# things that we can evaluate safely at compile time, even if not asked for it:
const
Expand Down Expand Up @@ -744,6 +745,8 @@ type
OnUnknown, # location is unknown (stack, heap or static)
OnStatic, # in a static section
OnStack, # location is on hardware stack
OnStackShadowDup, # location is on the stack but also replicated
# on the shadow stack
OnHeap # location is on heap or global
# (reference counting needed)
TLocFlags* = set[TLocFlag]
Expand All @@ -753,6 +756,7 @@ type
flags*: TLocFlags # location's flags
lode*: PNode # Node where the location came from; can be faked
r*: Rope # rope value of location (code generators)
dup*: Rope # duplicated location for precise stack scans

# ---------------- end of backend information ------------------------------

Expand Down Expand Up @@ -1017,16 +1021,11 @@ proc add*(father, son: PNode) =

type Indexable = PNode | PType

template `[]`*(n: Indexable, i: int): Indexable =
n.sons[i]
template `[]`*(n: Indexable, i: int): Indexable = n.sons[i]
template `[]=`*(n: Indexable, i: int; x: Indexable) = n.sons[i] = x

template `-|`*(b, s: untyped): untyped =
(if b >= 0: b else: s.len + b)

# son access operators with support for negative indices
template `{}`*(n: Indexable, i: int): untyped = n[i -| n]
template `{}=`*(n: Indexable, i: int, s: Indexable) =
n.sons[i -| n] = s
template `[]`*(n: Indexable, i: BackwardsIndex): Indexable = n[n.len - i.int]
template `[]=`*(n: Indexable, i: BackwardsIndex; x: Indexable) = n[n.len - i.int] = x

when defined(useNodeIds):
const nodeIdToDebug* = -1 # 299750 # 300761 #300863 # 300879
Expand All @@ -1036,9 +1035,9 @@ proc newNode*(kind: TNodeKind): PNode =
new(result)
result.kind = kind
#result.info = UnknownLineInfo() inlined:
result.info.fileIndex = int32(- 1)
result.info.col = int16(- 1)
result.info.line = int16(- 1)
result.info.fileIndex = int32(-1)
result.info.col = int16(-1)
result.info.line = int16(-1)
when defined(useNodeIds):
result.id = gNodeId
if result.id == nodeIdToDebug:
Expand Down Expand Up @@ -1392,6 +1391,14 @@ proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
result = t
while result.kind in kinds: result = lastSon(result)

proc skipTypes*(t: PType, kinds: TTypeKinds; maxIters: int): PType =
result = t
var i = maxIters
while result.kind in kinds:
result = lastSon(result)
dec i
if i == 0: return nil

proc skipTypesOrNil*(t: PType, kinds: TTypeKinds): PType =
## same as skipTypes but handles 'nil'
result = t
Expand All @@ -1405,7 +1412,7 @@ proc isGCedMem*(t: PType): bool {.inline.} =

proc propagateToOwner*(owner, elem: PType) =
const HaveTheirOwnEmpty = {tySequence, tyOpt, tySet, tyPtr, tyRef, tyProc}
owner.flags = owner.flags + (elem.flags * {tfHasMeta})
owner.flags = owner.flags + (elem.flags * {tfHasMeta, tfTriggersCompileTime})
if tfNotNil in elem.flags:
if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvocation}:
owner.flags.incl tfNotNil
Expand All @@ -1420,15 +1427,12 @@ proc propagateToOwner*(owner, elem: PType) =
owner.flags.incl tfHasMeta

if tfHasAsgn in elem.flags:
let o2 = elem.skipTypes({tyGenericInst, tyAlias})
let o2 = owner.skipTypes({tyGenericInst, tyAlias})
if o2.kind in {tyTuple, tyObject, tyArray,
tySequence, tyOpt, tySet, tyDistinct}:
o2.flags.incl tfHasAsgn
owner.flags.incl tfHasAsgn

if tfTriggersCompileTime in elem.flags:
owner.flags.incl tfTriggersCompileTime

if owner.kind notin {tyProc, tyGenericInst, tyGenericBody,
tyGenericInvocation, tyPtr}:
let elemB = elem.skipTypes({tyGenericInst, tyAlias})
Expand All @@ -1442,6 +1446,10 @@ proc rawAddSon*(father, son: PType) =
add(father.sons, son)
if not son.isNil: propagateToOwner(father, son)

proc rawAddSonNoPropagationOfTypeFlags*(father, son: PType) =
if isNil(father.sons): father.sons = @[]
add(father.sons, son)

proc addSonNilAllowed*(father, son: PNode) =
if isNil(father.sons): father.sons = @[]
add(father.sons, son)
Expand Down Expand Up @@ -1604,10 +1612,10 @@ proc hasPattern*(s: PSym): bool {.inline.} =
result = isRoutine(s) and s.ast.sons[patternPos].kind != nkEmpty

iterator items*(n: PNode): PNode =
for i in 0.. <n.safeLen: yield n.sons[i]
for i in 0..<n.safeLen: yield n.sons[i]

iterator pairs*(n: PNode): tuple[i: int, n: PNode] =
for i in 0.. <n.len: yield (i, n.sons[i])
for i in 0..<n.len: yield (i, n.sons[i])

proc isAtom*(n: PNode): bool {.inline.} =
result = n.kind >= nkNone and n.kind <= nkNilLit
Expand Down Expand Up @@ -1663,3 +1671,10 @@ when false:
if n.isNil: return true
for i in 0 ..< n.safeLen:
if n[i].containsNil: return true

template hasDestructor*(t: PType): bool = tfHasAsgn in t.flags
template incompleteType*(t: PType): bool =
t.sym != nil and {sfForward, sfNoForward} * t.sym.flags == {sfForward}

template typeCompleted*(s: PSym) =
incl s.flags, sfNoForward
6 changes: 3 additions & 3 deletions compiler/canonicalizer.nim
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ proc hashTree(c: var MD5Context, n: PNode) =
of nkStrLit..nkTripleStrLit:
c &= n.strVal
else:
for i in 0.. <n.len: hashTree(c, n.sons[i])
for i in 0..<n.len: hashTree(c, n.sons[i])

proc hashType(c: var MD5Context, t: PType) =
# modelled after 'typeToString'
Expand Down Expand Up @@ -151,13 +151,13 @@ proc hashType(c: var MD5Context, t: PType) =
c.hashType(t.sons[0])
of tyProc:
c &= (if tfIterator in t.flags: "iterator " else: "proc ")
for i in 0.. <t.len: c.hashType(t.sons[i])
for i in 0..<t.len: c.hashType(t.sons[i])
md5Update(c, cast[cstring](addr(t.callConv)), 1)

if tfNoSideEffect in t.flags: c &= ".noSideEffect"
if tfThread in t.flags: c &= ".thread"
else:
for i in 0.. <t.len: c.hashType(t.sons[i])
for i in 0..<t.len: c.hashType(t.sons[i])
if tfNotNil in t.flags: c &= "not nil"

proc canonConst(n: PNode): TUid =
Expand Down
Loading

0 comments on commit fb44c52

Please sign in to comment.