]> Cypherpunks repositories - gostls13.git/commitdiff
Make it only necessary to exit blocks, not scopes. Allow
authorAustin Clements <aclements@csail.mit.edu>
Mon, 24 Aug 2009 20:48:16 +0000 (13:48 -0700)
committerAustin Clements <aclements@csail.mit.edu>
Mon, 24 Aug 2009 20:48:16 +0000 (13:48 -0700)
variables to be given initial values in some cases, to make
building global scopes more convenient.

R=rsc
APPROVED=rsc
DELTA=29  (17 added, 0 deleted, 12 changed)
OCL=33760
CL=33766

usr/austin/eval/decls.go
usr/austin/eval/expr.go
usr/austin/eval/scope.go
usr/austin/eval/value.go

index 068acf92bd58b6504e01be48c1d1921511a36b62..6b8a887f3653a6c8ebb68aecda90f9b5d0fa510f 100644 (file)
@@ -35,7 +35,7 @@ type Type interface {
        isFloat() bool;
        // isIdeal returns true if this is an ideal int or float.
        isIdeal() bool;
-       // ZeroVal returns a new zero value of this type.
+       // Zero returns a new zero value of this type.
        Zero() Value;
        // String returns the string representation of this type.
        String() string;
@@ -82,6 +82,8 @@ type IntValue interface {
        Set(int64);
 }
 
+// TODO(austin) IdealIntValue and IdealFloatValue should not exist
+// because ideals are not l-values.
 type IdealIntValue interface {
        Value;
        Get() *bignum.Integer;
@@ -183,6 +185,10 @@ type Variable struct {
        Index int;
        // Static type of this variable
        Type Type;
+       // Value of this variable.  This is only used by Scope.NewFrame;
+       // therefore, it is useful for global scopes but cannot be used
+       // in function scopes.
+       Init Value;
 }
 
 type Constant struct {
index 024d574f5614b3bd23f50f0f6c8bcc775c70c9d3..73125f3a6ddf97ba1de229b3894fc619adddb66e 100644 (file)
@@ -1705,6 +1705,8 @@ func CompileExpr(scope *Scope, expr ast.Expr) (*Expr, os.Error) {
                return &Expr{t, func(f *Frame, out Value) { out.(*idealFloatV).V = ec.evalIdealFloat() }}, nil;
        case *stringType:
                return &Expr{t, func(f *Frame, out Value) { out.(StringValue).Set(ec.evalString(f)) }}, nil;
+       case *ArrayType:
+               return &Expr{t, func(f *Frame, out Value) { out.(ArrayValue).Assign(ec.evalArray(f)) }}, nil;
        case *PtrType:
                return &Expr{t, func(f *Frame, out Value) { out.(PtrValue).Set(ec.evalPtr(f)) }}, nil;
        case *FuncType:
index 7ab4f36a294b855839d97556e3acbbccb408c70f..fd95530b1cd739d56b4f92c7c3beeb51ed5d3f10 100644 (file)
@@ -11,7 +11,7 @@ import (
 )
 
 func (b *block) enterChild() *block {
-       if b.inner != nil {
+       if b.inner != nil && b.inner.scope == b.scope {
                log.Crash("Failed to exit child block before entering another child");
        }
        sub := &block{
@@ -28,17 +28,19 @@ func (b *block) exit() {
        if b.outer == nil {
                log.Crash("Cannot exit top-level block");
        }
-       if b.outer.inner != b {
-               log.Crash("Already exited block");
-       }
-       if b.inner != nil {
-               log.Crash("Exit of parent block without exit of child block");
+       if b.outer.scope == b.scope {
+               if b.outer.inner != b {
+                       log.Crash("Already exited block");
+               }
+               if b.inner != nil && b.inner.scope == b.scope {
+                       log.Crash("Exit of parent block without exit of child block");
+               }
        }
        b.outer.inner = nil;
 }
 
 func (b *block) ChildScope() *Scope {
-       if b.inner != nil {
+       if b.inner != nil && b.inner.scope == b.scope {
                log.Crash("Failed to exit child block before entering a child scope");
        }
        sub := b.enterChild();
@@ -58,11 +60,11 @@ func (b *block) DefineVar(name string, pos token.Position, t Type) (*Variable, D
 }
 
 func (b *block) DefineSlot(t Type) *Variable {
-       if b.inner != nil {
+       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};
+       v := &Variable{token.Position{}, index, t, nil};
        b.numVars++;
        if index+1 > b.scope.maxVars {
                b.scope.maxVars = index+1;
@@ -107,7 +109,14 @@ func (b *block) Lookup(name string) (level int, def Def) {
 }
 
 func (s *Scope) NewFrame(outer *Frame) *Frame {
-       return outer.child(s.maxVars);
+       fr := outer.child(s.maxVars);
+       for _, v := range s.defs {
+               switch v := v.(type) {
+               case *Variable:
+                       fr.Vars[v.Index] = v.Init;
+               }
+       }
+       return fr;
 }
 
 func (f *Frame) Get(level int, index int) Value {
index 3aa23199703cf4dce491453776e17ddb5038f8b5..5f533c0d67026d10e1d1d3a4b7f4e5674a3e7ead 100644 (file)
@@ -400,7 +400,7 @@ func (v *structV) String() string {
        res := "{";
        for i, v := range *v {
                if i > 0 {
-                       res += "; ";
+                       res += ", ";
                }
                res += v.String();
        }