diff --git a/go/src/dsl/cst/lvalues.go b/go/src/dsl/cst/lvalues.go index 9d051ab59..23568a041 100644 --- a/go/src/dsl/cst/lvalues.go +++ b/go/src/dsl/cst/lvalues.go @@ -784,10 +784,10 @@ type LocalVariableLvalueNode struct { // a = 1; // b = 1; // if (true) { - // a = 3; <-- frameBind is false; updates outer a - // var b = 4; <-- frameBind is true; creates new inner b + // a = 3; <-- setAtScope is false; updates outer a + // var b = 4; <-- setAtScope is true; creates new inner b // } - frameBind bool + setAtScope bool } func (this *RootNode) BuildLocalVariableLvalueNode(astNode *dsl.ASTNode) (IAssignable, error) { @@ -795,12 +795,12 @@ func (this *RootNode) BuildLocalVariableLvalueNode(astNode *dsl.ASTNode) (IAssig variableName := string(astNode.Token.Lit) typeName := "any" - frameBind := false + setAtScope := false if astNode.Children != nil { // typed, like 'num x = 3' typeNode := astNode.Children[0] lib.InternalCodingErrorIf(typeNode.Type != dsl.NodeTypeTypedecl) typeName = string(typeNode.Token.Lit) - frameBind = true + setAtScope = true } typeGatedMlrvalName, err := types.NewTypeGatedMlrvalName( variableName, @@ -812,17 +812,17 @@ func (this *RootNode) BuildLocalVariableLvalueNode(astNode *dsl.ASTNode) (IAssig // TODO: type-gated mlrval return NewLocalVariableLvalueNode( typeGatedMlrvalName, - frameBind, + setAtScope, ), nil } func NewLocalVariableLvalueNode( typeGatedMlrvalName *types.TypeGatedMlrvalName, - frameBind bool, + setAtScope bool, ) *LocalVariableLvalueNode { return &LocalVariableLvalueNode{ typeGatedMlrvalName: typeGatedMlrvalName, - frameBind: frameBind, + setAtScope: setAtScope, } } @@ -846,7 +846,7 @@ func (this *LocalVariableLvalueNode) AssignIndexed( return err } - if this.frameBind { + if this.setAtScope { state.Stack.SetAtScope(this.typeGatedMlrvalName.Name, rvalue) } else { state.Stack.Set(this.typeGatedMlrvalName.Name, rvalue) @@ -854,7 +854,7 @@ func (this *LocalVariableLvalueNode) AssignIndexed( return nil } else { // TODO: propagate error return - if this.frameBind { + if this.setAtScope { state.Stack.SetAtScopeIndexed(this.typeGatedMlrvalName.Name, indices, rvalue) } else { state.Stack.SetIndexed(this.typeGatedMlrvalName.Name, indices, rvalue) diff --git a/go/src/runtime/stack.go b/go/src/runtime/stack.go index eceb38cdc..55abd8f90 100644 --- a/go/src/runtime/stack.go +++ b/go/src/runtime/stack.go @@ -163,8 +163,7 @@ func (this *StackFrameSet) Dump() { stackFrame := entry.Value.(*StackFrame) fmt.Printf(" VARIABLES (count %d):\n", len(stackFrame.vars)) for k, v := range stackFrame.vars { - fmt.Printf(" %-16s %s\n", k, v.String()) - //// PEND fmt.Printf(" %-16s %s\n", k, v.ValueString()) + fmt.Printf(" %-16s %s\n", k, v.ValueString()) } } } @@ -277,27 +276,23 @@ type StackFrame struct { // TODO: just a map for now. In the C impl, pre-computation of // name-to-array-slot indices was an important optimization, especially for // compute-intensive scenarios. - vars map[string]*types.Mlrval - //// PEND vars map[string]*types.TypeGatedMlrvalVariable + vars map[string]*types.TypeGatedMlrvalVariable } func NewStackFrame() *StackFrame { return &StackFrame{ - vars: make(map[string]*types.Mlrval), - //// PEND vars: make(map[string]*types.TypeGatedMlrvalVariable), + vars: make(map[string]*types.TypeGatedMlrvalVariable), } } // Returns nil on no such func (this *StackFrame) Get(name string) *types.Mlrval { - return this.vars[name] - //// PEND - // slot := this.vars[name] - // if slot == nil { - // return nil - // } else { - // return slot.GetValue() - // } + slot := this.vars[name] + if slot == nil { + return nil + } else { + return slot.GetValue() + } } // Returns nil on no such @@ -306,40 +301,36 @@ func (this *StackFrame) Has(name string) bool { } func (this *StackFrame) Clear() { - this.vars = make(map[string]*types.Mlrval) - //// PEND this.vars = make(map[string]*types.TypeGatedMlrvalVariable) + this.vars = make(map[string]*types.TypeGatedMlrvalVariable) } // TODO: make a typemasked ... -func (this *StackFrame) Set(name string, mlrval *types.Mlrval) /* PEND error*/ { - this.vars[name] = mlrval.Copy() - //// PEND - // slot := this.vars[name] - // if slot == nil { - // slot, err := types.NewTypeGatedMlrvalVariable(name, "var", mlrval) - // if err != nil { - // return err - // } else { - // this.vars[name] = slot - // return nil - // } - // } else { - // return slot.Assign(mlrval.Copy()) - // } - +// TODO: honor error-return at callsites +func (this *StackFrame) Set(name string, mlrval *types.Mlrval) error { + slot := this.vars[name] + if slot == nil { + slot, err := types.NewTypeGatedMlrvalVariable(name, "any", mlrval) + if err != nil { + return err + } else { + this.vars[name] = slot + return nil + } + this.vars[name] = slot + return nil + } else { + return slot.Assign(mlrval.Copy()) + } } -func (this *StackFrame) Unset(name string) /* PEND error */ { - this.vars[name] = types.MlrvalPointerFromAbsent() - //// PEND - // slot := this.vars[name] - // if slot != nil { - // return slot.Assign(types.MlrvalPointerFromAbsent()) - // } else { - // return nil - // } +func (this *StackFrame) Unset(name string) { + slot := this.vars[name] + if slot != nil { + slot.Unassign() + } } +// TODO: implement error-return, and honor it at callsites func (this *StackFrame) SetIndexed( name string, indices []*types.Mlrval, diff --git a/go/src/types/mlrval_typing.go b/go/src/types/mlrval_typing.go index 1ab6769a0..a824de874 100644 --- a/go/src/types/mlrval_typing.go +++ b/go/src/types/mlrval_typing.go @@ -94,3 +94,7 @@ func (this *TypeGatedMlrvalVariable) Assign(value *Mlrval) error { this.value = value.Copy() return nil } + +func (this *TypeGatedMlrvalVariable) Unassign() { + this.value = MlrvalPointerFromAbsent() +}