changed integer promotion rules; breaks bootstrapping and lots of code

This commit is contained in:
Araq 2012-07-08 21:03:47 +02:00
commit 4fbba0a65a
42 changed files with 643 additions and 261 deletions

View file

@ -224,7 +224,8 @@ type
sfMainModule, # module is the main module sfMainModule, # module is the main module
sfSystemModule, # module is the system module sfSystemModule, # module is the system module
sfNoReturn, # proc never returns (an exit proc) 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 sfCompilerProc, # proc is a compiler proc, that is a C proc that is
# needed for the code generator # needed for the code generator
sfProcvar, # proc can be passed to a proc var sfProcvar, # proc can be passed to a proc var

View file

@ -1037,8 +1037,9 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
InitLocExpr(p, e.sons[1], a) InitLocExpr(p, e.sons[1], a)
var t = skipTypes(e.sons[1].typ, abstractVarRange) var t = skipTypes(e.sons[1].typ, abstractVarRange)
case t.kind case t.kind
of tyInt..tyInt64: of tyInt..tyInt64, tyUInt..tyUInt64:
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprInt($1)", [rdLoc(a)])) putIntoDest(p, d, e.typ,
ropecg(p.module, "#reprInt((NI64)$1)", [rdLoc(a)]))
of tyFloat..tyFloat128: of tyFloat..tyFloat128:
putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)])) putIntoDest(p, d, e.typ, ropecg(p.module, "#reprFloat($1)", [rdLoc(a)]))
of tyBool: of tyBool:

View file

@ -1066,7 +1066,8 @@ proc createVar(p: var TProc, typ: PType, indirect: bool): PRope =
result = nil result = nil
proc isIndirect(v: PSym): bool = 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) = proc genVarInit(p: var TProc, v: PSym, n: PNode, r: var TCompRes) =
var var

View file

@ -74,24 +74,51 @@ proc getSysType(kind: TTypeKind): PType =
InternalError("wanted: " & $kind & " got: " & $result.kind) InternalError("wanted: " & $kind & " got: " & $result.kind)
if result == nil: InternalError("type not found: " & $kind) if result == nil: InternalError("type not found: " & $kind)
when false: var
var intTypeCache: array[-5..64, PType]
intTypeCache: array[-5..64, PType]
proc getIntLitType*(literal: PNode): PType = proc getIntLitType*(literal: PNode): PType =
# we cache some common integer literal types for performance: # we cache some common integer literal types for performance:
let value = literal.intVal let value = literal.intVal
if value >= low(intTypeCache) and value <= high(intTypeCache): if value >= low(intTypeCache) and value <= high(intTypeCache):
result = intTypeCache[value.int] result = intTypeCache[value.int]
if result == nil: 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) let ti = getSysType(tyInt)
result = copyType(ti, ti.owner, false) result = copyType(ti, ti.owner, false)
result.n = literal 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 = proc getCompilerProc(name: string): PSym =
var ident = getIdent(name, hashIgnoreStyle(name)) var ident = getIdent(name, hashIgnoreStyle(name))

79
compiler/saturate.nim Normal file
View file

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

View file

@ -19,7 +19,7 @@ proc sameMethodDispatcher(a, b: PSym): bool =
result = true result = true
proc resolveOverloads(c: PContext, n, orig: PNode, proc resolveOverloads(c: PContext, n, orig: PNode,
filter: TSymKinds): TCandidate = filter: TSymKinds): TCandidate =
var initialBinding: PNode var initialBinding: PNode
var f = n.sons[0] var f = n.sons[0]
if f.kind == nkBracketExpr: if f.kind == nkBracketExpr:
@ -67,9 +67,17 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
not sameMethodDispatcher(best.calleeSym, alt.calleeSym): not sameMethodDispatcher(best.calleeSym, alt.calleeSym):
if best.state != csMatch: if best.state != csMatch:
InternalError(n.info, "x.state is not 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) % [ LocalError(n.Info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
getProcHeader(best.calleeSym), getProcHeader(alt.calleeSym), getProcHeader(best.calleeSym), getProcHeader(alt.calleeSym),
best.calleeSym.Name.s]) args])
proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode = proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
assert x.state == csMatch assert x.state == csMatch

View file

@ -213,6 +213,11 @@ proc markUsed*(n: PNode, s: PSym) =
if sfDeprecated in s.flags: Message(n.info, warnDeprecated, s.name.s) if sfDeprecated in s.flags: Message(n.info, warnDeprecated, s.name.s)
if sfError in s.flags: LocalError(n.info, errWrongSymbolX, 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 = proc useSym*(sym: PSym): PNode =
result = newSymNode(sym) result = newSymNode(sym)
markUsed(result, sym) markUsed(result, sym)

View file

@ -74,8 +74,10 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
smoduleId != c.module.id and smoduleId != c.friendModule.id: smoduleId != c.module.id and smoduleId != c.friendModule.id:
LocalError(n.info, errXCannotBePassedToProcVar, s.name.s) LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
result = symChoice(c, n, s) result = symChoice(c, n, s)
if result.kind == nkSym and isGenericRoutine(result.sym): if result.kind == nkSym:
LocalError(n.info, errInstantiateXExplicitely, s.name.s) markIndirect(c, result.sym)
if isGenericRoutine(result.sym):
LocalError(n.info, errInstantiateXExplicitely, s.name.s)
of skConst: of skConst:
markUsed(n, s) markUsed(n, s)
case skipTypes(s.typ, abstractInst).kind case skipTypes(s.typ, abstractInst).kind
@ -130,9 +132,10 @@ proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) =
GlobalError(info, errGenerated, MsgKindToString(errIllegalConvFromXtoY) % [ GlobalError(info, errGenerated, MsgKindToString(errIllegalConvFromXtoY) % [
src.typeToString, castDest.typeToString]) src.typeToString, castDest.typeToString])
const
IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64}
proc checkConvertible(info: TLineInfo, castDest, src: PType) = proc checkConvertible(info: TLineInfo, castDest, src: PType) =
const
IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64}
if sameType(castDest, src) and castDest.sym == src.sym: if sameType(castDest, src) and castDest.sym == src.sym:
# don't annoy conversions that may be needed on another processor: # don't annoy conversions that may be needed on another processor:
if castDest.kind notin {tyInt..tyUInt64, tyNil}: if castDest.kind notin {tyInt..tyUInt64, tyNil}:
@ -177,8 +180,8 @@ proc isCastable(dst, src: PType): bool =
result = false result = false
else: else:
result = (ds >= ss) or result = (ds >= ss) or
(skipTypes(dst, abstractInst).kind in {tyInt..tyFloat128}) or (skipTypes(dst, abstractInst).kind in IntegralTypes) or
(skipTypes(src, abstractInst).kind in {tyInt..tyFloat128}) (skipTypes(src, abstractInst).kind in IntegralTypes)
proc semConv(c: PContext, n: PNode, s: PSym): PNode = proc semConv(c: PContext, n: PNode, s: PSym): PNode =
if sonsLen(n) != 2: GlobalError(n.info, errConvNeedsOneArg) if sonsLen(n) != 2: GlobalError(n.info, errConvNeedsOneArg)
@ -191,9 +194,11 @@ proc semConv(c: PContext, n: PNode, s: PSym): PNode =
checkConvertible(result.info, result.typ, op.typ) checkConvertible(result.info, result.typ, op.typ)
else: else:
for i in countup(0, sonsLen(op) - 1): for i in countup(0, sonsLen(op) - 1):
if sameType(result.typ, op.sons[i].typ): let it = op.sons[i]
markUsed(n, op.sons[i].sym) if sameType(result.typ, it.typ):
return op.sons[i] markUsed(n, it.sym)
markIndirect(c, it.sym)
return it
localError(n.info, errUseQualifier, op.sons[0].sym.name.s) localError(n.info, errUseQualifier, op.sons[0].sym.name.s)
proc semCast(c: PContext, n: PNode): PNode = proc semCast(c: PContext, n: PNode): PNode =
@ -222,7 +227,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
n.typ = getSysType(tyInt) n.typ = getSysType(tyInt)
of tyArrayConstr, tyArray: of tyArrayConstr, tyArray:
n.typ = n.sons[1].typ.sons[0] # indextype 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 n.typ = n.sons[1].typ
else: GlobalError(n.info, errInvalidArgForX, opToStr[m]) else: GlobalError(n.info, errInvalidArgForX, opToStr[m])
result = n 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 if n.kind notin nkCallKinds or n.sons[0].kind != nkSym: return
var callee = n.sons[0].sym 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 if {sfNoSideEffect, sfCompileTime} * callee.flags != {} and
{sfForward, sfImportc} * callee.flags == {}: {sfForward, sfImportc} * callee.flags == {}:
if sfCompileTime notin callee.flags and 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 if skipTypes(n.sons[1].typ, {tyGenericInst, tyRange, tyOrdinal}).kind in
{tyInt..tyInt64}: {tyInt..tyInt64}:
var idx = getOrdValue(n.sons[1]) 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, errInvalidIndexValueForTuple)
else: else:
GlobalError(n.info, errIndexTypesDoNotMatch) GlobalError(n.info, errIndexTypesDoNotMatch)
@ -1302,13 +1325,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkNilLit: of nkNilLit:
result.typ = getSysType(tyNil) result.typ = getSysType(tyNil)
of nkIntLit: of nkIntLit:
# XXX this is stupid: if result.typ == nil: setIntLitType(result)
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 nkInt8Lit:
if result.typ == nil: result.typ = getSysType(tyInt8) if result.typ == nil: result.typ = getSysType(tyInt8)
of nkInt16Lit: of nkInt16Lit:

