Skip to content

Commit

Permalink
Support the private field and auto change the struct to the point whe…
Browse files Browse the repository at this point in the history
…n exec the method
  • Loading branch information
SimFG committed Jul 29, 2024
1 parent 5e660e7 commit 12f0cff
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 2 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@
custom_tests.json
pro/
test/avs/

simfg
.idea
9 changes: 9 additions & 0 deletions checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,15 @@ func (v *checker) MemberNode(node *ast.MemberNode) Nature {
if m, ok := base.MethodByName(name.Value); ok {
return m
}
if m, ok := reflect.PtrTo(base).MethodByName(name.Value); ok {
if kind(base) == reflect.Interface {
return m.Type, info{}
} else {
node.SetMethodIndex(m.Index)
node.Name = name.Value
return m.Type, info{method: true}
}
}
}

base = base.Deref()
Expand Down
52 changes: 50 additions & 2 deletions vm/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"fmt"
"math"
"reflect"
"unsafe"
)

"github.com/expr-lang/expr/internal/deref"

Check failure on line 12 in vm/runtime/runtime.go

View workflow job for this annotation

GitHub Actions / debug

syntax error: non-declaration statement outside function body

Check failure on line 12 in vm/runtime/runtime.go

View workflow job for this annotation

GitHub Actions / test (1.18, 386)

syntax error: non-declaration statement outside function body

Check failure on line 12 in vm/runtime/runtime.go

View workflow job for this annotation

GitHub Actions / test (1.22, 386)

syntax error: non-declaration statement outside function body

Check failure on line 12 in vm/runtime/runtime.go

View workflow job for this annotation

GitHub Actions / race

syntax error: non-declaration statement outside function body

Check failure on line 12 in vm/runtime/runtime.go

View workflow job for this annotation

GitHub Actions / test (1.18)

syntax error: non-declaration statement outside function body

Check failure on line 12 in vm/runtime/runtime.go

View workflow job for this annotation

GitHub Actions / test (1.19)

syntax error: non-declaration statement outside function body

Check failure on line 12 in vm/runtime/runtime.go

View workflow job for this annotation

GitHub Actions / test (1.20)

syntax error: non-declaration statement outside function body

Check failure on line 12 in vm/runtime/runtime.go

View workflow job for this annotation

GitHub Actions / test (1.21)

syntax error: non-declaration statement outside function body

Check failure on line 12 in vm/runtime/runtime.go

View workflow job for this annotation

GitHub Actions / test (1.22)

syntax error: non-declaration statement outside function body
)
Expand Down Expand Up @@ -95,12 +97,23 @@ func FetchField(from any, field *Field) any {
// is a struct as we already did it on compilation step.
value := fieldByIndex(v, field)
if value.IsValid() {
return value.Interface()
return GetFieldValue(value)
}
}
panic(fmt.Sprintf("cannot get %v from %T", field.Path[0], from))
}

func GetFieldValue(value reflect.Value) (result any) {
defer func() {
if err := recover(); err != nil {
h := reflect.NewAt(value.Type(), unsafe.Pointer(value.UnsafeAddr())).Elem()
result = h.Interface()
}
}()
result = value.Interface()
return
}

func fieldByIndex(v reflect.Value, field *Field) reflect.Value {
if len(field.Index) == 1 {
return v.Field(field.Index[0])
Expand Down Expand Up @@ -129,14 +142,49 @@ func FetchMethod(from any, method *Method) any {
kind := v.Kind()
if kind != reflect.Invalid {
// Methods can be defined on any type, no need to dereference.
method := v.Method(method.Index)
method := GetMethodValue(v, method.Index)
if method.IsValid() {
return method.Interface()
}
}
panic(fmt.Sprintf("cannot fetch %v from %T", method.Name, from))
}

func GetMethodValue(value reflect.Value, index int) (result reflect.Value) {
defer func() {
if err := recover(); err != nil {
structType := value.Type()
pointerType := reflect.PtrTo(structType)
pointerValue := reflect.New(pointerType.Elem())
pointerValue.Elem().Set(value)
result = pointerValue.Method(index)
}
}()
result = value.Method(index)
return
}

func Deref(i any) any {
if i == nil {
return nil
}

v := reflect.ValueOf(i)

for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
if v.IsNil() {
return nil
}
v = v.Elem()
}

if v.IsValid() {
return v.Interface()
}

panic(fmt.Sprintf("cannot dereference %v", i))
}

func Slice(array, from, to any) any {
v := reflect.ValueOf(array)

Expand Down

0 comments on commit 12f0cff

Please sign in to comment.