From 3903cbdecd344a2b6082f6277fcd63c1be1a0fbc Mon Sep 17 00:00:00 2001 From: Michael Sippel Date: Wed, 1 May 2024 11:54:55 +0200 Subject: [PATCH] wip sugar --- src/dict.rs | 19 ++++-- src/lexer.rs | 11 +++- src/lib.rs | 1 + src/parser.rs | 53 +++++++++++++--- src/sugar.rs | 134 ++++++++++++++++++++++++++++++++++++++++ src/test/mod.rs | 1 + src/test/parser.rs | 84 ++++++++++++------------- src/test/sugar.rs | 10 +++ src/test/unification.rs | 4 +- 9 files changed, 257 insertions(+), 60 deletions(-) create mode 100644 src/sugar.rs create mode 100644 src/test/sugar.rs diff --git a/src/dict.rs b/src/dict.rs index 83b63ee..9b751b9 100644 --- a/src/dict.rs +++ b/src/dict.rs @@ -1,8 +1,11 @@ -use crate::bimap::Bimap; +use crate::{ + bimap::Bimap, + sugar::SUGARID_LIMIT +}; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\ -#[derive(Eq, PartialEq, Hash, Clone, Debug)] +#[derive(Eq, PartialEq, Hash, Clone, Copy, Debug)] pub enum TypeID { Fun(u64), Var(u64) @@ -20,11 +23,19 @@ pub struct TypeDict { impl TypeDict { pub fn new() -> Self { - TypeDict { + let mut dict = TypeDict { typenames: Bimap::new(), type_lit_counter: 0, type_var_counter: 0, - } + }; + + dict.add_typename("Seq".into()); + dict.add_typename("Enum".into()); + dict.add_typename("Struct".into()); + + assert_eq!( dict.type_lit_counter, SUGARID_LIMIT ); + + dict } pub fn add_varname(&mut self, tn: String) -> TypeID { diff --git a/src/lexer.rs b/src/lexer.rs index 8c56a0d..62b8efe 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -6,9 +6,9 @@ pub enum LadderTypeToken { Symbol( String ), Char( char ), Num( i64 ), - Open, - Close, - Ladder, + Open, OpenSeq, OpenStruct, + Close, CloseSeq, CloseStruct, + Ladder, Enum } #[derive(PartialEq, Eq, Clone, Debug)] @@ -75,6 +75,11 @@ where It: Iterator match c { '<' => { self.chars.next(); return Some(Ok(LadderTypeToken::Open)); }, '>' => { self.chars.next(); return Some(Ok(LadderTypeToken::Close)); }, + '[' => { self.chars.next(); return Some(Ok(LadderTypeToken::OpenSeq)); }, + ']' => { self.chars.next(); return Some(Ok(LadderTypeToken::CloseSeq)); }, + '{' => { self.chars.next(); return Some(Ok(LadderTypeToken::OpenStruct)); }, + '}' => { self.chars.next(); return Some(Ok(LadderTypeToken::CloseStruct)); }, + '|' => { self.chars.next(); return Some(Ok(LadderTypeToken::Enum)); }, '~' => { self.chars.next(); return Some(Ok(LadderTypeToken::Ladder)); }, '\'' => { self.chars.next(); state = LexerState::Char(None); }, c => { diff --git a/src/lib.rs b/src/lib.rs index 1a270cc..cf5487d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ pub mod lexer; pub mod parser; pub mod unparser; pub mod curry; +pub mod sugar; pub mod lnf; pub mod subtype; pub mod unification; diff --git a/src/parser.rs b/src/parser.rs index 85ff9b4..87ed5c1 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3,6 +3,7 @@ use { crate::{ dict::*, term::*, + sugar::*, lexer::* } }; @@ -21,7 +22,7 @@ pub enum ParseError { //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\ impl TypeDict { - pub fn parse(&mut self, s: &str) -> Result { + pub fn parse(&mut self, s: &str) -> Result { let mut tokens = LadderTypeLexer::from(s.chars()).peekable(); match self.parse_ladder(&mut tokens) { @@ -36,7 +37,7 @@ impl TypeDict { } } - fn parse_app(&mut self, tokens: &mut Peekable>) -> Result + fn parse_app(&mut self, tokens: &mut Peekable>) -> Result where It: Iterator { let mut args = Vec::new(); @@ -44,7 +45,11 @@ impl TypeDict { match tok { Ok(LadderTypeToken::Close) => { tokens.next(); - return Ok(TypeTerm::App(args)); + return Ok(SugaredTypeTerm::App(args)); + } + Ok(LadderTypeToken::CloseSeq) | + Ok(LadderTypeToken::CloseStruct) => { + return Err(ParseError::UnexpectedToken) } _ => { match self.parse_ladder(tokens) { @@ -57,29 +62,59 @@ impl TypeDict { Err(ParseError::UnexpectedEnd) } - fn parse_rung(&mut self, tokens: &mut Peekable>) -> Result + fn parse_seq(&mut self, tokens: &mut Peekable>) -> Result + where It: Iterator + { + let mut pattern = Vec::new(); + while let Some(tok) = tokens.peek() { + match tok { + Ok(LadderTypeToken::CloseSeq) => { + tokens.next(); + return Ok(SugaredTypeTerm::Seq(pattern)); + } + Ok(LadderTypeToken::Close) | + Ok(LadderTypeToken::CloseStruct) => { + return Err(ParseError::UnexpectedToken) + } + _ => { + match self.parse_ladder(tokens) { + Ok(a) => { pattern.push(a); } + Err(err) => { return Err(err); } + } + } + } + } + Err(ParseError::UnexpectedEnd) + } + + fn parse_rung(&mut self, tokens: &mut Peekable>) -> Result where It: Iterator { match tokens.next() { Some(Ok(LadderTypeToken::Open)) => self.parse_app(tokens), + Some(Ok(LadderTypeToken::OpenSeq)) => self.parse_app(tokens), + Some(Ok(LadderTypeToken::OpenStruct)) => self.parse_app(tokens), + Some(Ok(LadderTypeToken::Enum)) => self.parse_app(tokens), Some(Ok(LadderTypeToken::Close)) => Err(ParseError::UnexpectedClose), + Some(Ok(LadderTypeToken::CloseStruct)) => Err(ParseError::UnexpectedToken), + Some(Ok(LadderTypeToken::CloseSeq)) => Err(ParseError::UnexpectedToken), Some(Ok(LadderTypeToken::Ladder)) => Err(ParseError::UnexpectedLadder), Some(Ok(LadderTypeToken::Symbol(s))) => - Ok(TypeTerm::TypeID( + Ok(SugaredTypeTerm::TypeID( if let Some(tyid) = self.get_typeid(&s) { tyid } else { self.add_typename(s) } )), - Some(Ok(LadderTypeToken::Char(c))) => Ok(TypeTerm::Char(c)), - Some(Ok(LadderTypeToken::Num(n))) => Ok(TypeTerm::Num(n)), + Some(Ok(LadderTypeToken::Char(c))) => Ok(SugaredTypeTerm::Char(c)), + Some(Ok(LadderTypeToken::Num(n))) => Ok(SugaredTypeTerm::Num(n)), Some(Err(err)) => Err(ParseError::LexError(err)), None => Err(ParseError::UnexpectedEnd) } } - fn parse_ladder(&mut self, tokens: &mut Peekable>) -> Result + fn parse_ladder(&mut self, tokens: &mut Peekable>) -> Result where It: Iterator { let mut rungs = Vec::new(); @@ -115,7 +150,7 @@ impl TypeDict { match rungs.len() { 0 => Err(ParseError::UnexpectedEnd), 1 => Ok(rungs[0].clone()), - _ => Ok(TypeTerm::Ladder(rungs)), + _ => Ok(SugaredTypeTerm::Ladder(rungs)), } } } diff --git a/src/sugar.rs b/src/sugar.rs new file mode 100644 index 0000000..98c1c7b --- /dev/null +++ b/src/sugar.rs @@ -0,0 +1,134 @@ +use crate::{ + TypeTerm, + TypeID +}; + +pub const SEQ_SUGARID : TypeID = TypeID::Fun(0); +pub const ENUM_SUGARID : TypeID = TypeID::Fun(1); +pub const STRUCT_SUGARID : TypeID = TypeID::Fun(2); +pub const SUGARID_LIMIT : u64 = 3; + +#[derive(Clone)] +pub enum SugaredTypeTerm { + /* Atomic Terms */ + + // Base types from dictionary + TypeID(TypeID), + + // Literals + Num(i64), + Char(char), + + + + /* Complex Terms */ + + // Type Parameters + // avoid currying to save space & indirection + App(Vec< SugaredTypeTerm >), + + // Type Ladders + Ladder(Vec< SugaredTypeTerm >), + + + /* Sugar Terms */ + Seq( Vec ), + Enum( Vec ), + Struct( Vec ) +} + + +#[derive(Clone)] +struct TypeAssignment { + id: Option, + ty: TypeTerm, +} + +#[derive(Clone)] +struct LayoutSugar { + Seq( Vec ), + Enum( Vec ), + Struct( Vec ) +} + + + +impl SugaredTypeTerm { + pub fn desugar(self) -> TypeTerm { + match self { + SugaredTypeTerm::TypeID(id) => TypeTerm::TypeID(id), + SugaredTypeTerm::Num(n) => TypeTerm::Num(n), + SugaredTypeTerm::Char(c) => TypeTerm::Char(c), + SugaredTypeTerm::App(params) => TypeTerm::App(params.into_iter().map(|p| p.desugar()).collect()), + SugaredTypeTerm::Ladder(rungs) => TypeTerm::Ladder(rungs.into_iter().map(|p| p.desugar()).collect()), + SugaredTypeTerm::Seq(pattern) => { + let mut params : Vec = pattern.into_iter().map(|p| p.desugar()).collect(); + params.insert(0, TypeTerm::TypeID(SEQ_SUGARID)); + TypeTerm::App(params) + } + SugaredTypeTerm::Enum(options) => { + let mut params : Vec = options.into_iter().map(|o| o.desugar()).collect(); + params.insert(0, TypeTerm::TypeID(ENUM_SUGARID)); + TypeTerm::App(params) + } + SugaredTypeTerm::Struct(members) => { + let mut params : Vec = members.into_iter().map(|m| m.desugar()).collect(); + params.insert(0, TypeTerm::TypeID(STRUCT_SUGARID)); + TypeTerm::App(params) + } + } + } + + // normalize any unsugared parts into sugared form + pub fn sugar(self) -> SugaredTypeTerm { + // todo: optimize + self.desugar().sugar() + } +} + +impl TypeTerm { + pub fn sugar(self) -> SugaredTypeTerm { + match self { + TypeTerm::TypeID(id) => SugaredTypeTerm::TypeID(id), + TypeTerm::Num(n) => SugaredTypeTerm::Num(n), + TypeTerm::Char(c) => SugaredTypeTerm::Char(c), + TypeTerm::App(mut params) => { + if params.len() > 0 { + let prim = params.remove(0); + match prim { + TypeTerm::TypeID( SEQ_SUGARID ) => + SugaredTypeTerm::Seq( + params + .into_iter() + .map(|p| p.sugar()) + .collect() + ), + + TypeTerm::TypeID( ENUM_SUGARID ) => + SugaredTypeTerm::Enum( + params + .into_iter() + .map(|p| p.sugar()) + .collect() + ), + TypeTerm::TypeID( STRUCT_SUGARID ) => + SugaredTypeTerm::Struct( + params + .into_iter() + .map(|p| p.sugar()) + .collect() + ), + other => SugaredTypeTerm::App( + params.into_iter().map(|p| p.sugar()).collect() + ) + } + } else { + SugaredTypeTerm::App(vec![]) + } + }, + TypeTerm::Ladder(rungs) => { + SugaredTypeTerm::Ladder(rungs.into_iter().map(|r| r.sugar()).collect()) + } + } + } +} diff --git a/src/test/mod.rs b/src/test/mod.rs index d116412..ea52c7d 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -2,6 +2,7 @@ pub mod lexer; pub mod parser; pub mod curry; +pub mod sugar; pub mod lnf; pub mod subtype; pub mod substitution; diff --git a/src/test/parser.rs b/src/test/parser.rs index 1166229..49deb7c 100644 --- a/src/test/parser.rs +++ b/src/test/parser.rs @@ -1,6 +1,6 @@ use { - crate::{term::*, dict::*, parser::*} + crate::{term::*, dict::*, parser::*, sugar::SUGARID_LIMIT} }; //<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\ @@ -17,7 +17,7 @@ fn test_parser_id() { ); assert_eq!( - Ok(TypeTerm::TypeID(TypeID::Fun(0))), + Ok(TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+0))), dict.parse("A") ); } @@ -43,16 +43,16 @@ fn test_parser_app() { assert_eq!( TypeDict::new().parse(""), Ok(TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(0)), - TypeTerm::TypeID(TypeID::Fun(1)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+0)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+1)), ])) ); assert_eq!( TypeDict::new().parse(""), Ok(TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(0)), - TypeTerm::TypeID(TypeID::Fun(1)), - TypeTerm::TypeID(TypeID::Fun(2)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+0)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+1)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+2)), ])) ); } @@ -78,16 +78,16 @@ fn test_parser_ladder() { assert_eq!( TypeDict::new().parse("A~B"), Ok(TypeTerm::Ladder(vec![ - TypeTerm::TypeID(TypeID::Fun(0)), - TypeTerm::TypeID(TypeID::Fun(1)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+0)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+1)), ])) ); assert_eq!( TypeDict::new().parse("A~B~C"), Ok(TypeTerm::Ladder(vec![ - TypeTerm::TypeID(TypeID::Fun(0)), - TypeTerm::TypeID(TypeID::Fun(1)), - TypeTerm::TypeID(TypeID::Fun(2)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+0)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+1)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+2)), ])) ); } @@ -98,12 +98,12 @@ fn test_parser_ladder_outside() { TypeDict::new().parse("~C"), Ok(TypeTerm::Ladder(vec![ TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(0)), - TypeTerm::TypeID(TypeID::Fun(1)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+0)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+1)), ]), - TypeTerm::TypeID(TypeID::Fun(2)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+2)), ])) - ); + ); } #[test] @@ -111,10 +111,10 @@ fn test_parser_ladder_inside() { assert_eq!( TypeDict::new().parse(""), Ok(TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(0)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+0)), TypeTerm::Ladder(vec![ - TypeTerm::TypeID(TypeID::Fun(1)), - TypeTerm::TypeID(TypeID::Fun(2)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+1)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+2)), ]) ])) ); @@ -125,12 +125,12 @@ fn test_parser_ladder_between() { assert_eq!( TypeDict::new().parse(">"), Ok(TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(0)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+0)), TypeTerm::Ladder(vec![ - TypeTerm::TypeID(TypeID::Fun(1)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+1)), TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(2)), - TypeTerm::TypeID(TypeID::Fun(3)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+2)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+3)), ]) ]) ])) @@ -156,48 +156,48 @@ fn test_parser_ladder_large() { Ok( TypeTerm::Ladder(vec![ TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(0)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+0)), TypeTerm::Ladder(vec![ - TypeTerm::TypeID(TypeID::Fun(1)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+1)), TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(2)), - TypeTerm::TypeID(TypeID::Fun(3)) + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+2)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+3)) ]), TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(4)), - TypeTerm::TypeID(TypeID::Fun(5)) + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+4)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+5)) ]), - TypeTerm::TypeID(TypeID::Fun(6)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+6)), TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(7)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+7)), TypeTerm::Num(10), - TypeTerm::TypeID(TypeID::Fun(8)) + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+8)) ]), TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(0)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+0)), TypeTerm::Ladder(vec![ TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(9)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+9)), TypeTerm::Num(10) ]), - TypeTerm::TypeID(TypeID::Fun(10)) + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+10)) ]) ]) ]) ]), TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(11)), - TypeTerm::TypeID(TypeID::Fun(10)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+11)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+10)), TypeTerm::Char(':') ]), TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(0)), - TypeTerm::TypeID(TypeID::Fun(10)) + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+0)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+10)) ]), - TypeTerm::TypeID(TypeID::Fun(12)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+12)), TypeTerm::App(vec![ - TypeTerm::TypeID(TypeID::Fun(0)), - TypeTerm::TypeID(TypeID::Fun(13)) + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+0)), + TypeTerm::TypeID(TypeID::Fun(SUGARID_LIMIT+13)) ]) ]) ) diff --git a/src/test/sugar.rs b/src/test/sugar.rs new file mode 100644 index 0000000..c6a9768 --- /dev/null +++ b/src/test/sugar.rs @@ -0,0 +1,10 @@ + +#[test] +fn test_sugar() { + + let mut dict = crate::TypeDict::new(); + + +} + + diff --git a/src/test/unification.rs b/src/test/unification.rs index 34d355d..19c6768 100644 --- a/src/test/unification.rs +++ b/src/test/unification.rs @@ -13,8 +13,8 @@ fn test_unify(ts1: &str, ts2: &str, expect_unificator: bool) { dict.add_varname(String::from("V")); dict.add_varname(String::from("W")); - let mut t1 = dict.parse(ts1).unwrap(); - let mut t2 = dict.parse(ts2).unwrap(); + let mut t1 = dict.parse(ts1).unwrap().desugar(); + let mut t2 = dict.parse(ts2).unwrap().desugar(); let σ = crate::unify( &t1, &t2 ); if expect_unificator {