001: /*
002: * TestVarFrameCmd.java --
003: *
004: * This procedure implements the "testvarframe" command. It is
005: * used for testing the local var frame and compiled local
006: * var frame implementation in Jacl.
007: *
008: * Copyright (c) 2006 by Mo DeJong
009: *
010: * See the file "license.terms" for information on usage and redistribution
011: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
012: *
013: * RCS: @(#) $Id: TestVarFrameCmd.java,v 1.5 2006/05/23 05:34:33 mdejong Exp $
014: */
015:
016: package tcl.lang;
017:
018: import java.util.*;
019:
020: public class TestVarFrameCmd implements Command {
021:
022: /*
023: *----------------------------------------------------------------------
024: *
025: * cmdProc --
026: *
027: * Iterate over the entries in a variable frame for a
028: * compiled procedure and return a buffer indicating
029: * contents of the var frame.
030: *
031: * Results:
032: * None.
033: *
034: * Side effects:
035: * None.
036: *
037: *----------------------------------------------------------------------
038: */
039:
040: public void cmdProc(Interp interp, // Current interpreter.
041: TclObject[] objv) // The argument objects.
042: throws TclException {
043: if (objv.length != 1) {
044: throw new TclNumArgsException(interp, 1, objv, "");
045: }
046:
047: CallFrame varFrame = interp.varFrame;
048:
049: if (varFrame == null) {
050: throw new TclException(interp,
051: "can't be invoked from global scope");
052: }
053:
054: HashMap localTable = varFrame.varTable;
055: Var[] compiledLocals = varFrame.compiledLocals;
056: String[] compiledLocalsNames = varFrame.compiledLocalsNames;
057: Var clocal;
058: Var var;
059: StringBuffer results = new StringBuffer(128);
060:
061: // Print contents of varFrame hashtable
062:
063: if (localTable == null) {
064: results.append("localTable is null\n");
065: } else {
066: // Iterate over Var entries in the local table.
067: results.append("localTable is {\n");
068:
069: for (Iterator iter = localTable.entrySet().iterator(); iter
070: .hasNext();) {
071: Map.Entry entry = (Map.Entry) iter.next();
072: var = (Var) entry.getValue();
073: if (var == null) {
074: results.append("null\n");
075: } else {
076: varInfo(interp, results, var, false);
077: }
078: }
079:
080: results.append("}\n");
081: }
082:
083: // Print contents of compiledLocals array
084:
085: if (compiledLocals == null) {
086: results.append("compiledLocals is null\n");
087: } else {
088: // Iterate over Var entries in the local table.
089: results.append("compiledLocals is {\n");
090:
091: for (int i = 0; i < compiledLocals.length; i++) {
092: clocal = compiledLocals[i];
093:
094: if (clocal == null) {
095: results.append("null\n");
096: continue;
097: }
098:
099: if (!clocal.hashKey.equals(compiledLocalsNames[i])) {
100: throw new TclException(
101: interp,
102: "compiledLocal["
103: + i
104: + "] varname \""
105: + clocal.hashKey
106: + "\" does not match compiledLocalsNames varname \""
107: + compiledLocalsNames[i] + "\"");
108: }
109:
110: var = clocal;
111: if (var.isVarNonLocal()) {
112: results.append("Non-Local ");
113: }
114: varInfo(interp, results, var, false);
115: }
116:
117: results.append("}\n");
118: }
119:
120: // Print info about the resolved refs in the compiled local array.
121:
122: if (compiledLocals == null) {
123: results.append("compiledLocals.resolved is null\n");
124: } else {
125: // Iterate over Var entries in the local table.
126: results.append("compiledLocals.resolved is {\n");
127:
128: for (int i = 0; i < compiledLocals.length; i++) {
129: clocal = compiledLocals[i];
130: if (clocal == null) {
131: results.append("null\n");
132: continue;
133: }
134:
135: varInfo(interp, results, clocal, true);
136: }
137:
138: results.append("}\n");
139: }
140:
141: interp.setResult(results.toString());
142: return;
143: }
144:
145: static void varInfo(Interp interp, StringBuffer results, Var var,
146: boolean resolveIt) {
147: // Compiled local entries can be null, but var passed to this
148: // method will never be null.
149:
150: // If resolveIt is true then try to resolve the variable as
151: // a scalar or array var. We want to know when a variable
152: // can't be resolved. If the varible can't be resolved
153: // we still want to print info indicating the flags
154: // that were set so the reason a var can't be resolved
155: // can be determined.
156:
157: if (resolveIt) {
158: Var resolved = var;
159: if (resolved.isVarLink()) {
160: resolved = resolved.linkto;
161: }
162: if (resolved.isVarScalar()) {
163: resolved = Var.resolveScalar(resolved);
164: } else if (resolved.isVarArray()) {
165: resolved = Var.resolveArray(resolved);
166: }
167: if (resolved == null) {
168: results.append("!RESOLVED ");
169: }
170: }
171:
172: Var linkto = var;
173:
174: if (linkto.isVarLink()) {
175: linkto = linkto.linkto;
176:
177: // After resolve, Var can't be a link
178: if (linkto.isVarLink()) {
179: throw new TclRuntimeError(
180: "var is still a link var after resolve");
181: }
182: }
183: if (resolveIt) {
184: // Always use the linked to var when resolveIt is true.
185: var = linkto;
186: }
187:
188: if ((var == linkto) && var.isVarUndefined()) {
189: results.append("UNDEFINED ");
190: } else if (linkto.isVarUndefined()) {
191: results.append("UNDEFINED-> ");
192: }
193:
194: if (linkto.isVarScalar()) {
195: results.append(var.hashKey);
196: } else if (linkto.isVarArray()) {
197: results.append(var.hashKey);
198: results.append("()");
199: } else if (linkto.isVarArrayElement()) {
200: results.append("(");
201: results.append(linkto.hashKey);
202: results.append(")");
203: } else {
204: results.append("?");
205: }
206:
207: // Print link info if the variable is
208: // linked into another frame.
209:
210: if (var.isVarLink()) {
211: results.append(" -> ");
212: String fullName = Var.getVariableFullName(interp, linkto);
213: if (fullName.length() == 0 && linkto.isVarArrayElement()) {
214: results.append("?()");
215: } else {
216: results.append(fullName);
217: }
218: }
219:
220: // The TRACE_EXISTS flag indicates that a variable has
221: // traces set. Most code would just test (var.traces == null),
222: // just make sure the two ways of representing this info
223: // are in sync.
224:
225: if (resolveIt && linkto.isVarTraceExists()) {
226: results.append(" TRACE_EXISTS");
227: }
228: // If the var.traces field does not match the
229: // TRACE_EXISTS flag, then generate an error.
230:
231: if (resolveIt) {
232: if (linkto.isVarTraceExists() && linkto.traces == null) {
233: throw new TclRuntimeError(
234: "TRACE_EXISTS flag set for var "
235: + " but var.traces is null");
236: } else if (!linkto.isVarTraceExists()
237: && linkto.traces != null) {
238: throw new TclRuntimeError(
239: "TRACE_EXISTS flag is not set for var "
240: + " but var.traces non-null");
241: }
242: }
243:
244: // The NO_CACHE flag indicates that a variable was
245: // returned by a resolver proc installed into the
246: // interp.
247:
248: if (resolveIt && linkto.isVarNoCache()) {
249: results.append(" NO_CACHE");
250: }
251:
252: results.append('\n');
253: }
254:
255: }
|