rip-lang 3.7.3 → 3.8.8
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 +111 -0
- package/README.md +42 -34
- package/docs/RIP-INTERNALS.md +2 -4
- package/docs/RIP-LANG.md +150 -3
- package/docs/RIP-TYPES.md +1 -2
- package/docs/demo.html +342 -0
- package/docs/dist/rip-ui.min.js +516 -0
- package/docs/dist/rip-ui.min.js.br +0 -0
- package/docs/dist/rip.browser.js +379 -461
- package/docs/dist/rip.browser.min.js +204 -220
- package/docs/dist/rip.browser.min.js.br +0 -0
- package/docs/dist/ui.js +956 -0
- package/docs/dist/ui.min.js +2 -0
- package/docs/dist/ui.min.js.br +0 -0
- package/docs/dist/ui.rip +957 -0
- package/docs/dist/ui.rip.br +0 -0
- package/docs/examples.rip +180 -0
- package/docs/index.html +3 -1599
- package/docs/playground-app.html +1022 -0
- package/docs/playground-js.html +1645 -0
- package/docs/playground-rip-ui.html +1419 -0
- package/docs/playground-rip.html +1450 -0
- package/docs/rip-fav.svg +5 -0
- package/package.json +3 -3
- package/scripts/serve.js +3 -2
- package/src/browser.js +38 -16
- package/src/compiler.js +165 -226
- package/src/components.js +153 -140
- package/src/grammar/README.md +234 -0
- package/src/grammar/lunar.rip +2412 -0
- package/src/grammar/solar.rip +18 -4
- package/src/lexer.js +82 -30
- package/src/parser-rd.js +3242 -0
- package/src/parser.js +6 -5
- package/src/repl.js +24 -5
- package/docs/NOTES.md +0 -93
- package/docs/RIP-GUIDE.md +0 -698
- package/docs/RIP-REACTIVITY.md +0 -311
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,117 @@ All notable changes to Rip will be documented in this file.
|
|
|
7
7
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
8
8
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
9
9
|
|
|
10
|
+
## [3.8.8] - 2026-02-16
|
|
11
|
+
|
|
12
|
+
### Compiler — Refactoring & Cleanup
|
|
13
|
+
|
|
14
|
+
- **Comprehension generator deduplication** — Extracted shared `_forInHeader`, `_forOfHeader`, and `_forAsHeader` helpers, consolidating loop header construction across `generateComprehension`, `generateComprehensionWithTarget`, and `generateComprehensionAsLoop`.
|
|
15
|
+
- **Cleaner for-of loop output** — `for own k of obj` now generates flatter JavaScript using `continue` guard clauses instead of nested `if` blocks.
|
|
16
|
+
- **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`.
|
|
17
|
+
- **Dead code removal** — Removed unused `break-if` and `continue-if` compiler handlers (the grammar handles these through the normal `if` path).
|
|
18
|
+
|
|
19
|
+
### REPL — Bug Fix
|
|
20
|
+
|
|
21
|
+
- **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.
|
|
22
|
+
|
|
23
|
+
### Documentation
|
|
24
|
+
|
|
25
|
+
- Fixed inaccurate content on the Rip UI demo About page (compiler/framework sizes, architecture description).
|
|
26
|
+
|
|
27
|
+
## [3.8.7] - 2026-02-14
|
|
28
|
+
|
|
29
|
+
Rip UI loading optimization (combined bundle, build-time compilation, FOUC prevention). See `packages/ui/CHANGELOG.md` v0.3.2.
|
|
30
|
+
|
|
31
|
+
## [3.8.6] - 2026-02-13
|
|
32
|
+
|
|
33
|
+
### Compiler — Render Block Fix
|
|
34
|
+
|
|
35
|
+
- **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`).
|
|
36
|
+
|
|
37
|
+
Rip UI hash routing and static demo. See `packages/ui/CHANGELOG.md` v0.3.1.
|
|
38
|
+
|
|
39
|
+
## [3.8.5] - 2026-02-13
|
|
40
|
+
|
|
41
|
+
### Build — GitHub Pages Fixes
|
|
42
|
+
|
|
43
|
+
- **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.
|
|
44
|
+
- Fixed Async example to use clean chained `!` syntax now that precedence is correct.
|
|
45
|
+
|
|
46
|
+
## [3.8.4] - 2026-02-13
|
|
47
|
+
|
|
48
|
+
### Compiler — Chained Dammit Operator Fix
|
|
49
|
+
|
|
50
|
+
- **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.
|
|
51
|
+
- Playground Async example restored to clean `fetch!(url).json!` syntax.
|
|
52
|
+
- 2 new tests (1,241 total).
|
|
53
|
+
|
|
54
|
+
## [3.8.3] - 2026-02-13
|
|
55
|
+
|
|
56
|
+
### Lexer — Heregex Forward Slash Escaping
|
|
57
|
+
|
|
58
|
+
- **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.
|
|
59
|
+
- 1 new test (1,239 total).
|
|
60
|
+
|
|
61
|
+
## [3.8.2] - 2026-02-13
|
|
62
|
+
|
|
63
|
+
### Compiler — Class Constructor Fixes
|
|
64
|
+
|
|
65
|
+
- **`@param` defaults in constructors** — `constructor: (@count = 0) ->` now correctly compiles to `constructor(count = 0) { this.count = count; }` instead of producing invalid `(.,this,count)` syntax.
|
|
66
|
+
- **`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()`.
|
|
67
|
+
- **Single-expression constructor autoAssignments** — `@param` assignments are now emitted in single-expression constructor bodies (previously only worked in block bodies).
|
|
68
|
+
- 3 new tests (1,238 total).
|
|
69
|
+
|
|
70
|
+
## [3.8.1] - 2026-02-13
|
|
71
|
+
|
|
72
|
+
### Playground — Fix Class Examples
|
|
73
|
+
|
|
74
|
+
- **Constructor syntax fix** — All playground examples now use `constructor: (@name) ->` instead of the bare `(@name) ->` shorthand, which produced invalid JS output.
|
|
75
|
+
|
|
76
|
+
## [3.8.0] - 2026-02-12
|
|
77
|
+
|
|
78
|
+
### Playground — Example Snippets & Source Persistence
|
|
79
|
+
|
|
80
|
+
- **Example snippets dropdown** — 6 curated examples (Basics, Reactive State, Classes, Regex & Strings, Async & Dammit, Full Demo) plus a Custom option for user code.
|
|
81
|
+
- **Source persistence** — Editor content saved to localStorage with 2-second debounce, restored on page load.
|
|
82
|
+
- **Auto-switch to Custom** — Editing code after selecting an example automatically switches the dropdown to Custom.
|
|
83
|
+
- Applied to all three playground versions (playground-rip.html, playground-js.html, playground-rip-ui.html).
|
|
84
|
+
|
|
85
|
+
### Language — Raw Heredocs
|
|
86
|
+
|
|
87
|
+
- **Raw heredocs (`'''\` and `"""\`)** — Appending `\` to a heredoc opener keeps JS escape sequences (`\n`, `\t`, `\u`, `\x`, `\\`) literal in the output.
|
|
88
|
+
- **`.class` shorthand fix** — `div.foo` or `.foo` with indented children in render blocks now produces correct JS.
|
|
89
|
+
|
|
90
|
+
### Parser — Recursive Descent Generator
|
|
91
|
+
|
|
92
|
+
- **Lunar grammar** (`src/grammar/lunar.rip`) — New recursive descent parser generator producing `src/parser-rd.js`.
|
|
93
|
+
- **98.3% test parity** — 1,162 of 1,182 tests passing with the generated parser.
|
|
94
|
+
|
|
95
|
+
## [3.7.4] - 2026-02-12
|
|
96
|
+
|
|
97
|
+
### Compiler — Reactive Scoping & Component Fixes
|
|
98
|
+
|
|
99
|
+
- **Effect cleanup** — `__effect` now captures return values as cleanup functions, run before re-execution and on disposal. Backward-compatible.
|
|
100
|
+
- **Component scope leak** — `collectProgramVariables` no longer recurses into component bodies. Inner `:=` variables don't pollute the outer scope.
|
|
101
|
+
- **Object key reactive transform** — Object literal keys are no longer transformed to `key.value` when the key name matches a reactive variable.
|
|
102
|
+
- **Component effect index** — Fixed `effect[1]` → `effect[2]` for the body of `~>` in components.
|
|
103
|
+
- **Component effect wrapping** — Effects now wrapped in `() => { expr; }` for proper reactivity.
|
|
104
|
+
- **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.
|
|
105
|
+
- **Reactive prop passthrough** — `buildComponentProps` passes `:=` members as signals (not values) to child components. Child's `__state` returns the signal as-is.
|
|
106
|
+
- **Child unmounting** — `generateChildComponent` tracks child instances in `_children`. `__Component.unmount()` cascades depth-first.
|
|
107
|
+
|
|
108
|
+
### Compiler — Nested Function Scope Chain
|
|
109
|
+
|
|
110
|
+
- **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`).
|
|
111
|
+
|
|
112
|
+
### Rip UI — Demo App Working
|
|
113
|
+
|
|
114
|
+
- **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`.
|
|
115
|
+
- **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.
|
|
116
|
+
|
|
117
|
+
### Language — `*@` Merge-This
|
|
118
|
+
|
|
119
|
+
- **`*@ = 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.
|
|
120
|
+
|
|
10
121
|
## [3.7.3] - 2026-02-11
|
|
11
122
|
|
|
12
123
|
### Fixes & Polish
|
package/README.md
CHANGED
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
|
-
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.
|
|
12
|
+
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-3.8.8-blue.svg" alt="Version"></a>
|
|
13
13
|
<a href="#zero-dependencies"><img src="https://img.shields.io/badge/dependencies-ZERO-brightgreen.svg" alt="Dependencies"></a>
|
|
14
|
-
<a href="#"><img src="https://img.shields.io/badge/tests-
|
|
14
|
+
<a href="#"><img src="https://img.shields.io/badge/tests-1%2C241%2F1%2C241-brightgreen.svg" alt="Tests"></a>
|
|
15
15
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green.svg" alt="License"></a>
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
Rip is a modern language inspired by CoffeeScript. It compiles to **ES2022** (classes, `?.`, `??`, modules), adds about a **dozen new operators**, includes **built-in reactivity**, and sports a self-hosting compiler with **zero dependencies** — all in about
|
|
20
|
+
Rip is a modern language inspired by CoffeeScript. It compiles to **ES2022** (classes, `?.`, `??`, modules), adds about a **dozen new operators**, includes **built-in reactivity**, and sports a self-hosting compiler with **zero dependencies** — all in about 11,000 lines of code.
|
|
21
21
|
|
|
22
22
|
> **No imports. No hooks. No dependency arrays. Just write code.**
|
|
23
23
|
|
|
@@ -146,9 +146,9 @@ State, computed values, and effects as language operators:
|
|
|
146
146
|
| Operator | Mnemonic | Example | What it does |
|
|
147
147
|
|----------|----------|---------|--------------|
|
|
148
148
|
| `=` | "gets value" | `x = 5` | Regular assignment |
|
|
149
|
-
| `:=` | "
|
|
149
|
+
| `:=` | "gets state" | `count := 0` | Reactive state container |
|
|
150
150
|
| `~=` | "always equals" | `twice ~= count * 2` | Auto-updates on changes |
|
|
151
|
-
| `~>` | "
|
|
151
|
+
| `~>` | "always calls" | `~> log count` | Runs on dependency changes |
|
|
152
152
|
| `=!` | "equals, dammit!" | `MAX =! 100` | Readonly constant |
|
|
153
153
|
|
|
154
154
|
---
|
|
@@ -227,6 +227,16 @@ html = '''
|
|
|
227
227
|
# Result: " <div>\n <p>Hello</p>\n </div>"
|
|
228
228
|
```
|
|
229
229
|
|
|
230
|
+
**Raw heredoc** — Append `\` to the opening delimiter (`'''\` or `"""\`) to prevent escape processing. Backslash sequences like `\n`, `\t`, `\u` stay literal:
|
|
231
|
+
|
|
232
|
+
```coffee
|
|
233
|
+
script = '''\
|
|
234
|
+
echo "hello\nworld"
|
|
235
|
+
sed 's/\t/ /g' file.txt
|
|
236
|
+
\'''
|
|
237
|
+
# \n and \t stay as literal characters, not newline/tab
|
|
238
|
+
```
|
|
239
|
+
|
|
230
240
|
**Heregex** — Extended regex with comments and whitespace:
|
|
231
241
|
|
|
232
242
|
```coffee
|
|
@@ -252,7 +262,7 @@ Rip's reactivity is framework-agnostic — use it with React, Vue, Svelte, or va
|
|
|
252
262
|
|
|
253
263
|
## Rip UI
|
|
254
264
|
|
|
255
|
-
Ship the
|
|
265
|
+
Ship the ~47KB Rip compiler to the browser. Components are `.rip` source files, compiled on demand, rendered with fine-grained reactivity. No build step. No bundler.
|
|
256
266
|
|
|
257
267
|
```coffee
|
|
258
268
|
Counter = component
|
|
@@ -267,7 +277,7 @@ Counter = component
|
|
|
267
277
|
|
|
268
278
|
Two keywords — `component` and `render` — are all the language adds. Everything else (`:=` state, `~=` computed, methods, lifecycle) is standard Rip.
|
|
269
279
|
|
|
270
|
-
See [@rip-lang/ui](packages/ui/) for the full framework: file-based router, reactive stash,
|
|
280
|
+
See [@rip-lang/ui](packages/ui/) for the full framework: file-based router, reactive stash, component store, and renderer. **[Try the demo](https://shreeve.github.io/rip-lang/demo.html)** — a complete app in one HTML file.
|
|
271
281
|
|
|
272
282
|
---
|
|
273
283
|
|
|
@@ -279,9 +289,9 @@ See [@rip-lang/ui](packages/ui/) for the full framework: file-based router, reac
|
|
|
279
289
|
| **Reactivity** | None | Built-in |
|
|
280
290
|
| **Dependencies** | Multiple | Zero |
|
|
281
291
|
| **Self-hosting** | No | Yes |
|
|
282
|
-
| **Lexer** | 3,558 LOC |
|
|
283
|
-
| **Compiler** | 10,346 LOC | 3,
|
|
284
|
-
| **Total** | 17,760 LOC | ~
|
|
292
|
+
| **Lexer** | 3,558 LOC | 2,024 LOC |
|
|
293
|
+
| **Compiler** | 10,346 LOC | 3,317 LOC |
|
|
294
|
+
| **Total** | 17,760 LOC | ~11,000 LOC |
|
|
285
295
|
|
|
286
296
|
Smaller codebase, modern output, built-in reactivity.
|
|
287
297
|
|
|
@@ -316,25 +326,25 @@ await rip("res = fetch! 'https://api.example.com/todos/1'; res.json!") // → {
|
|
|
316
326
|
|
|
317
327
|
```
|
|
318
328
|
Source -> Lexer -> emitTypes -> Parser -> S-Expressions -> Codegen -> JavaScript
|
|
319
|
-
(
|
|
329
|
+
(2,024) (types.js) (359) ["=", "x", 42] (3,431) + source map
|
|
320
330
|
```
|
|
321
331
|
|
|
322
332
|
Simple arrays (with `.loc`) instead of AST node classes. The compiler is self-hosting — `bun run parser` rebuilds from source.
|
|
323
333
|
|
|
324
334
|
| Component | File | Lines |
|
|
325
335
|
|-----------|------|-------|
|
|
326
|
-
| Lexer + Rewriter | `src/lexer.js` |
|
|
327
|
-
| Compiler + Codegen | `src/compiler.js` | 3,
|
|
336
|
+
| Lexer + Rewriter | `src/lexer.js` | 2,024 |
|
|
337
|
+
| Compiler + Codegen | `src/compiler.js` | 3,431 |
|
|
328
338
|
| Type System | `src/types.js` | 1,099 |
|
|
329
|
-
| Component System | `src/components.js` | 1,
|
|
330
|
-
| Source Maps | `src/sourcemaps.js` |
|
|
339
|
+
| Component System | `src/components.js` | 1,281 |
|
|
340
|
+
| Source Maps | `src/sourcemaps.js` | 121 |
|
|
331
341
|
| Parser (generated) | `src/parser.js` | 359 |
|
|
332
|
-
| Grammar | `src/grammar/grammar.rip` |
|
|
333
|
-
| Parser Generator | `src/grammar/solar.rip` |
|
|
342
|
+
| Grammar | `src/grammar/grammar.rip` | 944 |
|
|
343
|
+
| Parser Generator | `src/grammar/solar.rip` | 929 |
|
|
334
344
|
| REPL | `src/repl.js` | 582 |
|
|
335
|
-
| Browser Entry | `src/browser.js` |
|
|
336
|
-
| Tags | `src/tags.js` |
|
|
337
|
-
| **Total** | | **~10,
|
|
345
|
+
| Browser Entry | `src/browser.js` | 125 |
|
|
346
|
+
| Tags | `src/tags.js` | 62 |
|
|
347
|
+
| **Total** | | **~10,957** |
|
|
338
348
|
|
|
339
349
|
---
|
|
340
350
|
|
|
@@ -344,14 +354,14 @@ Rip includes optional packages for full-stack development:
|
|
|
344
354
|
|
|
345
355
|
| Package | Version | Purpose |
|
|
346
356
|
|---------|---------|---------|
|
|
347
|
-
| [rip-lang](https://www.npmjs.com/package/rip-lang) | 3.
|
|
348
|
-
| [@rip-lang/api](packages/api/) | 1.1.
|
|
349
|
-
| [@rip-lang/server](packages/server/) | 1.1.
|
|
350
|
-
| [@rip-lang/db](packages/db/) | 1.1.
|
|
351
|
-
| [@rip-lang/ui](packages/ui/) | 0.2
|
|
352
|
-
| [@rip-lang/swarm](packages/swarm/) | 1.1.
|
|
353
|
-
| [@rip-lang/csv](packages/csv/) | 1.1.
|
|
354
|
-
| [@rip-lang/schema](packages/schema/) | 0.1.
|
|
357
|
+
| [rip-lang](https://www.npmjs.com/package/rip-lang) | 3.8.8 | Core language compiler |
|
|
358
|
+
| [@rip-lang/api](packages/api/) | 1.1.6 | HTTP framework (Sinatra-style routing, 37 validators) |
|
|
359
|
+
| [@rip-lang/server](packages/server/) | 1.1.5 | Multi-worker app server (hot reload, HTTPS, mDNS) |
|
|
360
|
+
| [@rip-lang/db](packages/db/) | 1.1.4 | DuckDB server with official UI (pure Bun FFI) |
|
|
361
|
+
| [@rip-lang/ui](packages/ui/) | 0.3.2 | Zero-build reactive web framework (stash, router, hash routing) |
|
|
362
|
+
| [@rip-lang/swarm](packages/swarm/) | 1.1.3 | Parallel job runner with worker pool |
|
|
363
|
+
| [@rip-lang/csv](packages/csv/) | 1.1.3 | CSV parser + writer |
|
|
364
|
+
| [@rip-lang/schema](packages/schema/) | 0.1.1 | ORM + validation |
|
|
355
365
|
| [VS Code Extension](packages/vscode/) | 0.3.1 | Syntax highlighting, type intelligence, source maps |
|
|
356
366
|
|
|
357
367
|
```bash
|
|
@@ -390,7 +400,7 @@ rip file.rip # Run
|
|
|
390
400
|
rip -c file.rip # Compile
|
|
391
401
|
rip -t file.rip # Tokens
|
|
392
402
|
rip -s file.rip # S-expressions
|
|
393
|
-
bun run test #
|
|
403
|
+
bun run test # 1241 tests
|
|
394
404
|
bun run parser # Rebuild parser
|
|
395
405
|
bun run browser # Build browser bundle
|
|
396
406
|
```
|
|
@@ -401,12 +411,10 @@ bun run browser # Build browser bundle
|
|
|
401
411
|
|
|
402
412
|
| Guide | Description |
|
|
403
413
|
|-------|-------------|
|
|
404
|
-
| [docs/RIP-
|
|
414
|
+
| [docs/RIP-LANG.md](docs/RIP-LANG.md) | Full language reference (syntax, operators, reactivity, types, future ideas) |
|
|
415
|
+
| [docs/RIP-INTERNALS.md](docs/RIP-INTERNALS.md) | Compiler architecture (lexer, parser, codegen, S-expressions) |
|
|
416
|
+
| [docs/RIP-TYPES.md](docs/RIP-TYPES.md) | Type system specification |
|
|
405
417
|
| [AGENT.md](AGENT.md) | AI agents — get up to speed for working on the compiler |
|
|
406
|
-
| [docs/RIP-LANG.md](docs/RIP-LANG.md) | Users — full language reference |
|
|
407
|
-
| [docs/RIP-TYPES.md](docs/RIP-TYPES.md) | Contributors — type system specification |
|
|
408
|
-
| [docs/RIP-REACTIVITY.md](docs/RIP-REACTIVITY.md) | Users — reactivity deep dive |
|
|
409
|
-
| [docs/RIP-INTERNALS.md](docs/RIP-INTERNALS.md) | Contributors — compiler architecture |
|
|
410
418
|
|
|
411
419
|
---
|
|
412
420
|
|
package/docs/RIP-INTERNALS.md
CHANGED
|
@@ -572,11 +572,9 @@ rip> .js # Toggle JS display
|
|
|
572
572
|
---
|
|
573
573
|
|
|
574
574
|
**See Also:**
|
|
575
|
-
- [RIP-
|
|
576
|
-
- [RIP-LANG.md](RIP-LANG.md) — Language reference
|
|
575
|
+
- [RIP-LANG.md](RIP-LANG.md) — Language reference (includes reactivity deep dive)
|
|
577
576
|
- [RIP-TYPES.md](RIP-TYPES.md) — Type system specification
|
|
578
|
-
- [RIP-REACTIVITY.md](RIP-REACTIVITY.md) — Reactivity deep dive
|
|
579
577
|
|
|
580
578
|
---
|
|
581
579
|
|
|
582
|
-
*Rip 3.
|
|
580
|
+
*Rip 3.8 — 1,241 tests passing — Zero dependencies — Self-hosting — ~11,000 LOC*
|
package/docs/RIP-LANG.md
CHANGED
|
@@ -23,6 +23,7 @@ Rip is a modern reactive language that compiles to ES2022 JavaScript. It combine
|
|
|
23
23
|
13. [JavaScript Interop](#13-javascript-interop)
|
|
24
24
|
14. [Common Patterns](#14-common-patterns)
|
|
25
25
|
15. [Quick Reference](#15-quick-reference)
|
|
26
|
+
16. [Future Ideas](#16-future-ideas)
|
|
26
27
|
|
|
27
28
|
---
|
|
28
29
|
|
|
@@ -84,6 +85,11 @@ multiline = """
|
|
|
84
85
|
"""
|
|
85
86
|
# Result: "This is a\nmulti-line string" (closing """ at col 2 strips 2 spaces)
|
|
86
87
|
|
|
88
|
+
# Raw heredocs — append \ to keep escape sequences literal
|
|
89
|
+
script = '''\
|
|
90
|
+
echo "hello\nworld" # \n stays as \n, not a newline
|
|
91
|
+
\'''
|
|
92
|
+
|
|
87
93
|
# Numbers
|
|
88
94
|
count = 42
|
|
89
95
|
price = 19.99
|
|
@@ -697,9 +703,9 @@ Rip's reactive features are **language-level operators**, not library imports.
|
|
|
697
703
|
| Operator | Name | Read as | Purpose |
|
|
698
704
|
|----------|------|---------|---------|
|
|
699
705
|
| `=` | Assign | "gets value" | Regular assignment |
|
|
700
|
-
| `:=` | State | "
|
|
706
|
+
| `:=` | State | "gets state" | Reactive state variable |
|
|
701
707
|
| `~=` | Computed | "always equals" | Computed value (auto-updates) |
|
|
702
|
-
| `~>` | Effect | "
|
|
708
|
+
| `~>` | Effect | "always calls" | Side effect on dependency change |
|
|
703
709
|
| `=!` | Readonly | "equals, dammit!" | Constant (`const`) |
|
|
704
710
|
|
|
705
711
|
## State (`:=`)
|
|
@@ -829,6 +835,64 @@ __effect(() => { console.log(count.value); });
|
|
|
829
835
|
|
|
830
836
|
The reactive runtime is **automatically inlined** when needed. Non-reactive code produces clean output with no runtime overhead.
|
|
831
837
|
|
|
838
|
+
## Effect Cleanup
|
|
839
|
+
|
|
840
|
+
Effects may return a cleanup function that runs before re-execution and on disposal:
|
|
841
|
+
|
|
842
|
+
```coffee
|
|
843
|
+
~>
|
|
844
|
+
id = setInterval tick, 1000
|
|
845
|
+
-> clearInterval id # cleanup: returned arrow function
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
This enables higher-level reactive utilities — without adding anything to the language.
|
|
849
|
+
|
|
850
|
+
## Timing Primitives
|
|
851
|
+
|
|
852
|
+
Unlike React's `useTransition` or Vue's flush modes, Rip does not add timing to the framework. Timing composes from the triad:
|
|
853
|
+
|
|
854
|
+
```coffee
|
|
855
|
+
# Delay — truthy after source is stable for N ms, falsy immediately
|
|
856
|
+
showLoading := delay 200 -> loading
|
|
857
|
+
|
|
858
|
+
# Debounce — propagates after value stops changing for N ms
|
|
859
|
+
debouncedQuery := debounce 300 -> query
|
|
860
|
+
|
|
861
|
+
# Throttle — at most one update per N ms
|
|
862
|
+
smoothScroll := throttle 100 -> scrollY
|
|
863
|
+
|
|
864
|
+
# Hold — once true, stays true for at least N ms
|
|
865
|
+
showSaved := hold 2000 -> saved
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
All four are implemented using `:=` (output signal) + `~>` (watches source, manages timers) + effect cleanup (cancels pending timers). No new compiler features, no scheduler.
|
|
869
|
+
|
|
870
|
+
### Writable Timing Signals
|
|
871
|
+
|
|
872
|
+
Timing utilities can wrap a source signal directly:
|
|
873
|
+
|
|
874
|
+
```coffee
|
|
875
|
+
navigating = delay 100, __state(false)
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
Reads return the delayed value; writes update the source immediately. A drop-in replacement for `__state` with asymmetric behavior.
|
|
879
|
+
|
|
880
|
+
## Types and Reactivity
|
|
881
|
+
|
|
882
|
+
Reactive operators work with Rip's optional type system:
|
|
883
|
+
|
|
884
|
+
```coffee
|
|
885
|
+
count:: number := 0 # Typed state
|
|
886
|
+
doubled:: number ~= count * 2 # Typed computed
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
Type annotations are erased from `.js` output. In `.d.ts` output, reactive state emits `Signal<T>` and computed values emit `Computed<T>`:
|
|
890
|
+
|
|
891
|
+
```ts
|
|
892
|
+
declare const count: Signal<number>;
|
|
893
|
+
declare const doubled: Computed<number>;
|
|
894
|
+
```
|
|
895
|
+
|
|
832
896
|
---
|
|
833
897
|
|
|
834
898
|
# 7. Async Patterns
|
|
@@ -1383,4 +1447,87 @@ count = 10 # Logs: "Count: 10, Doubled: 20"
|
|
|
1383
1447
|
|
|
1384
1448
|
---
|
|
1385
1449
|
|
|
1386
|
-
|
|
1450
|
+
# 16. Future Ideas
|
|
1451
|
+
|
|
1452
|
+
Ideas and candidates that have been discussed but not yet implemented.
|
|
1453
|
+
|
|
1454
|
+
## Standard Library (`stdlib`)
|
|
1455
|
+
|
|
1456
|
+
Rip is a zero-dependency language, but a small standard library of useful
|
|
1457
|
+
utilities would save users from writing the same one-liners in every project.
|
|
1458
|
+
These are **not** language features — they're plain functions that could ship
|
|
1459
|
+
as a prelude or optional import.
|
|
1460
|
+
|
|
1461
|
+
### Candidates
|
|
1462
|
+
|
|
1463
|
+
```coffee
|
|
1464
|
+
# Printing (Ruby's p)
|
|
1465
|
+
p = console.log
|
|
1466
|
+
|
|
1467
|
+
# Exit with optional code (uses implicit `it`)
|
|
1468
|
+
exit = -> process.exit(it)
|
|
1469
|
+
|
|
1470
|
+
# Tap — call a function for side effects, return the original value
|
|
1471
|
+
# Useful in pipe chains: data |> tap(console.log) |> process
|
|
1472
|
+
tap = (v, fn) -> fn(v); v
|
|
1473
|
+
|
|
1474
|
+
# Identity — returns its argument unchanged
|
|
1475
|
+
# Useful as a default callback: items.filter(id)
|
|
1476
|
+
id = -> it
|
|
1477
|
+
|
|
1478
|
+
# No-op — does nothing
|
|
1479
|
+
# Useful as a default handler: onClick ?= noop
|
|
1480
|
+
noop = ->
|
|
1481
|
+
|
|
1482
|
+
# String method aliases (shorter names for common checks)
|
|
1483
|
+
String::starts = String::startsWith
|
|
1484
|
+
String::ends = String::endsWith
|
|
1485
|
+
String::has = String::includes
|
|
1486
|
+
|
|
1487
|
+
# Clamp a value to a range
|
|
1488
|
+
clamp = (v, lo, hi) -> Math.min(Math.max(v, lo), hi)
|
|
1489
|
+
|
|
1490
|
+
# Sleep for N milliseconds (returns a Promise)
|
|
1491
|
+
sleep = (ms) -> new Promise (resolve) -> setTimeout resolve, ms
|
|
1492
|
+
|
|
1493
|
+
# Times helper — call a function N times, collect results
|
|
1494
|
+
times = (n, fn) -> (fn(i) for i in [0...n])
|
|
1495
|
+
```
|
|
1496
|
+
|
|
1497
|
+
### Design Questions
|
|
1498
|
+
|
|
1499
|
+
- **Prelude vs import?** Should these be injected automatically (like Go's
|
|
1500
|
+
`fmt` or Rip's reactive runtime), or explicitly imported (`import { p, tap }
|
|
1501
|
+
from '@rip-lang/std'`)? Leaning toward explicit — Rip's philosophy is zero
|
|
1502
|
+
magic in the output.
|
|
1503
|
+
|
|
1504
|
+
- **Scope?** Keep it tiny. A stdlib that grows to 500 functions defeats the
|
|
1505
|
+
purpose. Each entry should save real keystrokes on something people do
|
|
1506
|
+
constantly.
|
|
1507
|
+
|
|
1508
|
+
- **Node vs Browser?** Some helpers (like `exit`) are Node-only. Others (like
|
|
1509
|
+
`p`, `tap`, `sleep`) work everywhere. May want to split into `std` (universal)
|
|
1510
|
+
and `std/node` (server-only).
|
|
1511
|
+
|
|
1512
|
+
## Future Syntax Ideas
|
|
1513
|
+
|
|
1514
|
+
Each would need design discussion before building.
|
|
1515
|
+
|
|
1516
|
+
- **`defer`** — Go-style cleanup that runs when the function exits. Compiles
|
|
1517
|
+
to try/finally. `defer file.close()`.
|
|
1518
|
+
|
|
1519
|
+
- **Pattern matching** — `match value` with destructuring arms. Big feature,
|
|
1520
|
+
needs careful design.
|
|
1521
|
+
|
|
1522
|
+
- **Reactive resource operator (`~>?`)** — Language-level `createResource`.
|
|
1523
|
+
`user ~>? fetch!("/api/users/#{id}").json!` gives `user.loading`,
|
|
1524
|
+
`user.error`, `user.data`. Park until real-world usage shows demand.
|
|
1525
|
+
|
|
1526
|
+
- **Pipe operator (`|>`) — Hack-style placeholder** — Currently Rip uses
|
|
1527
|
+
Elixir-style first-arg insertion. A `%` placeholder for arbitrary position
|
|
1528
|
+
(`data |> fn(1, %, 3)`) could be added later if needed. Current design
|
|
1529
|
+
covers 95%+ of cases.
|
|
1530
|
+
|
|
1531
|
+
---
|
|
1532
|
+
|
|
1533
|
+
*Rip 3.8 — 1,241 tests passing — Zero dependencies — Self-hosting — ~11,000 LOC*
|
package/docs/RIP-TYPES.md
CHANGED
|
@@ -1977,6 +1977,5 @@ The type system uses a two-phase approach:
|
|
|
1977
1977
|
---
|
|
1978
1978
|
|
|
1979
1979
|
**See Also:**
|
|
1980
|
-
- [RIP-LANG.md](RIP-LANG.md) — Language reference
|
|
1981
|
-
- [RIP-REACTIVITY.md](RIP-REACTIVITY.md) — Reactive system details
|
|
1980
|
+
- [RIP-LANG.md](RIP-LANG.md) — Language reference (includes reactivity and types)
|
|
1982
1981
|
- [RIP-INTERNALS.md](RIP-INTERNALS.md) — Compiler internals
|