Merge branch 'devel' of https://github.com/Araq/Nimrod into devel
This commit is contained in:
commit
29fdc7a5be
12 changed files with 238 additions and 15 deletions
|
|
@ -495,18 +495,46 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
else: stackTrace(c, tos, pc, errNilAccess)
|
else: stackTrace(c, tos, pc, errNilAccess)
|
||||||
of opcAddInt:
|
of opcAddInt:
|
||||||
decodeBC(rkInt)
|
decodeBC(rkInt)
|
||||||
regs[ra].intVal = regs[rb].intVal + regs[rc].intVal
|
let
|
||||||
|
bVal = regs[rb].intVal
|
||||||
|
cVal = regs[rc].intVal
|
||||||
|
sum = bVal +% cVal
|
||||||
|
if (sum xor bVal) >= 0 or (sum xor cVal) >= 0:
|
||||||
|
regs[ra].intVal = sum
|
||||||
|
else:
|
||||||
|
stackTrace(c, tos, pc, errOverOrUnderflow)
|
||||||
of opcAddImmInt:
|
of opcAddImmInt:
|
||||||
decodeBImm(rkInt)
|
decodeBImm(rkInt)
|
||||||
#message(c.debug[pc], warnUser, "came here")
|
#message(c.debug[pc], warnUser, "came here")
|
||||||
#debug regs[rb].node
|
#debug regs[rb].node
|
||||||
regs[ra].intVal = regs[rb].intVal + imm
|
let
|
||||||
|
bVal = regs[rb].intVal
|
||||||
|
cVal = imm
|
||||||
|
sum = bVal +% cVal
|
||||||
|
if (sum xor bVal) >= 0 or (sum xor cVal) >= 0:
|
||||||
|
regs[ra].intVal = sum
|
||||||
|
else:
|
||||||
|
stackTrace(c, tos, pc, errOverOrUnderflow)
|
||||||
of opcSubInt:
|
of opcSubInt:
|
||||||
decodeBC(rkInt)
|
decodeBC(rkInt)
|
||||||
regs[ra].intVal = regs[rb].intVal - regs[rc].intVal
|
let
|
||||||
|
bVal = regs[rb].intVal
|
||||||
|
cVal = regs[rc].intVal
|
||||||
|
diff = bVal -% cVal
|
||||||
|
if (diff xor bVal) >= 0 or (diff xor not cVal) >= 0:
|
||||||
|
regs[ra].intVal = diff
|
||||||
|
else:
|
||||||
|
stackTrace(c, tos, pc, errOverOrUnderflow)
|
||||||
of opcSubImmInt:
|
of opcSubImmInt:
|
||||||
decodeBImm(rkInt)
|
decodeBImm(rkInt)
|
||||||
regs[ra].intVal = regs[rb].intVal - imm
|
let
|
||||||
|
bVal = regs[rb].intVal
|
||||||
|
cVal = imm
|
||||||
|
diff = bVal -% cVal
|
||||||
|
if (diff xor bVal) >= 0 or (diff xor not cVal) >= 0:
|
||||||
|
regs[ra].intVal = diff
|
||||||
|
else:
|
||||||
|
stackTrace(c, tos, pc, errOverOrUnderflow)
|
||||||
of opcLenSeq:
|
of opcLenSeq:
|
||||||
decodeBImm(rkInt)
|
decodeBImm(rkInt)
|
||||||
#assert regs[rb].kind == nkBracket
|
#assert regs[rb].kind == nkBracket
|
||||||
|
|
@ -539,7 +567,18 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
regs[ra].intVal = nimsets.cardSet(regs[rb].node)
|
regs[ra].intVal = nimsets.cardSet(regs[rb].node)
|
||||||
of opcMulInt:
|
of opcMulInt:
|
||||||
decodeBC(rkInt)
|
decodeBC(rkInt)
|
||||||
regs[ra].intVal = regs[rb].intVal * regs[rc].intVal
|
let
|
||||||
|
bVal = regs[rb].intVal
|
||||||
|
cVal = regs[rc].intVal
|
||||||
|
product = bVal *% cVal
|
||||||
|
floatProd = toBiggestFloat(bVal) * toBiggestFloat(cVal)
|
||||||
|
resAsFloat = toBiggestFloat(product)
|
||||||
|
if resAsFloat == floatProd:
|
||||||
|
regs[ra].intVal = product
|
||||||
|
elif 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
|
||||||
|
regs[ra].intVal = product
|
||||||
|
else:
|
||||||
|
stackTrace(c, tos, pc, errOverOrUnderflow)
|
||||||
of opcDivInt:
|
of opcDivInt:
|
||||||
decodeBC(rkInt)
|
decodeBC(rkInt)
|
||||||
if regs[rc].intVal == 0: stackTrace(c, tos, pc, errConstantDivisionByZero)
|
if regs[rc].intVal == 0: stackTrace(c, tos, pc, errConstantDivisionByZero)
|
||||||
|
|
@ -632,7 +671,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
of opcUnaryMinusInt:
|
of opcUnaryMinusInt:
|
||||||
decodeB(rkInt)
|
decodeB(rkInt)
|
||||||
assert regs[rb].kind == rkInt
|
assert regs[rb].kind == rkInt
|
||||||
regs[ra].intVal = -regs[rb].intVal
|
let val = regs[rb].intVal
|
||||||
|
if val != int64.low:
|
||||||
|
regs[ra].intVal = -val
|
||||||
|
else:
|
||||||
|
stackTrace(c, tos, pc, errOverOrUnderflow)
|
||||||
of opcUnaryMinusFloat:
|
of opcUnaryMinusFloat:
|
||||||
decodeB(rkFloat)
|
decodeB(rkFloat)
|
||||||
assert regs[rb].kind == rkFloat
|
assert regs[rb].kind == rkFloat
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ proc clearHandlers*(handler: var TEventHandler) =
|
||||||
## Clears all of the callbacks from the event handler.
|
## Clears all of the callbacks from the event handler.
|
||||||
setLen(handler.handlers, 0)
|
setLen(handler.handlers, 0)
|
||||||
|
|
||||||
proc getEventhandler(emitter: var TEventEmitter, event: string): int =
|
proc getEventHandler(emitter: var TEventEmitter, event: string): int =
|
||||||
for k in 0..high(emitter.s):
|
for k in 0..high(emitter.s):
|
||||||
if emitter.s[k].name == event: return k
|
if emitter.s[k].name == event: return k
|
||||||
return -1
|
return -1
|
||||||
|
|
@ -94,8 +94,6 @@ proc emit*(emitter: var TEventEmitter, event: string, args: TEventArgs) =
|
||||||
var i = getEventHandler(emitter, event)
|
var i = getEventHandler(emitter, event)
|
||||||
if i >= 0:
|
if i >= 0:
|
||||||
emit(emitter, emitter.s[i], args)
|
emit(emitter, emitter.s[i], args)
|
||||||
else:
|
|
||||||
raise newException(EInvalidEvent, "invalid event: " & event)
|
|
||||||
|
|
||||||
proc initEventEmitter*(): TEventEmitter =
|
proc initEventEmitter*(): TEventEmitter =
|
||||||
## Creates and returns a new EventEmitter.
|
## Creates and returns a new EventEmitter.
|
||||||
|
|
|
||||||
|
|
@ -182,3 +182,129 @@ proc zlibAllocMem*(AppData: Pointer, Items, Size: int): Pointer {.cdecl.} =
|
||||||
|
|
||||||
proc zlibFreeMem*(AppData, `Block`: Pointer) {.cdecl.} =
|
proc zlibFreeMem*(AppData, `Block`: Pointer) {.cdecl.} =
|
||||||
dealloc(`Block`)
|
dealloc(`Block`)
|
||||||
|
|
||||||
|
proc uncompress*(sourceBuf: cstring, sourceLen: int): string =
|
||||||
|
## Given a deflated cstring returns its inflated version.
|
||||||
|
##
|
||||||
|
## Passing a nil cstring will crash this proc in release mode and assert in
|
||||||
|
## debug mode.
|
||||||
|
##
|
||||||
|
## Returns nil on problems. Failure is a very loose concept, it could be you
|
||||||
|
## passing a non deflated string, or it could mean not having enough memory
|
||||||
|
## for the inflated version.
|
||||||
|
##
|
||||||
|
## The uncompression algorithm is based on
|
||||||
|
## http://stackoverflow.com/questions/17820664 but does ignore some of the
|
||||||
|
## original signed/unsigned checks, so may fail with big chunks of data
|
||||||
|
## exceeding the positive size of an int32. The algorithm can deal with
|
||||||
|
## concatenated deflated values properly.
|
||||||
|
assert (not sourceBuf.isNil)
|
||||||
|
|
||||||
|
var z: TZStream
|
||||||
|
# Initialize input.
|
||||||
|
z.next_in = sourceBuf
|
||||||
|
|
||||||
|
# Input left to decompress.
|
||||||
|
var left = zlib.Uint(sourceLen)
|
||||||
|
if left < 1:
|
||||||
|
# Incomplete gzip stream, or overflow?
|
||||||
|
return
|
||||||
|
|
||||||
|
# Create starting space for output (guess double the input size, will grow if
|
||||||
|
# needed -- in an extreme case, could end up needing more than 1000 times the
|
||||||
|
# input size)
|
||||||
|
var space = zlib.Uint(left shl 1)
|
||||||
|
if space < left:
|
||||||
|
space = left
|
||||||
|
|
||||||
|
var decompressed = newStringOfCap(space)
|
||||||
|
|
||||||
|
# Initialize output.
|
||||||
|
z.next_out = addr(decompressed[0])
|
||||||
|
# Output generated so far.
|
||||||
|
var have = 0
|
||||||
|
|
||||||
|
# Set up for gzip decoding.
|
||||||
|
z.avail_in = 0;
|
||||||
|
var status = inflateInit2(z, (15+16))
|
||||||
|
if status != Z_OK:
|
||||||
|
# Out of memory.
|
||||||
|
return
|
||||||
|
|
||||||
|
# Make sure memory allocated by inflateInit2() is freed eventually.
|
||||||
|
finally: discard inflateEnd(z)
|
||||||
|
|
||||||
|
# Decompress all of self.
|
||||||
|
while true:
|
||||||
|
# Allow for concatenated gzip streams (per RFC 1952).
|
||||||
|
if status == Z_STREAM_END:
|
||||||
|
discard inflateReset(z)
|
||||||
|
|
||||||
|
# Provide input for inflate.
|
||||||
|
if z.avail_in == 0:
|
||||||
|
# This only makes sense in the C version using unsigned values.
|
||||||
|
z.avail_in = left
|
||||||
|
left -= z.avail_in
|
||||||
|
|
||||||
|
# Decompress the available input.
|
||||||
|
while true:
|
||||||
|
# Allocate more output space if none left.
|
||||||
|
if space == have:
|
||||||
|
# Double space, handle overflow.
|
||||||
|
space = space shl 1
|
||||||
|
if space < have:
|
||||||
|
# Space was likely already maxed out.
|
||||||
|
discard inflateEnd(z)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Increase space.
|
||||||
|
decompressed.setLen(space)
|
||||||
|
# Update output pointer (might have moved).
|
||||||
|
z.next_out = addr(decompressed[have])
|
||||||
|
|
||||||
|
# Provide output space for inflate.
|
||||||
|
z.avail_out = zlib.Uint(space - have)
|
||||||
|
have += z.avail_out;
|
||||||
|
|
||||||
|
# Inflate and update the decompressed size.
|
||||||
|
status = inflate(z, Z_SYNC_FLUSH);
|
||||||
|
have -= z.avail_out;
|
||||||
|
|
||||||
|
# Bail out if any errors.
|
||||||
|
if status != Z_OK and status != Z_BUF_ERROR and status != Z_STREAM_END:
|
||||||
|
# Invalid gzip stream.
|
||||||
|
discard inflateEnd(z)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Repeat until all output is generated from provided input (note
|
||||||
|
# that even if z.avail_in is zero, there may still be pending
|
||||||
|
# output -- we're not done until the output buffer isn't filled)
|
||||||
|
if z.avail_out != 0:
|
||||||
|
break
|
||||||
|
# Continue until all input consumed.
|
||||||
|
if left == 0 and z.avail_in == 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Verify that the input is a valid gzip stream.
|
||||||
|
if status != Z_STREAM_END:
|
||||||
|
# Incomplete gzip stream.
|
||||||
|
return
|
||||||
|
|
||||||
|
decompressed.setLen(have)
|
||||||
|
swap(result, decompressed)
|
||||||
|
|
||||||
|
|
||||||
|
proc inflate*(buffer: var string): bool {.discardable.} =
|
||||||
|
## Convenience proc which inflates a string containing compressed data.
|
||||||
|
##
|
||||||
|
## Passing a nil string will crash this proc in release mode and assert in
|
||||||
|
## debug mode. It is ok to pass a buffer which doesn't contain deflated data,
|
||||||
|
## in this case the proc won't modify the buffer.
|
||||||
|
##
|
||||||
|
## Returns true if `buffer` was successfully inflated.
|
||||||
|
assert (not buffer.isNil)
|
||||||
|
if buffer.len < 1: return
|
||||||
|
var temp = uncompress(addr(buffer[0]), buffer.len)
|
||||||
|
if not temp.isNil:
|
||||||
|
swap(buffer, temp)
|
||||||
|
result = true
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
errmsg: "type mismatch: got (array[0..2, float], array[0..1, float])"
|
errormsg: "type mismatch: got (array[0..2, float], array[0..1, float])"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
proc `+`*[R, T] (v1, v2: array[R, T]): array[R, T] =
|
proc `+`*[R, T] (v1, v2: array[R, T]): array[R, T] =
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
errmsg: "nested proc can have generic parameters only when"
|
errormsg: "nested proc can have generic parameters only when"
|
||||||
line: 6
|
line: 6
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
discard """
|
discard """
|
||||||
cmd: "nimrod check $# $#"
|
cmd: "nimrod check $# $#"
|
||||||
errmsg: "'proc' is not a concrete type"
|
errormsg: "'proc' is not a concrete type"
|
||||||
errmsg: "'Foo' is not a concrete type."
|
errormsg: "'Foo' is not a concrete type."
|
||||||
errmsg: "invalid type: 'TBaseMed'"
|
errormsg: "invalid type: 'TBaseMed'"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
discard """
|
discard """
|
||||||
output: '''108
|
output: '''108
|
||||||
11 -1 1936
|
11 -1 1936
|
||||||
4.0000000000000002e-001
|
4.0000000000000002e-01
|
||||||
true
|
true
|
||||||
truefalse'''
|
truefalse'''
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
11
tests/vm/toverflowopcaddimmint.nim
Normal file
11
tests/vm/toverflowopcaddimmint.nim
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "over- or underflow"
|
||||||
|
"""
|
||||||
|
|
||||||
|
static:
|
||||||
|
proc p =
|
||||||
|
var
|
||||||
|
x = int64.high
|
||||||
|
discard x + 1
|
||||||
|
assert false
|
||||||
|
p()
|
||||||
12
tests/vm/toverflowopcaddint.nim
Normal file
12
tests/vm/toverflowopcaddint.nim
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "over- or underflow"
|
||||||
|
"""
|
||||||
|
|
||||||
|
static:
|
||||||
|
proc p =
|
||||||
|
var
|
||||||
|
x = int64.high
|
||||||
|
y = 1
|
||||||
|
discard x + y
|
||||||
|
assert false
|
||||||
|
p()
|
||||||
11
tests/vm/toverflowopcmulint.nim
Normal file
11
tests/vm/toverflowopcmulint.nim
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "over- or underflow"
|
||||||
|
"""
|
||||||
|
|
||||||
|
static:
|
||||||
|
proc p =
|
||||||
|
var
|
||||||
|
x = 1 shl 62
|
||||||
|
discard x * 2
|
||||||
|
assert false
|
||||||
|
p()
|
||||||
10
tests/vm/toverflowopcsubimmint.nim
Normal file
10
tests/vm/toverflowopcsubimmint.nim
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "over- or underflow"
|
||||||
|
"""
|
||||||
|
|
||||||
|
static:
|
||||||
|
proc p =
|
||||||
|
var x = int64.low
|
||||||
|
discard x - 1
|
||||||
|
assert false
|
||||||
|
p()
|
||||||
12
tests/vm/toverflowopcsubint.nim
Normal file
12
tests/vm/toverflowopcsubint.nim
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "over- or underflow"
|
||||||
|
"""
|
||||||
|
|
||||||
|
static:
|
||||||
|
proc p =
|
||||||
|
var
|
||||||
|
x = int64.low
|
||||||
|
y = 1
|
||||||
|
discard x - y
|
||||||
|
assert false
|
||||||
|
p()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue