From: Austin Clements Date: Fri, 4 Sep 2009 19:55:25 +0000 (-0700) Subject: Make world.Define{Const,Var} indicate if the definition was X-Git-Tag: weekly.2009-11-06~630 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=c7d27f88f8935912ed438bccac1191c03878affe;p=gostls13.git Make world.Define{Const,Var} indicate if the definition was successful. R=rsc APPROVED=rsc DELTA=43 (31 added, 0 deleted, 12 changed) OCL=34375 CL=34397 --- diff --git a/usr/austin/eval/scope.go b/usr/austin/eval/scope.go index 3fe94e4be4..7e10293d5d 100644 --- a/usr/austin/eval/scope.go +++ b/usr/austin/eval/scope.go @@ -142,13 +142,13 @@ func (b *block) defineSlot(t Type, temp bool) *Variable { return v; } -func (b *block) DefineConst(name string, pos token.Position, t Type, v Value) *Constant { - if _, ok := b.defs[name]; ok { - return nil; +func (b *block) DefineConst(name string, pos token.Position, t Type, v Value) (*Constant, Def) { + if prev, ok := b.defs[name]; ok { + return nil, prev; } c := &Constant{pos, t, v}; b.defs[name] = c; - return c; + return c, nil; } func (b *block) DefineType(name string, pos token.Position, t Type) Type { diff --git a/usr/austin/eval/stmt.go b/usr/austin/eval/stmt.go index 0d657c1d7f..758157827c 100644 --- a/usr/austin/eval/stmt.go +++ b/usr/austin/eval/stmt.go @@ -365,7 +365,7 @@ func (a *stmtCompiler) compileVarDecl(decl *ast.GenDecl) { a.defineVar(n, t); } } else { - // Decalaration with assignment + // Declaration with assignment lhs := make([]ast.Expr, len(spec.Names)); for i, n := range spec.Names { lhs[i] = n; @@ -388,9 +388,17 @@ func (a *stmtCompiler) compileDecl(decl ast.Decl) { } // Declare and initialize v before compiling func // so that body can refer to itself. - c := a.block.DefineConst(d.Name.Value, a.pos, decl.Type, decl.Type.Zero()); + c, prev := a.block.DefineConst(d.Name.Value, a.pos, decl.Type, decl.Type.Zero()); + if prev != nil { + pos := prev.Pos(); + if pos.IsValid() { + a.diagAt(d.Name, "identifier %s redeclared in this block\n\tprevious declaration at %s", d.Name.Value, &pos); + } else { + a.diagAt(d.Name, "identifier %s redeclared in this block", d.Name.Value); + } + } fn := a.compileFunc(a.block, decl, d.Body); - if fn == nil { + if c == nil || fn == nil { return; } var zeroThread Thread; diff --git a/usr/austin/eval/world.go b/usr/austin/eval/world.go index e307019135..6738f6b50c 100644 --- a/usr/austin/eval/world.go +++ b/usr/austin/eval/world.go @@ -5,6 +5,7 @@ package eval import ( + "fmt"; "go/ast"; "go/parser"; "go/scanner"; @@ -154,12 +155,34 @@ func (w *World) Compile(text string) (Code, os.Error) { return nil, err; } -func (w *World) DefineConst(name string, t Type, val Value) { - w.scope.DefineConst(name, token.Position{}, t, val); +type RedefinitionError struct { + Name string; + Prev Def; } -func (w *World) DefineVar(name string, t Type, val Value) { - v, _ := w.scope.DefineVar(name, token.Position{}, t); +func (e *RedefinitionError) String() string { + res := "identifier " + e.Name + " redeclared"; + pos := e.Prev.Pos(); + if pos.IsValid() { + res += "; previous declaration at " + pos.String(); + } + return res; +} + +func (w *World) DefineConst(name string, t Type, val Value) os.Error { + _, prev := w.scope.DefineConst(name, token.Position{}, t, val); + if prev != nil { + return &RedefinitionError{name, prev}; + } + return nil; +} + +func (w *World) DefineVar(name string, t Type, val Value) os.Error { + v, prev := w.scope.DefineVar(name, token.Position{}, t); + if prev != nil { + return &RedefinitionError{name, prev}; + } v.Init = val; + return nil; }