summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAustin Clements <aclements@csail.mit.edu>2009-09-04 12:55:25 -0700
committerAustin Clements <aclements@csail.mit.edu>2009-09-04 12:55:25 -0700
commitffed1a45acb5c71e2204f1024f55f16eba172dac (patch)
tree594929941218e3f71465160d38d572bfc5a91bc9
parentcd435919e10f9af67192eae5165380e0788571a9 (diff)
downloadgolang-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.go8
-rw-r--r--usr/austin/eval/stmt.go14
-rw-r--r--usr/austin/eval/world.go31
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;
}