Refactor lambda binding and parameter handling

Introduce `BoundKind::Parameter` to represent function parameters.
Modify `Binder` to correctly handle parameters within lambda
definitions, ensuring they are only defined within function scopes.
Update `LambdaCollector` to register the body of lambdas as templates
for global definitions.
Adjust `Dumper` to accurately represent lambda parameters.
Update `Specializer` and `TCO` to handle the new `BoundKind::Parameter`.
Refactor `Call` and `TailCall` to use a single `args` node, often a
tuple.
Adjust type signatures in RTL to use `StaticType::Tuple` for function
parameters.
This commit is contained in:
Michael Schimmel
2026-02-20 12:14:22 +01:00
parent 8d6d3be5c2
commit e2279f214b
17 changed files with 497 additions and 247 deletions
+38 -15
View File
@@ -38,8 +38,12 @@ impl<'a> Parser<'a> {
Ok(Node {
identity: identity.clone(),
kind: UntypedKind::Call {
callee: Box::new(self.make_id_node("quote", identity)),
args: vec![expr],
callee: Box::new(self.make_id_node("quote", identity.clone())),
args: Box::new(Node {
identity,
kind: UntypedKind::Tuple { elements: vec![expr] },
ty: (),
}),
},
ty: (),
})
@@ -186,7 +190,7 @@ impl<'a> Parser<'a> {
}
fn parse_fn(&mut self, identity: Identity) -> Result<Node<UntypedKind>, String> {
let params = self.parse_param_vector()?;
let params = Box::new(self.parse_param_vector()?);
let body = self.parse_expression()?;
Ok(Node {
@@ -205,7 +209,7 @@ impl<'a> Parser<'a> {
UntypedKind::Identifier(sym) => sym,
_ => return Err("Expected identifier for macro name".to_string()),
};
let params = self.parse_param_vector()?;
let params = Box::new(self.parse_param_vector()?);
let body = self.parse_expression()?;
Ok(Node {
identity,
@@ -214,34 +218,53 @@ impl<'a> Parser<'a> {
})
}
fn parse_param_vector(&mut self) -> Result<Vec<Symbol>, String> {
fn parse_param_vector(&mut self) -> Result<Node<UntypedKind>, String> {
if *self.peek() != TokenKind::LeftBracket {
return Err(format!("Expected parameter vector [...] for fn, found {:?}", self.peek()));
}
self.advance()?;
let token = self.advance()?;
let identity = Rc::new(NodeIdentity { location: token.location });
let mut params = Vec::new();
let mut elements = Vec::new();
while *self.peek() != TokenKind::RightBracket {
let token = self.advance()?;
match token.kind {
TokenKind::Identifier(name) => params.push(name.into()),
_ => return Err(format!("Expected identifier in param vector, found {:?}", token.kind)),
let next_token = self.advance()?;
let p_identity = Rc::new(NodeIdentity { location: next_token.location });
match next_token.kind {
TokenKind::Identifier(name) => {
elements.push(Node {
identity: p_identity,
kind: UntypedKind::Parameter(name.into()),
ty: (),
});
},
_ => return Err(format!("Expected identifier in param vector, found {:?}", next_token.kind)),
}
}
self.expect(TokenKind::RightBracket)?;
Ok(params)
Ok(Node {
identity,
kind: UntypedKind::Tuple { elements },
ty: (),
})
}
fn parse_call(&mut self, callee: Node<UntypedKind>, identity: Identity) -> Result<Node<UntypedKind>, String> {
let mut args = Vec::new();
let mut elements = Vec::new();
while *self.peek() != TokenKind::RightParen && *self.peek() != TokenKind::EOF {
args.push(self.parse_expression()?);
elements.push(self.parse_expression()?);
}
// The arguments are wrapped in a Tuple node, reusing the call's identity/location.
let args_node = Node {
identity: identity.clone(),
kind: UntypedKind::Tuple { elements },
ty: (),
};
Ok(Node {
identity,
kind: UntypedKind::Call { callee: Box::new(callee), args },
kind: UntypedKind::Call { callee: Box::new(callee), args: Box::new(args_node) },
ty: (),
})
}