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;
Set(int64);
}
+// TODO(austin) IdealIntValue and IdealFloatValue should not exist
+// because ideals are not l-values.
type IdealIntValue interface {
Value;
Get() *bignum.Integer;
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 {
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:
)
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{
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();
}
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;
}
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 {