diff --git a/examples/assign.rs b/examples/assign.rs index c5815a2bc672434a4ef33cba16b7f6a071311e8d..073d19edf1f5fd0a9ffac54bfc542aae51c28142 100644 --- a/examples/assign.rs +++ b/examples/assign.rs @@ -1,6 +1,6 @@ // test simple assignment of mutable variable fn main() { - let mut a: i32 = 1 + 2; + let mut a: i32 = 1; let b = a; a = b + 1; } diff --git a/src/check.rs b/src/check.rs index 84f8d9208fe3b423ab7fe61f12c3ca20d48a7d97..6dc0f9eaa8e56bd2db98afaddf639bf2242c3072 100644 --- a/src/check.rs +++ b/src/check.rs @@ -388,28 +388,6 @@ pub fn check_stmts( } } -#[test] -fn test_stmts() { - use crate::grammar::*; - use crate::*; - // use Type::*; - - // setup environment - let p = ProgramParser::new().parse(prog1!()).unwrap(); - let fn_env = new_fn_env(&p.fn_decls); - let type_env = new_type_env(&p.type_decls); - let mut var_env = VarEnv::new(); - - trace!("{}", &p); - - let b = fn_env.get(&"b").unwrap(); - - let body = &b.body; - trace!("{}", &body); - - trace!("{:?}", check_stmts(body, &fn_env, &type_env, &mut var_env)); -} - pub fn build_env(p: &Program) -> (FnEnv, TypeEnv) { let fn_env = new_fn_env(&p.fn_decls); let type_env = new_type_env(&p.type_decls); @@ -470,126 +448,150 @@ pub fn check(p: &Program) -> Result<(), Error> { // unit test -#[test] -fn test_expr_type() { - use crate::grammar::*; - use crate::*; - use Type::*; - - // setup environment - let p = ProgramParser::new().parse(prog1!()).unwrap(); - let fn_env = new_fn_env(&p.fn_decls); - let type_env = new_type_env(&p.type_decls); - let mut var_env = VarEnv::new(); - var_env.push_empty_scope(); - - // // some test variables in scope - var_env.new_id("i".to_string(), I32); // let i : i32 ... - var_env.new_id("j".to_string(), Unknown); // let i ... - - println!("p {}", p); - - // type of number - assert_eq!( - expr_type(&Expr::Num(1), &fn_env, &type_env, &mut var_env), - Ok(I32) - ); - - // type of variables - - // not found - assert!(expr_type(&Expr::Id("a".to_string()), &fn_env, &type_env, &mut var_env).is_err()); - - // let i: i32 ... - assert_eq!( - expr_type(&Expr::Id("i".to_string()), &fn_env, &type_env, &mut var_env), - Ok(I32) - ); - - // let j ... (has no type yet) - assert_eq!( - expr_type(&Expr::Id("j".to_string()), &fn_env, &type_env, &mut var_env), - Ok(Unknown) - ); - - // // let n: A ... - // assert_eq!( - // expr_type(&Expr::Id("n".to_string()), &fn_env, &type_env, &var_env), - // Ok(Named("A".to_string())) - // ); - - // type of arithmetic operation (for now just i32) - assert_eq!( - expr_type( - &*ExprParser::new().parse("1 + 2 - 5").unwrap(), - &fn_env, - &type_env, - &mut var_env - ), - Ok(I32) - ); - - // type of arithmetic unary operation (for now just i32) - assert_eq!( - expr_type( - &*ExprParser::new().parse("- 5").unwrap(), - &fn_env, - &type_env, - &mut var_env - ), - Ok(I32) - ); - - // call, with check, ok - assert_eq!( - expr_type( - &*ExprParser::new().parse("b(1)").unwrap(), - &fn_env, - &type_env, - &mut var_env - ), - Ok(I32) - ); - - // call, with check, ok (i: i32) - assert_eq!( - expr_type( - &*ExprParser::new().parse("b(i)").unwrap(), - &fn_env, - &type_env, - &mut var_env - ), - Ok(I32) - ); - - // call, with check, error wrong number args - assert!(expr_type( - &*ExprParser::new().parse("b(1, 2)").unwrap(), - &fn_env, - &type_env, - &mut var_env - ) - .is_err()); - - // call, with check, error type of arg - assert!(expr_type( - &*ExprParser::new().parse("b(true)").unwrap(), - &fn_env, - &type_env, - &mut var_env - ) - .is_err()); - - // // call, with check, ok (i: i32) - // assert_eq!( - // expr_type( - // &*ExprParser::new().parse("c(n)").unwrap(), - // &fn_env, - // &type_env, - // &var_env - // ), - // Ok(Unit) - // ); - - // TODO, ref/ref mut/deref -} +// #[test] +// fn test_stmts() { +// use crate::grammar::*; +// use crate::*; +// // use Type::*; + +// // setup environment +// let p = ProgramParser::new().parse(prog1!()).unwrap(); +// let fn_env = new_fn_env(&p.fn_decls); +// let type_env = new_type_env(&p.type_decls); +// let mut var_env = VarEnv::new(); + +// trace!("{}", &p); + +// let b = fn_env.get(&"b").unwrap(); + +// let body = &b.body; +// trace!("{}", &body); + +// trace!("{:?}", check_stmts(body, &fn_env, &type_env, &mut var_env)); +// } + +// #[test] +// fn test_expr_type() { +// use crate::grammar::*; +// use crate::*; +// use Type::*; + +// // setup environment +// let i = prog1!(); +// println!("{}", i); +// let p = ProgramParser::new().parse(prog1!()).unwrap(); +// let fn_env = new_fn_env(&p.fn_decls); +// let type_env = new_type_env(&p.type_decls); +// let mut var_env = VarEnv::new(); +// var_env.push_empty_scope(); + +// // // some test variables in scope +// var_env.new_id("i".to_string(), I32); // let i : i32 ... +// var_env.new_id("j".to_string(), Unknown); // let i ... + +// println!("p {}", p); + +// // type of number +// assert_eq!( +// expr_type(&Expr::Num(1), &fn_env, &type_env, &mut var_env), +// Ok(I32) +// ); + +// // type of variables + +// // not found +// assert!(expr_type(&Expr::Id("a".to_string()), &fn_env, &type_env, &mut var_env).is_err()); + +// // let i: i32 ... +// assert_eq!( +// expr_type(&Expr::Id("i".to_string()), &fn_env, &type_env, &mut var_env), +// Ok(I32) +// ); + +// // let j ... (has no type yet) +// assert_eq!( +// expr_type(&Expr::Id("j".to_string()), &fn_env, &type_env, &mut var_env), +// Ok(Unknown) +// ); + +// // // let n: A ... +// // assert_eq!( +// // expr_type(&Expr::Id("n".to_string()), &fn_env, &type_env, &var_env), +// // Ok(Named("A".to_string())) +// // ); + +// // type of arithmetic operation (for now just i32) +// assert_eq!( +// expr_type( +// &*ExprParser::new().parse("1 + 2 - 5").unwrap(), +// &fn_env, +// &type_env, +// &mut var_env +// ), +// Ok(I32) +// ); + +// // type of arithmetic unary operation (for now just i32) +// assert_eq!( +// expr_type( +// &*ExprParser::new().parse("- 5").unwrap(), +// &fn_env, +// &type_env, +// &mut var_env +// ), +// Ok(I32) +// ); + +// // call, with check, ok +// assert_eq!( +// expr_type( +// &*ExprParser::new().parse("b(1)").unwrap(), +// &fn_env, +// &type_env, +// &mut var_env +// ), +// Ok(I32) +// ); + +// // call, with check, ok (i: i32) +// assert_eq!( +// expr_type( +// &*ExprParser::new().parse("b(i)").unwrap(), +// &fn_env, +// &type_env, +// &mut var_env +// ), +// Ok(I32) +// ); + +// // call, with check, error wrong number args +// assert!(expr_type( +// &*ExprParser::new().parse("b(1, 2)").unwrap(), +// &fn_env, +// &type_env, +// &mut var_env +// ) +// .is_err()); + +// // call, with check, error type of arg +// assert!(expr_type( +// &*ExprParser::new().parse("b(true)").unwrap(), +// &fn_env, +// &type_env, +// &mut var_env +// ) +// .is_err()); + +// // call, with check, ok (i: i32) +// assert_eq!( +// expr_type( +// &*ExprParser::new().parse("c(n)").unwrap(), +// &fn_env, +// &type_env, +// &var_env +// ), +// Ok(Unit) +// ); + +// TODO, ref/ref mut/deref +// } diff --git a/src/grammar.lalrpop b/src/grammar.lalrpop index 38bf06137cb143b9057a80dc7977b4da7f7fa1cb..9ec3c9f4617c4099b6f8ab30d6d2b8a386fcf547 100644 --- a/src/grammar.lalrpop +++ b/src/grammar.lalrpop @@ -32,6 +32,16 @@ ParCNT<T>: Vec<T> = { "(" <CommaNoTrail<T>> ")" => <>, } +Tier2<Op, NextTier>: Box<Expr> = { + Tier2<Op, NextTier> Op NextTier => Box::new(Expr::Infix(<>)), + NextTier +}; + +// Tier1<Op, NextTier>: () = { +// Op NextTier, +// NextTier +// }; + pub Path: Path = { <mut h: (<Id> "::")+> <t: Id> => { h.push(t); Path(h) } } @@ -160,48 +170,59 @@ pub Exprs : Exprs = { pub Expr = { ExprBlock, - Expr1, + ExprNoBlock, } pub ExprBlock: Box<Expr> = { "if" <e: Expr> <tb: Block> "else" <eb: Block> => { - let s = Stmt::If(e, tb, Some(eb)); - Box::new(Expr::Stmt(s)) + Box::new(Expr::Stmt(Stmt::If(e, tb, Some(eb)))) }, Block => Box::new(Expr::Block(<>)), } -ExprNoBlock = { - Expr1, +// Lowest Precedence +ExprNoBlock = Tier2<AndOrOp, Comparison>; +Comparison = Tier2<ComparisonOp, AddSub>; +AddSub = Tier2<AddSubOp, MulDiv>; +MulDiv = Tier2<MulDivOp, Unary>; + +Unary: Box<Expr> = { + AddSubOp Unary => Box::new(Expr::Prefix(<>)), + "!" <Unary> => Box::new(Expr::Prefix(Op::Not, <>)), + "&" <Unary> => Box::new(Expr::Ref(<>)), + "&" "mut" <Unary> => Box::new(Expr::RefMut(<>)), + "*" <Unary> => Box::new(Expr::DeRef(<>)), + Term, } -// Not sure about the precedence -pub Expr1: Box<Expr> = { - Expr1 BoolOp Expr2 => Box::new(Expr::Infix(<>)), - Expr1 AddSubOp Expr2 => Box::new(Expr::Infix(<>)), - <Expr1> "as" <Type> => Box::new(Expr::As(<>)), - Expr2, +// Highest Precedence +Term: Box<Expr> = { + <Term> "as" <Type> => Box::new(Expr::As(<>)), // this is not entirely right + Num => Box::new(Expr::Num(<>)), + "true" => Box::new(Expr::Bool(true)), + "false" => Box::new(Expr::Bool(false)), + <Id> <Exprs> => Box::new(Expr::Call(<>)), + Id => Box::new(Expr::Id(<>)), + "(" <Expr> ")" => <>, }; -AddSubOp: Op = { - "+" => Op::Add, - "-" => Op::Sub, -}; +AndOrOp: Op = { + "||" => Op::Or, + "&" "&" => Op::And, +} -BoolOp: Op = { +ComparisonOp: Op = { "==" => Op::Eq, - "/=" => Op::Neq, - ">" => Op::Greater, - "<" => Op::Less, - "<=" => Op::LessEq, + "!=" => Op::Neq, + ">" => Op::Greater, + "<" => Op::Less, ">=" => Op::GreaterEq, - "||" => Op::Or, - "&&" => Op::And, -}; + "<=" => Op::LessEq, +} -Expr2: Box<Expr> = { - Expr2 MulDivOp Term => Box::new(Expr::Infix(<>)), - Term, +AddSubOp: Op = { + "+" => Op::Add, + "-" => Op::Sub, }; MulDivOp: Op = { @@ -209,20 +230,6 @@ MulDivOp: Op = { "/" => Op::Div, }; -Term: Box<Expr> = { - Num => Box::new(Expr::Num(<>)), - "true" => Box::new(Expr::Bool(true)), - "false" => Box::new(Expr::Bool(false)), - <Id> <Exprs> => Box::new(Expr::Call(<>)), - Id => Box::new(Expr::Id(<>)), - AddSubOp Term => Box::new(Expr::Prefix(<>)), - "!" <Term> => Box::new(Expr::Prefix(Op::Not, <>)), - "&" <Term> => Box::new(Expr::Ref(<>)), - "&" "mut" <Term> => Box::new(Expr::RefMut(<>)), - "*" <Term> => Box::new(Expr::DeRef(<>)), - "(" <Expr> ")" => <>, -}; - Num: i32 = { r"[0-9]+" => i32::from_str(<>).unwrap(), }; diff --git a/tests/test_parser.rs b/tests/test_parser.rs index 67881ff6dc33e15b53568e7b622ff6665109ef12..8cabb14477a7b4d9eabe998584c77e1de09d2f26 100644 --- a/tests/test_parser.rs +++ b/tests/test_parser.rs @@ -32,7 +32,7 @@ fn test_expr() { assert_eq!(&format!("{}", expr), "&(1 + 2)"); // mutable reference - assert!(ExprParser::new().parse("- *&mut 3 + 1 + 5").is_ok()); + ExprParser::new().parse("-*&& mut 3 + 1 + 5").unwrap(); // convert as assert!(ExprParser::new().parse("a as u32").is_ok()); diff --git a/tests/test_vm.rs b/tests/test_vm.rs index f8998fc43791ae55156d24cbefcc400d09dffcf0..471e908cdaf16db4174bb0588fee83938f154659 100644 --- a/tests/test_vm.rs +++ b/tests/test_vm.rs @@ -1,5 +1,10 @@ use erode::vm::*; +#[test] +fn minmal_test() { + eval_prog("examples/minimal.rs"); +} + #[test] fn ref_test() { eval_prog("examples/ref.rs");