docs: document remaining packages and simplify AST types (#45)

## Summary

- Added doc comments across the codebase: `pkg/lambda`, `pkg/saccharine`, `pkg/codec`, `pkg/engine`, `pkg/iterator`, `pkg/set`, `pkg/convert`, `internal/registry`, and `cmd/lambda`.
- Made lambda and saccharine expression structs use public fields instead of getters, matching `go/ast` conventions.
- Removed superfluous constructors for saccharine and lambda expression/statement types in favor of struct literals.
- Consolidated saccharine token constructors into a single `NewToken` function.
- Removed the unused `trace` package.

## Test plan

- [x] `go build ./...` passes.
- [x] `go test ./...` passes.
- [ ] Verify `go doc` output renders correctly for documented packages.

Reviewed-on: #45
Co-authored-by: M.V. Hutz <git@maximhutz.me>
Co-committed-by: M.V. Hutz <git@maximhutz.me>
This commit was merged in pull request #45.
This commit is contained in:
2026-02-10 01:15:41 +00:00
committed by Maxim Hutz
parent 1f486875fd
commit 361f529bdc
33 changed files with 506 additions and 463 deletions

View File

@@ -5,13 +5,12 @@ import (
"fmt"
"git.maximhutz.com/max/lambda/pkg/iterator"
"git.maximhutz.com/max/lambda/pkg/trace"
)
type TokenIterator = iterator.Iterator[Token]
type tokenIterator = iterator.Iterator[Token]
func parseRawToken(i *TokenIterator, expected TokenType) (*Token, error) {
return iterator.Do(i, func(i *TokenIterator) (*Token, error) {
func parseRawToken(i *tokenIterator, expected TokenType) (*Token, error) {
return iterator.Do(i, func(i *tokenIterator) (*Token, error) {
if tok, err := i.Next(); err != nil {
return nil, err
} else if tok.Type != expected {
@@ -22,7 +21,7 @@ func parseRawToken(i *TokenIterator, expected TokenType) (*Token, error) {
})
}
func passSoftBreaks(i *TokenIterator) {
func passSoftBreaks(i *tokenIterator) {
for {
if _, err := parseRawToken(i, TokenSoftBreak); err != nil {
return
@@ -30,8 +29,8 @@ func passSoftBreaks(i *TokenIterator) {
}
}
func parseToken(i *TokenIterator, expected TokenType, ignoreSoftBreaks bool) (*Token, error) {
return iterator.Do(i, func(i *TokenIterator) (*Token, error) {
func parseToken(i *tokenIterator, expected TokenType, ignoreSoftBreaks bool) (*Token, error) {
return iterator.Do(i, func(i *tokenIterator) (*Token, error) {
if ignoreSoftBreaks {
passSoftBreaks(i)
}
@@ -40,15 +39,15 @@ func parseToken(i *TokenIterator, expected TokenType, ignoreSoftBreaks bool) (*T
})
}
func parseString(i *TokenIterator) (string, error) {
func parseString(i *tokenIterator) (string, error) {
if tok, err := parseToken(i, TokenAtom, true); err != nil {
return "", trace.Wrap(err, "no variable (col %d)", i.Index())
return "", fmt.Errorf("no variable (col %d): %w", i.Index(), err)
} else {
return tok.Value, nil
}
}
func parseBreak(i *TokenIterator) (*Token, error) {
func parseBreak(i *tokenIterator) (*Token, error) {
if tok, softErr := parseRawToken(i, TokenSoftBreak); softErr == nil {
return tok, nil
} else if tok, hardErr := parseRawToken(i, TokenHardBreak); hardErr == nil {
@@ -58,13 +57,13 @@ func parseBreak(i *TokenIterator) (*Token, error) {
}
}
func parseList[U any](i *TokenIterator, fn func(*TokenIterator) (U, error), minimum int) ([]U, error) {
func parseList[U any](i *tokenIterator, fn func(*tokenIterator) (U, error), minimum int) ([]U, error) {
results := []U{}
for {
if u, err := fn(i); err != nil {
if len(results) < minimum {
return nil, trace.Wrap(err, "expected at least '%v' items, got only '%v'", minimum, len(results))
return nil, fmt.Errorf("expected at least '%v' items, got only '%v': %w", minimum, len(results), err)
}
return results, nil
} else {
@@ -73,45 +72,45 @@ func parseList[U any](i *TokenIterator, fn func(*TokenIterator) (U, error), mini
}
}
func parseAbstraction(i *TokenIterator) (*Abstraction, error) {
return iterator.Do(i, func(i *TokenIterator) (*Abstraction, error) {
func parseAbstraction(i *tokenIterator) (*Abstraction, error) {
return iterator.Do(i, func(i *tokenIterator) (*Abstraction, error) {
if _, err := parseToken(i, TokenSlash, true); err != nil {
return nil, trace.Wrap(err, "no function slash (col %d)", i.MustGet().Column)
return nil, fmt.Errorf("no function slash (col %d): %w", i.MustGet().Column, err)
} else if parameters, err := parseList(i, parseString, 0); err != nil {
return nil, err
} else if _, err = parseToken(i, TokenDot, true); err != nil {
return nil, trace.Wrap(err, "no function dot (col %d)", i.MustGet().Column)
return nil, fmt.Errorf("no function dot (col %d): %w", i.MustGet().Column, err)
} else if body, err := parseExpression(i); err != nil {
return nil, err
} else {
return NewAbstraction(parameters, body), nil
return &Abstraction{Parameters: parameters, Body: body}, nil
}
})
}
func parseApplication(i *TokenIterator) (*Application, error) {
return iterator.Do(i, func(i *TokenIterator) (*Application, error) {
func parseApplication(i *tokenIterator) (*Application, error) {
return iterator.Do(i, func(i *tokenIterator) (*Application, error) {
if _, err := parseToken(i, TokenOpenParen, true); err != nil {
return nil, trace.Wrap(err, "no openning brackets (col %d)", i.MustGet().Column)
return nil, fmt.Errorf("no openning brackets (col %d): %w", i.MustGet().Column, err)
} else if expressions, err := parseList(i, parseExpression, 1); err != nil {
return nil, err
} else if _, err := parseToken(i, TokenCloseParen, true); err != nil {
return nil, trace.Wrap(err, "no closing brackets (col %d)", i.MustGet().Column)
return nil, fmt.Errorf("no closing brackets (col %d): %w", i.MustGet().Column, err)
} else {
return NewApplication(expressions[0], expressions[1:]), nil
return &Application{Abstraction: expressions[0], Arguments: expressions[1:]}, nil
}
})
}
func parseAtom(i *TokenIterator) (*Atom, error) {
func parseAtom(i *tokenIterator) (*Atom, error) {
if tok, err := parseToken(i, TokenAtom, true); err != nil {
return nil, trace.Wrap(err, "no variable (col %d)", i.Index())
return nil, fmt.Errorf("no variable (col %d): %w", i.Index(), err)
} else {
return NewAtom(tok.Value), nil
return &Atom{Name: tok.Value}, nil
}
}
func parseStatements(i *TokenIterator) ([]Statement, error) {
func parseStatements(i *tokenIterator) ([]Statement, error) {
statements := []Statement{}
//nolint:errcheck
@@ -130,7 +129,7 @@ func parseStatements(i *TokenIterator) ([]Statement, error) {
return statements, nil
}
func parseClause(i *TokenIterator, braces bool) (*Clause, error) {
func parseClause(i *tokenIterator, braces bool) (*Clause, error) {
if braces {
if _, err := parseToken(i, TokenOpenBrace, true); err != nil {
return nil, err
@@ -156,11 +155,11 @@ func parseClause(i *TokenIterator, braces bool) (*Clause, error) {
}
}
return NewClause(stmts[:len(stmts)-1], last.Value), nil
return &Clause{Statements: stmts[:len(stmts)-1], Returns: last.Value}, nil
}
func parseExpression(i *TokenIterator) (Expression, error) {
return iterator.Do(i, func(i *TokenIterator) (Expression, error) {
func parseExpression(i *tokenIterator) (Expression, error) {
return iterator.Do(i, func(i *tokenIterator) (Expression, error) {
passSoftBreaks(i)
switch peek := i.MustGet(); peek.Type {
@@ -178,8 +177,8 @@ func parseExpression(i *TokenIterator) (Expression, error) {
})
}
func parseLet(i *TokenIterator) (*LetStatement, error) {
return iterator.Do(i, func(i *TokenIterator) (*LetStatement, error) {
func parseLet(i *tokenIterator) (*LetStatement, error) {
return iterator.Do(i, func(i *tokenIterator) (*LetStatement, error) {
if parameters, err := parseList(i, parseString, 1); err != nil {
return nil, err
} else if _, err := parseToken(i, TokenAssign, true); err != nil {
@@ -187,20 +186,20 @@ func parseLet(i *TokenIterator) (*LetStatement, error) {
} else if body, err := parseExpression(i); err != nil {
return nil, err
} else {
return NewLet(parameters[0], parameters[1:], body), nil
return &LetStatement{Name: parameters[0], Parameters: parameters[1:], Body: body}, nil
}
})
}
func parseDeclare(i *TokenIterator) (*DeclareStatement, error) {
func parseDeclare(i *tokenIterator) (*DeclareStatement, error) {
if value, err := parseExpression(i); err != nil {
return nil, err
} else {
return NewDeclare(value), nil
return &DeclareStatement{Value: value}, nil
}
}
func parseStatement(i *TokenIterator) (Statement, error) {
func parseStatement(i *tokenIterator) (Statement, error) {
if let, letErr := parseLet(i); letErr == nil {
return let, nil
} else if declare, declErr := parseDeclare(i); declErr == nil {