rip-lang 2.9.0 → 2.9.1
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 +39 -0
- package/README.md +32 -2
- package/docs/BROWSER.md +8 -8
- package/docs/GUIDE.md +13 -13
- package/docs/INTERNALS.md +11 -11
- package/docs/RATIONALE.md +180 -0
- package/docs/REACTIVITY.md +5 -5
- package/docs/TYPES.md +1132 -0
- package/docs/dist/rip.browser.js +12 -5
- package/docs/dist/rip.browser.min.js +10 -10
- package/docs/dist/rip.browser.min.js.br +0 -0
- package/docs/examples/README.md +21 -142
- package/docs/examples/arrows.rip +3 -13
- package/docs/examples/module.rip +41 -31
- package/docs/examples/reactivity.rip +48 -0
- package/package.json +1 -1
- package/src/compiler.js +13 -3
- package/src/grammar/grammar.rip +2 -2
- package/src/grammar/solar.rip +1 -1
- package/src/parser.js +1 -1
- package/docs/PHILOSOPHY.md +0 -569
- package/docs/WHY-NOT-COFFEESCRIPT.md +0 -186
- package/docs/WHY-YES-RIP.md +0 -757
- package/docs/examples/object-syntax.rip +0 -74
- package/docs/examples/prototype.rip +0 -30
- package/docs/examples/sexpr.rip +0 -128
- package/docs/examples/use-loader.js +0 -9
- package/docs/examples/utils.rip +0 -20
package/docs/PHILOSOPHY.md
DELETED
|
@@ -1,569 +0,0 @@
|
|
|
1
|
-
<p><img src="rip.svg" alt="Rip Logo" width="100"></p>
|
|
2
|
-
|
|
3
|
-
# Rip Philosophy & Design
|
|
4
|
-
|
|
5
|
-
> Why Rip exists, how it compares to CoffeeScript, and the design decisions that shape it.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Table of Contents
|
|
10
|
-
|
|
11
|
-
1. [Why S-Expressions](#1-why-s-expressions)
|
|
12
|
-
2. [Rip vs CoffeeScript](#2-rip-vs-coffeescript)
|
|
13
|
-
3. [Current Assessment](#3-current-assessment)
|
|
14
|
-
4. [The Full Debate](#4-the-full-debate)
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
# 1. Why S-Expressions
|
|
19
|
-
|
|
20
|
-
**TL;DR:** S-expressions make compilers 50% smaller, 10x easier to maintain, and infinitely more elegant.
|
|
21
|
-
|
|
22
|
-
## The Central Insight
|
|
23
|
-
|
|
24
|
-
Most compilers use complex AST node classes. Rip uses **simple arrays**:
|
|
25
|
-
|
|
26
|
-
```javascript
|
|
27
|
-
// Traditional AST (CoffeeScript, TypeScript, Babel)
|
|
28
|
-
class BinaryOp {
|
|
29
|
-
constructor(op, left, right) {
|
|
30
|
-
this.op = op;
|
|
31
|
-
this.left = left;
|
|
32
|
-
this.right = right;
|
|
33
|
-
}
|
|
34
|
-
compile() { /* 50+ lines */ }
|
|
35
|
-
optimize() { /* 30+ lines */ }
|
|
36
|
-
validate() { /* 20+ lines */ }
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Rip's S-Expression
|
|
40
|
-
["+", left, right] // That's it!
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
**Result:** CoffeeScript's compiler is 17,760 LOC. Rip's is ~11,000 LOC—smaller, yet includes a complete reactive runtime with state, computed values, and effects.
|
|
44
|
-
|
|
45
|
-
## The Fundamental Rule
|
|
46
|
-
|
|
47
|
-
> **Transform the IR (s-expressions), not the output (strings)**
|
|
48
|
-
|
|
49
|
-
This single principle led to major refactorings that eliminated over 140 lines of fragile code.
|
|
50
|
-
|
|
51
|
-
## Real-World Example: Flattening Logical Chains
|
|
52
|
-
|
|
53
|
-
**The Problem:**
|
|
54
|
-
```javascript
|
|
55
|
-
// Parser creates deeply nested s-expressions:
|
|
56
|
-
["&&", ["&&", ["&&", ["!", "a"], ["!", "b"]], ["!", "c"]], "d"]
|
|
57
|
-
|
|
58
|
-
// Which generates ugly code:
|
|
59
|
-
if (((!a && !b) && !c) && d)
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
**❌ String Manipulation Approach (What We Didn't Do)**
|
|
63
|
-
|
|
64
|
-
```javascript
|
|
65
|
-
unwrapLogical(code) {
|
|
66
|
-
// Try to fix the OUTPUT with regex
|
|
67
|
-
while (code.includes('((')) {
|
|
68
|
-
code = code.replace(/* complex regex */, /* replacement */);
|
|
69
|
-
// 100+ lines of regex hell
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
**Problems:**
|
|
75
|
-
- 100+ lines of complex regex
|
|
76
|
-
- Fragile (breaks if format changes)
|
|
77
|
-
- Hard to debug
|
|
78
|
-
- Slow (string parsing)
|
|
79
|
-
|
|
80
|
-
**✅ S-Expression Approach (What We Actually Did)**
|
|
81
|
-
|
|
82
|
-
```javascript
|
|
83
|
-
flattenBinaryChain(sexpr) {
|
|
84
|
-
// Transform the IR directly
|
|
85
|
-
if (!Array.isArray(sexpr) || sexpr[0] !== '&&') return sexpr;
|
|
86
|
-
|
|
87
|
-
const operands = [];
|
|
88
|
-
const collect = (expr) => {
|
|
89
|
-
if (Array.isArray(expr) && expr[0] === '&&') {
|
|
90
|
-
for (let i = 1; i < expr.length; i++) {
|
|
91
|
-
collect(expr[i]);
|
|
92
|
-
}
|
|
93
|
-
} else {
|
|
94
|
-
operands.push(expr);
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
collect(sexpr);
|
|
99
|
-
return ['&&', ...operands];
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Input: ["&&", ["&&", a, b], c]
|
|
103
|
-
// Output: ["&&", a, b, c]
|
|
104
|
-
// Generate: "a && b && c"
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
**Benefits:**
|
|
108
|
-
- 50 lines of clear logic
|
|
109
|
-
- Type-safe (works with arrays)
|
|
110
|
-
- Easy to debug (inspect data)
|
|
111
|
-
- Fast (no parsing)
|
|
112
|
-
|
|
113
|
-
## The Developer Experience Gap
|
|
114
|
-
|
|
115
|
-
### Debugging Comparison
|
|
116
|
-
|
|
117
|
-
**String Manipulation:**
|
|
118
|
-
```javascript
|
|
119
|
-
console.log(iifeCode);
|
|
120
|
-
// "(() => {\n const result = [];\n for (const x of arr) {\n..."
|
|
121
|
-
// What you see: A blob of text
|
|
122
|
-
// Time to debug: 20-30 minutes
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
**S-Expression:**
|
|
126
|
-
```javascript
|
|
127
|
-
console.log(sexpr);
|
|
128
|
-
// ["comprehension", ["*", "x", 2], [["for-in", ["x"], ["array", 1, 2, 3], null]], []]
|
|
129
|
-
// What you see: Clear structure
|
|
130
|
-
// Time to debug: 2-3 minutes
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Time to Debug Issue
|
|
134
|
-
|
|
135
|
-
**String Manipulation:** 58 minutes (and that's if you're lucky!)
|
|
136
|
-
**S-Expression:** 8 minutes (and you're confident it's correct)
|
|
137
|
-
|
|
138
|
-
**7x faster debugging!**
|
|
139
|
-
|
|
140
|
-
## The Architecture Lesson
|
|
141
|
-
|
|
142
|
-
### Why CoffeeScript is 17,760 LOC
|
|
143
|
-
|
|
144
|
-
**CoffeeScript's approach:**
|
|
145
|
-
```javascript
|
|
146
|
-
class Literal extends Base
|
|
147
|
-
compile() { ... }
|
|
148
|
-
|
|
149
|
-
class Block extends Base
|
|
150
|
-
compile() { ... }
|
|
151
|
-
|
|
152
|
-
class Op extends Base
|
|
153
|
-
compile() { ... }
|
|
154
|
-
|
|
155
|
-
// 50+ AST node classes
|
|
156
|
-
// 10,000+ LOC of node definitions
|
|
157
|
-
// Complex inheritance hierarchies
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### Why Rip is ~14,000 LOC (with a complete framework)
|
|
161
|
-
|
|
162
|
-
**Rip's approach:**
|
|
163
|
-
```javascript
|
|
164
|
-
generate(sexpr, context) {
|
|
165
|
-
switch (sexpr[0]) {
|
|
166
|
-
case '+': return `(${left} + ${right})`;
|
|
167
|
-
case 'if': return `if (${cond}) { ... }`;
|
|
168
|
-
// Simple pattern matching
|
|
169
|
-
// No classes, no inheritance
|
|
170
|
-
// Just data transformation
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
**The difference:**
|
|
176
|
-
- CoffeeScript: Object-oriented with inheritance
|
|
177
|
-
- Rip: Functional with pattern matching
|
|
178
|
-
|
|
179
|
-
## Practical Guidelines
|
|
180
|
-
|
|
181
|
-
### ✅ DO: Work at S-Expression Level
|
|
182
|
-
|
|
183
|
-
```javascript
|
|
184
|
-
// Good: Transform before generating
|
|
185
|
-
const flattened = this.flattenBinaryChain(sexpr);
|
|
186
|
-
return this.generate(flattened, context);
|
|
187
|
-
|
|
188
|
-
// Good: Detect pattern and change generation
|
|
189
|
-
if (this.comprehensionTarget) {
|
|
190
|
-
return this.generateComprehensionWithTarget(...);
|
|
191
|
-
}
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
### ❌ DON'T: Manipulate Generated Strings
|
|
195
|
-
|
|
196
|
-
```javascript
|
|
197
|
-
// Bad: Generate then parse
|
|
198
|
-
const code = this.generate(expr);
|
|
199
|
-
const unwrapped = code.match(/pattern/);
|
|
200
|
-
|
|
201
|
-
// Bad: String replacement
|
|
202
|
-
return code.replace(/old/g, 'new');
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
## The Philosophy
|
|
206
|
-
|
|
207
|
-
### Lisp Got It Right 60 Years Ago
|
|
208
|
-
|
|
209
|
-
```lisp
|
|
210
|
-
; Code is data, data is code
|
|
211
|
-
(+ 1 2) ; This is both an expression AND a list
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
**The insight:** When your IR is simple data (lists/arrays), transformations are trivial!
|
|
215
|
-
|
|
216
|
-
### Why Other Languages Forgot
|
|
217
|
-
|
|
218
|
-
**Traditional compiler theory:**
|
|
219
|
-
- "You need typed AST nodes"
|
|
220
|
-
- "Object-oriented design is cleaner"
|
|
221
|
-
- "Visitor pattern for traversal"
|
|
222
|
-
|
|
223
|
-
**Reality:**
|
|
224
|
-
- AST nodes → Complex inheritance
|
|
225
|
-
- OOP → Boilerplate everywhere
|
|
226
|
-
- Visitor pattern → Indirection hell
|
|
227
|
-
|
|
228
|
-
**Rip remembered:**
|
|
229
|
-
- Arrays → Simple access
|
|
230
|
-
- Pattern matching → Direct logic
|
|
231
|
-
- Recursion → Natural traversal
|
|
232
|
-
|
|
233
|
-
## The Bottom Line
|
|
234
|
-
|
|
235
|
-
**Question:** Why s-expressions?
|
|
236
|
-
|
|
237
|
-
**Answer:** Because transforming **data** is easier than parsing **strings**.
|
|
238
|
-
|
|
239
|
-
**Evidence:**
|
|
240
|
-
- 35% smaller compiler
|
|
241
|
-
- 10x easier debugging
|
|
242
|
-
- 7x faster refactoring
|
|
243
|
-
- 100% elimination of regex fragility
|
|
244
|
-
- Infinite improvement in developer joy
|
|
245
|
-
|
|
246
|
-
**Philosophy:** Simplicity scales. ✨
|
|
247
|
-
|
|
248
|
-
---
|
|
249
|
-
|
|
250
|
-
# 2. Rip vs CoffeeScript
|
|
251
|
-
|
|
252
|
-
## Quick Summary
|
|
253
|
-
|
|
254
|
-
| Metric | CoffeeScript | Rip |
|
|
255
|
-
|--------|--------------|-----|
|
|
256
|
-
| **Feature Parity** | Baseline | ~99% |
|
|
257
|
-
| **Unique Features** | 0 | 10+ innovations |
|
|
258
|
-
| **Dependencies** | Multiple | **ZERO** |
|
|
259
|
-
| **Self-Hosting** | No | **YES** |
|
|
260
|
-
| **Total LOC** | 17,760 | ~14,000 |
|
|
261
|
-
|
|
262
|
-
## Rip's Killer Features (Not in CoffeeScript)
|
|
263
|
-
|
|
264
|
-
### 1. Dual Optional Syntax
|
|
265
|
-
|
|
266
|
-
**CoffeeScript:** 4 soak operators (`?`, `?[]`, `?()`, `?::`)
|
|
267
|
-
|
|
268
|
-
**Rip:** 10 total operators - **BOTH CoffeeScript soak AND ES6 optional!**
|
|
269
|
-
|
|
270
|
-
```coffee
|
|
271
|
-
# CoffeeScript soak (transpiled)
|
|
272
|
-
arr?[0] # → (arr != null ? arr[0] : undefined)
|
|
273
|
-
|
|
274
|
-
# ES6 optional (native)
|
|
275
|
-
obj?.prop # → obj?.prop
|
|
276
|
-
arr?.[0] # → arr?.[0]
|
|
277
|
-
x ?? y # → x ?? y
|
|
278
|
-
|
|
279
|
-
# Mix and match!
|
|
280
|
-
obj?.arr?[0] # ES6 + CoffeeScript together!
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
### 2. Zero Dependencies + Self-Hosting
|
|
284
|
-
|
|
285
|
-
```json
|
|
286
|
-
// package.json
|
|
287
|
-
{
|
|
288
|
-
"dependencies": {} // ← ZERO dependencies!
|
|
289
|
-
}
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
**What's included:**
|
|
293
|
-
- ✅ Full compiler (lexer, parser, codegen)
|
|
294
|
-
- ✅ **SLR(1) parser generator** (solar.rip - ~1,000 lines)
|
|
295
|
-
- ✅ Self-hosting capability (Rip compiles itself)
|
|
296
|
-
- ✅ Triple REPL (terminal, browser, console)
|
|
297
|
-
- ✅ Test framework
|
|
298
|
-
- ✅ Browser bundler
|
|
299
|
-
|
|
300
|
-
**Bootstrap loop:**
|
|
301
|
-
```bash
|
|
302
|
-
# Rip compiles the parser generator
|
|
303
|
-
./bin/rip src/grammar/solar.rip → solar.js
|
|
304
|
-
|
|
305
|
-
# solar.js compiles the grammar
|
|
306
|
-
bun solar.js src/grammar/grammar.rip → parser.js
|
|
307
|
-
|
|
308
|
-
# parser.js used by Rip → COMPLETE LOOP ✅
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
### 3. Ternary Operator (JavaScript Style)
|
|
312
|
-
|
|
313
|
-
```coffee
|
|
314
|
-
# Both styles work in Rip!
|
|
315
|
-
result = cond ? truthy : falsy # JavaScript style
|
|
316
|
-
result = if cond then truthy else falsy # CoffeeScript style
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
**Why possible:** By using `??` for nullish, `?` became available for ternary.
|
|
320
|
-
|
|
321
|
-
### 4. Heregex (Extended Regular Expressions)
|
|
322
|
-
|
|
323
|
-
```rip
|
|
324
|
-
pattern = ///
|
|
325
|
-
^ \d+ # starts with digits
|
|
326
|
-
\s* # optional whitespace
|
|
327
|
-
[a-z]+ # followed by letters
|
|
328
|
-
$ # end of string
|
|
329
|
-
///gi
|
|
330
|
-
|
|
331
|
-
# Compiles to: /^\d+\s*[a-z]+$/gi
|
|
332
|
-
# Comments and whitespace automatically stripped!
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
### 5. Ruby-Style Regex
|
|
336
|
-
|
|
337
|
-
```rip
|
|
338
|
-
# =~ operator with automatic _ capture
|
|
339
|
-
email =~ /(.+)@(.+)/
|
|
340
|
-
username = _[1]
|
|
341
|
-
domain = _[2]
|
|
342
|
-
|
|
343
|
-
# Inline extraction
|
|
344
|
-
zip = "12345-6789"[/^(\d{5})/, 1] # Returns "12345"
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
### 6. Dammit Operator (Call-and-Await)
|
|
348
|
-
|
|
349
|
-
```rip
|
|
350
|
-
# The ! operator calls AND awaits
|
|
351
|
-
result = fetchData! # → await fetchData()
|
|
352
|
-
user = getUser!(id) # → await getUser(id)
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
### 7. Void Functions (Side-Effect Only)
|
|
356
|
-
|
|
357
|
-
```rip
|
|
358
|
-
# ! at definition suppresses implicit returns
|
|
359
|
-
def processItems!
|
|
360
|
-
for item in items
|
|
361
|
-
item.update()
|
|
362
|
-
# ← Returns undefined, not last expression
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
### 8. Smart Comprehension Optimization
|
|
366
|
-
|
|
367
|
-
```rip
|
|
368
|
-
fn = ->
|
|
369
|
-
process x for x in arr # ← Rip: plain loop!
|
|
370
|
-
doMore() # ← Last statement returns
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
**CoffeeScript:** Generates IIFE (wasteful array building)
|
|
374
|
-
**Rip:** Context-aware - plain loop when result unused!
|
|
375
|
-
|
|
376
|
-
### 9. __DATA__ Marker
|
|
377
|
-
|
|
378
|
-
```rip
|
|
379
|
-
console.log "Config:", DATA
|
|
380
|
-
|
|
381
|
-
__DATA__
|
|
382
|
-
host=localhost
|
|
383
|
-
port=8080
|
|
384
|
-
debug=true
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
Ruby-style __DATA__ marker for inline config/templates/test data.
|
|
388
|
-
|
|
389
|
-
### 10. Auto-Detection
|
|
390
|
-
|
|
391
|
-
```coffee
|
|
392
|
-
# No manual async keyword needed!
|
|
393
|
-
getData = ->
|
|
394
|
-
await fetch(url)
|
|
395
|
-
# Automatically becomes: async function getData()
|
|
396
|
-
|
|
397
|
-
# No manual * needed!
|
|
398
|
-
counter = ->
|
|
399
|
-
yield 1
|
|
400
|
-
# Automatically becomes: function* counter()
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
## Key Design Differences
|
|
404
|
-
|
|
405
|
-
### Module System
|
|
406
|
-
|
|
407
|
-
| CoffeeScript | Rip | Rationale |
|
|
408
|
-
|-------------|-----|-----------|
|
|
409
|
-
| CommonJS | ES6 modules | Future-proof, tree-shaking |
|
|
410
|
-
| `require()` | `import` | Native browser support |
|
|
411
|
-
|
|
412
|
-
### Class Compilation
|
|
413
|
-
|
|
414
|
-
| CoffeeScript | Rip | Rationale |
|
|
415
|
-
|-------------|-----|-----------|
|
|
416
|
-
| ES5 functions | ES6 classes | Cleaner, native, optimized |
|
|
417
|
-
|
|
418
|
-
### Implementation Comparison
|
|
419
|
-
|
|
420
|
-
| Component | CoffeeScript 2.7 | Rip | Difference |
|
|
421
|
-
|-----------|------------------|-----|------------|
|
|
422
|
-
| **Lexer+Rewriter** | 3,558 LOC | 3,537 LOC | Expanded syntax |
|
|
423
|
-
| **Parser Generator** | 2,285 LOC (Jison) | ~1,000 LOC (Solar) | Built-in, ~250× faster! |
|
|
424
|
-
| **Compiler** | 10,346 LOC (AST Nodes) | 5,500 LOC (S-expressions) | +Reactive runtime! |
|
|
425
|
-
| **Total** | **17,760 LOC** | **~11,000 LOC** | **Smaller + reactive runtime** |
|
|
426
|
-
|
|
427
|
-
## Feature Comparison Table
|
|
428
|
-
|
|
429
|
-
| Feature | CoffeeScript | Rip | Winner |
|
|
430
|
-
|---------|-------------|------|--------|
|
|
431
|
-
| **Optional operators** | 4 soak | 10 (5 soak + 5 ES6) | 🏆 Rip |
|
|
432
|
-
| **Ternary** | ❌ No | ✅ Yes | 🏆 Rip |
|
|
433
|
-
| **Heregex** | ⚠️ Deprecated | ✅ Full support | 🏆 Rip |
|
|
434
|
-
| **Regex features** | Basic | ✅ Ruby-style (=~, indexing) | 🏆 Rip |
|
|
435
|
-
| **REPL modes** | 1 (terminal) | 3 (terminal, browser, console) | 🏆 Rip |
|
|
436
|
-
| **Async shorthand** | ❌ No | ✅ Dammit operator | 🏆 Rip |
|
|
437
|
-
| **Void functions** | ❌ No | ✅ Side-effect only | 🏆 Rip |
|
|
438
|
-
| **__DATA__ marker** | ❌ No | ✅ Ruby-style | 🏆 Rip |
|
|
439
|
-
| **Comprehension optimization** | Always IIFE | Context-aware | 🏆 Rip |
|
|
440
|
-
| **Modules** | CommonJS | ES6 | 🏆 Rip |
|
|
441
|
-
| **Classes** | ES5 | ES6 | 🏆 Rip |
|
|
442
|
-
| **Dependencies** | Multiple | ✅ **ZERO** | 🏆 Rip |
|
|
443
|
-
| **Parser generator** | External (Jison) | ✅ **Built-in (solar.rip)** | 🏆 Rip |
|
|
444
|
-
| **Self-hosting** | ❌ No | ✅ **Yes** | 🏆 Rip |
|
|
445
|
-
| **Extensibility** | Hard | Easy | 🏆 Rip |
|
|
446
|
-
| **Block comments** | ✅ Yes | ✅ Yes | 🤝 Tie |
|
|
447
|
-
| **Chained compare** | ✅ Yes | ❌ No | 🏆 CS |
|
|
448
|
-
|
|
449
|
-
**Score:** Rip 16, CoffeeScript 1, Tie 1
|
|
450
|
-
|
|
451
|
-
## When to Use Which
|
|
452
|
-
|
|
453
|
-
### Use CoffeeScript When:
|
|
454
|
-
- ✅ Legacy codebase (already using CoffeeScript)
|
|
455
|
-
- ✅ Need CommonJS modules
|
|
456
|
-
- ✅ Team has CoffeeScript expertise
|
|
457
|
-
|
|
458
|
-
### Use Rip When:
|
|
459
|
-
- ✅ Starting new project
|
|
460
|
-
- ✅ Want modern ES6+ output
|
|
461
|
-
- ✅ Value dual optional syntax
|
|
462
|
-
- ✅ Need 100% test coverage
|
|
463
|
-
- ✅ Want unique features (heregex, regex+, dammit)
|
|
464
|
-
- ✅ Need easy extensibility
|
|
465
|
-
- ✅ Want smaller, cleaner implementation
|
|
466
|
-
|
|
467
|
-
---
|
|
468
|
-
|
|
469
|
-
# 3. Current Assessment
|
|
470
|
-
|
|
471
|
-
> **v2.5.1 - Production-Ready with Fine-Grained Reactivity**
|
|
472
|
-
|
|
473
|
-
## Summary
|
|
474
|
-
|
|
475
|
-
| Layer | Syntax | Runtime | Features | DX | Score |
|
|
476
|
-
|-------|--------|---------|----------|-----|-------|
|
|
477
|
-
| **Reactivity** | A+ | A+ | A+ | A+ | **A+** |
|
|
478
|
-
|
|
479
|
-
## Reactivity ⭐⭐⭐⭐⭐ (Production-Ready)
|
|
480
|
-
|
|
481
|
-
**This is genuinely excellent.**
|
|
482
|
-
|
|
483
|
-
```coffee
|
|
484
|
-
count := 0 # State
|
|
485
|
-
doubled ~= count * 2 # Computed (auto-tracks)
|
|
486
|
-
log ~> console.log count # Effect (auto-runs)
|
|
487
|
-
```
|
|
488
|
-
|
|
489
|
-
| Aspect | Rating | Notes |
|
|
490
|
-
|--------|--------|-------|
|
|
491
|
-
| Syntax | A+ | `:=`, `~=`, `=!` are elegant and unique |
|
|
492
|
-
| Semantics | A | Proper dependency tracking, lazy computed |
|
|
493
|
-
| Performance | A- | Efficient - only recomputes when needed |
|
|
494
|
-
| Scalability | A | Works the same at any scale |
|
|
495
|
-
|
|
496
|
-
**Competitive with:** SolidJS signals, Vue 3 refs, Preact signals
|
|
497
|
-
|
|
498
|
-
## Framework-Agnostic Design
|
|
499
|
-
|
|
500
|
-
Rip's reactivity system is **framework-agnostic** — use it with React, Vue, Svelte, or vanilla JavaScript. The reactive primitives (state, computed, effects) work independently of any UI layer.
|
|
501
|
-
|
|
502
|
-
## Competitive Analysis
|
|
503
|
-
|
|
504
|
-
| Framework | Reactivity | DX | Performance | Overall |
|
|
505
|
-
|-----------|------------|-----|-------------|---------|
|
|
506
|
-
| **Rip** | A+ | A+ | A | **A** |
|
|
507
|
-
| SolidJS | A+ | A | A+ | A |
|
|
508
|
-
| Vue 3 | A- | A | B+ | A- |
|
|
509
|
-
| React | B | A- | B | B+ |
|
|
510
|
-
|
|
511
|
-
**Rip's Position:**
|
|
512
|
-
|
|
513
|
-
| Strength | Why |
|
|
514
|
-
|----------|-----|
|
|
515
|
-
| **Reactivity A+** | State, computed, effects, batching |
|
|
516
|
-
| **DX A+** | Cleanest syntax of all, no boilerplate |
|
|
517
|
-
| **Framework-agnostic** | Use with any UI framework |
|
|
518
|
-
|
|
519
|
-
## Completed Features
|
|
520
|
-
|
|
521
|
-
- [x] Reactivity primitives (state, computed, effects)
|
|
522
|
-
- [x] **Batching** (`__batch()` for grouped updates)
|
|
523
|
-
- [x] **Error primitives** (`__catchErrors`, `__handleError`)
|
|
524
|
-
|
|
525
|
-
## Best Current Uses
|
|
526
|
-
|
|
527
|
-
- Building fast web applications
|
|
528
|
-
- Projects requiring minimal bundle size
|
|
529
|
-
- Learning reactive programming concepts
|
|
530
|
-
- Projects valuing clean syntax over ecosystem size
|
|
531
|
-
|
|
532
|
-
**The framework is production-ready** with performance competitive with the fastest frameworks available.
|
|
533
|
-
|
|
534
|
-
---
|
|
535
|
-
|
|
536
|
-
# 4. The Full Debate
|
|
537
|
-
|
|
538
|
-
For a thorough exploration of the arguments for and against languages like Rip in the modern JavaScript ecosystem, see:
|
|
539
|
-
|
|
540
|
-
- [Why Not CoffeeScript](WHY-NOT-COFFEESCRIPT.md) - The strongest case against revival
|
|
541
|
-
- [Why YES Rip](WHY-YES-RIP.md) - The counter-argument and Rip's answer
|
|
542
|
-
|
|
543
|
-
These documents present a point/counterpoint debate:
|
|
544
|
-
1. **WHY-NOT-COFFEESCRIPT.md** - Makes the case that CoffeeScript should remain a historical artifact, citing ecosystem abandonment, TypeScript's dominance, and tooling degradation.
|
|
545
|
-
2. **WHY-YES-RIP.md** - Directly rebuts each argument, showing how Rip addresses these concerns with zero dependencies, modern output, and unique features.
|
|
546
|
-
|
|
547
|
-
The debate structure demonstrates intellectual honesty—Rip acknowledges the valid criticisms and shows how it provides a different path forward.
|
|
548
|
-
|
|
549
|
-
---
|
|
550
|
-
|
|
551
|
-
## Conclusion
|
|
552
|
-
|
|
553
|
-
**Rip exists because:**
|
|
554
|
-
|
|
555
|
-
1. **Simplicity scales** - S-expressions make compilers maintainable
|
|
556
|
-
2. **Zero dependencies** - True autonomy from the npm ecosystem
|
|
557
|
-
3. **Modern output** - ES6+ everywhere, no legacy baggage
|
|
558
|
-
4. **Unique features** - 10+ innovations CoffeeScript lacks
|
|
559
|
-
5. **Best-in-class DX** - Cleanest syntax in the industry
|
|
560
|
-
6. **Production-ready** - 100% test coverage, self-hosting
|
|
561
|
-
|
|
562
|
-
**Philosophy:** Programming should be joyful, not painful. Rip remembers what we were fighting for.
|
|
563
|
-
|
|
564
|
-
---
|
|
565
|
-
|
|
566
|
-
**See Also:**
|
|
567
|
-
- [GUIDE.md](GUIDE.md) - Complete language reference
|
|
568
|
-
- [INTERNALS.md](INTERNALS.md) - Compiler architecture
|
|
569
|
-
- [BROWSER.md](BROWSER.md) - Browser usage and REPL guide
|