Merge branch 'devel' of git://github.com/Araq/Nimrod

This commit is contained in:
Miguel
2014-02-10 05:16:39 +04:00
6 changed files with 76 additions and 67 deletions

View File

@@ -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:

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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