diff options
author | Araq <rumpf_a@web.de> | 2012-07-08 21:03:47 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-07-08 21:03:47 +0200 |
commit | 4fbba0a65ad310ba9498f1cf9f79eb0826b19f81 (patch) | |
tree | dece3596fbdf153263f5672b4011139f70a4df6a | |
parent | 36247e0947699a56d5bc51d48188b6dda1815587 (diff) | |
download | Nim-4fbba0a65ad310ba9498f1cf9f79eb0826b19f81.tar.gz |
changed integer promotion rules; breaks bootstrapping and lots of code
42 files changed, 642 insertions, 260 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 511d6f116..e3528dece 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -224,7 +224,8 @@ type sfMainModule, # module is the main module sfSystemModule, # module is the system module sfNoReturn, # proc never returns (an exit proc) - sfAddrTaken, # the variable's address is taken (ex- or implicitely) + sfAddrTaken, # the variable's address is taken (ex- or implicitely); + # *OR*: a proc is indirectly called (used as first class) sfCompilerProc, # proc is a compiler proc, that is a C proc that is # needed for the code generator sfProcvar, # proc can be passed to a proc var diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 1e1bf8072..78a107bbb 100755 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1037,8 +1037,9 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) = InitLocExpr(p, e.sons[1], a) var t = skipTypes(e.sons[1].typ, abstractVarRange) case t.kind - of tyInt..tyInt64: - putIntoDest(p, d, e.typ, ropecg(p.module, "#reprInt($1)", [rdLoc(a)])) + of tyInt..tyInt64, tyUInt..tyUInt64: + putIntoDest(p, d, e.typ, + ropecg(p.module, "#reprInt((NI64)$1)", [rdLoc(a)])) of tyFloat..tyFloat128: putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)])) of tyBool: diff --git a/compiler/ecmasgen.nim b/compiler/ecmasgen.nim index 30a697d8e..9b3601ae4 100755 --- a/compiler/ecmasgen.nim +++ b/compiler/ecmasgen.nim @@ -1066,7 +1066,8 @@ proc createVar(p: var TProc, typ: PType, indirect: bool): PRope = result = nil proc isIndirect(v: PSym): bool = - result = (sfAddrTaken in v.flags) and (mapType(v.typ) != etyObject) + result = (sfAddrTaken in v.flags) and (mapType(v.typ) != etyObject) and + v.kind notin {skProc, skConverter, skMethod, skIterator} proc genVarInit(p: var TProc, v: PSym, n: PNode, r: var TCompRes) = var diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim index 09c99c027..fcfc35ff1 100755 --- a/compiler/magicsys.nim +++ b/compiler/magicsys.nim @@ -74,24 +74,51 @@ proc getSysType(kind: TTypeKind): PType = InternalError("wanted: " & $kind & " got: " & $result.kind) if result == nil: InternalError("type not found: " & $kind) -when false: - var - intTypeCache: array[-5..64, PType] +var + intTypeCache: array[-5..64, PType] - proc getIntLitType*(literal: PNode): PType = - # we cache some common integer literal types for performance: - let value = literal.intVal - if value >= low(intTypeCache) and value <= high(intTypeCache): - result = intTypeCache[value.int] - if result == nil: - let ti = getSysType(tyInt) - result = copyType(ti, ti.owner, false) - result.n = literal - intTypeCache[value.int] = result - else: +proc getIntLitType*(literal: PNode): PType = + # we cache some common integer literal types for performance: + let value = literal.intVal + if value >= low(intTypeCache) and value <= high(intTypeCache): + result = intTypeCache[value.int] + if result == nil: let ti = getSysType(tyInt) result = copyType(ti, ti.owner, false) result.n = literal + intTypeCache[value.int] = result + else: + let ti = getSysType(tyInt) + result = copyType(ti, ti.owner, false) + result.n = literal + +proc setIntLitType*(result: PNode) = + let i = result.intVal + case platform.IntSize + of 8: result.typ = getIntLitType(result) + of 4: + if i >= low(int32) and i <= high(int32): + result.typ = getIntLitType(result) + else: + result.typ = getSysType(tyInt64) + of 2: + if i >= low(int16) and i <= high(int16): + result.typ = getIntLitType(result) + elif i >= low(int32) and i <= high(int32): + result.typ = getSysType(tyInt32) + else: + result.typ = getSysType(tyInt64) + of 1: + # 8 bit CPUs are insane ... + if i >= low(int8) and i <= high(int8): + result.typ = getIntLitType(result) + elif i >= low(int16) and i <= high(int16): + result.typ = getSysType(tyInt16) + elif i >= low(int32) and i <= high(int32): + result.typ = getSysType(tyInt32) + else: + result.typ = getSysType(tyInt64) + else: InternalError(result.info, "invalid int size") proc getCompilerProc(name: string): PSym = var ident = getIdent(name, hashIgnoreStyle(name)) diff --git a/compiler/saturate.nim b/compiler/saturate.nim new file mode 100644 index 000000000..e0968843b --- /dev/null +++ b/compiler/saturate.nim @@ -0,0 +1,79 @@ +# +# +# The Nimrod Compiler +# (c) Copyright 2012 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## Saturated arithmetic routines. XXX Make part of the stdlib? + +proc `|+|`*(a, b: biggestInt): biggestInt = + ## saturated addition. + result = a +% b + if (result xor a) >= 0'i64 or (result xor b) >= 0'i64: + return result + if a < 0 or b < 0: + result = low(result) + else: + result = high(result) + +proc `|-|`*(a, b: biggestInt): biggestInt = + result = a -% b + if (result xor a) >= 0'i64 or (result xor not b) >= 0'i64: + return result + if b > 0: + result = low(result) + else: + result = high(result) + +proc `|abs|`*(a: biggestInt): biggestInt = + if a != low(a): + if a >= 0: result = a + else: result = -a + else: + result = low(a) + +proc `|div|`*(a, b: biggestInt): biggestInt = + # (0..5) div (0..4) == (0..5) div (1..4) == (0 div 4) .. (5 div 1) + if b == 0'i64: + # make the same as ``div 1``: + result = a + elif a == low(a) and b == -1'i64: + result = high(result) + else: + result = a div b + +proc `|mod|`*(a, b: biggestInt): biggestInt = + if b == 0'i64: + result = a + else: + result = a mod b + +proc `|*|`*(a, b: biggestInt): biggestInt = + var + resAsFloat, floatProd: float64 + result = a *% b + floatProd = toBiggestFloat(a) # conversion + floatProd = floatProd * toBiggestFloat(b) + resAsFloat = toBiggestFloat(result) + + # Fast path for normal case: small multiplicands, and no info + # is lost in either method. + if resAsFloat == floatProd: return result + + # Somebody somewhere lost info. Close enough, or way off? Note + # that a != 0 and b != 0 (else resAsFloat == floatProd == 0). + # The difference either is or isn't significant compared to the + # true value (of which floatProd is a good approximation). + + # abs(diff)/abs(prod) <= 1/32 iff + # 32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough" + if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd): + return result + + if floatProd >= 0.0: + result = high(result) + else: + result = low(result) diff --git a/compiler/semcall.nim b/compiler/semcall.nim index f0c9f42b0..8ba582a33 100755 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -18,8 +18,8 @@ proc sameMethodDispatcher(a, b: PSym): bool = if aa.kind == nkSym and bb.kind == nkSym and aa.sym == bb.sym: result = true -proc resolveOverloads(c: PContext, n, orig: PNode, - filter: TSymKinds): TCandidate = +proc resolveOverloads(c: PContext, n, orig: PNode, + filter: TSymKinds): TCandidate = var initialBinding: PNode var f = n.sons[0] if f.kind == nkBracketExpr: @@ -67,9 +67,17 @@ proc resolveOverloads(c: PContext, n, orig: PNode, not sameMethodDispatcher(best.calleeSym, alt.calleeSym): if best.state != csMatch: InternalError(n.info, "x.state is not csMatch") + #writeMatches(best) + #writeMatches(alt) + var args = "(" + for i in countup(1, sonsLen(n) - 1): + if i > 1: add(args, ", ") + add(args, typeToString(n.sons[i].typ)) + add(args, ")") + LocalError(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [ getProcHeader(best.calleeSym), getProcHeader(alt.calleeSym), - best.calleeSym.Name.s]) + args]) proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode = assert x.state == csMatch diff --git a/compiler/semdata.nim b/compiler/semdata.nim index c28c8c7a1..9eff8c4f4 100755 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -213,6 +213,11 @@ proc markUsed*(n: PNode, s: PSym) = if sfDeprecated in s.flags: Message(n.info, warnDeprecated, s.name.s) if sfError in s.flags: LocalError(n.info, errWrongSymbolX, s.name.s) +proc markIndirect*(c: PContext, s: PSym) = + if s.kind in {skProc, skConverter, skMethod, skIterator}: + incl(s.flags, sfAddrTaken) + # XXX add to 'c' for global analysis + proc useSym*(sym: PSym): PNode = result = newSymNode(sym) markUsed(result, sym) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 22af8b4e0..7aa723c52 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -74,8 +74,10 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = smoduleId != c.module.id and smoduleId != c.friendModule.id: LocalError(n.info, errXCannotBePassedToProcVar, s.name.s) result = symChoice(c, n, s) - if result.kind == nkSym and isGenericRoutine(result.sym): - LocalError(n.info, errInstantiateXExplicitely, s.name.s) + if result.kind == nkSym: + markIndirect(c, result.sym) + if isGenericRoutine(result.sym): + LocalError(n.info, errInstantiateXExplicitely, s.name.s) of skConst: markUsed(n, s) case skipTypes(s.typ, abstractInst).kind @@ -129,10 +131,11 @@ proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) = if diff == high(int): GlobalError(info, errGenerated, MsgKindToString(errIllegalConvFromXtoY) % [ src.typeToString, castDest.typeToString]) - + +const + IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64} + proc checkConvertible(info: TLineInfo, castDest, src: PType) = - const - IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64} if sameType(castDest, src) and castDest.sym == src.sym: # don't annoy conversions that may be needed on another processor: if castDest.kind notin {tyInt..tyUInt64, tyNil}: @@ -177,8 +180,8 @@ proc isCastable(dst, src: PType): bool = result = false else: result = (ds >= ss) or - (skipTypes(dst, abstractInst).kind in {tyInt..tyFloat128}) or - (skipTypes(src, abstractInst).kind in {tyInt..tyFloat128}) + (skipTypes(dst, abstractInst).kind in IntegralTypes) or + (skipTypes(src, abstractInst).kind in IntegralTypes) proc semConv(c: PContext, n: PNode, s: PSym): PNode = if sonsLen(n) != 2: GlobalError(n.info, errConvNeedsOneArg) @@ -190,10 +193,12 @@ proc semConv(c: PContext, n: PNode, s: PSym): PNode = if op.kind != nkSymChoice: checkConvertible(result.info, result.typ, op.typ) else: - for i in countup(0, sonsLen(op) - 1): - if sameType(result.typ, op.sons[i].typ): - markUsed(n, op.sons[i].sym) - return op.sons[i] + for i in countup(0, sonsLen(op) - 1): + let it = op.sons[i] + if sameType(result.typ, it.typ): + markUsed(n, it.sym) + markIndirect(c, it.sym) + return it localError(n.info, errUseQualifier, op.sons[0].sym.name.s) proc semCast(c: PContext, n: PNode): PNode = @@ -222,7 +227,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = n.typ = getSysType(tyInt) of tyArrayConstr, tyArray: n.typ = n.sons[1].typ.sons[0] # indextype - of tyInt..tyInt64, tyChar, tyBool, tyEnum: + of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32: n.typ = n.sons[1].typ else: GlobalError(n.info, errInvalidArgForX, opToStr[m]) result = n @@ -498,6 +503,24 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode = if n.kind notin nkCallKinds or n.sons[0].kind != nkSym: return var callee = n.sons[0].sym + # constant folding that is necessary for correctness of semantic pass: + if callee.magic != mNone and callee.magic in ctfeWhitelist and n.typ != nil: + var call = newNodeIT(nkCall, n.info, n.typ) + call.add(n.sons[0]) + var allConst = true + for i in 1 .. < n.len: + let a = getConstExpr(c.module, n.sons[i]) + if a != nil: call.add(a) + else: + allConst = false + call.add(n.sons[i]) + if allConst: + result = semfold.getConstExpr(c.module, call) + if result.isNil: result = n + else: return result + result.typ = semfold.getIntervalType(callee.magic, call) + + # optimization pass: not necessary for correctness of the semantic pass if {sfNoSideEffect, sfCompileTime} * callee.flags != {} and {sfForward, sfImportc} * callee.flags == {}: if sfCompileTime notin callee.flags and @@ -901,7 +924,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode = if skipTypes(n.sons[1].typ, {tyGenericInst, tyRange, tyOrdinal}).kind in {tyInt..tyInt64}: var idx = getOrdValue(n.sons[1]) - if (idx >= 0) and (idx < sonsLen(arr)): n.typ = arr.sons[int(idx)] + if idx >= 0 and idx < sonsLen(arr): n.typ = arr.sons[int(idx)] else: GlobalError(n.info, errInvalidIndexValueForTuple) else: GlobalError(n.info, errIndexTypesDoNotMatch) @@ -1301,15 +1324,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = nil of nkNilLit: result.typ = getSysType(tyNil) - of nkIntLit: - # XXX this is stupid: - if result.typ == nil: - let i = result.intVal - if i >= low(int32) and i <= high(int32): - result.typ = getSysType(tyInt) - else: - result.typ = getSysType(tyInt64) - of nkInt8Lit: + of nkIntLit: + if result.typ == nil: setIntLitType(result) + of nkInt8Lit: if result.typ == nil: result.typ = getSysType(tyInt8) of nkInt16Lit: if result.typ == nil: result.typ = getSysType(tyInt16) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index ce9e03513..061a29fad 100755 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -13,7 +13,7 @@ import strutils, lists, options, ast, astalgo, trees, treetab, nimsets, times, nversion, platform, math, msgs, os, condsyms, idents, renderer, types, - commands, magicsys + commands, magicsys, saturate proc getConstExpr*(m: PSym, n: PNode): PNode # evaluates the constant expression or returns nil if it is no constant @@ -26,12 +26,19 @@ proc newStrNodeT*(strVal: string, n: PNode): PNode # implementation -proc newIntNodeT(intVal: BiggestInt, n: PNode): PNode = - if skipTypes(n.typ, abstractVarRange).kind == tyChar: +proc newIntNodeT(intVal: BiggestInt, n: PNode): PNode = + case skipTypes(n.typ, abstractVarRange).kind + of tyInt: + result = newIntNode(nkIntLit, intVal) + result.typ = getIntLitType(result) + # hrm, this is not correct: 1 + high(int) shouldn't produce tyInt64 ... + #setIntLitType(result) + of tyChar: result = newIntNode(nkCharLit, intVal) - else: + result.typ = n.typ + else: result = newIntNode(nkIntLit, intVal) - result.typ = n.typ + result.typ = n.typ result.info = n.info proc newFloatNodeT(floatVal: BiggestFloat, n: PNode): PNode = @@ -67,6 +74,150 @@ proc ordinalValToString(a: PNode): string = else: result = $x +proc isFloatRange(t: PType): bool {.inline.} = + result = t.kind == tyRange and t.sons[0].kind in {tyFloat..tyFloat128} + +proc isIntRange(t: PType): bool {.inline.} = + result = t.kind == tyRange and t.sons[0].kind in { + tyInt..tyInt64, tyUInt8..tyUInt32} + +proc pickIntRange(a, b: PType): PType = + if isIntRange(a): result = a + elif isIntRange(b): result = b + else: result = a + +proc isIntRangeOrLit(t: PType): bool = + result = isIntRange(t) or isIntLit(t) + +proc pickMinInt(n: PNode): biggestInt = + if n.kind in {nkIntLit..nkUInt64Lit}: + result = n.intVal + elif isIntLit(n.typ): + result = n.typ.n.intVal + elif isIntRange(n.typ): + result = firstOrd(n.typ) + else: + InternalError(n.info, "pickMinInt") + +proc pickMaxInt(n: PNode): biggestInt = + if n.kind in {nkIntLit..nkUInt64Lit}: + result = n.intVal + elif isIntLit(n.typ): + result = n.typ.n.intVal + elif isIntRange(n.typ): + result = lastOrd(n.typ) + else: + InternalError(n.info, "pickMaxInt") + +proc makeRange(typ: PType, first, last: biggestInt): PType = + var n = newNode(nkRange) + addSon(n, newIntNode(nkIntLit, min(first, last))) + addSon(n, newIntNode(nkIntLit, max(first, last))) + result = newType(tyRange, typ.owner) + result.n = n + addSon(result, skipTypes(typ, {tyRange})) + +proc makeRangeF(typ: PType, first, last: biggestFloat): PType = + var n = newNode(nkRange) + addSon(n, newFloatNode(nkFloatLit, min(first.float, last.float))) + addSon(n, newFloatNode(nkFloatLit, max(first.float, last.float))) + result = newType(tyRange, typ.owner) + result.n = n + addSon(result, skipTypes(typ, {tyRange})) + +proc getIntervalType*(m: TMagic, n: PNode): PType = + # Nimrod requires interval arithmetic for ``range`` types. Lots of tedious + # work but the feature is very nice for reducing explicit conversions. + result = n.typ + + template commutativeOp(opr: expr) {.immediate.} = + let a = n.sons[1] + let b = n.sons[2] + if isIntRangeOrLit(a.typ) and isIntRangeOrLit(b.typ): + result = makeRange(pickIntRange(a.typ, b.typ), + opr(pickMinInt(a), pickMinInt(b)), + opr(pickMaxInt(a), pickMaxInt(b))) + + template binaryOp(opr: expr) {.immediate.} = + let a = n.sons[1] + let b = n.sons[2] + if isIntRange(a.typ) and b.kind in {nkIntLit..nkUInt64Lit}: + result = makeRange(a.typ, + opr(pickMinInt(a), pickMinInt(b)), + opr(pickMaxInt(a), pickMaxInt(b))) + + case m + of mUnaryMinusI, mUnaryMinusI64: + let a = n.sons[1].typ + if isIntRange(a): + # (1..3) * (-1) == (-3.. -1) + result = makeRange(a, 0|-|lastOrd(a), 0|-|firstOrd(a)) + of mUnaryMinusF64: + let a = n.sons[1].typ + if isFloatRange(a): + result = makeRangeF(a, -getFloat(a.n.sons[1]), + -getFloat(a.n.sons[0])) + of mAbsF64: + let a = n.sons[1].typ + if isFloatRange(a): + # abs(-5.. 1) == (1..5) + result = makeRangeF(a, abs(getFloat(a.n.sons[1])), + abs(getFloat(a.n.sons[0]))) + of mAbsI, mAbsI64: + let a = n.sons[1].typ + if isIntRange(a): + result = makeRange(a, `|abs|`(getInt(a.n.sons[1])), + `|abs|`(getInt(a.n.sons[0]))) + of mSucc: + let a = n.sons[1].typ + let b = n.sons[2].typ + if isIntRange(a) and isIntLit(b): + # (-5.. 1) + 6 == (-5 + 6)..(-1 + 6) + result = makeRange(a, pickMinInt(n.sons[1]) |+| pickMinInt(n.sons[2]), + pickMaxInt(n.sons[1]) |+| pickMaxInt(n.sons[2])) + of mPred: + let a = n.sons[1].typ + let b = n.sons[2].typ + if isIntRange(a) and isIntLit(b): + result = makeRange(a, pickMinInt(n.sons[1]) |-| pickMinInt(n.sons[2]), + pickMaxInt(n.sons[1]) |-| pickMaxInt(n.sons[2])) + of mAddI, mAddI64, mAddU, mAddU64: + commutativeOp(`|+|`) + of mMulI, mMulI64, mMulU, mMulU64: + commutativeOp(`|*|`) + of mSubI, mSubI64, mSubU, mSubU64: + binaryOp(`|-|`) + of mBitandI, mBitandI64: + var a = n.sons[1] + var b = n.sons[2] + # symmetrical: + if b.kind notin {nkIntLit..nkUInt64Lit}: swap(a, b) + if b.kind in {nkIntLit..nkUInt64Lit}: + let x = b.intVal|+|1 + if (x and -x) == x and x >= 0: + result = makeRange(a.typ, 0, b.intVal) + of mModI, mModI64, mModU, mModU64: + # so ... if you ever wondered about modulo's signedness; this defines it: + let a = n.sons[1] + let b = n.sons[2] + if b.kind in {nkIntLit..nkUInt64Lit}: + if b.intVal >= 0: + result = makeRange(a.typ, 0, b.intVal-1) + else: + result = makeRange(a.typ, b.intVal+1, 0) + of mDivI, mDivI64, mDivU, mDivU64: + binaryOp(`|div|`) + of mMinI, mMinI64: + commutativeOp(min) + of mMaxI, mMaxI64: + commutativeOp(max) + else: nil + +discard """ + mShlI, mShlI64, + mShrI, mShrI64, mAddF64, mSubF64, mMulF64, mDivF64, mMaxF64, mMinF64 +""" + proc evalOp(m: TMagic, n, a, b, c: PNode): PNode = # b and c may be nil result = nil diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index b7e890e67..e3cc7d610 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -40,6 +40,11 @@ proc semTypeTraits(c: PContext, n: PNode): PNode = # pass unmodified to evals result = n +proc semOrd(c: PContext, n: PNode): PNode = + result = n + result.typ = makeRangeType(c, firstOrd(n.sons[1].typ), + lastOrd(n.sons[1].typ), n.info) + proc magicsAfterOverloadResolution(c: PContext, n: PNode, flags: TExprFlags): PNode = case n[0].sym.magic @@ -49,5 +54,6 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode, result = newStrNodeT(renderTree(n[1], {renderNoComments}), n) result.typ = getSysType(tyString) of mInstantiationInfo: result = semInstantiationInfo(c, n) + of mOrd: result = semOrd(c, n) else: result = n diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index c437ce2b5..10722d853 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -132,7 +132,8 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = var a = semConstExpr(c, n[1]) var b = semConstExpr(c, n[2]) if not sameType(a.typ, b.typ): GlobalError(n.info, errPureTypeMismatch) - if a.typ.kind notin {tyInt..tyInt64,tyEnum,tyBool,tyChar,tyFloat..tyFloat128}: + if a.typ.kind notin {tyInt..tyInt64,tyEnum,tyBool,tyChar,tyFloat..tyFloat128, + tyUInt8..tyUInt32}: GlobalError(n.info, errOrdinalTypeExpected) if enumHasHoles(a.typ): GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 6819bb37f..4a7ba9587 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -34,8 +34,13 @@ type # for example TTypeRelation* = enum # order is important! - isNone, isConvertible, isIntConv, isSubtype, - isGeneric + isNone, isConvertible, + isIntConv, + isSubtype, + isSubrange, # subrange of the wanted type; no type conversion + # but apart from that counts as ``isSubtype`` + isGeneric, + isFromIntLit, # conversion *from* int literal; proven safe isEqual proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} = @@ -56,10 +61,6 @@ proc initCandidate*(c: var TCandidate, callee: PType) = proc put(t: var TIdTable, key, val: PType) {.inline.} = IdTablePut(t, key, val) - when false: - if val.kind == tyObject and isDefined"testme" and - IdentEq(val.sym.name, "TTable"): - assert false proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode, calleeScope = -1) = initCandidateAux(c, callee.typ) @@ -100,7 +101,7 @@ proc cmpCandidates*(a, b: TCandidate): int = if (a.calleeScope != -1) and (b.calleeScope != -1): result = a.calleeScope - b.calleeScope -proc writeMatches(c: TCandidate) = +proc writeMatches*(c: TCandidate) = Writeln(stdout, "exact matches: " & $c.exactMatches) Writeln(stdout, "subtype matches: " & $c.subtypeMatches) Writeln(stdout, "conv matches: " & $c.convMatches) @@ -160,15 +161,25 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation = if a.kind == f.kind: result = isEqual else: - var k = skipTypes(a, {tyRange}).kind - if k == f.kind: result = isSubtype - elif k == tyInt and f.kind in {tyRange, tyInt8..tyUInt64}: - # and a.n != nil and a.n.intVal >= firstOrd(f) and - # a.n.intVal <= lastOrd(f): + let ab = skipTypes(a, {tyRange}) + let k = ab.kind + if k == f.kind: result = isSubrange + elif k == tyInt and f.kind in {tyRange, tyInt8..tyInt64, + tyUInt..tyUInt64} and + isIntLit(ab) and ab.n.intVal >= firstOrd(f) and + ab.n.intVal <= lastOrd(f): # integer literal in the proper range; we want ``i16 + 4`` to stay an # ``int16`` operation so we declare the ``4`` pseudo-equal to int16 + result = isFromIntLit + elif f.kind == tyInt and k in {tyInt8..tyInt32}: result = isIntConv - elif k >= min and k <= max: result = isConvertible + elif k >= min and k <= max: + result = isConvertible + elif a.kind == tyRange and a.sons[0].kind in {tyInt..tyInt64, + tyUInt8..tyUInt32} and + a.n[0].intVal >= firstOrd(f) and + a.n[1].intVal <= lastOrd(f): + result = isConvertible else: result = isNone #elif f.kind == tyInt and k in {tyInt..tyInt32}: result = isIntConv #elif f.kind == tyUInt and k in {tyUInt..tyUInt32}: result = isIntConv @@ -186,10 +197,10 @@ proc handleFloatRange(f, a: PType): TTypeRelation = if a.kind == f.kind: result = isEqual else: - var k = skipTypes(a, {tyRange}).kind - if k == f.kind: result = isSubtype - elif k == tyInt and f.kind >= tyFloat and f.kind <= tyFloat128: - result = isIntConv + let ab = skipTypes(a, {tyRange}) + var k = ab.kind + if k == f.kind: result = isSubrange + elif isIntLit(ab): result = isConvertible elif k >= tyFloat and k <= tyFloat128: result = isConvertible else: result = isNone @@ -229,7 +240,7 @@ proc tupleRel(mapping: var TIdTable, f, a: PType): TTypeRelation = proc matchTypeClass(mapping: var TIdTable, f, a: PType): TTypeRelation = for i in countup(0, f.sonsLen - 1): let son = f.sons[i] - var match = son.kind == a.kind + var match = son.kind == skipTypes(a, {tyRange}).kind if not match: case son.kind @@ -584,12 +595,17 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType, of isConvertible: inc(m.convMatches) result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) - of isIntConv: + of isIntConv: + # too lazy to introduce another ``*matches`` field, so we conflate + # ``isIntConv`` and ``isIntLit`` here: inc(m.intConvMatches) result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) of isSubtype: inc(m.subtypeMatches) result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c) + of isSubrange: + inc(m.subtypeMatches) + result = copyTree(arg) of isGeneric: inc(m.genericMatches) if m.calleeSym != nil and m.calleeSym.kind in {skMacro, skTemplate}: @@ -601,6 +617,11 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType, if skipTypes(result.typ, abstractVar).kind in {tyTuple}: result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) # BUGFIX: use ``result.typ`` and not `f` here + of isFromIntLit: + # too lazy to introduce another ``*matches`` field, so we conflate + # ``isIntConv`` and ``isIntLit`` here: + inc(m.intConvMatches, 256) + result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) of isEqual: inc(m.exactMatches) result = copyTree(arg) diff --git a/compiler/transf.nim b/compiler/transf.nim index bf6354665..3c3ae12c9 100755 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -734,7 +734,6 @@ proc transform(c: PTransf, n: PNode): PTransNode = # we inline constants if they are not complex constants: if cnst != nil and not dontInlineConstant(n, cnst): result = PTransNode(cnst) # do not miss an optimization - warnNarrowingConversion(result.pnode) proc processTransf(context: PPassContext, n: PNode): PNode = # Note: For interactive mode we cannot call 'passes.skipCodegen' and skip diff --git a/compiler/types.nim b/compiler/types.nim index 9b4b869e4..8005ba806 100755 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -102,6 +102,9 @@ proc getOrdValue(n: PNode): biggestInt = LocalError(n.info, errOrdinalTypeExpected) result = 0 +proc isIntLit*(t: PType): bool {.inline.} = + result = t.n != nil and t.n.kind == nkIntLit + proc isCompatibleToCString(a: PType): bool = if a.kind == tyArray: if (firstOrd(a.sons[0]) == 0) and @@ -400,8 +403,15 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string = result = "" if t == nil: return if prefer == preferName and t.sym != nil and sfAnon notin t.sym.flags: + if t.kind == tyInt and isIntLit(t): + return t.sym.Name.s & "(" & $t.n.intVal & ")" return t.sym.Name.s case t.Kind + of tyInt: + if not isIntLit(t): + result = typeToStr[t.kind] + else: + result = "intLit(" & $t.n.intVal & ")" of tyGenericBody, tyGenericInst, tyGenericInvokation: result = typeToString(t.sons[0]) & '[' for i in countup(1, sonsLen(t) -1 -ord(t.kind != tyGenericInvokation)): @@ -536,7 +546,7 @@ proc lastOrd(t: PType): biggestInt = of tyUInt8: result = 0xFF of tyUInt16: result = 0xFFFF of tyUInt32: result = 0xFFFFFFFF - of tyUInt64: result = -1 + of tyUInt64: result = 0x7FFFFFFFFFFFFFFF'i64 of tyEnum: assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym) result = t.n.sons[sonsLen(t.n) - 1].sym.position diff --git a/doc/manual.txt b/doc/manual.txt index 02c1294e5..f526d9d22 100755 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -570,9 +570,67 @@ operation meaning `Automatic type conversion`:idx: is performed in expressions where different kinds of integer types are used: the smaller type is converted to the larger. + +A `narrowing type conversion`:idx: converts a larger to a smaller type (for +example ``int32 -> int16``. A `widening type conversion`:idx: converts a +smaller type to a larger type (for example ``int16 -> int32``). In Nimrod only +widening type conversion are *implicit*: + +.. code-block:: nimrod + var myInt16 = 5i16 + var myInt: int + myInt16 + 34 # of type ``int16`` + myInt16 + myInt # of type ``int`` + myInt16 + 2i32 # of type ``int32`` + +However, ``int`` literals are implicitely convertible to a smaller integer type +if the literal's value fits this smaller type and such a conversion is less +expensive than other implicit conversions, so ``myInt16 + 34`` produces +an ``int16`` result. + For further details, see `Convertible relation`_. +Subrange types +~~~~~~~~~~~~~~ +A `subrange`:idx: type is a range of values from an ordinal type (the base +type). To define a subrange type, one must specify it's limiting values: the +lowest and highest value of the type: + +.. code-block:: nimrod + type + TSubrange = range[0..5] + + +``TSubrange`` is a subrange of an integer which can only hold the values 0 +to 5. Assigning any other value to a variable of type ``TSubrange`` is a +checked runtime error (or static error if it can be statically +determined). Assignments from the base type to one of its subrange types +(and vice versa) are allowed. + +A subrange type has the same size as its base type (``int`` in the example). + +Nimrod requires `interval arithmetic`:idx: for subrange types over a set +of built-in operators that involve constants: ``x mod 3`` is of +type ``range[0..2]``. The following built-in operators for integers are +affected by this rule: ``-``, ``+``, ``*``, ``min``, ``max``, ``succ``, +``pred``, ``mod``, ``div``, ``and`` (bitwise and). + +Bitwise and only produces a ``range`` if one of its operands is a +constant *x* so that (x+1) is a number of two. +(Bitwise and then behaves as a ``mod`` operation.) + +This means that the following code is accepted: + +.. code-block:: nimrod + case (x and 3) + 7 + of 7: echo "A" + of 8: echo "B" + of 9: echo "C" + of 10: echo "D" + # note: no ``else`` required as (x and 3) + 7 has the type: range[7..10] + + Pre-defined floating point types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -729,26 +787,6 @@ ordinal value and its string value by using a tuple. It is also possible to only specify one of them. -Subrange types -~~~~~~~~~~~~~~ -A `subrange`:idx: type is a range of values from an ordinal type (the base -type). To define a subrange type, one must specify it's limiting values: the -lowest and highest value of the type: - -.. code-block:: nimrod - type - TSubrange = range[0..5] - - -``TSubrange`` is a subrange of an integer which can only hold the values 0 -to 5. Assigning any other value to a variable of type ``TSubrange`` is a -checked runtime error (or static error if it can be statically -determined). Assignments from the base type to one of its subrange types -(and vice versa) are allowed. - -A subrange type has the same size as its base type (``int`` in the example). - - String type ~~~~~~~~~~~ All string literals are of the type `string`:idx:. A string in Nimrod is very @@ -1798,7 +1836,9 @@ evaluated and if its value is in a *slicelist* the corresponding statements given *slicelist* the ``else`` part is executed. If there is no ``else`` part and not all possible values that ``expr`` can hold occur in a ``slicelist``, a static error occurs. This holds only for expressions of -ordinal types. +ordinal types. "All possible values" of ``expr`` are determined by ``expr``'s +type. + If the expression is not of an ordinal type, and no ``else`` part is given, control passes after the ``case`` statement. diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim index 549e4724a..9030b7b53 100755 --- a/lib/core/typeinfo.nim +++ b/lib/core/typeinfo.nim @@ -59,7 +59,7 @@ type rawType: PNimType ppointer = ptr pointer - pbyteArray = ptr array[0.. 0xffff, byte] + pbyteArray = ptr array[0.. 0xffff, int8] TGenSeq {.pure.} = object len, space: int diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim index 506da9c84..19701f896 100755 --- a/lib/impure/db_postgres.nim +++ b/lib/impure/db_postgres.nim @@ -84,7 +84,7 @@ proc setupQuery(db: TDbConn, query: TSqlQuery, result = PQExec(db, q) if PQresultStatus(result) != PGRES_TUPLES_OK: dbError(db) -proc setRow(res: PPGresult, r: var TRow, line, cols: int) = +proc setRow(res: PPGresult, r: var TRow, line, cols: int32) = for col in 0..cols-1: setLen(r[col], 0) var x = PQgetvalue(res, line, col) @@ -96,7 +96,7 @@ iterator FastRows*(db: TDbConn, query: TSqlQuery, ## fast, but potenially dangerous: If the for-loop-body executes another ## query, the results can be undefined. For Postgres it is safe though. var res = setupQuery(db, query, args) - var L = int(PQnfields(res)) + var L = PQnfields(res) var result = newRow(L) for i in 0..PQntuples(res)-1: setRow(res, result, i, L) @@ -107,7 +107,7 @@ proc getRow*(db: TDbConn, query: TSqlQuery, args: openarray[string]): TRow = ## retrieves a single row. var res = setupQuery(db, query, args) - var L = int(PQnfields(res)) + var L = PQnfields(res) result = newRow(L) setRow(res, result, 0, L) PQclear(res) diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim index b6c8003b9..dbeb1e594 100755 --- a/lib/impure/db_sqlite.nim +++ b/lib/impure/db_sqlite.nim @@ -64,7 +64,7 @@ proc TryExec*(db: TDbConn, query: TSqlQuery, ## tries to execute the query and returns true if successful, false otherwise. var q = dbFormat(query, args) var stmt: sqlite3.PStmt - if prepare_v2(db, q, q.len, stmt, nil) == SQLITE_OK: + if prepare_v2(db, q, q.len.cint, stmt, nil) == SQLITE_OK: if step(stmt) == SQLITE_DONE: result = finalize(stmt) == SQLITE_OK @@ -79,9 +79,9 @@ proc newRow(L: int): TRow = proc setupQuery(db: TDbConn, query: TSqlQuery, args: openarray[string]): PStmt = var q = dbFormat(query, args) - if prepare_v2(db, q, q.len, result, nil) != SQLITE_OK: dbError(db) + if prepare_v2(db, q, q.len.cint, result, nil) != SQLITE_OK: dbError(db) -proc setRow(stmt: PStmt, r: var TRow, cols: int) = +proc setRow(stmt: PStmt, r: var TRow, cols: cint) = for col in 0..cols-1: setLen(r[col], column_bytes(stmt, col)) # set capacity setLen(r[col], 0) @@ -94,7 +94,7 @@ iterator FastRows*(db: TDbConn, query: TSqlQuery, ## fast, but potenially dangerous: If the for-loop-body executes another ## query, the results can be undefined. For Sqlite it is safe though. var stmt = setupQuery(db, query, args) - var L = int(columnCount(stmt)) + var L = (columnCount(stmt)) var result = newRow(L) while step(stmt) == SQLITE_ROW: setRow(stmt, result, L) @@ -105,7 +105,7 @@ proc getRow*(db: TDbConn, query: TSqlQuery, args: openarray[string]): TRow = ## retrieves a single row. var stmt = setupQuery(db, query, args) - var L = int(columnCount(stmt)) + var L = (columnCount(stmt)) result = newRow(L) if step(stmt) == SQLITE_ROW: setRow(stmt, result, L) diff --git a/lib/impure/graphics.nim b/lib/impure/graphics.nim index 348907f9a..1392fd903 100755 --- a/lib/impure/graphics.nim +++ b/lib/impure/graphics.nim @@ -35,14 +35,15 @@ type proc toSdlColor*(c: TColor): Sdl.TColor = ## Convert colors.TColor to SDL.TColor var x = c.extractRGB - result.r = toU8(x.r) - result.g = toU8(x.g) - result.b = toU8(x.b) + result.r = x.r and 0xff + result.g = x.g and 0xff + result.b = x.b and 0xff proc createSdlColor*(sur: PSurface, c: TColor, alpha: int = 0): int32 = ## Creates a color using ``sdl.MapRGBA``. var x = c.extractRGB - return sdl.MapRGBA(sur.s.format, toU8(x.r), toU8(x.g), toU8(x.b), toU8(alpha)) + return sdl.MapRGBA(sur.s.format, x.r and 0xff, x.g and 0xff, + x.b and 0xff, alpha and 0xff) proc toSdlRect*(r: TRect): sdl.TRect = ## Convert ``graphics.TRect`` to ``sdl.TRect``. diff --git a/lib/impure/re.nim b/lib/impure/re.nim index 1fe1582bd..f3a6e5a44 100755 --- a/lib/impure/re.nim +++ b/lib/impure/re.nim @@ -82,7 +82,7 @@ proc matchOrFind(s: string, pattern: TRegEx, matches: var openarray[string], start, flags: cint): cint = var rawMatches: array[0..maxSubpatterns * 3 - 1, cint] - res = pcre.Exec(pattern.h, pattern.e, s, len(s), start, flags, + res = pcre.Exec(pattern.h, pattern.e, s, len(s).cint, start, flags, cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3) if res < 0'i32: return res for i in 1..int(res)-1: @@ -100,7 +100,7 @@ proc findBounds*(s: string, pattern: TRegEx, matches: var openarray[string], ## is written into `matches` and ``(-1,0)`` is returned. var rawMatches: array[0..maxSubpatterns * 3 - 1, cint] - res = pcre.Exec(pattern.h, pattern.e, s, len(s), start, 0'i32, + res = pcre.Exec(pattern.h, pattern.e, s, len(s).cint, start, 0'i32, cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3) if res < 0'i32: return (-1, 0) for i in 1..int(res)-1: @@ -119,7 +119,7 @@ proc findBounds*(s: string, pattern: TRegEx, ## ``(-1,0)`` is returned. var rawMatches: array[0..maxSubpatterns * 3 - 1, cint] - res = pcre.Exec(pattern.h, pattern.e, s, len(s), start, 0'i32, + res = pcre.Exec(pattern.h, pattern.e, s, len(s).cint, start, 0'i32, cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3) if res < 0'i32: return (-1, 0) for i in 1..int(res)-1: @@ -135,14 +135,14 @@ proc findBounds*(s: string, pattern: TRegEx, ## match, ``(-1,0)`` is returned. var rawMatches: array[0..3 - 1, cint] - res = pcre.Exec(pattern.h, nil, s, len(s), start, 0'i32, + res = pcre.Exec(pattern.h, nil, s, len(s).cint, start, 0'i32, cast[ptr cint](addr(rawMatches)), 3) if res < 0'i32: return (int(res), 0) return (int(rawMatches[0]), int(rawMatches[1]-1)) proc matchOrFind(s: string, pattern: TRegEx, start, flags: cint): cint = var rawMatches: array [0..maxSubpatterns * 3 - 1, cint] - result = pcre.Exec(pattern.h, pattern.e, s, len(s), start, flags, + result = pcre.Exec(pattern.h, pattern.e, s, len(s).cint, start, flags, cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3) if result >= 0'i32: result = rawMatches[1] - rawMatches[0] @@ -180,7 +180,7 @@ proc find*(s: string, pattern: TRegEx, matches: var openarray[string], ## is written into ``matches`` and -1 is returned. var rawMatches: array[0..maxSubpatterns * 3 - 1, cint] - res = pcre.Exec(pattern.h, pattern.e, s, len(s), start, 0'i32, + res = pcre.Exec(pattern.h, pattern.e, s, len(s).cint, start, 0'i32, cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3) if res < 0'i32: return res for i in 1..int(res)-1: @@ -195,7 +195,7 @@ proc find*(s: string, pattern: TRegEx, start = 0): int = ## match, -1 is returned. var rawMatches: array[0..3 - 1, cint] - res = pcre.Exec(pattern.h, nil, s, len(s), start, 0'i32, + res = pcre.Exec(pattern.h, nil, s, len(s).cint, start, 0'i32, cast[ptr cint](addr(rawMatches)), 3) if res < 0'i32: return res return rawMatches[0] @@ -205,7 +205,7 @@ iterator findAll*(s: string, pattern: TRegEx, start = 0): string = var i = int32(start) var rawMatches: array[0..maxSubpatterns * 3 - 1, cint] while true: - let res = pcre.Exec(pattern.h, pattern.e, s, len(s), i, 0'i32, + let res = pcre.Exec(pattern.h, pattern.e, s, len(s).cint, i, 0'i32, cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3) if res < 0'i32: break let a = rawMatches[0] diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim index b84c3d53e..0fd1d8cd2 100644 --- a/lib/pure/oids.nim +++ b/lib/pure/oids.nim @@ -53,7 +53,8 @@ proc oidToString*(oid: TOid, str: cstring) = str[24] = '\0' var - incr, fuzz: int + incr: int + fuzz: int32 proc genOid*(): TOid = ## generates a new OID. diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 808c0735e..6ed7e8d2c 100755 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -244,7 +244,7 @@ when defined(Windows) and not defined(useNimRtl): var s = PFileHandleStream(s) if s.atTheEnd: return 0 var br: int32 - var a = winlean.ReadFile(s.handle, buffer, bufLen, br, nil) + var a = winlean.ReadFile(s.handle, buffer, bufLen.cint, br, nil) # TRUE and zero bytes returned (EOF). # TRUE and n (>0) bytes returned (good data). # FALSE and bytes returned undefined (system error). @@ -255,7 +255,7 @@ when defined(Windows) and not defined(useNimRtl): 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) + var a = winlean.writeFile(s.handle, buffer, bufLen.cint, bytesWritten, nil) if a == 0: OSError() proc newFileHandleStream(handle: THandle): PFileHandleStream = @@ -293,7 +293,7 @@ when defined(Windows) and not defined(useNimRtl): proc CreatePipeHandles(Rdhandle, WrHandle: var THandle) = var piInheritablePipe: TSecurityAttributes - piInheritablePipe.nlength = SizeOF(TSecurityAttributes) + piInheritablePipe.nlength = SizeOF(TSecurityAttributes).cint piInheritablePipe.lpSecurityDescriptor = nil piInheritablePipe.Binherithandle = 1 if CreatePipe(Rdhandle, Wrhandle, piInheritablePipe, 1024) == 0'i32: @@ -313,7 +313,7 @@ when defined(Windows) and not defined(useNimRtl): success: int hi, ho, he: THandle new(result) - SI.cb = SizeOf(SI) + SI.cb = SizeOf(SI).cint if poParentStreams notin options: SI.dwFlags = STARTF_USESTDHANDLES # STARTF_USESHOWWINDOW or CreatePipeHandles(SI.hStdInput, HI) @@ -323,16 +323,16 @@ when defined(Windows) and not defined(useNimRtl): HE = HO else: CreatePipeHandles(HE, Si.hStdError) - result.inputHandle = hi - result.outputHandle = ho - result.errorHandle = he + result.inputHandle = TFileHandle(hi) + result.outputHandle = TFileHandle(ho) + result.errorHandle = TFileHandle(he) else: SI.hStdError = GetStdHandle(STD_ERROR_HANDLE) SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE) SI.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE) - result.inputHandle = si.hStdInput - result.outputHandle = si.hStdOutput - result.errorHandle = si.hStdError + result.inputHandle = TFileHandle(si.hStdInput) + result.outputHandle = TFileHandle(si.hStdOutput) + result.errorHandle = TFileHandle(si.hStdError) var cmdl: cstring when false: # poUseShell in options: @@ -394,7 +394,7 @@ when defined(Windows) and not defined(useNimRtl): discard TerminateProcess(p.FProcessHandle, 0) proc waitForExit(p: PProcess, timeout: int = -1): int = - discard WaitForSingleObject(p.FProcessHandle, timeout) + discard WaitForSingleObject(p.FProcessHandle, timeout.int32) var res: int32 discard GetExitCodeProcess(p.FProcessHandle, res) @@ -424,7 +424,7 @@ when defined(Windows) and not defined(useNimRtl): ProcInfo: TProcessInformation process: THandle L: int32 - SI.cb = SizeOf(SI) + SI.cb = SizeOf(SI).cint SI.hStdError = GetStdHandle(STD_ERROR_HANDLE) SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE) SI.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE) @@ -454,7 +454,7 @@ when defined(Windows) and not defined(useNimRtl): for i in 0..readfds.len()-1: rfds[i] = readfds[i].FProcessHandle - var ret = waitForMultipleObjects(readfds.len, + var ret = waitForMultipleObjects(readfds.len.int32, addr(rfds), 0'i32, timeout) case ret of WAIT_TIMEOUT: diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index 8c15c6adb..162e644d9 100755 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -343,7 +343,7 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") = name.sin_port = sockets.htons(int16(port)) name.sin_addr.s_addr = sockets.htonl(INADDR_ANY) if bindSocket(socket.fd, cast[ptr TSockAddr](addr(name)), - sizeof(name)) < 0'i32: + sizeof(name).TSockLen) < 0'i32: OSError() else: var hints: TAddrInfo @@ -366,7 +366,7 @@ when false: name.sin_port = sockets.htons(int16(port)) name.sin_addr.s_addr = sockets.htonl(INADDR_ANY) if bindSocket(cint(socket), cast[ptr TSockAddr](addr(name)), - sizeof(name)) < 0'i32: + sizeof(name).TSockLen) < 0'i32: OSError() proc getSockName*(socket: TSocket): TPort = @@ -378,7 +378,7 @@ proc getSockName*(socket: TSocket): TPort = name.sin_family = posix.AF_INET #name.sin_port = htons(cint16(port)) #name.sin_addr.s_addr = htonl(INADDR_ANY) - var namelen: cint = sizeof(name) + var namelen = sizeof(name).TSockLen if getsockname(socket.fd, cast[ptr TSockAddr](addr(name)), addr(namelen)) == -1'i32: OSError() @@ -398,7 +398,7 @@ proc acceptAddr*(server: TSocket): tuple[client: TSocket, address: string] = ## **Warning:** This function might block even if socket is non-blocking ## when using SSL. var sockAddress: Tsockaddr_in - var addrLen: cint = sizeof(sockAddress) + var addrLen = sizeof(sockAddress).TSockLen var sock = accept(server.fd, cast[ptr TSockAddr](addr(sockAddress)), addr(addrLen)) @@ -477,9 +477,9 @@ proc getServByName*(name, proto: string): TServent = proc getServByPort*(port: TPort, proto: string): TServent = ## well-known getservbyport proc. when defined(Windows): - var s = winlean.getservbyport(ze(int16(port)), proto) + var s = winlean.getservbyport(ze(int16(port)).cint, proto) else: - var s = posix.getservbyport(ze(int16(port)), proto) + var s = posix.getservbyport(ze(int16(port)).cint, proto) if s == nil: OSError() result.name = $s.s_name result.aliases = cstringArrayToSeq(s.s_aliases) @@ -492,11 +492,11 @@ proc getHostByAddr*(ip: string): THostEnt = myaddr.s_addr = inet_addr(ip) when defined(windows): - var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr), + var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cint, cint(sockets.AF_INET)) if s == nil: OSError() else: - var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr), + var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).cint, cint(posix.AF_INET)) if s == nil: raise newException(EOS, $hStrError(h_errno)) @@ -539,7 +539,7 @@ proc getHostByName*(name: string): THostEnt = proc getSockOptInt*(socket: TSocket, level, optname: int): int = ## getsockopt for integer options. var res: cint - var size: cint = sizeof(res) + var size = sizeof(res).cint if getsockopt(socket.fd, cint(level), cint(optname), addr(res), addr(size)) < 0'i32: OSError() @@ -549,7 +549,7 @@ proc setSockOptInt*(socket: TSocket, level, optname, optval: int) = ## setsockopt for integer options. var value = cint(optval) if setsockopt(socket.fd, cint(level), cint(optname), addr(value), - sizeof(value)) < 0'i32: + sizeof(value).cint) < 0'i32: OSError() proc connect*(socket: TSocket, name: string, port = TPort(0), @@ -608,7 +608,7 @@ proc connect*(socket: TSocket, name: string, port = TPort(0), of AF_INET: s.sin_family = posix.AF_INET of AF_INET6: s.sin_family = posix.AF_INET6 else: nil - if connect(socket.fd, cast[ptr TSockAddr](addr(s)), sizeof(s)) < 0'i32: + if connect(socket.fd, cast[ptr TSockAddr](addr(s)), sizeof(s).cint) < 0'i32: OSError() proc connectAsync*(socket: TSocket, name: string, port = TPort(0), diff --git a/lib/pure/times.nim b/lib/pure/times.nim index e6163ad8c..622c2655f 100755 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -111,7 +111,7 @@ type ## in the range 0 to 23. monthday*: range[1..31] ## The day of the month, in the range 1 to 31. month*: TMonth ## The current month. - year*: int ## The current year. + year*: range[-10_000..10_000] ## The current year. weekday*: TWeekDay ## The current day of the week. yearday*: range[0..365] ## The number of days since January 1, ## in the range 0 to 365. @@ -122,7 +122,7 @@ type timezone*: int ## The offset of the (non-DST) timezone in seconds ## west of UTC. - TTimeInterval* = object + TTimeInterval* {.pure.} = object ## a time interval miliseconds*: int ## The number of miliseconds seconds*: int ## The number of seconds minutes*: int ## The number of minutes @@ -150,11 +150,11 @@ proc `$` *(timeInfo: TTimeInfo): string proc `$` *(time: TTime): string ## converts a calendar time to a string representation. -proc `-` *(a, b: TTime): int64{. +proc `-`*(a, b: TTime): int64 {. rtl, extern: "ntDiffTime".} ## computes the difference of two calendar times. Result is in seconds. -proc `<` * (a, b: TTime): bool {. +proc `<`*(a, b: TTime): bool {. rtl, extern: "ntLtTime".} = ## returns true iff ``a < b``, that is iff a happened before b. result = a - b < 0 @@ -175,8 +175,8 @@ proc getStartMilsecs*(): int {.deprecated.} ## get the miliseconds from the start of the program. **Deprecated since ## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead. -proc newInterval*(miliseconds, seconds, minutes, hours, days, months, - years: int = 0): TTimeInterval = +proc initInterval*(miliseconds, seconds, minutes, hours, days, months, + years: int = 0): TTimeInterval = ## creates a new ``TTimeInterval``. result.miliseconds = miliseconds result.seconds = seconds @@ -188,23 +188,20 @@ proc newInterval*(miliseconds, seconds, minutes, hours, days, months, proc isLeapYear(year: int): bool = if year mod 400 == 0: - return true + return true elif year mod 100 == 0: - return false + return false elif year mod 4 == 0: - return true + return true else: - return false + return false proc getDaysInMonth(month: TMonth, year: int): int = # http://www.dispersiondesign.com/articles/time/number_of_days_in_a_month - if month == mFeb: # Feb - if isLeapYear(year): - result = 29 - else: - result = 28 - elif month in [mApr, mJun, mSep, mNov]: result = 30 - else: result = 31 + case month + of mFeb: result = if isLeapYear(year): 29 else: 28 + of mApr, mJun, mSep, mNov: result = 30 + else: result = 31 proc calculateSeconds(a: TTimeInfo, interval: TTimeInterval): float = var anew = a @@ -228,9 +225,10 @@ proc calculateSeconds(a: TTimeInfo, interval: TTimeInterval): float = proc `+`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo = ## adds ``interval`` time. ## - ## **Note:** This has been only briefly tested and it may not be very accurate. + ## **Note:** This has been only briefly tested and it may not be + ## very accurate. let t = timeInfoToTime(a) - var secs = calculateSeconds(a, interval) + let secs = calculateSeconds(a, interval) if a.tzname == "UTC": result = getGMTime(TTime(float(t) + secs)) else: @@ -242,7 +240,7 @@ proc `-`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo = ## **Note:** This has been only briefly tested, it is inaccurate especially ## when you subtract so much that you reach the Julian calendar. let t = timeInfoToTime(a) - var secs = calculateSeconds(a, interval) + let secs = calculateSeconds(a, interval) if a.tzname == "UTC": result = getGMTime(TTime(float(t) - secs)) else: @@ -329,7 +327,7 @@ when not defined(ECMAScript): proc timeInfoToTM(t: TTimeInfo): structTM = const - weekDays: array [TWeekDay, int] = [1, 2, 3, 4, 5, 6, 0] + weekDays: array [TWeekDay, int8] = [1'i8,2'i8,3'i8,4'i8,5'i8,6'i8,0'i8] result.second = t.second result.minute = t.minute result.hour = t.hour @@ -362,13 +360,13 @@ when not defined(ECMAScript): var a = t result = tmToTimeInfo(localtime(addr(a))[], true) # copying is needed anyway to provide reentrancity; thus - # the convertion is not expensive + # the conversion is not expensive proc getGMTime(t: TTime): TTimeInfo = var a = t result = tmToTimeInfo(gmtime(addr(a))[], false) # copying is needed anyway to provide reentrancity; thus - # the convertion is not expensive + # the conversion is not expensive proc TimeInfoToTime(timeInfo: TTimeInfo): TTime = var cTimeInfo = timeInfo # for C++ we have to make a copy, diff --git a/lib/system.nim b/lib/system.nim index e90ca56e1..69733d6a1 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -182,8 +182,8 @@ when not defined(EcmaScript) and not defined(NimrodVM): include "system/hti" type - Byte* = Int8 ## this is an alias for ``int8``, that is a signed - ## int 8 bits wide. + Byte* = uInt8 ## this is an alias for ``uint8``, that is an unsigned + ## int 8 bits wide. Natural* = range[0..high(int)] ## is an int type ranging from zero to the maximum value @@ -967,7 +967,7 @@ type type # these work for most platforms: cchar* {.importc: "char", nodecl.} = char ## This is the same as the type ``char`` in *C*. - cschar* {.importc: "signed char", nodecl.} = byte + cschar* {.importc: "signed char", nodecl.} = int8 ## This is the same as the type ``signed char`` in *C*. cshort* {.importc: "short", nodecl.} = int16 ## This is the same as the type ``short`` in *C*. @@ -1156,6 +1156,10 @@ proc `$` *(x: int64): string {.magic: "Int64ToStr", noSideEffect.} ## The stingify operator for an integer argument. Returns `x` ## converted to a decimal string. +proc `$` *(x: uint64): string {.noSideEffect.} + ## The stingify operator for an unsigned integer argument. Returns `x` + ## converted to a decimal string. + proc `$` *(x: float): string {.magic: "FloatToStr", noSideEffect.} ## The stingify operator for a float argument. Returns `x` ## converted to a decimal string. @@ -1177,7 +1181,7 @@ proc `$` *(x: string): string {.magic: "StrToStr", noSideEffect.} ## as it is. This operator is useful for generic code, so ## that ``$expr`` also works if ``expr`` is already a string. -proc `$` *[T](x: ordinal[T]): string {.magic: "EnumToStr", noSideEffect.} +proc `$` *[TEnum: enum](x: TEnum): string {.magic: "EnumToStr", noSideEffect.} ## The stingify operator for an enumeration argument. This works for ## any enumeration type thanks to compiler magic. If ## a ``$`` operator for a concrete enumeration is provided, this is @@ -1850,7 +1854,7 @@ when not defined(EcmaScript) and not defined(NimrodVM): proc getFileSize*(f: TFile): int64 ## retrieves the file size (in bytes) of `f`. - proc ReadBytes*(f: TFile, a: var openarray[byte], start, len: int): int + proc ReadBytes*(f: TFile, a: var openarray[int8], start, len: int): int ## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns ## the actual number of bytes that have been read which may be less than ## `len` (if not as many bytes are remaining), but not greater. @@ -1865,7 +1869,7 @@ when not defined(EcmaScript) and not defined(NimrodVM): ## the actual number of bytes that have been read which may be less than ## `len` (if not as many bytes are remaining), but not greater. - proc writeBytes*(f: TFile, a: openarray[byte], start, len: int): int + proc writeBytes*(f: TFile, a: openarray[int8], start, len: int): int ## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns ## the number of actual written bytes, which may be less than `len` in case ## of an error. diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 3376b9413..7c2c234c2 100755 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -71,7 +71,8 @@ proc c_fopen(filename, mode: cstring): C_TextFileStar {. importc: "fopen", nodecl.} proc c_fclose(f: C_TextFileStar) {.importc: "fclose", nodecl.} -proc c_sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs.} +proc c_sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs, + noSideEffect.} # we use it only in a way that cannot lead to security issues proc c_fread(buf: Pointer, size, n: int, f: C_BinaryFileStar): int {. diff --git a/lib/system/repr.nim b/lib/system/repr.nim index 83fa7aa1d..028887b4c 100755 --- a/lib/system/repr.nim +++ b/lib/system/repr.nim @@ -20,6 +20,11 @@ proc reprPointer(x: pointer): string {.compilerproc.} = c_sprintf(buf, "%p", x) return $buf +proc `$`(x: uint64): string = + var buf: array [0..59, char] + c_sprintf(buf, "%llu", x) + return $buf + proc reprStrAux(result: var string, s: string) = if cast[pointer](s) == nil: add result, "nil" @@ -67,7 +72,7 @@ proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} = result = $e & " (invalid data!)" type - pbyteArray = ptr array[0.. 0xffff, byte] + pbyteArray = ptr array[0.. 0xffff, int8] proc addSetElem(result: var string, elem: int, typ: PNimType) = case typ.kind diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index ac0880f79..d5234e62f 100755 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -222,17 +222,17 @@ proc fwrite(buf: Pointer, size, n: int, f: TFile): int {. proc readBuffer(f: TFile, buffer: pointer, len: int): int = result = fread(buffer, 1, len, f) -proc ReadBytes(f: TFile, a: var openarray[byte], start, len: int): int = +proc ReadBytes(f: TFile, a: var openarray[int8], start, len: int): int = result = readBuffer(f, addr(a[start]), len) proc ReadChars(f: TFile, a: var openarray[char], start, len: int): int = result = readBuffer(f, addr(a[start]), len) -proc writeBytes(f: TFile, a: openarray[byte], start, len: int): int = - var x = cast[ptr array[0..1000_000_000, byte]](a) +proc writeBytes(f: TFile, a: openarray[int8], start, len: int): int = + var x = cast[ptr array[0..1000_000_000, int8]](a) result = writeBuffer(f, addr(x[start]), len) proc writeChars(f: TFile, a: openarray[char], start, len: int): int = - var x = cast[ptr array[0..1000_000_000, byte]](a) + var x = cast[ptr array[0..1000_000_000, int8]](a) result = writeBuffer(f, addr(x[start]), len) proc writeBuffer(f: TFile, buffer: pointer, len: int): int = result = fwrite(buffer, 1, len, f) diff --git a/lib/windows/windows.nim b/lib/windows/windows.nim index d3ff5ad91..ff28ab255 100755 --- a/lib/windows/windows.nim +++ b/lib/windows/windows.nim @@ -13,8 +13,8 @@ {.deadCodeElim: on.} type - WideChar* = int16 - PWideChar* = ptr int16 + WideChar* = uint16 + PWideChar* = ptr uint16 type # WinNT.h -- Defines the 32-Bit Windows types and constants SHORT* = int16 @@ -72,7 +72,6 @@ type # WinDef.h -- Basic Windows Type Definitions DWORD* = int32 WINBOOL* = int32 - BYTE* = char WORD* = int16 # FLOAT* = float PFLOAT* = ptr FLOAT @@ -296,13 +295,13 @@ type when defined(winUnicode): type - PTBYTE* = ptr int16 + PTBYTE* = ptr uint16 PTCH* = PWideChar PTCHAR* = PWideChar PTSTR* = PWideChar else: type - PTBYTE* = ptr int8 + PTBYTE* = ptr byte PTCH* = cstring PTCHAR* = cstring PTSTR* = cstring @@ -316,12 +315,12 @@ type when defined(winUnicode): type - TBYTE* = int16 + TBYTE* = uint16 TCHAR* = widechar BCHAR* = int16 else: type - TBYTE* = int8 + TBYTE* = uint8 TCHAR* = char BCHAR* = int8 type @@ -7432,34 +7431,34 @@ type PDCB* = ptr DCB const - bm_DCB_fBinary* = 0x00000001 - bp_DCB_fBinary* = 0 + bm_DCB_fBinary* = 1 + bp_DCB_fBinary* = 0'i32 bm_DCB_fParity* = 0x00000002 - bp_DCB_fParity* = 1 + bp_DCB_fParity* = 1'i32 bm_DCB_fOutxCtsFlow* = 0x00000004 - bp_DCB_fOutxCtsFlow* = 2 + bp_DCB_fOutxCtsFlow* = 2'i32 bm_DCB_fOutxDsrFlow* = 0x00000008 - bp_DCB_fOutxDsrFlow* = 3 + bp_DCB_fOutxDsrFlow* = 3'i32 bm_DCB_fDtrControl* = 0x00000030 - bp_DCB_fDtrControl* = 4 + bp_DCB_fDtrControl* = 4'i32 bm_DCB_fDsrSensitivity* = 0x00000040 - bp_DCB_fDsrSensitivity* = 6 + bp_DCB_fDsrSensitivity* = 6'i32 bm_DCB_fTXContinueOnXoff* = 0x00000080 - bp_DCB_fTXContinueOnXoff* = 7 + bp_DCB_fTXContinueOnXoff* = 7'i32 bm_DCB_fOutX* = 0x00000100 - bp_DCB_fOutX* = 8 + bp_DCB_fOutX* = 8'i32 bm_DCB_fInX* = 0x00000200 - bp_DCB_fInX* = 9 + bp_DCB_fInX* = 9'i32 bm_DCB_fErrorChar* = 0x00000400 - bp_DCB_fErrorChar* = 10 + bp_DCB_fErrorChar* = 10'i32 bm_DCB_fNull* = 0x00000800 - bp_DCB_fNull* = 11 + bp_DCB_fNull* = 11'i32 bm_DCB_fRtsControl* = 0x00003000 - bp_DCB_fRtsControl* = 12 + bp_DCB_fRtsControl* = 12'i32 bm_DCB_fAbortOnError* = 0x00004000 - bp_DCB_fAbortOnError* = 14 + bp_DCB_fAbortOnError* = 14'i32 bm_DCB_fDummy2* = 0xFFFF8000'i32 - bp_DCB_fDummy2* = 15 + bp_DCB_fDummy2* = 15'i32 proc fBinary*(a: var DCB): DWORD proc set_fBinary*(a: var DCB, fBinary: DWORD) @@ -7575,21 +7574,21 @@ type const bm_COMSTAT_fCtsHold* = 0x00000001 - bp_COMSTAT_fCtsHold* = 0 + bp_COMSTAT_fCtsHold* = 0'i32 bm_COMSTAT_fDsrHold* = 0x00000002 - bp_COMSTAT_fDsrHold* = 1 + bp_COMSTAT_fDsrHold* = 1'i32 bm_COMSTAT_fRlsdHold* = 0x00000004 - bp_COMSTAT_fRlsdHold* = 2 + bp_COMSTAT_fRlsdHold* = 2'i32 bm_COMSTAT_fXoffHold* = 0x00000008 - bp_COMSTAT_fXoffHold* = 3 + bp_COMSTAT_fXoffHold* = 3'i32 bm_COMSTAT_fXoffSent* = 0x00000010 - bp_COMSTAT_fXoffSent* = 4 + bp_COMSTAT_fXoffSent* = 4'i32 bm_COMSTAT_fEof* = 0x00000020 - bp_COMSTAT_fEof* = 5 + bp_COMSTAT_fEof* = 5'i32 bm_COMSTAT_fTxim* = 0x00000040 - bp_COMSTAT_fTxim* = 6 + bp_COMSTAT_fTxim* = 6'i32 bm_COMSTAT_fReserved* = 0xFFFFFF80'i32 - bp_COMSTAT_fReserved* = 7 + bp_COMSTAT_fReserved* = 7'i32 proc fCtsHold*(a: var COMSTAT): DWORD # should be renamed to get_<x>? @@ -9984,25 +9983,25 @@ type const bm_LDT_ENTRY_BaseMid* = 0x000000FF - bp_LDT_ENTRY_BaseMid* = 0 + bp_LDT_ENTRY_BaseMid* = 0'i32 bm_LDT_ENTRY_Type* = 0x00001F00 - bp_LDT_ENTRY_Type* = 8 + bp_LDT_ENTRY_Type* = 8'i32 bm_LDT_ENTRY_Dpl* = 0x00006000 - bp_LDT_ENTRY_Dpl* = 13 + bp_LDT_ENTRY_Dpl* = 13'i32 bm_LDT_ENTRY_Pres* = 0x00008000 - bp_LDT_ENTRY_Pres* = 15 + bp_LDT_ENTRY_Pres* = 15'i32 bm_LDT_ENTRY_LimitHi* = 0x000F0000 - bp_LDT_ENTRY_LimitHi* = 16 + bp_LDT_ENTRY_LimitHi* = 16'i32 bm_LDT_ENTRY_Sys* = 0x00100000 - bp_LDT_ENTRY_Sys* = 20 + bp_LDT_ENTRY_Sys* = 20'i32 bm_LDT_ENTRY_Reserved_0* = 0x00200000 - bp_LDT_ENTRY_Reserved_0* = 21 + bp_LDT_ENTRY_Reserved_0* = 21'i32 bm_LDT_ENTRY_Default_Big* = 0x00400000 - bp_LDT_ENTRY_Default_Big* = 22 + bp_LDT_ENTRY_Default_Big* = 22'i32 bm_LDT_ENTRY_Granularity* = 0x00800000 - bp_LDT_ENTRY_Granularity* = 23 + bp_LDT_ENTRY_Granularity* = 23'i32 bm_LDT_ENTRY_BaseHi* = 0xFF000000 - bp_LDT_ENTRY_BaseHi* = 24 + bp_LDT_ENTRY_BaseHi* = 24'i32 type LOCALESIGNATURE* {.final, pure.} = object @@ -22820,7 +22819,7 @@ proc SEXT_HIWORD*(L: int32): int32 = proc ZEXT_HIWORD*(L: int32): int32 = # return type might be wrong - result = ze(HIWORD(L)) + result = HIWORD(L) and 0xffff'i32 proc SEXT_LOWORD*(L: int32): int32 = result = LOWORD(L) @@ -22869,13 +22868,13 @@ proc MAKEWPARAM*(L, h: int32): WPARAM = result = WPARAM(MAKELONG(L, h)) proc GET_X_LPARAM*(lp: Windows.LParam): int32 = - result = int16(LOWORD(lp)) + result = LOWORD(lp.int32) proc GET_Y_LPARAM*(lp: Windows.LParam): int32 = - result = int16(HIWORD(lp)) + result = HIWORD(lp.int32) proc UNICODE_NULL*(): WCHAR = - result = 0'i16 + result = 0'u16 @@ -23500,7 +23499,8 @@ proc ListView_EnsureVisible(hwndLV: HWND, i, fPartialOK: int32): LRESULT = MAKELPARAM(fPartialOK, 0)) proc ListView_FindItem(wnd: HWND, iStart: int32, lvfi: var LV_FINDINFO): int32 = - result = SendMessage(wnd, LVM_FINDITEM, WPARAM(iStart), cast[LPARAM](addr(lvfi))) + result = SendMessage(wnd, LVM_FINDITEM, WPARAM(iStart), + cast[LPARAM](addr(lvfi))).int32 proc ListView_GetBkColor(wnd: HWND): LRESULT = result = SendMessage(wnd, LVM_GETBKCOLOR, 0, 0) @@ -23534,7 +23534,7 @@ proc ListView_GetItemCount(wnd: HWND): LRESULT = proc ListView_GetItemPosition(hwndLV: HWND, i: int32, pt: var POINT): int32 = result = SendMessage(hwndLV, LVM_GETITEMPOSITION, WPARAM(int32(i)), - cast[LPARAM](addr(pt))) + cast[LPARAM](addr(pt))).int32 proc ListView_GetItemSpacing(hwndLV: HWND, fSmall: int32): LRESULT = result = SendMessage(hwndLV, LVM_GETITEMSPACING, fSmall, 0) @@ -23878,10 +23878,10 @@ proc GetLargestConsoleWindowSize(hConsoleOutput: HANDLE): COORD = result.x = toU16(res shr 16) proc Succeeded(Status: HRESULT): WINBOOL = - result = (Status and 0x80000000'i32) + result = (Status and 0x80000000).WinBool proc Failed(Status: HRESULT): WINBOOL = - result = (Status and 0x80000000'i32) + result = (Status and 0x80000000).WinBool proc IsError(Status: HRESULT): WINBOOL = result = ord((int(Status) shr 31) == SEVERITY_ERROR) @@ -23920,7 +23920,7 @@ proc MAKELCID(LangId, SortId: int16): DWORD = result = toU32((ze(SortId) shl 16) or ze(LangId)) proc MAKESORTLCID(LangId, SortId, SortVersion: int16): DWORD = - result = MAKELCID(LangId, SortId) or int(SortVersion shl 20'i32) + result = MAKELCID(LangId, SortId) or (SortVersion shl 20'i32) proc LANGIDFROMLCID(LocaleId: LCID): int16 = result = toU16(LocaleId) diff --git a/lib/wrappers/gtk/gtk2.nim b/lib/wrappers/gtk/gtk2.nim index 9f455e5ba..515b65002 100755 --- a/lib/wrappers/gtk/gtk2.nim +++ b/lib/wrappers/gtk/gtk2.nim @@ -16257,7 +16257,7 @@ proc COLUMN_REQUESTED_WIDTH*(column: PTreeViewColumn): int32 = MaxWidth = column.max_width else: MaxWidth = column.requested_width - result = CLAMP(column.requested_width, MinWidth, MaxWidth) + result = CLAMP(column.requested_width, MinWidth, MaxWidth).int32 proc DRAW_EXPANDERS*(tree_view: PTreeView): bool = result = (not (FLAG_SET(tree_view, TREE_VIEW_IS_LIST))) and diff --git a/lib/wrappers/gtk/pango.nim b/lib/wrappers/gtk/pango.nim index cc6acb005..5d9fcd96f 100755 --- a/lib/wrappers/gtk/pango.nim +++ b/lib/wrappers/gtk/pango.nim @@ -878,10 +878,10 @@ proc get_tab*(tab_array: PTabArray, tab_index: gint, proc get_positions_in_pixels*(tab_array: PTabArray): gboolean{.cdecl, dynlib: lib, importc: "pango_tab_array_get_positions_in_pixels".} proc ASCENT*(rect: TRectangle): int32 = - result = - int(rect.y) + result = -rect.y proc DESCENT*(rect: TRectangle): int32 = - result = int(rect.y) + int(rect.height) + result = (rect.y) + (rect.height) proc LBEARING*(rect: TRectangle): int32 = result = rect.x diff --git a/lib/wrappers/sdl/sdl.nim b/lib/wrappers/sdl/sdl.nim index a48cb59ef..597a9b0b0 100755 --- a/lib/wrappers/sdl/sdl.nim +++ b/lib/wrappers/sdl/sdl.nim @@ -280,9 +280,9 @@ else: const LibName = "libSDL.so(|.1|.0)" const - MAJOR_VERSION* = 1'i8 - MINOR_VERSION* = 2'i8 - PATCHLEVEL* = 11'i8 # SDL.h constants + MAJOR_VERSION* = 1 + MINOR_VERSION* = 2 + PATCHLEVEL* = 11 # SDL.h constants INIT_TIMER* = 0x00000001 INIT_AUDIO* = 0x00000010 INIT_VIDEO* = 0x00000020 @@ -2523,8 +2523,8 @@ proc AllocSurface(flags: int32, width, height, depth: int, AMask) proc MustLock(Surface: PSurface): bool = - Result = ((surface[] .offset != 0) or - ((surface[] .flags and (HWSURFACE or ASYNCBLIT or RLEACCEL)) != 0)) + Result = ((surface[].offset != 0) or + ((surface[].flags and (HWSURFACE or ASYNCBLIT or RLEACCEL)) != 0)) proc LockMutex(mutex: Pmutex): int = Result = mutexP(mutex) diff --git a/lib/wrappers/sdl/sdl_image.nim b/lib/wrappers/sdl/sdl_image.nim index cc770a07f..7df9aedd4 100755 --- a/lib/wrappers/sdl/sdl_image.nim +++ b/lib/wrappers/sdl/sdl_image.nim @@ -141,9 +141,9 @@ else: const ImageLibName = "libSDL_image.so" const - IMAGE_MAJOR_VERSION* = 1'i8 - IMAGE_MINOR_VERSION* = 2'i8 - IMAGE_PATCHLEVEL* = 5'i8 + IMAGE_MAJOR_VERSION* = 1 + IMAGE_MINOR_VERSION* = 2 + IMAGE_PATCHLEVEL* = 5 # This macro can be used to fill a version structure with the compile-time # version of the SDL_image library. diff --git a/lib/wrappers/sdl/sdl_mixer.nim b/lib/wrappers/sdl/sdl_mixer.nim index 09abe182f..9199a9271 100755 --- a/lib/wrappers/sdl/sdl_mixer.nim +++ b/lib/wrappers/sdl/sdl_mixer.nim @@ -161,9 +161,9 @@ else: const MixerLibName = "libSDL_mixer.so" const - MAJOR_VERSION* = 1'i8 - MINOR_VERSION* = 2'i8 - PATCHLEVEL* = 7'i8 # Backwards compatibility + MAJOR_VERSION* = 1 + MINOR_VERSION* = 2 + PATCHLEVEL* = 7 # Backwards compatibility CHANNELS* = 8 # Good default values for a PC soundcard DEFAULT_FREQUENCY* = 22050 diff --git a/lib/wrappers/sdl/sdl_mixer_nosmpeg.nim b/lib/wrappers/sdl/sdl_mixer_nosmpeg.nim index 885e9845b..11f00e0a7 100755 --- a/lib/wrappers/sdl/sdl_mixer_nosmpeg.nim +++ b/lib/wrappers/sdl/sdl_mixer_nosmpeg.nim @@ -15,9 +15,9 @@ else: const MixerLibName = "libSDL_mixer.so" const - MAJOR_VERSION* = 1'i8 - MINOR_VERSION* = 2'i8 - PATCHLEVEL* = 7'i8 # Backwards compatibility + MAJOR_VERSION* = 1 + MINOR_VERSION* = 2 + PATCHLEVEL* = 7 # Backwards compatibility CHANNELS* = 8 # Good default values for a PC soundcard DEFAULT_FREQUENCY* = 22050 diff --git a/lib/wrappers/sdl/sdl_net.nim b/lib/wrappers/sdl/sdl_net.nim index bfd4f0a28..742a59314 100755 --- a/lib/wrappers/sdl/sdl_net.nim +++ b/lib/wrappers/sdl/sdl_net.nim @@ -122,9 +122,9 @@ else: const NetLibName = "libSDL_net.so" const #* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL * - MAJOR_VERSION* = 1'i8 - MINOR_VERSION* = 2'i8 - PATCHLEVEL* = 5'i8 # SDL_Net.h constants + MAJOR_VERSION* = 1 + MINOR_VERSION* = 2 + PATCHLEVEL* = 5 # SDL_Net.h constants #* Resolve a host name and port to an IP address in network form. # If the function succeeds, it will return 0. # If the host couldn't be resolved, the host portion of the returned diff --git a/lib/wrappers/sdl/sdl_ttf.nim b/lib/wrappers/sdl/sdl_ttf.nim index dd65af275..f501e31d8 100755 --- a/lib/wrappers/sdl/sdl_ttf.nim +++ b/lib/wrappers/sdl/sdl_ttf.nim @@ -165,9 +165,9 @@ else: const ttfLibName = "libSDL_ttf.so(|.1|.0)" const - MAJOR_VERSION* = 2'i8 - MINOR_VERSION* = 0'i8 - PATCHLEVEL* = 8'i8 # Backwards compatibility + MAJOR_VERSION* = 2 + MINOR_VERSION* = 0 + PATCHLEVEL* = 8 # Backwards compatibility STYLE_NORMAL* = 0x00000000 STYLE_BOLD* = 0x00000001 diff --git a/lib/wrappers/sdl/smpeg.nim b/lib/wrappers/sdl/smpeg.nim index a836379ac..33f317631 100755 --- a/lib/wrappers/sdl/smpeg.nim +++ b/lib/wrappers/sdl/smpeg.nim @@ -171,9 +171,9 @@ proc filter_deblocking*(): PFilter{.cdecl, # SMPEG.h #------------------------------------------------------------------------------ const - MAJOR_VERSION* = 0'i8 - MINOR_VERSION* = 4'i8 - PATCHLEVEL* = 2'i8 + MAJOR_VERSION* = 0 + MINOR_VERSION* = 4 + PATCHLEVEL* = 2 type TVersion*{.final.} = object diff --git a/lib/wrappers/zip/zlib.nim b/lib/wrappers/zip/zlib.nim index 9b49b9663..de52a06e1 100755 --- a/lib/wrappers/zip/zlib.nim +++ b/lib/wrappers/zip/zlib.nim @@ -160,19 +160,20 @@ proc inflateSyncPoint*(z: PZstream): int32{.cdecl, dynlib: libz, proc get_crc_table*(): pointer{.cdecl, dynlib: libz, importc: "get_crc_table".} proc deflateInit(strm: var TZStream, level: int32): int32 = - result = deflateInitu(strm, level, ZLIB_VERSION(), sizeof(TZStream)) + result = deflateInitu(strm, level, ZLIB_VERSION(), sizeof(TZStream).cint) proc inflateInit(strm: var TZStream): int32 = - result = inflateInitu(strm, ZLIB_VERSION(), sizeof(TZStream)) + result = inflateInitu(strm, ZLIB_VERSION(), sizeof(TZStream).cint) proc deflateInit2(strm: var TZStream, level, `method`, windowBits, memLevel, strategy: int32): int32 = result = deflateInit2u(strm, level, `method`, windowBits, memLevel, - strategy, ZLIB_VERSION(), sizeof(TZStream)) + strategy, ZLIB_VERSION(), sizeof(TZStream).cint) proc inflateInit2(strm: var TZStream, windowBits: int32): int32 = - result = inflateInit2u(strm, windowBits, ZLIB_VERSION(), sizeof(TZStream)) + result = inflateInit2u(strm, windowBits, ZLIB_VERSION(), + sizeof(TZStream).cint) proc zlibAllocMem*(AppData: Pointer, Items, Size: int): Pointer {.cdecl.} = result = Alloc(Items * Size) diff --git a/tests/compile/tnewlibs.nim b/tests/compile/tnewlibs.nim index aca2e3c30..b208b78dd 100755 --- a/tests/compile/tnewlibs.nim +++ b/tests/compile/tnewlibs.nim @@ -10,7 +10,7 @@ import osproc, cairowin32, cairoxlib, gl, glut, glu, glx, glext, wingl, - lua, lualib, lauxlib, mysql, sqlite3, + lua, lualib, lauxlib, mysql, sqlite3, db_mongo writeln(stdout, "test compilation of binding modules") diff --git a/todo.txt b/todo.txt index e32c03ee6..603c2d1ad 100755 --- a/todo.txt +++ b/todo.txt @@ -1,12 +1,11 @@ version 0.9.0 ============= +- deprecate ``var x, y = 0`` as it's confusing for tuple consistency - finish support for unsigned ints: - - document new type conversion rules + - support more unsigned operations - test codegen - - provide ``$`` for unsigned ints -Debug GC session: - test sequence of closures; especially that the GC does not leak for those! New pragmas: @@ -15,8 +14,6 @@ New pragmas: - document destructors - ``borrow`` needs to take type classes into account -- make templates hygienic by default: try to gensym() everything in the 'block' - of a template; find a better solution for gensym instead of `*ident` - introduce ``;`` to the parser - make use of ``tyIter`` to fix the implicit items/pairs issue - ``=`` should be overloadable; requires specialization for ``=`` @@ -50,7 +47,10 @@ version 0.9.XX - document it - fix exception handling +- make templates hygienic by default: try to gensym() everything in the 'block' + of a template; find a better solution for gensym instead of `*ident` - document nimdoc properly finally +- make 'clamp' a magic for the range stuff - implement a warning message for shadowed 'result' variable - implement the high level optimizer - change overloading resolution @@ -101,7 +101,7 @@ Library newSeq(result, a.len) for i in 0..a.len-1: result[i] = a[i] - --> ensure @[] calls the array version! + --> ensure @[] still calls the array version! Low priority @@ -147,7 +147,6 @@ Further optimization ideas Version 2 and beyond ==================== - - shared memory heap: ``shared ref`` etc. The only hard part in the GC is to "stop the world". However, it may be worthwhile to generate explicit (or implicit) syncGC() calls in loops. Automatic loop injection seems diff --git a/web/news.txt b/web/news.txt index d4a03488c..5529a9e33 100755 --- a/web/news.txt +++ b/web/news.txt @@ -87,7 +87,11 @@ Changes affecting backwards compatibility - Deprecated the ``ssl`` module. - Deprecated ``nimrod pretty`` as it never worked good enough and has some inherent problems. -- The integer promotion rules changed. +- The integer promotion rules changed; the compiler is now less picky in some + situations and more picky in other situations: In particular implicit + conversions from ``int`` to ``int32`` are now forbidden. +- ``system.byte`` is now an alias for ``uint8``; it used to be an alias + to ``int8``. Compiler Additions @@ -123,6 +127,7 @@ Language Additions - The apostrophe in type suffixes for numerical literal is now optional. - Unsigned integer types have been added. - The integer promotion rules changed. +- Nimrod now tracks proper intervals for ``range`` over some built-in operators. 2012-02-09 Version 0.8.14 released |