Commit Graph

66 Commits

Author SHA1 Message Date
90c205db2e refactor: improve Makefile structure and usability (#11)
## Description

This PR refactors the Makefile to improve usability, maintainability, and cross-platform compatibility.
The changes modernize the Makefile structure and make it more user-friendly.

Changes made:
- Renamed the `it` target to `build` for better clarity and conventional naming.
- Added a `help` target as the default goal to display available targets and their descriptions.
- Moved the TEST variable to the top with other configuration variables for better organization.
- Updated binary name from `lambda.exe` to `lambda` and used `${BINARY_NAME}` variable consistently throughout.
- Replaced all `@` prefixes with the `.SILENT:` directive for cleaner syntax.
- Added a `clean` target to remove all build artifacts (binary, program.out, profile directory).
- Made the `graph` target cross-platform by replacing macOS-specific `open` command with file:// URL echo.
- Updated .gitignore to include the `lambda` binary.

### Decisions

- Used `.SILENT:` directive instead of individual `@` prefixes for a cleaner, more maintainable Makefile.
- Made `help` the default target so users can run `make` without arguments to see available commands.
- Removed platform-specific commands (like `open`) in favor of cross-platform alternatives.

## Benefits

- Improved discoverability: Users can run `make` to see all available targets.
- Better maintainability: Using `${BINARY_NAME}` variable consistently makes future changes easier.
- Cross-platform compatibility: Removed macOS-specific commands.
- Cleaner syntax: `.SILENT:` directive eliminates repetitive `@` prefixes.
- More conventional: Renamed `it` to `build` follows standard Makefile conventions.

## Checklist

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

Reviewed-on: #11
Co-authored-by: M.V. Hutz <git@maximhutz.me>
Co-committed-by: M.V. Hutz <git@maximhutz.me>
2026-01-11 21:13:41 +00: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
Max
17fa94113a style: no capitalized error messages 2025-12-26 00:08:15 -05:00
Max
d74894223e fix: does need to compare to true 2025-12-26 00:07:10 -05:00
Max
5ff8892d13 style: no underscores in variable names 2025-12-26 00:04:41 -05:00