1
0
mirror of https://github.com/golang/go synced 2024-11-22 00:04:41 -07:00

convenience wrapper

R=austin
DELTA=142  (128 added, 4 deleted, 10 changed)
OCL=34275
CL=34284
This commit is contained in:
Russ Cox 2009-09-02 17:15:43 -07:00
parent 9e85c790e5
commit c9edbbd4d0
8 changed files with 146 additions and 14 deletions

View File

@ -18,5 +18,6 @@ GOFILES=\
typec.go\
util.go\
value.go\
world.go\
include $(GOROOT)/src/Make.pkg

View File

@ -41,6 +41,7 @@ func (a *compiler) numError() int {
func newUniverse() *Scope {
sc := &Scope{nil, 0};
sc.block = &block{
offset: -1,
scope: sc,
defs: make(map[string] Def)
};

View File

@ -667,7 +667,7 @@ func (a *exprInfo) exprFromType(t Type) *expr {
}
func (a *exprInfo) compileIdent(b *block, constant bool, callCtx bool, name string) *expr {
level, def := b.Lookup(name);
bl, level, def := b.Lookup(name);
if def == nil {
a.diag("%s: undefined", name);
return nil;
@ -693,6 +693,9 @@ func (a *exprInfo) compileIdent(b *block, constant bool, callCtx bool, name stri
a.diag("variable %s used in constant expression", name);
return nil;
}
if bl.offset < 0 {
return a.compileGlobalVariable(def);
}
return a.compileVariable(level, def);
case Type:
if callCtx {
@ -716,6 +719,21 @@ func (a *exprInfo) compileVariable(level int, v *Variable) *expr {
return expr;
}
func (a *exprInfo) compileGlobalVariable(v *Variable) *expr {
if v.Type == nil {
// Placeholder definition from an earlier error
a.silentErrors++;
return nil;
}
if v.Init == nil {
v.Init = v.Type.Zero();
}
expr := a.newExpr(v.Type, "variable");
val := v.Init;
expr.genValue(func(t *Thread) Value { return val });
return expr;
}
func (a *exprInfo) compileIdealInt(i *bignum.Integer, desc string) *expr {
expr := a.newExpr(IdealIntType, desc);
expr.eval = func() *bignum.Integer { return i };

37
usr/austin/eval/main.go Normal file
View File

@ -0,0 +1,37 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"./_obj/eval";
"bufio";
"os";
)
func main() {
w := eval.NewWorld();
r := bufio.NewReader(os.Stdin);
for {
print("; ");
line, err := r.ReadString('\n');
if err != nil {
break;
}
code, err := w.Compile(line);
if err != nil {
println(err.String());
continue;
}
v, err := code.Run();
if err != nil {
println(err.String());
continue;
}
if v != nil {
println(v.String());
}
}
}

View File

@ -122,12 +122,15 @@ func (b *block) DefineSlot(t Type) *Variable {
if b.inner != nil && b.inner.scope == b.scope {
log.Crash("Failed to exit child block before defining variable");
}
index := b.offset+b.numVars;
v := &Variable{token.Position{}, index, t, nil};
b.numVars++;
if index+1 > b.scope.maxVars {
b.scope.maxVars = index+1;
index := -1;
if b.offset >= 0 {
index = b.offset+b.numVars;
b.numVars++;
if index+1 > b.scope.maxVars {
b.scope.maxVars = index+1;
}
}
v := &Variable{token.Position{}, index, t, nil};
return v;
}
@ -152,25 +155,29 @@ func (b *block) DefineType(name string, pos token.Position, t Type) Type {
return nt;
}
func (b *block) Lookup(name string) (level int, def Def) {
func (b *block) Lookup(name string) (bl *block, level int, def Def) {
for b != nil {
if d, ok := b.defs[name]; ok {
return level, d;
return b, level, d;
}
if b.outer != nil && b.scope != b.outer.scope {
level++;
}
b = b.outer;
}
return 0, nil;
return nil, 0, nil;
}
func (s *Scope) NewFrame(outer *Frame) *Frame {
fr := outer.child(s.maxVars);
// TODO(rsc): Take this loop out once eval_test.go
// no longer fiddles with init.
for _, v := range s.defs {
switch v := v.(type) {
case *Variable:
fr.Vars[v.Index] = v.Init;
if v.Index >= 0 {
fr.Vars[v.Index] = v.Init;
}
}
}
return fr;

View File

@ -230,9 +230,11 @@ func (a *stmtCompiler) defineVar(ident *ast.Ident, t Type) *Variable {
// Initialize the variable
index := v.Index;
a.push(func(v *Thread) {
v.f.Vars[index] = t.Zero();
});
if v.Index >= 0 {
a.push(func(v *Thread) {
v.f.Vars[index] = t.Zero();
});
}
return v;
}

View File

@ -26,7 +26,7 @@ type typeCompiler struct {
}
func (a *typeCompiler) compileIdent(x *ast.Ident, allowRec bool) Type {
_, def := a.block.Lookup(x.Value);
_bl, _index, def := a.block.Lookup(x.Value);
if def == nil {
a.diagAt(x, "%s: undefined", x.Value);
return nil;

66
usr/austin/eval/world.go Normal file
View File

@ -0,0 +1,66 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package eval
import (
"os";
"go/ast";
"go/parser";
)
// TODO: Make CompileExpr and CompileStmts
// methods on World.
type World struct {
scope *Scope;
frame *Frame;
}
func NewWorld() (*World) {
w := new(World);
w.scope = universe.ChildScope();
w.scope.offset = -1; // this block's vars allocate directly
w.scope.numVars = 1; // inner blocks have frames: offset+numVars >= 0
return w;
}
type Code struct {
w *World;
stmt *Stmt;
expr *Expr;
}
func (w *World) Compile(text string) (*Code, os.Error) {
asts, err := parser.ParseStmtList("input", text);
if err != nil {
return nil, err;
}
if len(asts) == 1 {
if s, ok := asts[0].(*ast.ExprStmt); ok {
expr, err := CompileExpr(w.scope, s.X);
if err != nil {
return nil, err;
}
return &Code{w: w, expr: expr}, nil;
}
}
stmt, err := CompileStmts(w.scope, asts);
if err != nil {
return nil, err;
}
return &Code{w: w, stmt: stmt}, nil;
}
func (c *Code) Run() (Value, os.Error) {
w := c.w;
w.frame = w.scope.NewFrame(nil);
if c.stmt != nil {
return nil, c.stmt.Exec(w.frame);
}
val, err := c.expr.Eval(w.frame);
return val, err;
}