/// <summary> /// Create a new empty value scope /// </summary> public Scope() { PotentialGarbage = new HashSet <double>(); _scopes = new HashLookup <double> [128]; // recursion depth limit _currentScopeIdx = 0; _scopes[_currentScopeIdx] = new HashLookup <double>(); // global scope }
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> /// Clear all scopes and restore empty globals /// </summary> public void Clear() { for (int i = _currentScopeIdx; i >= 0; i--) { _scopes[i] = null; } _currentScopeIdx = 0; _scopes[_currentScopeIdx] = new HashLookup <double>(); }
public static HashLookup <string> DebugSymbolsForBuiltIns() { var tmp = new HashLookup <string>(64); Action <string> add = name => { tmp.Add(NanTags.GetCrushedName(name), name); }; add("="); add("equals"); add(">"); add("<"); add("<>"); add("not-equal"); add("assert"); add("random"); add("eval"); add("call"); add("not"); add("or"); add("and"); add("readkey"); add("readline"); add("print"); add("substring"); add("length"); add("replace"); add("concat"); add("+"); add("-"); add("*"); add("/"); add("%"); add("()"); return(tmp); }
/// <summary> /// Create a new value scope, copying references from a parent scope /// </summary> public Scope(Scope parentScope) { PotentialGarbage = new HashSet <double>(); _scopes = new HashLookup <double> [128]; // recursion depth limit _currentScopeIdx = 0; var global = new HashLookup <double>(); foreach (var pair in parentScope.ListAllVisible()) { global.Add(pair); // all parent refs become globals, regardless of original hierarchy } _scopes[_currentScopeIdx] = global; }
public void Init(RuntimeMemoryModel bin, TextReader input, TextWriter output, HashLookup <string> debugSymbols = null) { _position = 0; _memory = bin; Functions = BuiltInFunctionSymbols(); program = bin.Tokens(); DebugSymbols = debugSymbols; _input = input; _output = output; _valueStack = new Stack <double>(); _returnStack = new Stack <int>(); // absolute position for call and return }
/// <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()); }
/// <summary> /// Start a new inner-most scope. /// Parameters are specially named by index (like "__p0", "__p1"). The compiler must match this. /// </summary> public void PushScope(ICollection <double> parameters = null) { unchecked { var sd = new HashLookup <double>(); var i = 0; if (parameters != null) { foreach (var parameter in parameters) { sd.Add(NameFor(i), parameter); i++; } } _currentScopeIdx++; _scopes[_currentScopeIdx] = sd; } }
/// <summary> /// Symbol mapping for built-in functions /// </summary> public static HashLookup <FunctionDefinition> BuiltInFunctionSymbols() { var tmp = new HashLookup <FunctionDefinition>(64); Action <string, FuncDef> add = (name, type) => { tmp.Add(NanTags.GetCrushedName(name), new FunctionDefinition { Kind = type }); }; add("=", FuncDef.Equal); add("equals", FuncDef.Equal); add(">", FuncDef.GreaterThan); add("<", FuncDef.LessThan); add("<>", FuncDef.NotEqual); add("not-equal", FuncDef.NotEqual); add("assert", FuncDef.Assert); add("random", FuncDef.Random); add("eval", FuncDef.Eval); add("call", FuncDef.Call); add("not", FuncDef.LogicNot); add("or", FuncDef.LogicOr); add("and", FuncDef.LogicAnd); add("readkey", FuncDef.ReadKey); add("readline", FuncDef.ReadLine); add("print", FuncDef.Print); add("substring", FuncDef.Substring); add("length", FuncDef.Length); add("replace", FuncDef.Replace); add("concat", FuncDef.Concat); add("+", FuncDef.MathAdd); add("-", FuncDef.MathSub); add("*", FuncDef.MathProd); add("/", FuncDef.MathDiv); add("%", FuncDef.MathMod); add("()", FuncDef.UnitEmpty); // empty value marker return(tmp); }
public string DiagnosticString(double token, HashLookup <string> symbols = null) { return(Stringify(token, NanTags.TypeOf(token), symbols)); }