Skip to content

Commit

Permalink
feat!: improve BinaryOperatorHandler api
Browse files Browse the repository at this point in the history
  • Loading branch information
moisespsena committed Sep 14, 2023
1 parent 80c25fd commit 124f7b6
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 61 deletions.
6 changes: 0 additions & 6 deletions bytecode.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"strings"

"github.com/gad-lang/gad/parser"
"github.com/gad-lang/gad/token"
)

// Bytecode holds the compiled functions and constants.
Expand Down Expand Up @@ -202,11 +201,6 @@ func (o *CompiledFunction) Copy() Object {
}
}

// BinaryOp implements Object interface.
func (*CompiledFunction) BinaryOp(token.Token, Object) (Object, error) {
return nil, ErrInvalidOperator
}

// IsFalsy implements Object interface.
func (*CompiledFunction) IsFalsy() bool { return false }

Expand Down
47 changes: 22 additions & 25 deletions objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -708,13 +708,15 @@ func (o Array) Items() (arr KeyValueArray) {

func (o Array) Sort() (_ Object, err error) {
sort.Slice(o, func(i, j int) bool {
v, e := o[i].BinaryOp(token.Less, o[j])
if e != nil && err == nil {
err = e
return false
}
if v != nil {
return !v.IsFalsy()
if bo, _ := o[i].(BinaryOperatorHandler); bo != nil {
v, e := bo.BinaryOp(token.Less, o[j])
if e != nil && err == nil {
err = e
return false
}
if v != nil {
return !v.IsFalsy()
}
}
return false
})
Expand All @@ -723,13 +725,15 @@ func (o Array) Sort() (_ Object, err error) {

func (o Array) SortReverse() (_ Object, err error) {
sort.Slice(o, func(i, j int) bool {
v, e := o[j].BinaryOp(token.Less, o[i])
if e != nil && err == nil {
err = e
return false
}
if v != nil {
return !v.IsFalsy()
if bo, _ := o[j].(BinaryOperatorHandler); bo != nil {
v, e := bo.BinaryOp(token.Less, o[i])
if e != nil && err == nil {
err = e
return false
}
if v != nil {
return !v.IsFalsy()
}
}
return false
})
Expand Down Expand Up @@ -787,7 +791,10 @@ func (o *ObjectPtr) BinaryOp(tok token.Token, right Object) (Object, error) {
if o.Value == nil {
return nil, errors.New("nil pointer")
}
return (*o.Value).BinaryOp(tok, right)
if bo, _ := (*o.Value).(BinaryOperatorHandler); bo != nil {
return bo.BinaryOp(tok, right)
}
return nil, ErrInvalidOperator
}

// CanCall implements Object interface.
Expand Down Expand Up @@ -1260,11 +1267,6 @@ func (o *Error) NewError(messages ...string) *Error {
return cp
}

// BinaryOp implements Object interface.
func (o *Error) BinaryOp(tok token.Token, right Object) (Object, error) {
return nil, ErrInvalidOperator
}

// RuntimeError represents a runtime error that wraps Error and includes trace information.
type RuntimeError struct {
Err *Error
Expand Down Expand Up @@ -1374,11 +1376,6 @@ func (o *RuntimeError) NewError(messages ...string) *RuntimeError {
return cp
}

// BinaryOp implements Object interface.
func (o *RuntimeError) BinaryOp(tok token.Token, right Object) (Object, error) {
return nil, ErrInvalidOperator
}

// StackTrace returns stack trace if set otherwise returns nil.
func (o *RuntimeError) StackTrace() StackTrace {
if o.fileSet == nil {
Expand Down
17 changes: 7 additions & 10 deletions objects_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ type Object interface {
// String should return a string of the type's value.
String() string

// BinaryOp handles +,-,*,/,%,<<,>>,<=,>=,<,> operators.
// Returned error stops VM execution if not handled with an error handler
// and VM.Run returns the same error as wrapped.
BinaryOp(tok token.Token, right Object) (Object, error)

// IsFalsy returns true if value is falsy otherwise false.
IsFalsy() bool

Expand Down Expand Up @@ -195,11 +190,6 @@ func (ObjectImpl) Equal(Object) bool { return false }
// IsFalsy implements Object interface.
func (ObjectImpl) IsFalsy() bool { return true }

// BinaryOp implements Object interface.
func (ObjectImpl) BinaryOp(_ token.Token, _ Object) (Object, error) {
return nil, ErrInvalidOperator
}

// NilType represents the type of global Nil Object. One should use
// the NilType in type switches only.
type NilType struct {
Expand Down Expand Up @@ -268,3 +258,10 @@ func Iterable(obj Object) bool {
}
return false
}

type BinaryOperatorHandler interface {
// BinaryOp handles +,-,*,/,%,<<,>>,<=,>=,<,> operators.
// Returned error stops VM execution if not handled with an error handler
// and VM.Run returns the same error as wrapped.
BinaryOp(tok token.Token, right Object) (Object, error)
}
7 changes: 5 additions & 2 deletions objects_namedargs.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,11 @@ func (o KeyValue) IsLess(other KeyValue) bool {
if o.Key().String() < other.Key().String() {
return true
}
v, _ := o.Value().BinaryOp(token.Less, other.Value())
return v == nil || !v.IsFalsy()
if bo, _ := o.Value().(BinaryOperatorHandler); bo != nil {
v, _ := bo.BinaryOp(token.Less, other.Value())
return v == nil || !v.IsFalsy()
}
return false
}

// CanIterate implements Object interface.
Expand Down
6 changes: 0 additions & 6 deletions objects_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import (

"github.com/stretchr/testify/require"

"github.com/gad-lang/gad/token"

. "github.com/gad-lang/gad"
)

Expand Down Expand Up @@ -193,10 +191,6 @@ func TestObjectImpl(t *testing.T) {
require.True(t, impl.IsFalsy())
require.False(t, Callable(impl))
require.False(t, Iterable(impl))
v, err := impl.BinaryOp(token.Add, Int(0))
require.Nil(t, v)
require.NotNil(t, err)
require.Equal(t, ErrInvalidOperator, err)
}

func TestObjectIndexGet(t *testing.T) {
Expand Down
14 changes: 2 additions & 12 deletions vm_loop.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,10 @@ VMLoop:
var value Object
var err error
switch left := left.(type) {
case Int:
value, err = left.BinaryOp(tok, right)
case String:
value, err = left.BinaryOp(tok, right)
case Float:
value, err = left.BinaryOp(tok, right)
case Uint:
value, err = left.BinaryOp(tok, right)
case Char:
value, err = left.BinaryOp(tok, right)
case Bool:
case BinaryOperatorHandler:
value, err = left.BinaryOp(tok, right)
default:
value, err = left.BinaryOp(tok, right)
err = ErrInvalidOperator
}
if err == nil {
vm.stack[vm.sp-2] = value
Expand Down

0 comments on commit 124f7b6

Please sign in to comment.