diff options
| author | Marc Vertes <mvertes@free.fr> | 2026-01-08 23:46:02 +0100 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2026-01-08 23:46:02 +0100 |
| commit | 6ae0a2530c9a57fc093d2159591d9cae8140d641 (patch) | |
| tree | 8c445c99bf3140930ead8ad8c70ebbed9838074e | |
| parent | 6875facb39de63eb6353be2f700b9eacb631e9fa (diff) | |
fix: improve composite literal for slices
| -rw-r--r-- | comp/compiler.go | 19 | ||||
| -rw-r--r-- | interp/interpreter_test.go | 4 | ||||
| -rw-r--r-- | parser/expr.go | 21 | ||||
| -rw-r--r-- | symbol/symbol.go | 19 | ||||
| -rw-r--r-- | vm/op_string.go | 39 | ||||
| -rw-r--r-- | vm/vm.go | 10 |
6 files changed, 73 insertions, 39 deletions
diff --git a/comp/compiler.go b/comp/compiler.go index 9d787b6..5d55be4 100644 --- a/comp/compiler.go +++ b/comp/compiler.go @@ -176,10 +176,18 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) { showStack() pop() ks := pop() + ts := top() switch ks.Kind { case symbol.Const: - if v := ks.Value.Value; v.CanInt() { - emit(t, vm.FieldFset) + switch ts.Type.Rtype.Kind() { + case reflect.Struct: + if v := ks.Value.Value; v.CanInt() { + emit(t, vm.FieldFset) + } + case reflect.Slice: + if v := ks.Value.Value; v.CanInt() { + emit(t, vm.IndexSet) + } } case symbol.Unset: j := top().Type.FieldIndex(ks.Name) @@ -249,7 +257,11 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) { c.Data = append(c.Data, s.Value) } if s.Kind == symbol.Type { - emit(t, vm.Fnew, s.Index) + if s.Type.Rtype.Kind() == reflect.Slice { + emit(t, vm.Fnew, s.Index, s.SliceLen) + } else { + emit(t, vm.Fnew, s.Index) + } } else { emit(t, vm.Dup, s.Index) } @@ -265,7 +277,6 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) { s.Index = len(c.Data) c.Data = append(c.Data, s.Value) flen = append(flen, len(stack)) - log.Println("### func label:", lc, s.Index, s.Value.Value, c.Data[0].Value) } else { c.Data[s.Index] = s.Value } diff --git a/interp/interpreter_test.go b/interp/interpreter_test.go index 5d0dd55..c7c3cbc 100644 --- a/interp/interpreter_test.go +++ b/interp/interpreter_test.go @@ -269,7 +269,7 @@ func TestComposite(t *testing.T) { {src: `type T struct{N int; S string}; var t T; t = T{2, "foo"}; t`, res: `{2 foo}`}, // #03 {src: `type T struct{N int; S string}; t := T{2, "foo"}; t`, res: `{2 foo}`}, // #04 {src: `type T struct{N int; S string}; t := T{S: "foo"}; t`, res: `{0 foo}`}, // #05 - // {src: `a := []int{}`, res: `[]`}, // #06 - // {src: `a := []int{1, 2, 3}`, res: `[1 2 3]`}, // #07 + {src: `a := []int{}`, res: `[]`}, // #06 + {src: `a := []int{1, 2, 3}; a`, res: `[1 2 3]`}, // #07 }) } diff --git a/parser/expr.go b/parser/expr.go index 3895ea8..e00113f 100644 --- a/parser/expr.go +++ b/parser/expr.go @@ -128,6 +128,18 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { ops = append(ops, scanner.Token{Tok: lang.Composite, Pos: t.Pos, Str: typeStr}) case lang.BracketBlock: + if i == 0 || in[i-1].Tok.IsOperator() { + // array or slice type expression + typ, err := p.parseTypeExpr(in[i:]) + if err != nil { + return out, err + } + typeStr = typ.String() + p.Symbols.Add(symbol.UnsetAddr, typ.String(), vm.NewValue(typ), symbol.Type, typ, p.funcScope != "") + out = append(out, scanner.Token{Tok: lang.Ident, Pos: t.Pos, Str: typeStr}) + i++ + break + } toks, err := p.parseExprStr(t.Block(), typeStr) if err != nil { return out, err @@ -135,9 +147,6 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { out = append(out, toks...) ops = append(ops, scanner.Token{Tok: lang.Index, Pos: t.Pos}) - case lang.Comment: - // return out, nil - case lang.Struct: typ, err := p.parseTypeExpr(in[i : i+2]) if err != nil { @@ -146,9 +155,10 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { typeStr = typ.String() p.Symbols.Add(symbol.UnsetAddr, typ.String(), vm.NewValue(typ), symbol.Type, typ, p.funcScope != "") out = append(out, scanner.Token{Tok: lang.Ident, Pos: t.Pos, Str: typeStr}) - log.Println("### typ:", typ) i++ + case lang.Comment: + default: log.Println("unxexpected token:", t) } @@ -168,6 +178,7 @@ func (p *Parser) parseComposite(s, typ string) (Tokens, error) { noColon := len(tokens) > 0 && tokens.Index(lang.Colon) == -1 var result Tokens + var sliceLen int for i, sub := range tokens.Split(lang.Comma) { toks, err := p.parseExpr(sub, typ) if err != nil { @@ -178,10 +189,12 @@ func (p *Parser) parseComposite(s, typ string) (Tokens, error) { result = append(result, scanner.Token{Tok: lang.Int, Str: strconv.Itoa(i)}) result = append(result, toks...) result = append(result, scanner.Token{Tok: lang.Colon, Str: ":"}) + sliceLen++ } else { result = append(result, toks...) } } + p.Symbols[typ].SliceLen = sliceLen return result, nil } diff --git a/symbol/symbol.go b/symbol/symbol.go index 96c860f..2ed8907 100644 --- a/symbol/symbol.go +++ b/symbol/symbol.go @@ -31,15 +31,16 @@ const UnsetAddr = -65535 // Symbol structure used in parser and compiler. type Symbol struct { - Kind Kind - Name string // - Index int // address of symbol in frame - PkgPath string // - Type *vm.Type // - Value vm.Value // - Cval constant.Value // - Local bool // if true address is relative to local frame, otherwise global - Used bool // + Kind Kind + Name string // + Index int // address of symbol in frame + PkgPath string // + Type *vm.Type // + Value vm.Value // + SliceLen int // initial slice length (slice types only) + Cval constant.Value // + Local bool // if true address is relative to local frame, otherwise global + Used bool // } // func (s *Symbol) String() string { diff --git a/vm/op_string.go b/vm/op_string.go index 15cc938..a39dcfa 100644 --- a/vm/op_string.go +++ b/vm/op_string.go @@ -30,28 +30,29 @@ func _() { _ = x[Greater-19] _ = x[Grow-20] _ = x[Index-21] - _ = x[Jump-22] - _ = x[JumpTrue-23] - _ = x[JumpFalse-24] - _ = x[JumpSetTrue-25] - _ = x[JumpSetFalse-26] - _ = x[Lower-27] - _ = x[Loweri-28] - _ = x[Mul-29] - _ = x[New-30] - _ = x[Negate-31] - _ = x[Not-32] - _ = x[Pop-33] - _ = x[Push-34] - _ = x[Return-35] - _ = x[Sub-36] - _ = x[Subi-37] - _ = x[Swap-38] + _ = x[IndexSet-22] + _ = x[Jump-23] + _ = x[JumpTrue-24] + _ = x[JumpFalse-25] + _ = x[JumpSetTrue-26] + _ = x[JumpSetFalse-27] + _ = x[Lower-28] + _ = x[Loweri-29] + _ = x[Mul-30] + _ = x[New-31] + _ = x[Negate-32] + _ = x[Not-33] + _ = x[Pop-34] + _ = x[Push-35] + _ = x[Return-36] + _ = x[Sub-37] + _ = x[Subi-38] + _ = x[Swap-39] } -const _Op_name = "NopAddAddrAssignFassignVassignCallCalliCallXDerefDupFdupFnewEqualEqualSetExitFieldFieldSetFieldFsetGreaterGrowIndexJumpJumpTrueJumpFalseJumpSetTrueJumpSetFalseLowerLoweriMulNewNegateNotPopPushReturnSubSubiSwap" +const _Op_name = "NopAddAddrAssignFassignVassignCallCalliCallXDerefDupFdupFnewEqualEqualSetExitFieldFieldSetFieldFsetGreaterGrowIndexIndexSetJumpJumpTrueJumpFalseJumpSetTrueJumpSetFalseLowerLoweriMulNewNegateNotPopPushReturnSubSubiSwap" -var _Op_index = [...]uint8{0, 3, 6, 10, 16, 23, 30, 34, 39, 44, 49, 52, 56, 60, 65, 73, 77, 82, 90, 99, 106, 110, 115, 119, 127, 136, 147, 159, 164, 170, 173, 176, 182, 185, 188, 192, 198, 201, 205, 209} +var _Op_index = [...]uint8{0, 3, 6, 10, 16, 23, 30, 34, 39, 44, 49, 52, 56, 60, 65, 73, 77, 82, 90, 99, 106, 110, 115, 123, 127, 135, 144, 155, 167, 172, 178, 181, 184, 190, 193, 196, 200, 206, 209, 213, 217} func (i Op) String() string { idx := int(i) - 0 @@ -41,6 +41,7 @@ const ( Greater // n1 n2 -- cond; cond = n1 > n2 Grow // -- ; sp += $1 Index // a i -- a[i] ; + IndexSet // a i v -- a; a[i] = v Jump // -- ; ip += $1 JumpTrue // cond -- ; if cond { ip += $1 } JumpFalse // cond -- ; if cond { ip += $1 } @@ -170,6 +171,10 @@ 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)) + if len(c.Arg) > 1 { + mem[len(mem)-1].Grow(c.Arg[1]) + mem[len(mem)-1].SetLen(c.Arg[1]) + } case Field: fv := mem[sp-1].FieldByIndex(c.Arg) if !fv.CanSet() { @@ -262,8 +267,11 @@ func (m *Machine) Run() (err error) { case Index: mem[sp-2].Value = mem[sp-2].Index(int(mem[sp-1].Int())) mem = mem[:sp-1] + case IndexSet: + log.Println("## IndexSet:", sp-3, mem[sp-3].Type) + mem[sp-3].Value.Index(int(mem[sp-2].Int())).Set(mem[sp-1].Value) + mem = mem[:sp-2] case Vassign: - // mem[sp-1].Set(mem[sp-2].Value) mem[sp-2].Set(mem[sp-1].Value) mem = mem[:sp-2] } |
