semfold compiles again
This commit is contained in:
parent
5bf31fcabe
commit
a6e53ec47b
2 changed files with 267 additions and 265 deletions
|
|
@ -217,11 +217,11 @@ errXExpectsTypeOrValue: "'$1' expects a type or value",
|
||||||
errXExpectsArrayType: "'$1' expects an array type",
|
errXExpectsArrayType: "'$1' expects an array type",
|
||||||
errIteratorCannotBeInstantiated: "'$1' cannot be instantiated because its body has not been compiled yet",
|
errIteratorCannotBeInstantiated: "'$1' cannot be instantiated because its body has not been compiled yet",
|
||||||
errExprXAmbiguous: "expression '$1' ambiguous in this context",
|
errExprXAmbiguous: "expression '$1' ambiguous in this context",
|
||||||
errConstantDivisionByZero: "division by zero",
|
errConstantDivisionByZero: ,
|
||||||
errOrdinalTypeExpected: "ordinal type expected",
|
errOrdinalTypeExpected: "ordinal type expected",
|
||||||
errOrdinalOrFloatTypeExpected: "ordinal or float type expected",
|
errOrdinalOrFloatTypeExpected: "ordinal or float type expected",
|
||||||
errOverOrUnderflow: "over- or underflow",
|
errOverOrUnderflow: ,
|
||||||
errCannotEvalXBecauseIncompletelyDefined: "cannot evaluate '$1' because type is not defined completely",
|
errCannotEvalXBecauseIncompletelyDefined: ,
|
||||||
errChrExpectsRange0_255: "'chr' expects an int in the range 0..255",
|
errChrExpectsRange0_255: "'chr' expects an int in the range 0..255",
|
||||||
errDynlibRequiresExportc: "'dynlib' requires 'exportc'",
|
errDynlibRequiresExportc: "'dynlib' requires 'exportc'",
|
||||||
errUndeclaredFieldX: "undeclared field: '$1'",
|
errUndeclaredFieldX: "undeclared field: '$1'",
|
||||||
|
|
@ -287,7 +287,7 @@ errImplOfXexpected: "implementation of '$1' expected",
|
||||||
errNoSymbolToBorrowFromFound: "no symbol to borrow from found",
|
errNoSymbolToBorrowFromFound: "no symbol to borrow from found",
|
||||||
errDiscardValueX: "value of type '$1' has to be discarded",
|
errDiscardValueX: "value of type '$1' has to be discarded",
|
||||||
errInvalidDiscard: "statement returns no value that can be discarded",
|
errInvalidDiscard: "statement returns no value that can be discarded",
|
||||||
errIllegalConvFromXtoY: "conversion from $1 to $2 is invalid",
|
errIllegalConvFromXtoY: ,
|
||||||
errCannotBindXTwice: "cannot bind parameter '$1' twice",
|
errCannotBindXTwice: "cannot bind parameter '$1' twice",
|
||||||
errInvalidOrderInArrayConstructor: "invalid order in array constructor",
|
errInvalidOrderInArrayConstructor: "invalid order in array constructor",
|
||||||
errInvalidOrderInEnumX: "invalid order in enum '$1'",
|
errInvalidOrderInEnumX: "invalid order in enum '$1'",
|
||||||
|
|
|
||||||
|
|
@ -13,78 +13,16 @@
|
||||||
import
|
import
|
||||||
strutils, options, ast, astalgo, trees, treetab, nimsets, times,
|
strutils, 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, modulegraphs
|
commands, magicsys, modulegraphs, strtabs
|
||||||
|
|
||||||
proc getConstExpr*(m: PSym, n: PNode): PNode
|
proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||||
# evaluates the constant expression or returns nil if it is no constant
|
|
||||||
# expression
|
|
||||||
proc evalOp*(m: TMagic, n, a, b, c: PNode): PNode
|
|
||||||
|
|
||||||
proc checkInRange(n: PNode, res: BiggestInt): bool =
|
|
||||||
if res in firstOrd(n.typ)..lastOrd(n.typ):
|
|
||||||
result = true
|
|
||||||
|
|
||||||
proc foldAdd(a, b: BiggestInt, n: PNode): PNode =
|
|
||||||
let res = a +% b
|
|
||||||
if ((res xor a) >= 0'i64 or (res xor b) >= 0'i64) and
|
|
||||||
checkInRange(n, res):
|
|
||||||
result = newIntNodeT(res, n)
|
|
||||||
|
|
||||||
proc foldSub*(a, b: BiggestInt, n: PNode): PNode =
|
|
||||||
let res = a -% b
|
|
||||||
if ((res xor a) >= 0'i64 or (res xor not b) >= 0'i64) and
|
|
||||||
checkInRange(n, res):
|
|
||||||
result = newIntNodeT(res, n)
|
|
||||||
|
|
||||||
proc foldAbs*(a: BiggestInt, n: PNode): PNode =
|
|
||||||
if a != firstOrd(n.typ):
|
|
||||||
result = newIntNodeT(a, n)
|
|
||||||
|
|
||||||
proc foldMod*(a, b: BiggestInt, n: PNode): PNode =
|
|
||||||
if b != 0'i64:
|
|
||||||
result = newIntNodeT(a mod b, n)
|
|
||||||
|
|
||||||
proc foldModU*(a, b: BiggestInt, n: PNode): PNode =
|
|
||||||
if b != 0'i64:
|
|
||||||
result = newIntNodeT(a %% b, n)
|
|
||||||
|
|
||||||
proc foldDiv*(a, b: BiggestInt, n: PNode): PNode =
|
|
||||||
if b != 0'i64 and (a != firstOrd(n.typ) or b != -1'i64):
|
|
||||||
result = newIntNodeT(a div b, n)
|
|
||||||
|
|
||||||
proc foldDivU*(a, b: BiggestInt, n: PNode): PNode =
|
|
||||||
if b != 0'i64:
|
|
||||||
result = newIntNodeT(a /% b, n)
|
|
||||||
|
|
||||||
proc foldMul*(a, b: BiggestInt, n: PNode): 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(n, res):
|
|
||||||
return newIntNodeT(res, n)
|
|
||||||
|
|
||||||
# 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(n, res):
|
|
||||||
return newIntNodeT(res, n)
|
|
||||||
|
|
||||||
proc newIntNodeT*(intVal: BiggestInt, n: PNode): PNode =
|
|
||||||
case skipTypes(n.typ, abstractVarRange).kind
|
case skipTypes(n.typ, abstractVarRange).kind
|
||||||
of tyInt:
|
of tyInt:
|
||||||
result = newIntNode(nkIntLit, intVal)
|
result = newIntNode(nkIntLit, intVal)
|
||||||
# See bug #6989. 'pred' et al only produce an int literal type if the
|
# See bug #6989. 'pred' et al only produce an int literal type if the
|
||||||
# original type was 'int', not a distinct int etc.
|
# original type was 'int', not a distinct int etc.
|
||||||
if n.typ.kind == tyInt:
|
if n.typ.kind == tyInt:
|
||||||
result.typ = getIntLitType(result)
|
result.typ = getIntLitType(g, result)
|
||||||
else:
|
else:
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
# hrm, this is not correct: 1 + high(int) shouldn't produce tyInt64 ...
|
# hrm, this is not correct: 1 + high(int) shouldn't produce tyInt64 ...
|
||||||
|
|
@ -97,20 +35,82 @@ proc newIntNodeT*(intVal: BiggestInt, n: PNode): PNode =
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
result.info = n.info
|
result.info = n.info
|
||||||
|
|
||||||
proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode): PNode =
|
proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode; g: ModuleGraph): PNode =
|
||||||
result = newFloatNode(nkFloatLit, floatVal)
|
result = newFloatNode(nkFloatLit, floatVal)
|
||||||
if skipTypes(n.typ, abstractVarRange).kind == tyFloat:
|
if skipTypes(n.typ, abstractVarRange).kind == tyFloat:
|
||||||
result.typ = getFloatLitType(result)
|
result.typ = getFloatLitType(g, result)
|
||||||
else:
|
else:
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
result.info = n.info
|
result.info = n.info
|
||||||
|
|
||||||
proc newStrNodeT*(strVal: string, n: PNode): PNode =
|
proc newStrNodeT*(strVal: string, n: PNode; g: ModuleGraph): PNode =
|
||||||
result = newStrNode(nkStrLit, strVal)
|
result = newStrNode(nkStrLit, strVal)
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
result.info = n.info
|
result.info = n.info
|
||||||
|
|
||||||
proc ordinalValToString*(a: PNode): string =
|
proc getConstExpr*(m: PSym, n: PNode; g: ModuleGraph): PNode
|
||||||
|
# evaluates the constant expression or returns nil if it is no constant
|
||||||
|
# expression
|
||||||
|
proc evalOp*(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode
|
||||||
|
|
||||||
|
proc checkInRange(n: PNode, res: BiggestInt): bool =
|
||||||
|
if res in firstOrd(n.typ)..lastOrd(n.typ):
|
||||||
|
result = true
|
||||||
|
|
||||||
|
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(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(n, res):
|
||||||
|
result = newIntNodeT(res, n, g)
|
||||||
|
|
||||||
|
proc foldAbs*(a: BiggestInt, n: PNode; g: ModuleGraph): PNode =
|
||||||
|
if a != firstOrd(n.typ):
|
||||||
|
result = newIntNodeT(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(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(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(n, res):
|
||||||
|
return newIntNodeT(res, n, g)
|
||||||
|
|
||||||
|
proc ordinalValToString*(a: PNode; g: ModuleGraph): string =
|
||||||
# because $ has the param ordinal[T], `a` is not necessarily an enum, but an
|
# because $ has the param ordinal[T], `a` is not necessarily an enum, but an
|
||||||
# ordinal
|
# ordinal
|
||||||
var x = getInt(a)
|
var x = getInt(a)
|
||||||
|
|
@ -122,14 +122,14 @@ proc ordinalValToString*(a: PNode): string =
|
||||||
of tyEnum:
|
of tyEnum:
|
||||||
var n = t.n
|
var n = t.n
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if n.sons[i].kind != nkSym: internalError(a.info, "ordinalValToString")
|
if n.sons[i].kind != nkSym: internalError(g.config, a.info, "ordinalValToString")
|
||||||
var field = n.sons[i].sym
|
var field = n.sons[i].sym
|
||||||
if field.position == x:
|
if field.position == x:
|
||||||
if field.ast == nil:
|
if field.ast == nil:
|
||||||
return field.name.s
|
return field.name.s
|
||||||
else:
|
else:
|
||||||
return field.ast.strVal
|
return field.ast.strVal
|
||||||
internalError(a.info, "no symbol for ordinal value: " & $x)
|
internalError(g.config, a.info, "no symbol for ordinal value: " & $x)
|
||||||
else:
|
else:
|
||||||
result = $x
|
result = $x
|
||||||
|
|
||||||
|
|
@ -148,12 +148,12 @@ proc pickIntRange(a, b: PType): PType =
|
||||||
proc isIntRangeOrLit(t: PType): bool =
|
proc isIntRangeOrLit(t: PType): bool =
|
||||||
result = isIntRange(t) or isIntLit(t)
|
result = isIntRange(t) or isIntLit(t)
|
||||||
|
|
||||||
proc makeRange(typ: PType, first, last: BiggestInt): PType =
|
proc makeRange(typ: PType, first, last: BiggestInt; g: ModuleGraph): PType =
|
||||||
let minA = min(first, last)
|
let minA = min(first, last)
|
||||||
let maxA = max(first, last)
|
let maxA = max(first, last)
|
||||||
let lowerNode = newIntNode(nkIntLit, minA)
|
let lowerNode = newIntNode(nkIntLit, minA)
|
||||||
if typ.kind == tyInt and minA == maxA:
|
if typ.kind == tyInt and minA == maxA:
|
||||||
result = getIntLitType(lowerNode)
|
result = getIntLitType(g, lowerNode)
|
||||||
elif typ.kind in {tyUint, tyUInt64}:
|
elif typ.kind in {tyUint, tyUInt64}:
|
||||||
# these are not ordinal types, so you get no subrange type for these:
|
# these are not ordinal types, so you get no subrange type for these:
|
||||||
result = typ
|
result = typ
|
||||||
|
|
@ -165,7 +165,7 @@ proc makeRange(typ: PType, first, last: BiggestInt): PType =
|
||||||
result.n = n
|
result.n = n
|
||||||
addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
|
addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
|
||||||
|
|
||||||
proc makeRangeF(typ: PType, first, last: BiggestFloat): PType =
|
proc makeRangeF(typ: PType, first, last: BiggestFloat; g: ModuleGraph): PType =
|
||||||
var n = newNode(nkRange)
|
var n = newNode(nkRange)
|
||||||
addSon(n, newFloatNode(nkFloatLit, min(first.float, last.float)))
|
addSon(n, newFloatNode(nkFloatLit, min(first.float, last.float)))
|
||||||
addSon(n, newFloatNode(nkFloatLit, max(first.float, last.float)))
|
addSon(n, newFloatNode(nkFloatLit, max(first.float, last.float)))
|
||||||
|
|
@ -175,9 +175,9 @@ proc makeRangeF(typ: PType, first, last: BiggestFloat): PType =
|
||||||
|
|
||||||
proc evalIs(n, a: PNode): PNode =
|
proc evalIs(n, a: PNode): PNode =
|
||||||
# XXX: This should use the standard isOpImpl
|
# XXX: This should use the standard isOpImpl
|
||||||
internalAssert a.kind == nkSym and a.sym.kind == skType
|
#internalAssert a.kind == nkSym and a.sym.kind == skType
|
||||||
internalAssert n.sonsLen == 3 and
|
#internalAssert n.sonsLen == 3 and
|
||||||
n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
|
# n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
|
||||||
|
|
||||||
let t1 = a.sym.typ
|
let t1 = a.sym.typ
|
||||||
|
|
||||||
|
|
@ -201,113 +201,113 @@ proc evalIs(n, a: PNode): PNode =
|
||||||
result = newIntNode(nkIntLit, ord(match))
|
result = newIntNode(nkIntLit, ord(match))
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
|
|
||||||
proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||||
# b and c may be nil
|
# b and c may be nil
|
||||||
result = nil
|
result = nil
|
||||||
case m
|
case m
|
||||||
of mOrd: result = newIntNodeT(getOrdValue(a), n)
|
of mOrd: result = newIntNodeT(getOrdValue(a), n, g)
|
||||||
of mChr: result = newIntNodeT(getInt(a), n)
|
of mChr: result = newIntNodeT(getInt(a), n, g)
|
||||||
of mUnaryMinusI, mUnaryMinusI64: result = newIntNodeT(- getInt(a), n)
|
of mUnaryMinusI, mUnaryMinusI64: result = newIntNodeT(- getInt(a), n, g)
|
||||||
of mUnaryMinusF64: result = newFloatNodeT(- getFloat(a), n)
|
of mUnaryMinusF64: result = newFloatNodeT(- getFloat(a), n, g)
|
||||||
of mNot: result = newIntNodeT(1 - getInt(a), n)
|
of mNot: result = newIntNodeT(1 - getInt(a), n, g)
|
||||||
of mCard: result = newIntNodeT(nimsets.cardSet(a), n)
|
of mCard: result = newIntNodeT(nimsets.cardSet(a), n, g)
|
||||||
of mBitnotI: result = newIntNodeT(not getInt(a), n)
|
of mBitnotI: result = newIntNodeT(not getInt(a), n, g)
|
||||||
of mLengthArray: result = newIntNodeT(lengthOrd(a.typ), n)
|
of mLengthArray: result = newIntNodeT(lengthOrd(a.typ), n, g)
|
||||||
of mLengthSeq, mLengthOpenArray, mXLenSeq, mLengthStr, mXLenStr:
|
of mLengthSeq, mLengthOpenArray, mXLenSeq, mLengthStr, mXLenStr:
|
||||||
if a.kind == nkNilLit:
|
if a.kind == nkNilLit:
|
||||||
result = newIntNodeT(0, n)
|
result = newIntNodeT(0, n, g)
|
||||||
elif a.kind in {nkStrLit..nkTripleStrLit}:
|
elif a.kind in {nkStrLit..nkTripleStrLit}:
|
||||||
result = newIntNodeT(len a.strVal, n)
|
result = newIntNodeT(len a.strVal, n, g)
|
||||||
else:
|
else:
|
||||||
result = newIntNodeT(sonsLen(a), n) # BUGFIX
|
result = newIntNodeT(sonsLen(a), n, g)
|
||||||
of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away
|
of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away
|
||||||
of mToFloat, mToBiggestFloat:
|
of mToFloat, mToBiggestFloat:
|
||||||
result = newFloatNodeT(toFloat(int(getInt(a))), n)
|
result = newFloatNodeT(toFloat(int(getInt(a))), n, g)
|
||||||
# XXX: Hides overflow/underflow
|
# XXX: Hides overflow/underflow
|
||||||
of mToInt, mToBiggestInt: result = newIntNodeT(system.toInt(getFloat(a)), n)
|
of mToInt, mToBiggestInt: result = newIntNodeT(system.toInt(getFloat(a)), n, g)
|
||||||
of mAbsF64: result = newFloatNodeT(abs(getFloat(a)), n)
|
of mAbsF64: result = newFloatNodeT(abs(getFloat(a)), n, g)
|
||||||
of mAbsI: result = foldAbs(getInt(a), n)
|
of mAbsI: result = foldAbs(getInt(a), n, g)
|
||||||
of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64:
|
of mZe8ToI, mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64:
|
||||||
# byte(-128) = 1...1..1000_0000'64 --> 0...0..1000_0000'64
|
# byte(-128) = 1...1..1000_0000'64 --> 0...0..1000_0000'64
|
||||||
result = newIntNodeT(getInt(a) and (`shl`(1, getSize(a.typ) * 8) - 1), n)
|
result = newIntNodeT(getInt(a) and (`shl`(1, getSize(a.typ) * 8) - 1), n, g)
|
||||||
of mToU8: result = newIntNodeT(getInt(a) and 0x000000FF, n)
|
of mToU8: result = newIntNodeT(getInt(a) and 0x000000FF, n, g)
|
||||||
of mToU16: result = newIntNodeT(getInt(a) and 0x0000FFFF, n)
|
of mToU16: result = newIntNodeT(getInt(a) and 0x0000FFFF, n, g)
|
||||||
of mToU32: result = newIntNodeT(getInt(a) and 0x00000000FFFFFFFF'i64, n)
|
of mToU32: result = newIntNodeT(getInt(a) and 0x00000000FFFFFFFF'i64, n, g)
|
||||||
of mUnaryLt: result = foldSub(getOrdValue(a), 1, n)
|
of mUnaryLt: result = foldSub(getOrdValue(a), 1, n, g)
|
||||||
of mSucc: result = foldAdd(getOrdValue(a), getInt(b), n)
|
of mSucc: result = foldAdd(getOrdValue(a), getInt(b), n, g)
|
||||||
of mPred: result = foldSub(getOrdValue(a), getInt(b), n)
|
of mPred: result = foldSub(getOrdValue(a), getInt(b), n, g)
|
||||||
of mAddI: result = foldAdd(getInt(a), getInt(b), n)
|
of mAddI: result = foldAdd(getInt(a), getInt(b), n, g)
|
||||||
of mSubI: result = foldSub(getInt(a), getInt(b), n)
|
of mSubI: result = foldSub(getInt(a), getInt(b), n, g)
|
||||||
of mMulI: result = foldMul(getInt(a), getInt(b), n)
|
of mMulI: result = foldMul(getInt(a), getInt(b), n, g)
|
||||||
of mMinI:
|
of mMinI:
|
||||||
if getInt(a) > getInt(b): result = newIntNodeT(getInt(b), n)
|
if getInt(a) > getInt(b): result = newIntNodeT(getInt(b), n, g)
|
||||||
else: result = newIntNodeT(getInt(a), n)
|
else: result = newIntNodeT(getInt(a), n, g)
|
||||||
of mMaxI:
|
of mMaxI:
|
||||||
if getInt(a) > getInt(b): result = newIntNodeT(getInt(a), n)
|
if getInt(a) > getInt(b): result = newIntNodeT(getInt(a), n, g)
|
||||||
else: result = newIntNodeT(getInt(b), n)
|
else: result = newIntNodeT(getInt(b), n, g)
|
||||||
of mShlI:
|
of mShlI:
|
||||||
case skipTypes(n.typ, abstractRange).kind
|
case skipTypes(n.typ, abstractRange).kind
|
||||||
of tyInt8: result = newIntNodeT(int8(getInt(a)) shl int8(getInt(b)), n)
|
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)
|
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)
|
of tyInt32: result = newIntNodeT(int32(getInt(a)) shl int32(getInt(b)), n, g)
|
||||||
of tyInt64, tyInt, tyUInt..tyUInt64:
|
of tyInt64, tyInt, tyUInt..tyUInt64:
|
||||||
result = newIntNodeT(`shl`(getInt(a), getInt(b)), n)
|
result = newIntNodeT(`shl`(getInt(a), getInt(b)), n, g)
|
||||||
else: internalError(n.info, "constant folding for shl")
|
else: internalError(g.config, n.info, "constant folding for shl")
|
||||||
of mShrI:
|
of mShrI:
|
||||||
case skipTypes(n.typ, abstractRange).kind
|
case skipTypes(n.typ, abstractRange).kind
|
||||||
of tyInt8: result = newIntNodeT(int8(getInt(a)) shr int8(getInt(b)), n)
|
of tyInt8: result = newIntNodeT(int8(getInt(a)) shr int8(getInt(b)), n, g)
|
||||||
of tyInt16: result = newIntNodeT(int16(getInt(a)) shr int16(getInt(b)), n)
|
of tyInt16: result = newIntNodeT(int16(getInt(a)) shr int16(getInt(b)), n, g)
|
||||||
of tyInt32: result = newIntNodeT(int32(getInt(a)) shr int32(getInt(b)), n)
|
of tyInt32: result = newIntNodeT(int32(getInt(a)) shr int32(getInt(b)), n, g)
|
||||||
of tyInt64, tyInt, tyUInt..tyUInt64:
|
of tyInt64, tyInt, tyUInt..tyUInt64:
|
||||||
result = newIntNodeT(`shr`(getInt(a), getInt(b)), n)
|
result = newIntNodeT(`shr`(getInt(a), getInt(b)), n, g)
|
||||||
else: internalError(n.info, "constant folding for shr")
|
else: internalError(g.config, n.info, "constant folding for shr")
|
||||||
of mDivI: result = foldDiv(getInt(a), getInt(b), n)
|
of mDivI: result = foldDiv(getInt(a), getInt(b), n, g)
|
||||||
of mModI: result = foldMod(getInt(a), getInt(b), n)
|
of mModI: result = foldMod(getInt(a), getInt(b), n, g)
|
||||||
of mAddF64: result = newFloatNodeT(getFloat(a) + getFloat(b), n)
|
of mAddF64: result = newFloatNodeT(getFloat(a) + getFloat(b), n, g)
|
||||||
of mSubF64: result = newFloatNodeT(getFloat(a) - getFloat(b), n)
|
of mSubF64: result = newFloatNodeT(getFloat(a) - getFloat(b), n, g)
|
||||||
of mMulF64: result = newFloatNodeT(getFloat(a) * getFloat(b), n)
|
of mMulF64: result = newFloatNodeT(getFloat(a) * getFloat(b), n, g)
|
||||||
of mDivF64:
|
of mDivF64:
|
||||||
if getFloat(b) == 0.0:
|
if getFloat(b) == 0.0:
|
||||||
if getFloat(a) == 0.0: result = newFloatNodeT(NaN, n)
|
if getFloat(a) == 0.0: result = newFloatNodeT(NaN, n, g)
|
||||||
elif getFloat(b).classify == fcNegZero: result = newFloatNodeT(-Inf, n)
|
elif getFloat(b).classify == fcNegZero: result = newFloatNodeT(-Inf, n, g)
|
||||||
else: result = newFloatNodeT(Inf, n)
|
else: result = newFloatNodeT(Inf, n, g)
|
||||||
else:
|
else:
|
||||||
result = newFloatNodeT(getFloat(a) / getFloat(b), n)
|
result = newFloatNodeT(getFloat(a) / getFloat(b), n, g)
|
||||||
of mMaxF64:
|
of mMaxF64:
|
||||||
if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(a), n)
|
if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(a), n, g)
|
||||||
else: result = newFloatNodeT(getFloat(b), n)
|
else: result = newFloatNodeT(getFloat(b), n, g)
|
||||||
of mMinF64:
|
of mMinF64:
|
||||||
if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(b), n)
|
if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(b), n, g)
|
||||||
else: result = newFloatNodeT(getFloat(a), n)
|
else: result = newFloatNodeT(getFloat(a), n, g)
|
||||||
of mIsNil: result = newIntNodeT(ord(a.kind == nkNilLit), n)
|
of mIsNil: result = newIntNodeT(ord(a.kind == nkNilLit), n, g)
|
||||||
of mLtI, mLtB, mLtEnum, mLtCh:
|
of mLtI, mLtB, mLtEnum, mLtCh:
|
||||||
result = newIntNodeT(ord(getOrdValue(a) < getOrdValue(b)), n)
|
result = newIntNodeT(ord(getOrdValue(a) < getOrdValue(b)), n, g)
|
||||||
of mLeI, mLeB, mLeEnum, mLeCh:
|
of mLeI, mLeB, mLeEnum, mLeCh:
|
||||||
result = newIntNodeT(ord(getOrdValue(a) <= getOrdValue(b)), n)
|
result = newIntNodeT(ord(getOrdValue(a) <= getOrdValue(b)), n, g)
|
||||||
of mEqI, mEqB, mEqEnum, mEqCh:
|
of mEqI, mEqB, mEqEnum, mEqCh:
|
||||||
result = newIntNodeT(ord(getOrdValue(a) == getOrdValue(b)), n)
|
result = newIntNodeT(ord(getOrdValue(a) == getOrdValue(b)), n, g)
|
||||||
of mLtF64: result = newIntNodeT(ord(getFloat(a) < getFloat(b)), n)
|
of mLtF64: result = newIntNodeT(ord(getFloat(a) < getFloat(b)), n, g)
|
||||||
of mLeF64: result = newIntNodeT(ord(getFloat(a) <= getFloat(b)), n)
|
of mLeF64: result = newIntNodeT(ord(getFloat(a) <= getFloat(b)), n, g)
|
||||||
of mEqF64: result = newIntNodeT(ord(getFloat(a) == getFloat(b)), n)
|
of mEqF64: result = newIntNodeT(ord(getFloat(a) == getFloat(b)), n, g)
|
||||||
of mLtStr: result = newIntNodeT(ord(getStr(a) < getStr(b)), n)
|
of mLtStr: result = newIntNodeT(ord(getStr(a) < getStr(b)), n, g)
|
||||||
of mLeStr: result = newIntNodeT(ord(getStr(a) <= getStr(b)), n)
|
of mLeStr: result = newIntNodeT(ord(getStr(a) <= getStr(b)), n, g)
|
||||||
of mEqStr: result = newIntNodeT(ord(getStr(a) == getStr(b)), n)
|
of mEqStr: result = newIntNodeT(ord(getStr(a) == getStr(b)), n, g)
|
||||||
of mLtU, mLtU64:
|
of mLtU, mLtU64:
|
||||||
result = newIntNodeT(ord(`<%`(getOrdValue(a), getOrdValue(b))), n)
|
result = newIntNodeT(ord(`<%`(getOrdValue(a), getOrdValue(b))), n, g)
|
||||||
of mLeU, mLeU64:
|
of mLeU, mLeU64:
|
||||||
result = newIntNodeT(ord(`<=%`(getOrdValue(a), getOrdValue(b))), n)
|
result = newIntNodeT(ord(`<=%`(getOrdValue(a), getOrdValue(b))), n, g)
|
||||||
of mBitandI, mAnd: result = newIntNodeT(a.getInt and b.getInt, n)
|
of mBitandI, mAnd: result = newIntNodeT(a.getInt and b.getInt, n, g)
|
||||||
of mBitorI, mOr: result = newIntNodeT(getInt(a) or getInt(b), n)
|
of mBitorI, mOr: result = newIntNodeT(getInt(a) or getInt(b), n, g)
|
||||||
of mBitxorI, mXor: result = newIntNodeT(a.getInt xor b.getInt, n)
|
of mBitxorI, mXor: result = newIntNodeT(a.getInt xor b.getInt, n, g)
|
||||||
of mAddU: result = newIntNodeT(`+%`(getInt(a), getInt(b)), n)
|
of mAddU: result = newIntNodeT(`+%`(getInt(a), getInt(b)), n, g)
|
||||||
of mSubU: result = newIntNodeT(`-%`(getInt(a), getInt(b)), n)
|
of mSubU: result = newIntNodeT(`-%`(getInt(a), getInt(b)), n, g)
|
||||||
of mMulU: result = newIntNodeT(`*%`(getInt(a), getInt(b)), n)
|
of mMulU: result = newIntNodeT(`*%`(getInt(a), getInt(b)), n, g)
|
||||||
of mModU: result = foldModU(getInt(a), getInt(b), n)
|
of mModU: result = foldModU(getInt(a), getInt(b), n, g)
|
||||||
of mDivU: result = foldDivU(getInt(a), getInt(b), n)
|
of mDivU: result = foldDivU(getInt(a), getInt(b), n, g)
|
||||||
of mLeSet: result = newIntNodeT(ord(containsSets(a, b)), n)
|
of mLeSet: result = newIntNodeT(ord(containsSets(a, b)), n, g)
|
||||||
of mEqSet: result = newIntNodeT(ord(equalSets(a, b)), n)
|
of mEqSet: result = newIntNodeT(ord(equalSets(a, b)), n, g)
|
||||||
of mLtSet:
|
of mLtSet:
|
||||||
result = newIntNodeT(ord(containsSets(a, b) and not equalSets(a, b)), n)
|
result = newIntNodeT(ord(containsSets(a, b) and not equalSets(a, b)), n, g)
|
||||||
of mMulSet:
|
of mMulSet:
|
||||||
result = nimsets.intersectSets(a, b)
|
result = nimsets.intersectSets(a, b)
|
||||||
result.info = n.info
|
result.info = n.info
|
||||||
|
|
@ -320,57 +320,57 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||||
of mSymDiffSet:
|
of mSymDiffSet:
|
||||||
result = nimsets.symdiffSets(a, b)
|
result = nimsets.symdiffSets(a, b)
|
||||||
result.info = n.info
|
result.info = n.info
|
||||||
of mConStrStr: result = newStrNodeT(getStrOrChar(a) & getStrOrChar(b), n)
|
of mConStrStr: result = newStrNodeT(getStrOrChar(a) & getStrOrChar(b), n, g)
|
||||||
of mInSet: result = newIntNodeT(ord(inSet(a, b)), n)
|
of mInSet: result = newIntNodeT(ord(inSet(a, b)), n, g)
|
||||||
of mRepr:
|
of mRepr:
|
||||||
# BUGFIX: we cannot eval mRepr here for reasons that I forgot.
|
# BUGFIX: we cannot eval mRepr here for reasons that I forgot.
|
||||||
discard
|
discard
|
||||||
of mIntToStr, mInt64ToStr: result = newStrNodeT($(getOrdValue(a)), n)
|
of mIntToStr, mInt64ToStr: result = newStrNodeT($(getOrdValue(a)), n, g)
|
||||||
of mBoolToStr:
|
of mBoolToStr:
|
||||||
if getOrdValue(a) == 0: result = newStrNodeT("false", n)
|
if getOrdValue(a) == 0: result = newStrNodeT("false", n, g)
|
||||||
else: result = newStrNodeT("true", n)
|
else: result = newStrNodeT("true", n, g)
|
||||||
of mCopyStr: result = newStrNodeT(substr(getStr(a), int(getOrdValue(b))), n)
|
of mCopyStr: result = newStrNodeT(substr(getStr(a), int(getOrdValue(b))), n, g)
|
||||||
of mCopyStrLast:
|
of mCopyStrLast:
|
||||||
result = newStrNodeT(substr(getStr(a), int(getOrdValue(b)),
|
result = newStrNodeT(substr(getStr(a), int(getOrdValue(b)),
|
||||||
int(getOrdValue(c))), n)
|
int(getOrdValue(c))), n, g)
|
||||||
of mFloatToStr: result = newStrNodeT($getFloat(a), n)
|
of mFloatToStr: result = newStrNodeT($getFloat(a), n, g)
|
||||||
of mCStrToStr, mCharToStr:
|
of mCStrToStr, mCharToStr:
|
||||||
if a.kind == nkBracket:
|
if a.kind == nkBracket:
|
||||||
var s = ""
|
var s = ""
|
||||||
for b in a.sons:
|
for b in a.sons:
|
||||||
s.add b.getStrOrChar
|
s.add b.getStrOrChar
|
||||||
result = newStrNodeT(s, n)
|
result = newStrNodeT(s, n, g)
|
||||||
else:
|
else:
|
||||||
result = newStrNodeT(getStrOrChar(a), n)
|
result = newStrNodeT(getStrOrChar(a), n, g)
|
||||||
of mStrToStr: result = a
|
of mStrToStr: result = a
|
||||||
of mEnumToStr: result = newStrNodeT(ordinalValToString(a), n)
|
of mEnumToStr: result = newStrNodeT(ordinalValToString(a, g), n, g)
|
||||||
of mArrToSeq:
|
of mArrToSeq:
|
||||||
result = copyTree(a)
|
result = copyTree(a)
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
of mCompileOption:
|
of mCompileOption:
|
||||||
result = newIntNodeT(ord(commands.testCompileOption(a.getStr, n.info)), n)
|
result = newIntNodeT(ord(commands.testCompileOption(g.config, a.getStr, n.info)), n, g)
|
||||||
of mCompileOptionArg:
|
of mCompileOptionArg:
|
||||||
result = newIntNodeT(ord(
|
result = newIntNodeT(ord(
|
||||||
testCompileOptionArg(getStr(a), getStr(b), n.info)), n)
|
testCompileOptionArg(g.config, getStr(a), getStr(b), n.info)), n, g)
|
||||||
of mEqProc:
|
of mEqProc:
|
||||||
result = newIntNodeT(ord(
|
result = newIntNodeT(ord(
|
||||||
exprStructuralEquivalent(a, b, strictSymEquality=true)), n)
|
exprStructuralEquivalent(a, b, strictSymEquality=true)), n, g)
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc getConstIfExpr(c: PSym, n: PNode): PNode =
|
proc getConstIfExpr(c: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var it = n.sons[i]
|
var it = n.sons[i]
|
||||||
if it.len == 2:
|
if it.len == 2:
|
||||||
var e = getConstExpr(c, it.sons[0])
|
var e = getConstExpr(c, it.sons[0], g)
|
||||||
if e == nil: return nil
|
if e == nil: return nil
|
||||||
if getOrdValue(e) != 0:
|
if getOrdValue(e) != 0:
|
||||||
if result == nil:
|
if result == nil:
|
||||||
result = getConstExpr(c, it.sons[1])
|
result = getConstExpr(c, it.sons[1], g)
|
||||||
if result == nil: return
|
if result == nil: return
|
||||||
elif it.len == 1:
|
elif it.len == 1:
|
||||||
if result == nil: result = getConstExpr(c, it.sons[0])
|
if result == nil: result = getConstExpr(c, it.sons[0], g)
|
||||||
else: internalError(it.info, "getConstIfExpr()")
|
else: internalError(g.config, it.info, "getConstIfExpr()")
|
||||||
|
|
||||||
proc leValueConv*(a, b: PNode): bool =
|
proc leValueConv*(a, b: PNode): bool =
|
||||||
result = false
|
result = false
|
||||||
|
|
@ -379,66 +379,66 @@ proc leValueConv*(a, b: PNode): bool =
|
||||||
case b.kind
|
case b.kind
|
||||||
of nkCharLit..nkUInt64Lit: result = a.intVal <= b.intVal
|
of nkCharLit..nkUInt64Lit: result = a.intVal <= b.intVal
|
||||||
of nkFloatLit..nkFloat128Lit: result = a.intVal <= round(b.floatVal).int
|
of nkFloatLit..nkFloat128Lit: result = a.intVal <= round(b.floatVal).int
|
||||||
else: internalError(a.info, "leValueConv")
|
else: result = false #internalError(a.info, "leValueConv")
|
||||||
of nkFloatLit..nkFloat128Lit:
|
of nkFloatLit..nkFloat128Lit:
|
||||||
case b.kind
|
case b.kind
|
||||||
of nkFloatLit..nkFloat128Lit: result = a.floatVal <= b.floatVal
|
of nkFloatLit..nkFloat128Lit: result = a.floatVal <= b.floatVal
|
||||||
of nkCharLit..nkUInt64Lit: result = a.floatVal <= toFloat(int(b.intVal))
|
of nkCharLit..nkUInt64Lit: result = a.floatVal <= toFloat(int(b.intVal))
|
||||||
else: internalError(a.info, "leValueConv")
|
else: result = false # internalError(a.info, "leValueConv")
|
||||||
else: internalError(a.info, "leValueConv")
|
else: result = false # internalError(a.info, "leValueConv")
|
||||||
|
|
||||||
proc magicCall(m: PSym, n: PNode): PNode =
|
proc magicCall(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
if sonsLen(n) <= 1: return
|
if sonsLen(n) <= 1: return
|
||||||
|
|
||||||
var s = n.sons[0].sym
|
var s = n.sons[0].sym
|
||||||
var a = getConstExpr(m, n.sons[1])
|
var a = getConstExpr(m, n.sons[1], g)
|
||||||
var b, c: PNode
|
var b, c: PNode
|
||||||
if a == nil: return
|
if a == nil: return
|
||||||
if sonsLen(n) > 2:
|
if sonsLen(n) > 2:
|
||||||
b = getConstExpr(m, n.sons[2])
|
b = getConstExpr(m, n.sons[2], g)
|
||||||
if b == nil: return
|
if b == nil: return
|
||||||
if sonsLen(n) > 3:
|
if sonsLen(n) > 3:
|
||||||
c = getConstExpr(m, n.sons[3])
|
c = getConstExpr(m, n.sons[3], g)
|
||||||
if c == nil: return
|
if c == nil: return
|
||||||
result = evalOp(s.magic, n, a, b, c)
|
result = evalOp(s.magic, n, a, b, c, g)
|
||||||
|
|
||||||
proc getAppType(n: PNode): PNode =
|
proc getAppType(n: PNode; g: ModuleGraph): PNode =
|
||||||
if gGlobalOptions.contains(optGenDynLib):
|
if gGlobalOptions.contains(optGenDynLib):
|
||||||
result = newStrNodeT("lib", n)
|
result = newStrNodeT("lib", n, g)
|
||||||
elif gGlobalOptions.contains(optGenStaticLib):
|
elif gGlobalOptions.contains(optGenStaticLib):
|
||||||
result = newStrNodeT("staticlib", n)
|
result = newStrNodeT("staticlib", n, g)
|
||||||
elif gGlobalOptions.contains(optGenGuiApp):
|
elif gGlobalOptions.contains(optGenGuiApp):
|
||||||
result = newStrNodeT("gui", n)
|
result = newStrNodeT("gui", n, g)
|
||||||
else:
|
else:
|
||||||
result = newStrNodeT("console", n)
|
result = newStrNodeT("console", n, g)
|
||||||
|
|
||||||
proc rangeCheck(n: PNode, value: BiggestInt) =
|
proc rangeCheck(n: PNode, value: BiggestInt; g: ModuleGraph) =
|
||||||
var err = false
|
var err = false
|
||||||
if n.typ.skipTypes({tyRange}).kind in {tyUInt..tyUInt64}:
|
if n.typ.skipTypes({tyRange}).kind in {tyUInt..tyUInt64}:
|
||||||
err = value <% firstOrd(n.typ) or value >% lastOrd(n.typ, fixedUnsigned=true)
|
err = value <% firstOrd(n.typ) or value >% lastOrd(n.typ, fixedUnsigned=true)
|
||||||
else:
|
else:
|
||||||
err = value < firstOrd(n.typ) or value > lastOrd(n.typ)
|
err = value < firstOrd(n.typ) or value > lastOrd(n.typ)
|
||||||
if err:
|
if err:
|
||||||
localError(n.info, errGenerated, "cannot convert " & $value &
|
localError(g.config, n.info, "cannot convert " & $value &
|
||||||
" to " & typeToString(n.typ))
|
" to " & typeToString(n.typ))
|
||||||
|
|
||||||
proc foldConv*(n, a: PNode; check = false): PNode =
|
proc foldConv*(n, a: PNode; g: ModuleGraph; check = false): PNode =
|
||||||
# XXX range checks?
|
# XXX range checks?
|
||||||
case skipTypes(n.typ, abstractRange).kind
|
case skipTypes(n.typ, abstractRange).kind
|
||||||
of tyInt..tyInt64, tyUInt..tyUInt64:
|
of tyInt..tyInt64, tyUInt..tyUInt64:
|
||||||
case skipTypes(a.typ, abstractRange).kind
|
case skipTypes(a.typ, abstractRange).kind
|
||||||
of tyFloat..tyFloat64:
|
of tyFloat..tyFloat64:
|
||||||
result = newIntNodeT(int(getFloat(a)), n)
|
result = newIntNodeT(int(getFloat(a)), n, g)
|
||||||
of tyChar: result = newIntNodeT(getOrdValue(a), n)
|
of tyChar: result = newIntNodeT(getOrdValue(a), n, g)
|
||||||
else:
|
else:
|
||||||
result = a
|
result = a
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
if check and result.kind in {nkCharLit..nkUInt64Lit}:
|
if check and result.kind in {nkCharLit..nkUInt64Lit}:
|
||||||
rangeCheck(n, result.intVal)
|
rangeCheck(n, result.intVal, g)
|
||||||
of tyFloat..tyFloat64:
|
of tyFloat..tyFloat64:
|
||||||
case skipTypes(a.typ, abstractRange).kind
|
case skipTypes(a.typ, abstractRange).kind
|
||||||
of tyInt..tyInt64, tyEnum, tyBool, tyChar:
|
of tyInt..tyInt64, tyEnum, tyBool, tyChar:
|
||||||
result = newFloatNodeT(toBiggestFloat(getOrdValue(a)), n)
|
result = newFloatNodeT(toBiggestFloat(getOrdValue(a)), n, g)
|
||||||
else:
|
else:
|
||||||
result = a
|
result = a
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
|
|
@ -448,19 +448,19 @@ proc foldConv*(n, a: PNode; check = false): PNode =
|
||||||
result = a
|
result = a
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
|
|
||||||
proc getArrayConstr(m: PSym, n: PNode): PNode =
|
proc getArrayConstr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
if n.kind == nkBracket:
|
if n.kind == nkBracket:
|
||||||
result = n
|
result = n
|
||||||
else:
|
else:
|
||||||
result = getConstExpr(m, n)
|
result = getConstExpr(m, n, g)
|
||||||
if result == nil: result = n
|
if result == nil: result = n
|
||||||
|
|
||||||
proc foldArrayAccess(m: PSym, n: PNode): PNode =
|
proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
var x = getConstExpr(m, n.sons[0])
|
var x = getConstExpr(m, n.sons[0], g)
|
||||||
if x == nil or x.typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyTypeDesc:
|
if x == nil or x.typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyTypeDesc:
|
||||||
return
|
return
|
||||||
|
|
||||||
var y = getConstExpr(m, n.sons[1])
|
var y = getConstExpr(m, n.sons[1], g)
|
||||||
if y == nil: return
|
if y == nil: return
|
||||||
|
|
||||||
var idx = getOrdValue(y)
|
var idx = getOrdValue(y)
|
||||||
|
|
@ -470,24 +470,24 @@ proc foldArrayAccess(m: PSym, n: PNode): PNode =
|
||||||
result = x.sons[int(idx)]
|
result = x.sons[int(idx)]
|
||||||
if result.kind == nkExprColonExpr: result = result.sons[1]
|
if result.kind == nkExprColonExpr: result = result.sons[1]
|
||||||
else:
|
else:
|
||||||
localError(n.info, errIndexOutOfBounds)
|
localError(g.config, n.info, "index out of bounds: " & $n)
|
||||||
of nkBracket:
|
of nkBracket:
|
||||||
idx = idx - x.typ.firstOrd
|
idx = idx - x.typ.firstOrd
|
||||||
if idx >= 0 and idx < x.len: result = x.sons[int(idx)]
|
if idx >= 0 and idx < x.len: result = x.sons[int(idx)]
|
||||||
else: localError(n.info, errIndexOutOfBounds)
|
else: localError(g.config, n.info, "index out of bounds: " & $n)
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
result = newNodeIT(nkCharLit, x.info, n.typ)
|
result = newNodeIT(nkCharLit, x.info, n.typ)
|
||||||
if idx >= 0 and idx < len(x.strVal):
|
if idx >= 0 and idx < len(x.strVal):
|
||||||
result.intVal = ord(x.strVal[int(idx)])
|
result.intVal = ord(x.strVal[int(idx)])
|
||||||
elif idx == len(x.strVal):
|
elif idx == len(x.strVal) and optLaxStrings in gOptions:
|
||||||
discard
|
discard
|
||||||
else:
|
else:
|
||||||
localError(n.info, errIndexOutOfBounds)
|
localError(g.config, n.info, "index out of bounds: " & $n)
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc foldFieldAccess(m: PSym, n: PNode): PNode =
|
proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
# a real field access; proc calls have already been transformed
|
# a real field access; proc calls have already been transformed
|
||||||
var x = getConstExpr(m, n.sons[0])
|
var x = getConstExpr(m, n.sons[0], g)
|
||||||
if x == nil or x.kind notin {nkObjConstr, nkPar, nkTupleConstr}: return
|
if x == nil or x.kind notin {nkObjConstr, nkPar, nkTupleConstr}: return
|
||||||
|
|
||||||
var field = n.sons[1].sym
|
var field = n.sons[1].sym
|
||||||
|
|
@ -501,13 +501,13 @@ proc foldFieldAccess(m: PSym, n: PNode): PNode =
|
||||||
if it.sons[0].sym.name.id == field.name.id:
|
if it.sons[0].sym.name.id == field.name.id:
|
||||||
result = x.sons[i].sons[1]
|
result = x.sons[i].sons[1]
|
||||||
return
|
return
|
||||||
localError(n.info, errFieldXNotFound, field.name.s)
|
localError(g.config, n.info, "field not found: " & field.name.s)
|
||||||
|
|
||||||
proc foldConStrStr(m: PSym, n: PNode): PNode =
|
proc foldConStrStr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
result = newNodeIT(nkStrLit, n.info, n.typ)
|
result = newNodeIT(nkStrLit, n.info, n.typ)
|
||||||
result.strVal = ""
|
result.strVal = ""
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
let a = getConstExpr(m, n.sons[i])
|
let a = getConstExpr(m, n.sons[i], g)
|
||||||
if a == nil: return nil
|
if a == nil: return nil
|
||||||
result.strVal.add(getStrOrChar(a))
|
result.strVal.add(getStrOrChar(a))
|
||||||
|
|
||||||
|
|
@ -519,7 +519,7 @@ proc newSymNodeTypeDesc*(s: PSym; info: TLineInfo): PNode =
|
||||||
else:
|
else:
|
||||||
result.typ = s.typ
|
result.typ = s.typ
|
||||||
|
|
||||||
proc getConstExpr(m: PSym, n: PNode): PNode =
|
proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
proc getSrcTimestamp(): DateTime =
|
proc getSrcTimestamp(): DateTime =
|
||||||
|
|
@ -539,32 +539,35 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
var s = n.sym
|
var s = n.sym
|
||||||
case s.kind
|
case s.kind
|
||||||
of skEnumField:
|
of skEnumField:
|
||||||
result = newIntNodeT(s.position, n)
|
result = newIntNodeT(s.position, n, g)
|
||||||
of skConst:
|
of skConst:
|
||||||
case s.magic
|
case s.magic
|
||||||
of mIsMainModule: result = newIntNodeT(ord(sfMainModule in m.flags), n)
|
of mIsMainModule: result = newIntNodeT(ord(sfMainModule in m.flags), n, g)
|
||||||
of mCompileDate: result = newStrNodeT(format(getSrcTimestamp(),
|
of mCompileDate: result = newStrNodeT(format(getSrcTimestamp(),
|
||||||
"yyyy-MM-dd"), n)
|
"yyyy-MM-dd"), n, g)
|
||||||
of mCompileTime: result = newStrNodeT(format(getSrcTimestamp(),
|
of mCompileTime: result = newStrNodeT(format(getSrcTimestamp(),
|
||||||
"HH:mm:ss"), n)
|
"HH:mm:ss"), n, g)
|
||||||
of mCpuEndian: result = newIntNodeT(ord(CPU[targetCPU].endian), n)
|
of mCpuEndian: result = newIntNodeT(ord(CPU[targetCPU].endian), n, g)
|
||||||
of mHostOS: result = newStrNodeT(toLowerAscii(platform.OS[targetOS].name), n)
|
of mHostOS: result = newStrNodeT(toLowerAscii(platform.OS[targetOS].name), n, g)
|
||||||
of mHostCPU: result = newStrNodeT(platform.CPU[targetCPU].name.toLowerAscii, n)
|
of mHostCPU: result = newStrNodeT(platform.CPU[targetCPU].name.toLowerAscii, n, g)
|
||||||
of mBuildOS: result = newStrNodeT(toLowerAscii(platform.OS[platform.hostOS].name), n)
|
of mBuildOS: result = newStrNodeT(toLowerAscii(platform.OS[platform.hostOS].name), n, g)
|
||||||
of mBuildCPU: result = newStrNodeT(platform.CPU[platform.hostCPU].name.toLowerAscii, n)
|
of mBuildCPU: result = newStrNodeT(platform.CPU[platform.hostCPU].name.toLowerAscii, n, g)
|
||||||
of mAppType: result = getAppType(n)
|
of mAppType: result = getAppType(n, g)
|
||||||
of mNaN: result = newFloatNodeT(NaN, n)
|
of mNaN: result = newFloatNodeT(NaN, n, g)
|
||||||
of mInf: result = newFloatNodeT(Inf, n)
|
of mInf: result = newFloatNodeT(Inf, n, g)
|
||||||
of mNegInf: result = newFloatNodeT(NegInf, n)
|
of mNegInf: result = newFloatNodeT(NegInf, n, g)
|
||||||
of mIntDefine:
|
of mIntDefine:
|
||||||
if isDefined(s.name):
|
if isDefined(g.config, s.name.s):
|
||||||
result = newIntNodeT(lookupSymbol(s.name).parseInt, n)
|
try:
|
||||||
|
result = newIntNodeT(g.config.symbols[s.name.s].parseInt, n, g)
|
||||||
|
except ValueError:
|
||||||
|
localError(g.config, n.info, "expression is not an integer literal")
|
||||||
of mStrDefine:
|
of mStrDefine:
|
||||||
if isDefined(s.name):
|
if isDefined(g.config, s.name.s):
|
||||||
result = newStrNodeT(lookupSymbol(s.name), n)
|
result = newStrNodeT(g.config.symbols[s.name.s], n, g)
|
||||||
else:
|
else:
|
||||||
result = copyTree(s.ast)
|
result = copyTree(s.ast)
|
||||||
of {skProc, skFunc, skMethod}:
|
of skProc, skFunc, skMethod:
|
||||||
result = n
|
result = n
|
||||||
of skType:
|
of skType:
|
||||||
# XXX gensym'ed symbols can come here and cannot be resolved. This is
|
# XXX gensym'ed symbols can come here and cannot be resolved. This is
|
||||||
|
|
@ -584,7 +587,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
of nkCharLit..nkNilLit:
|
of nkCharLit..nkNilLit:
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
of nkIfExpr:
|
of nkIfExpr:
|
||||||
result = getConstIfExpr(m, n)
|
result = getConstIfExpr(m, n, g)
|
||||||
of nkCallKinds:
|
of nkCallKinds:
|
||||||
if n.sons[0].kind != nkSym: return
|
if n.sons[0].kind != nkSym: return
|
||||||
var s = n.sons[0].sym
|
var s = n.sons[0].sym
|
||||||
|
|
@ -597,68 +600,67 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
of mSizeOf:
|
of mSizeOf:
|
||||||
var a = n.sons[1]
|
var a = n.sons[1]
|
||||||
if computeSize(a.typ) < 0:
|
if computeSize(a.typ) < 0:
|
||||||
localError(a.info, errCannotEvalXBecauseIncompletelyDefined,
|
localError(g.config, a.info, "cannot evaluate 'sizeof' because its type is not defined completely")
|
||||||
"sizeof")
|
|
||||||
result = nil
|
result = nil
|
||||||
elif skipTypes(a.typ, typedescInst+{tyRange}).kind in
|
elif skipTypes(a.typ, typedescInst+{tyRange}).kind in
|
||||||
IntegralTypes+NilableTypes+{tySet}:
|
IntegralTypes+NilableTypes+{tySet}:
|
||||||
#{tyArray,tyObject,tyTuple}:
|
#{tyArray,tyObject,tyTuple}:
|
||||||
result = newIntNodeT(getSize(a.typ), n)
|
result = newIntNodeT(getSize(a.typ), n, g)
|
||||||
else:
|
else:
|
||||||
result = nil
|
result = nil
|
||||||
# XXX: size computation for complex types is still wrong
|
# XXX: size computation for complex types is still wrong
|
||||||
of mLow:
|
of mLow:
|
||||||
result = newIntNodeT(firstOrd(n.sons[1].typ), n)
|
result = newIntNodeT(firstOrd(n.sons[1].typ), n, g)
|
||||||
of mHigh:
|
of mHigh:
|
||||||
if skipTypes(n.sons[1].typ, abstractVar).kind notin
|
if skipTypes(n.sons[1].typ, abstractVar).kind notin
|
||||||
{tySequence, tyString, tyCString, tyOpenArray, tyVarargs}:
|
{tySequence, tyString, tyCString, tyOpenArray, tyVarargs}:
|
||||||
result = newIntNodeT(lastOrd(skipTypes(n[1].typ, abstractVar)), n)
|
result = newIntNodeT(lastOrd(skipTypes(n[1].typ, abstractVar)), n, g)
|
||||||
else:
|
else:
|
||||||
var a = getArrayConstr(m, n.sons[1])
|
var a = getArrayConstr(m, n.sons[1], g)
|
||||||
if a.kind == nkBracket:
|
if a.kind == nkBracket:
|
||||||
# we can optimize it away:
|
# we can optimize it away:
|
||||||
result = newIntNodeT(sonsLen(a)-1, n)
|
result = newIntNodeT(sonsLen(a)-1, n, g)
|
||||||
of mLengthOpenArray:
|
of mLengthOpenArray:
|
||||||
var a = getArrayConstr(m, n.sons[1])
|
var a = getArrayConstr(m, n.sons[1], g)
|
||||||
if a.kind == nkBracket:
|
if a.kind == nkBracket:
|
||||||
# we can optimize it away! This fixes the bug ``len(134)``.
|
# we can optimize it away! This fixes the bug ``len(134)``.
|
||||||
result = newIntNodeT(sonsLen(a), n)
|
result = newIntNodeT(sonsLen(a), n, g)
|
||||||
else:
|
else:
|
||||||
result = magicCall(m, n)
|
result = magicCall(m, n, g)
|
||||||
of mLengthArray:
|
of mLengthArray:
|
||||||
# It doesn't matter if the argument is const or not for mLengthArray.
|
# It doesn't matter if the argument is const or not for mLengthArray.
|
||||||
# This fixes bug #544.
|
# This fixes bug #544.
|
||||||
result = newIntNodeT(lengthOrd(n.sons[1].typ), n)
|
result = newIntNodeT(lengthOrd(n.sons[1].typ), n, g)
|
||||||
of mAstToStr:
|
of mAstToStr:
|
||||||
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
|
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, g)
|
||||||
of mConStrStr:
|
of mConStrStr:
|
||||||
result = foldConStrStr(m, n)
|
result = foldConStrStr(m, n, g)
|
||||||
of mIs:
|
of mIs:
|
||||||
let a = getConstExpr(m, n[1])
|
let a = getConstExpr(m, n[1], g)
|
||||||
if a != nil and a.kind == nkSym and a.sym.kind == skType:
|
if a != nil and a.kind == nkSym and a.sym.kind == skType:
|
||||||
result = evalIs(n, a)
|
result = evalIs(n, a)
|
||||||
else:
|
else:
|
||||||
result = magicCall(m, n)
|
result = magicCall(m, n, g)
|
||||||
except OverflowError:
|
except OverflowError:
|
||||||
localError(n.info, errOverOrUnderflow)
|
localError(g.config, n.info, "over- or underflow")
|
||||||
except DivByZeroError:
|
except DivByZeroError:
|
||||||
localError(n.info, errConstantDivisionByZero)
|
localError(g.config, n.info, "division by zero")
|
||||||
of nkAddr:
|
of nkAddr:
|
||||||
var a = getConstExpr(m, n.sons[0])
|
var a = getConstExpr(m, n.sons[0], g)
|
||||||
if a != nil:
|
if a != nil:
|
||||||
result = n
|
result = n
|
||||||
n.sons[0] = a
|
n.sons[0] = a
|
||||||
of nkBracket:
|
of nkBracket:
|
||||||
result = copyTree(n)
|
result = copyTree(n)
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var a = getConstExpr(m, n.sons[i])
|
var a = getConstExpr(m, n.sons[i], g)
|
||||||
if a == nil: return nil
|
if a == nil: return nil
|
||||||
result.sons[i] = a
|
result.sons[i] = a
|
||||||
incl(result.flags, nfAllConst)
|
incl(result.flags, nfAllConst)
|
||||||
of nkRange:
|
of nkRange:
|
||||||
var a = getConstExpr(m, n.sons[0])
|
var a = getConstExpr(m, n.sons[0], g)
|
||||||
if a == nil: return
|
if a == nil: return
|
||||||
var b = getConstExpr(m, n.sons[1])
|
var b = getConstExpr(m, n.sons[1], g)
|
||||||
if b == nil: return
|
if b == nil: return
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
|
|
@ -666,7 +668,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
of nkCurly:
|
of nkCurly:
|
||||||
result = copyTree(n)
|
result = copyTree(n)
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var a = getConstExpr(m, n.sons[i])
|
var a = getConstExpr(m, n.sons[i], g)
|
||||||
if a == nil: return nil
|
if a == nil: return nil
|
||||||
result.sons[i] = a
|
result.sons[i] = a
|
||||||
incl(result.flags, nfAllConst)
|
incl(result.flags, nfAllConst)
|
||||||
|
|
@ -682,45 +684,45 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||||
result = copyTree(n)
|
result = copyTree(n)
|
||||||
if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
|
if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var a = getConstExpr(m, n.sons[i].sons[1])
|
var a = getConstExpr(m, n.sons[i].sons[1], g)
|
||||||
if a == nil: return nil
|
if a == nil: return nil
|
||||||
result.sons[i].sons[1] = a
|
result.sons[i].sons[1] = a
|
||||||
else:
|
else:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var a = getConstExpr(m, n.sons[i])
|
var a = getConstExpr(m, n.sons[i], g)
|
||||||
if a == nil: return nil
|
if a == nil: return nil
|
||||||
result.sons[i] = a
|
result.sons[i] = a
|
||||||
incl(result.flags, nfAllConst)
|
incl(result.flags, nfAllConst)
|
||||||
of nkChckRangeF, nkChckRange64, nkChckRange:
|
of nkChckRangeF, nkChckRange64, nkChckRange:
|
||||||
var a = getConstExpr(m, n.sons[0])
|
var a = getConstExpr(m, n.sons[0], g)
|
||||||
if a == nil: return
|
if a == nil: return
|
||||||
if leValueConv(n.sons[1], a) and leValueConv(a, n.sons[2]):
|
if leValueConv(n.sons[1], a) and leValueConv(a, n.sons[2]):
|
||||||
result = a # a <= x and x <= b
|
result = a # a <= x and x <= b
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
else:
|
else:
|
||||||
localError(n.info, errGenerated, `%`(
|
localError(g.config, n.info,
|
||||||
msgKindToString(errIllegalConvFromXtoY),
|
"conversion from $1 to $2 is invalid" %
|
||||||
[typeToString(n.sons[0].typ), typeToString(n.typ)]))
|
[typeToString(n.sons[0].typ), typeToString(n.typ)])
|
||||||
of nkStringToCString, nkCStringToString:
|
of nkStringToCString, nkCStringToString:
|
||||||
var a = getConstExpr(m, n.sons[0])
|
var a = getConstExpr(m, n.sons[0], g)
|
||||||
if a == nil: return
|
if a == nil: return
|
||||||
result = a
|
result = a
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||||
var a = getConstExpr(m, n.sons[1])
|
var a = getConstExpr(m, n.sons[1], g)
|
||||||
if a == nil: return
|
if a == nil: return
|
||||||
result = foldConv(n, a, check=n.kind == nkHiddenStdConv)
|
result = foldConv(n, a, g, check=n.kind == nkHiddenStdConv)
|
||||||
of nkCast:
|
of nkCast:
|
||||||
var a = getConstExpr(m, n.sons[1])
|
var a = getConstExpr(m, n.sons[1], g)
|
||||||
if a == nil: return
|
if a == nil: return
|
||||||
if n.typ != nil and n.typ.kind in NilableTypes:
|
if n.typ != nil and n.typ.kind in NilableTypes:
|
||||||
# we allow compile-time 'cast' for pointer types:
|
# we allow compile-time 'cast' for pointer types:
|
||||||
result = a
|
result = a
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
of nkBracketExpr: result = foldArrayAccess(m, n)
|
of nkBracketExpr: result = foldArrayAccess(m, n, g)
|
||||||
of nkDotExpr: result = foldFieldAccess(m, n)
|
of nkDotExpr: result = foldFieldAccess(m, n, g)
|
||||||
of nkStmtListExpr:
|
of nkStmtListExpr:
|
||||||
if n.len == 2 and n[0].kind == nkComesFrom:
|
if n.len == 2 and n[0].kind == nkComesFrom:
|
||||||
result = getConstExpr(m, n[1])
|
result = getConstExpr(m, n[1], g)
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue