#[derive(Debug)]
pub struct Statement {
pub t: StatementType,
pub start: usize,
pub end: usize,
}
#[derive(Debug)]
pub enum StatementType {
Use(String),
Definition(String, Definition),
Pool(Rpn),
Expression(Rpn),
Declaration(String, String),
PointerDeclaration(String, String),
DeclareAssign(String, String, Rpn),
PointerDeclareAssign(String, String, Rpn),
If(Rpn, Vec<Statement>, Option<Vec<Statement>>),
While(Rpn, Vec<Statement>),
Do(Rpn, Vec<Statement>),
For(Box<Statement>, Rpn, Box<Statement>, Vec<Statement>),
Repeat(Rpn, Vec<Statement>),
Loop(Vec<Statement>),
}
#[derive(Debug)]
pub enum Root {
Environment(String, Environment),
Function(String, Function),
Assembly(String),
Include(String),
Typedef {
name: String,
t: String,
},
Struct {
name: String,
contents: Vec<StructMember>,
},
}
#[derive(Debug)]
pub struct Environment {
pub contents: Vec<Statement>,
}
#[derive(Debug)]
pub struct Function {
pub environment: String,
pub contents: Vec<Statement>,
pub start: usize,
pub end: usize,
}
#[derive(Debug)]
pub struct StructMember {
pub name: String,
pub t: String,
}
#[derive(Debug, Clone)]
pub enum Definition {
Def(Def),
Alias(Alias),
Macro(Macro),
}
#[derive(Debug, Clone)]
pub struct Def {
pub bytecode: u8,
pub args: Vec<DefinitionParam>,
}
#[derive(Debug, Clone)]
pub struct Macro {
pub args: Vec<DefinitionParam>,
pub target: String,
}
#[derive(Debug, Clone)]
pub struct Alias {
pub args: Vec<DefinitionParam>,
pub target: String,
pub target_args: Vec<AliasParam>,
}
#[derive(Debug, Clone)]
pub enum DefinitionParam {
Return(String),
Const(String),
Type(String),
}
#[derive(Debug, Clone)]
pub enum AliasParam {
ArgId(usize),
Expression(Rpn),
Const(Rpn),
}
#[derive(Debug, Clone)]
pub enum Rpn {
Variable(String),
Signed(i64),
String(String),
Call(String, Vec<Rpn>),
Negate(Box<Rpn>),
Deref(Box<Rpn>),
Not(Box<Rpn>),
Address(String),
Mul(Box<Rpn>, Box<Rpn>),
Div(Box<Rpn>, Box<Rpn>),
Mod(Box<Rpn>, Box<Rpn>),
Add(Box<Rpn>, Box<Rpn>),
Sub(Box<Rpn>, Box<Rpn>),
ShiftLeft(Box<Rpn>, Box<Rpn>),
ShiftRight(Box<Rpn>, Box<Rpn>),
BinaryAnd(Box<Rpn>, Box<Rpn>),
BinaryXor(Box<Rpn>, Box<Rpn>),
BinaryOr(Box<Rpn>, Box<Rpn>),
Equ(Box<Rpn>, Box<Rpn>),
NotEqu(Box<Rpn>, Box<Rpn>),
LessThan(Box<Rpn>, Box<Rpn>),
GreaterThan(Box<Rpn>, Box<Rpn>),
LessThanEqu(Box<Rpn>, Box<Rpn>),
GreaterThanEqu(Box<Rpn>, Box<Rpn>),
LogicalAnd(Box<Rpn>, Box<Rpn>),
LogicalOr(Box<Rpn>, Box<Rpn>),
Set(String, Box<Rpn>),
}
impl Rpn {
pub fn eval_const(&self) -> Result<i64, String> {
Ok(match self {
Rpn::Variable(..) => {
return Err("Unexpected variable, expression must be constant".to_string())
}
Rpn::String(..) => {
return Err("Unexpected string, expression must be constant".to_string())
}
Rpn::Call(..) => return Err("Unexpected call, expression must be constant".to_string()),
Rpn::Deref(..) => {
return Err("Unexpected dereference, expression must be constant".to_string())
}
Rpn::Address(..) => {
return Err("Unexpected address operator, expression must be constant".to_string())
}
Rpn::Set(..) => {
return Err("Unexpected assignment, expression must be constant".to_string())
}
Rpn::Signed(value) => *value,
Rpn::Negate(i) => i.eval_const()?,
Rpn::Not(i) => i.eval_const()?,
Rpn::Mul(l, r) => l.eval_const()? * r.eval_const()?,
Rpn::Div(l, r) => l.eval_const()? / r.eval_const()?,
Rpn::Mod(l, r) => l.eval_const()? % r.eval_const()?,
Rpn::Add(l, r) => l.eval_const()? + r.eval_const()?,
Rpn::Sub(l, r) => l.eval_const()? - r.eval_const()?,
Rpn::ShiftLeft(l, r) => l.eval_const()? << r.eval_const()?,
Rpn::ShiftRight(l, r) => l.eval_const()? >> r.eval_const()?,
Rpn::BinaryAnd(l, r) => l.eval_const()? & r.eval_const()?,
Rpn::BinaryXor(l, r) => l.eval_const()? ^ r.eval_const()?,
Rpn::BinaryOr(l, r) => l.eval_const()? | r.eval_const()?,
Rpn::Equ(l, r) => (l.eval_const()? == r.eval_const()?) as i64,
Rpn::NotEqu(l, r) => (l.eval_const()? != r.eval_const()?) as i64,
Rpn::LessThan(l, r) => (l.eval_const()? < r.eval_const()?) as i64,
Rpn::GreaterThan(l, r) => (l.eval_const()? > r.eval_const()?) as i64,
Rpn::LessThanEqu(l, r) => (l.eval_const()? <= r.eval_const()?) as i64,
Rpn::GreaterThanEqu(l, r) => (l.eval_const()? >= r.eval_const()?) as i64,
Rpn::LogicalAnd(l, r) => (l.eval_const()? != 0 && r.eval_const()? != 0) as i64,
Rpn::LogicalOr(l, r) => (l.eval_const()? != 0 || r.eval_const()? != 0) as i64,
})
}
}