rip-lang 3.7.4 → 3.8.9
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 +106 -1
- 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 +514 -0
- package/docs/dist/rip-ui.min.js.br +0 -0
- package/docs/dist/rip.browser.js +327 -478
- package/docs/dist/rip.browser.min.js +168 -208
- package/docs/dist/rip.browser.min.js.br +0 -0
- package/docs/dist/ui.js +962 -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 +21 -5
- package/src/compiler.js +191 -292
- package/src/components.js +100 -95
- package/src/grammar/README.md +234 -0
- package/src/grammar/grammar.rip +5 -5
- package/src/grammar/lunar.rip +2412 -0
- package/src/grammar/solar.rip +18 -4
- package/src/lexer.js +53 -24
- package/src/parser-rd.js +3242 -0
- package/src/parser.js +10 -9
- 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/src/parser.js
CHANGED
|
@@ -113,12 +113,12 @@ const parserInstance = {
|
|
|
113
113
|
case 227: return ["yield-from", $[$0]];
|
|
114
114
|
case 228: return ["if", $[$0-1], $[$0]];
|
|
115
115
|
case 229: return $[$0-4].length === 3 ? ["if", $[$0-4][1], $[$0-4][2], ["if", $[$0-1], $[$0]]] : [...$[$0-4], ["if", $[$0-1], $[$0]]];
|
|
116
|
-
case 230: return ["
|
|
116
|
+
case 230: return ["if", ["!", $[$0-1]], $[$0]];
|
|
117
117
|
case 231: return ["if", ["!", $[$0-3]], $[$0-2], $[$0]];
|
|
118
118
|
case 233: return $[$0-2].length === 3 ? ["if", $[$0-2][1], $[$0-2][2], $[$0]] : [...$[$0-2], $[$0]];
|
|
119
119
|
case 235: case 236: return ["if", $[$0], [$[$0-2]]];
|
|
120
120
|
case 237: return ["?:", $[$0-4], $[$0-6], $[$0-1]];
|
|
121
|
-
case 238: case 239: return ["
|
|
121
|
+
case 238: case 239: return ["if", ["!", $[$0]], [$[$0-2]]];
|
|
122
122
|
case 240: return ["try", $[$0]];
|
|
123
123
|
case 241: return ["try", $[$0-1], $[$0]];
|
|
124
124
|
case 242: return ["try", $[$0-2], $[$0]];
|
|
@@ -133,8 +133,8 @@ const parserInstance = {
|
|
|
133
133
|
case 254: return ["when", $[$0-2], $[$0-1]];
|
|
134
134
|
case 255: return ["while", $[$0]];
|
|
135
135
|
case 256: return ["while", $[$0-2], $[$0]];
|
|
136
|
-
case 257: return ["
|
|
137
|
-
case 258: return ["
|
|
136
|
+
case 257: return ["while", ["!", $[$0]]];
|
|
137
|
+
case 258: return ["while", ["!", $[$0-2]], $[$0]];
|
|
138
138
|
case 259: return $[$0-1].length === 2 ? [$[$0-1][0], $[$0-1][1], $[$0]] : [$[$0-1][0], $[$0-1][1], $[$0-1][2], $[$0]];
|
|
139
139
|
case 260: case 261: return $[$0].length === 2 ? [$[$0][0], $[$0][1], [$[$0-1]]] : [$[$0][0], $[$0][1], $[$0][2], [$[$0-1]]];
|
|
140
140
|
case 263: return ["loop", $[$0]];
|
|
@@ -251,11 +251,12 @@ const parserInstance = {
|
|
|
251
251
|
[TERROR, EOF] = [2, 1];
|
|
252
252
|
lexer = Object.create(this.lexer);
|
|
253
253
|
sharedState = { ctx: {} };
|
|
254
|
-
for (const k in this.ctx)
|
|
255
|
-
if (Object.hasOwn(this.ctx, k))
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
254
|
+
for (const k in this.ctx) {
|
|
255
|
+
if (!Object.hasOwn(this.ctx, k))
|
|
256
|
+
continue;
|
|
257
|
+
const v = this.ctx[k];
|
|
258
|
+
sharedState.ctx[k] = v;
|
|
259
|
+
}
|
|
259
260
|
lexer.setInput(input, sharedState.ctx);
|
|
260
261
|
[sharedState.ctx.lexer, sharedState.ctx.parser] = [lexer, this];
|
|
261
262
|
if (lexer.loc == null)
|
package/src/repl.js
CHANGED
|
@@ -370,11 +370,30 @@ export class RipREPL {
|
|
|
370
370
|
// Extract last expression for result capture
|
|
371
371
|
const lines = js.trim().split('\n');
|
|
372
372
|
let lastLine = lines[lines.length - 1];
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
373
|
+
const STMT_RE = /^\s*(import |export |let |const |var |for |while |if |else |switch |try |class |function )/;
|
|
374
|
+
|
|
375
|
+
if (lastLine && !STMT_RE.test(lastLine)) {
|
|
376
|
+
// If the last line is a continuation of a multi-line expression
|
|
377
|
+
// (e.g., })(); from a comprehension IIFE), scan backwards to find
|
|
378
|
+
// where the expression actually starts by tracking delimiter depth
|
|
379
|
+
if (/^\s*[}\)]/.test(lastLine)) {
|
|
380
|
+
let depth = 0;
|
|
381
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
382
|
+
for (const ch of lines[i]) {
|
|
383
|
+
if (ch === '(' || ch === '{' || ch === '[') depth--;
|
|
384
|
+
if (ch === ')' || ch === '}' || ch === ']') depth++;
|
|
385
|
+
}
|
|
386
|
+
if (depth <= 0 && !STMT_RE.test(lines[i])) {
|
|
387
|
+
if (lines[lines.length - 1].endsWith(';'))
|
|
388
|
+
lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
|
|
389
|
+
lines[i] = '__result = ' + lines[i];
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
} else {
|
|
394
|
+
if (lastLine.endsWith(';')) lastLine = lastLine.slice(0, -1);
|
|
395
|
+
lines[lines.length - 1] = '__result = ' + lastLine + ';';
|
|
396
|
+
}
|
|
378
397
|
}
|
|
379
398
|
|
|
380
399
|
// Build module code
|
package/docs/NOTES.md
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
<img src="https://raw.githubusercontent.com/shreeve/rip-lang/main/docs/rip.png" style="width:50px" /> <br>
|
|
2
|
-
|
|
3
|
-
# Rip — Notes
|
|
4
|
-
|
|
5
|
-
Ideas, future plans, and design thoughts for Rip.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Standard Library (`stdlib`)
|
|
10
|
-
|
|
11
|
-
Rip is a zero-dependency language, but a small standard library of useful
|
|
12
|
-
utilities would save users from writing the same one-liners in every project.
|
|
13
|
-
These are **not** language features — they're plain functions that could ship
|
|
14
|
-
as a prelude or optional import.
|
|
15
|
-
|
|
16
|
-
### Candidates
|
|
17
|
-
|
|
18
|
-
```coffee
|
|
19
|
-
# Printing (Ruby's p)
|
|
20
|
-
p = console.log
|
|
21
|
-
|
|
22
|
-
# Exit with optional code (uses implicit `it`)
|
|
23
|
-
exit = -> process.exit(it)
|
|
24
|
-
|
|
25
|
-
# Tap — call a function for side effects, return the original value
|
|
26
|
-
# Useful in pipe chains: data |> tap(console.log) |> process
|
|
27
|
-
tap = (v, fn) -> fn(v); v
|
|
28
|
-
|
|
29
|
-
# Identity — returns its argument unchanged
|
|
30
|
-
# Useful as a default callback: items.filter(id)
|
|
31
|
-
id = -> it
|
|
32
|
-
|
|
33
|
-
# No-op — does nothing
|
|
34
|
-
# Useful as a default handler: onClick ?= noop
|
|
35
|
-
noop = ->
|
|
36
|
-
|
|
37
|
-
# String method aliases (shorter names for common checks)
|
|
38
|
-
String::starts = String::startsWith
|
|
39
|
-
String::ends = String::endsWith
|
|
40
|
-
String::has = String::includes
|
|
41
|
-
|
|
42
|
-
# Clamp a value to a range
|
|
43
|
-
clamp = (v, lo, hi) -> Math.min(Math.max(v, lo), hi)
|
|
44
|
-
|
|
45
|
-
# Sleep for N milliseconds (returns a Promise)
|
|
46
|
-
sleep = (ms) -> new Promise (resolve) -> setTimeout resolve, ms
|
|
47
|
-
|
|
48
|
-
# Times helper — call a function N times, collect results
|
|
49
|
-
times = (n, fn) -> (fn(i) for i in [0...n])
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### Design Questions
|
|
53
|
-
|
|
54
|
-
- **Prelude vs import?** Should these be injected automatically (like Go's
|
|
55
|
-
`fmt` or Rip's reactive runtime), or explicitly imported (`import { p, tap }
|
|
56
|
-
from '@rip-lang/std'`)? Leaning toward explicit — Rip's philosophy is zero
|
|
57
|
-
magic in the output.
|
|
58
|
-
|
|
59
|
-
- **Scope?** Keep it tiny. A stdlib that grows to 500 functions defeats the
|
|
60
|
-
purpose. Each entry should save real keystrokes on something people do
|
|
61
|
-
constantly.
|
|
62
|
-
|
|
63
|
-
- **Node vs Browser?** Some helpers (like `exit`) are Node-only. Others (like
|
|
64
|
-
`p`, `tap`, `sleep`) work everywhere. May want to split into `std` (universal)
|
|
65
|
-
and `std/node` (server-only).
|
|
66
|
-
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
## Future Syntax Ideas
|
|
70
|
-
|
|
71
|
-
Ideas that have been discussed but not yet implemented. Each would need
|
|
72
|
-
design discussion before building.
|
|
73
|
-
|
|
74
|
-
- **`defer`** — Go-style cleanup that runs when the function exits. Compiles
|
|
75
|
-
to try/finally. `defer file.close()`.
|
|
76
|
-
|
|
77
|
-
- **`is a` / `isnt a`** — Readable instanceof. `x is a String` →
|
|
78
|
-
`x instanceof String`.
|
|
79
|
-
|
|
80
|
-
- **`.starts?` / `.ends?` / `.has?`** — Ruby-style question-mark methods.
|
|
81
|
-
`url.starts? "https"` → `url.startsWith("https")`.
|
|
82
|
-
|
|
83
|
-
- **Pattern matching** — `match value` with destructuring arms. Big feature,
|
|
84
|
-
needs careful design.
|
|
85
|
-
|
|
86
|
-
- **Reactive resource operator (`~>?`)** — Language-level `createResource`.
|
|
87
|
-
`user ~>? fetch!("/api/users/#{id}").json!` gives `user.loading`,
|
|
88
|
-
`user.error`, `user.data`. Park until real-world usage shows demand.
|
|
89
|
-
|
|
90
|
-
- **Pipe operator (`|>`) — Hack-style placeholder** — Currently Rip uses
|
|
91
|
-
Elixir-style first-arg insertion. A `%` placeholder for arbitrary position
|
|
92
|
-
(`data |> fn(1, %, 3)`) could be added later if needed. Current design
|
|
93
|
-
covers 95%+ of cases.
|