private string Stringify(double token, DataType type, HashLookup <string> debugSymbols) { switch (type) { case DataType.Invalid: return(""); case DataType.NoValue: return(""); case DataType.VariableRef: var rref = NanTags.DecodeVariableRef(token); if (debugSymbols?.ContainsKey(rref) == true) { return("'" + debugSymbols[rref] + "' (" + rref.ToString("X") + ")"); } return(rref.ToString("X")); case DataType.Opcode: NanTags.DecodeLongOpCode(token, out var ccls, out var cact, out var refr); if (ccls == 'm') { if (debugSymbols?.ContainsKey(refr) == true) { return(ccls + "" + cact + " '" + debugSymbols[refr] + "' (" + refr.ToString("X") + ")"); } } if (ccls == 'i') { if (debugSymbols?.ContainsKey(refr) == true) { return("Incr " + ((sbyte)cact) + " '" + debugSymbols[refr] + "' (" + refr.ToString("X") + ")"); } } NanTags.DecodeOpCode(token, out _, out _, out var p1, out var p2); return(ccls + "" + cact + " (" + p1 + ", " + p2 + ")"); case DataType.ValSmallString: return("[" + NanTags.DecodeShortStr(token) + "]"); case DataType.PtrHashtable: case DataType.PtrGrid: case DataType.PtrSet: case DataType.PtrVector: case DataType.PtrString: case DataType.PtrStaticString: NanTags.DecodePointer(token, out var targ, out _); return(" -> " + targ); case DataType.ValInt32: return(NanTags.DecodeInt32(token).ToString()); case DataType.ValUInt32: return(NanTags.DecodeUInt32(token).ToString()); case DataType.Number: return(token.ToString(CultureInfo.InvariantCulture)); default: throw new ArgumentOutOfRangeException(nameof(type), type, null); } }
/// <summary> /// Produce a diagnostic description of the memory layout /// </summary> public string ToString(HashLookup <string> debugSymbols) { int index = 0; var sb = new StringBuilder(); // Try to display static strings meaningfully if (NanTags.TypeOf(encodedTokens[0]) == DataType.Opcode) { index = 1; NanTags.DecodeLongOpCode(encodedTokens[0], out var c1, out var c2, out var count); if (c1 == 'c' && c2 == 's') { sb.AppendLine("Data table: " + count + " tokens (" + (count * 8) + " bytes)"); while (index < count) { var length = NanTags.DecodeUInt32(encodedTokens[index]); var chunkCount = (int)Math.Ceiling(length / 8.0d); sb.Append(" " + index + ": (" + length + ") ["); index++; for (var ch = 0; ch < chunkCount; ch++) { var raw = BitConverter.GetBytes(encodedTokens[index++]); sb.Append(MakeSafe(Encoding.ASCII.GetString(raw))); } sb.AppendLine("]"); } sb.AppendLine("End of data table"); } } // output remaining bytecodes for (; index < encodedTokens.Count; index++) { var token = encodedTokens[index]; var type = NanTags.TypeOf(token); sb.Append(index.ToString()); sb.Append(" "); sb.Append(type.ToString()); sb.Append(": "); sb.AppendLine(Stringify(token, type, debugSymbols)); } return(sb.ToString()); }