changed integer promotion rules; breaks bootstrapping and lots of code
This commit is contained in:
parent
36247e0947
commit
4fbba0a65a
42 changed files with 643 additions and 261 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,6 @@ 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]
|
||||||
|
|
||||||
|
|
@ -93,6 +92,34 @@ when false:
|
||||||
result = copyType(ti, ti.owner, false)
|
result = copyType(ti, ti.owner, false)
|
||||||
result.n = literal
|
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))
|
||||||
result = StrTableGet(compilerprocs, ident)
|
result = StrTableGet(compilerprocs, ident)
|
||||||
|
|
|
||||||
79
compiler/saturate.nim
Normal file
79
compiler/saturate.nim
Normal 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)
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,9 @@ 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:
|
||||||
|
markIndirect(c, result.sym)
|
||||||
|
if isGenericRoutine(result.sym):
|
||||||
LocalError(n.info, errInstantiateXExplicitely, s.name.s)
|
LocalError(n.info, errInstantiateXExplicitely, s.name.s)
|
||||||
of skConst:
|
of skConst:
|
||||||
markUsed(n, s)
|
markUsed(n, s)
|
||||||
|
|
@ -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])
|
||||||
|
|
||||||
proc checkConvertible(info: TLineInfo, castDest, src: PType) =
|
|
||||||
const
|
const
|
||||||
IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64}
|
IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64}
|
||||||
|
|
||||||
|
proc checkConvertible(info: TLineInfo, castDest, src: PType) =
|
||||||
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:
|
||||||
|
|
|
||||||
|
|
@ -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,8 +27,15 @@ 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
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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``.
|
||||||
|
|
|
||||||
|
|
@ -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]
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -175,7 +175,7 @@ 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
|
||||||
|
|
@ -198,12 +198,9 @@ proc isLeapYear(year: int): bool =
|
||||||
|
|
||||||
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,
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ 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)]
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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 {.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
13
todo.txt
13
todo.txt
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue