overload resolution for proc vars

This commit is contained in:
Andreas Rumpf 2009-06-24 17:13:22 +02:00
commit 300430fbba
56 changed files with 2772 additions and 2430 deletions

View file

@ -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

View file

@ -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

View file

@ -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>`_

View file

@ -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

View file

@ -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.