parent
14e0ab48dd
commit
afe670f178
6 changed files with 110 additions and 0 deletions
|
@ -92,3 +92,15 @@ func (i *Int) Boolean() (*Boolean, error) {
|
||||||
func (i *Int) Value() *big.Int {
|
func (i *Int) Value() *big.Int {
|
||||||
return i.val
|
return i.val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Abs returns a stack integer whose underlying value is
|
||||||
|
// the absolute value of the original stack integer.
|
||||||
|
func (i *Int) Abs() (*Int, error) {
|
||||||
|
a := big.NewInt(0).Abs(i.Value())
|
||||||
|
b, err := NewInt(a)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
|
@ -24,3 +24,9 @@ func (b *Boolean) Boolean() (*Boolean, error) {
|
||||||
func (b *Boolean) Value() bool {
|
func (b *Boolean) Value() bool {
|
||||||
return b.val
|
return b.val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Not returns a Boolean whose underlying value is flipped.
|
||||||
|
// If the value is True, it is flipped to False and viceversa
|
||||||
|
func (b *Boolean) Not() *Boolean {
|
||||||
|
return NewBoolean(!b.Value())
|
||||||
|
}
|
||||||
|
|
|
@ -148,3 +148,13 @@ func (ras *RandomAccess) PopByteArray() (*ByteArray, error) {
|
||||||
}
|
}
|
||||||
return item.ByteArray()
|
return item.ByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PopBoolean will remove the last stack item that was added
|
||||||
|
// and cast it to a Boolean.
|
||||||
|
func (ras *RandomAccess) PopBoolean() (*Boolean, error) {
|
||||||
|
item, err := ras.Pop()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return item.Boolean()
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ type stackInfo func(op stack.Instruction, ctx *stack.Context, istack *stack.Invo
|
||||||
var opFunc = map[stack.Instruction]stackInfo{
|
var opFunc = map[stack.Instruction]stackInfo{
|
||||||
stack.INC: Inc,
|
stack.INC: Inc,
|
||||||
stack.DEC: Dec,
|
stack.DEC: Dec,
|
||||||
|
stack.ABS: Abs,
|
||||||
|
stack.NOT: Not,
|
||||||
stack.SIGN: Sign,
|
stack.SIGN: Sign,
|
||||||
stack.NEGATE: Negate,
|
stack.NEGATE: Negate,
|
||||||
stack.ADD: Add,
|
stack.ADD: Add,
|
||||||
|
|
|
@ -94,6 +94,39 @@ func Dec(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rst
|
||||||
return NONE, nil
|
return NONE, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Abs pops an integer off of the stack and pushes its absolute value onto the stack.
|
||||||
|
// Returns an error if the popped value is not an integer or if the absolute value cannot be taken
|
||||||
|
func Abs(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||||
|
|
||||||
|
i, err := ctx.Estack.PopInt()
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
|
||||||
|
a, err := i.Abs()
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Estack.Push(a)
|
||||||
|
|
||||||
|
return NONE, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not flips the stack Item's value.
|
||||||
|
// If the value is True, it is flipped to False and viceversa.
|
||||||
|
func Not(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||||
|
|
||||||
|
b, err := ctx.Estack.PopBoolean()
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Estack.Push(b.Not())
|
||||||
|
|
||||||
|
return NONE, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Sign puts the sign of the top stack Item on top of the stack.
|
// Sign puts the sign of the top stack Item on top of the stack.
|
||||||
// If value is negative, put -1;
|
// If value is negative, put -1;
|
||||||
// If positive, put 1;
|
// If positive, put 1;
|
||||||
|
|
|
@ -118,6 +118,53 @@ func TestSubOp(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAbsOp(t *testing.T) {
|
||||||
|
|
||||||
|
v := VM{}
|
||||||
|
|
||||||
|
a, err := stack.NewInt(big.NewInt(-20))
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := stack.NewContext([]byte{})
|
||||||
|
ctx.Estack.Push(a)
|
||||||
|
|
||||||
|
v.executeOp(stack.ABS, ctx)
|
||||||
|
|
||||||
|
// Stack should have one item
|
||||||
|
assert.Equal(t, 1, ctx.Estack.Len())
|
||||||
|
|
||||||
|
item, err := ctx.Estack.PopInt()
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, int64(20), item.Value().Int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotOp(t *testing.T) {
|
||||||
|
|
||||||
|
v := VM{}
|
||||||
|
|
||||||
|
b := stack.NewBoolean(false)
|
||||||
|
|
||||||
|
ctx := stack.NewContext([]byte{})
|
||||||
|
ctx.Estack.Push(b)
|
||||||
|
|
||||||
|
v.executeOp(stack.NOT, ctx)
|
||||||
|
|
||||||
|
// Stack should have one item
|
||||||
|
assert.Equal(t, 1, ctx.Estack.Len())
|
||||||
|
|
||||||
|
item, err := ctx.Estack.PopBoolean()
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, true, item.Value())
|
||||||
|
}
|
||||||
|
|
||||||
func TestSignOp(t *testing.T) {
|
func TestSignOp(t *testing.T) {
|
||||||
|
|
||||||
v := VM{}
|
v := VM{}
|
||||||
|
|
Loading…
Reference in a new issue