///|
pub(all) struct Position {
fname : String
lnum : Int
bol : Int
cnum : Int
} derive(Debug, Hash, ToJson)
///|
pub impl Show for Position with fn output(self, logger) {
logger.write_char('"')
if self.fname != "" {
logger..write_string(self.fname).write_char(':')
}
logger
..write_string(self.lnum.to_string())
..write_char(':')
..write_string(self.column().to_string())
.write_char('"')
}
///|
pub impl Eq for Position with fn equal(self, other) {
self.fname == other.fname && self.cnum == other.cnum
}
///|
pub impl Compare for Position with fn compare(self, other) {
match self.fname.compare(other.fname) {
0 =>
match self.lnum.compare(other.lnum) {
0 => self.column().compare(other.column())
r => r
}
r => r
}
}
///|
test "compre position" {
let a = { fname: "", lnum: 10, bol: 0, cnum: 0 }
let b = { fname: "", lnum: 10, bol: 0, cnum: 0 }
assert_eq(a.compare(b), 0)
let a = { fname: "", lnum: 10, bol: 0, cnum: 0 }
let b = { fname: "", lnum: 1, bol: 0, cnum: 0 }
assert_eq(a.compare(b), 1)
assert_eq(b.compare(a), -1)
let a = { fname: "", lnum: 10, bol: 2, cnum: 5 }
let b = { fname: "", lnum: 10, bol: 2, cnum: 5 }
assert_eq(a.compare(b), 0)
let a = { fname: "", lnum: 10, bol: 2, cnum: 5 }
let b = { fname: "", lnum: 10, bol: 2, cnum: 10 }
assert_eq(a.compare(b), -1)
assert_eq(b.compare(a), 1)
}
///|
pub fn Position::column(self : Position) -> Int {
self.cnum - self.bol + 1
}
///|
pub(all) struct Location {
start : Position
end : Position
} derive(Eq, Compare, Hash, Debug)
///|
pub(all) struct BasePos {
base_pkg : String
base_fname : String
base_lnum : Int
} derive(Eq, Compare, Hash, Debug)
///|
pub fn BasePos::none() -> BasePos {
{ base_pkg: "", base_fname: "", base_lnum: -1 }
}
///|
pub fn BasePos::from_position(pkg~ : String, pos : Position) -> BasePos {
{ base_pkg: pkg, base_fname: pos.fname, base_lnum: pos.lnum }
}
///|
pub fn Location::trim_first_char(self : Location) -> Location {
{
start: {
fname: self.start.fname,
lnum: self.start.lnum,
bol: self.start.bol,
cnum: self.start.cnum + 1,
},
end: self.end,
}
}
///|
pub fn Location::trim_last_char(self : Location) -> Location {
{
start: self.start,
end: {
fname: self.end.fname,
lnum: self.end.lnum,
bol: self.end.bol,
cnum: self.end.cnum - 1,
},
}
}
///|
pub impl Show for Location with fn output(self, buf) {
buf
..write_string(self.start.fname)
..write_string("-")
..write_string(self.start.lnum.to_string())
..write_string(":")
..write_string(self.start.column().to_string())
..write_string("-")
..write_string(self.end.lnum.to_string())
..write_string(":")
.write_string(self.end.column().to_string())
}
///|
pub impl ToJson for Location with fn to_json(loc) {
match show_loc.val {
Hidden => Json::null()
Json =>
{
"file": loc.start.fname,
"start": { "line": loc.start.lnum, "column": loc.start.column() },
"end": { "line": loc.end.lnum, "column": loc.end.column() },
}
String => {
let str = "\{loc.start.lnum}:\{loc.start.column()}-\{loc.end.lnum}:\{loc.end.column()}"
Json::string(str)
}
}
}
///|
pub fn Location::merge(self : Location, other : Location) -> Location {
guard! self.start.fname == other.start.fname
let start = if self.start < other.start { self.start } else { other.start }
let end = if self.end > other.end { self.end } else { other.end }
{ start, end }
}