summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElizabeth Alexander Hunt <lizhunt@amazon.com>2026-08-13 11:49:40 -0700
committerElizabeth Alexander Hunt <lizhunt@amazon.com>2026-08-13 11:49:40 -0700
commitca16123c89f5731e2a3096d3780e641d071280d6 (patch)
tree411c42a91890408fd8a74c95d073389c50531986
parent0e03b779e48cf7c96b6fc351c1f4b3ed7a76d01c (diff)
downloadgock-ca16123c89f5731e2a3096d3780e641d071280d6.tar.gz
gock-ca16123c89f5731e2a3096d3780e641d071280d6.zip
Stuff
-rw-r--r--src/main.rs167
1 files changed, 131 insertions, 36 deletions
diff --git a/src/main.rs b/src/main.rs
index 660a835..7736a08 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,5 @@
+use std::fmt;
+
#[derive(Debug, Clone, PartialEq, Eq)]
enum TokenType {
Lparen,
@@ -21,7 +23,7 @@ struct Blame {
char: usize,
}
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Debug, PartialEq, Eq, Clone)]
struct Token {
token: TokenType,
blame: Blame,
@@ -112,7 +114,7 @@ enum Atomic {
}
enum SimpleType {
- Arrow((Box<SimpleType>, Box<SimpleType>)),
+ Arrow(Box<(SimpleType, SimpleType)>),
Atom(Atomic),
}
@@ -120,7 +122,7 @@ type Identifier = String;
struct Binding {
name: Identifier,
- arg_type: Option<Box<TypeDeclaration>>, // TODO: Gradual typing!
+ arg_type: Option<TypeDeclaration>, // TODO: Gradual typing!
}
enum TypeDeclaration {
@@ -133,8 +135,10 @@ struct Assignment {
computation: Computation,
}
+struct Arguments(Vec<Binding>);
+
struct Abstraction {
- arguments: Vec<Binding>,
+ arguments: Arguments,
body: Box<Computation>,
}
@@ -142,6 +146,13 @@ struct Application {
apply: Box<(Computation, Computation)>,
}
+struct Assignments(Vec<Assignment>);
+
+struct LetStatement {
+ assignments: Assignments,
+ body: Box<Computation>,
+}
+
enum Computation {
Application(Application),
Abstraction(Abstraction),
@@ -149,14 +160,70 @@ enum Computation {
LetStatement(LetStatement), // TODO: I think we can flatten these to just a long Abstraction
}
-enum ASTNode {
- Binding(Binding),
- TypeDeclaration(TypeDeclaration),
- Assignment(Assignment),
- Abstraction(Abstraction),
- Application(Application),
- Computation(Computation),
- LetStatement(LetStatement),
+impl fmt::Display for Arguments {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "Arguments(")?;
+ for v in &self.0 {
+ write!(f, "\t{}", v)?;
+ }
+ write!(f, ")")
+ }
+}
+
+impl fmt::Display for Assignment {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "Assignment({}, {})", self.binding, self.computation)
+ }
+}
+
+impl fmt::Display for Assignments {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "Assignments(")?;
+ for v in &self.0 {
+ write!(f, "\t{}", v)?;
+ }
+ write!(f, ")")
+ }
+}
+
+impl fmt::Display for Binding {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "Binding({}, {})", self.name, "TYPE TODO")
+ }
+}
+
+impl fmt::Display for TypeDeclaration {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ TypeDeclaration::BaseType(name) => write!(f, "BaseType({})", name),
+ TypeDeclaration::Arrow(arrow) => write!(f, "Arrow({}, {})", (**arrow).0, (**arrow).1),
+ }
+ }
+}
+
+impl fmt::Display for Computation {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Computation::Identifier(name) => write!(f, "Identifier({})", name),
+ Computation::Application(application) => write!(
+ f,
+ "Application({}, {})",
+ (*application.apply).0,
+ (*application.apply).1
+ ),
+ Computation::Abstraction(abstraction) => write!(
+ f,
+ "Abstraction({}, {})",
+ (abstraction.arguments),
+ (*abstraction.body)
+ ),
+ Computation::LetStatement(let_statement) => write!(
+ f,
+ "LetStatement({}, {})",
+ let_statement.assignments, let_statement.body
+ ),
+ }
+ }
}
struct Parser {
@@ -174,7 +241,7 @@ impl Parser {
fn peek(&mut self) -> Result<&Token, ParsingFailure> {
return self
.tokens
- .get(self.position + 1)
+ .get(self.position)
.ok_or(ParsingFailure::PastTokens);
}
@@ -213,7 +280,24 @@ impl Parser {
return self.consume_if_match(f, String::from("Unexpected error"));
}
- fn parse_type_declaration(&mut self) -> Result<TypeDeclaration, ParsingFailure> {}
+ fn parse_type_declaration(&mut self) -> Result<TypeDeclaration, ParsingFailure> {
+ self.consume_if_match_nomsg(|it| (*it).token == TokenType::Lparen)?;
+ let my_type = self.consume_if_and_map(
+ |it| match ((*it).token).clone() {
+ // unfortunately, gotta clone to make the borrow checker happy. maybe i'll come back to this :3
+ TokenType::Identifier(name) => Some(name.clone()),
+ _ => None,
+ },
+ String::from("BWA"),
+ );
+ if let Ok(name) = my_type {
+ return Ok(TypeDeclaration::BaseType(name as Identifier));
+ }
+ let left = self.parse_type_declaration()?;
+ self.consume_if_match_nomsg(|it| (*it).token == TokenType::Arrow)?;
+ let right = self.parse_type_declaration()?;
+ return Ok(TypeDeclaration::Arrow(Box::new((left, right))));
+ }
fn parse_binding(&mut self) -> Result<Binding, ParsingFailure> {
let name = self.consume_if_and_map(
@@ -231,7 +315,7 @@ impl Parser {
if let Ok(type_decl) = self.parse_type_declaration() {
return Ok(Binding {
name,
- arg_type: Some(Box::new(type_decl)),
+ arg_type: Some(type_decl),
});
}
return Err(ParsingFailure::Blame(
@@ -259,15 +343,19 @@ impl Parser {
}
fn parse_let_statement(&mut self) -> Result<LetStatement, ParsingFailure> {
- self.consume_if_match_nomsg(|it| (*it).token == TokenType::Identifier(String::from("let")));
+ self.consume_if_match_nomsg(|it| {
+ (*it).token == TokenType::Identifier(String::from("let"))
+ })?;
let mut assignments: Vec<Assignment> = Vec::new();
loop {
if let Ok(_done) = self.consume_if_match_nomsg(|it| {
(*it).token == TokenType::Identifier(String::from("in"))
}) {
- let body = self.parse_computation()?;
-
- return Ok(LetStatement { assignments });
+ let body = Box::new(self.parse_computation()?);
+ return Ok(LetStatement {
+ assignments: Assignments(assignments),
+ body,
+ });
}
let assignment = self.parse_assignment()?;
self.consume_if_match_nomsg(|it| (*it).token == TokenType::Semicolon)?;
@@ -279,16 +367,16 @@ impl Parser {
self.consume_if_match_nomsg(|it| (*it).token == TokenType::Lbracket)?;
let mut arguments: Vec<Binding> = Vec::new();
loop {
- if let Ok(_done) = self.consume_if_match_nomsg(|it| (*it).token == TokenType::Rbracket)
- {
- return Ok(Abstraction {
- arguments,
- body: Box::new(self.parse_computation()?),
- });
- }
arguments.push(self.parse_binding()?);
- self.consume_if_match_nomsg(|it| (*it).token == TokenType::Comma);
+ if let Err(_) = self.consume_if_match_nomsg(|it| (*it).token == TokenType::Comma) {
+ break;
+ }
}
+ self.consume_if_match_nomsg(|it| (*it).token == TokenType::Rbracket)?;
+ return Ok(Abstraction {
+ arguments: Arguments(arguments),
+ body: Box::new(self.parse_computation()?),
+ });
}
fn parse_application(&mut self) -> Result<Application, ParsingFailure> {
@@ -302,13 +390,21 @@ impl Parser {
}
fn parse_computation(&mut self) -> Result<Computation, ParsingFailure> {
- let next = *(self.peek()?);
- match next.token {
+ let next = self.peek()?.clone();
+ return match next.token {
TokenType::Identifier(identifier) => {
- Computation::LetStatement(self.parse_let_statement()?)
+ if identifier == String::from("let") {
+ Ok(Computation::LetStatement(self.parse_let_statement()?))
+ } else {
+ Ok(Computation::Identifier(identifier))
+ }
}
- TokenType::Lbrace => Computation::Abstraction(self.parse_abstraction()?),
- TokenType::Lparen => Computation::Application(self.parse_application()?),
+ TokenType::Lbrace => Ok(Computation::Abstraction(self.parse_abstraction()?)),
+ TokenType::Lparen => Ok(Computation::Application(self.parse_application()?)),
+ _ => Err(ParsingFailure::Blame(
+ next.blame,
+ String::from("Expected application, abstraction, or let statement"),
+ )),
};
}
@@ -318,7 +414,6 @@ impl Parser {
tokens,
};
}
- // fn new() -> Parser {}
}
pub enum StepResult<T> {
@@ -429,10 +524,10 @@ mod tests {
#[test]
fn test_parse() {
- let prog = "let Identity: ((Int) -> (Int)) = [a] { a };";
+ let prog = "let Identity: ((Int) -> (Int)) = [a] { a }; in Identity";
let tokens = Lexer::analyze(prog);
let mut parser = Parser::new(tokens);
- let ast = parser.parse().ok();
- ast.unwrap();
+ let ast = parser.parse_computation().ok();
+ println!("{}", ast.unwrap());
}
}