diff options
author | Araq <rumpf_a@web.de> | 2011-09-27 00:27:51 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-09-27 00:27:51 +0200 |
commit | da6046dcba20cb4aaff1e5712ac7a33a3c4e8445 (patch) | |
tree | 5be930165364b1d436828b19bb36fe18d37c7589 | |
parent | 7c34357856f0922fb265d81f1d215008b2dd8c14 (diff) | |
download | Nim-da6046dcba20cb4aaff1e5712ac7a33a3c4e8445.tar.gz |
bugfix: overloading resolution for typeof
-rwxr-xr-x | compiler/sem.nim | 2 | ||||
-rwxr-xr-x | compiler/semcall.nim | 4 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 14 | ||||
-rwxr-xr-x | compiler/semtypes.nim | 14 | ||||
-rwxr-xr-x | compiler/sigmatch.nim | 2 | ||||
-rwxr-xr-x | doc/manual.txt | 136 | ||||
-rwxr-xr-x | tests/accept/run/ttoseq.nim | 7 |
7 files changed, 98 insertions, 81 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim index c0ea23d2e..78a04f744 100755 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -35,7 +35,7 @@ proc semStmtScope(c: PContext, n: PNode): PNode type TExprFlag = enum - efAllowType, efLValue, efWantIterator + efAllowType, efLValue, efWantIterator, efInTypeof TExprFlags = set[TExprFlag] proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode diff --git a/compiler/semcall.nim b/compiler/semcall.nim index f20349c0f..822649d6c 100755 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -35,6 +35,8 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds, z.calleeSym = sym matches(c, n, z) if z.state == csMatch: + # little hack so that iterators are preferred over everything else: + if sym.kind == skIterator: inc(z.exactMatches, 200) case x.state of csEmpty, csNoMatch: x = z of csMatch: @@ -48,7 +50,7 @@ proc semDirectCallWithBinding(c: PContext, n, f: PNode, filter: TSymKinds, # do not generate an error yet; the semantic checking will check for # an overloaded () operator elif y.state == csMatch and cmpCandidates(x, y) == 0 and - not sameMethodDispatcher(x.calleeSym, y.calleeSym): + not sameMethodDispatcher(x.calleeSym, y.calleeSym): if x.state != csMatch: InternalError(n.info, "x.state is not csMatch") LocalError(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [ diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index b042a6436..e720cf055 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -445,13 +445,15 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) = n.sons[i] = analyseIfAddressTaken(c, n.sons[i]) proc semDirectCallAnalyseEffects(c: PContext, n: PNode, - flags: TExprFlags): PNode = - var symflags = {skProc, skMethod, skConverter} + flags: TExprFlags): PNode = if efWantIterator in flags: - # for ``type countup(1,3)``, see ``tests/ttoseq``. - symflags = {skIterator} - result = semDirectCall(c, n, symflags) - if result != nil: + result = semDirectCall(c, n, {skIterator}) + elif efInTypeOf in flags: + # for ``type(countup(1,3))``, see ``tests/ttoseq``. + result = semDirectCall(c, n, {skIterator, skProc, skMethod, skConverter}) + else: + result = semDirectCall(c, n, {skProc, skMethod, skConverter}) + if result != nil: if result.sons[0].kind != nkSym: InternalError("semDirectCallAnalyseEffects") var callee = result.sons[0].sym diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 9ff7ea27f..d7ca0d8ef 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -625,23 +625,15 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = if s.ast == nil: GlobalError(n.info, errCannotInstantiateX, s.name.s) result = instGenericContainer(c, n, result) -proc FixupRemainingGenericInvokations(c: PContext, n: PNode, - typ: PType): PType = - if typ.kind == tyGenericInvokation: - nil - else: - result = typ - proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = nil if gCmd == cmdIdeTools: suggestExpr(c, n) case n.kind of nkEmpty: nil - of nkTypeOfExpr: - # for ``type countup(1,3)``, see ``tests/ttoseq``. - # XXX We should find a better solution. + of nkTypeOfExpr: + # for ``type(countup(1,3))``, see ``tests/ttoseq``. checkSonsLen(n, 1) - result = semExprWithType(c, n.sons[0], {efWantIterator}).typ + result = semExprWithType(c, n.sons[0], {efInTypeof}).typ of nkPar: if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev) else: GlobalError(n.info, errTypeExpected) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 1e93385d9..543027b41 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -18,7 +18,7 @@ type TCandidateState* = enum csEmpty, csMatch, csNoMatch TCandidate* {.final.} = object - exactMatches: int + exactMatches*: int subtypeMatches: int intConvMatches: int # conversions to int are not as expensive convMatches: int diff --git a/doc/manual.txt b/doc/manual.txt index c088e7d83..77511d782 100755 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -435,7 +435,7 @@ have no side-effect can be used in constant expressions too: The rules for compile-time computability are: -1. Literals are compile-time computable. +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`_ @@ -1294,14 +1294,14 @@ algorithm (in pseudo-code) determines type equality: Since types are graphs which can have cycles, the above algorithm needs an auxiliary set ``s`` to detect this case. - - + + Type equality modulo type distinction ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The following algorithm (in pseudo-code) determines whether two types -are equal with no respect to ``distinct`` types. For brevity the cycle check -with an auxiliary set ``s`` is omitted: +The following algorithm (in pseudo-code) determines whether two types +are equal with no respect to ``distinct`` types. For brevity the cycle check +with an auxiliary set ``s`` is omitted: .. code-block:: nimrod proc typeEqualsOrDistinct(a, b: PType): bool = @@ -1324,15 +1324,15 @@ with an auxiliary set ``s`` is omitted: for i in 0..a.tupleLen-1: if not typeEqualsOrDistinct(a[i], b[i]): return false result = true - of distinct: - result = typeEqualsOrDistinct(a.baseType, b.baseType) + of distinct: + result = typeEqualsOrDistinct(a.baseType, b.baseType) of object, enum: result = a == b of proc: result = typeEqualsOrDistinct(a.parameterTuple, b.parameterTuple) and typeEqualsOrDistinct(a.resultType, b.resultType) and - a.callingConvention == b.callingConvention - elif a.kind == distinct: + a.callingConvention == b.callingConvention + elif a.kind == distinct: result = typeEqualsOrDistinct(a.baseType, b) elif b.kind == distinct: result = typeEqualsOrDistinct(a, b.baseType) @@ -1413,10 +1413,10 @@ The convertible relation can be relaxed by a user-defined type # you can use the explicit form too x = chr.toInt echo x # => 97 - -The type conversion ``T(a)`` is an L-value if ``a`` is an L-value and + +The type conversion ``T(a)`` is an L-value if ``a`` is an L-value and ``typeEqualsOrDistinct(T, type(a))`` holds. - + Assignment compatibility ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1460,7 +1460,8 @@ statements always have to be intended:: complexStmt ::= ifStmt | whileStmt | caseStmt | tryStmt | forStmt | blockStmt | asmStmt | procDecl | iteratorDecl | macroDecl | templateDecl - | constSection | typeSection | whenStmt | varSection + | constSection | letSection + | typeSection | whenStmt | varSection @@ -1474,26 +1475,26 @@ Syntax:: Example: .. code-block:: nimrod - proc p(x, y: int): int {.optional.} = - return x + y + proc p(x, y: int): int {.optional.} = + return x + y discard p(3, 4) # discard the return value of `p` The `discard`:idx: statement evaluates its expression for side-effects and -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 implicitely if the called proc/iterator has -been declared with the `discardable`:idx: pragma: - -.. code-block:: nimrod - proc p(x, y: int): int {.discardable.} = - return x + y - - p(3, 4) # now valid - +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 implicitely if the called proc/iterator has +been declared with the `discardable`:idx: pragma: + +.. code-block:: nimrod + proc p(x, y: int): int {.discardable.} = + return x + y + + p(3, 4) # now valid + Var statement ~~~~~~~~~~~~~ @@ -2430,6 +2431,18 @@ be used to get the type of an expression: var x = 0 var y: type(x) # y has type int +If ``type`` is used to determine the result type of a proc/iterator/converter +call ``c(X)`` (where ``X`` stands for a possibly empty list of arguments), the +interpretation where ``c`` is an iterator is preferred over the +other interpretations: + +.. code-block:: nimrod + import strutils + + # strutils contains both a ``split`` proc and iterator, but since an + # an iterator is the preferred interpretation, `y` has the type ``string``: + var y: type("a b c".split) + Type constraints ~~~~~~~~~~~~~~~~ @@ -2979,16 +2992,16 @@ only consist of an assembler statement. error pragma ------------ The `error`:idx: pragma is used to make the compiler output an error message -with the given content. Compilation does not necessarily abort after an error -though. - -The ``error`` pragma can also be used to -annotate a symbol (like an iterator or proc). The *usage* of the symbol then -triggers a compile-time error. This is especially useful to rule out that some -operation is valid due to overloading and type conversions: - -.. code-block:: nimrod - ## check that underlying int values are compared and not the pointers: +with the given content. Compilation does not necessarily abort after an error +though. + +The ``error`` pragma can also be used to +annotate a symbol (like an iterator or proc). The *usage* of the symbol then +triggers a compile-time error. This is especially useful to rule out that some +operation is valid due to overloading and type conversions: + +.. code-block:: nimrod + ## check that underlying int values are compared and not the pointers: proc `==`(x, y: ptr int): bool {.error.} @@ -3308,6 +3321,7 @@ Memory allocation requires no lock at all! This design easily scales to massive multicore processors that will become the norm in the future. + Thread pragma ------------- @@ -3402,24 +3416,24 @@ The interaction between threads and exceptions is simple: A *handled* exception in one thread cannot affect any other thread. However, an *unhandled* exception in one thread terminates the whole *process*! -Taint mode -========== - -The Nimrod compiler and most parts of the standard library support -a `taint mode`:idx:. 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 -option) it is a distinct string type which helps to detect input -validation errors: - -.. code-block:: nimrod - 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: - echo "hi, ", name.string - -If the taint mode is turned off, ``TaintedString`` is simply an alias for -``string``. - +Taint mode +========== + +The Nimrod compiler and most parts of the standard library support +a `taint mode`:idx:. 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 +option) it is a distinct string type which helps to detect input +validation errors: + +.. code-block:: nimrod + 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: + echo "hi, ", name.string + +If the taint mode is turned off, ``TaintedString`` is simply an alias for +``string``. + diff --git a/tests/accept/run/ttoseq.nim b/tests/accept/run/ttoseq.nim index a7f6c5efd..d631a91e0 100755 --- a/tests/accept/run/ttoseq.nim +++ b/tests/accept/run/ttoseq.nim @@ -10,3 +10,10 @@ template toSeq*(iter: expr): expr = for x in items(toSeq(countup(2, 6))): stdout.write(x) +import strutils + +var y: type("a b c".split) +y = "xzy" + + + |