Compare commits
2 Commits
2a7db71ded
...
69ccf679e7
Author | SHA1 | Date | |
---|---|---|---|
69ccf679e7 | |||
5436a706d7 |
@ -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!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 }
|
||||||
|
Loading…
Reference in New Issue
Block a user