subscript 9.2.0 → 10.0.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/README.md +101 -184
- package/feature/access.js +68 -7
- package/feature/accessor.js +49 -0
- package/feature/asi.js +15 -0
- package/feature/async.js +45 -0
- package/feature/block.js +41 -0
- package/feature/class.js +69 -0
- package/feature/collection.js +40 -0
- package/feature/comment.js +25 -5
- package/feature/control.js +2 -142
- package/feature/destruct.js +33 -0
- package/feature/function.js +44 -0
- package/feature/group.js +13 -9
- package/feature/if.js +23 -38
- package/feature/literal.js +13 -0
- package/feature/loop.js +107 -106
- package/feature/module.js +42 -0
- package/feature/number.js +41 -38
- package/feature/op/arithmetic.js +29 -0
- package/feature/op/arrow.js +33 -0
- package/feature/op/assign-logical.js +33 -0
- package/feature/op/assignment.js +26 -0
- package/feature/op/bitwise-unsigned.js +17 -0
- package/feature/op/bitwise.js +29 -0
- package/feature/op/comparison.js +19 -0
- package/feature/op/defer.js +15 -0
- package/feature/op/equality.js +16 -0
- package/feature/op/identity.js +15 -0
- package/feature/op/increment.js +23 -0
- package/feature/op/logical.js +21 -0
- package/feature/op/membership.js +17 -0
- package/feature/op/nullish.js +13 -0
- package/feature/op/optional.js +61 -0
- package/feature/op/pow.js +19 -0
- package/feature/op/range.js +26 -0
- package/feature/op/spread.js +15 -0
- package/feature/op/ternary.js +15 -0
- package/feature/op/type.js +18 -0
- package/feature/op/unary.js +41 -0
- package/feature/prop.js +34 -0
- package/feature/regex.js +31 -0
- package/feature/seq.js +21 -0
- package/feature/string.js +24 -17
- package/feature/switch.js +48 -0
- package/feature/template.js +39 -0
- package/feature/try.js +57 -0
- package/feature/unit.js +35 -0
- package/feature/var.js +51 -41
- package/jessie.js +31 -0
- package/jessie.min.js +8 -0
- package/justin.js +39 -48
- package/justin.min.js +8 -4
- package/package.json +15 -16
- package/parse.js +146 -0
- package/subscript.d.ts +45 -5
- package/subscript.js +62 -22
- package/subscript.min.js +5 -4
- package/util/bundle.js +507 -0
- package/util/stringify.js +172 -0
- package/feature/add.js +0 -22
- package/feature/array.js +0 -11
- package/feature/arrow.js +0 -23
- package/feature/assign.js +0 -11
- package/feature/bitwise.js +0 -11
- package/feature/bool.js +0 -5
- package/feature/call.js +0 -15
- package/feature/compare.js +0 -11
- package/feature/increment.js +0 -11
- package/feature/logic.js +0 -11
- package/feature/mult.js +0 -25
- package/feature/object.js +0 -17
- package/feature/optional.js +0 -23
- package/feature/pow.js +0 -5
- package/feature/shift.js +0 -12
- package/feature/spread.js +0 -6
- package/feature/ternary.js +0 -10
- package/src/compile.d.ts +0 -17
- package/src/compile.js +0 -28
- package/src/const.js +0 -45
- package/src/parse.d.ts +0 -22
- package/src/parse.js +0 -113
- package/src/stringify.js +0 -27
- /package/{LICENSE → license} +0 -0
package/feature/prop.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal property access: a.b, a[b], f()
|
|
3
|
+
* For array literals, private fields, see member.js
|
|
4
|
+
*/
|
|
5
|
+
import { access, binary, group, operator, compile } from '../parse.js';
|
|
6
|
+
|
|
7
|
+
const ACCESS = 170;
|
|
8
|
+
|
|
9
|
+
// a[b] - computed member access only (no array literal support)
|
|
10
|
+
access('[]', ACCESS);
|
|
11
|
+
|
|
12
|
+
// a.b - dot member access
|
|
13
|
+
binary('.', ACCESS);
|
|
14
|
+
|
|
15
|
+
// (a) - grouping only (no sequences)
|
|
16
|
+
group('()', ACCESS);
|
|
17
|
+
|
|
18
|
+
// a(b,c,d), a() - function calls
|
|
19
|
+
access('()', ACCESS);
|
|
20
|
+
|
|
21
|
+
// Compile
|
|
22
|
+
const err = msg => { throw Error(msg) };
|
|
23
|
+
operator('[]', (a, b) => (b == null && err('Missing index'), a = compile(a), b = compile(b), ctx => a(ctx)[b(ctx)]));
|
|
24
|
+
operator('.', (a, b) => (a = compile(a), b = !b[0] ? b[1] : b, ctx => a(ctx)[b]));
|
|
25
|
+
operator('()', (a, b) => {
|
|
26
|
+
// Group: (expr) - no second argument means grouping, not call
|
|
27
|
+
if (b === undefined) return a == null ? err('Empty ()') : compile(a);
|
|
28
|
+
// Function call: a(b,c)
|
|
29
|
+
const args = !b ? () => [] :
|
|
30
|
+
b[0] === ',' ? (b = b.slice(1).map(compile), ctx => b.map(arg => arg(ctx))) :
|
|
31
|
+
(b = compile(b), ctx => [b(ctx)]);
|
|
32
|
+
a = compile(a);
|
|
33
|
+
return ctx => a(ctx)(...args(ctx));
|
|
34
|
+
});
|
package/feature/regex.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regex literals: /pattern/flags
|
|
3
|
+
*
|
|
4
|
+
* AST:
|
|
5
|
+
* /abc/gi → [, /abc/gi]
|
|
6
|
+
*
|
|
7
|
+
* Note: Disambiguates from division by context:
|
|
8
|
+
* - `/` after value = division (falls through to prev)
|
|
9
|
+
* - `/` at start or after operator = regex
|
|
10
|
+
*/
|
|
11
|
+
import { token, skip, err, next, idx, cur } from '../parse.js';
|
|
12
|
+
|
|
13
|
+
const PREFIX = 140, SLASH = 47, BSLASH = 92;
|
|
14
|
+
|
|
15
|
+
const regexChar = c => c === BSLASH ? 2 : c && c !== SLASH; // \x = 2 chars, else 1 until /
|
|
16
|
+
const regexFlag = c => c === 103 || c === 105 || c === 109 || c === 115 || c === 117 || c === 121; // g i m s u y
|
|
17
|
+
|
|
18
|
+
token('/', PREFIX, a => {
|
|
19
|
+
if (a) return; // has left operand = division, fall through
|
|
20
|
+
|
|
21
|
+
// Invalid regex start (quantifiers) or /= - fall through
|
|
22
|
+
const first = cur.charCodeAt(idx);
|
|
23
|
+
if (first === SLASH || first === 42 || first === 43 || first === 63 || first === 61) return;
|
|
24
|
+
|
|
25
|
+
const pattern = next(regexChar);
|
|
26
|
+
cur.charCodeAt(idx) === SLASH || err('Unterminated regex');
|
|
27
|
+
skip(); // consume closing /
|
|
28
|
+
|
|
29
|
+
try { return [, new RegExp(pattern, next(regexFlag))]; }
|
|
30
|
+
catch (e) { err('Invalid regex: ' + e.message); }
|
|
31
|
+
});
|
package/feature/seq.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sequence operators (C-family)
|
|
3
|
+
*
|
|
4
|
+
* , ; — returns last evaluated value
|
|
5
|
+
*/
|
|
6
|
+
import { nary, operator, compile } from '../parse.js';
|
|
7
|
+
|
|
8
|
+
const STATEMENT = 5, SEQ = 10;
|
|
9
|
+
|
|
10
|
+
// Sequences
|
|
11
|
+
nary(',', SEQ);
|
|
12
|
+
nary(';', STATEMENT, true); // right-assoc to allow same-prec statements
|
|
13
|
+
|
|
14
|
+
// Compile - returns last evaluated value
|
|
15
|
+
const seq = (...args) => (args = args.map(compile), ctx => {
|
|
16
|
+
let r;
|
|
17
|
+
for (const arg of args) r = arg(ctx);
|
|
18
|
+
return r;
|
|
19
|
+
});
|
|
20
|
+
operator(',', seq);
|
|
21
|
+
operator(';', seq);
|
package/feature/string.js
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Strings with escape sequences
|
|
3
|
+
*
|
|
4
|
+
* Configurable via parse.string: { '"': true } or { '"': true, "'": true }
|
|
5
|
+
*/
|
|
6
|
+
import { parse, lookup, next, err, skip, idx, cur } from '../parse.js';
|
|
3
7
|
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
qc && err('Unexpected string') // must not follow another token
|
|
7
|
-
skip()
|
|
8
|
-
// while (c = cur.charCodeAt(idx), c - q) {
|
|
9
|
-
// if (c === BSLASH) skip(), c = cur[idx], skip(), str += escape[c] || c
|
|
10
|
-
// else str += cur[idx], skip()
|
|
11
|
-
// }
|
|
12
|
-
next(c => c - q && (c === BSLASH ? (str += escape[cur[idx+1]] || cur[idx+1], 2 ) : (str += cur[idx], 1)))
|
|
13
|
-
skip() || err('Bad string')
|
|
14
|
-
return [, str]
|
|
15
|
-
}
|
|
8
|
+
const BSLASH = 92, DQUOTE = 34, SQUOTE = 39;
|
|
9
|
+
const esc = { n: '\n', r: '\r', t: '\t', b: '\b', f: '\f', v: '\v' };
|
|
16
10
|
|
|
11
|
+
// Parse string with given quote char code
|
|
12
|
+
const parseString = q => (a, _, s = '') => {
|
|
13
|
+
if (a || !parse.string?.[String.fromCharCode(q)]) return;
|
|
14
|
+
skip();
|
|
15
|
+
next(c => c - q && (c === BSLASH ? (s += esc[cur[idx + 1]] || cur[idx + 1], 2) : (s += cur[idx], 1)));
|
|
16
|
+
cur[idx] === String.fromCharCode(q) ? skip() : err('Bad string');
|
|
17
|
+
return [, s];
|
|
18
|
+
};
|
|
17
19
|
|
|
18
|
-
//
|
|
19
|
-
lookup[DQUOTE] =
|
|
20
|
-
lookup[
|
|
20
|
+
// Register both quote chars (enabled via parse.string config)
|
|
21
|
+
lookup[DQUOTE] = parseString(DQUOTE);
|
|
22
|
+
lookup[SQUOTE] = parseString(SQUOTE);
|
|
23
|
+
|
|
24
|
+
// Default: double quotes only
|
|
25
|
+
parse.string = { '"': true };
|
|
26
|
+
|
|
27
|
+
export { esc };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Switch/case/default
|
|
2
|
+
// AST: ['switch', val, [';', ['case', test], stmts..., ['default'], stmts...]]
|
|
3
|
+
import { expr, skip, space, parens, operator, compile } from '../parse.js';
|
|
4
|
+
import { keyword, block } from './block.js';
|
|
5
|
+
import { BREAK } from './control.js';
|
|
6
|
+
|
|
7
|
+
const STATEMENT = 5, ASSIGN = 20, COLON = 58;
|
|
8
|
+
|
|
9
|
+
keyword('switch', STATEMENT + 1, () => (space(), ['switch', parens(), block()]));
|
|
10
|
+
keyword('case', STATEMENT + 1, () => (space(), (c => (space() === COLON && skip(), ['case', c]))(expr(ASSIGN))));
|
|
11
|
+
keyword('default', STATEMENT + 1, () => (space() === COLON && skip(), ['default']));
|
|
12
|
+
|
|
13
|
+
// Compile
|
|
14
|
+
operator('switch', (val, cases) => {
|
|
15
|
+
val = compile(val);
|
|
16
|
+
// Parse cases body: [';', ['case', test], stmts..., ['default'], stmts...]
|
|
17
|
+
if (!cases) return ctx => val(ctx);
|
|
18
|
+
const parsed = [];
|
|
19
|
+
const items = cases[0] === ';' ? cases.slice(1) : [cases];
|
|
20
|
+
let current = null;
|
|
21
|
+
for (const item of items) {
|
|
22
|
+
if (Array.isArray(item) && (item[0] === 'case' || item[0] === 'default')) {
|
|
23
|
+
if (current) parsed.push(current);
|
|
24
|
+
current = [item[0] === 'case' ? compile(item[1]) : null, []];
|
|
25
|
+
} else if (current) {
|
|
26
|
+
current[1].push(compile(item));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (current) parsed.push(current);
|
|
30
|
+
|
|
31
|
+
return ctx => {
|
|
32
|
+
const v = val(ctx);
|
|
33
|
+
let matched = false, result;
|
|
34
|
+
for (const [test, stmts] of parsed) {
|
|
35
|
+
if (matched || test === null || test(ctx) === v) {
|
|
36
|
+
matched = true;
|
|
37
|
+
for (const stmt of stmts) {
|
|
38
|
+
try { result = stmt(ctx); }
|
|
39
|
+
catch (e) {
|
|
40
|
+
if (e?.type === BREAK) return e.value !== undefined ? e.value : result;
|
|
41
|
+
throw e;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template literals: `a ${x} b` → ['`', [,'a '], 'x', [,' b']]
|
|
3
|
+
* Tagged templates: tag`...` → ['``', 'tag', ...]
|
|
4
|
+
*/
|
|
5
|
+
import { parse, skip, err, expr, lookup, cur, idx, operator, compile } from '../parse.js';
|
|
6
|
+
|
|
7
|
+
const ACCESS = 170, BACKTICK = 96, DOLLAR = 36, OBRACE = 123, BSLASH = 92;
|
|
8
|
+
const esc = { n: '\n', r: '\r', t: '\t', b: '\b', f: '\f', v: '\v' };
|
|
9
|
+
|
|
10
|
+
// Parse template body after opening `
|
|
11
|
+
const parseBody = () => {
|
|
12
|
+
const parts = [];
|
|
13
|
+
for (let s = '', c; (c = cur.charCodeAt(idx)) !== BACKTICK; )
|
|
14
|
+
!c ? err('Unterminated template') :
|
|
15
|
+
c === BSLASH ? (skip(), s += esc[cur[idx]] || cur[idx], skip()) :
|
|
16
|
+
c === DOLLAR && cur.charCodeAt(idx + 1) === OBRACE ? (s && parts.push([, s]), s = '', skip(2), parts.push(expr(0, 125))) :
|
|
17
|
+
(s += cur[idx], skip(), c = cur.charCodeAt(idx), c === BACKTICK && s && parts.push([, s]));
|
|
18
|
+
return skip(), parts;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const prev = lookup[BACKTICK];
|
|
22
|
+
// Tagged templates: decline when ASI with newline (return undefined to let ASI handle)
|
|
23
|
+
lookup[BACKTICK] = (a, prec) =>
|
|
24
|
+
a && prec < ACCESS ? (parse.asi && parse.newline ? void 0 : (skip(), ['``', a, ...parseBody()])) : // tagged
|
|
25
|
+
!a ? (skip(), (p => p.length < 2 && p[0]?.[0] === undefined ? p[0] || [,''] : ['`', ...p])(parseBody())) : // plain
|
|
26
|
+
prev?.(a, prec);
|
|
27
|
+
|
|
28
|
+
// Compile
|
|
29
|
+
operator('`', (...parts) => (parts = parts.map(compile), ctx => parts.map(p => p(ctx)).join('')));
|
|
30
|
+
operator('``', (tag, ...parts) => {
|
|
31
|
+
tag = compile(tag);
|
|
32
|
+
const strings = [], exprs = [];
|
|
33
|
+
for (const p of parts) {
|
|
34
|
+
if (Array.isArray(p) && p[0] === undefined) strings.push(p[1]);
|
|
35
|
+
else exprs.push(compile(p));
|
|
36
|
+
}
|
|
37
|
+
const strs = Object.assign([...strings], { raw: strings });
|
|
38
|
+
return ctx => tag(ctx)(strs, ...exprs.map(e => e(ctx)));
|
|
39
|
+
});
|
package/feature/try.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// try/catch/finally/throw statements
|
|
2
|
+
// AST: ['catch', ['try', body], param, catchBody] or ['finally', inner, body]
|
|
3
|
+
import { space, parse, parens, expr, operator, compile } from '../parse.js';
|
|
4
|
+
import { keyword, infix, block } from './block.js';
|
|
5
|
+
import { BREAK, CONTINUE, RETURN } from './control.js';
|
|
6
|
+
|
|
7
|
+
const STATEMENT = 5;
|
|
8
|
+
|
|
9
|
+
keyword('try', STATEMENT + 1, () => ['try', block()]);
|
|
10
|
+
infix('catch', STATEMENT + 1, a => (space(), ['catch', a, parens(), block()]));
|
|
11
|
+
infix('finally', STATEMENT + 1, a => ['finally', a, block()]);
|
|
12
|
+
|
|
13
|
+
keyword('throw', STATEMENT + 1, () => {
|
|
14
|
+
parse.asi && (parse.newline = false);
|
|
15
|
+
space();
|
|
16
|
+
if (parse.newline) throw SyntaxError('Unexpected newline after throw');
|
|
17
|
+
return ['throw', expr(STATEMENT)];
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Compile
|
|
21
|
+
operator('try', tryBody => {
|
|
22
|
+
tryBody = tryBody ? compile(tryBody) : null;
|
|
23
|
+
return ctx => tryBody?.(ctx);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
operator('catch', (tryNode, catchName, catchBody) => {
|
|
27
|
+
const tryBody = tryNode?.[1] ? compile(tryNode[1]) : null;
|
|
28
|
+
catchBody = catchBody ? compile(catchBody) : null;
|
|
29
|
+
return ctx => {
|
|
30
|
+
let result;
|
|
31
|
+
try {
|
|
32
|
+
result = tryBody?.(ctx);
|
|
33
|
+
} catch (e) {
|
|
34
|
+
if (e?.type === BREAK || e?.type === CONTINUE || e?.type === RETURN) throw e;
|
|
35
|
+
if (catchName !== null && catchBody) {
|
|
36
|
+
const had = catchName in ctx, orig = ctx[catchName];
|
|
37
|
+
ctx[catchName] = e;
|
|
38
|
+
try { result = catchBody(ctx); }
|
|
39
|
+
finally { had ? ctx[catchName] = orig : delete ctx[catchName]; }
|
|
40
|
+
} else if (catchName === null) throw e;
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
operator('finally', (inner, finallyBody) => {
|
|
47
|
+
inner = inner ? compile(inner) : null;
|
|
48
|
+
finallyBody = finallyBody ? compile(finallyBody) : null;
|
|
49
|
+
return ctx => {
|
|
50
|
+
let result;
|
|
51
|
+
try { result = inner?.(ctx); }
|
|
52
|
+
finally { finallyBody?.(ctx); }
|
|
53
|
+
return result;
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
operator('throw', val => (val = compile(val), ctx => { throw val(ctx); }));
|
package/feature/unit.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit suffixes: 5px, 10rem, 2s, 500ms
|
|
3
|
+
*
|
|
4
|
+
* AST:
|
|
5
|
+
* 5px → ['px', [,5]]
|
|
6
|
+
* 2.5s → ['s', [,2.5]]
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* import { unit } from 'subscript/feature/unit.js'
|
|
10
|
+
* unit('px', 'em', 'rem', 's', 'ms')
|
|
11
|
+
*/
|
|
12
|
+
import { lookup, next, parse, idx, seek, operator, compile } from '../parse.js';
|
|
13
|
+
|
|
14
|
+
const units = {};
|
|
15
|
+
|
|
16
|
+
export const unit = (...names) => names.forEach(name => {
|
|
17
|
+
units[name] = 1;
|
|
18
|
+
operator(name, val => (val = compile(val), ctx => ({ value: val(ctx), unit: name })));
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Wrap number handler to check for unit suffix
|
|
22
|
+
const wrapNum = cc => {
|
|
23
|
+
const orig = lookup[cc];
|
|
24
|
+
if (!orig) return;
|
|
25
|
+
lookup[cc] = (a, prec) => {
|
|
26
|
+
const r = orig(a, prec);
|
|
27
|
+
if (!r || r[0] !== undefined) return r;
|
|
28
|
+
const start = idx, u = next(c => parse.id(c) && !(c >= 48 && c <= 57));
|
|
29
|
+
return u && units[u] ? [u, r] : (u && seek(start), r);
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Wrap digit and period handlers
|
|
34
|
+
for (let i = 48; i <= 57; i++) wrapNum(i);
|
|
35
|
+
wrapNum(46);
|
package/feature/var.js
CHANGED
|
@@ -1,49 +1,59 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Variable declarations: let, const
|
|
3
|
-
*
|
|
2
|
+
* Variable declarations: let, const, var
|
|
3
|
+
*
|
|
4
4
|
* AST:
|
|
5
|
-
* let x
|
|
6
|
-
* let x = 1
|
|
7
|
-
* const
|
|
5
|
+
* let x = 1 → ['let', ['=', 'x', 1]]
|
|
6
|
+
* let x = 1, y = 2 → ['let', ['=', 'x', 1], ['=', 'y', 2]]
|
|
7
|
+
* const {a} = x → ['const', ['=', ['{}', 'a'], 'x']]
|
|
8
|
+
* for (let x in o) → ['for', ['in', ['let', 'x'], 'o'], body]
|
|
9
|
+
* var x → ['var', 'x'] (acts as assignment target)
|
|
8
10
|
*/
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
11
|
+
import { token, expr, space, operator, compile } from '../parse.js';
|
|
12
|
+
import { keyword } from './block.js';
|
|
13
|
+
import { destructure } from './destruct.js';
|
|
12
14
|
|
|
13
|
-
const
|
|
15
|
+
const STATEMENT = 5, SEQ = 10, ASSIGN = 20;
|
|
14
16
|
|
|
15
|
-
// let
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return [
|
|
27
|
-
}
|
|
17
|
+
// let/const: expr(SEQ-1) consumes assignment, stops before comma
|
|
18
|
+
// For for-in/of, return ['in/of', ['let', x], iterable] not ['let', ['in', x, it]]
|
|
19
|
+
// For comma, return ['let', decl1, decl2, ...] not ['let', [',', ...]]
|
|
20
|
+
const decl = keyword => {
|
|
21
|
+
let node = expr(SEQ - 1);
|
|
22
|
+
// for (let x in obj) - restructure so for-loop sees in/of at top
|
|
23
|
+
if (node?.[0] === 'in' || node?.[0] === 'of')
|
|
24
|
+
return [node[0], [keyword, node[1]], node[2]];
|
|
25
|
+
// let x = 1, y = 2 - flatten comma into nary let
|
|
26
|
+
if (node?.[0] === ',')
|
|
27
|
+
return [keyword, ...node.slice(1)];
|
|
28
|
+
return [keyword, node];
|
|
29
|
+
};
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return ctx => { ctx[name] = val ? val(ctx) : undefined }
|
|
32
|
-
})
|
|
31
|
+
token('let', STATEMENT + 1, a => !a && decl('let'));
|
|
32
|
+
token('const', STATEMENT + 1, a => !a && decl('const'));
|
|
33
33
|
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
space()
|
|
38
|
-
const name = next(parse.id)
|
|
39
|
-
if (!name) err('Expected identifier')
|
|
40
|
-
space()
|
|
41
|
-
P.cur.charCodeAt(P.idx) === 61 && P.cur.charCodeAt(P.idx + 1) !== 61 || err('Expected =')
|
|
42
|
-
skip()
|
|
43
|
-
return ['const', name, expr(PREC_STATEMENT)]
|
|
44
|
-
})
|
|
34
|
+
// var: just declares identifier, assignment happens separately
|
|
35
|
+
// var x = 5 → ['=', ['var', 'x'], 5]
|
|
36
|
+
keyword('var', STATEMENT, () => (space(), ['var', expr(ASSIGN)]));
|
|
45
37
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
38
|
+
// Compile
|
|
39
|
+
const varOp = (...decls) => {
|
|
40
|
+
decls = decls.map(d => {
|
|
41
|
+
// Just identifier: let x
|
|
42
|
+
if (typeof d === 'string') return ctx => { ctx[d] = undefined; };
|
|
43
|
+
// Assignment: let x = 1
|
|
44
|
+
if (d[0] === '=') {
|
|
45
|
+
const [, pattern, val] = d;
|
|
46
|
+
const v = compile(val);
|
|
47
|
+
if (typeof pattern === 'string') return ctx => { ctx[pattern] = v(ctx); };
|
|
48
|
+
return ctx => destructure(pattern, v(ctx), ctx);
|
|
49
|
+
}
|
|
50
|
+
return compile(d);
|
|
51
|
+
});
|
|
52
|
+
return ctx => { for (const d of decls) d(ctx); };
|
|
53
|
+
};
|
|
54
|
+
operator('let', varOp);
|
|
55
|
+
operator('const', varOp);
|
|
56
|
+
// var just declares the variable (assignment handled by = operator)
|
|
57
|
+
operator('var', name => (typeof name === 'string'
|
|
58
|
+
? ctx => { ctx[name] = undefined; }
|
|
59
|
+
: () => {}));
|
package/jessie.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* jessie: Practical JS subset
|
|
3
|
+
*
|
|
4
|
+
* Builds on justin with statements: blocks, variables, if/else,
|
|
5
|
+
* loops, functions, try/catch, switch, throw.
|
|
6
|
+
*/
|
|
7
|
+
import './justin.js';
|
|
8
|
+
|
|
9
|
+
// Statement features (var.js must come before destruct.js)
|
|
10
|
+
import './feature/var.js';
|
|
11
|
+
import './feature/function.js';
|
|
12
|
+
import './feature/async.js';
|
|
13
|
+
import './feature/class.js';
|
|
14
|
+
import './feature/regex.js';
|
|
15
|
+
import './feature/destruct.js';
|
|
16
|
+
|
|
17
|
+
// Control flow
|
|
18
|
+
import './feature/if.js';
|
|
19
|
+
import './feature/loop.js';
|
|
20
|
+
import './feature/try.js';
|
|
21
|
+
import './feature/switch.js';
|
|
22
|
+
|
|
23
|
+
// Module system
|
|
24
|
+
import './feature/module.js';
|
|
25
|
+
import './feature/accessor.js';
|
|
26
|
+
|
|
27
|
+
// Automatic Semicolon Insertion
|
|
28
|
+
import './feature/asi.js';
|
|
29
|
+
|
|
30
|
+
export * from './parse.js';
|
|
31
|
+
export { default } from './subscript.js';
|
package/jessie.min.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
var u,c,m=r=>(u=0,c=r,m.newline=!1,r=A(),c[u]?I():r||""),I=(r="Unexpected token",e=u,t=c.slice(0,e).split(`
|
|
2
|
+
`),o=t.pop(),n=c.slice(Math.max(0,e-40),e),s="\u032D",f=(c[e]||"\u2205")+s,l=c.slice(e+1,e+20))=>{throw SyntaxError(`${r} at ${t.length+1}:${o.length+1}
|
|
3
|
+
${(c[e-41]!==`
|
|
4
|
+
`?"...":"")+n}${f}${l}`)},V=(r,e=u)=>(Array.isArray(r)&&(r.loc=e),r),k=(r,e=u,t)=>{for(;t=r(c.charCodeAt(u));)u+=t;return c.slice(e,u)},g=(r=1)=>c[u+=r],G=r=>u=r,A=(r=0,e)=>{let t,o,n,s,f=m.reserved,l;for(e&&m.asi&&(m.newline=!1),m.reserved=0;(t=m.space())&&(l=m.newline,1)&&t!==e&&(n=((s=w[t])&&s(o,r))??(m.asi&&o&&l&&(n=m.asi(o,r,A)))??(!o&&!m.reserved&&k(m.id)));)o=n,m.reserved=0;return m.reserved=f,e&&(t==e?u++:I("Unclosed "+String.fromCharCode(e-(e>42?2:1)))),o},h=m.space=(r,e=u)=>{for(;(r=c.charCodeAt(u))<=32;)m.asi&&r===10&&(m.newline=!0),u++;return r},mt=m.id=r=>r>=48&&r<=57||r>=65&&r<=90||r>=97&&r<=122||r==36||r==95||r>=192&&r!=215&&r!=247,X=(r,e=r.length)=>c.substr(u,e)===r&&!m.id(c.charCodeAt(u+e)),N=()=>(g(),A(0,41)),w=[],S=(r,e=32,t,o=r.charCodeAt(0),n=r.length,s=w[o],f=r.toUpperCase()!==r,l,y)=>w[o]=(E,T,F,C=u)=>(l=F,(F?r==F:(n<2||r.charCodeAt(1)===c.charCodeAt(u+1)&&(n<3||c.substr(u,n)==r))&&(!f||!m.id(c.charCodeAt(u+n)))&&(l=F=r))&&T<e&&(u+=n,(y=t(E))?V(y,C):(u=C,l=0,f&&y!==!1&&(m.reserved=1),!f&&!s&&I()),y)||s?.(E,T,l)),d=(r,e,t=!1)=>S(r,e,(o,n)=>o&&(n=A(e-(t?.5:0)))&&[r,o,n]),v=(r,e,t)=>S(r,e,o=>t?o&&[r,o]:!o&&(o=A(e-.5))&&[r,o]),P=(r,e)=>S(r,200,t=>!t&&[,e]),sr=(r,e,t)=>{S(r,e,(o,n)=>(n=A(e-(t?.5:0)),o?.[0]!==r&&(o=[r,o||null]),n?.[0]===r?o.push(...n.slice(1)):o.push(n||null),o))},H=(r,e)=>S(r[0],e,t=>!t&&[r,A(0,r.charCodeAt(1))||null]),pr=(r,e)=>S(r[0],e,t=>t&&[r,t,A(0,r.charCodeAt(1))||null]),ir={},p=(r,e,t=ir[r])=>ir[r]=(...o)=>e(...o)||t?.(...o),i=r=>Array.isArray(r)?r[0]===void 0?(e=>()=>e)(r[1]):ir[r[0]]?.(...r.slice(1))??I(`Unknown operator: ${r[0]}`,r?.loc):r===void 0?()=>{}:e=>e?.[r];var Y=46,j=48,Z=57,br=69,re=101,ee=43,te=45,oe=97,ne=102,ie=65,se=70,fr=r=>[,(r=+k(e=>e===Y&&c.charCodeAt(u+1)!==Y||e>=j&&e<=Z||((e===br||e===re)&&((e=c.charCodeAt(u+1))>=j&&e<=Z||e===ee||e===te)?2:0)))!=r?I():r],pe={2:r=>r===48||r===49,8:r=>r>=48&&r<=55,16:r=>r>=j&&r<=Z||r>=oe&&r<=ne||r>=ie&&r<=se};m.number=null;w[Y]=r=>!r&&c.charCodeAt(u+1)!==Y&&fr();for(let r=j;r<=Z;r++)w[r]=e=>e?void 0:fr();w[j]=r=>{if(r)return;let e=m.number;if(e){for(let[t,o]of Object.entries(e))if(t[0]==="0"&&c[u+1]?.toLowerCase()===t[1])return g(2),[,parseInt(k(pe[o]),o)]}return fr()};var fe=92,vr=34,Tr=39,le={n:`
|
|
5
|
+
`,r:"\r",t:" ",b:"\b",f:"\f",v:"\v"},Ir=r=>(e,t,o="")=>{if(!(e||!m.string?.[String.fromCharCode(r)]))return g(),k(n=>n-r&&(n===fe?(o+=le[c[u+1]]||c[u+1],2):(o+=c[u],1))),c[u]===String.fromCharCode(r)?g():I("Bad string"),[,o]};w[vr]=Ir(vr);w[Tr]=Ir(Tr);m.string={'"':!0};var ue=20;"= += -= *= /= %= |= &= ^= >>= <<=".split(" ").map(r=>d(r,ue,!0));var Rr=(r,e,t,o)=>typeof r=="string"?n=>e(n,r,n):r[0]==="."?(t=i(r[1]),o=r[2],n=>e(t(n),o,n)):r[0]==="[]"&&r.length===3?(t=i(r[1]),o=i(r[2]),n=>e(t(n),o(n),n)):r[0]==="()"&&r.length===2?Rr(r[1],e):(()=>{throw Error("Invalid assignment target")})(),Nr={"=":(r,e,t)=>r[e]=t,"+=":(r,e,t)=>r[e]+=t,"-=":(r,e,t)=>r[e]-=t,"*=":(r,e,t)=>r[e]*=t,"/=":(r,e,t)=>r[e]/=t,"%=":(r,e,t)=>r[e]%=t,"|=":(r,e,t)=>r[e]|=t,"&=":(r,e,t)=>r[e]&=t,"^=":(r,e,t)=>r[e]^=t,">>=":(r,e,t)=>r[e]>>=t,"<<=":(r,e,t)=>r[e]<<=t};for(let r in Nr)p(r,(e,t)=>(t=i(t),Rr(e,(o,n,s)=>Nr[r](o,n,t(s)))));var me=30,ce=40,_r=140;d("!",_r);v("!",_r);d("||",me);d("&&",ce);p("!",r=>(r=i(r),e=>!r(e)));p("||",(r,e)=>(r=i(r),e=i(e),t=>r(t)||e(t)));p("&&",(r,e)=>(r=i(r),e=i(e),t=>r(t)&&e(t)));var de=50,Ae=60,he=70,Or=100,ye=140;d("|",de);d("&",he);d("^",Ae);d(">>",Or);d("<<",Or);v("~",ye);p("~",r=>(r=i(r),e=>~r(e)));p("|",(r,e)=>(r=i(r),e=i(e),t=>r(t)|e(t)));p("&",(r,e)=>(r=i(r),e=i(e),t=>r(t)&e(t)));p("^",(r,e)=>(r=i(r),e=i(e),t=>r(t)^e(t)));p(">>",(r,e)=>(r=i(r),e=i(e),t=>r(t)>>e(t)));p("<<",(r,e)=>(r=i(r),e=i(e),t=>r(t)<<e(t)));var q=90;d("<",q);d(">",q);d("<=",q);d(">=",q);p(">",(r,e)=>(r=i(r),e=i(e),t=>r(t)>e(t)));p("<",(r,e)=>(r=i(r),e=i(e),t=>r(t)<e(t)));p(">=",(r,e)=>(r=i(r),e=i(e),t=>r(t)>=e(t)));p("<=",(r,e)=>(r=i(r),e=i(e),t=>r(t)<=e(t)));var Pr=80;d("==",Pr);d("!=",Pr);p("==",(r,e)=>(r=i(r),e=i(e),t=>r(t)==e(t)));p("!=",(r,e)=>(r=i(r),e=i(e),t=>r(t)!=e(t)));var Mr=110,lr=120,Ur=140;d("+",Mr);d("-",Mr);d("*",lr);d("/",lr);d("%",lr);v("+",Ur);v("-",Ur);p("+",(r,e)=>e!==void 0?(r=i(r),e=i(e),t=>r(t)+e(t)):(r=i(r),t=>+r(t)));p("-",(r,e)=>e!==void 0?(r=i(r),e=i(e),t=>r(t)-e(t)):(r=i(r),t=>-r(t)));p("*",(r,e)=>(r=i(r),e=i(e),t=>r(t)*e(t)));p("/",(r,e)=>(r=i(r),e=i(e),t=>r(t)/e(t)));p("%",(r,e)=>(r=i(r),e=i(e),t=>r(t)%e(t)));var x=150;S("++",x,r=>r?["++",r,null]:["++",A(x-1)]);S("--",x,r=>r?["--",r,null]:["--",A(x-1)]);var ur=(r,e,t,o)=>typeof r=="string"?n=>e(n,r):r[0]==="."?(t=i(r[1]),o=r[2],n=>e(t(n),o)):r[0]==="[]"&&r.length===3?(t=i(r[1]),o=i(r[2]),n=>e(t(n),o(n))):r[0]==="()"&&r.length===2?ur(r[1],e):(()=>{throw Error("Invalid increment target")})();p("++",(r,e)=>ur(r,e===null?(t,o)=>t[o]++:(t,o)=>++t[o]));p("--",(r,e)=>ur(r,e===null?(t,o)=>t[o]--:(t,o)=>--t[o]));var ge=5,Ee=10,ae=170;H("()",ae);sr(",",Ee);sr(";",ge,!0);var Lr=(...r)=>(r=r.map(i),e=>{let t;for(let o of r)t=o(e);return t});p(",",Lr);p(";",Lr);var M=r=>r?.[0]==="_"&&r[1]==="_"||r==="constructor"||r==="prototype",mr=170;pr("[]",mr);d(".",mr);pr("()",mr);var b=r=>{throw Error(r)};p("[]",(r,e)=>e===void 0?(r=r?r[0]===","?r.slice(1):[r]:[],r=r.map(t=>t==null?(()=>{}):t[0]==="..."?(t=i(t[1]),o=>t(o)):(t=i(t),o=>[t(o)])),t=>r.flatMap(o=>o(t))):(e==null&&b("Missing index"),r=i(r),e=i(e),t=>{let o=e(t);return M(o)?void 0:r(t)[o]}));p(".",(r,e)=>(r=i(r),e=e[0]?e:e[1],M(e)?()=>{}:t=>r(t)[e]));p("()",(r,e)=>{if(e===void 0)return r==null?b("Empty ()"):i(r);let t=n=>n?.[0]===","&&n.slice(1).some(s=>s==null||t(s));t(e)&&b("Empty argument");let o=e?e[0]===","?(e=e.slice(1).map(i),n=>e.map(s=>s(n))):(e=i(e),n=>[e(n)]):()=>[];return cr(r,(n,s,f)=>n[s](...o(f)))});var O=r=>typeof r=="string"||Array.isArray(r)&&(r[0]==="."||r[0]==="?."||r[0]==="[]"&&r.length===3||r[0]==="?.[]"||r[0]==="()"&&r.length===2&&O(r[1])||r[0]==="{}"),cr=(r,e,t,o)=>r==null?b("Empty ()"):r[0]==="()"&&r.length==2?cr(r[1],e):typeof r=="string"?n=>e(n,r,n):r[0]==="."?(t=i(r[1]),o=r[2],n=>e(t(n),o,n)):r[0]==="?."?(t=i(r[1]),o=r[2],n=>{let s=t(n);return s==null?void 0:e(s,o,n)}):r[0]==="[]"&&r.length===3?(t=i(r[1]),o=i(r[2]),n=>e(t(n),o(n),n)):r[0]==="?.[]"?(t=i(r[1]),o=i(r[2]),n=>{let s=t(n);return s==null?void 0:e(s,o(n),n)}):(r=i(r),n=>e([r(n)],0,n)),U=cr;var Fr=new WeakMap,Se=(r,...e)=>typeof r=="string"?i(m(r)):Fr.get(r)||Fr.set(r,Ce(r,e)).get(r),Gr=57344,Ce=(r,e)=>{let t=r.reduce((s,f,l)=>s+(l?String.fromCharCode(Gr+l-1):"")+f,""),o=m(t),n=s=>{if(typeof s=="string"&&s.length===1){let f=s.charCodeAt(0)-Gr,l;if(f>=0&&f<e.length)return l=e[f],we(l)?l:[,l]}return Array.isArray(s)?s.map(n):s};return i(n(o))},we=r=>typeof r=="string"||Array.isArray(r)&&(typeof r[0]=="string"||r[0]===void 0),Xr=Se;var ke=32,ve=m.space;m.comment??={"//":`
|
|
6
|
+
`,"/*":"*/"};var dr;m.space=()=>{dr||(dr=Object.entries(m.comment).map(([n,s])=>[n,s,n.charCodeAt(0)]));for(var r;r=ve();){for(var e=0,t;t=dr[e++];)if(r===t[2]&&c.substr(u,t[0].length)===t[0]){var o=u+t[0].length;if(t[1]===`
|
|
7
|
+
`)for(;c.charCodeAt(o)>=ke;)o++;else{for(;c[o]&&c.substr(o,t[1].length)!==t[1];)o++;c[o]&&(o+=t[1].length)}G(o),r=0;break}if(r)return r}return r};var Kr=80;d("===",Kr);d("!==",Kr);p("===",(r,e)=>(r=i(r),e=i(e),t=>r(t)===e(t)));p("!==",(r,e)=>(r=i(r),e=i(e),t=>r(t)!==e(t)));var Te=30;d("??",Te);p("??",(r,e)=>(r=i(r),e=i(e),t=>r(t)??e(t)));var Ie=130,Ne=20;d("**",Ie,!0);d("**=",Ne,!0);p("**",(r,e)=>(r=i(r),e=i(e),t=>r(t)**e(t)));var Re=r=>{throw Error(r)};p("**=",(r,e)=>(O(r)||Re("Invalid assignment target"),e=i(e),U(r,(t,o,n)=>t[o]**=e(n))));var Dr=90;d("in",Dr);d("of",Dr);p("in",(r,e)=>(r=i(r),e=i(e),t=>r(t)in e(t)));var _e=20,Oe=100,Pe=r=>{throw Error(r)};d(">>>",Oe);d(">>>=",_e,!0);p(">>>",(r,e)=>(r=i(r),e=i(e),t=>r(t)>>>e(t)));p(">>>=",(r,e)=>(O(r)||Pe("Invalid assignment target"),e=i(e),U(r,(t,o,n)=>t[o]>>>=e(n))));var L=(r,e,t)=>{if(typeof r=="string"){t[r]=e;return}let[o,...n]=r;if(o==="{}")for(let s of n){let f,l,y;s[0]==="="?[,[,f,l],y]=s:[,f,l]=s;let E=e[f];E===void 0&&y&&(E=i(y)(t)),L(l,E,t)}else if(o==="[]"){let s=0;for(let f of n){if(f===null){s++;continue}if(Array.isArray(f)&&f[0]==="..."){t[f[1]]=e.slice(s);break}let l=f,y;Array.isArray(f)&&f[0]==="="&&([,l,y]=f);let E=e[s++];E===void 0&&y&&(E=i(y)(t)),L(l,E,t)}}};var Ar=20,rr=r=>{throw Error(r)};d("||=",Ar,!0);d("&&=",Ar,!0);d("??=",Ar,!0);p("=",(r,e)=>{if(Array.isArray(r)&&(r[0]==="let"||r[0]==="const"||r[0]==="var")){let t=r[1];return e=i(e),typeof t=="string"?o=>{o[t]=e(o)}:o=>L(t,e(o),o)}return O(r)||rr("Invalid assignment target"),e=i(e),U(r,(t,o,n)=>t[o]=e(n))});p("||=",(r,e)=>(O(r)||rr("Invalid assignment target"),e=i(e),U(r,(t,o,n)=>t[o]||=e(n))));p("&&=",(r,e)=>(O(r)||rr("Invalid assignment target"),e=i(e),U(r,(t,o,n)=>t[o]&&=e(n))));p("??=",(r,e)=>(O(r)||rr("Invalid assignment target"),e=i(e),U(r,(t,o,n)=>t[o]??=e(n))));P("true",!0);P("false",!1);P("null",null);P("undefined",void 0);P("NaN",NaN);P("Infinity",1/0);var hr=20;S("?",hr,(r,e,t)=>r&&(e=A(hr-1))&&k(o=>o===58)&&(t=A(hr-1),["?",r,e,t]));p("?",(r,e,t)=>(r=i(r),e=i(e),t=i(t),o=>r(o)?e(o):t(o)));var Me=20;d("=>",Me,!0);p("=>",(r,e)=>{r=r[0]==="()"?r[1]:r,r=r?r[0]===","?r.slice(1):[r]:[];let t=-1,o=null;return r.length&&Array.isArray(r[r.length-1])&&r[r.length-1][0]==="..."&&(t=r.length-1,o=r[t][1],r=r.slice(0,-1)),e=i(e[0]==="{}"?e[1]:e),(n=null)=>(n=Object.create(n),(...s)=>(r.forEach((f,l)=>n[f]=s[l]),o&&(n[o]=s.slice(t)),e(n)))});var Ue=140;v("...",Ue);p("...",r=>(r=i(r),e=>Object.entries(r(e))));var Br=170;S("?.",Br,(r,e)=>{if(!r)return;let t=h();return t===40?(g(),["?.()",r,A(0,41)||null]):t===91?(g(),["?.[]",r,A(0,93)]):(e=A(Br),e?["?.",r,e]:void 0)});p("?.",(r,e)=>(r=i(r),M(e)?()=>{}:t=>r(t)?.[e]));p("?.[]",(r,e)=>(r=i(r),e=i(e),t=>{let o=e(t);return M(o)?void 0:r(t)?.[o]}));p("?.()",(r,e)=>{let t=e?e[0]===","?(e=e.slice(1).map(i),n=>e.map(s=>s(n))):(e=i(e),n=>[e(n)]):()=>[];if(r[0]==="?."){let n=i(r[1]),s=r[2];return M(s)?()=>{}:f=>n(f)?.[s]?.(...t(f))}if(r[0]==="?.[]"){let n=i(r[1]),s=i(r[2]);return f=>{let l=n(f),y=s(f);return M(y)?void 0:l?.[y]?.(...t(f))}}if(r[0]==="."){let n=i(r[1]),s=r[2];return M(s)?()=>{}:f=>n(f)?.[s]?.(...t(f))}if(r[0]==="[]"&&r.length===3){let n=i(r[1]),s=i(r[2]);return f=>{let l=n(f),y=s(f);return M(y)?void 0:l?.[y]?.(...t(f))}}let o=i(r);return n=>o(n)?.(...t(n))});var er=140;v("typeof",er);v("void",er);v("delete",er);v("new",er);p("typeof",r=>(r=i(r),e=>typeof r(e)));p("void",r=>(r=i(r),e=>(r(e),void 0)));p("delete",r=>{if(r[0]==="."){let e=i(r[1]),t=r[2];return o=>delete e(o)[t]}if(r[0]==="[]"){let e=i(r[1]),t=i(r[2]);return o=>delete e(o)[t(o)]}return()=>!0});p("new",r=>{let e=i(r?.[0]==="()"?r[1]:r),t=r?.[0]==="()"?r[2]:null,o=t?t[0]===","?(n=>s=>n.map(f=>f(s)))(t.slice(1).map(i)):(n=>s=>[n(s)])(i(t)):()=>[];return n=>new(e(n))(...o(n))});var tr=Symbol("accessor"),Qr=20,Le=40,Fe=41,Ge=123,Xe=125,$r=r=>e=>{if(e)return;h();let t=k(m.id);if(!t||(h(),c.charCodeAt(u)!==Le))return!1;g();let o=A(0,Fe);return h(),c.charCodeAt(u)!==Ge?!1:(g(),[r,t,o,A(0,Xe)])};S("get",Qr-1,$r("get"));S("set",Qr-1,$r("set"));p("get",(r,e)=>(e=e?i(e):()=>{},t=>[[tr,r,{get:function(){let o=Object.create(t||{});return o.this=this,e(o)}}]]));p("set",(r,e,t)=>(t=t?i(t):()=>{},o=>[[tr,r,{set:function(n){let s=Object.create(o||{});s.this=this,s[e]=n,t(s)}}]]));var Ke=20,Hr=200;H("[]",Hr);H("{}",Hr);d(":",Ke-1,!0);p("{}",(r,e)=>{if(e!==void 0)return;r=r?r[0]!==","?[r]:r.slice(1):[];let t=r.map(o=>i(typeof o=="string"?[":",o,o]:o));return o=>{let n={},s={};for(let f of t.flatMap(l=>l(o)))if(f[0]===tr){let[,l,y]=f;s[l]={...s[l],...y,configurable:!0,enumerable:!0}}else n[f[0]]=f[1];for(let f in s)Object.defineProperty(n,f,s[f]);return n}});p(":",(r,e)=>(e=i(e),Array.isArray(r)?(r=i(r),t=>[[r(t),e(t)]]):t=>[[r,e(t)]]));var De=170,or=96,Be=36,Qe=123,$e=92,He={n:`
|
|
8
|
+
`,r:"\r",t:" ",b:"\b",f:"\f",v:"\v"},jr=()=>{let r=[];for(let e="",t;(t=c.charCodeAt(u))!==or;)t?t===$e?(g(),e+=He[c[u]]||c[u],g()):t===Be&&c.charCodeAt(u+1)===Qe?(e&&r.push([,e]),e="",g(2),r.push(A(0,125))):(e+=c[u],g(),t=c.charCodeAt(u),t===or&&e&&r.push([,e])):I("Unterminated template");return g(),r},je=w[or];w[or]=(r,e)=>r&&e<De?m.asi&&m.newline?void 0:(g(),["``",r,...jr()]):r?je?.(r,e):(g(),(t=>t.length<2&&t[0]?.[0]===void 0?t[0]||[,""]:["`",...t])(jr()));p("`",(...r)=>(r=r.map(i),e=>r.map(t=>t(e)).join("")));p("``",(r,...e)=>{r=i(r);let t=[],o=[];for(let s of e)Array.isArray(s)&&s[0]===void 0?t.push(s[1]):o.push(i(s));let n=Object.assign([...t],{raw:t});return s=>r(s)(n,...o.map(f=>f(s)))});m.string["'"]=!0;m.number={"0x":16,"0b":2,"0o":8};var yr=5,Wr=123,zr=125,a=(r,e,t,o=r.charCodeAt(0),n=r.length,s=w[o],f)=>w[o]=(l,y,E,T=u)=>!l&&(E?r==E:(n<2||c.substr(u,n)==r)&&(E=r))&&y<e&&!m.id(c.charCodeAt(u+n))&&(G(u+n),(f=t())?V(f,T):(G(T),!s&&I()),f)||s?.(l,y,E),gr=(r,e,t,o=r.charCodeAt(0),n=r.length,s=w[o],f)=>w[o]=(l,y,E,T=u)=>l&&(E?r==E:(n<2||c.substr(u,n)==r)&&(E=r))&&y<e&&!m.id(c.charCodeAt(u+n))&&(G(u+n),V(f=t(l),T),f)||s?.(l,y,E),_=()=>(h()===Wr||I("Expected {"),g(),A(yr-.5,zr)||null),K=()=>h()!==Wr?A(yr+.5):(g(),["block",A(yr-.5,zr)||null]);p("block",r=>r===void 0?()=>{}:(r=i(r),e=>r(e)));var Er=5,We=10,ze=20,Jr=r=>{let e=A(We-1);return e?.[0]==="in"||e?.[0]==="of"?[e[0],[r,e[1]],e[2]]:e?.[0]===","?[r,...e.slice(1)]:[r,e]};S("let",Er+1,r=>!r&&Jr("let"));S("const",Er+1,r=>!r&&Jr("const"));a("var",Er,()=>(h(),["var",A(ze)]));var Vr=(...r)=>(r=r.map(e=>{if(typeof e=="string")return t=>{t[e]=void 0};if(e[0]==="="){let[,t,o]=e,n=i(o);return typeof t=="string"?s=>{s[t]=n(s)}:s=>L(t,n(s),s)}return i(e)}),e=>{for(let t of r)t(e)});p("let",Vr);p("const",Vr);p("var",r=>typeof r=="string"?e=>{e[r]=void 0}:()=>{});var D=Symbol("break"),W=Symbol("continue"),B=Symbol("return");var Je=200;a("function",Je,()=>{h();let r=k(m.id);return r&&h(),["function",r,N()||null,_()]});p("function",(r,e,t)=>{t=t?i(t):()=>{};let o=e?e[0]===","?e.slice(1):[e]:[],n=null,s=-1,f=o[o.length-1];return Array.isArray(f)&&f[0]==="..."&&(s=o.length-1,n=f[1],o.length--),l=>{let y=(...E)=>{let T={};o.forEach((C,R)=>T[C]=E[R]),n&&(T[n]=E.slice(s));let F=new Proxy(T,{get:(C,R)=>R in C?C[R]:l[R],set:(C,R,xr)=>((R in C?C:l)[R]=xr,!0),has:(C,R)=>R in C||R in l});try{return t(F)}catch(C){if(C?.type===B)return C.value;throw C}};return r&&(l[r]=y),y}});var nr=140,ar=20;v("await",nr);a("yield",nr,()=>(h(),c[u]==="*"?(g(),h(),["yield*",A(ar)]):["yield",A(ar)]));a("async",nr,()=>{if(h(),X("function"))return["async",A(nr)];let r=A(ar-.5);return r&&["async",r]});p("async",r=>{let e=i(r);return t=>{let o=e(t);return async function(...n){return o(...n)}}});p("await",r=>(r=i(r),async e=>await r(e)));p("yield",r=>(r=r?i(r):null,e=>{throw{__yield__:r?r(e):void 0}}));p("yield*",r=>(r=i(r),e=>{throw{__yield_all__:r(e)}}));var Sr=200,Ve=140,Ye=90,Ze=Symbol("static");P("super",Symbol.for("super"));v("static",Ve);d("instanceof",Ye);S("#",Sr,r=>{if(r)return;let e=k(m.id);return e?"#"+e:void 0});a("class",Sr,()=>{h();let r=k(m.id)||null;if(r==="extends")r=null;else if(h(),!X("extends"))return["class",r,null,_()];return h(),["class",r,A(Sr),_()]});var qe=r=>{throw Error(r)};p("instanceof",(r,e)=>(r=i(r),e=i(e),t=>r(t)instanceof e(t)));p("class",(r,e,t)=>(e=e?i(e):null,t=t?i(t):null,o=>{let n=e?e(o):Object,s=function(...f){if(!(this instanceof s))return qe("Class constructor must be called with new");let l=e?Reflect.construct(n,f,s):this;return s.prototype.__constructor__&&s.prototype.__constructor__.apply(l,f),l};if(Object.setPrototypeOf(s.prototype,n.prototype),Object.setPrototypeOf(s,n),t){let f=Object.create(o);f.super=n;let l=t(f),y=Array.isArray(l)&&typeof l[0]?.[0]=="string"?l:[];for(let[E,T]of y)E==="constructor"?s.prototype.__constructor__=T:s.prototype[E]=T}return r&&(o[r]=s),s}));p("static",r=>(r=i(r),e=>[[Ze,r(e)]]));var xe=140,Cr=47,be=92,rt=r=>r===be?2:r&&r!==Cr,et=r=>r===103||r===105||r===109||r===115||r===117||r===121;S("/",xe,r=>{if(r)return;let e=c.charCodeAt(u);if(e===Cr||e===42||e===43||e===63||e===61)return;let t=k(rt);c.charCodeAt(u)===Cr||I("Unterminated regex"),g();try{return[,new RegExp(t,k(et))]}catch(o){I("Invalid regex: "+o.message)}});var tt=5,ot=59,nt=()=>{let r=u;return h()===ot&&g(),h(),X("else")?(g(4),!0):(G(r),!1)};a("if",tt+1,()=>{h();let r=["if",N(),K()];return nt()&&r.push(K()),r});p("if",(r,e,t)=>(r=i(r),e=i(e),t=t!==void 0?i(t):null,o=>r(o)?e(o):t?.(o)));var z=(r,e)=>{try{return{v:r(e)}}catch(t){if(t?.type===D)return{b:1};if(t?.type===W)return{c:1};if(t?.type===B)return{r:1,v:t.value};throw t}},Q=5,it=125,st=59;a("while",Q+1,()=>(h(),["while",N(),K()]));a("do",Q+1,()=>(r=>(h(),g(5),h(),["do",r,N()]))(K()));a("for",Q+1,()=>(h(),X("await")?(g(5),h(),["for await",N(),K()]):["for",N(),K()]));a("break",Q+1,()=>["break"]);a("continue",Q+1,()=>["continue"]);a("return",Q+1,()=>{m.asi&&(m.newline=!1),h();let r=c.charCodeAt(u);return!r||r===it||r===st||m.newline?["return"]:["return",A(Q)]});p("while",(r,e)=>(r=i(r),e=i(e),t=>{let o,n;for(;r(t)&&!(o=z(e,t)).b;){if(o.r)return o.v;o.c||(n=o.v)}return n}));p("do",(r,e)=>(r=i(r),e=i(e),t=>{let o,n;do{if((o=z(r,t)).b)break;if(o.r)return o.v;o.c||(n=o.v)}while(e(t));return n}));p("for",(r,e)=>{if(Array.isArray(r)&&r[0]===";"){let[,t,o,n]=r;return t=t?i(t):null,o=o?i(o):()=>!0,n=n?i(n):null,e=i(e),s=>{let f,l;for(t?.(s);o(s)&&!(f=z(e,s)).b;n?.(s)){if(f.r)return f.v;f.c||(l=f.v)}return l}}if(Array.isArray(r)&&(r[0]==="in"||r[0]==="of")){let[t,o,n]=r;if(Array.isArray(o)&&(o[0]==="let"||o[0]==="const"||o[0]==="var")&&(o=o[1]),t==="in")return ft(o,n,e);if(t==="of")return pt(o,n,e)}});var pt=(r,e,t)=>{e=i(e),t=i(t);let o=Array.isArray(r);return n=>{let s,f,l=o?null:n[r];for(let y of e(n)){if(o?L(r,y,n):n[r]=y,(s=z(t,n)).b)break;if(s.r)return s.v;s.c||(f=s.v)}return o||(n[r]=l),f}},ft=(r,e,t)=>{e=i(e),t=i(t);let o=Array.isArray(r);return n=>{let s,f,l=o?null:n[r];for(let y in e(n)){if(o?L(r,y,n):n[r]=y,(s=z(t,n)).b)break;if(s.r)return s.v;s.c||(f=s.v)}return o||(n[r]=l),f}};p("break",()=>()=>{throw{type:D}});p("continue",()=>()=>{throw{type:W}});p("return",r=>(r=r!==void 0?i(r):null,e=>{throw{type:B,value:r?.(e)}}));var J=5;a("try",J+1,()=>["try",_()]);gr("catch",J+1,r=>(h(),["catch",r,N(),_()]));gr("finally",J+1,r=>["finally",r,_()]);a("throw",J+1,()=>{if(m.asi&&(m.newline=!1),h(),m.newline)throw SyntaxError("Unexpected newline after throw");return["throw",A(J)]});p("try",r=>(r=r?i(r):null,e=>r?.(e)));p("catch",(r,e,t)=>{let o=r?.[1]?i(r[1]):null;return t=t?i(t):null,n=>{let s;try{s=o?.(n)}catch(f){if(f?.type===D||f?.type===W||f?.type===B)throw f;if(e!==null&&t){let l=e in n,y=n[e];n[e]=f;try{s=t(n)}finally{l?n[e]=y:delete n[e]}}else if(e===null)throw f}return s}});p("finally",(r,e)=>(r=r?i(r):null,e=e?i(e):null,t=>{let o;try{o=r?.(t)}finally{e?.(t)}return o}));p("throw",r=>(r=i(r),e=>{throw r(e)}));var wr=5,lt=20,Yr=58;a("switch",wr+1,()=>(h(),["switch",N(),_()]));a("case",wr+1,()=>(h(),(r=>(h()===Yr&&g(),["case",r]))(A(lt))));a("default",wr+1,()=>(h()===Yr&&g(),["default"]));p("switch",(r,e)=>{if(r=i(r),!e)return s=>r(s);let t=[],o=e[0]===";"?e.slice(1):[e],n=null;for(let s of o)Array.isArray(s)&&(s[0]==="case"||s[0]==="default")?(n&&t.push(n),n=[s[0]==="case"?i(s[1]):null,[]]):n&&n[1].push(i(s));return n&&t.push(n),s=>{let f=r(s),l=!1,y;for(let[E,T]of t)if(l||E===null||E(s)===f){l=!0;for(let F of T)try{y=F(s)}catch(C){if(C?.type===D)return C.value!==void 0?C.value:y;throw C}}return y}});var kr=5,$=10,Zr=42,ut=w[Zr];w[Zr]=(r,e)=>r?ut?.(r,e):(g(),"*");S("from",$+1,r=>r?r[0]!=="="&&r[0]!==","&&(h(),["from",r,A($+1)]):!1);S("as",$+2,r=>r?(h(),["as",r,A($+2)]):!1);a("import",kr,()=>(h(),["import",A($)]));a("export",kr,()=>(h(),["export",A(kr)]));a("default",$+1,()=>(h(),["default",A($)]));p("import",()=>()=>{});p("export",()=>()=>{});p("from",(r,e)=>()=>{});p("as",(r,e)=>()=>{});p("default",r=>i(r));var qr=5;m.asi=(r,e,t)=>{if(e>=qr)return;let o=t(qr-.5);if(o)return r?.[0]!==";"?[";",r,o]:(r.push(o),r)};export{pr as access,d as binary,i as compile,c as cur,Xr as default,I as err,A as expr,H as group,mt as id,u as idx,P as literal,V as loc,w as lookup,sr as nary,k as next,p as operator,ir as operators,N as parens,m as parse,G as seek,g as skip,h as space,S as token,v as unary,X as word};
|
package/justin.js
CHANGED
|
@@ -1,48 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import './
|
|
8
|
-
import './
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
operator('>>>=', (a, b) => (b = compile(b), prop(a, (obj, path, ctx) => (obj[path] >>>= b(ctx)))))
|
|
41
|
-
|
|
42
|
-
// add JS literals
|
|
43
|
-
token('undefined', 20, a => a ? err() : [, undefined])
|
|
44
|
-
token('NaN', 20, a => a ? err() : [, NaN])
|
|
45
|
-
token('null', 20, a => a ? err() : [, null])
|
|
46
|
-
|
|
47
|
-
export default subscript
|
|
48
|
-
export * from './subscript.js'
|
|
1
|
+
/**
|
|
2
|
+
* justin: JSON superset expression language
|
|
3
|
+
*
|
|
4
|
+
* Builds on subscript with JS-specific features:
|
|
5
|
+
* optional chaining, arrow functions, spread, templates.
|
|
6
|
+
*/
|
|
7
|
+
import './subscript.js';
|
|
8
|
+
import { parse } from './parse.js';
|
|
9
|
+
|
|
10
|
+
// Add single quotes
|
|
11
|
+
parse.string["'"] = true;
|
|
12
|
+
|
|
13
|
+
// Add hex, binary, octal prefixes
|
|
14
|
+
parse.number = { '0x': 16, '0b': 2, '0o': 8 };
|
|
15
|
+
|
|
16
|
+
import './feature/comment.js';
|
|
17
|
+
|
|
18
|
+
// Extended operators
|
|
19
|
+
// Note: assignment (=) is in subscript, must come BEFORE identity (===)
|
|
20
|
+
import './feature/op/identity.js'; // === !==
|
|
21
|
+
import './feature/op/nullish.js'; // ??
|
|
22
|
+
import './feature/op/pow.js'; // ** **=
|
|
23
|
+
import './feature/op/membership.js'; // in (instanceof is in jessie/class.js)
|
|
24
|
+
import './feature/op/bitwise-unsigned.js'; // >>> >>>=
|
|
25
|
+
import './feature/op/assign-logical.js'; // ||= &&= ??= + destructuring
|
|
26
|
+
|
|
27
|
+
// JS-specific operators (ternary, arrow, spread, optional chaining, typeof/void/delete/new)
|
|
28
|
+
import './feature/literal.js';
|
|
29
|
+
import './feature/op/ternary.js';
|
|
30
|
+
import './feature/op/arrow.js';
|
|
31
|
+
import './feature/op/spread.js';
|
|
32
|
+
import './feature/op/optional.js';
|
|
33
|
+
import './feature/op/unary.js';
|
|
34
|
+
|
|
35
|
+
import './feature/collection.js';
|
|
36
|
+
import './feature/template.js';
|
|
37
|
+
|
|
38
|
+
export * from './parse.js';
|
|
39
|
+
export { default } from './subscript.js';
|