overload resolution for proc vars
This commit is contained in:
parent
36818817bd
commit
300430fbba
56 changed files with 2772 additions and 2430 deletions
|
|
@ -29,8 +29,8 @@ addrExpr ::= 'addr' '(' optInd expr ')'
|
|||
symbol ::= '`' (KEYWORD | IDENT | operator | '(' ')'
|
||||
| '[' ']' | '=' | literal)+ '`'
|
||||
| IDENT
|
||||
primary ::= (prefixOperator optInd)* (symbol | constructor |
|
||||
castExpr | addrExpr) (
|
||||
primary ::= ((prefixOperator | 'bind') optInd)* (symbol | constructor |
|
||||
castExpr | addrExpr) (
|
||||
'.' optInd symbol
|
||||
| '(' optInd namedExprList [SAD] ')'
|
||||
| '[' optInd
|
||||
|
|
@ -42,7 +42,7 @@ primary ::= (prefixOperator optInd)* (symbol | constructor |
|
|||
literal ::= INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
|
||||
| FLOAT_LIT | FLOAT32_LIT | FLOAT64_LIT
|
||||
| STR_LIT | RSTR_LIT | TRIPLESTR_LIT
|
||||
| CHAR_LIT | RCHAR_LIT
|
||||
| CHAR_LIT
|
||||
| NIL
|
||||
|
||||
constructor ::= literal
|
||||
|
|
|
|||
|
|
@ -336,7 +336,7 @@ Precedence level Operators First characte
|
|||
|
||||
|
||||
The grammar's start symbol is ``module``. The grammar is LL(1) and therefore
|
||||
not ambigious.
|
||||
not ambiguous.
|
||||
|
||||
.. include:: grammar.txt
|
||||
:literal:
|
||||
|
|
@ -920,6 +920,95 @@ each other:
|
|||
Most calling conventions exist only for the Windows 32-bit platform.
|
||||
|
||||
|
||||
Type relations
|
||||
--------------
|
||||
|
||||
The following section defines several relations on types that are needed to
|
||||
describe the type checking done by the compiler.
|
||||
|
||||
|
||||
Type equality
|
||||
~~~~~~~~~~~~~
|
||||
Nimrod uses structural type equivalence for most types. Only for objects,
|
||||
enumerations and abstract types name equivalence is used. The following
|
||||
algorithm determines type equality:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc typeEqualsAux(a, b: PType,
|
||||
s: var set[tuple[PType, PType]]): bool =
|
||||
if (a,b) in s: return true
|
||||
incl(s, (a,b))
|
||||
if a.kind == b.kind:
|
||||
case a.kind
|
||||
of int, intXX, float, floatXX, char, string, cstring, pointer, bool, nil:
|
||||
# leaf type: kinds identical; nothing more to check
|
||||
result = true
|
||||
of ref, ptr, var, set, seq, openarray:
|
||||
result = typeEqualsAux(a.baseType, b.baseType, s)
|
||||
of range:
|
||||
result = typeEqualsAux(a.baseType, b.baseType, s) and
|
||||
(a.rangeA == b.rangeA) and (a.rangeB == b.rangeB)
|
||||
of array:
|
||||
result = typeEqualsAux(a.baseType, b.baseType, s) and
|
||||
typeEqualsAux(a.indexType, b.indexType, s)
|
||||
of tuple:
|
||||
if a.tupleLen == b.tupleLen:
|
||||
for i in 0..a.tupleLen-1:
|
||||
if not typeEqualsAux(a[i], b[i], s): return false
|
||||
result = true
|
||||
of object, enum, abstract:
|
||||
result = a == b
|
||||
of proc:
|
||||
result = typeEqualsAux(a.parameterTuple, b.parameterTuple, s) and
|
||||
typeEqualsAux(a.resultType, b.resultType, s) and
|
||||
a.callingConvention == b.callingConvention
|
||||
|
||||
proc typeEquals(a, b: PType): bool =
|
||||
var s: set[tuple[PType, PType]] = {}
|
||||
result = typeEqualsAux(a, b, s)
|
||||
|
||||
Since types are graphs which can have cycles, the above algorithm needs an
|
||||
auxiliary set ``s`` to detect this case.
|
||||
|
||||
|
||||
Subtype relation
|
||||
~~~~~~~~~~~~~~~~
|
||||
If object ``b`` inherits from ``a``, ``b`` is a subtype of ``a``. This subtype
|
||||
relation is extended to the types ``var``, ``ref``, ``ptr``:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc isSubtype(a, b: PType): bool =
|
||||
if a.kind == b.kind:
|
||||
case a.kind
|
||||
of object:
|
||||
var aa = a.baseType
|
||||
while aa != nil and aa != b: aa = aa.baseType
|
||||
result = aa == b
|
||||
of var, ref, ptr:
|
||||
result = isSubtype(a.baseType, b.baseType)
|
||||
|
||||
XXX nil is a special value!
|
||||
|
||||
|
||||
Convertible relation
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
A type ``a`` is convertible to type ``b`` iff the following algorithm returns
|
||||
true:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc isConvertible(a, b: PType): bool =
|
||||
if a.kind == b.kind:
|
||||
case a.kind
|
||||
of proc:
|
||||
var x = a.parameterTuple
|
||||
var y = b.parameterTuple
|
||||
if x.tupleLen == y.tupleLen:
|
||||
for i in 0.. x.tupleLen-1:
|
||||
if not isSubtype(x[i], y[i]): return false
|
||||
result = isSubType(b.resultType, a.resultType)
|
||||
|
||||
|
||||
|
||||
|
||||
Statements and expressions
|
||||
--------------------------
|
||||
|
|
@ -927,8 +1016,7 @@ Nimrod uses the common statement/expression paradigm: `Statements`:idx: do not
|
|||
produce a value in contrast to expressions. Call expressions are statements.
|
||||
If the called procedure returns a value, it is not a valid statement
|
||||
as statements do not produce values. To evaluate an expression for
|
||||
side-effects and throwing its value away, one can use the ``discard``
|
||||
statement.
|
||||
side-effects and throw its value away, one can use the ``discard`` statement.
|
||||
|
||||
Statements are separated into `simple statements`:idx: and
|
||||
`complex statements`:idx:.
|
||||
|
|
@ -1917,11 +2005,11 @@ iterator in which case the overloading resolution takes place:
|
|||
|
||||
# Module C
|
||||
import A, B
|
||||
write(stdout, x) # error: x is ambigious
|
||||
write(stdout, x) # error: x is ambiguous
|
||||
write(stdout, A.x) # no error: qualifier used
|
||||
|
||||
var x = 4
|
||||
write(stdout, x) # not ambigious: uses the module C's x
|
||||
write(stdout, x) # not ambiguous: uses the module C's x
|
||||
|
||||
|
||||
Messages
|
||||
|
|
|
|||
|
|
@ -154,6 +154,9 @@ Index
|
|||
* `system.html#313 <system.html#313>`_
|
||||
* `system.html#314 <system.html#314>`_
|
||||
|
||||
`<=`:idx:
|
||||
`times.html#115 <times.html#115>`_
|
||||
|
||||
`<=`:idx:
|
||||
* `system.html#253 <system.html#253>`_
|
||||
* `system.html#254 <system.html#254>`_
|
||||
|
|
@ -169,9 +172,6 @@ Index
|
|||
* `system.html#345 <system.html#345>`_
|
||||
* `system.html#346 <system.html#346>`_
|
||||
|
||||
`<=`:idx:
|
||||
`times.html#115 <times.html#115>`_
|
||||
|
||||
`<=%`:idx:
|
||||
* `system.html#305 <system.html#305>`_
|
||||
* `system.html#306 <system.html#306>`_
|
||||
|
|
@ -201,7 +201,7 @@ Index
|
|||
* `macros.html#117 <macros.html#117>`_
|
||||
|
||||
`=~`:idx:
|
||||
`regexprs.html#111 <regexprs.html#111>`_
|
||||
`regexprs.html#108 <regexprs.html#108>`_
|
||||
|
||||
`>`:idx:
|
||||
`system.html#357 <system.html#357>`_
|
||||
|
|
@ -218,18 +218,18 @@ Index
|
|||
`@`:idx:
|
||||
`system.html#365 <system.html#365>`_
|
||||
|
||||
`[]`:idx:
|
||||
`strtabs.html#107 <strtabs.html#107>`_
|
||||
|
||||
`[]`:idx:
|
||||
`macros.html#113 <macros.html#113>`_
|
||||
|
||||
`[]=`:idx:
|
||||
`macros.html#114 <macros.html#114>`_
|
||||
`[]`:idx:
|
||||
`strtabs.html#107 <strtabs.html#107>`_
|
||||
|
||||
`[]=`:idx:
|
||||
`strtabs.html#106 <strtabs.html#106>`_
|
||||
|
||||
`[]=`:idx:
|
||||
`macros.html#114 <macros.html#114>`_
|
||||
|
||||
`[ESC]`:idx:
|
||||
`manual.html#134 <manual.html#134>`_
|
||||
|
||||
|
|
@ -366,8 +366,7 @@ Index
|
|||
`xmlgen.html#111 <xmlgen.html#111>`_
|
||||
|
||||
`backslash`:idx:
|
||||
* `manual.html#127 <manual.html#127>`_
|
||||
* `regexprs.html#101 <regexprs.html#101>`_
|
||||
`manual.html#127 <manual.html#127>`_
|
||||
|
||||
`backspace`:idx:
|
||||
`manual.html#132 <manual.html#132>`_
|
||||
|
|
@ -1228,7 +1227,7 @@ Index
|
|||
`system.html#156 <system.html#156>`_
|
||||
|
||||
`EInvalidRegEx`:idx:
|
||||
`regexprs.html#104 <regexprs.html#104>`_
|
||||
`regexprs.html#101 <regexprs.html#101>`_
|
||||
|
||||
`EInvalidValue`:idx:
|
||||
`system.html#148 <system.html#148>`_
|
||||
|
|
@ -1265,12 +1264,12 @@ Index
|
|||
`enum_cursor_type`:idx:
|
||||
`mysql.html#237 <mysql.html#237>`_
|
||||
|
||||
`Enumeration`:idx:
|
||||
`manual.html#148 <manual.html#148>`_
|
||||
|
||||
`enumeration`:idx:
|
||||
`tut1.html#113 <tut1.html#113>`_
|
||||
|
||||
`Enumeration`:idx:
|
||||
`manual.html#148 <manual.html#148>`_
|
||||
|
||||
`enum_field_types`:idx:
|
||||
`mysql.html#202 <mysql.html#202>`_
|
||||
|
||||
|
|
@ -1546,8 +1545,8 @@ Index
|
|||
* `strutils.html#124 <strutils.html#124>`_
|
||||
* `strutils.html#125 <strutils.html#125>`_
|
||||
* `strutils.html#126 <strutils.html#126>`_
|
||||
* `regexprs.html#109 <regexprs.html#109>`_
|
||||
* `regexprs.html#110 <regexprs.html#110>`_
|
||||
* `regexprs.html#106 <regexprs.html#106>`_
|
||||
* `regexprs.html#107 <regexprs.html#107>`_
|
||||
|
||||
`findChars`:idx:
|
||||
`strutils.html#123 <strutils.html#123>`_
|
||||
|
|
@ -1631,9 +1630,6 @@ Index
|
|||
* `system.html#478 <system.html#478>`_
|
||||
* `system.html#479 <system.html#479>`_
|
||||
|
||||
`generic character types`:idx:
|
||||
`regexprs.html#102 <regexprs.html#102>`_
|
||||
|
||||
`Generics`:idx:
|
||||
* `manual.html#207 <manual.html#207>`_
|
||||
* `tut2.html#108 <tut2.html#108>`_
|
||||
|
|
@ -2258,11 +2254,11 @@ Index
|
|||
`xmlgen.html#150 <xmlgen.html#150>`_
|
||||
|
||||
`match`:idx:
|
||||
* `regexprs.html#106 <regexprs.html#106>`_
|
||||
* `regexprs.html#107 <regexprs.html#107>`_
|
||||
* `regexprs.html#103 <regexprs.html#103>`_
|
||||
* `regexprs.html#104 <regexprs.html#104>`_
|
||||
|
||||
`matchLen`:idx:
|
||||
`regexprs.html#108 <regexprs.html#108>`_
|
||||
`regexprs.html#105 <regexprs.html#105>`_
|
||||
|
||||
`math`:idx:
|
||||
`nimrodc.html#118 <nimrodc.html#118>`_
|
||||
|
|
@ -2301,7 +2297,7 @@ Index
|
|||
`mysql.html#191 <mysql.html#191>`_
|
||||
|
||||
`MaxSubpatterns`:idx:
|
||||
`regexprs.html#105 <regexprs.html#105>`_
|
||||
`regexprs.html#102 <regexprs.html#102>`_
|
||||
|
||||
`MAX_TINYINT_WIDTH`:idx:
|
||||
`mysql.html#190 <mysql.html#190>`_
|
||||
|
|
@ -3095,12 +3091,12 @@ Index
|
|||
`ord`:idx:
|
||||
`system.html#172 <system.html#172>`_
|
||||
|
||||
`ordinal`:idx:
|
||||
`tut1.html#114 <tut1.html#114>`_
|
||||
|
||||
`Ordinal`:idx:
|
||||
`system.html#114 <system.html#114>`_
|
||||
|
||||
`ordinal`:idx:
|
||||
`tut1.html#114 <tut1.html#114>`_
|
||||
|
||||
`Ordinal types`:idx:
|
||||
`manual.html#141 <manual.html#141>`_
|
||||
|
||||
|
|
@ -3623,16 +3619,16 @@ Index
|
|||
`system.html#419 <system.html#419>`_
|
||||
|
||||
`reBinary`:idx:
|
||||
`regexprs.html#116 <regexprs.html#116>`_
|
||||
`regexprs.html#113 <regexprs.html#113>`_
|
||||
|
||||
`Recursive module dependancies`:idx:
|
||||
`manual.html#216 <manual.html#216>`_
|
||||
|
||||
`reEmail`:idx:
|
||||
`regexprs.html#119 <regexprs.html#119>`_
|
||||
`regexprs.html#116 <regexprs.html#116>`_
|
||||
|
||||
`reFloat`:idx:
|
||||
`regexprs.html#118 <regexprs.html#118>`_
|
||||
`regexprs.html#115 <regexprs.html#115>`_
|
||||
|
||||
`REFRESH_DES_KEY_FILE`:idx:
|
||||
`mysql.html#154 <mysql.html#154>`_
|
||||
|
|
@ -3680,13 +3676,13 @@ Index
|
|||
`nimrodc.html#112 <nimrodc.html#112>`_
|
||||
|
||||
`reHex`:idx:
|
||||
`regexprs.html#115 <regexprs.html#115>`_
|
||||
|
||||
`reIdentifier`:idx:
|
||||
`regexprs.html#112 <regexprs.html#112>`_
|
||||
|
||||
`reIdentifier`:idx:
|
||||
`regexprs.html#109 <regexprs.html#109>`_
|
||||
|
||||
`reInteger`:idx:
|
||||
`regexprs.html#114 <regexprs.html#114>`_
|
||||
`regexprs.html#111 <regexprs.html#111>`_
|
||||
|
||||
`removeDir`:idx:
|
||||
`os.html#150 <os.html#150>`_
|
||||
|
|
@ -3695,10 +3691,10 @@ Index
|
|||
`os.html#141 <os.html#141>`_
|
||||
|
||||
`reNatural`:idx:
|
||||
`regexprs.html#113 <regexprs.html#113>`_
|
||||
`regexprs.html#110 <regexprs.html#110>`_
|
||||
|
||||
`reOctal`:idx:
|
||||
`regexprs.html#117 <regexprs.html#117>`_
|
||||
`regexprs.html#114 <regexprs.html#114>`_
|
||||
|
||||
`repeatChar`:idx:
|
||||
`strutils.html#148 <strutils.html#148>`_
|
||||
|
|
@ -3724,7 +3720,7 @@ Index
|
|||
`manual.html#189 <manual.html#189>`_
|
||||
|
||||
`reURL`:idx:
|
||||
`regexprs.html#120 <regexprs.html#120>`_
|
||||
`regexprs.html#117 <regexprs.html#117>`_
|
||||
|
||||
`round`:idx:
|
||||
`math.html#121 <math.html#121>`_
|
||||
|
|
@ -3889,9 +3885,6 @@ Index
|
|||
* `system.html#226 <system.html#226>`_
|
||||
* `system.html#227 <system.html#227>`_
|
||||
|
||||
`simple assertions`:idx:
|
||||
`regexprs.html#103 <regexprs.html#103>`_
|
||||
|
||||
`simple statements`:idx:
|
||||
`manual.html#174 <manual.html#174>`_
|
||||
|
||||
|
|
@ -5154,6 +5147,9 @@ Index
|
|||
* `manual.html#156 <manual.html#156>`_
|
||||
* `tut2.html#103 <tut2.html#103>`_
|
||||
|
||||
`verbose`:idx:
|
||||
`regexprs.html#118 <regexprs.html#118>`_
|
||||
|
||||
`vertical tabulator`:idx:
|
||||
`manual.html#126 <manual.html#126>`_
|
||||
|
||||
|
|
|
|||
17
doc/tut1.txt
17
doc/tut1.txt
|
|
@ -264,7 +264,7 @@ For integers or other ordinal types value ranges are also possible:
|
|||
However, the above code does not compile: The reason is that you have to cover
|
||||
every value that ``n`` may contain, but the code only handles the values
|
||||
``0..8``. Since it is not very practical to list every other possible integer
|
||||
(though it is possible thanks to the range notation!), we fix this by telling
|
||||
(though it is possible thanks to the range notation), we fix this by telling
|
||||
the compiler that for every other value nothing should be done:
|
||||
|
||||
.. code-block:: nimrod
|
||||
|
|
@ -624,7 +624,8 @@ Nimrod provides the ability to overload procedures similar to C++:
|
|||
.. code-block:: nimrod
|
||||
proc toString(x: int): string = ...
|
||||
proc toString(x: bool): string =
|
||||
if x: return "true" else: return "false"
|
||||
if x: return "true"
|
||||
else: return "false"
|
||||
|
||||
Echo(toString(13)) # calls the toString(x: int) proc
|
||||
Echo(toString(true)) # calls the toString(x: bool) proc
|
||||
|
|
@ -634,7 +635,7 @@ The compiler chooses the most appropriate proc for the ``toString`` calls. How
|
|||
this overloading resolution algorithm works exactly is not discussed here
|
||||
(it will be specified in the manual soon).
|
||||
However, it does not lead to nasty suprises and is based on a quite simple
|
||||
unification algorithm. Ambigious calls are reported as errors.
|
||||
unification algorithm. Ambiguous calls are reported as errors.
|
||||
|
||||
|
||||
Operators
|
||||
|
|
@ -643,7 +644,7 @@ The Nimrod library makes heavy use of overloading - one reason for this is that
|
|||
each operator like ``+`` is a just an overloaded proc. The parser lets you
|
||||
use operators in `infix notation` (``a + b``) or `prefix notation` (``+ a``).
|
||||
An infix operator always receives two arguments, a prefix operator always one.
|
||||
Postfix operators are not possible, because this would be ambigious: Does
|
||||
Postfix operators are not possible, because this would be ambiguous: Does
|
||||
``a @ @ b`` mean ``(a) @ (@b)`` or ``(a@) @ (b)``? It always means
|
||||
``(a) @ (@b)``, because there are no postfix operators in Nimrod.
|
||||
|
||||
|
|
@ -1331,7 +1332,7 @@ This is best illustrated by an example:
|
|||
|
||||
|
||||
A symbol of a module *can* be *qualified* with the ``module.symbol`` syntax. If
|
||||
the symbol is ambigious, it even *has* to be qualified. A symbol is ambigious
|
||||
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:
|
||||
|
||||
|
|
@ -1344,11 +1345,11 @@ imported by a third one:
|
|||
|
||||
# Module C
|
||||
import A, B
|
||||
write(stdout, x) # error: x is ambigious
|
||||
write(stdout, x) # error: x is ambiguous
|
||||
write(stdout, A.x) # no error: qualifier used
|
||||
|
||||
var x = 4
|
||||
write(stdout, x) # not ambigious: uses the module C's x
|
||||
write(stdout, x) # not ambiguous: uses the module C's x
|
||||
|
||||
|
||||
But this rule does not apply to procedures or iterators. Here the overloading
|
||||
|
|
@ -1367,7 +1368,7 @@ rules apply:
|
|||
write(stdout, x("")) # no error: B.x is called
|
||||
|
||||
proc x*(a: int): string = nil
|
||||
write(stdout, x(3)) # ambigious: which `x` is to call?
|
||||
write(stdout, x(3)) # ambiguous: which `x` is to call?
|
||||
|
||||
|
||||
From statement
|
||||
|
|
|
|||
13
doc/tut2.txt
13
doc/tut2.txt
|
|
@ -34,7 +34,7 @@ While Nimrod's support for object oriented programming (OOP) is minimalistic,
|
|||
powerful OOP technics can be used. OOP is seen as *one* way to design a
|
||||
program, not *the only* way. Often a procedural approach leads to simpler
|
||||
and more efficient code. In particular, prefering aggregation over inheritance
|
||||
often results in a better design.
|
||||
is often the better design.
|
||||
|
||||
|
||||
Objects
|
||||
|
|
@ -446,8 +446,7 @@ containers:
|
|||
# this uses an explicit stack (which is more efficient anyway):
|
||||
var stack: seq[PBinaryTree[T]] = @[root]
|
||||
while stack.len > 0:
|
||||
var n = stack[stack.len-1]
|
||||
setLen(stack, stack.len-1) # pop `n` of the stack
|
||||
var n = stack.pop()
|
||||
while n != nil:
|
||||
yield n
|
||||
add(stack, n.ri) # push right subtree onto the stack
|
||||
|
|
@ -562,11 +561,11 @@ via a special ``:`` syntax:
|
|||
block:
|
||||
var fn = filename
|
||||
var f: TFile
|
||||
if openFile(f, fn, mode):
|
||||
if open(f, fn, mode):
|
||||
try:
|
||||
actions
|
||||
finally:
|
||||
closeFile(f)
|
||||
close(f)
|
||||
else:
|
||||
quit("cannot open: " & fn)
|
||||
|
||||
|
|
@ -593,9 +592,7 @@ Macros enable advanced compile-time code tranformations, but they
|
|||
cannot change Nimrod's syntax. However, this is no real restriction because
|
||||
Nimrod's syntax is flexible enough anyway.
|
||||
|
||||
`Macros`:idx: can be used to implement `domain specific languages`:idx:.
|
||||
|
||||
To write macros, one needs to know how the Nimrod concrete syntax is converted
|
||||
To write a macro, one needs to know how the Nimrod concrete syntax is converted
|
||||
to an abstract syntax tree (AST). The AST is documented in the
|
||||
`macros <macros.html>`_ module.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue