feat: add tuple index access, multiline args, and effect unification fix

- Tuple index: `pair.0`, `pair.1` syntax across parser, typechecker,
  interpreter, C/JS backends, formatter, linter, and symbol table
- Multi-line function args: allow newlines inside argument lists
- Fix effect unification for callback parameters (empty expected
  effects means "no constraint", not "must be pure")

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-17 16:20:32 -05:00
parent bac63bab2a
commit 542255780d
12 changed files with 176 additions and 8 deletions

View File

@@ -1646,6 +1646,20 @@ impl Parser {
} else if self.check(TokenKind::Dot) {
let start = expr.span();
self.advance();
// Check for tuple index access: expr.0, expr.1, etc.
if let TokenKind::Int(n) = self.peek_kind() {
let index = n as usize;
self.advance();
let span = start.merge(self.previous_span());
expr = Expr::TupleIndex {
object: Box::new(expr),
index,
span,
};
continue;
}
let field = self.parse_ident()?;
// Check if this is an effect operation: Effect.operation(args)
@@ -1681,11 +1695,14 @@ impl Parser {
fn parse_args(&mut self) -> Result<Vec<Expr>, ParseError> {
let mut args = Vec::new();
self.skip_newlines();
while !self.check(TokenKind::RParen) {
args.push(self.parse_expr()?);
self.skip_newlines();
if !self.check(TokenKind::RParen) {
self.expect(TokenKind::Comma)?;
self.skip_newlines();
}
}