summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--comp/compiler.go1
-rw-r--r--interp/interpreter_test.go12
-rw-r--r--parser/expr.go15
-rw-r--r--parser/parse.go43
-rw-r--r--parser/tokens.go1
-rw-r--r--vm/vm.go3
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) }
diff --git a/vm/vm.go b/vm/vm.go
index fac1a53..f5bb78e 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -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: