Skip to content
Snippets Groups Projects
Commit f62d8f7b authored by Per Lindgren's avatar Per Lindgren
Browse files

all tests pass

parent 46f125d3
No related branches found
No related tags found
No related merge requests found
// 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;
}
......@@ -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,115 +448,139 @@ pub fn check(p: &Program) -> Result<(), Error> {
// unit test
#[test]
fn test_expr_type() {
use crate::grammar::*;
use crate::*;
use Type::*;
// #[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();
var_env.push_empty_scope();
// // 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();
// // 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 ...
// trace!("{}", &p);
println!("p {}", p);
// let b = fn_env.get(&"b").unwrap();
// type of number
assert_eq!(
expr_type(&Expr::Num(1), &fn_env, &type_env, &mut var_env),
Ok(I32)
);
// let body = &b.body;
// trace!("{}", &body);
// type of variables
// trace!("{:?}", check_stmts(body, &fn_env, &type_env, &mut var_env));
// }
// not found
assert!(expr_type(&Expr::Id("a".to_string()), &fn_env, &type_env, &mut var_env).is_err());
// #[test]
// fn test_expr_type() {
// use crate::grammar::*;
// use crate::*;
// use Type::*;
// let i: i32 ...
assert_eq!(
expr_type(&Expr::Id("i".to_string()), &fn_env, &type_env, &mut var_env),
Ok(I32)
);
// // 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();
// let j ... (has no type yet)
assert_eq!(
expr_type(&Expr::Id("j".to_string()), &fn_env, &type_env, &mut var_env),
Ok(Unknown)
);
// // // 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);
// // let n: A ...
// // type of number
// assert_eq!(
// expr_type(&Expr::Id("n".to_string()), &fn_env, &type_env, &var_env),
// Ok(Named("A".to_string()))
// expr_type(&Expr::Num(1), &fn_env, &type_env, &mut var_env),
// Ok(I32)
// );
// 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 variables
// 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)
);
// // not found
// assert!(expr_type(&Expr::Id("a".to_string()), &fn_env, &type_env, &mut var_env).is_err());
// call, with check, ok
assert_eq!(
expr_type(
&*ExprParser::new().parse("b(1)").unwrap(),
&fn_env,
&type_env,
&mut var_env
),
Ok(I32)
);
// // let i: i32 ...
// assert_eq!(
// expr_type(&Expr::Id("i".to_string()), &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)
);
// // let j ... (has no type yet)
// assert_eq!(
// expr_type(&Expr::Id("j".to_string()), &fn_env, &type_env, &mut var_env),
// Ok(Unknown)
// );
// 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());
// // // 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!(
......@@ -592,4 +594,4 @@ fn test_expr_type() {
// );
// TODO, ref/ref mut/deref
}
// }
......@@ -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::Neq,
">" => Op::Greater,
"<" => Op::Less,
"<=" => Op::LessEq,
">=" => 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(),
};
......
......@@ -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());
......
use erode::vm::*;
#[test]
fn minmal_test() {
eval_prog("examples/minimal.rs");
}
#[test]
fn ref_test() {
eval_prog("examples/ref.rs");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment