mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-12 06:18:51 +00:00
committed by
Andreas Rumpf
parent
8407a57499
commit
afbcd1b330
@@ -10,7 +10,9 @@
|
||||
# abstract syntax tree + symbol table
|
||||
|
||||
import
|
||||
lineinfos, hashes, options, ropes, idents, idgen
|
||||
lineinfos, hashes, options, ropes, idents, idgen, int128
|
||||
|
||||
export int128
|
||||
|
||||
type
|
||||
TCallingConvention* = enum
|
||||
@@ -1055,7 +1057,7 @@ template `[]`*(n: Indexable, i: BackwardsIndex): Indexable = n[n.len - i.int]
|
||||
template `[]=`*(n: Indexable, i: BackwardsIndex; x: Indexable) = n[n.len - i.int] = x
|
||||
|
||||
when defined(useNodeIds):
|
||||
const nodeIdToDebug* = -1 # 299750 # 300761 #300863 # 300879
|
||||
const nodeIdToDebug* = 2322967# 2322968
|
||||
var gNodeId: int
|
||||
|
||||
proc newNode*(kind: TNodeKind): PNode =
|
||||
@@ -1233,10 +1235,48 @@ proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode =
|
||||
result = newNode(kind)
|
||||
result.intVal = intVal
|
||||
|
||||
proc newIntTypeNode*(kind: TNodeKind, intVal: BiggestInt, typ: PType): PNode =
|
||||
result = newIntNode(kind, intVal)
|
||||
proc newIntNode*(kind: TNodeKind, intVal: Int128): PNode =
|
||||
result = newNode(kind)
|
||||
result.intVal = castToInt64(intVal)
|
||||
|
||||
proc lastSon*(n: PType): PType = n.sons[^1]
|
||||
|
||||
proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
|
||||
## Used throughout the compiler code to test whether a type tree contains or
|
||||
## doesn't contain a specific type/types - it is often the case that only the
|
||||
## last child nodes of a type tree need to be searched. This is a really hot
|
||||
## path within the compiler!
|
||||
result = t
|
||||
while result.kind in kinds: result = lastSon(result)
|
||||
|
||||
proc newIntTypeNode*(intVal: BiggestInt, typ: PType): PNode =
|
||||
|
||||
# this is dirty. abstractVarRange isn't defined yet and therefor it
|
||||
# is duplicated here.
|
||||
const abstractVarRange = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
|
||||
tyTypeDesc, tyAlias, tyInferred, tySink, tyOwned}
|
||||
case skipTypes(typ, abstractVarRange).kind
|
||||
of tyInt: result = newNode(nkIntLit)
|
||||
of tyInt8: result = newNode(nkInt8Lit)
|
||||
of tyInt16: result = newNode(nkInt16Lit)
|
||||
of tyInt32: result = newNode(nkInt32Lit)
|
||||
of tyInt64: result = newNode(nkInt64Lit)
|
||||
of tyChar: result = newNode(nkCharLit)
|
||||
of tyUInt: result = newNode(nkUIntLit)
|
||||
of tyUInt8: result = newNode(nkUInt8Lit)
|
||||
of tyUInt16: result = newNode(nkUInt16Lit)
|
||||
of tyUInt32: result = newNode(nkUInt32Lit)
|
||||
of tyUInt64: result = newNode(nkUInt64Lit)
|
||||
else: # tyBool, tyEnum
|
||||
# XXX: does this really need to be the kind nkIntLit?
|
||||
result = newNode(nkIntLit)
|
||||
result.intVal = intVal
|
||||
result.typ = typ
|
||||
|
||||
proc newIntTypeNode*(intVal: Int128, typ: PType): PNode =
|
||||
# XXX: introduce range check
|
||||
newIntTypeNode(castToInt64(intVal), typ)
|
||||
|
||||
proc newFloatNode*(kind: TNodeKind, floatVal: BiggestFloat): PNode =
|
||||
result = newNode(kind)
|
||||
result.floatVal = floatVal
|
||||
@@ -1325,7 +1365,6 @@ proc sonsLen*(n: PType): int = n.sons.len
|
||||
proc len*(n: PType): int = n.sons.len
|
||||
proc sonsLen*(n: PNode): int = n.sons.len
|
||||
proc lastSon*(n: PNode): PNode = n.sons[^1]
|
||||
proc lastSon*(n: PType): PType = n.sons[^1]
|
||||
|
||||
proc assignType*(dest, src: PType) =
|
||||
dest.kind = src.kind
|
||||
@@ -1421,14 +1460,6 @@ proc initNodeTable*(x: var TNodeTable) =
|
||||
x.counter = 0
|
||||
newSeq(x.data, StartSize)
|
||||
|
||||
proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
|
||||
## Used throughout the compiler code to test whether a type tree contains or
|
||||
## doesn't contain a specific type/types - it is often the case that only the
|
||||
## last child nodes of a type tree need to be searched. This is a really hot
|
||||
## path within the compiler!
|
||||
result = t
|
||||
while result.kind in kinds: result = lastSon(result)
|
||||
|
||||
proc skipTypes*(t: PType, kinds: TTypeKinds; maxIters: int): PType =
|
||||
result = t
|
||||
var i = maxIters
|
||||
@@ -1604,14 +1635,25 @@ proc hasSubnodeWith*(n: PNode, kind: TNodeKind): bool =
|
||||
return true
|
||||
result = false
|
||||
|
||||
proc getInt*(a: PNode): BiggestInt =
|
||||
proc getInt*(a: PNode): Int128 =
|
||||
case a.kind
|
||||
of nkCharLit..nkUInt64Lit: result = a.intVal
|
||||
of nkCharLit, nkUIntLit..nkUInt64Lit:
|
||||
result = toInt128(cast[uint64](a.intVal))
|
||||
of nkInt8Lit..nkInt64Lit:
|
||||
result = toInt128(a.intVal)
|
||||
of nkIntLit:
|
||||
# XXX: enable this assert
|
||||
# assert a.typ.kind notin {tyChar, tyUint..tyUInt64}
|
||||
result = toInt128(a.intVal)
|
||||
else:
|
||||
raiseRecoverableError("cannot extract number from invalid AST node")
|
||||
|
||||
proc getInt64*(a: PNode): int64 {.deprecated: "use getInt".} =
|
||||
case a.kind
|
||||
of nkCharLit, nkUIntLit..nkUInt64Lit, nkIntLit..nkInt64Lit:
|
||||
result = a.intVal
|
||||
else:
|
||||
raiseRecoverableError("cannot extract number from invalid AST node")
|
||||
#internalError(a.info, "getInt")
|
||||
#doAssert false, "getInt"
|
||||
#result = 0
|
||||
|
||||
proc getFloat*(a: PNode): BiggestFloat =
|
||||
case a.kind
|
||||
|
||||
@@ -92,7 +92,7 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
|
||||
let ty = skipTypes(a.t, abstractVar+{tyPtr})
|
||||
case ty.kind
|
||||
of tyArray:
|
||||
let first = firstOrd(p.config, ty)
|
||||
let first = toInt64(firstOrd(p.config, ty))
|
||||
if first == 0:
|
||||
result = "($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)]
|
||||
else:
|
||||
|
||||
@@ -30,6 +30,9 @@ proc intLiteral(i: BiggestInt): Rope =
|
||||
else:
|
||||
result = ~"(IL64(-9223372036854775807) - IL64(1))"
|
||||
|
||||
proc intLiteral(i: Int128): Rope =
|
||||
intLiteral(toInt64(i))
|
||||
|
||||
proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
|
||||
case n.kind
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
@@ -1436,7 +1439,7 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
|
||||
if d.k == locNone:
|
||||
getTemp(p, n.typ, d)
|
||||
# generate call to newSeq before adding the elements per hand:
|
||||
let L = int(lengthOrd(p.config, n.sons[1].typ))
|
||||
let L = toInt(lengthOrd(p.config, n.sons[1].typ))
|
||||
if p.config.selectedGC == gcDestructors:
|
||||
let seqtype = n.typ
|
||||
linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n",
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# included from cgen.nim
|
||||
|
||||
## This include file contains the logic to produce constant string
|
||||
## and seq literals. The code here is responsible that
|
||||
## ``const x = ["a", "b"]`` works without hidden runtime creation code.
|
||||
@@ -19,7 +21,7 @@ template detectVersion(field, corename) =
|
||||
if core == nil or core.kind != skConst:
|
||||
m.g.field = 1
|
||||
else:
|
||||
m.g.field = int ast.getInt(core.ast)
|
||||
m.g.field = toInt(ast.getInt(core.ast))
|
||||
result = m.g.field
|
||||
|
||||
proc detectStrVersion(m: BModule): int =
|
||||
|
||||
@@ -246,10 +246,10 @@ proc genGotoState(p: BProc, n: PNode) =
|
||||
lineF(p, cpsStmts, " goto BeforeRet_;$n", [])
|
||||
var statesCounter = lastOrd(p.config, n.sons[0].typ)
|
||||
if n.len >= 2 and n[1].kind == nkIntLit:
|
||||
statesCounter = n[1].intVal
|
||||
statesCounter = getInt(n[1])
|
||||
let prefix = if n.len == 3 and n[2].kind == nkStrLit: n[2].strVal.rope
|
||||
else: rope"STATE"
|
||||
for i in 0i64 .. statesCounter:
|
||||
for i in 0i64 .. toInt64(statesCounter):
|
||||
lineF(p, cpsStmts, "case $2: goto $1$2;$n", [prefix, rope(i)])
|
||||
lineF(p, cpsStmts, "}$n", [])
|
||||
|
||||
@@ -494,7 +494,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||
if aSize > 10_000:
|
||||
localError(p.config, it.info,
|
||||
"case statement has too many cases for computed goto"); return
|
||||
arraySize = aSize.int
|
||||
arraySize = toInt(aSize)
|
||||
if firstOrd(p.config, it.sons[0].typ) != 0:
|
||||
localError(p.config, it.info,
|
||||
"case statement has to start at 0 for computed goto"); return
|
||||
@@ -527,7 +527,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||
return
|
||||
|
||||
let val = getOrdValue(it.sons[j])
|
||||
lineF(p, cpsStmts, "TMP$#_:$n", [intLiteral(val+id+1)])
|
||||
lineF(p, cpsStmts, "TMP$#_:$n", [intLiteral(toInt64(val)+id+1)])
|
||||
|
||||
genStmts(p, it.lastSon)
|
||||
|
||||
@@ -1211,7 +1211,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
|
||||
var t = skipTypes(objtype, abstractVar)
|
||||
assert t.kind == tyObject
|
||||
discard genTypeInfo(p.module, t, a.lode.info)
|
||||
var L = lengthOrd(p.config, field.typ)
|
||||
var L = toInt64(lengthOrd(p.config, field.typ))
|
||||
if not containsOrIncl(p.module.declaredThings, field.id):
|
||||
appcg(p.module, cfsVars, "extern $1",
|
||||
[discriminatorTableDecl(p.module, t, field)])
|
||||
|
||||
@@ -805,7 +805,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
|
||||
let foo = getTypeDescAux(m, t.sons[0], check)
|
||||
addf(m.s[cfsTypes], "typedef $1 $2[1];$n", [foo, result])
|
||||
of tyArray:
|
||||
var n: BiggestInt = lengthOrd(m.config, t)
|
||||
var n: BiggestInt = toInt64(lengthOrd(m.config, t))
|
||||
if n <= 0: n = 1 # make an array of at least one element
|
||||
result = getTypeName(m, origTyp, sig)
|
||||
m.typeCache[sig] = result
|
||||
@@ -1047,6 +1047,8 @@ proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): Rope =
|
||||
internalError(m.config, d.info, "anonymous obj with discriminator")
|
||||
result = "NimDT_$1_$2" % [rope($hashType(objtype)), rope(d.name.s.mangle)]
|
||||
|
||||
proc rope(arg: Int128): Rope = rope($arg)
|
||||
|
||||
proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): Rope =
|
||||
discard cgsym(m, "TNimNode")
|
||||
var tmp = discriminatorTableName(m, objtype, d)
|
||||
@@ -1105,8 +1107,8 @@ proc genObjectFields(m: BModule, typ, origType: PType, n: PNode, expr: Rope;
|
||||
internalError(m.config, b.info, "genObjectFields; nkOfBranch broken")
|
||||
for j in 0 .. sonsLen(b) - 2:
|
||||
if b.sons[j].kind == nkRange:
|
||||
var x = int(getOrdValue(b.sons[j].sons[0]))
|
||||
var y = int(getOrdValue(b.sons[j].sons[1]))
|
||||
var x = toInt(getOrdValue(b.sons[j].sons[0]))
|
||||
var y = toInt(getOrdValue(b.sons[j].sons[1]))
|
||||
while x <= y:
|
||||
addf(m.s[cfsTypeInit3], "$1[$2] = &$3;$n", [tmp, rope(x), tmp2])
|
||||
inc(x)
|
||||
|
||||
@@ -113,6 +113,9 @@ proc cgFormatValue(result: var string; value: string): void =
|
||||
proc cgFormatValue(result: var string; value: BiggestInt): void =
|
||||
result.addInt value
|
||||
|
||||
proc cgFormatValue(result: var string; value: Int128): void =
|
||||
result.addInt128 value
|
||||
|
||||
# TODO: please document
|
||||
macro ropecg(m: BModule, frmt: static[FormatStr], args: untyped): Rope =
|
||||
args.expectKind nnkBracket
|
||||
|
||||
@@ -174,7 +174,7 @@ proc newStateAssgn(ctx: var Ctx, toValue: PNode): PNode =
|
||||
proc newStateAssgn(ctx: var Ctx, stateNo: int = -2): PNode =
|
||||
# Creates state assignment:
|
||||
# :state = stateNo
|
||||
ctx.newStateAssgn(newIntTypeNode(nkIntLit, stateNo, ctx.g.getSysType(TLineInfo(), tyInt)))
|
||||
ctx.newStateAssgn(newIntTypeNode(stateNo, ctx.g.getSysType(TLineInfo(), tyInt)))
|
||||
|
||||
proc newEnvVar(ctx: var Ctx, name: string, typ: PType): PSym =
|
||||
result = newSym(skVar, getIdent(ctx.g.cache, name), ctx.fn, ctx.fn.info)
|
||||
@@ -359,7 +359,7 @@ proc addElseToExcept(ctx: var Ctx, n: PNode) =
|
||||
block: # :unrollFinally = true
|
||||
branchBody.add(newTree(nkAsgn,
|
||||
ctx.newUnrollFinallyAccess(n.info),
|
||||
newIntTypeNode(nkIntLit, 1, ctx.g.getSysType(n.info, tyBool))))
|
||||
newIntTypeNode(1, ctx.g.getSysType(n.info, tyBool))))
|
||||
|
||||
block: # :curExc = getCurrentException()
|
||||
branchBody.add(newTree(nkAsgn,
|
||||
@@ -832,7 +832,7 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
|
||||
block: # :unrollFinally = true
|
||||
let asgn = newNodeI(nkAsgn, n.info)
|
||||
asgn.add(ctx.newUnrollFinallyAccess(n.info))
|
||||
asgn.add(newIntTypeNode(nkIntLit, 1, ctx.g.getSysType(n.info, tyBool)))
|
||||
asgn.add(newIntTypeNode(1, ctx.g.getSysType(n.info, tyBool)))
|
||||
result.add(asgn)
|
||||
|
||||
if n[0].kind != nkEmpty:
|
||||
@@ -1162,7 +1162,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
|
||||
let cond = newTree(nkCall,
|
||||
ctx.g.getSysMagic(info, "==", mEqI).newSymNode(),
|
||||
ctx.newStateAccess(),
|
||||
newIntTypeNode(nkIntLit, 0, intTyp))
|
||||
newIntTypeNode(0, intTyp))
|
||||
cond.typ = boolTyp
|
||||
|
||||
let raiseStmt = newTree(nkRaiseStmt, ctx.g.emptyNode)
|
||||
@@ -1174,7 +1174,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
|
||||
block:
|
||||
let cond = newTree(nkCall,
|
||||
ctx.g.getSysMagic(info, "<", mLtI).newSymNode,
|
||||
newIntTypeNode(nkIntLit, 0, intTyp),
|
||||
newIntTypeNode(0, intTyp),
|
||||
ctx.newStateAccess())
|
||||
cond.typ = boolTyp
|
||||
|
||||
@@ -1186,7 +1186,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
|
||||
let cond = newTree(nkCall,
|
||||
ctx.g.getSysMagic(info, "<", mLtI).newSymNode,
|
||||
ctx.newStateAccess(),
|
||||
newIntTypeNode(nkIntLit, 0, intTyp))
|
||||
newIntTypeNode(0, intTyp))
|
||||
cond.typ = boolTyp
|
||||
|
||||
let negateState = newTree(nkCall,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
## This module implements the 'implies' relation for guards.
|
||||
|
||||
import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer, idents,
|
||||
saturate, modulegraphs, options, lineinfos
|
||||
saturate, modulegraphs, options, lineinfos, int128
|
||||
|
||||
const
|
||||
someEq = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
|
||||
@@ -522,7 +522,7 @@ proc geImpliesIn(x, c, aSet: PNode): TImplication =
|
||||
var value = newIntNode(c.kind, c.intVal)
|
||||
let max = lastOrd(nil, x.typ)
|
||||
# don't iterate too often:
|
||||
if max - value.intVal < 1000:
|
||||
if max - getInt(value) < toInt128(1000):
|
||||
var i, pos, neg: int
|
||||
while value.intVal <= max:
|
||||
if inSet(aSet, value): inc pos
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
## This module is for compiler internal use only. For reliable error
|
||||
## messages and range checks, the compiler needs a data type that can
|
||||
## hold all from ``low(BiggestInt)`` to ``high(BiggestUInt)``, This
|
||||
## type is for that purpose.
|
||||
|
||||
from math import trunc
|
||||
|
||||
type
|
||||
Int128* = object
|
||||
@@ -24,6 +29,7 @@ const
|
||||
Ten* = Int128(udata: [10'u32,0,0,0])
|
||||
Min = Int128(udata: [0'u32,0,0,0x80000000'u32])
|
||||
Max = Int128(udata: [high(uint32),high(uint32),high(uint32),uint32(high(int32))])
|
||||
NegOne* = Int128(udata: [0xffffffff'u32,0xffffffff'u32,0xffffffff'u32,0xffffffff'u32])
|
||||
|
||||
template low*(t: typedesc[Int128]): Int128 = Min
|
||||
template high*(t: typedesc[Int128]): Int128 = Max
|
||||
@@ -74,11 +80,85 @@ proc toInt64*(arg: Int128): int64 =
|
||||
|
||||
cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
|
||||
|
||||
proc toInt32*(arg: Int128): int32 =
|
||||
if isNegative(arg):
|
||||
assert(arg.sdata(3) == -1, "out of range")
|
||||
assert(arg.sdata(2) == -1, "out of range")
|
||||
assert(arg.sdata(1) == -1, "out of range")
|
||||
else:
|
||||
assert(arg.sdata(3) == 0, "out of range")
|
||||
assert(arg.sdata(2) == 0, "out of range")
|
||||
assert(arg.sdata(1) == 0, "out of range")
|
||||
|
||||
arg.sdata(0)
|
||||
|
||||
proc toInt16*(arg: Int128): int16 =
|
||||
if isNegative(arg):
|
||||
assert(arg.sdata(3) == -1, "out of range")
|
||||
assert(arg.sdata(2) == -1, "out of range")
|
||||
assert(arg.sdata(1) == -1, "out of range")
|
||||
else:
|
||||
assert(arg.sdata(3) == 0, "out of range")
|
||||
assert(arg.sdata(2) == 0, "out of range")
|
||||
assert(arg.sdata(1) == 0, "out of range")
|
||||
|
||||
int16(arg.sdata(0))
|
||||
|
||||
proc toInt8*(arg: Int128): int8 =
|
||||
if isNegative(arg):
|
||||
assert(arg.sdata(3) == -1, "out of range")
|
||||
assert(arg.sdata(2) == -1, "out of range")
|
||||
assert(arg.sdata(1) == -1, "out of range")
|
||||
else:
|
||||
assert(arg.sdata(3) == 0, "out of range")
|
||||
assert(arg.sdata(2) == 0, "out of range")
|
||||
assert(arg.sdata(1) == 0, "out of range")
|
||||
|
||||
int8(arg.sdata(0))
|
||||
|
||||
proc toInt*(arg: Int128): int =
|
||||
when sizeof(int) == 4:
|
||||
cast[int](toInt32(arg))
|
||||
else:
|
||||
cast[int](toInt64(arg))
|
||||
|
||||
proc toUInt64*(arg: Int128): uint64 =
|
||||
assert(arg.udata[3] == 0)
|
||||
assert(arg.udata[2] == 0)
|
||||
bitconcat(arg.udata[1], arg.udata[0])
|
||||
|
||||
proc toUInt32*(arg: Int128): uint32 =
|
||||
assert(arg.udata[3] == 0)
|
||||
assert(arg.udata[2] == 0)
|
||||
assert(arg.udata[1] == 0)
|
||||
arg.udata[0]
|
||||
|
||||
proc toUInt16*(arg: Int128): uint16 =
|
||||
assert(arg.udata[3] == 0)
|
||||
assert(arg.udata[2] == 0)
|
||||
assert(arg.udata[1] == 0)
|
||||
uint16(arg.udata[0])
|
||||
|
||||
proc toUInt8*(arg: Int128): uint8 =
|
||||
assert(arg.udata[3] == 0)
|
||||
assert(arg.udata[2] == 0)
|
||||
assert(arg.udata[1] == 0)
|
||||
uint8(arg.udata[0])
|
||||
|
||||
proc toUInt*(arg: Int128): uint =
|
||||
when sizeof(int) == 4:
|
||||
cast[uint](toInt32(arg))
|
||||
else:
|
||||
cast[uint](toInt64(arg))
|
||||
|
||||
proc castToInt64*(arg: Int128): int64 =
|
||||
## Conversion to int64 without range check.
|
||||
cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
|
||||
|
||||
proc castToUInt64*(arg: Int128): uint64 =
|
||||
## Conversion to uint64 without range check.
|
||||
cast[uint64](bitconcat(arg.udata[1], arg.udata[0]))
|
||||
|
||||
proc addToHex(result: var string; arg: uint32) =
|
||||
for i in 0 ..< 8:
|
||||
let idx = (arg shr ((7-i) * 4)) and 0xf
|
||||
@@ -206,7 +286,6 @@ proc `shl`*(a: Int128, b: int): Int128 =
|
||||
result.udata[2] = 0
|
||||
result.udata[3] = a.udata[0] shl (b and 31)
|
||||
|
||||
|
||||
proc `+`*(a,b: Int128): Int128 =
|
||||
let tmp0 = uint64(a.udata[0]) + uint64(b.udata[0])
|
||||
result.udata[0] = cast[uint32](tmp0)
|
||||
@@ -319,7 +398,8 @@ proc fastLog2*(a: Int128): int =
|
||||
|
||||
proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
|
||||
assert(divisor != Zero)
|
||||
let isNegative = isNegative(dividend) xor isNegative(divisor)
|
||||
let isNegativeA = isNegative(dividend)
|
||||
let isNegativeB = isNegative(divisor)
|
||||
|
||||
var dividend = abs(dividend)
|
||||
let divisor = abs(divisor)
|
||||
@@ -351,8 +431,14 @@ proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
|
||||
|
||||
denominator = denominator shr 1
|
||||
|
||||
result.quotient = quotient
|
||||
result.remainder = dividend
|
||||
if isNegativeA xor isNegativeB:
|
||||
result.quotient = -quotient
|
||||
else:
|
||||
result.quotient = quotient
|
||||
if isNegativeB:
|
||||
result.remainder = -dividend
|
||||
else:
|
||||
result.remainder = dividend
|
||||
|
||||
proc `div`*(a,b: Int128): Int128 =
|
||||
let (a,b) = divMod(a,b)
|
||||
@@ -362,28 +448,32 @@ proc `mod`*(a,b: Int128): Int128 =
|
||||
let (a,b) = divMod(a,b)
|
||||
return b
|
||||
|
||||
proc `$`*(a: Int128): string =
|
||||
if a == Zero:
|
||||
result = "0"
|
||||
elif a == low(Int128):
|
||||
result = "-170141183460469231731687303715884105728"
|
||||
proc addInt128*(result: var string; value: Int128) =
|
||||
let initialSize = result.len
|
||||
if value == Zero:
|
||||
result.add "0"
|
||||
elif value == low(Int128):
|
||||
result.add "-170141183460469231731687303715884105728"
|
||||
else:
|
||||
let isNegative = isNegative(a)
|
||||
var a = abs(a)
|
||||
while a > Zero:
|
||||
let (quot, rem) = divMod(a, Ten)
|
||||
let isNegative = isNegative(value)
|
||||
var value = abs(value)
|
||||
while value > Zero:
|
||||
let (quot, rem) = divMod(value, Ten)
|
||||
result.add "0123456789"[rem.toInt64]
|
||||
a = quot
|
||||
value = quot
|
||||
if isNegative:
|
||||
result.add '-'
|
||||
|
||||
var i = 0
|
||||
var i = initialSize
|
||||
var j = high(result)
|
||||
while i < j:
|
||||
swap(result[i], result[j])
|
||||
i += 1
|
||||
j -= 1
|
||||
|
||||
proc `$`*(a: Int128): string =
|
||||
result.addInt128(a)
|
||||
|
||||
proc parseDecimalInt128*(arg: string, pos: int = 0): Int128 =
|
||||
assert(pos < arg.len)
|
||||
assert(arg[pos] in {'-','0'..'9'})
|
||||
@@ -435,6 +525,77 @@ proc `+`*(a: BiggestInt, b: Int128): Int128 =
|
||||
proc `+`*(a: Int128, b: BiggestInt): Int128 =
|
||||
a + toInt128(b)
|
||||
|
||||
proc toFloat64*(arg: Int128): float64 =
|
||||
let isNegative = isNegative(arg)
|
||||
let arg = abs(arg)
|
||||
|
||||
let a = float64(bitconcat(arg.udata[1], arg.udata[0]))
|
||||
let b = float64(bitconcat(arg.udata[3], arg.udata[2]))
|
||||
|
||||
result = a + 18446744073709551616'f64 * b # a + 2^64 * b
|
||||
if isNegative:
|
||||
result = -result
|
||||
|
||||
proc ldexp(x: float64, exp: cint): float64 {.importc: "ldexp", header: "<math.h>".}
|
||||
|
||||
template bitor(a,b,c: Int128): Int128 = bitor(bitor(a,b), c)
|
||||
|
||||
proc toInt128*(arg: float64): Int128 =
|
||||
let isNegative = arg < 0
|
||||
assert(arg < 0x47E0000000000000'f64, "out of range")
|
||||
assert(arg >= 0xC7E0000000000000'f64, "out of range")
|
||||
let v0 = ldexp(abs(arg), -100)
|
||||
let w0 = uint64(trunc(v0))
|
||||
let v1 = ldexp(v0 - float64(w0), 50)
|
||||
let w1 = uint64(trunc(v1))
|
||||
let v2 = ldexp(v1 - float64(w1), 50)
|
||||
let w2 = uint64(trunc(v2))
|
||||
|
||||
let res = bitor(toInt128(w0) shl 100, toInt128(w1) shl 50, toInt128(w2))
|
||||
if isNegative:
|
||||
return -res
|
||||
else:
|
||||
return res
|
||||
|
||||
proc maskUInt64*(arg: Int128): Int128 {.noinit, inline.} =
|
||||
result.udata[0] = arg.udata[0]
|
||||
result.udata[1] = arg.udata[1]
|
||||
result.udata[2] = 0
|
||||
result.udata[3] = 0
|
||||
|
||||
proc maskUInt32*(arg: Int128): Int128 {.noinit, inline.} =
|
||||
result.udata[0] = arg.udata[0]
|
||||
result.udata[1] = 0
|
||||
result.udata[2] = 0
|
||||
result.udata[3] = 0
|
||||
|
||||
proc maskUInt16*(arg: Int128): Int128 {.noinit, inline.} =
|
||||
result.udata[0] = arg.udata[0] and 0xffff
|
||||
result.udata[1] = 0
|
||||
result.udata[2] = 0
|
||||
result.udata[3] = 0
|
||||
|
||||
proc maskUInt8*(arg: Int128): Int128 {.noinit, inline.} =
|
||||
result.udata[0] = arg.udata[0] and 0xff
|
||||
result.udata[1] = 0
|
||||
result.udata[2] = 0
|
||||
result.udata[3] = 0
|
||||
|
||||
proc maskBytes*(arg: Int128, numbytes: int): Int128 {.noinit.} =
|
||||
case numbytes
|
||||
of 1:
|
||||
return maskUInt8(arg)
|
||||
of 2:
|
||||
return maskUInt16(arg)
|
||||
of 4:
|
||||
return maskUInt32(arg)
|
||||
of 8:
|
||||
return maskUInt64(arg)
|
||||
else:
|
||||
assert(false, "masking only implemented for 1, 2, 4 and 8 bytes")
|
||||
|
||||
|
||||
|
||||
|
||||
when isMainModule:
|
||||
let (a,b) = divMod(Ten,Ten)
|
||||
|
||||
@@ -1173,7 +1173,7 @@ proc genCheckedFieldOp(p: PProc, n: PNode, addrTyp: PType, r: var TCompRes) =
|
||||
proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
var
|
||||
a, b: TCompRes
|
||||
first: BiggestInt
|
||||
first: Int128
|
||||
r.typ = etyBaseIndex
|
||||
let m = if n.kind == nkHiddenAddr: n.sons[0] else: n
|
||||
gen(p, m.sons[0], a)
|
||||
@@ -1182,8 +1182,8 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
let (x, tmp) = maybeMakeTemp(p, m[0], a)
|
||||
r.address = x
|
||||
var typ = skipTypes(m.sons[0].typ, abstractPtrs)
|
||||
if typ.kind == tyArray: first = firstOrd(p.config, typ.sons[0])
|
||||
else: first = 0
|
||||
if typ.kind == tyArray:
|
||||
first = firstOrd(p.config, typ.sons[0])
|
||||
if optBoundsCheck in p.options:
|
||||
useMagic(p, "chckIndx")
|
||||
r.res = "chckIndx($1, $2, $3.length+$2-1)-$2" % [b.res, rope(first), tmp]
|
||||
@@ -1612,7 +1612,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||
of tyBool:
|
||||
result = putToSeq("false", indirect)
|
||||
of tyArray:
|
||||
let length = int(lengthOrd(p.config, t))
|
||||
let length = toInt(lengthOrd(p.config, t))
|
||||
let e = elemType(t)
|
||||
let jsTyp = arrayTypeForElemType(e)
|
||||
if jsTyp.len > 0:
|
||||
|
||||
@@ -7,8 +7,12 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# included from jsgen.nim
|
||||
|
||||
## Type info generation for the JS backend.
|
||||
|
||||
proc rope(arg: Int128): Rope = rope($arg)
|
||||
|
||||
proc genTypeInfo(p: PProc, typ: PType): Rope
|
||||
proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
|
||||
var
|
||||
|
||||
@@ -933,7 +933,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
|
||||
|
||||
var loopBody = newNodeI(nkStmtList, body.info, 3)
|
||||
var whileLoop = newNodeI(nkWhileStmt, body.info, 2)
|
||||
whileLoop.sons[0] = newIntTypeNode(nkIntLit, 1, getSysType(g, body.info, tyBool))
|
||||
whileLoop.sons[0] = newIntTypeNode(1, getSysType(g, body.info, tyBool))
|
||||
whileLoop.sons[1] = loopBody
|
||||
result.add whileLoop
|
||||
|
||||
|
||||
@@ -288,7 +288,7 @@ proc setLenSeqCall(c: var TLiftCtx; t: PType; x, y: PNode): PNode =
|
||||
result = newTree(nkCall, newSymNode(op, x.info), x, lenCall)
|
||||
|
||||
proc forallElements(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
let i = declareCounter(c, body, firstOrd(c.g.config, t))
|
||||
let i = declareCounter(c, body, toInt64(firstOrd(c.g.config, t)))
|
||||
let whileLoop = genWhileLoop(c, i, x)
|
||||
let elemType = t.lastSon
|
||||
fillBody(c, elemType, whileLoop.sons[1], x.at(i, elemType),
|
||||
|
||||
@@ -330,7 +330,7 @@ proc newIntLit*(g: ModuleGraph; info: TLineInfo; value: BiggestInt): PNode =
|
||||
|
||||
proc genHigh*(g: ModuleGraph; n: PNode): PNode =
|
||||
if skipTypes(n.typ, abstractVar).kind == tyArray:
|
||||
result = newIntLit(g, n.info, lastOrd(g.config, skipTypes(n.typ, abstractVar)))
|
||||
result = newIntLit(g, n.info, toInt64(lastOrd(g.config, skipTypes(n.typ, abstractVar))))
|
||||
else:
|
||||
result = newNodeI(nkCall, n.info, 2)
|
||||
result.typ = getSysType(g, n.info, tyInt)
|
||||
@@ -339,7 +339,7 @@ proc genHigh*(g: ModuleGraph; n: PNode): PNode =
|
||||
|
||||
proc genLen*(g: ModuleGraph; n: PNode): PNode =
|
||||
if skipTypes(n.typ, abstractVar).kind == tyArray:
|
||||
result = newIntLit(g, n.info, lastOrd(g.config, skipTypes(n.typ, abstractVar)) + 1)
|
||||
result = newIntLit(g, n.info, toInt64(lastOrd(g.config, skipTypes(n.typ, abstractVar)) + 1))
|
||||
else:
|
||||
result = newNodeI(nkCall, n.info, 2)
|
||||
result.typ = getSysType(g, n.info, tyInt)
|
||||
|
||||
@@ -59,17 +59,17 @@ proc someInSet*(s: PNode, a, b: PNode): bool =
|
||||
result = false
|
||||
|
||||
proc toBitSet*(conf: ConfigRef; s: PNode, b: var TBitSet) =
|
||||
var first, j: BiggestInt
|
||||
var first, j: Int128
|
||||
first = firstOrd(conf, s.typ.sons[0])
|
||||
bitSetInit(b, int(getSize(conf, s.typ)))
|
||||
for i in 0 ..< sonsLen(s):
|
||||
if s.sons[i].kind == nkRange:
|
||||
j = getOrdValue(s.sons[i].sons[0], first)
|
||||
while j <= getOrdValue(s.sons[i].sons[1], first):
|
||||
bitSetIncl(b, j - first)
|
||||
bitSetIncl(b, toInt64(j - first))
|
||||
inc(j)
|
||||
else:
|
||||
bitSetIncl(b, getOrdValue(s.sons[i], first) - first)
|
||||
bitSetIncl(b, toInt64(getOrdValue(s.sons[i]) - first))
|
||||
|
||||
proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): PNode =
|
||||
var
|
||||
@@ -77,7 +77,7 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
|
||||
elemType: PType
|
||||
n: PNode
|
||||
elemType = settype.sons[0]
|
||||
first = firstOrd(conf, elemType)
|
||||
first = firstOrd(conf, elemType).toInt64
|
||||
result = newNodeI(nkCurly, info)
|
||||
result.typ = settype
|
||||
result.info = info
|
||||
@@ -90,7 +90,7 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
|
||||
inc(b)
|
||||
if (b >= len(s) * ElemSize) or not bitSetIn(s, b): break
|
||||
dec(b)
|
||||
let aa = newIntTypeNode(nkIntLit, a + first, elemType)
|
||||
let aa = newIntTypeNode(a + first, elemType)
|
||||
aa.info = info
|
||||
if a == b:
|
||||
addSon(result, aa)
|
||||
@@ -98,7 +98,7 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
|
||||
n = newNodeI(nkRange, info)
|
||||
n.typ = elemType
|
||||
addSon(n, aa)
|
||||
let bb = newIntTypeNode(nkIntLit, b + first, elemType)
|
||||
let bb = newIntTypeNode(b + first, elemType)
|
||||
bb.info = info
|
||||
addSon(n, bb)
|
||||
addSon(result, n)
|
||||
|
||||
@@ -330,8 +330,7 @@ proc ulitAux(g: TSrcGen; n: PNode, x: BiggestInt, size: int): string =
|
||||
if nfBase2 in n.flags: result = "0b" & toBin(x, size * 8)
|
||||
elif nfBase8 in n.flags: result = "0o" & toOct(x, size * 3)
|
||||
elif nfBase16 in n.flags: result = "0x" & toHex(x, size * 2)
|
||||
else: result = $x
|
||||
# XXX proper unsigned output!
|
||||
else: result = $cast[BiggestUInt](x)
|
||||
|
||||
proc atom(g: TSrcGen; n: PNode): string =
|
||||
when defined(nimpretty):
|
||||
|
||||
@@ -367,7 +367,7 @@ proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
|
||||
if n.typ != nil and n.typ.n == nil:
|
||||
result.flags.incl tfUnresolved
|
||||
result.n = newNode(nkRange, n.info, @[
|
||||
newIntTypeNode(nkIntLit, 0, intType),
|
||||
newIntTypeNode(0, intType),
|
||||
makeStaticExpr(c, nMinusOne(c, n))])
|
||||
|
||||
template rangeHasUnresolvedStatic*(t: PType): bool =
|
||||
@@ -391,8 +391,8 @@ proc makeRangeType*(c: PContext; first, last: BiggestInt;
|
||||
info: TLineInfo; intType: PType = nil): PType =
|
||||
let intType = if intType != nil: intType else: getSysType(c.graph, info, tyInt)
|
||||
var n = newNodeI(nkRange, info)
|
||||
addSon(n, newIntTypeNode(nkIntLit, first, intType))
|
||||
addSon(n, newIntTypeNode(nkIntLit, last, intType))
|
||||
addSon(n, newIntTypeNode(first, intType))
|
||||
addSon(n, newIntTypeNode(last, intType))
|
||||
result = newTypeS(tyRange, c)
|
||||
result.n = n
|
||||
addSonSkipIntLit(result, intType) # basetype of range
|
||||
|
||||
@@ -532,12 +532,12 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result.typ = newTypeS(tyArray, c)
|
||||
rawAddSon(result.typ, nil) # index type
|
||||
var
|
||||
firstIndex, lastIndex: BiggestInt = 0
|
||||
firstIndex, lastIndex: Int128
|
||||
indexType = getSysType(c.graph, n.info, tyInt)
|
||||
lastValidIndex = lastOrd(c.config, indexType)
|
||||
if sonsLen(n) == 0:
|
||||
rawAddSon(result.typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
|
||||
lastIndex = -1
|
||||
lastIndex = toInt128(-1)
|
||||
else:
|
||||
var x = n.sons[0]
|
||||
if x.kind == nkExprColonExpr and sonsLen(x) == 2:
|
||||
@@ -558,7 +558,7 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
#var typ = skipTypes(result.sons[0].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal})
|
||||
for i in 1 ..< sonsLen(n):
|
||||
if lastIndex == lastValidIndex:
|
||||
let validIndex = makeRangeType(c, firstIndex, lastValidIndex, n.info,
|
||||
let validIndex = makeRangeType(c, toInt64(firstIndex), toInt64(lastValidIndex), n.info,
|
||||
indexType)
|
||||
localError(c.config, n.info, "size of array exceeds range of index " &
|
||||
"type '$1' by $2 elements" % [typeToString(validIndex), $(n.len-i)])
|
||||
@@ -580,7 +580,7 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
addSonSkipIntLit(result.typ, typ)
|
||||
for i in 0 ..< result.len:
|
||||
result.sons[i] = fitNode(c, typ, result.sons[i], result.sons[i].info)
|
||||
result.typ.sons[0] = makeRangeType(c, firstIndex, lastIndex, n.info,
|
||||
result.typ.sons[0] = makeRangeType(c, toInt64(firstIndex), toInt64(lastIndex), n.info,
|
||||
indexType)
|
||||
|
||||
proc fixAbstractType(c: PContext, n: PNode) =
|
||||
@@ -1478,7 +1478,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if skipTypes(n.sons[1].typ, {tyGenericInst, tyRange, tyOrdinal, tyAlias, tySink}).kind in
|
||||
{tyInt..tyInt64}:
|
||||
let idx = getOrdValue(n.sons[1])
|
||||
if idx >= 0 and idx < len(arr): n.typ = arr.sons[int(idx)]
|
||||
if idx >= 0 and idx < len(arr): n.typ = arr.sons[toInt(idx)]
|
||||
else: localError(c.config, n.info, "invalid index value for tuple subscript")
|
||||
result = n
|
||||
else:
|
||||
|
||||
@@ -15,7 +15,12 @@ import
|
||||
platform, math, msgs, idents, renderer, types,
|
||||
commands, magicsys, modulegraphs, strtabs, lineinfos
|
||||
|
||||
proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
proc errorType*(g: ModuleGraph): PType =
|
||||
## creates a type representing an error state
|
||||
result = newType(tyError, g.owners[^1])
|
||||
result.flags.incl tfCheckedForDestructor
|
||||
|
||||
proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode {.deprecated: "intVal should be Int128".} =
|
||||
case skipTypes(n.typ, abstractVarRange).kind
|
||||
of tyInt:
|
||||
result = newIntNode(nkIntLit, intVal)
|
||||
@@ -35,6 +40,15 @@ proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
result.typ = n.typ
|
||||
result.info = n.info
|
||||
|
||||
proc newIntNodeT*(intVal: Int128, n: PNode; g: ModuleGraph): PNode =
|
||||
result = newIntTypeNode(intVal, n.typ)
|
||||
# See bug #6989. 'pred' et al only produce an int literal type if the
|
||||
# original type was 'int', not a distinct int etc.
|
||||
if n.typ.kind == tyInt:
|
||||
# access cache for the int lit type
|
||||
result.typ = getIntLitType(g, result)
|
||||
result.info = n.info
|
||||
|
||||
proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode; g: ModuleGraph): PNode =
|
||||
result = newFloatNode(nkFloatLit, floatVal)
|
||||
result.typ = n.typ
|
||||
@@ -50,65 +64,30 @@ proc getConstExpr*(m: PSym, n: PNode; g: ModuleGraph): PNode
|
||||
# expression
|
||||
proc evalOp*(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode
|
||||
|
||||
proc checkInRange(conf: ConfigRef; n: PNode, res: BiggestInt): bool =
|
||||
if res in firstOrd(conf, n.typ)..lastOrd(conf, n.typ):
|
||||
result = true
|
||||
proc checkInRange(conf: ConfigRef; n: PNode, res: Int128): bool =
|
||||
res in firstOrd(conf, n.typ)..lastOrd(conf, n.typ)
|
||||
|
||||
proc foldAdd(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
let res = a +% b
|
||||
if ((res xor a) >= 0'i64 or (res xor b) >= 0'i64) and
|
||||
checkInRange(g.config, n, res):
|
||||
proc foldAdd(a, b: Int128, n: PNode; g: ModuleGraph): PNode =
|
||||
let res = a + b
|
||||
if checkInRange(g.config, n, res):
|
||||
result = newIntNodeT(res, n, g)
|
||||
|
||||
proc foldSub*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
let res = a -% b
|
||||
if ((res xor a) >= 0'i64 or (res xor not b) >= 0'i64) and
|
||||
checkInRange(g.config, n, res):
|
||||
proc foldSub(a, b: Int128, n: PNode; g: ModuleGraph): PNode =
|
||||
let res = a - b
|
||||
if checkInRange(g.config, n, res):
|
||||
result = newIntNodeT(res, n, g)
|
||||
|
||||
proc foldUnarySub(a: BiggestInt, n: PNode, g: ModuleGraph): PNode =
|
||||
proc foldUnarySub(a: Int128, n: PNode, g: ModuleGraph): PNode =
|
||||
if a != firstOrd(g.config, n.typ):
|
||||
result = newIntNodeT(-a, n, g)
|
||||
|
||||
proc foldAbs*(a: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
proc foldAbs(a: Int128, n: PNode; g: ModuleGraph): PNode =
|
||||
if a != firstOrd(g.config, n.typ):
|
||||
result = newIntNodeT(abs(a), n, g)
|
||||
|
||||
proc foldMod*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
if b != 0'i64:
|
||||
result = newIntNodeT(a mod b, n, g)
|
||||
|
||||
proc foldModU*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
if b != 0'i64:
|
||||
result = newIntNodeT(a %% b, n, g)
|
||||
|
||||
proc foldDiv*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
if b != 0'i64 and (a != firstOrd(g.config, n.typ) or b != -1'i64):
|
||||
result = newIntNodeT(a div b, n, g)
|
||||
|
||||
proc foldDivU*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
if b != 0'i64:
|
||||
result = newIntNodeT(a /% b, n, g)
|
||||
|
||||
proc foldMul*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||
let res = a *% b
|
||||
let floatProd = toBiggestFloat(a) * toBiggestFloat(b)
|
||||
let resAsFloat = toBiggestFloat(res)
|
||||
|
||||
# Fast path for normal case: small multiplicands, and no info
|
||||
# is lost in either method.
|
||||
if resAsFloat == floatProd and checkInRange(g.config, n, res):
|
||||
return newIntNodeT(res, n, g)
|
||||
|
||||
# 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) and
|
||||
checkInRange(g.config, n, res):
|
||||
proc foldMul(a, b: Int128, n: PNode; g: ModuleGraph): PNode =
|
||||
let res = a * b
|
||||
if checkInRange(g.config, n, res):
|
||||
return newIntNodeT(res, n, g)
|
||||
|
||||
proc ordinalValToString*(a: PNode; g: ModuleGraph): string =
|
||||
@@ -119,7 +98,7 @@ proc ordinalValToString*(a: PNode; g: ModuleGraph): string =
|
||||
var t = skipTypes(a.typ, abstractRange)
|
||||
case t.kind
|
||||
of tyChar:
|
||||
result = $chr(int(x) and 0xff)
|
||||
result = $chr(toInt64(x) and 0xff)
|
||||
of tyEnum:
|
||||
var n = t.n
|
||||
for i in 0 ..< sonsLen(n):
|
||||
@@ -176,7 +155,7 @@ proc makeRangeF(typ: PType, first, last: BiggestFloat; g: ModuleGraph): PType =
|
||||
result.n = n
|
||||
addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
|
||||
|
||||
proc fitLiteral(c: ConfigRef, n: PNode): PNode =
|
||||
proc fitLiteral(c: ConfigRef, n: PNode): PNode {.deprecated: "no substitute".} =
|
||||
# Trim the literal value in order to make it fit in the destination type
|
||||
if n == nil:
|
||||
# `n` may be nil if the overflow check kicks in
|
||||
@@ -188,12 +167,9 @@ proc fitLiteral(c: ConfigRef, n: PNode): PNode =
|
||||
|
||||
let typ = n.typ.skipTypes(abstractRange)
|
||||
if typ.kind in tyUInt..tyUInt32:
|
||||
result.intVal = result.intVal and lastOrd(c, typ, fixedUnsigned=true)
|
||||
result.intVal = result.intVal and castToInt64(lastOrd(c, typ))
|
||||
|
||||
proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||
template doAndFit(op: untyped): untyped =
|
||||
# Implements wrap-around behaviour for unsigned types
|
||||
fitLiteral(g.config, op)
|
||||
# b and c may be nil
|
||||
result = nil
|
||||
case m
|
||||
@@ -201,45 +177,61 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||
of mChr: result = newIntNodeT(getInt(a), n, g)
|
||||
of mUnaryMinusI, mUnaryMinusI64: result = foldUnarySub(getInt(a), n, g)
|
||||
of mUnaryMinusF64: result = newFloatNodeT(- getFloat(a), n, g)
|
||||
of mNot: result = newIntNodeT(1 - getInt(a), n, g)
|
||||
of mNot: result = newIntNodeT(One - getInt(a), n, g)
|
||||
of mCard: result = newIntNodeT(nimsets.cardSet(g.config, a), n, g)
|
||||
of mBitnotI: result = doAndFit(newIntNodeT(not getInt(a), n, g))
|
||||
of mBitnotI:
|
||||
if n.typ.isUnsigned:
|
||||
result = newIntNodeT(bitnot(getInt(a)).maskBytes(int(n.typ.size)), n, g)
|
||||
else:
|
||||
result = newIntNodeT(bitnot(getInt(a)), n, g)
|
||||
of mLengthArray: result = newIntNodeT(lengthOrd(g.config, a.typ), n, g)
|
||||
of mLengthSeq, mLengthOpenArray, mXLenSeq, mLengthStr, mXLenStr:
|
||||
if a.kind == nkNilLit:
|
||||
result = newIntNodeT(0, n, g)
|
||||
result = newIntNodeT(Zero, n, g)
|
||||
elif a.kind in {nkStrLit..nkTripleStrLit}:
|
||||
result = newIntNodeT(len a.strVal, n, g)
|
||||
result = newIntNodeT(toInt128(a.strVal.len), n, g)
|
||||
else:
|
||||
result = newIntNodeT(sonsLen(a), n, g)
|
||||
result = newIntNodeT(toInt128(sonsLen(a)), n, g)
|
||||
of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away
|
||||
of mToFloat, mToBiggestFloat:
|
||||
result = newFloatNodeT(toFloat(int(getInt(a))), n, g)
|
||||
result = newFloatNodeT(toFloat64(getInt(a)), n, g)
|
||||
# XXX: Hides overflow/underflow
|
||||
of mToInt, mToBiggestInt: result = newIntNodeT(system.toInt(getFloat(a)), n, g)
|
||||
of mAbsF64: result = newFloatNodeT(abs(getFloat(a)), n, g)
|
||||
of mAbsI: result = foldAbs(getInt(a), n, g)
|
||||
of mUnaryLt: result = doAndFit(foldSub(getOrdValue(a), 1, n, g))
|
||||
of mSucc: result = doAndFit(foldAdd(getOrdValue(a), getInt(b), n, g))
|
||||
of mPred: result = doAndFit(foldSub(getOrdValue(a), getInt(b), n, g))
|
||||
of mUnaryLt: result = foldSub(getOrdValue(a), One, n, g)
|
||||
of mSucc: result = foldAdd(getOrdValue(a), getInt(b), n, g)
|
||||
of mPred: result = foldSub(getOrdValue(a), getInt(b), n, g)
|
||||
of mAddI: result = foldAdd(getInt(a), getInt(b), n, g)
|
||||
of mSubI: result = foldSub(getInt(a), getInt(b), n, g)
|
||||
of mMulI: result = foldMul(getInt(a), getInt(b), n, g)
|
||||
of mMinI:
|
||||
if getInt(a) > getInt(b): result = newIntNodeT(getInt(b), n, g)
|
||||
else: result = newIntNodeT(getInt(a), n, g)
|
||||
if getInt(a) > getInt(b): result = newIntNodeT(getInt64(b), n, g)
|
||||
else: result = newIntNodeT(getInt64(a), n, g)
|
||||
of mMaxI:
|
||||
if getInt(a) > getInt(b): result = newIntNodeT(getInt(a), n, g)
|
||||
else: result = newIntNodeT(getInt(b), n, g)
|
||||
let argA = getInt(a)
|
||||
let argB = getInt(b)
|
||||
result = newIntNodeT(if argA > argB: argA else: argB, n, g)
|
||||
of mShlI:
|
||||
case skipTypes(n.typ, abstractRange).kind
|
||||
of tyInt8: result = newIntNodeT(int8(getInt(a)) shl int8(getInt(b)), n, g)
|
||||
of tyInt16: result = newIntNodeT(int16(getInt(a)) shl int16(getInt(b)), n, g)
|
||||
of tyInt32: result = newIntNodeT(int32(getInt(a)) shl int32(getInt(b)), n, g)
|
||||
of tyInt64, tyInt:
|
||||
result = newIntNodeT(`shl`(getInt(a), getInt(b)), n, g)
|
||||
of tyUInt..tyUInt64:
|
||||
result = doAndFit(newIntNodeT(`shl`(getInt(a), getInt(b)), n, g))
|
||||
of tyInt8: result = newIntNodeT(toInt8(getInt(a)) shl getInt64(b), n, g)
|
||||
of tyInt16: result = newIntNodeT(toInt16(getInt(a)) shl getInt64(b), n, g)
|
||||
of tyInt32: result = newIntNodeT(toInt32(getInt(a)) shl getInt64(b), n, g)
|
||||
of tyInt64: result = newIntNodeT(toInt64(getInt(a)) shl getInt64(b), n, g)
|
||||
of tyInt:
|
||||
if g.config.target.intSize == 4:
|
||||
result = newIntNodeT(toInt128(toInt32(getInt(a)) shl getInt64(b)), n, g)
|
||||
else:
|
||||
result = newIntNodeT(toInt128(toInt64(getInt(a)) shl getInt64(b)), n, g)
|
||||
of tyUInt8: result = newIntNodeT(toInt128(toUInt8(getInt(a)) shl getInt64(b)), n, g)
|
||||
of tyUInt16: result = newIntNodeT(toInt128(toUInt16(getInt(a)) shl getInt64(b)), n, g)
|
||||
of tyUInt32: result = newIntNodeT(toInt128(toUInt32(getInt(a)) shl getInt64(b)), n, g)
|
||||
of tyUInt64: result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl getInt64(b)), n, g)
|
||||
of tyUInt:
|
||||
if g.config.target.intSize == 4:
|
||||
result = newIntNodeT(BiggestInt(toUInt32(getInt(a)) shl getInt64(b)), n, g)
|
||||
else:
|
||||
result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl getInt64(b)), n, g)
|
||||
else: internalError(g.config, n.info, "constant folding for shl")
|
||||
of mShrI:
|
||||
var a = cast[uint64](getInt(a))
|
||||
@@ -263,14 +255,22 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||
result = newIntNodeT(c, n, g)
|
||||
of mAshrI:
|
||||
case skipTypes(n.typ, abstractRange).kind
|
||||
of tyInt8: result = newIntNodeT(ashr(int8(getInt(a)), int8(getInt(b))), n, g)
|
||||
of tyInt16: result = newIntNodeT(ashr(int16(getInt(a)), int16(getInt(b))), n, g)
|
||||
of tyInt32: result = newIntNodeT(ashr(int32(getInt(a)), int32(getInt(b))), n, g)
|
||||
of tyInt8: result = newIntNodeT(ashr(int8(getInt64(a)), int8(getInt64(b))), n, g)
|
||||
of tyInt16: result = newIntNodeT(ashr(int16(getInt64(a)), int16(getInt64(b))), n, g)
|
||||
of tyInt32: result = newIntNodeT(ashr(int32(getInt64(a)), int32(getInt64(b))), n, g)
|
||||
of tyInt64, tyInt:
|
||||
result = newIntNodeT(ashr(getInt(a), getInt(b)), n, g)
|
||||
result = newIntNodeT(ashr(getInt64(a), getInt64(b)), n, g)
|
||||
else: internalError(g.config, n.info, "constant folding for ashr")
|
||||
of mDivI: result = foldDiv(getInt(a), getInt(b), n, g)
|
||||
of mModI: result = foldMod(getInt(a), getInt(b), n, g)
|
||||
of mDivI:
|
||||
let argA = getInt(a)
|
||||
let argB = getInt(b)
|
||||
if argB != Zero and (argA != firstOrd(g.config, n.typ) or argB != NegOne):
|
||||
result = newIntNodeT(argA div argB, n, g)
|
||||
of mModI:
|
||||
let argA = getInt(a)
|
||||
let argB = getInt(b)
|
||||
if argB != Zero and (argA != firstOrd(g.config, n.typ) or argB != NegOne):
|
||||
result = newIntNodeT(argA mod argB, n, g)
|
||||
of mAddF64: result = newFloatNodeT(getFloat(a) + getFloat(b), n, g)
|
||||
of mSubF64: result = newFloatNodeT(getFloat(a) - getFloat(b), n, g)
|
||||
of mMulF64: result = newFloatNodeT(getFloat(a) * getFloat(b), n, g)
|
||||
@@ -296,17 +296,32 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||
of mLeStr: result = newIntNodeT(ord(getStr(a) <= getStr(b)), n, g)
|
||||
of mEqStr: result = newIntNodeT(ord(getStr(a) == getStr(b)), n, g)
|
||||
of mLtU, mLtU64:
|
||||
result = newIntNodeT(ord(`<%`(getOrdValue(a), getOrdValue(b))), n, g)
|
||||
result = newIntNodeT(ord(`<%`(getOrdValue64(a), getOrdValue64(b))), n, g)
|
||||
of mLeU, mLeU64:
|
||||
result = newIntNodeT(ord(`<=%`(getOrdValue(a), getOrdValue(b))), n, g)
|
||||
of mBitandI, mAnd: result = doAndFit(newIntNodeT(a.getInt and b.getInt, n, g))
|
||||
of mBitorI, mOr: result = doAndFit(newIntNodeT(getInt(a) or getInt(b), n, g))
|
||||
of mBitxorI, mXor: result = doAndFit(newIntNodeT(a.getInt xor b.getInt, n, g))
|
||||
of mAddU: result = doAndFit(newIntNodeT(`+%`(getInt(a), getInt(b)), n, g))
|
||||
of mSubU: result = doAndFit(newIntNodeT(`-%`(getInt(a), getInt(b)), n, g))
|
||||
of mMulU: result = doAndFit(newIntNodeT(`*%`(getInt(a), getInt(b)), n, g))
|
||||
of mModU: result = doAndFit(foldModU(getInt(a), getInt(b), n, g))
|
||||
of mDivU: result = doAndFit(foldDivU(getInt(a), getInt(b), n, g))
|
||||
result = newIntNodeT(ord(`<=%`(getOrdValue64(a), getOrdValue64(b))), n, g)
|
||||
of mBitandI, mAnd: result = newIntNodeT(bitand(a.getInt, b.getInt), n, g)
|
||||
of mBitorI, mOr: result = newIntNodeT(bitor(getInt(a), getInt(b)), n, g)
|
||||
of mBitxorI, mXor: result = newIntNodeT(bitxor(getInt(a), getInt(b)), n, g)
|
||||
of mAddU:
|
||||
let val = maskBytes(getInt(a) + getInt(b), int(n.typ.size))
|
||||
result = newIntNodeT(val, n, g)
|
||||
of mSubU:
|
||||
let val = maskBytes(getInt(a) - getInt(b), int(n.typ.size))
|
||||
result = newIntNodeT(val, n, g)
|
||||
# echo "subU: ", val, " n: ", n, " result: ", val
|
||||
of mMulU:
|
||||
let val = maskBytes(getInt(a) * getInt(b), int(n.typ.size))
|
||||
result = newIntNodeT(val, n, g)
|
||||
of mModU:
|
||||
let argA = maskBytes(getInt(a), int(a.typ.size))
|
||||
let argB = maskBytes(getInt(b), int(a.typ.size))
|
||||
if argB != Zero:
|
||||
result = newIntNodeT(argA mod argB, n, g)
|
||||
of mDivU:
|
||||
let argA = maskBytes(getInt(a), int(a.typ.size))
|
||||
let argB = maskBytes(getInt(b), int(a.typ.size))
|
||||
if argB != Zero:
|
||||
result = newIntNodeT(argA div argB, n, g)
|
||||
of mLeSet: result = newIntNodeT(ord(containsSets(g.config, a, b)), n, g)
|
||||
of mEqSet: result = newIntNodeT(ord(equalSets(g.config, a, b)), n, g)
|
||||
of mLtSet:
|
||||
@@ -332,10 +347,10 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||
of mBoolToStr:
|
||||
if getOrdValue(a) == 0: result = newStrNodeT("false", n, g)
|
||||
else: result = newStrNodeT("true", n, g)
|
||||
of mCopyStr: result = newStrNodeT(substr(getStr(a), int(getOrdValue(b))), n, g)
|
||||
of mCopyStr: result = newStrNodeT(substr(getStr(a), int(toInt64(getOrdValue(b)))), n, g)
|
||||
of mCopyStrLast:
|
||||
result = newStrNodeT(substr(getStr(a), int(getOrdValue(b)),
|
||||
int(getOrdValue(c))), n, g)
|
||||
result = newStrNodeT(substr(getStr(a), toInt(getOrdValue(b)),
|
||||
toInt(getOrdValue(c))), n, g)
|
||||
of mFloatToStr: result = newStrNodeT($getFloat(a), n, g)
|
||||
of mCStrToStr, mCharToStr:
|
||||
if a.kind == nkBracket:
|
||||
@@ -415,13 +430,8 @@ proc getAppType(n: PNode; g: ModuleGraph): PNode =
|
||||
else:
|
||||
result = newStrNodeT("console", n, g)
|
||||
|
||||
proc rangeCheck(n: PNode, value: BiggestInt; g: ModuleGraph) =
|
||||
var err = false
|
||||
if n.typ.skipTypes({tyRange}).kind in {tyUInt..tyUInt64}:
|
||||
err = value <% firstOrd(g.config, n.typ) or value >% lastOrd(g.config, n.typ, fixedUnsigned=true)
|
||||
else:
|
||||
err = value < firstOrd(g.config, n.typ) or value > lastOrd(g.config, n.typ)
|
||||
if err:
|
||||
proc rangeCheck(n: PNode, value: Int128; g: ModuleGraph) =
|
||||
if value < firstOrd(g.config, n.typ) or value > lastOrd(g.config, n.typ):
|
||||
localError(g.config, n.info, "cannot convert " & $value &
|
||||
" to " & typeToString(n.typ))
|
||||
|
||||
@@ -429,43 +439,35 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode =
|
||||
let dstTyp = skipTypes(n.typ, abstractRange)
|
||||
let srcTyp = skipTypes(a.typ, abstractRange)
|
||||
|
||||
|
||||
# if srcTyp.kind == tyUInt64 and "FFFFFF" in $n:
|
||||
# echo "n: ", n, " a: ", a
|
||||
# echo "from: ", srcTyp, " to: ", dstTyp, " check: ", check
|
||||
# echo getInt(a)
|
||||
# echo high(int64)
|
||||
# writeStackTrace()
|
||||
|
||||
# XXX range checks?
|
||||
case dstTyp.kind
|
||||
of tyInt..tyInt64, tyUInt..tyUInt64:
|
||||
case srcTyp.kind
|
||||
of tyFloat..tyFloat64:
|
||||
result = newIntNodeT(int(getFloat(a)), n, g)
|
||||
of tyChar:
|
||||
result = newIntNodeT(getOrdValue(a), n, g)
|
||||
of tyUInt..tyUInt64, tyInt..tyInt64:
|
||||
let toSigned = dstTyp.kind in tyInt..tyInt64
|
||||
result = newIntNodeT(BiggestInt(getFloat(a)), n, g)
|
||||
of tyChar, tyUInt..tyUInt64, tyInt..tyInt64:
|
||||
var val = a.getOrdValue
|
||||
|
||||
if dstTyp.kind in {tyInt, tyInt64, tyUInt, tyUInt64}:
|
||||
# No narrowing needed
|
||||
discard
|
||||
elif dstTyp.kind in {tyInt..tyInt64}:
|
||||
# Signed type: Overflow check (if requested) and conversion
|
||||
if check: rangeCheck(n, val, g)
|
||||
let mask = (`shl`(1, getSize(g.config, dstTyp) * 8) - 1)
|
||||
let valSign = val < 0
|
||||
val = abs(val) and mask
|
||||
if valSign: val = -val
|
||||
else:
|
||||
# Unsigned type: Conversion
|
||||
let mask = (`shl`(1, getSize(g.config, dstTyp) * 8) - 1)
|
||||
val = val and mask
|
||||
|
||||
if check: rangeCheck(n, val, g)
|
||||
result = newIntNodeT(val, n, g)
|
||||
if dstTyp.kind in {tyUInt .. tyUInt64}:
|
||||
result.kind = nkUIntLit
|
||||
else:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
if check and result.kind in {nkCharLit..nkUInt64Lit}:
|
||||
rangeCheck(n, result.intVal, g)
|
||||
rangeCheck(n, getInt(result), g)
|
||||
of tyFloat..tyFloat64:
|
||||
case srcTyp.kind
|
||||
of tyInt..tyInt64, tyEnum, tyBool, tyChar:
|
||||
result = newFloatNodeT(toBiggestFloat(getOrdValue(a)), n, g)
|
||||
result = newFloatNodeT(toFloat64(getOrdValue(a)), n, g)
|
||||
else:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
@@ -490,16 +492,16 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
var y = getConstExpr(m, n.sons[1], g)
|
||||
if y == nil: return
|
||||
|
||||
var idx = getOrdValue(y)
|
||||
var idx = toInt64(getOrdValue(y))
|
||||
case x.kind
|
||||
of nkPar, nkTupleConstr:
|
||||
if idx >= 0 and idx < sonsLen(x):
|
||||
result = x.sons[int(idx)]
|
||||
result = x.sons[idx]
|
||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||
else:
|
||||
localError(g.config, n.info, formatErrorIndexBound(idx, sonsLen(x)-1) & $n)
|
||||
of nkBracket:
|
||||
idx = idx - firstOrd(g.config, x.typ)
|
||||
idx = idx - toInt64(firstOrd(g.config, x.typ))
|
||||
if idx >= 0 and idx < x.len: result = x.sons[int(idx)]
|
||||
else: localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
@@ -729,8 +731,7 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
var a = getConstExpr(m, n.sons[1], g)
|
||||
if a == nil: return
|
||||
# XXX: we should enable `check` for other conversion types too
|
||||
result = foldConv(n, a, g, check=n.kind == nkHiddenStdConv)
|
||||
result = foldConv(n, a, g, check=true)
|
||||
of nkCast:
|
||||
var a = getConstExpr(m, n.sons[1], g)
|
||||
if a == nil: return
|
||||
|
||||
@@ -186,7 +186,9 @@ proc semOrd(c: PContext, n: PNode): PNode =
|
||||
if isOrdinalType(parType, allowEnumWithHoles=true):
|
||||
discard
|
||||
elif parType.kind == tySet:
|
||||
result.typ = makeRangeType(c, firstOrd(c.config, parType), lastOrd(c.config, parType), n.info)
|
||||
let a = toInt64(firstOrd(c.config, parType))
|
||||
let b = toInt64(lastOrd(c.config, parType))
|
||||
result.typ = makeRangeType(c, a, b, n.info)
|
||||
else:
|
||||
localError(c.config, n.info, errOrdinalTypeExpected)
|
||||
result.typ = errorType(c)
|
||||
@@ -273,7 +275,7 @@ proc semDynamicBindSym(c: PContext, n: PNode): PNode =
|
||||
# executed like 'normal' VM callback
|
||||
idx = vm.registerCallback("bindSymImpl", bindSymWrapper)
|
||||
# dummy node to carry idx information to VM
|
||||
idxNode = newIntTypeNode(nkIntLit, idx, c.graph.getSysType(TLineInfo(), tyInt))
|
||||
idxNode = newIntTypeNode(idx, c.graph.getSysType(TLineInfo(), tyInt))
|
||||
|
||||
result = copyNode(n)
|
||||
for x in n: result.add x
|
||||
|
||||
@@ -100,7 +100,7 @@ proc allPossibleValues(c: PContext, t: PType): IntSet =
|
||||
for field in t.n.sons:
|
||||
result.incl(field.sym.position)
|
||||
else:
|
||||
for i in firstOrd(c.config, t) .. lastOrd(c.config, t):
|
||||
for i in toInt64(firstOrd(c.config, t)) .. toInt64(lastOrd(c.config, t)):
|
||||
result.incl(i.int)
|
||||
|
||||
proc branchVals(c: PContext, caseNode: PNode, caseIdx: int,
|
||||
|
||||
@@ -69,7 +69,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
base = semTypeNode(c, n.sons[0].sons[0], nil)
|
||||
if base.kind != tyEnum:
|
||||
localError(c.config, n.sons[0].info, "inheritance only works with an enum")
|
||||
counter = lastOrd(c.config, base) + 1
|
||||
counter = toInt64(lastOrd(c.config, base)) + 1
|
||||
rawAddSon(result, base)
|
||||
let isPure = result.sym != nil and sfPure in result.sym.flags
|
||||
var symbols: TStrTable
|
||||
@@ -93,7 +93,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCString}:
|
||||
if not isOrdinalType(v.sons[0].typ, allowEnumWithHoles=true):
|
||||
localError(c.config, v.sons[0].info, errOrdinalTypeExpected & "; given: " & typeToString(v.sons[0].typ, preferDesc))
|
||||
x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
|
||||
x = toInt64(getOrdValue(v.sons[0])) # first tuple part is the ordinal
|
||||
else:
|
||||
localError(c.config, strVal.info, errStringLiteralExpected)
|
||||
else:
|
||||
@@ -104,7 +104,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
else:
|
||||
if not isOrdinalType(v.typ, allowEnumWithHoles=true):
|
||||
localError(c.config, v.info, errOrdinalTypeExpected & "; given: " & typeToString(v.typ, preferDesc))
|
||||
x = getOrdValue(v)
|
||||
x = toInt64(getOrdValue(v))
|
||||
if i != 1:
|
||||
if x != counter: incl(result.flags, tfEnumHasHoles)
|
||||
if x < counter:
|
||||
@@ -507,7 +507,7 @@ proc semBranchRange(c: PContext, t, a, b: PNode, covered: var Int128): PNode =
|
||||
result.add(at)
|
||||
result.add(bt)
|
||||
if emptyRange(ac, bc): localError(c.config, b.info, "range is empty")
|
||||
else: covered = covered + getOrdValue(bc) - getOrdValue(ac) + 1
|
||||
else: covered = covered + getOrdValue(bc) + 1 - getOrdValue(ac)
|
||||
|
||||
proc semCaseBranchRange(c: PContext, t, b: PNode,
|
||||
covered: var Int128): PNode =
|
||||
@@ -582,7 +582,7 @@ proc toCover(c: PContext, t: PType): Int128 =
|
||||
elif t.kind in {tyInt, tyUInt}:
|
||||
result = toInt128(1) shl (c.config.target.intSize * 8)
|
||||
else:
|
||||
result = toInt128(lengthOrd(c.config, t))
|
||||
result = lengthOrd(c.config, t)
|
||||
|
||||
proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
father: PNode, rectype: PType, hasCaseFields = false)
|
||||
|
||||
@@ -377,8 +377,8 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
|
||||
if k == f.kind: result = isSubrange
|
||||
elif k == tyInt and f.kind in {tyRange, tyInt8..tyInt64,
|
||||
tyUInt..tyUInt64} and
|
||||
isIntLit(ab) and ab.n.intVal >= firstOrd(nil, f) and
|
||||
ab.n.intVal <= lastOrd(nil, f):
|
||||
isIntLit(ab) and getInt(ab.n) >= firstOrd(nil, f) and
|
||||
getInt(ab.n) <= lastOrd(nil, f):
|
||||
# passing 'nil' to firstOrd/lastOrd here as type checking rules should
|
||||
# not depent on the target integer size configurations!
|
||||
# integer literal in the proper range; we want ``i16 + 4`` to stay an
|
||||
@@ -902,10 +902,10 @@ proc inferStaticsInRange(c: var TCandidate,
|
||||
allowUnresolved = true)
|
||||
let upperBound = tryResolvingStaticExpr(c, inferred.n[1],
|
||||
allowUnresolved = true)
|
||||
template doInferStatic(e: PNode, r: BiggestInt) =
|
||||
template doInferStatic(e: PNode, r: Int128) =
|
||||
var exp = e
|
||||
var rhs = r
|
||||
if inferStaticParam(c, exp, rhs):
|
||||
if inferStaticParam(c, exp, toInt64(rhs)):
|
||||
return isGeneric
|
||||
else:
|
||||
failureToInferStaticParam(c.c.config, exp)
|
||||
@@ -918,7 +918,7 @@ proc inferStaticsInRange(c: var TCandidate,
|
||||
return isNone
|
||||
doInferStatic(upperBound, lengthOrd(c.c.config, concrete) + lowerBound.intVal - 1)
|
||||
elif upperBound.kind == nkIntLit:
|
||||
doInferStatic(lowerBound, upperBound.intVal + 1 - lengthOrd(c.c.config, concrete))
|
||||
doInferStatic(lowerBound, getInt(upperBound) + 1 - lengthOrd(c.c.config, concrete))
|
||||
|
||||
template subtypeCheck() =
|
||||
if result <= isSubrange and f.lastSon.skipTypes(abstractInst).kind in {
|
||||
|
||||
@@ -332,7 +332,7 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||
typ.size = elemSize
|
||||
typ.align = int16(elemSize)
|
||||
else:
|
||||
typ.size = lengthOrd(conf, typ.sons[0]) * elemSize
|
||||
typ.size = toInt64(lengthOrd(conf, typ.sons[0]) * int32(elemSize))
|
||||
typ.align = typ.sons[1].align
|
||||
|
||||
of tyUncheckedArray:
|
||||
@@ -341,11 +341,11 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||
typ.size = 0
|
||||
typ.align = base.align
|
||||
of tyEnum:
|
||||
if firstOrd(conf, typ) < 0:
|
||||
if firstOrd(conf, typ) < Zero:
|
||||
typ.size = 4 # use signed int32
|
||||
typ.align = 4
|
||||
else:
|
||||
length = lastOrd(conf, typ) # BUGFIX: use lastOrd!
|
||||
length = toInt64(lastOrd(conf, typ)) # BUGFIX: use lastOrd!
|
||||
if length + 1 < `shl`(1, 8):
|
||||
typ.size = 1
|
||||
typ.align = 1
|
||||
@@ -363,7 +363,7 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||
typ.size = szUncomputedSize
|
||||
typ.align = szUncomputedSize # in original version this was 1
|
||||
else:
|
||||
length = lengthOrd(conf, typ.sons[0])
|
||||
length = toInt64(lengthOrd(conf, typ.sons[0]))
|
||||
if length <= 8:
|
||||
typ.size = 1
|
||||
elif length <= 16:
|
||||
|
||||
@@ -489,8 +489,8 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
|
||||
result = newTransNode(nkChckRange, n, 3)
|
||||
dest = skipTypes(n.typ, abstractVar)
|
||||
result[0] = transform(c, n.sons[1])
|
||||
result[1] = newIntTypeNode(nkIntLit, firstOrd(c.graph.config, dest), dest).PTransNode
|
||||
result[2] = newIntTypeNode(nkIntLit, lastOrd(c.graph.config, dest), dest).PTransNode
|
||||
result[1] = newIntTypeNode(firstOrd(c.graph.config, dest), dest).PTransNode
|
||||
result[2] = newIntTypeNode(lastOrd(c.graph.config, dest), dest).PTransNode
|
||||
of tyFloat..tyFloat128:
|
||||
# XXX int64 -> float conversion?
|
||||
if skipTypes(n.typ, abstractVar).kind == tyRange:
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import
|
||||
intsets, ast, astalgo, trees, msgs, strutils, platform, renderer, options,
|
||||
lineinfos
|
||||
lineinfos, int128
|
||||
|
||||
type
|
||||
TPreferedDesc* = enum
|
||||
@@ -77,12 +77,35 @@ proc isPureObject*(typ: PType): bool =
|
||||
t = t.sons[0].skipTypes(skipPtrs)
|
||||
result = t.sym != nil and sfPure in t.sym.flags
|
||||
|
||||
proc getOrdValue*(n: PNode; onError = high(BiggestInt)): BiggestInt =
|
||||
proc isUnsigned*(t: PType): bool =
|
||||
t.skipTypes(abstractInst).kind in {tyChar, tyUInt..tyUInt64}
|
||||
|
||||
proc getOrdValue*(n: PNode; onError = high(Int128)): Int128 =
|
||||
case n.kind
|
||||
of nkCharLit, nkUIntLit..nkUInt64Lit:
|
||||
# XXX: enable this assert
|
||||
#assert n.typ == nil or isUnsigned(n.typ), $n.typ
|
||||
toInt128(cast[uint64](n.intVal))
|
||||
of nkIntLit..nkInt64Lit:
|
||||
# XXX: enable this assert
|
||||
#assert n.typ == nil or not isUnsigned(n.typ), $n.typ.kind
|
||||
toInt128(n.intVal)
|
||||
of nkNilLit:
|
||||
int128.Zero
|
||||
of nkHiddenStdConv: getOrdValue(n.sons[1], onError)
|
||||
else:
|
||||
# XXX: The idea behind the introduction of int128 was to finally
|
||||
# have all calculations numerically far away from any
|
||||
# overflows. This command just introduces such overflows and
|
||||
# should therefore really be revisited.
|
||||
onError
|
||||
|
||||
proc getOrdValue64*(n: PNode): BiggestInt {.deprecated: "use getOrdvalue".} =
|
||||
case n.kind
|
||||
of nkCharLit..nkUInt64Lit: n.intVal
|
||||
of nkNilLit: 0
|
||||
of nkHiddenStdConv: getOrdValue(n.sons[1], onError)
|
||||
else: onError
|
||||
of nkHiddenStdConv: getOrdValue64(n.sons[1])
|
||||
else: high(BiggestInt)
|
||||
|
||||
proc getFloatValue*(n: PNode): BiggestFloat =
|
||||
case n.kind
|
||||
@@ -629,10 +652,10 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
result = typeToStr[t.kind]
|
||||
result.addTypeFlags(t)
|
||||
|
||||
proc firstOrd*(conf: ConfigRef; t: PType): BiggestInt =
|
||||
proc firstOrd*(conf: ConfigRef; t: PType): Int128 =
|
||||
case t.kind
|
||||
of tyBool, tyChar, tySequence, tyOpenArray, tyString, tyVarargs, tyProxy:
|
||||
result = 0
|
||||
result = Zero
|
||||
of tySet, tyVar: result = firstOrd(conf, t.sons[0])
|
||||
of tyArray: result = firstOrd(conf, t.sons[0])
|
||||
of tyRange:
|
||||
@@ -640,20 +663,22 @@ proc firstOrd*(conf: ConfigRef; t: PType): BiggestInt =
|
||||
assert(t.n.kind == nkRange)
|
||||
result = getOrdValue(t.n.sons[0])
|
||||
of tyInt:
|
||||
if conf != nil and conf.target.intSize == 4: result = - (2147483646) - 2
|
||||
else: result = 0x8000000000000000'i64
|
||||
of tyInt8: result = - 128
|
||||
of tyInt16: result = - 32768
|
||||
of tyInt32: result = - 2147483646 - 2
|
||||
of tyInt64: result = 0x8000000000000000'i64
|
||||
of tyUInt..tyUInt64: result = 0
|
||||
if conf != nil and conf.target.intSize == 4:
|
||||
result = toInt128(-2147483648)
|
||||
else:
|
||||
result = toInt128(0x8000000000000000'i64)
|
||||
of tyInt8: result = toInt128(-128)
|
||||
of tyInt16: result = toInt128(-32768)
|
||||
of tyInt32: result = toInt128(-2147483648)
|
||||
of tyInt64: result = toInt128(0x8000000000000000'i64)
|
||||
of tyUInt..tyUInt64: result = Zero
|
||||
of tyEnum:
|
||||
# if basetype <> nil then return firstOrd of basetype
|
||||
if sonsLen(t) > 0 and t.sons[0] != nil:
|
||||
result = firstOrd(conf, t.sons[0])
|
||||
else:
|
||||
assert(t.n.sons[0].kind == nkSym)
|
||||
result = t.n.sons[0].sym.position
|
||||
result = toInt128(t.n.sons[0].sym.position)
|
||||
of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tySink,
|
||||
tyStatic, tyInferred, tyUserTypeClasses:
|
||||
result = firstOrd(conf, lastSon(t))
|
||||
@@ -661,11 +686,10 @@ proc firstOrd*(conf: ConfigRef; t: PType): BiggestInt =
|
||||
if t.len > 0: result = firstOrd(conf, lastSon(t))
|
||||
else: internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')')
|
||||
of tyUncheckedArray:
|
||||
result = 0
|
||||
result = Zero
|
||||
else:
|
||||
internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')')
|
||||
result = 0
|
||||
|
||||
result = Zero
|
||||
|
||||
proc firstFloat*(t: PType): BiggestFloat =
|
||||
case t.kind
|
||||
@@ -682,10 +706,10 @@ proc firstFloat*(t: PType): BiggestFloat =
|
||||
internalError(newPartialConfigRef(), "invalid kind for firstFloat(" & $t.kind & ')')
|
||||
NaN
|
||||
|
||||
proc lastOrd*(conf: ConfigRef; t: PType; fixedUnsigned = false): BiggestInt =
|
||||
proc lastOrd*(conf: ConfigRef; t: PType): Int128 =
|
||||
case t.kind
|
||||
of tyBool: result = 1
|
||||
of tyChar: result = 255
|
||||
of tyBool: result = toInt128(1'u)
|
||||
of tyChar: result = toInt128(255'u)
|
||||
of tySet, tyVar: result = lastOrd(conf, t.sons[0])
|
||||
of tyArray: result = lastOrd(conf, t.sons[0])
|
||||
of tyRange:
|
||||
@@ -693,38 +717,37 @@ proc lastOrd*(conf: ConfigRef; t: PType; fixedUnsigned = false): BiggestInt =
|
||||
assert(t.n.kind == nkRange)
|
||||
result = getOrdValue(t.n.sons[1])
|
||||
of tyInt:
|
||||
if conf != nil and conf.target.intSize == 4: result = 0x7FFFFFFF
|
||||
else: result = 0x7FFFFFFFFFFFFFFF'i64
|
||||
of tyInt8: result = 0x0000007F
|
||||
of tyInt16: result = 0x00007FFF
|
||||
of tyInt32: result = 0x7FFFFFFF
|
||||
of tyInt64: result = 0x7FFFFFFFFFFFFFFF'i64
|
||||
if conf != nil and conf.target.intSize == 4: result = toInt128(0x7FFFFFFF)
|
||||
else: result = toInt128(0x7FFFFFFFFFFFFFFF'u64)
|
||||
of tyInt8: result = toInt128(0x0000007F)
|
||||
of tyInt16: result = toInt128(0x00007FFF)
|
||||
of tyInt32: result = toInt128(0x7FFFFFFF)
|
||||
of tyInt64: result = toInt128(0x7FFFFFFFFFFFFFFF'u64)
|
||||
of tyUInt:
|
||||
if conf != nil and conf.target.intSize == 4: result = 0xFFFFFFFF
|
||||
elif fixedUnsigned: result = 0xFFFFFFFFFFFFFFFF'i64
|
||||
else: result = 0x7FFFFFFFFFFFFFFF'i64
|
||||
of tyUInt8: result = 0xFF
|
||||
of tyUInt16: result = 0xFFFF
|
||||
of tyUInt32: result = 0xFFFFFFFF
|
||||
if conf != nil and conf.target.intSize == 4:
|
||||
result = toInt128(0xFFFFFFFF)
|
||||
else:
|
||||
result = toInt128(0xFFFFFFFFFFFFFFFF'u64)
|
||||
of tyUInt8: result = toInt128(0xFF)
|
||||
of tyUInt16: result = toInt128(0xFFFF)
|
||||
of tyUInt32: result = toInt128(0xFFFFFFFF)
|
||||
of tyUInt64:
|
||||
if fixedUnsigned: result = 0xFFFFFFFFFFFFFFFF'i64
|
||||
else: result = 0x7FFFFFFFFFFFFFFF'i64
|
||||
result = toInt128(0xFFFFFFFFFFFFFFFF'u64)
|
||||
of tyEnum:
|
||||
assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
|
||||
result = t.n.sons[sonsLen(t.n) - 1].sym.position
|
||||
result = toInt128(t.n.sons[sonsLen(t.n) - 1].sym.position)
|
||||
of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tySink,
|
||||
tyStatic, tyInferred, tyUserTypeClasses:
|
||||
result = lastOrd(conf, lastSon(t))
|
||||
of tyProxy: result = 0
|
||||
of tyProxy: result = Zero
|
||||
of tyOrdinal:
|
||||
if t.len > 0: result = lastOrd(conf, lastSon(t))
|
||||
else: internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')')
|
||||
of tyUncheckedArray:
|
||||
result = high(BiggestInt)
|
||||
result = Zero
|
||||
else:
|
||||
internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')')
|
||||
result = 0
|
||||
|
||||
result = Zero
|
||||
|
||||
proc lastFloat*(t: PType): BiggestFloat =
|
||||
case t.kind
|
||||
@@ -758,7 +781,7 @@ proc floatRangeCheck*(x: BiggestFloat, t: PType): bool =
|
||||
internalError(newPartialConfigRef(), "invalid kind for floatRangeCheck:" & $t.kind)
|
||||
false
|
||||
|
||||
proc lengthOrd*(conf: ConfigRef; t: PType): BiggestInt =
|
||||
proc lengthOrd*(conf: ConfigRef; t: PType): Int128 =
|
||||
case t.skipTypes(tyUserTypeClasses).kind
|
||||
of tyInt64, tyInt32, tyInt:
|
||||
# XXX: this is just wrong
|
||||
@@ -767,11 +790,7 @@ proc lengthOrd*(conf: ConfigRef; t: PType): BiggestInt =
|
||||
else:
|
||||
let last = lastOrd(conf, t)
|
||||
let first = firstOrd(conf, t)
|
||||
# XXX use a better overflow check here:
|
||||
if last == high(BiggestInt) and first <= 0:
|
||||
result = last
|
||||
else:
|
||||
result = last - first + 1
|
||||
result = last - first + One
|
||||
|
||||
# -------------- type equality -----------------------------------------------
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import
|
||||
strutils, msgs, vmdef, vmgen, nimsets, types, passes,
|
||||
parser, vmdeps, idents, trees, renderer, options, transf, parseutils,
|
||||
vmmarshal, gorgeimpl, lineinfos, tables, btrees, macrocacheimpl,
|
||||
modulegraphs, sighashes
|
||||
modulegraphs, sighashes, int128
|
||||
|
||||
from semfold import leValueConv, ordinalValToString
|
||||
from evaltempl import evalTemplate
|
||||
@@ -411,7 +411,7 @@ proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType):
|
||||
dest.intVal = int(src.floatVal)
|
||||
else:
|
||||
dest.intVal = src.intVal
|
||||
if dest.intVal < firstOrd(c.config, desttyp) or dest.intVal > lastOrd(c.config, desttyp):
|
||||
if toInt128(dest.intVal) < firstOrd(c.config, desttyp) or toInt128(dest.intVal) > lastOrd(c.config, desttyp):
|
||||
return true
|
||||
of tyUInt..tyUInt64:
|
||||
if dest.kind != rkInt:
|
||||
@@ -1312,7 +1312,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
of opcQuit:
|
||||
if c.mode in {emRepl, emStaticExpr, emStaticStmt}:
|
||||
message(c.config, c.debug[pc], hintQuitCalled)
|
||||
msgQuit(int8(getOrdValue(regs[ra].regToNode)))
|
||||
msgQuit(int8(toInt(getOrdValue(regs[ra].regToNode))))
|
||||
else:
|
||||
return TFullReg(kind: rkNone)
|
||||
of opcSetLenStr:
|
||||
|
||||
@@ -596,12 +596,12 @@ proc genField(c: PCtx; n: PNode): TRegister =
|
||||
|
||||
proc genIndex(c: PCtx; n: PNode; arr: PType): TRegister =
|
||||
if arr.skipTypes(abstractInst).kind == tyArray and (let x = firstOrd(c.config, arr);
|
||||
x != 0):
|
||||
x != Zero):
|
||||
let tmp = c.genx(n)
|
||||
# freeing the temporary here means we can produce: regA = regA - Imm
|
||||
c.freeTemp(tmp)
|
||||
result = c.getTemp(n.typ)
|
||||
c.gABI(n, opcSubImmInt, result, tmp, x.int)
|
||||
c.gABI(n, opcSubImmInt, result, tmp, toInt(x))
|
||||
else:
|
||||
result = c.genx(n)
|
||||
|
||||
@@ -1767,7 +1767,7 @@ proc getNullValue(typ: PType, info: TLineInfo; conf: ConfigRef): PNode =
|
||||
getNullValueAux(t, t.n, result, conf, currPosition)
|
||||
of tyArray:
|
||||
result = newNodeIT(nkBracket, info, t)
|
||||
for i in 0 ..< int(lengthOrd(conf, t)):
|
||||
for i in 0 ..< toInt(lengthOrd(conf, t)):
|
||||
addSon(result, getNullValue(elemType(t), info, conf))
|
||||
of tyTuple:
|
||||
result = newNodeIT(nkTupleConstr, info, t)
|
||||
|
||||
@@ -122,7 +122,7 @@ proc hash*(x: int): Hash {.inline.} =
|
||||
|
||||
proc hash*(x: int64): Hash {.inline.} =
|
||||
## Efficient hashing of `int64` integers.
|
||||
result = toU32(x)
|
||||
result = cast[int](x)
|
||||
|
||||
proc hash*(x: uint): Hash {.inline.} =
|
||||
## Efficient hashing of unsigned integers.
|
||||
@@ -130,7 +130,7 @@ proc hash*(x: uint): Hash {.inline.} =
|
||||
|
||||
proc hash*(x: uint64): Hash {.inline.} =
|
||||
## Efficient hashing of `uint64` integers.
|
||||
result = toU32(cast[int](x))
|
||||
result = cast[int](x)
|
||||
|
||||
proc hash*(x: char): Hash {.inline.} =
|
||||
## Efficient hashing of characters.
|
||||
|
||||
@@ -29,6 +29,7 @@ block tcast:
|
||||
let rt = ty(exp)
|
||||
const ct = ty(exp)
|
||||
if $rt != $ct:
|
||||
echo astToStr(exp)
|
||||
echo "Got ", ct
|
||||
echo "Expected ", rt
|
||||
|
||||
@@ -52,7 +53,7 @@ block tcast:
|
||||
crossCheck(uint8, uint8.high + 5'u8)
|
||||
crossCheck(uint16, uint16.high + 5'u16)
|
||||
crossCheck(uint32, uint32.high + 5'u32)
|
||||
crossCheck(uint64, (-1).uint64 + 5'u64)
|
||||
crossCheck(uint64, 0xFFFFFFFFFFFFFFFF'u64 + 5'u64)
|
||||
|
||||
doAssert $sub1(0'u8) == "255"
|
||||
doAssert $sub1(0'u16) == "65535"
|
||||
@@ -69,12 +70,10 @@ block tcast:
|
||||
crossCheck(int64, high(int8).int16.int32.int64)
|
||||
crossCheck(int64, low(int8).int16.int32.int64)
|
||||
|
||||
crossCheck(int64, 0xFFFFFFFFFFFFFFFF'u64)
|
||||
crossCheck(int32, 0xFFFFFFFFFFFFFFFF'u64)
|
||||
crossCheck(int16, 0xFFFFFFFFFFFFFFFF'u64)
|
||||
crossCheck(int8 , 0xFFFFFFFFFFFFFFFF'u64)
|
||||
|
||||
|
||||
doAssert not compiles(echo int64(0xFFFFFFFFFFFFFFFF'u64))
|
||||
doAssert not compiles(echo int32(0xFFFFFFFFFFFFFFFF'u64))
|
||||
doAssert not compiles(echo int16(0xFFFFFFFFFFFFFFFF'u64))
|
||||
doAssert not compiles(echo int8(0xFFFFFFFFFFFFFFFF'u64))
|
||||
|
||||
block tnot:
|
||||
# Signed types
|
||||
@@ -116,32 +115,6 @@ block tnot:
|
||||
doAssert t7 == 4
|
||||
|
||||
|
||||
|
||||
block tshl:
|
||||
# Signed types
|
||||
block:
|
||||
const t0: int8 = 1'i8 shl 8
|
||||
const t1: int16 = 1'i16 shl 16
|
||||
const t2: int32 = 1'i32 shl 32
|
||||
const t3: int64 = 1'i64 shl 64
|
||||
doAssert t0 == 0
|
||||
doAssert t1 == 0
|
||||
doAssert t2 == 1
|
||||
doAssert t3 == 1
|
||||
|
||||
# Unsigned types
|
||||
block:
|
||||
const t0: uint8 = 1'u8 shl 8
|
||||
const t1: uint16 = 1'u16 shl 16
|
||||
const t2: uint32 = 1'u32 shl 32
|
||||
const t3: uint64 = 1'u64 shl 64
|
||||
doAssert t0 == 0
|
||||
doAssert t1 == 0
|
||||
doAssert t2 == 0
|
||||
doAssert t3 == 1
|
||||
|
||||
|
||||
|
||||
block tshr:
|
||||
proc T() =
|
||||
# let VI = -8
|
||||
|
||||
@@ -122,8 +122,13 @@ let expLines = splitLines(expected.strip)
|
||||
|
||||
if resLines.len != expLines.len:
|
||||
echo("Not matched! Wrong number of lines!")
|
||||
echo()
|
||||
echo(result)
|
||||
echo expLines.len
|
||||
echo resLines.len
|
||||
echo("Expected: -----------")
|
||||
echo expected
|
||||
echo("Gotten: -------------")
|
||||
echo result
|
||||
echo("---------------------")
|
||||
quit(QuitFailure)
|
||||
|
||||
var ok = true
|
||||
|
||||
@@ -24,4 +24,4 @@ doAssertRaises(OverflowError): discard high(int64) * 2
|
||||
|
||||
doAssert abs(-1) == 1
|
||||
doAssert 2 div 2 == 1
|
||||
doAssert 2 * 3 == 6
|
||||
doAssert 2 * 3 == 6
|
||||
|
||||
@@ -5,7 +5,7 @@ discard """
|
||||
static:
|
||||
proc p =
|
||||
var
|
||||
x = 1 shl 62
|
||||
x = 1'i64 shl 62
|
||||
discard x * 2
|
||||
assert false
|
||||
p()
|
||||
|
||||
Reference in New Issue
Block a user