Compare commits
2 Commits
2a7db71ded
...
69ccf679e7
Author | SHA1 | Date | |
---|---|---|---|
69ccf679e7 | |||
5436a706d7 |
@ -1,7 +1,7 @@
|
||||
use std::ops;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::parser;
|
||||
use crate::parser::{self, GuardedBlock};
|
||||
use parser::Atom;
|
||||
|
||||
pub struct Env<'a> {
|
||||
@ -31,12 +31,41 @@ impl<'a> Env<'a> {
|
||||
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) {
|
||||
match &ast {
|
||||
parser::Stmt::ReplPrint(expr) =>
|
||||
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!(),
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use std::fmt;
|
||||
pub enum Stmt {
|
||||
Assignment(String, Expr),
|
||||
Funcall(Expr),
|
||||
Conditional(Vec<Expr>, Option<Expr>),
|
||||
Conditional(Vec<GuardedBlock>, Option<Expr>),
|
||||
ReplPrint(Expr),
|
||||
}
|
||||
|
||||
@ -20,7 +20,6 @@ pub enum Expr {
|
||||
Mult(Box<Expr>, Box<Expr>),
|
||||
Div(Box<Expr>, Box<Expr>),
|
||||
Block(Vec<Stmt>),
|
||||
GuardedBlock(Box<GuardedBlock>),
|
||||
Object(Vec<Stmt>),
|
||||
}
|
||||
|
||||
@ -28,6 +27,7 @@ pub enum Expr {
|
||||
pub enum Atom {
|
||||
String(String),
|
||||
Num(f64),
|
||||
Bool(bool),
|
||||
}
|
||||
|
||||
impl fmt::Display for Atom {
|
||||
@ -35,6 +35,7 @@ impl fmt::Display for Atom {
|
||||
match self {
|
||||
Atom::String(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:funcdef() { f }
|
||||
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)) }
|
||||
|
||||
}
|
||||
@ -79,6 +81,8 @@ peg::parser! {
|
||||
= i:id() "<-" _ e:expr() stop() { Stmt::Assignment(i, e) }
|
||||
rule num() -> f64
|
||||
= n:$(digit()+ "."? digit()* / "." digit()+) _ { n.parse().unwrap() }
|
||||
rule _bool() -> bool
|
||||
= "true" _ { true } / "false" _ { false }
|
||||
rule funcall() -> Expr
|
||||
= i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Expr::Funcall(i, e) }
|
||||
rule funcdef() -> Expr
|
||||
@ -88,19 +92,19 @@ peg::parser! {
|
||||
rule object() -> Expr
|
||||
= "{" _ stop() indent() __* a:assignment()+ dedent() __* "}" _ { Expr::Object(a) }
|
||||
|
||||
rule _if() -> Expr
|
||||
rule _if() -> GuardedBlock
|
||||
= "if" _ g:expr() b:indented_block() {
|
||||
Expr::GuardedBlock(Box::new(GuardedBlock {
|
||||
GuardedBlock {
|
||||
guard: g,
|
||||
block: b,
|
||||
}))
|
||||
}
|
||||
}
|
||||
rule elif() -> Expr
|
||||
rule elif() -> GuardedBlock
|
||||
= "elif" _ g:expr() b:indented_block() {
|
||||
Expr::GuardedBlock(Box::new(GuardedBlock {
|
||||
GuardedBlock {
|
||||
guard: g,
|
||||
block: b
|
||||
}))
|
||||
}
|
||||
}
|
||||
rule _else() -> Expr
|
||||
= "else" _ b:block() { b }
|
||||
|
Loading…
Reference in New Issue
Block a user