/// <summary> /// Update line number dictionary after deleting lines. /// </summary> private void UpdateLineMap(CodePosition position, int length) { // subtract length of line we replaced length -= (int)(position.AfterPosition - position.StartPosition); var address = Position + 1 + position.AfterPosition; Bytecode.Seek(position.AfterPosition + length + 1, SeekOrigin.Begin); // pass \x00 while (true) { var nextAddressStr = Bytecode.Read(2); if (nextAddressStr.Length < 2 || nextAddressStr == "\0\0") { break; } var nextAddress = nextAddressStr.ToUnsignedInteger(); Bytecode.Seek(-2, SeekOrigin.Current); Bytecode.Write((nextAddress + length).ToBasicUnsignedInteger()); Bytecode.Seek(nextAddress - address - 2, SeekOrigin.Current); address = nextAddress; } // update line number dict foreach (var line in position.Deleteable) { _lineNumberMap.Remove(line); } foreach (var line in position.Beyond) { _lineNumberMap[line] += length; } }
/// <summary> /// Preparse to build line number dictionary. /// </summary> private void RebuildLineNumbers() { _lineNumberMap.Clear(); var offsets = new List <long>(); Bytecode.Seek(0, SeekOrigin.Begin); var scanPosition = 0L; while (true) { Bytecode.ReadByte(); // pass \x00 var scanline = Bytecode.ReadLineNumber(); if (scanline == -1) { // if parse_line_number returns -1, it leaves the stream pointer here: 00 _00_ 00 1A break; } _lineNumberMap[scanline] = scanPosition; Bytecode.SkipUntilLineEnd(); scanPosition = Bytecode.Position; offsets.Add(scanPosition); } _lineNumberMap[BasicLastLineNumber] = scanPosition; // rebuild offsets Bytecode.Seek(0, SeekOrigin.Begin); var lastPosition = 0L; foreach (var postion in offsets) { Bytecode.ReadByte(); Bytecode.Write(((int)(Position + 1 + postion)).ToBasicUnsignedInteger()); Bytecode.Read((int)(postion - lastPosition - 3)); lastPosition = postion; } // ensure program is properly sealed - last offset must be 00 00. keep, but ignore, anything after. Bytecode.Write("\0\0\0"); }