diff options
Diffstat (limited to 'doc/manual.txt')
-rw-r--r-- | doc/manual.txt | 287 |
1 files changed, 225 insertions, 62 deletions
diff --git a/doc/manual.txt b/doc/manual.txt index fb357f7d3..6526ba2cb 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -79,8 +79,21 @@ 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*. However, the implementation provides a means to disable these -runtime checks. See the section pragmas_ for details. +exceptions* or *dying with a fatal error*. However, the implementation +provides a means to disable these runtime checks. See the section pragmas_ +for details. + +Wether 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: + +.. code-block:: nimrod + var a: array[0..1, char] + let i = 5 + try: + a[i] = 'N' + except EInvalidIndex: + echo "invalid index" An `unchecked runtime error`:idx: is an error that is not guaranteed to be detected, and can cause the subsequent behavior of the computation to @@ -480,24 +493,27 @@ precedence and associativity; this is useful for meta programming. Associativity ------------- -All binary operators are left-associative, except binary operators whose -relevant char is ``^``. +Binary operators whose relevant character is ``^`` are right-associative, all +other binary operators are left-associative. Precedence ---------- -For operators that are not keywords the precedence is determined by the -following rules: +Unary operators always bind stronger than any binary +operator: ``$a + b`` is ``($a) + b`` and not ``$(a + b)``. -If the operator ends with ``=`` and its relevant character is none of -``<``, ``>``, ``!``, ``=``, ``~``, ``?``, it is an *assignment operator* which -has the lowest precedence. - -If the operator's relevant character is ``@`` it is a `sigil-like`:idx: +If an unary operator's relevant 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)``. +For binary operators that are not keywords the precedence is determined by the +following rules: + +If the operator ends with ``=`` and its relevant character is none of +``<``, ``>``, ``!``, ``=``, ``~``, ``?``, it is an *assignment operator* which +has the lowest precedence. + Otherwise precedence is determined by the relevant character. ================ =============================================== ================== =============== @@ -508,7 +524,7 @@ Precedence level Operators Relevant char 7 ``+ -`` ``+ ~ |`` OP7 6 ``&`` ``&`` OP6 5 ``..`` ``.`` OP5 - 4 ``== <= < >= > != in not_in is isnot not of`` ``= < > !`` OP4 + 4 ``== <= < >= > != in notin is isnot not of`` ``= < > !`` OP4 3 ``and`` OP3 2 ``or xor`` OP2 1 ``@ : ?`` OP1 @@ -516,6 +532,51 @@ Precedence level Operators Relevant char ================ =============================================== ================== =============== +Strong spaces +------------- + +The number of spaces preceeding a non-keyword operator affects precedence +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:: nimrod + #! strongSpaces + if foo+4 * 4 == 8 and b&c | 9 ++ + bar: + echo "" + # is parsed as + if ((foo+4)*4 == 8) and (((b&c) | 9) ++ bar): echo "" + + +Furthermore whether an operator is used a prefix operator is affected by the +number of spaces: + +.. code-block:: nimrod + #! strongSpaces + echo $foo + # is parsed as + echo($foo) + +This also affects whether ``[]``, ``{}``, ``()`` are parsed as constructors +or as accessors: + +.. code-block:: nimrod + #! strongSpaces + echo (1,2) + # is parsed as + echo((1,2)) + +Only 0, 1, 2, 4 or 8 spaces are allowed to specify precedence and it is +enforced that infix operators have the same amount of spaces before and after +them. This rules does not apply when a newline follows after the operator, +then only the preceding spaces are considered. + + +Grammar +------- + The grammar's start symbol is ``module``. .. include:: grammar.txt @@ -1508,6 +1569,28 @@ currency. This can be solved with templates_. defineCurrency(TEuro, int) +The borrow pragma can also be used to annotate the distinct type to allow +certain builtin operations to be lifted: + +.. code-block:: nimrod + type + Foo = object + a, b: int + s: string + + Bar {.borrow: `.`.} = distinct Foo + + var bb: ref Bar + new bb + # field access now valid + bb.a = 90 + bb.s = "abc" + +Currently only the dot accessor can be borrowed in this way. + + + + Void type --------- @@ -2822,7 +2905,6 @@ 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 for loop context is supported. - Implict items/pairs invocations ------------------------------- @@ -2847,10 +2929,11 @@ First class iterators There are 2 kinds of iterators in Nimrod: *inline* and *closure* iterators. 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; one cannot pass them around like first class procs. +increase in code size. Inline iterators are second class citizens; +They can be passed as parameters only to other inlining code facilities like +templates, macros and other inline iterators. -In contrast to that, a `closure iterator`:idx: can be passed around: +In contrast to that, a `closure iterator`:idx: can be passed around more freely: .. code-block:: nimrod iterator count0(): int {.closure.} = @@ -2873,9 +2956,7 @@ Closure iterators have other restrictions than inline iterators: 1. ``yield`` in a closure iterator can not occur in a ``try`` statement. 2. For now, a closure iterator cannot be evaluated at compile time. 3. ``return`` is allowed in a closure iterator (but rarely useful). -4. Since closure iterators can be used as a collaborative tasking - system, ``void`` is a valid return type for them. -5. Both inline and closure iterators cannot be recursive. +4. Both inline and closure iterators cannot be recursive. Iterators that are neither marked ``{.closure.}`` nor ``{.inline.}`` explicitly default to being inline, but that this may change in future versions of the @@ -2937,6 +3018,14 @@ parameters of an outer factory proc: for f in foo(): echo f +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 +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. + Type sections ============= @@ -4016,8 +4105,8 @@ Static params can also appear in the signatures of generic types: AffineTransform2D[T] = Matrix[3, 3, T] AffineTransform3D[T] = Matrix[4, 4, T] - AffineTransform3D[float] # OK - AffineTransform2D[string] # Error, `string` is not a `Number` + var m1: AffineTransform3D[float] # OK + var m2: AffineTransform2D[string] # Error, `string` is not a `Number` typedesc @@ -4106,6 +4195,59 @@ types that will match the typedesc param: The constraint can be a concrete type or a type class. +Special Operators +================= + +dot operators +------------- + +Nimrod offers a special family of dot operators that can be used to +intercept and rewrite proc call and field access attempts, referring +to previously undeclared symbol names. They can be used to provide a +fluent interface to objects lying outside the static confines of the +Nimrod's type system such as values from dynamic scripting languages +or dynamic file formats such as JSON or XML. + +When Nimrod encounters an expression that cannot be resolved by the +standard overload resolution rules, the current scope will be searched +for a dot operator that can be matched against a re-written form of +the expression, where the unknown field or proc name is converted to +an additional static string parameter: + +.. code-block:: nimrod + a.b # becomes `.`(a, "b") + a.b(c, d) # becomes `.`(a, "b", c, d) + +The matched dot operators can be symbols of any callable kind (procs, +templates and macros), depending on the desired effect: + +.. code-block:: nimrod + proc `.` (js: PJsonNode, field: string): JSON = js[field] + + var js = parseJson("{ x: 1, y: 2}") + echo js.x # outputs 1 + echo js.y # outputs 2 + +The following dot operators are available: + +operator `.` +------------ +This operator will be matched against both field accesses and method calls. + +operator `.()` +--------------- +This operator will be matched exclusively against method calls. It has higher +precedence than the `.` operator and this allows you to handle expressions like +`x.y` and `x.y()` differently if you are interfacing with a scripting language +for example. + +operator `.=` +------------- +This operator will be matched against assignments to missing fields. + +.. code-block:: nimrod + a.b = c # becomes `.=`(a, "b", c) + Term rewriting macros ===================== @@ -4758,42 +4900,6 @@ This may change in future versions of language, but for now use the ``finalizer`` parameter to ``new``. -delegator pragma ----------------- - -**Note**: The design of the delegator feature is subject to change. - -The delegator pragma can be used to intercept and rewrite proc call and field -access attempts referring to previously undeclared symbol names. It can be used -to provide a fluent interface to objects lying outside the static confines of -the Nimrod's type system such as values from dynamic scripting languages or -dynamic file formats such as JSON or XML. - -A delegator is a special form of the `()` operator marked with the delagator -pragma. When Nimrod encounters an expression that cannot be resolved by the -standard overload resolution, any delegators in the current scope will be -matched against a rewritten form of the expression following the standard -signature matching rules. In the rewritten expression, the name of the unknown -proc or field name is inserted as an additional static string parameter always -appearing in the leading position: - -.. code-block:: nimrod - a.b => delegator("b", a) - a.b(c, d) => delegator("b", a, c) - a b, c, d => delegator("a", b, c, d) - - -The delegators can be any callable symbol type (procs, templates, macros) -depending on the desired effect: - -.. code-block:: nimrod - proc `()` (field: string, js: PJsonNode): JSON {.delegator.} = js[field] - - var js = parseJson("{ x: 1, y: 2}") - echo js.x # outputs 1 - echo js.y # outputs 2 - - procvar pragma -------------- The `procvar`:idx: pragma is used to mark a proc that it can be passed to a @@ -4876,16 +4982,16 @@ field which is used for runtime type identification is omitted. This is necessary for binary compatibility with other compiled languages. -NoStackFrame pragma -------------------- -A proc can be marked with the `noStackFrame`:idx: pragma to tell the compiler +AsmNoStackFrame pragma +---------------------- +A proc can be marked with the `AsmNoStackFrame`:idx: pragma to tell the compiler it should not generate a stack frame for the proc. There are also no exit statements like ``return result;`` generated and the generated C function is declared as ``__declspec(naked)`` or ``__attribute__((naked))`` (depending on the used C compiler). -**Note**: This pragma should only be used by procs which consist solely of assembler -statements. +**Note**: This pragma should only be used by procs which consist solely of +assembler statements. error pragma ------------ @@ -5303,6 +5409,63 @@ strings automatically: printf("hallo %s", "world") # "world" will be passed as C string +Union pragma +------------ +The `union`:idx: pragma can be applied to any ``object`` type. It means all +of the object's fields are overlaid in memory. This produces a ``union`` +instead of a ``struct`` in the generated C/C++ code. The object declaration +then must not use inheritance or any GC'ed memory but this is currently not +checked. + +**Future directions**: GC'ed memory should be allowed in unions and the GC +should scan unions conservatively. + +Packed pragma +------------- +The `packed`:idx: 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 +compile-time error. Usage with inheritance should be defined and documented. + +Unchecked pragma +---------------- +The `unchecked`:idx: 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 +translated into a C array of undetermined size: + +.. code-block:: nimrod + type + ArrayPart{.unchecked.} = array[0..0, int] + MySeq = object + len, cap: int + data: ArrayPart + +Produces roughly this C code: + +.. code-block:: C + typedef struct { + NI len; + NI cap; + NI data[]; + } MySeq; + +The bounds checking done at compile time is not disabled for now, so to access +``s.data[C]`` (where ``C`` is a constant) the array's index needs needs to +include ``C``. + +The base type of the unchecked array may not contain any GC'ed memory but this +is currently not checked. + +**Future directions**: GC'ed memory should be allowed in unchecked arrays and +there should be an explicit annotation of how the GC is to determine the +runtime size of the array. + + Dynlib pragma for import ------------------------ With the `dynlib`:idx: pragma a procedure or a variable can be imported from |