diff options
author | Araq <rumpf_a@web.de> | 2011-06-17 01:04:33 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-06-17 01:04:33 +0200 |
commit | 849208d779e860230bb8682b3b356ba2942dd889 (patch) | |
tree | bc6428bf782f9d47e121177c0e5f300062b3f1aa | |
parent | dc6a80bd1d36b158a090ed0fb622140856be3dfe (diff) | |
download | Nim-849208d779e860230bb8682b3b356ba2942dd889.tar.gz |
got rid of unsound co/contravariance in procvars
-rwxr-xr-x | compiler/sigmatch.nim | 67 | ||||
-rwxr-xr-x | lib/pure/osproc.nim | 12 | ||||
-rw-r--r-- | lib/pure/romans.nim | 59 | ||||
-rwxr-xr-x | lib/pure/streams.nim | 34 | ||||
-rwxr-xr-x | todo.txt | 5 | ||||
-rwxr-xr-x | web/news.txt | 1 |
6 files changed, 122 insertions, 56 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index c9ab27123..ac1429e4e 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -189,6 +189,39 @@ proc constraintRel(mapping: var TIdTable, f, a: PType): TTypeRelation = result = isNone if f.kind == a.kind: result = isGeneric +proc procTypeRel(mapping: var TIdTable, f, a: PType): TTypeRelation = + proc inconsistentVarTypes(f, a: PType): bool {.inline.} = + result = f.kind != a.kind and (f.kind == tyVar or a.kind == tyVar) + + case a.kind + of tyNil: result = isSubtype + of tyProc: + if sonsLen(f) != sonsLen(a) or f.callconv != a.callconv: return + # Note: We have to do unification for the parameters before the + # return type! + result = isEqual # start with maximum; also correct for no + # params at all + for i in countup(1, sonsLen(f)-1): + var m = typeRel(mapping, f.sons[i], a.sons[i]) + if m <= isSubtype or inconsistentVarTypes(f.sons[i], a.sons[i]): + return isNone + else: result = minRel(m, result) + if f.sons[0] != nil: + if a.sons[0] != nil: + var m = typeRel(mapping, f.sons[0], a.sons[0]) + # Subtype is sufficient for return types! + if m < isSubtype or inconsistentVarTypes(f.sons[0], a.sons[0]): + result = isNone + elif m == isSubtype: result = isConvertible + else: result = minRel(m, result) + else: + result = isNone + elif a.sons[0] != nil: + result = isNone + if tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags: + result = isNone + else: nil + proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation = # is a subtype of f? result = isNone @@ -316,39 +349,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation = of tyNil: result = isSubtype else: nil of tyProc: - case a.kind - of tyNil: result = isSubtype - of tyProc: - if (sonsLen(f) == sonsLen(a)) and (f.callconv == a.callconv): - # Note: We have to do unification for the parameters before the - # return type! - result = isEqual # start with maximum; also correct for no - # params at all - var m: TTypeRelation - for i in countup(1, sonsLen(f) - 1): - m = typeRel(mapping, f.sons[i], a.sons[i]) - if (m == isNone) and - (typeRel(mapping, a.sons[i], f.sons[i]) == isSubtype): - # allow ``f.son`` as subtype of ``a.son``! - result = isConvertible - elif m < isSubtype: - return isNone - else: - result = minRel(m, result) - if f.sons[0] != nil: - if a.sons[0] != nil: - m = typeRel(mapping, f.sons[0], a.sons[0]) - # Subtype is sufficient for return types! - if m < isSubtype: result = isNone - elif m == isSubtype: result = isConvertible - else: result = minRel(m, result) - else: - result = isNone - elif a.sons[0] != nil: - result = isNone - if (tfNoSideEffect in f.flags) and not (tfNoSideEffect in a.flags): - result = isNone - else: nil + result = procTypeRel(mapping, f, a) of tyPointer: case a.kind of tyPointer: result = isEqual diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index d74cf1fdc..de5317717 100755 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -232,10 +232,11 @@ when defined(Windows) and not defined(useNimRtl): handle: THandle atTheEnd: bool - proc hsClose(s: PFileHandleStream) = nil # nothing to do here - proc hsAtEnd(s: PFileHandleStream): bool = return s.atTheEnd + proc hsClose(s: PStream) = nil # nothing to do here + proc hsAtEnd(s: PStream): bool = return PFileHandleStream(s).atTheEnd - proc hsReadData(s: PFileHandleStream, buffer: pointer, bufLen: int): int = + proc hsReadData(s: PStream, buffer: pointer, bufLen: int): int = + var s = PFileHandleStream(s) if s.atTheEnd: return 0 var br: int32 var a = winlean.ReadFile(s.handle, buffer, bufLen, br, nil) @@ -246,7 +247,8 @@ when defined(Windows) and not defined(useNimRtl): s.atTheEnd = br < bufLen result = br - proc hsWriteData(s: PFileHandleStream, buffer: pointer, bufLen: int) = + proc hsWriteData(s: PStream, buffer: pointer, bufLen: int) = + var s = PFileHandleStream(s) var bytesWritten: int32 var a = winlean.writeFile(s.handle, buffer, bufLen, bytesWritten, nil) if a == 0: OSError() @@ -507,7 +509,7 @@ elif not defined(useNimRtl): quit("execve call failed: " & $strerror(errno)) # Parent process. Copy process information. if poEchoCmd in options: - echo(command & " " & join(args, " ")) + echo(command, " ", join(args, " ")) result.id = pid result.inputHandle = p_stdin[writeIdx] diff --git a/lib/pure/romans.nim b/lib/pure/romans.nim new file mode 100644 index 000000000..dee3226d8 --- /dev/null +++ b/lib/pure/romans.nim @@ -0,0 +1,59 @@ +# +# +# Nimrod's Runtime Library +# (c) Copyright 2011 Philippe Lhoste +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## Module for converting an integer to a Roman numeral. +## See http://en.wikipedia.org/wiki/Roman_numerals for reference. + +const + RomanNumeralDigits* = {'I', 'i', 'V', 'v', 'X', 'x', 'L', 'l', 'C', 'c', + 'D', 'd', 'M', 'm'} ## set of all characters a Roman numeral may consist of + +proc romanToDecimal*(romanVal: string): int = + ## Converts a Roman numeral to its int representation. + result = 0 + var prevVal = 0 + for i in countdown(romanVal.len - 1, 0): + var val = 0 + case romanVal[i] + of 'I', 'i': val = 1 + of 'V', 'v': val = 5 + of 'X', 'x': val = 10 + of 'L', 'l': val = 50 + of 'C', 'c': val = 100 + of 'D', 'd': val = 500 + of 'M', 'm': val = 1000 + else: + raise newException(EInvalidValue, "invalid roman numeral: " & $romanVal) + if val >= prevVal: + inc(result, val) + else: + dec(result, val) + prevVal = val + +proc decimalToRoman*(number: range[1..3_999]): string = + ## Converts a number to a Roman numeral. + const romanComposites = [ + ("M", 1000), ("CM", 900), + ("D", 500), ("CD", 400), ("C", 100), + ("XC", 90), ("L", 50), ("XL", 40), ("X", 10), ("IX", 9), + ("V", 5), ("IV", 4), ("I", 1)] + result = "" + var decVal = number + for key, val in items(romanComposites): + while decVal >= val: + dec(decVal, val) + result.add(key) + +when isMainModule: + import math + randomize() + for i in 1 .. 100: + var rnd = 1 + random(3990) + assert rnd == rnd.decimalToRoman.romanToDecimal + diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index f4d2911fc..d0e6ecec7 100755 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -104,28 +104,34 @@ type data*: string pos: int -proc ssAtEnd(s: PStringStream): bool = +proc ssAtEnd(s: PStream): bool = + var s = PStringStream(s) return s.pos >= s.data.len -proc ssSetPosition(s: PStringStream, pos: int) = +proc ssSetPosition(s: PStream, pos: int) = + var s = PStringStream(s) s.pos = min(pos, s.data.len-1) -proc ssGetPosition(s: PStringStream): int = +proc ssGetPosition(s: PStream): int = + var s = PStringStream(s) return s.pos -proc ssReadData(s: PStringStream, buffer: pointer, bufLen: int): int = +proc ssReadData(s: PStream, buffer: pointer, bufLen: int): int = + var s = PStringStream(s) result = min(bufLen, s.data.len - s.pos) if result > 0: copyMem(buffer, addr(s.data[s.pos]), result) inc(s.pos, result) -proc ssWriteData(s: PStringStream, buffer: pointer, bufLen: int) = +proc ssWriteData(s: PStream, buffer: pointer, bufLen: int) = + var s = PStringStream(s) if bufLen > 0: setLen(s.data, s.data.len + bufLen) copyMem(addr(s.data[s.pos]), buffer, bufLen) inc(s.pos, bufLen) -proc ssClose(s: PStringStream) = +proc ssClose(s: PStream) = + var s = PStringStream(s) s.data = nil proc newStringStream*(s: string = ""): PStringStream = @@ -145,16 +151,16 @@ type TFileStream* = object of TStream f: TFile -proc fsClose(s: PFileStream) = close(s.f) -proc fsAtEnd(s: PFileStream): bool = return EndOfFile(s.f) -proc fsSetPosition(s: PFileStream, pos: int) = setFilePos(s.f, pos) -proc fsGetPosition(s: PFileStream): int = return int(getFilePos(s.f)) +proc fsClose(s: PStream) = close(PFileStream(s).f) +proc fsAtEnd(s: PStream): bool = return EndOfFile(PFileStream(s).f) +proc fsSetPosition(s: PStream, pos: int) = setFilePos(PFileStream(s).f, pos) +proc fsGetPosition(s: PStream): int = return int(getFilePos(PFileStream(s).f)) -proc fsReadData(s: PFileStream, buffer: pointer, bufLen: int): int = - result = readBuffer(s.f, buffer, bufLen) +proc fsReadData(s: PStream, buffer: pointer, bufLen: int): int = + result = readBuffer(PFileStream(s).f, buffer, bufLen) -proc fsWriteData(s: PFileStream, buffer: pointer, bufLen: int) = - if writeBuffer(s.f, buffer, bufLen) != bufLen: +proc fsWriteData(s: PStream, buffer: pointer, bufLen: int) = + if writeBuffer(PFileStream(s).f, buffer, bufLen) != bufLen: raise newEIO("cannot write to stream") proc newFileStream*(f: TFile): PFileStream = diff --git a/todo.txt b/todo.txt index eab2a5ea6..068068beb 100755 --- a/todo.txt +++ b/todo.txt @@ -5,7 +5,6 @@ High priority (version 0.8.12) * add --deadlock_prevention:on|off switch? timeout for locks? * built-in serialization - bug: invoking a generic iterator twice triggers a code gen bug (titer2) -- bug: forward proc for generic seems broken - sorting with leads to a strange memory corruption! --> system.swap or genericAssign is broken! And indeed, if reference counts are not modified and the GC is triggered in between a swap, bad things @@ -15,20 +14,18 @@ High priority (version 0.8.12) version 0.9.0 ============= +- bug: forward proc for generic seems broken - test the sort implementation again - warning for implicit openArray -> varargs convention - implement explicit varargs - tests: run modules that contain "#RUN_ME", compile the other modules; run the GC tests -- fix the streams implementation so that it uses methods - fix overloading resolution -- wrong co-/contravariance - make ^ available as operator - implement closures; implement proper coroutines Bugs ---- -- proc (x: int) is passable to proc (x: var int) !? - the parser allows empty object case branches - bug: generic assign still buggy - Optimization: If we use a temporary for the result anyway the code gen diff --git a/web/news.txt b/web/news.txt index ca8f701a6..adc8213f1 100755 --- a/web/news.txt +++ b/web/news.txt @@ -45,6 +45,7 @@ Changes affecting backwards compatibility dereference a pointer explicitely. - ``system.readFile`` does not return ``nil`` anymore but raises an ``EIO`` exception instead. +- Unsound co-/contravariance for procvars has been removed. Additions |