Commit Graph

43 Commits

Author SHA1 Message Date
b52a7596ef perf: implement structural sharing for expression trees
Replace mutable in-place expression modification with immutable
expressions that use structural sharing. This eliminates unnecessary
copying during variable substitution and beta reduction.

## Changes

- Make expression fields unexported (immutable by design)
- Convert Substitute() and Rename() to return new expressions
- Implement structural sharing: return self when unchanged
- Remove Copy() method entirely
- Add getter methods for expression fields

## Performance Impact

Benchmarked across all samples:

| Sample      | Before | After | Improvement |
|-------------|--------|-------|-------------|
| church      | 230ms  | 170ms | 26% faster  |
| saccharine  | 320ms  | 160ms | 50% faster  |
| simple      | 30ms   | 20ms  | 33% faster  |

## Key Optimization

Previously, variable substitution created deep copies:
```go
*e = replacement.Copy()  // Deep copy entire tree
```

Now uses structural sharing:
```go
return replacement  // Share pointer directly
```

This eliminates 100% of Copy() allocation overhead (10-50ms per sample).

## Files Modified

- pkg/lambda/expression.go: Unexport fields, remove Copy(), add methods
- pkg/lambda/substitute.go: Functional API with structural sharing
- pkg/lambda/rename.go: Functional API with structural sharing
- pkg/lambda/reduce.go: Use new functional API
- pkg/lambda/get_free_variables.go: Access unexported fields
- pkg/lambda/is_free_variable.go: Access unexported fields
- pkg/lambda/stringify.go: Access unexported fields
2026-01-10 20:16:57 -05: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
aabe92f2dc fix: cannot omit final newline 2025-12-29 20:17:50 -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
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
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
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
Max
44046e6abb fix: drop zero-init of fresh name generator 2025-12-26 00:02:32 -05:00
Max
c80587d522 style: unneeded else 2025-12-26 00:01:15 -05:00
Max
6f3b252819 style: no "this" or "self" as receiver 2025-12-26 00:00:10 -05:00
Max
e6e4a0df6f style: no punctuation or capitalization in errors 2025-12-25 23:52:39 -05:00
Max
32b1ba12f4 feat: golangci lint 2025-12-25 23:48:39 -05:00
Max
d9deee0734 fix: cannot parse just a token 2025-12-25 02:00:04 -05:00
Max
99703c2587 fix: unbound substitutions, explanation tag 2025-12-25 01:55:46 -05:00
Max
88ee4f799e feat: reducer works 2025-12-25 00:40:34 -05:00
Max
d5999e8e1c feat: reducer, but doesn`t work 2025-12-25 00:30:15 -05:00
Max
2c3ce9baf7 feat: wogihrsoiuvjsroirgj 2025-12-24 14:55:33 -05:00
Max
1d8ecba118 feat: parser 2025-12-23 21:54:42 -05:00
Max
61bb622dcd feat: tokenizer 2025-12-23 14:17:43 -05:00