View file

@ -13,7 +13,7 @@
import import
strutils, lists, options, ast, astalgo, trees, treetab, nimsets, times, strutils, lists, options, ast, astalgo, trees, treetab, nimsets, times,
nversion, platform, math, msgs, os, condsyms, idents, renderer, types, nversion, platform, math, msgs, os, condsyms, idents, renderer, types,
commands, magicsys commands, magicsys, saturate
proc getConstExpr*(m: PSym, n: PNode): PNode proc getConstExpr*(m: PSym, n: PNode): PNode
# evaluates the constant expression or returns nil if it is no constant # evaluates the constant expression or returns nil if it is no constant
@ -27,11 +27,18 @@ proc newStrNodeT*(strVal: string, n: PNode): PNode
# implementation # implementation
proc newIntNodeT(intVal: BiggestInt, n: PNode): PNode = proc newIntNodeT(intVal: BiggestInt, n: PNode): PNode =
if skipTypes(n.typ, abstractVarRange).kind == tyChar: 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) result = newIntNode(nkCharLit, intVal)
result.typ = n.typ
else: else:
result = newIntNode(nkIntLit, intVal) result = newIntNode(nkIntLit, intVal)
result.typ = n.typ result.typ = n.typ
result.info = n.info result.info = n.info
proc newFloatNodeT(floatVal: BiggestFloat, n: PNode): PNode = proc newFloatNodeT(floatVal: BiggestFloat, n: PNode): PNode =
@ -67,6 +74,150 @@ proc ordinalValToString(a: PNode): string =
else: else:
result = $x 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 = proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
# b and c may be nil # b and c may be nil
result = nil result = nil

View file

@ -40,6 +40,11 @@ proc semTypeTraits(c: PContext, n: PNode): PNode =
# pass unmodified to evals # pass unmodified to evals
result = n 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, proc magicsAfterOverloadResolution(c: PContext, n: PNode,
flags: TExprFlags): PNode = flags: TExprFlags): PNode =
case n[0].sym.magic case n[0].sym.magic
@ -49,5 +54,6 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n) result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
result.typ = getSysType(tyString) result.typ = getSysType(tyString)
of mInstantiationInfo: result = semInstantiationInfo(c, n) of mInstantiationInfo: result = semInstantiationInfo(c, n)
of mOrd: result = semOrd(c, n)
else: result = n else: result = n

View file

@ -132,7 +132,8 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
var a = semConstExpr(c, n[1]) var a = semConstExpr(c, n[1])
var b = semConstExpr(c, n[2]) var b = semConstExpr(c, n[2])
if not sameType(a.typ, b.typ): GlobalError(n.info, errPureTypeMismatch) 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) GlobalError(n.info, errOrdinalTypeExpected)
if enumHasHoles(a.typ): if enumHasHoles(a.typ):
GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s) GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s)

View file

@ -34,8 +34,13 @@ type
# for example # for example
TTypeRelation* = enum # order is important! TTypeRelation* = enum # order is important!
isNone, isConvertible, isIntConv, isSubtype, isNone, isConvertible,
isGeneric 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 isEqual
proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} = 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.} = proc put(t: var TIdTable, key, val: PType) {.inline.} =
IdTablePut(t, key, val) 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) = proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode, calleeScope = -1) =
initCandidateAux(c, callee.typ) initCandidateAux(c, callee.typ)
@ -100,7 +101,7 @@ proc cmpCandidates*(a, b: TCandidate): int =
if (a.calleeScope != -1) and (b.calleeScope != -1): if (a.calleeScope != -1) and (b.calleeScope != -1):
result = a.calleeScope - b.calleeScope result = a.calleeScope - b.calleeScope
proc writeMatches(c: TCandidate) = proc writeMatches*(c: TCandidate) =
Writeln(stdout, "exact matches: " & $c.exactMatches) Writeln(stdout, "exact matches: " & $c.exactMatches)
Writeln(stdout, "subtype matches: " & $c.subtypeMatches) Writeln(stdout, "subtype matches: " & $c.subtypeMatches)
Writeln(stdout, "conv matches: " & $c.convMatches) Writeln(stdout, "conv matches: " & $c.convMatches)
@ -160,15 +161,25 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
if a.kind == f.kind: if a.kind == f.kind:
result = isEqual result = isEqual
else: else:
var k = skipTypes(a, {tyRange}).kind let ab = skipTypes(a, {tyRange})
if k == f.kind: result = isSubtype let k = ab.kind
elif k == tyInt and f.kind in {tyRange, tyInt8..tyUInt64}: if k == f.kind: result = isSubrange
# and a.n != nil and a.n.intVal >= firstOrd(f) and elif k == tyInt and f.kind in {tyRange, tyInt8..tyInt64,
# a.n.intVal <= lastOrd(f): 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 # integer literal in the proper range; we want ``i16 + 4`` to stay an
# ``int16`` operation so we declare the ``4`` pseudo-equal to int16 # ``int16`` operation so we declare the ``4`` pseudo-equal to int16
result = isFromIntLit
elif f.kind == tyInt and k in {tyInt8..tyInt32}:
result = isIntConv 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 else: result = isNone
#elif f.kind == tyInt and k in {tyInt..tyInt32}: result = isIntConv #elif f.kind == tyInt and k in {tyInt..tyInt32}: result = isIntConv
#elif f.kind == tyUInt and k in {tyUInt..tyUInt32}: 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: if a.kind == f.kind:
result = isEqual result = isEqual
else: else:
var k = skipTypes(a, {tyRange}).kind let ab = skipTypes(a, {tyRange})
if k == f.kind: result = isSubtype var k = ab.kind
elif k == tyInt and f.kind >= tyFloat and f.kind <= tyFloat128: if k == f.kind: result = isSubrange
result = isIntConv elif isIntLit(ab): result = isConvertible
elif k >= tyFloat and k <= tyFloat128: result = isConvertible elif k >= tyFloat and k <= tyFloat128: result = isConvertible
else: result = isNone 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 = proc matchTypeClass(mapping: var TIdTable, f, a: PType): TTypeRelation =
for i in countup(0, f.sonsLen - 1): for i in countup(0, f.sonsLen - 1):
let son = f.sons[i] let son = f.sons[i]
var match = son.kind == a.kind var match = son.kind == skipTypes(a, {tyRange}).kind
if not match: if not match:
case son.kind case son.kind
@ -585,11 +596,16 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
inc(m.convMatches) inc(m.convMatches)
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) 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) inc(m.intConvMatches)
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
of isSubtype: of isSubtype:
inc(m.subtypeMatches) inc(m.subtypeMatches)
result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c) result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c)
of isSubrange:
inc(m.subtypeMatches)
result = copyTree(arg)
of isGeneric: of isGeneric:
inc(m.genericMatches) inc(m.genericMatches)
if m.calleeSym != nil and m.calleeSym.kind in {skMacro, skTemplate}: 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}: if skipTypes(result.typ, abstractVar).kind in {tyTuple}:
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
# BUGFIX: use ``result.typ`` and not `f` here # 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: of isEqual:
inc(m.exactMatches) inc(m.exactMatches)
result = copyTree(arg) result = copyTree(arg)

View file

@ -734,7 +734,6 @@ proc transform(c: PTransf, n: PNode): PTransNode =
# we inline constants if they are not complex constants: # we inline constants if they are not complex constants:
if cnst != nil and not dontInlineConstant(n, cnst): if cnst != nil and not dontInlineConstant(n, cnst):
result = PTransNode(cnst) # do not miss an optimization result = PTransNode(cnst) # do not miss an optimization
warnNarrowingConversion(result.pnode)
proc processTransf(context: PPassContext, n: PNode): PNode = proc processTransf(context: PPassContext, n: PNode): PNode =
# Note: For interactive mode we cannot call 'passes.skipCodegen' and skip # Note: For interactive mode we cannot call 'passes.skipCodegen' and skip

View file

