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(()) |     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; |     let is_tail = ctx.is_tail; | ||||||
|     ctx.is_tail = false; |     ctx.is_tail = false; | ||||||
|     if let Some((last, butlast)) = ast.split_last() { |     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); | 	    let mut fun_ctx = LexicalContext::new(ctx); | ||||||
| 	    fun_ctx.is_tail = true; | 	    fun_ctx.is_tail = true; | ||||||
| 	    emit_all(w, body.as_ref(), &mut fun_ctx)?; | 	    emit_all(w, body, &mut fun_ctx)?; | ||||||
| 	    write!(w, "}}")?; | 	    write!(w, "}}")?; | ||||||
| 	} | 	} | ||||||
| 	parser::Expr::Plus(e1, e2) => { | 	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 parser; | ||||||
| mod evaluator; |  | ||||||
| mod emitter; | mod emitter; | ||||||
| mod internal; | mod internal; | ||||||
| 
 | 
 | ||||||
| @ -11,11 +10,11 @@ use std::fs::File; | |||||||
| use std::path::PathBuf; | use std::path::PathBuf; | ||||||
| 
 | 
 | ||||||
| #[derive(Parser, Debug)] | #[derive(Parser, Debug)] | ||||||
| #[clap(author, version, about = "Interpreter for Deelang")] | #[clap(author, version, about = "Compiler for Deelang")] | ||||||
| struct Cli { | struct Cli { | ||||||
|     #[clap(help="Specify a file to run")] |     #[clap(help="Specify a file to compile")] | ||||||
|     file: Option<PathBuf>, |     file: Option<PathBuf>, | ||||||
|     #[clap(short, long, help="Only parse, do not evaluate")] |     #[clap(short, long, help="Emit a parse tree")] | ||||||
|     parse: bool, |     parse: bool, | ||||||
|     #[clap(short, long, help="Cross-compile to ECMAScript")] |     #[clap(short, long, help="Cross-compile to ECMAScript")] | ||||||
|     ecmascript: bool, |     ecmascript: bool, | ||||||
| @ -24,7 +23,6 @@ struct Cli { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn repl(cli: &Cli) { | fn repl(cli: &Cli) { | ||||||
|     let mut global = evaluator::Env::global(); |  | ||||||
|     let mut toplevel = emitter::LexicalContext::toplevel(); |     let mut toplevel = emitter::LexicalContext::toplevel(); | ||||||
|     let mut out = io::stdout(); |     let mut out = io::stdout(); | ||||||
|     loop { |     loop { | ||||||
| @ -35,10 +33,8 @@ fn repl(cli: &Cli) { | |||||||
|             println!("{:#?}", tree); |             println!("{:#?}", tree); | ||||||
|         } else if cli.ecmascript { |         } else if cli.ecmascript { | ||||||
| 	    emitter::emit(&mut out, &tree, &mut toplevel).ok(); | 	    emitter::emit(&mut out, &tree, &mut toplevel).ok(); | ||||||
| 	} else { |  | ||||||
|             evaluator::eval(&tree, &mut global); |  | ||||||
|         } |  | ||||||
| 	} | 	} | ||||||
|  |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn script(cli: &Cli) { | fn script(cli: &Cli) { | ||||||
| @ -57,8 +53,6 @@ fn script(cli: &Cli) { | |||||||
| 	emitter::emit_injector(&mut out).ok(); | 	emitter::emit_injector(&mut out).ok(); | ||||||
| 	let mut toplevel = emitter::LexicalContext::toplevel(); | 	let mut toplevel = emitter::LexicalContext::toplevel(); | ||||||
| 	emitter::emit_all(&mut out, &tree, &mut toplevel).ok(); | 	emitter::emit_all(&mut out, &tree, &mut toplevel).ok(); | ||||||
|     } else { |  | ||||||
|         todo!(); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user