use std::ops::Deref; #[derive(Debug)] pub struct WithLocation { pub value: T, pub start: usize, pub end: usize, } impl WithLocation { pub fn new(value: T, start: usize, end: usize) -> WithLocation { WithLocation { value: value, start: start, end: end, } } pub fn map U>(self, f: F) -> WithLocation { WithLocation { value: f(self.value), start: self.start, end: self.end, } } pub fn join_map(self, other: WithLocation, f: F) -> WithLocation where F: FnOnce(WithLocation, WithLocation) -> V { let start = self.start; let end = other.end; WithLocation { value: f(self, other), start: start, end: end, } } } impl Deref for WithLocation { type Target = T; fn deref(&self) -> &Self::Target { &self.value } } #[derive(Debug)] pub struct Program(pub Box>); #[derive(Debug)] pub enum UnaryOp { Pos, Neg, Not, } #[derive(Debug)] pub enum BinOp { Add, Sub, Mul, Div, FloorDiv, Eq, Neq, Gt, Lt, Ge, Le, And, Or, } #[derive(Debug)] pub enum Expression { Let(Vec>, Box>), UnaryOp(UnaryOp, Box>), BinOp(BinOp, Box>, Box>), Number(u64), String(String), Name(String), Nil, } #[derive(Debug)] pub struct RecordField { name: WithLocation, ty: WithLocation, } impl RecordField { pub fn new(name: WithLocation, ty: WithLocation) -> RecordField { RecordField { name, ty } } } #[derive(Debug)] pub enum Ty { Name(String), Array(Box), Record(Vec>), } #[derive(Debug)] pub struct Declaration { pub name: WithLocation, pub declaration: DeclarationBody, } #[derive(Debug)] pub enum DeclarationBody { Var { ty: Option>, value: Box>, }, Ty { ty: WithLocation, }, Fun { ty: Box>, }, } impl Declaration { pub fn new_var(name: WithLocation, type_: Option>, value: Box>) -> Declaration { Declaration { name: name, declaration: DeclarationBody::Var { ty: type_, value: value, } } } pub fn new_ty(name: WithLocation, type_: WithLocation) -> Declaration { Declaration { name: name, declaration: DeclarationBody::Ty { ty: type_, } } } }