minor documentation updates

This commit is contained in:
Araq
2015-02-16 02:56:40 +01:00
parent 442dc30922
commit eaf00dd1fb
4 changed files with 115 additions and 3 deletions

89
compiler/forloops.nim Normal file
View File

@@ -0,0 +1,89 @@
#
#
# The Nim Compiler
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module implements for loop detection for better C code generation.
import ast, astalgo
const
someCmp = {mEqI, mEqI64, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
mEqUntracedRef, mLeI, mLeI64, mLeF64, mLeU, mLeU64, mLeEnum,
mLeCh, mLeB, mLePtr, mLtI, mLtI64, mLtF64, mLtU, mLtU64, mLtEnum,
mLtCh, mLtB, mLtPtr}
proc isCounter(s: PSym): bool {.inline.} =
s.kind in {skResult, skVar, skLet, skTemp} and
{sfGlobal, sfAddrTaken} * s.flags == {}
proc isCall(n: PNode): bool {.inline.} =
n.kind in nkCallKinds and n[0].kind == nkSym
proc fromSystem(op: PSym): bool = sfSystemModule in getModule(op).flags
proc getCounter(lastStmt: PNode): PSym =
if lastStmt.isCall:
let op = lastStmt.sym
if op.magic in {mDec, mInc} or
((op.name.s == "+=" or op.name.s == "-=") and op.fromSystem):
if op[1].kind == nkSym and isCounter(op[1].sym):
result = op[1].sym
proc counterInTree(n, loop: PNode; counter: PSym): bool =
# prune the search tree: within the loop the counter may be used:
if n == loop: return
case n.kind
of nkSym:
if n.sym == counter: return true
of nkVarSection, nkLetSection:
# definitions are fine!
for it in n:
if counterInTree(it.lastSon): return true
else:
for i in 0 .. <safeLen(n):
if counterInTree(n[i], loop, counter): return true
proc copyExcept(n: PNode, x, dest: PNode) =
if x == n: return
if n.kind in {nkStmtList, nkStmtListExpr}:
for i in 0 .. <n.len: copyExcept(n[i], x, dest)
else:
dest.add n
type
ForLoop* = object
counter*: PSym
init*, cond*, increment*, body*: PNode
proc extractForLoop*(loop, fullTree: PNode): ForLoop =
## returns 'counter == nil' if the while loop 'n' is not a for loop:
assert loop.kind == nkWhileStmt
let cond == loop[0]
if not cond.isCall: return
if cond[0].sym.magic notin someCmp: return
var lastStmt = loop[1]
while lastStmt.kind in {nkStmtList, nkStmtListExpr}:
lastStmt = lastStmt.lastSon
let counter = getCounter(lastStmt)
if counter.isNil or counter.ast.isNil: return
template `=~`(a, b): expr = a.kind == nkSym and a.sym == b
if cond[1] =~ counter or cond[2] =~ counter:
# ok, now check 'counter' is not used *after* the loop
if counterInTree(fullTree, loop, counter): return
# ok, success, fill in the fields:
result.counter = counter
result.init = counter.ast
result.cond = cond
result.increment = lastStmt
result.body = newNodeI(nkStmtList, loop[1].info)
copyExcept(loop[1], lastStmt, result.body)

View File

@@ -569,7 +569,7 @@ language for object types:
type
StdMap {.importcpp: "std::map", header: "<map>".} [K, V] = object
proc `[]=`[K, V](this: var StdMap[K, V]; key: K; val: V) {.
importcpp: "#[#] = #".}
importcpp: "#[#] = #", header: "<map>".}
var x: StdMap[cint, cdouble]
x[6] = 91.4

View File

@@ -749,7 +749,8 @@ Forward declarations
--------------------
Every variable, procedure, etc. needs to be declared before it can be used.
(The reason for this is compilation efficiency.)
(The reason for this is that it is non-trivial to do better than that in a
language that supports meta programming as extensively as Nim does.)
However, this cannot be done for mutually recursive procedures:
.. code-block:: nim
@@ -767,7 +768,7 @@ introduced to the compiler before it is completely defined. The syntax for
such a forward declaration is simple: just omit the ``=`` and the
procedure's body.
Later versions of the language may get rid of the need for forward
Later versions of the language will weaken the requirements for forward
declarations.
The example also shows that a proc's body can consist of a single expression

22
tests/closure/tfib50.nim Normal file
View File

@@ -0,0 +1,22 @@
discard """
output: "20365011074"
"""
import tables
proc memoize(f: proc (a: int): int): proc (a: int): int =
var previous = initTable[int, int]()
return proc(i: int): int =
if not previous.hasKey i:
previous[i] = f(i)
return previous[i]
var fib: proc(a: int): int
fib = memoize(proc (i: int): int =
if i == 0 or i == 1:
return 1
return fib(i-1) + fib(i-2)
)
echo fib(50)