new StackVariable type wrapping string-name and offset-indices

This commit is contained in:
John Kerl 2021-02-17 14:55:58 -05:00
parent 583e5c1c1d
commit dbcb3fbc83
6 changed files with 149 additions and 108 deletions

View file

@ -33,7 +33,7 @@ import (
// ================================================================
type ForLoopOneVariableNode struct {
variableName string
indexVariable *runtime.StackVariable
indexableNode IEvaluable
statementBlockNode *StatementBlockNode
}
@ -44,7 +44,7 @@ func NewForLoopOneVariableNode(
statementBlockNode *StatementBlockNode,
) *ForLoopOneVariableNode {
return &ForLoopOneVariableNode{
variableName,
runtime.NewStackVariable(variableName),
indexableNode,
statementBlockNode,
}
@ -128,7 +128,7 @@ func (this *ForLoopOneVariableNode) Execute(state *runtime.State) (*BlockExitPay
for pe := mapval.Head; pe != nil; pe = pe.Next {
mapkey := types.MlrvalFromString(pe.Key)
err := state.Stack.SetAtScope(this.variableName, &mapkey)
err := state.Stack.SetAtScope(this.indexVariable, &mapkey)
if err != nil {
return nil, err
}
@ -163,7 +163,7 @@ func (this *ForLoopOneVariableNode) Execute(state *runtime.State) (*BlockExitPay
state.Stack.PushStackFrame()
defer state.Stack.PopStackFrame()
for _, element := range arrayval {
err := state.Stack.SetAtScope(this.variableName, &element)
err := state.Stack.SetAtScope(this.indexVariable, &element)
if err != nil {
return nil, err
}
@ -207,21 +207,21 @@ func (this *ForLoopOneVariableNode) Execute(state *runtime.State) (*BlockExitPay
// ================================================================
type ForLoopTwoVariableNode struct {
keyVariableName string
valueVariableName string
keyIndexVariable *runtime.StackVariable
valueIndexVariable *runtime.StackVariable
indexableNode IEvaluable
statementBlockNode *StatementBlockNode
}
func NewForLoopTwoVariableNode(
keyVariableName string,
valueVariableName string,
keyIndexVariable *runtime.StackVariable,
valueIndexVariable *runtime.StackVariable,
indexableNode IEvaluable,
statementBlockNode *StatementBlockNode,
) *ForLoopTwoVariableNode {
return &ForLoopTwoVariableNode{
keyVariableName,
valueVariableName,
keyIndexVariable,
valueIndexVariable,
indexableNode,
statementBlockNode,
}
@ -258,10 +258,12 @@ func (this *RootNode) BuildForLoopTwoVariableNode(astNode *dsl.ASTNode) (*ForLoo
lib.InternalCodingErrorIf(keyVariableASTNode.Type != dsl.NodeTypeLocalVariable)
lib.InternalCodingErrorIf(keyVariableASTNode.Token == nil)
keyVariableName := string(keyVariableASTNode.Token.Lit)
keyIndexVariable := runtime.NewStackVariable(keyVariableName)
lib.InternalCodingErrorIf(valueVariableASTNode.Type != dsl.NodeTypeLocalVariable)
lib.InternalCodingErrorIf(valueVariableASTNode.Token == nil)
valueVariableName := string(valueVariableASTNode.Token.Lit)
valueIndexVariable := runtime.NewStackVariable(valueVariableName)
// TODO: error if loop-over node isn't map/array (inasmuch as can be
// detected at CST-build time)
@ -276,8 +278,8 @@ func (this *RootNode) BuildForLoopTwoVariableNode(astNode *dsl.ASTNode) (*ForLoo
}
return NewForLoopTwoVariableNode(
keyVariableName,
valueVariableName,
keyIndexVariable,
valueIndexVariable,
indexableNode,
statementBlockNode,
), nil
@ -311,11 +313,11 @@ func (this *ForLoopTwoVariableNode) Execute(state *runtime.State) (*BlockExitPay
for pe := mapval.Head; pe != nil; pe = pe.Next {
mapkey := types.MlrvalFromString(pe.Key)
err := state.Stack.SetAtScope(this.keyVariableName, &mapkey)
err := state.Stack.SetAtScope(this.keyIndexVariable, &mapkey)
if err != nil {
return nil, err
}
err = state.Stack.SetAtScope(this.valueVariableName, pe.Value)
err = state.Stack.SetAtScope(this.valueIndexVariable, pe.Value)
if err != nil {
return nil, err
}
@ -352,11 +354,11 @@ func (this *ForLoopTwoVariableNode) Execute(state *runtime.State) (*BlockExitPay
for zindex, element := range arrayval {
mindex := types.MlrvalFromInt(int(zindex + 1))
err := state.Stack.SetAtScope(this.keyVariableName, &mindex)
err := state.Stack.SetAtScope(this.keyIndexVariable, &mindex)
if err != nil {
return nil, err
}
err = state.Stack.SetAtScope(this.valueVariableName, &element)
err = state.Stack.SetAtScope(this.valueIndexVariable, &element)
if err != nil {
return nil, err
}
@ -400,21 +402,21 @@ func (this *ForLoopTwoVariableNode) Execute(state *runtime.State) (*BlockExitPay
// ================================================================
type ForLoopMultivariableNode struct {
keyVariableNames []string
valueVariableName string
keyIndexVariables []*runtime.StackVariable
valueIndexVariable *runtime.StackVariable
indexableNode IEvaluable
statementBlockNode *StatementBlockNode
}
func NewForLoopMultivariableNode(
keyVariableNames []string,
valueVariableName string,
keyIndexVariables []*runtime.StackVariable,
valueIndexVariable *runtime.StackVariable,
indexableNode IEvaluable,
statementBlockNode *StatementBlockNode,
) *ForLoopMultivariableNode {
return &ForLoopMultivariableNode{
keyVariableNames,
valueVariableName,
keyIndexVariables,
valueIndexVariable,
indexableNode,
statementBlockNode,
}
@ -449,15 +451,17 @@ func (this *RootNode) BuildForLoopMultivariableNode(
lib.InternalCodingErrorIf(keyVariablesASTNode.Type != dsl.NodeTypeParameterList)
lib.InternalCodingErrorIf(keyVariablesASTNode.Children == nil)
keyVariableNames := make([]string, len(keyVariablesASTNode.Children))
keyIndexVariables := make([]*runtime.StackVariable, len(keyVariablesASTNode.Children))
for i, keyVariableASTNode := range keyVariablesASTNode.Children {
lib.InternalCodingErrorIf(keyVariableASTNode.Token == nil)
keyVariableNames[i] = string(keyVariableASTNode.Token.Lit)
keyIndexVariableName := string(keyVariableASTNode.Token.Lit)
keyIndexVariables[i] = runtime.NewStackVariable(keyIndexVariableName)
}
lib.InternalCodingErrorIf(valueVariableASTNode.Type != dsl.NodeTypeLocalVariable)
lib.InternalCodingErrorIf(valueVariableASTNode.Token == nil)
valueVariableName := string(valueVariableASTNode.Token.Lit)
valueIndexVariable := runtime.NewStackVariable(valueVariableName)
// TODO: error if loop-over node isn't map/array (inasmuch as can be
// detected at CST-build time)
@ -472,8 +476,8 @@ func (this *RootNode) BuildForLoopMultivariableNode(
}
return NewForLoopMultivariableNode(
keyVariableNames,
valueVariableName,
keyIndexVariables,
valueIndexVariable,
indexableNode,
statementBlockNode,
), nil
@ -521,11 +525,11 @@ func (this *ForLoopMultivariableNode) Execute(state *runtime.State) (*BlockExitP
// ----------------------------------------------------------------
func (this *ForLoopMultivariableNode) executeOuter(
mlrval *types.Mlrval,
keyVariableNames []string,
keyIndexVariables []*runtime.StackVariable,
state *runtime.State,
) (*BlockExitPayload, error) {
if len(keyVariableNames) == 1 {
return this.executeInner(mlrval, keyVariableNames[0], state)
if len(keyIndexVariables) == 1 {
return this.executeInner(mlrval, keyIndexVariables[0], state)
}
// else, recurse
@ -535,12 +539,12 @@ func (this *ForLoopMultivariableNode) executeOuter(
for pe := mapval.Head; pe != nil; pe = pe.Next {
mapkey := types.MlrvalFromString(pe.Key)
err := state.Stack.SetAtScope(keyVariableNames[0], &mapkey)
err := state.Stack.SetAtScope(keyIndexVariables[0], &mapkey)
if err != nil {
return nil, err
}
blockExitPayload, err := this.executeOuter(pe.Value, keyVariableNames[1:], state)
blockExitPayload, err := this.executeOuter(pe.Value, keyIndexVariables[1:], state)
if err != nil {
return nil, err
}
@ -568,12 +572,12 @@ func (this *ForLoopMultivariableNode) executeOuter(
for zindex, element := range arrayval {
mindex := types.MlrvalFromInt(int(zindex + 1))
err := state.Stack.SetAtScope(keyVariableNames[0], &mindex)
err := state.Stack.SetAtScope(keyIndexVariables[0], &mindex)
if err != nil {
return nil, err
}
blockExitPayload, err := this.executeOuter(&element, keyVariableNames[1:], state)
blockExitPayload, err := this.executeOuter(&element, keyIndexVariables[1:], state)
if err != nil {
return nil, err
}
@ -614,7 +618,7 @@ func (this *ForLoopMultivariableNode) executeOuter(
// ----------------------------------------------------------------
func (this *ForLoopMultivariableNode) executeInner(
mlrval *types.Mlrval,
keyVariableName string,
keyIndexVariable *runtime.StackVariable,
state *runtime.State,
) (*BlockExitPayload, error) {
if mlrval.IsMap() {
@ -623,11 +627,11 @@ func (this *ForLoopMultivariableNode) executeInner(
for pe := mapval.Head; pe != nil; pe = pe.Next {
mapkey := types.MlrvalFromString(pe.Key)
err := state.Stack.SetAtScope(keyVariableName, &mapkey)
err := state.Stack.SetAtScope(keyIndexVariable, &mapkey)
if err != nil {
return nil, err
}
err = state.Stack.SetAtScope(this.valueVariableName, pe.Value)
err = state.Stack.SetAtScope(this.valueIndexVariable, pe.Value)
if err != nil {
return nil, err
}
@ -661,11 +665,11 @@ func (this *ForLoopMultivariableNode) executeInner(
for zindex, element := range arrayval {
mindex := types.MlrvalFromInt(int(zindex + 1))
err := state.Stack.SetAtScope(keyVariableName, &mindex)
err := state.Stack.SetAtScope(keyIndexVariable, &mindex)
if err != nil {
return nil, err
}
err = state.Stack.SetAtScope(this.valueVariableName, &element)
err = state.Stack.SetAtScope(this.valueIndexVariable, &element)
if err != nil {
return nil, err
}

View file

@ -173,12 +173,12 @@ func (this *FullOosvarRvalueNode) Evaluate(
// ----------------------------------------------------------------
type LocalVariableNode struct {
variableName string
stackVariable *runtime.StackVariable
}
func (this *RootNode) BuildLocalVariableNode(variableName string) *LocalVariableNode {
return &LocalVariableNode{
variableName: variableName,
stackVariable: runtime.NewStackVariable(variableName),
}
}
func (this *LocalVariableNode) Evaluate(

View file

@ -779,8 +779,8 @@ func (this *FullOosvarLvalueNode) UnassignIndexed(
// ----------------------------------------------------------------
type LocalVariableLvalueNode struct {
variableName string
typeName string
stackVariable *runtime.StackVariable
typeName string
// a = 1;
// b = 1;
@ -804,19 +804,19 @@ func (this *RootNode) BuildLocalVariableLvalueNode(astNode *dsl.ASTNode) (IAssig
defineTypedAtScope = true
}
return NewLocalVariableLvalueNode(
variableName,
runtime.NewStackVariable(variableName),
typeName,
defineTypedAtScope,
), nil
}
func NewLocalVariableLvalueNode(
variableName string,
stackVariable *runtime.StackVariable,
typeName string,
defineTypedAtScope bool,
) *LocalVariableLvalueNode {
return &LocalVariableLvalueNode{
variableName: variableName,
stackVariable: stackVariable,
typeName: typeName,
defineTypedAtScope: defineTypedAtScope,
}
@ -839,15 +839,15 @@ func (this *LocalVariableLvalueNode) AssignIndexed(
var err error = nil
if indices == nil {
if this.defineTypedAtScope {
err = state.Stack.DefineTypedAtScope(this.variableName, this.typeName, rvalue)
err = state.Stack.DefineTypedAtScope(this.stackVariable, this.typeName, rvalue)
} else {
err = state.Stack.Set(this.variableName, rvalue)
err = state.Stack.Set(this.stackVariable, rvalue)
}
} else {
// There is no 'map x[1] = {}' in the DSL grammar.
lib.InternalCodingErrorIf(this.defineTypedAtScope)
err = state.Stack.SetIndexed(this.variableName, indices, rvalue)
err = state.Stack.SetIndexed(this.stackVariable, indices, rvalue)
}
return err
}
@ -863,9 +863,9 @@ func (this *LocalVariableLvalueNode) UnassignIndexed(
state *runtime.State,
) {
if indices == nil {
state.Stack.Unset(this.variableName)
state.Stack.Unset(this.stackVariable)
} else {
state.Stack.UnsetIndexed(this.variableName, indices)
state.Stack.UnsetIndexed(this.stackVariable, indices)
}
}

View file

@ -129,7 +129,7 @@ func (this *UDFCallsite) Evaluate(
for i, _ := range arguments {
err := state.Stack.DefineTypedAtScope(
this.udf.signature.typeGatedParameterNames[i].Name,
runtime.NewStackVariable(this.udf.signature.typeGatedParameterNames[i].Name),
this.udf.signature.typeGatedParameterNames[i].TypeName,
arguments[i],
)

View file

@ -123,7 +123,7 @@ func (this *UDSCallsite) Execute(state *runtime.State) (*BlockExitPayload, error
for i, _ := range arguments {
err := state.Stack.DefineTypedAtScope(
this.uds.signature.typeGatedParameterNames[i].Name,
runtime.NewStackVariable(this.uds.signature.typeGatedParameterNames[i].Name),
this.uds.signature.typeGatedParameterNames[i].TypeName,
arguments[i],
)

View file

@ -34,6 +34,27 @@ import (
"miller/src/types"
)
// ================================================================
// STACK VARIABLE
// StackVariable is an opaque handle which a callsite can hold onto, which
// keeps stack-offset information in it that is private to us.
type StackVariable struct {
name string
// Type like "int" or "num" or "var" is stored in the stack itself
frameSetIndex int
indexInFrame int
}
// TODO: be sure to invalidate slot 0 for struct uninit
func NewStackVariable(name string) *StackVariable {
return &StackVariable{
name: name,
frameSetIndex: 0,
indexInFrame: 0,
}
}
// ================================================================
// STACK METHODS
@ -78,12 +99,12 @@ func (this *Stack) PopStackFrame() {
// scope. It's an error to define it again in the same scope, whether the type
// is the same or not.
func (this *Stack) DefineTypedAtScope(
variableName string,
stackVariable *StackVariable,
typeName string,
mlrval *types.Mlrval,
) error {
head := this.stackFrameSets.Front().Value.(*StackFrameSet)
return head.defineTypedAtScope(variableName, typeName, mlrval)
return head.defineTypedAtScope(stackVariable, typeName, mlrval)
}
// For untyped declarations at the current scope -- these are in binds of
@ -92,11 +113,11 @@ func (this *Stack) DefineTypedAtScope(
// E.g. 'for (int i = 0; i < 10; i += 1)' uses DefineTypedAtScope
// E.g. 'for (i = 0; i < 10; i += 1)' uses Set.
func (this *Stack) SetAtScope(
variableName string,
stackVariable *StackVariable,
mlrval *types.Mlrval,
) error {
head := this.stackFrameSets.Front().Value.(*StackFrameSet)
return head.setAtScope(variableName, mlrval)
return head.setAtScope(stackVariable, mlrval)
}
// For 'a = 2', checking for outer-scoped to maybe reuse, else insert new in
@ -107,42 +128,46 @@ func (this *Stack) SetAtScope(
// However if it waa previously assigned untyped with 'a = "hello"' then the
// assignment is OK.
func (this *Stack) Set(
variableName string,
stackVariable *StackVariable,
mlrval *types.Mlrval,
) error {
head := this.stackFrameSets.Front().Value.(*StackFrameSet)
return head.set(variableName, mlrval)
return head.set(stackVariable, mlrval)
}
// E.g. 'x[1] = 2' where the variable x may or may not have been already set.
func (this *Stack) SetIndexed(
variableName string,
stackVariable *StackVariable,
indices []*types.Mlrval,
mlrval *types.Mlrval,
) error {
head := this.stackFrameSets.Front().Value.(*StackFrameSet)
return head.setIndexed(variableName, indices, mlrval)
return head.setIndexed(stackVariable, indices, mlrval)
}
// E.g. 'unset x'
func (this *Stack) Unset(variableName string) {
func (this *Stack) Unset(
stackVariable *StackVariable,
) {
head := this.stackFrameSets.Front().Value.(*StackFrameSet)
head.unset(variableName)
head.unset(stackVariable)
}
// E.g. 'unset x[1]'
func (this *Stack) UnsetIndexed(
variableName string,
stackVariable *StackVariable,
indices []*types.Mlrval,
) {
head := this.stackFrameSets.Front().Value.(*StackFrameSet)
head.unsetIndexed(variableName, indices)
head.unsetIndexed(stackVariable, indices)
}
// Returns nil on no-such
func (this *Stack) Get(variableName string) *types.Mlrval {
func (this *Stack) Get(
stackVariable *StackVariable,
) *types.Mlrval {
head := this.stackFrameSets.Front().Value.(*StackFrameSet)
return head.get(variableName)
return head.get(stackVariable)
}
func (this *Stack) Dump() {
@ -189,56 +214,60 @@ func (this *StackFrameSet) dump() {
// See Stack.DefineTypedAtScope comments above
func (this *StackFrameSet) defineTypedAtScope(
variableName string,
stackVariable *StackVariable,
typeName string,
mlrval *types.Mlrval,
) error {
return this.stackFrames.Front().Value.(*StackFrame).defineTyped(variableName, typeName, mlrval)
return this.stackFrames.Front().Value.(*StackFrame).defineTyped(
stackVariable, typeName, mlrval,
)
}
// See Stack.SetAtScope comments above
func (this *StackFrameSet) setAtScope(
variableName string,
stackVariable *StackVariable,
mlrval *types.Mlrval,
) error {
return this.stackFrames.Front().Value.(*StackFrame).set(variableName, mlrval)
return this.stackFrames.Front().Value.(*StackFrame).set(stackVariable, mlrval)
}
// See Stack.Set comments above
func (this *StackFrameSet) set(
variableName string,
stackVariable *StackVariable,
mlrval *types.Mlrval,
) error {
for entry := this.stackFrames.Front(); entry != nil; entry = entry.Next() {
stackFrame := entry.Value.(*StackFrame)
if stackFrame.has(variableName) {
return stackFrame.set(variableName, mlrval)
if stackFrame.has(stackVariable) {
return stackFrame.set(stackVariable, mlrval)
}
}
return this.setAtScope(variableName, mlrval)
return this.setAtScope(stackVariable, mlrval)
}
// See Stack.SetIndexed comments above
func (this *StackFrameSet) setIndexed(
variableName string,
stackVariable *StackVariable,
indices []*types.Mlrval,
mlrval *types.Mlrval,
) error {
for entry := this.stackFrames.Front(); entry != nil; entry = entry.Next() {
stackFrame := entry.Value.(*StackFrame)
if stackFrame.has(variableName) {
return stackFrame.setIndexed(variableName, indices, mlrval)
if stackFrame.has(stackVariable) {
return stackFrame.setIndexed(stackVariable, indices, mlrval)
}
}
return this.stackFrames.Front().Value.(*StackFrame).setIndexed(variableName, indices, mlrval)
return this.stackFrames.Front().Value.(*StackFrame).setIndexed(stackVariable, indices, mlrval)
}
// See Stack.Unset comments above
func (this *StackFrameSet) unset(variableName string) {
func (this *StackFrameSet) unset(
stackVariable *StackVariable,
) {
for entry := this.stackFrames.Front(); entry != nil; entry = entry.Next() {
stackFrame := entry.Value.(*StackFrame)
if stackFrame.has(variableName) {
stackFrame.unset(variableName)
if stackFrame.has(stackVariable) {
stackFrame.unset(stackVariable)
return
}
}
@ -246,24 +275,26 @@ func (this *StackFrameSet) unset(variableName string) {
// See Stack.UnsetIndexed comments above
func (this *StackFrameSet) unsetIndexed(
variableName string,
stackVariable *StackVariable,
indices []*types.Mlrval,
) {
for entry := this.stackFrames.Front(); entry != nil; entry = entry.Next() {
stackFrame := entry.Value.(*StackFrame)
if stackFrame.has(variableName) {
stackFrame.unsetIndexed(variableName, indices)
if stackFrame.has(stackVariable) {
stackFrame.unsetIndexed(stackVariable, indices)
return
}
}
}
// Returns nil on no-such
func (this *StackFrameSet) get(variableName string) *types.Mlrval {
func (this *StackFrameSet) get(
stackVariable *StackVariable,
) *types.Mlrval {
// Scope-walk
for entry := this.stackFrames.Front(); entry != nil; entry = entry.Next() {
stackFrame := entry.Value.(*StackFrame)
mlrval := stackFrame.get(variableName)
mlrval := stackFrame.get(stackVariable)
if mlrval != nil {
return mlrval
}
@ -288,8 +319,10 @@ func newStackFrame() *StackFrame {
}
// Returns nil on no such
func (this *StackFrame) get(variableName string) *types.Mlrval {
slot := this.vars[variableName]
func (this *StackFrame) get(
stackVariable *StackVariable,
) *types.Mlrval {
slot := this.vars[stackVariable.name]
if slot == nil {
return nil
} else {
@ -297,8 +330,10 @@ func (this *StackFrame) get(variableName string) *types.Mlrval {
}
}
func (this *StackFrame) has(variableName string) bool {
return this.vars[variableName] != nil
func (this *StackFrame) has(
stackVariable *StackVariable,
) bool {
return this.vars[stackVariable.name] != nil
}
func (this *StackFrame) clear() {
@ -307,19 +342,19 @@ func (this *StackFrame) clear() {
// TODO: audit for honor of error-return at callsites
func (this *StackFrame) set(
variableName string,
stackVariable *StackVariable,
mlrval *types.Mlrval,
) error {
slot := this.vars[variableName]
slot := this.vars[stackVariable.name]
if slot == nil {
slot, err := types.NewTypeGatedMlrvalVariable(variableName, "any", mlrval)
slot, err := types.NewTypeGatedMlrvalVariable(stackVariable.name, "any", mlrval)
if err != nil {
return err
} else {
this.vars[variableName] = slot
this.vars[stackVariable.name] = slot
return nil
}
this.vars[variableName] = slot
this.vars[stackVariable.name] = slot
return nil
} else {
return slot.Assign(mlrval)
@ -328,33 +363,35 @@ func (this *StackFrame) set(
// TODO: audit for honor of error-return at callsites
func (this *StackFrame) defineTyped(
variableName string,
stackVariable *StackVariable,
typeName string,
mlrval *types.Mlrval,
) error {
slot := this.vars[variableName]
slot := this.vars[stackVariable.name]
if slot == nil {
slot, err := types.NewTypeGatedMlrvalVariable(variableName, typeName, mlrval)
slot, err := types.NewTypeGatedMlrvalVariable(stackVariable.name, typeName, mlrval)
if err != nil {
return err
} else {
this.vars[variableName] = slot
this.vars[stackVariable.name] = slot
return nil
}
this.vars[variableName] = slot
this.vars[stackVariable.name] = slot
return nil
} else {
return errors.New(
fmt.Sprintf(
"%s: variable %s has already been defined in the same scope.",
lib.MlrExeName(), variableName,
lib.MlrExeName(), stackVariable.name,
),
)
}
}
func (this *StackFrame) unset(variableName string) {
slot := this.vars[variableName]
func (this *StackFrame) unset(
stackVariable *StackVariable,
) {
slot := this.vars[stackVariable.name]
if slot != nil {
slot.Unassign()
}
@ -362,18 +399,18 @@ func (this *StackFrame) unset(variableName string) {
// TODO: audit for honor of error-return at callsites
func (this *StackFrame) setIndexed(
variableName string,
stackVariable *StackVariable,
indices []*types.Mlrval,
mlrval *types.Mlrval,
) error {
value := this.get(variableName)
value := this.get(stackVariable)
if value == nil {
lib.InternalCodingErrorIf(len(indices) < 1)
leadingIndex := indices[0]
if leadingIndex.IsString() || leadingIndex.IsInt() {
newval := types.MlrvalEmptyMap()
newval.PutIndexed(indices, mlrval)
return this.set(variableName, &newval)
return this.set(stackVariable, &newval)
} else {
return errors.New(
fmt.Sprintf(
@ -390,10 +427,10 @@ func (this *StackFrame) setIndexed(
}
func (this *StackFrame) unsetIndexed(
variableName string,
stackVariable *StackVariable,
indices []*types.Mlrval,
) {
value := this.get(variableName)
value := this.get(stackVariable)
if value == nil {
return
}