@ -102,6 +102,9 @@ proc getOrdValue(n: PNode): biggestInt =
LocalError(n.info, errOrdinalTypeExpected) LocalError(n.info, errOrdinalTypeExpected)
result = 0 result = 0
proc isIntLit*(t: PType): bool {.inline.} =
result = t.n != nil and t.n.kind == nkIntLit
proc isCompatibleToCString(a: PType): bool = proc isCompatibleToCString(a: PType): bool =
if a.kind == tyArray: if a.kind == tyArray:
if (firstOrd(a.sons[0]) == 0) and if (firstOrd(a.sons[0]) == 0) and
@ -400,8 +403,15 @@ proc TypeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
result = "" result = ""
if t == nil: return if t == nil: return
if prefer == preferName and t.sym != nil and sfAnon notin t.sym.flags: 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 return t.sym.Name.s
case t.Kind case t.Kind
of tyInt:
if not isIntLit(t):
result = typeToStr[t.kind]
else:
result = "intLit(" & $t.n.intVal & ")"
of tyGenericBody, tyGenericInst, tyGenericInvokation: of tyGenericBody, tyGenericInst, tyGenericInvokation:
result = typeToString(t.sons[0]) & '[' result = typeToString(t.sons[0]) & '['
for i in countup(1, sonsLen(t) -1 -ord(t.kind != tyGenericInvokation)): 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 tyUInt8: result = 0xFF
of tyUInt16: result = 0xFFFF of tyUInt16: result = 0xFFFF
of tyUInt32: result = 0xFFFFFFFF of tyUInt32: result = 0xFFFFFFFF
of tyUInt64: result = -1 of tyUInt64: result = 0x7FFFFFFFFFFFFFFF'i64
of tyEnum: of tyEnum:
assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym) assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
result = t.n.sons[sonsLen(t.n) - 1].sym.position result = t.n.sons[sonsLen(t.n) - 1].sym.position

View file

