diff --git a/src/emitter.rs b/src/emitter.rs index d207607..7873ca4 100644 --- a/src/emitter.rs +++ b/src/emitter.rs @@ -44,7 +44,7 @@ pub fn emit_injector(w: &mut dyn Write) -> std::io::Result<()>{ Ok(()) } -pub fn emit_all(w: &mut dyn Write, ast: &Vec, ctx: &mut LexicalContext) -> std::io::Result<()> { +pub fn emit_all(w: &mut dyn Write, ast: &[parser::Stmt], ctx: &mut LexicalContext) -> std::io::Result<()> { let is_tail = ctx.is_tail; ctx.is_tail = false; if let Some((last, butlast)) = ast.split_last() { @@ -152,7 +152,7 @@ pub fn emit_expr(w: &mut dyn Write, expr: &parser::Expr, ctx: &mut LexicalContex } let mut fun_ctx = LexicalContext::new(ctx); fun_ctx.is_tail = true; - emit_all(w, body.as_ref(), &mut fun_ctx)?; + emit_all(w, body, &mut fun_ctx)?; write!(w, "}}")?; } parser::Expr::Plus(e1, e2) => { diff --git a/src/evaluator.rs b/src/evaluator.rs deleted file mode 100644 index f11f57a..0000000 --- a/src/evaluator.rs +++ /dev/null @@ -1,139 +0,0 @@ -use std::ops; -use std::collections::HashMap; - -use crate::parser::{self, GuardedBlock}; -use parser::Atom; - -pub struct Env<'a> { - pub parent: Option<&'a Env<'a>>, - pub values: HashMap -} - -impl<'a> Env<'a> { - pub fn global() -> Self { - Env { - parent: None, - values: HashMap::new(), - } - } - pub fn child(parent: &'a Env<'a>) -> Self { - Env { - parent: Some(parent), - values: HashMap::new(), - } - } - pub fn lookup(&self, id: &str) -> Atom { - if let Some(a) = self.values.get(id) { - a.clone() - } else if let Some(parent) = self.parent { - parent.lookup(id) - } else { - 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::BareExpr(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 stmt in block { - eval(stmt, env); - } - } - } - } - _ => todo!(), - } -} - -pub fn eval_expr(ast: &parser::Expr, env: &Env) -> Atom { - match ast { - parser::Expr::Id(a) => env.lookup(a), - parser::Expr::Atom(a) => a.clone(), - parser::Expr::UnaryMinus(a) => -eval_expr(a, env), - parser::Expr::Plus(a, b) => eval_expr(a, env) + eval_expr(b, env), - parser::Expr::Minus(a, b) => eval_expr(a, env) - eval_expr(b, env), - parser::Expr::Mult(a, b) => eval_expr(a, env) * eval_expr(b, env), - parser::Expr::Div(a, b) => eval_expr(a, env) / eval_expr(b, env), - _ => panic!("Couldn't evalute expression {{ {:?} }}", ast), - } -} - -impl ops::Neg for Atom { - type Output = Self; - - fn neg(self) -> Self { - match self { - Atom::Num(a) => Atom::Num(-a), - _ => panic!("Can't negate non-numeral type!"), - } - } -} - -impl ops::Add for Atom { - type Output = Self; - - fn add(self, other: Self) -> Self { - match (self, other) { - (Atom::Num(a), Atom::Num(b)) => Atom::Num(a + b), - _ => panic!("Can't add non-numeral types!"), - } - } -} - -impl ops::Sub for Atom { - type Output = Self; - - fn sub(self, other: Self) -> Self { - match (self, other) { - (Atom::Num(a), Atom::Num(b)) => Atom::Num(a - b), - _ => panic!("Can't subtract non-numeral types!"), - } - } -} - -impl ops::Mul for Atom { - type Output = Self; - - fn mul(self, other: Self) -> Self { - match (self, other) { - (Atom::Num(a), Atom::Num(b)) => Atom::Num(a * b), - _ => panic!("Can't multiply non-numeral types!"), - } - } -} - -impl ops::Div for Atom { - type Output = Self; - - fn div(self, other: Self) -> Self { - match (self, other) { - (Atom::Num(a), Atom::Num(b)) => Atom::Num(a / b), - _ => panic!("Can't divide non-numeral types!"), - } - } -} diff --git a/src/main.rs b/src/main.rs index facf6d8..c09eb15 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,4 @@ mod parser; -mod evaluator; mod emitter; mod internal; @@ -11,11 +10,11 @@ use std::fs::File; use std::path::PathBuf; #[derive(Parser, Debug)] -#[clap(author, version, about = "Interpreter for Deelang")] +#[clap(author, version, about = "Compiler for Deelang")] struct Cli { - #[clap(help="Specify a file to run")] + #[clap(help="Specify a file to compile")] file: Option, - #[clap(short, long, help="Only parse, do not evaluate")] + #[clap(short, long, help="Emit a parse tree")] parse: bool, #[clap(short, long, help="Cross-compile to ECMAScript")] ecmascript: bool, @@ -24,7 +23,6 @@ struct Cli { } fn repl(cli: &Cli) { - let mut global = evaluator::Env::global(); let mut toplevel = emitter::LexicalContext::toplevel(); let mut out = io::stdout(); loop { @@ -35,10 +33,8 @@ fn repl(cli: &Cli) { println!("{:#?}", tree); } else if cli.ecmascript { emitter::emit(&mut out, &tree, &mut toplevel).ok(); - } else { - evaluator::eval(&tree, &mut global); - } - } + } + }; } fn script(cli: &Cli) { @@ -57,8 +53,6 @@ fn script(cli: &Cli) { emitter::emit_injector(&mut out).ok(); let mut toplevel = emitter::LexicalContext::toplevel(); emitter::emit_all(&mut out, &tree, &mut toplevel).ok(); - } else { - todo!(); } }