From 24ff5f311f6c797681be1cff0fb2d0b75c0f848f Mon Sep 17 00:00:00 2001 From: Greg Brown Date: Thu, 14 Jan 2021 14:37:27 +0000 Subject: Finish AutoChomp --- src/nibble/convert.rs | 36 +++++++++++++++++++++--------------- src/nibble/cst.rs | 14 +++++++++----- src/nibble/mod.rs | 48 ------------------------------------------------ 3 files changed, 30 insertions(+), 68 deletions(-) (limited to 'src/nibble') diff --git a/src/nibble/convert.rs b/src/nibble/convert.rs index 5cbf5e2..e3c8bfc 100644 --- a/src/nibble/convert.rs +++ b/src/nibble/convert.rs @@ -1,8 +1,12 @@ use std::{collections::HashMap, fmt}; +use proc_macro2::Span; use syn::punctuated::Pair; -use crate::chomp::ast::{self, NamedExpression}; +use crate::chomp::{ + ast::{self, NamedExpression}, + Name, +}; use super::cst::{Alt, Call, Cat, Fix, Ident, Labelled, ParenExpression, Term}; @@ -20,7 +24,7 @@ pub struct Context { } impl Context { - pub fn new>(globals: &[Ident], params: I) -> Self { + pub fn new>(globals: &[Name], params: I) -> Self { let mut names = HashMap::new(); for global in globals { names.insert(global.to_string(), Binding::Global); @@ -33,7 +37,7 @@ impl Context { Self { names, vars: 0 } } - pub fn lookup(&self, name: &Ident) -> Option { + pub fn lookup(&self, name: &Name) -> Option { // we make variable binding cheaper by inserting wrong and pulling right. match self.names.get(&name.to_string()).copied() { Some(Binding::Variable(index)) => Some(Binding::Variable(self.vars - index - 1)), @@ -41,7 +45,7 @@ impl Context { } } - pub fn with_variable R, R>(&mut self, name: &Ident, f: F) -> R { + pub fn with_variable R, R>(&mut self, name: &Name, f: F) -> R { let old = self .names .insert(name.to_string(), Binding::Variable(self.vars)); @@ -64,13 +68,14 @@ impl Context { #[derive(Clone, Debug)] pub enum ConvertError { - UndeclaredName(Ident), + UndeclaredName(Name), } impl From for syn::Error { fn from(e: ConvertError) -> Self { match e { - ConvertError::UndeclaredName(ident) => { + ConvertError::UndeclaredName(name) => { + let ident = name.into_ident(Span::call_site()); Self::new(ident.span(), "undeclared name") } } @@ -80,12 +85,12 @@ impl From for syn::Error { impl fmt::Display for ConvertError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::UndeclaredName(i) => { - let start = i.span().start(); + Self::UndeclaredName(name) => { + let start = name.span().unwrap_or_else(Span::call_site).start(); write!( f, "{}:{}: undeclared name `{}'", - start.line, start.column, i + start.line, start.column, name ) } } @@ -101,12 +106,12 @@ pub trait Convert { impl Convert for Ident { fn convert(self, context: &mut Context) -> Result { let span = Some(self.span()); - let binding = match context.lookup(&self) { - Some(b) => b, - None => return Err(ConvertError::UndeclaredName(self)), - }; let name = self.into(); + let binding = context + .lookup(&name) + .ok_or_else(|| ConvertError::UndeclaredName(name.clone()))?; + Ok(match binding { Binding::Variable(index) => NamedExpression { name: Some(name), @@ -155,11 +160,12 @@ impl Convert for Fix { fn convert(self, context: &mut Context) -> Result { let span = self.span(); let expr = self.expr; - let inner = context.with_variable(&self.arg, |context| expr.convert(context))?; + let arg = self.arg.into(); + let inner = context.with_variable(&arg, |context| expr.convert(context))?; Ok(NamedExpression { name: None, expr: ast::Fix { - arg: Some(self.arg.into()), + arg: Some(arg), inner: Box::new(inner), } .into(), diff --git a/src/nibble/cst.rs b/src/nibble/cst.rs index f6fa51b..2fcc99f 100644 --- a/src/nibble/cst.rs +++ b/src/nibble/cst.rs @@ -9,7 +9,7 @@ use syn::{ LitStr, Token, }; -use crate::chomp::{Name, ast}; +use crate::chomp::{ast, Name}; use super::convert::{Context, Convert, ConvertError}; @@ -332,15 +332,19 @@ impl File { let mut map = Vec::new(); for stmt in self.lets { let span = stmt.span(); - let params = stmt.args.into_iter().flat_map(|args| args.into_iter()); + let name: Name = stmt.name.into(); + let params = stmt + .args + .into_iter() + .flat_map(|args| args.into_iter()) + .map(Name::from); let mut context = Context::new(&names, params.clone()); - names.push(stmt.name.clone()); let mut expr = stmt.expr.convert(&mut context)?; - let name: Name = stmt.name.into(); + names.push(name.clone()); expr.name = Some(name.clone()); map.push(ast::Function { name, - params: params.map(|name| Some(name.into())).collect(), + params: params.map(Some).collect(), expr, span, }); diff --git a/src/nibble/mod.rs b/src/nibble/mod.rs index 14791fd..41e895c 100644 --- a/src/nibble/mod.rs +++ b/src/nibble/mod.rs @@ -1,50 +1,2 @@ pub mod convert; pub mod cst; -// impl File { -// /// Returns function list and the goal. The function list consists of an -// /// [`Ident`], the converted [`ast::Expression`] and the number of arguments. -// pub fn convert(self) -> (Vec<(Ident, ast::Expression, usize)>, ast::Expression) { -// let mut context = Context::new(); -// let map = self -// .lets -// .into_iter() -// .map(|stmt| { -// let count = stmt.args.as_ref().map(ArgList::len).unwrap_or_default(); -// context.set_variables( -// stmt.args -// .into_iter() -// .flat_map(|args| args.into_iter().map(|arg| arg.to_string())), -// ); -// (stmt.name, stmt.expr.convert(&mut context), count) -// }) -// .collect(); -// let goal = self.goal.expr.convert(&mut context); -// (map, goal) -// } -// } - -// #[cfg(test)] -// mod tests { -// use super::{Epsilon, Ident, Literal}; -// use syn::parse_str; - -// #[test] -// fn parse_epsilon() { -// assert!(parse_str::("_").is_ok()); -// } - -// #[test] -// fn parse_ident() { -// assert_eq!(parse_str::("x").unwrap().to_string(), "x"); -// assert_eq!(parse_str::("x_yz").unwrap().to_string(), "x_yz"); -// assert_eq!(parse_str::("a123").unwrap().to_string(), "a123"); -// assert_eq!(parse_str::("𝒢𝒢").unwrap().to_string(), "𝒢𝒢"); -// assert!(parse_str::("1").is_err()); -// assert!(parse_str::("_").is_err()); -// } - -// #[test] -// fn parse_literal() { -// assert_eq!(parse_str::(r#""hello""#).unwrap().value(), "hello") -// } -// } -- cgit v1.2.3