diff --git a/vm/class.go b/vm/class.go index 53bd1597d..60c7e5a52 100644 --- a/vm/class.go +++ b/vm/class.go @@ -730,6 +730,31 @@ var builtinModuleCommonClassMethods = []*BuiltinMethodObject{ // Instance methods ----------------------------------------------------- var builtinClassCommonInstanceMethods = []*BuiltinMethodObject{ + { + // eql? compares the if the 2 objects have the same value and the same type + // + // ```ruby + // 10.eql?(10) # => true + // 10.0.eql?(10) # => false + // ``` + // + // ```ruby + // [10, 10].eql?([10, 10]) # => true + // [10.0, 10].eql?([10, 10]) # => false + // ``` + // + // @return [@boolean] + Name: "eql?", + Fn: func(receiver Object, sourceLine int, t *Thread, args []Object, blockFrame *normalCallFrame) Object { + if len(args) != 1 { + return t.vm.InitErrorObject(errors.ArgumentError, sourceLine, errors.WrongNumberOfArgument, 1, len(args)) + } + if receiver.Class() == args[0].Class() && receiver.equalTo(args[0]) { + return TRUE + } + return FALSE + }, + }, { // General method for comparing equalty of the objects // diff --git a/vm/evaluation_test.go b/vm/evaluation_test.go index d2369a92e..3625163cb 100644 --- a/vm/evaluation_test.go +++ b/vm/evaluation_test.go @@ -2559,3 +2559,41 @@ func TestUnusedVariableFail(t *testing.T) { v.checkSP(t, i, 1) } } + +func TestEqlComparisonOperation(t *testing.T) { + tests := []struct { + input string + expected interface{} + }{ + {`10.eql? 10`, true}, + {`10.0.eql? 10`, false}, + {`10.eql? 10.0`, false}, + } + + for i, tt := range tests { + v := initTestVM() + evaluated := v.testEval(t, tt.input, getFilename()) + VerifyExpected(t, i, evaluated, tt.expected) + v.checkCFP(t, i, 0) + v.checkSP(t, i, 1) + } +} + +func TestEqlComparisonOperationFail(t *testing.T) { + tests := []struct { + input string + expected string + expectedCFP int + }{ + {`10.eql?`, "ArgumentError: Expect 1 argument(s). got: 0", 1}, + {`10.0.eql? 10, 10`, "ArgumentError: Expect 1 argument(s). got: 2", 1}, + } + + for i, tt := range tests { + v := initTestVM() + evaluated := v.testEval(t, tt.input, getFilename()) + checkErrorMsg(t, i, evaluated, tt.expected) + v.checkCFP(t, i, tt.expectedCFP) + v.checkSP(t, i, 1) + } +}