diff options
| author | Elizabeth Alexander Hunt <me@liz.coffee> | 2026-08-03 09:18:06 -0700 |
|---|---|---|
| committer | Elizabeth Alexander Hunt <me@liz.coffee> | 2026-08-03 09:18:06 -0700 |
| commit | fc2844ae88c85f082b47630b92a55bca3ff285b1 (patch) | |
| tree | 4a6cca7892459ece38bf72b61352d4fc1bb239e0 /src/main.rs | |
| download | gock-fc2844ae88c85f082b47630b92a55bca3ff285b1.tar.gz gock-fc2844ae88c85f082b47630b92a55bca3ff285b1.zip | |
Init
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..7ec318a --- /dev/null +++ b/src/main.rs @@ -0,0 +1,190 @@ +#[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<Token> { + let mut tokens: Vec<Token> = 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<Token> { + let mut tokens = Vec::new(); + let mut ident_start: Option<usize> = None; + + let flush = |tokens: &mut Vec<Token>, ident_start: &mut Option<usize>, 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<SimpleType>, Box<SimpleType>)), + Atom(Atomic), +} + +type Identifier = String; + +struct Binding { + name: Identifier, + arg_type: Option<SimpleType>, +} + +enum ASTNode { + Abstraction { + binding: Binding, + body: Box<ASTNode>, + }, + Application((Box<ASTNode>, Box<ASTNode>)), + Identifier(Identifier), +} + +pub enum StepResult<T> { + Terminal(T), + Continue, +} + +pub trait Steppable<T> { + fn small_step(&mut self) -> StepResult<T>; +} + +pub struct Environment<'a, T> { + parent_scope: Option<&'a Environment<'a, T>>, + capture: Identifier, + substitution: &'a T, +} + +impl<T> 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)); + } +} |
