rip-lang 3.13.136 → 3.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md DELETED
@@ -1,1500 +0,0 @@
1
- <img src="https://raw.githubusercontent.com/shreeve/rip-lang/main/docs/assets/rip.png" style="width:50px" /> <br>
2
-
3
- # Changelog
4
-
5
- All notable changes to Rip will be documented in this file.
6
-
7
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
8
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
9
-
10
- ## [Unreleased]
11
-
12
- ### Breaking — Merge Assign Operator
13
-
14
- - **`*>` replaces `*` for merge assignment** — The merge-assign form is now `*>target = value` (including `*>@ = props`). The old `*target = value` form is removed.
15
-
16
- ## [3.13.16] - 2026-02-25
17
-
18
- ### Breaking — Merge `@rip-lang/api` into `@rip-lang/server`
19
-
20
- - **One package for framework + server** — `@rip-lang/api` no longer exists. All imports change from `'@rip-lang/api'` to `'@rip-lang/server'` and `'@rip-lang/api/middleware'` to `'@rip-lang/server/middleware'`. The default export (`.`) is `api.rip` (the web framework), `./middleware` is `middleware.rip`, and `./server` is `server.rip` (the process manager).
21
- - **`packages/api/` deleted** — Files moved to `packages/server/` (api.rip, middleware.rip, tests/).
22
-
23
- ### CLI — `rip serve` Subcommand
24
-
25
- - **`rip serve`** — New subcommand that resolves `@rip-lang/server/server` lazily and passes all args through. One tool to compile, run, and serve. Clear error message if `@rip-lang/server` isn't installed.
26
- - **File watching on by default** — `*.rip` files are watched automatically. `--watch=<glob>` to customize, `--static` to disable everything. The `-w`/`--watch` bare flags are removed.
27
- - **Removed `-w`/`--web` browser REPL** — The `rip -w` flag for launching a browser playground is removed.
28
- - **CLI cleanup** — Removed dead `startREPL` import, eliminated `__filename`, deduplicated `loaderPath`, removed narrating comments. 308 → 218 lines.
29
-
30
- ### Compiler — Fix Postfix `if` with `@method` Calls in Value Context
31
-
32
- - **Bug fix** — `@method arg1, arg2 if condition` in value context (e.g., inside `->`) silently dropped the method call, compiling to just `condition ? arg2 : undefined` instead of `condition ? this.method(arg1, arg2) : undefined`. The issue was in `unwrapBlock` treating call expressions with array operators (like `['.', 'this', 'x']`) as lists of statements. Fixed by checking if `body[0]` is an s-expression operator. Added 2 regression tests (1,257 total).
33
-
34
- ### Server — Bundle Caching + Brotli Compression
35
-
36
- - **Memory-cached bundle** — The component bundle JSON is built once per worker lifetime and served from memory. No more glob scan + file reads on every `/bundle` request.
37
- - **Brotli compression** — Bundle is pre-compressed with `zlib.brotliCompressSync` at cache time. When the browser sends `Accept-Encoding: br`, the pre-compressed version is served (~5KB instead of ~65KB).
38
- - **Client-side ETag caching** — The `launch()` function in `app.rip` stores the bundle ETag and data in `sessionStorage`. On subsequent page loads, it sends `If-None-Match` manually (browser `fetch()` doesn't do this automatically). Server returns 304 when content unchanged — zero bytes on the wire.
39
- - **Deterministic ETags** — Glob scan results are sorted before JSON serialization, ensuring identical hashes across requests.
40
- - **`Cache-Control: no-cache` on `send()`** — Makes caching explicit for subresources served via `@send`.
41
-
42
- ### Server — `@cache` Helper
43
-
44
- - **Sinatra-style cache duration** — `@cache '1 day'` sets `Cache-Control: public, max-age=86400`. Supports seconds, minutes, hours, days, weeks, years, or raw numbers. `@send` respects pre-set `Cache-Control` instead of always overriding to `no-cache`.
45
-
46
- ### Server — `Rip-No-Log` Header
47
-
48
- - **App-controlled log suppression** — Set `@header 'Rip-No-Log', '1'` in a `before` filter to suppress the server's access log for specific routes (e.g., `/favicon.png`, `/ping`). The header is stripped from the response before reaching the browser.
49
-
50
- ### Server — Watch Improvements
51
-
52
- - **Filter non-existent watch dirs** — The `serve` middleware filters directories with `existsSync` before registering them with the file watcher, preventing `ENOENT` errors for missing `css/` directories.
53
- - **Cleaner watch error format** — `rip-server: watch skipped (ENOENT): app/css` with relative paths.
54
-
55
- ### Server — Setup Fix
56
-
57
- - **`proc.unref()` for spawned processes** — The `startDb` function in `demos/streamline/api/db.rip` now unrefs the spawned `rip-db` child process so the setup subprocess can exit cleanly. Without this, `rip serve` would hang after setup because the child kept the parent alive.
58
-
59
- ### Standard Library (added in 3.11.x)
60
-
61
- - **13 global helpers** — `abort`, `assert`, `exit`, `kind`, `noop`, `p`, `pp`, `raise`, `rand`, `sleep`, `todo`, `warn`, `zip`. All use `??=` (overridable). Injected via `globalThis` in compiled output, CLI REPL, and browser REPL.
62
-
63
- ### Postfix `!?` Operator (added in 3.11.x)
64
-
65
- - **Defined check** — `val!?` compiles to `val !== undefined` (true if not undefined). Distinct from `val?` which checks `val != null` (not null and not undefined).
66
-
67
- ### Rip Loader
68
-
69
- - **Rewrite `@rip-lang/*` imports to absolute paths** — The rip-loader now rewrites `@rip-lang/*` import specifiers to absolute filesystem paths via `import.meta.resolve`. This is necessary because Bun's worker threads ignore `NODE_PATH` and `onResolve` doesn't fire for imports in compiled source.
70
-
71
- ### Swarm (`@rip-lang/swarm`)
72
-
73
- - **Worker error delivery** — Don't exit before error message arrives at the main thread.
74
- - **Startup failure detection** — Exit handler detects worker startup failures.
75
- - **Pre-flight module check** — Validates worker module exists before spawning.
76
- - **Quiet mode** — `-q`/`--quiet` flag suppresses progress output.
77
- - **Derive rip-loader path from swarm's own location** — Uses `import.meta.url` instead of `require.resolve` (which fails from directories without `node_modules`).
78
-
79
- ### UI Framework
80
-
81
- - **Auto-detect hot reload under `rip serve`** — `watch: true` is automatically enabled when `SOCKET_PREFIX` env var is present.
82
- - **Brotli + ETag caching for `rip.min.js`** — Pre-compressed `.br` file served with ETag; 304 on reload.
83
- - **Auto-launch for server-backed apps** — `data-launch` attribute on script tag triggers `launch()` with bundle URL.
84
- - **Component remount on route param change** — Same route with different params now correctly remounts.
85
- - **CSS hot-swap** — `.css` file changes trigger style reload without full page refresh.
86
- - **Fix fragment removal** — Components with multiple root elements now clean up all nodes.
87
-
88
- ### VS Code Extension
89
-
90
- - **v0.5.5** — Fix hover overshoot, source map interpolation.
91
- - **v0.5.3** — Hover support for component declarations.
92
- - **v0.5.2** — Type hover for all declarations.
93
-
94
- ### Type System
95
-
96
- - **Generic return types** — `def foo():: Promise<User>` now emits correct `.d.ts`.
97
-
98
- ### Documentation
99
-
100
- - **All `@rip-lang/api` references updated** — AGENTS.md, README.md, RIP-LANG.md, RIP-INTERNALS.md, all package READMEs, all demo files.
101
- - **Server README** — Merged 901 lines of web framework documentation (validators, routing, middleware, context, file serving, error handling, utility functions, Hono migration guide) from the deleted api README.
102
- - **Version numbers and test counts updated** across all documentation.
103
-
104
- ### Packages Published
105
-
106
- | Package | Version |
107
- |---------|---------|
108
- | `rip-lang` | 3.13.16 |
109
- | `@rip-lang/server` | 1.3.7 |
110
- | `@rip-lang/db` | 1.3.14 |
111
- | `@rip-lang/grid` | 0.2.9 |
112
- | `@rip-lang/csv` | 1.3.5 |
113
- | `@rip-lang/http` | 1.1.7 |
114
- | `@rip-lang/print` | 1.1.8 |
115
- | `@rip-lang/x12` | 0.2.7 |
116
- | `@rip-lang/schema` | 0.3.7 |
117
- | `@rip-lang/swarm` | 1.2.17 |
118
-
119
- ## [3.10.12] - 2026-02-20
120
-
121
- ### Compiler — Fix Variable Scoping in Effect Blocks
122
-
123
- - **Effect block bodies now scope variables correctly** — Variables assigned inside `~>` block bodies (e.g., `prev = document.querySelector(...)`) were being hoisted to the enclosing function scope instead of staying local to the effect's arrow function. This caused `ReferenceError` in strict mode. Fixed in both the standalone compiler (`compiler.js`) and the component compiler (`components.js`) by treating effect blocks as proper function boundaries in variable collection, and using `generateFunctionBody` (matching how computed blocks were already handled) instead of raw expression generation.
124
-
125
- ## [3.10.6] - 2026-02-20
126
-
127
- ### CLI — Fix Multiline Argument Corruption
128
-
129
- - **`execSync` → `spawnSync` in `bin/rip`** — The CLI runner was passing script arguments through a shell via `execSync` with string interpolation. Any argument containing a newline (JSON payloads, heredoc content, multiline strings) was silently split into separate shell commands. Replaced all three `execSync` call sites (`.rip` file execution, compiled temp file execution, and `bin/` script fallback) with `spawnSync` using argument arrays, bypassing the shell entirely. Exit codes use `?? 1` (nullish coalescing) instead of `|| 0` for correct signal-kill handling.
130
-
131
- ### Utilities — `curl.rip` Improvements
132
-
133
- - **Stdin TTY guard** — `curl.rip` no longer hangs when run interactively without a payload argument. Added `process.stdin.isTTY` check to only read from stdin when piped or heredoc'd.
134
- - **Documented inline and heredoc modes** — Updated header comments to clearly show both usage patterns.
135
-
136
- ## [3.9.1] - 2026-02-18
137
-
138
- ### Runtime — Reactivity & Reconciliation
139
-
140
- - **Auto-batching in event handlers** — DOM event callbacks now automatically batch reactive updates, preventing redundant renders during multi-stash mutations.
141
- - **Fixed list reconciliation** — Keyed list diffing now handles insert/remove/reorder correctly, resolving issues with fragment teardown and stale nodes.
142
- - **Fixed fragment teardown** — Components with multiple root elements now clean up all nodes on removal.
143
- - **Multi-statement computed blocks** — Computed properties can now contain multiple statements, not just a single expression.
144
-
145
- ### Lexer — Render Rewriter Fix
146
-
147
- - **Fixed `STRING_END` in render rewriter** — Template strings inside render blocks now correctly handle the closing delimiter, fixing parse errors in components with interpolated template literals.
148
-
149
- ### UI Framework
150
-
151
- - **`importRip` race fix** — Concurrent `importRip()` calls no longer produce duplicate module evaluations.
152
- - **ISO-8601 week numbers** — Added week number utilities for calendar-based components.
153
- - **Bare dot shorthand for div** — `.className` at the start of a line now implies `div.className`.
154
-
155
- ### VS Code Extension (0.3.2)
156
-
157
- - **HTML injection grammar** — `<script type="text/rip">` blocks in HTML files now get Rip syntax highlighting automatically.
158
-
159
- ### Documentation & Examples
160
-
161
- - **Sierpinski Triangle demo** — Interactive fractal demo showcasing reactive rendering at `docs/sierpinski.html`.
162
- - **Playground reorganization** — Consolidated playground into `docs/index.html` with Example tab, active nav highlighting, and View Source panel.
163
- - **Renamed `apps/` to `demos/`** — Clearer naming for example applications.
164
-
165
- ## [3.9.0] - 2026-02-17
166
-
167
- ### Architecture — Render Rewriter Extraction
168
-
169
- - **Extracted `rewriteRender()` from lexer into component system** — The ~330-line render block rewriter, which handles implicit div, `#id` combining, `<=>` binding, `@event` modifiers, `.__clsx` dynamic classes, `->` nesting injection, and hyphenated attributes, now lives in `src/components.js` via `installComponentSupport(CodeGenerator, Lexer)`. This matches the existing `installTypeSupport(Lexer)` pattern from `src/types.js`. The core lexer (`src/lexer.js`) no longer contains any UI/template transformation code, and uses `this.rewriteRender?.()` to gracefully skip render rewriting when component support is not installed.
170
-
171
- ### Lexer — Render Block Fixes
172
-
173
- - **Fixed `startsWithTag` backward scan** — The helper that determines if a line starts with a template tag now correctly skips over balanced parenthetical expressions (function calls, grouped args) instead of stopping at `)` or `CALL_END`. This fixes cases where template elements with parenthesized arguments were not recognized for implicit nesting.
174
- - **Added `isClsxCallEnd` handling** — Dynamic class expressions (`.('card', active && 'active')`) followed by indented children now correctly wrap in an outer call, producing the right AST shape for the component compiler.
175
-
176
- ### Build — Simplified Browser Bundles
177
-
178
- - **Reduced dist output from 10 files to 4** — The browser build now produces only `rip.browser.min.js` + `.br` (compiler only) and `rip-ui.min.js` + `.br` (compiler + UI). Intermediate artifacts (`rip.browser.js`, `ui.rip`, `ui.rip.br`, `ui.js`, `ui.min.js`, `ui.min.js.br`) eliminated. Build script reduced from 154 to 58 lines.
179
-
180
- ### Streamline App
181
-
182
- - **Updated Streamline Swim School components** — Revised layout, auth, bookings, profile, booking/confirm, and booking/time components. Removed standalone `app.css` in favor of inline styles.
183
-
184
- ## [3.8.10] - 2026-02-17
185
-
186
- ### Compiler — Bug Fix
187
-
188
- - **Fixed `or throw` variable hoisting bug** — The `x = expr or throw` pattern inside function bodies was erroneously adding the target variable to the program-level `programVars` set. This "poisoned" the variable filter for subsequent sibling functions, causing them to omit local `let` declarations and produce `ReferenceError` at runtime. Most notably, this broke `@rip-lang/api`'s `store` variable when multiple exported functions used the pattern. Fixed by removing the incorrect `programVars.add()` call from `generateAssignment`.
189
-
190
- ### Schema — New Features
191
-
192
- - **`Model.fromSchema()` bridge** — ORM models can now auto-configure their schema, table name, and primary key directly from a parsed `.schema` AST via `Model.fromSchema(schema, 'ModelName')`, eliminating manual field re-declaration.
193
- - **Dependency-ordered SQL DDL** — `emit-sql.js` now topologically sorts tables so foreign key references are always defined before use.
194
- - **`app-demo.rip` example** — Rewrote the schema demo in Rip (was JavaScript), showcasing TypeScript generation, SQL DDL, and runtime validation from a single `.schema` file.
195
-
196
- ## [3.8.9] - 2026-02-16
197
-
198
- ### Compiler — Grammar Desugaring & Cleanup
199
-
200
- - **`until` desugared to `while`** — Grammar now emits `["while", ["!", cond], ...]` directly, eliminating `generateUntil` from the compiler. Also fixes the `until...when` guard bug where the guard expression was silently dropped.
201
- - **`unless` desugared to `if`** — Grammar now emits `["if", ["!", cond], ...]` for all `unless` forms, removing ~20 `unless`-specific code paths from the compiler (dispatch table, postfix conditionals, assignment handlers, return/throw handlers, control flow analysis).
202
- - **`toSearchable` renamed to `toMatchable`** — The regex helper name now matches the `.match()` API it wraps.
203
- - **Added missing `%%=` handler** — The mathematical modulo assignment operator now works correctly instead of crashing during code generation.
204
-
205
- ## [3.8.8] - 2026-02-16
206
-
207
- ### Compiler — Refactoring & Cleanup
208
-
209
- - **Comprehension generator deduplication** — Extracted shared `_forInHeader`, `_forOfHeader`, and `_forAsHeader` helpers, consolidating loop header construction across `generateComprehension`, `generateComprehensionWithTarget`, and `generateComprehensionAsLoop`.
210
- - **Cleaner for-of loop output** — `for own k of obj` now generates flatter JavaScript using `continue` guard clauses instead of nested `if` blocks.
211
- - **Component child deduplication** — Extracted `appendChildren` helper in `components.js`, consolidating duplicate child-processing logic from `generateTag` and `generateDynamicTag`. Also fixed a missing `componentMembers` check in `generateDynamicTag`.
212
- - **Dead code removal** — Removed unused `break-if` and `continue-if` compiler handlers (the grammar handles these through the normal `if` path).
213
-
214
- ### REPL — Bug Fix
215
-
216
- - **Comprehension crash fix** — The REPL now correctly handles multi-line expressions (comprehensions, IIFEs). Previously, the result capture logic produced broken JavaScript by prepending `__result =` to the closing `})();` line instead of the expression start.
217
-
218
- ### Documentation
219
-
220
- - Fixed inaccurate content on the Rip UI demo About page (compiler/framework sizes, architecture description).
221
-
222
- ## [3.8.7] - 2026-02-14
223
-
224
- Rip UI loading optimization (combined bundle, build-time compilation, FOUC prevention). See `packages/ui/CHANGELOG.md` v0.3.2.
225
-
226
- ## [3.8.6] - 2026-02-13
227
-
228
- ### Compiler — Render Block Fix
229
-
230
- - **Render block fix** — Identifiers matching HTML tag names (e.g., `title`) are no longer misclassified as template elements when preceded by control flow keywords (`if`, `unless`, `while`, `until`, `when`).
231
-
232
- Rip UI hash routing and static demo. See `packages/ui/CHANGELOG.md` v0.3.1.
233
-
234
- ## [3.8.5] - 2026-02-13
235
-
236
- ### Build — GitHub Pages Fixes
237
-
238
- - **Copy ui.rip instead of symlink** — `bun run browser` now copies `packages/ui/ui.rip` to `docs/dist/ui.rip` on every build. Symlinks return 404 on GitHub Pages.
239
- - Fixed Async example to use clean chained `!` syntax now that precedence is correct.
240
-
241
- ## [3.8.4] - 2026-02-13
242
-
243
- ### Compiler — Chained Dammit Operator Fix
244
-
245
- - **Chained `!` parenthesization** — `fetch!(url).json!` now correctly compiles to `await (await fetch(url)).json()` instead of `await await fetch(url).json()` which had wrong JS precedence. The `await` from `!` metadata is now parenthesized when used as a property access base.
246
- - Playground Async example restored to clean `fetch!(url).json!` syntax.
247
- - 2 new tests (1,241 total).
248
-
249
- ## [3.8.3] - 2026-02-13
250
-
251
- ### Lexer — Heregex Forward Slash Escaping
252
-
253
- - **Auto-escape `/` in heregex** — Forward slashes inside `///...///` are now automatically escaped to `\/` in the compiled regex literal. Previously required manual `\/` escaping, defeating the purpose of heregex.
254
- - 1 new test (1,239 total).
255
-
256
- ## [3.8.2] - 2026-02-13
257
-
258
- ### Compiler — Class Constructor Fixes
259
-
260
- - **`@param` defaults in constructors** — `constructor: (@count = 0) ->` now correctly compiles to `constructor(count = 0) { this.count = count; }` instead of producing invalid `(.,this,count)` syntax.
261
- - **`super` with `@param` in subclass constructors** — `constructor: (@name) -> super @name, "woof"` now compiles to `constructor(_name) { super(_name, "woof"); this.name = _name; }` using a temporary parameter to avoid illegal `this` access before `super()`.
262
- - **Single-expression constructor autoAssignments** — `@param` assignments are now emitted in single-expression constructor bodies (previously only worked in block bodies).
263
- - 3 new tests (1,238 total).
264
-
265
- ## [3.8.1] - 2026-02-13
266
-
267
- ### Playground — Fix Class Examples
268
-
269
- - **Constructor syntax fix** — All playground examples now use `constructor: (@name) ->` instead of the bare `(@name) ->` shorthand, which produced invalid JS output.
270
-
271
- ## [3.8.0] - 2026-02-12
272
-
273
- ### Playground — Example Snippets & Source Persistence
274
-
275
- - **Example snippets dropdown** — 6 curated examples (Basics, Reactive State, Classes, Regex & Strings, Async & Dammit, Full Demo) plus a Custom option for user code.
276
- - **Source persistence** — Editor content saved to localStorage with 2-second debounce, restored on page load.
277
- - **Auto-switch to Custom** — Editing code after selecting an example automatically switches the dropdown to Custom.
278
- - Applied to all three playground versions (playground-rip.html, playground-js.html, playground-rip-ui.html).
279
-
280
- ### Language — Raw Heredocs
281
-
282
- - **Raw heredocs (`'''\` and `"""\`)** — Appending `\` to a heredoc opener keeps JS escape sequences (`\n`, `\t`, `\u`, `\x`, `\\`) literal in the output.
283
- - **`.class` shorthand fix** — `div.foo` or `.foo` with indented children in render blocks now produces correct JS.
284
-
285
- ### Parser — Recursive Descent Generator
286
-
287
- - **Lunar grammar** (`src/grammar/lunar.rip`) — New recursive descent parser generator producing `src/parser-rd.js`.
288
- - **98.3% test parity** — 1,162 of 1,182 tests passing with the generated parser.
289
-
290
- ## [3.7.4] - 2026-02-12
291
-
292
- ### Compiler — Reactive Scoping & Component Fixes
293
-
294
- - **Effect cleanup** — `__effect` now captures return values as cleanup functions, run before re-execution and on disposal. Backward-compatible.
295
- - **Component scope leak** — `collectProgramVariables` no longer recurses into component bodies. Inner `:=` variables don't pollute the outer scope.
296
- - **Object key reactive transform** — Object literal keys are no longer transformed to `key.value` when the key name matches a reactive variable.
297
- - **Component effect index** — Fixed `effect[1]` → `effect[2]` for the body of `~>` in components.
298
- - **Component effect wrapping** — Effects now wrapped in `() => { expr; }` for proper reactivity.
299
- - **Dot-chain property names** — `app.data.count` no longer transforms `count` as a reactive member when it's a property name in a dot chain.
300
- - **Reactive prop passthrough** — `buildComponentProps` passes `:=` members as signals (not values) to child components. Child's `__state` returns the signal as-is.
301
- - **Child unmounting** — `generateChildComponent` tracks child instances in `_children`. `__Component.unmount()` cascades depth-first.
302
-
303
- ### Compiler — Nested Function Scope Chain
304
-
305
- - **Scope stack for variable hoisting** — Nested functions no longer re-declare variables from enclosing function scopes. Previously, the compiler only checked program-level variables; now it tracks a full scope chain. Fixes incorrect `let` shadowing in deeply nested function patterns (e.g., `mountRoute` inside `createRenderer` in `ui.rip`).
306
-
307
- ### Rip UI — Demo App Working
308
-
309
- - **Router `navigating` getter/setter** — The `_navigating` signal is now accessible through `router.navigating` (read/write), fixing a cross-scope reference where `createRenderer` accessed a variable local to `createRouter`.
310
- - **Component props passthrough** — `__Component` base class now assigns all props to `this` via `Object.assign(this, props)` before `_init`, so components can access `@router`, `@app`, `@params` etc.
311
-
312
- ### Language — `*@` Merge-This
313
-
314
- - **`*@ = props`** — New merge-assign variant for `this`. Compiles to `Object.assign(this, props)`. Natural extension of `*obj = expr` — no `??=` guard needed since `this` is never null.
315
-
316
- ## [3.7.3] - 2026-02-11
317
-
318
- ### Fixes & Polish
319
-
320
- - **Interface `::` fix** — `::` type annotations in interface bodies no longer produce double colons in `.d.ts` output.
321
- - **`.=` dot chain support** — `obj.name .= toUpperCase()` now works (walks back full property chain).
322
- - **`*` merge auto-init** — `*foo = {...}` auto-creates `foo` if undefined via `??= {}`.
323
- - **`loop n` uses `it`** — Loop counter is accessible as `it` inside the body.
324
- - **Syntax highlighting** — `|>` pipe operator added to VS Code, Vim, Playground, and rip-print.
325
-
326
- ## [3.7.0] - 2026-02-11
327
-
328
- ### Pipe Operator (`|>`)
329
-
330
- - **First-arg insertion pipe** — `x |> fn` compiles to `fn(x)`, and `x |> fn(y)` compiles to `fn(x, y)`. Combines the simplicity of F#-style pipes with multi-arg support like Elixir — no placeholder syntax needed. Left-associative, chains naturally: `5 |> double |> add(1)`.
331
- - Works with dotted references (`x |> Math.sqrt`, `x |> console.log`) and dotted calls (`x |> obj.method(y)` → `obj.method(x, y)`).
332
- - Implicit calls close at pipe boundaries — `x |> fn 1 |> bar 2` works correctly without parens.
333
-
334
- ### Method Assignment (`.=`) — A Rip Original
335
-
336
- - **Compound method assignment** — `x .= trim()` compiles to `x = x.trim()`. The method-call equivalent of `+=`. No other language has this. Combined with implicit `it`, enables concise transformation pipelines: `items .= filter -> it.active` then `items .= map -> it.name`.
337
-
338
- ### Prototype Operator (`::`)
339
-
340
- - **CoffeeScript-style prototype access restored** — `String::trim` compiles to `String.prototype.trim`. Disambiguated from type annotations by spacing: `::` with no space is prototype, `::` with a space is a type annotation. Both coexist cleanly.
341
-
342
- ### `loop n` — Repeat N Times
343
-
344
- - **Counted loop** — `loop 5 -> body` compiles to `for (let _i = 0; _i < 5; _i++) { body }`. Works with literals, variables, and expressions.
345
-
346
- ### Implicit `it` Parameter
347
-
348
- - **Auto-injected parameter** — Arrow functions with no explicit params that reference `it` in the body automatically inject `it` as the parameter. `arr.filter -> it > 5` compiles to `arr.filter(function(it) { return (it > 5); })`. Works with both `->` and `=>`. Stops at nested function boundaries.
349
-
350
- ### Negative Indexing
351
-
352
- - **Python-style negative indexing** — `arr[-1]` compiles to `arr.at(-1)`, `arr[-2]` to `arr.at(-2)`, etc. Works on arrays and strings. Optional variant: `arr?[-1]` → `arr?.at(-1)`. Only literal negative numbers trigger the transform; variable indexes pass through unchanged.
353
-
354
- ### Browser Runtime — Full Async/Await Support
355
-
356
- - **`rip()` console REPL** — Wraps user code in a Rip `do ->` block, so the compiler handles implicit return and auto-async natively. Sync code returns values directly; async code returns a Promise (use `await rip("...")` in the console). Variables persist on `globalThis` across calls.
357
- - **`importRip(url)`** — Fetch, compile, and import `.rip` files as ES modules via blob URL. Registered on `globalThis` for use in `<script type="text/rip">` blocks.
358
- - **Async `<script type="text/rip">`** — `processRipScripts` wraps compiled code in an async IIFE, enabling `await` (Rip's `!` operator) in inline scripts.
359
- - **Playground** — Run button uses async IIFE for `await` support. Cmd+Enter shortcut registered on Monaco editor.
360
- - **Eager reactive runtime** — `globalThis.__rip` is registered when `rip.browser.js` loads, making reactive primitives available to framework code.
361
- - **`compileToJS` on globalThis** — The compiler function is globally accessible for framework auto-detection.
362
-
363
- ## [3.4.3] - 2026-02-09
364
-
365
- ### Source Maps & IDE Intelligence
366
-
367
- - **Source Map V3 support** — New `src/sourcemaps.js` implements ECMA-426 source maps with zero dependencies. VLQ encoder + SourceMapGenerator class in ~120 lines.
368
- - **Inline source maps** — `-m` flag embeds source maps as base64 data URLs in compiled output. One file for everything — debuggers read them natively.
369
- - **Reverse source maps** — `toReverseMap()` provides O(1) source→generated position lookup for IDE type intelligence.
370
- - **S-expression locations** — Parser now attaches `.loc = {r, c}` on every S-expression node. Locations flow from lexer through parser to code generator using consistent `{r, c}` naming.
371
- - **Parser cleanup** — Removed legacy Jison location format (`first_line`/`first_column`), dead `ranges` variable, and `locFirst`/`locLast` extraction. Parser uses `{r, c}` natively.
372
- - **VS Code Extension v0.3.1** — Level 2 type intelligence: autocomplete, hover, and go-to-definition from third-party `.d.ts` files inside `.rip` files. Shadow `.ts` compilation with 300ms debounce. Configurable via `rip.types.intellisense` setting.
373
-
374
- ## [3.3.1] - 2026-02-09
375
-
376
- ### Playground & Extension
377
-
378
- - **Playground cleanup** — Eliminated dead CSS rules, extracted shared Monaco config, DRYed up toggle handlers, fixed flicker by restoring button states before page reveal, added smooth fade-in transition, defaulted light/dark mode to system `prefers-color-scheme`.
379
- - **VS Code Extension v0.2.0** — Auto-generate `.d.ts` files on save, commands for single-file and workspace-wide type generation, auto-detect compiler binary, configurable settings.
380
- - **Extension published** to VS Code Marketplace as `rip-lang.rip`.
381
-
382
- ## [3.2.1] - 2026-02-08
383
-
384
- ### Test Suite & Solar Cleanup
385
-
386
- - **Test suite overhaul** — Redistributed tests from `stabilization.rip` and `compatibility.rip` into proper files, removed duplicates, added `reactivity.rip` and `types.rip` test files, added `for-as` guard tests. Now 1,140 tests.
387
- - **Solar parser generator cleanup** — Removed ~79 lines of dead Jison compatibility code, optimized runtime parser with `.call` instead of `.apply`, modernized variable naming from `yy` prefixes.
388
-
389
- ## [3.2.0] - 2026-02-08
390
-
391
- ### Rip Types — Optional Type System
392
-
393
- - **Type annotations** (`::`) on variables, parameters, and return types — compile-time only, stripped from JS output.
394
- - **Type aliases** (`type Name =`) for named types, structural types, union types.
395
- - **Interfaces** with `extends` support.
396
- - **Enums** with runtime JS generation and `.d.ts` emission.
397
- - **Generics** (`<T>`) for reusable type definitions.
398
- - **`.d.ts` emission** — `emitTypes()` generates TypeScript declaration files directly from annotated token stream.
399
- - **CLI flag** — `-d`/`--dts` generates `.d.ts` files alongside compiled JS.
400
- - **Architecture** — All type logic consolidated in `src/types.js` (lexer sidecar), minimal changes to lexer and compiler. Added `::` annotations and `type` keyword to lexer.
401
-
402
- ## [3.1.0] - 2026-02-08
403
-
404
- ### Rip UI — Zero-Build Reactive Web Framework
405
-
406
- Rip UI inverts the traditional web development model. Instead of building and
407
- bundling on the server, the 40KB Rip compiler ships to the browser. Components
408
- are delivered as `.rip` source files, stored in a browser-local Virtual File
409
- System, compiled on demand, and rendered with fine-grained DOM updates.
410
-
411
- **Component model** — Two keywords added to the language:
412
-
413
- - `component` — Declares an anonymous ES6 class with reactive props, computed
414
- values, effects, methods, and lifecycle hooks. `@` properties become props
415
- the parent can set. `:=` creates signals, `~=` creates computed values.
416
- - `render` — Defines a Pug/Jade-like template DSL inside a component. Tags are
417
- bare identifiers, classes use dot notation (`div.card.active`), dynamic
418
- classes use dot-parens (`div.("active" if @selected)`), and events use
419
- `@click: handler`. No virtual DOM — each reactive binding creates a direct
420
- effect that updates exactly the DOM nodes it touches.
421
-
422
- **Framework modules** (all in `packages/ui/`):
423
-
424
- | Module | Role |
425
- |--------|------|
426
- | `stash.js` | Deep reactive state tree with path-based navigation |
427
- | `vfs.js` | Browser-local Virtual File System with file watchers |
428
- | `router.js` | File-based router (URL ↔ VFS paths, History API) |
429
- | `renderer.js` | Component lifecycle, layout nesting, route transitions |
430
- | `ui.js` | `createApp` entry point, re-exports everything |
431
-
432
- **Compiler changes** (`src/components.js`, 1,193 lines):
433
-
434
- - 22 methods installed on `CodeGenerator.prototype` via `installComponentSupport()`
435
- - Categorizes component body into state, computed, readonly, methods, effects, render
436
- - Emits fine-grained DOM creation (`_create()`) and reactive setup (`_setup()`)
437
- - Block factories for conditionals and loops with disposable effects
438
- - Keyed reconciliation for list rendering
439
- - Component runtime emitted only when `component` keyword is used
440
-
441
- **No build step. No bundler. No configuration files.**
442
-
443
- ---
444
-
445
- ## [3.0.0] - 2026-02-07
446
-
447
- ### Complete Rewrite
448
-
449
- Rip 3.0 is a ground-up rewrite of the entire compiler pipeline. Every component is new:
450
-
451
- - **Lexer + Rewriter** (`src/lexer.js`) — 1,542 LOC, down from 3,260
452
- - **Compiler + Codegen** (`src/compiler.js`) — 3,148 LOC, down from 6,016
453
- - **Grammar** (`src/grammar/grammar.rip`) — 887 LOC, updated for new syntax
454
- - **Parser** (`src/parser.js`) — 352 LOC, regenerated from new grammar
455
- - **REPL** (`src/repl.js`) — 654 LOC, rewritten for the new pipeline
456
- - **Browser** (`src/browser.js`) — 79 LOC, rewritten for the new pipeline
457
- - **CLI** (`bin/rip`) — 267 LOC, updated to use the new pipeline
458
- - **Total**: ~7,700 LOC (down from ~10,100)
459
-
460
- ### Language Changes
461
-
462
- #### Removed
463
- - Postfix spread/rest (`x...`) — use prefix `...x` (ES6)
464
- - Prototype access (`x::y`, `x?::y`) — use `.prototype` or class syntax
465
- - `is not` contraction — use `isnt`
466
-
467
- #### Added
468
- - JS-style ternary operator: `x ? a : b`
469
- - `for...as` iteration: `for x as iterable` (replaces `for x from iterable`)
470
- - `as!` async shorthand: `for x as! iterable` (shorthand for `for await x as iterable`)
471
-
472
- #### Kept
473
- - Existence check: `x?` compiles to `(x != null)` — works after any expression
474
- - All reactive operators: `:=`, `~=`, `~>`, `=!`
475
- - Dammit operator: `x!` compiles to `await x()`
476
- - Optional chaining: `?.`, `?.[]`, `?.()` (ES6 dot-form)
477
- - Optional chaining shorthand: `?[]`, `?()` (compiles to `?.[]`, `?.()`)
478
- - Nullish coalescing: `??`
479
- - All other CoffeeScript-compatible syntax
480
-
481
- ### Tests
482
- - 1,073 tests passing (100%)
483
- - 25 test files across all language features
484
-
485
- ---
486
-
487
- ## [2.9.0] - 2026-02-05
488
-
489
- ### Compiler Fix
490
-
491
- - **Interpolated string object keys**: `{"#{k}": v}` now correctly compiles to `{[\`${k}\`]: v}` instead of invalid `{\`${k}\`: v}`. Template literals in object key position are wrapped in computed property syntax.
492
-
493
- ### @rip-lang/db — DuckDB Server with Official UI
494
-
495
- Major milestone: complete DuckDB HTTP server with the official DuckDB UI.
496
-
497
- - **Pure Bun FFI driver** — Direct calls to DuckDB's C API, no npm packages, no Zig
498
- - **Modern chunk-based API** — Uses `duckdb_fetch_chunk` + `duckdb_vector_get_data` for direct columnar memory reads. No deprecated `duckdb_value_*` functions.
499
- - **DuckDB UI loads instantly** — Full binary serialization protocol, proper COOP/COEP headers, SSE keepalive, version handshake
500
- - **Complete type support** — DECIMAL (exact precision), ENUM (dictionary lookup), UUID (native hugeint), LIST/STRUCT/MAP (child vector traversal), all timestamp variants
501
- - **Timestamp policy** — All timestamps normalized to UTC Date objects; TIMESTAMPTZ recommended
502
- - **Binary protocol** — Native 16-byte UUID serialization, uint64-aligned validity bitmaps, proper TypeInfo encoding
503
-
504
- ### @rip-lang/api — v1.0.0
505
-
506
- - Published as stable 1.0.0
507
- - Polished README with feature table and cross-references
508
-
509
- ### @rip-lang/server — v1.0.0
510
-
511
- - Published as stable 1.0.0
512
- - Added proper dependencies (rip-lang + @rip-lang/api)
513
- - Polished README with feature table and cross-references
514
-
515
- ### Housekeeping
516
-
517
- - Removed all Zig code and npm DuckDB dependency from @rip-lang/db
518
- - Consolidated documentation (DEBUGGING.md + INTERNALS.md → README.md)
519
- - Dynamic platform detection for DuckDB UI headers
520
- - Support both `--port=N` and `--port N` argument formats
521
- - Updated all package dependencies to ^2.9.0
522
- - Removed bun.lock from git tracking
523
-
524
- ---
525
-
526
- ## [2.7.2] - 2026-02-03
527
-
528
- ### Clean ES Module REPL
529
-
530
- **Proper `vm.SourceTextModule` Implementation**: The REPL now uses Node's standard ES module API instead of temp files:
531
-
532
- ```coffee
533
- rip> { Cash } = await import("./utils.rip")
534
- rip> config = Cash((await import("./config.rip")).default)
535
- rip> config.app.name
536
- → 'Rip Labs API'
537
- ```
538
-
539
- **Key improvements:**
540
- - Uses `vm.SourceTextModule` for in-memory module evaluation (no temp files)
541
- - `.rip` files compiled on-the-fly via module linker
542
- - Cross-runtime compatible (Node.js, Bun, potentially Deno)
543
- - Dynamic `await import()` transformed to static imports automatically
544
- - Clean variable persistence through VM context
545
-
546
- This is the standard way to handle ES modules in sandboxed contexts - no hacks required.
547
-
548
- ---
549
-
550
- ## [2.7.1] - 2026-02-03
551
-
552
- ### Bun-Native REPL with Dynamic Import Support
553
-
554
- **Full `import()` Support in REPL**: The REPL now uses Bun's native evaluation instead of Node's `vm` module, enabling dynamic imports:
555
-
556
- ```coffee
557
- rip> { Cash } = await import("./utils.js")
558
- rip> config = Cash((await import("./config.js")).default)
559
- rip> config.app.name
560
- → 'My App'
561
- ```
562
-
563
- **Key changes:**
564
- - Replaced `vm.runInContext` with file-based async evaluation
565
- - Variables persist across REPL lines via `globalThis.__ripRepl`
566
- - Temp files cleaned up automatically on exit
567
- - Reactive runtime injected into global scope for cross-line sharing
568
-
569
- This enables using the REPL for real development workflows with module imports.
570
-
571
- ---
572
-
573
- ## [2.5.1] - 2026-01-16
574
-
575
- ### Template Enhancement
576
-
577
- **Hyphenated Attributes Work Directly**:
578
- ```coffee
579
- render
580
- # Before: needed quoted keys or spread syntax
581
- i {"data-lucide": "search"}
582
-
583
- # Now: just works!
584
- i data-lucide: "search", aria-hidden: "true"
585
- div data-testid: "container", aria-label: "Menu"
586
- span data-foo-bar-baz: "multiple-hyphens-work"
587
- ```
588
-
589
- The lexer now automatically converts hyphenated attribute names (like `data-*`, `aria-*`) into quoted strings, making HTML-style data attributes intuitive and clean.
590
-
591
- ---
592
-
593
- ## [2.5.0] - 2026-01-16
594
-
595
- ### Major Release - Parser Optimization + Complete Framework
596
-
597
- This release consolidates all improvements since 2.2.1 into a polished, well-documented package. Rip is now a complete language AND reactive framework in just 51KB (Brotli compressed).
598
-
599
- ---
600
-
601
- ### 🚀 Parser Optimization
602
-
603
- **Interleaved Delta-Encoded Parse Table** - Major size reduction for the generated parser:
604
- - New format in `solar.rip`: `[count, Δkey₁, Δkey₂..., val₁, val₂...]` per state
605
- - **31% smaller Brotli** for parser alone (19.2KB → 13.2KB)
606
- - **17% faster module load** time
607
- - Identical runtime performance (same data structure after decode)
608
- - Solar parser generator now **250× faster** than Jison
609
-
610
- ---
611
-
612
- ### ✨ New Language Features
613
-
614
- **Ruby-Style Constructor Syntax**:
615
- ```coffee
616
- # Both are equivalent
617
- counter = new Counter()
618
- counter = Counter.new() # Ruby-style - elegant!
619
-
620
- # Works with arguments
621
- user = User.new("Alice", 30)
622
-
623
- # Chainable
624
- Counter.new().mount("#app")
625
- ```
626
-
627
- **"Equal, Dammit!" Operator (`=!`)**:
628
- ```coffee
629
- # Regular assignment → let (can reassign)
630
- host = "localhost"
631
- host = "example.com" # OK
632
-
633
- # Equal, dammit! → const (can't reassign)
634
- API_URL =! "https://api.example.com"
635
- API_URL = "other" # Error! const cannot be reassigned
636
- ```
637
- Note: `=!` compiles to plain `const` - does NOT pull in the reactive runtime.
638
-
639
- **Smart Two-Way Binding**:
640
- ```coffee
641
- # Automatically uses valueAsNumber for number/range inputs
642
- input type: "number", value <=> count # No .valueAsNumber needed!
643
- input type: "range", value <=> volume # Just works!
644
- ```
645
-
646
- ---
647
-
648
- ### 🎨 Template & Component Improvements
649
-
650
- **Pug-Style Shorthand**:
651
- ```coffee
652
- # Implicit div for class-only selectors
653
- .card # → <div class="card">
654
- .btn.primary # → <div class="btn primary">
655
-
656
- # Nested shorthand works correctly
657
- .container
658
- .row
659
- .col "Content"
660
- ```
661
-
662
- **Dynamic Class Syntax**:
663
- ```coffee
664
- div.("bg-white rounded-lg shadow-md") # Static Tailwind classes
665
- button.(active && "bg-blue-500") # Conditional classes
666
- ```
667
-
668
- **Component Mount with Selectors**:
669
- ```coffee
670
- # Both work
671
- Counter.new().mount(document.body)
672
- Counter.new().mount("#app") # Selector string support
673
- ```
674
-
675
- ---
676
-
677
- ### 🖥️ Browser REPL Enhancements
678
-
679
- **Live Demo Tab** (now default):
680
- - Interactive component demos
681
- - Temperature converter, counter examples
682
- - Real-time reactive updates
683
-
684
- **UI Improvements**:
685
- - Tab state persists in URL hash
686
- - No flash of wrong tab on page load
687
- - Consistent pane header heights
688
- - GitHub icon link in header
689
-
690
- **Demo Improvements**:
691
- - Shows `@prop` syntax for component props
692
- - Uses Ruby-style `.new()` syntax
693
- - Fat arrows for proper `this` binding
694
-
695
- ---
696
-
697
- ### 📚 Documentation Overhaul
698
-
699
- **Consolidated Documentation** - 13 files merged into 4 main docs:
700
- - `docs/RIP-LANG.md` - Language reference
701
- - `docs/RIP-INTERNALS.md` - Compiler architecture, S-expressions, Solar
702
- - `docs/PHILOSOPHY.md` - Design principles, CoffeeScript comparison
703
- - `docs/BROWSER.md` - Browser usage, REPL, deployment
704
-
705
- **Kept Separate** (referenced from PHILOSOPHY.md):
706
- - `docs/WHY-NOT-COFFEESCRIPT.md` - The case against CoffeeScript
707
- - `docs/WHY-YES-RIP.md` - The case for Rip
708
-
709
- **Updated Statistics**:
710
- - ~14,000 LOC total (smaller than CoffeeScript's 17,760, yet includes full reactive framework)
711
- - 51KB browser bundle (compiler + reactive runtime + templates + components)
712
- - 1046 tests passing
713
- - Solar: ~1,000 LOC, 250× faster than Jison
714
-
715
- ---
716
-
717
- ### 🔧 Internal Improvements
718
-
719
- **Compiler Consolidation**:
720
- - Merged `codegen.js` into `compiler.js` (single file for all code generation)
721
- - Renamed `docs/CODEGEN.md` to `docs/COMPILER.md`
722
-
723
- **Project Cleanup**:
724
- - Deleted unused `src/runtime.js` (runtime now embedded in compiler output)
725
- - Deleted redundant `docs/demo.html`
726
- - Overhauled `AGENT.md` for accuracy
727
- - Added `notes.txt` to `.gitignore`
728
-
729
- **Bug Fixes**:
730
- - Fixed `<=>` two-way binding in components
731
- - Fixed reactive variable shadowing in function bodies
732
- - Fixed nested Pug-style shorthand in render blocks
733
- - Fixed `generateParam` bug
734
- - Consistent name handling in `generateReadonly`
735
-
736
- ---
737
-
738
- ### 📊 Updated Scores
739
-
740
- | Category | Score | Notes |
741
- |----------|-------|-------|
742
- | **Reactivity** | A+ | Fine-grained, state, effects |
743
- | **Templates** | A | S-expressions, Pug shorthand |
744
- | **Components** | A | Props, lifecycle, context API |
745
- | **Performance** | A | 250× faster parser gen, 51KB bundle |
746
-
747
- ---
748
-
749
- ### Summary
750
-
751
- **What's in 51KB?**
752
- - Complete compiler (lexer, parser, code generator)
753
- - Reactive runtime (state, computed values, effects)
754
- - Template engine (S-expression syntax, dynamic classes)
755
- - Component system (props, lifecycle, fine-grained updates)
756
- - Zero dependencies
757
-
758
- **Comparison**:
759
- - React (min+gzip): ~42KB (just the library, no compiler)
760
- - Vue (min+gzip): ~34KB (just the library, no compiler)
761
- - **Rip: 51KB (complete language + framework, runs anywhere!)**
762
-
763
- ---
764
-
765
- ## [2.2.1] - 2026-01-15
766
-
767
- ### Added - Context API & Error Primitives
768
-
769
- **Context API** - Pass data through component trees without prop drilling:
770
- - `setContext(key, value)` - Set context in current component
771
- - `getContext(key)` - Get context from nearest ancestor
772
- - `hasContext(key)` - Check if context exists
773
-
774
- **Error Primitives** - Low-level building blocks for error handling:
775
- - `__catchErrors(fn)` - Wrap function to route errors to handler
776
- - `__handleError(error)` - Route error to handler or rethrow
777
- - `__setErrorHandler(fn)` - Set current error handler
778
-
779
- **Dynamic Class Syntax** - Cleaner Tailwind support:
780
- ```coffee
781
- div.("bg-white rounded-lg shadow-md") # Static classes
782
- button.(active && "bg-blue-500") # Conditional classes
783
- ```
784
-
785
- **Other Improvements**:
786
- - Components now track parent via `_parent` pointer
787
- - Batching optimization with `__batch()` for grouped updates
788
- - Improved reactive runtime documentation (~330 lines total)
789
-
790
- **Updated Scores**:
791
- - Components: B+ → A- (Context API implemented)
792
- - Tests: 1017 → 1033
793
-
794
- ---
795
-
796
- ## [2.2.0] - 2026-01-15
797
-
798
- ### Added - Keyed Reconciliation & Per-Item Effects
799
-
800
- **The Final Boss: True Svelte-Class Performance**
801
-
802
- Lists now have O(1) performance for ALL operations:
803
- - **Add item**: Create 1 node (not rebuild all)
804
- - **Remove item**: Remove 1 node (not rebuild all)
805
- - **Reorder**: Move existing nodes (not recreate)
806
- - **Selection change**: Per-item effects update independently
807
-
808
- **Key Features**:
809
- - Keyed reconciliation via `key:` attribute
810
- - Per-item effects with proper cleanup
811
- - Conditional effect cleanup (no memory leaks)
812
- - Effect disposal on item removal
813
-
814
- **Example**:
815
- ```coffee
816
- for item, i in items
817
- li key: item.id, class: (i == selected && "selected"), item.name
818
- ```
819
-
820
- Each item gets its own effect. Changing `selected` updates ONLY the affected classes, not the whole list.
821
-
822
- ---
823
-
824
- ## [2.1.0] - 2026-01-15
825
-
826
- ### Added - Fine-Grained Reactivity
827
-
828
- **MAJOR PERFORMANCE IMPROVEMENT**: Components now update only specific DOM nodes that changed, not the entire tree. This brings Rip to Svelte-class performance.
829
-
830
- **Architecture Change**:
831
- - Before: `render()` recreates all DOM on every state change
832
- - After: `_create()` builds DOM once, `_setup()` wires minimal effects
833
-
834
- **Performance**:
835
- - Text binding: O(1) instead of O(n)
836
- - Attribute binding: O(1) instead of O(n)
837
- - **30-40x faster** for typical reactive updates
838
-
839
- **New Features**:
840
- - Fine-grained text bindings: `span count` → effect updates just that text node
841
- - Fine-grained attribute bindings: `div class: active` → effect updates just that attribute
842
- - Fine-grained conditionals: `if show` → anchor-based content swapping
843
- - Fine-grained loops: `for item in items` → tracked node list
844
- - Named slots: Props can be DOM nodes (`@header`, `@footer`, etc.)
845
-
846
- **Updated Scores**:
847
- - Reactivity: A → A+
848
- - Templates: A- → A
849
- - Components: A- → A
850
-
851
- ---
852
-
853
- ## [2.0.0] - 2026-01-14
854
-
855
- ### Added - Reactive UI Framework
856
-
857
- **Phase 1: Reactivity** (previously released)
858
- - State-based reactivity: `count := 0` creates reactive state
859
- - Computed values: `doubled ~= count * 2` auto-tracks dependencies
860
- - Effects: `~> console.log count` runs on changes
861
- - Runtime: `__state()`, `__computed()`, `__effect()`, `__batch()`, `__readonly()`
862
-
863
- **Phase 2: Templates**
864
- - Indentation-based template syntax in `render` blocks
865
- - CSS-style selectors: `div#main.card.active`
866
- - Event handlers: `@click: handler`
867
- - Event modifiers: `@click.prevent.stop: handler`
868
- - Two-way binding: `input value <=> username`
869
- - Spread attributes: `div ...props`
870
- - Dynamic classes: `div.('btn', isActive && 'active')` (clsx-style)
871
- - Control flow: `if`/`else`, `for` loops in templates
872
- - Special attributes: `key:`, `ref:`
873
- - Multiple roots via `DocumentFragment`
874
- - Runtime helpers: `h()`, `frag()`, `txt()`, `cx()`
875
-
876
- **Phase 3: Components**
877
- - `component` keyword for defining UI components
878
- - Props system:
879
- - Required: `@label`
880
- - Optional: `@label?`
881
- - Default: `@label = "default"`
882
- - Rest: `@...rest`
883
- - Reactive state within components (auto-state)
884
- - Computed values within components (auto-computed)
885
- - Component composition: `Button label: "Click"` inside render
886
- - Children/slots: `@children` prop for nested content
887
- - Lifecycle hooks: `mounted:`, `unmounted:`
888
- - Reactive re-rendering via effect-based mount
889
-
890
- ### Changed
891
- - Grammar extended with `component`, `render`, `style` keywords
892
- - Lexer handles template contexts (ID selectors, arrow injection)
893
- - Codegen generates ES6 classes for components
894
-
895
- ### Technical Details
896
- - Components compile to ES6 classes with constructor, render, mount, unmount
897
- - Props validated at construction (required props throw if missing)
898
- - State variables become `__state()` calls
899
- - Computed values become `__computed()` calls
900
- - `mount()` wraps render in `__effect()` for reactive updates
901
- - PascalCase names in templates trigger component instantiation
902
-
903
- All 1033 tests passing (100%) ✅
904
-
905
- ---
906
-
907
- ## [1.5.7] - 2025-11-16
908
-
909
- ### Changed
910
- - **Documentation updates** - Updated all version references to 1.5.7
911
- - Updated README.md version badge and status section
912
- - Updated AGENT.md current status section
913
- - Regenerated parser and browser bundles with correct version
914
- - All compiled artifacts current and properly versioned
915
-
916
- All 968 tests passing (100%) ✅
917
-
918
- ## [1.5.6] - 2025-11-16
919
-
920
- ### Fixed
921
- - **Package completeness** - Ensure all compiled files included in npm package
922
- - Regenerated parser with optimized encoding
923
- - Rebuilt browser bundles (44.55 KB compressed)
924
- - All compiled artifacts present and current
925
-
926
- All 968 tests passing (100%) ✅
927
-
928
- ## [1.5.5] - 2025-11-16
929
-
930
- ### Changed
931
- - **Parser optimization: Sign-based parseTable encoding** - 28.7% faster parsing!
932
- - Transformed parseTable from `[type, value]` arrays to semantic integers
933
- - Positive N = GOTO/SHIFT to state N (forward movement)
934
- - Negative -N = REDUCE by rule N (contraction)
935
- - 0 = ACCEPT (parsing complete)
936
- - undefined = ERROR (syntax error)
937
- - **Performance improvements:**
938
- - Parse speed: 28.7% faster (3.27ms → 2.33ms average)
939
- - Full compile: 16.3% faster (15.24ms → 12.75ms)
940
- - File size: 24.5% smaller (291.9KB → 220.4KB, -71.5KB)
941
- - **Why it's fast:** Direct integer comparison (`action > 0`, `action < 0`) instead of array unpacking, better cache locality, fewer allocations
942
- - The sign bit elegantly encodes operation semantics
943
- - Updated src/grammar/solar.rip with optimized encoding
944
- - Regenerated src/parser.js with new format
945
- - Documented in AGENT.md architecture section
946
-
947
- All 968 tests passing (100%) ✅
948
-
949
- ## [1.5.3] - 2025-11-09
950
-
951
- ### Added
952
- - **Keyboard shortcuts for Run button in browser REPL** (repl.html)
953
- - **F5** - Execute code (all platforms)
954
- - **Cmd+Enter** - Execute code (Mac)
955
- - **Ctrl+Enter** - Execute code (Windows/Linux)
956
- - Refactored Run button handler into reusable `runCode()` function
957
- - Added global keyboard event listener with preventDefault to avoid conflicts
958
- - Updated Run button tooltip to show available shortcuts
959
- - Improves workflow for quick code execution without mouse clicks
960
-
961
- All 962 tests passing (100%) ✅
962
-
963
- ## [1.5.2] - 2025-11-09
964
-
965
- ### Fixed
966
- - **Fixed 'in' operator to check array VALUES instead of INDICES** (#60)
967
- - JavaScript's `in` operator checks indices: `'apple' in ['apple', 'banana']` returns `false`
968
- - Previous fix (v1.4.2) only handled string literal in variable case
969
- - Now handles ALL cases: variable in variable, literal in literal, variable in literal
970
- - Uses runtime dispatch: arrays/strings → `.includes()`, objects → `in` operator
971
- - Added 15 comprehensive tests (12 execution + 3 code generation)
972
- - Critical fix: prevents silent bugs where membership checks return wrong results
973
- - Example: `val = 'apple'; val in ['apple', 'banana']` now correctly returns `true`
974
-
975
- All 962 tests passing (100%) ✅
976
-
977
- ## [1.5.1] - 2025-11-09
978
-
979
- ### Fixed
980
- - **Refined heredoc closing delimiter logic** for edge cases
981
- - Only uses closing position when it's at or left of content minimum
982
- - Falls back to minimum indent when closing is right of content (old behavior)
983
- - Removes trailing whitespace-only line when using minimum indent fallback
984
- - Prevents incorrect dedenting when closing delimiter is indented beyond content
985
-
986
- ### Changed
987
- - **Refactored heredoc logic into helper methods** for maintainability
988
- - Extracted `getHeredocClosingColumn()` - Detects closing delimiter position
989
- - Extracted `extractHeredocContent()` - Gets content from tokens
990
- - Extracted `findMinimumIndent()` - Calculates minimum indentation
991
- - Extracted `selectHeredocIndent()` - Chooses baseline intelligently
992
- - Extracted `removeTrailingWhitespaceLine()` - Cleans up edge case
993
- - Main heredoc logic now 15 lines (was 70), crystal clear
994
- - Zero performance impact, much more maintainable
995
-
996
- - **Added inline SVG favicon to HTML files**
997
- - index.html now has embedded favicon
998
- - No HTTP request needed for favicon
999
- - Works in all contexts (local, GitHub Pages, offline)
1000
-
1001
- - **Enhanced dev server** (scripts/serve.js)
1002
- - Now strips `/rip-lang/` prefix for GitHub Pages URL compatibility
1003
- - Works with both local and GitHub Pages paths
1004
-
1005
- All 947 tests passing (100%) ✅
1006
-
1007
- ## [1.5.0] - 2025-11-09
1008
-
1009
- ### Added
1010
- - **Heredoc closing delimiter position determines dedenting baseline** (#58)
1011
- - When closing `'''` or `"""` has only whitespace before it, use its column as baseline
1012
- - Strip that exact amount from all content lines
1013
- - Preserve additional indentation beyond baseline
1014
- - Falls back to minimum-indent behavior when non-whitespace precedes closing delimiter
1015
- - Visual control: Move closing delimiter left/right to control stripping
1016
- - Perfect for code generation use cases
1017
- - Works with both single (`'''`) and double (`"""`) quote heredocs
1018
- - Added 10 comprehensive tests covering all edge cases
1019
-
1020
- ### Removed
1021
- - **Soak super syntax** (`super?()`) - Removed for clarity and simplicity
1022
- - Semantically questionable (parent methods always exist in practice)
1023
- - Zero real-world usage (one test only)
1024
- - Makes `super?()` a parse error (clearer than silently handling)
1025
- - Removed `generateOptionalSuper` method from codegen
1026
- - Removed `?super` from dispatch table
1027
- - Removed test from test/rip/classes.rip
1028
-
1029
- ### Changed
1030
- - Test count: 938 → 947 (+10 heredoc tests, -1 soak super test)
1031
-
1032
- All 947 tests passing (100%) ✅
1033
-
1034
- ## [1.4.6] - 2025-11-08
1035
-
1036
- ### Changed
1037
- - **Documentation updates for consistency**
1038
- - Updated AGENT.md to reflect current version (1.4.6)
1039
- - Standardized all test count references to 938/938 (100%)
1040
- - Updated README.md version references
1041
-
1042
- All 938 tests passing (100%) ✅
1043
-
1044
- ## [1.4.5] - 2025-11-08
1045
-
1046
- ### Changed
1047
- - **Renamed rip-loader.ts → rip-loader.js** - Pure JavaScript, no TypeScript
1048
- - Removed fake TypeScript annotation (`err: any` → `err`)
1049
- - Updated `bunfig.toml` to reference `.js` file
1050
- - Updated `package.json` exports and files array
1051
- - Honest about what the file is - simplicity and clarity
1052
-
1053
- - **Completed CODEGEN-FINAL-ANALYSIS recommendations**
1054
- - Extracted `isNegativeOneLiteral()` helper method (DRY principle)
1055
- - Removed duplicate negative-one literal checks
1056
- - Deleted analysis document (all work complete)
1057
-
1058
- All 938 tests passing (100%) ✅
1059
-
1060
- ## [1.4.4] - 2025-11-08
1061
-
1062
- ### Changed
1063
- - **S-expression formatter - Clean room rebuild**
1064
- - Complete rewrite of `formatSExpr()` with clear, simple rules
1065
- - Fixed indentation hierarchy: children ALWAYS indented more than parents
1066
- - Fixed method chaining indentation (`.` operator in call heads)
1067
- - Multi-line heads now properly re-indented to maintain hierarchy
1068
- - Block nodes always expand children on separate lines
1069
- - Removed all column-based continuation complexity
1070
- - +89 lines added, -52 lines removed (net +37 for clarity)
1071
-
1072
- - **INLINE_FORMS cleanup**
1073
- - Removed legacy MUMPS cruft (tag, entryref, lock-*, newline, etc.)
1074
- - Organized by category with aligned comments
1075
- - Added `new` to inline forms for compact constructor calls
1076
- - Clear documentation of what belongs and why
1077
-
1078
- ### Improved
1079
- - S-expression output is now beautifully formatted with perfect hierarchy
1080
- - Method chaining like `s.replace().trim()` displays correctly
1081
- - Simple constructors stay compact: `(new (Date))`
1082
- - Complex constructors expand naturally: `(new (Set (...)))`
1083
-
1084
- All 938 tests passing (100%) ✅
1085
-
1086
- ## [1.4.3] - 2025-11-07
1087
-
1088
- ### Refactored
1089
- - **Convert generateNot to s-expression approach** - Following Rip philosophy!
1090
- - Check operand TYPE at s-expression level (not regex on generated code)
1091
- - Handles primitives: `!1`, `!x`, `!true` (clean output without extra parens)
1092
- - Handles property access: `!obj.prop`, `!arr[0]` (clean output)
1093
- - Conservative for complex expressions: `!(a + b)` (keeps parens)
1094
- - Simple, maintainable logic (~26 lines)
1095
- - Follows philosophy from Issues #46 (flattenBinaryChain) and #49 (unwrapComprehensionIIFE)
1096
- - **Work at IR level, not string level!**
1097
-
1098
- All 938 tests passing (100%) ✅
1099
-
1100
- ## [1.4.2] - 2025-11-07
1101
-
1102
- ### Fixed
1103
- - **Critical: Fix 'in' operator with string literals** - Restores self-hosting!
1104
- - JavaScript's `in` operator checks numeric indices on strings, NOT characters
1105
- - `'\n' in "text"` incorrectly returns `false` (should check if newline exists)
1106
- - Fixed `generateIn()` to detect string literal checks and use `.includes()`
1107
- - Pattern: `'x' in variable` → runtime type check with `.includes()` for strings/arrays
1108
- - **This broke parser regeneration since Phase 1!** (`bun run parser` now works ✅)
1109
- - Added 7 tests for string literal `in` operator behavior
1110
- - Critical for bootstrap: solar.rip uses `'\n' in action` pattern
1111
-
1112
- ### Changed
1113
- - **Massive code cleanup** - Removed 2,042 lines of dead/duplicate code (28%)!
1114
- - Removed ALL 37 Phase 2 duplicate switch cases (1,614 lines) - never cleaned after extraction
1115
- - Removed old* cases (47 lines), error-throwing cases (26 lines), forwarding cases (185 lines)
1116
- - Removed duplicate property cases (149 lines), function cases (185 lines)
1117
- - Eliminated pointless switch wrapper with only default case (4 lines)
1118
- - Extracted duplicate `findPostfixConditional` helper (DRY principle)
1119
- - Added missing assignment operators to dispatch table
1120
- - Centralized number literal regex patterns
1121
- - Result: 7,263 → 5,239 LOC (27.9% reduction!)
1122
-
1123
- ### Documentation
1124
- - Consolidated AI agent docs into single AGENT.md (removed duplicate rip-agent-onboarding.md)
1125
- - Updated all LOC references (5,239 LOC, ~45% smaller than CoffeeScript)
1126
- - Cleaned up 8 obsolete planning docs
1127
- - Created simple .cursor/rules/rip-quick-start.md pointer
1128
-
1129
- All 938 tests passing (100%) ✅
1130
-
1131
- ## [1.4.1] - 2025-11-07
1132
-
1133
- ### Changed
1134
- - **Dispatch table Phase 2 complete** (#54) - Extracted all remaining 39 cases (100% complete!)
1135
- - Exception handling: `try`, `throw` (2 cases)
1136
- - Switch statements: `switch`, `when` (2 cases)
1137
- - Comprehensions: `comprehension`, `object-comprehension` (2 cases)
1138
- - Classes: `class`, `super`, `?call`, `?super` (4 cases)
1139
- - Modules: `import`, `export`, `export-default`, `export-all`, `export-from` (5 cases)
1140
- - Special forms: `do-iife`, `regex`, `tagged-template`, `str` (4 cases)
1141
- - **All 110 node types now in dispatch table** - Perfect O(1) lookup ✅
1142
- - Codegen organization complete - Easy to navigate and maintain
1143
- - File size: 6,203 → 7,263 LOC (+1,060 lines from extraction)
1144
- - All 931 tests passing (100%) ✅
1145
-
1146
- ## [1.4.0] - 2025-11-07
1147
-
1148
- ### Changed
1149
- - **Major refactoring: Dispatch table architecture** (#52 Phase 1) - Extracted 71/110 cases (65%)
1150
- - Added O(1) dispatch table (was O(n) switch with 110 cases)
1151
- - Extracted 71 generator methods organized by category
1152
- - Shared methods for similar operations (DRY principle)
1153
- - Binary operators: 20+ cases → 1 shared method
1154
- - Assignment operators: 17 cases → 1 shared method
1155
- - All operators, property access, functions, loops, exception handling extracted
1156
- - ~1,500 lines reorganized into categorized methods
1157
- - Clear organization: operators, property access, functions, control flow, etc.
1158
- - Remaining 39 cases documented for Phase 2
1159
- - Test count: 926 → 931 (+5 tests from Issue #49)
1160
-
1161
- ## [1.3.14] - 2025-11-07
1162
-
1163
- ### Changed
1164
- - **S-expression comprehension generation** (#49) - Removed string manipulation anti-pattern
1165
- - Replaced `unwrapComprehensionIIFE()` with s-expression-based approach
1166
- - Added `generateComprehensionWithTarget()` for direct array building
1167
- - No more generating IIFE then unwrapping with regex ✅
1168
- - Follows same philosophy as Issue #46 improvements
1169
- - **42 lines removed** (string manipulation eliminated)
1170
- - Safer, faster, cleaner code generation
1171
- - Test count: 926 → 931 (+5 tests)
1172
- - Added CODEGEN-ANALYSIS.md with optimization roadmap
1173
-
1174
- ## [1.3.13] - 2025-11-07
1175
-
1176
- ### Fixed
1177
- - **Clean logical chains** (#46) - Flatten nested logical operators at s-expression level
1178
- - Transforms deeply nested chains: `if (((!a && !b) && !c) && d)` → `if (!a && !b && !c && d)`
1179
- - Works by flattening s-expression tree BEFORE code generation (Rip philosophy!)
1180
- - Added `flattenBinaryChain()` to recursively flatten same-operator chains
1181
- - Pure chains unwrap completely, mixed precedence stays safe ✅
1182
- - Example: `arr[len - (x || 1)]` preserves inner parens
1183
- - Much cleaner than regex string manipulation (50 lines vs 100+)
1184
- - Test count: 922 → 926 (+4 tests)
1185
-
1186
- ## [1.3.12] - 2025-11-07
1187
-
1188
- ### Changed
1189
- - **Cleaner output in delimited contexts** (#44) - Removed redundant outer parens
1190
- - Function args: `fn((expr))` → `fn(expr)`
1191
- - Assignments: `x = (value)` → `x = value`
1192
- - Array indices: `arr[(index)]` → `arr[index]`
1193
- - Applied unwrap() in contexts that already provide delimiters
1194
- - Safety preserved: `arr[len - (x || 1)]` keeps inner parens ✅
1195
- - Object literals still protected
1196
- - Test count: 913 → 922 (+9 tests)
1197
-
1198
- ## [1.3.11] - 2025-11-07
1199
-
1200
- ### Fixed
1201
- - **Critical: Safe operator wrapping** - Reverted to conservative wrapping approach
1202
- - Always wrap `&&`, `||`, `??` operators by default (safe precedence)
1203
- - Unwrap only in guaranteed-safe contexts (if/while conditions)
1204
- - Prevents broken JavaScript: `arr[len - (x || 1)]` now preserves parens ✅
1205
- - Mixed precedence now safe: `a - (b || c)` preserves parens ✅
1206
-
1207
- ### Changed
1208
- - **Improved unwrapLogical()** - Better aggressive unwrapping for conditions
1209
- - `if (!isEmpty && isValid)` still clean in conditions ✅
1210
- - But never breaks precedence in mixed contexts ✅
1211
- - Best of both worlds: safety + readability
1212
-
1213
- ## [1.3.10] - 2025-11-06
1214
-
1215
- ### Changed
1216
- - **Eliminated exponential parentheses** (#42) - Removed paren hell in logical operator chains
1217
- - Stopped wrapping `&&`, `||`, `??` operators (left-associative, safe to chain)
1218
- - `(((!a && !b) && !c) && d)` → `!a && !b && !c && d` (4 layers → 0!)
1219
- - Created `unwrapLogical()` for aggressive unwrapping in conditions
1220
- - Matches CoffeeScript clean output
1221
-
1222
- ### Fixed
1223
- - **Unary NOT precedence bug** - `!(a && b)` now generates correctly
1224
- - Was: `!a && b` (wrong precedence) ❌
1225
- - Now: `(!(a && b))` (correct precedence) ✅
1226
-
1227
- ### Changed
1228
- - Test count: 907 → 913 (+6 tests)
1229
-
1230
- ## [1.3.9] - 2025-11-06
1231
-
1232
- ### Fixed
1233
- - **Indentation in for-in loops with index and guard** - Fixed broken indentation
1234
- - For-loops with both index variable and guard clause now indent correctly
1235
- - Root cause: Mixed array building with formatStatements causing double-indent
1236
- - Solution: Direct code building with explicit indent levels (Option 2)
1237
- - Example: `for symbol, i in arr when guard` now has perfect indentation
1238
- - Every statement at correct level (no 0-space or 12-space chaos)
1239
-
1240
- ## [1.3.8] - 2025-11-06
1241
-
1242
- ### Changed
1243
- - **Cleaner conditions** (#40) - Removed excessive double parentheses
1244
- - `if ((x > y))` → `if (x > y)` (single parens)
1245
- - Applied to all conditionals: if, unless, while, until, guards
1246
- - Used existing `unwrap()` helper for consistency
1247
- - Smart negation handling (keeps parens when needed for precedence)
1248
- - More readable, professional output
1249
- - Test count: 901 → 907 (+6 tests)
1250
-
1251
- ## [1.3.7] - 2025-11-06
1252
-
1253
- ### Changed
1254
- - **Cleaner arrow function syntax** (#38) - Remove parens around single parameters
1255
- - `(x) => x * 2` → `x => x * 2` (single simple param)
1256
- - Keeps parens for multiple params, destructuring, defaults, rest
1257
- - Matches ESLint/Prettier standards
1258
- - More idiomatic modern JavaScript
1259
- - Test count: 893 → 901 (+8 tests)
1260
-
1261
- ## [1.3.6] - 2025-11-06
1262
-
1263
- ### Changed
1264
- - **Simplified Object.hasOwn() generation** - Removed unnecessary _pregenerated pattern
1265
- - Direct inline generation instead of wrapper objects
1266
- - Cleaner code flow (~30 lines removed)
1267
- - No need for special handling since Object.hasOwn() is built-in ES2022
1268
-
1269
- ## [1.3.5] - 2025-11-06
1270
-
1271
- ### Changed
1272
- - **Modernized to Object.hasOwn()** (#36) - Replaced hasOwnProperty with ES2022 standard
1273
- - All `obj.hasOwnProperty(key)` → `Object.hasOwn(obj, key)`
1274
- - Cannot be shadowed by instance properties
1275
- - Works with null-prototype objects
1276
- - More readable and safer
1277
- - Uses clean `continue` pattern like CoffeeScript
1278
- - Test count: 891 → 893 (+2 tests)
1279
-
1280
- ## [1.3.4] - 2025-11-06
1281
-
1282
- ### Fixed
1283
- - **Semicolons in all contexts** - Extended clean semicolon removal to nested blocks
1284
- - Function bodies now have clean blocks (no semicolons after `}`)
1285
- - Method bodies now have clean blocks
1286
- - Loop bodies and nested contexts all clean
1287
- - Added helper methods: `needsSemicolon()` and `addSemicolon()`
1288
- - Applied smart semicolon logic to all statement generation
1289
-
1290
- ### Changed
1291
- - Cleaner JavaScript output throughout entire codebase, not just top-level
1292
-
1293
- ## [1.3.3] - 2025-11-06
1294
-
1295
- ### Changed
1296
- - **Cleaner JavaScript output** (#34) - Removed unnecessary semicolons after block statements
1297
- - Function and class declarations no longer have trailing semicolons
1298
- - Control flow blocks (if/for/while/switch/try) no longer have trailing semicolons
1299
- - Produces more idiomatic, professional-looking JavaScript
1300
- - Matches standard formatters (Prettier, ESLint)
1301
- - Test count: 878 → 891 (+13 tests)
1302
-
1303
- ## [1.3.2] - 2025-11-05
1304
-
1305
- ### Changed
1306
- - Minor code cleanup and refinements
1307
- - Updated solar.rip indentation handling for better code generation
1308
-
1309
- ## [1.3.1] - 2025-11-05
1310
-
1311
- ### Added
1312
- - **Otherwise operator (`!?`)** (#32) - Undefined-only coalescing
1313
- - Returns first value that is NOT `undefined`
1314
- - Unlike `??` (nullish), treats `null`, `false`, `0`, `""` as valid values
1315
- - Perfect for optional parameters with meaningful falsy values
1316
- - Syntax: `value1 !? value2 !? 'default'`
1317
- - Example: `timeout = config.timeout !? 5000` (null/0 are valid!)
1318
- - Test count: 868 → 878 (+10 tests)
1319
-
1320
- ## [1.3.0] - 2025-11-05
1321
-
1322
- ### Added
1323
- - **Script execution with proper argument passing** - `rip script.rip -h` now passes `-h` to script
1324
- - Arguments before script name → rip options
1325
- - Arguments after script name → script arguments
1326
- - Fixes issue where rip would consume script's flags
1327
- - **Solar.rip synchronization** - Updated to match solar-parser 1.2.0
1328
- - New CLI options: `--version`, `--info`, `--sexpr`
1329
- - Removed `commonCode` architecture for simpler code generation
1330
- - Fixed file writing bug (was using `unless` incorrectly)
1331
-
1332
- ### Changed
1333
- - Improved CLI argument parsing for better script execution
1334
-
1335
- ## [1.2.2] - 2025-11-04
1336
-
1337
- ### Added
1338
- - **Browser REPL UI improvements** - Cleaner, more intuitive interface
1339
- - Made "Live Compiler" the default tab
1340
- - Added Clear and Run buttons to Rip Source panel
1341
- - Converted checkboxes to toggle buttons (gray/blue states)
1342
- - Consistent header layout across both panes
1343
- - Helpful tooltips on all buttons
1344
-
1345
- ### Fixed
1346
- - **For-loop destructuring with defaults** (#30) - Full CoffeeScript compatibility
1347
- - `for [a, b = 99, c = 88] in arr` now works correctly
1348
- - Generates proper ES6 destructuring with defaults
1349
- - Previously generated invalid s-expressions in patterns
1350
-
1351
- ### Changed
1352
- - Test count: 867 → 868 (+1 test)
1353
-
1354
- ## [1.2.1] - 2025-11-04
1355
-
1356
- ### Fixed
1357
- - **Slice syntax with nested indices** (#28) - Property access after nested brackets now works
1358
- - `line[_[0].length..]` now compiles correctly
1359
- - Fixed lexer rewriter to use bracket depth counting
1360
- - Previously failed with parse error
1361
- - Example: `arr[obj.data[0].length..]` → `arr.slice(obj.data[0].length)`
1362
- - Test count: 865 → 867 (+2 tests)
1363
-
1364
- ## [1.2.0] - 2025-11-04
1365
-
1366
- ### Fixed
1367
- - **Switch without discriminant context bug** (#26) - Statement context no longer adds returns
1368
- - Switch in loops now generates correct code (no invalid returns)
1369
- - Made `generateSwitchAsIfChain()` context-aware
1370
- - Value context: adds returns (switch as expression)
1371
- - Statement context: plain statements (side effects only)
1372
- - **__DATA__ section generation** - Natural code emission without string surgery
1373
- - `var DATA;` now positioned logically before `_setDataSection()` call
1374
- - Removed ~50 lines of complex regex/string manipulation
1375
- - Clean, obvious code generation in `generateProgram()`
1376
- - **S-expression pretty printer** - Restored missing features
1377
- - Fixed heregex handling (multi-line regex collapsing)
1378
- - Fixed program node formatting with proper indentation
1379
- - Faster with Set lookup for INLINE_FORMS
1380
- - Modern JS with optional chaining and nullish coalescing
1381
-
1382
- ### Changed
1383
- - Test count: 864 → 865 (+1 test)
1384
- - Improved code generation architecture
1385
-
1386
- ## [1.1.5] - 2025-11-03
1387
-
1388
- ### Fixed
1389
- - **npm package files** - Added `scripts/serve.js` for `rip -w` command
1390
- - Browser REPL now works for npm users
1391
- - Fixed missing dependency for web server functionality
1392
-
1393
- ### Changed
1394
- - S-expression printer improvements backported to docs/examples/sexpr.rip
1395
-
1396
- ## [1.1.4] - 2025-11-03
1397
-
1398
- ### Fixed
1399
- - **S-expression printer** - Improved performance and correctness
1400
- - Faster Set-based INLINE_FORMS lookup
1401
- - Modern JavaScript features (optional chaining, nullish coalescing)
1402
- - Proper heregex and program node formatting
1403
- - All functionality restored and working
1404
-
1405
- ## [1.1.3] - 2025-11-03
1406
-
1407
- ### Fixed
1408
- - **Package files** - Included `scripts/serve.js` in npm package
1409
- - Required for `rip -w` browser REPL command
1410
-
1411
- ## [1.1.2] - 2025-11-02
1412
-
1413
- ### Added
1414
- - **npm publishing safeguards** (#24) - Professional package configuration
1415
- - `files` whitelist (only 51 essential files published)
1416
- - `prepublishOnly` script (runs tests + rebuilds browser bundle)
1417
- - `pack` script for previewing package contents
1418
- - **Comprehension optimization** (#22) - Eliminated wasteful IIFEs
1419
- - Function-final comprehension assignments ~24% smaller
1420
- - Smarter context detection for when to use IIFE vs plain loop
1421
-
1422
- ### Changed
1423
- - Package size optimized: excludes test/, scripts/, dev files
1424
- - Test count: 864 tests (all passing)
1425
-
1426
- ## [1.1.1] - 2025-11-01
1427
-
1428
- ### Fixed
1429
- - **Browser REPL launcher (`rip -w`)** - Port fallback now works correctly
1430
- - Fixed `ReferenceError: assignedPort is not defined`
1431
- - Server tries port 3000, falls back to OS-assigned port if busy
1432
- - Browser opens with correct port automatically
1433
- - Works when installed globally via `npm install -g rip-lang` or `bun install -g rip-lang`
1434
-
1435
- ### Changed
1436
- - Refactored serve.js to eliminate code duplication
1437
- - Improved port detection by parsing server output
1438
-
1439
- ## [1.1.0] - 2025-11-01
1440
-
1441
- ### Added
1442
- - **Beautiful s-expression formatter** - Canonical format with proper indentation
1443
- - Deployed in CLI (`-s` flag), browser REPL, and as standalone utility
1444
- - 80% more compact than JSON, fully parenthesized
1445
- - Heregex patterns collapsed to single line
1446
- - Meta-circular: Rip code formatting Rip's data structures!
1447
- - **Script execution** - `rip script.rip` now executes directly (no explicit `bun` needed)
1448
- - Auto-detects .rip files and uses Bun loader
1449
- - Passes arguments correctly
1450
- - Shebang support: `#!/usr/bin/env rip`
1451
- - **Browser REPL launcher** - `rip -w` starts local server and opens browser
1452
- - One-command workflow
1453
- - Works offline with local changes
1454
- - Cross-platform (macOS, Windows, Linux)
1455
- - **Resizable REPL panes** - Drag slider between Rip source and JavaScript output
1456
- - **Local time display** - Build timestamp shown in user's timezone
1457
- - **Friendly error messages** - Clear "File not found" instead of stack traces
1458
-
1459
- ### Fixed
1460
- - **Postfix `by` step in comprehensions** - `for i in [0..10] by 2` now works
1461
- - **Nested IIFE elimination** - Major code generation optimization (37% smaller)
1462
- - **Throw in expressions** - Properly wrapped in IIFE
1463
- - **Rest parameters in middle position** - Both functions and array destructuring
1464
- - `def fn(first, ...middle, last)` works
1465
- - `[first, ...middle, last] = arr` works
1466
- - **Parser error messages** - Now show line and column numbers
1467
- - **Range loops without variable** - `for [1..10]` optimization
1468
- - **Comprehension context detection** - Smart IIFE vs plain loop decisions
1469
- - **Step handling refactoring** - Unified logic, 37% code reduction
1470
- - **Global installation** - `rip -w` works correctly when installed via npm/bun
1471
-
1472
- ### Changed
1473
- - Version bumped to 1.1.0
1474
- - Test count: 843 → 864 (+21 tests, all passing)
1475
- - Documentation updated throughout
1476
- - Package.json prepared for NPM publishing
1477
-
1478
- ### Documentation
1479
- - Complete GitHub workflow system (issues, PRs, templates)
1480
- - AI agent onboarding guide
1481
- - CONTRIBUTING.md with real examples
1482
- - Updated README, AGENT.md, COFFEESCRIPT-COMPARISON.md
1483
- - All stats current (864 tests)
1484
-
1485
- ### Infrastructure
1486
- - 10 complete GitHub workflows (issue → branch → test → fix → PR → merge)
1487
- - Comprehensive test coverage (100% passing)
1488
- - Ready for NPM publish
1489
-
1490
- ## [1.0.0] - 2025-10-31
1491
-
1492
- ### Initial Release
1493
- - Complete Rip language compiler
1494
- - CoffeeScript-inspired syntax with modern ES2022 output
1495
- - Zero dependencies (includes SLR(1) parser generator)
1496
- - Self-hosting capability
1497
- - 843/843 tests passing
1498
- - Terminal REPL
1499
- - Browser bundle (43KB brotli-compressed)
1500
- - Complete documentation