mirror of
https://github.com/johnkerl/miller.git
synced 2026-08-04 13:33:18 +00:00
new StackVariable type wrapping string-name and offset-indices
This commit is contained in:
parent
583e5c1c1d
commit
dbcb3fbc83
6 changed files with 149 additions and 108 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue