Commit c7d27f88 authored by Austin Clements's avatar Austin Clements

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
parent fdf5efe4
...@@ -142,13 +142,13 @@ func (b *block) defineSlot(t Type, temp bool) *Variable { ...@@ -142,13 +142,13 @@ func (b *block) defineSlot(t Type, temp bool) *Variable {
return v; return v;
} }
func (b *block) DefineConst(name string, pos token.Position, t Type, v Value) *Constant { func (b *block) DefineConst(name string, pos token.Position, t Type, v Value) (*Constant, Def) {
if _, ok := b.defs[name]; ok { if prev, ok := b.defs[name]; ok {
return nil; return nil, prev;
} }
c := &Constant{pos, t, v}; c := &Constant{pos, t, v};
b.defs[name] = c; b.defs[name] = c;
return c; return c, nil;
} }
func (b *block) DefineType(name string, pos token.Position, t Type) Type { func (b *block) DefineType(name string, pos token.Position, t Type) Type {
......
...@@ -365,7 +365,7 @@ func (a *stmtCompiler) compileVarDecl(decl *ast.GenDecl) { ...@@ -365,7 +365,7 @@ func (a *stmtCompiler) compileVarDecl(decl *ast.GenDecl) {
a.defineVar(n, t); a.defineVar(n, t);
} }
} else { } else {
// Decalaration with assignment // Declaration with assignment
lhs := make([]ast.Expr, len(spec.Names)); lhs := make([]ast.Expr, len(spec.Names));
for i, n := range spec.Names { for i, n := range spec.Names {
lhs[i] = n; lhs[i] = n;
...@@ -388,9 +388,17 @@ func (a *stmtCompiler) compileDecl(decl ast.Decl) { ...@@ -388,9 +388,17 @@ func (a *stmtCompiler) compileDecl(decl ast.Decl) {
} }
// Declare and initialize v before compiling func // Declare and initialize v before compiling func
// so that body can refer to itself. // 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); fn := a.compileFunc(a.block, decl, d.Body);
if fn == nil { if c == nil || fn == nil {
return; return;
} }
var zeroThread Thread; var zeroThread Thread;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package eval package eval
import ( import (
"fmt";
"go/ast"; "go/ast";
"go/parser"; "go/parser";
"go/scanner"; "go/scanner";
...@@ -154,12 +155,34 @@ func (w *World) Compile(text string) (Code, os.Error) { ...@@ -154,12 +155,34 @@ func (w *World) Compile(text string) (Code, os.Error) {
return nil, err; return nil, err;
} }
func (w *World) DefineConst(name string, t Type, val Value) { type RedefinitionError struct {
w.scope.DefineConst(name, token.Position{}, t, val); Name string;
Prev Def;
} }
func (w *World) DefineVar(name string, t Type, val Value) { func (e *RedefinitionError) String() string {
v, _ := w.scope.DefineVar(name, token.Position{}, t); 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; v.Init = val;
return nil;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment