diff options
Diffstat (limited to 'doc')
52 files changed, 3046 insertions, 1437 deletions
diff --git a/doc/advopt.txt b/doc/advopt.txt index 195122cc7..18a5a527b 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -16,10 +16,12 @@ Advanced commands: Advanced options: -o, --out:FILE set the output filename --stdout output to stdout + --colors:on|off turn compiler messages coloring on|off --listFullPaths list full paths in messages - -w, --warnings:on|off turn all warnings on|off + -w:on|off|list, --warnings:on|off|list + turn all warnings on|off or list all available --warning[X]:on|off turn specific warning X on|off - --hints:on|off turn all hints on|off + --hints:on|off|list turn all hints on|off or list all available --hint[X]:on|off turn specific hint X on|off --lib:PATH set the system library path --import:PATH add an automatically imported module @@ -58,7 +60,7 @@ Advanced options: --skipUserCfg do not read the user's configuration file --skipParentCfg do not read the parent dirs' configuration files --skipProjCfg do not read the project's configuration file - --gc:refc|v2|markAndSweep|boehm|none + --gc:refc|v2|markAndSweep|boehm|go|none select the GC to use; default is 'refc' --index:on|off turn index file generation on|off --putenv:key=value set an environment variable diff --git a/doc/apis.txt b/doc/apis.txt index 165279490..277c1925b 100644 --- a/doc/apis.txt +++ b/doc/apis.txt @@ -20,7 +20,7 @@ English word To use Notes ------------------- ------------ -------------------------------------- initialize initT ``init`` is used to create a value type ``T`` -new newP ``new`` is used to create a +new newP ``new`` is used to create a reference type ``P`` find find should return the position where something was found; for a bool result diff --git a/doc/astspec.txt b/doc/astspec.txt index 4c27272e2..c84fad8e8 100644 --- a/doc/astspec.txt +++ b/doc/astspec.txt @@ -1,5 +1,6 @@ The AST in Nim -================= +============== + This section describes how the AST is modelled with Nim's type system. The AST consists of nodes (``NimNode``) with a variable number of children. Each node has a field named ``kind`` which describes what the node @@ -23,10 +24,10 @@ contains: case kind: NimNodeKind ## the node's kind of nnkNone, nnkEmpty, nnkNilLit: discard ## node contains no additional fields - of nnkCharLit..nnkInt64Lit: - intVal: biggestInt ## the int literal + of nnkCharLit..nnkUInt64Lit: + intVal: BiggestInt ## the int literal of nnkFloatLit..nnkFloat64Lit: - floatVal: biggestFloat ## the float literal + floatVal: BiggestFloat ## the float literal of nnkStrLit..nnkTripleStrLit: strVal: string ## the string literal of nnkIdent: @@ -40,27 +41,32 @@ For the ``NimNode`` type, the ``[]`` operator has been overloaded: ``n[i]`` is ``n``'s ``i``-th child. To specify the AST for the different Nim constructs, the notation -``nodekind(son1, son2, ...)`` or ``nodekind(value)`` or +``nodekind(son1, son2, ...)`` or ``nodekind(value)`` or ``nodekind(field=value)`` is used. -Some child may be missing. A missing child is a node of kind ``nnkEmpty``; +Some child may be missing. A missing child is a node of kind ``nnkEmpty``; a child can never be nil. Leaf nodes/Atoms ================ -A leaf of the AST often corresponds to a terminal symbol in the concrete -syntax. +A leaf of the AST often corresponds to a terminal symbol in the concrete +syntax. Note that the default ``float`` in Nim maps to ``float64`` such that +the default AST for a float is ``nnkFloat64Lit`` as below. ----------------- --------------------------------------------- -Nim expression corresponding AST +Nim expression Corresponding AST ----------------- --------------------------------------------- ``42`` ``nnkIntLit(intVal = 42)`` ``42'i8`` ``nnkInt8Lit(intVal = 42)`` ``42'i16`` ``nnkInt16Lit(intVal = 42)`` ``42'i32`` ``nnkInt32Lit(intVal = 42)`` ``42'i64`` ``nnkInt64Lit(intVal = 42)`` -``42.0`` ``nnkFloatLit(floatVal = 42.0)`` +``42'u8`` ``nnkUInt8Lit(intVal = 42)`` +``42'u16`` ``nnkUInt16Lit(intVal = 42)`` +``42'u32`` ``nnkUInt32Lit(intVal = 42)`` +``42'u64`` ``nnkUInt64Lit(intVal = 42)`` +``42.0`` ``nnkFloat64Lit(floatVal = 42.0)`` ``42.0'f32`` ``nnkFloat32Lit(floatVal = 42.0)`` ``42.0'f64`` ``nnkFloat64Lit(floatVal = 42.0)`` ``"abc"`` ``nnkStrLit(strVal = "abc")`` @@ -90,7 +96,11 @@ Concrete syntax: AST: .. code-block:: nim - nnkCommand(nnkIdent(!"echo"), nnkStrLit("abc"), nnkStrLit("xyz")) + nnkCommand( + nnkIdent(!"echo"), + nnkStrLit("abc"), + nnkStrLit("xyz") + ) Call with ``()`` @@ -104,7 +114,11 @@ Concrete syntax: AST: .. code-block:: nim - nnkCall(nnkIdent(!"echo"), nnkStrLit("abc"), nnkStrLit("xyz")) + nnkCall( + nnkIdent(!"echo"), + nnkStrLit("abc"), + nnkStrLit("xyz") + ) Infix operator call @@ -118,8 +132,53 @@ Concrete syntax: AST: .. code-block:: nim - nnkInfix(nnkIdent(!"&"), nnkStrLit("abc"), nnkStrLit("xyz")) + nnkInfix( + nnkIdent(!"&"), + nnkStrLit("abc"), + nnkStrLit("xyz") + ) + +Note that with multiple infix operators, the command is parsed by operator +precedence. + +Concrete syntax: + +.. code-block:: nim + 5 + 3 * 4 + +AST: + +.. code-block:: nim + nnkInfix( + nnkIdent(!"+"), + nnkIntLit(5), + nnkInfix( + nnkIdent(!"*"), + nnkIntLit(3), + nnkIntLit(4) + ) + ) +As a side note, if you choose to use infix operators in a prefix form, the AST +behaves as a +[parenthetical function call](./macros.html#calls-expressions-call-with) with +``nnkAccQuoted``, as follows: + +Concrete syntax: + +.. code-block:: nim + `+`(3, 4) + +AST: + +.. code-block:: nim + nnkCall( + nnkAccQuoted( + nnkIdent(!"+") + ), + nnkIntLit(3), + nnkIntLit(4) + ) Prefix operator call -------------------- @@ -132,13 +191,16 @@ Concrete syntax: AST: .. code-block:: nim - nnkPrefix(nnkIdent(!"?"), nnkStrLit("abc")) + nnkPrefix( + nnkIdent(!"?"), + nnkStrLit("abc") + ) Postfix operator call --------------------- -**Note:** There are no postfix operators in Nim. However, the +**Note:** There are no postfix operators in Nim. However, the ``nnkPostfix`` node is used for the *asterisk export marker* ``*``: Concrete syntax: @@ -149,7 +211,10 @@ Concrete syntax: AST: .. code-block:: nim - nnkPostfix(nnkIdent(!"*"), nnkIdent(!"identifier")) + nnkPostfix( + nnkIdent(!"*"), + nnkIdent(!"identifier") + ) Call with named arguments @@ -158,15 +223,39 @@ Call with named arguments Concrete syntax: .. code-block:: nim - writeln(file=stdout, "hallo") + writeLine(file=stdout, "hallo") AST: .. code-block:: nim - nnkCall(nnkIdent(!"writeln"), - nnkExprEqExpr(nnkIdent(!"file"), nnkIdent(!"stdout")), - nnkStrLit("hallo")) + nnkCall( + nnkIdent(!"writeLine"), + nnkExprEqExpr( + nnkIdent(!"file"), + nnkIdent(!"stdout") + ), + nnkStrLit("hallo") + ) + +Call with raw string literal +---------------------------- + +This is used, for example, in the ``bindSym`` examples +[here](http://nim-lang.org/docs/manual.html#macros-bindsym) and with +``re"some regexp"`` in the regular expression module. +Concrete syntax: + +.. code-block:: nim + echo"abc" + +AST: + +.. code-block:: nim + nnkCallStrLit( + nnkIdent(!"echo"), + nnkRStrLit("hello") + ) Dereference operator ``[]`` --------------------------- @@ -223,6 +312,9 @@ AST: .. code-block:: nim nnkDotExpr(nnkIdent(!"x"), nnkIdent(!"y")) +If you use Nim's flexible calling syntax (as in ``x.len()``), the result is the +same as above but wrapped in an ``nnkCall``. + Array access operator ``[]`` ---------------------------- @@ -241,7 +333,7 @@ AST: Parentheses ----------- -Parentheses for affecting operator precedence or tuple construction +Parentheses for affecting operator precedence or tuple construction are built with the ``nnkPar`` node. Concrete syntax: @@ -253,12 +345,12 @@ AST: .. code-block:: nim nnkPar(nnkIntLit(1), nnkIntLit(2), nnkPar(nnkIntLit(3))) - - + + Curly braces ------------ -Curly braces are used as the set constructor. +Curly braces are used as the set constructor. Concrete syntax: @@ -270,11 +362,26 @@ AST: .. code-block:: nim nnkCurly(nnkIntLit(1), nnkIntLit(2), nnkIntLit(3)) +When used as a table constructor, the syntax is different. + +Concrete syntax: + +.. code-block:: nim + {a: 3, b: 5} + +AST: + +.. code-block:: nim + nnkTableConstr( + nnkExprColonExpr(nnkIdent(!"a"), nnkIntLit(3)), + nnkExprColonExpr(nnkIdent(!"b"), nnkIntLit(5)) + ) + Brackets -------- -Brackets are used as the array constructor. +Brackets are used as the array constructor. Concrete syntax: @@ -290,7 +397,9 @@ AST: Ranges ------ -Ranges occur in set constructors, case statement branches or array slices. +Ranges occur in set constructors, case statement branches, or array slices. +Internally, the node kind ``nnkRange`` is used, but when constructing the +AST, construction with ``..`` as an infix operator should be used instead. Concrete syntax: @@ -300,13 +409,39 @@ Concrete syntax: AST: .. code-block:: nim - nnkRange(nnkIntLit(1), nnkIntLit(3)) + nnkInfix( + nnkIdent(!".."), + nnkIntLit(1), + nnkIntLit(3) + ) + +Example code: + +.. code-block:: nim + macro genRepeatEcho(): stmt = + result = newNimNode(nnkStmtList) + + var forStmt = newNimNode(nnkForStmt) # generate a for statement + forStmt.add(ident("i")) # use the variable `i` for iteration + + var rangeDef = newNimNode(nnkInfix).add( + ident("..")).add( + newIntLitNode(3),newIntLitNode(5)) # iterate over the range 3..5 + + forStmt.add(rangeDef) + forStmt.add(newCall(ident("echo"), newIntLitNode(3))) # meat of the loop + result.add(forStmt) + + genRepeatEcho() # gives: + # 3 + # 3 + # 3 If expression ------------- -The representation of the if expression is subtle, but easy to traverse. +The representation of the ``if`` expression is subtle, but easy to traverse. Concrete syntax: @@ -322,6 +457,69 @@ AST: nnkElseExpr(expr3) ) +Documentation Comments +---------------------- + +Double-hash (``##``) comments in the code actually have their own format, +but the comments do not yet show up in the AST, which will only show that +a comment exists, not what it contains. Single-hash (``#``) comments are ignored. + +Concrete syntax: + +.. code-block:: nim + ## This is a comment + ## This is part of the first comment + stmt1 + ## Yet another + +AST: + +.. code-block:: nim + nnkCommentStmt() # only appears once for the first two lines! + stmt1 + nnkCommentStmt() # another nnkCommentStmt because there is another comment + # (separate from the first) + +Pragmas +------- + +One of Nim's cool features is pragmas, which allow fine-tuning of various +aspects of the language. They come in all types, such as adorning procs and +objects, but the standalone ``emit`` pragma shows the basics with the AST. + +Concrete syntax: + +.. code-block:: nim + {.emit: "#include <stdio.h>".} + +AST: + +.. code-block:: nim + nnkPragma( + nnkExprColonExpr( + nnkIdent(!"emit"), + nnkStrLit("#include <stdio.h>") # the "argument" + ) + ) + +As many ``nnkIdent`` appear as there are pragmas between ``{..}``. Note that +the declaration of new pragmas is essentially the same: + +Concrete syntax: + +.. code-block:: nim + {.pragma: cdeclRename, cdecl.} + +AST: + +.. code-block:: nim + nnkPragma( + nnkExprColonExpr( + nnkIdent(!"pragma"), # this is always first when declaring a new pragma + nnkIdent(!"cdeclRename") # the name of the pragma + ), + nnkIdent(!"cdecl") + ) Statements ========== @@ -335,7 +533,7 @@ there is no ``else`` branch, no ``nnkElse`` child exists. Concrete syntax: .. code-block:: nim - if cond1: + if cond1: stmt1 elif cond2: stmt2 @@ -374,6 +572,8 @@ AST: .. code-block:: nim nnkAsgn(nnkIdent(!"x"), nnkIntLit(42)) +This is not the syntax for assignment when combined with ``var``, ``let``, +or ``const``. Statement list -------------- @@ -390,7 +590,7 @@ AST: .. code-block:: nim nnkStmtList(stmt1, stmt2, stmt3) - + Case statement -------------- @@ -398,7 +598,7 @@ Concrete syntax: .. code-block:: nim case expr1 - of expr2, expr3..expr4: + of expr2, expr3..expr4: stmt1 of expr5: stmt2 @@ -459,11 +659,11 @@ Concrete syntax: .. code-block:: nim try: stmt1 - except e1, e2: + except e1, e2: stmt2 except e3: stmt3 - except: + except: stmt4 finally: stmt5 @@ -472,9 +672,9 @@ AST: .. code-block:: nim nnkTryStmt( - stmt1, - nnkExceptBranch(e1, e2, stmt2), - nnkExceptBranch(e3, stmt3), + stmt1, + nnkExceptBranch(e1, e2, stmt2), + nnkExceptBranch(e3, stmt3), nnkExceptBranch(stmt4), nnkFinally(stmt5) ) @@ -499,12 +699,18 @@ Yield statement Like ``return``, but with ``nnkYieldStmt`` kind. +.. code-block:: nim + nnkYieldStmt(expr1) + Discard statement ----------------- Like ``return``, but with ``nnkDiscardStmt`` kind. +.. code-block:: nim + nnkDiscardStmt(expr1) + Continue statement ------------------ @@ -519,54 +725,679 @@ AST: .. code-block:: nim nnkContinueStmt() +Break statement +--------------- + +Concrete syntax: + +.. code-block:: nim + break otherLocation + +AST: + +.. code-block:: nim + nnkBreakStmt(nnkIdent(!"otherLocation")) + +If ``break`` is used without a jump-to location, ``nnkEmpty`` replaces ``nnkIdent``. + +Block statement +--------------- + +Concrete syntax: + +.. code-block:: nim + block name: + +AST: + +.. code-block:: nim + nnkBlockStmt(nnkIdent(!"name"), nnkStmtList(...)) + +A ``block`` doesn't need an name, in which case ``nnkEmpty`` is used. + +Asm statement +------------- + +Concrete syntax: + +.. code-block:: nim + asm """ + some asm + """ + +AST: + +.. code-block:: nim + nnkAsmStmt( + nnkEmpty(), # for pragmas + nnkTripleStrLit("some asm"), + ) + +Import section +-------------- + +Nim's ``import`` statement actually takes different variations depending +on what keywords are present. Let's start with the simplest form. + +Concrete syntax: + +.. code-block:: nim + import math + +AST: + +.. code-block:: nim + nnkImportStmt(nnkIdent(!"math")) + +With ``except``, we get ``nnkImportExceptStmt``. + +Concrete syntax: + +.. code-block:: nim + import math except pow + +AST: + +.. code-block:: nim + nnkImportExceptStmt(nnkIdent(!"math"),nnkIdent(!"pow")) + +Note that ``import math as m`` does not use a different node; rather, +we use ``nnkImportStmt`` with ``as`` as an infix operator. + +Concrete syntax: + +.. code-block:: nim + import strutils as su + +AST: + +.. code-block:: nim + nnkImportStmt( + nnkInfix( + nnkIdent(!"as"), + nnkIdent(!"strutils"), + nnkIdent(!"su") + ) + ) + +From statement +-------------- + +If we use ``from ... import``, the result is different, too. + +Concrete syntax: + +.. code-block:: nim + from math import pow + +AST: + +.. code-block:: nim + nnkFromStmt(nnkIdent(!"math"), nnkIdent(!"pow")) + +Using ``from math as m import pow`` works identically to the ``as`` modifier +with the ``import`` statement, but wrapped in ``nnkFromStmt``. + +Export statement +---------------- + +When you are making an imported module accessible by modules that import yours, +the ``export`` syntax is pretty straightforward. + +Concrete syntax: + +.. code-block:: nim + export unsigned + +AST: + +.. code-block:: nim + nnkExportStmt(nnkIdent(!"unsigned")) + +Similar to the ``import`` statement, the AST is different for +``export ... except``. + +Concrete syntax: + +.. code-block:: nim + export math except pow # we're going to implement our own exponentiation + +AST: + +.. code-block:: nim + nnkExportExceptStmt(nnkIdent(!"math"),nnkIdent(!"pow")) + +Include statement +----------------- + +Like a plain ``import`` statement but with ``nnkIncludeStmt``. + +Concrete syntax: + +.. code-block:: nim + include blocks + +AST: + +.. code-block:: nim + nnkIncludeStmt(nnkIdent(!"blocks")) + Var section ----------- -To be written. +Concrete syntax: + +.. code-block:: nim + var a = 3 + +AST: +.. code-block:: nim + nnkVarSection( + nnkIdentDefs( + nnkIdent(!"a"), + nnkEmpty(), # or nnkIdent(...) if the variable declares the type + nnkIntLit(3), + ) + ) + +Note that either the second or third (or both) parameters above must exist, +as the compiler needs to know the type somehow (which it can infer from +the given assignment). + +This is not the same AST for all uses of ``var``. See +[Procedure declaration](http://nim-lang.org/docs/macros.html#statements-procedure-declaration) +for details. + +Let section +----------- + +This is equivalent to ``var``, but with ``nnkLetSection`` rather than +``nnkVarSection``. + +Concrete syntax: + +.. code-block:: nim + let v = 3 + +AST: + +.. code-block:: nim + nnkLetSection( + nnkIdentDefs(!"v"), + nnkEmpty(), # for the type + nnkIntLit(3) + ) Const section ------------- -To be written. +Concrete syntax: +.. code-block:: nim + const a = 3 + +AST: + +.. code-block:: nim + nnkConstSection( + nnkConstDef( # not nnkConstDefs! + nnkIdent(!"a"), + nnkEmpty(), # or nnkIdent(...) if the variable declares the type + nnkIntLit(3), # required in a const declaration! + ) + ) Type section ------------ -To be written. +Starting with the simplest case, a ``type`` section appears much like ``var`` +and ``const``. + +Concrete syntax: + +.. code-block:: nim + type A = int + +AST: + +.. code-block:: nim + nnkTypeSection( + nnkTypeDef( + nnkIdent(!"A"), + nnkEmpty(), + nnkIdent(!"int") + ) + ) + +Declaring ``distinct`` types is similar, with the last ``nnkIdent`` wrapped +in ``nnkDistinctTy``. + +Concrete syntax: + +.. code-block:: nim + type MyInt = distinct int + +AST: + +.. code-block:: nim + # ... + nnkTypeDef( + nnkIdent(!"MyInt"), + nnkEmpty(), + nnkDistinctTy( + nnkIdent(!"int") + ) + ) + +If a type section uses generic parameters, they are treated here: + +Concrete syntax: + +.. code-block:: nim + type A[T] = expr1 + +AST: + +.. code-block:: nim + nnkTypeSection( + nnkTypeDef( + nnkIdent(!"A"), + nnkGenericParams( + nnkIdentDefs( + nnkIdent(!"T"), + nnkEmpty(), # if the type is declared with options, like + # ``[T: SomeInteger]``, they are given here + nnkEmpty(), + ) + ) + expr1, + ) + ) + +Note that not all ``nnkTypeDef`` utilize ``nnkIdent`` as their +their parameter. One of the most common uses of type declarations +is to work with objects. + +Concrete syntax: + +.. code-block:: nim + type IO = object of RootObj + +AST: + +.. code-block:: nim + # ... + nnkTypeDef( + nnkIdent(!"IO"), + nnkEmpty(), + nnkObjectTy( + nnkEmpty(), # no pragmas here + nnkOfInherit( + nnkIdent(!"RootObj") # inherits from RootObj + ) + nnkEmpty() + ) + ) + +Nim's object syntax is rich. Let's take a look at an involved example in +its entirety to see some of the complexities. + +Concrete syntax: + +.. code-block:: nim + type Obj[T] = object {.inheritable.} + name: string + case isFat: bool + of true: + m: array[100_000, T] + of false: + m: array[10, T] + +AST: + +.. code-block:: nim + # ... + nnkObjectTy( + nnkPragma( + nnkIdent(!"inheritable") + ), + nnkEmpty(), + nnkRecList( # list of object parameters + nnkIdentDefs( + nnkIdent(!"name"), + nnkIdent(!"string"), + nnkEmpty() + ), + nnkRecCase( # case statement within object (not nnkCaseStmt) + nnkIdentDefs( + nnkIdent(!"isFat"), + nnkIdent(!"bool"), + nnkEmpty() + ), + nnkOfBranch( + nnkIdent(!"true"), + nnkRecList( # again, a list of object parameters + nnkIdentDefs( + nnkIdent(!"m"), + nnkBracketExpr( + nnkIdent(!"array"), + nnkIntLit(100000), + nnkIdent(!"T") + ), + nnkEmpty() + ) + ), + nnkOfBranch( + nnkIdent(!"false"), + nnkRecList( + nnkIdentDefs( + nnkIdent(!"m"), + nnkBracketExpr( + nnkIdent(!"array"), + nnkIntLit(10), + nnkIdent(!"T") + ), + nnkEmpty() + ) + ) + ) + ) + ) + ) + + +Using an ``enum`` is similar to using an ``object``. + +Concrete syntax: + +.. code-block:: nim + type X = enum + First + +AST: + +.. code-block:: nim + # ... + nnkEnumTy( + nnkEmpty(), + nnkIdent(!"First") # you need at least one nnkIdent or the compiler complains + ) + +The usage of ``concept`` (experimental) is similar to objects. + +Concrete syntax: + +.. code-block:: nim + type Con = concept x,y,z + (x & y & z) is string + +AST: + +.. code-block:: nim + # ... + nnkTypeClassTy( # note this isn't nnkConceptTy! + nnkArglist( + # ... idents for x, y, z + ) + # ... + ) + +Static types, like ``static[int]``, use ``nnkIdent`` wrapped in +``nnkStaticTy``. + +Concrete syntax: + +.. code-block:: nim + type A[T: static[int]] = object + +AST: + +.. code-block:: nim + # ... within nnkGenericParams + nnkIdentDefs( + nnkIdent(!"T"), + nnkStaticTy( + nnkIdent(!"int") + ), + nnkEmpty() + ) + # ... + +In general, declaring types mirrors this syntax (i.e., ``nnkStaticTy`` for +``static``, etc.). Examples follow (exceptions marked by ``*``): + +------------- --------------------------------------------- +Nim type Corresponding AST +------------- --------------------------------------------- +``static`` ``nnkStaticTy`` +``tuple`` ``nnkTupleTy`` +``var`` ``nnkVarTy`` +``ptr`` ``nnkPtrTy`` +``ref`` ``nnkRefTy`` +``distinct`` ``nnkDistinctTy`` +``enum`` ``nnkEnumTy`` +``concept`` ``nnkTypeClassTy``\* +``array`` ``nnkBracketExpr(nnkIdent(!"array"),...``\* +``proc`` ``nnkProcTy`` +``iterator`` ``nnkIteratorTy`` +``object`` ``nnkObjectTy`` + +Take special care when declaring types as ``proc``. The behavior is similar +to ``Procedure declaration``, below, but does not treat ``nnkGenericParams``. +Generic parameters are treated in the type, not the ``proc`` itself. + +Concrete syntax: + +.. code-block:: nim + type MyProc[T] = proc(x: T) + +AST: + +.. code-block:: nim + # ... + nnkTypeDef( + nnkIdent(!"MyProc"), + nnkGenericParams( # here, not with the proc + # ... + ) + nnkProcTy( # behaves like a procedure declaration from here on + nnkFormalParams( + # ... + ) + ) + ) + +The same syntax applies to ``iterator`` (with ``nnkIteratorTy``), but +*does not* apply to ``converter`` or ``template``. + +Mixin statement +--------------- + +Concrete syntax: + +.. code-block:: nim + mixin x +AST: + +.. code-block:: nim + nnkMixinStmt(nnkIdent(!"x")) + +Bind statement +-------------- + +Concrete syntax: + +.. code-block:: nim + bind x + +AST: + +.. code-block:: nim + nnkBindStmt(nnkIdent(!"x")) Procedure declaration --------------------- -To be written. +Let's take a look at a procedure with a lot of interesting aspects to get +a feel for how procedure calls are broken down. + +Concrete syntax: + +.. code-block:: nim + proc hello*[T: SomeInteger](x: int = 3, y: float32): int {.inline.} = discard + +AST: + +.. code-block:: nim + nnkProcDef( + nnkPostfix(nnkIdent(!"*"), nnkIdent(!"hello")), # the exported proc name + nnkEmpty(), # patterns for term rewriting in templates and macros (not procs) + nnkGenericParams( # generic type parameters, like with type declaration + nnkIdentDefs( + nnkIdent(!"T"), nnkIdent(!"SomeInteger") + ) + ), + nnkFormalParams( + nnkIdent(!"int"), # the first FormalParam is the return type. nnkEmpty() if there is none + nnkIdentDefs( + nnkIdent(!"x"), + nnkIdent(!"int"), # type type (required for procs, not for templates) + nnkIntLit(3) # a default value + ), + nnkIdentDefs( + nnkIdent(!"y"), + nnkIdent(!"float32"), + nnkEmpty() + ) + nnkPragma(nnkIdent(!"inline")), + nnkEmpty(), # reserved slot for future use + nnkStmtList(nnkDiscardStmt(nnkEmpty())) # the meat of the proc + ) + ) + +There is another consideration. Nim has flexible type identification for +its procs. Even though ``proc(a: int, b: int)`` and ``proc(a, b: int)`` +are equivalent in the code, the AST is a little different for the latter. + +Concrete syntax: +.. code-block:: nim + proc(a, b: int) + +AST: + +.. code-block:: nim + # ...AST as above... + nnkFormalParams( + nnkEmpty(), # no return here + nnkIdentDefs( + nnkIdent(!"a"), # the first parameter + nnkIdent(!"b"), # directly to the second parameter + nnkIdent(!"int"), # their shared type identifier + nnkEmpty(), # default value would go here + ) + ), + # ... + +When a procedure uses the special ``var`` type return variable, the result +is different from that of a var section. + +Concrete syntax: + +.. code-block:: nim + proc hello(): var int + +AST: + +.. code-block:: nim + # ... + nnkFormalParams( + nnkVarTy( + nnkIdent(!"int") + ) + ) Iterator declaration -------------------- -To be written. +The syntax for iterators is similar to procs, but with ``nnkIteratorDef`` +replacing ``nnkProcDef``. + +Concrete syntax: + +.. code-block:: nim + iterator nonsense[T](x: seq[T]): float {.closure.} = ... + +AST: +.. code-block:: nim + nnkIteratorDef( + nnkIdent(!"nonsense"), + nnkEmpty(), + ... + ) + +Converter declaration +--------------------- + +A converter is similar to a proc. + +Concrete syntax: + +.. code-block:: nim + converter toBool(x: float): bool + +AST: + +.. code-block:: nim + nnkConverterDef( + nnkIdent(!"toBool"), + # ... + ) Template declaration -------------------- -To be written. +Templates (as well as macros, as we'll see) have a slightly expanded AST when +compared to procs and iterators. The reason for this is [term-rewriting +macros](http://nim-lang.org/docs/manual.html#term-rewriting-macros). Notice +the ``nnkEmpty()`` as the second argument to ``nnkProcDef`` and +``nnkIteratorDef`` above? That's where the term-rewriting macros go. + +Concrete syntax: + +.. code-block:: nim + template optOpt{expr1}(a: int): int +AST: + +.. code-block:: nim + nnkTemplateDef( + nnkIdent(!"optOpt"), + nnkStmtList( # instead of nnkEmpty() + expr1 + ), + # follows like a proc or iterator + ) + +If the template does not have types for its parameters, the type identifiers +inside ``nnkFormalParams`` just becomes ``nnkEmpty``. Macro declaration ----------------- -To be written. +Macros behave like templates, but ``nnkTemplateDef`` is replaced with +``nnkMacroDef``. Special node kinds ================== -There are several node kinds that are used for semantic checking or code +There are several node kinds that are used for semantic checking or code generation. These are accessible from this module, but should not be used. Other node kinds are especially designed to make AST manipulations easier. -These are explained here. +These are explained here. To be written. diff --git a/doc/docs.txt b/doc/docs.txt index ecf0cc268..4484784ae 100644 --- a/doc/docs.txt +++ b/doc/docs.txt @@ -28,7 +28,7 @@ The documentation consists of several documents: builtin templating system. - | `Term rewriting macros <trmacros.html>`_ - | Term rewriting macros enhance the compilation process with user defined + | Term rewriting macros enhance the compilation process with user defined optimizations. - | `Internal documentation <intern.html>`_ diff --git a/doc/endb.txt b/doc/endb.txt index 049f9d40d..6757d98e3 100644 --- a/doc/endb.txt +++ b/doc/endb.txt @@ -1,203 +1,203 @@ -============================================== - Embedded Nim Debugger (ENDB) User Guide -============================================== - -:Author: Andreas Rumpf -:Version: |nimversion| - -.. contents:: - +============================================== + Embedded Nim Debugger (ENDB) User Guide +============================================== + +:Author: Andreas Rumpf +:Version: |nimversion| + +.. contents:: + **WARNING**: ENDB is not maintained anymore! Please help if you're interested in this tool. - -Nim comes with a platform independent debugger - -the Embedded Nim Debugger (ENDB). The debugger is -*embedded* into your executable if it has been -compiled with the ``--debugger:on`` command line option. -This also defines the conditional symbol ``ENDB`` for you. - -Note: You must not compile your program with the ``--app:gui`` -command line option because then there would be no console -available for the debugger. - -If you start your program the debugger will immediately show -a prompt on the console. You can now enter a command. The next sections -deal with the possible commands. As usual in Nim in all commands -underscores and case do not matter. Optional components of a command -are listed in brackets ``[...]`` here. - - -General Commands -================ - -``h``, ``help`` - Display a quick reference of the possible commands. - -``q``, ``quit`` - Quit the debugger and the program. - -<ENTER> - (Without any typed command) repeat the previous debugger command. - If there is no previous command, ``step_into`` is assumed. - -Executing Commands -================== - -``s``, ``step_into`` - Single step, stepping into routine calls. - -``n``, ``step_over`` - Single step, without stepping into routine calls. - -``f``, ``skip_current`` - Continue execution until the current routine finishes. - -``c``, ``continue`` - Continue execution until the next breakpoint. - -``i``, ``ignore`` - Continue execution, ignore all breakpoints. This effectively quits - the debugger and runs the program until it finishes. - - -Breakpoint Commands -=================== - -``b``, ``setbreak`` [fromline [toline]] [file] - Set a new breakpoint for the given file - and line numbers. If no file is given, the current execution point's - filename is used. If the filename has no extension, ``.nim`` is - appended for your convenience. - If no line numbers are given, the current execution point's - line is used. If both ``fromline`` and ``toline`` are given the - breakpoint contains a line number range. Some examples if it is still - unclear: - - * ``b 12 15 thallo`` creates a breakpoint that - will be triggered if the instruction pointer reaches one of the - lines 12-15 in the file ``thallo.nim``. - * ``b 12 thallo`` creates a breakpoint that - will be triggered if the instruction pointer reaches the - line 12 in the file ``thallo.nim``. - * ``b 12`` creates a breakpoint that - will be triggered if the instruction pointer reaches the - line 12 in the current file. - * ``b`` creates a breakpoint that - will be triggered if the instruction pointer reaches the - current line in the current file again. - -``breakpoints`` - Display the entire breakpoint list. - -``disable`` <identifier> - Disable a breakpoint. It remains disabled until you turn it on again - with the ``enable`` command. - -``enable`` <identifier> - Enable a breakpoint. - -Often it happens when debugging that you keep retyping the breakpoints again -and again because they are lost when you restart your program. This is not -necessary: A special pragma has been defined for this: - - -The ``breakpoint`` pragma -------------------------- - -The ``breakpoint`` pragma is syntactically a statement. It can be used -to mark the *following line* as a breakpoint: - -.. code-block:: Nim - write("1") - {.breakpoint: "before_write_2".} - write("2") - -The name of the breakpoint here is ``before_write_2``. Of course the -breakpoint's name is optional - the compiler will generate one for you -if you leave it out. - -Code for the ``breakpoint`` pragma is only generated if the debugger -is turned on, so you don't need to remove it from your source code after -debugging. - - -The ``watchpoint`` pragma -------------------------- - -The ``watchpoint`` pragma is syntactically a statement. It can be used -to mark a location as a watchpoint: - -.. code-block:: Nim - var a: array [0..20, int] - - {.watchpoint: a[3].} - for i in 0 .. 20: a[i] = i - -ENDB then writes a stack trace whenever the content of the location ``a[3]`` -changes. The current implementation only tracks a hash value of the location's -contents and so locations that are not word sized may encounter false -negatives in very rare cases. - -Code for the ``watchpoint`` pragma is only generated if the debugger -is turned on, so you don't need to remove it from your source code after -debugging. - -Due to the primitive implementation watchpoints are even slower than -breakpoints: After *every* executed Nim code line it is checked whether the -location changed. - - -Data Display Commands -===================== - -``e``, ``eval`` <exp> - Evaluate the expression <exp>. Note that ENDB has no full-blown expression - evaluator built-in. So expressions are limited: - - * To display global variables prefix their names with their - owning module: ``nim1.globalVar`` - * To display local variables or parameters just type in - their name: ``localVar``. If you want to inspect variables that are not - in the current stack frame, use the ``up`` or ``down`` command. - - Unfortunately, only inspecting variables is possible at the moment. Maybe - a future version will implement a full-blown Nim expression evaluator, - but this is not easy to do and would bloat the debugger's code. - - Since displaying the whole data structures is often not needed and - painfully slow, the debugger uses a *maximal display depth* concept for - displaying. - - You can alter the maximal display depth with the ``maxdisplay`` - command. - -``maxdisplay`` <natural> - Sets the maximal display depth to the given integer value. A value of 0 - means there is no maximal display depth. Default is 3. - -``o``, ``out`` <filename> <exp> - Evaluate the expression <exp> and store its string representation into a - file named <filename>. If the file does not exist, it will be created, - otherwise it will be opened for appending. - -``w``, ``where`` - Display the current execution point. - -``u``, ``up`` - Go up in the call stack. - -``d``, ``down`` - Go down in the call stack. - -``stackframe`` [file] - Displays the content of the current stack frame in ``stdout`` or - appends it to the file, depending on whether a file is given. - -``callstack`` - Display the entire call stack (but not its content). - -``l``, ``locals`` - Display the available local variables in the current stack frame. - -``g``, ``globals`` - Display all the global variables that are available for inspection. + +Nim comes with a platform independent debugger - +the Embedded Nim Debugger (ENDB). The debugger is +*embedded* into your executable if it has been +compiled with the ``--debugger:on`` command line option. +This also defines the conditional symbol ``ENDB`` for you. + +Note: You must not compile your program with the ``--app:gui`` +command line option because then there would be no console +available for the debugger. + +If you start your program the debugger will immediately show +a prompt on the console. You can now enter a command. The next sections +deal with the possible commands. As usual in Nim in all commands +underscores and case do not matter. Optional components of a command +are listed in brackets ``[...]`` here. + + +General Commands +================ + +``h``, ``help`` + Display a quick reference of the possible commands. + +``q``, ``quit`` + Quit the debugger and the program. + +<ENTER> + (Without any typed command) repeat the previous debugger command. + If there is no previous command, ``step_into`` is assumed. + +Executing Commands +================== + +``s``, ``step_into`` + Single step, stepping into routine calls. + +``n``, ``step_over`` + Single step, without stepping into routine calls. + +``f``, ``skip_current`` + Continue execution until the current routine finishes. + +``c``, ``continue`` + Continue execution until the next breakpoint. + +``i``, ``ignore`` + Continue execution, ignore all breakpoints. This effectively quits + the debugger and runs the program until it finishes. + + +Breakpoint Commands +=================== + +``b``, ``setbreak`` [fromline [toline]] [file] + Set a new breakpoint for the given file + and line numbers. If no file is given, the current execution point's + filename is used. If the filename has no extension, ``.nim`` is + appended for your convenience. + If no line numbers are given, the current execution point's + line is used. If both ``fromline`` and ``toline`` are given the + breakpoint contains a line number range. Some examples if it is still + unclear: + + * ``b 12 15 thallo`` creates a breakpoint that + will be triggered if the instruction pointer reaches one of the + lines 12-15 in the file ``thallo.nim``. + * ``b 12 thallo`` creates a breakpoint that + will be triggered if the instruction pointer reaches the + line 12 in the file ``thallo.nim``. + * ``b 12`` creates a breakpoint that + will be triggered if the instruction pointer reaches the + line 12 in the current file. + * ``b`` creates a breakpoint that + will be triggered if the instruction pointer reaches the + current line in the current file again. + +``breakpoints`` + Display the entire breakpoint list. + +``disable`` <identifier> + Disable a breakpoint. It remains disabled until you turn it on again + with the ``enable`` command. + +``enable`` <identifier> + Enable a breakpoint. + +Often it happens when debugging that you keep retyping the breakpoints again +and again because they are lost when you restart your program. This is not +necessary: A special pragma has been defined for this: + + +The ``breakpoint`` pragma +------------------------- + +The ``breakpoint`` pragma is syntactically a statement. It can be used +to mark the *following line* as a breakpoint: + +.. code-block:: Nim + write("1") + {.breakpoint: "before_write_2".} + write("2") + +The name of the breakpoint here is ``before_write_2``. Of course the +breakpoint's name is optional - the compiler will generate one for you +if you leave it out. + +Code for the ``breakpoint`` pragma is only generated if the debugger +is turned on, so you don't need to remove it from your source code after +debugging. + + +The ``watchpoint`` pragma +------------------------- + +The ``watchpoint`` pragma is syntactically a statement. It can be used +to mark a location as a watchpoint: + +.. code-block:: Nim + var a: array [0..20, int] + + {.watchpoint: a[3].} + for i in 0 .. 20: a[i] = i + +ENDB then writes a stack trace whenever the content of the location ``a[3]`` +changes. The current implementation only tracks a hash value of the location's +contents and so locations that are not word sized may encounter false +negatives in very rare cases. + +Code for the ``watchpoint`` pragma is only generated if the debugger +is turned on, so you don't need to remove it from your source code after +debugging. + +Due to the primitive implementation watchpoints are even slower than +breakpoints: After *every* executed Nim code line it is checked whether the +location changed. + + +Data Display Commands +===================== + +``e``, ``eval`` <exp> + Evaluate the expression <exp>. Note that ENDB has no full-blown expression + evaluator built-in. So expressions are limited: + + * To display global variables prefix their names with their + owning module: ``nim1.globalVar`` + * To display local variables or parameters just type in + their name: ``localVar``. If you want to inspect variables that are not + in the current stack frame, use the ``up`` or ``down`` command. + + Unfortunately, only inspecting variables is possible at the moment. Maybe + a future version will implement a full-blown Nim expression evaluator, + but this is not easy to do and would bloat the debugger's code. + + Since displaying the whole data structures is often not needed and + painfully slow, the debugger uses a *maximal display depth* concept for + displaying. + + You can alter the maximal display depth with the ``maxdisplay`` + command. + +``maxdisplay`` <natural> + Sets the maximal display depth to the given integer value. A value of 0 + means there is no maximal display depth. Default is 3. + +``o``, ``out`` <filename> <exp> + Evaluate the expression <exp> and store its string representation into a + file named <filename>. If the file does not exist, it will be created, + otherwise it will be opened for appending. + +``w``, ``where`` + Display the current execution point. + +``u``, ``up`` + Go up in the call stack. + +``d``, ``down`` + Go down in the call stack. + +``stackframe`` [file] + Displays the content of the current stack frame in ``stdout`` or + appends it to the file, depending on whether a file is given. + +``callstack`` + Display the entire call stack (but not its content). + +``l``, ``locals`` + Display the available local variables in the current stack frame. + +``g``, ``globals`` + Display all the global variables that are available for inspection. diff --git a/doc/estp.txt b/doc/estp.txt index 500ee52a5..805a84eb7 100644 --- a/doc/estp.txt +++ b/doc/estp.txt @@ -1,30 +1,30 @@ -=================================================== - Embedded Stack Trace Profiler (ESTP) User Guide -=================================================== - -:Author: Andreas Rumpf -:Version: |nimversion| - - -Nim comes with a platform independent profiler - -the Embedded Stack Trace Profiler (ESTP). The profiler -is *embedded* into your executable. To activate the profiler you need to do: - -* compile your program with the ``--profiler:on --stackTrace:on`` command +=================================================== + Embedded Stack Trace Profiler (ESTP) User Guide +=================================================== + +:Author: Andreas Rumpf +:Version: |nimversion| + + +Nim comes with a platform independent profiler - +the Embedded Stack Trace Profiler (ESTP). The profiler +is *embedded* into your executable. To activate the profiler you need to do: + +* compile your program with the ``--profiler:on --stackTrace:on`` command line options * import the ``nimprof`` module * run your program as usual. -You can in fact look at ``nimprof``'s source code to see how to implement +You can in fact look at ``nimprof``'s source code to see how to implement your own profiler. - -The setting ``--profiler:on`` defines the conditional symbol ``profiler``. - -After your program has finished the profiler will create a + +The setting ``--profiler:on`` defines the conditional symbol ``profiler``. + +After your program has finished the profiler will create a file ``profile_results.txt`` containing the profiling results. Since the profiler works by examining stack traces, it's essential that -the option ``--stackTrace:on`` is active! Unfortunately this means that a +the option ``--stackTrace:on`` is active! Unfortunately this means that a profiling build is much slower than a release build. @@ -32,7 +32,7 @@ Memory profiler =============== You can also use ESTP as a memory profiler to see which stack traces allocate -the most memory and thus create the most GC pressure. It may also help to +the most memory and thus create the most GC pressure. It may also help to find memory leaks. To activate the memory profiler you need to do: * compile your program with the ``--profiler:off --stackTrace:on -d:memProfiler`` @@ -40,22 +40,22 @@ find memory leaks. To activate the memory profiler you need to do: * import the ``nimprof`` module * run your program as usual. -Define the symbol ``ignoreAllocationSize`` so that only the number of +Define the symbol ``ignoreAllocationSize`` so that only the number of allocations is counted and the sizes of the memory allocations do not matter. Example results file ==================== -The results file lists stack traces ordered by significance. +The results file lists stack traces ordered by significance. The following example file has been generated by profiling the Nim compiler -itself: It shows that in total 5.4% of the runtime has been spent +itself: It shows that in total 5.4% of the runtime has been spent in ``crcFromRope`` or its children. In general the stack traces show you immediately where the problem is because the trace acts like an explanation; in traditional profilers you can only find -expensive leaf functions easily but the *reason* why they are invoked +expensive leaf functions easily but the *reason* why they are invoked often remains mysterious. :: diff --git a/doc/exception_hierarchy_fragment.txt b/doc/exception_hierarchy_fragment.txt index f4a419fc4..a02d9ccef 100644 --- a/doc/exception_hierarchy_fragment.txt +++ b/doc/exception_hierarchy_fragment.txt @@ -11,8 +11,8 @@ * `FloatInvalidOpError <system.html#FloatInvalidOpError>`_ * `FloatOverflowError <system.html#FloatOverflowError>`_ * `FloatUnderflowError <system.html#FloatUnderflowError>`_ - * `FieldError <system.html#InvalidFieldError>`_ - * `IndexError <system.html#InvalidIndexError>`_ + * `FieldError <system.html#FieldError>`_ + * `IndexError <system.html#IndexError>`_ * `ObjectAssignmentError <system.html#ObjectAssignmentError>`_ * `ObjectConversionError <system.html#ObjectConversionError>`_ * `ValueError <system.html#ValueError>`_ diff --git a/doc/filelist.txt b/doc/filelist.txt index beff8f6c8..71379b40d 100644 --- a/doc/filelist.txt +++ b/doc/filelist.txt @@ -4,12 +4,12 @@ Short description of Nim's modules ============== ========================================================== Module Description ============== ========================================================== -nim main module: parses the command line and calls +nim main module: parses the command line and calls ``main.MainCommand`` main implements the top-level command dispatching nimconf implements the config file reader syntaxes dispatcher for the different parsers and filters -filter_tmpl standard template filter (``#! stdtempl``) +filter_tmpl standard template filter (``#? stdtempl``) lexbase buffer handling of the lexical analyser lexer lexical analyser parser Nim's parser diff --git a/doc/filters.txt b/doc/filters.txt index e725321e6..46bc6c3e5 100644 --- a/doc/filters.txt +++ b/doc/filters.txt @@ -4,13 +4,13 @@ Source Code Filters .. contents:: -A `Source Code Filter` transforms the input character stream to an in-memory -output stream before parsing. A filter can be used to provide templating +A `Source Code Filter` transforms the input character stream to an in-memory +output stream before parsing. A filter can be used to provide templating systems or preprocessors. -To use a filter for a source file the *shebang* notation is used:: +To use a filter for a source file the ``#?`` notation is used:: - #! stdtmpl(subsChar = '$', metaChar = '#') + #? stdtmpl(subsChar = '$', metaChar = '#') #proc generateXML(name, age: string): string = # result = "" <xml> @@ -20,7 +20,8 @@ To use a filter for a source file the *shebang* notation is used:: As the example shows, passing arguments to a filter can be done just like an ordinary procedure call with named or positional arguments. The -available parameters depend on the invoked filter. +available parameters depend on the invoked filter. Before version 0.12.0 of +the language ``#!`` was used instead of ``#?``. Pipe operator @@ -28,7 +29,7 @@ Pipe operator Filters can be combined with the ``|`` pipe operator:: - #! strip(startswith="<") | stdtmpl + #? strip(startswith="<") | stdtmpl #proc generateXML(name, age: string): string = # result = "" <xml> @@ -52,7 +53,7 @@ Parameters and their defaults: ``sub: string = ""`` the substring that is searched for - + ``by: string = ""`` the string the substring is replaced with @@ -71,7 +72,7 @@ Parameters and their defaults: ``leading: bool = true`` strip leading whitespace - + ``trailing: bool = true`` strip trailing whitespace @@ -89,24 +90,24 @@ Parameters and their defaults: ``metaChar: char = '#'`` prefix for a line that contains Nim code - + ``subsChar: char = '$'`` prefix for a Nim expression within a template line - + ``conc: string = " & "`` the operation for concatenation - + ``emit: string = "result.add"`` the operation to emit a string literal - + ``toString: string = "$"`` the operation that is applied to each expression Example:: - #! stdtmpl | standard + #? stdtmpl | standard #proc generateHTMLPage(title, currentTab, content: string, - # tabs: openArray[string]): string = + # tabs: openArray[string]): string = # result = "" <head><title>$title</title></head> <body> @@ -114,7 +115,7 @@ Example:: <ul> #for tab in items(tabs): #if currentTab == tab: - <li><a id="selected" + <li><a id="selected" #else: <li><a #end if @@ -132,11 +133,11 @@ The filter transforms this into: .. code-block:: nim proc generateHTMLPage(title, currentTab, content: string, - tabs: openArray[string]): string = + tabs: openArray[string]): string = result = "" - result.add("<head><title>" & $(title) & "</title></head>\n" & - "<body>\n" & - " <div id=\"menu\">\n" & + result.add("<head><title>" & $(title) & "</title></head>\n" & + "<body>\n" & + " <div id=\"menu\">\n" & " <ul>\n") for tab in items(tabs): if currentTab == tab: @@ -146,17 +147,17 @@ The filter transforms this into: #end result.add(" href=\"" & $(tab) & ".html\">" & $(tab) & "</a></li>\n") #end - result.add(" </ul>\n" & - " </div>\n" & - " <div id=\"content\">\n" & - " " & $(content) & "\n" & - " A dollar: $.\n" & - " </div>\n" & + result.add(" </ul>\n" & + " </div>\n" & + " <div id=\"content\">\n" & + " " & $(content) & "\n" & + " A dollar: $.\n" & + " </div>\n" & "</body>\n") - + Each line that does not start with the meta character (ignoring leading -whitespace) is converted to a string literal that is added to ``result``. +whitespace) is converted to a string literal that is added to ``result``. The substitution character introduces a Nim expression *e* within the string literal. *e* is converted to a string with the *toString* operation @@ -172,16 +173,16 @@ produces ``$``. The template engine is quite flexible. It is easy to produce a procedure that writes the template code directly to a file:: - #! stdtmpl(emit="f.write") | standard + #? stdtmpl(emit="f.write") | standard #proc writeHTMLPage(f: File, title, currentTab, content: string, - # tabs: openArray[string]) = + # tabs: openArray[string]) = <head><title>$title</title></head> <body> <div id="menu"> <ul> #for tab in items(tabs): #if currentTab == tab: - <li><a id="selected" + <li><a id="selected" #else: <li><a #end if diff --git a/doc/gc.txt b/doc/gc.txt index f51421bcd..4ada88d2f 100644 --- a/doc/gc.txt +++ b/doc/gc.txt @@ -37,13 +37,13 @@ The cycle collector can be en-/disabled independently from the other parts of the GC with ``GC_enableMarkAndSweep`` and ``GC_disableMarkAndSweep``. The compiler analyses the types for their possibility to build cycles, but often it is necessary to help this analysis with the ``acyclic`` pragma (see -`acyclic <manual.html#acyclic-pragma>`_ for further information). +`acyclic <manual.html#acyclic-pragma>`_ for further information). -You can also use the ``acyclic`` pragma for data that is cyclic in reality and +You can also use the ``acyclic`` pragma for data that is cyclic in reality and then break up the cycles explicitly with ``GC_addCycleRoot``. This can be a -very valuable optimization; the Nim compiler itself relies on this +very valuable optimization; the Nim compiler itself relies on this optimization trick to improve performance. Note that ``GC_addCycleRoot`` is -a quick operation; the root is only registered for the next run of the +a quick operation; the root is only registered for the next run of the cycle collector. @@ -51,7 +51,7 @@ Realtime support ================ To enable realtime support, the symbol `useRealtimeGC`:idx: needs to be -defined via ``--define:useRealtimeGC`` (you can put this into your config +defined via ``--define:useRealtimeGC`` (you can put this into your config file as well). With this switch the GC supports the following operations: .. code-block:: nim @@ -60,21 +60,21 @@ file as well). With this switch the GC supports the following operations: The unit of the parameters ``MaxPauseInUs`` and ``us`` is microseconds. -These two procs are the two modus operandi of the realtime GC: +These two procs are the two modus operandi of the realtime GC: (1) GC_SetMaxPause Mode You can call ``GC_SetMaxPause`` at program startup and then each triggered - GC run tries to not take longer than ``MaxPause`` time. However, it is - possible (and common) that the work is nevertheless not evenly distributed - as each call to ``new`` can trigger the GC and thus take ``MaxPause`` + GC run tries to not take longer than ``MaxPause`` time. However, it is + possible (and common) that the work is nevertheless not evenly distributed + as each call to ``new`` can trigger the GC and thus take ``MaxPause`` time. (2) GC_step Mode This allows the GC to perform some work for up to ``us`` time. This is - useful to call in a main loop to ensure the GC can do its work. To - bind all GC activity to a ``GC_step`` call, deactivate the GC with + useful to call in a main loop to ensure the GC can do its work. To + bind all GC activity to a ``GC_step`` call, deactivate the GC with ``GC_disable`` at program startup. These procs provide a "best effort" realtime guarantee; in particular the @@ -87,7 +87,7 @@ is triggered. Time measurement ---------------- -The GC's way of measuring time uses (see ``lib/system/timers.nim`` for the +The GC's way of measuring time uses (see ``lib/system/timers.nim`` for the implementation): 1) ``QueryPerformanceCounter`` and ``QueryPerformanceFrequency`` on Windows. @@ -95,7 +95,7 @@ implementation): 3) ``gettimeofday`` on Posix systems. As such it supports a resolution of nanoseconds internally; however the API -uses microseconds for convenience. +uses microseconds for convenience. Define the symbol ``reportMissedDeadlines`` to make the GC output whenever it @@ -106,7 +106,7 @@ later versions of the collector. Tweaking the GC --------------- -The collector checks whether there is still time left for its work after +The collector checks whether there is still time left for its work after every ``workPackage``'th iteration. This is currently set to 100 which means that up to 100 objects are traversed and freed before it checks again. Thus ``workPackage`` affects the timing granularity and may need to be tweaked in diff --git a/doc/grammar.txt b/doc/grammar.txt index b53515495..72dc6c974 100644 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -179,7 +179,7 @@ simpleStmt = ((returnStmt | raiseStmt | yieldStmt | discardStmt | breakStmt | continueStmt | pragmaStmt | importStmt | exportStmt | fromStmt | includeStmt | commentStmt) / exprStmt) COMMENT? complexOrSimpleStmt = (ifStmt | whenStmt | whileStmt - | tryStmt | finallyStmt | exceptStmt | forStmt + | tryStmt | forStmt | blockStmt | staticStmt | deferStmt | asmStmt | 'proc' routine | 'method' routine diff --git a/doc/intern.txt b/doc/intern.txt index 9582fc96f..05847169f 100644 --- a/doc/intern.txt +++ b/doc/intern.txt @@ -22,8 +22,8 @@ Path Purpose ``bin`` generated binary files ``build`` generated C code for the installation ``compiler`` the Nim compiler itself; note that this - code has been translated from a bootstrapping - version written in Pascal, so the code is **not** + code has been translated from a bootstrapping + version written in Pascal, so the code is **not** a poster child of good Nim code ``config`` configuration files for Nim ``dist`` additional packages for the distribution @@ -38,8 +38,8 @@ Path Purpose Bootstrapping the compiler ========================== -As of version 0.8.5 the compiler is maintained in Nim. (The first versions -have been implemented in Object Pascal.) The Python-based build system has +As of version 0.8.5 the compiler is maintained in Nim. (The first versions +have been implemented in Object Pascal.) The Python-based build system has been rewritten in Nim too. Compiling the compiler is a simple matter of running:: @@ -121,7 +121,7 @@ Look at the file ``lib/system/hti.nim`` for more information. Debugging the compiler ====================== -You can of course use GDB or Visual Studio to debug the +You can of course use GDB or Visual Studio to debug the compiler (via ``--debuginfo --lineDir:on``). However, there are also lots of procs that aid in debugging: @@ -180,7 +180,7 @@ children. Types and symbols are represented by other nodes, because they may contain cycles. The AST changes its shape after semantic checking. This is needed to make life easier for the code generators. See the "ast" module for the type definitions. The `macros <macros.html>`_ module contains many -examples how the AST represents each syntactic structure. +examples how the AST represents each syntactic structure. How the RTL is compiled @@ -202,7 +202,7 @@ Compilation cache ================= The implementation of the compilation cache is tricky: There are lots -of issues to be solved for the front- and backend. In the following +of issues to be solved for the front- and backend. In the following sections *global* means *shared between modules* or *property of the whole program*. @@ -214,31 +214,31 @@ Methods and type converters ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Nim contains language features that are *global*. The best example for that -are multi methods: Introducing a new method with the same name and some +are multi methods: Introducing a new method with the same name and some compatible object parameter means that the method's dispatcher needs to take the new method into account. So the dispatching logic is only completely known after the whole program has been translated! -Other features that are *implicitly* triggered cause problems for modularity +Other features that are *implicitly* triggered cause problems for modularity too. Type converters fall into this category: .. code-block:: nim # module A converter toBool(x: int): bool = result = x != 0 - + .. code-block:: nim # module B import A - + if 1: echo "ugly, but should work" If in the above example module ``B`` is re-compiled, but ``A`` is not then ``B`` needs to be aware of ``toBool`` even though ``toBool`` is not referenced -in ``B`` *explicitly*. +in ``B`` *explicitly*. -Both the multi method and the type converter problems are solved by storing +Both the multi method and the type converter problems are solved by storing them in special sections in the ROD file that are loaded *unconditionally* when the ROD file is read. @@ -266,7 +266,7 @@ Backend issues - Emulated thread vars are global. -However the biggest problem is that dead code elimination breaks modularity! +However the biggest problem is that dead code elimination breaks modularity! To see why, consider this scenario: The module ``G`` (for example the huge Gtk2 module...) is compiled with dead code elimination turned on. So none of ``G``'s procs is generated at all. @@ -274,13 +274,13 @@ of ``G``'s procs is generated at all. Then module ``B`` is compiled that requires ``G.P1``. Ok, no problem, ``G.P1`` is loaded from the symbol file and ``G.c`` now contains ``G.P1``. -Then module ``A`` (that depends onto ``B`` and ``G``) is compiled and ``B`` +Then module ``A`` (that depends onto ``B`` and ``G``) is compiled and ``B`` and ``G`` are left unchanged. ``A`` requires ``G.P2``. -So now ``G.c`` MUST contain both ``P1`` and ``P2``, but we haven't even -loaded ``P1`` from the symbol file, nor do we want to because we then quickly -would restore large parts of the whole program. But we also don't want to -store ``P1`` in ``B.c`` because that would mean to store every symbol where +So now ``G.c`` MUST contain both ``P1`` and ``P2``, but we haven't even +loaded ``P1`` from the symbol file, nor do we want to because we then quickly +would restore large parts of the whole program. But we also don't want to +store ``P1`` in ``B.c`` because that would mean to store every symbol where it is referred from which ultimately means the main module and putting everything in a single C file. @@ -290,7 +290,7 @@ that is implemented in the C code generator (have a look at the ``ccgmerge`` module). The merging may lead to *cruft* (aka dead code) in generated C code which can only be removed by recompiling a project with the compilation cache turned off. Nevertheless the merge solution is way superior to the -cheap solution "turn off dead code elimination if the compilation cache is +cheap solution "turn off dead code elimination if the compilation cache is turned on". @@ -394,7 +394,7 @@ Consider this example: # r is on the stack setRef(r.left) # here we should update the refcounts! -We have to decide at runtime whether the reference is on the stack or not. +We have to decide at runtime whether the reference is on the stack or not. The generated code looks roughly like this: .. code-block:: C @@ -422,7 +422,7 @@ Design A ``closure`` proc var can call ordinary procs of the default Nim calling convention. But not the other way round! A closure is implemented as a ``tuple[prc, env]``. ``env`` can be nil implying a call without a closure. -This means that a call through a closure generates an ``if`` but the +This means that a call through a closure generates an ``if`` but the interoperability is worth the cost of the ``if``. Thunk generation would be possible too, but it's slightly more effort to implement. @@ -430,7 +430,7 @@ Tests with GCC on Amd64 showed that it's really beneficical if the 'environment' pointer is passed as the last argument, not as the first argument. Proper thunk generation is harder because the proc that is to wrap -could stem from a complex expression: +could stem from a complex expression: .. code-block:: nim receivesClosure(returnsDefaultCC[i]) @@ -438,15 +438,15 @@ could stem from a complex expression: A thunk would need to call 'returnsDefaultCC[i]' somehow and that would require an *additional* closure generation... Ok, not really, but it requires to pass the function to call. So we'd end up with 2 indirect calls instead of one. -Another much more severe problem which this solution is that it's not GC-safe +Another much more severe problem which this solution is that it's not GC-safe to pass a proc pointer around via a generic ``ref`` type. Example code: .. code-block:: nim - proc add(x: int): proc (y: int): int {.closure.} = - return proc (y: int): int = + proc add(x: int): proc (y: int): int {.closure.} = + return proc (y: int): int = return x + y var add2 = add(2) @@ -458,16 +458,16 @@ This should produce roughly this code: type PEnv = ref object x: int # data - - proc anon(y: int, c: PClosure): int = + + proc anon(y: int, c: PClosure): int = return y + c.x - + proc add(x: int): tuple[prc, data] = var env: PEnv new env env.x = x result = (anon, env) - + var add2 = add(2) let tmp = if add2.data == nil: add2.prc(5) else: add2.prc(5, add2.data) echo tmp @@ -476,9 +476,9 @@ This should produce roughly this code: Beware of nesting: .. code-block:: nim - proc add(x: int): proc (y: int): proc (z: int): int {.closure.} {.closure.} = - return lamba (y: int): proc (z: int): int {.closure.} = - return lambda (z: int): int = + proc add(x: int): proc (y: int): proc (z: int): int {.closure.} {.closure.} = + return lamba (y: int): proc (z: int): int {.closure.} = + return lambda (z: int): int = return x + y + z var add24 = add(2)(4) @@ -490,26 +490,26 @@ This should produce roughly this code: type PEnvX = ref object x: int # data - + PEnvY = ref object y: int ex: PEnvX - + proc lambdaZ(z: int, ey: PEnvY): int = return ey.ex.x + ey.y + z - + proc lambdaY(y: int, ex: PEnvX): tuple[prc, data: PEnvY] = var ey: PEnvY new ey ey.y = y ey.ex = ex result = (lambdaZ, ey) - + proc add(x: int): tuple[prc, data: PEnvX] = var ex: PEnvX ex.x = x result = (labmdaY, ex) - + var tmp = add(2) var tmp2 = tmp.fn(4, tmp.data) var add24 = tmp2.fn(4, tmp2.data) @@ -517,14 +517,14 @@ This should produce roughly this code: We could get rid of nesting environments by always inlining inner anon procs. -More useful is escape analysis and stack allocation of the environment, +More useful is escape analysis and stack allocation of the environment, however. Alternative ----------- -Process the closure of all inner procs in one pass and accumulate the +Process the closure of all inner procs in one pass and accumulate the environments. This is however not always possible. @@ -532,21 +532,21 @@ Accumulator ----------- .. code-block:: nim - proc getAccumulator(start: int): proc (): int {.closure} = + proc getAccumulator(start: int): proc (): int {.closure} = var i = start - return lambda: int = + return lambda: int = inc i return i - + proc p = var delta = 7 proc accumulator(start: int): proc(): int = var x = start-1 - result = proc (): int = + result = proc (): int = x = x + delta inc delta return x - + var a = accumulator(3) var b = accumulator(4) echo a() + b() @@ -560,7 +560,7 @@ pass generates code to setup the environment and to pass it around. However, this pass does not change the types! So we have some kind of mismatch here; on the one hand the proc expression becomes an explicit tuple, on the other hand the tyProc(ccClosure) type is not changed. For C code generation it's also -important the hidden formal param is ``void*`` and not something more +important the hidden formal param is ``void*`` and not something more specialized. However the more specialized env type needs to passed to the backend somehow. We deal with this by modifying ``s.ast[paramPos]`` to contain the formal hidden parameter, but not ``s.typ``! diff --git a/doc/koch.txt b/doc/koch.txt index 7da137458..a58d386ea 100644 --- a/doc/koch.txt +++ b/doc/koch.txt @@ -71,7 +71,7 @@ options: are limited to pure Nim code at compilation time. Enabling this switch will allow macros to execute non-nim code at compilation time (eg. open a file and write to it). ---gc:refc|v2|markAndSweep|boehm|none +--gc:refc|v2|markAndSweep|boehm|go|none Selects which garbage collection strategy to use for the compiler and generated code. See the `Nim's Garbage Collector <gc.html>`_ documentation for more information. diff --git a/doc/lib.txt b/doc/lib.txt index 385e7a91a..3dc58eebf 100644 --- a/doc/lib.txt +++ b/doc/lib.txt @@ -35,17 +35,12 @@ Core implicitly by the compiler. Do not import it directly. It relies on compiler magic to work. -* `unsigned <unsigned.html>`_ - This module implements basic arithmetic operators for unsigned integers. - To discourage users from using unsigned integers, it's not part - of ``system``, but an extra import. - * `threads <threads.html>`_ Nim thread support. **Note**: This is part of the system module. Do not import it explicitly. * `channels <channels.html>`_ - Nim message passing support for threads. **Note**: This is part of the + Nim message passing support for threads. **Note**: This is part of the system module. Do not import it explicitly. * `locks <locks.html>`_ @@ -55,7 +50,7 @@ Core Contains the AST API and documentation of Nim for writing macros. * `typeinfo <typeinfo.html>`_ - Provides (unsafe) access to Nim's run time type information. + Provides (unsafe) access to Nim's run time type information. * `typetraits <typetraits.html>`_ This module defines compile-time reflection procs for working with types. @@ -110,9 +105,9 @@ String handling * `unicode <unicode.html>`_ This module provides support to handle the Unicode UTF-8 encoding. - + * `encodings <encodings.html>`_ - Converts between different character encodings. On UNIX, this uses + Converts between different character encodings. On UNIX, this uses the ``iconv`` library, on Windows the Windows API. * `pegs <pegs.html>`_ @@ -123,16 +118,11 @@ String handling Ropes can represent very long strings efficiently; especially concatenation is done in O(1) instead of O(n). -* `unidecode <unidecode.html>`_ - This module provides Unicode to ASCII transliterations: - It finds the sequence of ASCII characters that is the closest approximation - to the Unicode string. - * `matchers <matchers.html>`_ This module contains various string matchers for email addresses, etc. * `subexes <subexes.html>`_ - This module implements advanted string substitution operations. + This module implements advanced string substitution operations. Generic Operating System Services @@ -159,7 +149,7 @@ Generic Operating System Services may provide other implementations for this standard stream interface. * `marshal <marshal.html>`_ - Contains procs for serialization and deseralization of arbitrary Nim + Contains procs for serialization and deseralization of arbitrary Nim data structures. * `terminal <terminal.html>`_ @@ -168,7 +158,7 @@ Generic Operating System Services sequences and does not depend on any other module. * `memfiles <memfiles.html>`_ - This module provides support for memory mapped files (Posix's ``mmap``) + This module provides support for memory mapped files (Posix's ``mmap``) on the different operating systems. * `fsmonitor <fsmonitor.html>`_ @@ -211,12 +201,6 @@ Internet Protocols and Support * `scgi <scgi.html>`_ This module implements helpers for SCGI applications. -* `sockets <sockets.html>`_ - This module implements a simple portable type-safe sockets layer. - -* `asyncio <asyncio.html>`_ - This module implements an asynchronous event loop for sockets. - * `browsers <browsers.html>`_ This module implements procs for opening URLs with the user's default browser. @@ -228,10 +212,7 @@ Internet Protocols and Support This module implements a simple HTTP client. * `smtp <smtp.html>`_ - This module implement a simple SMTP client. - -* `ftpclient <ftpclient.html>`_ - This module implements an FTP client. + This module implement a simple SMTP client. * `cookies <cookies.html>`_ This module contains helper procs for parsing and generating cookies. @@ -263,7 +244,7 @@ Internet Protocols and Support This module implements a high-level sockets API. It will replace the ``sockets`` module in the future. -* `rawsockets <rawsockets.html>`_ +* `nativesockets <nativesockets.html>`_ This module implements a low-level sockets API. * `selectors <selectors.html>`_ @@ -275,8 +256,6 @@ Parsers * `parseopt <parseopt.html>`_ The ``parseopt`` module implements a command line option parser. - **Deprecated since version 0.9.3:** Use the `parseopt2 - <parseopt2.html>`_ module instead. * `parseopt2 <parseopt2.html>`_ The ``parseopt2`` module implements a command line option parser. This @@ -325,6 +304,10 @@ Parsers * `rstgen <rstgen.html>`_ This module implements a generator of HTML/Latex from reStructuredText. +* `sexp <sexp.html>`_ + High performance sexp parser and generator, mainly for communication + with emacs. + XML Processing -------------- @@ -346,7 +329,7 @@ XML Processing This module parses an HTML document and creates its XML tree representation. * `htmlgen <htmlgen.html>`_ - This module implements a simple XML and HTML code + This module implements a simple XML and HTML code generator. Each commonly used HTML tag has a corresponding macro that generates a string with its HTML representation. @@ -381,7 +364,7 @@ Miscellaneous * `oids <oids.html>`_ An OID is a global ID that consists of a timestamp, - a unique counter and a random value. This combination should suffice to + a unique counter and a random value. This combination should suffice to produce a globally distributed unique ID. This implementation was extracted from the Mongodb interface and it thus binary compatible with a Mongo OID. @@ -395,13 +378,6 @@ Miscellaneous This module implements new experimental features. Currently the syntax sugar for anonymous procedures. -Database support ----------------- - -* `redis <redis.html>`_ - This module implements a redis client. It allows you to connect to a - redis-server instance, send commands and receive replies. - Modules for JS backend --------------------------- @@ -410,6 +386,31 @@ Modules for JS backend Declaration of the Document Object Model for the JS backend. +Deprecated modules +------------------ + +* `asyncio <asyncio.html>`_ + This module implements an asynchronous event loop for sockets. + **Deprecated since version 0.11.2:** + Use the `asyncnet <asyncnet.html>`_ together with the + `asyncdispatch <asyncdispatch.html>`_ module instead. + +* `ftpclient <ftpclient.html>`_ + This module implements an FTP client. + **Deprecated since version 0.11.3:** + Use the `asyncftpclient <asyncftpclient.html>`_ module instead. + +* `sockets <sockets.html>`_ + This module implements a simple portable type-safe sockets layer. + **Deprecated since version 0.11.2:** + Use the `net <net.html>`_ or the `rawsockets <rawsockets.html>`_ module + instead. + +* `rawsockets <rawsockets.html>`_ + **Deprecated since version 0.11.4:** + This module has been renamed to `nativesockets <nativesockets.html>`_. + + Impure libraries ================ @@ -440,31 +441,10 @@ Database support Other ----- -* `graphics <graphics.html>`_ - This module implements graphical output for Nim; the current - implementation uses SDL but the interface is meant to support multiple - backends some day. - -* `dialogs <dialogs.html>`_ - This module implements portable dialogs for Nim; the implementation - builds on the GTK interface. On Windows, native dialogs are shown if - appropriate. - -* `zipfiles <zipfiles.html>`_ - This module implements a zip archive creator/reader/modifier. - -* `web <web.html>`_ - This module contains simple high-level procedures for dealing with the - Web like loading the contents of a Web page from an URL. - * `ssl <ssl.html>`_ - This module provides an easy to use sockets-style + This module provides an easy to use sockets-style Nim interface to the OpenSSL library. -* `rdstdin <rdstdin.html>`_ - This module contains code for reading from `stdin`:idx:. On UNIX the GNU - readline library is wrapped and set up. - Wrappers ======== @@ -475,20 +455,8 @@ not contained in the distribution. You can then find them on the website. Windows specific ---------------- -* `windows <windows.html>`_ - Contains a wrapper for the Win32 API. * `winlean <winlean.html>`_ Contains a wrapper for a small subset of the Win32 API. -* `shellapi <shellapi.html>`_ - Contains a wrapper for the ``shellapi.h`` header. -* `shfolder <shfolder.html>`_ - Contains a wrapper for the ``shfolder.h`` header. -* `mmsystem <mmsystem.html>`_ - Contains a wrapper for the ``mmsystem.h`` header. -* `psapi <psapi.html>`_ - Contains a wrapper for the ``psapi.h`` header. -* `nb30 <nb30.html>`_ - This module contains the definitions for portable NetBIOS 3.0 support. UNIX specific @@ -496,12 +464,6 @@ UNIX specific * `posix <posix.html>`_ Contains a wrapper for the POSIX standard. -* `readline <readline.html>`_ - Part of the wrapper for the GNU readline library. -* `history <history.html>`_ - Part of the wrapper for the GNU readline library. -* `rltypedefs <rltypedefs.html>`_ - Part of the wrapper for the GNU readline library. Regular expressions @@ -509,27 +471,6 @@ Regular expressions * `pcre <pcre.html>`_ Wrapper for the PCRE library. -* `tre <tre.html>`_ - Wrapper for the TRE library. - - -Graphics libraries ------------------- - -* `sdl <sdl.html>`_ - Part of the wrapper for SDL. -* `sdl_gfx <sdl_gfx.html>`_ - Part of the wrapper for SDL. -* `sdl_image <sdl_image.html>`_ - Part of the wrapper for SDL. -* `sdl_mixer <sdl_mixer.html>`_ - Part of the wrapper for SDL. -* `sdl_net <sdl_net.html>`_ - Part of the wrapper for SDL. -* `sdl_ttf <sdl_ttf.html>`_ - Part of the wrapper for SDL. -* `smpeg <smpeg.html>`_ - Part of the wrapper for SDL. GUI libraries @@ -550,15 +491,6 @@ Database support Contains a wrapper for SQLite 3 API. * `odbcsql <odbcsql.html>`_ interface to the ODBC driver. -* `sphinx <sphinx.html>`_ - Nim wrapper for ``sphinx``. - - -XML Processing --------------- - -* `expat <expat.html>`_ - Wrapper of the expat XML parser. Network Programming and Internet Protocols @@ -577,25 +509,16 @@ Network Programming and Internet Protocols Wrapper for OpenSSL. -Data Compression and Archiving ------------------------------- - -* `zlib <zlib.html>`_ - Wrapper for the zlib library. - -* `libzip <libzip.html>`_ - Interface to the `lib zip <http://www.nih.at/libzip/index.html>`_ library by - Dieter Baron and Thomas Klausner. - Scientific computing -------------------- -* `libsvm <libsvm.html>`_ +* `libsvm <libsvm.html>`_ Low level wrapper for `lib svm <http://www.csie.ntu.edu.tw/~cjlin/libsvm/>`_. + Nimble -==================== +====== Nimble is a package manager for the Nim programming language. For instructions on how to install Nimble packages see diff --git a/doc/manual/about.txt b/doc/manual/about.txt index 78167efe3..58e3baa85 100644 --- a/doc/manual/about.txt +++ b/doc/manual/about.txt @@ -1,37 +1,37 @@ About this document =================== -**Note**: This document is a draft! Several of Nim's features need more -precise wording. This manual will evolve into a proper specification some -day. +**Note**: This document is a draft! Several of Nim's features may need more +precise wording. This manual is constantly evolving until the 1.0 release and is +not to be considered as the final proper specification. This document describes the lexis, the syntax, and the semantics of Nim. -The language constructs are explained using an extended BNF, in -which ``(a)*`` means 0 or more ``a``'s, ``a+`` means 1 or more ``a``'s, and -``(a)?`` means an optional *a*. Parentheses may be used to group elements. +The language constructs are explained using an extended BNF, in which ``(a)*`` +means 0 or more ``a``'s, ``a+`` means 1 or more ``a``'s, and ``(a)?`` means an +optional *a*. Parentheses may be used to group elements. ``&`` is the lookahead operator; ``&a`` means that an ``a`` is expected but not consumed. It will be consumed in the following rule. -The ``|``, ``/`` symbols are used to mark alternatives and have the lowest -precedence. ``/`` is the ordered choice that requires the parser to try the +The ``|``, ``/`` symbols are used to mark alternatives and have the lowest +precedence. ``/`` is the ordered choice that requires the parser to try the alternatives in the given order. ``/`` is often used to ensure the grammar -is not ambiguous. +is not ambiguous. Non-terminals start with a lowercase letter, abstract terminal symbols are in UPPERCASE. Verbatim terminal symbols (including keywords) are quoted with ``'``. An example:: ifStmt = 'if' expr ':' stmts ('elif' expr ':' stmts)* ('else' stmts)? - + The binary ``^*`` operator is used as a shorthand for 0 or more occurrences -separated by its second argument; likewise ``^+`` means 1 or more -occurrences: ``a ^+ b`` is short for ``a (b a)*`` +separated by its second argument; likewise ``^+`` means 1 or more +occurrences: ``a ^+ b`` is short for ``a (b a)*`` and ``a ^* b`` is short for ``(a (b a)*)?``. Example:: arrayConstructor = '[' expr ^* ',' ']' Other parts of Nim - like scoping rules or runtime semantics are only -described in an informal manner for now. +described in the, more easily comprehensible, informal manner for now. diff --git a/doc/manual/definitions.txt b/doc/manual/definitions.txt index 9eb20f70f..21954fb78 100644 --- a/doc/manual/definitions.txt +++ b/doc/manual/definitions.txt @@ -26,11 +26,11 @@ program execution. Unless explicitly classified, an error is a static error. A `checked runtime error`:idx: is an error that the implementation detects and reports at runtime. The method for reporting such errors is via *raising -exceptions* or *dying with a fatal error*. However, the implementation +exceptions* or *dying with a fatal error*. However, the implementation provides a means to disable these runtime checks. See the section pragmas_ -for details. +for details. -Wether a checked runtime error results in an exception or in a fatal error at +Whether a checked runtime error results in an exception or in a fatal error at runtime is implementation specific. Thus the following program is always invalid: diff --git a/doc/manual/effects.txt b/doc/manual/effects.txt index a79f6ea85..254a43fbb 100644 --- a/doc/manual/effects.txt +++ b/doc/manual/effects.txt @@ -5,7 +5,7 @@ Exception tracking ------------------ Nim supports exception tracking. The `raises`:idx: pragma can be used -to explicitly define which exceptions a proc/iterator/method/converter is +to explicitly define which exceptions a proc/iterator/method/converter is allowed to raise. The compiler verifies this: .. code-block:: nim @@ -24,7 +24,7 @@ An empty ``raises`` list (``raises: []``) means that no exception may be raised: result = false -A ``raises`` list can also be attached to a proc type. This affects type +A ``raises`` list can also be attached to a proc type. This affects type compatibility: .. code-block:: nim @@ -35,7 +35,7 @@ compatibility: proc p(x: string) = raise newException(OSError, "OS") - + c = p # type error @@ -46,30 +46,30 @@ possibly raised exceptions; the algorithm operates on ``p``'s call graph: raise ``system.Exception`` (the base type of the exception hierarchy) and thus any exception unless ``T`` has an explicit ``raises`` list. However if the call is of the form ``f(...)`` where ``f`` is a parameter - of the currently analysed routine it is ignored. The call is optimistically + of the currently analysed routine it is ignored. The call is optimistically assumed to have no effect. Rule 2 compensates for this case. -2. Every expression of some proc type wihtin a call that is not a call - itself (and not nil) is assumed to be called indirectly somehow and thus +2. Every expression of some proc type within a call that is not a call + itself (and not nil) is assumed to be called indirectly somehow and thus its raises list is added to ``p``'s raises list. -3. Every call to a proc ``q`` which has an unknown body (due to a forward - declaration or an ``importc`` pragma) is assumed to +3. Every call to a proc ``q`` which has an unknown body (due to a forward + declaration or an ``importc`` pragma) is assumed to raise ``system.Exception`` unless ``q`` has an explicit ``raises`` list. -4. Every call to a method ``m`` is assumed to +4. Every call to a method ``m`` is assumed to raise ``system.Exception`` unless ``m`` has an explicit ``raises`` list. 5. For every other call the analysis can determine an exact ``raises`` list. -6. For determining a ``raises`` list, the ``raise`` and ``try`` statements +6. For determining a ``raises`` list, the ``raise`` and ``try`` statements of ``p`` are taken into consideration. -Rules 1-2 ensure the following works: +Rules 1-2 ensure the following works: .. code-block:: nim proc noRaise(x: proc()) {.raises: [].} = # unknown call that might raise anything, but valid: x() - + proc doRaise() {.raises: [IOError].} = raise newException(IOError, "IO") - + proc use() {.raises: [].} = # doesn't compile! Can raise IOError! noRaise(doRaise) @@ -82,21 +82,21 @@ Tag tracking ------------ The exception tracking is part of Nim's `effect system`:idx:. Raising an -exception is an *effect*. Other effects can also be defined. A user defined +exception is an *effect*. Other effects can also be defined. A user defined effect is a means to *tag* a routine and to perform checks against this tag: .. code-block:: nim type IO = object ## input/output effect proc readLine(): string {.tags: [IO].} - + proc no_IO_please() {.tags: [].} = # the compiler prevents this: let x = readLine() -A tag has to be a type name. A ``tags`` list - like a ``raises`` list - can +A tag has to be a type name. A ``tags`` list - like a ``raises`` list - can also be attached to a proc type. This affects type compatibility. -The inference for tag tracking is analogous to the inference for +The inference for tag tracking is analogous to the inference for exception tracking. @@ -105,7 +105,7 @@ Read/Write tracking **Note**: Read/write tracking is not yet implemented! -The inference for read/write tracking is analogous to the inference for +The inference for read/write tracking is analogous to the inference for exception tracking. diff --git a/doc/manual/ffi.txt b/doc/manual/ffi.txt index 4a4e0316f..f9056b159 100644 --- a/doc/manual/ffi.txt +++ b/doc/manual/ffi.txt @@ -70,8 +70,8 @@ the compiler to pass the type by reference (hidden pointer) to procs. Varargs pragma -------------- -The ``varargs`` pragma can be applied to procedures only (and procedure -types). It tells Nim that the proc can take a variable number of parameters +The ``varargs`` pragma can be applied to procedures only (and procedure +types). It tells Nim that the proc can take a variable number of parameters after the last specified parameter. Nim string values will be converted to C strings automatically: @@ -94,20 +94,20 @@ should scan unions conservatively. Packed pragma ------------- -The ``packed`` pragma can be applied to any ``object`` type. It ensures -that the fields of an object are packed back-to-back in memory. It is useful -to store packets or messages from/to network or hardware drivers, and for -interoperability with C. Combining packed pragma with inheritance is not -defined, and it should not be used with GC'ed memory (ref's). +The ``packed`` pragma can be applied to any ``object`` type. It ensures +that the fields of an object are packed back-to-back in memory. It is useful +to store packets or messages from/to network or hardware drivers, and for +interoperability with C. Combining packed pragma with inheritance is not +defined, and it should not be used with GC'ed memory (ref's). -**Future directions**: Using GC'ed memory in packed pragma will result in +**Future directions**: Using GC'ed memory in packed pragma will result in compile-time error. Usage with inheritance should be defined and documented. Unchecked pragma ---------------- The ``unchecked`` pragma can be used to mark a named array as ``unchecked`` -meaning its bounds are not checked. This is often useful when one wishes to -implement his own flexibly sized arrays. Additionally an unchecked array is +meaning its bounds are not checked. This is often useful to +implement customized flexibly sized arrays. Additionally an unchecked array is translated into a C array of undetermined size: .. code-block:: nim @@ -141,7 +141,7 @@ runtime size of the array. Dynlib pragma for import ------------------------ With the ``dynlib`` pragma a procedure or a variable can be imported from -a dynamic library (``.dll`` files for Windows, ``lib*.so`` files for UNIX). +a dynamic library (``.dll`` files for Windows, ``lib*.so`` files for UNIX). The non-optional argument has to be the name of the dynamic library: .. code-block:: Nim @@ -152,17 +152,17 @@ In general, importing a dynamic library does not require any special linker options or linking with import libraries. This also implies that no *devel* packages need to be installed. -The ``dynlib`` import mechanism supports a versioning scheme: +The ``dynlib`` import mechanism supports a versioning scheme: -.. code-block:: nim - proc Tcl_Eval(interp: pTcl_Interp, script: cstring): int {.cdecl, +.. code-block:: nim + proc Tcl_Eval(interp: pTcl_Interp, script: cstring): int {.cdecl, importc, dynlib: "libtcl(|8.5|8.4|8.3).so.(1|0)".} At runtime the dynamic library is searched for (in this order):: - + libtcl.so.1 libtcl.so.0 - libtcl8.5.so.1 + libtcl8.5.so.1 libtcl8.5.so.0 libtcl8.4.so.1 libtcl8.4.so.0 @@ -175,22 +175,22 @@ string expressions in general: .. code-block:: nim import os - proc getDllName: string = + proc getDllName: string = result = "mylib.dll" if existsFile(result): return result = "mylib2.dll" if existsFile(result): return quit("could not load dynamic library") - + proc myImport(s: cstring) {.cdecl, importc, dynlib: getDllName().} **Note**: Patterns like ``libtcl(|8.5|8.4).so`` are only supported in constant strings, because they are precompiled. -**Note**: Passing variables to the ``dynlib`` pragma will fail at runtime +**Note**: Passing variables to the ``dynlib`` pragma will fail at runtime because of order of initialization problems. -**Note**: A ``dynlib`` import can be overriden with +**Note**: A ``dynlib`` import can be overriden with the ``--dynlibOverride:name`` command line option. The Compiler User Guide contains further information. diff --git a/doc/manual/generics.txt b/doc/manual/generics.txt index cce3a8830..c6206d030 100644 --- a/doc/manual/generics.txt +++ b/doc/manual/generics.txt @@ -53,7 +53,7 @@ The following example shows a generic binary tree can be modelled: add(root, newNode("hallo")) # instantiates generic procs ``newNode`` and add(root, newNode("world")) # ``add`` for str in inorder(root): - writeln(stdout, str) + writeLine(stdout, str) Is operator @@ -116,7 +116,7 @@ type class matches ``array`` any array type ``set`` any set type ``seq`` any seq type -``auto`` any type +``any`` any type ================== =================================================== Furthermore, every generic type automatically creates a type class of the same @@ -163,13 +163,6 @@ module to illustrate this: 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. -If a proc param doesn't have a type specified, Nim will use the -``distinct auto`` type class (also known as ``any``): - -.. code-block:: nim - # allow any combination of param types - proc concat(a, b): string = $a & $b - Procs written with the implicitly generic style will often need to refer to the type parameters of the matched generic type. They can be easily accessed using the dot syntax: @@ -219,7 +212,7 @@ Concepts are written in the following form: (x < y) is bool Container[T] = concept c - c.len is ordinal + c.len is Ordinal items(c) is iterator for value in c: type(value) is T diff --git a/doc/manual/lexing.txt b/doc/manual/lexing.txt index e2f006f04..7f81ab422 100644 --- a/doc/manual/lexing.txt +++ b/doc/manual/lexing.txt @@ -25,7 +25,7 @@ a separate token. This trick allows parsing of Nim with only 1 token of lookahead. The parser uses a stack of indentation levels: the stack consists of integers -counting the spaces. The indentation information is queried at strategic +counting the spaces. The indentation information is queried at strategic places in the parser but ignored otherwise: The pseudo terminal ``IND{>}`` denotes an indentation that consists of more spaces than the entry at the top of the stack; IND{=} an indentation that has the same number of spaces. ``DED`` @@ -36,7 +36,7 @@ With this notation we can now easily define the core of the grammar: A block of statements (simplified example):: ifStmt = 'if' expr ':' stmt - (IND{=} 'elif' expr ':' stmt)* + (IND{=} 'elif' expr ':' stmt)* (IND{=} 'else' ':' stmt)? simpleStmt = ifStmt / ... @@ -80,7 +80,7 @@ underscores ``__`` are not allowed:: digit ::= '0'..'9' IDENTIFIER ::= letter ( ['_'] (letter | digit) )* -Currently any unicode character with an ordinal value > 127 (non ASCII) is +Currently any Unicode character with an ordinal value > 127 (non ASCII) is classified as a ``letter`` and may thus be part of an identifier but later versions of the language may assign some Unicode characters to belong to the operator characters instead. @@ -101,25 +101,28 @@ Two identifiers are considered equal if the following algorithm returns true: .. code-block:: nim proc sameIdentifier(a, b: string): bool = - a[0] == b[0] and a.replace("_", "").toLower == b.replace("_", "").toLower + a[0] == b[0] and + a.replace(re"_|–", "").toLower == b.replace(re"_|–", "").toLower That means only the first letters are compared in a case sensitive manner. Other -letters are compared case insensitively and underscores are ignored. +letters are compared case insensitively and underscores and en-dash (Unicode +point U+2013) are ignored. -This rather strange way to do identifier comparisons is called +This rather unorthodox way to do identifier comparisons is called `partial case insensitivity`:idx: and has some advantages over the conventional case sensitivity: It allows programmers to mostly use their own preferred -spelling style and libraries written by different programmers cannot use -incompatible conventions. A Nim-aware editor or IDE can show the identifiers as -preferred. Another advantage is that it frees the programmer from remembering +spelling style, be it humpStyle, snake_style or dash–style and libraries written +by different programmers cannot use incompatible conventions. +A Nim-aware editor or IDE can show the identifiers as preferred. +Another advantage is that it frees the programmer from remembering the exact spelling of an identifier. The exception with respect to the first letter allows common code like ``var foo: Foo`` to be parsed unambiguously. -Historically, Nim was a `style-insensitive`:idx: language. This means that it -was not case-sensitive and underscores were ignored and there was no distinction -between ``foo`` and ``Foo``. +Historically, Nim was a fully `style-insensitive`:idx: language. This meant that +it was not case-sensitive and underscores were ignored and there was no even a +distinction between ``foo`` and ``Foo``. String literals @@ -153,7 +156,7 @@ contain the following `escape sequences`:idx:\ : ================== =================================================== -Strings in Nim may contain any 8-bit value, even embedded zeros. However +Strings in Nim may contain any 8-bit value, even embedded zeros. However some operations may interpret the first binary zero as a terminator. @@ -171,7 +174,7 @@ be whitespace between the opening ``"""`` and the newline), the newline (and the preceding whitespace) is not included in the string. The ending of the string literal is defined by the pattern ``"""[^"]``, so this: -.. code-block:: nim +.. code-block:: nim """"long string within quotes"""" Produces:: @@ -184,9 +187,9 @@ Raw string literals Terminal symbol in the grammar: ``RSTR_LIT``. -There are also raw string literals that are preceded with the -letter ``r`` (or ``R``) and are delimited by matching double quotes (just -like ordinary string literals) and do not interpret the escape sequences. +There are also raw string literals that are preceded with the +letter ``r`` (or ``R``) and are delimited by matching double quotes (just +like ordinary string literals) and do not interpret the escape sequences. This is especially convenient for regular expressions or Windows paths: .. code-block:: nim @@ -198,21 +201,21 @@ To produce a single ``"`` within a raw string literal, it has to be doubled: .. code-block:: nim r"a""b" - + Produces:: - + a"b -``r""""`` is not possible with this notation, because the three leading -quotes introduce a triple quoted string literal. ``r"""`` is the same -as ``"""`` since triple quoted string literals do not interpret escape +``r""""`` is not possible with this notation, because the three leading +quotes introduce a triple quoted string literal. ``r"""`` is the same +as ``"""`` since triple quoted string literals do not interpret escape sequences either. Generalized raw string literals ------------------------------- -Terminal symbols in the grammar: ``GENERALIZED_STR_LIT``, +Terminal symbols in the grammar: ``GENERALIZED_STR_LIT``, ``GENERALIZED_TRIPLESTR_LIT``. The construct ``identifier"string literal"`` (without whitespace between the @@ -276,9 +279,9 @@ Numerical constants are of a single type and have the form:: bindigit = '0'..'1' HEX_LIT = '0' ('x' | 'X' ) hexdigit ( ['_'] hexdigit )* DEC_LIT = digit ( ['_'] digit )* - OCT_LIT = '0o' octdigit ( ['_'] octdigit )* + OCT_LIT = '0' ('o' | 'c' | 'C') octdigit ( ['_'] octdigit )* BIN_LIT = '0' ('b' | 'B' ) bindigit ( ['_'] bindigit )* - + INT_LIT = HEX_LIT | DEC_LIT | OCT_LIT @@ -289,7 +292,7 @@ Numerical constants are of a single type and have the form:: INT32_LIT = INT_LIT ['\''] ('i' | 'I') '32' INT64_LIT = INT_LIT ['\''] ('i' | 'I') '64' - UINT8_LIT = INT_LIT ['\''] ('u' | 'U') + UINT_LIT = INT_LIT ['\''] ('u' | 'U') UINT8_LIT = INT_LIT ['\''] ('u' | 'U') '8' UINT16_LIT = INT_LIT ['\''] ('u' | 'U') '16' UINT32_LIT = INT_LIT ['\''] ('u' | 'U') '32' @@ -297,15 +300,17 @@ Numerical constants are of a single type and have the form:: exponent = ('e' | 'E' ) ['+' | '-'] digit ( ['_'] digit )* FLOAT_LIT = digit (['_'] digit)* (('.' (['_'] digit)* [exponent]) |exponent) - FLOAT32_LIT = HEX_LIT '\'' ('f'|'F') '32' - | (FLOAT_LIT | DEC_LIT | OCT_LIT | BIN_LIT) ['\''] ('f'|'F') '32' - FLOAT64_LIT = HEX_LIT '\'' ('f'|'F') '64' - | (FLOAT_LIT | DEC_LIT | OCT_LIT | BIN_LIT) ['\''] ('f'|'F') '64' + FLOAT32_SUFFIX = ('f' | 'F') ['32'] + FLOAT32_LIT = HEX_LIT '\'' FLOAT32_SUFFIX + | (FLOAT_LIT | DEC_LIT | OCT_LIT | BIN_LIT) ['\''] FLOAT32_SUFFIX + FLOAT64_SUFFIX = ( ('f' | 'F') '64' ) | 'd' | 'D' + FLOAT64_LIT = HEX_LIT '\'' FLOAT64_SUFFIX + | (FLOAT_LIT | DEC_LIT | OCT_LIT | BIN_LIT) ['\''] FLOAT64_SUFFIX As can be seen in the productions, numerical constants can contain underscores for readability. Integer and floating point literals may be given in decimal (no -prefix), binary (prefix ``0b``), octal (prefix ``0o``) and hexadecimal +prefix), binary (prefix ``0b``), octal (prefix ``0o`` or ``0c``) and hexadecimal (prefix ``0x``) notation. There exists a literal for each numerical type that is @@ -331,8 +336,11 @@ The type suffixes are: ``'u16`` uint16 ``'u32`` uint32 ``'u64`` uint64 + ``'f`` float32 + ``'d`` float64 ``'f32`` float32 ``'f64`` float64 + ``'f128`` float128 ================= ========================= Floating point literals may also be in binary, octal or hexadecimal @@ -340,12 +348,18 @@ notation: ``0B0_10001110100_0000101001000111101011101111111011000101001101001001'f64`` is approximately 1.72826e35 according to the IEEE floating point standard. +Literals are bounds checked so that they fit the datatype. Non base-10 +literals are used mainly for flags and bit pattern representations, therefore +bounds checking is done on bit width, not value range. If the literal fits in +the bit width of the datatype, it is accepted. +Hence: 0b10000000'u8 == 0x80'u8 == 128, but, 0b10000000'i8 == 0x80'i8 == -1 +instead of causing an overflow error. Operators --------- -In Nim one can define his own operators. An operator is any -combination of the following characters:: +Nim allows user defined operators. An operator is any combination of the +following characters:: = + - * / < > @ $ ~ & % | @@ -355,7 +369,7 @@ These keywords are also operators: ``and or not xor shl shr div mod in notin is isnot of``. `=`:tok:, `:`:tok:, `::`:tok: are not available as general operators; they -are used for other notational purposes. +are used for other notational purposes. ``*:`` is as a special case the two tokens `*`:tok: and `:`:tok: (to support ``var v*: T``). @@ -369,7 +383,7 @@ The following strings denote other tokens:: ` ( ) { } [ ] , ; [. .] {. .} (. .) -The `slice`:idx: operator `..`:tok: takes precedence over other tokens that -contain a dot: `{..}`:tok: are the three tokens `{`:tok:, `..`:tok:, `}`:tok: +The `slice`:idx: operator `..`:tok: takes precedence over other tokens that +contain a dot: `{..}`:tok: are the three tokens `{`:tok:, `..`:tok:, `}`:tok: and not the two tokens `{.`:tok:, `.}`:tok:. diff --git a/doc/manual/locking.txt b/doc/manual/locking.txt index 864eeccb5..b14c98636 100644 --- a/doc/manual/locking.txt +++ b/doc/manual/locking.txt @@ -63,7 +63,7 @@ model low level lockfree mechanisms: .. code-block:: nim var dummyLock {.compileTime.}: int var atomicCounter {.guard: dummyLock.}: int - + template atomicRead(x): expr = {.locks: [dummyLock].}: memoryReadBarrier() @@ -135,30 +135,30 @@ Lock levels are used to enforce a global locking order in order to prevent deadlocks at compile-time. A lock level is an constant integer in the range 0..1_000. Lock level 0 means that no lock is acquired at all. -If a section of code holds a lock of level ``M`` than it can also acquire any +If a section of code holds a lock of level ``M`` than it can also acquire any lock of level ``N < M``. Another lock of level ``M`` cannot be acquired. Locks -of the same level can only be acquired *at the same time* within a +of the same level can only be acquired *at the same time* within a single ``locks`` section: .. code-block:: nim var a, b: TLock[2] var x: TLock[1] # invalid locking order: TLock[1] cannot be acquired before TLock[2]: - {.locks: [x].}: + {.locks: [x].}: {.locks: [a].}: ... # valid locking order: TLock[2] acquired before TLock[1]: - {.locks: [a].}: + {.locks: [a].}: {.locks: [x].}: ... # invalid locking order: TLock[2] acquired before TLock[2]: - {.locks: [a].}: + {.locks: [a].}: {.locks: [b].}: ... # valid locking order, locks of the same level acquired at the same time: - {.locks: [a, b].}: + {.locks: [a, b].}: ... @@ -187,7 +187,7 @@ level. This then means that the routine may acquire locks of up to this level. This is essential so that procs can be called within a ``locks`` section: .. code-block:: nim - proc p() {.locks: 3.} = discard + proc p() {.locks: 3.} = discard var a: TLock[4] {.locks: [a].}: @@ -195,6 +195,6 @@ This is essential so that procs can be called within a ``locks`` section: p() -As usual ``locks`` is an inferred effect and there is a subtype +As usual ``locks`` is an inferred effect and there is a subtype relation: ``proc () {.locks: N.}`` is a subtype of ``proc () {.locks: M.}`` iff (M <= N). diff --git a/doc/manual/modules.txt b/doc/manual/modules.txt index 70f6026b2..e6a08b5ce 100644 --- a/doc/manual/modules.txt +++ b/doc/manual/modules.txt @@ -81,8 +81,8 @@ A module alias can be introduced via the ``as`` keyword: echo su.format("$1", "lalelu") -The original module name is then not accessible. The -notations ``path/to/module`` or ``path.to.module`` or ``"path/to/module"`` +The original module name is then not accessible. The +notations ``path/to/module`` or ``path.to.module`` or ``"path/to/module"`` can be used to refer to a module in subdirectories: .. code-block:: nim @@ -104,7 +104,7 @@ Likewise the following does not make sense as the name is ``strutils`` already: From import statement ~~~~~~~~~~~~~~~~~~~~~ -After the ``from`` statement a module name follows followed by +After the ``from`` statement a module name follows followed by an ``import`` to list the symbols one likes to use without explict full qualification: @@ -115,8 +115,8 @@ full qualification: # always possible: full qualification: echo strutils.replace("abc", "a", "z") -It's also possible to use ``from module import nil`` if one wants to import -the module but wants to enforce fully qualified access to every symbol +It's also possible to use ``from module import nil`` if one wants to import +the module but wants to enforce fully qualified access to every symbol in ``module``. @@ -134,18 +134,26 @@ modules don't need to import a module's dependencies: # module A import B export B.MyObject - + proc `$`*(x: MyObject): string = "my object" .. code-block:: nim # module C import A - - # B.MyObject has been imported implicitly here: + + # B.MyObject has been imported implicitly here: var x: MyObject echo($x) +Note on paths +----------- +In module related statements, if any part of the module name / +path begins with a number, you may have to quote it in double quotes. +In the following example, it would be seen as a literal number '3.0' of type +'float64' if not quoted, if uncertain - quote it: +.. code-block:: nim + import "gfx/3d/somemodule" Scope rules ----------- @@ -177,9 +185,8 @@ following places: Module scope ~~~~~~~~~~~~ All identifiers of a module are valid from the point of declaration until -the end of the module. Identifiers from indirectly dependent modules are *not* -available. The `system`:idx: module is automatically imported in every other -module. +the end of the module. Identifiers from indirectly dependent modules are *not* +available. The `system`:idx: module is automatically imported in every module. If a module imports an identifier by two different modules, each occurrence of the identifier has to be qualified, unless it is an overloaded procedure or diff --git a/doc/manual/pragmas.txt b/doc/manual/pragmas.txt index 46fd89b13..f89194c9a 100644 --- a/doc/manual/pragmas.txt +++ b/doc/manual/pragmas.txt @@ -18,9 +18,7 @@ The deprecated pragma is used to mark a symbol as deprecated: proc p() {.deprecated.} var x {.deprecated.}: char -It can also be used as a statement. Then it takes a list of *renamings*. The -upcoming ``nimfix`` tool can automatically update the code and perform these -renamings: +It can also be used as a statement, in that case it takes a list of *renamings*. .. code-block:: nim type @@ -28,6 +26,9 @@ renamings: Stream = ref object {.deprecated: [TFile: File, PStream: Stream].} +The ``nimfix`` tool can be used to, without effort, automatically update your +code and refactor it by performing these renamings. + noSideEffect pragma ------------------- @@ -54,9 +55,7 @@ destructor pragma ----------------- The ``destructor`` pragma is used to mark a proc to act as a type destructor. -Its usage is deprecated, use the ``override`` pragma instead. -See `type bound operations`_. - +Its usage is deprecated, See `type bound operations`_ instead. override pragma --------------- @@ -71,9 +70,21 @@ procedural variable. compileTime pragma ------------------ -The ``compileTime`` pragma is used to mark a proc to be used at compile -time only. No code will be generated for it. Compile time procs are useful -as helpers for macros. +The ``compileTime`` pragma is used to mark a proc or variable to be used at +compile time only. No code will be generated for it. Compile time procs are +useful as helpers for macros. Since version 0.12.0 of the language, a proc +that uses ``system.NimNode`` within its parameter types is implictly declared +``compileTime``: + +.. code-block:: nim + proc astHelper(n: NimNode): NimNode = + result = n + +Is the same as: + +.. code-block:: nim + proc astHelper(n: NimNode): NimNode {.compileTime.} = + result = n noReturn pragma @@ -372,7 +383,7 @@ The ``register`` pragma is for variables only. It declares the variable as in a hardware register for faster access. C compilers usually ignore this though and for good reasons: Often they do a better job without it anyway. -In highly specific cases (a dispatch loop of an bytecode interpreter for +In highly specific cases (a dispatch loop of a bytecode interpreter for example) it may provide benefits, though. @@ -430,13 +441,13 @@ Example: 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 + of the symbols may include other call expressions, whose types will be resolved at this point too. - 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. + 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 expressions that need to be resolved and steps + 2 and 3 will be repeated as necessary. 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 @@ -513,3 +524,485 @@ Example: add "foo" add "bar" + +Implementation Specific Pragmas +=============================== + +This section describes additional pragmas that the current Nim implementation +supports but which should not be seen as part of the language specification. + +Bitsize pragma +-------------- + +The ``bitsize`` pragma is for object field members. It declares the field as +a bitfield in C/C++. + +.. code-block:: Nim + type + mybitfield = object + flag {.bitsize:1.}: cuint + +generates: + +.. code-block:: C + struct mybitfield { + unsigned int flag:1; + }; + + +Volatile pragma +--------------- +The ``volatile`` pragma is for variables only. It declares the variable as +``volatile``, whatever that means in C/C++ (its semantics are not well defined +in C/C++). + +**Note**: This pragma will not exist for the LLVM backend. + + +NoDecl pragma +------------- +The ``noDecl`` pragma can be applied to almost any symbol (variable, proc, +type, etc.) and is sometimes useful for interoperability with C: +It tells Nim that it should not generate a declaration for the symbol in +the C code. For example: + +.. code-block:: Nim + var + EACCES {.importc, noDecl.}: cint # pretend EACCES was a variable, as + # Nim does not know its value + +However, the ``header`` pragma is often the better alternative. + +**Note**: This will not work for the LLVM backend. + + +Header pragma +------------- +The ``header`` pragma is very similar to the ``noDecl`` pragma: It can be +applied to almost any symbol and specifies that it should not be declared +and instead the generated code should contain an ``#include``: + +.. code-block:: Nim + type + PFile {.importc: "FILE*", header: "<stdio.h>".} = distinct pointer + # import C's FILE* type; Nim will treat it as a new pointer type + +The ``header`` pragma always expects a string constant. The string contant +contains the header file: As usual for C, a system header file is enclosed +in angle brackets: ``<>``. If no angle brackets are given, Nim +encloses the header file in ``""`` in the generated C code. + +**Note**: This will not work for the LLVM backend. + + +IncompleteStruct pragma +----------------------- +The ``incompleteStruct`` pragma tells the compiler to not use the +underlying C ``struct`` in a ``sizeof`` expression: + +.. code-block:: Nim + type + DIR* {.importc: "DIR", header: "<dirent.h>", + final, pure, incompleteStruct.} = object + + +Compile pragma +-------------- +The ``compile`` pragma can be used to compile and link a C/C++ source file +with the project: + +.. code-block:: Nim + {.compile: "myfile.cpp".} + +**Note**: Nim computes a SHA1 checksum and only recompiles the file if it +has changed. You can use the ``-f`` command line option to force recompilation +of the file. + + +Link pragma +----------- +The ``link`` pragma can be used to link an additional file with the project: + +.. code-block:: Nim + {.link: "myfile.o".} + + +PassC pragma +------------ +The ``passC`` pragma can be used to pass additional parameters to the C +compiler like you would using the commandline switch ``--passC``: + +.. code-block:: Nim + {.passC: "-Wall -Werror".} + +Note that you can use ``gorge`` from the `system module <system.html>`_ to +embed parameters from an external command at compile time: + +.. code-block:: Nim + {.passC: gorge("pkg-config --cflags sdl").} + +PassL pragma +------------ +The ``passL`` pragma can be used to pass additional parameters to the linker +like you would using the commandline switch ``--passL``: + +.. code-block:: Nim + {.passL: "-lSDLmain -lSDL".} + +Note that you can use ``gorge`` from the `system module <system.html>`_ to +embed parameters from an external command at compile time: + +.. code-block:: Nim + {.passL: gorge("pkg-config --libs sdl").} + + +Emit pragma +----------- +The ``emit`` pragma can be used to directly affect the output of the +compiler's code generator. So it makes your code unportable to other code +generators/backends. Its usage is highly discouraged! However, it can be +extremely useful for interfacing with `C++`:idx: or `Objective C`:idx: code. + +Example: + +.. code-block:: Nim + {.emit: """ + static int cvariable = 420; + """.} + + {.push stackTrace:off.} + proc embedsC() = + var nimVar = 89 + # use backticks to access Nim symbols within an emit section: + {.emit: """fprintf(stdout, "%d\n", cvariable + (int)`nimVar`);""".} + {.pop.} + + embedsC() + +As can be seen from the example, to Nim symbols can be referred via backticks. +Use two backticks to produce a single verbatim backtick. + +For a toplevel emit statement the section where in the generated C/C++ file +the code should be emitted can be influenced via the +prefixes ``/*TYPESECTION*/`` or ``/*VARSECTION*/`` or ``/*INCLUDESECTION*/``: + +.. code-block:: Nim + {.emit: """/*TYPESECTION*/ + struct Vector3 { + public: + Vector3(): x(5) {} + Vector3(float x_): x(x_) {} + float x; + }; + """.} + + type Vector3 {.importcpp: "Vector3", nodecl} = object + x: cfloat + + proc constructVector3(a: cfloat): Vector3 {.importcpp: "Vector3(@)", nodecl} + + +ImportCpp pragma +---------------- + +**Note**: `c2nim <c2nim.html>`_ can parse a large subset of C++ and knows +about the ``importcpp`` pragma pattern language. It is not necessary +to know all the details described here. + + +Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the +``importcpp`` pragma can be used to import `C++`:idx: methods or C++ symbols +in general. The generated code then uses the C++ method calling +syntax: ``obj->method(arg)``. In combination with the ``header`` and ``emit`` +pragmas this allows *sloppy* interfacing with libraries written in C++: + +.. code-block:: Nim + # Horrible example of how to interface with a C++ engine ... ;-) + + {.link: "/usr/lib/libIrrlicht.so".} + + {.emit: """ + using namespace irr; + using namespace core; + using namespace scene; + using namespace video; + using namespace io; + using namespace gui; + """.} + + const + irr = "<irrlicht/irrlicht.h>" + + type + IrrlichtDeviceObj {.final, header: irr, + importcpp: "IrrlichtDevice".} = object + IrrlichtDevice = ptr IrrlichtDeviceObj + + proc createDevice(): IrrlichtDevice {. + header: irr, importcpp: "createDevice(@)".} + proc run(device: IrrlichtDevice): bool {. + header: irr, importcpp: "#.run(@)".} + +The compiler needs to be told to generate C++ (command ``cpp``) for +this to work. The conditional symbol ``cpp`` is defined when the compiler +emits C++ code. + + +Namespaces +~~~~~~~~~~ + +The *sloppy interfacing* example uses ``.emit`` to produce ``using namespace`` +declarations. It is usually much better to instead refer to the imported name +via the ``namespace::identifier`` notation: + +.. code-block:: nim + type + IrrlichtDeviceObj {.final, header: irr, + importcpp: "irr::IrrlichtDevice".} = object + + +Importcpp for enums +~~~~~~~~~~~~~~~~~~~ + +When ``importcpp`` is applied to an enum type the numerical enum values are +annotated with the C++ enum type, like in this example: ``((TheCppEnum)(3))``. +(This turned out to be the simplest way to implement it.) + + +Importcpp for procs +~~~~~~~~~~~~~~~~~~~ + +Note that the ``importcpp`` variant for procs uses a somewhat cryptic pattern +language for maximum flexibility: + +- A hash ``#`` symbol is replaced by the first or next argument. +- A dot following the hash ``#.`` indicates that the call should use C++'s dot + or arrow notation. +- An at symbol ``@`` is replaced by the remaining arguments, separated by + commas. + +For example: + +.. code-block:: nim + proc cppMethod(this: CppObj, a, b, c: cint) {.importcpp: "#.CppMethod(@)".} + var x: ptr CppObj + cppMethod(x[], 1, 2, 3) + +Produces: + +.. code-block:: C + x->CppMethod(1, 2, 3) + +As a special rule to keep backwards compatibility with older versions of the +``importcpp`` pragma, if there is no special pattern +character (any of ``# ' @``) at all, C++'s +dot or arrow notation is assumed, so the above example can also be written as: + +.. code-block:: nim + proc cppMethod(this: CppObj, a, b, c: cint) {.importcpp: "CppMethod".} + +Note that the pattern language naturally also covers C++'s operator overloading +capabilities: + +.. code-block:: nim + proc vectorAddition(a, b: Vec3): Vec3 {.importcpp: "# + #".} + proc dictLookup(a: Dict, k: Key): Value {.importcpp: "#[#]".} + + +- An apostrophe ``'`` followed by an integer ``i`` in the range 0..9 + is replaced by the i'th parameter *type*. The 0th position is the result + type. This can be used to pass types to C++ function templates. Between + the ``'`` and the digit an asterisk can be used to get to the base type + of the type. (So it "takes away a star" from the type; ``T*`` becomes ``T``.) + Two stars can be used to get to the element type of the element type etc. + +For example: + +.. code-block:: nim + + type Input {.importcpp: "System::Input".} = object + proc getSubsystem*[T](): ptr T {.importcpp: "SystemManager::getSubsystem<'*0>()", nodecl.} + + let x: ptr Input = getSubsystem[Input]() + +Produces: + +.. code-block:: C + x = SystemManager::getSubsystem<System::Input>() + + +- ``#@`` is a special case to support a ``cnew`` operation. It is required so + that the call expression is inlined directly, without going through a + temporary location. This is only required to circumvent a limitation of the + current code generator. + +For example C++'s ``new`` operator can be "imported" like this: + +.. code-block:: nim + proc cnew*[T](x: T): ptr T {.importcpp: "(new '*0#@)", nodecl.} + + # constructor of 'Foo': + proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)".} + + let x = cnew constructFoo(3, 4) + +Produces: + +.. code-block:: C + x = new Foo(3, 4) + +However, depending on the use case ``new Foo`` can also be wrapped like this +instead: + +.. code-block:: nim + proc newFoo(a, b: cint): ptr Foo {.importcpp: "new Foo(@)".} + + let x = newFoo(3, 4) + + +Wrapping constructors +~~~~~~~~~~~~~~~~~~~~~ + +Sometimes a C++ class has a private copy constructor and so code like +``Class c = Class(1,2);`` must not be generated but instead ``Class c(1,2);``. +For this purpose the Nim proc that wraps a C++ constructor needs to be +annotated with the `constructor`:idx: pragma. This pragma also helps to generate +faster C++ code since construction then doesn't invoke the copy constructor: + +.. code-block:: nim + # a better constructor of 'Foo': + proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)", constructor.} + + +Wrapping destructors +~~~~~~~~~~~~~~~~~~~~ + +Since Nim generates C++ directly, any destructor is called implicitly by the +C++ compiler at the scope exits. This means that often one can get away with +not wrapping the destructor at all! However when it needs to be invoked +explicitly, it needs to be wrapped. But the pattern language already provides +everything that is required for that: + +.. code-block:: nim + proc destroyFoo(this: var Foo) {.importcpp: "#.~Foo()".} + + +Importcpp for objects +~~~~~~~~~~~~~~~~~~~~~ + +Generic ``importcpp``'ed objects are mapped to C++ templates. This means that +you can import C++'s templates rather easily without the need for a pattern +language for object types: + +.. code-block:: nim + type + StdMap {.importcpp: "std::map", header: "<map>".} [K, V] = object + proc `[]=`[K, V](this: var StdMap[K, V]; key: K; val: V) {. + importcpp: "#[#] = #", header: "<map>".} + + var x: StdMap[cint, cdouble] + x[6] = 91.4 + + +Produces: + +.. code-block:: C + std::map<int, double> x; + x[6] = 91.4; + + +- If more precise control is needed, the apostrophe ``'`` can be used in the + supplied pattern to denote the concrete type parameters of the generic type. + See the usage of the apostrophe operator in proc patterns for more details. + +.. code-block:: nim + + type + VectorIterator {.importcpp: "std::vector<'0>::iterator".} [T] = object + + var x: VectorIterator[cint] + + +Produces: + +.. code-block:: C + + std::vector<int>::iterator x; + + +ImportObjC pragma +----------------- +Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the +``importobjc`` pragma can be used to import `Objective C`:idx: methods. The +generated code then uses the Objective C method calling syntax: ``[obj method +param1: arg]``. In addition with the ``header`` and ``emit`` pragmas this +allows *sloppy* interfacing with libraries written in Objective C: + +.. code-block:: Nim + # horrible example of how to interface with GNUStep ... + + {.passL: "-lobjc".} + {.emit: """ + #include <objc/Object.h> + @interface Greeter:Object + { + } + + - (void)greet:(long)x y:(long)dummy; + @end + + #include <stdio.h> + @implementation Greeter + + - (void)greet:(long)x y:(long)dummy + { + printf("Hello, World!\n"); + } + @end + + #include <stdlib.h> + """.} + + type + Id {.importc: "id", header: "<objc/Object.h>", final.} = distinct int + + proc newGreeter: Id {.importobjc: "Greeter new", nodecl.} + proc greet(self: Id, x, y: int) {.importobjc: "greet", nodecl.} + proc free(self: Id) {.importobjc: "free", nodecl.} + + var g = newGreeter() + g.greet(12, 34) + g.free() + +The compiler needs to be told to generate Objective C (command ``objc``) for +this to work. The conditional symbol ``objc`` is defined when the compiler +emits Objective C code. + + +CodegenDecl pragma +------------------ + +The ``codegenDecl`` pragma can be used to directly influence Nim's code +generator. It receives a format string that determines how the variable or +proc is declared in the generated code: + +.. code-block:: nim + var + a {.codegenDecl: "$# progmem $#".}: int + + proc myinterrupt() {.codegenDecl: "__interrupt $# $#$#".} = + echo "realistic interrupt handler" + + +InjectStmt pragma +----------------- + +The ``injectStmt`` pragma can be used to inject a statement before every +other statement in the current module. It is only supposed to be used for +debugging: + +.. code-block:: nim + {.injectStmt: gcInvariants().} + + # ... complex code here that produces crashes ... + diff --git a/doc/manual/procs.txt b/doc/manual/procs.txt index 9de984ecf..ee74b2ea6 100644 --- a/doc/manual/procs.txt +++ b/doc/manual/procs.txt @@ -2,17 +2,46 @@ Procedures ========== What most programming languages call `methods`:idx: or `functions`:idx: are -called `procedures`:idx: in Nim (which is the correct terminology). A -procedure declaration defines an identifier and associates it with a block -of code. -A procedure may call itself recursively. A parameter may be given a default -value that is used if the caller does not provide a value for this parameter. - -If the proc declaration has no body, it is a `forward`:idx: declaration. If -the proc returns a value, the procedure body can access an implicitly declared +called `procedures`:idx: in Nim (which is the correct terminology). A procedure +declaration consists of an identifier, zero or more formal parameters, a return +value type and a block of code. Formal parameters are declared as a list of +identifiers separated by either comma or semicolon. A parameter is given a type +by ``: typename``. The type applies to all parameters immediately before it, +until either the beginning of the parameter list, a semicolon separator or an +already typed parameter, is reached. The semicolon can be used to make +separation of types and subsequent identifiers more distinct. + +.. code-block:: nim + # Using only commas + proc foo(a, b: int, c, d: bool): int + + # Using semicolon for visual distinction + proc foo(a, b: int; c, d: bool): int + + # Will fail: a is untyped since ';' stops type propagation. + proc foo(a; b: int; c, d: bool): int + +A parameter may be declared with a default value which is used if the caller +does not provide a value for the argument. + +.. code-block:: nim + # b is optional with 47 as its default value + proc foo(a: int, b: int = 47): int + +Parameters can be declared mutable and so allow the proc to modify those +arguments, by using the type modifier `var`. + +.. code-block:: nim + # "returning" a value to the caller through the 2nd argument + # Notice that the function uses no actual return value at all (ie void) + proc foo(inp: int, outp: var int) = + outp = inp + 47 + +If the proc declaration has no body, it is a `forward`:idx: declaration. If the +proc returns a value, the procedure body can access an implicitly declared variable named `result`:idx: that represents the return value. Procs can be -overloaded. The overloading resolution algorithm tries to find the proc that is -the best match for the arguments. Example: +overloaded. The overloading resolution algorithm determines which proc is the +best match for the arguments. Example: .. code-block:: nim @@ -41,9 +70,8 @@ Calling a procedure can be done in many different ways: # call as a command statement: no () needed: callme 0, 1, "abc", '\t' +A procedure may call itself recursively. -A procedure cannot modify its parameters (unless the parameters have the type -`var`). `Operators`:idx: are procedures with a special operator symbol as identifier: @@ -92,7 +120,7 @@ current module: Method call syntax ------------------ -For object oriented programming, the syntax ``obj.method(args)`` can be used +For object oriented programming, the syntax ``obj.method(args)`` can be used instead of ``method(obj, args)``. The parentheses can be omitted if there are no remaining arguments: ``obj.len`` (instead of ``len(obj)``). @@ -100,26 +128,34 @@ This method call syntax is not restricted to objects, it can be used to supply any type of first argument for procedures: .. code-block:: nim - + echo("abc".len) # is the same as echo(len("abc")) echo("abc".toUpper()) echo({'a', 'b', 'c'}.card) - stdout.writeln("Hallo") # the same as writeln(stdout, "Hallo") + stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo") Another way to look at the method call syntax is that it provides the missing postfix notation. +The method call syntax conflicts with explicit generic instantiations: +``p[T](x)`` cannot be written as ``x.p[T]`` because ``x.p[T]`` is always +parsed as ``(x.p)[T]``. + +**Future directions**: ``p[.T.]`` might be introduced as an alternative syntax +to pass explict types to a generic and then ``x.p[.T.]`` can be parsed as +``x.(p[.T.])``. + See also: `Limitations of the method call syntax`_. Properties ---------- Nim has no need for *get-properties*: Ordinary get-procedures that are called -with the *method call syntax* achieve the same. But setting a value is +with the *method call syntax* achieve the same. But setting a value is different; for this a special setter syntax is needed: .. code-block:: nim - + type Socket* = ref object of RootObj FHost: int # cannot be accessed from the outside of the module @@ -129,7 +165,7 @@ different; for this a special setter syntax is needed: proc `host=`*(s: var Socket, value: int) {.inline.} = ## setter of hostAddr s.FHost = value - + proc host*(s: Socket): int {.inline.} = ## getter of hostAddr s.FHost @@ -152,18 +188,18 @@ more argument in this case: .. code-block:: nim proc optarg(x: int, y: int = 0): int = x + y proc singlearg(x: int): int = 20*x - + echo optarg 1, " ", singlearg 2 # prints "1 40" - + let fail = optarg 1, optarg 8 # Wrong. Too many arguments for a command call let x = optarg(1, optarg 8) # traditional procedure call with 2 arguments let y = 1.optarg optarg 8 # same thing as above, w/o the parenthesis assert x == y -The command invocation syntax also can't have complex expressions as arguments. -For example: (`anonymous procs`_), ``if``, ``case`` or ``try``. The (`do -notation`_) is limited, but usable for a single proc (see the example in the -corresponding section). Function calls with no arguments still needs () to +The command invocation syntax also can't have complex expressions as arguments. +For example: (`anonymous procs`_), ``if``, ``case`` or ``try``. The (`do +notation`_) is limited, but usable for a single proc (see the example in the +corresponding section). Function calls with no arguments still needs () to distinguish between a call and the function itself as a first class value. @@ -193,7 +229,7 @@ the proc's name. cmp(x.len, y.len)) -Procs as expressions can appear both as nested procs and inside top level +Procs as expressions can appear both as nested procs and inside top level executable code. @@ -209,10 +245,10 @@ calls can use the ``do`` keyword: sort(cities) do (x,y: string) -> int: cmp(x.len, y.len) # Less parenthesis using the method plus command syntax: - cities = cities.map do (x:string) -> string: + cities = cities.map do (x:string) -> string: "City of " & x -``do`` is written after the parentheses enclosing the regular proc params. +``do`` is written after the parentheses enclosing the regular proc params. The proc expression represented by the do block is appended to them. More than one ``do`` block can appear in a single call: @@ -233,11 +269,11 @@ Nonoverloadable builtins The following builtin procs cannot be overloaded for reasons of implementation simplicity (they require specialized semantic checking):: - declared, defined, definedInScope, compiles, low, high, sizeOf, + declared, defined, definedInScope, compiles, low, high, sizeOf, is, of, shallowCopy, getAst, astToStr, spawn, procCall -Thus they act more like keywords than like ordinary identifiers; unlike a -keyword however, a redefinition may `shadow`:idx: the definition in +Thus they act more like keywords than like ordinary identifiers; unlike a +keyword however, a redefinition may `shadow`:idx: the definition in the ``system`` module. From this list the following should not be written in dot notation ``x.f`` since ``x`` cannot be type checked before it gets passed to ``f``:: @@ -314,11 +350,11 @@ returned value is an l-value and can be modified by the caller: proc WriteAccessToG(): var int = result = g - + WriteAccessToG() = 6 assert g == 6 -It is a compile time error if the implicitly introduced pointer could be +It is a compile time error if the implicitly introduced pointer could be used to access a location beyond its lifetime: .. code-block:: nim @@ -326,7 +362,7 @@ used to access a location beyond its lifetime: var g = 0 result = g # Error! -For iterators, a component of a tuple return type can have a ``var`` type too: +For iterators, a component of a tuple return type can have a ``var`` type too: .. code-block:: nim iterator mpairs(a: var seq[string]): tuple[key: int, val: var string] = @@ -356,32 +392,37 @@ dispatch. x: int PlusExpr = ref object of Expression a, b: Expression - - method eval(e: Expression): int = + + method eval(e: Expression): int {.base.} = # override this base method quit "to override!" - + method eval(e: Literal): int = return e.x - + method eval(e: PlusExpr): int = # watch out: relies on dynamic binding result = eval(e.a) + eval(e.b) - + proc newLit(x: int): Literal = new(result) result.x = x - + proc newPlus(a, b: Expression): PlusExpr = new(result) result.a = a result.b = b -echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4))) - + echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4))) + In the example the constructors ``newLit`` and ``newPlus`` are procs because they should use static binding, but ``eval`` is a method because it requires dynamic binding. +As can be seen in the example, base methods have to be annotated with +the `base`:idx: pragma. The ``base`` pragma also acts as a reminder for the +programmer that a base method ``m`` is used as the foundation to determine all +the effects that a call to ``m`` might cause. + In a multi-method all parameters that have an object type are used for the dispatching: @@ -390,24 +431,24 @@ dispatching: Thing = ref object of RootObj Unit = ref object of Thing x: int - - method collide(a, b: Thing) {.inline.} = + + method collide(a, b: Thing) {.base, inline.} = quit "to override!" - + method collide(a: Thing, b: Unit) {.inline.} = echo "1" - + method collide(a: Unit, b: Thing) {.inline.} = echo "2" - + var a, b: Unit new a new b collide(a, b) # output: 2 -Invocation of a multi-method cannot be ambiguous: collide 2 is preferred over -collide 1 because the resolution works from left to right. +Invocation of a multi-method cannot be ambiguous: collide 2 is preferred over +collide 1 because the resolution works from left to right. In the example ``Unit, Thing`` is preferred over ``Thing, Unit``. **Performance note**: Nim does not produce a virtual method table, but @@ -422,7 +463,7 @@ Iterators and the for statement The `for`:idx: statement is an abstract mechanism to iterate over the elements of a container. It relies on an `iterator`:idx: to do so. Like ``while`` statements, ``for`` statements open an `implicit block`:idx:, so that they -can be left with a ``break`` statement. +can be left with a ``break`` statement. The ``for`` loop declares iteration variables - their scope reaches until the end of the loop body. The iteration variables' types are inferred by the @@ -458,7 +499,7 @@ The compiler generates code as if the programmer would have written this: If the iterator yields a tuple, there can be as many iteration variables as there are components in the tuple. The i'th iteration variable's type is -the type of the i'th component. In other words, implicit tuple unpacking in a +the type of the i'th component. In other words, implicit tuple unpacking in a for loop context is supported. Implict items/pairs invocations @@ -470,12 +511,12 @@ ie. an ``items`` iterator is implicitly invoked: .. code-block:: nim for x in [1,2,3]: echo x - + If the for loop has exactly 2 variables, a ``pairs`` iterator is implicitly invoked. -Symbol lookup of the identifiers ``items``/``pairs`` is performed after -the rewriting step, so that all overloadings of ``items``/``pairs`` are taken +Symbol lookup of the identifiers ``items``/``pairs`` is performed after +the rewriting step, so that all overloads of ``items``/``pairs`` are taken into account. @@ -483,7 +524,7 @@ First class iterators --------------------- There are 2 kinds of iterators in Nim: *inline* and *closure* iterators. -An `inline iterator`:idx: is an iterator that's always inlined by the compiler +An `inline iterator`:idx: is an iterator that's always inlined by the compiler leading to zero overhead for the abstraction, but may result in a heavy increase in code size. Inline iterators are second class citizens; They can be passed as parameters only to other inlining code facilities like @@ -494,7 +535,7 @@ In contrast to that, a `closure iterator`:idx: can be passed around more freely: .. code-block:: nim iterator count0(): int {.closure.} = yield 0 - + iterator count2(): int {.closure.} = var x = 1 yield x @@ -511,14 +552,15 @@ 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. Both inline and closure iterators cannot be recursive. +3. ``return`` is allowed in a closure iterator (but rarely useful) and ends + iteration. +4. Neither inline nor closure iterators can 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 +default to being inline, but this may change in future versions of the implementation. -The ``iterator`` type is always of the calling convention ``closure`` +The ``iterator`` type is always of the calling convention ``closure`` implicitly; the following example shows how to use iterators to implement a `collaborative tasking`:idx: system: @@ -612,8 +654,8 @@ parameters of an outer factory proc: Implicit return type -------------------- - Since inline interators must always produce values that will be consumed in - a for loop, the compiler will implicity use the ``auto`` return type if no + Since inline iterators must always produce values that will be consumed in + a for loop, the compiler will implicitly use the ``auto`` return type if no type is given by the user. In contrast, since closure iterators can be used as a collaborative tasking system, ``void`` is a valid return type for them. @@ -621,7 +663,7 @@ parameters of an outer factory proc: Converters ========== -A converter is like an ordinary proc except that it enhances +A converter is like an ordinary proc except that it enhances the "implicitly convertible" type relation (see `Convertible relation`_): .. code-block:: nim diff --git a/doc/manual/special_ops.txt b/doc/manual/special_ops.txt index 46135f129..702693423 100644 --- a/doc/manual/special_ops.txt +++ b/doc/manual/special_ops.txt @@ -34,7 +34,7 @@ templates and macros), depending on the desired effect: The following dot operators are available: operator `.` ------------- +------------ This operator will be matched against both field accesses and method calls. operator `.()` diff --git a/doc/manual/stmts.txt b/doc/manual/stmts.txt index 5b1284872..a833d7b7d 100644 --- a/doc/manual/stmts.txt +++ b/doc/manual/stmts.txt @@ -2,7 +2,7 @@ Statements and expressions ========================== Nim uses the common statement/expression paradigm: Statements do not -produce a value in contrast to expressions. However, some expressions are +produce a value in contrast to expressions. However, some expressions are statements. Statements are separated into `simple statements`:idx: and @@ -10,15 +10,15 @@ Statements are separated into `simple statements`:idx: and Simple statements are statements that cannot contain other statements like assignments, calls or the ``return`` statement; complex statements can contain other statements. To avoid the `dangling else problem`:idx:, complex -statements always have to be intended. The details can be found in the grammar. +statements always have to be indented. The details can be found in the grammar. Statement list expression ------------------------- -Statements can also occur in an expression context that looks +Statements can also occur in an expression context that looks like ``(stmt1; stmt2; ...; ex)``. This is called -an statement list expression or ``(;)``. The type +an statement list expression or ``(;)``. The type of ``(stmt1; stmt2; ...; ex)`` is the type of ``ex``. All the other statements must be of type ``void``. (One can use ``discard`` to produce a ``void`` type.) ``(;)`` does not introduce a new scope. @@ -30,24 +30,24 @@ Discard statement Example: .. code-block:: nim - proc p(x, y: int): int = + proc p(x, y: int): int = result = x + y discard p(3, 4) # discard the return value of `p` The ``discard`` statement evaluates its expression for side-effects and -throws the expression's resulting value away. +throws the expression's resulting value away. Ignoring the return value of a procedure without using a discard statement is a static error. The return value can be ignored implicitly if the called proc/iterator has -been declared with the `discardable`:idx: pragma: +been declared with the `discardable`:idx: pragma: .. code-block:: nim - proc p(x, y: int): int {.discardable.} = + proc p(x, y: int): int {.discardable.} = result = x + y - + p(3, 4) # now valid An empty ``discard`` statement is often used as a null statement: @@ -60,6 +60,24 @@ An empty ``discard`` statement is often used as a null statement: else: discard +Void context +------------ + +In a list of statements every expression except the last one needs to have the +type ``void``. In addition to this rule an assignment to the builtin ``result`` +symbol also triggers a ``void`` context: + +.. code-block:: nim + proc invalid*(): string = + result = "foo" + "invalid" # Error: value of type 'string' has to be discarded + +.. code-block:: nim + proc valid*(): string = + let x = 317 + "valid" + + Var statement ------------- @@ -98,11 +116,11 @@ T = enum cast[T](0); this may be an invalid value The implicit initialization can be avoided for optimization reasons with the -`noinit`:idx: pragma: +`noinit`:idx: pragma: .. code-block:: nim var - a {.noInit.}: array [0..1023, char] + a {.noInit.}: array [0..1023, char] If a proc is annotated with the ``noinit`` pragma this refers to its implicit ``result`` variable: @@ -113,13 +131,13 @@ If a proc is annotated with the ``noinit`` pragma this refers to its implicit The implicit initialization can be also prevented by the `requiresInit`:idx: type pragma. The compiler requires an explicit initialization then. However -it does a `control flow analysis`:idx: to prove the variable has been +it does a `control flow analysis`:idx: to prove the variable has been initialized and does not rely on syntactic properties: .. code-block:: nim type MyObject = object {.requiresInit.} - + proc p() = # the following is valid: var x: MyObject @@ -129,11 +147,12 @@ initialized and does not rely on syntactic properties: x = a() use x + let statement ------------- A ``let`` statement declares new local and global `single assignment`:idx: -variables and binds a value to them. The syntax is the same as that of the ``var`` +variables and binds a value to them. The syntax is the same as that of the ``var`` statement, except that the keyword ``var`` is replaced by the keyword ``let``. Let variables are not l-values and can thus not be passed to ``var`` parameters nor can their address be taken. They cannot be assigned new values. @@ -141,6 +160,19 @@ nor can their address be taken. They cannot be assigned new values. For let variables the same pragmas are available as for ordinary variables. +Tuple unpacking +--------------- + +In a ``var`` or ``let`` statement tuple unpacking can be performed. The special +identifier ``_`` can be used to ignore some parts of the tuple: + +.. code-block:: nim + proc returnsTuple(): (int, int, int) = (4, 2, 3) + + let (x, _, z) = returnsTuple() + + + Const section ------------- @@ -157,33 +189,33 @@ have no side-effect can be used in constant expressions too: constEval = contains("abc", 'b') # computed at compile time! -The rules for compile-time computability are: +The rules for compile-time computability are: 1. Literals are compile-time computable. 2. Type conversions are compile-time computable. 3. Procedure calls of the form ``p(X)`` are compile-time computable if - ``p`` is a proc without side-effects (see the `noSideEffect pragma`_ - for details) and if ``X`` is a (possibly empty) list of compile-time - computable arguments. + ``p`` is a proc without side-effects (see the `noSideEffect pragma + <#pragmas-nosideeffect-pragma>`_ for details) and if ``X`` is a + (possibly empty) list of compile-time computable arguments. -Constants cannot be of type ``ptr``, ``ref``, ``var`` or ``object``, nor can +Constants cannot be of type ``ptr``, ``ref``, ``var`` or ``object``, nor can they contain such a type. Static statement/expression --------------------------- -A static statement/expression can be used to enforce compile +A static statement/expression can be used to enforce compile time evaluation explicitly. Enforced compile time evaluation can even evaluate -code that has side effects: +code that has side effects: .. code-block:: static: echo "echo at compile time" -It's a static error if the compiler cannot perform the evaluation at compile +It's a static error if the compiler cannot perform the evaluation at compile time. The current implementation poses some restrictions for compile time @@ -215,22 +247,18 @@ the expression after the ``elif`` is evaluated (if there is an ``elif`` branch), if it is true the corresponding statements after the ``:`` are executed. This goes on until the last ``elif``. If all conditions fail, the ``else`` part is executed. If there is no ``else`` -part, execution continues with the statement after the ``if`` statement. +part, execution continues with the next statement. -The scoping for an ``if`` statement is slightly subtle to support an important -use case. A new scope starts for the ``if``/``elif`` condition and ends after -the corresponding *then* block: +In ``if`` statements new scopes begin immediately after the ``if``/``elif``/``else`` keywords and ends after the corresponding *then* block. +For visualization purposes the scopes have been enclosed in ``{| |}`` in the following example: .. code-block:: nim if {| (let m = input =~ re"(\w+)=\w+"; m.isMatch): echo "key ", m[0], " value ", m[1] |} elif {| (let m = input =~ re""; m.isMatch): - echo "new m in this scope" |} - else: - # 'm' not declared here - -In the example the scopes have been enclosed in ``{| |}``. - + echo "new m in this scope" |} + else: {| + echo "m not declared here" |} Case statement -------------- @@ -244,7 +272,7 @@ Example: echo("permission denied") of "go-for-a-walk": echo("please yourself") else: echo("unknown command") - + # indentation of the branches is also allowed; and so is an optional colon # after the selecting expression: case readline(stdin): @@ -252,15 +280,15 @@ Example: echo("permission denied") of "go-for-a-walk": echo("please yourself") else: echo("unknown command") - + The ``case`` statement is similar to the if statement, but it represents a multi-branch selection. The expression after the keyword ``case`` is evaluated and if its value is in a *slicelist* the corresponding statements (after the ``of`` keyword) are executed. If the value is not in any given *slicelist* the ``else`` part is executed. If there is no ``else`` -part and not all possible values that ``expr`` can hold occur in a -``slicelist``, a static error occurs. This holds only for expressions of +part and not all possible values that ``expr`` can hold occur in a +``slicelist``, a static error occurs. This holds only for expressions of ordinal types. "All possible values" of ``expr`` are determined by ``expr``'s type. To suppress the static error an ``else`` part with an empty ``discard`` statement should be used. @@ -281,7 +309,7 @@ expanded into a list of its elements: of SymChars, '_': echo "an identifier" of '0'..'9': echo "a number" else: echo "other" - + # is equivalent to: proc classify(s: string) = case s[0] @@ -320,6 +348,37 @@ a special syntactic extension, the ``when`` construct is also available within ``object`` definitions. +When nimvm statement +-------------------- + +``nimvm`` is a special symbol, that may be used as expression of ``when nimvm`` +statement to differentiate execution path between runtime and compile time. + +Example: + +.. code-block:: nim + proc someProcThatMayRunInCompileTime(): bool = + when nimvm: + # This code runs in compile time + result = true + else: + # This code runs in runtime + result = false + const ctValue = someProcThatMayRunInCompileTime() + let rtValue = someProcThatMayRunInCompileTime() + assert(ctValue == true) + assert(rtValue == false) + +``when nimvm`` statement must meet the following requirements: + +* Its expression must always be ``nimvm``. More complex expressions are not + allowed. +* It must not contain ``elif`` branches. +* It must contain ``else`` branch. +* Code in branches must not affect semantics of the code that follows the + ``when nimvm`` statement. E.g. it must not define symbols that are used in + the following code. + Return statement ---------------- @@ -580,14 +639,14 @@ A table constructor is syntactic sugar for an array constructor: .. code-block:: nim {"key1": "value1", "key2", "key3": "value2"} - + # is the same as: [("key1", "value1"), ("key2", "value2"), ("key3", "value2")] -The empty table can be written ``{:}`` (in contrast to the empty set +The empty table can be written ``{:}`` (in contrast to the empty set which is ``{}``) which is thus another way to write as the empty array -constructor ``[]``. This slightly unusal way of supporting tables +constructor ``[]``. This slightly unusual way of supporting tables has lots of advantages: * The order of the (key,value)-pairs is preserved, thus it is easy to diff --git a/doc/manual/syntax.txt b/doc/manual/syntax.txt index cf44eb588..c444a3995 100644 --- a/doc/manual/syntax.txt +++ b/doc/manual/syntax.txt @@ -15,17 +15,22 @@ Associativity Binary operators whose first character is ``^`` are right-associative, all other binary operators are left-associative. -Operators ending in ``>`` but longer than a single character are -called `arrow like`:idx:. - +.. code-block:: nim + proc `^/`(x, y: float): float = + # a right-associative division operator + result = x / y + echo 12 ^/ 4 ^/ 8 # 24.0 (4 / 8 = 0.5, then + 12 / 0.5 = 24.0) + echo 12 / 4 / 8 # 0.375 (12 / 4 = 3.0, then + 3 / 8 = 0.375) Precedence ---------- -Unary operators always bind stronger than any binary +Unary operators always bind stronger than any binary operator: ``$a + b`` is ``($a) + b`` and not ``$(a + b)``. -If an unary operator's first character is ``@`` it is a `sigil-like`:idx: +If an unary operator's first character is ``@`` it is a `sigil-like`:idx: operator which binds stronger than a ``primarySuffix``: ``@x.abc`` is parsed as ``(@x).abc`` whereas ``$x.abc`` is parsed as ``$(x.abc)``. @@ -33,9 +38,12 @@ as ``(@x).abc`` whereas ``$x.abc`` is parsed as ``$(x.abc)``. For binary operators that are not keywords the precedence is determined by the following rules: -If the operator ends with ``=`` and its first character is none of +Operators ending in either ``->``, ``~>`` or ``=>`` are called +`arrow like`:idx:, and have the lowest precedence of all operators. + +If the operator ends with ``=`` and its first character is none of ``<``, ``>``, ``!``, ``=``, ``~``, ``?``, it is an *assignment operator* which -has the lowest precedence. +has the second lowest precedence. Otherwise precedence is determined by the first character. @@ -43,14 +51,14 @@ Otherwise precedence is determined by the first character. Precedence level Operators First character Terminal symbol ================ =============================================== ================== =============== 10 (highest) ``$ ^`` OP10 - 9 ``* / div mod shl shr %`` ``* % \ /`` OP9 - 8 ``+ -`` ``+ ~ |`` OP8 + 9 ``* / div mod shl shr %`` ``* % \ /`` OP9 + 8 ``+ -`` ``+ - ~ |`` OP8 7 ``&`` ``&`` OP7 6 ``..`` ``.`` OP6 - 5 ``== <= < >= > != in notin is isnot not of`` ``= < > !`` OP5 + 5 ``== <= < >= > != in notin is isnot not of`` ``= < > !`` OP5 4 ``and`` OP4 3 ``or xor`` OP3 - 2 ``@ : ?`` OP2 + 2 ``@ : ?`` OP2 1 *assignment operator* (like ``+=``, ``*=``) OP1 0 (lowest) *arrow like operator* (like ``->``, ``=>``) OP0 ================ =============================================== ================== =============== @@ -60,14 +68,14 @@ Strong spaces ------------- The number of spaces preceding a non-keyword operator affects precedence -if the experimental parser directive ``#!strongSpaces`` is used. Indentation +if the experimental parser directive ``#?strongSpaces`` is used. Indentation is not used to determine the number of spaces. If 2 or more operators have the same number of preceding spaces the precedence table applies, so ``1 + 3 * 4`` is still parsed as ``1 + (3 * 4)``, but ``1+3 * 4`` is parsed as ``(1+3) * 4``: .. code-block:: nim - #! strongSpaces - if foo+4 * 4 == 8 and b&c | 9 ++ + #? strongSpaces + if foo+4 * 4 == 8 and b&c | 9 ++ bar: echo "" # is parsed as @@ -75,10 +83,10 @@ is still parsed as ``1 + (3 * 4)``, but ``1+3 * 4`` is parsed as ``(1+3) * 4``: Furthermore whether an operator is used a prefix operator is affected by the -number of spaces: +number of spaces: .. code-block:: nim - #! strongSpaces + #? strongSpaces echo $foo # is parsed as echo($foo) @@ -87,7 +95,7 @@ This also affects whether ``[]``, ``{}``, ``()`` are parsed as constructors or as accessors: .. code-block:: nim - #! strongSpaces + #? strongSpaces echo (1,2) # is parsed as echo((1,2)) diff --git a/doc/manual/taint.txt b/doc/manual/taint.txt index 84f0c68b1..492686f31 100644 --- a/doc/manual/taint.txt +++ b/doc/manual/taint.txt @@ -1,11 +1,11 @@ Taint mode ========== -The Nim compiler and most parts of the standard library support -a taint mode. Input strings are declared with the `TaintedString`:idx: +The Nim compiler and most parts of the standard library support +a taint mode. Input strings are declared with the `TaintedString`:idx: string type declared in the ``system`` module. -If the taint mode is turned on (via the ``--taintMode:on`` command line +If the taint mode is turned on (via the ``--taintMode:on`` command line option) it is a distinct string type which helps to detect input validation errors: @@ -13,7 +13,7 @@ validation errors: echo "your name: " var name: TaintedString = stdin.readline # it is safe here to output the name without any input validation, so - # we simply convert `name` to string to make the compiler happy: + # we simply convert `name` to string to make the compiler happy: echo "hi, ", name.string If the taint mode is turned off, ``TaintedString`` is simply an alias for diff --git a/doc/manual/templates.txt b/doc/manual/templates.txt index eeb907ce0..092d65ea2 100644 --- a/doc/manual/templates.txt +++ b/doc/manual/templates.txt @@ -16,17 +16,17 @@ Example: assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6)) -The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact +The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact templates: | ``a > b`` is transformed into ``b < a``. -| ``a in b`` is transformed into ``contains(b, a)``. +| ``a in b`` is transformed into ``contains(b, a)``. | ``notin`` and ``isnot`` have the obvious meanings. -The "types" of templates can be the symbols ``expr`` (stands for *expression*), -``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type -description*). These are "meta types", they can only be used in certain -contexts. Real types can be used too; this implies that expressions are +The "types" of templates can be the symbols ``expr`` (stands for *expression*), +``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type +description*). These are "meta types", they can only be used in certain +contexts. Real types can be used too; this implies that expressions are expected. @@ -40,7 +40,7 @@ So ordinary templates cannot receive undeclared identifiers: .. code-block:: nim - template declareInt(x: expr) = + template declareInt(x: expr) = var x: int declareInt(x) # error: unknown identifier: 'x' @@ -51,7 +51,7 @@ receive undeclared identifiers: .. code-block:: nim - template declareInt(x: expr) {.immediate.} = + template declareInt(x: expr) {.immediate.} = var x: int declareInt(x) # valid @@ -75,12 +75,12 @@ special ``:`` syntax: close(f) else: quit("cannot open: " & fn) - + withFile(txt, "ttempl3.txt", fmWrite): - txt.writeln("line 1") - txt.writeln("line 2") - -In the example the two ``writeln`` statements are bound to the ``actions`` + txt.writeLine("line 1") + txt.writeLine("line 2") + +In the example the two ``writeLine`` statements are bound to the ``actions`` parameter. @@ -92,9 +92,9 @@ bound from the definition scope of the template: .. code-block:: nim # Module A - var + var lastId = 0 - + template genId*: expr = inc(lastId) lastId @@ -102,10 +102,10 @@ bound from the definition scope of the template: .. code-block:: nim # Module B import A - + echo genId() # Works as 'lastId' has been bound in 'genId's defining scope -As in generics symbol binding can be influenced via ``mixin`` or ``bind`` +As in generics symbol binding can be influenced via ``mixin`` or ``bind`` statements. @@ -117,11 +117,11 @@ In templates identifiers can be constructed with the backticks notation: .. code-block:: nim - template typedef(name: expr, typ: typedesc) {.immediate.} = + template typedef(name: expr, typ: typedesc) {.immediate.} = type `T name`* {.inject.} = typ `P name`* {.inject.} = ref `T name` - + typedef(myint, int) var x: PMyInt @@ -150,7 +150,7 @@ shadowed by the same argument name even when fully qualified: tstLev(levA) # produces: 'levA levA' - + But the global symbol can properly be captured by a ``bind`` statement: .. code-block:: nim @@ -177,14 +177,14 @@ Per default templates are `hygienic`:idx:\: Local identifiers declared in a template cannot be accessed in the instantiation context: .. code-block:: nim - + template newException*(exceptn: typedesc, message: string): expr = var e: ref exceptn # e is implicitly gensym'ed here new(e) e.msg = message e - + # so this works: let e = "message" raise newException(EIO, e) @@ -196,7 +196,7 @@ symbols are not exposed but inject'ed are. The default for symbols of entity ``type``, ``var``, ``let`` and ``const`` is ``gensym`` and for ``proc``, ``iterator``, ``converter``, ``template``, -``macro`` is ``inject``. However, if the name of the entity is passed as a +``macro`` is ``inject``. However, if the name of the entity is passed as a template parameter, it is an inject'ed symbol: .. code-block:: nim @@ -204,10 +204,10 @@ template parameter, it is an inject'ed symbol: block: var f: File # since 'f' is a template param, it's injected implicitly ... - + withFile(txt, "ttempl3.txt", fmWrite): - txt.writeln("line 1") - txt.writeln("line 2") + txt.writeLine("line 1") + txt.writeLine("line 2") The ``inject`` and ``gensym`` pragmas are second class annotations; they have @@ -215,7 +215,7 @@ no semantics outside of a template definition and cannot be abstracted over: .. code-block:: nim {.pragma myInject: inject.} - + template t() = var x {.myInject.}: int # does NOT work @@ -299,7 +299,7 @@ variable number of arguments: # add a call to the statement list that writes ": " add(result, newCall("write", newIdentNode("stdout"), newStrLitNode(": "))) # add a call to the statement list that writes the expressions value: - add(result, newCall("writeln", newIdentNode("stdout"), n[i])) + add(result, newCall("writeLine", newIdentNode("stdout"), n[i])) var a: array [0..10, int] @@ -314,15 +314,15 @@ The macro call expands to: .. code-block:: nim write(stdout, "a[0]") write(stdout, ": ") - writeln(stdout, a[0]) + writeLine(stdout, a[0]) write(stdout, "a[1]") write(stdout, ": ") - writeln(stdout, a[1]) + writeLine(stdout, a[1]) write(stdout, "x") write(stdout, ": ") - writeln(stdout, x) + writeLine(stdout, x) Arguments that are passed to a ``varargs`` parameter are wrapped in an array @@ -333,10 +333,10 @@ children. BindSym ------- -The above ``debug`` macro relies on the fact that ``write``, ``writeln`` and -``stdout`` are declared in the system module and thus visible in the +The above ``debug`` macro relies on the fact that ``write``, ``writeLine`` and +``stdout`` are declared in the system module and thus visible in the instantiating context. There is a way to use bound identifiers -(aka `symbols`:idx:) instead of using unbound identifiers. The ``bindSym`` +(aka `symbols`:idx:) instead of using unbound identifiers. The ``bindSym`` builtin can be used for that: .. code-block:: nim @@ -348,7 +348,7 @@ builtin can be used for that: # we can bind symbols in scope via 'bindSym': add(result, newCall(bindSym"write", bindSym"stdout", toStrLit(n[i]))) add(result, newCall(bindSym"write", bindSym"stdout", newStrLitNode(": "))) - add(result, newCall(bindSym"writeln", bindSym"stdout", n[i])) + add(result, newCall(bindSym"writeLine", bindSym"stdout", n[i])) var a: array [0..10, int] @@ -363,17 +363,17 @@ The macro call expands to: .. code-block:: nim write(stdout, "a[0]") write(stdout, ": ") - writeln(stdout, a[0]) + writeLine(stdout, a[0]) write(stdout, "a[1]") write(stdout, ": ") - writeln(stdout, a[1]) + writeLine(stdout, a[1]) write(stdout, "x") write(stdout, ": ") - writeln(stdout, x) + writeLine(stdout, x) -However, the symbols ``write``, ``writeln`` and ``stdout`` are already bound +However, the symbols ``write``, ``writeLine`` and ``stdout`` are already bound and are not looked up again. As the example shows, ``bindSym`` does work with overloaded symbols implicitly. @@ -418,8 +418,8 @@ powerful programming construct that still suffices. So the "check list" is: Macros as pragmas ----------------- -Whole routines (procs, iterators etc.) can also be passed to a template or -a macro via the pragma notation: +Whole routines (procs, iterators etc.) can also be passed to a template or +a macro via the pragma notation: .. code-block:: nim template m(s: stmt) = discard diff --git a/doc/manual/threads.txt b/doc/manual/threads.txt index fc3040c87..f2b79a34f 100644 --- a/doc/manual/threads.txt +++ b/doc/manual/threads.txt @@ -37,7 +37,7 @@ that contains GC'ed memory (``string``, ``seq``, ``ref`` or a closure) either directly or indirectly through a call to a GC unsafe proc. The `gcsafe`:idx: annotation can be used to mark a proc to be gcsafe, -otherwise this property is inferred by the compiler. Note that ``noSideEfect`` +otherwise this property is inferred by the compiler. Note that ``noSideEffect`` implies ``gcsafe``. The only way to create a thread is via ``spawn`` or ``createThead``. ``spawn`` is usually the preferable method. Either way the invoked proc must not use ``var`` parameters nor must any of its parameters @@ -146,7 +146,7 @@ wait on multiple flow variables at the same time: # wait until 2 out of 3 servers received the update: proc main = - var responses = newSeq[RawFlowVar](3) + var responses = newSeq[FlowVarBase](3) for i in 0..2: responses[i] = spawn tellServer(Update, "key", "value") var index = awaitAny(responses) diff --git a/doc/manual/trmacros.txt b/doc/manual/trmacros.txt index 90d01e475..446896e28 100644 --- a/doc/manual/trmacros.txt +++ b/doc/manual/trmacros.txt @@ -3,32 +3,32 @@ Term rewriting macros Term rewriting macros are macros or templates that have not only a *name* but also a *pattern* that is searched for after the semantic checking -phase of the compiler: This means they provide an easy way to enhance the +phase of the compiler: This means they provide an easy way to enhance the compilation pipeline with user defined optimizations: .. code-block:: nim template optMul{`*`(a, 2)}(a: int): int = a+a - + let x = 3 echo x * 2 The compiler now rewrites ``x * 2`` as ``x + x``. The code inside the curlies is the pattern to match against. The operators ``*``, ``**``, -``|``, ``~`` have a special meaning in patterns if they are written in infix +``|``, ``~`` have a special meaning in patterns if they are written in infix notation, so to match verbatim against ``*`` the ordinary function call syntax needs to be used. Unfortunately optimizations are hard to get right and even the tiny example -is **wrong**: +is **wrong**: .. code-block:: nim template optMul{`*`(a, 2)}(a: int): int = a+a - + proc f(): int = echo "side effect!" result = 55 - + echo f() * 2 We cannot duplicate 'a' if it denotes an expression that has a side effect! @@ -36,26 +36,30 @@ Fortunately Nim supports side effect analysis: .. code-block:: nim template optMul{`*`(a, 2)}(a: int{noSideEffect}): int = a+a - + proc f(): int = echo "side effect!" result = 55 - + echo f() * 2 # not optimized ;-) +You can make one overload matching with a constraint and one without, and the +one with a constraint will have precedence, and so you can handle both cases +differently. + So what about ``2 * a``? We should tell the compiler ``*`` is commutative. We cannot really do that however as the following code only swaps arguments blindly: .. code-block:: nim template mulIsCommutative{`*`(a, b)}(a, b: int): int = b*a - + What optimizers really need to do is a *canonicalization*: .. code-block:: nim template canonMul{`*`(a, b)}(a: int{lit}, b: int): int = b*a -The ``int{lit}`` parameter pattern matches against an expression of +The ``int{lit}`` parameter pattern matches against an expression of type ``int``, but only if it's a literal. @@ -63,7 +67,7 @@ type ``int``, but only if it's a literal. Parameter constraints --------------------- -The `parameter constraint`:idx: expression can use the operators ``|`` (or), +The `parameter constraint`:idx: expression can use the operators ``|`` (or), ``&`` (and) and ``~`` (not) and the following predicates: =================== ===================================================== @@ -71,7 +75,7 @@ Predicate Meaning =================== ===================================================== ``atom`` The matching node has no children. ``lit`` The matching node is a literal like "abc", 12. -``sym`` The matching node must be a symbol (a bound +``sym`` The matching node must be a symbol (a bound identifier). ``ident`` The matching node must be an identifier (an unbound identifier). @@ -97,16 +101,18 @@ Predicate Meaning ``enumfield`` A symbol which is a field in an enumeration. ``forvar`` A for loop variable. ``label`` A label (used in ``block`` statements). -``nk*`` The matching AST must have the specified kind. +``nk*`` The matching AST must have the specified kind. (Example: ``nkIfStmt`` denotes an ``if`` statement.) -``alias`` States that the marked parameter needs to alias +``alias`` States that the marked parameter needs to alias with *some* other parameter. ``noalias`` States that *every* other parameter must not alias with the marked parameter. =================== ===================================================== +Predicates that share their name with a keyword have to be escaped with +backticks: `` `const` ``. The ``alias`` and ``noalias`` predicates refer not only to the matching AST, -but also to every other bound parameter; syntactially they need to occur after +but also to every other bound parameter; syntactically they need to occur after the ordinary AST predicates: .. code-block:: nim @@ -144,15 +150,15 @@ constant folding, so the following does not work: The reason is that the compiler already transformed the 1 into "1" for the ``echo`` statement. However, a term rewriting macro should not change the -semantics anyway. In fact they can be deactived with the ``--patterns:off`` -command line option or temporarily with the ``patterns`` pragma. +semantics anyway. In fact they can be deactivated with the ``--patterns:off`` +command line option or temporarily with the ``patterns`` pragma. The ``{}`` operator ~~~~~~~~~~~~~~~~~~~ A pattern expression can be bound to a pattern parameter via the ``expr{param}`` -notation: +notation: .. code-block:: nim template t{(0|1|2){x}}(x: expr): expr = x+1 @@ -170,7 +176,7 @@ The ``~`` operator is the **not** operator in patterns: template t{x = (~x){y} and (~x){z}}(x, y, z: bool): stmt = x = y if x: x = z - + var a = false b = true @@ -183,12 +189,12 @@ The ``*`` operator ~~~~~~~~~~~~~~~~~~ The ``*`` operator can *flatten* a nested binary expression like ``a & b & c`` -to ``&(a, b, c)``: +to ``&(a, b, c)``: .. code-block:: nim var calls = 0 - + proc `&&`(s: varargs[string]): string = result = s[0] for i in 1..len(s)-1: result.add s[i] @@ -205,8 +211,8 @@ to ``&(a, b, c)``: The second operator of `*` must be a parameter; it is used to gather all the arguments. The expression ``"my" && (space & "awe" && "some " ) && "concat"`` -is passed to ``optConc`` in ``a`` as a special list (of kind ``nkArgList``) -which is flattened into a call expression; thus the invocation of ``optConc`` +is passed to ``optConc`` in ``a`` as a special list (of kind ``nkArgList``) +which is flattened into a call expression; thus the invocation of ``optConc`` produces: .. code-block:: nim @@ -239,7 +245,7 @@ all the arguments, but also the matched operators in reverse polish notation: var x, y, z: Matrix - echo x + y * z - x + echo x + y * z - x This passes the expression ``x + y * z - x`` to the ``optM`` macro as an ``nnkArgList`` node containing:: @@ -259,17 +265,17 @@ an ``nnkArgList`` node containing:: Parameters ---------- -Parameters in a pattern are type checked in the matching process. If a +Parameters in a pattern are type checked in the matching process. If a parameter is of the type ``varargs`` it is treated specially and it can match 0 or more arguments in the AST to be matched against: .. code-block:: nim template optWrite{ write(f, x) - ((write|writeln){w})(f, y) + ((write|writeLine){w})(f, y) }(x, y: varargs[expr], f: File, w: expr) = w(f, x, y) - + Example: Partial evaluation @@ -304,7 +310,7 @@ The following example shows how some form of hoisting can be implemented: The ``optPeg`` template optimizes the case of a peg constructor with a string literal, so that the pattern will only be parsed once at program startup and -stored in a global ``gl`` which is then re-used. This optimization is called +stored in a global ``gl`` which is then re-used. This optimization is called hoisting because it is comparable to classical loop hoisting. @@ -337,7 +343,7 @@ ordinary routines. Move optimization ----------------- -The ``call`` constraint is particularly useful to implement a move +The ``call`` constraint is particularly useful to implement a move optimization for types that have copying semantics: .. code-block:: nim @@ -345,15 +351,15 @@ optimization for types that have copying semantics: ## puts a (key, value)-pair into `t`. The semantics of string require ## a copy here: let idx = findInsertionPosition(key) - t[idx] = key - t[idx] = val + t[idx].key = key + t[idx].val = val proc `[]=`*(t: var Table, key: string{call}, val: string{call}) = ## puts a (key, value)-pair into `t`. Optimized version that knows that ## the strings are unique and thus don't need to be copied: let idx = findInsertionPosition(key) - shallowCopy t[idx], key - shallowCopy t[idx], val + shallowCopy t[idx].key, key + shallowCopy t[idx].val, val var t: Table # overloading resolution ensures that the optimized []= is called here: diff --git a/doc/manual/type_bound_ops.txt b/doc/manual/type_bound_ops.txt index 59d55a6cd..c707979fe 100644 --- a/doc/manual/type_bound_ops.txt +++ b/doc/manual/type_bound_ops.txt @@ -21,27 +21,49 @@ helper distinct or object type has to be used for one pointer type. operator `=` ------------ -This operator is the assignment operator. Note that in the contexts -like ``let v = expr``, ``var v = expr``, ``parameter = defaultValue`` or for -parameter passing no assignment is performed. The ``override`` pragma is -optional for overriding ``=``. +This operator is the assignment operator. Note that in the contexts +``result = expr``, ``parameter = defaultValue`` or for +parameter passing no assignment is performed. For a type ``T`` that has an +overloaded assignment operator ``var v = T()`` is rewritten +to ``var v: T; v = T()``; in other words ``var`` and ``let`` contexts do count +as assignments. + +The assignment operator needs to be attached to an object or distinct +type ``T``. Its signature has to be ``(var T, T)``. Example: + +.. code-block:: nim + type + Concrete = object + a, b: string + + proc `=`(d: var Concrete; src: Concrete) = + shallowCopy(d.a, src.a) + shallowCopy(d.b, src.b) + echo "Concrete '=' called" + + var x, y: array[0..2, Concrete] + var cA, cB: Concrete + + var cATup, cBTup: tuple[x: int, ha: Concrete] + + x = y + cA = cB + cATup = cBTup -**Note**: Overriding of operator ``=`` is not yet implemented. destructors ----------- A destructor must have a single parameter with a concrete type (the name of a -generic type is allowed too). The name of the destructor has to be ``destroy`` -and it need to be annotated with the ``override`` pragma. +generic type is allowed too). The name of the destructor has to be ``=destroy``. -``destroy(v)`` will be automatically invoked for every local stack +``=destroy(v)`` will be automatically invoked for every local stack variable ``v`` that goes out of scope. -If a structured type features a field with destructable type and +If a structured type features a field with destructable type and the user has not provided an explicit implementation, a destructor for the -structured type will be automatically generated. Calls to any base class +structured type will be automatically generated. Calls to any base class destructors in both user-defined and generated destructors will be inserted. A destructor is attached to the type it destructs; expressions of this type @@ -52,13 +74,13 @@ can then only be used in *destructible contexts* and as parameters: MyObj = object x, y: int p: pointer - - proc destroy(o: var MyObj) {.override.} = + + proc `=destroy`(o: var MyObj) = if o.p != nil: dealloc o.p - + proc open: MyObj = result = MyObj(x: 1, y: 2, p: alloc(3)) - + proc work(o: MyObj) = echo o.x # No destructor invoked here for 'o' as 'o' is a parameter. @@ -68,7 +90,7 @@ can then only be used in *destructible contexts* and as parameters: var x = open() # valid: pass 'x' to some other proc: work(x) - + # Error: usage of a type with a destructor in a non destructible context echo open() @@ -85,7 +107,7 @@ be destructed at its scope exit. Later versions of the language will improve the support of destructors. Be aware that destructors are not called for objects allocated with ``new``. -This may change in future versions of language, but for now the ``finalizer`` +This may change in future versions of language, but for now the `finalizer`:idx: parameter to ``new`` has to be used. **Note**: Destructors are still experimental and the spec might change @@ -95,7 +117,7 @@ significantly in order to incorporate an escape analysis. deepCopy -------- -``deepCopy`` is a builtin that is invoked whenever data is passed to +``=deepCopy`` is a builtin that is invoked whenever data is passed to a ``spawn``'ed proc to ensure memory safety. The programmer can override its behaviour for a specific ``ref`` or ``ptr`` type ``T``. (Later versions of the language may weaken this restriction.) @@ -103,10 +125,10 @@ language may weaken this restriction.) The signature has to be: .. code-block:: nim - proc deepCopy(x: T): T {.override.} + proc `=deepCopy`(x: T): T -This mechanism is used by most data structures that support shared memory like -channels to implement thread safe automatic memory management. +This mechanism will be used by most data structures that support shared memory +like channels to implement thread safe automatic memory management. The builtin ``deepCopy`` can even clone closures and their environments. See the documentation of `spawn`_ for details. diff --git a/doc/manual/type_rel.txt b/doc/manual/type_rel.txt index d1593a02e..434d6b030 100644 --- a/doc/manual/type_rel.txt +++ b/doc/manual/type_rel.txt @@ -9,11 +9,11 @@ Type equality ------------- Nim uses structural type equivalence for most types. Only for objects, enumerations and distinct types name equivalence is used. The following -algorithm (in pseudo-code) determines type equality: +algorithm, *in pseudo-code*, determines type equality: .. code-block:: nim proc typeEqualsAux(a, b: PType, - s: var set[PType * PType]): bool = + s: var HashSet[(PType, PType)]): bool = if (a,b) in s: return true incl(s, (a,b)) if a.kind == b.kind: @@ -43,7 +43,7 @@ algorithm (in pseudo-code) determines type equality: a.callingConvention == b.callingConvention proc typeEquals(a, b: PType): bool = - var s: set[PType * PType] = {} + var s: HashSet[(PType, PType)] = {} result = typeEqualsAux(a, b, s) Since types are graphs which can have cycles, the above algorithm needs an @@ -294,6 +294,21 @@ If the formal parameter ``f`` is of type ``var T`` in addition to the ordinary type checking, the argument is checked to be an `l-value`:idx:. ``var T`` matches better than just ``T`` then. +.. code-block:: nim + proc sayHi(x: int): string = + # matches a non-var int + result = $x + proc sayHi(x: var int): string = + # matches a var int + result = $(x + 10) + + proc sayHello(x: int) = + var m = x # a mutable version of x + echo sayHi(x) # matches the non-var version of sayHi + echo sayHi(m) # matches the var version of sayHi + + sayHello(3) # 3 + # 13 Automatic dereferencing ----------------------- diff --git a/doc/manual/type_sections.txt b/doc/manual/type_sections.txt index 8420a0098..34bbe6bd5 100644 --- a/doc/manual/type_sections.txt +++ b/doc/manual/type_sections.txt @@ -18,6 +18,6 @@ Example: A type section begins with the ``type`` keyword. It contains multiple type definitions. A type definition binds a type to a name. Type definitions can be recursive or even mutually recursive. Mutually recursive types are only -possible within a single ``type`` section. Nominal types like ``objects`` +possible within a single ``type`` section. Nominal types like ``objects`` or ``enums`` can only be defined in a ``type`` section. diff --git a/doc/manual/types.txt b/doc/manual/types.txt index e9d33045b..babf3286f 100644 --- a/doc/manual/types.txt +++ b/doc/manual/types.txt @@ -342,6 +342,34 @@ builtin ``len`` procedure; the length never counts the terminating zero. The assignment operator for strings always copies the string. The ``&`` operator concatenates strings. +Most native Nim types support conversion to strings with the special ``$`` proc. +When calling the ``echo`` proc, for example, the built-in stringify operation +for the parameter is called: + +.. code-block:: nim + + echo 3 # calls `$` for `int` + +Whenever a user creates a specialized object, implementation of this procedure +provides for ``string`` representation. + +.. code-block:: nim + type + Person = object + name: string + age: int + + proc `$`(p: Person): string = # `$` always returns a string + result = p.name & " is " & + $p.age & # we *need* the `$` in front of p.age, which + # is natively an integer, to convert it to + # a string + " years old." + +While ``$p.name`` can also be used, the ``$`` operation on a string does +nothing. Note that we cannot rely on automatic conversion from an ``int`` to +a ``string`` like we can for the ``echo`` proc. + Strings are compared by their lexicographical order. All comparison operators are available. Strings can be indexed like arrays (lower bound is 0). Unlike arrays, they can be used in case statements: @@ -462,6 +490,11 @@ to an open array parameter. The openarray type cannot be nested: multidimensional openarrays are not supported because this is seldom needed and cannot be done efficiently. +.. code-block:: nim + proc testOpenArray(x: openArray[int]) = echo repr(x) + + testOpenArray([1,2,3]) # array[] + testOpenArray(@[1,2,3]) # seq[] Varargs ------- @@ -560,11 +593,12 @@ can also be defined with indentation instead of ``[]``: Objects provide many features that tuples do not. Object provide inheritance and information hiding. Objects have access to their type at runtime, so that -the ``of`` operator can be used to determine the object's type. +the ``of`` operator can be used to determine the object's type. The ``of`` operator +is similar to the ``instanceof`` operator in Java. .. code-block:: nim type - Person {.inheritable.} = object + Person = object of RootObj name*: string # the * means that `name` is accessible from other modules age: int # no * means that the field is hidden @@ -575,6 +609,7 @@ the ``of`` operator can be used to determine the object's type. student: Student person: Person assert(student of Student) # is true + assert(student of Person) # also true Object fields that should be visible from outside the defining module, have to be marked by ``*``. In contrast to tuples, different object types are @@ -593,6 +628,7 @@ an ``object`` type or a ``ref object`` type: .. code-block:: nim var student = Student(name: "Anton", age: 5, id: 3) +Note that, unlike tuples, objects require the field names along with their values. For a ``ref object`` type ``system.new`` is invoked implicitly. @@ -803,7 +839,7 @@ exclude ``nil`` as a valid value with the ``not nil`` annotation: p(x) The compiler ensures that every code path initializes variables which contain -not nilable pointers. The details of this analysis are still to be specified +non nilable pointers. The details of this analysis are still to be specified here. @@ -864,7 +900,9 @@ Future directions: * Builtin regions like ``private``, ``global`` and ``local`` will prove very useful for the upcoming OpenCL target. * Builtin "regions" can model ``lent`` and ``unique`` pointers. - +* An assignment operator can be attached to a region so that proper write + barriers can be generated. This would imply that the GC can be implemented + completely in user-space. Procedural type @@ -961,7 +999,7 @@ Most calling conventions exist only for the Windows 32-bit platform. Assigning/passing a procedure to a procedural variable is only allowed if one of the following conditions hold: 1) The procedure that is accessed resides in the current module. -2) The procedure is marked with the ``procvar`` pragma (see `procvar pragma`_). +2) The procedure is marked with the ``procvar`` pragma (see `procvar pragma <#pragmas-procvar-pragma>`_). 3) The procedure has a calling convention that differs from ``nimcall``. 4) The procedure is anonymous. @@ -1130,7 +1168,7 @@ that don't. Distinct types provide a means to introduce a new string type It is an essential property of abstract types that they **do not** imply a -subtype relation between the abtract type and its base type. Explict type +subtype relation between the abstract type and its base type. Explicit type conversions from ``string`` to ``SQL`` are allowed: .. code-block:: nim @@ -1195,3 +1233,27 @@ However, a ``void`` type cannot be inferred in generic code: The ``void`` type is only valid for parameters and return types; other symbols cannot have the type ``void``. + + +Auto type +--------- + +The ``auto`` type can only be used for return types and parameters. For return +types it causes the compiler to infer the type from the routine body: + +.. code-block:: nim + proc returnsInt(): auto = 1984 + +For parameters it currently creates implicitly generic routines: + +.. code-block:: nim + proc foo(a, b: auto) = discard + +Is the same as: + +.. code-block:: nim + proc foo[T1, T2](a: T1, b: T2) = discard + +However later versions of the language might change this to mean "infer the +parameters' types from the body". Then the above ``foo`` would be rejected as +the parameters' types can not be infered from an empty ``discard`` statement. diff --git a/doc/nep1.txt b/doc/nep1.txt new file mode 100644 index 000000000..b4bd6309c --- /dev/null +++ b/doc/nep1.txt @@ -0,0 +1,208 @@ +============================================== +Nim Enhancement Proposal #1 - Standard Library Style Guide +============================================== +:Author: Clay Sweetser +:Version: |nimversion| + +.. contents:: + + +Introduction +============ +Although Nim supports a variety of code and formatting styles, it is +nevertheless beneficial that certain community efforts, such as the standard +library, should follow a consistent set of style guidelines when suitable. +This enhancement proposal aims to list a series of guidelines that the standard +library should follow. + +Note that there can be exceptions to these rules. Nim being as flexible as it +is, there will be parts of this style guide that don't make sense in certain +contexts. Furthermore, just as +`Python's style guide<http://legacy.python.org/dev/peps/pep-0008/>`_ changes +over time, this style guide will too. + +These rules will only be enforced for contributions to the Nim +codebase and official projects, such as the Nim compiler, the standard library, +and the various official tools such as C2Nim. + +---------------- +Style Guidelines +---------------- + +Spacing and Whitespace Conventions +----------------------------------- + +- Lines should be no longer than 80 characters. Limiting the amount of + information present on each line makes for more readable code - the reader + has smaller chunks to process. + +- Two spaces should be used for indentation of blocks; tabstops are not allowed + (the compiler enforces this). Using spaces means that the appearance of code + is more consistent across editors. Unlike spaces, tabstop width varies across + editors, and not all editors provide means of changing this width. + +- Although use of whitespace for stylistic reasons other than the ones endorsed + by this guide are allowed, careful thought should be put into such practices. + Not all editors support automatic alignment of code sections, and re-aligning + long sections of code by hand can quickly become tedious. + + .. code-block:: nim + # This is bad, as the next time someone comes + # to edit this code block, they + # must re-align all the assignments again: + type + WordBool* = int16 + CalType* = int + ... # 5 lines later + CalId* = int + LongLong* = int64 + LongLongPtr* = ptr LongLong + + +Naming Conventions +------------------------- + +Note: While the rules outlined below are the *current* naming conventions, +these conventions have not always been in place. Previously, the naming +conventions for identifiers followed the Pascal tradition of prefixes which +indicated the base type of the identifier - PFoo for pointer and reference +types, TFoo for value types, EFoo for exceptions, etc. Though this has since +changed, there are many places in the standard library which still use this +convention. Such style remains in place purely for legacy reasons, and will be +changed in the future. + +- Type identifiers should be in PascalCase. All other identifiers should be in + camelCase with the exception of constants which **may** use PascalCase but + are not required to. + + .. code-block:: nim + const aConstant = 42 + const FooBar = 4.2 + + var aVariable = "Meep" + + type FooBar = object + + For constants coming from a C/C++ wrapper, ALL_UPPERCASE are allowed, but ugly. + (Why shout CONSTANT? Constants do no harm, variables do!) + +- When naming types that come in value, pointer, and reference varieties, use a + regular name for the variety that is to be used the most, and add a "Obj", + "Ref", or "Ptr" suffix for the other varieties. If there is no single variety + that will be used the most, add the suffixes to the pointer variants only. The + same applies to C/C++ wrappers. + + .. code-block:: nim + type + Handle = int64 # Will be used most often + HandleRef = ref Handle # Will be used less often +- Exception and Error types should have the "Error" suffix. + + .. code-block:: nim + type UnluckyError = object of Exception +- Unless marked with the `{.pure.}` pragma, members of enums should have an + identifying prefix, such as an abbreviation of the enum's name. + + .. code-block:: nim + type PathComponent = enum + pcDir + pcLinkToDir + pcFile + pcLinkToFile +- Non-pure enum values should use camelCase whereas pure enum values should use + PascalCase. + + .. code-block:: nim + type PathComponent {.pure.} = enum + Dir + LinkToDir + File + LinkToFile +- In the age of HTTP, HTML, FTP, TCP, IP, UTF, WWW it is foolish to pretend + these are somewhat special words requiring all uppercase. Instead tread them as what they are: Real words. So it's ``parseUrl`` rather than ``parseURL``, ``checkHttpHeader`` instead of ``checkHTTPHeader`` etc. + + +Coding Conventions +------------------ + +- The 'return' statement should only be used when it's control-flow properties + are required. Use a procedures implicit 'result' variable instead. This + improves readability. + +- Prefer to return `[]` and `""` instead of `nil`, or throw an exception if + that is appropriate. + +- Use a proc when possible, only using the more powerful facilities of macros, + templates, iterators, and converters when necessary. + +- Use the 'let' statement (not the var statement) when declaring variables that + do not change within their scope. Using the let statement ensures that + variables remain immutable, and gives those who read the code a better idea + of the code's purpose. + +- For new types, it is usually recommended to have both 'ref' and 'object' + versions of the type available for others to use. By making both variants + available for use, the type may be allocated both on the stack and the heap. + + +Conventions for multi-line statements and expressions +----------------------------------------------------- + +- Any tuple type declarations that are longer than one line should use the + regular object type layout instead. This enhances the readability of the + tuple declaration by splitting its members information across multiple lines. + + .. code-block:: nim + type + ShortTuple = tuple[a: int, b: string] + + ReallyLongTuple = tuple + wordyTupleMemberOne: string + wordyTupleMemberTwo: int + wordyTupleMemberThree: double +- Similarly, any procedure type declarations that are longer than one line + should be formatted in the style of a regular type. + + .. code-block:: nim + type + EventCallback = proc ( + timeRecieved: Time + errorCode: int + event: Event + ) +- Multi-line procedure declarations/argument lists should continue on the same + column as the opening brace. This style is different from that of procedure + type declarations in order to distinguish between the heading of a procedure + and its body. If the procedure name is too long to make this style + convenient, then one of the styles for multi-line procedure calls (or + consider renaming your procedure). + + .. code-block:: nim + proc lotsOfArguments(argOne: string, argTwo: int, argThree:float + argFour: proc(), argFive: bool): int + {.heyLookALongPragma.} = +- Multi-line procedure calls should either have one argument per line (like + multi-line type declarations) or continue on the same column as the opening + parenthesis (like multi-line procedure declarations). It is suggested that + the former style be used for procedure calls with complex argument + structures, and the latter style for procedure calls with simpler argument + structures. + + .. code-block:: nim + # Each argument on a new line, like type declarations + # Best suited for 'complex' procedure calls. + readDirectoryChangesW( + directoryHandle.THandle, + buffer.start, + bufferSize.int32, + watchSubdir.WinBool, + filterFlags, + cast[ptr dword](nil), + cast[Overlapped](ol), + cast[OverlappedCompletionRoutine](nil) + ) + + # Multiple arguments on new lines, aligned to the opening parenthesis + # Best suited for 'simple' procedure calls + startProcess(nimExecutable, currentDirectory, compilerArguments + environment, processOptions) diff --git a/doc/nimc.txt b/doc/nimc.txt index 831fce567..95449d060 100644 --- a/doc/nimc.txt +++ b/doc/nimc.txt @@ -263,416 +263,6 @@ Nim manual. Some of the features here only make sense for the C code generator and are subject to change. -NoDecl pragma -------------- -The ``noDecl`` pragma can be applied to almost any symbol (variable, proc, -type, etc.) and is sometimes useful for interoperability with C: -It tells Nim that it should not generate a declaration for the symbol in -the C code. For example: - -.. code-block:: Nim - var - EACCES {.importc, noDecl.}: cint # pretend EACCES was a variable, as - # Nim does not know its value - -However, the ``header`` pragma is often the better alternative. - -**Note**: This will not work for the LLVM backend. - - -Header pragma -------------- -The ``header`` pragma is very similar to the ``noDecl`` pragma: It can be -applied to almost any symbol and specifies that it should not be declared -and instead the generated code should contain an ``#include``: - -.. code-block:: Nim - type - PFile {.importc: "FILE*", header: "<stdio.h>".} = distinct pointer - # import C's FILE* type; Nim will treat it as a new pointer type - -The ``header`` pragma always expects a string constant. The string contant -contains the header file: As usual for C, a system header file is enclosed -in angle brackets: ``<>``. If no angle brackets are given, Nim -encloses the header file in ``""`` in the generated C code. - -**Note**: This will not work for the LLVM backend. - - -IncompleteStruct pragma ------------------------ -The ``incompleteStruct`` pragma tells the compiler to not use the -underlying C ``struct`` in a ``sizeof`` expression: - -.. code-block:: Nim - type - DIR* {.importc: "DIR", header: "<dirent.h>", - final, pure, incompleteStruct.} = object - - -Compile pragma --------------- -The ``compile`` pragma can be used to compile and link a C/C++ source file -with the project: - -.. code-block:: Nim - {.compile: "myfile.cpp".} - -**Note**: Nim computes a CRC checksum and only recompiles the file if it -has changed. You can use the ``-f`` command line option to force recompilation -of the file. - - -Link pragma ------------ -The ``link`` pragma can be used to link an additional file with the project: - -.. code-block:: Nim - {.link: "myfile.o".} - - -PassC pragma ------------- -The ``passC`` pragma can be used to pass additional parameters to the C -compiler like you would using the commandline switch ``--passC``: - -.. code-block:: Nim - {.passC: "-Wall -Werror".} - -Note that you can use ``gorge`` from the `system module <system.html>`_ to -embed parameters from an external command at compile time: - -.. code-block:: Nim - {.passC: gorge("pkg-config --cflags sdl").} - -PassL pragma ------------- -The ``passL`` pragma can be used to pass additional parameters to the linker -like you would using the commandline switch ``--passL``: - -.. code-block:: Nim - {.passL: "-lSDLmain -lSDL".} - -Note that you can use ``gorge`` from the `system module <system.html>`_ to -embed parameters from an external command at compile time: - -.. code-block:: Nim - {.passL: gorge("pkg-config --libs sdl").} - - -Emit pragma ------------ -The ``emit`` pragma can be used to directly affect the output of the -compiler's code generator. So it makes your code unportable to other code -generators/backends. Its usage is highly discouraged! However, it can be -extremely useful for interfacing with `C++`:idx: or `Objective C`:idx: code. - -Example: - -.. code-block:: Nim - {.emit: """ - static int cvariable = 420; - """.} - - {.push stackTrace:off.} - proc embedsC() = - var nimVar = 89 - # use backticks to access Nim symbols within an emit section: - {.emit: """fprintf(stdout, "%d\n", cvariable + (int)`nimVar`);""".} - {.pop.} - - embedsC() - -As can be seen from the example, to Nim symbols can be referred via backticks. -Use two backticks to produce a single verbatim backtick. - - -ImportCpp pragma ----------------- - -**Note**: `c2nim <c2nim.html>`_ can parse a large subset of C++ and knows -about the ``importcpp`` pragma pattern language. It is not necessary -to know all the details described here. - - -Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the -``importcpp`` pragma can be used to import `C++`:idx: methods or C++ symbols -in general. The generated code then uses the C++ method calling -syntax: ``obj->method(arg)``. In combination with the ``header`` and ``emit`` -pragmas this allows *sloppy* interfacing with libraries written in C++: - -.. code-block:: Nim - # Horrible example of how to interface with a C++ engine ... ;-) - - {.link: "/usr/lib/libIrrlicht.so".} - - {.emit: """ - using namespace irr; - using namespace core; - using namespace scene; - using namespace video; - using namespace io; - using namespace gui; - """.} - - const - irr = "<irrlicht/irrlicht.h>" - - type - IrrlichtDeviceObj {.final, header: irr, - importcpp: "IrrlichtDevice".} = object - IrrlichtDevice = ptr IrrlichtDeviceObj - - proc createDevice(): IrrlichtDevice {. - header: irr, importcpp: "createDevice(@)".} - proc run(device: IrrlichtDevice): bool {. - header: irr, importcpp: "#.run(@)".} - -The compiler needs to be told to generate C++ (command ``cpp``) for -this to work. The conditional symbol ``cpp`` is defined when the compiler -emits C++ code. - - -Namespaces -~~~~~~~~~~ - -The *sloppy interfacing* example uses ``.emit`` to produce ``using namespace`` -declarations. It is usually much better to instead refer to the imported name -via the ``namespace::identifier`` notation: - -.. code-block:: nim - type - IrrlichtDeviceObj {.final, header: irr, - importcpp: "irr::IrrlichtDevice".} = object - - -Importcpp for enums -~~~~~~~~~~~~~~~~~~~ - -When ``importcpp`` is applied to an enum type the numerical enum values are -annotated with the C++ enum type, like in this example: ``((TheCppEnum)(3))``. -(This turned out to be the simplest way to implement it.) - - -Importcpp for procs -~~~~~~~~~~~~~~~~~~~ - -Note that the ``importcpp`` variant for procs uses a somewhat cryptic pattern -language for maximum flexibility: - -- A hash ``#`` symbol is replaced by the first or next argument. -- A dot following the hash ``#.`` indicates that the call should use C++'s dot - or arrow notation. -- An at symbol ``@`` is replaced by the remaining arguments, separated by - commas. - -For example: - -.. code-block:: nim - proc cppMethod(this: CppObj, a, b, c: cint) {.importcpp: "#.CppMethod(@)".} - var x: ptr CppObj - cppMethod(x[], 1, 2, 3) - -Produces: - -.. code-block:: C - x->CppMethod(1, 2, 3) - -As a special rule to keep backwards compatibility with older versions of the -``importcpp`` pragma, if there is no special pattern -character (any of ``# ' @``) at all, C++'s -dot or arrow notation is assumed, so the above example can also be written as: - -.. code-block:: nim - proc cppMethod(this: CppObj, a, b, c: cint) {.importcpp: "CppMethod".} - -Note that the pattern language naturally also covers C++'s operator overloading -capabilities: - -.. code-block:: nim - proc vectorAddition(a, b: Vec3): Vec3 {.importcpp: "# + #".} - proc dictLookup(a: Dict, k: Key): Value {.importcpp: "#[#]".} - - -- An apostrophe ``'`` followed by an integer ``i`` in the range 0..9 - is replaced by the i'th parameter *type*. The 0th position is the result - type. This can be used to pass types to C++ function templates. Between - the ``'`` and the digit an asterisk can be used to get to the base type - of the type. (So it "takes away a star" from the type; ``T*`` becomes ``T``.) - Two stars can be used to get to the element type of the element type etc. - -For example: - -.. code-block:: nim - - type Input {.importcpp: "System::Input".} = object - proc getSubsystem*[T](): ptr T {.importcpp: "SystemManager::getSubsystem<'*0>()".} - - let x: ptr Input = getSubsystem[Input]() - -Produces: - -.. code-block:: C - x = SystemManager::getSubsystem<System::Input>() - - -- ``#@`` is a special case to support a ``cnew`` operation. It is required so - that the call expression is inlined directly, without going through a - temporary location. This is only required to circumvent a limitation of the - current code generator. - -For example C++'s ``new`` operator can be "imported" like this: - -.. code-block:: nim - proc cnew*[T](x: T): ptr T {.importcpp: "(new '*0#@)", nodecl.} - - # constructor of 'Foo': - proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)".} - - let x = cnew constructFoo(3, 4) - -Produces: - -.. code-block:: C - x = new Foo(3, 4) - -However, depending on the use case ``new Foo`` can also be wrapped like this -instead: - -.. code-block:: nim - proc newFoo(a, b: cint): ptr Foo {.importcpp: "new Foo(@)".} - - let x = newFoo(3, 4) - - -Wrapping constructors -~~~~~~~~~~~~~~~~~~~~~ - -Sometimes a C++ class has a private copy constructor and so code like -``Class c = Class(1,2);`` must not be generated but instead ``Class c(1,2);``. -For this purpose the Nim proc that wraps a C++ constructor needs to be -annotated with the `constructor`:idx: pragma. This pragma also helps to generate -faster C++ code since construction then doesn't invoke the copy constructor: - -.. code-block:: nim - # a better constructor of 'Foo': - proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)", constructor.} - - -Wrapping destructors -~~~~~~~~~~~~~~~~~~~~ - -Since Nim generates C++ directly, any destructor is called implicitly by the -C++ compiler at the scope exits. This means that often one can get away with -not wrapping the destructor at all! However when it needs to be invoked -explicitly, it needs to be wrapped. But the pattern language already provides -everything that is required for that: - -.. code-block:: nim - proc destroyFoo(this: var Foo) {.importcpp: "#.~Foo()".} - - -Importcpp for objects -~~~~~~~~~~~~~~~~~~~~~ - -Generic ``importcpp``'ed objects are mapped to C++ templates. This means that -you can import C++'s templates rather easily without the need for a pattern -language for object types: - -.. code-block:: nim - type - StdMap {.importcpp: "std::map", header: "<map>".} [K, V] = object - proc `[]=`[K, V](this: var StdMap[K, V]; key: K; val: V) {. - importcpp: "#[#] = #", header: "<map>".} - - var x: StdMap[cint, cdouble] - x[6] = 91.4 - - -Produces: - -.. code-block:: C - std::map<int, double> x; - x[6] = 91.4; - - -ImportObjC pragma ------------------ -Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the -``importobjc`` pragma can be used to import `Objective C`:idx: methods. The -generated code then uses the Objective C method calling syntax: ``[obj method -param1: arg]``. In addition with the ``header`` and ``emit`` pragmas this -allows *sloppy* interfacing with libraries written in Objective C: - -.. code-block:: Nim - # horrible example of how to interface with GNUStep ... - - {.passL: "-lobjc".} - {.emit: """ - #include <objc/Object.h> - @interface Greeter:Object - { - } - - - (void)greet:(long)x y:(long)dummy; - @end - - #include <stdio.h> - @implementation Greeter - - - (void)greet:(long)x y:(long)dummy - { - printf("Hello, World!\n"); - } - @end - - #include <stdlib.h> - """.} - - type - Id {.importc: "id", header: "<objc/Object.h>", final.} = distinct int - - proc newGreeter: Id {.importobjc: "Greeter new", nodecl.} - proc greet(self: Id, x, y: int) {.importobjc: "greet", nodecl.} - proc free(self: Id) {.importobjc: "free", nodecl.} - - var g = newGreeter() - g.greet(12, 34) - g.free() - -The compiler needs to be told to generate Objective C (command ``objc``) for -this to work. The conditional symbol ``objc`` is defined when the compiler -emits Objective C code. - - -CodegenDecl pragma ------------------- - -The ``codegenDecl`` pragma can be used to directly influence Nim's code -generator. It receives a format string that determines how the variable or -proc is declared in the generated code: - -.. code-block:: nim - var - a {.codegenDecl: "$# progmem $#".}: int - - proc myinterrupt() {.codegenDecl: "__interrupt $# $#$#".} = - echo "realistic interrupt handler" - - -InjectStmt pragma ------------------ - -The ``injectStmt`` pragma can be used to inject a statement before every -other statement in the current module. It is only supposed to be used for -debugging: - -.. code-block:: nim - {.injectStmt: gcInvariants().} - - # ... complex code here that produces crashes ... - - LineDir option -------------- The ``lineDir`` option can be turned on or off. If turned on the @@ -706,15 +296,6 @@ The *breakpoint* pragma was specially added for the sake of debugging with ENDB. See the documentation of `endb <endb.html>`_ for further information. -Volatile pragma ---------------- -The ``volatile`` pragma is for variables only. It declares the variable as -``volatile``, whatever that means in C/C++ (its semantics are not well defined -in C/C++). - -**Note**: This pragma will not exist for the LLVM backend. - - DynlibOverride ============== diff --git a/doc/nimdoc.css b/doc/nimdoc.css index e3bab07de..a002b6be1 100644 --- a/doc/nimdoc.css +++ b/doc/nimdoc.css @@ -1,4 +1,9 @@ /* +NOTE - THIS IS PROBABLY NOT THE CSS FILE YOU WANT +The CSS text used by Nim's documentation tools (such as 'koch web', +'rst2html', etc) is contained in 'config\nimdoc.cfg' +*/ +/* :Author: David Goodger :Contact: goodger@python.org :Date: $Date: 2006-05-21 22:44:42 +0200 (Sun, 21 May 2006) $ diff --git a/doc/nimfix.txt b/doc/nimfix.txt index 6d78f3e3f..62064fe69 100644 --- a/doc/nimfix.txt +++ b/doc/nimfix.txt @@ -1,12 +1,12 @@ -===================== - Nimfix User Guide -===================== - -:Author: Andreas Rumpf -:Version: |nimversion| - +===================== + Nimfix User Guide +===================== + +:Author: Andreas Rumpf +:Version: |nimversion| + **WARNING**: Nimfix is currently beta-quality. - + Nimfix is a tool to help you upgrade from Nimrod (<= version 0.9.6) to Nim (=> version 0.10.0). @@ -48,7 +48,7 @@ Options: --wholeProject overwrite every processed file. --checkExtern:on|off style check also extern names --styleCheck:on|off|auto performs style checking for identifiers - and suggests an alternative spelling; + and suggests an alternative spelling; 'auto' corrects the spelling. In addition, all command line options of Nim are supported. diff --git a/doc/nimgrep.txt b/doc/nimgrep.txt index 2d429e8b5..791ead162 100644 --- a/doc/nimgrep.txt +++ b/doc/nimgrep.txt @@ -7,11 +7,11 @@ Nimgrep is a command line tool for search&replace tasks. It can search for -regex or peg patterns and can search whole directories at once. User +regex or peg patterns and can search whole directories at once. User confirmation for every single replace operation can be requested. -Nimgrep has particularly good support for Nim's -eccentric *style insensitivity*. Apart from that it is a generic text +Nimgrep has particularly good support for Nim's +eccentric *style insensitivity*. Apart from that it is a generic text manipulation tool. @@ -34,10 +34,10 @@ Options: --find, -f find the pattern (default) --replace, -r replace the pattern --peg pattern is a peg - --re pattern is a regular expression (default); extended + --re pattern is a regular expression (default); extended syntax for the regular expression is always turned on --recursive process directories recursively - --confirm confirm each occurrence/replacement; there is a chance + --confirm confirm each occurrence/replacement; there is a chance to abort any time without touching the file --stdin read pattern from stdin (to avoid the shell's confusing quoting rules) diff --git a/doc/niminst.txt b/doc/niminst.txt index ca05cc514..7bd0f719e 100644 --- a/doc/niminst.txt +++ b/doc/niminst.txt @@ -11,12 +11,12 @@ Introduction ============ niminst is a tool to generate an installer for a Nim program. Currently -it can create an installer for Windows +it can create an installer for Windows via `Inno Setup <http://www.jrsoftware.org/isinfo.php>`_ as well as -installation/deinstallation scripts for UNIX. Later versions will support +installation/deinstallation scripts for UNIX. Later versions will support Linux' package management systems. -niminst works by reading a configuration file that contains all the +niminst works by reading a configuration file that contains all the information that it needs to generate an installer for the different operating systems. @@ -24,7 +24,7 @@ systems. Configuration file ================== -niminst uses the Nim `parsecfg <parsecfg.html>`_ module to parse the +niminst uses the Nim `parsecfg <parsecfg.html>`_ module to parse the configuration file. Here's an example of how the syntax looks like: .. include:: doc/mytest.cfg @@ -54,10 +54,10 @@ Key description ``OS`` the OSes to generate C code for; for example: ``"windows;linux;macosx"`` ``CPU`` the CPUs to generate C code for; for example: - ``"i386;amd64;powerpc"`` + ``"i386;amd64;powerpc"`` ``Authors`` the project's authors ``Description`` the project's description -``App`` the application's type: "Console" or "GUI". If +``App`` the application's type: "Console" or "GUI". If "Console", niminst generates a special batch file for Windows to open up the command line shell. ``License`` the filename of the application's license @@ -69,7 +69,7 @@ Key description Many sections support the ``files`` key. Listed filenames can be separated by semicolon or the ``files`` key can be repeated. Wildcards -in filenames are supported. If it is a directory name, all files in the +in filenames are supported. If it is a directory name, all files in the directory are used:: [Config] @@ -87,35 +87,35 @@ will be installed into the OS's configuration directory. Documentation section --------------------- -The ``documentation`` section supports the ``files`` key. -Listed files will be installed into the OS's native documentation directory +The ``documentation`` section supports the ``files`` key. +Listed files will be installed into the OS's native documentation directory (which might be ``$appdir/doc``). -There is a ``start`` key which determines whether the Windows installer +There is a ``start`` key which determines whether the Windows installer generates a link to e.g. the ``index.html`` of your documentation. Other section ------------- -The ``other`` section currently only supports the ``files`` key. -Listed files will be installed into the application installation directory +The ``other`` section currently only supports the ``files`` key. +Listed files will be installed into the application installation directory (``$appdir``). Lib section ----------- -The ``lib`` section currently only supports the ``files`` key. -Listed files will be installed into the OS's native library directory +The ``lib`` section currently only supports the ``files`` key. +Listed files will be installed into the OS's native library directory (which might be ``$appdir/lib``). Windows section --------------- -The ``windows`` section supports the ``files`` key for Windows specific files. -Listed files will be installed into the application installation directory +The ``windows`` section supports the ``files`` key for Windows specific files. +Listed files will be installed into the application installation directory (``$appdir``). Other possible options are: @@ -133,8 +133,8 @@ Key description UnixBin section --------------- -The ``UnixBin`` section currently only supports the ``files`` key. -Listed files will be installed into the OS's native bin directory +The ``UnixBin`` section currently only supports the ``files`` key. +Listed files will be installed into the OS's native bin directory (e.g. ``/usr/local/bin``). The exact location depends on the installation path the user specifies when running the ``install.sh`` script. @@ -150,7 +150,7 @@ Key description ``InstallScript`` boolean flag whether an installation shell script should be generated. Example: ``InstallScript: "Yes"`` ``UninstallScript`` boolean flag whether a deinstallation shell script - should be generated. + should be generated. Example: ``UninstallScript: "Yes"`` ==================== ======================================================= @@ -163,7 +163,7 @@ Possible options are: ==================== ======================================================= Key description ==================== ======================================================= -``path`` Path to Inno Setup. +``path`` Path to Inno Setup. Example: ``path = r"c:\inno setup 5\iscc.exe"`` ``flags`` Flags to pass to Inno Setup. Example: ``flags = "/Q"`` @@ -178,7 +178,7 @@ Possible options are: ==================== ======================================================= Key description ==================== ======================================================= -``path`` Path to the C compiler. +``path`` Path to the C compiler. ``flags`` Flags to pass to the C Compiler. Example: ``flags = "-w"`` ==================== ======================================================= diff --git a/doc/nims.txt b/doc/nims.txt new file mode 100644 index 000000000..7c76efe42 --- /dev/null +++ b/doc/nims.txt @@ -0,0 +1,119 @@ +================================ + NimScript +================================ + +Strictly speaking, ``NimScript`` is the subset of Nim that can be evaluated +by Nim's builtin virtual machine (VM). This VM is used for Nim's compiletime +function evaluation features, but also replaces Nim's existing configuration +system. + +So instead of a ``myproject.nim.cfg`` configuration file, you can use +a ``myproject.nims`` file that simply contains Nim code controlling the +compilation process. For a directory wide configuration, use ``config.nims`` +instead of ``nim.cfg``. + +The VM cannot deal with ``importc``, the FFI is not available, so there are not +many stdlib modules that you can use with Nim's VM. However, at least the +following modules are available: + +* `strutils <strutils.html>`_ +* `ospaths <ospaths.html>`_ +* `math <math.html>`_ + +The `system <system.html>`_ module in NimScript mode additionally supports +these operations: `nimscript <nimscript.html>`_. + + +NimScript as a configuration file +================================= + +What is ``x.y.key = "value"`` in the configuration file +becomes ``switch("x.y.key", "value")``. ``--option`` is ``switch("option")``. +The ``system`` module also exports 2 ``--`` templates for convenience: + +.. code-block:: nim + --forceBuild + # is the same as: + switch("forceBuild") + + +NimScript as a build tool +========================= + +The ``task`` template that the ``system`` module defines allows a NimScript +file to be used as a build tool. The following example defines a +task ``build`` that is an alias for the ``c`` command: + +.. code-block:: nim + task build, "builds an example": + setCommand "c" + + +In fact, as a convention the following tasks should be available: + +========= =================================================== +Task Description +========= =================================================== +``build`` Build the project with the required + backend (``c``, ``cpp`` or ``js``). +``tests`` Runs the tests belonging to the project. +``bench`` Runs benchmarks belonging to the project. +========= =================================================== + + +If the task runs an external command via ``exec`` it should afterwards call +``setCommand "nop"`` to tell the Nim compiler that nothing else needs to be +done: + +.. code-block:: nim + + task tests, "test regular expressions": + exec "nim c -r tests" + setCommand "nop" + + +Nimble integration +================== + +A ``project.nims`` file can also be used as an alternative to +a ``project.nimble`` file to specify the meta information (for example, author, +description) and dependencies of a Nimble package. This means you can easily +have platform specific dependencies: + +.. code-block:: nim + + version = "1.0" + author = "The green goo." + description = "Lexer generation and regex implementation for Nim." + license = "MIT" + + when defined(windows): + requires "oldwinapi >= 1.0" + else: + requires "gtk2 >= 1.0" + + + + +Standalone NimScript +==================== + +NimScript can also be used directly as a portable replacement for Bash and +Batch files. Use ``nim e myscript.nims`` to run ``myscript.nims``. For example, +installation of Nimble is done with this simple script: + +.. code-block:: nim + + mode = ScriptMode.Verbose + + var id = 0 + while dirExists("nimble" & $id): + inc id + + exec "git clone https://github.com/nim-lang/nimble.git nimble" & $id + + withDir "nimble" & $id & "/src": + exec "nim c nimble" + + mvFile "nimble" & $id & "/src/nimble".toExe, "bin/nimble".toExe + diff --git a/doc/nimsuggest.txt b/doc/nimsuggest.txt new file mode 100644 index 000000000..2b52196b9 --- /dev/null +++ b/doc/nimsuggest.txt @@ -0,0 +1,174 @@ +================================ + Nim IDE Integration Guide +================================ + +:Author: Unknown +:Version: |nimversion| + +.. contents:: + + +Nim differs from many other compilers in that it is really fast, +and being so fast makes it suited to provide external queries for +text editors about the source code being written. Through the +``nimsuggest`` tool, any IDE +can query a ``.nim`` source file and obtain useful information like +definition of symbols or suggestions for completion. + +This document will guide you through the available options. If you +want to look at practical examples of nimsuggest support you can look +at the +`various editor integrations <https://github.com/Araq/Nim/wiki/Editor-Support>`_ +already available. + + +Installation +============ + +Nimsuggest is available as a Nimble package but currently does not install +properly via Nimble. As nimsuggest is part of the compiler it also doesn't make +too much sense as a Nimble package. Instead we will do the building manually:: + + cd compiler/nimsuggest + nim c -d:release nimsuggest + cp nimsuggest ../../bin + # OR: copy the nimsuggest binary to where your 'nim' binary is + cd ../.. + + + +Nimsuggest invocation +===================== + +Run it via ``nimsuggest --stdin myproject.nim``. Nimsuggest is a server that +takes queries that are related to ``myproject``. There is some support so that +you can throw random ``.nim`` files which are not part of ``myproject`` at +Nimsuggest too, but usually the query refer to modules/files that are part of +``myproject``. + +``--stdin`` means that Nimsuggest reads the query from ``stdin``. This is great +for testing things out and playing with it but for an editor communication +via sockets is more reasonable so that is the default. It listens to port 6000 +by default. + + +Specifying the location of the query +------------------------------------ + +Nimsuggest than waits for queries to process. A query consists of a +cryptic 3 letter "command" ``def`` or ``con`` or ``sug`` or ``use`` followed by +a location. A query location consists of: + + +``file.nim`` + This is the name of the module or include file the query refers to. + +``dirtyfile.nim`` + This is optional. + + The ``file`` paramater is enough for static analysis, but IDEs + tend to have *unsaved buffers* where the user may still be in + the middle of typing a line. In such situations the IDE can + save the current contents to a temporary file and then use the + ``dirtyfile.nim`` option to tell Nimsuggest that ``foobar.nim`` should + be taken from ``temporary/foobar.nim``. + + +``line`` + An integer with the line you are going to query. For the compiler + lines start at **1**. + +``col`` + An integer with the column you are going to query. For the + compiler columns start at **1**. + + +Definitions +----------- + +The ``def`` Nimsuggest command performs a query about the definition +of a specific symbol. If available, Nimsuggest will answer with the +type, source file, line/column information and other accessory data +if available like a docstring. With this information an IDE can +provide the typical *Jump to definition* where a user puts the +cursor on a symbol or uses the mouse to select it and is redirected +to the place where the symbol is located. + +Since Nim is implemented in Nim, one of the nice things of +this feature is that any user with an IDE supporting it can quickly +jump around the standard library implementation and see exactly +what a proc does, learning about the language and seeing real life +examples of how to write/implement specific features. + +Nimsuggest will always answer with a single definition or none if it +can't find any valid symbol matching the position of the query. + + +Suggestions +----------- + +The ``sug`` Nimsuggest command performs a query about possible +completion symbols at some point in the file. + +The typical usage scenario for this option is to call it after the +user has typed the dot character for `the object oriented call +syntax <tut2.html#method-call-syntax>`_. Nimsuggest will try to return +the suggestions sorted first by scope (from innermost to outermost) +and then by item name. + + +Invocation context +------------------ + +The ``con`` Nimsuggest command is very similar to the suggestions +command, but instead of being used after the user has typed a dot +character, this one is meant to be used after the user has typed +an opening brace to start typing parameters. + + +Symbol usages +------------- + +The ``use`` Nimsuggest command lists all usages of the symbol at +a position. IDEs can use this to find all the places in the file +where the symbol is used and offer the user to rename it in all +places at the same time. + +For this kind of query the IDE will most likely ignore all the +type/signature info provided by Nimsuggest and concentrate on the +filename, line and column position of the multiple returned answers. + + + +Parsing nimsuggest output +========================= + +Nimsuggest output is always returned on single lines separated by +tab characters (``\t``). The values of each column are: + +1. Three characters indicating the type of returned answer (e.g. + ``def`` for definition, ``sug`` for suggestion, etc). +2. Type of the symbol. This can be ``skProc``, ``skLet``, and just + about any of the enums defined in the module ``compiler/ast.nim``. +3. Full qualitifed path of the symbol. If you are querying a symbol + defined in the ``proj.nim`` file, this would have the form + ``proj.symbolName``. +4. Type/signature. For variables and enums this will contain the + type of the symbol, for procs, methods and templates this will + contain the full unique signature (e.g. ``proc (File)``). +5. Full path to the file containing the symbol. +6. Line where the symbol is located in the file. Lines start to + count at **1**. +7. Column where the symbol is located in the file. Columns start + to count at **1**. +8. Docstring for the symbol if available or the empty string. To + differentiate the docstring from end of answer, + the docstring is always provided enclosed in double quotes, and + if the docstring spans multiple lines, all following lines of the + docstring will start with a blank space to align visually with + the starting quote. + + Also, you won't find raw ``\n`` characters breaking the one + answer per line format. Instead you will need to parse sequences + in the form ``\xHH``, where *HH* is a hexadecimal value (e.g. + newlines generate the sequence ``\x0A``). diff --git a/doc/pegdocs.txt b/doc/pegdocs.txt index 118949cad..4c557aed8 100644 --- a/doc/pegdocs.txt +++ b/doc/pegdocs.txt @@ -14,7 +14,7 @@ notation meaning order, to the text ahead, until one of them succeeds and possibly consumes some text. Indicate success if one of expressions succeeded. Otherwise do not consume any text - and indicate failure. + and indicate failure. ``A ... Z`` Sequence: Apply expressions `A`, ..., `Z`, in this order, to consume consecutive portions of the text ahead, as long as they succeed. Indicate success if all succeeded. @@ -27,11 +27,11 @@ notation meaning ``{E}`` Capture: Apply expression `E` and store the substring that matched `E` into a *capture* that can be accessed after the matching process. -``$i`` Back reference to the ``i``th capture. ``i`` counts from 1. -``$`` Anchor: Matches at the end of the input. No character - is consumed. Same as ``!.``. -``^`` Anchor: Matches at the start of the input. No character - is consumed. +``$i`` Back reference to the ``i``th capture. ``i`` counts from 1. +``$`` Anchor: Matches at the end of the input. No character + is consumed. Same as ``!.``. +``^`` Anchor: Matches at the start of the input. No character + is consumed. ``&E`` And predicate: Indicate success if expression `E` matches the text ahead; otherwise indicate failure. Do not consume any text. @@ -41,15 +41,15 @@ notation meaning ``E+`` One or more: Apply expression `E` repeatedly to match the text ahead, as long as it succeeds. Consume the matched text (if any) and indicate success if there was at least - one match. Otherwise indicate failure. + one match. Otherwise indicate failure. ``E*`` Zero or more: Apply expression `E` repeatedly to match the text ahead, as long as it succeeds. Consume the matched - text (if any). Always indicate success. + text (if any). Always indicate success. ``E?`` Zero or one: If expression `E` matches the text ahead, - consume it. Always indicate success. + consume it. Always indicate success. ``[s]`` Character class: If the character ahead appears in the string `s`, consume it and indicate success. Otherwise - indicate failure. + indicate failure. ``[a-b]`` Character range: If the character ahead is one from the range `a` through `b`, consume it and indicate success. Otherwise indicate failure. @@ -70,7 +70,7 @@ notation meaning failure. ``@E`` Search: Shorthand for ``(!E .)* E``. (Search loop for the pattern `E`.) -``{@} E`` Captured Search: Shorthand for ``{(!E .)*} E``. (Search +``{@} E`` Captured Search: Shorthand for ``{(!E .)*} E``. (Search loop for the pattern `E`.) Everything until and exluding `E` is captured. ``@@ E`` Same as ``{@} E``. @@ -79,7 +79,7 @@ notation meaning matching engine.** ``\identifier`` Built-in macro for a longer expression. ``\ddd`` Character with decimal code *ddd*. -``\"``, etc Literal ``"``, etc. +``\"``, etc Literal ``"``, etc. =============== ============================================================ @@ -101,9 +101,9 @@ macro meaning ``\n`` any newline combination: ``\10 / \13\10 / \13`` ``\i`` ignore case for matching; use this at the start of the PEG ``\y`` ignore style for matching; use this at the start of the PEG -``\skip`` pat skip pattern *pat* before trying to match other tokens; +``\skip`` pat skip pattern *pat* before trying to match other tokens; this is useful for whitespace skipping, for example: - ``\skip(\s*) {\ident} ':' {\ident}`` matches key value + ``\skip(\s*) {\ident} ':' {\ident}`` matches key value pairs ignoring whitespace around the ``':'``. ``\ident`` a standard ASCII identifier: ``[a-zA-Z_][a-zA-Z_0-9]*`` ``\letter`` any Unicode letter @@ -133,42 +133,42 @@ The PEG parser implements this grammar (written in PEG syntax):: # Example grammar of PEG in PEG syntax. # Comments start with '#'. # First symbol is the start symbol. - + grammar <- rule* / expr - + identifier <- [A-Za-z][A-Za-z0-9_]* charsetchar <- "\\" . / [^\]] charset <- "[" "^"? (charsetchar ("-" charsetchar)?)+ "]" stringlit <- identifier? ("\"" ("\\" . / [^"])* "\"" / "'" ("\\" . / [^'])* "'") builtin <- "\\" identifier / [^\13\10] - + comment <- '#' @ \n ig <- (\s / comment)* # things to ignore - + rule <- identifier \s* "<-" expr ig identNoArrow <- identifier !(\s* "<-") prefixOpr <- ig '&' / ig '!' / ig '@' / ig '{@}' / ig '@@' literal <- ig identifier? '$' [0-9]+ / '$' / '^' / - ig identNoArrow / - ig charset / - ig stringlit / - ig builtin / - ig '.' / - ig '_' / + ig identNoArrow / + ig charset / + ig stringlit / + ig builtin / + ig '.' / + ig '_' / (ig "(" expr ig ")") postfixOpr <- ig '?' / ig '*' / ig '+' primary <- prefixOpr* (literal postfixOpr*) - + # Concatenation has higher priority than choice: # ``a b / c`` means ``(a b) / c`` - + seqExpr <- primary+ expr <- seqExpr (ig "/" expr)* -**Note**: As a special syntactic extension if the whole PEG is only a single -expression, identifiers are not interpreted as non-terminals, but are +**Note**: As a special syntactic extension if the whole PEG is only a single +expression, identifiers are not interpreted as non-terminals, but are interpreted as verbatim string: .. code-block:: nim @@ -185,10 +185,10 @@ Check if `s` matches Nim's "while" keyword: .. code-block:: nim s =~ peg" y'while'" -Exchange (key, val)-pairs: +Exchange (key, val)-pairs: .. code-block:: nim - "key: val; key2: val2".replace(peg"{\ident} \s* ':' \s* {\ident}", "$2: $1") + "key: val; key2: val2".replacef(peg"{\ident} \s* ':' \s* {\ident}", "$2: $1") Determine the ``#include``'ed files of a C file: diff --git a/doc/readme.txt b/doc/readme.txt index e5d9e2c27..6f4cece87 100644 --- a/doc/readme.txt +++ b/doc/readme.txt @@ -1,7 +1,7 @@ -============================ -Nim's documenation system -============================ - -This folder contains Nim's documentation. The documentation -is written in a format called *reStructuredText*, a markup language that reads -like ASCII and can be converted to HTML automatically! +============================ +Nim's documenation system +============================ + +This folder contains Nim's documentation. The documentation +is written in a format called *reStructuredText*, a markup language that reads +like ASCII and can be converted to HTML automatically! diff --git a/doc/regexprs.txt b/doc/regexprs.txt index d912c623e..5c6d37e89 100644 --- a/doc/regexprs.txt +++ b/doc/regexprs.txt @@ -175,17 +175,17 @@ for themselves. For example: example meaning ============== ============================================================ ``\040`` is another way of writing a space -``\40`` is the same, provided there are fewer than 40 previous +``\40`` is the same, provided there are fewer than 40 previous capturing subpatterns ``\7`` is always a back reference ``\11`` might be a back reference, or another way of writing a tab ``\011`` is always a tab ``\0113`` is a tab followed by the character "3" -``\113`` might be a back reference, otherwise the character with +``\113`` might be a back reference, otherwise the character with octal code 113 -``\377`` might be a back reference, otherwise the byte consisting +``\377`` might be a back reference, otherwise the byte consisting entirely of 1 bits -``\81`` is either a back reference, or a binary zero followed by +``\81`` is either a back reference, or a binary zero followed by the two characters "8" and "1" ============== ============================================================ @@ -240,7 +240,7 @@ even when Unicode character property support is available. Simple assertions ----------------- -The fourth use of backslash is for certain `simple assertions`:idx:. An +The fourth use of backslash is for certain `simple assertions`:idx:. An assertion specifies a condition that has to be met at a particular point in a match, without consuming any characters from the subject string. The use of subpatterns for more complicated assertions is described below. The diff --git a/doc/sets_fragment.txt b/doc/sets_fragment.txt index 84b13e672..a6fe7555d 100644 --- a/doc/sets_fragment.txt +++ b/doc/sets_fragment.txt @@ -1,6 +1,16 @@ The set type models the mathematical notion of a set. The set's -basetype can only be an ordinal type. The reason is that sets are implemented -as high performance bit vectors. +basetype can only be an ordinal type of a certain size, namely: + * ``int8``-``int16`` + * ``uint8``/``byte``-``uint16`` + * ``char`` + * ``enum`` +or equivalent. The reason is that sets are implemented as high +performance bit vectors. Attempting to declare a set with a larger type will +result in an error: + +.. code-block:: nim + + var s: set[int64] # Error: set is too large Sets can be constructed via the set constructor: ``{}`` is the empty set. The empty set is type compatible with any concrete set type. The constructor diff --git a/doc/spawn.txt b/doc/spawn.txt index fb2f851c7..5d65243d2 100644 --- a/doc/spawn.txt +++ b/doc/spawn.txt @@ -2,7 +2,7 @@ Parallel & Spawn ========================================================== -Nim has two flavors of parallelism: +Nim has two flavors of parallelism: 1) `Structured`:idx parallelism via the ``parallel`` statement. 2) `Unstructured`:idx: parallelism via the standalone ``spawn`` statement. @@ -30,10 +30,10 @@ variables at the same time: .. code-block:: nim import threadpool, ... - + # wait until 2 out of 3 servers received the update: proc main = - var responses = newSeq[RawFlowVar](3) + var responses = newSeq[FlowVarBase](3) for i in 0..2: responses[i] = spawn tellServer(Update, "key", "value") var index = awaitAny(responses) @@ -89,7 +89,7 @@ restrictions / changes: the ``parallel`` section. This is called the *immutability check*. Currently it is not specified what exactly "complex location" means. We need to make this an optimization! -* Every array access has to be provably within bounds. This is called +* Every array access has to be provably within bounds. This is called the *bounds check*. * Slices are optimized so that no copy is performed. This optimization is not yet performed for ordinary slices outside of a ``parallel`` section. Slices diff --git a/doc/subexes.txt b/doc/subexes.txt index decf30eef..54304f033 100644 --- a/doc/subexes.txt +++ b/doc/subexes.txt @@ -1,11 +1,11 @@ Substitution Expressions (subex) ================================ -A *subex* (*Substitution Expression*) represents an advanted string +A *subex* (*Substitution Expression*) represents an advanced string substitution. In contrast to a `regex`:idx: which deals with string analysis, a *subex* deals with string synthesis. -Thanks to its conditional construct ``$[0|1|2|else]`` it supports +Thanks to its conditional construct ``$[0|1|2|else]`` it supports `internationalization`:idx: of format string literals quite well. @@ -37,7 +37,7 @@ Notation meaning ``$[zero|one|def]1`` use ``X = parseInt(arg[1])`` to determine which branch to use. If ``X == 0`` the 'zero' branch is selected, if ``X == 1`` the 'one' branch is - selected, etc. Otherwise the 'def' branch is + selected, etc. Otherwise the 'def' branch is selected. ``$x`` is interpreted in branches too. If a branch needs to contain ``|``, ``]`` put them in single quotes. To produce a verbatim single @@ -50,12 +50,12 @@ Examples .. code-block:: nim subex"$1($', '{2..})" % ["f", "a", "b", "c"] == "f(a, b, c)" - + subex"$1 $[files|file|files]{1} copied" % ["1"] == "1 file copied" - + subex"$['''|'|''''|']']#" % "0" == "'|" - + subex("type\n TEnum = enum\n $', '40c'\n '{..}") % [ "fieldNameA", "fieldNameB", "fieldNameC", "fieldNameD"] - + diff --git a/doc/tools.txt b/doc/tools.txt index 7f2830879..bad603925 100644 --- a/doc/tools.txt +++ b/doc/tools.txt @@ -4,6 +4,15 @@ Tools available with Nim The standard distribution ships with the following tools: +- | `Documentation generator <docs/docgen.html>`_ + | The builtin document generator ``nim doc2`` generates HTML documentation + from ``.nim`` source files. + +- | `Nimsuggest for IDE support <nimsuggest.html>`_ + | Through the ``nimsuggest`` tool, any IDE can query a ``.nim`` source file + and obtain useful information like definition of symbols or suggestions for + completion. + - | `Nim Installation Generator <niminst.html>`_ | How to generate a nice installer for your Nim program. diff --git a/doc/tut1.txt b/doc/tut1.txt index cb5a0c8dd..7dce8a218 100644 --- a/doc/tut1.txt +++ b/doc/tut1.txt @@ -16,11 +16,12 @@ Introduction </p></blockquote> -This document is a tutorial for the programming language *Nim*. +This document is a tutorial for the programming language *Nim*. This tutorial assumes that you are familiar with basic programming concepts like variables, types or statements but is kept very basic. The `manual <manual.html>`_ contains many more examples of the advanced language features. - +All code examples in this tutorial, as well as the ones found in the rest of +Nim's documentation, follow the `Nim style guide <nep1.html>`. The first program @@ -50,7 +51,7 @@ Commonly used commands and switches have abbreviations, so you can also use:: nim c -r greetings.nim To compile a release version use:: - + nim c -d:release greetings.nim By default the Nim compiler generates a large amount of runtime checks @@ -116,7 +117,7 @@ hash character ``#``. Documentation comments start with ``##``: .. code-block:: nim # A comment. - + var myVariable: int ## a documentation comment @@ -200,7 +201,7 @@ constant declaration at compile time: .. code-block:: nim const x = "abc" # the constant x contains the string "abc" - + Indentation can be used after the ``const`` keyword to list a whole section of constants: @@ -214,7 +215,7 @@ constants: The let statement ================= -The ``let`` statement works like the ``var`` statement but the declared +The ``let`` statement works like the ``var`` statement but the declared symbols are *single assignment* variables: After the initialization their value cannot change: @@ -228,7 +229,7 @@ and put it into a data section": .. code-block:: const input = readLine(stdin) # Error: constant expression expected - + .. code-block:: let input = readLine(stdin) # works @@ -310,8 +311,8 @@ the compiler that for every other value nothing should be done: else: discard The empty `discard statement`_ is a *do nothing* statement. The compiler knows -that a case statement with an else part cannot fail and thus the error -disappears. Note that it is impossible to cover all possible string values: +that a case statement with an else part cannot fail and thus the error +disappears. Note that it is impossible to cover all possible string values: that is why string cases always need an ``else`` branch. In general the case statement is used for subrange types or enumerations where @@ -333,8 +334,8 @@ The while statement is a simple looping construct: name = readLine(stdin) # no ``var``, because we do not declare a new variable here -The example uses a while loop to keep asking the user for his name, as long as -he types in nothing (only presses RETURN). +The example uses a while loop to keep asking the users for their name, as long +as the user types in nothing (only presses RETURN). For statement @@ -406,7 +407,7 @@ The block's *label* (``myblock`` in the example) is optional. Break statement --------------- A block can be left prematurely with a ``break`` statement. The break statement -can leave a ``while``, ``for``, or a ``block`` statement. It leaves the +can leave a ``while``, ``for``, or a ``block`` statement. It leaves the innermost construct, unless a label of a block is given: .. code-block:: nim @@ -461,7 +462,7 @@ differences: * The statements within a branch do not open a new scope. * The compiler checks the semantics and produces code *only* for the statements that belong to the first condition that evaluates to ``true``. - + The ``when`` statement is useful for writing platform specific code, similar to the ``#ifdef`` construct in the C programming language. @@ -486,14 +487,14 @@ to be indented, but single simple statements do not: .. code-block:: nim # no indentation needed for single assignment statement: if x: x = false - + # indentation needed for nested if statement: if x: if y: y = false else: y = true - + # indentation needed, because two statements follow the condition: if x: x = false @@ -514,7 +515,7 @@ contain indentation at certain places for better readability: As a rule of thumb, indentation within expressions is allowed after operators, an open parenthesis and after commas. -With parenthesis and semicolons ``(;)`` you can use statements where only +With parenthesis and semicolons ``(;)`` you can use statements where only an expression is allowed: .. code-block:: nim @@ -545,9 +546,9 @@ procedures are defined with the ``proc`` keyword: 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`` -and returns true if he answered "yes" (or something similar) and returns -false if he answered "no" (or something similar). A ``return`` statement leaves -the procedure (and therefore the while loop) immediately. The +and returns true if they answered "yes" (or something similar) and returns +false if they answered "no" (or something similar). A ``return`` statement +leaves the procedure (and therefore the while loop) immediately. The ``(question: string): bool`` syntax describes that the procedure expects a parameter named ``question`` of type ``string`` and returns a value of type ``bool``. ``Bool`` is a built-in type: the only valid values for ``bool`` are @@ -560,45 +561,45 @@ Some terminology: in the example ``question`` is called a (formal) *parameter*, Result variable --------------- -A procedure that returns a value has an implicit ``result`` variable declared +A procedure that returns a value has an implicit ``result`` variable declared that represents the return value. A ``return`` statement with no expression is a -shorthand for ``return result``. The ``result`` value is always returned +shorthand for ``return result``. The ``result`` value is always returned automatically at the end a procedure if there is no ``return`` statement at the exit. .. code-block:: nim - proc sumTillNegative(x: varargs[int]): int = + proc sumTillNegative(x: varargs[int]): int = for i in x: if i < 0: return - result = result + i - + result = result + i + echo sumTillNegative() # echos 0 echo sumTillNegative(3, 4, 5) # echos 12 echo sumTillNegative(3, 4 , -1 , 6) # echos 7 -The ``result`` variable is already implicitly declared at the start of the +The ``result`` variable is already implicitly declared at the start of the function, so declaring it again with 'var result', for example, would shadow it with a normal variable of the same name. The result variable is also already initialised with the type's default value. Note that referential data types will be ``nil`` at the start of the procedure, and thus may require manual initialisation. - + Parameters ---------- Parameters are constant in the procedure body. By default, their value cannot be -changed because this allows the compiler to implement parameter passing in the +changed because this allows the compiler to implement parameter passing in the most efficient way. If a mutable variable is needed inside the procedure, it has to be declared with ``var`` in the procedure body. Shadowing the parameter name -is possible, and actually an idiom: +is possible, and actually an idiom: .. code-block:: nim proc printSeq(s: seq, nprinted: int = -1) = var nprinted = if nprinted == -1: s.len else: min(nprinted, s.len) for i in 0 .. <nprinted: echo s[i] - + If the procedure needs to modify the argument for the caller, a ``var`` parameter can be used: @@ -630,12 +631,12 @@ allow to silently throw away a return value: The return value can be ignored implicitly if the called proc/iterator has -been declared with the ``discardable`` pragma: +been declared with the ``discardable`` pragma: .. code-block:: nim - proc p(x, y: int): int {.discardable.} = + proc p(x, y: int): int {.discardable.} = return x + y - + p(3, 4) # now valid The ``discard`` statement can also be used to create block comments as @@ -757,16 +758,25 @@ However, this cannot be done for mutually recursive procedures: # forward declaration: proc even(n: int): bool - proc odd(n: int): bool = +proc even(n: int): bool + +proc odd(n: int): bool = + assert(n >= 0) # makes sure we don't run into negative recursion + if n == 0: false + else: n == 1 or even(n-1) - proc even(n: int): bool = +proc even(n: int): bool = + assert(n >= 0) # makes sure we don't run into negative recursion + if n == 1: false + else: n == 0 or odd(n-1) Here ``odd`` depends on ``even`` and vice versa. Thus ``even`` needs to be 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. +procedure's body. The ``assert`` just adds border conditions, and will be +covered later in `Modules`_ section. Later versions of the language will weaken the requirements for forward declarations. @@ -899,7 +909,7 @@ object on the heap, so there is a trade-off to be made here. Integers -------- -Nim has these integer types built-in: +Nim has these integer types built-in: ``int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64``. The default integer type is ``int``. Integer literals can have a *type suffix* @@ -1114,7 +1124,7 @@ Arrays An array is a simple fixed length container. Each element in the array has the same type. The array's index type can be any ordinal type. -Arrays can be constructed via ``[]``: +Arrays can be constructed via ``[]``: .. code-block:: nim @@ -1224,8 +1234,8 @@ Example: .. code-block:: nim var - x: seq[int] # a sequence of integers - x = @[1, 2, 3, 4, 5, 6] # the @ turns the array into a sequence + x: seq[int] # a reference to a sequence of integers + x = @[1, 2, 3, 4, 5, 6] # the @ turns the array into a sequence allocated on the heap Sequence variables are initialized with ``nil``. However, most sequence operations cannot deal with ``nil`` (leading to an exception being @@ -1269,6 +1279,23 @@ The `len <system.html#len,TOpenArray>`_, `low <system.html#low>`_ and `high with a compatible base type can be passed to an openarray parameter, the index type does not matter. +.. code-block:: nim + var + fruits: seq[string] # reference to a sequence of strings that is initialized with 'nil' + capitals: array[3, string] # array of strings with a fixed size + + fruits = @[] # creates an empty sequence on the heap that will be referenced by 'fruits' + + capitals = ["New York", "London", "Berlin"] # array 'capitals' allows only assignment of three elements + fruits.add("Banana") # sequence 'fruits' is dynamically expandable during runtime + fruits.add("Mango") + + proc openArraySize(oa: openArray[string]): int = + oa.len + + assert openArraySize(fruits) == 2 # procedure accepts a sequence as parameter + assert openArraySize(capitals) == 3 # but also an array type + The openarray type cannot be nested: multidimensional openarrays are not supported because this is seldom needed and cannot be done efficiently. @@ -1303,7 +1330,7 @@ type conversions in this context: myWriteln(stdout, 123, "abc", 4.0) # is transformed by the compiler to: - myWriteln(stdout, [$123, $"def", $4.0]) + myWriteln(stdout, [$123, $"abc", $4.0]) In this example `$ <system.html#$>`_ is applied to any argument that is passed to the parameter ``a``. Note that `$ <system.html#$>`_ applied to strings is a @@ -1325,11 +1352,11 @@ define operators which accept Slice objects to define ranges. b = "Slices are useless." echo a[7..12] # --> 'a prog' - b[11.. -2] = "useful" + b[11..^2] = "useful" echo b # --> 'Slices are useful.' -In the previous example slices are used to modify a part of a string, and even -a negative index is used. The slice's bounds can hold any value supported by +In the previous example slices are used to modify a part of a string. The +slice's bounds can hold any value supported by their type, but it is the proc using the slice object which defines what values are accepted. @@ -1370,12 +1397,12 @@ integer. var building: tuple[street: string, number: int] building = ("Rue del Percebe", 13) echo(building.street) - + # The following line does not compile, they are different tuples! #person = building # --> Error: type mismatch: got (tuple[street: string, number: int]) # but expected 'Person' - + # The following works because the field names and types are the same. var teacher: tuple[name: string, age: int] = ("Mark", 42) person = teacher @@ -1450,13 +1477,13 @@ operators perform implicit dereferencing operations for reference types: type Node = ref NodeObj - NodeObj = object - le, ri: PNode + NodeObj = object + le, ri: Node data: int var n: Node new(n) - n.data = 9 + n.data = 9 # no need to write n[].data; in fact n[].data is highly discouraged! To allocate a new traced object, the built-in procedure ``new`` has to be used. @@ -1559,9 +1586,9 @@ This is best illustrated by an example: A symbol of a module *can* be *qualified* with the ``module.symbol`` syntax. If -the symbol is ambiguous, it even *has* to be qualified. A symbol is ambiguous -if it is defined in two (or more) different modules and both modules are -imported by a third one: +the symbol is ambiguous, it even *has* to be qualified. A symbol is ambiguous +if it is defined in two (or more) different modules and both modules are +imported by a third one: .. code-block:: nim # Module A diff --git a/doc/tut2.txt b/doc/tut2.txt index e1ac20074..83ea9ad33 100644 --- a/doc/tut2.txt +++ b/doc/tut2.txt @@ -207,7 +207,7 @@ for any type: echo("abc".len) # is the same as echo(len("abc")) echo("abc".toUpper()) echo({'a', 'b', 'c'}.card) - stdout.writeln("Hallo") # the same as writeln(stdout, "Hallo") + stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo") (Another way to look at the method call syntax is that it provides the missing postfix notation.) @@ -217,9 +217,9 @@ So "pure object oriented" code is easy to write: .. code-block:: nim import strutils - stdout.writeln("Give a list of numbers (separated by spaces): ") + stdout.writeLine("Give a list of numbers (separated by spaces): ") stdout.write(stdin.readLine.split.map(parseInt).max.`$`) - stdout.writeln(" is the maximum!") + stdout.writeLine(" is the maximum!") Properties @@ -233,17 +233,15 @@ is needed: type Socket* = ref object of RootObj - FHost: int # cannot be accessed from the outside of the module - # the `F` prefix is a convention to avoid clashes since - # the accessors are named `host` + host: int # cannot be accessed from the outside of the module due to missing star proc `host=`*(s: var Socket, value: int) {.inline.} = - ## setter of hostAddr - s.FHost = value + ## setter of host address + s.host = value proc host*(s: Socket): int {.inline.} = - ## getter of hostAddr - s.FHost + ## getter of host address + s.host var s: Socket new s @@ -537,7 +535,7 @@ containers: add(root, newNode("hello")) # instantiates ``newNode`` and ``add`` add(root, "world") # instantiates the second ``add`` proc for str in preorder(root): - stdout.writeln(str) + stdout.writeLine(str) The example shows a generic binary tree. Depending on context, the brackets are used either to introduce type parameters or to instantiate a generic proc, @@ -582,7 +580,7 @@ simple proc for logging: debug = true proc log(msg: string) {.inline.} = - if debug: stdout.writeln(msg) + if debug: stdout.writeLine(msg) var x = 4 @@ -599,7 +597,7 @@ Turning the ``log`` proc into a template solves this problem: debug = true template log(msg: string) = - if debug: stdout.writeln(msg) + if debug: stdout.writeLine(msg) var x = 4 @@ -629,10 +627,10 @@ via a special ``:`` syntax: quit("cannot open: " & fn) withFile(txt, "ttempl3.txt", fmWrite): - txt.writeln("line 1") - txt.writeln("line 2") + txt.writeLine("line 1") + txt.writeLine("line 2") -In the example the two ``writeln`` statements are bound to the ``body`` +In the example the two ``writeLine`` statements are bound to the ``body`` parameter. The ``withFile`` template contains boilerplate code and helps to avoid a common bug: to forget to close the file. Note how the ``let fn = filename`` statement ensures that ``filename`` is evaluated only @@ -686,7 +684,7 @@ variable number of arguments: # add a call to the statement list that writes ": " result.add(newCall("write", newIdentNode("stdout"), newStrLitNode(": "))) # add a call to the statement list that writes the expressions value: - result.add(newCall("writeln", newIdentNode("stdout"), n[i])) + result.add(newCall("writeLine", newIdentNode("stdout"), n[i])) var a: array[0..10, int] @@ -701,15 +699,15 @@ The macro call expands to: .. code-block:: nim write(stdout, "a[0]") write(stdout, ": ") - writeln(stdout, a[0]) + writeLine(stdout, a[0]) write(stdout, "a[1]") write(stdout, ": ") - writeln(stdout, a[1]) + writeLine(stdout, a[1]) write(stdout, "x") write(stdout, ": ") - writeln(stdout, x) + writeLine(stdout, x) |