Compare commits

...

2 Commits

Author SHA1 Message Date
69ccf679e7 WIP bc I forgot what I was doing 2024-11-04 10:07:12 -06:00
5436a706d7 Get/Set variables from the environment 2022-06-01 16:35:35 -05:00
2 changed files with 43 additions and 10 deletions

View File

@ -1,7 +1,7 @@
use std::ops; use std::ops;
use std::collections::HashMap; use std::collections::HashMap;
use crate::parser; use crate::parser::{self, GuardedBlock};
use parser::Atom; use parser::Atom;
pub struct Env<'a> { pub struct Env<'a> {
@ -31,12 +31,41 @@ impl<'a> Env<'a> {
panic!("Variable {} not in scope.", id) panic!("Variable {} not in scope.", id)
} }
} }
pub fn set(&mut self, id: String, atom: Atom) {
self.values.insert(id, atom);
}
} }
pub fn eval(ast: &parser::Stmt, env: &mut Env) { pub fn eval(ast: &parser::Stmt, env: &mut Env) {
match &ast { match &ast {
parser::Stmt::ReplPrint(expr) => parser::Stmt::ReplPrint(expr) =>
println!("{}", eval_expr(expr, env)), println!("{}", eval_expr(expr, env)),
parser::Stmt::Assignment(id, expr) =>
env.set(id.clone(), eval_expr(expr, env)),
parser::Stmt::Conditional(guarded_blocks, default_block) => {
let mut matched = false;
for GuardedBlock { guard, block } in guarded_blocks {
let res = eval_expr(&guard, env);
match res {
Atom::Bool(true) => {
matched = true;
for stmt in block {
eval(stmt, env);
}
break;
}
Atom::Bool(false) => continue,
_ => panic!("Conditional expression does not evaluate to a bool"),
}
}
if !matched {
if let Some(block) = default_block {
for expr in default_block {
eval_expr(expr, env);
}
}
}
}
_ => todo!(), _ => todo!(),
} }
} }

View File

@ -4,7 +4,7 @@ use std::fmt;
pub enum Stmt { pub enum Stmt {
Assignment(String, Expr), Assignment(String, Expr),
Funcall(Expr), Funcall(Expr),
Conditional(Vec<Expr>, Option<Expr>), Conditional(Vec<GuardedBlock>, Option<Expr>),
ReplPrint(Expr), ReplPrint(Expr),
} }
@ -20,7 +20,6 @@ pub enum Expr {
Mult(Box<Expr>, Box<Expr>), Mult(Box<Expr>, Box<Expr>),
Div(Box<Expr>, Box<Expr>), Div(Box<Expr>, Box<Expr>),
Block(Vec<Stmt>), Block(Vec<Stmt>),
GuardedBlock(Box<GuardedBlock>),
Object(Vec<Stmt>), Object(Vec<Stmt>),
} }
@ -28,6 +27,7 @@ pub enum Expr {
pub enum Atom { pub enum Atom {
String(String), String(String),
Num(f64), Num(f64),
Bool(bool),
} }
impl fmt::Display for Atom { impl fmt::Display for Atom {
@ -35,6 +35,7 @@ impl fmt::Display for Atom {
match self { match self {
Atom::String(a) => write!(f, "\"{}\"", a), Atom::String(a) => write!(f, "\"{}\"", a),
Atom::Num(a) => write!(f, "{}", a), Atom::Num(a) => write!(f, "{}", a),
Atom::Bool(a) => write!(f, "{}", a),
} }
} }
} }
@ -68,7 +69,8 @@ peg::parser! {
f:funcall() { f } f:funcall() { f }
f:funcdef() { f } f:funcdef() { f }
o:object() { o } o:object() { o }
i:id() _ { Expr::Id(i) } b:_bool() _ { Expr::Atom(Atom::Bool(b)) }
i:id() { Expr::Id(i) }
n:num() _ { Expr::Atom(Atom::Num(n)) } n:num() _ { Expr::Atom(Atom::Num(n)) }
} }
@ -79,6 +81,8 @@ peg::parser! {
= i:id() "<-" _ e:expr() stop() { Stmt::Assignment(i, e) } = i:id() "<-" _ e:expr() stop() { Stmt::Assignment(i, e) }
rule num() -> f64 rule num() -> f64
= n:$(digit()+ "."? digit()* / "." digit()+) _ { n.parse().unwrap() } = n:$(digit()+ "."? digit()* / "." digit()+) _ { n.parse().unwrap() }
rule _bool() -> bool
= "true" _ { true } / "false" _ { false }
rule funcall() -> Expr rule funcall() -> Expr
= i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Expr::Funcall(i, e) } = i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Expr::Funcall(i, e) }
rule funcdef() -> Expr rule funcdef() -> Expr
@ -88,19 +92,19 @@ peg::parser! {
rule object() -> Expr rule object() -> Expr
= "{" _ stop() indent() __* a:assignment()+ dedent() __* "}" _ { Expr::Object(a) } = "{" _ stop() indent() __* a:assignment()+ dedent() __* "}" _ { Expr::Object(a) }
rule _if() -> Expr rule _if() -> GuardedBlock
= "if" _ g:expr() b:indented_block() { = "if" _ g:expr() b:indented_block() {
Expr::GuardedBlock(Box::new(GuardedBlock { GuardedBlock {
guard: g, guard: g,
block: b, block: b,
}))
} }
rule elif() -> Expr }
rule elif() -> GuardedBlock
= "elif" _ g:expr() b:indented_block() { = "elif" _ g:expr() b:indented_block() {
Expr::GuardedBlock(Box::new(GuardedBlock { GuardedBlock {
guard: g, guard: g,
block: b block: b
})) }
} }
rule _else() -> Expr rule _else() -> Expr
= "else" _ b:block() { b } = "else" _ b:block() { b }