use internment::ArcIntern; use crate::ir::ast as ir; use crate::syntax::ast as syntax; impl From for ir::Program { fn from(mut value: syntax::Program) -> Self { ir::Program { statements: value.statements.drain(..).map(Into::into).collect(), } } } impl From> for ir::Program { fn from(mut value: Vec) -> Self { ir::Program { statements: value.drain(..).map(Into::into).collect(), } } } impl From for ir::Statement { fn from(value: syntax::Statement) -> Self { match value { syntax::Statement::Binding(loc, name, expr) => { ir::Statement::Binding(loc, ArcIntern::from(name), ir::Expression::from(expr)) } syntax::Statement::Print(loc, name) => ir::Statement::Print(loc, ArcIntern::from(name)), } } } impl From for ir::Expression { fn from(value: syntax::Expression) -> Self { match value { syntax::Expression::Primitive(loc, name, mut exprs) => ir::Expression::Primitive( loc, ir::Primitive::try_from(name.as_str()).unwrap(), exprs.drain(..).map(Into::into).collect(), ), syntax::Expression::Reference(loc, name) => { ir::Expression::Reference(loc, ArcIntern::from(name)) } syntax::Expression::Value(loc, value) => { ir::Expression::Value(loc, ir::Value::from(value)) } } } } impl From for ir::ValueOrRef { fn from(value: syntax::Expression) -> Self { match value { syntax::Expression::Primitive(loc, _, _) => { panic!("{:?}: couldn't convert to valueorref", loc) } syntax::Expression::Reference(loc, var) => { ir::ValueOrRef::Ref(loc, ArcIntern::new(var)) } syntax::Expression::Value(loc, val) => ir::ValueOrRef::Value(loc, val.into()), } } } impl From for ir::Value { fn from(x: syntax::Value) -> Self { match x { syntax::Value::Number(base, value) => ir::Value::Number(base, value), } } } proptest::proptest! { #[test] fn translation_maintains_semantics(input: syntax::Program) { let syntax_result = input.eval(); let ir = ir::Program::from(input.simplify()); let ir_result = ir.eval(); assert_eq!(syntax_result, ir_result); } }