diff options
| author | Marc Vertes <mvertes@free.fr> | 2025-12-02 15:45:14 +0100 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2025-12-02 15:45:14 +0100 |
| commit | 3d64f909cfb55d8886ac4b4839a98f8f6cdc98e7 (patch) | |
| tree | c0e4149ef652f2d422d2f598da1651fde4009496 /comp/compiler.go | |
| parent | f40a1c23467eef36f53635e525f8b25f591e8a45 (diff) | |
feat: support of struct literal composite
Added missing vm instructions to allocate a typed value on the stack
and to set a structure field.
It's possible now to generate struct literal composites for non
keyed struct fields.
Diffstat (limited to 'comp/compiler.go')
| -rw-r--r-- | comp/compiler.go | 56 |
1 files changed, 25 insertions, 31 deletions
diff --git a/comp/compiler.go b/comp/compiler.go index 610d4a1..7b12086 100644 --- a/comp/compiler.go +++ b/comp/compiler.go @@ -56,6 +56,15 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) { } push := func(s *parser.Symbol) { stack = append(stack, s) } pop := func() *parser.Symbol { l := len(stack) - 1; s := stack[l]; stack = stack[:l]; return s } + top := func() *parser.Symbol { return stack[len(stack)-1] } + + showStack := func() { + _, file, line, _ := runtime.Caller(1) + fmt.Fprintf(os.Stderr, "%s%d: showstack: %d\n", path.Base(file), line, len(stack)) + for i, s := range stack { + fmt.Fprintf(os.Stderr, "%s:%d: stack[%d]: %v\n", path.Base(file), line, i, s) + } + } for i, t := range tokens { switch t.Tok { @@ -144,23 +153,17 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) { emit(t, vm.CallX, t.Beg) case lang.Composite: - log.Println("COMPOSITE") - /* - d := pop() - switch d.Type.Rtype.Kind() { - case reflect.Struct: - // nf := d.typ.Rtype.NumField() - // emit(t.Pos, vm.New, d.index, c.typeSym(d.typ).index) - emit(t, vm.Field, 0) - emit(t, vm.Vassign) - emit(t, vm.Fdup, 2) - emit(t, vm.Field, 1) - emit(t, vm.Vassign) - emit(t, vm.Pop, 1) - // emit(t, vm.Fdup, 2) - // Assume an element list with no keys, one per struct field in order + d := top() // let the type symbol on the stack, may be required for assignment + switch d.Type.Rtype.Kind() { + case reflect.Struct: + emit(t, vm.Fnew, d.Index) + nf := d.Type.Rtype.NumField() + for i := 0; i < nf; i++ { + emit(t, vm.FieldSet, i) } - */ + default: + return fmt.Errorf("composite kind not supported yet: %v", d.Type.Rtype.Kind()) + } case lang.Grow: emit(t, vm.Grow, t.Beg) @@ -169,6 +172,7 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) { // TODO: support assignment to local, composite objects. st := tokens[i-1] l := len(c.Data) + showStack() d := pop() typ := d.Type if typ == nil { @@ -242,7 +246,9 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) { s.Index = len(c.Data) c.Data = append(c.Data, s.Value) } - emit(t, vm.Dup, s.Index) + if s.Kind != parser.SymType { + emit(t, vm.Dup, s.Index) + } } case lang.Label: @@ -389,7 +395,7 @@ func (c *Compiler) PrintCode() { extra = "// " + d } } - fmt.Fprintf(os.Stderr, "%4d %-14v %v\n", i, l, extra) + fmt.Fprintf(os.Stderr, "%4d %-18v %v\n", i, l, extra) } for _, label := range labels[len(c.Code)] { @@ -403,19 +409,7 @@ type entry struct { *parser.Symbol } -func (e entry) String() string { - if e.Symbol != nil { - return fmt.Sprintf("name: %s,local: %t, i: %d, k: %d, t: %s, v: %v", - e.name, - e.Local, - e.Index, - e.Kind, - e.Type, - e.Value, - ) - } - return e.name -} +func (e entry) String() string { return fmt.Sprintf("name: %s, sym: %v", e.name, e.Symbol) } // PrintData pretty prints the generated global data symbols in compiler. func (c *Compiler) PrintData() { |
