diff options
| author | Austin Clements <aclements@csail.mit.edu> | 2009-09-04 12:55:25 -0700 |
|---|---|---|
| committer | Austin Clements <aclements@csail.mit.edu> | 2009-09-04 12:55:25 -0700 |
| commit | ffed1a45acb5c71e2204f1024f55f16eba172dac (patch) | |
| tree | 594929941218e3f71465160d38d572bfc5a91bc9 | |
| parent | cd435919e10f9af67192eae5165380e0788571a9 (diff) | |
| download | golang-ffed1a45acb5c71e2204f1024f55f16eba172dac.tar.gz | |
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
| -rw-r--r-- | usr/austin/eval/scope.go | 8 | ||||
| -rw-r--r-- | usr/austin/eval/stmt.go | 14 | ||||
| -rw-r--r-- | usr/austin/eval/world.go | 31 |
3 files changed, 42 insertions, 11 deletions
diff --git a/usr/austin/eval/scope.go b/usr/austin/eval/scope.go index 3fe94e4be..7e10293d5 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 0d657c1d7..758157827 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 e30701913..6738f6b50 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; } |
