Repository: goby-lang/goby (go)

Issue:
Including an Array causes an internal error
The following code causes an internal error and subsequent panic:

```ruby
» class TestClass
¤   include []
» end
interface conversion: vm.Object is *vm.RClass, not *vm.Error
#» UndefinedMethodError: Undefined Method '[]' for TestClass
» exit
interface conversion: vm.Object is nil, not *vm.Error
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x70 pc=0xa4b5b4]

goroutine 1 [running]:
github.com/goby-lang/goby/vm.(*VM).GetREPLResult(0xc420092820, 0xc4201fa540, 0x3)
  /path/to/go/src/github.com/goby-lang/goby/vm/repl.go:73 +0x44
github.com/goby-lang/goby/igb.StartIgb(0xbd6b78, 0x7)
  /path/to/go/src/github.com/goby-lang/goby/igb/repl.go:227 +0xd18
main.main()
  /path/to/go/src/github.com/goby-lang/goby/goby.go:29 +0xbaa
```

Pull request description:
Fix #640
This closes #640

Patch:
diff --git a/vm/class.go b/vm/class.go
index 60c7e5a..4218da4 100644
--- a/vm/class.go
+++ b/vm/class.go
@@ -543,6 +543,10 @@ var builtinModuleCommonClassMethods = []*BuiltinMethodObject{
 		// @return [Null]
 		Name: "include",
 		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))
+			}
+
 			var class *RClass
 			module, ok := args[0].(*RClass)
 


Test patch:
diff --git a/vm/class_test.go b/vm/class_test.go
index b1b2ad9..797e9f6 100644
--- a/vm/class_test.go
+++ b/vm/class_test.go
@@ -554,40 +554,6 @@ func TestGeneralAssignmentByOperation(t *testing.T) {
 	}
 }
 
-func TestForbiddenInclusionWithClass(t *testing.T) {
-	input := `class Foo
-end
-
-class Bar
-  include Foo
-end
-	`
-	expected := `TypeError: Expect argument to be Module. got: Class`
-
-	v := initTestVM()
-	evaluated := v.testEval(t, input, getFilename())
-	checkErrorMsg(t, i, evaluated, expected)
-	v.checkCFP(t, 0, 2)
-	v.checkSP(t, 0, 1)
-}
-
-func TestForbiddenExtensionWithClass(t *testing.T) {
-	input := `class Foo
-end
-
-class Bar
-  extend Foo
-end
-	`
-	expected := `TypeError: Expect argument to be Module. got: Class`
-
-	v := initTestVM()
-	evaluated := v.testEval(t, input, getFilename())
-	checkErrorMsg(t, i, evaluated, expected)
-	v.checkCFP(t, 0, 2)
-	v.checkSP(t, 0, 1)
-}
-
 // Method tests
 
 func TestMethodsMethod(t *testing.T) {
@@ -1904,3 +1870,29 @@ func TestClassInspectCallsToString(t *testing.T) {
 	vm.checkCFP(t, i, 0)
 	vm.checkSP(t, i, 1)
 }
+
+func TestModuleInclusionFail(t *testing.T) {
+	testsFail := []errorTestCase{
+		{`
+class Foo
+  include []
+end
+`, "ArgumentError: Expect 1 argument(s). got: 0", 2},
+		{`
+class Foo
+  include
+end`, "ArgumentError: Expect 1 argument(s). got: 0", 2},
+		{`
+class Foo
+  include "123"
+end`, "TypeError: Expect argument to be Module. got: String", 2},
+	}
+
+	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)
+	}
+}