Remove interpreter & evaluator
This commit is contained in:
parent
7213f4a487
commit
03b140189c
@ -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<parser::Stmt>, 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) => {
|
||||
|
139
src/evaluator.rs
139
src/evaluator.rs
@ -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<String, Atom>
|
||||
}
|
||||
|
||||
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!"),
|
||||
}
|
||||
}
|
||||
}
|
14
src/main.rs
14
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<PathBuf>,
|
||||
#[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!();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user