private void DoIndexedGet(Stack <double> valueStack, ushort paramCount) { var target = valueStack.Pop(); var value = _memory.Variables.Resolve(NanTags.DecodeVariableRef(target)); var type = NanTags.TypeOf(value); switch (type) { // Note: Numeric types should read the bit at index // Hashes and arrays do the obvious lookup // Sets return true/false for occupancy case DataType.PtrString: case DataType.PtrStaticString: // get the other indexes. If more than one, build a string out of the bits? // What to do with out-of-range? var str = _memory.DereferenceString(NanTags.DecodePointer(value)); var sb = new StringBuilder(paramCount - 1); for (int i = 0; i < paramCount; i++) { var idx = _memory.CastInt(valueStack.Pop()); if (idx >= 0 && idx < str.Length) { sb.Append(str[idx]); } } var result = _memory.StoreStringAndGetReference(sb.ToString()); valueStack.Push(result); return; default: throw new Exception("Indexing of type '" + type + "' is not yet supported"); } }
public double CastDouble(double encoded) { var type = NanTags.TypeOf(encoded); double result; switch (type) { case DataType.Number: return(encoded); case DataType.ValInt32: return(NanTags.DecodeInt32(encoded)); case DataType.ValUInt32: return(NanTags.DecodeUInt32(encoded)); case DataType.VariableRef: // Follow scope var next = Variables.Resolve(NanTags.DecodeVariableRef(encoded)); return(CastDouble(next)); case DataType.ValSmallString: double.TryParse(NanTags.DecodeShortStr(encoded), out result); return(result); case DataType.PtrStaticString: case DataType.PtrString: NanTags.DecodePointer(encoded, out var target, out _); double.TryParse(DereferenceString(target), out result); return(result); // All the things that can't be meaningfully cast default: return(0.0d); } }
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); } }
private int HandleFunctionDefinition(ushort argCount, ushort tokenCount, int position, Stack <double> valueStack) { var functionNameHash = NanTags.DecodeVariableRef(valueStack.Pop()); if (Functions.ContainsKey(functionNameHash)) { throw new Exception("Function '" + functionNameHash + "' redefined at " + position + ". Original at " + Functions[functionNameHash]); } Functions.Add(functionNameHash, new FunctionDefinition { StartPosition = position, ParamCount = argCount }); return(position + tokenCount + 1); // + definition length + terminator }
public int CastInt(double encoded) { int result; var type = NanTags.TypeOf(encoded); switch (type) { case DataType.Invalid: case DataType.Opcode: case DataType.NoValue: return(0); case DataType.VariableRef: // Follow scope var next = Variables.Resolve(NanTags.DecodeVariableRef(encoded)); return(CastInt(next)); case DataType.ValSmallString: int.TryParse(NanTags.DecodeShortStr(encoded), out result); return(result); case DataType.PtrStaticString: case DataType.PtrString: NanTags.DecodePointer(encoded, out var target, out _); int.TryParse(DereferenceString(target), out result); return(result); case DataType.PtrHashtable: case DataType.PtrGrid: case DataType.PtrSet: case DataType.PtrVector: return(0); case DataType.Number: return((int)encoded); case DataType.ValInt32: return(NanTags.DecodeInt32(encoded)); case DataType.ValUInt32: return((int)NanTags.DecodeUInt32(encoded)); default: throw new ArgumentOutOfRangeException(); } }
public string CastString(double encoded) { var type = NanTags.TypeOf(encoded); switch (type) { case DataType.Invalid: return("<invalid value>"); case DataType.Number: return(encoded.ToString(CultureInfo.InvariantCulture)); case DataType.Opcode: return("<Op Code>"); case DataType.NoValue: return(""); case DataType.VariableRef: // Follow scope var next = Variables.Resolve(NanTags.DecodeVariableRef(encoded)); return(CastString(next)); case DataType.ValSmallString: return(NanTags.DecodeShortStr(encoded)); case DataType.PtrStaticString: case DataType.PtrString: NanTags.DecodePointer(encoded, out var target, out _); return(DereferenceString(target)); case DataType.PtrHashtable: case DataType.PtrGrid: case DataType.PtrSet: case DataType.PtrVector: return("<complex type>"); case DataType.ValInt32: return(NanTags.DecodeInt32(encoded).ToString()); case DataType.ValUInt32: return(NanTags.DecodeUInt32(encoded).ToString()); default: throw new ArgumentOutOfRangeException(); } }
private int PrepareFunctionCall(int position, ushort nbParams, Stack <double> valueStack, Stack <int> returnStack) { var functionNameHash = NanTags.DecodeVariableRef(valueStack.Pop()); var param = ReadParams(position, nbParams, valueStack); // Evaluate function. var evalResult = EvaluateFunctionCall(ref position, functionNameHash, nbParams, param, returnStack, valueStack); // Add result on stack as a value. if (NanTags.TypeOf(evalResult) != DataType.NoValue) { valueStack.Push(evalResult); } else if (NanTags.DecodeNonValue(evalResult) == NonValueType.Unit) { valueStack.Push(evalResult); } return(position); }
public void identifier_names_can_be_encoded_and_survive_a_round_trip() { var enc = NanTags.EncodeVariableRef("HelloWorld", out var crush); var type = NanTags.TypeOf(enc); var enc2 = NanTags.EncodeVariableRef("Hel" + "lo" + "Wo" + 'r' + 'l' + 'd', out var crush2); var other = NanTags.EncodeVariableRef("HelloWorld2", out var crushOther); Console.WriteLine("Crush: " + crush.ToString("X")); Console.WriteLine("Crush: " + crushOther.ToString("X")); var checkCrush = NanTags.DecodeVariableRef(enc); Assert.That(checkCrush, Is.EqualTo(crush)); Assert.That(type, Is.EqualTo(DataType.VariableRef)); Assert.That(NanTags.AreEqual(enc, enc2), Is.True); Assert.That(NanTags.AreEqual(enc, other), Is.False); Assert.That(crush, Is.EqualTo(crush2)); Assert.That(crush, Is.Not.EqualTo(crushOther)); }
public bool CastBoolean(double encoded) { var type = NanTags.TypeOf(encoded); switch (type) { case DataType.Number: return(Math.Abs(encoded) > double.Epsilon); case DataType.ValInt32: return(NanTags.DecodeInt32(encoded) != 0); case DataType.ValUInt32: return(NanTags.DecodeUInt32(encoded) != 0); case DataType.ValSmallString: { var strVal = NanTags.DecodeShortStr(encoded); return(StringTruthyness(strVal)); } case DataType.PtrString: case DataType.PtrStaticString: { NanTags.DecodePointer(encoded, out var ptr, out _); var strVal = DereferenceString(ptr); return(StringTruthyness(strVal)); } case DataType.VariableRef: // Follow scope var next = Variables.Resolve(NanTags.DecodeVariableRef(encoded)); return(CastBoolean(next)); // All the things that can't be meaningfully cast are 'false' default: return(false); } }