Compare commits
No commits in common. "69ccf679e7409e3b52c6ea15cb50f204a0b078ef" and "2a7db71ded2dfccfae8473db18ba44005cbe803b" have entirely different histories.
69ccf679e7
...
2a7db71ded
@ -1,7 +1,7 @@
|
|||||||
use std::ops;
|
use std::ops;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::parser::{self, GuardedBlock};
|
use crate::parser;
|
||||||
use parser::Atom;
|
use parser::Atom;
|
||||||
|
|
||||||
pub struct Env<'a> {
|
pub struct Env<'a> {
|
||||||
@ -31,41 +31,12 @@ 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!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<GuardedBlock>, Option<Expr>),
|
Conditional(Vec<Expr>, Option<Expr>),
|
||||||
ReplPrint(Expr),
|
ReplPrint(Expr),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,6 +20,7 @@ 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>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +28,6 @@ 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,7 +35,6 @@ 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),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,8 +68,7 @@ peg::parser! {
|
|||||||
f:funcall() { f }
|
f:funcall() { f }
|
||||||
f:funcdef() { f }
|
f:funcdef() { f }
|
||||||
o:object() { o }
|
o:object() { o }
|
||||||
b:_bool() _ { Expr::Atom(Atom::Bool(b)) }
|
i:id() _ { Expr::Id(i) }
|
||||||
i:id() { Expr::Id(i) }
|
|
||||||
n:num() _ { Expr::Atom(Atom::Num(n)) }
|
n:num() _ { Expr::Atom(Atom::Num(n)) }
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -81,8 +79,6 @@ 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
|
||||||
@ -92,19 +88,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() -> GuardedBlock
|
rule _if() -> Expr
|
||||||
= "if" _ g:expr() b:indented_block() {
|
= "if" _ g:expr() b:indented_block() {
|
||||||
GuardedBlock {
|
Expr::GuardedBlock(Box::new(GuardedBlock {
|
||||||
guard: g,
|
guard: g,
|
||||||
block: b,
|
block: b,
|
||||||
}
|
}))
|
||||||
}
|
}
|
||||||
rule elif() -> GuardedBlock
|
rule elif() -> Expr
|
||||||
= "elif" _ g:expr() b:indented_block() {
|
= "elif" _ g:expr() b:indented_block() {
|
||||||
GuardedBlock {
|
Expr::GuardedBlock(Box::new(GuardedBlock {
|
||||||
guard: g,
|
guard: g,
|
||||||
block: b
|
block: b
|
||||||
}
|
}))
|
||||||
}
|
}
|
||||||
rule _else() -> Expr
|
rule _else() -> Expr
|
||||||
= "else" _ b:block() { b }
|
= "else" _ b:block() { b }
|
||||||
|
Loading…
Reference in New Issue
Block a user