diff options
author | Meng-Ying Yang <garfield@dexon.org> | 2019-04-16 17:31:23 +0800 |
---|---|---|
committer | Meng-Ying Yang <garfield@dexon.org> | 2019-05-06 15:50:03 +0800 |
commit | 8b6b72945d424b107f88f8cee55f2f84fab5be4b (patch) | |
tree | 930f50e639c59f6136ecb768c3232af54e043b1a | |
parent | e26d72dd1007cc62f9b69186a0cd56f696fe1180 (diff) | |
download | dexon-8b6b72945d424b107f88f8cee55f2f84fab5be4b.tar.gz dexon-8b6b72945d424b107f88f8cee55f2f84fab5be4b.tar.zst dexon-8b6b72945d424b107f88f8cee55f2f84fab5be4b.zip |
core: vm: sqlvm: add built-in function BITNOT()
-rw-r--r-- | core/vm/sqlvm/runtime/functions.go | 49 | ||||
-rw-r--r-- | core/vm/sqlvm/runtime/instructions_op_test.go | 53 | ||||
-rw-r--r-- | core/vm/sqlvm/runtime/instructions_tmpl_data.go | 50 |
3 files changed, 152 insertions, 0 deletions
diff --git a/core/vm/sqlvm/runtime/functions.go b/core/vm/sqlvm/runtime/functions.go index 7b062fdee..d426c8a77 100644 --- a/core/vm/sqlvm/runtime/functions.go +++ b/core/vm/sqlvm/runtime/functions.go @@ -29,6 +29,7 @@ const ( BITAND BITOR BITXOR + BITNOT ) type fn func(*common.Context, []*Operand, uint64) (*Operand, error) @@ -48,6 +49,7 @@ var ( BITAND: fnBitAnd, BITOR: fnBitOr, BITXOR: fnBitXor, + BITNOT: fnBitNot, } ) @@ -356,3 +358,50 @@ func fnBitXor(ctx *common.Context, ops []*Operand, length uint64) (result *Opera } return } + +type bitUnFunc func(b byte) byte + +func fnBitNot(ctx *common.Context, ops []*Operand, length uint64) (result *Operand, err error) { + if len(ops) < 2 { + err = se.ErrorCodeInvalidOperandNum + return + } + + op := ops[1] + if !metaAllBitOp(op) { + err = se.ErrorCodeInvalidDataType + return + } + + result = op.clone(true) + result.Data = make([]Tuple, len(op.Data)) + for i := 0; i < len(op.Data); i++ { + result.Data[i] = op.Data[i].bitUnOp( + op.Meta, + func(b byte) byte { return ^b }, + ) + } + return +} + +func (t Tuple) bitUnOp(meta []ast.DataType, bFn bitUnFunc) (t2 Tuple) { + t2 = make(Tuple, len(t)) + for i := 0; i < len(t); i++ { + t2[i] = t[i].bitUnOp(meta[i], bFn) + } + return +} + +func (r *Raw) bitUnOp(dType ast.DataType, bFn bitUnFunc) (r2 *Raw) { + bytes := r.toBytes(dType) + + n := len(bytes) + bytes2 := make([]byte, n) + for i := 0; i < n; i++ { + bytes2[i] = bFn(bytes[i]) + } + + r2 = &Raw{} + r2.fromBytes(bytes2, dType) + return +} diff --git a/core/vm/sqlvm/runtime/instructions_op_test.go b/core/vm/sqlvm/runtime/instructions_op_test.go index 42f5074db..088d889fb 100644 --- a/core/vm/sqlvm/runtime/instructions_op_test.go +++ b/core/vm/sqlvm/runtime/instructions_op_test.go @@ -3879,3 +3879,56 @@ func (s *instructionSuite) TestOpFuncBitXor() { s.run(testcases, opFunc) } + +func (s *instructionSuite) TestOpFuncBitNot() { + testcases := []opTestcase{ + { + "Func BitNot", + Instruction{ + Op: FUNC, + Input: []*Operand{ + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(ast.DataTypeMajorUint, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(2)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(ast.DataTypeMajorUint, 1), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(13)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(ast.DataTypeMajorUint, 0), ast.ComposeDataType(ast.DataTypeMajorUint, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorFixedBytes, 0), ast.ComposeDataType(ast.DataTypeMajorFixedBytes, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(128)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-128)}, &Raw{Bytes: []byte{0x12, 0x34}}, &Raw{Bytes: []byte{0xff, 0x00}}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(ast.DataTypeMajorUint, 0), ast.ComposeDataType(ast.DataTypeMajorUint, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorInt, 0), ast.ComposeDataType(ast.DataTypeMajorFixedBytes, 0), ast.ComposeDataType(ast.DataTypeMajorFixedBytes, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(127)}, &Raw{Value: decimal.NewFromFloat(255)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(127)}, &Raw{Bytes: []byte{0xed, 0xcb}}, &Raw{Bytes: []byte{0x00, 0xff}}}, + }, + ), + nil, + }, + } + + s.run(testcases, opFunc) +} diff --git a/core/vm/sqlvm/runtime/instructions_tmpl_data.go b/core/vm/sqlvm/runtime/instructions_tmpl_data.go index c0928615f..6cc1716eb 100644 --- a/core/vm/sqlvm/runtime/instructions_tmpl_data.go +++ b/core/vm/sqlvm/runtime/instructions_tmpl_data.go @@ -2784,5 +2784,55 @@ var testData = &tmplData{ }, }, // -- end of FUNC BITXOR + { + TestName: "OpFuncBitNot", OpFunc: "opFunc", + Cases: []*tmplTestCase{ + { + Name: "Func BitNot", + Error: "nil", OpCode: "FUNC", + Inputs: []*tmplOp{ + { + Im: true, + Metas: []*tmplOpMeta{ + {Major: "Uint", Minor: 0}, + }, + Data: []string{`{V: 2}`}, + }, + { + Im: true, + Metas: []*tmplOpMeta{ + {Major: "Uint", Minor: 1}, + }, + Data: []string{`{V: 13}`}, + }, + { + Im: false, + Metas: []*tmplOpMeta{ + {Major: "Uint", Minor: 0}, + {Major: "Uint", Minor: 0}, + {Major: "Int", Minor: 0}, + {Major: "Int", Minor: 0}, + {Major: "FixedBytes", Minor: 0}, + {Major: "FixedBytes", Minor: 0}, + }, + Data: []string{"{V: 128, V: 0, V: -1, V: -128, B: {0x12, 0x34}, B: {0xff, 0x00}}"}, + }, + }, + Output: &tmplOp{ + Im: false, + Metas: []*tmplOpMeta{ + {Major: "Uint", Minor: 0}, + {Major: "Uint", Minor: 0}, + {Major: "Int", Minor: 0}, + {Major: "Int", Minor: 0}, + {Major: "FixedBytes", Minor: 0}, + {Major: "FixedBytes", Minor: 0}, + }, + Data: []string{`{V: 127, V: 255, V: 0, V: 127, B: {0xed, 0xcb}, B: {0x00, 0xff}}`}, + }, + }, + }, + }, + // -- end of FUNC BITNOT }, } |