From 487ce4fe0fa081f58d790d7d6417bf7d2659197c Mon Sep 17 00:00:00 2001 From: Greg Brown Date: Sat, 9 Jan 2021 11:53:21 +0000 Subject: Make all ast spans optional. --- src/chomp/ast.rs | 12 ++-- src/chomp/check/inline.rs | 157 ++++++++++++++++++++++++++++++++++++++++---- src/chomp/check/spanning.rs | 2 +- src/chomp/typed.rs | 2 +- 4 files changed, 151 insertions(+), 22 deletions(-) (limited to 'src/chomp') diff --git a/src/chomp/ast.rs b/src/chomp/ast.rs index 58d76c9..76d75ae 100644 --- a/src/chomp/ast.rs +++ b/src/chomp/ast.rs @@ -262,7 +262,7 @@ pub struct Parameter { } impl Parameter { - pub fn new(name: Name, index: usize) -> Self { + pub const fn new(name: Name, index: usize) -> Self { Self { name, index } } @@ -288,17 +288,17 @@ impl Display for Parameter { /// A macro invocation. #[derive(Clone, Debug)] pub struct Call { - pub name: Ident, + pub name: Name, pub args: Vec, pub span: Option, } impl Call { - pub fn new(name: Ident, args: Vec, span: Option) -> Self { + pub fn new(name: Name, args: Vec, span: Option) -> Self { Self { name, args, span } } - pub fn name(&self) -> &Ident { + pub fn name(&self) -> &Name { &self.name } @@ -487,14 +487,14 @@ impl From for Expression { #[derive(Clone, Debug)] pub struct Function { - pub name: Ident, + pub name: Name, pub params: usize, pub expr: Expression, pub span: Option, } impl Function { - pub const fn new(name: Ident, params: usize, expr: Expression, span: Option) -> Self { + pub const fn new(name: Name, params: usize, expr: Expression, span: Option) -> Self { Self { name, params, diff --git a/src/chomp/check/inline.rs b/src/chomp/check/inline.rs index a6a831c..43a2eb8 100644 --- a/src/chomp/check/inline.rs +++ b/src/chomp/check/inline.rs @@ -79,27 +79,156 @@ impl Folder for InlineCalls { #[cfg(test)] mod tests { - use proc_macro2::Span; - use syn::Ident; + use crate::chomp::Name; use super::*; - const OPT_NAME: &str = "opt"; - const OPT: Function = Function::new( - Ident::new(OPT_NAME, Span::call_site()), - 1, - Expression::Alt(Alt::new( - Epsilon::default().into(), + fn opt() -> Function { + Function::new( + Name::Spanless("opt".to_string()), + 1, + Expression::Alt(Alt::new( + Expression::Epsilon(None), + None, + Parameter::new(Name::Spanless("x".to_string()), 0).into(), + )), None, - Parameter::new(None, 0).into(), - )), - None, - ); + ) + } #[test] fn test_inline_absent() { let expr = Epsilon::default(); - let inlined = expr.fold(&mut InlineCalls::new(OPT)); - assert_eq!(inlined, Ok(Expression::from(Epsilon::default()))) + let inlined = expr.fold(&mut InlineCalls::new(opt())); + assert_eq!(inlined, Ok(Epsilon::default().into())) + } + + #[test] + fn test_inline_in_fix() { + let expr = Fix::new( + Name::Spanless("rec".to_string()), + Call::new( + Name::Spanless("opt".to_string()), + vec![Variable::new(Name::Spanless("rec".to_string()), 0).into()], + None, + ) + .into(), + None, + ); + let inlined = expr.fold(&mut InlineCalls::new(opt())); + assert_eq!( + inlined, + Ok(Fix::new( + Name::Spanless("rec".to_string()), + Alt::new( + Epsilon::default().into(), + None, + Variable::new(Name::Spanless("rec".to_string()), 0).into() + ) + .into(), + None + ) + .into()) + ) + } + + #[test] + fn test_inline_deepens_vars() { + let function = Function::new( + Name::Spanless("plus".into()), + 1, + Fix::new( + Name::Spanless("rec".to_string()), + Cat::new( + Parameter::new(Name::Spanless("x".to_string()), 0).into(), + None, + Variable::new(Name::Spanless("rec".to_string()), 0).into(), + ) + .into(), + None, + ) + .into(), + None, + ); + let expr = Fix::new( + Name::Spanless("var".to_string()), + Call::new( + Name::Spanless("plus".into()), + vec![Variable::new(Name::Spanless("var".to_string()), 0).into()], + None, + ) + .into(), + None + ); + let inlined = expr.fold(&mut InlineCalls::new(function)); + assert_eq!( + inlined, + Ok(Fix::new( + Name::Spanless("var".to_string()), + Fix::new( + Name::Spanless("rec".to_string()), + Cat::new( + Variable::new(Name::Spanless("var".to_string()), 1).into(), + None, + Variable::new(Name::Spanless("rec".to_string()), 0).into(), + ) + .into(), + None, + ) + .into(), + None + ) + .into()) + ) + } + + #[test] + fn test_inline_resets_vars() { + let function = Function::new( + Name::Spanless("plus".into()), + 1, + Cat::new( + Fix::new( + Name::Spanless("rec".to_string()), + Epsilon::default().into(), + None, + ) + .into(), + None, + Parameter::new(Name::Spanless("x".to_string()), 0).into(), + ) + .into(), + None, + ); + let expr = Fix::new( + Name::Spanless("var".to_string()), + Call::new( + Name::Spanless("plus".into()), + vec![Variable::new(Name::Spanless("var".to_string()), 0).into()], + None, + ) + .into(), + None + ); + let inlined = expr.fold(&mut InlineCalls::new(function)); + assert_eq!( + inlined, + Ok(Fix::new( + Name::Spanless("var".to_string()), + Cat::new( + Fix::new( + Name::Spanless("rec".to_string()), + Epsilon::default().into(), + None, + ) + .into(), + None, + Variable::new(Name::Spanless("var".to_string()), 0).into(), + ) + .into(), + None + ) + .into()) + ) } } diff --git a/src/chomp/check/spanning.rs b/src/chomp/check/spanning.rs index 91e593b..59c3811 100644 --- a/src/chomp/check/spanning.rs +++ b/src/chomp/check/spanning.rs @@ -1,4 +1,4 @@ -use proc_macro2::{Ident, Span}; +use proc_macro2::Span; use super::super::{ ast::{Alt, Call, Cat, Epsilon, Fix, Literal, Parameter, Variable}, diff --git a/src/chomp/typed.rs b/src/chomp/typed.rs index ab6cbc8..db07552 100644 --- a/src/chomp/typed.rs +++ b/src/chomp/typed.rs @@ -1,7 +1,7 @@ use std::hash::{Hash, Hasher}; use proc_macro2::Span; -use syn::{Ident, Token}; +use syn::Token; use super::{ ast, -- cgit v1.2.3