mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-16 22:11:18 +00:00
Merge branch 'master' of github.com:Araq/Nimrod
This commit is contained in:
@@ -2232,7 +2232,6 @@ Type casts
|
||||
----------
|
||||
Example:
|
||||
|
||||
|
||||
.. code-block:: nimrod
|
||||
cast[int](x)
|
||||
|
||||
@@ -2243,11 +2242,27 @@ only needed for low-level programming and are inherently unsafe.
|
||||
|
||||
The addr operator
|
||||
-----------------
|
||||
The `addr` operator returns the address of an l-value. If the
|
||||
type of the location is ``T``, the `addr` operator result is
|
||||
of the type ``ptr T``. Taking the address of an object that resides
|
||||
on the stack is **unsafe**, as the pointer may live longer than the
|
||||
object on the stack and can thus reference a non-existing object.
|
||||
The `addr`:idx: operator returns the address of an l-value. If the type of the
|
||||
location is ``T``, the `addr` operator result is of the type ``ptr T``. An
|
||||
address is always an untraced reference. Taking the address of an object that
|
||||
resides on the stack is **unsafe**, as the pointer may live longer than the
|
||||
object on the stack and can thus reference a non-existing object. You can get
|
||||
the address of variables, but you can't use it on variables declared through
|
||||
``let`` statements:
|
||||
|
||||
.. code-block:: nimrod
|
||||
|
||||
let t1 = "Hello"
|
||||
var
|
||||
t2 = t1
|
||||
t3 : pointer = addr(t2)
|
||||
echo repr(addr(t2))
|
||||
# --> ref 0x7fff6b71b670 --> 0x10bb81050"Hello"
|
||||
echo cast[ptr string](t3)[]
|
||||
# --> Hello
|
||||
# The following line doesn't compile:
|
||||
echo repr(addr(t1))
|
||||
# Error: expression has no address
|
||||
|
||||
|
||||
Procedures
|
||||
@@ -2682,16 +2697,14 @@ In contrast to that, a `closure iterator`:idx: can be passed around:
|
||||
invoke(count0)
|
||||
invoke(count2)
|
||||
|
||||
|
||||
Closure iterators have other restrictions than inline iterators:
|
||||
|
||||
1.) ``yield`` in a closure iterator can not occur in a ``try`` statement.
|
||||
2.) For now, a closure iterator cannot be evaluated at compile time.
|
||||
3.) ``return`` is allowed in a closure iterator (but rarely useful).
|
||||
4.) Since closure iterators can be used as a collaborative tasking
|
||||
system, ``void`` is a valid return type for them.
|
||||
5.) Both inline and closure iterators cannot be recursive.
|
||||
|
||||
1. ``yield`` in a closure iterator can not occur in a ``try`` statement.
|
||||
2. For now, a closure iterator cannot be evaluated at compile time.
|
||||
3. ``return`` is allowed in a closure iterator (but rarely useful).
|
||||
4. Since closure iterators can be used as a collaborative tasking
|
||||
system, ``void`` is a valid return type for them.
|
||||
5. Both inline and closure iterators cannot be recursive.
|
||||
|
||||
Iterators that are neither marked ``{.closure.}`` nor ``{.inline.}`` explicitly
|
||||
default to being inline, but that this may change in future versions of the
|
||||
@@ -2843,6 +2856,23 @@ in an implicit try block:
|
||||
finally: close(f)
|
||||
...
|
||||
|
||||
The ``except`` statement has a limitation in this form: you can't specify the
|
||||
type of the exception, you have to catch everything. Also, if you want to use
|
||||
both ``finally`` and ``except`` you need to reverse the usual sequence of the
|
||||
statements. Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc test() =
|
||||
raise newException(E_base, "Hey ho")
|
||||
|
||||
proc tester() =
|
||||
finally: echo "3. Finally block"
|
||||
except: echo "2. Except block"
|
||||
echo "1. Pre exception"
|
||||
test()
|
||||
echo "4. Post exception"
|
||||
# --> 1, 2, 3 is printed, 4 is never reached
|
||||
|
||||
|
||||
Raise statement
|
||||
---------------
|
||||
|
||||
41
doc/tut1.txt
41
doc/tut1.txt
@@ -349,6 +349,7 @@ provides. The example uses the built-in ``countup`` iterator:
|
||||
echo("Counting to ten: ")
|
||||
for i in countup(1, 10):
|
||||
echo($i)
|
||||
# --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines
|
||||
|
||||
The built-in ``$`` operator turns an integer (``int``) and many other types
|
||||
into a string. The variable ``i`` is implicitly declared by the ``for`` loop
|
||||
@@ -362,6 +363,7 @@ the same:
|
||||
while i <= 10:
|
||||
echo($i)
|
||||
inc(i) # increment i by 1
|
||||
# --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines
|
||||
|
||||
Counting down can be achieved as easily (but is less often needed):
|
||||
|
||||
@@ -369,6 +371,7 @@ Counting down can be achieved as easily (but is less often needed):
|
||||
echo("Counting down from 10 to 1: ")
|
||||
for i in countdown(10, 1):
|
||||
echo($i)
|
||||
# --> Outputs 10 9 8 7 6 5 4 3 2 1 on different lines
|
||||
|
||||
Since counting up occurs so often in programs, Nimrod also has a ``..`` iterator
|
||||
that does the same:
|
||||
@@ -1202,6 +1205,28 @@ raised) for performance reasons. Thus one should use empty sequences ``@[]``
|
||||
rather than ``nil`` as the *empty* value. But ``@[]`` creates a sequence
|
||||
object on the heap, so there is a trade-off to be made here.
|
||||
|
||||
The ``for`` statement can be used with one or two variables when used with a
|
||||
sequence. When you use the one variable form, the variable will hold the value
|
||||
provided by the sequence. The ``for`` statement is looping over the results
|
||||
from the ``items()`` iterator from the `system <system.html>`_ module. But if
|
||||
you use the two variable form, the first variable will hold the index position
|
||||
and the second variable will hold the value. Here the ``for`` statement is
|
||||
looping over the results from the ``pairs()`` iterator from the `system
|
||||
<system.html>`_ module. Examples:
|
||||
|
||||
.. code-block:: nimrod
|
||||
for i in @[3, 4, 5]:
|
||||
echo($i)
|
||||
# --> 3
|
||||
# --> 4
|
||||
# --> 5
|
||||
|
||||
for i, value in @[3, 4, 5]:
|
||||
echo("index: ", $i, ", value:", $value)
|
||||
# --> index: 0, value:3
|
||||
# --> index: 1, value:4
|
||||
# --> index: 2, value:5
|
||||
|
||||
|
||||
Open arrays
|
||||
-----------
|
||||
@@ -1303,14 +1328,10 @@ untraced references are *unsafe*. However for certain low-level operations
|
||||
Traced references are declared with the **ref** keyword, untraced references
|
||||
are declared with the **ptr** keyword.
|
||||
|
||||
The empty ``[]`` subscript notation can be used to *derefer* a reference,
|
||||
meaning to retrieve the item the reference points to. The ``addr`` operator
|
||||
returns the address of an item. An address is always an untraced reference:
|
||||
``addr`` is an *unsafe* feature.
|
||||
|
||||
The ``.`` (access a tuple/object field operator)
|
||||
and ``[]`` (array/string/sequence index operator) operators perform implicit
|
||||
dereferencing operations for reference types:
|
||||
The empty ``[]`` subscript notation can be used to *derefer* a reference,
|
||||
meaning to retrieve the item the reference points to. The ``.`` (access a
|
||||
tuple/object field operator) and ``[]`` (array/string/sequence index operator)
|
||||
operators perform implicit dereferencing operations for reference types:
|
||||
|
||||
.. code-block:: nimrod
|
||||
|
||||
@@ -1327,8 +1348,8 @@ dereferencing operations for reference types:
|
||||
|
||||
To allocate a new traced object, the built-in procedure ``new`` has to be used.
|
||||
To deal with untraced memory, the procedures ``alloc``, ``dealloc`` and
|
||||
``realloc`` can be used. The documentation of the system module contains
|
||||
further information.
|
||||
``realloc`` can be used. The documentation of the `system <system.html>`_
|
||||
module contains further information.
|
||||
|
||||
If a reference points to *nothing*, it has the value ``nil``.
|
||||
|
||||
|
||||
16
doc/tut2.txt
16
doc/tut2.txt
@@ -218,7 +218,7 @@ So "pure object oriented" code is easy to write:
|
||||
import strutils
|
||||
|
||||
stdout.writeln("Give a list of numbers (separated by spaces): ")
|
||||
stdout.write(stdin.readLine.split.each(parseInt).max.`$`)
|
||||
stdout.write(stdin.readLine.split.map(parseInt).max.`$`)
|
||||
stdout.writeln(" is the maximum!")
|
||||
|
||||
|
||||
@@ -433,6 +433,20 @@ handled, it is propagated through the call stack. This means that often
|
||||
the rest of the procedure - that is not within a ``finally`` clause -
|
||||
is not executed (if an exception occurs).
|
||||
|
||||
If you need to *access* the actual exception object or message inside an
|
||||
``except`` branch you can use the getCurrentException() and
|
||||
getCurrentExceptionMsg() procs from the `system <system.html>`_ module.
|
||||
Example:
|
||||
|
||||
.. code-block:: nimrod
|
||||
try:
|
||||
doSomethingHere()
|
||||
except:
|
||||
let
|
||||
e = getCurrentException()
|
||||
msg = getCurrentExceptionMsg()
|
||||
echo "Got exception ", repr(e), " with message ", msg
|
||||
|
||||
|
||||
Exception hierarchy
|
||||
-------------------
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
import strutils
|
||||
|
||||
echo "Give a list of numbers (separated by spaces): "
|
||||
stdin.readLine.split.each(parseInt).max.`$`.echo(" is the maximum!")
|
||||
stdin.readLine.split.map(parseInt).max.`$`.echo(" is the maximum!")
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
## This module implements operations for the built-in `seq`:idx: type which
|
||||
## were inspired by functional programming languages. If you are looking for
|
||||
## the typical `map` function which applies a function to every element in a
|
||||
## sequence, it already exists as the `each` proc in the `system
|
||||
## <system.html>`_ module in both mutable and immutable styles.
|
||||
## sequence, it already exists in the `system <system.html>`_ module in both
|
||||
## mutable and immutable styles.
|
||||
##
|
||||
## Also, for functional style programming you may want to pass `anonymous procs
|
||||
## <manual.html#anonymous-procs>`_ to procs like ``filter`` to reduce typing.
|
||||
|
||||
@@ -141,6 +141,11 @@ proc randomize*()
|
||||
## number, i.e. a tickcount. Note: Does nothing for the ECMAScript target,
|
||||
## as ECMAScript does not support this.
|
||||
|
||||
proc randomize*(seed: int)
|
||||
## initializes the random number generator with a specific seed.
|
||||
## Note: Does nothing for the ECMAScript target,
|
||||
## as ECMAScript does not support this.
|
||||
|
||||
when not defined(ECMAScript):
|
||||
proc sqrt*(x: float): float {.importc: "sqrt", header: "<math.h>".}
|
||||
## computes the square root of `x`.
|
||||
@@ -190,15 +195,17 @@ when not defined(ECMAScript):
|
||||
proc rand(): cint {.importc: "rand", nodecl.}
|
||||
|
||||
when not defined(windows):
|
||||
proc srand48(seed: cint) {.importc: "srand48", nodecl.}
|
||||
proc srand48(seed: clong) {.importc: "srand48", nodecl.}
|
||||
proc drand48(): float {.importc: "drand48", nodecl.}
|
||||
proc random(max: float): float =
|
||||
result = drand48() * max
|
||||
|
||||
proc randomize() =
|
||||
let x = gettime(nil)
|
||||
srand(x)
|
||||
when defined(srand48): srand48(x)
|
||||
randomize(gettime(nil))
|
||||
|
||||
proc randomize(seed: int) =
|
||||
srand(cint(seed))
|
||||
when defined(srand48): srand48(seed)
|
||||
proc random(max: int): int =
|
||||
result = int(rand()) mod max
|
||||
|
||||
@@ -217,6 +224,7 @@ else:
|
||||
proc random(max: float): float =
|
||||
result = float(mathrandom() * float(max))
|
||||
proc randomize() = nil
|
||||
proc randomize(seed: int) = nil
|
||||
|
||||
proc sqrt*(x: float): float {.importc: "Math.sqrt", nodecl.}
|
||||
proc ln*(x: float): float {.importc: "Math.log", nodecl.}
|
||||
@@ -301,3 +309,18 @@ proc standardDeviation*(s: TRunningStat): float =
|
||||
|
||||
{.pop.}
|
||||
{.pop.}
|
||||
|
||||
when isMainModule and not defined(ECMAScript):
|
||||
# Verifies random seed initialization.
|
||||
let seed = gettime(nil)
|
||||
randomize(seed)
|
||||
const SIZE = 10
|
||||
var buf : array[0..SIZE, int]
|
||||
# Fill the buffer with random values
|
||||
for i in 0..SIZE-1:
|
||||
buf[i] = random(high(int))
|
||||
# Check that the second random calls are the same for each position.
|
||||
randomize(seed)
|
||||
for i in 0..SIZE-1:
|
||||
assert buf[i] == random(high(int)), "non deterministic random seeding"
|
||||
echo "random values equal after reseeding"
|
||||
|
||||
@@ -850,13 +850,51 @@ proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
|
||||
for c in items(s):
|
||||
case c
|
||||
of '\0'..'\31', '\128'..'\255':
|
||||
add(result, '\\')
|
||||
add(result, "\\x")
|
||||
add(result, toHex(ord(c), 2))
|
||||
of '\\': add(result, "\\\\")
|
||||
of '\'': add(result, "\\'")
|
||||
of '\"': add(result, "\\\"")
|
||||
else: add(result, c)
|
||||
add(result, suffix)
|
||||
|
||||
proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
|
||||
rtl, extern: "nsuUnescape".} =
|
||||
## Unescapes a string `s`. This complements ``escape`` as it performs the
|
||||
## opposite operations.
|
||||
##
|
||||
## If `s` does not begin with ``prefix`` and end with ``suffix`` a EInvalidValue
|
||||
## exception will be raised.
|
||||
result = newStringOfCap(s.len)
|
||||
var i = 0
|
||||
if s[0 .. prefix.len-1] != prefix:
|
||||
raise newException(EInvalidValue,
|
||||
"String does not start with a prefix of: " & prefix)
|
||||
i.inc()
|
||||
while True:
|
||||
if i == s.len-suffix.len: break
|
||||
case s[i]
|
||||
of '\\':
|
||||
case s[i+1]:
|
||||
of 'x':
|
||||
let j = parseHexInt(s[i+2 .. i+3])
|
||||
result.add(chr(j))
|
||||
inc(i, 2)
|
||||
of '\\':
|
||||
result.add('\\')
|
||||
of '\'':
|
||||
result.add('\'')
|
||||
of '\"':
|
||||
result.add('\"')
|
||||
else: result.add("\\" & s[i+1])
|
||||
inc(i)
|
||||
of '\0': break
|
||||
else:
|
||||
result.add(s[i])
|
||||
i.inc()
|
||||
if s[i .. -1] != suffix:
|
||||
raise newException(EInvalidValue,
|
||||
"String does not end with a suffix of: " & suffix)
|
||||
|
||||
proc validIdentifier*(s: string): bool {.noSideEffect,
|
||||
rtl, extern: "nsuValidIdentifier".} =
|
||||
|
||||
@@ -38,7 +38,8 @@ type
|
||||
char* {.magic: Char.} ## built-in 8 bit character type (unsigned)
|
||||
string* {.magic: String.} ## built-in string type
|
||||
cstring* {.magic: Cstring.} ## built-in cstring (*compatible string*) type
|
||||
pointer* {.magic: Pointer.} ## built-in pointer type
|
||||
pointer* {.magic: Pointer.} ## built-in pointer type, use the ``addr``
|
||||
## operator to get a pointer to a variable
|
||||
|
||||
const
|
||||
on* = true ## alias for ``true``
|
||||
@@ -1460,15 +1461,51 @@ proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} =
|
||||
result = s[L]
|
||||
setLen(s, L)
|
||||
|
||||
proc each*[T, S](data: openArray[T], op: proc (x: T): S {.closure.}): seq[S] =
|
||||
## The well-known `map`:idx: operation from functional programming. Applies
|
||||
proc each*[T, S](data: openArray[T], op: proc (x: T): S {.closure.}): seq[S] {.
|
||||
deprecated.} =
|
||||
## The well-known ``map`` operation from functional programming. Applies
|
||||
## `op` to every item in `data` and returns the result as a sequence.
|
||||
##
|
||||
## **Deprecated since version 0.9:** Use the ``map`` proc instead.
|
||||
newSeq(result, data.len)
|
||||
for i in 0..data.len-1: result[i] = op(data[i])
|
||||
|
||||
proc each*[T](data: var openArray[T], op: proc (x: var T) {.closure.}) =
|
||||
## The well-known `map`:idx: operation from functional programming. Applies
|
||||
proc each*[T](data: var openArray[T], op: proc (x: var T) {.closure.}) {.
|
||||
deprecated.} =
|
||||
## The well-known ``map`` operation from functional programming. Applies
|
||||
## `op` to every item in `data` modifying it directly.
|
||||
##
|
||||
## **Deprecated since version 0.9:** Use the ``map`` proc instead.
|
||||
for i in 0..data.len-1: op(data[i])
|
||||
|
||||
proc map*[T, S](data: openArray[T], op: proc (x: T): S {.closure.}): seq[S] =
|
||||
## Returns a new sequence with the results of `op` applied to every item in
|
||||
## `data`.
|
||||
##
|
||||
## Since the input is not modified you can use this version of ``map`` to
|
||||
## transform the type of the elements in the input sequence. Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## let
|
||||
## a = @[1, 2, 3, 4]
|
||||
## b = map(a, proc(x: int): string = $x)
|
||||
## assert b == @["1", "2", "3", "4"]
|
||||
newSeq(result, data.len)
|
||||
for i in 0..data.len-1: result[i] = op(data[i])
|
||||
|
||||
proc map*[T](data: var openArray[T], op: proc (x: var T) {.closure.}) =
|
||||
## Applies `op` to every item in `data` modifying it directly.
|
||||
##
|
||||
## Note that this version of ``map`` requires your input and output types to
|
||||
## be the same, since they are modified in-place. Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## var a = @["1", "2", "3", "4"]
|
||||
## echo repr(a)
|
||||
## # --> ["1", "2", "3", "4"]
|
||||
## map(a, proc(x: var string) = x &= "42")
|
||||
## echo repr(a)
|
||||
## # --> ["142", "242", "342", "442"]
|
||||
for i in 0..data.len-1: op(data[i])
|
||||
|
||||
iterator fields*[T: tuple](x: T): TObject {.
|
||||
|
||||
@@ -16598,6 +16598,7 @@ proc message_dialog_new*(parent: PWindow, flags: TDialogFlags,
|
||||
cdecl, importc: "gtk_message_dialog_new", dynlib: lib.}
|
||||
proc set_markup*(msgDialog: PMessageDialog, str: cstring) {.cdecl,
|
||||
importc: "gtk_message_dialog_set_markup", dynlib: lib.}
|
||||
|
||||
proc signal_new*(name: cstring, signal_flags: TSignalRunType,
|
||||
object_type: TType, function_offset: guint,
|
||||
marshaller: TSignalMarshaller, return_val: TType, n_args: guint): guint{.
|
||||
@@ -16895,6 +16896,15 @@ type
|
||||
proc set_tooltip_text*(w: PWidget, t: cstring){.cdecl,
|
||||
dynlib: lib, importc: "gtk_widget_set_tooltip_text".}
|
||||
|
||||
proc get_tooltip_text*(w: PWidget): cstring{.cdecl,
|
||||
dynlib: lib, importc: "gtk_widget_get_tooltip_text".}
|
||||
|
||||
proc set_tooltip_markup*(w: PWidget, m: cstring) {.cdecl, dynlib: lib,
|
||||
importc: "gtk_widget_set_tooltip_markup".}
|
||||
|
||||
proc get_tooltip_markup*(w: PWidget): cstring {.cdecl, dynlib: lib,
|
||||
importc: "gtk_widget_get_tooltip_markup".}
|
||||
|
||||
proc set_tooltip_column*(w: PTreeview, column: gint){.cdecl,
|
||||
dynlib: lib, importc: "gtk_tree_view_set_tooltip_column".}
|
||||
|
||||
@@ -16907,6 +16917,9 @@ proc trigger_tooltip_query*(widg: PTooltip){.cdecl, dynlib: lib,
|
||||
proc set_has_tooltip*(widget: PWidget, b: gboolean){.cdecl, dynlib: lib,
|
||||
importc: "gtk_widget_set_has_tooltip".}
|
||||
|
||||
proc get_has_tooltip*(widget: PWidget): gboolean{.cdecl, dynlib: lib,
|
||||
importc: "gtk_widget_get_has_tooltip".}
|
||||
|
||||
proc set_markup*(tp: PTooltip, mk: cstring){.cdecl, dynlib: lib,
|
||||
importc: "gtk_tooltip_set_markup".}
|
||||
|
||||
@@ -17037,6 +17050,10 @@ proc remove*(combo_box: PComboBoxText; position: gint){.cdecl,
|
||||
importc: "gtk_combo_box_text_remove", dynlib: lib.}
|
||||
proc get_active_text*(combo_box: PComboBoxText): cstring{.cdecl,
|
||||
importc: "gtk_combo_box_text_get_active_text", dynlib: lib.}
|
||||
proc is_active*(win: PWindow): gboolean{.cdecl,
|
||||
importc: "gtk_window_is_active", dynlib: lib.}
|
||||
proc has_toplevel_focus*(win: PWindow): gboolean{.cdecl,
|
||||
importc: "gtk_window_has_toplevel_focus", dynlib: lib.}
|
||||
|
||||
proc nimrod_init*() =
|
||||
var
|
||||
|
||||
@@ -4,8 +4,8 @@ import json, tables
|
||||
proc run(json_params: TTable) =
|
||||
let json_elems = json_params["files"].elems
|
||||
# These fail compilation.
|
||||
var files = each(json_elems, proc (x: PJsonNode): string = x.str)
|
||||
#var files = json_elems.each do (x: PJsonNode) -> string: x.str
|
||||
var files = map(json_elems, proc (x: PJsonNode): string = x.str)
|
||||
#var files = json_elems.map do (x: PJsonNode) -> string: x.str
|
||||
echo "Hey!"
|
||||
|
||||
when isMainModule:
|
||||
|
||||
@@ -21,7 +21,7 @@ proc takeParseInt(x: proc (y: string): int {.noSideEffect.}): int =
|
||||
result = x("123")
|
||||
|
||||
echo "Give a list of numbers (separated by spaces): "
|
||||
var x = stdin.readline.split.each(parseInt).max
|
||||
var x = stdin.readline.split.map(parseInt).max
|
||||
echo x, " is the maximum!"
|
||||
echo "another number: ", takeParseInt(parseInt)
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ from that model.
|
||||
# Prints the maximum integer from a list of integers
|
||||
# delimited by whitespace read from stdin.
|
||||
let tokens = stdin.readLine.split
|
||||
echo tokens.each(parseInt).max, " is the maximum."
|
||||
echo tokens.map(parseInt).max, " is the maximum."
|
||||
|
||||
|
||||
Nimrod is efficient
|
||||
|
||||
Reference in New Issue
Block a user