rip-lang 3.13.133 → 3.13.135
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 +0 -1
- package/README.md +4 -7
- package/bin/rip +16 -4
- package/docs/RIP-LANG.md +0 -42
- package/docs/RIP-TYPES.md +47 -52
- package/docs/demo.html +2 -2
- package/docs/dist/rip.js +2294 -1544
- package/docs/dist/rip.min.js +202 -192
- package/docs/dist/rip.min.js.br +0 -0
- package/package.json +1 -1
- package/rip-loader.js +2 -2
- package/src/AGENTS.md +76 -11
- package/src/browser.js +5 -5
- package/src/compiler.js +961 -639
- package/src/components.js +274 -109
- package/src/error.js +250 -0
- package/src/grammar/grammar.rip +2 -12
- package/src/lexer.js +15 -11
- package/src/parser.js +220 -223
- package/src/repl.js +3 -2
- package/src/sourcemap-utils.js +39 -6
- package/src/typecheck.js +312 -80
- package/src/types.js +229 -54
- package/src/ui.rip +4 -0
package/docs/dist/rip.min.js.br
CHANGED
|
Binary file
|
package/package.json
CHANGED
package/rip-loader.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { plugin } from "bun";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
|
-
import { compileToJS } from "./src/compiler.js";
|
|
5
|
+
import { compileToJS, formatError } from "./src/compiler.js";
|
|
6
6
|
|
|
7
7
|
await plugin({
|
|
8
8
|
name: "rip-loader",
|
|
@@ -32,7 +32,7 @@ await plugin({
|
|
|
32
32
|
loader: "js",
|
|
33
33
|
};
|
|
34
34
|
} catch (err) {
|
|
35
|
-
console.error(
|
|
35
|
+
console.error(formatError(err, { file: args.path }));
|
|
36
36
|
throw err;
|
|
37
37
|
}
|
|
38
38
|
});
|
package/src/AGENTS.md
CHANGED
|
@@ -4,6 +4,43 @@ This covers `compiler.js`, `lexer.js`, `components.js`, `browser.js`, `types.js`
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## Architecture Overview
|
|
8
|
+
|
|
9
|
+
The code emitter is `CodeEmitter` in `compiler.js`. It takes s-expression ASTs
|
|
10
|
+
from the parser and produces JavaScript strings. The class was previously called
|
|
11
|
+
`CodeGenerator`; all codegen methods now use `emit*` naming (e.g. `emitIf`,
|
|
12
|
+
`emitSwitch`, `emitClass`). Utility methods that analyze or transform the AST
|
|
13
|
+
without producing output keep descriptive verbs: `collect*`, `extract*`,
|
|
14
|
+
`unwrap*`, `contains*`, `has*`, `find*`, `build*`, `format*`.
|
|
15
|
+
|
|
16
|
+
Key helpers:
|
|
17
|
+
- `asyncIIFE(hasAwait, body)` / `asyncIIFEOpen(hasAwait)` — centralized async
|
|
18
|
+
IIFE wrapping. All 6 expression-context IIFE sites route through these.
|
|
19
|
+
- `_tryPostfixCall(head, rest, context)` — shared postfix-if optimization for
|
|
20
|
+
both simple and complex callee call paths.
|
|
21
|
+
- `_emitArgs(rest)` — shared argument-list emission.
|
|
22
|
+
- `_emitClassMembers(members, parentClass)` — shared class member emission for
|
|
23
|
+
object-style class bodies (handles bound methods, `@param`, `atParamMap`).
|
|
24
|
+
|
|
25
|
+
### Cleanup Status
|
|
26
|
+
|
|
27
|
+
The compiler has been through a hardening pass. Current state:
|
|
28
|
+
|
|
29
|
+
| Area | Status | Notes |
|
|
30
|
+
| ---- | ------ | ----- |
|
|
31
|
+
| Async IIFE emission | Done | All 6 sites centralized via `asyncIIFE`/`asyncIIFEOpen` |
|
|
32
|
+
| `containsAwait` scope | Done | All enclosed nodes checked (disc, conditions, finally, etc.) |
|
|
33
|
+
| `emitClass` | Done | Deduplicated member loops, fixed 3 latent bugs |
|
|
34
|
+
| `emit()` dispatch | Done | Deduplicated postfix-if and args generation |
|
|
35
|
+
| `emitBodyWithReturns` | Reviewed, not refactored | 143 lines, 12 responsibilities — complex but working, no known bugs |
|
|
36
|
+
| `emitAssignment` | Reviewed, not refactored | 138 lines, 8 patterns — complex but working, no known bugs |
|
|
37
|
+
| `emitForIn` | Reviewed, not refactored | 107 lines — inherent complexity from loop variants |
|
|
38
|
+
| `emitProgram` | Reviewed, not refactored | 136 lines — sequential setup, each section unique |
|
|
39
|
+
| Test runner | Done | Async tests tracked via `pendingTests` + `Promise.all` |
|
|
40
|
+
| Test coverage | Done | 1631 tests, async IIFE + class + nested construct coverage |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
7
44
|
## S-Expression Patterns
|
|
8
45
|
|
|
9
46
|
Common patterns:
|
|
@@ -26,7 +63,7 @@ Complete node reference:
|
|
|
26
63
|
['program', ...statements]
|
|
27
64
|
|
|
28
65
|
// Variables & Assignment
|
|
29
|
-
['=', target, value] // x = expr
|
|
66
|
+
['=', target, value] // x = expr
|
|
30
67
|
['+=', target, value] // Also: -=, *=, /=, %=, **=
|
|
31
68
|
['&&=', target, value] ['||=', target, value]
|
|
32
69
|
['?=', target, value] ['??=', target, value]
|
|
@@ -66,7 +103,6 @@ Complete node reference:
|
|
|
66
103
|
['!', expr] ['~', expr] ['typeof', expr]
|
|
67
104
|
['delete', expr] ['instanceof', expr, type]
|
|
68
105
|
['?', expr] // Existence check (x?)
|
|
69
|
-
['defined', expr] // Defined check (x!?)
|
|
70
106
|
['presence', expr] // Presence check (x?!) — Houdini operator
|
|
71
107
|
['++', expr, isPostfix] ['--', expr, isPostfix]
|
|
72
108
|
|
|
@@ -143,7 +179,7 @@ Tagged template bridge:
|
|
|
143
179
|
## Context-Aware Generation
|
|
144
180
|
|
|
145
181
|
```javascript
|
|
146
|
-
|
|
182
|
+
emit(sexpr, context = 'statement')
|
|
147
183
|
```
|
|
148
184
|
|
|
149
185
|
- Value context: emit an expression result
|
|
@@ -151,13 +187,42 @@ generate(sexpr, context = 'statement')
|
|
|
151
187
|
|
|
152
188
|
Comprehensions are the canonical example — value context becomes an IIFE with array building, statement context becomes a plain loop.
|
|
153
189
|
|
|
190
|
+
### Expression-Context Construct Audit
|
|
191
|
+
|
|
192
|
+
When a construct appears in value context and cannot be a simple JS expression, the
|
|
193
|
+
compiler wraps it in an IIFE. If the enclosed code contains `await`, the IIFE must
|
|
194
|
+
be `async` and the call must be `await`ed. All async IIFE sites use the centralized
|
|
195
|
+
`asyncIIFE()` / `asyncIIFEOpen()` helpers.
|
|
196
|
+
|
|
197
|
+
| Construct | Method | IIFE type | Enclosed nodes |
|
|
198
|
+
| --------- | --------- | --------- | -------------- |
|
|
199
|
+
| `if` (multi-stmt) | `emitIfAsExpression` | async IIFE | condition, thenBranch, elseBranches |
|
|
200
|
+
| `switch` | `emitSwitch` | async IIFE | disc, case labels, case bodies, defaultCase |
|
|
201
|
+
| `switch` (no disc) | `emitSwitchAsIfChain` | async IIFE | when-conditions, when-bodies, defaultCase |
|
|
202
|
+
| `try` | `emitTry` | async IIFE | try body, catch clause, finally block |
|
|
203
|
+
| comprehension | `emitComprehension` | async IIFE | expr, iterators, guards |
|
|
204
|
+
| object comp. | `emitObjectComprehension` | async IIFE | keyExpr, valueExpr, iterators, guards |
|
|
205
|
+
| `or return` etc. | `emitControl` | sync IIFE | expr, ctrl value (return/throw semantics) |
|
|
206
|
+
| `x = e or return` | `emitAssignment` | sync IIFE | expr, target, ctrl value |
|
|
207
|
+
| `throw` | `emitThrow` | sync IIFE | throw expression |
|
|
208
|
+
| `do ->` | `emitDoIIFE` | user fn | user's function (handles own async) |
|
|
209
|
+
| ternary `?:` | `emitTernary` | none | direct JS ternary |
|
|
210
|
+
| block (comma) | `emitBlock` | none | comma expression |
|
|
211
|
+
| calls + postfix if | `emit` | none | conditional rewrite |
|
|
212
|
+
| `->` in value | `emitThinArrow` | none | parenthesized function |
|
|
213
|
+
|
|
214
|
+
**Invariant:** every node listed in the "Enclosed nodes" column must appear in
|
|
215
|
+
that site's `containsAwait` check. The sync IIFE sites use `return`/`throw`
|
|
216
|
+
inside the IIFE, which cannot propagate to the enclosing function, so async
|
|
217
|
+
handling is intentionally omitted.
|
|
218
|
+
|
|
154
219
|
## Dispatch Table
|
|
155
220
|
|
|
156
221
|
All node types dispatch through `GENERATORS` for O(1) lookup. To change a feature:
|
|
157
222
|
|
|
158
223
|
1. Inspect the s-expression with `echo 'code' | ./bin/rip -s`
|
|
159
224
|
2. Search `GENERATORS` in `src/compiler.js`
|
|
160
|
-
3. Edit the matching
|
|
225
|
+
3. Edit the matching `emit*` method
|
|
161
226
|
4. Run `bun run test`
|
|
162
227
|
|
|
163
228
|
For grammar work:
|
|
@@ -204,7 +269,7 @@ if (Array.isArray(body) && body[0] === 'block') {
|
|
|
204
269
|
|
|
205
270
|
## Component Internals
|
|
206
271
|
|
|
207
|
-
The component system is a compiler sidecar. `installComponentSupport(
|
|
272
|
+
The component system is a compiler sidecar. `installComponentSupport(CodeEmitter, Lexer)` adds methods to both prototypes.
|
|
208
273
|
|
|
209
274
|
### Render Rewriter
|
|
210
275
|
|
|
@@ -247,9 +312,9 @@ Key mechanisms:
|
|
|
247
312
|
Key entry points:
|
|
248
313
|
|
|
249
314
|
- `buildRender` — initializes counters and create/setup line arrays
|
|
250
|
-
- `
|
|
251
|
-
- `
|
|
252
|
-
- `
|
|
315
|
+
- `emitNode` — dispatch for elements, text, conditionals, loops, components
|
|
316
|
+
- `emitConditional` — emits conditional block factories
|
|
317
|
+
- `emitTemplateLoop` — emits `__reconcile(...)`
|
|
253
318
|
- `emitBlockFactory` — shared factory emitter used by conditionals and loops
|
|
254
319
|
|
|
255
320
|
### Factory Mode
|
|
@@ -263,7 +328,7 @@ Block factories need locals and `ctx.member` references instead of `this._elN` a
|
|
|
263
328
|
- `_pushEffect(body)` — emits `__effect(...)` or `disposers.push(__effect(...))`
|
|
264
329
|
- `_loopVarStack` — threads loop variables through nested factories
|
|
265
330
|
|
|
266
|
-
Factory mode is entered in `
|
|
331
|
+
Factory mode is entered in `emitConditionBranch` and `emitTemplateLoop` via save/restore of `[_createLines, _setupLines, _factoryMode, _factoryVars]`.
|
|
267
332
|
|
|
268
333
|
### Auto-Wired Event Handlers
|
|
269
334
|
|
|
@@ -332,7 +397,7 @@ div ~fade
|
|
|
332
397
|
Pipeline:
|
|
333
398
|
|
|
334
399
|
- rewriter converts the tilde form into `__transition__`
|
|
335
|
-
- `
|
|
400
|
+
- `emitAttributes` emits `this._t = "fade"`
|
|
336
401
|
- conditionals check `_t` for async leave / enter
|
|
337
402
|
- runtime `__transition(el, name, dir, done)` performs the CSS class dance
|
|
338
403
|
|
|
@@ -453,7 +518,7 @@ Type emission logic lives in `types.js`. Type-checking integration and diagnosti
|
|
|
453
518
|
|
|
454
519
|
- `installTypeSupport(Lexer)` adds `rewriteTypes()`
|
|
455
520
|
- `emitTypes(tokens)` emits `.d.ts`
|
|
456
|
-
- `
|
|
521
|
+
- `emitEnum()` emits runtime JS for enums
|
|
457
522
|
- `typecheck.js` drives `rip check` and mediates TypeScript diagnostics
|
|
458
523
|
|
|
459
524
|
Types are processed at the token layer before parsing.
|
package/src/browser.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
export { Lexer } from './lexer.js';
|
|
5
5
|
export { parser } from './parser.js';
|
|
6
|
-
export {
|
|
7
|
-
import { getStdlibCode } from './compiler.js';
|
|
6
|
+
export { CodeEmitter, Compiler, compile, compileToJS, formatSExpr, getStdlibCode, getReactiveRuntime, getComponentRuntime, RipError, formatError, formatErrorHTML } from './compiler.js';
|
|
7
|
+
import { getStdlibCode, formatError as _formatError } from './compiler.js';
|
|
8
8
|
|
|
9
9
|
// Version info (replaced during build)
|
|
10
10
|
export const VERSION = "0.0.0";
|
|
@@ -90,7 +90,7 @@ async function processRipScripts() {
|
|
|
90
90
|
let js = '';
|
|
91
91
|
for (const s of individual) {
|
|
92
92
|
try { js += compileToJS(s.code, opts) + '\n'; }
|
|
93
|
-
catch (e) { console.error(
|
|
93
|
+
catch (e) { console.error(_formatError(e, { source: s.code, file: s.url || 'inline', color: false })); }
|
|
94
94
|
}
|
|
95
95
|
if (js) {
|
|
96
96
|
try { await (0, eval)(`(async()=>{\n${js}\n})()`); }
|
|
@@ -132,7 +132,7 @@ async function processRipScripts() {
|
|
|
132
132
|
const js = compileToJS(s.code, opts);
|
|
133
133
|
compiled.push({ js, url: s.url || 'inline' });
|
|
134
134
|
} catch (e) {
|
|
135
|
-
console.error(
|
|
135
|
+
console.error(_formatError(e, { source: s.code, file: s.url || 'inline', color: false }));
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
|
|
@@ -281,7 +281,7 @@ export function rip(code) {
|
|
|
281
281
|
if (result !== undefined) globalThis._ = result;
|
|
282
282
|
return result;
|
|
283
283
|
} catch (error) {
|
|
284
|
-
console.error(
|
|
284
|
+
console.error(_formatError(error, { source: code, color: false }));
|
|
285
285
|
return undefined;
|
|
286
286
|
}
|
|
287
287
|
}
|