summaryrefslogtreecommitdiff
path: root/comp
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 /comp
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 'comp')
-rw-r--r--comp/compiler.go55
1 files changed, 38 insertions, 17 deletions
diff --git a/comp/compiler.go b/comp/compiler.go
index 8a136e1..8a7db22 100644
--- a/comp/compiler.go
+++ b/comp/compiler.go
@@ -99,15 +99,15 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
emit(t, vm.Dup, i)
case lang.Add:
- push(&symbol.Symbol{Type: arithmeticOpType(pop(), pop())})
+ push(&symbol.Symbol{Kind: symbol.Value, Type: arithmeticOpType(pop(), pop())})
emit(t, vm.Add)
case lang.Mul:
- push(&symbol.Symbol{Type: arithmeticOpType(pop(), pop())})
+ push(&symbol.Symbol{Kind: symbol.Value, Type: arithmeticOpType(pop(), pop())})
emit(t, vm.Mul)
case lang.Sub:
- push(&symbol.Symbol{Type: arithmeticOpType(pop(), pop())})
+ push(&symbol.Symbol{Kind: symbol.Value, Type: arithmeticOpType(pop(), pop())})
emit(t, vm.Sub)
case lang.Minus:
@@ -120,11 +120,11 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
// Unary '+' is idempotent. Nothing to do.
case lang.Addr:
- push(&symbol.Symbol{Type: vm.PointerTo(pop().Type)})
+ push(&symbol.Symbol{Kind: symbol.Value, Type: vm.PointerTo(pop().Type)})
emit(t, vm.Addr)
case lang.Deref:
- push(&symbol.Symbol{Type: pop().Type.Elem()})
+ push(&symbol.Symbol{Kind: symbol.Value, Type: pop().Type.Elem()})
emit(t, vm.Deref)
case lang.Index:
@@ -136,14 +136,14 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
} else {
emit(t, vm.Index)
}
- push(&symbol.Symbol{Type: s.Type.Elem()})
+ push(&symbol.Symbol{Kind: symbol.Value, Type: s.Type.Elem()})
case lang.Greater:
- push(&symbol.Symbol{Type: booleanOpType(pop(), pop())})
+ push(&symbol.Symbol{Kind: symbol.Value, Type: booleanOpType(pop(), pop())})
emit(t, vm.Greater)
case lang.Less:
- push(&symbol.Symbol{Type: booleanOpType(pop(), pop())})
+ push(&symbol.Symbol{Kind: symbol.Value, Type: booleanOpType(pop(), pop())})
emit(t, vm.Lower)
case lang.Call:
@@ -159,7 +159,7 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
pop()
}
for i := 0; i < typ.Rtype.NumOut(); i++ {
- push(&symbol.Symbol{Type: typ.Out(i)})
+ push(&symbol.Symbol{Kind: symbol.Value, Type: typ.Out(i)})
}
emit(t, vm.Call, narg)
@@ -173,7 +173,7 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
rtyp := s.Value.Value.Type()
// TODO: pop input types (careful with variadic function).
for i := 0; i < rtyp.NumOut(); i++ {
- push(&symbol.Symbol{Type: &vm.Type{Rtype: rtyp.Out(i)}})
+ push(&symbol.Symbol{Kind: symbol.Value, Type: &vm.Type{Rtype: rtyp.Out(i)}})
}
emit(t, vm.CallX, t.Beg)
@@ -182,6 +182,10 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
pop()
ks := pop()
ts := top()
+ if ts.IsPtr() {
+ // Resolve index on the element type
+ ts = &symbol.Symbol{Kind: symbol.Value, Type: &vm.Type{Rtype: ts.Type.Rtype.Elem()}}
+ }
switch ks.Kind {
case symbol.Const:
switch ts.Type.Rtype.Kind() {
@@ -190,9 +194,10 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
emit(t, vm.FieldFset)
}
case reflect.Slice:
- if v := ks.Value.Value; v.CanInt() {
- emit(t, vm.IndexSet)
+ if ts.Type.Elem().IsPtr() {
+ emit(t, vm.Addr)
}
+ emit(t, vm.IndexSet)
case reflect.Map:
emit(t, vm.MapSet)
}
@@ -276,9 +281,12 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
c.Data = append(c.Data, s.Value)
}
if s.Kind == symbol.Type {
- if s.Type.Rtype.Kind() == reflect.Slice {
+ switch s.Type.Rtype.Kind() {
+ case reflect.Slice:
emit(t, vm.Fnew, s.Index, s.SliceLen)
- } else {
+ case reflect.Pointer:
+ emit(t, vm.FnewE, s.Index, 1)
+ default:
emit(t, vm.Fnew, s.Index, 1)
}
} else {
@@ -357,6 +365,7 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
if len(stack) < 1 {
return errorf("missing symbol")
}
+ showStack()
s := pop()
switch s.Kind {
case symbol.Pkg:
@@ -384,9 +393,21 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
case symbol.Unset:
return errorf("invalid symbol: %s", s.Name)
default:
- if f, ok := s.Type.Rtype.FieldByName(t.Str[1:]); ok {
- emit(t, vm.Field, f.Index...)
- push(&symbol.Symbol{Type: s.Type.FieldType(t.Str[1:])})
+ // FIXME: handle pointer indirection here
+ log.Println("## XXX", s.Type, s.Type.IsPtr())
+ typ := s.Type.Rtype
+ isPtr := typ.Kind() == reflect.Pointer
+ if isPtr {
+ typ = typ.Elem()
+ }
+ if f, ok := typ.FieldByName(t.Str[1:]); ok {
+ if isPtr {
+ emit(t, vm.FieldE, f.Index...)
+ push(&symbol.Symbol{Type: s.Type.Elem().FieldType(t.Str[1:])})
+ } else {
+ emit(t, vm.Field, f.Index...)
+ push(&symbol.Symbol{Type: s.Type.FieldType(t.Str[1:])})
+ }
break
}
return fmt.Errorf("field or method not found: %s", t.Str[1:])