summaryrefslogtreecommitdiff
path: root/vm/vm.go
diff options
context:
space:
mode:
authorMarc Vertes <mvertes@free.fr>2026-01-14 18:44:17 +0100
committerMarc Vertes <mvertes@free.fr>2026-01-14 18:44:17 +0100
commit31e3793202402fda21905027c18ebfa5c8d8c832 (patch)
treedbe52ae31fada099bc65fcd9c7d61f6266c6ba78 /vm/vm.go
parentde3baf0e06862f0420950f025b3328068f3b6df2 (diff)
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.
Diffstat (limited to 'vm/vm.go')
-rw-r--r--vm/vm.go11
1 files changed, 11 insertions, 0 deletions
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() {