From 31e3793202402fda21905027c18ebfa5c8d8c832 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Wed, 14 Jan 2026 18:44:17 +0100 Subject: fix: improve handling of indirections Added 2 VM instructions, FnewE variant of Fnew with a dereference, and FieldE, variant of Field with dereference. It's now possible to pointers in structs and literal composites. --- vm/vm.go | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'vm/vm.go') diff --git a/vm/vm.go b/vm/vm.go index 2baf384..3f04bf6 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -32,10 +32,12 @@ const ( Dup // addr -- value ; value = mem[addr] Fdup // addr -- value ; value = mem[addr] Fnew // -- x; x = new mem[$1] + FnewE // -- x; x = new mem[$1].Elem() Equal // n1 n2 -- cond ; cond = n1 == n2 EqualSet // n1 n2 -- n1 cond ; cond = n1 == n2 Exit // -- ; Field // s -- f ; f = s.FieldIndex($1, ...) + FieldE // s -- f ; f = s.FieldIndex($1, ...) FieldSet // s d -- s ; s.FieldIndex($1, ...) = d FieldFset // s i v -- s; s.FieldIndex(i) = v Greater // n1 n2 -- cond; cond = n1 > n2 @@ -173,6 +175,8 @@ func (m *Machine) Run() (err error) { mem = append(mem, mem[c.Arg[0]+fp-1]) case Fnew: mem = append(mem, NewValue(mem[c.Arg[0]].Type, c.Arg[1:]...)) + case FnewE: + mem = append(mem, NewValue(mem[c.Arg[0]].Type.Elem(), c.Arg[1:]...)) case Field: fv := mem[sp-1].FieldByIndex(c.Arg) if !fv.CanSet() { @@ -180,6 +184,13 @@ func (m *Machine) Run() (err error) { fv = reflect.NewAt(fv.Type(), unsafe.Pointer(fv.UnsafeAddr())).Elem() } mem[sp-1].Value = fv + case FieldE: + fv := mem[sp-1].Value.Elem().FieldByIndex(c.Arg) + 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].Value = fv case FieldSet: fv := mem[sp-2].FieldByIndex(c.Arg) if !fv.CanSet() { -- cgit v1.2.3