diff --git a/reflect_test.go b/reflect_test.go index 0409866..fc1a359 100644 --- a/reflect_test.go +++ b/reflect_test.go @@ -14,6 +14,34 @@ type testStruct struct { Jkl interface{} } +func (t *testStruct) FuncPointerReciever() string { + return "abc" +} + +func (t testStruct) FuncNoArgsNoRet() { + return +} + +func (t testStruct) FuncNoArgs() string { + return "abc" +} + +func (t testStruct) FuncNoArgsMultRet() (string, error) { + return "def", nil +} + +func (t testStruct) FuncOneArgs(a string) string { + return a +} + +func (t testStruct) FuncMultArgs(a, b string) string { + return a + b +} + +func (t testStruct) FuncVarArgs(as ...string) int { + return len(as) +} + func TestReflect(t *testing.T) { Terst(t) @@ -35,6 +63,10 @@ func Test_reflectStruct(t *testing.T) { abc := &testStruct{} failSet("abc", abc) + test(` + abc.FuncPointerReciever(); + `, "abc") + test(` [ abc.Abc, abc.Ghi ]; `, "false,") @@ -78,6 +110,26 @@ func Test_reflectStruct(t *testing.T) { [ abc.Def, abc.abc ]; `, "451,") Is(abc.Def, 451) + + test(` + abc.FuncNoArgsNoRet(); + `, "undefined") + test(` + abc.FuncNoArgs(); + `, "abc") + test(` + abc.FuncOneArgs("abc"); + `, "abc") + test(` + abc.FuncMultArgs("abc", "def"); + `, "abcdef") + test(` + abc.FuncVarArgs("abc", "def", "ghi"); + `, "3") + + test(`raise: + abc.FuncNoArgsMultRet(); + `, "TypeError") } } diff --git a/runtime.go b/runtime.go index a59ab60..c763cb5 100644 --- a/runtime.go +++ b/runtime.go @@ -322,6 +322,21 @@ func (self *_runtime) toValue(value interface{}) Value { case reflect.Array: return toValue_object(self.newGoArray(value)) } + case reflect.Func: + return toValue_object(self.newNativeFunction(func(call FunctionCall) Value { + args := make([]reflect.Value, len(call.ArgumentList)) + for i, a := range call.ArgumentList { + args[i] = reflect.ValueOf(a.export()) + } + + retvals := value.Call(args) + if len(retvals) > 1 { + panic(newTypeError()) + } else if len(retvals) == 1 { + return toValue(retvals[0].Interface()) + } + return UndefinedValue() + })) case reflect.Struct: return toValue_object(self.newGoStructObject(value)) case reflect.Map: diff --git a/type_go_struct.go b/type_go_struct.go index 0cc205e..307d7bd 100644 --- a/type_go_struct.go +++ b/type_go_struct.go @@ -27,13 +27,25 @@ func _newGoStructObject(value reflect.Value) *_goStructObject { } func (self _goStructObject) getValue(name string) reflect.Value { - return reflect.Indirect(self.value).FieldByName(name) + if field := reflect.Indirect(self.value).FieldByName(name); (field != reflect.Value{}) { + return field + } + + if method := self.value.MethodByName(name); (method != reflect.Value{}) { + return method + } + + return reflect.Value{} } func (self _goStructObject) field(name string) (reflect.StructField, bool) { return reflect.Indirect(self.value).Type().FieldByName(name) } +func (self _goStructObject) method(name string) (reflect.Method, bool) { + return reflect.Indirect(self.value).Type().MethodByName(name) +} + func (self _goStructObject) setValue(name string, value Value) bool { field, exists := self.field(name) if !exists { @@ -60,10 +72,17 @@ func goStructGetOwnProperty(self *_object, name string) *_property { func goStructEnumerate(self *_object, all bool, each func(string) bool) { object := self.value.(*_goStructObject) - count := object.value.NumField() - type_ := object.value.Type() - for index := 0; index < count; index++ { - if !each(type_.Field(index).Name) { + + // Enumerate fields + for index := 0; index < reflect.Indirect(object.value).NumField(); index++ { + if !each(reflect.Indirect(object.value).Type().Field(index).Name) { + return + } + } + + // Enumerate methods + for index := 0; index < object.value.NumMethod(); index++ { + if !each(object.value.Type().Method(index).Name) { return } }