Skip to content

Commit

Permalink
Merge pull request #21 from sidhant92/types_conversion
Browse files Browse the repository at this point in the history
implicit conversion of data types
  • Loading branch information
sidhant92 authored Aug 27, 2024
2 parents 33eaffd + cab2fd0 commit 433510a
Show file tree
Hide file tree
Showing 16 changed files with 216 additions and 56 deletions.
7 changes: 5 additions & 2 deletions internal/operator/abstract_operator.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package operator

import "github.com/sidhant92/bool-parser-go/pkg/constant"
import (
"github.com/sidhant92/bool-parser-go/pkg/constant"
"github.com/sidhant92/bool-parser-go/pkg/domain"
)

type AbstractOperator interface {
Evaluate(containerDataType constant.ContainerDataType, dataType constant.DataType, validated bool, left interface{}, right ...interface{}) (bool, error)
Evaluate(containerDataType constant.ContainerDataType, leftOperand interface{}, leftOperandDataType constant.DataType, rightOperands []domain.EvaluatedNode) (bool, error)

GetSymbol() string

Expand Down
16 changes: 10 additions & 6 deletions internal/operator/contains_all_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@ package operator

import (
"github.com/sidhant92/bool-parser-go/pkg/constant"
"github.com/sidhant92/bool-parser-go/pkg/domain"
"reflect"
)

type ContainsAllOperator struct {
}

func (e *ContainsAllOperator) Evaluate(containerDataType constant.ContainerDataType, dataType constant.DataType, validated bool, left interface{}, right ...interface{}) (bool, error) {
var leftArray []interface{}
rv := reflect.ValueOf(left)
func (e *ContainsAllOperator) Evaluate(containerDataType constant.ContainerDataType, leftOperand interface{}, leftOperandDataType constant.DataType, rightOperands []domain.EvaluatedNode) (bool, error) {
var leftArray []domain.EvaluatedNode
rv := reflect.ValueOf(leftOperand)
if rv.Kind() == reflect.Slice {
for i := 0; i < rv.Len(); i++ {
leftArray = append(leftArray, rv.Index(i).Interface())
leftArray = append(leftArray, domain.EvaluatedNode{
Value: rv.Index(i).Interface(),
DataType: leftOperandDataType,
})
}
}
for _, value := range right {
res, err := GetOperator(constant.IN).Evaluate(constant.PRIMITIVE, dataType, validated, value, leftArray...)
for _, rightOperand := range rightOperands {
res, err := GetOperator(constant.IN).Evaluate(constant.PRIMITIVE, rightOperand.Value, rightOperand.DataType, leftArray)
if err != nil {
return false, err
}
Expand Down
16 changes: 10 additions & 6 deletions internal/operator/contains_any_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@ package operator

import (
"github.com/sidhant92/bool-parser-go/pkg/constant"
"github.com/sidhant92/bool-parser-go/pkg/domain"
"reflect"
)

type ContainsAnyOperator struct {
}

func (e *ContainsAnyOperator) Evaluate(containerDataType constant.ContainerDataType, dataType constant.DataType, validated bool, left interface{}, right ...interface{}) (bool, error) {
var leftArray []interface{}
rv := reflect.ValueOf(left)
func (e *ContainsAnyOperator) Evaluate(containerDataType constant.ContainerDataType, leftOperand interface{}, leftOperandDataType constant.DataType, rightOperands []domain.EvaluatedNode) (bool, error) {
var leftArray []domain.EvaluatedNode
rv := reflect.ValueOf(leftOperand)
if rv.Kind() == reflect.Slice {
for i := 0; i < rv.Len(); i++ {
leftArray = append(leftArray, rv.Index(i).Interface())
leftArray = append(leftArray, domain.EvaluatedNode{
Value: rv.Index(i).Interface(),
DataType: leftOperandDataType,
})
}
}
for _, value := range right {
res, err := GetOperator(constant.IN).Evaluate(constant.PRIMITIVE, dataType, validated, value, leftArray...)
for _, rightOperand := range rightOperands {
res, err := GetOperator(constant.IN).Evaluate(constant.PRIMITIVE, rightOperand.Value, rightOperand.DataType, leftArray)
if err != nil {
return false, err
}
Expand Down
15 changes: 12 additions & 3 deletions internal/operator/equals_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,29 @@ package operator
import (
"github.com/sidhant92/bool-parser-go/internal/datatype"
"github.com/sidhant92/bool-parser-go/pkg/constant"
"github.com/sidhant92/bool-parser-go/pkg/domain"
)

type EqualsOperator struct {
}

func (e *EqualsOperator) Evaluate(containerDataType constant.ContainerDataType, dataType constant.DataType, validated bool, left interface{}, right ...interface{}) (bool, error) {
dt := datatype.GetDataType(dataType)
res, err := dt.Compare(left, right[0], validated)
func (e *EqualsOperator) Evaluate(containerDataType constant.ContainerDataType, leftOperand interface{}, leftOperandDataType constant.DataType, rightOperands []domain.EvaluatedNode) (bool, error) {
comparableDataType := getComparableDataType(leftOperandDataType, rightOperands[0].DataType)
dt := datatype.GetDataType(comparableDataType)
res, err := dt.Compare(leftOperand, rightOperands[0].Value, true)
if err != nil {
return false, err
}
return res == 0, nil
}

func getComparableDataType(leftOperandDataType constant.DataType, rightOperandDataType constant.DataType) constant.DataType {
if constant.DataTypeAttributes[leftOperandDataType].Priority > constant.DataTypeAttributes[rightOperandDataType].Priority {
return leftOperandDataType
}
return rightOperandDataType
}

func (e *EqualsOperator) GetSymbol() string {
return "="
}
Expand Down
12 changes: 9 additions & 3 deletions internal/operator/greater_than_equal_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ package operator
import (
"github.com/sidhant92/bool-parser-go/internal/datatype"
"github.com/sidhant92/bool-parser-go/pkg/constant"
"github.com/sidhant92/bool-parser-go/pkg/domain"
)

type GreaterThanEqualOperator struct {
}

func (e *GreaterThanEqualOperator) Evaluate(containerDataType constant.ContainerDataType, dataType constant.DataType, validated bool, left interface{}, right ...interface{}) (bool, error) {
dt := datatype.GetDataType(dataType)
res, err := dt.Compare(left, right[0], validated)
func (e *GreaterThanEqualOperator) Evaluate(containerDataType constant.ContainerDataType, leftOperand interface{}, leftOperandDataType constant.DataType, rightOperands []domain.EvaluatedNode) (bool, error) {
err := Validate(leftOperand, leftOperandDataType, rightOperands[0].Value, rightOperands[0].DataType)
if err != nil {
return false, err
}
comparableDataType := GetComparableDataType(leftOperandDataType, rightOperands[0].DataType)
dt := datatype.GetDataType(comparableDataType)
res, err := dt.Compare(leftOperand, rightOperands[0].Value, true)
if err != nil {
return false, err
}
Expand Down
12 changes: 9 additions & 3 deletions internal/operator/greater_than_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ package operator
import (
"github.com/sidhant92/bool-parser-go/internal/datatype"
"github.com/sidhant92/bool-parser-go/pkg/constant"
"github.com/sidhant92/bool-parser-go/pkg/domain"
)

type GreaterThanOperator struct {
}

func (e *GreaterThanOperator) Evaluate(containerDataType constant.ContainerDataType, dataType constant.DataType, validated bool, left interface{}, right ...interface{}) (bool, error) {
dt := datatype.GetDataType(dataType)
res, err := dt.Compare(left, right[0], validated)
func (e *GreaterThanOperator) Evaluate(containerDataType constant.ContainerDataType, leftOperand interface{}, leftOperandDataType constant.DataType, rightOperands []domain.EvaluatedNode) (bool, error) {
err := Validate(leftOperand, leftOperandDataType, rightOperands[0].Value, rightOperands[0].DataType)
if err != nil {
return false, err
}
comparableDataType := GetComparableDataType(leftOperandDataType, rightOperands[0].DataType)
dt := datatype.GetDataType(comparableDataType)
res, err := dt.Compare(leftOperand, rightOperands[0].Value, true)
if err != nil {
return false, err
}
Expand Down
7 changes: 4 additions & 3 deletions internal/operator/in_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ package operator

import (
"github.com/sidhant92/bool-parser-go/pkg/constant"
"github.com/sidhant92/bool-parser-go/pkg/domain"
)

type InOperator struct {
}

func (e *InOperator) Evaluate(containerDataType constant.ContainerDataType, dataType constant.DataType, validated bool, left interface{}, right ...interface{}) (bool, error) {
for _, value := range right {
res, err := GetOperator(constant.EQUALS).Evaluate(containerDataType, dataType, validated, left, value)
func (e *InOperator) Evaluate(containerDataType constant.ContainerDataType, leftOperand interface{}, leftOperandDataType constant.DataType, rightOperands []domain.EvaluatedNode) (bool, error) {
for _, value := range rightOperands {
res, err := GetOperator(constant.EQUALS).Evaluate(containerDataType, leftOperand, leftOperandDataType, []domain.EvaluatedNode{value})
if err != nil {
return false, err
}
Expand Down
12 changes: 9 additions & 3 deletions internal/operator/less_than_equal_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ package operator
import (
"github.com/sidhant92/bool-parser-go/internal/datatype"
"github.com/sidhant92/bool-parser-go/pkg/constant"
"github.com/sidhant92/bool-parser-go/pkg/domain"
)

type LessThanEqualOperator struct {
}

func (e *LessThanEqualOperator) Evaluate(containerDataType constant.ContainerDataType, dataType constant.DataType, validated bool, left interface{}, right ...interface{}) (bool, error) {
dt := datatype.GetDataType(dataType)
res, err := dt.Compare(left, right[0], validated)
func (e *LessThanEqualOperator) Evaluate(containerDataType constant.ContainerDataType, leftOperand interface{}, leftOperandDataType constant.DataType, rightOperands []domain.EvaluatedNode) (bool, error) {
err := Validate(leftOperand, leftOperandDataType, rightOperands[0].Value, rightOperands[0].DataType)
if err != nil {
return false, err
}
comparableDataType := GetComparableDataType(leftOperandDataType, rightOperands[0].DataType)
dt := datatype.GetDataType(comparableDataType)
res, err := dt.Compare(leftOperand, rightOperands[0].Value, true)
if err != nil {
return false, err
}
Expand Down
12 changes: 9 additions & 3 deletions internal/operator/less_than_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ package operator
import (
"github.com/sidhant92/bool-parser-go/internal/datatype"
"github.com/sidhant92/bool-parser-go/pkg/constant"
"github.com/sidhant92/bool-parser-go/pkg/domain"
)

type LessThanOperator struct {
}

func (e *LessThanOperator) Evaluate(containerDataType constant.ContainerDataType, dataType constant.DataType, validated bool, left interface{}, right ...interface{}) (bool, error) {
dt := datatype.GetDataType(dataType)
res, err := dt.Compare(left, right[0], validated)
func (e *LessThanOperator) Evaluate(containerDataType constant.ContainerDataType, leftOperand interface{}, leftOperandDataType constant.DataType, rightOperands []domain.EvaluatedNode) (bool, error) {
err := Validate(leftOperand, leftOperandDataType, rightOperands[0].Value, rightOperands[0].DataType)
if err != nil {
return false, err
}
comparableDataType := GetComparableDataType(leftOperandDataType, rightOperands[0].DataType)
dt := datatype.GetDataType(comparableDataType)
res, err := dt.Compare(leftOperand, rightOperands[0].Value, true)
if err != nil {
return false, err
}
Expand Down
5 changes: 3 additions & 2 deletions internal/operator/not_equals_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ package operator

import (
"github.com/sidhant92/bool-parser-go/pkg/constant"
"github.com/sidhant92/bool-parser-go/pkg/domain"
)

type NotEqualsOperator struct {
}

func (e *NotEqualsOperator) Evaluate(containerDataType constant.ContainerDataType, dataType constant.DataType, validated bool, left interface{}, right ...interface{}) (bool, error) {
func (e *NotEqualsOperator) Evaluate(containerDataType constant.ContainerDataType, leftOperand interface{}, leftOperandDataType constant.DataType, rightOperands []domain.EvaluatedNode) (bool, error) {
eq := GetOperator(constant.EQUALS)
res, err := eq.Evaluate(containerDataType, dataType, validated, left, right[0])
res, err := eq.Evaluate(containerDataType, leftOperand, leftOperandDataType, rightOperands)
if err != nil {
return false, err
}
Expand Down
41 changes: 41 additions & 0 deletions internal/operator/numeric_operator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package operator

import (
"github.com/sidhant92/bool-parser-go/internal/datatype"
"github.com/sidhant92/bool-parser-go/pkg/constant"
errors2 "github.com/sidhant92/bool-parser-go/pkg/error"
"log"
)

func GetComparableDataType(leftOperandDataType constant.DataType, rightOperandDataType constant.DataType) constant.DataType {
if (constant.DataTypeAttributes[leftOperandDataType].Numeric && !constant.DataTypeAttributes[rightOperandDataType].Numeric) || (!constant.DataTypeAttributes[leftOperandDataType].Numeric && constant.DataTypeAttributes[rightOperandDataType].Numeric) {
if constant.DataTypeAttributes[leftOperandDataType].Numeric {
return leftOperandDataType
}
return rightOperandDataType
}
if constant.DataTypeAttributes[leftOperandDataType].Priority > constant.DataTypeAttributes[rightOperandDataType].Priority {
return leftOperandDataType
}
return rightOperandDataType
}

func Validate(leftOperand interface{}, leftOperandDataType constant.DataType, rightOperand interface{}, rightOperandDataType constant.DataType) error {
if constant.DataTypeAttributes[leftOperandDataType].Numeric && constant.DataTypeAttributes[rightOperandDataType].Numeric {
return nil
}
if !constant.DataTypeAttributes[leftOperandDataType].Numeric && !constant.DataTypeAttributes[rightOperandDataType].Numeric {
return nil
}
rightDataType := datatype.GetDataType(rightOperandDataType)
if !constant.DataTypeAttributes[leftOperandDataType].Numeric && !rightDataType.IsValid(leftOperand) {
log.Printf("Incompatible data types %s and %s", leftOperandDataType, rightOperandDataType)
return errors2.INCOMPATIBLE_DATA_TYPE
}
leftDataType := datatype.GetDataType(leftOperandDataType)
if !constant.DataTypeAttributes[rightOperandDataType].Numeric && !leftDataType.IsValid(rightOperand) {
log.Printf("Incompatible data types %s and %s", leftOperandDataType, rightOperandDataType)
return errors2.INCOMPATIBLE_DATA_TYPE
}
return nil
}
13 changes: 7 additions & 6 deletions internal/service/operator_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/sidhant92/bool-parser-go/internal/containerdatatype"
op "github.com/sidhant92/bool-parser-go/internal/operator"
"github.com/sidhant92/bool-parser-go/pkg/constant"
"github.com/sidhant92/bool-parser-go/pkg/domain"
errors2 "github.com/sidhant92/bool-parser-go/pkg/error"
"log"
"slices"
Expand All @@ -21,21 +22,21 @@ func (o *OperatorService) GetOperatorFromSymbol(symbol string) constant.Operator
panic("Unknown Operator " + symbol)
}

func (o *OperatorService) Evaluate(operator constant.Operator, containerDataType constant.ContainerDataType, dataType constant.DataType, leftOperand interface{}, rightOperand ...interface{}) (bool, error) {
func (o *OperatorService) Evaluate(operator constant.Operator, containerDataType constant.ContainerDataType, leftOperand interface{}, leftOperandDataType constant.DataType, rightOperands []domain.EvaluatedNode) (bool, error) {
var abstractOperator = op.GetOperator(operator)
if !slices.Contains(abstractOperator.GetAllowedContainerTypes(), containerDataType) {
log.Printf("Invalid container type %s for the the operator %s", containerDataType, operator)
return false, errors2.INVALID_CONTAINER_DATA_TYPE
}
if !slices.Contains(abstractOperator.GetAllowedDataTypes(), dataType) {
log.Printf("Invalid data type %s for the the operator %s", dataType, operator)
if !slices.Contains(abstractOperator.GetAllowedDataTypes(), leftOperandDataType) {
log.Printf("Invalid data type %s for the the operator %s for the operand %v", leftOperandDataType, operator, leftOperand)
return false, errors2.INVALID_DATA_TYPE
}
if !containerdatatype.GetContainerDataType(containerDataType).IsValid(dataType, leftOperand) {
log.Printf("validation failed for the operator %s for the the operand %v", operator, leftOperand)
if !containerdatatype.GetContainerDataType(containerDataType).IsValid(leftOperandDataType, leftOperand) {
log.Printf("validation failed for the operator %s for the the operand %v for data type %s", operator, leftOperand, leftOperandDataType)
return false, errors2.INVALID_DATA_TYPE
}
res, err := abstractOperator.Evaluate(containerDataType, dataType, true, leftOperand, rightOperand...)
res, err := abstractOperator.Evaluate(containerDataType, leftOperand, leftOperandDataType, rightOperands)
if err != nil {
return false, err
}
Expand Down
Loading

0 comments on commit 433510a

Please sign in to comment.