@ -570,9 +570,67 @@ operation meaning
`Automatic type conversion`:idx: is performed in expressions where different `Automatic type conversion`:idx: is performed in expressions where different
kinds of integer types are used: the smaller type is converted to the larger. 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`_. 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 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. 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 String type
~~~~~~~~~~~ ~~~~~~~~~~~
All string literals are of the type `string`:idx:. A string in Nimrod is very 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`` 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 part and not all possible values that ``expr`` can hold occur in a
``slicelist``, a static error occurs. This holds only for expressions of ``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 If the expression is not of an ordinal type, and no ``else`` part is
given, control passes after the ``case`` statement. given, control passes after the ``case`` statement.

View file

@ -59,7 +59,7 @@ type
rawType: PNimType rawType: PNimType
ppointer = ptr pointer ppointer = ptr pointer
pbyteArray = ptr array[0.. 0xffff, byte] pbyteArray = ptr array[0.. 0xffff, int8]
TGenSeq {.pure.} = object TGenSeq {.pure.} = object
len, space: int len, space: int

View file

@ -84,7 +84,7 @@ proc setupQuery(db: TDbConn, query: TSqlQuery,
result = PQExec(db, q) result = PQExec(db, q)
if PQresultStatus(result) != PGRES_TUPLES_OK: dbError(db) 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: for col in 0..cols-1:
setLen(r[col], 0) setLen(r[col], 0)
var x = PQgetvalue(res, line, col) 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 ## fast, but potenially dangerous: If the for-loop-body executes another
## query, the results can be undefined. For Postgres it is safe though. ## query, the results can be undefined. For Postgres it is safe though.
var res = setupQuery(db, query, args) var res = setupQuery(db, query, args)
var L = int(PQnfields(res)) var L = PQnfields(res)
var result = newRow(L) var result = newRow(L)
for i in 0..PQntuples(res)-1: for i in 0..PQntuples(res)-1:
setRow(res, result, i, L) setRow(res, result, i, L)
@ -107,7 +107,7 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): TRow = args: openarray[string]): TRow =
## retrieves a single row. ## retrieves a single row.
var res = setupQuery(db, query, args) var res = setupQuery(db, query, args)
var L = int(PQnfields(res)) var L = PQnfields(res)
result = newRow(L) result = newRow(L)
setRow(res, result, 0, L) setRow(res, result, 0, L)
PQclear(res) PQclear(res)

View file

@ -64,7 +64,7 @@ proc TryExec*(db: TDbConn, query: TSqlQuery,
## tries to execute the query and returns true if successful, false otherwise. ## tries to execute the query and returns true if successful, false otherwise.
var q = dbFormat(query, args) var q = dbFormat(query, args)
var stmt: sqlite3.PStmt 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: if step(stmt) == SQLITE_DONE:
result = finalize(stmt) == SQLITE_OK result = finalize(stmt) == SQLITE_OK
@ -79,9 +79,9 @@ proc newRow(L: int): TRow =
proc setupQuery(db: TDbConn, query: TSqlQuery, proc setupQuery(db: TDbConn, query: TSqlQuery,
args: openarray[string]): PStmt = args: openarray[string]): PStmt =
var q = dbFormat(query, args) 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: for col in 0..cols-1:
setLen(r[col], column_bytes(stmt, col)) # set capacity setLen(r[col], column_bytes(stmt, col)) # set capacity
setLen(r[col], 0) 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 ## fast, but potenially dangerous: If the for-loop-body executes another
## query, the results can be undefined. For Sqlite it is safe though. ## query, the results can be undefined. For Sqlite it is safe though.
var stmt = setupQuery(db, query, args) var stmt = setupQuery(db, query, args)
var L = int(columnCount(stmt)) var L = (columnCount(stmt))
var result = newRow(L) var result = newRow(L)
while step(stmt) == SQLITE_ROW: while step(stmt) == SQLITE_ROW:
setRow(stmt, result, L) setRow(stmt, result, L)
@ -105,7 +105,7 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
args: openarray[string]): TRow = args: openarray[string]): TRow =
## retrieves a single row. ## retrieves a single row.
var stmt = setupQuery(db, query, args) var stmt = setupQuery(db, query, args)
var L = int(columnCount(stmt)) var L = (columnCount(stmt))
result = newRow(L) result = newRow(L)
if step(stmt) == SQLITE_ROW: if step(stmt) == SQLITE_ROW:
setRow(stmt, result, L) setRow(stmt, result, L)

View file

@ -35,14 +35,15 @@ type
proc toSdlColor*(c: TColor): Sdl.TColor = proc toSdlColor*(c: TColor): Sdl.TColor =
## Convert colors.TColor to SDL.TColor ## Convert colors.TColor to SDL.TColor
var x = c.extractRGB var x = c.extractRGB
result.r = toU8(x.r) result.r = x.r and 0xff
result.g = toU8(x.g) result.g = x.g and 0xff
result.b = toU8(x.b) result.b = x.b and 0xff
proc createSdlColor*(sur: PSurface, c: TColor, alpha: int = 0): int32 = proc createSdlColor*(sur: PSurface, c: TColor, alpha: int = 0): int32 =
## Creates a color using ``sdl.MapRGBA``. ## Creates a color using ``sdl.MapRGBA``.
var x = c.extractRGB 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 = proc toSdlRect*(r: TRect): sdl.TRect =
## Convert ``graphics.TRect`` to ``sdl.TRect``. ## Convert ``graphics.TRect`` to ``sdl.TRect``.

View file

@ -82,7 +82,7 @@ proc matchOrFind(s: string, pattern: TRegEx, matches: var openarray[string],
start, flags: cint): cint = start, flags: cint): cint =
var var
rawMatches: array[0..maxSubpatterns * 3 - 1, cint] 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) cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3)
if res < 0'i32: return res if res < 0'i32: return res
for i in 1..int(res)-1: 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. ## is written into `matches` and ``(-1,0)`` is returned.
var var
rawMatches: array[0..maxSubpatterns * 3 - 1, cint] 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) cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3)
if res < 0'i32: return (-1, 0) if res < 0'i32: return (-1, 0)
for i in 1..int(res)-1: for i in 1..int(res)-1:
@ -119,7 +119,7 @@ proc findBounds*(s: string, pattern: TRegEx,
## ``(-1,0)`` is returned. ## ``(-1,0)`` is returned.
var var
rawMatches: array[0..maxSubpatterns * 3 - 1, cint] 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) cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3)
if res < 0'i32: return (-1, 0) if res < 0'i32: return (-1, 0)
for i in 1..int(res)-1: for i in 1..int(res)-1:
@ -135,14 +135,14 @@ proc findBounds*(s: string, pattern: TRegEx,
## match, ``(-1,0)`` is returned. ## match, ``(-1,0)`` is returned.
var var
rawMatches: array[0..3 - 1, cint] 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) cast[ptr cint](addr(rawMatches)), 3)
if res < 0'i32: return (int(res), 0) if res < 0'i32: return (int(res), 0)
return (int(rawMatches[0]), int(rawMatches[1]-1)) return (int(rawMatches[0]), int(rawMatches[1]-1))
proc matchOrFind(s: string, pattern: TRegEx, start, flags: cint): cint = proc matchOrFind(s: string, pattern: TRegEx, start, flags: cint): cint =
var rawMatches: array [0..maxSubpatterns * 3 - 1, 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) cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3)
if result >= 0'i32: if result >= 0'i32:
result = rawMatches[1] - rawMatches[0] 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. ## is written into ``matches`` and -1 is returned.
var var
rawMatches: array[0..maxSubpatterns * 3 - 1, cint] 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) cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3)
if res < 0'i32: return res if res < 0'i32: return res
for i in 1..int(res)-1: for i in 1..int(res)-1:
@ -195,7 +195,7 @@ proc find*(s: string, pattern: TRegEx, start = 0): int =
## match, -1 is returned. ## match, -1 is returned.
var var
rawMatches: array[0..3 - 1, cint] 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) cast[ptr cint](addr(rawMatches)), 3)
if res < 0'i32: return res if res < 0'i32: return res
return rawMatches[0] return rawMatches[0]
@ -205,7 +205,7 @@ iterator findAll*(s: string, pattern: TRegEx, start = 0): string =
var i = int32(start) var i = int32(start)
var rawMatches: array[0..maxSubpatterns * 3 - 1, cint] var rawMatches: array[0..maxSubpatterns * 3 - 1, cint]
while true: 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) cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3)
if res < 0'i32: break if res < 0'i32: break
let a = rawMatches[0] let a = rawMatches[0]

View file

@ -53,7 +53,8 @@ proc oidToString*(oid: TOid, str: cstring) =
str[24] = '\0' str[24] = '\0'
var var
incr, fuzz: int incr: int
fuzz: int32
proc genOid*(): TOid = proc genOid*(): TOid =
## generates a new OID. ## generates a new OID.

View file

@ -244,7 +244,7 @@ when defined(Windows) and not defined(useNimRtl):
var s = PFileHandleStream(s) var s = PFileHandleStream(s)
if s.atTheEnd: return 0 if s.atTheEnd: return 0
var br: int32 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 zero bytes returned (EOF).
# TRUE and n (>0) bytes returned (good data). # TRUE and n (>0) bytes returned (good data).
# FALSE and bytes returned undefined (system error). # 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) = proc hsWriteData(s: PStream, buffer: pointer, bufLen: int) =
var s = PFileHandleStream(s) var s = PFileHandleStream(s)
var bytesWritten: int32 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() if a == 0: OSError()
proc newFileHandleStream(handle: THandle): PFileHandleStream = proc newFileHandleStream(handle: THandle): PFileHandleStream =
@ -293,7 +293,7 @@ when defined(Windows) and not defined(useNimRtl):
proc CreatePipeHandles(Rdhandle, WrHandle: var THandle) = proc CreatePipeHandles(Rdhandle, WrHandle: var THandle) =
var piInheritablePipe: TSecurityAttributes var piInheritablePipe: TSecurityAttributes
piInheritablePipe.nlength = SizeOF(TSecurityAttributes) piInheritablePipe.nlength = SizeOF(TSecurityAttributes).cint
piInheritablePipe.lpSecurityDescriptor = nil piInheritablePipe.lpSecurityDescriptor = nil
piInheritablePipe.Binherithandle = 1 piInheritablePipe.Binherithandle = 1
if CreatePipe(Rdhandle, Wrhandle, piInheritablePipe, 1024) == 0'i32: if CreatePipe(Rdhandle, Wrhandle, piInheritablePipe, 1024) == 0'i32:
@ -313,7 +313,7 @@ when defined(Windows) and not defined(useNimRtl):
success: int success: int
hi, ho, he: THandle hi, ho, he: THandle
new(result) new(result)
SI.cb = SizeOf(SI) SI.cb = SizeOf(SI).cint
if poParentStreams notin options: if poParentStreams notin options:
SI.dwFlags = STARTF_USESTDHANDLES # STARTF_USESHOWWINDOW or SI.dwFlags = STARTF_USESTDHANDLES # STARTF_USESHOWWINDOW or
CreatePipeHandles(SI.hStdInput, HI) CreatePipeHandles(SI.hStdInput, HI)
@ -323,16 +323,16 @@ when defined(Windows) and not defined(useNimRtl):
HE = HO HE = HO
else: else:
CreatePipeHandles(HE, Si.hStdError) CreatePipeHandles(HE, Si.hStdError)
result.inputHandle = hi result.inputHandle = TFileHandle(hi)
result.outputHandle = ho result.outputHandle = TFileHandle(ho)
result.errorHandle = he result.errorHandle = TFileHandle(he)
else: else:
SI.hStdError = GetStdHandle(STD_ERROR_HANDLE) SI.hStdError = GetStdHandle(STD_ERROR_HANDLE)
SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE) SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE)
SI.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE) SI.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE)
result.inputHandle = si.hStdInput result.inputHandle = TFileHandle(si.hStdInput)
result.outputHandle = si.hStdOutput result.outputHandle = TFileHandle(si.hStdOutput)
result.errorHandle = si.hStdError result.errorHandle = TFileHandle(si.hStdError)
var cmdl: cstring var cmdl: cstring
when false: # poUseShell in options: when false: # poUseShell in options:
@ -394,7 +394,7 @@ when defined(Windows) and not defined(useNimRtl):
discard TerminateProcess(p.FProcessHandle, 0) discard TerminateProcess(p.FProcessHandle, 0)
proc waitForExit(p: PProcess, timeout: int = -1): int = proc waitForExit(p: PProcess, timeout: int = -1): int =
discard WaitForSingleObject(p.FProcessHandle, timeout) discard WaitForSingleObject(p.FProcessHandle, timeout.int32)
var res: int32 var res: int32
discard GetExitCodeProcess(p.FProcessHandle, res) discard GetExitCodeProcess(p.FProcessHandle, res)
@ -424,7 +424,7 @@ when defined(Windows) and not defined(useNimRtl):
ProcInfo: TProcessInformation ProcInfo: TProcessInformation
process: THandle process: THandle
L: int32 L: int32
SI.cb = SizeOf(SI) SI.cb = SizeOf(SI).cint
SI.hStdError = GetStdHandle(STD_ERROR_HANDLE) SI.hStdError = GetStdHandle(STD_ERROR_HANDLE)
SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE) SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE)
SI.hStdOutput = GetStdHandle(STD_OUTPUT_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: for i in 0..readfds.len()-1:
rfds[i] = readfds[i].FProcessHandle rfds[i] = readfds[i].FProcessHandle
var ret = waitForMultipleObjects(readfds.len, var ret = waitForMultipleObjects(readfds.len.int32,
addr(rfds), 0'i32, timeout) addr(rfds), 0'i32, timeout)
case ret case ret
of WAIT_TIMEOUT: of WAIT_TIMEOUT:

View file

@ -343,7 +343,7 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") =
name.sin_port = sockets.htons(int16(port)) name.sin_port = sockets.htons(int16(port))
name.sin_addr.s_addr = sockets.htonl(INADDR_ANY) name.sin_addr.s_addr = sockets.htonl(INADDR_ANY)
if bindSocket(socket.fd, cast[ptr TSockAddr](addr(name)), if bindSocket(socket.fd, cast[ptr TSockAddr](addr(name)),
sizeof(name)) < 0'i32: sizeof(name).TSockLen) < 0'i32:
OSError() OSError()
else: else:
var hints: TAddrInfo var hints: TAddrInfo
@ -366,7 +366,7 @@ when false:
name.sin_port = sockets.htons(int16(port)) name.sin_port = sockets.htons(int16(port))
name.sin_addr.s_addr = sockets.htonl(INADDR_ANY) name.sin_addr.s_addr = sockets.htonl(INADDR_ANY)
if bindSocket(cint(socket), cast[ptr TSockAddr](addr(name)), if bindSocket(cint(socket), cast[ptr TSockAddr](addr(name)),
sizeof(name)) < 0'i32: sizeof(name).TSockLen) < 0'i32:
OSError() OSError()
proc getSockName*(socket: TSocket): TPort = proc getSockName*(socket: TSocket): TPort =
@ -378,7 +378,7 @@ proc getSockName*(socket: TSocket): TPort =
name.sin_family = posix.AF_INET name.sin_family = posix.AF_INET
#name.sin_port = htons(cint16(port)) #name.sin_port = htons(cint16(port))
#name.sin_addr.s_addr = htonl(INADDR_ANY) #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)), if getsockname(socket.fd, cast[ptr TSockAddr](addr(name)),
addr(namelen)) == -1'i32: addr(namelen)) == -1'i32:
OSError() 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 ## **Warning:** This function might block even if socket is non-blocking
## when using SSL. ## when using SSL.
var sockAddress: Tsockaddr_in var sockAddress: Tsockaddr_in
var addrLen: cint = sizeof(sockAddress) var addrLen = sizeof(sockAddress).TSockLen
var sock = accept(server.fd, cast[ptr TSockAddr](addr(sockAddress)), var sock = accept(server.fd, cast[ptr TSockAddr](addr(sockAddress)),
addr(addrLen)) addr(addrLen))
@ -477,9 +477,9 @@ proc getServByName*(name, proto: string): TServent =
proc getServByPort*(port: TPort, proto: string): TServent = proc getServByPort*(port: TPort, proto: string): TServent =
## well-known getservbyport proc. ## well-known getservbyport proc.
when defined(Windows): when defined(Windows):
var s = winlean.getservbyport(ze(int16(port)), proto) var s = winlean.getservbyport(ze(int16(port)).cint, proto)
else: else:
var s = posix.getservbyport(ze(int16(port)), proto) var s = posix.getservbyport(ze(int16(port)).cint, proto)
if s == nil: OSError() if s == nil: OSError()
result.name = $s.s_name result.name = $s.s_name
result.aliases = cstringArrayToSeq(s.s_aliases) result.aliases = cstringArrayToSeq(s.s_aliases)
@ -492,11 +492,11 @@ proc getHostByAddr*(ip: string): THostEnt =
myaddr.s_addr = inet_addr(ip) myaddr.s_addr = inet_addr(ip)
when defined(windows): when defined(windows):
var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr), var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cint,
cint(sockets.AF_INET)) cint(sockets.AF_INET))
if s == nil: OSError() if s == nil: OSError()
else: else:
var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr), var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).cint,
cint(posix.AF_INET)) cint(posix.AF_INET))
if s == nil: if s == nil:
raise newException(EOS, $hStrError(h_errno)) raise newException(EOS, $hStrError(h_errno))
@ -539,7 +539,7 @@ proc getHostByName*(name: string): THostEnt =
proc getSockOptInt*(socket: TSocket, level, optname: int): int = proc getSockOptInt*(socket: TSocket, level, optname: int): int =
## getsockopt for integer options. ## getsockopt for integer options.
var res: cint var res: cint
var size: cint = sizeof(res) var size = sizeof(res).cint
if getsockopt(socket.fd, cint(level), cint(optname), if getsockopt(socket.fd, cint(level), cint(optname),
addr(res), addr(size)) < 0'i32: addr(res), addr(size)) < 0'i32:
OSError() OSError()
@ -549,7 +549,7 @@ proc setSockOptInt*(socket: TSocket, level, optname, optval: int) =
## setsockopt for integer options. ## setsockopt for integer options.
var value = cint(optval) var value = cint(optval)
if setsockopt(socket.fd, cint(level), cint(optname), addr(value), if setsockopt(socket.fd, cint(level), cint(optname), addr(value),
sizeof(value)) < 0'i32: sizeof(value).cint) < 0'i32:
OSError() OSError()
proc connect*(socket: TSocket, name: string, port = TPort(0), 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_INET: s.sin_family = posix.AF_INET
of AF_INET6: s.sin_family = posix.AF_INET6 of AF_INET6: s.sin_family = posix.AF_INET6
else: nil 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() OSError()
proc connectAsync*(socket: TSocket, name: string, port = TPort(0), proc connectAsync*(socket: TSocket, name: string, port = TPort(0),

View file

@ -111,7 +111,7 @@ type
## in the range 0 to 23. ## in the range 0 to 23.
monthday*: range[1..31] ## The day of the month, in the range 1 to 31. monthday*: range[1..31] ## The day of the month, in the range 1 to 31.
month*: TMonth ## The current month. 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. weekday*: TWeekDay ## The current day of the week.
yearday*: range[0..365] ## The number of days since January 1, yearday*: range[0..365] ## The number of days since January 1,
## in the range 0 to 365. ## in the range 0 to 365.
@ -122,7 +122,7 @@ type
timezone*: int ## The offset of the (non-DST) timezone in seconds timezone*: int ## The offset of the (non-DST) timezone in seconds
## west of UTC. ## west of UTC.
TTimeInterval* = object TTimeInterval* {.pure.} = object ## a time interval
miliseconds*: int ## The number of miliseconds miliseconds*: int ## The number of miliseconds
seconds*: int ## The number of seconds seconds*: int ## The number of seconds
minutes*: int ## The number of minutes minutes*: int ## The number of minutes
@ -150,11 +150,11 @@ proc `$` *(timeInfo: TTimeInfo): string
proc `$` *(time: TTime): string proc `$` *(time: TTime): string
## converts a calendar time to a string representation. ## converts a calendar time to a string representation.
proc `-` *(a, b: TTime): int64{. proc `-`*(a, b: TTime): int64 {.
rtl, extern: "ntDiffTime".} rtl, extern: "ntDiffTime".}
## computes the difference of two calendar times. Result is in seconds. ## computes the difference of two calendar times. Result is in seconds.
proc `<` * (a, b: TTime): bool {. proc `<`*(a, b: TTime): bool {.
rtl, extern: "ntLtTime".} = rtl, extern: "ntLtTime".} =
## returns true iff ``a < b``, that is iff a happened before b. ## returns true iff ``a < b``, that is iff a happened before b.
result = a - b < 0 result = a - b < 0
@ -175,8 +175,8 @@ proc getStartMilsecs*(): int {.deprecated.}
## get the miliseconds from the start of the program. **Deprecated since ## get the miliseconds from the start of the program. **Deprecated since
## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead. ## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead.
proc newInterval*(miliseconds, seconds, minutes, hours, days, months, proc initInterval*(miliseconds, seconds, minutes, hours, days, months,
years: int = 0): TTimeInterval = years: int = 0): TTimeInterval =
## creates a new ``TTimeInterval``. ## creates a new ``TTimeInterval``.
result.miliseconds = miliseconds result.miliseconds = miliseconds
result.seconds = seconds result.seconds = seconds
@ -188,22 +188,19 @@ proc newInterval*(miliseconds, seconds, minutes, hours, days, months,
proc isLeapYear(year: int): bool = proc isLeapYear(year: int): bool =
if year mod 400 == 0: if year mod 400 == 0:
return true return true
elif year mod 100 == 0: elif year mod 100 == 0:
return false return false
elif year mod 4 == 0: elif year mod 4 == 0:
return true return true
else: else:
return false return false
proc getDaysInMonth(month: TMonth, year: int): int = proc getDaysInMonth(month: TMonth, year: int): int =
# http://www.dispersiondesign.com/articles/time/number_of_days_in_a_month # http://www.dispersiondesign.com/articles/time/number_of_days_in_a_month
if month == mFeb: # Feb case month
if isLeapYear(year): of mFeb: result = if isLeapYear(year): 29 else: 28
result = 29 of mApr, mJun, mSep, mNov: result = 30
else:
result = 28
elif month in [mApr, mJun, mSep, mNov]: result = 30
else: result = 31 else: result = 31
proc calculateSeconds(a: TTimeInfo, interval: TTimeInterval): float = proc calculateSeconds(a: TTimeInfo, interval: TTimeInterval): float =
@ -228,9 +225,10 @@ proc calculateSeconds(a: TTimeInfo, interval: TTimeInterval): float =
proc `+`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo = proc `+`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
## adds ``interval`` time. ## 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) let t = timeInfoToTime(a)
var secs = calculateSeconds(a, interval) let secs = calculateSeconds(a, interval)
if a.tzname == "UTC": if a.tzname == "UTC":
result = getGMTime(TTime(float(t) + secs)) result = getGMTime(TTime(float(t) + secs))
else: else:
@ -242,7 +240,7 @@ proc `-`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
## **Note:** This has been only briefly tested, it is inaccurate especially ## **Note:** This has been only briefly tested, it is inaccurate especially
## when you subtract so much that you reach the Julian calendar. ## when you subtract so much that you reach the Julian calendar.
let t = timeInfoToTime(a) let t = timeInfoToTime(a)
var secs = calculateSeconds(a, interval) let secs = calculateSeconds(a, interval)
if a.tzname == "UTC": if a.tzname == "UTC":
result = getGMTime(TTime(float(t) - secs)) result = getGMTime(TTime(float(t) - secs))
else: else:
@ -329,7 +327,7 @@ when not defined(ECMAScript):
proc timeInfoToTM(t: TTimeInfo): structTM = proc timeInfoToTM(t: TTimeInfo): structTM =
const 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.second = t.second
result.minute = t.minute result.minute = t.minute
result.hour = t.hour result.hour = t.hour
@ -362,13 +360,13 @@ when not defined(ECMAScript):
var a = t var a = t
result = tmToTimeInfo(localtime(addr(a))[], true) result = tmToTimeInfo(localtime(addr(a))[], true)
# copying is needed anyway to provide reentrancity; thus # copying is needed anyway to provide reentrancity; thus
# the convertion is not expensive # the conversion is not expensive
proc getGMTime(t: TTime): TTimeInfo = proc getGMTime(t: TTime): TTimeInfo =
var a = t var a = t
result = tmToTimeInfo(gmtime(addr(a))[], false) result = tmToTimeInfo(gmtime(addr(a))[], false)
# copying is needed anyway to provide reentrancity; thus # copying is needed anyway to provide reentrancity; thus
# the convertion is not expensive # the conversion is not expensive
proc TimeInfoToTime(timeInfo: TTimeInfo): TTime = proc TimeInfoToTime(timeInfo: TTimeInfo): TTime =
var cTimeInfo = timeInfo # for C++ we have to make a copy, var cTimeInfo = timeInfo # for C++ we have to make a copy,

View file

@ -182,8 +182,8 @@ when not defined(EcmaScript) and not defined(NimrodVM):
include "system/hti" include "system/hti"
type type
Byte* = Int8 ## this is an alias for ``int8``, that is a signed Byte* = uInt8 ## this is an alias for ``uint8``, that is an unsigned
## int 8 bits wide. ## int 8 bits wide.
Natural* = range[0..high(int)] Natural* = range[0..high(int)]
## is an int type ranging from zero to the maximum value ## is an int type ranging from zero to the maximum value
@ -967,7 +967,7 @@ type
type # these work for most platforms: type # these work for most platforms:
cchar* {.importc: "char", nodecl.} = char cchar* {.importc: "char", nodecl.} = char
## This is the same as the type ``char`` in *C*. ## 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*. ## This is the same as the type ``signed char`` in *C*.
cshort* {.importc: "short", nodecl.} = int16 cshort* {.importc: "short", nodecl.} = int16
## This is the same as the type ``short`` in *C*. ## 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` ## The stingify operator for an integer argument. Returns `x`
## converted to a decimal string. ## 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.} proc `$` *(x: float): string {.magic: "FloatToStr", noSideEffect.}
## The stingify operator for a float argument. Returns `x` ## The stingify operator for a float argument. Returns `x`
## converted to a decimal string. ## 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 ## as it is. This operator is useful for generic code, so
## that ``$expr`` also works if ``expr`` is already a string. ## 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 ## The stingify operator for an enumeration argument. This works for
## any enumeration type thanks to compiler magic. If ## any enumeration type thanks to compiler magic. If
## a ``$`` operator for a concrete enumeration is provided, this is ## 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 proc getFileSize*(f: TFile): int64
## retrieves the file size (in bytes) of `f`. ## 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 ## 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 ## 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. ## `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 ## 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. ## `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 ## 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 ## the number of actual written bytes, which may be less than `len` in case
## of an error. ## of an error.

