summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGreg Brown <gmb60@cam.ac.uk>2021-01-14 14:37:27 +0000
committerGreg Brown <gmb60@cam.ac.uk>2021-01-14 14:37:27 +0000
commit24ff5f311f6c797681be1cff0fb2d0b75c0f848f (patch)
treee4cc216813f2a9c40dc496148dbd4eeed83fb87c /src
parent3d13ff5a0f40b750f754898ab4568d4afc0f1a9e (diff)
Finish AutoChomp
Diffstat (limited to 'src')
-rw-r--r--src/main.rs25
-rw-r--r--src/nibble/convert.rs36
-rw-r--r--src/nibble/cst.rs14
-rw-r--r--src/nibble/mod.rs48
4 files changed, 43 insertions, 80 deletions
diff --git a/src/main.rs b/src/main.rs
index 100bb68..10156e6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,21 +1,22 @@
use std::{
error::Error,
- fmt::Display,
io::{self, Read, Write},
process::exit,
};
-use chomp::{chomp::{ast::substitute::InlineCalls, typed::{TypeInfer, context::Context, lower::{Backend, GenerateCode}}, visit::Visitable}, lower::RustBackend, nibble::cst::File};
-
-#[derive(Debug)]
-struct UndecVar;
-
-impl Display for UndecVar {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "Undeclared variable somewhere.")
- }
-}
-impl Error for UndecVar {}
+use chomp::{
+ chomp::{
+ ast::substitute::InlineCalls,
+ typed::{
+ context::Context,
+ lower::{Backend, GenerateCode},
+ TypeInfer,
+ },
+ visit::Visitable,
+ },
+ lower::RustBackend,
+ nibble::cst::File,
+};
fn main() {
let mut input = String::new();
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<I: IntoIterator<Item = Ident>>(globals: &[Ident], params: I) -> Self {
+ pub fn new<I: IntoIterator<Item = Name>>(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<Binding> {
+ pub fn lookup(&self, name: &Name) -> Option<Binding> {
// 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<F: FnOnce(&mut Self) -> R, R>(&mut self, name: &Ident, f: F) -> R {
+ pub fn with_variable<F: FnOnce(&mut Self) -> 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<ConvertError> 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<ConvertError> 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<NamedExpression, ConvertError> {
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<NamedExpression, ConvertError> {
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::<Epsilon>("_").is_ok());
-// }
-
-// #[test]
-// fn parse_ident() {
-// assert_eq!(parse_str::<Ident>("x").unwrap().to_string(), "x");
-// assert_eq!(parse_str::<Ident>("x_yz").unwrap().to_string(), "x_yz");
-// assert_eq!(parse_str::<Ident>("a123").unwrap().to_string(), "a123");
-// assert_eq!(parse_str::<Ident>("𝒢𝒢").unwrap().to_string(), "𝒢𝒢");
-// assert!(parse_str::<Ident>("1").is_err());
-// assert!(parse_str::<Ident>("_").is_err());
-// }
-
-// #[test]
-// fn parse_literal() {
-// assert_eq!(parse_str::<Literal>(r#""hello""#).unwrap().value(), "hello")
-// }
-// }