]> Cypherpunks repositories - gostls13.git/commitdiff
convenience wrapper
authorRuss Cox <rsc@golang.org>
Thu, 3 Sep 2009 00:15:43 +0000 (17:15 -0700)
committerRuss Cox <rsc@golang.org>
Thu, 3 Sep 2009 00:15:43 +0000 (17:15 -0700)
R=austin
DELTA=142  (128 added, 4 deleted, 10 changed)
OCL=34275
CL=34284

usr/austin/eval/Makefile
usr/austin/eval/compiler.go
usr/austin/eval/expr.go
usr/austin/eval/main.go [new file with mode: 0644]
usr/austin/eval/scope.go
usr/austin/eval/stmt.go
usr/austin/eval/typec.go
usr/austin/eval/world.go [new file with mode: 0644]

index 154838ea379fef4be9f71d06f99637ac472c81cf..37f7c02a710cd6bb8a9a9600bbe8953985b67269 100644 (file)
@@ -18,5 +18,6 @@ GOFILES=\
        typec.go\
        util.go\
        value.go\
+       world.go\
 
 include $(GOROOT)/src/Make.pkg
index f4ababf74f57983f76fbde3845d50b0e54f83274..b13cd298c1cdbb7ea2d11e0398b8abf210995f94 100644 (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)
        };
index cacfc61e12601cf2650217157b198a2d7ce14161..a29373d6a6832bf150e5e70cb3c96c942ff55e16 100644 (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 };
diff --git a/usr/austin/eval/main.go b/usr/austin/eval/main.go
new file mode 100644 (file)
index 0000000..a4401e1
--- /dev/null
@@ -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());
+               }
+       }
+}
+
index bc85476dc6066695d2188a2046d242d9a1cbf7a6..1c0acb640071a67a5538bdd010146e3b28d4cd21 100644 (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;
index e0d6ebeb30e5240e8ba86032ef8f38622fad8666..a3573c260d53cb6280184f26b5b30d910301c2be 100644 (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;
 }
 
index 8aefeda34c47e009ed74f8e20a3be959377ff577..a4d055fb5926167402de1d40e32b1d7454c16db2 100644 (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;
diff --git a/usr/austin/eval/world.go b/usr/austin/eval/world.go
new file mode 100644 (file)
index 0000000..7f7e5fc
--- /dev/null
@@ -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;
+}
+