diff options
| -rw-r--r-- | comp/compiler.go | 1 | ||||
| -rw-r--r-- | interp/interpreter_test.go | 12 | ||||
| -rw-r--r-- | parser/expr.go | 15 | ||||
| -rw-r--r-- | parser/parse.go | 43 | ||||
| -rw-r--r-- | parser/tokens.go | 1 | ||||
| -rw-r--r-- | vm/vm.go | 3 |
6 files changed, 49 insertions, 26 deletions
diff --git a/comp/compiler.go b/comp/compiler.go index 4817914..37ed0bd 100644 --- a/comp/compiler.go +++ b/comp/compiler.go @@ -262,7 +262,6 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) { // It could be either an undefined symbol or a key ident in a literal composite expr. s = &symbol.Symbol{Name: t.Str} } - log.Println("Ident symbol", t.Str, s.Local, s.Index, s.Type) push(s) if s.Kind == symbol.Pkg || s.Kind == symbol.Unset { break diff --git a/interp/interpreter_test.go b/interp/interpreter_test.go index 30f3fac..e6274a4 100644 --- a/interp/interpreter_test.go +++ b/interp/interpreter_test.go @@ -72,10 +72,13 @@ func TestExpr(t *testing.T) { func TestAssign(t *testing.T) { run(t, []etest{ - {src: "var a int = 1; a", res: "1"}, // #00 - {src: "var a, b int = 1, 2; b", res: "2"}, // #01 - {src: "var a, b int; a, b = 1, 2; b", res: "2"}, // #02 - {src: "a, b := 1, 2; b", res: "2"}, // #03 + {src: "var a int = 1; a", res: "1"}, // #00 + {src: "var a, b int = 1, 2; b", res: "2"}, // #01 + {src: "var a, b int; a, b = 1, 2; b", res: "2"}, // #02 + {src: "a, b := 1, 2; b", res: "2"}, // #03 + {src: "func f() int {return 2}; a := f(); a", res: "2"}, // #04 + // {src: "func f() (int, int) {return 2, 3}; a, b := f(), b", res: "3"}, // #05 + // {src: "func f() (int, int) {return 2, 3}; var a, b = f(), b", res: "3"}, // #06 }) } @@ -114,6 +117,7 @@ func TestFunc(t *testing.T) { {src: "func f(a, b, c int) int {return a+b-c} ; f(7, 1, 3)", res: "5"}, // #07 {src: "var a int; func f() {a = a+2}; f(); a", res: "2"}, // #08 {src: "var f = func(a int) int {return a+3}; f(2)", res: "5"}, // #09 + {src: "var a int; func f(a int) {a = a+2}; f(); a", res: "0"}, // #10 }) } diff --git a/parser/expr.go b/parser/expr.go index 1f15185..d49cfd5 100644 --- a/parser/expr.go +++ b/parser/expr.go @@ -62,14 +62,13 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { out = append(out, t) case lang.Range: - ops = ops[:len(ops)-1] // Suppress previous assign or define. addop(t) case lang.Colon: t.Str = typeStr addop(t) - case lang.Add, lang.And, lang.Assign, lang.Define, lang.Equal, lang.Greater, lang.Less, lang.Mul, lang.Not, lang.Sub, lang.Shl, lang.Shr: + case lang.Add, lang.And, lang.Equal, lang.Greater, lang.Less, lang.Mul, lang.Not, lang.Sub, lang.Shl, lang.Shr: if i == 0 || in[i-1].Tok.IsOperator() { // An operator preceded by an operator or no token is unary. t.Tok = lang.UnaryOp[t.Tok] @@ -100,10 +99,6 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { ctype = s.Type.String() } out = append(out, t) - if i+1 < len(in) && in[i+1].Tok == lang.Define { - // Ident is to be assigned next. Define it as a var. - p.Symbols.Add(symbol.UnsetAddr, t.Str, vm.Value{}, symbol.Var, nil, false) - } case lang.ParenBlock: toks, err := p.parseBlock(t, typeStr) @@ -145,7 +140,6 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { return out, err } ctype = typ.String() - // p.Symbols.Add(symbol.UnsetAddr, ctype, vm.NewValue(typ), symbol.Type, typ, p.funcScope != "") p.Symbols.Add(symbol.UnsetAddr, ctype, vm.NewValue(typ), symbol.Type, typ, false) out = append(out, newIdent(ctype, t.Pos)) i += n - 1 @@ -159,12 +153,7 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) { break } out = append(out, toks...) - if i < len(in)-2 && in[i+1].Tok == lang.Assign { - // A bracket block followed by assign implies an IndexAssign token, - // as assignement to a map element cannot be implemented through a normal Assign. - ops = append(ops, newIndexAssign(t.Pos)) - i++ - } else if toks[len(toks)-1].Tok != lang.Slice { + if toks[len(toks)-1].Tok != lang.Slice { ops = append(ops, newIndex(t.Pos)) } diff --git a/parser/parse.go b/parser/parse.go index 18613f4..9c1fd13 100644 --- a/parser/parse.go +++ b/parser/parse.go @@ -163,11 +163,37 @@ func (p *Parser) parseStmt(in Tokens) (out Tokens, err error) { func (p *Parser) parseAssign(in Tokens, aindex int) (out Tokens, err error) { rhs := in[aindex+1:].Split(lang.Comma) - if len(rhs) == 1 { - return p.parseExpr(in, "") - } lhs := in[:aindex].Split(lang.Comma) define := in[aindex].Tok == lang.Define + if len(rhs) == 1 { + for _, e := range lhs { + toks, err := p.parseExpr(e, "") + if err != nil { + return out, err + } + if define && len(e) == 1 && e[0].Tok == lang.Ident { + p.Symbols.Add(symbol.UnsetAddr, e[0].Str, vm.Value{}, symbol.Var, nil, false) + } + out = append(out, toks...) + } + toks, err := p.parseExpr(rhs[0], "") + if err != nil { + return out, err + } + if out[len(out)-1].Tok == lang.Index { + // Map elements cannot be assigned directly, but only through IndexAssign. + out = out[:len(out)-1] + out = append(out, toks...) + out = append(out, newToken(lang.IndexAssign, "", in[aindex].Pos)) + } else { + out = append(out, toks...) + if out[len(out)-1].Tok != lang.Range { + out = append(out, newToken(in[aindex].Tok, "", in[aindex].Pos)) + } + } + return out, err + } + // Multiple values in right hand side. for i, e := range rhs { toks, err := p.parseExpr(lhs[i], "") if err != nil { @@ -185,8 +211,15 @@ func (p *Parser) parseAssign(in Tokens, aindex int) (out Tokens, err error) { if err != nil { return out, err } - out = append(out, toks...) - out = append(out, newToken(in[aindex].Tok, "", in[aindex].Pos)) + if out[len(out)-1].Tok == lang.Index { + // Map elements cannot be assigned directly, but only through IndexAssign. + out = out[:len(out)-1] + out = append(out, toks...) + out = append(out, newToken(lang.IndexAssign, "", in[aindex].Pos)) + } else { + out = append(out, toks...) + out = append(out, newToken(in[aindex].Tok, "", in[aindex].Pos)) + } } return out, err } diff --git a/parser/tokens.go b/parser/tokens.go index 7a241f3..9c4354d 100644 --- a/parser/tokens.go +++ b/parser/tokens.go @@ -88,7 +88,6 @@ func newReturn(pos int) Token { return newToken(lang.Ret func newJumpSetFalse(label string, pos int) Token { return newToken(lang.JumpSetFalse, label, pos) } func newJumpSetTrue(label string, pos int) Token { return newToken(lang.JumpSetTrue, label, pos) } func newComposite(pos int) Token { return newToken(lang.Composite, "", pos) } -func newIndexAssign(pos int) Token { return newToken(lang.IndexAssign, "", pos) } func newIndex(pos int) Token { return newToken(lang.Index, "", pos) } func newInt(i, pos int) Token { return newToken(lang.Int, strconv.Itoa(i), pos) } func newColon(pos int) Token { return newToken(lang.Colon, "", pos) } @@ -150,8 +150,7 @@ func (m *Machine) Run() (err error) { case Deref: mem[sp-1].Value = mem[sp-1].Value.Elem() case Dup: - k := c.Arg[0] - mem = append(mem, mem[k]) + mem = append(mem, mem[c.Arg[0]]) case New: mem[c.Arg[0]+fp-1] = NewValue(mem[c.Arg[1]].Type) case Equal: |
