#[derive(Debug, Clone, PartialEq)] enum TokenType { Lparen, Rparen, Lbrace, Rbrace, Lbracket, Rbracket, Colon, Identifier(String), Eof, } #[derive(Debug, Clone, Copy)] struct Blame { line: usize, char: usize, } #[derive(Debug)] struct Token { token: TokenType, blame: Blame, } struct Lexer; impl Lexer { pub fn analyze(program: &str) -> Vec { let mut tokens: Vec = program .lines() .enumerate() .flat_map(|(line, text)| Self::lex_line(line, text)) .collect(); tokens.push(Token { token: TokenType::Eof, blame: Blame { line: tokens.len(), char: 0, }, }); tokens } fn lex_line(line: usize, text: &str) -> Vec { let mut tokens = Vec::new(); let mut ident_start: Option = None; let flush = |tokens: &mut Vec, ident_start: &mut Option, end: usize| { if let Some(start) = ident_start.take() { if end > start { tokens.push(Token { token: TokenType::Identifier(text[start..end].to_string()), blame: Blame { line, char: start }, }); } } }; for (i, c) in text.char_indices() { let singlechar = match c { '(' => Some(TokenType::Lparen), ')' => Some(TokenType::Rparen), '[' => Some(TokenType::Lbracket), ']' => Some(TokenType::Rbracket), '{' => Some(TokenType::Lbrace), '}' => Some(TokenType::Rbrace), ':' => Some(TokenType::Colon), _ => None, }; if c == ' ' || c == '\t' { flush(&mut tokens, &mut ident_start, i); continue; } if let Some(tt) = singlechar { flush(&mut tokens, &mut ident_start, i); tokens.push(Token { token: tt, blame: Blame { line, char: i }, }); continue; } if ident_start.is_none() { ident_start = Some(i); } } flush(&mut tokens, &mut ident_start, text.len()); tokens } } enum Atomic { Unit, Bool, Int, } enum SimpleType { Arrow((Box, Box)), Atom(Atomic), } type Identifier = String; struct Binding { name: Identifier, arg_type: Option, } enum ASTNode { Abstraction { binding: Binding, body: Box, }, Application((Box, Box)), Identifier(Identifier), } pub enum StepResult { Terminal(T), Continue, } pub trait Steppable { fn small_step(&mut self) -> StepResult; } pub struct Environment<'a, T> { parent_scope: Option<&'a Environment<'a, T>>, capture: Identifier, substitution: &'a T, } impl Environment<'_, T> { fn add<'a>(&'a self, identifier: Identifier, substitution: &'a T) -> Environment<'a, T> { return Environment { parent_scope: Some(&self), capture: identifier, substitution: substitution, }; } fn get<'a>(&'a self, identifier: Identifier) -> Option<&'a T> { if *identifier == *(self.capture) { return Some(self.substitution); } return match self.parent_scope { Some(scope) => (*scope).get(identifier), None => None, }; } fn root<'a>(identifier: Identifier, substitution: &'a T) -> Environment<'a, T> { return Environment { parent_scope: None, capture: identifier, substitution: substitution, }; } } fn main() { println!("Hello, world!"); } #[cfg(test)] mod tests { use super::*; #[test] fn test_env() { let ident = Identifier::from("ident"); let ident2 = Identifier::from("ident2"); let val: i32 = 1; let val2: i32 = 2; let val3: i32 = 3; let env = Environment::root(ident.clone(), &val); assert_eq!(env.get(ident.clone()), Some(&val)); let env2 = env.add(ident2.clone(), &val2); assert_eq!(env2.get(ident.clone()), Some(&val2)); let env3 = env2.add(ident.clone(), &val3); assert_eq!(env3.get(ident2.clone()), Some(&val2)); assert_eq!(env3.get(ident.clone()), Some(&val3)); assert_eq!(env.get(ident.clone()), Some(&val)); } }