parent
7bf4d691a9
commit
045db09af2
4 changed files with 131 additions and 26 deletions
|
@ -100,6 +100,20 @@ func (i *Int) Value() *big.Int {
|
||||||
return i.val
|
return i.val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lte returns a bool value from the comparison of two integers, a and b.
|
||||||
|
// value is true if a <= b.
|
||||||
|
// value is false if a > b.
|
||||||
|
func (i *Int) Lte(s *Int) bool {
|
||||||
|
return i.Value().Cmp(s.Value()) != 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gte returns a bool value from the comparison of two integers, a and b.
|
||||||
|
// value is true if a >= b.
|
||||||
|
// value is false if a < b.
|
||||||
|
func (i *Int) Gte(s *Int) bool {
|
||||||
|
return i.Value().Cmp(s.Value()) != -1
|
||||||
|
}
|
||||||
|
|
||||||
// Abs returns a stack integer whose underlying value is
|
// Abs returns a stack integer whose underlying value is
|
||||||
// the absolute value of the original stack integer.
|
// the absolute value of the original stack integer.
|
||||||
func (i *Int) Abs() (*Int, error) {
|
func (i *Int) Abs() (*Int, error) {
|
||||||
|
|
|
@ -10,7 +10,9 @@ var opFunc = map[stack.Instruction]stackInfo{
|
||||||
stack.BOOLAND: BoolAnd,
|
stack.BOOLAND: BoolAnd,
|
||||||
stack.BOOLOR: BoolOr,
|
stack.BOOLOR: BoolOr,
|
||||||
stack.LT: Lt,
|
stack.LT: Lt,
|
||||||
|
stack.LTE: Lte,
|
||||||
stack.GT: Gt,
|
stack.GT: Gt,
|
||||||
|
stack.GTE: Gte,
|
||||||
stack.SHR: Shr,
|
stack.SHR: Shr,
|
||||||
stack.SHL: Shl,
|
stack.SHL: Shl,
|
||||||
stack.INC: Inc,
|
stack.INC: Inc,
|
||||||
|
|
|
@ -317,17 +317,36 @@ func Negate(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation,
|
||||||
return NONE, nil
|
return NONE, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func popTwoIntegers(ctx *stack.Context) (*stack.Int, *stack.Int, error) {
|
// Lte pops two integers, a and b, off of the stack and pushes a boolean the stack
|
||||||
operandA, err := ctx.Estack.PopInt()
|
// whose value is true if a's value is less than or equal to b's value.
|
||||||
|
// Returns an error if either items cannot be casted to an integer
|
||||||
|
func Lte(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||||
|
|
||||||
|
operandA, operandB, err := popTwoIntegers(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return FAULT, err
|
||||||
}
|
}
|
||||||
operandB, err := ctx.Estack.PopInt()
|
res := operandB.Lte(operandA)
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
ctx.Estack.Push(stack.NewBoolean(res))
|
||||||
|
|
||||||
|
return NONE, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return operandA, operandB, nil
|
// Gte pops two integers, a and b, off of the stack and pushes a boolean the stack
|
||||||
|
// whose value is true if a's value is greated than or equal to b's value.
|
||||||
|
// Returns an error if either items cannot be casted to an integer
|
||||||
|
func Gte(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rstack *stack.RandomAccess) (Vmstate, error) {
|
||||||
|
|
||||||
|
operandA, operandB, err := popTwoIntegers(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return FAULT, err
|
||||||
|
}
|
||||||
|
res := operandB.Gte(operandA)
|
||||||
|
|
||||||
|
ctx.Estack.Push(stack.NewBoolean(res))
|
||||||
|
|
||||||
|
return NONE, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shl pops two integers, a and b, off of the stack and pushes an integer to the stack
|
// Shl pops two integers, a and b, off of the stack and pushes an integer to the stack
|
||||||
|
@ -402,6 +421,19 @@ func Gt(op stack.Instruction, ctx *stack.Context, istack *stack.Invocation, rsta
|
||||||
return NONE, nil
|
return NONE, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func popTwoIntegers(ctx *stack.Context) (*stack.Int, *stack.Int, error) {
|
||||||
|
operandA, err := ctx.Estack.PopInt()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
operandB, err := ctx.Estack.PopInt()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return operandA, operandB, nil
|
||||||
|
}
|
||||||
|
|
||||||
func popTwoByteArrays(ctx *stack.Context) (*stack.ByteArray, *stack.ByteArray, error) {
|
func popTwoByteArrays(ctx *stack.Context) (*stack.ByteArray, *stack.ByteArray, error) {
|
||||||
// Pop first stack item and cast as byte array
|
// Pop first stack item and cast as byte array
|
||||||
ba1, err := ctx.Estack.PopByteArray()
|
ba1, err := ctx.Estack.PopByteArray()
|
||||||
|
|
|
@ -385,6 +385,64 @@ func TestNegateOp(t *testing.T) {
|
||||||
assert.Equal(t, int64(20), item.Value().Int64())
|
assert.Equal(t, int64(20), item.Value().Int64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLteOp(t *testing.T) {
|
||||||
|
|
||||||
|
v := VM{}
|
||||||
|
|
||||||
|
a, err := stack.NewInt(big.NewInt(10))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
b, err := stack.NewInt(big.NewInt(10))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
ctx := stack.NewContext([]byte{})
|
||||||
|
ctx.Estack.Push(a).Push(b)
|
||||||
|
|
||||||
|
// b is the first item pop.
|
||||||
|
// a is the second item pop.
|
||||||
|
// we perform a <= b and place
|
||||||
|
// the result on top of the evaluation
|
||||||
|
// stack
|
||||||
|
v.executeOp(stack.LTE, ctx)
|
||||||
|
|
||||||
|
// Stack should have one item
|
||||||
|
assert.Equal(t, 1, ctx.Estack.Len())
|
||||||
|
|
||||||
|
item, err := ctx.Estack.PopBoolean()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, true, item.Value())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGteOp(t *testing.T) {
|
||||||
|
|
||||||
|
v := VM{}
|
||||||
|
|
||||||
|
a, err := stack.NewInt(big.NewInt(10))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
b, err := stack.NewInt(big.NewInt(2))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
ctx := stack.NewContext([]byte{})
|
||||||
|
ctx.Estack.Push(a).Push(b)
|
||||||
|
|
||||||
|
// b is the first item pop.
|
||||||
|
// a is the second item pop.
|
||||||
|
// we perform a >= b and place
|
||||||
|
// the result on top of the evaluation
|
||||||
|
// stack
|
||||||
|
v.executeOp(stack.GTE, ctx)
|
||||||
|
|
||||||
|
// Stack should have one item
|
||||||
|
assert.Equal(t, 1, ctx.Estack.Len())
|
||||||
|
|
||||||
|
item, err := ctx.Estack.PopBoolean()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, true, item.Value())
|
||||||
|
}
|
||||||
|
|
||||||
func TestShlOp(t *testing.T) {
|
func TestShlOp(t *testing.T) {
|
||||||
|
|
||||||
v := VM{}
|
v := VM{}
|
||||||
|
@ -556,4 +614,3 @@ func TestGtOp(t *testing.T) {
|
||||||
|
|
||||||
assert.Equal(t, true, item.Value())
|
assert.Equal(t, true, item.Value())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue