rip-lang 1.1.0 → 1.1.2

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.
Files changed (54) hide show
  1. package/CHANGELOG.md +63 -91
  2. package/README.md +190 -47
  3. package/bin/rip +56 -31
  4. package/docs/COFFEESCRIPT-COMPARISON.md +2 -2
  5. package/docs/SOLAR.md +72 -6
  6. package/docs/WHY-YES-RIP.md +1 -1
  7. package/docs/dist/rip.browser.js +40 -2
  8. package/docs/dist/rip.browser.min.js +170 -168
  9. package/docs/dist/rip.browser.min.js.br +0 -0
  10. package/docs/examples/sexpr.rip +134 -0
  11. package/docs/favicon.zip +0 -0
  12. package/docs/repl.html +4 -131
  13. package/docs/rip-512b.png +0 -0
  14. package/package.json +13 -2
  15. package/src/browser.js +1 -1
  16. package/src/codegen.js +71 -0
  17. package/src/compiler.js +3 -0
  18. package/src/grammar/grammar.rip +25 -25
  19. package/src/grammar/solar.rip +47 -177
  20. package/.cursor/rules/rip-agent-onboarding.md +0 -681
  21. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -98
  22. package/.github/ISSUE_TEMPLATE/coffeescript_compatibility.yml +0 -85
  23. package/.github/ISSUE_TEMPLATE/config.yml +0 -10
  24. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -82
  25. package/.github/ISSUE_TEMPLATE/question.yml +0 -54
  26. package/.github/pull_request_template.md +0 -83
  27. package/AGENT.md +0 -623
  28. package/CONTRIBUTING.md +0 -330
  29. package/SETUP.md +0 -144
  30. package/bar.coffee +0 -394
  31. package/bunfig.toml +0 -11
  32. package/scripts/build-browser.js +0 -76
  33. package/scripts/serve.js +0 -74
  34. package/test/rip/assignment.rip +0 -115
  35. package/test/rip/async.rip +0 -361
  36. package/test/rip/basic.rip +0 -171
  37. package/test/rip/classes.rip +0 -167
  38. package/test/rip/compatibility.rip +0 -338
  39. package/test/rip/comprehensions.rip +0 -104
  40. package/test/rip/control.rip +0 -177
  41. package/test/rip/data.rip +0 -215
  42. package/test/rip/errors.rip +0 -129
  43. package/test/rip/functions.rip +0 -443
  44. package/test/rip/guards.rip +0 -247
  45. package/test/rip/literals.rip +0 -131
  46. package/test/rip/loops.rip +0 -117
  47. package/test/rip/modules.rip +0 -87
  48. package/test/rip/operators.rip +0 -158
  49. package/test/rip/optional.rip +0 -184
  50. package/test/rip/properties.rip +0 -94
  51. package/test/rip/regex.rip +0 -301
  52. package/test/rip/stabilization.rip +0 -825
  53. package/test/rip/strings.rip +0 -483
  54. package/test/runner.js +0 -329
package/CHANGELOG.md CHANGED
@@ -5,106 +5,78 @@ All notable changes to Rip will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [1.1.0] - 2025-11-01
9
-
10
- ### Major Enhancements
11
-
12
- #### Comprehensions & Loops
13
- - **Postfix comprehensions with `by` step** - `(x for x in [0...10] by 2)` now works ([#1](https://github.com/shreeve/rip-lang/issues/1))
14
- - **Range loops without loop variable** - `for [1...N]` for N-time repetition ([#9](https://github.com/shreeve/rip-lang/issues/9))
15
- - **Nested comprehension optimization** - Eliminated wasteful nested IIFEs, 50%+ output reduction ([#11](https://github.com/shreeve/rip-lang/issues/11))
16
- - **Unified step handling** - Supports any negative step (`by -2`, `by -3`), 37% code reduction ([#3](https://github.com/shreeve/rip-lang/issues/3))
8
+ ## [1.1.1] - 2025-11-01
17
9
 
18
- #### Parameter Handling
19
- - **Rest parameters in middle position** - `(first, middle..., last)` now generates valid JavaScript ([#15](https://github.com/shreeve/rip-lang/issues/15))
20
- - **Array destructuring with rest in middle** - `[first, ...middle, last] = arr` works correctly ([#17](https://github.com/shreeve/rip-lang/issues/17))
10
+ ### Fixed
11
+ - **Browser REPL launcher (`rip -w`)** - Port fallback now works correctly
12
+ - Fixed `ReferenceError: assignedPort is not defined`
13
+ - Server tries port 3000, falls back to OS-assigned port if busy
14
+ - Browser opens with correct port automatically
15
+ - Works when installed globally via `npm install -g rip-lang` or `bun install -g rip-lang`
21
16
 
22
- #### Error Handling
23
- - **Throw in expression position** - `x = fn() || throw "error"` wraps in IIFE for valid JS ([#13](https://github.com/shreeve/rip-lang/issues/13))
24
- - **Parser error locations** - Errors now show line and column numbers for easy debugging ([#7](https://github.com/shreeve/rip-lang/issues/7))
17
+ ### Changed
18
+ - Refactored serve.js to eliminate code duplication
19
+ - Improved port detection by parsing server output
25
20
 
26
- #### Developer Experience
27
- - **`rip` executes scripts directly** - `rip script.rip` now runs scripts (no `bun` needed) ([#19](https://github.com/shreeve/rip-lang/issues/19))
28
- - **`rip -w` launches browser REPL** - One command to start local server and open REPL
29
- - **Beautiful s-expression formatter** - Canonical format with 80% less vertical space
30
- - **Friendly error messages** - "File not found: X" instead of stack traces
21
+ ## [1.1.0] - 2025-11-01
31
22
 
32
- ### Browser REPL Enhancements
33
- - **Resizable panes** - Drag slider between Rip source and JavaScript output
23
+ ### Added
24
+ - **Beautiful s-expression formatter** - Canonical format with proper indentation
25
+ - Deployed in CLI (`-s` flag), browser REPL, and as standalone utility
26
+ - 80% more compact than JSON, fully parenthesized
27
+ - Heregex patterns collapsed to single line
28
+ - Meta-circular: Rip code formatting Rip's data structures!
29
+ - **Script execution** - `rip script.rip` now executes directly (no explicit `bun` needed)
30
+ - Auto-detects .rip files and uses Bun loader
31
+ - Passes arguments correctly
32
+ - Shebang support: `#!/usr/bin/env rip`
33
+ - **Browser REPL launcher** - `rip -w` starts local server and opens browser
34
+ - One-command workflow
35
+ - Works offline with local changes
36
+ - Cross-platform (macOS, Windows, Linux)
37
+ - **Resizable REPL panes** - Drag slider between Rip source and JavaScript output
34
38
  - **Local time display** - Build timestamp shown in user's timezone
35
- - **Canonical s-expression display** - Compact, readable format with proper indentation
36
- - **Heregex collapse** - Multi-line regexes displayed as single-line quoted strings
37
-
38
- ### Bug Fixes
39
- - **Comprehension last-statement context** - Fixed array destructuring comprehensions ([#5](https://github.com/shreeve/rip-lang/issues/5))
40
- - **Block comments** - Confirmed working (handled by CoffeeScript lexer)
41
-
42
- ### Infrastructure
43
- - **GitHub issue templates** - Bug report, feature request, CoffeeScript compatibility, questions
44
- - **PR template** - Comprehensive checklist for contributions
45
- - **CONTRIBUTING.md** - Complete workflow guide with real examples
46
- - **docs/WORKFLOW.md** - Quick command reference
47
- - **.cursor/rules/rip-agent-onboarding.md** - AI agent onboarding guide
48
- - **ISSUE-11.md** - Handoff documentation for complex issues
39
+ - **Friendly error messages** - Clear "File not found" instead of stack traces
40
+
41
+ ### Fixed
42
+ - **Postfix `by` step in comprehensions** - `for i in [0..10] by 2` now works
43
+ - **Nested IIFE elimination** - Major code generation optimization (37% smaller)
44
+ - **Throw in expressions** - Properly wrapped in IIFE
45
+ - **Rest parameters in middle position** - Both functions and array destructuring
46
+ - `def fn(first, ...middle, last)` works
47
+ - `[first, ...middle, last] = arr` works
48
+ - **Parser error messages** - Now show line and column numbers
49
+ - **Range loops without variable** - `for [1..10]` optimization
50
+ - **Comprehension context detection** - Smart IIFE vs plain loop decisions
51
+ - **Step handling refactoring** - Unified logic, 37% code reduction
52
+ - **Global installation** - `rip -w` works correctly when installed via npm/bun
53
+
54
+ ### Changed
55
+ - Version bumped to 1.1.0
56
+ - Test count: 843 → 864 (+21 tests, all passing)
57
+ - Documentation updated throughout
58
+ - Package.json prepared for NPM publishing
49
59
 
50
60
  ### Documentation
51
- - **Real-world output comparison** - Demonstrated 50% smaller output vs CoffeeScript
52
- - **Heregex interpolation behavior** - Documented #{} vs ${} in regexes
53
- - **Updated all stats** - Test counts, file references, feature lists
54
- - **Cleaned up HTML files** - Removed outdated files, renamed for clarity
55
-
56
- ### Code Quality
57
- - **Refactored step handling** - Eliminated code duplication, cleaner logic
58
- - **Consistent formatting** - All s-expressions use canonical parenthesized format
59
- - **Meta-circular utilities** - S-expression formatter written in Rip itself
60
-
61
- ### Testing
62
- - **21 new tests added** - Coverage for all new features
63
- - **Test count: 843 → 864** - All passing (100%)
64
- - **Comprehensive coverage** - Nested comprehensions, rest in middle, throw expressions
61
+ - Complete GitHub workflow system (issues, PRs, templates)
62
+ - AI agent onboarding guide
63
+ - CONTRIBUTING.md with real examples
64
+ - Updated README, AGENT.md, COFFEESCRIPT-COMPARISON.md
65
+ - All stats current (864 tests)
65
66
 
66
- ### Package
67
- - **Ready for NPM** - Complete package.json with engines, repository, keywords
68
- - **Bun requirement** - Clearly specified (Bun >=1.0.0)
69
-
70
- ### Real-World Validation
71
- - **bar.coffee migration** - Complex 400-line CoffeeScript file now compiles perfectly
72
- - **Output quality** - 608 lines (CoffeeScript) → 304 lines (Rip) = 50% smaller
73
- - **All features working** - Nested switches, comprehensions, rest params, everything!
74
-
75
- ---
67
+ ### Infrastructure
68
+ - 10 complete GitHub workflows (issue branch test → fix → PR → merge)
69
+ - Comprehensive test coverage (100% passing)
70
+ - Ready for NPM publish
76
71
 
77
72
  ## [1.0.0] - 2025-10-31
78
73
 
79
74
  ### Initial Release
80
-
81
- - ✅ Complete CoffeeScript-inspired syntax
82
- - 843/843 tests passing (100%)
83
- - Zero dependencies
84
- - Self-hosting compiler
85
- - ES2022 output
86
- - Triple REPL (terminal, browser, console)
87
- - 43KB browser bundle
88
- - ✅ Comprehensive documentation
89
-
90
- **Features:**
91
- - Dual optional syntax (CoffeeScript soak + ES6 optional chaining)
92
- - Dammit operator (`!`) for call-and-await
93
- - Void functions (side-effect only)
94
- - Heregex (extended regex with comments)
95
- - Ruby-style regex (`=~` operator, indexing)
96
- - __DATA__ marker
97
- - Auto-detection (async/generators)
98
- - Context-aware comprehensions
99
- - Smart range optimization
100
-
101
- **Implementation:**
102
- - 9,450 LOC (50% smaller than CoffeeScript's 17,760)
103
- - S-expression IR (simple arrays vs complex AST)
104
- - SLR(1) parser generator included (solar.rip)
105
- - Complete ES6 module support
106
-
107
- ---
108
-
109
- [1.1.0]: https://github.com/shreeve/rip-lang/compare/v1.0.0...v1.1.0
110
- [1.0.0]: https://github.com/shreeve/rip-lang/releases/tag/v1.0.0
75
+ - Complete Rip language compiler
76
+ - CoffeeScript-inspired syntax with modern ES2022 output
77
+ - Zero dependencies (includes SLR(1) parser generator)
78
+ - Self-hosting capability
79
+ - 843/843 tests passing
80
+ - Terminal REPL
81
+ - Browser bundle (43KB brotli-compressed)
82
+ - Complete documentation
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  </p>
10
10
 
11
11
  <p align="center">
12
- <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-1.1.0-blue.svg" alt="Version"></a>
12
+ <a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-1.1.1-blue.svg" alt="Version"></a>
13
13
  <a href="#es2022-target"><img src="https://img.shields.io/badge/target-ES2022-blue.svg" alt="Target"></a>
14
14
  <a href="#current-status"><img src="https://img.shields.io/badge/tests-864%2F864-brightgreen.svg" alt="Tests"></a>
15
15
  <a href="#current-status"><img src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg" alt="Coverage"></a>
@@ -28,17 +28,16 @@ Rip brings CoffeeScript's elegance to modern JavaScript—but **50% smaller**, c
28
28
  #### 💎 Elegant syntax with modern features
29
29
 
30
30
  ```coffee
31
- def parseUsers(...inputs)
32
- users = for input in inputs
33
- # Ruby-style regex with =~ operator and _ captures
34
- if input =~ /^(\w+):([^@]+@[\w.]+)$/
35
- name = _[1] ?? "guest" # Nullish coalescing
36
- domain = input[/@([\w.]+)/, 1] # Regex extraction syntax
37
- { name, domain }
38
-
39
31
  # Async with dammit operator! (call and await)
40
32
  fetchUser = (id) => fetch! "/api/user/${id}"
41
33
 
34
+ # Ruby-style regex with =~ operator and _ captures
35
+ def parseUsers(...inputs)
36
+ users = for input in inputs when input =~ /^(\w+):([^@]+@[\w.]+)$/
37
+ name = _[1] ?? "guest" # Nullish coalescing, _ captures
38
+ domain = input[/@([\w.]+)/, 1] # Regex extraction syntax
39
+ { name, domain }
40
+
42
41
  parseUsers "alice:alice@example.com", "bob:bob@test.org"
43
42
  ```
44
43
 
@@ -47,21 +46,20 @@ parseUsers "alice:alice@example.com", "bob:bob@test.org"
47
46
  ```javascript
48
47
  let _, fetchUser;
49
48
 
49
+ fetchUser = async (id) => await fetch(`/api/user/${id}`);
50
50
  function parseUsers(...inputs) {
51
51
  let domain, name, users;
52
- return (users = (() => {
53
- const result = [];
54
- for (const input of inputs) {
55
- result.push((() => { if ((_ = toSearchable(input).match(/^(\w+):([^@]+@[\w.]+)$/))) {
56
- name = (_[1] ?? "guest");
57
- domain = (_ = toSearchable(input).match(/@([\w.]+)/)) && _[1];
58
- return {name, domain};
59
- } })());
52
+
53
+ users = [];
54
+ for (const input of inputs) {
55
+ if ((_ = toSearchable(input).match(/^(\w+):([^@]+@[\w.]+)$/))) {
56
+ name = (_[1] ?? "guest");
57
+ domain = (_ = toSearchable(input).match(/@([\w.]+)/)) && _[1];
58
+ users.push({name, domain});
60
59
  }
61
- return result;
62
- })());
60
+ }
61
+ return users;
63
62
  };
64
- fetchUser = async (id) => await fetch(`/api/user/${id}`);
65
63
  parseUsers("alice:alice@example.com", "bob:bob@test.org");
66
64
  ```
67
65
 
@@ -190,7 +188,7 @@ case '+': {
190
188
  | Component | CoffeeScript | Rip | Notes |
191
189
  |-----------|--------------|-----|-------|
192
190
  | Lexer+Rewriter | 3,558 LOC | **3,145 LOC** | Expanded syntax |
193
- | Parser Generator | 2,285 LOC (Jison) | **1,047 LOC** (Solar) | Built-in, ~83x faster |
191
+ | Parser Generator | 2,285 LOC (Jison) | **928 LOC** (Solar) | Built-in, ~156× faster! |
194
192
  | Compiler | 10,346 LOC (AST Nodes) | **4,738 LOC** (S-expressions) | Powerful capabilities |
195
193
  | Tools | 1,571 LOC (Repl, Cake) | **520 LOC** (Repl, Browser) | 3 Repl's + Browser |
196
194
  | **Total** | **17,760 LOC** | **9,450 LOC** | **~50% smaller** |
@@ -200,19 +198,131 @@ case '+': {
200
198
  - ✅ **Self-hosting** - Rip compiles itself
201
199
  - ✅ **No external tools** - Just a JavaScript runtime
202
200
 
201
+ ### Real-World Example: The Complete Pipeline
202
+
203
+ Let's see how Rip code flows through the compilation pipeline:
204
+
205
+ **Step 1: Rip Source Code**
206
+ ```coffee
207
+ # Rip code - edit me!
208
+ def fibonacci(n)
209
+ if n <= 1
210
+ n
211
+ else
212
+ fibonacci(n - 1) + fibonacci(n - 2)
213
+
214
+ # Try heregex
215
+ pattern = ///
216
+ ^ \d+ # digits
217
+ \s* # space
218
+ [a-z]+ # letters
219
+ $
220
+ ///i
221
+
222
+ # Try regex features
223
+ email = "user@example.com"
224
+ domain = email[/@(.+)$/, 1]
225
+
226
+ console.log "Fib(10):", fibonacci(10)
227
+ console.log "Domain:", domain
228
+ ```
229
+
230
+ **Step 2: S-Expression Intermediate Representation**
231
+
232
+ The parser converts this to simple arrays (s-expressions):
233
+
234
+ ```lisp
235
+ (program
236
+ (def fibonacci (n)
237
+ (block
238
+ (if (<= n 1) (block n)
239
+ (block (+ (fibonacci (- n 1)) (fibonacci (- n 2)))))))
240
+ (= pattern "/^ \\d+\\s*[a-z]+$/i")
241
+ (= email "user@example.com")
242
+ (= domain (regex-index email /@(.+)$/ 1))
243
+ ((. console log) "Fib(10):" (fibonacci 10))
244
+ ((. console log) "Domain:" domain)
245
+ )
246
+ ```
247
+
248
+ **Key insights:**
249
+ - Each operation is just an array: `["+", left, right]`
250
+ - No complex AST node classes - just plain data
251
+ - Easy to inspect, transform, and debug
252
+ - Pattern matching in codegen is straightforward
253
+
254
+ **Step 3: JavaScript Output**
255
+
256
+ The code generator pattern-matches on s-expressions to produce clean JavaScript:
257
+
258
+ ```javascript
259
+ let _, domain, email, pattern;
260
+
261
+ function fibonacci(n) {
262
+ return ((n <= 1) ? n : (fibonacci((n - 1)) + fibonacci((n - 2))));
263
+ };
264
+ pattern = /^\d+\s*[a-z]+$/i;
265
+ email = "user@example.com";
266
+ domain = (_ = toSearchable(email).match(/@(.+)$/)) && _[1];
267
+ console.log("Fib(10):", fibonacci(10));
268
+ console.log("Domain:", domain);
269
+ ```
270
+
271
+ **The beauty:** Simple arrays in, clean JavaScript out. No complex AST traversal needed!
272
+
273
+ **Try it yourself:**
274
+ ```bash
275
+ # See the s-expressions
276
+ echo 'x = 42' | ./bin/rip -s
277
+
278
+ # See the generated JavaScript
279
+ echo 'x = 42' | ./bin/rip -c
280
+ ```
281
+
203
282
  ---
204
283
 
205
284
  ## Quick Start
206
285
 
207
286
  ### Installation & Setup
208
287
 
288
+ **🚀 Fastest Way: Install from Bun Package Registry**
289
+
290
+ First, install Bun if you haven't already:
291
+
292
+ ```bash
293
+ # Install Bun (macOS, Linux, WSL)
294
+ curl -fsSL https://bun.sh/install | bash
295
+
296
+ # Or on Windows (PowerShell)
297
+ powershell -c "irm bun.sh/install.ps1|iex"
298
+ ```
299
+
300
+ Then install Rip globally:
301
+
302
+ ```bash
303
+ # Install Rip globally
304
+ bun add -g rip-lang
305
+
306
+ # Start the REPL immediately!
307
+ rip
308
+ ```
309
+
310
+ That's it! You can now:
311
+ - Run `rip` anywhere for an interactive REPL
312
+ - Compile Rip files: `rip yourfile.rip`
313
+ - Execute `.rip` files: `bun yourfile.rip`
314
+
315
+ ---
316
+
317
+ **Alternative: Install from Source**
318
+
209
319
  **Step 1: Clone the repository**
210
320
  ```bash
211
321
  git clone https://github.com/shreeve/rip-lang.git
212
- cd rip
322
+ cd rip-lang
213
323
  ```
214
324
 
215
- **Step 2: Set up global Bun loader (recommended)**
325
+ **Step 2: Set up global Bun loader**
216
326
  ```bash
217
327
  # Link Rip globally so it's available everywhere
218
328
  bun link
@@ -245,10 +355,12 @@ cat ~/.bunfig.toml
245
355
  # Should include: preload = ["rip-lang/loader"]
246
356
  ```
247
357
 
358
+ ---
359
+
248
360
  **No npm install needed** - Rip has zero dependencies!
249
361
 
250
362
  **Requirements:**
251
- - **Bun** (recommended) - For automatic `.rip` loader
363
+ - **Bun** (recommended) - For automatic `.rip` loader and REPL
252
364
  - **Or** any ES2022-compatible runtime: Deno, Node.js 12+, modern browsers
253
365
  - Note: Deno/Node require compilation first (`./bin/rip -o output.js input.rip`)
254
366
 
@@ -274,7 +386,7 @@ bun hello.rip
274
386
 
275
387
  **You can also import .rip modules directly:**
276
388
 
277
- ```rip
389
+ ```coffee
278
390
  # utils.rip
279
391
  export def add(a, b)
280
392
  a + b
@@ -282,7 +394,7 @@ export def add(a, b)
282
394
  export multiply = (a, b) => a * b
283
395
  ```
284
396
 
285
- ```rip
397
+ ```coffee
286
398
  # main.rip
287
399
  import { add, multiply } from "./utils.rip"
288
400
 
@@ -300,19 +412,50 @@ bun main.rip # Works automatically!
300
412
  # Interactive REPL
301
413
  ./bin/rip
302
414
 
303
- # Compile to JavaScript
415
+ # Execute a Rip script (default behavior)
304
416
  ./bin/rip examples/fibonacci.rip
305
417
 
306
- # See s-expressions (the IR)
418
+ # Compile and show JavaScript output
419
+ ./bin/rip -c examples/fibonacci.rip
420
+
421
+ # Compile and save to file
422
+ ./bin/rip -o output.js examples/fibonacci.rip
423
+ ```
424
+
425
+ ### Debug Flags (Mix and Match!)
426
+
427
+ Rip supports flexible debugging with flags that can be combined:
428
+
429
+ ```bash
430
+ # Show ONLY s-expressions (no JavaScript)
307
431
  ./bin/rip -s examples/fibonacci.rip
308
432
 
309
- # See tokens (from lexer)
433
+ # Show ONLY tokens (no JavaScript)
310
434
  ./bin/rip -t examples/fibonacci.rip
311
435
 
312
- # Save compiled output
313
- ./bin/rip -o output.js examples/fibonacci.rip
436
+ # Show s-expressions AND JavaScript
437
+ ./bin/rip -s -c examples/fibonacci.rip
438
+
439
+ # Show tokens AND JavaScript
440
+ ./bin/rip -t -c examples/fibonacci.rip
441
+
442
+ # Show EVERYTHING (full debug mode)
443
+ ./bin/rip -s -t -c examples/fibonacci.rip
444
+
445
+ # Pipe mode (no headers, just output)
446
+ ./bin/rip -q -c examples/fibonacci.rip
314
447
  ```
315
448
 
449
+ **How it works:**
450
+ - `rip script.rip` **executes** the script (default behavior)
451
+ - `echo 'code' | rip` **compiles** and shows JavaScript (stdin defaults to compile mode)
452
+ - `-c` flag **compiles** and shows JavaScript output
453
+ - `-o file.js` **compiles** and saves to file
454
+ - `-s` or `-t` alone show **only** that output (no JavaScript)
455
+ - Add `-c` to **also** show the compiled JavaScript
456
+ - Mix and match as needed for debugging
457
+ - Browser REPL always shows JavaScript (checkboxes toggle `-s` and `-t`)
458
+
316
459
  ### Interactive REPL
317
460
 
318
461
  Rip includes a full-featured REPL for interactive development:
@@ -423,7 +566,7 @@ bun run serve # Start dev server (REPL at localhost:3000)
423
566
 
424
567
  ### Core Syntax
425
568
 
426
- ```rip
569
+ ```coffee
427
570
  # Variables (function-scoped, auto-hoisted)
428
571
  x = 42
429
572
  name = "Alice"
@@ -469,7 +612,7 @@ greeting = "Hello, ${name}!"
469
612
 
470
613
  ### Modern Features
471
614
 
472
- ```rip
615
+ ```coffee
473
616
  # Destructuring
474
617
  {name, age} = person
475
618
  [first, second] = numbers
@@ -625,7 +768,7 @@ Rip provides **two distinct approaches** to safe property/method access:
625
768
 
626
769
  **Compiles to explicit null/undefined checks:**
627
770
 
628
- ```rip
771
+ ```coffee
629
772
  # Existence check
630
773
  arr?
631
774
  # → (arr != null)
@@ -657,7 +800,7 @@ a ?= 10
657
800
 
658
801
  **Passes through to native JavaScript:**
659
802
 
660
- ```rip
803
+ ```coffee
661
804
  # Optional property
662
805
  user?.profile?.name
663
806
  # → user?.profile?.name
@@ -689,7 +832,7 @@ a ??= 10
689
832
 
690
833
  **You can combine both styles in the same expression:**
691
834
 
692
- ```rip
835
+ ```coffee
693
836
  # ES6 optional property + CoffeeScript soak index
694
837
  obj?.arr?[0]
695
838
  # → (obj?.arr != null ? obj?.arr[0] : undefined)
@@ -728,12 +871,12 @@ Both syntaxes handle `null` and `undefined` - pick the style that fits your proj
728
871
  ### The Pipeline
729
872
 
730
873
  ```
731
- ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
732
- Source │────>│ Lexer │────>│ Parser │────>│ Codegen
733
- Code │ (Coffee) (Solar) (Rip)
734
- └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
735
- 3,145 LOC 1,047 LOC 4,738 LOC
736
- 15 yrs tested Generated! Optimized!
874
+ ┌────────┐ ┌────────────┐ ┌──────────┐ ┌─────────┐
875
+ Source │───>│ Lexer │───>│ Parser │───>│ Codegen
876
+ Code │ (Coffee) (Solar) (Rip)
877
+ └────────┘ └────────────┘ └──────────┘ └─────────┘
878
+ 3,145 LOC 928 LOC 4,738 LOC
879
+ 15 yrs tested Generated! S-expr Optimized!
737
880
  ```
738
881
 
739
882
  ### Components
@@ -748,8 +891,8 @@ Both syntaxes handle `null` and `undefined` - pick the style that fits your proj
748
891
  - Solar-generated SLR(1) parser
749
892
  - Built from grammar specification
750
893
  - Generates s-expressions directly
751
- - Regenerate with `bun run parser` (~150ms, instant feedback!)
752
- - **Note:** Solar's 83x speed advantage over Jison (150ms vs 12.5s) made rapid grammar iteration possible
894
+ - Regenerate with `bun run parser` (~80ms, instant feedback!)
895
+ - **Note:** Solar's 156× speed advantage over Jison (80ms vs 12.5s) made rapid grammar iteration possible
753
896
 
754
897
  **3. Code Generator** (`src/codegen.js`)
755
898
  - Pattern matches on s-expressions
@@ -995,7 +1138,7 @@ rip/
995
1138
  ```
996
1139
 
997
1140
  3. **Write tests:**
998
- ```rip
1141
+ ```coffee
999
1142
  test "feature name", "code", expectedResult
1000
1143
  ```
1001
1144
 
@@ -1019,7 +1162,7 @@ rip/
1019
1162
 
1020
1163
  Rip requires parentheses for ALL arrow function parameters:
1021
1164
 
1022
- ```rip
1165
+ ```coffee
1023
1166
  # ✅ Always use parentheses
1024
1167
  () => expr # Zero params
1025
1168
  (x) => expr # One param
@@ -1233,7 +1376,7 @@ MIT
1233
1376
  **Inspired by:**
1234
1377
  - CoffeeScript (syntax and lexer)
1235
1378
  - Lisp/Scheme (s-expressions)
1236
- - Solar (parser generator) - **This project wouldn't have been possible without Solar's incredible speed (150ms vs Jison's 12.5 seconds for parser generation). Solar's performance enabled rapid iteration on grammar changes with instant feedback, making development a joy.**
1379
+ - Solar (parser generator) - **This project wouldn't have been possible without Solar's incredible speed (80ms vs Jison's 12.5 seconds for parser generation). Solar's performance enabled rapid iteration on grammar changes with instant feedback, making development a joy.**
1237
1380
  - Ruby (regex operators, __DATA__ marker)
1238
1381
 
1239
1382
  **Built by:** Developers who believe simplicity scales