niminst: bugfixes; documentation changes
This commit is contained in:
parent
4cfc0462a4
commit
f58cc49672
9 changed files with 70 additions and 85 deletions
|
|
@ -1024,7 +1024,7 @@ proc getStrOrChar*(a: PNode): string =
|
||||||
|
|
||||||
proc isGenericRoutine*(s: PSym): bool =
|
proc isGenericRoutine*(s: PSym): bool =
|
||||||
case s.kind
|
case s.kind
|
||||||
of skProc, skTemplate, skMacro, skIterator, skMethod:
|
of skProc, skTemplate, skMacro, skIterator, skMethod, skConverter:
|
||||||
result = s.ast != nil and s.ast[genericParamsPos].kind != nkEmpty
|
result = s.ast != nil and s.ast[genericParamsPos].kind != nkEmpty
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -736,37 +736,10 @@ variadic proc, it is implicitely converted to ``cstring`` too:
|
||||||
|
|
||||||
Even though the conversion is implict, it is not *safe*: The garbage collector
|
Even though the conversion is implict, it is not *safe*: The garbage collector
|
||||||
does not consider a ``cstring`` to be a root and may collect the underlying
|
does not consider a ``cstring`` to be a root and may collect the underlying
|
||||||
memory:
|
memory. However in practice this almost never happens as the GC considers
|
||||||
|
stack roots conservatively. One can use the builtin procs ``GC_ref`` and
|
||||||
.. code-block:: nimrod
|
``GC_unref`` to keep the string data alive for the rare cases where it does
|
||||||
var nimStr = "example"
|
not work.
|
||||||
var cStr: cstring = nimStr
|
|
||||||
var i = 0
|
|
||||||
while cStr[i] != '\0':
|
|
||||||
# since `nimStr`'s lifetime ended here the GC is allowed to free
|
|
||||||
# the memory occupied by "example":
|
|
||||||
GC_collect()
|
|
||||||
# now cStr points to garbage:
|
|
||||||
echo cStr[i]
|
|
||||||
inc i
|
|
||||||
|
|
||||||
However this a very contrived example; in practice this almost never happens.
|
|
||||||
One can use the builtin procs ``GC_ref`` and ``GC_unref`` to make this code
|
|
||||||
safe:
|
|
||||||
|
|
||||||
.. code-block:: nimrod
|
|
||||||
var nimStr = "example"
|
|
||||||
GC_ref(nimStr) # keep GC from freeing 'nimStr'
|
|
||||||
var cStr: cstring = nimStr
|
|
||||||
var i = 0
|
|
||||||
while cStr[i] != '\0':
|
|
||||||
# since `nimStr`'s lifetime ended here the GC is allowed to free
|
|
||||||
# the memory occupied by "example":
|
|
||||||
GC_collect()
|
|
||||||
# now cStr points to garbage:
|
|
||||||
echo cStr[i]
|
|
||||||
inc i
|
|
||||||
GC_unref(nimStr) # GC is allowed to free 'nimStr'
|
|
||||||
|
|
||||||
|
|
||||||
Structured types
|
Structured types
|
||||||
|
|
|
||||||
78
doc/tut1.txt
78
doc/tut1.txt
|
|
@ -31,9 +31,9 @@ We start the tour with a modified "hello world" program:
|
||||||
|
|
||||||
.. code-block:: Nimrod
|
.. code-block:: Nimrod
|
||||||
# This is a comment
|
# This is a comment
|
||||||
Echo("What's your name? ")
|
echo("What's your name? ")
|
||||||
var name: string = readLine(stdin)
|
var name: string = readLine(stdin)
|
||||||
Echo("Hi, ", name, "!")
|
echo("Hi, ", name, "!")
|
||||||
|
|
||||||
|
|
||||||
Save this code to the file "greetings.nim". Now compile and run it::
|
Save this code to the file "greetings.nim". Now compile and run it::
|
||||||
|
|
@ -65,12 +65,12 @@ done with spaces only, tabulators are not allowed.
|
||||||
|
|
||||||
String literals are enclosed in double quotes. The ``var`` statement declares
|
String literals are enclosed in double quotes. The ``var`` statement declares
|
||||||
a new variable named ``name`` of type ``string`` with the value that is
|
a new variable named ``name`` of type ``string`` with the value that is
|
||||||
returned by the ``readline`` procedure. Since the compiler knows that
|
returned by the ``readLine`` procedure. Since the compiler knows that
|
||||||
``readline`` returns a string, you can leave out the type in the declaration
|
``readLine`` returns a string, you can leave out the type in the declaration
|
||||||
(this is called `local type inference`:idx:). So this will work too:
|
(this is called `local type inference`:idx:). So this will work too:
|
||||||
|
|
||||||
.. code-block:: Nimrod
|
.. code-block:: Nimrod
|
||||||
var name = readline(stdin)
|
var name = readLine(stdin)
|
||||||
|
|
||||||
Note that this is basically the only form of type inference that exists in
|
Note that this is basically the only form of type inference that exists in
|
||||||
Nimrod: it is a good compromise between brevity and readability.
|
Nimrod: it is a good compromise between brevity and readability.
|
||||||
|
|
@ -140,10 +140,10 @@ which code snippet the comment refers to. Since comments are a proper part of
|
||||||
the syntax, watch their indentation:
|
the syntax, watch their indentation:
|
||||||
|
|
||||||
.. code-block::
|
.. code-block::
|
||||||
Echo("Hello!")
|
echo("Hello!")
|
||||||
# comment has the same indentation as above statement -> fine
|
# comment has the same indentation as above statement -> fine
|
||||||
Echo("Hi!")
|
echo("Hi!")
|
||||||
# comment has not the right indentation -> syntax error!
|
# comment has not the correct indentation level -> syntax error!
|
||||||
|
|
||||||
**Note**: To comment out a large piece of code, it is often better to use a
|
**Note**: To comment out a large piece of code, it is often better to use a
|
||||||
``when false:`` statement.
|
``when false:`` statement.
|
||||||
|
|
@ -244,7 +244,7 @@ The if statement is one way to branch the control flow:
|
||||||
elif name == "name":
|
elif name == "name":
|
||||||
echo("Very funny, your name is name.")
|
echo("Very funny, your name is name.")
|
||||||
else:
|
else:
|
||||||
Echo("Hi, ", name, "!")
|
echo("Hi, ", name, "!")
|
||||||
|
|
||||||
There can be zero or more elif parts, and the else part is optional. The
|
There can be zero or more elif parts, and the else part is optional. The
|
||||||
keyword ``elif`` is short for ``else if``, and is useful to avoid excessive
|
keyword ``elif`` is short for ``else if``, and is useful to avoid excessive
|
||||||
|
|
@ -267,7 +267,7 @@ a multi-branch:
|
||||||
of "Dave", "Frank":
|
of "Dave", "Frank":
|
||||||
echo("Cool name!")
|
echo("Cool name!")
|
||||||
else:
|
else:
|
||||||
Echo("Hi, ", name, "!")
|
echo("Hi, ", name, "!")
|
||||||
|
|
||||||
As it can be seen, for an ``of`` branch a comma separated list of values is also
|
As it can be seen, for an ``of`` branch a comma separated list of values is also
|
||||||
allowed.
|
allowed.
|
||||||
|
|
@ -280,11 +280,11 @@ For integers or other ordinal types value ranges are also possible:
|
||||||
# this statement will be explained later:
|
# this statement will be explained later:
|
||||||
from strutils import parseInt
|
from strutils import parseInt
|
||||||
|
|
||||||
Echo("A number please: ")
|
echo("A number please: ")
|
||||||
let n = parseInt(readLine(stdin))
|
let n = parseInt(readLine(stdin))
|
||||||
case n
|
case n
|
||||||
of 0..2, 4..7: Echo("The number is in the set: {0, 1, 2, 4, 5, 6, 7}")
|
of 0..2, 4..7: echo("The number is in the set: {0, 1, 2, 4, 5, 6, 7}")
|
||||||
of 3, 8: Echo("The number is 3 or 8")
|
of 3, 8: echo("The number is 3 or 8")
|
||||||
|
|
||||||
However, the above code does not compile: the reason is that you have to cover
|
However, the above code does not compile: the reason is that you have to cover
|
||||||
every value that ``n`` may contain, but the code only handles the values
|
every value that ``n`` may contain, but the code only handles the values
|
||||||
|
|
@ -295,8 +295,8 @@ the compiler that for every other value nothing should be done:
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
...
|
...
|
||||||
case n
|
case n
|
||||||
of 0..2, 4..7: Echo("The number is in the set: {0, 1, 2, 4, 5, 6, 7}")
|
of 0..2, 4..7: echo("The number is in the set: {0, 1, 2, 4, 5, 6, 7}")
|
||||||
of 3, 8: Echo("The number is 3 or 8")
|
of 3, 8: echo("The number is 3 or 8")
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
The ``nil`` statement is a *do nothing* statement. The compiler knows that a
|
The ``nil`` statement is a *do nothing* statement. The compiler knows that a
|
||||||
|
|
@ -316,10 +316,10 @@ The while statement is a simple looping construct:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
|
|
||||||
Echo("What's your name? ")
|
echo("What's your name? ")
|
||||||
var name = readLine(stdin)
|
var name = readLine(stdin)
|
||||||
while name == "":
|
while name == "":
|
||||||
Echo("Please tell me your name: ")
|
echo("Please tell me your name: ")
|
||||||
name = readLine(stdin)
|
name = readLine(stdin)
|
||||||
# no ``var``, because we do not declare a new variable here
|
# no ``var``, because we do not declare a new variable here
|
||||||
|
|
||||||
|
|
@ -334,9 +334,9 @@ The `for`:idx: statement is a construct to loop over any element an *iterator*
|
||||||
provides. The example uses the built-in ``countup`` iterator:
|
provides. The example uses the built-in ``countup`` iterator:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
Echo("Counting to ten: ")
|
echo("Counting to ten: ")
|
||||||
for i in countup(1, 10):
|
for i in countup(1, 10):
|
||||||
Echo($i)
|
echo($i)
|
||||||
|
|
||||||
The built-in ``$`` operator turns an integer (``int``) and many other types
|
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
|
into a string. The variable ``i`` is implicitly declared by the ``for`` loop
|
||||||
|
|
@ -345,18 +345,18 @@ through the values 1, 2, .., 10. Each value is ``echo``-ed. This code does
|
||||||
the same:
|
the same:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
Echo("Counting to 10: ")
|
echo("Counting to 10: ")
|
||||||
var i = 1
|
var i = 1
|
||||||
while i <= 10:
|
while i <= 10:
|
||||||
Echo($i)
|
echo($i)
|
||||||
inc(i) # increment i by 1
|
inc(i) # increment i by 1
|
||||||
|
|
||||||
Counting down can be achieved as easily (but is less often needed):
|
Counting down can be achieved as easily (but is less often needed):
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
Echo("Counting down from 10 to 1: ")
|
echo("Counting down from 10 to 1: ")
|
||||||
for i in countdown(10, 1):
|
for i in countdown(10, 1):
|
||||||
Echo($i)
|
echo($i)
|
||||||
|
|
||||||
Since counting up occurs so often in programs, Nimrod has a special syntax that
|
Since counting up occurs so often in programs, Nimrod has a special syntax that
|
||||||
calls the ``countup`` iterator implicitly:
|
calls the ``countup`` iterator implicitly:
|
||||||
|
|
@ -400,18 +400,18 @@ unless a label of a block is given:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
block myblock:
|
block myblock:
|
||||||
Echo("entering block")
|
echo("entering block")
|
||||||
while true:
|
while true:
|
||||||
Echo("looping")
|
echo("looping")
|
||||||
break # leaves the loop, but not the block
|
break # leaves the loop, but not the block
|
||||||
Echo("still in block")
|
echo("still in block")
|
||||||
|
|
||||||
block myblock2:
|
block myblock2:
|
||||||
Echo("entering block")
|
echo("entering block")
|
||||||
while true:
|
while true:
|
||||||
Echo("looping")
|
echo("looping")
|
||||||
break myblock2 # leaves the block (and the loop)
|
break myblock2 # leaves the block (and the loop)
|
||||||
Echo("still in block")
|
echo("still in block")
|
||||||
|
|
||||||
|
|
||||||
Continue statement
|
Continue statement
|
||||||
|
|
@ -423,7 +423,7 @@ the next iteration immediately:
|
||||||
while true:
|
while true:
|
||||||
let x = readLine(stdin)
|
let x = readLine(stdin)
|
||||||
if x == "": continue
|
if x == "": continue
|
||||||
Echo(x)
|
echo(x)
|
||||||
|
|
||||||
|
|
||||||
When statement
|
When statement
|
||||||
|
|
@ -516,17 +516,17 @@ of a `procedure` is needed. (Some languages call them *methods* or
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
proc yes(question: string): bool =
|
proc yes(question: string): bool =
|
||||||
Echo(question, " (y/n)")
|
echo(question, " (y/n)")
|
||||||
while true:
|
while true:
|
||||||
case readLine(stdin)
|
case readLine(stdin)
|
||||||
of "y", "Y", "yes", "Yes": return true
|
of "y", "Y", "yes", "Yes": return true
|
||||||
of "n", "N", "no", "No": return false
|
of "n", "N", "no", "No": return false
|
||||||
else: Echo("Please be clear: yes or no")
|
else: echo("Please be clear: yes or no")
|
||||||
|
|
||||||
if yes("Should I delete all your important files?"):
|
if yes("Should I delete all your important files?"):
|
||||||
Echo("I'm sorry Dave, I'm afraid I can't do that.")
|
echo("I'm sorry Dave, I'm afraid I can't do that.")
|
||||||
else:
|
else:
|
||||||
Echo("I think you know what the problem is just as well as I do.")
|
echo("I think you know what the problem is just as well as I do.")
|
||||||
|
|
||||||
This example shows a procedure named ``yes`` that asks the user a ``question``
|
This example shows a procedure named ``yes`` that asks the user a ``question``
|
||||||
and returns true if he answered "yes" (or something similar) and returns
|
and returns true if he answered "yes" (or something similar) and returns
|
||||||
|
|
@ -662,8 +662,8 @@ Nimrod provides the ability to overload procedures similar to C++:
|
||||||
if x: return "true"
|
if x: return "true"
|
||||||
else: return "false"
|
else: return "false"
|
||||||
|
|
||||||
Echo(toString(13)) # calls the toString(x: int) proc
|
echo(toString(13)) # calls the toString(x: int) proc
|
||||||
Echo(toString(true)) # calls the toString(x: bool) proc
|
echo(toString(true)) # calls the toString(x: bool) proc
|
||||||
|
|
||||||
(Note that ``toString`` is usually the ``$`` operator in Nimrod.)
|
(Note that ``toString`` is usually the ``$`` operator in Nimrod.)
|
||||||
The compiler chooses the most appropriate proc for the ``toString`` calls. How
|
The compiler chooses the most appropriate proc for the ``toString`` calls. How
|
||||||
|
|
@ -704,7 +704,7 @@ The "``" notation can also be used to call an operator just like a procedure
|
||||||
with a real name:
|
with a real name:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
if `==`( `+`(3, 4), 7): Echo("True")
|
if `==`( `+`(3, 4), 7): echo("True")
|
||||||
|
|
||||||
|
|
||||||
Forward declarations
|
Forward declarations
|
||||||
|
|
@ -738,9 +738,9 @@ Iterators
|
||||||
Let's return to the boring counting example:
|
Let's return to the boring counting example:
|
||||||
|
|
||||||
.. code-block:: nimrod
|
.. code-block:: nimrod
|
||||||
Echo("Counting to ten: ")
|
echo("Counting to ten: ")
|
||||||
for i in countup(1, 10):
|
for i in countup(1, 10):
|
||||||
Echo($i)
|
echo($i)
|
||||||
|
|
||||||
Can a ``countup`` proc be written that supports this loop? Lets try:
|
Can a ``countup`` proc be written that supports this loop? Lets try:
|
||||||
|
|
||||||
|
|
|
||||||
14
doc/tut2.txt
14
doc/tut2.txt
|
|
@ -387,17 +387,17 @@ The `try`:idx: statement handles exceptions:
|
||||||
f: TFile
|
f: TFile
|
||||||
if open(f, "numbers.txt"):
|
if open(f, "numbers.txt"):
|
||||||
try:
|
try:
|
||||||
var a = readLine(f)
|
let a = readLine(f)
|
||||||
var b = readLine(f)
|
let b = readLine(f)
|
||||||
echo("sum: " & $(parseInt(a) + parseInt(b)))
|
echo "sum: ", parseInt(a) + parseInt(b)
|
||||||
except EOverflow:
|
except EOverflow:
|
||||||
echo("overflow!")
|
echo "overflow!"
|
||||||
except EInvalidValue:
|
except EInvalidValue:
|
||||||
echo("could not convert string to integer")
|
echo "could not convert string to integer"
|
||||||
except EIO:
|
except EIO:
|
||||||
echo("IO error!")
|
echo "IO error!"
|
||||||
except:
|
except:
|
||||||
echo("Unknown exception!")
|
echo "Unknown exception!"
|
||||||
# reraise the unknown exception:
|
# reraise the unknown exception:
|
||||||
raise
|
raise
|
||||||
finally:
|
finally:
|
||||||
|
|
|
||||||
3
todo.txt
3
todo.txt
|
|
@ -1,8 +1,8 @@
|
||||||
version 0.8.14
|
version 0.8.14
|
||||||
==============
|
==============
|
||||||
|
|
||||||
- improve niminst
|
|
||||||
- fix line info in assertions
|
- fix line info in assertions
|
||||||
|
- bug: tsortdev does not run with native GC
|
||||||
|
|
||||||
version 0.9.0
|
version 0.9.0
|
||||||
=============
|
=============
|
||||||
|
|
@ -47,7 +47,6 @@ Bugs
|
||||||
without ``-d:release`` leaks memory; good way to figure out how a
|
without ``-d:release`` leaks memory; good way to figure out how a
|
||||||
fixed amount of stack can hold an arbitrary number of GC roots!
|
fixed amount of stack can hold an arbitrary number of GC roots!
|
||||||
- bug: temp2.nim triggers weird compiler and except.nim bug
|
- bug: temp2.nim triggers weird compiler and except.nim bug
|
||||||
- bug: tsortdev does not run with native GC
|
|
||||||
|
|
||||||
|
|
||||||
version 0.9.XX
|
version 0.9.XX
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c ?{f} -o ?{changeFileExt(f, "o")}
|
||||||
# linkCmd.add(" " & changeFileExt(f, "o"))
|
# linkCmd.add(" " & changeFileExt(f, "o"))
|
||||||
# end for
|
# end for
|
||||||
|
|
||||||
ECHO %LINKER% %LINK_FLAGS% -o ?{c.binPaths[0]}\?{toLower(c.name)}.exe ?linkCmd
|
ECHO %LINKER% %LINK_FLAGS% -o ?{firstBinPath(c)\toLower(c.name)}.exe ?linkCmd
|
||||||
%LINKER% %LINK_FLAGS% -o ?{c.binPaths[0]}\?{toLower(c.name)}.exe ?linkCmd
|
%LINKER% %LINK_FLAGS% -o ?{firstBinPath(c)\toLower(c.name)}.exe ?linkCmd
|
||||||
|
|
||||||
ECHO SUCCESS
|
ECHO SUCCESS
|
||||||
|
|
|
||||||
|
|
@ -90,8 +90,8 @@ case $myos in
|
||||||
$CC $COMP_FLAGS -Ibuild -c ?{f} -o ?{changeFileExt(f, "o")} || exit 1
|
$CC $COMP_FLAGS -Ibuild -c ?{f} -o ?{changeFileExt(f, "o")} || exit 1
|
||||||
# add(linkCmd, " \\\n" & changeFileExt(f, "o"))
|
# add(linkCmd, " \\\n" & changeFileExt(f, "o"))
|
||||||
# end for
|
# end for
|
||||||
echo "$LINKER $LINK_FLAGS -o ?{c.binPaths[0]}/?{toLower(c.name)} ?linkCmd"
|
echo "$LINKER $LINK_FLAGS -o ?{firstBinPath(c)/toLower(c.name)} ?linkCmd"
|
||||||
$LINKER $LINK_FLAGS -o ?{c.binPaths[0]}/?{toLower(c.name)} ?linkCmd || exit 1
|
$LINKER $LINK_FLAGS -o ?{firstBinPath(c)/toLower(c.name)} ?linkCmd || exit 1
|
||||||
;;
|
;;
|
||||||
# end for
|
# end for
|
||||||
*)
|
*)
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,13 @@ proc initConfigData(c: var TConfigData) =
|
||||||
c.uninstallScript = false
|
c.uninstallScript = false
|
||||||
c.vars = newStringTable(modeStyleInsensitive)
|
c.vars = newStringTable(modeStyleInsensitive)
|
||||||
|
|
||||||
|
proc firstBinPath(c: TConfigData): string =
|
||||||
|
if c.binPaths.len > 0: result = c.binPaths[0]
|
||||||
|
else: result = ""
|
||||||
|
|
||||||
|
proc `\`(a, b: string): string =
|
||||||
|
result = if a.len == 0: b else: a & '\\' & b
|
||||||
|
|
||||||
proc skipRoot(f: string): string =
|
proc skipRoot(f: string): string =
|
||||||
# "abc/def/xyz" --> "def/xyz"
|
# "abc/def/xyz" --> "def/xyz"
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
|
||||||
|
|
@ -106,8 +106,14 @@ Roadmap to 1.0
|
||||||
==============
|
==============
|
||||||
|
|
||||||
Version 0.9.0
|
Version 0.9.0
|
||||||
* closures and anonymous procs
|
* closures
|
||||||
* recursive iterators/coroutines
|
* recursive iterators/coroutines
|
||||||
|
|
||||||
|
Version 0.9.x
|
||||||
* 2-phase type system for better interaction between macros, templates
|
* 2-phase type system for better interaction between macros, templates
|
||||||
and overloading
|
and overloading
|
||||||
|
* term rewriting macros
|
||||||
|
* the syntactic distinction between statements and expressions will be
|
||||||
|
removed
|
||||||
|
* forward declarations will likely be removed
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue