protected void TraceScope(string msg) { string lead = new String(' ', (_callCount - 1) * 2); StackScope scope = _callStack[_callCount - 1]; string output = lead + "Scope[" + (_callCount - 1) + "] VSS=" + scope.varStackStart + (scope.terminal ? " TERMINAL" : "") + " - Name='" + scope.name + "'"; if (null != scope.funcType) { output += " functype(" + scope.funcType.ToString() + ")"; } else if (null != scope.classInstance) { output += " @(" + scope.classInstance.classDef.name + ")"; } Console.WriteLine(output + " by='" + msg + "'"); //Console.WriteLine(lead + "C" + _callCount + " - " + msg); }
// BIG IMPORTANT FUNCTION. // Searches the current call stack for a variable with the given name and returns a VarStackRef, // which can be used by GetVarAtIndex to find the variable, usually later at execution time. // This saves us from having to do string searches for variables at execution time, but also // adds a lot of complexity to the system. Since the idea is to create these Refs during // TypeCheck, any discrepancy between the order scopes are pushed/popped and variables created // between TypeCheck and Evaluate WILL result in a grave error. public VarStackRef GetVarIndexByName(ExecContext context, string name, bool stopAtTerminals = false) { bool onlyUnique = false; int callIx = _callCount; int varIx = _varCount - 1; while (--callIx >= 0) { StackScope scope = _callStack[callIx]; if (!onlyUnique && null != scope.classInstance) { // If this scope is a class function call, search that class for // a member with that name. ITypeDef typeDef = null; MemberRef memRef = _callStack[callIx].classInstance.classDef.GetMemberRef(context, name, scope.isStatic ? ClassDef.SEARCH.STATIC : ClassDef.SEARCH.EITHER, ref typeDef); if (!memRef.isInvalid) { return(new VarStackRef(typeDef, callIx - _callCount, memRef)); } } if (!onlyUnique && null != scope.classDef) { ITypeDef typeDef = null; MemberRef memRef = _callStack[callIx].classDef.GetMemberRef(context, name, scope.isStatic ? ClassDef.SEARCH.STATIC : ClassDef.SEARCH.EITHER, ref typeDef); if (!memRef.isInvalid) { return(new VarStackRef(typeDef, callIx - _callCount, memRef)); } } // Otherwise, search the variable stack for it. while (varIx >= scope.varStackStart) { if (null != _varStack[varIx] && _varStack[varIx].name == name) { Variable var = _varStack[varIx]; if (var.unique) { return(new VarStackRef(var, false)); } else if (!onlyUnique) { return(new VarStackRef(_varStack[varIx].type, callIx - _callCount, varIx - scope.varStackStart)); } else { return(new VarStackRef(VarStackRef.ErrorType.NonUnique)); } } --varIx; } if (scope.hardTerminal) { break; } if (scope.terminal) { if (stopAtTerminals) { break; } else { onlyUnique = true; } } } // Search globals last. Globals are always in scope. int globIx = _globals.GetIndex(name); if (globIx >= 0) { Variable var = _globals.Get(globIx); return(new VarStackRef(var, true)); } return(new VarStackRef(VarStackRef.ErrorType.NotFound)); }
public override string ToString() { string res = ""; int count = _globals.Count; res += "GLOBALS:\n"; for (int ii = 0; ii < count; ++ii) { Variable var = _globals.Get(ii); if (var.type is TypeDef_Function) { res += " " + ((TypeDef_Function)var.type).GetDebugString(var.name); } else { res += GetVariableString(var); } } res += "STACK: varCount = " + _varCount + ", callCount = " + _callCount + "\n"; if (_callCount > 0) { for (int iVar = 0; iVar <= _callStack[0].varStackStart - 1; ++iVar) { Variable var = _varStack[iVar]; res += GetVariableString(var); } for (int iCall = 0; iCall < _callCount; ++iCall) { StackScope scope = _callStack[iCall]; if (scope.terminal) { res += " *** " + scope.name + " ***\n"; } else { res += " --- " + scope.name + " ---\n"; } int startIndex = scope.varStackStart; int endIndex; if (iCall < _callCount - 1) { endIndex = _callStack[iCall + 1].varStackStart - 1; } else { endIndex = _varCount - 1; } for (int iVar = startIndex; iVar <= endIndex; ++iVar) { Variable var = _varStack[iVar]; res += " " + GetVariableString(var); } } } else { for (int iVar = 0; iVar < _varCount; ++iVar) { Variable var = _varStack[iVar]; res += " " + GetVariableString(var); } } return(res); }