Implement more math: non-rigogous translation for now, more precise operation correctness later
This commit is contained in:
parent
706f3982a7
commit
69475a98f5
|
@ -7,6 +7,9 @@ type
|
|||
|
||||
Int256* = distinct int # TODO
|
||||
|
||||
# TODO
|
||||
# We'll have a fast fixed Int256, for now this
|
||||
|
||||
proc `==`*(a: Int256, b: Int256): bool =
|
||||
a.int == b.int
|
||||
|
||||
|
@ -82,12 +85,24 @@ proc `and`*(a: Int256, b: Int256): Int256 =
|
|||
proc `or`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int or b.int).Int256
|
||||
|
||||
proc `xor`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int xor b.int).Int256
|
||||
|
||||
proc max*(a: Int256, b: Int256): Int256 =
|
||||
max(a.int, b.int).Int256
|
||||
|
||||
proc min*(a: Int256, b: Int256): Int256 =
|
||||
min(a.int, b.int).Int256
|
||||
|
||||
proc `-`*(a: Int256): Int256 =
|
||||
(-(a.int)).Int256
|
||||
|
||||
proc `shl`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int shl b.int).Int256
|
||||
|
||||
proc `shr`*(a: Int256, b: Int256): Int256 =
|
||||
(a.int shr b.int).Int256
|
||||
|
||||
proc repeat(b: cstring, count: int): cstring =
|
||||
# TODO: faster
|
||||
var s = $b
|
||||
|
|
BIN
src/gdb.txt
BIN
src/gdb.txt
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
# not implemented
|
|
@ -1 +0,0 @@
|
|||
|
|
|
@ -1,24 +1,23 @@
|
|||
import
|
||||
../constants, ../utils_numeric, ../stack
|
||||
../constants, ../utils_numeric, ../computation,
|
||||
.. / vm / [gas_meter, stack],
|
||||
helpers
|
||||
|
||||
template pushRes =
|
||||
computation.stack.push(res)
|
||||
|
||||
proc add*(computation: var Computation) =
|
||||
proc add*(computation: var BaseComputation) =
|
||||
# Addition
|
||||
var (left, right = computation.stack.popInt(2)
|
||||
var (left, right) = computation.stack.popInt(2)
|
||||
|
||||
var res = (left + right) and constants.UINT_256_MAX
|
||||
pushRes()
|
||||
|
||||
proc addmod*(computation: var Computation) =
|
||||
proc addmod*(computation: var BaseComputation) =
|
||||
# Modulo Addition
|
||||
var (left, right, arg) = computation.stack.popInt(3)
|
||||
|
||||
var res = if arg == 0: 0.Int256 else: (left + right) mod arg
|
||||
pushRes()
|
||||
|
||||
proc sub*(computation: var Computation) =
|
||||
proc sub*(computation: var BaseComputation) =
|
||||
# Subtraction
|
||||
var (left, right) = computation.stack.popInt(2)
|
||||
|
||||
|
@ -26,62 +25,62 @@ proc sub*(computation: var Computation) =
|
|||
pushRes()
|
||||
|
||||
|
||||
proc modulo*(computation: var Computation) =
|
||||
proc modulo*(computation: var BaseComputation) =
|
||||
# Modulo
|
||||
var (value, arg) = computation.stack.popInt(2)
|
||||
|
||||
var res = if arg == 0: 0.Int256 else: value mod arg
|
||||
pushRes()
|
||||
|
||||
proc smod*(computation: var Computation) =
|
||||
proc smod*(computation: var BaseComputation) =
|
||||
# Signed Modulo
|
||||
var (value, arg) = computation.stack.popInt(2)
|
||||
value = unsignedToSigned(value)
|
||||
arg = unsignedToSigned(value)
|
||||
|
||||
var posOrNeg = if value < 0: -1.Int256 else 1.Int256
|
||||
var res = if mod == 0: 0.Int256 else: ((value.abs mod arg.abs) * posOrNeg) and constants.UINT_256_MAX
|
||||
var posOrNeg = if value < 0: -1.Int256 else: 1.Int256
|
||||
var res = if arg == 0: 0.Int256 else: ((value.abs mod arg.abs) * posOrNeg) and constants.UINT_256_MAX
|
||||
res = signedToUnsigned(res)
|
||||
pushRes()
|
||||
|
||||
proc mul*(computation: var Computation) =
|
||||
proc mul*(computation: var BaseComputation) =
|
||||
# Multiplication
|
||||
var (left, right) = computation.stack.popInt(2)
|
||||
|
||||
var res = (left * right) and constants.UINT_256_MAX
|
||||
pushRes()
|
||||
|
||||
proc mulmod*(computation: var Computation) =
|
||||
proc mulmod*(computation: var BaseComputation) =
|
||||
# Modulo Multiplication
|
||||
var (left, right, arg) = computation.stack.popInt(3)
|
||||
|
||||
var res = if mod == 0: 0.Int256 else: (left * right) mod arg
|
||||
var res = if arg == 0: 0.Int256 else: (left * right) mod arg
|
||||
pushRes()
|
||||
|
||||
proc divide*(computation: var Computation) =
|
||||
proc divide*(computation: var BaseComputation) =
|
||||
# Division
|
||||
var (numerator, denominator) = computation.stack.popInt(2)
|
||||
|
||||
var res = if denominator == 0: 0.Int256 else: (numerator div denominator) and constants.UINT_256_MAX
|
||||
pushRes()
|
||||
|
||||
proc sdiv*(computation: var Computation) =
|
||||
proc sdiv*(computation: var BaseComputation) =
|
||||
# Signed Division
|
||||
var (numerator, denominator) = computation.stack.popInt(2)
|
||||
numerator = unsignedToSigned(numerator)
|
||||
denominator = unsignedToSigned(denominator)
|
||||
|
||||
var posOrNeg = if numerator * denominator < 0: -1.Int256 else 1.Int256
|
||||
var posOrNeg = if numerator * denominator < 0: -1.Int256 else: 1.Int256
|
||||
var res = if denominator == 0: 0.Int256 else: (posOrNeg * (numerator.abs div denominator.abs))
|
||||
res = unsignedToSigned(res)
|
||||
pushRes()
|
||||
|
||||
# no curry
|
||||
proc exp*(computation: var Computation, gasPerByte: Int256) =
|
||||
proc exp*(computation: var BaseComputation, gasPerByte: Int256) =
|
||||
# Exponentiation
|
||||
var (base, exponent) = computation.stack.popInt(2)
|
||||
|
||||
var bitSize = exponent.bitLength()
|
||||
var bitSize = 0.Int256 # TODO exponent.bitLength()
|
||||
var byteSize = ceil8(bitSize) div 8
|
||||
var res = if base == 0: 0.Int256 else: (base ^ exponent) mod constants.UINT_256_CEILING
|
||||
computation.gasMeter.consumeGas(
|
||||
|
@ -90,7 +89,7 @@ proc exp*(computation: var Computation, gasPerByte: Int256) =
|
|||
)
|
||||
pushRes()
|
||||
|
||||
proc signextend(computation: var Computation) =
|
||||
proc signextend(computation: var BaseComputation) =
|
||||
# Signed Extend
|
||||
var (bits, value) = computation.stack.popInt(2)
|
||||
|
||||
|
@ -98,7 +97,7 @@ proc signextend(computation: var Computation) =
|
|||
if bits <= 31.Int256:
|
||||
var testBit = bits * 8.Int256 + 7.Int256
|
||||
var signBit = (1.Int256 shl testBit)
|
||||
res = if value and signBit != 0: value or (constants.UINT_256_CEILING - signBit) else: value and (signBit - 1)
|
||||
res = if value != 0 and signBit != 0: value or (constants.UINT_256_CEILING - signBit) else: value and (signBit - 1.Int256)
|
||||
else:
|
||||
res = value
|
||||
pushRes()
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import
|
||||
../constants, ../utils_numeric, ../computation, ../vm/stack,
|
||||
helpers
|
||||
|
||||
quasiBoolean(lt, `<`) # Lesser Comparison
|
||||
|
||||
quasiBoolean(gt, `>`) # Greater Comparison
|
||||
|
||||
quasiBoolean(slt, `<`, signed=true) # Signed Lesser Comparison
|
||||
|
||||
quasiBoolean(sgt, `>`, signed=true) # Signed Greater Comparison
|
||||
|
||||
quasiBoolean(eq, `==`) # Equality
|
||||
|
||||
quasiBoolean(andOp, `and`, nonzero=true) # Bitwise And
|
||||
|
||||
quasiBoolean(orOp, `or`, nonzero=true) # Bitwise Or
|
||||
|
||||
quasiBoolean(xorOp, `xor`, nonzero=true) # Bitwise XOr
|
||||
|
||||
# proc iszero*(computation: var BaseComputation) =
|
||||
# var value = computation.stack.popInt()
|
||||
|
||||
# var res = if value == 0: 1.Int256 else: 0.Int256
|
||||
# pushRes()
|
||||
|
||||
# proc notOp*(computation: var BaseComputation) =
|
||||
# var value = computation.stack.popInt()
|
||||
|
||||
# var res = constants.UINT_256_MAX - value
|
||||
# pushRes()
|
||||
|
||||
# proc byteOp*(computation: var BaseComputation) =
|
||||
# # Bitwise And
|
||||
# var (position, value) = computation.stack.popInt(2)
|
||||
|
||||
# var res = if position >= 32.Int256: 0.Int256 else: (value div (256.Int256 ^ (31.Int256 - position))) mod 256
|
||||
# pushRes()
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
import macros
|
||||
|
||||
|
||||
template pushRes* =
|
||||
let resNode = ident("res")
|
||||
computation.stack.push(`resNode`)
|
||||
|
||||
macro quasiBoolean*(name: untyped, op: untyped, signed: untyped = nil, nonzero: untyped = nil): untyped =
|
||||
var signedNode = newEmptyNode()
|
||||
var finishSignedNode = newEmptyNode()
|
||||
let resNode = ident("res")
|
||||
let leftNode = ident("left")
|
||||
let rightNode = ident("right")
|
||||
if not signed.isNil:
|
||||
signedNode = quote:
|
||||
`leftNode` = unsignedToSigned(`leftNode`)
|
||||
`rightNode` = unsignedToSigned(`rightNode`)
|
||||
finishSignedNode = quote:
|
||||
`resNode` = signedToUnsigned(`resNode`)
|
||||
var test = if nonzero.isNil:
|
||||
quote:
|
||||
`op`(`leftNode`, `rightNode`)
|
||||
else:
|
||||
quote:
|
||||
`op`(`leftNode`, `rightNode`) != 0
|
||||
result = quote:
|
||||
proc `name`*(computation: var BaseComputation) =
|
||||
var (`leftNode`, `rightNode`) = computation.stack.popInt(2)
|
||||
`signedNode`
|
||||
|
||||
var `resNode` = if `test`: 1.Int256 else: 0.Int256
|
||||
`finishSignedNode`
|
||||
computation.stack.push(`resNode`)
|
|
@ -6,13 +6,13 @@ proc intToBigEndian*(value: Int256): cstring =
|
|||
proc bigEndianToInt*(value: cstring): Int256 =
|
||||
result = 0.Int256
|
||||
|
||||
proc unsignedToSigned(value: Int256): Int256 =
|
||||
proc unsignedToSigned*(value: Int256): Int256 =
|
||||
if value <= UINT_255_MAX:
|
||||
return value
|
||||
else:
|
||||
return value - UINT_256_CEILING
|
||||
|
||||
proc signedToUnsigned(value: Int256): Int256 =
|
||||
proc signedToUnsigned*(value: Int256): Int256 =
|
||||
if value < 0:
|
||||
return value + UINT_256_CEILING
|
||||
else:
|
||||
|
@ -27,7 +27,7 @@ macro ceilXX(ceiling: static[int]): untyped =
|
|||
return value
|
||||
else:
|
||||
return value + `ceiling`.Int256 - remainder
|
||||
echo result.repr
|
||||
|
||||
|
||||
ceilXX(32)
|
||||
ceilXX(8)
|
||||
|
|
|
@ -87,26 +87,32 @@ proc pop*(stack: var Stack; numItems: int): seq[Value] =
|
|||
result = stack.internalPop(numItems)
|
||||
ensurePop(result, numItems)
|
||||
|
||||
# proc popInt*(stack: var Stack): Int256 =
|
||||
# var elements = stack.internalPop(1, Int256)
|
||||
# ensurePop(elements, 1)
|
||||
# result = elements[0]
|
||||
proc popInt*(stack: var Stack): Int256 =
|
||||
var elements = stack.internalPop(1, Int256)
|
||||
ensurePop(elements, 1)
|
||||
result = elements[0]
|
||||
|
||||
macro internalPopTuple(numItems: static[int]): untyped =
|
||||
var name = ident(%"internalPopTuple{numItems}")
|
||||
var typ = nnkPar.newTree()
|
||||
var t = ident("T")
|
||||
var resultNode = ident("result")
|
||||
var stackNode = ident("stack")
|
||||
for z in 0 ..< numItems:
|
||||
typ.add(t)
|
||||
result = quote:
|
||||
proc `name`(stack: var Stack, `t`: typedesc): `typ` =
|
||||
for z in 0 ..< `numItems`:
|
||||
var value = stack.values.pop()
|
||||
case value.kind:
|
||||
of VInt:
|
||||
result[z] = toType(value.i, `t`)
|
||||
of VBinary:
|
||||
result[z] = toType(value.b, `t`)
|
||||
proc `name`*(`stackNode`: var Stack, `t`: typedesc): `typ`
|
||||
result[^1] = nnkStmtList.newTree()
|
||||
for z in 0 ..< numItems:
|
||||
var zNode = newLit(z)
|
||||
var element = quote:
|
||||
var value = `stackNode`.values.pop()
|
||||
case value.kind:
|
||||
of VInt:
|
||||
`resultNode`[`zNode`] = toType(value.i, `t`)
|
||||
of VBinary:
|
||||
`resultNode`[`zNode`] = toType(value.b, `t`)
|
||||
result[^1].add(element)
|
||||
|
||||
# define pop<T> for tuples
|
||||
internalPopTuple(2)
|
||||
|
@ -120,11 +126,11 @@ macro popInt*(stack: typed; numItems: static[int]): untyped =
|
|||
var resultNode = ident("result")
|
||||
if numItems >= 8:
|
||||
result = quote:
|
||||
`resultNode` = `stack`.internalPop(`numItems`, Int256)
|
||||
`stack`.internalPop(`numItems`, Int256)
|
||||
else:
|
||||
var name = ident(%"internalPopTuple{numItems}")
|
||||
result = quote:
|
||||
`resultNode` = `name`(`stack`, Int256)
|
||||
`name`(`stack`, Int256)
|
||||
|
||||
# proc popInt*(stack: var Stack, numItems: int): seq[Int256] =
|
||||
# result = stack.internalPop(numItems, Int256)
|
||||
|
|
Loading…
Reference in New Issue