summaryrefslogtreecommitdiff
path: root/vm
diff options
context:
space:
mode:
authorMarc Vertes <mvertes@free.fr>2025-03-03 10:49:27 +0100
committerMarc Vertes <mvertes@free.fr>2025-03-03 10:49:27 +0100
commitab69cd9ba61092650abdff6484b12021182385ce (patch)
tree4805a0365fc481df57c8f0b5d45f7f993b9a0ef9 /vm
parentdabd9e5eb81bbc9aeaeb32fb3e3ce83eef258a77 (diff)
fix: improve structparscan-struct
Use 'unsafe' to modify private struct fields, allowing to keep unmodified field names: before they were prefixed with a capital. Parse package statement. Provide a also a default package name for REPL and tests. The support of packages is still incomplete.
Diffstat (limited to 'vm')
-rw-r--r--vm/type.go11
-rw-r--r--vm/vm.go8
2 files changed, 15 insertions, 4 deletions
diff --git a/vm/type.go b/vm/type.go
index 49215db..7c33cd2 100644
--- a/vm/type.go
+++ b/vm/type.go
@@ -6,12 +6,16 @@ import "reflect"
// Type is the representation of a runtime type.
type Type struct {
- Name string
- Rtype reflect.Type
+ PkgPath string
+ Name string
+ Rtype reflect.Type
}
func (t *Type) String() string {
if t.Name != "" {
+ if t.PkgPath != "" {
+ return t.PkgPath + "." + t.Name
+ }
return t.Name
}
return t.Rtype.String()
@@ -84,7 +88,8 @@ func FuncOf(arg, ret []*Type, variadic bool) *Type {
func StructOf(fields []*Type) *Type {
rf := make([]reflect.StructField, len(fields))
for i, f := range fields {
- rf[i].Name = "X" + f.Name
+ rf[i].Name = f.Name
+ rf[i].PkgPath = f.PkgPath
rf[i].Type = f.Rtype
}
return &Type{Rtype: reflect.StructOf(rf)}
diff --git a/vm/vm.go b/vm/vm.go
index 408be6e..3cb9358 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -6,6 +6,7 @@ import (
"log" // for tracing only
"reflect" // for optional CallX only
"strconv" // for tracing only
+ "unsafe" // to allow setting unexported struct fields
)
const debug = true
@@ -184,7 +185,12 @@ func (m *Machine) Run() (err error) {
case Fdup:
mem = append(mem, mem[int(op[2])+fp-1])
case Field:
- mem[sp-1].Data = mem[sp-1].Data.FieldByIndex(slint(op[2:]))
+ fv := mem[sp-1].Data.FieldByIndex(slint(op[2:]))
+ if !fv.CanSet() {
+ // Normally private fields can not bet set via reflect. Override this limitation.
+ fv = reflect.NewAt(fv.Type(), unsafe.Pointer(fv.UnsafeAddr())).Elem()
+ }
+ mem[sp-1].Data = fv
case Jump:
ip += int(op[2])
continue