Commit Graph

69 Commits

Author SHA1 Message Date
24a74e625d refactor: update binary name from lambda.exe to lambda
Changed BINARY_NAME from lambda.exe to lambda and updated all execution references to use the ${BINARY_NAME} variable.
Added lambda binary to .gitignore.
2026-01-11 16:05:50 -05:00
0260a065cb refactor: move TEST variable to top of Makefile
Moved TEST variable declaration to the top with other configuration variables for better organization.
2026-01-11 16:04:11 -05:00
e31fb88077 feat: add help target as default Makefile goal
Added a help target that displays all available Makefile targets with descriptions.
Set help as the default goal so running 'make' without arguments shows usage information.
2026-01-11 16:03:28 -05:00
099be4ede6 refactor: rename Makefile target from it to build
Renamed the 'it' target to 'build' for better clarity and conventional naming.
Updated all target dependencies (run, profile, explain) to reference the new build target.
2026-01-11 16:02:27 -05:00
72a0afbbc0 perf: implement structural sharing for expression trees (#10)
## Description

The profiler revealed that 75% of CPU time was spent on memory allocation, with the primary bottleneck being expression copying during variable substitution. Every time a variable was substituted with an expression, `replacement.Copy()` would create a full deep copy of the entire expression tree.

This PR refactors the lambda calculus interpreter from a mutable, pointer-based implementation to an immutable, structurally-shared implementation. Expressions are now immutable value types that share unchanged subtrees instead of copying them.

**Key changes:**
- Made expression fields unexported to enforce immutability.
- Converted `Substitute()` and `Rename()` from in-place mutation to functional methods that return new expressions.
- Implemented structural sharing: methods return the same pointer when nothing changes.
- Removed `Copy()` method entirely - no more deep copying during substitution.
- Added getter methods for accessing expression fields from outside the package.

### Decisions

**Immutability over mutation:** Switched from mutable `*Expression` pointers with in-place updates to immutable expressions that return new trees. This is a fundamental architectural shift but aligns with functional programming principles and enables structural sharing.

**Structural sharing strategy:** When `Substitute()` or `Rename()` encounters an unchanged subtree, it returns the original pointer instead of creating a new object. This is safe because expressions are now immutable.

**Field encapsulation:** Made all expression fields unexported (`Parameter` → `parameter`, `Body` → `body`, etc.) to prevent external mutation. Added getter methods for controlled access.

## Benefits

**Performance improvements** (measured across all samples):

| Sample      | Before CPU | After CPU | Improvement | Copy Overhead Eliminated |
|-------------|-----------|----------|-------------|--------------------------|
| **saccharine** | 320ms | 160ms | **50% faster** | 50ms (15.6% of total) |
| **church** | 230ms | 170ms | **26% faster** | 40ms (17.4% of total) |
| **simple** | 30ms | 20ms | **33% faster** | 10ms (33.3% of total) |

**Wall-clock improvements:**
- saccharine: 503ms → 303ms (40% faster)
- church: 404ms → 302ms (25% faster)

**Memory allocation eliminated:**
- Before: `runtime.mallocgcSmallScanNoHeader` consumed 10-50ms per sample
- After: **Completely eliminated from profile** 
- All `Copy()` method calls removed from hot path

**The optimization in action:**

Before:
```go
func Substitute(e *Expression, target string, replacement Expression) {
    switch typed := (*e).(type) {
    case *Variable:
        if typed.Value == target {
            *e = replacement.Copy()  // Deep copy entire tree!
        }
    }
}
```

After:
```go
func (v *Variable) Substitute(target string, replacement Expression) Expression {
    if v.value == target {
        return replacement  // Share pointer directly, no allocation
    }
    return v  // Unchanged, share self
}
```

**Codebase improvements:**
- More idiomatic functional programming style.
- Immutability prevents entire class of mutation bugs.
- Clearer ownership semantics (expressions are values, not mutable objects).
- Easier to reason about correctness (no action at a distance).

## Checklist

- [x] Code follows conventional commit format.
- [x] Branch follows naming convention (`perf/structural-sharing`).
- [x] Tests pass (no test files exist, but build succeeds and profiling confirms correctness).
- [x] Documentation updated (added comments explaining structural sharing).

Reviewed-on: #10
Co-authored-by: M.V. Hutz <git@maximhutz.me>
Co-committed-by: M.V. Hutz <git@maximhutz.me>
2026-01-11 02:15:38 +00:00
22019acbb1 feat: add PHONY declarations and docs target to Makefile (#9)
---
name: "Default Template"
about: "The default template for `lambda`."
title: "feat: add PHONY declarations and docs target to Makefile"
ref: "main"
assignees: []
labels: []
---

## Description

This PR improves the Makefile by adding proper `.PHONY` declarations and a new `docs` target.
The `.PHONY` declarations ensure make properly handles targets that don't create files.
The `docs` target provides an easy way to view Go package documentation locally using godoc.

Changes:
- Add `.PHONY` declaration for all non-file targets (`it`, `run`, `profile`, `explain`, `graph`, `docs`).
- Add `docs` target that runs godoc server on port 6060 with helpful usage message.

### Decisions

None.

## Benefits

- Prevents make from getting confused if files with target names exist.
- Provides convenient documentation viewing with `make docs`.
- Improves Makefile maintainability following best practices.

## Checklist

- [x] Code follows conventional commit format.
- [x] Branch follows naming convention (`<type>/<description>`). Always use underscores.
- [ ] Tests pass (if applicable).
- [x] Documentation updated (if applicable).

Reviewed-on: #9
Co-authored-by: M.V. Hutz <git@maximhutz.me>
Co-committed-by: M.V. Hutz <git@maximhutz.me>
2026-01-10 23:29:30 +00:00
d831312dc3 feat: complete PR template frontmatter fields (#8)
## Description

Adds all recommended frontmatter fields to the Gitea pull request template.
This includes `about`, `ref`, `assignees`, and `labels` fields in addition to the required `name` and `title` fields.
These fields provide better template documentation and default PR settings.

## Benefits

- The PR template now includes a description (`about`) explaining its purpose.
- Default target branch is explicitly set to `main` via the `ref` field.
- Template follows Gitea best practices with all available frontmatter fields.
- Provides a complete, well-documented template structure for contributors.

## Checklist

- [x] Code follows conventional commit format.
- [x] Branch follows naming convention (`<type>/<description>`).
- [x] Tests pass (if applicable).
- [x] Documentation updated (if applicable).

Reviewed-on: #8
Co-authored-by: M.V. Hutz <git@maximhutz.me>
Co-committed-by: M.V. Hutz <git@maximhutz.me>
2026-01-10 23:00:32 +00:00
c0353c8e1f feat: add required name field to PR template (#7)
## Description

Gitea requires a `name` field in the frontmatter of pull request templates.
This PR adds the required `name: "Default Template"` field to fix the template validation error.
Additionally updates CLAUDE.md to reference the PR template format and use lowercase for PR title placeholder.

## Benefits

- The pull request template is now valid and will be properly loaded by Gitea.
- Users creating PRs will see the template automatically populated.
- CLAUDE.md now documents the PR template format for consistency.

## Checklist

- [x] Code follows conventional commit format.
- [x] Branch follows naming convention (`<type>/<description>`).
- [x] Tests pass (if applicable).
- [x] Documentation updated (if applicable).

Reviewed-on: #7
Co-authored-by: M.V. Hutz <git@maximhutz.me>
Co-committed-by: M.V. Hutz <git@maximhutz.me>
2026-01-10 22:54:43 +00:00
e63c0df410 fix: move PR template to correct Gitea location (#6)
## Description

Gitea requires the pull request template to be at `.gitea/PULL_REQUEST_TEMPLATE.md` (as a file), not in a `.gitea/PULL_REQUEST_TEMPLATE/` directory.
This PR moves the template from `.gitea/PULL_REQUEST_TEMPLATE/default.md` to `.gitea/PULL_REQUEST_TEMPLATE.md` to ensure it works correctly with Gitea.

## Benefits

- The pull request template will now be automatically loaded when creating new PRs in Gitea.
- Follows Gitea's documented convention for PR templates.

## Checklist

- [x] Code follows conventional commit format.
- [x] Branch follows naming convention (`<type>/<description>`).
- [x] Tests pass (if applicable).
- [x] Documentation updated (if applicable).

Reviewed-on: #6
Co-authored-by: M.V. Hutz <git@maximhutz.me>
Co-committed-by: M.V. Hutz <git@maximhutz.me>
2026-01-10 22:49:24 +00:00
8b6c632e4d feat: add pull request template (#5)
## Description

Added a standardized pull request template to improve PR quality and consistency. The template provides a clear structure for contributors to follow when creating PRs.

The template includes:
- Title placeholder following conventional commit format (`<type>: <description>`)
- Description section with guidance on context, rationale, and changes
- Optional Decisions section for architectural choices
- Benefits section to highlight improvements
- Checklist for conventional commits, branch naming, tests, and documentation

### Decisions

Created the template in `.gitea/PULL_REQUEST_TEMPLATE/default.md` to support multiple template types in the future.

## Benefits

- Ensures PRs follow project conventions (conventional commits, branch naming)
- Provides clear structure for describing changes
- Helps reviewers understand context and benefits
- Reduces back-and-forth by reminding contributors of requirements
- Supports future expansion with additional template types

Reviewed-on: #5
Co-authored-by: M.V. Hutz <git@maximhutz.me>
Co-committed-by: M.V. Hutz <git@maximhutz.me>
2026-01-10 22:44:41 +00:00
7a5944594f docs: add project guidelines for Claude Code (#4)
## Summary
- Add CLAUDE.md with project guidelines
- Documents conventional commit format and types
- Specifies branch naming conventions
- Includes PR management instructions using tea CLI

## Test plan
- Review CLAUDE.md content
- Verify formatting and accuracy

Reviewed-on: #4
Co-authored-by: M.V. Hutz <git@maximhutz.me>
Co-committed-by: M.V. Hutz <git@maximhutz.me>
2026-01-10 22:32:15 +00:00
Max
242fda3b4a feat: progress 2026-01-10 11:37:18 -05:00
Max
2499921679 style: moved functions around 2025-12-30 15:58:14 -05:00
Max
412d3924eb docs: document methods 2025-12-29 20:44:55 -05:00
Max
05cd8bc4f3 feat: meaningful comments for internal packages 2025-12-29 20:39:43 -05:00
Max
aabe92f2dc fix: cannot omit final newline 2025-12-29 20:17:50 -05:00
Max
13989e4c61 style: better flag explanation 2025-12-29 20:06:35 -05:00
Max
529abb7c26 fix: clearly state fatal errors 2025-12-29 20:01:44 -05:00
Max
351faa7e08 feat: statistics flag, commented some more 2025-12-29 20:00:29 -05:00
Max
3f9f3a603f feat: added links 2025-12-29 19:28:45 -05:00
Max
1d981ecce3 feat: compiled solution 2025-12-29 02:40:42 -05:00
Max
17cf8f86f8 feat: explanation as observer too 2025-12-29 01:31:09 -05:00
Max
5ceb845137 feat: more stuff to talk about 2025-12-29 01:15:39 -05:00
Max
a2ce5b6897 feat: rename profiler to performance, typeless event emitter 2025-12-29 01:15:14 -05:00
Max
c2b397a9f6 feat: observer pattern for statistics 2025-12-29 00:51:50 -05:00
Max
e9dc3fe171 feat: added optional profiling 2025-12-28 22:52:10 -05:00
Max
a4c049c0ff feat: push outputs to file 2025-12-28 03:39:24 -05:00
Max
6be3b7958a feat: use iterative approach for reduce once 2025-12-28 02:37:22 -05:00
Max
633d4a4d3b fix: no stringify in hot loop 2025-12-28 02:19:48 -05:00
Max
ee9e71d58e fix: no ds store 2025-12-28 02:07:46 -05:00
Max
0945cedf51 feat: only compute all free variables during a-conversion 2025-12-28 02:07:14 -05:00
Max
4d81aca0b2 feat: fun little program 2025-12-28 00:53:43 -05:00
Max
f4897d53a9 feat: it works! 2025-12-27 23:51:04 -05:00
Max
f038d0a685 feat: parse saccharine, conversion incoming 2025-12-27 23:36:44 -05:00
Max
14fc4b30da feat: cleaner parsing functions 2025-12-27 20:46:10 -05:00
Max
c37e96770f feat: tokenizer accepts braces, line terminator, and equal sign 2025-12-27 19:52:18 -05:00
Max
0e185fbf41 feat: expression 2025-12-27 03:43:19 -05:00
Max
bf0edfc593 style: renamed token index to column 2025-12-27 02:43:17 -05:00
Max
7f5298c8ed feat: added simple back 2025-12-27 02:41:26 -05:00
Max
1896cd652d feat: better error messages 2025-12-27 02:39:56 -05:00
Max
884180de92 feat: error for when there is more source code than parsed 2025-12-27 02:08:18 -05:00
Max
df53409887 fix: parameters converted in opposite order 2025-12-27 01:41:00 -05:00
Max
5841023dde fix: no log errors 2025-12-27 01:18:52 -05:00
Max
a05a63627e feat: better recursive descent 2025-12-27 01:18:06 -05:00
Max
e3629acb45 feat: stuff 2025-12-26 03:37:05 -05:00
Max
f26e7fbdc9 feat: saccharine example 2025-12-26 02:49:18 -05:00
Max
d427703afe wip: new folder structure, overhaul language 2025-12-26 02:39:15 -05:00
Max
11e7f70625 feat: stuff 2025-12-26 01:59:56 -05:00
Max
fa44051dec fix: don`t overlap "close" 2025-12-26 01:03:06 -05:00
Max
c2ec9127e8 style: no capitalized error messages 2025-12-26 00:08:36 -05:00