325 lines
6.9 KiB
Rust
325 lines
6.9 KiB
Rust
//! Ast definition for Ayin.
|
|
|
|
use std::collections::BTreeMap;
|
|
|
|
/// A Program.
|
|
#[derive(PartialEq, PartialOrd, Debug, Clone)]
|
|
pub struct Program {
|
|
pub includes: Vec<File>,
|
|
pub defs: Vec<Definition>,
|
|
}
|
|
|
|
#[derive(PartialEq, Eq, Hash, PartialOrd, Debug, Clone)]
|
|
pub struct File(pub String);
|
|
|
|
#[derive(PartialEq, PartialOrd, Debug, Clone)]
|
|
pub struct Definition {
|
|
pub mutable: bool,
|
|
pub name: Name,
|
|
pub expr: Expr,
|
|
}
|
|
|
|
/// An expression.
|
|
#[derive(PartialEq, PartialOrd, Debug, Clone)]
|
|
pub enum Expr {
|
|
Not(Box<Expr>),
|
|
Op {
|
|
lhs: Box<Expr>,
|
|
op: Op,
|
|
rhs: Box<Expr>,
|
|
},
|
|
Value(Value),
|
|
Var(Name),
|
|
Func(Box<Fn>),
|
|
FunCall {
|
|
func: Box<Expr>,
|
|
args: Vec<Expr>,
|
|
},
|
|
Block(Vec<Statement>),
|
|
If {
|
|
condition: Box<Expr>,
|
|
then: Box<Expr>,
|
|
r#else: Box<Expr>,
|
|
},
|
|
Access {
|
|
expr: Box<Expr>,
|
|
field: Label,
|
|
},
|
|
Record(BTreeMap<Label, Expr>),
|
|
Vector(Vec<Expr>),
|
|
}
|
|
|
|
#[derive(PartialEq, PartialOrd, Debug, Clone)]
|
|
pub enum Op {
|
|
Assign,
|
|
Compare(Cmp),
|
|
Calc(Calc),
|
|
Bool(BoolOp),
|
|
}
|
|
|
|
#[derive(PartialEq, PartialOrd, Debug, Clone)]
|
|
pub enum BoolOp {
|
|
And,
|
|
Or,
|
|
}
|
|
|
|
#[derive(PartialEq, PartialOrd, Debug, Clone)]
|
|
pub enum Cmp {
|
|
Eq,
|
|
NotEq,
|
|
Gt,
|
|
Lt,
|
|
Gte,
|
|
Lte,
|
|
}
|
|
|
|
#[derive(PartialEq, PartialOrd, Debug, Clone)]
|
|
pub enum Calc {
|
|
Add,
|
|
Sub,
|
|
Div,
|
|
Mul,
|
|
Mod,
|
|
BinAnd,
|
|
BinOr,
|
|
}
|
|
|
|
/// A statement.
|
|
#[derive(PartialEq, PartialOrd, Debug, Clone)]
|
|
pub enum Statement {
|
|
Expr(Expr),
|
|
Let(Definition),
|
|
Return(Option<Expr>),
|
|
Loop(Box<Expr>),
|
|
Break,
|
|
}
|
|
|
|
/// A reduced value.
|
|
#[derive(PartialEq, PartialOrd, Debug, Clone)]
|
|
pub enum Value {
|
|
Int(i32),
|
|
Float(f32),
|
|
String(String),
|
|
Boolean(bool),
|
|
Record(Record),
|
|
Vector(Vector),
|
|
Label(Label),
|
|
Ref(Ref),
|
|
Closure { env: EnvName, expr: Box<Expr> },
|
|
PrimitiveFunc(Name),
|
|
Return(Box<Value>),
|
|
Break,
|
|
}
|
|
|
|
/// A mutable variable.
|
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
|
|
pub struct Ref(pub u64);
|
|
|
|
/// An anonymous function.
|
|
#[derive(PartialEq, PartialOrd, Debug, Clone)]
|
|
pub struct Fn {
|
|
pub args: Vec<Arg>,
|
|
pub body: Expr,
|
|
}
|
|
|
|
/// A function argument.
|
|
#[derive(PartialEq, PartialOrd, Debug, Clone)]
|
|
pub struct Arg {
|
|
pub name: Name,
|
|
}
|
|
|
|
/// A symbol.
|
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
|
|
pub struct Name(pub String);
|
|
|
|
/// A field.
|
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
|
|
pub struct Label(pub String);
|
|
|
|
/// A reference to the environment.
|
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
|
|
pub struct EnvName(pub String);
|
|
|
|
#[derive(PartialEq, PartialOrd, Debug, Clone)]
|
|
pub struct Record(pub BTreeMap<Label, Ref>);
|
|
|
|
#[derive(PartialEq, PartialOrd, Debug, Clone)]
|
|
pub struct Vector(pub Vec<Ref>);
|
|
|
|
// ----- //
|
|
// Impls //
|
|
// ----- //
|
|
|
|
impl From<&str> for Name {
|
|
fn from(value: &str) -> Name {
|
|
Name(value.into())
|
|
}
|
|
}
|
|
|
|
impl From<&str> for Label {
|
|
fn from(value: &str) -> Label {
|
|
Label(value.into())
|
|
}
|
|
}
|
|
|
|
impl From<&str> for Expr {
|
|
fn from(value: &str) -> Expr {
|
|
Expr::Var(value.into())
|
|
}
|
|
}
|
|
|
|
impl From<Vec<(&str, Expr)>> for Expr {
|
|
fn from(rec: Vec<(&str, Expr)>) -> Expr {
|
|
Expr::Record(
|
|
rec.into_iter()
|
|
.map(|(lbl, expr)| (Label(lbl.into()), expr))
|
|
.collect(),
|
|
)
|
|
}
|
|
}
|
|
|
|
impl Expr {
|
|
pub fn field(self, label: &str) -> Expr {
|
|
Expr::Access {
|
|
expr: Box::new(self),
|
|
field: label.into(),
|
|
}
|
|
}
|
|
pub fn call(self, args: Vec<Expr>) -> Expr {
|
|
Expr::FunCall {
|
|
func: Box::new(self),
|
|
args,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<i32> for Value {
|
|
fn from(i: i32) -> Value {
|
|
Value::Int(i)
|
|
}
|
|
}
|
|
|
|
impl From<i32> for Expr {
|
|
fn from(i: i32) -> Expr {
|
|
Expr::Value(i.into())
|
|
}
|
|
}
|
|
|
|
impl From<f32> for Value {
|
|
fn from(f: f32) -> Value {
|
|
Value::Float(f)
|
|
}
|
|
}
|
|
|
|
impl From<f32> for Expr {
|
|
fn from(f: f32) -> Expr {
|
|
Expr::Value(f.into())
|
|
}
|
|
}
|
|
|
|
impl From<bool> for Value {
|
|
fn from(b: bool) -> Value {
|
|
Value::Boolean(b)
|
|
}
|
|
}
|
|
|
|
impl From<bool> for Expr {
|
|
fn from(b: bool) -> Expr {
|
|
Expr::Value(b.into())
|
|
}
|
|
}
|
|
|
|
impl From<Vec<Definition>> for Program {
|
|
fn from(defs: Vec<Definition>) -> Program {
|
|
Program {
|
|
defs,
|
|
includes: vec![],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<Vec<Statement>> for Expr {
|
|
fn from(stmts: Vec<Statement>) -> Expr {
|
|
Expr::Block(stmts)
|
|
}
|
|
}
|
|
|
|
impl Record {
|
|
pub fn get(&self, label: &Label) -> Result<&Ref, Error> {
|
|
match self.0.get(label) {
|
|
Some(v) => Ok(v),
|
|
None => Err(Error::LabelNotFound(label.clone())),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Vector {
|
|
pub fn get(&self, index: usize) -> Result<&Ref, Error> {
|
|
match self.0.get(index) {
|
|
Some(v) => Ok(v),
|
|
None => Err(Error::IndexOutOfBounds(index)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for Expr {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
let mut string = "".to_string();
|
|
match self {
|
|
Expr::Value(value) => match value {
|
|
Value::Int(i) => string.push_str(&format!("{i}")),
|
|
Value::Float(f) => string.push_str(&format!("{f:2}")),
|
|
Value::String(s) => string.push_str(&format!("{s:?}")),
|
|
Value::Boolean(b) => string.push_str(&format!("{b}")),
|
|
Value::Closure { .. } => string.push_str("<fn>"),
|
|
_ => {}
|
|
},
|
|
Expr::Func(_) => string.push_str("<fn>"),
|
|
Expr::Record(map) => {
|
|
string.push_str("{");
|
|
for (key, val) in map {
|
|
string.push_str(&format!(" .{}: {},", key.0, val));
|
|
}
|
|
if map.len() > 0 {
|
|
string.push_str(" }");
|
|
} else {
|
|
string.push_str("}");
|
|
}
|
|
}
|
|
Expr::Vector(vec) => {
|
|
string.push_str("[");
|
|
for val in vec {
|
|
string.push_str(&format!(" {},", val));
|
|
}
|
|
if vec.len() > 0 {
|
|
string.push_str(" ]");
|
|
} else {
|
|
string.push_str("]");
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
f.write_str(&string)
|
|
}
|
|
}
|
|
|
|
pub const UNIT_VALUE: Value = Value::Record(Record(BTreeMap::new()));
|
|
pub const UNIT: Expr = Expr::Value(UNIT_VALUE);
|
|
|
|
pub enum Error {
|
|
LabelNotFound(Label),
|
|
IndexOutOfBounds(usize),
|
|
}
|
|
|
|
impl std::fmt::Display for Error {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Error::LabelNotFound(a) => {
|
|
write!(f, "Label not found: {a:?}")
|
|
}
|
|
Error::IndexOutOfBounds(a) => {
|
|
write!(f, "Indexout of bounds: {a:?}")
|
|
}
|
|
}
|
|
}
|
|
}
|