// Given a variable pointer with just the name of the target known, resolve to a variable // pointer that more specifically points to the exact instance: whether it's global, // or the exact position of a temporary on the callstack. LiteralVariablePointer ResolveVariablePointer(LiteralVariablePointer varPointer) { int contextIndex = varPointer.contextIndex; if (contextIndex == -1) { contextIndex = GetContextIndexOfVariableNamed(varPointer.variableName); } var valueOfVariablePointedTo = GetRawVariableWithName(varPointer.variableName, contextIndex); // Extra layer of indirection: // When accessing a pointer to a pointer (e.g. when calling nested or // recursive functions that take a variable references, ensure we don't create // a chain of indirection by just returning the final target. var doubleRedirectionPointer = valueOfVariablePointedTo as LiteralVariablePointer; if (doubleRedirectionPointer) { return(doubleRedirectionPointer); } // Make copy of the variable pointer so we're not using the value direct from // the runtime. Temporary must be local to the current scope. else { return(new LiteralVariablePointer(varPointer.variableName, contextIndex)); } }
internal void Assign(VariableAssignment varAss, Runtime.Object value) { var name = varAss.variableName; int contextIndex = -1; // Are we assigning to a global variable? bool setGlobal = false; if (varAss.isNewDeclaration) { setGlobal = varAss.isGlobal; } else { setGlobal = _globalVariables.ContainsKey(name); } // Constructing new variable pointer reference if (varAss.isNewDeclaration) { var varPointer = value as LiteralVariablePointer; if (varPointer) { var fullyResolvedVariablePointer = ResolveVariablePointer(varPointer); value = fullyResolvedVariablePointer; } } // Assign to existing variable pointer? // Then assign to the variable that the pointer is pointing to by name. else { // De-reference variable reference to point to LiteralVariablePointer existingPointer = null; do { existingPointer = GetRawVariableWithName(name, contextIndex) as LiteralVariablePointer; if (existingPointer) { name = existingPointer.variableName; contextIndex = existingPointer.contextIndex; setGlobal = (contextIndex == 0); } } while(existingPointer); } if (setGlobal) { SetGlobal(name, value); } else { _callStack.SetTemporaryVariable(name, value, varAss.isNewDeclaration, contextIndex); } }
internal Runtime.Object ValueAtVariablePointer(LiteralVariablePointer pointer) { return(GetVariableWithName(pointer.variableName, pointer.contextIndex)); }