View file

@ -71,7 +71,8 @@ proc c_fopen(filename, mode: cstring): C_TextFileStar {.
importc: "fopen", nodecl.} importc: "fopen", nodecl.}
proc c_fclose(f: C_TextFileStar) {.importc: "fclose", 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 # 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 {. proc c_fread(buf: Pointer, size, n: int, f: C_BinaryFileStar): int {.

View file

@ -20,6 +20,11 @@ proc reprPointer(x: pointer): string {.compilerproc.} =
c_sprintf(buf, "%p", x) c_sprintf(buf, "%p", x)
return $buf 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) = proc reprStrAux(result: var string, s: string) =
if cast[pointer](s) == nil: if cast[pointer](s) == nil:
add result, "nil" add result, "nil"
@ -67,7 +72,7 @@ proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} =
result = $e & " (invalid data!)" result = $e & " (invalid data!)"
type type
pbyteArray = ptr array[0.. 0xffff, byte] pbyteArray = ptr array[0.. 0xffff, int8]
proc addSetElem(result: var string, elem: int, typ: PNimType) = proc addSetElem(result: var string, elem: int, typ: PNimType) =
case typ.kind case typ.kind

View file

@ -222,17 +222,17 @@ proc fwrite(buf: Pointer, size, n: int, f: TFile): int {.
proc readBuffer(f: TFile, buffer: pointer, len: int): int = proc readBuffer(f: TFile, buffer: pointer, len: int): int =
result = fread(buffer, 1, len, f) 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) result = readBuffer(f, addr(a[start]), len)
proc ReadChars(f: TFile, a: var openarray[char], start, len: int): int = proc ReadChars(f: TFile, a: var openarray[char], start, len: int): int =
result = readBuffer(f, addr(a[start]), len) result = readBuffer(f, addr(a[start]), len)
proc writeBytes(f: TFile, a: openarray[byte], start, len: int): int = proc writeBytes(f: TFile, a: openarray[int8], 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) result = writeBuffer(f, addr(x[start]), len)
proc writeChars(f: TFile, a: openarray[char], start, len: int): int = 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) result = writeBuffer(f, addr(x[start]), len)
proc writeBuffer(f: TFile, buffer: pointer, len: int): int = proc writeBuffer(f: TFile, buffer: pointer, len: int): int =
result = fwrite(buffer, 1, len, f) result = fwrite(buffer, 1, len, f)

View file

@ -13,8 +13,8 @@
{.deadCodeElim: on.} {.deadCodeElim: on.}
type type
WideChar* = int16 WideChar* = uint16
PWideChar* = ptr int16 PWideChar* = ptr uint16
type # WinNT.h -- Defines the 32-Bit Windows types and constants type # WinNT.h -- Defines the 32-Bit Windows types and constants
SHORT* = int16 SHORT* = int16
@ -72,7 +72,6 @@ type # WinDef.h -- Basic Windows Type Definitions
DWORD* = int32 DWORD* = int32
WINBOOL* = int32 WINBOOL* = int32
BYTE* = char
WORD* = int16 WORD* = int16
# FLOAT* = float # FLOAT* = float
PFLOAT* = ptr FLOAT PFLOAT* = ptr FLOAT
@ -296,13 +295,13 @@ type
when defined(winUnicode): when defined(winUnicode):
type type
PTBYTE* = ptr int16 PTBYTE* = ptr uint16
PTCH* = PWideChar PTCH* = PWideChar
PTCHAR* = PWideChar PTCHAR* = PWideChar
PTSTR* = PWideChar PTSTR* = PWideChar
else: else:
type type
PTBYTE* = ptr int8 PTBYTE* = ptr byte
PTCH* = cstring PTCH* = cstring
PTCHAR* = cstring PTCHAR* = cstring
PTSTR* = cstring PTSTR* = cstring
@ -316,12 +315,12 @@ type
when defined(winUnicode): when defined(winUnicode):
type type
TBYTE* = int16 TBYTE* = uint16
TCHAR* = widechar TCHAR* = widechar
BCHAR* = int16 BCHAR* = int16
else: else:
type type
TBYTE* = int8 TBYTE* = uint8
TCHAR* = char TCHAR* = char
BCHAR* = int8 BCHAR* = int8
type type
@ -7432,34 +7431,34 @@ type
PDCB* = ptr DCB PDCB* = ptr DCB
const const
bm_DCB_fBinary* = 0x00000001 bm_DCB_fBinary* = 1
bp_DCB_fBinary* = 0 bp_DCB_fBinary* = 0'i32
bm_DCB_fParity* = 0x00000002 bm_DCB_fParity* = 0x00000002
bp_DCB_fParity* = 1 bp_DCB_fParity* = 1'i32
bm_DCB_fOutxCtsFlow* = 0x00000004 bm_DCB_fOutxCtsFlow* = 0x00000004
bp_DCB_fOutxCtsFlow* = 2 bp_DCB_fOutxCtsFlow* = 2'i32
bm_DCB_fOutxDsrFlow* = 0x00000008 bm_DCB_fOutxDsrFlow* = 0x00000008
bp_DCB_fOutxDsrFlow* = 3 bp_DCB_fOutxDsrFlow* = 3'i32
bm_DCB_fDtrControl* = 0x00000030 bm_DCB_fDtrControl* = 0x00000030
bp_DCB_fDtrControl* = 4 bp_DCB_fDtrControl* = 4'i32
bm_DCB_fDsrSensitivity* = 0x00000040 bm_DCB_fDsrSensitivity* = 0x00000040
bp_DCB_fDsrSensitivity* = 6 bp_DCB_fDsrSensitivity* = 6'i32
bm_DCB_fTXContinueOnXoff* = 0x00000080 bm_DCB_fTXContinueOnXoff* = 0x00000080
bp_DCB_fTXContinueOnXoff* = 7 bp_DCB_fTXContinueOnXoff* = 7'i32
bm_DCB_fOutX* = 0x00000100 bm_DCB_fOutX* = 0x00000100
bp_DCB_fOutX* = 8 bp_DCB_fOutX* = 8'i32
bm_DCB_fInX* = 0x00000200 bm_DCB_fInX* = 0x00000200
bp_DCB_fInX* = 9 bp_DCB_fInX* = 9'i32
bm_DCB_fErrorChar* = 0x00000400 bm_DCB_fErrorChar* = 0x00000400
bp_DCB_fErrorChar* = 10 bp_DCB_fErrorChar* = 10'i32
bm_DCB_fNull* = 0x00000800 bm_DCB_fNull* = 0x00000800
bp_DCB_fNull* = 11 bp_DCB_fNull* = 11'i32
bm_DCB_fRtsControl* = 0x00003000 bm_DCB_fRtsControl* = 0x00003000
bp_DCB_fRtsControl* = 12 bp_DCB_fRtsControl* = 12'i32
bm_DCB_fAbortOnError* = 0x00004000 bm_DCB_fAbortOnError* = 0x00004000
bp_DCB_fAbortOnError* = 14 bp_DCB_fAbortOnError* = 14'i32
bm_DCB_fDummy2* = 0xFFFF8000'i32 bm_DCB_fDummy2* = 0xFFFF8000'i32
bp_DCB_fDummy2* = 15 bp_DCB_fDummy2* = 15'i32
proc fBinary*(a: var DCB): DWORD proc fBinary*(a: var DCB): DWORD
proc set_fBinary*(a: var DCB, fBinary: DWORD) proc set_fBinary*(a: var DCB, fBinary: DWORD)
@ -7575,21 +7574,21 @@ type
const const
bm_COMSTAT_fCtsHold* = 0x00000001 bm_COMSTAT_fCtsHold* = 0x00000001
bp_COMSTAT_fCtsHold* = 0 bp_COMSTAT_fCtsHold* = 0'i32
bm_COMSTAT_fDsrHold* = 0x00000002 bm_COMSTAT_fDsrHold* = 0x00000002
bp_COMSTAT_fDsrHold* = 1 bp_COMSTAT_fDsrHold* = 1'i32
bm_COMSTAT_fRlsdHold* = 0x00000004 bm_COMSTAT_fRlsdHold* = 0x00000004
bp_COMSTAT_fRlsdHold* = 2 bp_COMSTAT_fRlsdHold* = 2'i32
bm_COMSTAT_fXoffHold* = 0x00000008 bm_COMSTAT_fXoffHold* = 0x00000008
bp_COMSTAT_fXoffHold* = 3 bp_COMSTAT_fXoffHold* = 3'i32
bm_COMSTAT_fXoffSent* = 0x00000010 bm_COMSTAT_fXoffSent* = 0x00000010
bp_COMSTAT_fXoffSent* = 4 bp_COMSTAT_fXoffSent* = 4'i32
bm_COMSTAT_fEof* = 0x00000020 bm_COMSTAT_fEof* = 0x00000020
bp_COMSTAT_fEof* = 5 bp_COMSTAT_fEof* = 5'i32
bm_COMSTAT_fTxim* = 0x00000040 bm_COMSTAT_fTxim* = 0x00000040
bp_COMSTAT_fTxim* = 6 bp_COMSTAT_fTxim* = 6'i32
bm_COMSTAT_fReserved* = 0xFFFFFF80'i32 bm_COMSTAT_fReserved* = 0xFFFFFF80'i32
bp_COMSTAT_fReserved* = 7 bp_COMSTAT_fReserved* = 7'i32
proc fCtsHold*(a: var COMSTAT): DWORD proc fCtsHold*(a: var COMSTAT): DWORD
# should be renamed to get_<x>? # should be renamed to get_<x>?
@ -9984,25 +9983,25 @@ type
const const
bm_LDT_ENTRY_BaseMid* = 0x000000FF bm_LDT_ENTRY_BaseMid* = 0x000000FF
bp_LDT_ENTRY_BaseMid* = 0 bp_LDT_ENTRY_BaseMid* = 0'i32
bm_LDT_ENTRY_Type* = 0x00001F00 bm_LDT_ENTRY_Type* = 0x00001F00
bp_LDT_ENTRY_Type* = 8 bp_LDT_ENTRY_Type* = 8'i32
bm_LDT_ENTRY_Dpl* = 0x00006000 bm_LDT_ENTRY_Dpl* = 0x00006000
bp_LDT_ENTRY_Dpl* = 13 bp_LDT_ENTRY_Dpl* = 13'i32
bm_LDT_ENTRY_Pres* = 0x00008000 bm_LDT_ENTRY_Pres* = 0x00008000
bp_LDT_ENTRY_Pres* = 15 bp_LDT_ENTRY_Pres* = 15'i32
bm_LDT_ENTRY_LimitHi* = 0x000F0000 bm_LDT_ENTRY_LimitHi* = 0x000F0000
bp_LDT_ENTRY_LimitHi* = 16 bp_LDT_ENTRY_LimitHi* = 16'i32
bm_LDT_ENTRY_Sys* = 0x00100000 bm_LDT_ENTRY_Sys* = 0x00100000
bp_LDT_ENTRY_Sys* = 20 bp_LDT_ENTRY_Sys* = 20'i32
bm_LDT_ENTRY_Reserved_0* = 0x00200000 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 bm_LDT_ENTRY_Default_Big* = 0x00400000
bp_LDT_ENTRY_Default_Big* = 22 bp_LDT_ENTRY_Default_Big* = 22'i32
bm_LDT_ENTRY_Granularity* = 0x00800000 bm_LDT_ENTRY_Granularity* = 0x00800000
bp_LDT_ENTRY_Granularity* = 23 bp_LDT_ENTRY_Granularity* = 23'i32
bm_LDT_ENTRY_BaseHi* = 0xFF000000 bm_LDT_ENTRY_BaseHi* = 0xFF000000
bp_LDT_ENTRY_BaseHi* = 24 bp_LDT_ENTRY_BaseHi* = 24'i32
type type
LOCALESIGNATURE* {.final, pure.} = object LOCALESIGNATURE* {.final, pure.} = object
@ -22820,7 +22819,7 @@ proc SEXT_HIWORD*(L: int32): int32 =
proc ZEXT_HIWORD*(L: int32): int32 = proc ZEXT_HIWORD*(L: int32): int32 =
# return type might be wrong # return type might be wrong
result = ze(HIWORD(L)) result = HIWORD(L) and 0xffff'i32
proc SEXT_LOWORD*(L: int32): int32 = proc SEXT_LOWORD*(L: int32): int32 =
result = LOWORD(L) result = LOWORD(L)
@ -22869,13 +22868,13 @@ proc MAKEWPARAM*(L, h: int32): WPARAM =
result = WPARAM(MAKELONG(L, h)) result = WPARAM(MAKELONG(L, h))
proc GET_X_LPARAM*(lp: Windows.LParam): int32 = proc GET_X_LPARAM*(lp: Windows.LParam): int32 =
result = int16(LOWORD(lp)) result = LOWORD(lp.int32)
proc GET_Y_LPARAM*(lp: Windows.LParam): int32 = proc GET_Y_LPARAM*(lp: Windows.LParam): int32 =
result = int16(HIWORD(lp)) result = HIWORD(lp.int32)
proc UNICODE_NULL*(): WCHAR = 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)) MAKELPARAM(fPartialOK, 0))
proc ListView_FindItem(wnd: HWND, iStart: int32, lvfi: var LV_FINDINFO): int32 = 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 = proc ListView_GetBkColor(wnd: HWND): LRESULT =
result = SendMessage(wnd, LVM_GETBKCOLOR, 0, 0) 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 = proc ListView_GetItemPosition(hwndLV: HWND, i: int32, pt: var POINT): int32 =
result = SendMessage(hwndLV, LVM_GETITEMPOSITION, WPARAM(int32(i)), 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 = proc ListView_GetItemSpacing(hwndLV: HWND, fSmall: int32): LRESULT =
result = SendMessage(hwndLV, LVM_GETITEMSPACING, fSmall, 0) result = SendMessage(hwndLV, LVM_GETITEMSPACING, fSmall, 0)
@ -23878,10 +23878,10 @@ proc GetLargestConsoleWindowSize(hConsoleOutput: HANDLE): COORD =
result.x = toU16(res shr 16) result.x = toU16(res shr 16)
proc Succeeded(Status: HRESULT): WINBOOL = proc Succeeded(Status: HRESULT): WINBOOL =
result = (Status and 0x80000000'i32) result = (Status and 0x80000000).WinBool
proc Failed(Status: HRESULT): WINBOOL = proc Failed(Status: HRESULT): WINBOOL =
result = (Status and 0x80000000'i32) result = (Status and 0x80000000).WinBool
proc IsError(Status: HRESULT): WINBOOL = proc IsError(Status: HRESULT): WINBOOL =
result = ord((int(Status) shr 31) == SEVERITY_ERROR) 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)) result = toU32((ze(SortId) shl 16) or ze(LangId))
proc MAKESORTLCID(LangId, SortId, SortVersion: int16): DWORD = 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 = proc LANGIDFROMLCID(LocaleId: LCID): int16 =
result = toU16(LocaleId) result = toU16(LocaleId)

View file

@ -16257,7 +16257,7 @@ proc COLUMN_REQUESTED_WIDTH*(column: PTreeViewColumn): int32 =
MaxWidth = column.max_width MaxWidth = column.max_width
else: else:
MaxWidth = column.requested_width 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 = proc DRAW_EXPANDERS*(tree_view: PTreeView): bool =
result = (not (FLAG_SET(tree_view, TREE_VIEW_IS_LIST))) and result = (not (FLAG_SET(tree_view, TREE_VIEW_IS_LIST))) and

View file

@ -878,10 +878,10 @@ proc get_tab*(tab_array: PTabArray, tab_index: gint,
proc get_positions_in_pixels*(tab_array: PTabArray): gboolean{.cdecl, proc get_positions_in_pixels*(tab_array: PTabArray): gboolean{.cdecl,
dynlib: lib, importc: "pango_tab_array_get_positions_in_pixels".} dynlib: lib, importc: "pango_tab_array_get_positions_in_pixels".}
proc ASCENT*(rect: TRectangle): int32 = proc ASCENT*(rect: TRectangle): int32 =
result = - int(rect.y) result = -rect.y
proc DESCENT*(rect: TRectangle): int32 = proc DESCENT*(rect: TRectangle): int32 =
result = int(rect.y) + int(rect.height) result = (rect.y) + (rect.height)
proc LBEARING*(rect: TRectangle): int32 = proc LBEARING*(rect: TRectangle): int32 =
result = rect.x result = rect.x

View file

@ -280,9 +280,9 @@ else:
const const
LibName = "libSDL.so(|.1|.0)" LibName = "libSDL.so(|.1|.0)"
const const
MAJOR_VERSION* = 1'i8 MAJOR_VERSION* = 1
MINOR_VERSION* = 2'i8 MINOR_VERSION* = 2
PATCHLEVEL* = 11'i8 # SDL.h constants PATCHLEVEL* = 11 # SDL.h constants
INIT_TIMER* = 0x00000001 INIT_TIMER* = 0x00000001
INIT_AUDIO* = 0x00000010 INIT_AUDIO* = 0x00000010
INIT_VIDEO* = 0x00000020 INIT_VIDEO* = 0x00000020
@ -2523,8 +2523,8 @@ proc AllocSurface(flags: int32, width, height, depth: int,
AMask) AMask)
proc MustLock(Surface: PSurface): bool = proc MustLock(Surface: PSurface): bool =
Result = ((surface[] .offset != 0) or Result = ((surface[].offset != 0) or
((surface[] .flags and (HWSURFACE or ASYNCBLIT or RLEACCEL)) != 0)) ((surface[].flags and (HWSURFACE or ASYNCBLIT or RLEACCEL)) != 0))
proc LockMutex(mutex: Pmutex): int = proc LockMutex(mutex: Pmutex): int =
Result = mutexP(mutex) Result = mutexP(mutex)

View file

@ -141,9 +141,9 @@ else:
const const
ImageLibName = "libSDL_image.so" ImageLibName = "libSDL_image.so"
const const
IMAGE_MAJOR_VERSION* = 1'i8 IMAGE_MAJOR_VERSION* = 1
IMAGE_MINOR_VERSION* = 2'i8 IMAGE_MINOR_VERSION* = 2
IMAGE_PATCHLEVEL* = 5'i8 IMAGE_PATCHLEVEL* = 5
# This macro can be used to fill a version structure with the compile-time # This macro can be used to fill a version structure with the compile-time
# version of the SDL_image library. # version of the SDL_image library.

View file

@ -161,9 +161,9 @@ else:
const const
MixerLibName = "libSDL_mixer.so" MixerLibName = "libSDL_mixer.so"
const const
MAJOR_VERSION* = 1'i8 MAJOR_VERSION* = 1
MINOR_VERSION* = 2'i8 MINOR_VERSION* = 2
PATCHLEVEL* = 7'i8 # Backwards compatibility PATCHLEVEL* = 7 # Backwards compatibility
CHANNELS* = 8 # Good default values for a PC soundcard CHANNELS* = 8 # Good default values for a PC soundcard
DEFAULT_FREQUENCY* = 22050 DEFAULT_FREQUENCY* = 22050

View file

@ -15,9 +15,9 @@ else:
const const
MixerLibName = "libSDL_mixer.so" MixerLibName = "libSDL_mixer.so"
const const
MAJOR_VERSION* = 1'i8 MAJOR_VERSION* = 1
MINOR_VERSION* = 2'i8 MINOR_VERSION* = 2
PATCHLEVEL* = 7'i8 # Backwards compatibility PATCHLEVEL* = 7 # Backwards compatibility
CHANNELS* = 8 # Good default values for a PC soundcard CHANNELS* = 8 # Good default values for a PC soundcard
DEFAULT_FREQUENCY* = 22050 DEFAULT_FREQUENCY* = 22050

View file

@ -122,9 +122,9 @@ else:
const const
NetLibName = "libSDL_net.so" NetLibName = "libSDL_net.so"
const #* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL * const #* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL *
MAJOR_VERSION* = 1'i8 MAJOR_VERSION* = 1
MINOR_VERSION* = 2'i8 MINOR_VERSION* = 2
PATCHLEVEL* = 5'i8 # SDL_Net.h constants PATCHLEVEL* = 5 # SDL_Net.h constants
#* Resolve a host name and port to an IP address in network form. #* Resolve a host name and port to an IP address in network form.
# If the function succeeds, it will return 0. # If the function succeeds, it will return 0.
# If the host couldn't be resolved, the host portion of the returned # If the host couldn't be resolved, the host portion of the returned

View file

@ -165,9 +165,9 @@ else:
const const
ttfLibName = "libSDL_ttf.so(|.1|.0)" ttfLibName = "libSDL_ttf.so(|.1|.0)"
const const
MAJOR_VERSION* = 2'i8 MAJOR_VERSION* = 2
MINOR_VERSION* = 0'i8 MINOR_VERSION* = 0
PATCHLEVEL* = 8'i8 # Backwards compatibility PATCHLEVEL* = 8 # Backwards compatibility
STYLE_NORMAL* = 0x00000000 STYLE_NORMAL* = 0x00000000
STYLE_BOLD* = 0x00000001 STYLE_BOLD* = 0x00000001

View file

@ -171,9 +171,9 @@ proc filter_deblocking*(): PFilter{.cdecl,
# SMPEG.h # SMPEG.h
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
const const
MAJOR_VERSION* = 0'i8 MAJOR_VERSION* = 0
MINOR_VERSION* = 4'i8 MINOR_VERSION* = 4
PATCHLEVEL* = 2'i8 PATCHLEVEL* = 2
type type
TVersion*{.final.} = object TVersion*{.final.} = object

View file

@ -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 get_crc_table*(): pointer{.cdecl, dynlib: libz, importc: "get_crc_table".}
proc deflateInit(strm: var TZStream, level: int32): int32 = 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 = 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, proc deflateInit2(strm: var TZStream,
level, `method`, windowBits, memLevel, level, `method`, windowBits, memLevel,
strategy: int32): int32 = strategy: int32): int32 =
result = deflateInit2u(strm, level, `method`, windowBits, memLevel, 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 = 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.} = proc zlibAllocMem*(AppData: Pointer, Items, Size: int): Pointer {.cdecl.} =
result = Alloc(Items * Size) result = Alloc(Items * Size)

View file

@ -10,7 +10,7 @@ import
osproc, osproc,
cairowin32, cairoxlib, cairowin32, cairoxlib,
gl, glut, glu, glx, glext, wingl, 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") writeln(stdout, "test compilation of binding modules")

View file

@ -1,12 +1,11 @@
version 0.9.0 version 0.9.0
============= =============
- deprecate ``var x, y = 0`` as it's confusing for tuple consistency
- finish support for unsigned ints: - finish support for unsigned ints:
- document new type conversion rules - support more unsigned operations
- test codegen - test codegen
- provide ``$`` for unsigned ints
Debug GC session:
- test sequence of closures; especially that the GC does not leak for those! - test sequence of closures; especially that the GC does not leak for those!
New pragmas: New pragmas:
@ -15,8 +14,6 @@ New pragmas:
- document destructors - document destructors
- ``borrow`` needs to take type classes into account - ``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 - introduce ``;`` to the parser
- make use of ``tyIter`` to fix the implicit items/pairs issue - make use of ``tyIter`` to fix the implicit items/pairs issue
- ``=`` should be overloadable; requires specialization for ``=`` - ``=`` should be overloadable; requires specialization for ``=``
@ -50,7 +47,10 @@ version 0.9.XX
- document it - document it
- fix exception handling - 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 - document nimdoc properly finally
- make 'clamp' a magic for the range stuff
- implement a warning message for shadowed 'result' variable - implement a warning message for shadowed 'result' variable
- implement the high level optimizer - implement the high level optimizer
- change overloading resolution - change overloading resolution
@ -101,7 +101,7 @@ Library
newSeq(result, a.len) newSeq(result, a.len)
for i in 0..a.len-1: result[i] = a[i] for i in 0..a.len-1: result[i] = a[i]
--> ensure @[] calls the array version! --> ensure @[] still calls the array version!
Low priority Low priority
@ -147,7 +147,6 @@ Further optimization ideas
Version 2 and beyond Version 2 and beyond
==================== ====================
- shared memory heap: ``shared ref`` etc. The only hard part in the GC is to - 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 "stop the world". However, it may be worthwhile to generate explicit
(or implicit) syncGC() calls in loops. Automatic loop injection seems (or implicit) syncGC() calls in loops. Automatic loop injection seems

View file

@ -87,7 +87,11 @@ Changes affecting backwards compatibility
- Deprecated the ``ssl`` module. - Deprecated the ``ssl`` module.
- Deprecated ``nimrod pretty`` as it never worked good enough and has some - Deprecated ``nimrod pretty`` as it never worked good enough and has some
inherent problems. 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 Compiler Additions
@ -123,6 +127,7 @@ Language Additions
- The apostrophe in type suffixes for numerical literal is now optional. - The apostrophe in type suffixes for numerical literal is now optional.
- Unsigned integer types have been added. - Unsigned integer types have been added.
- The integer promotion rules changed. - 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 2012-02-09 Version 0.8.14 released