Compare commits
	
		
			2 Commits
		
	
	
		
			25fe7933f2
			...
			8259b57a46
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8259b57a46 | |||
| 0524efef03 | 
| @ -42,7 +42,7 @@ pub fn emit_all(w: &mut dyn Write, ast: &Vec<parser::Stmt>, ctx: &mut LexicalCon | ||||
| 
 | ||||
| pub fn emit(w: &mut dyn Write, stmt: &parser::Stmt, ctx: &mut LexicalContext) -> std::io::Result<()> { | ||||
|     match &stmt { | ||||
| 	parser::Stmt::ReplPrint(expr) => { | ||||
| 	parser::Stmt::BareExpr(expr) => { | ||||
| 	    write!(w, "console.log((")?; | ||||
| 	    emit_expr(w, expr, ctx)?; | ||||
| 	    writeln!(w, "));")?; | ||||
| @ -72,13 +72,13 @@ pub fn emit(w: &mut dyn Write, stmt: &parser::Stmt, ctx: &mut LexicalContext) -> | ||||
| 		emit_expr(w, &if_block.guard, ctx)?; | ||||
| 		writeln!(w, ") {{")?; | ||||
| 		let mut block_ctx = LexicalContext::new(ctx); | ||||
| 		emit_expr(w, &if_block.block, &mut block_ctx)?; | ||||
| 		emit_all(w, &if_block.block, &mut block_ctx)?; | ||||
| 		writeln!(w, "}}")?; | ||||
| 	    } | ||||
| 	    if let Some(block) = else_block { | ||||
| 		writeln!(w, "else {{")?; | ||||
| 		let mut block_ctx = LexicalContext::new(ctx); | ||||
| 		emit_expr(w, block, &mut block_ctx)?; | ||||
| 		emit_all(w, block, &mut block_ctx)?; | ||||
| 		writeln!(w, "}}")?; | ||||
| 	    } | ||||
| 	} | ||||
| @ -113,18 +113,9 @@ 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_expr(w, body.as_ref(), &mut fun_ctx)?; | ||||
| 	    emit_all(w, body.as_ref(), &mut fun_ctx)?; | ||||
| 	    write!(w, "}}")?; | ||||
| 	} | ||||
| 	parser::Expr::Block(stmts) => { | ||||
| 	    let mut peek_iter = stmts.iter().peekable(); | ||||
| 	    while let Some(stmt) = peek_iter.next() { | ||||
| 		if peek_iter.peek().is_none() { | ||||
| 		    write!(w, "return ")?; | ||||
| 		} | ||||
| 		emit(w, stmt, ctx)?; | ||||
| 	    } | ||||
| 	}   
 | ||||
| 	parser::Expr::Plus(e1, e2) => { | ||||
| 	    emit_expr(w, e1.as_ref(), ctx)?; | ||||
| 	    write!(w, " + ")?; | ||||
|  | ||||
| @ -38,7 +38,7 @@ impl<'a> Env<'a> { | ||||
| 
 | ||||
| pub fn eval(ast: &parser::Stmt, env: &mut Env) { | ||||
|     match &ast { | ||||
|         parser::Stmt::ReplPrint(expr) => | ||||
|         parser::Stmt::BareExpr(expr) => | ||||
|             println!("{}", eval_expr(expr, env)), | ||||
|         parser::Stmt::Assignment(id, expr) => | ||||
|             env.set(id.clone(), eval_expr(expr, env)), | ||||
| @ -49,11 +49,9 @@ pub fn eval(ast: &parser::Stmt, env: &mut Env) { | ||||
|                 match res { | ||||
|                     Atom::Bool(true) => { | ||||
|                         matched = true; | ||||
| 			if let parser::Expr::Block(block) = block { | ||||
|                             for stmt in block { | ||||
| 				eval(stmt, env); | ||||
|                             } | ||||
| 			} | ||||
|                         for stmt in block { | ||||
| 			    eval(stmt, env); | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|                     Atom::Bool(false) => continue, | ||||
| @ -62,7 +60,9 @@ pub fn eval(ast: &parser::Stmt, env: &mut Env) { | ||||
|             } | ||||
|             if !matched { | ||||
|                 if let Some(block) = default_block { | ||||
|                     eval_expr(block, env); | ||||
| 		    for stmt in block { | ||||
| 			eval(stmt, env); | ||||
| 		    } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @ -4,8 +4,8 @@ use std::fmt; | ||||
| pub enum Stmt { | ||||
|     Assignment(String, Expr), | ||||
|     Funcall(Expr), | ||||
|     Conditional(Vec<GuardedBlock>, Option<Expr>), | ||||
|     ReplPrint(Expr), | ||||
|     Conditional(Vec<GuardedBlock>, Option<Block>), | ||||
|     BareExpr(Expr), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug,PartialEq,Clone)] | ||||
| @ -13,16 +13,16 @@ pub enum Expr { | ||||
|     Id(String), | ||||
|     Atom(Atom), | ||||
|     Funcall(String, Vec<Expr>), | ||||
|     Funcdef(Option<String>, Box<Expr>), | ||||
|     Funcdef(Option<String>, Block), | ||||
|     UnaryMinus(Box<Expr>), | ||||
|     Plus(Box<Expr>, Box<Expr>), | ||||
|     Minus(Box<Expr>, Box<Expr>), | ||||
|     Mult(Box<Expr>, Box<Expr>), | ||||
|     Div(Box<Expr>, Box<Expr>), | ||||
|     Block(Vec<Stmt>), | ||||
|     Object(Vec<Stmt>), | ||||
| } | ||||
| 
 | ||||
| pub type Block = Vec<Stmt>; | ||||
| 
 | ||||
| #[derive(Debug,PartialEq,Clone)] | ||||
| pub enum Atom { | ||||
|     String(String), | ||||
| @ -43,7 +43,7 @@ impl fmt::Display for Atom { | ||||
| #[derive(Debug,PartialEq,Clone)] | ||||
| pub struct GuardedBlock { | ||||
|     pub guard: Expr, | ||||
|     pub block: Expr, | ||||
|     pub block: Block, | ||||
| } | ||||
| 
 | ||||
| peg::parser! { | ||||
| @ -54,7 +54,7 @@ peg::parser! { | ||||
|             = a:assignment() { a } / | ||||
|             f:funcall() stop() { Stmt::Funcall(f) } / | ||||
|             c:conditional() { c } / | ||||
|             e:expr() stop() { Stmt::ReplPrint(e) } | ||||
|             e:expr() stop() { Stmt::BareExpr(e) } | ||||
|         rule expr() -> Expr = precedence! { | ||||
|             "-" _ e1:@ { Expr::UnaryMinus(Box::new(e1)) } | ||||
|             -- | ||||
| @ -69,7 +69,6 @@ peg::parser! { | ||||
|             f:funcall() { f } | ||||
|             f:funcdef() { f } | ||||
| 	    b:boolean() _ { Expr::Atom(Atom::Bool(b)) } | ||||
|             o:object() { o } | ||||
|             i:id() _ { Expr::Id(i) } | ||||
|             n:num() _ { Expr::Atom(Atom::Num(n)) } | ||||
| 
 | ||||
| @ -86,12 +85,9 @@ peg::parser! { | ||||
|         rule funcall() -> Expr | ||||
|             = i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Expr::Funcall(i, e) } | ||||
|         rule funcdef() -> Expr | ||||
|             = i:id()? "->" _ e:(expr() / block()) { Expr::Funcdef(i, Box::new(e)) } | ||||
|             = i:id()? "->" _ b:(block()) { Expr::Funcdef(i, b) } | ||||
|         rule conditional() -> Stmt | ||||
|             = i:_if() __* ei:elif()* __* e:_else()? __* { Stmt::Conditional([vec![i], ei].concat(), e) } | ||||
|         rule object() -> Expr | ||||
|             = "{" _ stop() indent() __* a:assignment()+ dedent() __* "}" _ { Expr::Object(a) } | ||||
|         
 | ||||
|         rule _if() -> GuardedBlock | ||||
|             = "if" _ g:expr() b:block() { | ||||
|                 GuardedBlock { | ||||
| @ -106,11 +102,12 @@ peg::parser! { | ||||
|                     block: b | ||||
|                 } | ||||
|             } | ||||
|         rule _else() -> Expr | ||||
|         rule _else() -> Block | ||||
|             = "else" _ b:block() { b } | ||||
|         rule block() -> Expr | ||||
|             = i:indented_block() { Expr::Block(i) } | ||||
|         rule indented_block() -> Vec<Stmt> | ||||
|         rule block() -> Block | ||||
|             = i:indented_block() { i } / | ||||
| 	    e:expr() { vec![Stmt::BareExpr(e)] } | ||||
|         rule indented_block() -> Block | ||||
|             = stop() indent() __* s:stmt()+ dedent() { s } | ||||
| 
 | ||||
|         rule letter() | ||||
| @ -285,36 +282,36 @@ foo <- x -> y -> x * y"; | ||||
|                 "foo".to_string(), | ||||
|                 Expr::Funcdef( | ||||
|                     None, | ||||
|                     Box::new(Expr::Funcall("bar".to_string(), vec![])), | ||||
|                 ) | ||||
|                     vec![Stmt::BareExpr(Expr::Funcall("bar".to_string(), vec![]))], | ||||
|                 ), | ||||
|             ), | ||||
|             Stmt::Assignment( | ||||
|                 "foo".to_string(), | ||||
|                 Expr::Funcdef( | ||||
|                     None, | ||||
|                     Box::new(Expr::Block(vec![ | ||||
| 		    vec![ | ||||
|                         Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![])), | ||||
|                         Stmt::Funcall(Expr::Funcall("baz".to_string(), vec![])), | ||||
|                     ])) | ||||
|                 ) | ||||
|                     ], | ||||
| 		) | ||||
|             ), | ||||
|             Stmt::Assignment( | ||||
|                 "foo".to_string(), | ||||
|                 Expr::Funcdef( | ||||
|                     Some("x".to_string()), | ||||
|                     Box::new( | ||||
|                         Expr::Funcdef( | ||||
|                     vec![ | ||||
|                         Stmt::BareExpr(Expr::Funcdef( | ||||
|                             Some("y".to_string()), | ||||
|                             Box::new( | ||||
|                                 Expr::Mult( | ||||
| 			    vec![ | ||||
|                                 Stmt::BareExpr(Expr::Mult( | ||||
|                                     Box::new(Expr::Id("x".to_string())), | ||||
|                                     Box::new(Expr::Id("y".to_string())), | ||||
|                                 ) | ||||
|                             ) | ||||
|                         ) | ||||
|                     ) | ||||
|                                 )) | ||||
|                             ], | ||||
|                         )) | ||||
|                     ], | ||||
|                 ) | ||||
|             ) | ||||
|             ), | ||||
|         ]; | ||||
|         assert_eq!(deelang_parser::program(prgm).unwrap(), expected); | ||||
|     } | ||||
| @ -333,30 +330,14 @@ else | ||||
|             vec![ | ||||
|                 GuardedBlock { | ||||
|                     guard: Expr::Id("foo".to_string()), | ||||
|                     block: Expr::Block(vec![Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![]))]) | ||||
|                     block: vec![Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![]))] | ||||
|                 }, | ||||
|                 GuardedBlock { | ||||
|                     guard: Expr::Id("baz".to_string()), | ||||
|                     block: Expr::Block(vec![Stmt::Funcall(Expr::Funcall("foobar".to_string(), vec![]))]) | ||||
|                     block: vec![Stmt::Funcall(Expr::Funcall("foobar".to_string(), vec![]))], | ||||
|                 }, | ||||
|             ], | ||||
|             Some(Expr::Block(vec![Stmt::Funcall(Expr::Funcall("quux".to_string(), vec![]))])), | ||||
|         )]; | ||||
|         assert_eq!(deelang_parser::program(prgm).unwrap(), expected); | ||||
|     } | ||||
|     #[test] | ||||
|     fn test_object() { | ||||
|         let prgm = r"fruit <- {
 | ||||
| >>>apple <- 1 | ||||
| pear <- 2 | ||||
| <<< | ||||
| }";
 | ||||
|         let expected = vec![Stmt::Assignment( | ||||
|             "fruit".to_string(), | ||||
|             Expr::Object(vec![ | ||||
|                 Stmt::Assignment("apple".to_string(), Expr::Atom(Atom::Num(1.0))), | ||||
|                 Stmt::Assignment("pear".to_string(), Expr::Atom(Atom::Num(2.0))), | ||||
|             ]), | ||||
|             Some(vec![Stmt::Funcall(Expr::Funcall("quux".to_string(), vec![]))]), | ||||
|         )]; | ||||
|         assert_eq!(deelang_parser::program(prgm).unwrap(), expected); | ||||
|     } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user