From bdefcc5466888049709b716d847b966f37811cec Mon Sep 17 00:00:00 2001 From: Ting-Wei Lan Date: Mon, 29 Apr 2019 13:16:18 +0800 Subject: code backup 23 --- core/vm/sqlvm/ast/types.go | 138 +++++++++++++++++++++++++++++++++++++++ core/vm/sqlvm/ast/types_test.go | 118 ++++++++++++++++++++++++++++++++- core/vm/sqlvm/checker/checker.go | 46 ++++++++++++- 3 files changed, 298 insertions(+), 4 deletions(-) (limited to 'core') diff --git a/core/vm/sqlvm/ast/types.go b/core/vm/sqlvm/ast/types.go index 826bb754b..caef6375d 100644 --- a/core/vm/sqlvm/ast/types.go +++ b/core/vm/sqlvm/ast/types.go @@ -147,6 +147,144 @@ func (v BoolValue) Not() BoolValue { return boolValueNotTruthTable[v-1] } +var boolValueEqualTruthTable = [3][3]BoolValue{ + BoolValueTrue - 1: { + BoolValueTrue - 1: BoolValueTrue, + BoolValueFalse - 1: BoolValueFalse, + BoolValueUnknown - 1: BoolValueUnknown, + }, + BoolValueFalse - 1: { + BoolValueTrue - 1: BoolValueFalse, + BoolValueFalse - 1: BoolValueTrue, + BoolValueUnknown - 1: BoolValueUnknown, + }, + BoolValueUnknown - 1: { + BoolValueTrue - 1: BoolValueUnknown, + BoolValueFalse - 1: BoolValueUnknown, + BoolValueUnknown - 1: BoolValueUnknown, + }, +} + +// Equal returns v = v2. +func (v BoolValue) Equal(v2 BoolValue) BoolValue { + return boolValueEqualTruthTable[v-1][v2-1] +} + +var boolValueNotEqualTruthTable = [3][3]BoolValue{ + BoolValueTrue - 1: { + BoolValueTrue - 1: BoolValueFalse, + BoolValueFalse - 1: BoolValueTrue, + BoolValueUnknown - 1: BoolValueUnknown, + }, + BoolValueFalse - 1: { + BoolValueTrue - 1: BoolValueTrue, + BoolValueFalse - 1: BoolValueFalse, + BoolValueUnknown - 1: BoolValueUnknown, + }, + BoolValueUnknown - 1: { + BoolValueTrue - 1: BoolValueUnknown, + BoolValueFalse - 1: BoolValueUnknown, + BoolValueUnknown - 1: BoolValueUnknown, + }, +} + +// NotEqual returns v ≠ v2. +func (v BoolValue) NotEqual(v2 BoolValue) BoolValue { + return boolValueNotEqualTruthTable[v-1][v2-1] +} + +var boolValueGreaterTruthTable = [3][3]BoolValue{ + BoolValueTrue - 1: { + BoolValueTrue - 1: BoolValueFalse, + BoolValueFalse - 1: BoolValueTrue, + BoolValueUnknown - 1: BoolValueUnknown, + }, + BoolValueFalse - 1: { + BoolValueTrue - 1: BoolValueFalse, + BoolValueFalse - 1: BoolValueFalse, + BoolValueUnknown - 1: BoolValueUnknown, + }, + BoolValueUnknown - 1: { + BoolValueTrue - 1: BoolValueUnknown, + BoolValueFalse - 1: BoolValueUnknown, + BoolValueUnknown - 1: BoolValueUnknown, + }, +} + +// Greater returns v > v2. +func (v BoolValue) Greater(v2 BoolValue) BoolValue { + return boolValueGreaterTruthTable[v-1][v2-1] +} + +var boolValueGreaterOrEqualTruthTable = [3][3]BoolValue{ + BoolValueTrue - 1: { + BoolValueTrue - 1: BoolValueTrue, + BoolValueFalse - 1: BoolValueTrue, + BoolValueUnknown - 1: BoolValueUnknown, + }, + BoolValueFalse - 1: { + BoolValueTrue - 1: BoolValueFalse, + BoolValueFalse - 1: BoolValueTrue, + BoolValueUnknown - 1: BoolValueUnknown, + }, + BoolValueUnknown - 1: { + BoolValueTrue - 1: BoolValueUnknown, + BoolValueFalse - 1: BoolValueUnknown, + BoolValueUnknown - 1: BoolValueUnknown, + }, +} + +// GreaterOrEqual returns v ≥ v2. +func (v BoolValue) GreaterOrEqual(v2 BoolValue) BoolValue { + return boolValueGreaterOrEqualTruthTable[v-1][v2-1] +} + +var boolValueLessTruthTable = [3][3]BoolValue{ + BoolValueTrue - 1: { + BoolValueTrue - 1: BoolValueFalse, + BoolValueFalse - 1: BoolValueFalse, + BoolValueUnknown - 1: BoolValueUnknown, + }, + BoolValueFalse - 1: { + BoolValueTrue - 1: BoolValueTrue, + BoolValueFalse - 1: BoolValueFalse, + BoolValueUnknown - 1: BoolValueUnknown, + }, + BoolValueUnknown - 1: { + BoolValueTrue - 1: BoolValueUnknown, + BoolValueFalse - 1: BoolValueUnknown, + BoolValueUnknown - 1: BoolValueUnknown, + }, +} + +// Less returns v < v2. +func (v BoolValue) Less(v2 BoolValue) BoolValue { + return boolValueLessTruthTable[v-1][v2-1] +} + +var boolValueLessOrEqualTruthTable = [3][3]BoolValue{ + BoolValueTrue - 1: { + BoolValueTrue - 1: BoolValueTrue, + BoolValueFalse - 1: BoolValueFalse, + BoolValueUnknown - 1: BoolValueUnknown, + }, + BoolValueFalse - 1: { + BoolValueTrue - 1: BoolValueTrue, + BoolValueFalse - 1: BoolValueTrue, + BoolValueUnknown - 1: BoolValueUnknown, + }, + BoolValueUnknown - 1: { + BoolValueTrue - 1: BoolValueUnknown, + BoolValueFalse - 1: BoolValueUnknown, + BoolValueUnknown - 1: BoolValueUnknown, + }, +} + +// LessOrEqual returns v ≤ v2. +func (v BoolValue) LessOrEqual(v2 BoolValue) BoolValue { + return boolValueLessOrEqualTruthTable[v-1][v2-1] +} + // DecomposeDataType to major and minor part with given data type. func DecomposeDataType(t DataType) (DataTypeMajor, DataTypeMinor) { return DataTypeMajor(t >> 8), DataTypeMinor(t & 0xff) diff --git a/core/vm/sqlvm/ast/types_test.go b/core/vm/sqlvm/ast/types_test.go index d5f8e159d..71c543f0f 100644 --- a/core/vm/sqlvm/ast/types_test.go +++ b/core/vm/sqlvm/ast/types_test.go @@ -242,7 +242,7 @@ func (s *TypesTestSuite) TestBoolValueValidity() { s.Require().Panics(func() { _ = v.NullBool() }) } -func (s *TypesTestSuite) TestBoolValueOperations() { +func (s *TypesTestSuite) TestBoolValueBooleanOperations() { and := func(v, v2 BoolValue) BoolValue { if v == BoolValueFalse || v2 == BoolValueFalse { return BoolValueFalse @@ -272,8 +272,7 @@ func (s *TypesTestSuite) TestBoolValueOperations() { case BoolValueUnknown: return BoolValueUnknown } - // v is invalid. - return v + panic("unreachable") } values := [3]BoolValue{BoolValueTrue, BoolValueFalse, BoolValueUnknown} for _, v := range values { @@ -300,6 +299,119 @@ func (s *TypesTestSuite) TestBoolValueOperations() { } } +func (s *TypesTestSuite) TestBoolValueEqualityOperations() { + equal := func(v, v2 BoolValue) BoolValue { + if v == BoolValueUnknown || v2 == BoolValueUnknown { + return BoolValueUnknown + } + if v == v2 { + return BoolValueTrue + } + return BoolValueFalse + } + notEqual := func(v, v2 BoolValue) BoolValue { + if v == BoolValueUnknown || v2 == BoolValueUnknown { + return BoolValueUnknown + } + if v == v2 { + return BoolValueFalse + } + return BoolValueTrue + } + values := [3]BoolValue{BoolValueTrue, BoolValueFalse, BoolValueUnknown} + for _, v := range values { + for _, v2 := range values { + expected := equal(v, v2) + actual := v.Equal(v2) + s.Require().Equal(expected, actual, + "%v = %v = %v, but %v is returned", v, v2, expected, actual) + } + } + for _, v := range values { + for _, v2 := range values { + expected := notEqual(v, v2) + actual := v.NotEqual(v2) + s.Require().Equal(expected, actual, + "%v ≠ %v = %v, but %v is returned", v, v2, expected, actual) + } + } +} + +func (s *TypesTestSuite) TestBoolValueOrderingOperations() { + boolValueToInt := func(v BoolValue) int { + return [2]int{ + BoolValueTrue - 1: 1, + BoolValueFalse - 1: 0, + }[v-1] + } + boolToBoolValue := func(v bool) BoolValue { + switch v { + case true: + return BoolValueTrue + case false: + return BoolValueFalse + } + panic("unreachable") + } + greater := func(v, v2 BoolValue) BoolValue { + if v == BoolValueUnknown || v2 == BoolValueUnknown { + return BoolValueUnknown + } + return boolToBoolValue(boolValueToInt(v) > boolValueToInt(v2)) + } + greaterOrEqual := func(v, v2 BoolValue) BoolValue { + if v == BoolValueUnknown || v2 == BoolValueUnknown { + return BoolValueUnknown + } + return boolToBoolValue(boolValueToInt(v) >= boolValueToInt(v2)) + } + less := func(v, v2 BoolValue) BoolValue { + if v == BoolValueUnknown || v2 == BoolValueUnknown { + return BoolValueUnknown + } + return boolToBoolValue(boolValueToInt(v) < boolValueToInt(v2)) + } + lessOrEqual := func(v, v2 BoolValue) BoolValue { + if v == BoolValueUnknown || v2 == BoolValueUnknown { + return BoolValueUnknown + } + return boolToBoolValue(boolValueToInt(v) <= boolValueToInt(v2)) + } + values := [3]BoolValue{BoolValueTrue, BoolValueFalse, BoolValueUnknown} + for _, v := range values { + for _, v2 := range values { + expected := greater(v, v2) + actual := v.Greater(v2) + s.Require().Equal(expected, actual, + "%v > %v = %v, but %v is returned", v, v2, expected, actual) + } + } + for _, v := range values { + for _, v2 := range values { + expected := greaterOrEqual(v, v2) + actual := v.GreaterOrEqual(v2) + s.Require().Equal(expected, actual, + "%v ≥ %v = %v, but %v is returned", v, v2, expected, actual) + } + } + for _, v := range values { + for _, v2 := range values { + expected := less(v, v2) + actual := v.Less(v2) + s.Require().Equal(expected, actual, + "%v < %v < %v, but %v is returned", v, v2, expected, actual) + } + } + for _, v := range values { + for _, v2 := range values { + expected := lessOrEqual(v, v2) + actual := v.LessOrEqual(v2) + s.Require().Equal(expected, actual, + "%v ≤ %v = %v, but %v is returned", v, v2, expected, actual) + } + } +} + func TestTypes(t *testing.T) { suite.Run(t, new(TypesTestSuite)) } diff --git a/core/vm/sqlvm/checker/checker.go b/core/vm/sqlvm/checker/checker.go index 792210bed..05e1cb10a 100644 --- a/core/vm/sqlvm/checker/checker.go +++ b/core/vm/sqlvm/checker/checker.go @@ -866,7 +866,7 @@ func checkExpr(n ast.ExprNode, return checkOrOperator(n, s, o, c, el, tr, ta) case *ast.GreaterOrEqualOperatorNode: - return n + return checkGreaterOrEqualOperator(n, s, o, c, el, tr, ta) case *ast.LessOrEqualOperatorNode: return n @@ -2019,3 +2019,47 @@ func checkOrOperator(n *ast.OrOperatorNode, } return r } + +func validateOrderedType(dt ast.DataType, el *errors.ErrorList, n ast.ExprNode, + fn, op string) bool { + + if !dt.Pending() { + major, _ := ast.DecomposeDataType(dt) + switch { + case major == ast.DataTypeMajorBool, + major == ast.DataTypeMajorAddress, + major == ast.DataTypeMajorInt, + major == ast.DataTypeMajorUint, + major == ast.DataTypeMajorFixedBytes, + major == ast.DataTypeMajorDynamicBytes, + major.IsFixedRange(), + major.IsFixedRange(): + default: + elAppendTypeErrorOperatorDataType(el, n, fn, op, dt) + return false + } + } + return true +} + +func checkGreaterOrEqualOperator(n *ast.GreaterOrEqualOperatorNode, + s schema.Schema, o CheckOptions, c *schemaCache, el *errors.ErrorList, + tr schema.TableRef, ta typeAction) ast.ExprNode { + + fn := "CheckGreaterOrEqualOperator" + op := "binary operator >=" + + object := n.GetObject() + object = checkExpr(object, s, o, c, el, tr, ta) + if object == nil { + return nil + } + subject := n.GetSubject() + subject = checkExpr(subject, s, o, c, el, tr, ta) + if subject == nil { + return nil + } + n.SetObject(object) + n.SetSubject(subject) + r := ast.ExprNode(n) +} -- cgit v1.2.3