2011-09-02 17:34:58 -05:00
|
|
|
type filename = str;
|
2011-07-05 04:48:19 -05:00
|
|
|
|
2011-07-27 07:19:39 -05:00
|
|
|
type file_pos = {ch: uint, byte: uint};
|
2011-07-16 01:01:10 -05:00
|
|
|
|
2011-07-05 04:48:19 -05:00
|
|
|
/* A codemap is a thing that maps uints to file/line/column positions
|
|
|
|
* in a crate. This to make it possible to represent the positions
|
|
|
|
* with single-word things, rather than passing records all over the
|
|
|
|
* compiler.
|
|
|
|
*/
|
2012-02-01 04:37:53 -06:00
|
|
|
|
|
|
|
type file_substr_ = {lo: uint, hi: uint, col: uint, line: uint};
|
|
|
|
type file_substr = option<file_substr_>;
|
|
|
|
|
2011-07-27 07:19:39 -05:00
|
|
|
type filemap =
|
2012-02-01 04:37:53 -06:00
|
|
|
@{name: filename, substr: file_substr, src: @str,
|
2012-01-25 16:53:45 -06:00
|
|
|
start_pos: file_pos, mutable lines: [file_pos]};
|
2011-07-05 04:48:19 -05:00
|
|
|
|
2011-08-04 18:20:09 -05:00
|
|
|
type codemap = @{mutable files: [filemap]};
|
2011-07-05 04:48:19 -05:00
|
|
|
|
2012-02-01 03:18:59 -06:00
|
|
|
type loc = {file: filemap, line: uint, col: uint};
|
2011-07-05 04:48:19 -05:00
|
|
|
|
2012-02-03 19:39:39 -06:00
|
|
|
fn new_codemap() -> codemap { @{mutable files: [] } }
|
2011-07-16 01:01:10 -05:00
|
|
|
|
2012-02-01 04:37:53 -06:00
|
|
|
fn new_filemap_w_substr(filename: filename, substr: file_substr,
|
|
|
|
src: @str,
|
|
|
|
start_pos_ch: uint, start_pos_byte: uint)
|
2011-07-27 07:19:39 -05:00
|
|
|
-> filemap {
|
2012-02-01 04:37:53 -06:00
|
|
|
ret @{name: filename, substr: substr, src: src,
|
2011-07-27 07:19:39 -05:00
|
|
|
start_pos: {ch: start_pos_ch, byte: start_pos_byte},
|
2011-08-19 17:16:48 -05:00
|
|
|
mutable lines: [{ch: start_pos_ch, byte: start_pos_byte}]};
|
2011-07-05 04:48:19 -05:00
|
|
|
}
|
|
|
|
|
2012-02-01 04:37:53 -06:00
|
|
|
fn new_filemap(filename: filename, src: @str,
|
|
|
|
start_pos_ch: uint, start_pos_byte: uint)
|
|
|
|
-> filemap {
|
2012-02-01 04:40:49 -06:00
|
|
|
ret new_filemap_w_substr(filename, none, src,
|
2012-02-01 04:37:53 -06:00
|
|
|
start_pos_ch, start_pos_byte);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_substr_info(cm: codemap, lo: uint, hi: uint)
|
|
|
|
-> (filename, file_substr_)
|
|
|
|
{
|
|
|
|
let pos = lookup_char_pos(cm, lo);
|
|
|
|
let name = #fmt("<%s:%u:%u>", pos.file.name, pos.line, pos.col);
|
|
|
|
ret (name, {lo: lo, hi: hi, col: pos.col, line: pos.line});
|
|
|
|
}
|
|
|
|
|
2011-07-27 07:19:39 -05:00
|
|
|
fn next_line(file: filemap, chpos: uint, byte_pos: uint) {
|
2011-08-19 17:16:48 -05:00
|
|
|
file.lines += [{ch: chpos, byte: byte_pos}];
|
2011-07-05 04:48:19 -05:00
|
|
|
}
|
|
|
|
|
2012-01-11 11:58:05 -06:00
|
|
|
type lookup_fn = fn@(file_pos) -> uint;
|
2011-07-05 04:48:19 -05:00
|
|
|
|
2012-01-25 15:22:10 -06:00
|
|
|
fn lookup_line(map: codemap, pos: uint, lookup: lookup_fn)
|
2012-02-03 19:39:39 -06:00
|
|
|
-> {fm: filemap, line: uint}
|
2012-01-25 15:22:10 -06:00
|
|
|
{
|
2011-12-20 15:38:10 -06:00
|
|
|
let len = vec::len(map.files);
|
2011-07-27 07:19:39 -05:00
|
|
|
let a = 0u;
|
2011-12-20 15:38:10 -06:00
|
|
|
let b = len;
|
2011-07-27 07:19:39 -05:00
|
|
|
while b - a > 1u {
|
|
|
|
let m = (a + b) / 2u;
|
2011-08-19 17:16:48 -05:00
|
|
|
if lookup(map.files[m].start_pos) > pos { b = m; } else { a = m; }
|
2011-07-05 04:48:19 -05:00
|
|
|
}
|
2012-01-21 03:00:06 -06:00
|
|
|
if (a >= len) {
|
2012-02-03 19:39:39 -06:00
|
|
|
fail #fmt("position %u does not resolve to a source location", pos)
|
2012-01-21 03:00:06 -06:00
|
|
|
}
|
2011-08-19 17:16:48 -05:00
|
|
|
let f = map.files[a];
|
2011-07-05 04:48:19 -05:00
|
|
|
a = 0u;
|
2011-08-15 18:38:23 -05:00
|
|
|
b = vec::len(f.lines);
|
2011-07-27 07:19:39 -05:00
|
|
|
while b - a > 1u {
|
|
|
|
let m = (a + b) / 2u;
|
2011-08-19 17:16:48 -05:00
|
|
|
if lookup(f.lines[m]) > pos { b = m; } else { a = m; }
|
2011-07-05 04:48:19 -05:00
|
|
|
}
|
2012-02-03 19:39:39 -06:00
|
|
|
ret {fm: f, line: a};
|
2012-01-25 15:22:10 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
|
2012-02-03 19:39:39 -06:00
|
|
|
let {fm: f, line: a} = lookup_line(map, pos, lookup);
|
|
|
|
ret {file: f, line: a + 1u, col: pos - lookup(f.lines[a])};
|
2011-07-16 01:01:10 -05:00
|
|
|
}
|
|
|
|
|
2011-07-27 07:19:39 -05:00
|
|
|
fn lookup_char_pos(map: codemap, pos: uint) -> loc {
|
|
|
|
fn lookup(pos: file_pos) -> uint { ret pos.ch; }
|
2011-07-16 01:01:10 -05:00
|
|
|
ret lookup_pos(map, pos, lookup);
|
|
|
|
}
|
|
|
|
|
2011-07-27 07:19:39 -05:00
|
|
|
fn lookup_byte_pos(map: codemap, pos: uint) -> loc {
|
|
|
|
fn lookup(pos: file_pos) -> uint { ret pos.byte; }
|
2011-07-16 01:01:10 -05:00
|
|
|
ret lookup_pos(map, pos, lookup);
|
2011-07-05 04:48:19 -05:00
|
|
|
}
|
|
|
|
|
2012-02-04 19:37:24 -06:00
|
|
|
enum expn_info_ {
|
|
|
|
expanded_from({call_site: span,
|
|
|
|
callie: {name: str, span: option<span>}})
|
2011-08-12 10:57:21 -05:00
|
|
|
}
|
2012-02-04 19:37:24 -06:00
|
|
|
type expn_info = option<@expn_info_>;
|
|
|
|
type span = {lo: uint, hi: uint, expn_info: expn_info};
|
2011-07-05 04:48:19 -05:00
|
|
|
|
2011-09-12 04:27:30 -05:00
|
|
|
fn span_to_str(sp: span, cm: codemap) -> str {
|
2012-02-04 19:37:24 -06:00
|
|
|
let lo = lookup_char_pos(cm, sp.lo);
|
|
|
|
let hi = lookup_char_pos(cm, sp.hi);
|
|
|
|
ret #fmt("%s:%u:%u: %u:%u", lo.file.name,
|
|
|
|
lo.line, lo.col, hi.line, hi.col)
|
2011-07-05 04:48:19 -05:00
|
|
|
}
|
|
|
|
|
2012-02-01 03:18:59 -06:00
|
|
|
type file_lines = {file: filemap, lines: [uint]};
|
2011-07-11 01:27:03 -05:00
|
|
|
|
2011-07-27 07:19:39 -05:00
|
|
|
fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines {
|
|
|
|
let lo = lookup_char_pos(cm, sp.lo);
|
|
|
|
let hi = lookup_char_pos(cm, sp.hi);
|
2012-02-01 03:18:59 -06:00
|
|
|
// FIXME: Check for filemap?
|
2011-08-19 17:16:48 -05:00
|
|
|
let lines = [];
|
2011-10-21 05:31:48 -05:00
|
|
|
uint::range(lo.line - 1u, hi.line as uint) {|i| lines += [i]; };
|
2012-02-01 03:18:59 -06:00
|
|
|
ret @{file: lo.file, lines: lines};
|
2011-07-11 01:27:03 -05:00
|
|
|
}
|
|
|
|
|
2012-02-01 05:45:44 -06:00
|
|
|
fn get_line(fm: filemap, line: int) -> str unsafe {
|
2011-08-19 17:16:48 -05:00
|
|
|
let begin: uint = fm.lines[line].byte - fm.start_pos.byte;
|
2011-07-27 07:19:39 -05:00
|
|
|
let end: uint;
|
2011-08-15 18:38:23 -05:00
|
|
|
if line as uint < vec::len(fm.lines) - 1u {
|
2011-08-19 17:16:48 -05:00
|
|
|
end = fm.lines[line + 1].byte - fm.start_pos.byte;
|
2011-07-13 14:19:59 -05:00
|
|
|
} else {
|
|
|
|
// If we're not done parsing the file, we're at the limit of what's
|
|
|
|
// parsed. If we just slice the rest of the string, we'll print out
|
|
|
|
// the remainder of the file, which is undesirable.
|
2012-01-25 16:53:45 -06:00
|
|
|
end = str::byte_len(*fm.src);
|
2012-02-01 06:20:21 -06:00
|
|
|
let rest = str::unsafe::slice_bytes(*fm.src, begin, end);
|
2012-02-11 03:57:39 -06:00
|
|
|
let newline = str::index_byte(rest, '\n' as u8);
|
2011-07-27 07:19:39 -05:00
|
|
|
if newline != -1 { end = begin + (newline as uint); }
|
2011-07-11 01:27:03 -05:00
|
|
|
}
|
2012-02-01 06:20:21 -06:00
|
|
|
ret str::unsafe::slice_bytes(*fm.src, begin, end);
|
2011-07-11 01:27:03 -05:00
|
|
|
}
|
|
|
|
|
2012-01-25 15:22:10 -06:00
|
|
|
fn lookup_byte_offset(cm: codemap::codemap, chpos: uint)
|
|
|
|
-> {fm: filemap, pos: uint}
|
|
|
|
{
|
|
|
|
fn lookup(pos: file_pos) -> uint { ret pos.ch; }
|
2012-02-03 19:39:39 -06:00
|
|
|
let {fm,line} = lookup_line(cm,chpos,lookup);
|
2012-02-01 02:35:11 -06:00
|
|
|
let line_offset = fm.lines[line].byte - fm.start_pos.byte;
|
2012-01-25 15:22:10 -06:00
|
|
|
let col = chpos - fm.lines[line].ch;
|
|
|
|
let col_offset = str::byte_len_range(*fm.src, line_offset, col);
|
|
|
|
ret {fm: fm, pos: line_offset + col_offset};
|
|
|
|
}
|
|
|
|
|
|
|
|
fn span_to_snippet(sp: span, cm: codemap::codemap) -> str {
|
|
|
|
let begin = lookup_byte_offset(cm,sp.lo);
|
|
|
|
let end = lookup_byte_offset(cm,sp.hi);
|
|
|
|
assert begin.fm == end.fm;
|
|
|
|
ret str::slice(*begin.fm.src, begin.pos, end.pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_snippet(cm: codemap::codemap, fidx: uint, lo: uint, hi: uint) -> str
|
|
|
|
{
|
|
|
|
let fm = cm.files[fidx];
|
|
|
|
ret str::slice(*fm.src, lo, hi)
|
|
|
|
}
|
|
|
|
|
2011-09-02 17:34:58 -05:00
|
|
|
fn get_filemap(cm: codemap, filename: str) -> filemap {
|
|
|
|
for fm: filemap in cm.files { if fm.name == filename { ret fm; } }
|
2011-07-11 01:27:03 -05:00
|
|
|
//XXjdm the following triggers a mismatched type bug
|
|
|
|
// (or expected function, found _|_)
|
2011-07-27 07:19:39 -05:00
|
|
|
fail; // ("asking for " + filename + " which we don't know about");
|
2011-07-11 01:27:03 -05:00
|
|
|
}
|
2012-01-26 03:52:08 -06:00
|
|
|
|
2011-07-05 04:48:19 -05:00
|
|
|
//
|
|
|
|
// Local Variables:
|
|
|
|
// mode: rust
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
|
|
|
// End:
|
|
|
|
//
|