aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm
diff options
context:
space:
mode:
Diffstat (limited to 'core/vm')
-rw-r--r--core/vm/sqlvm/errors/errors.go2
-rw-r--r--core/vm/sqlvm/runtime/functions.go11
-rw-r--r--core/vm/sqlvm/runtime/instructions.go36
-rw-r--r--core/vm/sqlvm/runtime/instructions_test.go4
-rw-r--r--core/vm/sqlvm/runtime/jumptable.go3
-rw-r--r--core/vm/sqlvm/runtime/opcodes.go5
6 files changed, 59 insertions, 2 deletions
diff --git a/core/vm/sqlvm/errors/errors.go b/core/vm/sqlvm/errors/errors.go
index b6c3909af..e69993300 100644
--- a/core/vm/sqlvm/errors/errors.go
+++ b/core/vm/sqlvm/errors/errors.go
@@ -123,6 +123,7 @@ const (
ErrorCodeDataLengthNotMatch
ErrorCodeMultipleEscapeByte
ErrorCodePendingEscapeByte
+ ErrorCodeNoSuchFunction
)
var errorCodeMap = [...]string{
@@ -157,6 +158,7 @@ var errorCodeMap = [...]string{
ErrorCodeDataLengthNotMatch: "data length not match",
ErrorCodeMultipleEscapeByte: "multiple escape byte",
ErrorCodePendingEscapeByte: "pending escape byte",
+ ErrorCodeNoSuchFunction: "no such function",
}
func (c ErrorCode) Error() string {
diff --git a/core/vm/sqlvm/runtime/functions.go b/core/vm/sqlvm/runtime/functions.go
new file mode 100644
index 000000000..798f5a573
--- /dev/null
+++ b/core/vm/sqlvm/runtime/functions.go
@@ -0,0 +1,11 @@
+package runtime
+
+import (
+ "github.com/dexon-foundation/dexon/core/vm/sqlvm/common"
+)
+
+type fn func(*common.Context, []*Operand, uint64) (*Operand, error)
+
+var (
+ fnTable = map[string]fn{}
+)
diff --git a/core/vm/sqlvm/runtime/instructions.go b/core/vm/sqlvm/runtime/instructions.go
index 5cd622180..cd034955a 100644
--- a/core/vm/sqlvm/runtime/instructions.go
+++ b/core/vm/sqlvm/runtime/instructions.go
@@ -1830,3 +1830,39 @@ func (t Tuple) neg(ctx *common.Context, meta []ast.DataType) (t2 Tuple, err erro
}
return
}
+
+func opFunc(ctx *common.Context, ops, registers []*Operand, output uint) (err error) {
+ if len(ops) < 2 {
+ err = se.ErrorCodeInvalidOperandNum
+ return
+ }
+
+ var (
+ op, funcID = ops[0], ops[1]
+ op2 *Operand
+ length uint64
+ )
+
+ if op.IsImmediate {
+ length, err = ast.DecimalToUint64(op.Data[0][0].Value)
+ if err != nil {
+ return
+ }
+ } else {
+ length = uint64(len(op.Data))
+ }
+
+ fn, ok := fnTable[string(funcID.Data[0][0].Bytes)]
+ if !ok {
+ err = se.ErrorCodeNoSuchFunction
+ return
+ }
+
+ result, err = fnTable[id](ctx, ops[2:], length)
+ if err != nil {
+ return
+ }
+
+ registers[output] = op2
+ return
+}
diff --git a/core/vm/sqlvm/runtime/instructions_test.go b/core/vm/sqlvm/runtime/instructions_test.go
index c071045e6..a399ad557 100644
--- a/core/vm/sqlvm/runtime/instructions_test.go
+++ b/core/vm/sqlvm/runtime/instructions_test.go
@@ -210,7 +210,7 @@ type opLoadTestCase struct {
func (s *opLoadSuite) SetupTest() {
s.ctx = &common.Context{}
- s.ctx.Storage = s.newStorage()
+ s.ctx.Storage = newStorage()
targetTableRef := schema.TableRef(1)
s.headHash = s.ctx.Storage.GetRowPathHash(targetTableRef, uint64(123456))
s.address = dexCommon.HexToAddress("0x6655")
@@ -374,7 +374,7 @@ func newFieldsOperand(fields []uint8) *Operand {
return o
}
-func (s *opLoadSuite) newStorage() *common.Storage {
+func newStorage() *common.Storage {
db := ethdb.NewMemDatabase()
state, _ := state.New(dexCommon.Hash{}, state.NewDatabase(db))
storage := common.NewStorage(state)
diff --git a/core/vm/sqlvm/runtime/jumptable.go b/core/vm/sqlvm/runtime/jumptable.go
index ef1fc8841..2930520a1 100644
--- a/core/vm/sqlvm/runtime/jumptable.go
+++ b/core/vm/sqlvm/runtime/jumptable.go
@@ -31,6 +31,9 @@ var jumpTable = [256]OpFunction{
CUT: opCut,
RANGE: opRange,
+ // 0x50
+ FUNC: opFunc,
+
// 0x60
LOAD: opLoad,
}
diff --git a/core/vm/sqlvm/runtime/opcodes.go b/core/vm/sqlvm/runtime/opcodes.go
index 5a0e5dd95..e65565670 100644
--- a/core/vm/sqlvm/runtime/opcodes.go
+++ b/core/vm/sqlvm/runtime/opcodes.go
@@ -51,6 +51,11 @@ const (
RANGE
)
+// 0x50 range - function ops
+const (
+ FUNC = iota + 0x50
+)
+
// 0x60 range - storage ops
const (
INSERT = iota + 0x60