public void Memory(char action, string targetName, int paramCount) { uint crush; switch (action) { case 's' when paramCount > 1: //set indexed _opcodes.Add(NanTags.EncodeVariableRef(targetName, out crush)); AddSymbol(crush, targetName); _opcodes.Add(NanTags.EncodeOpcode('m', 'S', (ushort)paramCount, 0)); break; case 'g' when paramCount > 0: // get indexed _opcodes.Add(NanTags.EncodeVariableRef(targetName, out crush)); AddSymbol(crush, targetName); _opcodes.Add(NanTags.EncodeOpcode('m', 'G', (ushort)paramCount, 0)); break; default: NanTags.EncodeVariableRef(targetName, out crush); AddSymbol(crush, targetName); _opcodes.Add(NanTags.EncodeLongOpcode('m', action, crush)); break; } }
/// <summary> /// Write opcodes and data section to stream /// References to string constants will be recalculated /// </summary> public void WriteToStream(Stream output) { // a string is [NanTag(UInt32): byte length] [string bytes, padded to 8 byte chunks] // 1) Calculate the string table size var dataLength = _stringTable.Select(CalculatePaddedSize).Sum() + _stringTable.Count; // 2) Write a jump command to skip the table var jumpCode = NanTags.EncodeLongOpcode('c', 's', (uint)dataLength); WriteCode(output, jumpCode); // 3) Write the strings, with a mapping dictionary long location = 1; // counting initial jump as 0 var mapping = new Dictionary <long, long>(); // original index, final memory location for (var index = 0; index < _stringTable.Count; index++) { var staticStr = _stringTable[index]; var bytes = Encoding.ASCII.GetBytes(staticStr); var chunks = CalculatePaddedSize(staticStr); var padSize = (chunks * 8) - bytes.Length; mapping.Add(index, location); var headerOpCode = NanTags.EncodeUInt32((uint)bytes.Length); WriteCode(output, headerOpCode); location++; output.Write(bytes, 0, bytes.Length); location += chunks; for (int p = 0; p < padSize; p++) { output.WriteByte(0); } } // 4) Write the op-codes foreach (var code in _opcodes) { var type = NanTags.TypeOf(code); switch (type) { case DataType.PtrString: case DataType.PtrStaticString: NanTags.DecodePointer(code, out var original, out _); var final = mapping[original]; WriteCode(output, NanTags.EncodePointer(final, DataType.PtrStaticString)); break; default: WriteCode(output, code); break; } } output.Flush(); }
/// <summary> /// Jump relative up /// </summary> public void UnconditionalJump(uint opCodeCount) { _opcodes.Add(NanTags.EncodeLongOpcode('c', 'j', opCodeCount)); }
/// <summary> /// Jump relative down if top of value-stack is false /// </summary> public void CompareJump(uint opCodeCount) { _opcodes.Add(NanTags.EncodeLongOpcode('c', 'c', opCodeCount)); }
public void Memory(char action, double opcode) { var crush = NanTags.DecodeUInt32(opcode); _opcodes.Add(NanTags.EncodeLongOpcode('m', action, crush)); }
public void Increment(sbyte incr, string targetName) { NanTags.EncodeVariableRef(targetName, out var crush); AddSymbol(crush, targetName); _opcodes.Add(NanTags.EncodeLongOpcode('i', (char)incr, crush)); }