summary refs log tree commit diff
path: root/src/libsyntax/codemap.rs
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-11-12 19:32:48 -0800
committerBrian Anderson <banderson@mozilla.com>2012-11-14 15:18:29 -0800
commitf67bfe97389a256fc95216c29a2b8a066ee16a2c (patch)
treea638c4c480ceb60138a39a05c5b04967ac814eb6 /src/libsyntax/codemap.rs
parent9ecf86343a136c71cbb2bb8da9bfd1734fec37f4 (diff)
downloadrust-f67bfe97389a256fc95216c29a2b8a066ee16a2c.tar.gz
rust-f67bfe97389a256fc95216c29a2b8a066ee16a2c.zip
Add types for character position and byte position in the codemap
Diffstat (limited to 'src/libsyntax/codemap.rs')
-rw-r--r--src/libsyntax/codemap.rs192
1 files changed, 157 insertions, 35 deletions
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 87328f25ca8..8333849b21d 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -10,8 +10,109 @@ use std::serialization::{Serializable,
                          Serializer,
                          Deserializer};
 
-pub type BytePos = uint;
-pub type CharPos = uint;
+trait Pos {
+    static pure fn from_uint(n: uint) -> self;
+    pure fn to_uint(&self) -> uint;
+}
+
+pub enum BytePos = uint;
+pub enum CharPos = uint;
+
+impl BytePos: Pos {
+    static pure fn from_uint(n: uint) -> BytePos { BytePos(n) }
+    pure fn to_uint(&self) -> uint { **self }
+}
+
+impl BytePos: cmp::Eq {
+    pure fn eq(other: &BytePos) -> bool {
+        *self == **other
+    }
+    pure fn ne(other: &BytePos) -> bool { !self.eq(other) }
+}
+
+impl BytePos: cmp::Ord {
+    pure fn lt(other: &BytePos) -> bool { *self < **other }
+    pure fn le(other: &BytePos) -> bool { *self <= **other }
+    pure fn ge(other: &BytePos) -> bool { *self >= **other }
+    pure fn gt(other: &BytePos) -> bool { *self > **other }
+}
+
+impl BytePos: Num {
+    pure fn add(other: &BytePos) -> BytePos {
+        BytePos(*self + **other)
+    }
+    pure fn sub(other: &BytePos) -> BytePos {
+        BytePos(*self - **other)
+    }
+    pure fn mul(other: &BytePos) -> BytePos {
+        BytePos(*self * (**other))
+    }
+    pure fn div(other: &BytePos) -> BytePos {
+        BytePos(*self / **other)
+    }
+    pure fn modulo(other: &BytePos) -> BytePos {
+        BytePos(*self % **other)
+    }
+    pure fn neg() -> BytePos {
+        BytePos(-*self)
+    }
+    pure fn to_int() -> int { *self as int }
+    static pure fn from_int(+n: int) -> BytePos { BytePos(n as uint) }
+}
+
+impl BytePos: to_bytes::IterBytes {
+    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
+        (*self).iter_bytes(lsb0, f)
+    }
+}
+
+impl CharPos: Pos {
+    static pure fn from_uint(n: uint) -> CharPos { CharPos(n) }
+    pure fn to_uint(&self) -> uint { **self }
+}
+
+impl CharPos: cmp::Eq {
+    pure fn eq(other: &CharPos) -> bool {
+        *self == **other
+    }
+    pure fn ne(other: &CharPos) -> bool { !self.eq(other) }
+}
+
+impl CharPos: cmp::Ord {
+    pure fn lt(other: &CharPos) -> bool { *self < **other }
+    pure fn le(other: &CharPos) -> bool { *self <= **other }
+    pure fn ge(other: &CharPos) -> bool { *self >= **other }
+    pure fn gt(other: &CharPos) -> bool { *self > **other }
+}
+
+impl CharPos: Num {
+    pure fn add(other: &CharPos) -> CharPos {
+        CharPos(*self + **other)
+    }
+    pure fn sub(other: &CharPos) -> CharPos {
+        CharPos(*self - **other)
+    }
+    pure fn mul(other: &CharPos) -> CharPos {
+        CharPos(*self * (**other))
+    }
+    pure fn div(other: &CharPos) -> CharPos {
+        CharPos(*self / **other)
+    }
+    pure fn modulo(other: &CharPos) -> CharPos {
+        CharPos(*self % **other)
+    }
+    pure fn neg() -> CharPos {
+        CharPos(-*self)
+    }
+    pure fn to_int() -> int { *self as int }
+    static pure fn from_int(+n: int) -> CharPos { CharPos(n as uint) }
+}
+
+impl CharPos: to_bytes::IterBytes {
+    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
+        (*self).iter_bytes(lsb0, f)
+    }
+}
 
 pub struct span {
     lo: CharPos,
@@ -37,8 +138,8 @@ impl<D: Deserializer> span: Deserializable<D> {
     }
 }
 
-pub struct Loc {
-    file: @FileMap, line: uint, col: uint
+pub struct Loc<A: Pos> {
+    file: @FileMap, line: uint, col: A
 }
 
 pub struct FilePos {
@@ -69,7 +170,7 @@ pub struct FileLines {
 pub enum FileSubstr {
     pub FssNone,
     pub FssInternal(span),
-    pub FssExternal({filename: ~str, line: uint, col: uint})
+    pub FssExternal({filename: ~str, line: uint, col: CharPos})
 }
 
 pub struct FileMap {
@@ -83,7 +184,7 @@ pub struct FileMap {
 pub impl FileMap {
     static fn new_w_substr(+filename: FileName, +substr: FileSubstr,
                            src: @~str,
-                           start_pos_ch: uint, start_pos_byte: uint)
+                           +start_pos_ch: CharPos, +start_pos_byte: BytePos)
         -> FileMap {
         return FileMap {
             name: filename, substr: substr, src: src,
@@ -93,18 +194,22 @@ pub impl FileMap {
     }
 
     static fn new(+filename: FileName, src: @~str,
-                  start_pos_ch: CharPos, start_pos_byte: BytePos)
+                  +start_pos_ch: CharPos, +start_pos_byte: BytePos)
         -> FileMap {
         return FileMap::new_w_substr(filename, FssNone, src,
                                      start_pos_ch, start_pos_byte);
     }
 
-    fn next_line(@self, chpos: CharPos, byte_pos: BytePos) {
-        self.lines.push(FilePos {ch: chpos, byte: byte_pos + self.start_pos.byte});
+    fn next_line(@self, +chpos: CharPos, +byte_pos: BytePos) {
+        self.lines.push(FilePos {
+            ch: chpos,
+            byte: byte_pos + self.start_pos.byte
+        });
     }
 
     pub fn get_line(@self, line: int) -> ~str unsafe {
-        let begin: uint = self.lines[line].byte - self.start_pos.byte;
+        let begin: BytePos = self.lines[line].byte - self.start_pos.byte;
+        let begin = begin.to_uint();
         let end = match str::find_char_from(*self.src, '\n', begin) {
             Some(e) => e,
             None => str::len(*self.src)
@@ -127,21 +232,22 @@ pub impl CodeMap {
 
     pub fn mk_substr_filename(@self, sp: span) -> ~str {
         let pos = self.lookup_char_pos(sp.lo);
-        return fmt!("<%s:%u:%u>", pos.file.name, pos.line, pos.col);
+        return fmt!("<%s:%u:%u>", pos.file.name,
+                    pos.line, pos.col.to_uint());
     }
 
-    pub fn lookup_char_pos(@self, pos: CharPos) -> Loc {
-        pure fn lookup(pos: FilePos) -> uint { return pos.ch; }
+    pub fn lookup_char_pos(@self, +pos: CharPos) -> Loc<CharPos> {
+        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
         return self.lookup_pos(pos, lookup);
     }
 
-    pub fn lookup_byte_pos(@self, pos: BytePos) -> Loc {
-        pure fn lookup(pos: FilePos) -> uint { return pos.byte; }
+    pub fn lookup_byte_pos(@self, +pos: BytePos) -> Loc<BytePos> {
+        pure fn lookup(pos: FilePos) -> uint { return pos.byte.to_uint(); }
         return self.lookup_pos(pos, lookup);
     }
 
-    pub fn lookup_char_pos_adj(@self, pos: CharPos)
-        -> {filename: ~str, line: uint, col: uint, file: Option<@FileMap>}
+    pub fn lookup_char_pos_adj(@self, +pos: CharPos)
+        -> {filename: ~str, line: uint, col: CharPos, file: Option<@FileMap>}
     {
         let loc = self.lookup_char_pos(pos);
         match (loc.file.substr) {
@@ -152,7 +258,8 @@ pub impl CodeMap {
                  file: Some(loc.file)}
             }
             FssInternal(sp) => {
-                self.lookup_char_pos_adj(sp.lo + (pos - loc.file.start_pos.ch))
+                self.lookup_char_pos_adj(
+                    sp.lo + (pos - loc.file.start_pos.ch))
             }
             FssExternal(eloc) => {
                 {filename: /* FIXME (#2543) */ copy eloc.filename,
@@ -164,14 +271,17 @@ pub impl CodeMap {
     }
 
     pub fn adjust_span(@self, sp: span) -> span {
-        pure fn lookup(pos: FilePos) -> uint { return pos.ch; }
+        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
         let line = self.lookup_line(sp.lo, lookup);
         match (line.fm.substr) {
             FssNone => sp,
             FssInternal(s) => {
-                self.adjust_span(span {lo: s.lo + (sp.lo - line.fm.start_pos.ch),
-                                       hi: s.lo + (sp.hi - line.fm.start_pos.ch),
-                                       expn_info: sp.expn_info})}
+                self.adjust_span(span {
+                    lo: s.lo + (sp.lo - line.fm.start_pos.ch),
+                    hi: s.lo + (sp.hi - line.fm.start_pos.ch),
+                    expn_info: sp.expn_info
+                })
+            }
             FssExternal(_) => sp
         }
     }
@@ -180,7 +290,7 @@ pub impl CodeMap {
         let lo = self.lookup_char_pos_adj(sp.lo);
         let hi = self.lookup_char_pos_adj(sp.hi);
         return fmt!("%s:%u:%u: %u:%u", lo.filename,
-                    lo.line, lo.col, hi.line, hi.col)
+                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
     }
 
     pub fn span_to_filename(@self, sp: span) -> FileName {
@@ -198,21 +308,24 @@ pub impl CodeMap {
         return @FileLines {file: lo.file, lines: lines};
     }
 
-    fn lookup_byte_offset(@self, chpos: CharPos)
+    fn lookup_byte_offset(@self, +chpos: CharPos)
         -> {fm: @FileMap, pos: BytePos} {
-        pure fn lookup(pos: FilePos) -> uint { return pos.ch; }
+        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
         let {fm, line} = self.lookup_line(chpos, lookup);
         let line_offset = fm.lines[line].byte - fm.start_pos.byte;
         let col = chpos - fm.lines[line].ch;
-        let col_offset = str::count_bytes(*fm.src, line_offset, col);
-        {fm: fm, pos: line_offset + col_offset}
+        let col_offset = str::count_bytes(*fm.src,
+                                          line_offset.to_uint(),
+                                          col.to_uint());
+        {fm: fm, pos: line_offset + BytePos(col_offset)}
     }
 
     pub fn span_to_snippet(@self, sp: span) -> ~str {
         let begin = self.lookup_byte_offset(sp.lo);
         let end = self.lookup_byte_offset(sp.hi);
         assert begin.fm.start_pos == end.fm.start_pos;
-        return str::slice(*begin.fm.src, begin.pos, end.pos);
+        return str::slice(*begin.fm.src,
+                          begin.pos.to_uint(), end.pos.to_uint());
     }
 
     pub fn get_filemap(@self, filename: ~str) -> @FileMap {
@@ -225,7 +338,7 @@ pub impl CodeMap {
 }
 
 priv impl CodeMap {
-    fn lookup_line(@self, pos: uint, lookup: LookupFn)
+    fn lookup_line<A: Pos>(@self, pos: A, lookup: LookupFn)
         -> {fm: @FileMap, line: uint}
     {
         let len = self.files.len();
@@ -233,31 +346,40 @@ priv impl CodeMap {
         let mut b = len;
         while b - a > 1u {
             let m = (a + b) / 2u;
-            if lookup(self.files[m].start_pos) > pos { b = m; } else { a = m; }
+            if lookup(self.files[m].start_pos) > pos.to_uint() {
+                b = m;
+            } else {
+                a = m;
+            }
         }
         if (a >= len) {
-            fail fmt!("position %u does not resolve to a source location", pos)
+            fail fmt!("position %u does not resolve to a source location",
+                      pos.to_uint())
         }
         let f = self.files[a];
         a = 0u;
         b = vec::len(f.lines);
         while b - a > 1u {
             let m = (a + b) / 2u;
-            if lookup(f.lines[m]) > pos { b = m; } else { a = m; }
+            if lookup(f.lines[m]) > pos.to_uint() { b = m; } else { a = m; }
         }
         return {fm: f, line: a};
     }
 
-    fn lookup_pos(@self, pos: uint, lookup: LookupFn) -> Loc {
+    fn lookup_pos<A: Pos Num>(@self, pos: A, lookup: LookupFn) -> Loc<A> {
         let {fm: f, line: a} = self.lookup_line(pos, lookup);
-        return Loc {file: f, line: a + 1u, col: pos - lookup(f.lines[a])};
+        return Loc {
+            file: f,
+            line: a + 1u,
+            col: pos - from_uint(lookup(f.lines[a]))
+        };
     }
 
     fn span_to_str_no_adj(@self, sp: span) -> ~str {
         let lo = self.lookup_char_pos(sp.lo);
         let hi = self.lookup_char_pos(sp.hi);
         return fmt!("%s:%u:%u: %u:%u", lo.file.name,
-                    lo.line, lo.col, hi.line, hi.col)
+                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
     }
 }