Skip to content

Commit

Permalink
Add a rand() that can handle 0-2 arguments to generate random numbers…
Browse files Browse the repository at this point in the history
… using math/rand

Co-authored-by: Lara Aydin <ayd.dilara@gmail.com>
Co-authored-by: Michael Grosser <michael@grosser.it>
  • Loading branch information
3 people committed Jan 15, 2020
1 parent fd1ea62 commit 9a09ecb
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 7 deletions.
21 changes: 19 additions & 2 deletions vm/class.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"sort"
"math/rand"

"github.com/goby-lang/goby/vm/classes"
"github.com/goby-lang/goby/vm/errors"
Expand Down Expand Up @@ -36,14 +37,14 @@ type RClass struct {
var externalClasses = map[string][]ClassLoader{}
var externalClassLock sync.Mutex

// RegisterExternalClass will add the given class to the global registry of available classes
// RegisterExternalClass will add the given class to the global registery of available classes
func RegisterExternalClass(path string, c ...ClassLoader) {
externalClassLock.Lock()
externalClasses[path] = c
externalClassLock.Unlock()
}

// ClassLoader can be registered with a vm so that it can load this library at vm creation
// ClassLoader can be registerd with a vm so that it can load this library at vm creation
type ClassLoader = func(*VM) error

func buildMethods(m map[string]Method) []*BuiltinMethodObject {
Expand Down Expand Up @@ -1308,6 +1309,22 @@ var builtinClassCommonInstanceMethods = []*BuiltinMethodObject{

},
},
{
Name: "rand",
Fn: func(receiver Object, sourceLine int, t *Thread, args []Object, blockFrame *normalCallFrame) Object {
aLen := len(args)
switch aLen {
case 0:
return t.vm.initFloatObject(rand.Float64())
case 1:
return t.vm.InitIntegerObject(rand.Intn(args[0].Value().(int)))
case 2:
return t.vm.InitIntegerObject(rand.Intn(args[1].Value().(int) - args[0].Value().(int) + 1) + args[0].Value().(int))
default:
return t.vm.InitErrorObject(errors.ArgumentError, sourceLine, errors.WrongNumberOfArgument, 2, aLen)
}
},
},
{
// A predicate class method that returns `true` if the object has an ability to respond to the method, otherwise `false`.
// Note that signs like `+` or `?` should be String literal.
Expand Down
44 changes: 39 additions & 5 deletions vm/class_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -985,15 +985,15 @@ func TestInheritsMethodMissingMethod(t *testing.T) {
{`
class Bar
end
Bar.new.inherits_method_missing?
`, false},
{`
class Bar
inherits_method_missing
end
Bar.new.inherits_method_missing?
`, true},
Expand Down Expand Up @@ -1132,6 +1132,40 @@ func TestRaiseMethodFail(t *testing.T) {
}
}

func TestRandMethod(t *testing.T) {
tests := []struct {
input string
expected string
}{
{`rand.class.name`, "Float"},
{`rand(1).class.name`, "Integer"},
{`rand(1, 2).class.name`, "Integer"},
{`(60 < rand(64, 66)).to_s`, "true"},
{`(70 > rand(64, 66)).to_s`, "true"},
}
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 TestRandMethodFail(t *testing.T) {
testsFail := []errorTestCase{
{`rand(1, 10, 100)`, "ArgumentError: Expect 2 argument(s). got: 3", 1},
}

for i, tt := range testsFail {
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)
}
}

func TestRespondToMethod(t *testing.T) {
tests := []struct {
input string
Expand Down Expand Up @@ -1642,7 +1676,7 @@ func TestClassSingletonClassMethod(t *testing.T) {
`, "#<Class:Bar>"},
{`
module Bar; end
Bar.singleton_class.name
`, "#<Class:Bar>"},
// Check if this works on non-class objects
Expand All @@ -1654,12 +1688,12 @@ func TestClassSingletonClassMethod(t *testing.T) {
// Below is for testing module inheritance chain
{`
module Bar; end
Bar.singleton_class.class.name
`, "Class"},
{`
module Bar; end
Bar.singleton_class.superclass.name
`, "Module"},
}
Expand Down

0 comments on commit 9a09ecb

Please sign in to comment.