1 /** This module implements the DebugInfo class 2 3 ──────────────────────────────────────────────────────────────────────────────── 4 5 Copyright (C) 2021 pillager86.rf.gd 6 7 This program is free software: you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free Software 9 Foundation, either version 3 of the License, or (at your option) any later 10 version. 11 12 This program is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 14 PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License along with 17 this program. If not, see <https://www.gnu.org/licenses/>. 18 */ 19 module mildew.vm.debuginfo; 20 21 import std..string; 22 import std.typecons; 23 24 /// Alias for a hash map that associates DebugInfos to specific blocks of raw bytecode. 25 alias DebugMap = DebugInfo[ubyte[]]; 26 27 /** 28 * Holds debug information to be associated with completed ubyte[] code. 29 */ 30 class DebugInfo 31 { 32 public: 33 alias LineData = Tuple!(size_t, "ip", size_t, "lineNumber"); 34 35 /// constructor 36 this(string src, string name = "") 37 { 38 _source = splitLines(src); 39 _name = name; 40 } 41 42 /// Add an ip-lineNumber pair 43 void addLine(size_t ip, size_t lineNumber) 44 { 45 _lines ~= tuple!(size_t, "ip", size_t, "lineNumber")(ip, lineNumber); 46 } 47 48 /// get line associated with ip 49 size_t getLineNumber(size_t ip) 50 { 51 long index = 0; 52 while(index < cast(long)_lines.length - 1) 53 { 54 if(ip >= _lines[index].ip && ip < _lines[index+1].ip) 55 return _lines[index].lineNumber; 56 ++index; 57 } 58 // if we get to this point assume the error was on the last line if it exists 59 if(_lines.length >= 1) 60 { 61 return _lines[$-1].lineNumber; 62 } 63 // else the line info is missing so just return 0 64 return 0; 65 } 66 67 /// get a line of source starting at 1 if it exists 68 string getSourceLine(size_t lineNum) 69 { 70 if(lineNum-1 >= _source.length) 71 return ""; 72 return _source[lineNum-1]; 73 } 74 75 /// name property 76 string name() const { return _name; } 77 78 override string toString() const 79 { 80 import std.format: format; 81 return format("#lines=%s, #source=%s, name=`%s`", _lines.length, _source.length, _name); 82 } 83 84 private: 85 /// represents the source code as lines for error reporting 86 string[] _source; 87 /// line data array 88 LineData[] _lines; 89 /// optional name 90 string _name; 91 }