mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-12 07:45:35 +00:00
Merge branch 'devel' of git://github.com/Araq/Nimrod
This commit is contained in:
@@ -1376,7 +1376,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
getTemp(p, getSysType(tyInt), i) # our counter
|
||||
initLocExpr(p, e.sons[1], a)
|
||||
initLocExpr(p, e.sons[2], b)
|
||||
if d.k == locNone: getTemp(p, a.t, d)
|
||||
if d.k == locNone: getTemp(p, getSysType(tyBool), d)
|
||||
lineF(p, cpsStmts, lookupOpr[op],
|
||||
[rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)])
|
||||
of mEqSet:
|
||||
|
||||
@@ -216,10 +216,12 @@ proc genx(c: PCtx; n: PNode; flags: TGenFlags = {}): TRegister =
|
||||
internalAssert tmp >= 0
|
||||
result = TRegister(tmp)
|
||||
|
||||
proc clearDest(n: PNode; dest: var TDest) {.inline.} =
|
||||
proc clearDest(c: PCtx; n: PNode; dest: var TDest) {.inline.} =
|
||||
# stmt is different from 'void' in meta programming contexts.
|
||||
# So we only set dest to -1 if 'void':
|
||||
if n.typ.isNil or n.typ.kind == tyEmpty: dest = -1
|
||||
if dest >= 0 and (n.typ.isNil or n.typ.kind == tyEmpty):
|
||||
c.freeTemp(dest)
|
||||
dest = -1
|
||||
|
||||
proc isNotOpr(n: PNode): bool =
|
||||
n.kind in nkCallKinds and n.sons[0].kind == nkSym and
|
||||
@@ -259,7 +261,7 @@ proc genWhile(c: PCtx; n: PNode) =
|
||||
proc genBlock(c: PCtx; n: PNode; dest: var TDest) =
|
||||
withBlock(n.sons[0].sym):
|
||||
c.gen(n.sons[1], dest)
|
||||
clearDest(n, dest)
|
||||
c.clearDest(n, dest)
|
||||
|
||||
proc genBreak(c: PCtx; n: PNode) =
|
||||
let L1 = c.xjmp(n, opcJmp)
|
||||
@@ -297,14 +299,16 @@ proc genIf(c: PCtx, n: PNode; dest: var TDest) =
|
||||
else:
|
||||
c.gen(it.sons[0], tmp)
|
||||
elsePos = c.xjmp(it.sons[0], opcFJmp, tmp) # if false
|
||||
c.clearDest(n, dest)
|
||||
c.gen(it.sons[1], dest) # then part
|
||||
if i < sonsLen(n)-1:
|
||||
endings.add(c.xjmp(it.sons[1], opcJmp, 0))
|
||||
c.patch(elsePos)
|
||||
else:
|
||||
c.clearDest(n, dest)
|
||||
c.gen(it.sons[0], dest)
|
||||
for endPos in endings: c.patch(endPos)
|
||||
clearDest(n, dest)
|
||||
c.clearDest(n, dest)
|
||||
|
||||
proc genAndOr(c: PCtx; n: PNode; opc: TOpcode; dest: var TDest) =
|
||||
# asgn dest, a
|
||||
@@ -385,8 +389,8 @@ proc genCase(c: PCtx; n: PNode; dest: var TDest) =
|
||||
if i < sonsLen(n)-1:
|
||||
endings.add(c.xjmp(it.lastSon, opcJmp, 0))
|
||||
c.patch(elsePos)
|
||||
c.clearDest(n, dest)
|
||||
for endPos in endings: c.patch(endPos)
|
||||
clearDest(n, dest)
|
||||
|
||||
proc genType(c: PCtx; typ: PType): int =
|
||||
for i, t in c.types:
|
||||
@@ -400,6 +404,7 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
|
||||
var endings: seq[TPosition] = @[]
|
||||
let elsePos = c.xjmp(n, opcTry, 0)
|
||||
c.gen(n.sons[0], dest)
|
||||
c.clearDest(n, dest)
|
||||
c.patch(elsePos)
|
||||
for i in 1 .. <n.len:
|
||||
let it = n.sons[i]
|
||||
@@ -415,6 +420,7 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
|
||||
# general except section:
|
||||
c.gABx(it, opcExcept, 0, 0)
|
||||
c.gen(it.lastSon, dest)
|
||||
c.clearDest(n, dest)
|
||||
if i < sonsLen(n)-1:
|
||||
endings.add(c.xjmp(it, opcJmp, 0))
|
||||
c.patch(endExcept)
|
||||
@@ -425,8 +431,8 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
|
||||
c.gABx(fin, opcFinally, 0, 0)
|
||||
if fin.kind == nkFinally:
|
||||
c.gen(fin.sons[0], dest)
|
||||
c.clearDest(n, dest)
|
||||
c.gABx(fin, opcFinallyEnd, 0, 0)
|
||||
clearDest(n, dest)
|
||||
|
||||
proc genRaise(c: PCtx; n: PNode) =
|
||||
let dest = genx(c, n.sons[0])
|
||||
@@ -860,7 +866,6 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||
of mNGenSym: genBinaryABC(c, n, dest, opcGenSym)
|
||||
of mMinI, mMaxI, mMinI64, mMaxI64, mAbsF64, mMinF64, mMaxF64, mAbsI, mAbsI64:
|
||||
c.genCall(n, dest)
|
||||
clearDest(n, dest)
|
||||
of mExpandToAst:
|
||||
if n.len != 2:
|
||||
globalError(n.info, errGenerated, "expandToAst requires 1 argument")
|
||||
@@ -1281,7 +1286,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
genMagic(c, n, dest)
|
||||
else:
|
||||
genCall(c, n, dest)
|
||||
clearDest(n, dest)
|
||||
clearDest(c, n, dest)
|
||||
of nkCharLit..nkInt64Lit:
|
||||
if isInt16Lit(n):
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
|
||||
106
doc/manual.txt
106
doc/manual.txt
@@ -1701,11 +1701,11 @@ algorithm returns true:
|
||||
result = isOrdinal(t) or t.kind in {float, float32, float64}
|
||||
|
||||
proc isExplicitlyConvertible(a, b: PType): bool =
|
||||
result = false
|
||||
if isImplicitlyConvertible(a, b): return true
|
||||
if typeEqualsOrDistinct(a, b): return true
|
||||
if isIntegralType(a) and isIntegralType(b): return true
|
||||
if isSubtype(a, b) or isSubtype(b, a): return true
|
||||
return false
|
||||
|
||||
The convertible relation can be relaxed by a user-defined type
|
||||
`converter`:idx:.
|
||||
@@ -1774,7 +1774,7 @@ Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc p(x, y: int): int =
|
||||
return x + y
|
||||
result = x + y
|
||||
|
||||
discard p(3, 4) # discard the return value of `p`
|
||||
|
||||
@@ -1789,7 +1789,7 @@ been declared with the `discardable`:idx: pragma:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc p(x, y: int): int {.discardable.} =
|
||||
return x + y
|
||||
result = x + y
|
||||
|
||||
p(3, 4) # now valid
|
||||
|
||||
@@ -2440,7 +2440,7 @@ A procedure cannot modify its parameters (unless the parameters have the type
|
||||
.. code-block:: nimrod
|
||||
proc `$` (x: int): string =
|
||||
# converts an integer to a string; this is a prefix operator.
|
||||
return intToStr(x)
|
||||
result = intToStr(x)
|
||||
|
||||
Operators with one parameter are prefix operators, operators with two
|
||||
parameters are infix operators. (However, the parser distinguishes these from
|
||||
@@ -2454,7 +2454,7 @@ notation. (Thus an operator can have more than two parameters):
|
||||
.. code-block:: nimrod
|
||||
proc `*+` (a, b, c: int): int =
|
||||
# Multiply and add
|
||||
return a * b + c
|
||||
result = a * b + c
|
||||
|
||||
assert `*+`(3, 4, 6) == `*`(a, `+`(b, c))
|
||||
|
||||
@@ -2500,7 +2500,7 @@ different; for this a special setter syntax is needed:
|
||||
|
||||
proc host*(s: TSocket): int {.inline.} =
|
||||
## getter of hostAddr
|
||||
return s.FHost
|
||||
s.FHost
|
||||
|
||||
var
|
||||
s: TSocket
|
||||
@@ -2650,11 +2650,12 @@ return values. This can be done in a cleaner way by returning a tuple:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc divmod(a, b: int): tuple[res, remainder: int] =
|
||||
return (a div b, a mod b)
|
||||
(a div b, a mod b)
|
||||
|
||||
var t = divmod(8, 5)
|
||||
|
||||
assert t.res == 1
|
||||
assert t.remainder = 3
|
||||
assert t.remainder == 3
|
||||
|
||||
One can use `tuple unpacking`:idx: to access the tuple's fields:
|
||||
|
||||
@@ -2726,7 +2727,7 @@ dispatch.
|
||||
|
||||
method eval(e: ref TPlusExpr): int =
|
||||
# watch out: relies on dynamic binding
|
||||
return eval(e.a) + eval(e.b)
|
||||
result = eval(e.a) + eval(e.b)
|
||||
|
||||
proc newLit(x: int): ref TLiteral =
|
||||
new(result)
|
||||
@@ -2925,7 +2926,7 @@ parameters of an outer factory proc:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc mycount(a, b: int): iterator (): int =
|
||||
return iterator (): int =
|
||||
result = iterator (): int =
|
||||
var x = a
|
||||
while x <= b:
|
||||
yield x
|
||||
@@ -3375,9 +3376,9 @@ module to illustrate this:
|
||||
## requires `x` and `y` to be of the same tuple type
|
||||
## generic ``==`` operator for tuples that is lifted from the components
|
||||
## of `x` and `y`.
|
||||
result = true
|
||||
for a, b in fields(x, y):
|
||||
if a != b: return false
|
||||
return true
|
||||
if a != b: result = false
|
||||
|
||||
Alternatively, the ``distinct`` type modifier can be applied to the type class
|
||||
to allow each param matching the type class to bind to a different type.
|
||||
@@ -3999,9 +4000,9 @@ predicate:
|
||||
|
||||
proc re(pattern: semistatic[string]): TRegEx =
|
||||
when isStatic(pattern):
|
||||
return precompiledRegex(pattern)
|
||||
result = precompiledRegex(pattern)
|
||||
else:
|
||||
return compile(pattern)
|
||||
result = compile(pattern)
|
||||
|
||||
Static params can also appear in the signatures of generic types:
|
||||
|
||||
@@ -4508,7 +4509,7 @@ This is best illustrated by an example:
|
||||
proc p*(x: A.T1): A.T1 =
|
||||
# this works because the compiler has already
|
||||
# added T1 to A's interface symbol table
|
||||
return x + 1
|
||||
result = x + 1
|
||||
|
||||
|
||||
Import statement
|
||||
@@ -5136,51 +5137,54 @@ Example:
|
||||
.. code-block:: nimrod
|
||||
{.deadCodeElim: on.}
|
||||
|
||||
NoForward pragma
|
||||
----------------
|
||||
The `noforward`:idx: pragma can be used to turn on and off a special compilation
|
||||
mode that to large extent eliminates the need for forward declarations. In this
|
||||
mode, the proc definitions may appear out of order and the compiler will postpone
|
||||
their semantic analysis and compilation until it actually needs to generate code
|
||||
using the definitions. In this regard, this mode is similar to the modus operandi
|
||||
of dynamic scripting languages, where the function calls are not resolved until
|
||||
the code is executed. Here is the detailed algorithm taken by the compiler:
|
||||
|
||||
1. When a callable symbol is first encountered, the compiler will only note the
|
||||
symbol callable name and it will add it to the appropriate overload set in the
|
||||
current scope. At this step, it won't try to resolve any of the type expressions
|
||||
used in the signature of the symbol (so they can refer to other not yet defined
|
||||
symbols).
|
||||
..
|
||||
NoForward pragma
|
||||
----------------
|
||||
The `noforward`:idx: pragma can be used to turn on and off a special compilation
|
||||
mode that to large extent eliminates the need for forward declarations. In this
|
||||
mode, the proc definitions may appear out of order and the compiler will postpone
|
||||
their semantic analysis and compilation until it actually needs to generate code
|
||||
using the definitions. In this regard, this mode is similar to the modus operandi
|
||||
of dynamic scripting languages, where the function calls are not resolved until
|
||||
the code is executed. Here is the detailed algorithm taken by the compiler:
|
||||
|
||||
2. When a top level call is encountered (usually at the very end of the module),
|
||||
the compiler will try to determine the actual types of all of the symbols in the
|
||||
matching overload set. This is a potentially recursive process as the signatures
|
||||
of the symbols may include other call expressions, whoose types will be resolved
|
||||
at this point too.
|
||||
1. When a callable symbol is first encountered, the compiler will only note the
|
||||
symbol callable name and it will add it to the appropriate overload set in the
|
||||
current scope. At this step, it won't try to resolve any of the type expressions
|
||||
used in the signature of the symbol (so they can refer to other not yet defined
|
||||
symbols).
|
||||
|
||||
3. Finally, after the best overload is picked, the compiler will start compiling
|
||||
the body of the respective symbol. This in turn will lead the compiler to discover
|
||||
more call expresions that need to be resolved and steps 2 and 3 will be repeated
|
||||
as necessary.
|
||||
2. When a top level call is encountered (usually at the very end of the module),
|
||||
the compiler will try to determine the actual types of all of the symbols in the
|
||||
matching overload set. This is a potentially recursive process as the signatures
|
||||
of the symbols may include other call expressions, whoose types will be resolved
|
||||
at this point too.
|
||||
|
||||
Please note that if a callable symbol is never used in this scenario, its body
|
||||
will never be compiled. This is the default behavior leading to best compilation
|
||||
times, but if exhaustive compilation of all definitions is required, using
|
||||
``nimrod check`` provides this option as well.
|
||||
3. Finally, after the best overload is picked, the compiler will start compiling
|
||||
the body of the respective symbol. This in turn will lead the compiler to discover
|
||||
more call expresions that need to be resolved and steps 2 and 3 will be repeated
|
||||
as necessary.
|
||||
|
||||
Example:
|
||||
Please note that if a callable symbol is never used in this scenario, its body
|
||||
will never be compiled. This is the default behavior leading to best compilation
|
||||
times, but if exhaustive compilation of all definitions is required, using
|
||||
``nimrod check`` provides this option as well.
|
||||
|
||||
.. code-block:: nimrod
|
||||
Example:
|
||||
|
||||
{.noforward: on.}
|
||||
.. code-block:: nimrod
|
||||
|
||||
proc foo(x: int) =
|
||||
bar x
|
||||
{.noforward: on.}
|
||||
|
||||
proc bar(x: int) =
|
||||
echo x
|
||||
proc foo(x: int) =
|
||||
bar x
|
||||
|
||||
proc bar(x: int) =
|
||||
echo x
|
||||
|
||||
foo(10)
|
||||
|
||||
foo(10)
|
||||
|
||||
Pragma pragma
|
||||
-------------
|
||||
@@ -5199,7 +5203,7 @@ Example:
|
||||
{.pragma: rtl, importc, dynlib: "client.dll", cdecl.}
|
||||
|
||||
proc p*(a, b: int): int {.rtl.} =
|
||||
return a+b
|
||||
result = a+b
|
||||
|
||||
In the example a new pragma named ``rtl`` is introduced that either imports
|
||||
a symbol from a dynamic library or exports the symbol for dynamic library
|
||||
|
||||
10
doc/tut1.txt
10
doc/tut1.txt
@@ -690,8 +690,8 @@ Nimrod provides the ability to overload procedures similar to C++:
|
||||
.. code-block:: nimrod
|
||||
proc toString(x: int): string = ...
|
||||
proc toString(x: bool): string =
|
||||
if x: return "true"
|
||||
else: return "false"
|
||||
if x: result = "true"
|
||||
else: result = "false"
|
||||
|
||||
echo(toString(13)) # calls the toString(x: int) proc
|
||||
echo(toString(true)) # calls the toString(x: bool) proc
|
||||
@@ -1569,7 +1569,7 @@ This is best illustrated by an example:
|
||||
proc p*(x: A.T1): A.T1 =
|
||||
# this works because the compiler has already
|
||||
# added T1 to A's interface symbol table
|
||||
return x + 1
|
||||
result = x + 1
|
||||
|
||||
|
||||
A symbol of a module *can* be *qualified* with the ``module.symbol`` syntax. If
|
||||
@@ -1600,11 +1600,11 @@ rules apply:
|
||||
|
||||
.. code-block:: nimrod
|
||||
# Module A
|
||||
proc x*(a: int): string = return $a
|
||||
proc x*(a: int): string = result = $a
|
||||
|
||||
.. code-block:: nimrod
|
||||
# Module B
|
||||
proc x*(a: string): string = return $a
|
||||
proc x*(a: string): string = result = $a
|
||||
|
||||
.. code-block:: nimrod
|
||||
# Module C
|
||||
|
||||
@@ -126,7 +126,7 @@ The syntax for type conversions is ``destination_type(expression_to_convert)``
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc getID(x: TPerson): int =
|
||||
return TStudent(x).id
|
||||
TStudent(x).id
|
||||
|
||||
The ``EInvalidObjectConversion`` exception is raised if ``x`` is not a
|
||||
``TStudent``.
|
||||
@@ -238,7 +238,7 @@ is needed:
|
||||
|
||||
proc host*(s: TSocket): int {.inline.} =
|
||||
## getter of hostAddr
|
||||
return s.FHost
|
||||
s.FHost
|
||||
|
||||
var
|
||||
s: TSocket
|
||||
|
||||
Reference in New Issue
Block a user