use std::fmt;
#[derive(Debug, Clone, PartialEq)]
pub struct Model {
pub items: Vec<Item>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Item {
EnumDef(EnumDef),
VarDecl(VarDecl),
Constraint(Constraint),
Solve(Solve),
Output(Output),
Include { filename: String, span: Span },
}
#[derive(Debug, Clone, PartialEq)]
pub struct EnumDef {
pub name: String,
pub values: Vec<String>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct VarDecl {
pub type_inst: TypeInst,
pub name: String,
pub expr: Option<Expr>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub enum TypeInst {
Basic {
is_var: bool,
base_type: BaseType,
},
Constrained {
is_var: bool,
base_type: BaseType,
domain: Expr,
},
Array {
index_sets: Vec<Expr>,
element_type: Box<TypeInst>,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BaseType {
Bool,
Int,
Float,
Enum(String),
}
#[derive(Debug, Clone, PartialEq)]
pub struct Constraint {
pub expr: Expr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SearchOption {
Complete,
Incomplete,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Solve {
Satisfy { search_option: Option<SearchOption>, span: Span },
Minimize { expr: Expr, search_option: Option<SearchOption>, span: Span },
Maximize { expr: Expr, search_option: Option<SearchOption>, span: Span },
}
#[derive(Debug, Clone, PartialEq)]
pub struct Output {
pub expr: Expr,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Expr {
pub kind: ExprKind,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ExprKind {
Ident(String),
BoolLit(bool),
IntLit(i64),
FloatLit(f64),
StringLit(String),
ArrayLit(Vec<Expr>),
SetLit(Vec<Expr>),
Range(Box<Expr>, Box<Expr>),
ArrayAccess {
array: Box<Expr>,
indices: Vec<Expr>,
},
BinOp {
op: BinOp,
left: Box<Expr>,
right: Box<Expr>,
},
UnOp {
op: UnOp,
expr: Box<Expr>,
},
Call {
name: String,
args: Vec<Expr>,
},
IfThenElse {
cond: Box<Expr>,
then_expr: Box<Expr>,
else_expr: Option<Box<Expr>>,
},
ArrayComp {
expr: Box<Expr>,
generators: Vec<Generator>,
},
GenCall {
name: String,
generators: Vec<Generator>,
body: Box<Expr>,
},
Array2D {
row_range: Box<Expr>,
col_range: Box<Expr>,
values: Box<Expr>, },
Array3D {
r1_range: Box<Expr>,
r2_range: Box<Expr>,
r3_range: Box<Expr>,
values: Box<Expr>, },
ImplicitIndexSet(BaseType),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinOp {
Add, Sub, Mul, Div, Mod, FDiv,
Lt, Le, Gt, Ge, Eq, Ne,
And, Or, Impl, Iff, Xor,
In, Range,
Concat, }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnOp {
Neg, Not, }
#[derive(Debug, Clone, PartialEq)]
pub struct Generator {
pub names: Vec<String>,
pub expr: Expr,
pub where_clause: Option<Expr>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Span {
pub start: usize,
pub end: usize,
}
impl Span {
pub fn new(start: usize, end: usize) -> Self {
Self { start, end }
}
pub fn dummy() -> Self {
Self { start: 0, end: 0 }
}
}
impl fmt::Display for BinOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
BinOp::Add => "+",
BinOp::Sub => "-",
BinOp::Mul => "*",
BinOp::Div => "div",
BinOp::Mod => "mod",
BinOp::FDiv => "/",
BinOp::Lt => "<",
BinOp::Le => "<=",
BinOp::Gt => ">",
BinOp::Ge => ">=",
BinOp::Eq => "==",
BinOp::Ne => "!=",
BinOp::And => "/\\",
BinOp::Or => "\\/",
BinOp::Impl => "->",
BinOp::Iff => "<->",
BinOp::Xor => "xor",
BinOp::In => "in",
BinOp::Range => "..",
BinOp::Concat => "++",
};
write!(f, "{}", s)
}
}
impl fmt::Display for UnOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
UnOp::Neg => "-",
UnOp::Not => "not",
};
write!(f, "{}", s)
}
}
impl fmt::Display for BaseType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
BaseType::Bool => "bool".to_string(),
BaseType::Int => "int".to_string(),
BaseType::Float => "float".to_string(),
BaseType::Enum(name) => name.clone(),
};
write!(f, "{}", s)
}
}