rip-lang 3.13.134 → 3.13.136
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 +1039 -449
- package/docs/dist/rip.min.js +168 -164
- package/docs/dist/rip.min.js.br +0 -0
- package/package.json +1 -1
- package/rip-loader.js +2 -2
- package/src/AGENTS.md +1 -2
- package/src/browser.js +5 -5
- package/src/compiler.js +106 -28
- package/src/components.js +176 -11
- 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 +365 -80
- package/src/types.js +226 -51
- package/src/ui.rip +4 -0
package/src/repl.js
CHANGED
|
@@ -17,7 +17,7 @@ import * as fs from 'fs';
|
|
|
17
17
|
import * as path from 'path';
|
|
18
18
|
import * as os from 'os';
|
|
19
19
|
import * as vm from 'vm';
|
|
20
|
-
import { Compiler, compileToJS, getStdlibCode, getReactiveRuntime, getComponentRuntime } from './compiler.js';
|
|
20
|
+
import { Compiler, compileToJS, getStdlibCode, getReactiveRuntime, getComponentRuntime, formatError } from './compiler.js';
|
|
21
21
|
import packageJson from '../package.json' with { type: 'json' };
|
|
22
22
|
|
|
23
23
|
const VERSION = packageJson.version;
|
|
@@ -205,6 +205,7 @@ export class RipREPL {
|
|
|
205
205
|
async evaluate(code) {
|
|
206
206
|
try {
|
|
207
207
|
this.history.push(code);
|
|
208
|
+
this._lastSource = code;
|
|
208
209
|
|
|
209
210
|
const compiler = new Compiler({
|
|
210
211
|
showTokens: this.showTokens,
|
|
@@ -433,7 +434,7 @@ export class RipREPL {
|
|
|
433
434
|
}
|
|
434
435
|
|
|
435
436
|
printError(error) {
|
|
436
|
-
console.log(
|
|
437
|
+
console.log(formatError(error, { source: this._lastSource, color: true }));
|
|
437
438
|
if (error.stack && process.env.RIP_DEBUG) {
|
|
438
439
|
console.log(`${colors.dim}${error.stack}${colors.reset}`);
|
|
439
440
|
}
|
package/src/sourcemap-utils.js
CHANGED
|
@@ -109,6 +109,10 @@ export function mapToSourcePos(entry, offset) {
|
|
|
109
109
|
// match string literals or identifiers in the source.
|
|
110
110
|
if (/^declare\s+function\s/.test(genLineText)) return null;
|
|
111
111
|
|
|
112
|
+
// If genToSrc has a mapping for this header line (e.g. imports, declarations),
|
|
113
|
+
// use it to target the correct source line for word matching.
|
|
114
|
+
const mappedSrcLine = entry.genToSrc.get(tsLine);
|
|
115
|
+
|
|
112
116
|
let lineStart = 0, curLine = 0;
|
|
113
117
|
for (let i = 0; i < entry.tsContent.length; i++) {
|
|
114
118
|
if (curLine === tsLine) { lineStart = i; break; }
|
|
@@ -121,6 +125,13 @@ export function mapToSourcePos(entry, offset) {
|
|
|
121
125
|
const srcLines = entry.source.split('\n');
|
|
122
126
|
const re = new RegExp('\\b' + word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\b');
|
|
123
127
|
|
|
128
|
+
// If we have a direct line mapping, try that source line first
|
|
129
|
+
if (mappedSrcLine !== undefined) {
|
|
130
|
+
const m = re.exec(srcLines[mappedSrcLine]);
|
|
131
|
+
if (m) return { line: mappedSrcLine, col: m.index };
|
|
132
|
+
return { line: mappedSrcLine, col: genCol };
|
|
133
|
+
}
|
|
134
|
+
|
|
124
135
|
// For let/var declarations, the error word may appear on many source lines
|
|
125
136
|
// (e.g. `Status` referenced in multiple variable annotations). Narrow the
|
|
126
137
|
// search to the source line that declares the same variable.
|
|
@@ -253,13 +264,17 @@ export function mapToSourcePos(entry, offset) {
|
|
|
253
264
|
// Scan ALL source lines for mappings to this gen line — a multi-line Rip
|
|
254
265
|
// expression (e.g. object literal) may compile to a single gen line, so
|
|
255
266
|
// multiple source lines can share one gen line. Pick the closest genCol.
|
|
267
|
+
// On ties, prefer the source line that genToSrc already identified (e.g.
|
|
268
|
+
// from an @rip-src annotation) so that stub render-block expressions land
|
|
269
|
+
// on their correct source lines instead of a sibling attribute line.
|
|
256
270
|
if (entry.srcColToGen) {
|
|
271
|
+
const origSrcLine = srcLine;
|
|
257
272
|
let bestDist = Infinity;
|
|
258
273
|
for (const [sl, entries] of entry.srcColToGen) {
|
|
259
274
|
for (const e of entries) {
|
|
260
275
|
if (e.genLine === tsLine) {
|
|
261
276
|
const dist = Math.abs(e.genCol - genCol);
|
|
262
|
-
if (dist < bestDist) {
|
|
277
|
+
if (dist < bestDist || (dist === bestDist && sl === origSrcLine)) {
|
|
263
278
|
bestDist = dist;
|
|
264
279
|
srcLine = sl;
|
|
265
280
|
approx = e.srcCol + (genCol - e.genCol);
|
|
@@ -310,17 +325,24 @@ export function mapToSourcePos(entry, offset) {
|
|
|
310
325
|
}
|
|
311
326
|
}
|
|
312
327
|
srcCol = Math.max(0, approx);
|
|
328
|
+
}
|
|
313
329
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
330
|
+
// Word not found on mapped line (or line was empty) — search nearby lines
|
|
331
|
+
// (handles cases where multiple source lines compress to one generated line,
|
|
332
|
+
// e.g. constructor params, or srcLine is blank)
|
|
333
|
+
{
|
|
334
|
+
let wordFallback = genText.slice(genCol).match(/^\w+/);
|
|
335
|
+
// Quoted string literal — peek inside the quotes (e.g. __RipProps<'inputz'>)
|
|
336
|
+
if (!wordFallback && (genText[genCol] === "'" || genText[genCol] === '"')) {
|
|
337
|
+
wordFallback = genText.slice(genCol + 1).match(/^\w+/);
|
|
338
|
+
}
|
|
317
339
|
if (wordFallback) {
|
|
318
340
|
let word = wordFallback[0];
|
|
319
341
|
if (word.startsWith('__bind_') && word.endsWith('__')) word = word.slice(7, -2);
|
|
320
342
|
const srcLines = entry.source.split('\n');
|
|
321
343
|
const re = new RegExp('\\b' + word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\b');
|
|
322
|
-
for (let delta =
|
|
323
|
-
for (const d of [srcLine + delta, srcLine - delta]) {
|
|
344
|
+
for (let delta = 0; delta <= 10; delta++) {
|
|
345
|
+
for (const d of delta === 0 ? [srcLine] : [srcLine + delta, srcLine - delta]) {
|
|
324
346
|
if (d >= 0 && d < srcLines.length) {
|
|
325
347
|
const m = re.exec(srcLines[d]);
|
|
326
348
|
if (m) return { line: d, col: m.index };
|
|
@@ -329,5 +351,16 @@ export function mapToSourcePos(entry, offset) {
|
|
|
329
351
|
}
|
|
330
352
|
}
|
|
331
353
|
}
|
|
354
|
+
|
|
355
|
+
// When text matching failed entirely (generated identifier like _2 doesn't
|
|
356
|
+
// exist in source), srcCol may land on whitespace or past EOL. Fall back to
|
|
357
|
+
// the first word on the source line so the diagnostic highlights something
|
|
358
|
+
// meaningful (e.g. the component name on a `Button` line).
|
|
359
|
+
if (srcText) {
|
|
360
|
+
if (srcCol >= srcText.length || /^\s*$/.test(srcText.slice(srcCol, srcCol + 1))) {
|
|
361
|
+
const firstWord = srcText.match(/^\s*(\w+)/);
|
|
362
|
+
if (firstWord) return { line: srcLine, col: firstWord.index + firstWord[0].length - firstWord[1].length };
|
|
363
|
+
}
|
|
364
|
+
}
|
|
332
365
|
return { line: srcLine, col: srcCol };
|
|
333
366
|
}
|