Skip to content

Commit 104a81c

Browse files
committed
Fix REPL
1 parent cd109c6 commit 104a81c

15 files changed

Lines changed: 455 additions & 206 deletions

README.md

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# subscript [![build](https://github.com/dy/subscript/actions/workflows/node.js.yml/badge.svg)](https://github.com/dy/subscript/actions/workflows/node.js.yml) [![npm](https://img.shields.io/npm/v/subscript)](http://npmjs.org/subscript) [![](https://img.shields.io/badge/MIT-%E0%A5%90-white)](https://krishnized.github.io/license)
1+
# sub<sub><sup> ✦ </sup></sub>script [![build](https://github.com/dy/subscript/actions/workflows/node.js.yml/badge.svg)](https://github.com/dy/subscript/actions/workflows/node.js.yml) [![npm](https://img.shields.io/npm/v/subscript)](http://npmjs.org/subscript) [![demo](https://img.shields.io/badge/demo-%F0%9F%9A%80-white)](https://dy.github.io/subscript/repl) [![](https://img.shields.io/badge/MIT-%E0%A5%90-white)](https://krishnized.github.io/license)
22

33
> Safe expression evaluator & language tool.
44
@@ -15,8 +15,6 @@ subscript`a + b * 2`({ a: 1, b: 3 }) // 7
1515
* **Self-hosting** — compiles own source (js in js)
1616
* **Language tool** — modular syntax extensions for custom DSL
1717

18-
[**Try REPL →**](https://dy.github.io/subscript/repl.html)
19-
2018

2119
## Presets
2220

@@ -72,7 +70,7 @@ token('px', 200, n => n && [, n[1] + 'px']) // 5px → "5px"
7270
See [docs.md](./docs.md) for full API.
7371

7472

75-
## Expressions
73+
## Expressions format
7674

7775
Subscript uses simplified syntax tree format:
7876

@@ -106,7 +104,6 @@ subscript`constructor.constructor("alert(1)")()`({})
106104
// undefined (blocked)
107105
```
108106

109-
110107
## Performance
111108

112109
Parse 30k times:
@@ -115,32 +112,39 @@ subscript: ~150 ms 🥇
115112
justin: ~183 ms
116113
jsep: ~270 ms 🥈
117114
jexpr: ~297 ms 🥉
118-
```
119-
<!--
120115
mr-parser: ~420 ms
121116
expr-eval: ~480 ms
122117
math-parser: ~570 ms
123118
math-expression-evaluator: ~900ms
124119
jexl: ~1056 ms
125120
mathjs: ~1200 ms
126121
new Function: ~1154 ms
127-
-->
128122
129-
Evaluate 30k times:
130-
```
123+
// Evaluate 30k times:
131124
new Function ~7ms 🥇
132125
subscript ~15ms 🥈
133126
justin: ~17 ms
134127
jsep ~30ms 🥉
135-
```
136-
<!--
137128
math-expression-evaluator: ~50ms
138129
expr-eval: ~72 ms
139130
jexl: ~110 ms
140131
mathjs: ~119 ms
141-
mr-parser: -
142-
math-parser: -
143-
-->
132+
```
133+
134+
135+
## Utils
136+
137+
**Bundle** — create custom dialect bundle:
138+
```js
139+
import { bundle } from 'subscript/util/bundle.js'
140+
141+
// Bundle specific features into single file
142+
const code = await bundle('subscript/jessie.js')
143+
// → self-contained ES module with parse, compile exports
144+
```
145+
146+
**REPL** — interactive dialect builder with live bundling:
147+
[**Try REPL →**](https://dy.github.io/subscript/repl.html)
144148

145149

146150
## Used by
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Property access and function calls: a.b, a[b], a(b)
2+
* Property access: a.b, a[b], a(b), [1,2,3]
33
* For private fields (#x), see class.js
44
*/
55
import { access, binary, operator, compile } from '../parse.js';
@@ -24,7 +24,7 @@ operator('[]', (a, b) => {
2424
// Array literal: [1,2,3] - b is strictly undefined (AST length 2)
2525
if (b === undefined) {
2626
a = !a ? [] : a[0] === ',' ? a.slice(1) : [a];
27-
a = a.map(a => a[0] === '...' ? (a = compile(a[1]), ctx => a(ctx)) : (a = compile(a), ctx => [a(ctx)]));
27+
a = a.map(a => a == null ? (() => undefined) : a[0] === '...' ? (a = compile(a[1]), ctx => a(ctx)) : (a = compile(a), ctx => [a(ctx)]));
2828
return ctx => a.flatMap(a => a(ctx));
2929
}
3030
// Member access: a[b]

feature/group.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { nary, group, operator, compile } from '../parse.js';
22
import { BREAK, CONTINUE } from './loop.js';
3-
import { prop } from './member.js';
3+
import { prop } from './access.js';
44

55
const STATEMENT = 5, SEQ = 10, ACCESS = 170;
66

feature/module.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,11 @@ keyword('export', STATEMENT, () => (space(), ['export', expr(STATEMENT)]));
3232

3333
// default: prefix for export default
3434
keyword('default', SEQ + 1, () => (space(), ['default', expr(SEQ)]));
35+
36+
// Compile stubs - import/export are parse-only (no runtime semantics)
37+
import { operator, compile } from '../parse.js';
38+
operator('import', () => () => undefined);
39+
operator('export', () => () => undefined);
40+
operator('from', (a, b) => () => undefined);
41+
operator('as', (a, b) => () => undefined);
42+
operator('default', (a) => compile(a));

feature/op/assign-logical.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66
import { binary, operator, compile } from '../../parse.js';
77
import { destructure } from '../destruct.js';
8-
import { isLval, prop } from '../member.js';
8+
import { isLval, prop } from '../access.js';
99

1010
const ASSIGN = 20;
1111
const err = msg => { throw Error(msg) };

feature/op/bitwise-unsigned.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* >>> >>>=
55
*/
66
import { binary, operator, compile } from '../../parse.js';
7-
import { isLval, prop } from '../member.js';
7+
import { isLval, prop } from '../access.js';
88

99
const ASSIGN = 20, SHIFT = 100;
1010
const err = msg => { throw Error(msg) };

feature/op/optional.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Common in: JS, TS, Swift, Kotlin, C#
99
*/
1010
import { token, expr, skip, space, operator, compile } from '../../parse.js';
11-
import { unsafe } from '../member.js';
11+
import { unsafe } from '../access.js';
1212

1313
const ACCESS = 170;
1414

feature/op/pow.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* ES2016+, not in classic JS/C
77
*/
88
import { binary, operator, compile } from '../../parse.js';
9-
import { isLval, prop } from '../member.js';
9+
import { isLval, prop } from '../access.js';
1010

1111
const EXP = 130, ASSIGN = 20;
1212

parse.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export let idx, cur,
1717
chr = (cur[at] || '∅') + ptr,
1818
after = cur.slice(at + 1, at + 20)
1919
) => {
20-
throw SyntaxError(`${msg} at ${lines.length + 1}:${last.length + 1}${before}${chr}${after}`)
20+
throw SyntaxError(`${msg} at ${lines.length + 1}:${last.length + 1}\n${(cur[at-41]!=='\n' ? '...' : '') +before}${chr}${after}`)
2121
},
2222

2323
// attach location to node (returns node for chaining)

0 commit comments

Comments
 (0)