simplex-lang 0.0.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/simplex.peggy"],"names":["$top_level_initializer","Start","SourceCharacter","WhiteSpace","LineTerminator","LineTerminatorSequence","Comment","MultiLineComment","MultiLineCommentNoLineTerminator","SingleLineComment","Identifier","IdentifierName","IdentifierStart","IdentifierPart","UnicodeLetter","UnicodeCombiningMark","ReservedWord","Keyword","Literal","NullLiteral","BooleanLiteral","NumericLiteral","DecimalLiteral","DecimalIntegerLiteral","DecimalDigit","NonZeroDigit","ExponentPart","ExponentIndicator","SignedInteger","HexIntegerLiteral","HexDigit","StringLiteral","DoubleStringCharacter","SingleStringCharacter","LineContinuation","EscapeSequence","CharacterEscapeSequence","SingleEscapeCharacter","NonEscapeCharacter","EscapeCharacter","HexEscapeSequence","UnicodeEscapeSequence","Ll","Lm","Lo","Lt","Lu","Mc","Mn","Nd","Nl","Pc","Zs","AndToken","ElseToken","FalseToken","IfToken","InToken","NotToken","NullToken","OrToken","ThenToken","TrueToken","TypeofToken","ModToken","__","_","EOS","EOF","PrimaryExpression","ArrayLiteral","ElementList","Elision","ObjectLiteral","PropertyNameAndValueList","PropertyAssignment","PropertyName","MemberExpression","CallExpression","Arguments","ArgumentList","LeftHandSideExpression","ExponentiationExpression","ExponentiationOperator","UnaryExpression","UnaryOperator","MultiplicativeExpression","MultiplicativeOperator","AdditiveExpression","AdditiveOperator","ConcatenationExpression","ConcatenationOperator","RelationalExpression","RelationalOperator","EqualityExpression","EqualityOperator","LogicalANDExpression","LogicalANDOperator","LogicalORExpression","LogicalOROperator","ConditionalExpression","NullishCoalescingExpression","NullishCoalescingOperator","PipeExpression","PipeOperator","ExpressionStatement"],"mappings":";;;;;AAAEA;AACFA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;AACAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oCAIyC,mBAAmB,E;+BAsCrB,cAAc,E;qCAGN;AAC/C;AACA;AACA;AACA;AACA;AACA,IAAI,E;mCAMqC,kBAAkB,E;2BAmD5C;AACf;AACA;AACA;AACA;AACA;AACA,IAAI,E;2BAGW;AACf;AACA;AACA;AACA;AACA;AACA,IAAI,E;2BACY;AAChB;AACA;AACA;AACA;AACA;AACA,IAAI,E;kCAG6D;AACjE;AACA,IAAI,E;kCAC0D;AAC9D;AACA,IAAI,E;2BAGuD;AAC3D;AACA;AACA;AACA;AACA;AACA,IAAI,E;4BACiC;AACrC;AACA;AACA;AACA;AACA;AACA,IAAI,E;4BACqC;AACzC;AACA;AACA;AACA;AACA;AACA,IAAI,E;kCAsByB;AAC7B;AACA;AACA;AACA;AACA;AACA,IAAI,E;iCAMsC;AAC1C;AACA;AACA;AACA;AACA;AACA,IAAI,E;iCACsC;AAC1C;AACA;AACA;AACA;AACA;AACA,IAAI,E;4BAGgD,gBAAgB,E;oCAClC,kBAAkB,E;4BAIA,gBAAgB,E;oCAClC,kBAAkB,E;4BAInB,YAAY,E;4BAItB,cAAc,E;4BAY3B,cAAc,E;4BACd,cAAc,E;4BACd,cAAc,E;4BACd,cAAc,E;4BACd,cAAc,E;4BACd,cAAc,E;4BAGiC,gBAAgB,E;kCASpC;AACrC;AACA,IAAI,E;kCAGmD;AACvD;AACA,IAAI,E;sCAuEqC,oBAAoB,E;mCAGvB;AACtC;AACA;AACA;AACA;AACA;AACA,IAAI,E;oCACoC;AACxC;AACA;AACA;AACA;AACA;AACA,IAAI,E;6CACiE;AACrE;AACA;AACA;AACA;AACA;AACA,IAAI,E;4CAI4C;AAChD;AACA,MAAM,E;kDAGoD;AAC1D;AACA,MAAM,E;sCAED,kDAAkD,E;kCAG7B,8CAA8C,E;4BAGxD;AAChB;AACA;AACA;AACA;AACA;AACA,IAAI,E;sCACmD;AACvD;AACA;AACA;AACA;AACA;AACA,IAAI,E;sCAC0D;AAC9D;AACA;AACA;AACA;AACA;AACA,IAAI,E;sCAG8D;AAClE;AACA,IAAI,E;sCAG6C;AACjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,E;0CAY0C;AAC9C;AACA;AACA;AACA,QAAQ,E;0CACmC;AAC3C;AACA;AACA;AACA,QAAQ,E;sCAEH;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,E;wCAI6C;AACjD;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,E;sCAGqB;AAC3B;AACA;AACA;AACA;AACA;AACA,QAAQ,E;0CACsC;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,E;0CACmC;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,E;sCAEH;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,E;gCAGoC;AACxC;AACA,IAAI,E;sCAG8C;AAClD;AACA,IAAI,E;sCASC,uDAAuD,E;8CAOJ;AACxD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,E;sCAWC,uDAAuD,E;sCAUv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","file":"index.js"}
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "@project/simplex-parser",
3
+ "version": "0.0.0",
4
+ "type": "module",
5
+ "main": "index.js",
6
+ "types": "index.d.ts"
7
+ }
@@ -0,0 +1,538 @@
1
+ import { parse } from '@project/simplex-parser'
2
+ import { ExpressionError, UnexpectedTypeError } from './errors.js'
3
+ import {
4
+ BinaryExpression,
5
+ Expression,
6
+ ExpressionByType,
7
+ ExpressionStatement,
8
+ Location,
9
+ LogicalExpression,
10
+ UnaryExpression
11
+ } from './simplex-tree.js'
12
+ import {
13
+ bool,
14
+ ensureFunction,
15
+ isSimple,
16
+ num,
17
+ prettyType,
18
+ relComp,
19
+ toStr
20
+ } from './utils.js'
21
+ import assert from 'node:assert'
22
+
23
+ interface ContextHelpers<Data, Globals> {
24
+ castToBoolean(this: void, val: unknown): boolean
25
+ ensureFunction(this: void, val: unknown): Function
26
+ getIdentifierValue(
27
+ this: void,
28
+ identifierName: string,
29
+ globals: Globals,
30
+ data: Data
31
+ ): unknown
32
+ getProperty(this: void, obj: unknown, key: unknown): unknown
33
+ callFunction(this: void, fn: unknown, args: unknown[] | null): unknown
34
+ pipe(
35
+ this: void,
36
+ head: unknown,
37
+ tail: { opt: boolean; next: (_: unknown) => unknown }[]
38
+ ): unknown
39
+ }
40
+
41
+ var hasOwn = Object.hasOwn
42
+ var ERROR_STACK_REGEX = /<anonymous>:(?<row>\d+):(?<col>\d+)/g
43
+
44
+ const defaultContextHelpers: ContextHelpers<
45
+ Record<string, unknown>,
46
+ Record<string, unknown>
47
+ > = {
48
+ castToBoolean: bool,
49
+
50
+ ensureFunction,
51
+
52
+ getIdentifierValue: (identifierName, globals, data) => {
53
+ if (identifierName === 'undefined') return undefined
54
+
55
+ if (globals != null && Object.hasOwn(globals, identifierName)) {
56
+ return globals[identifierName]
57
+ }
58
+
59
+ if (data != null && Object.hasOwn(data, identifierName)) {
60
+ return data[identifierName]
61
+ }
62
+
63
+ throw new Error(`Unknown identifier - ${identifierName}`)
64
+ },
65
+
66
+ getProperty(obj, key) {
67
+ if (obj == null) return obj
68
+
69
+ if (typeof obj !== 'object') {
70
+ throw new UnexpectedTypeError('object', prettyType(obj))
71
+ }
72
+
73
+ if (isSimple(key) === false) {
74
+ throw new UnexpectedTypeError(
75
+ 'object key to be simple type',
76
+ prettyType(key)
77
+ )
78
+ }
79
+
80
+ if (hasOwn(obj, key as any)) {
81
+ // @ts-expect-error Type cannot be used as an index type
82
+ return obj[key] as unknown
83
+ }
84
+
85
+ return undefined
86
+ },
87
+
88
+ callFunction(fn, args) {
89
+ return (
90
+ args === null
91
+ ? ensureFunction(fn)()
92
+ : ensureFunction(fn).apply(null, args)
93
+ ) as unknown
94
+ },
95
+
96
+ pipe(head, tail) {
97
+ var result = head
98
+ for (const it of tail) {
99
+ if (it.opt && result == null) return result
100
+ result = it.next(result)
101
+ }
102
+ return result
103
+ }
104
+ }
105
+
106
+ type ExpressionUnaryOperators = Record<
107
+ UnaryExpression['operator'],
108
+ (val: unknown) => unknown
109
+ >
110
+
111
+ export const defaultUnaryOperators: ExpressionUnaryOperators = {
112
+ '+': val => num(val),
113
+ '-': val => -num(val),
114
+ 'not': val => !bool(val),
115
+ 'typeof': val => typeof val
116
+ }
117
+
118
+ type ExpressionBinaryOperators = Record<
119
+ BinaryExpression['operator'] | LogicalExpression['operator'],
120
+ (left: unknown, right: unknown) => unknown
121
+ >
122
+
123
+ export const defaultBinaryOperators: ExpressionBinaryOperators = {
124
+ '!=': (a, b) => a !== b,
125
+
126
+ '==': (a, b) => a === b,
127
+
128
+ '*': (a, b) => num(a) * num(b),
129
+
130
+ '+': (a, b) => num(a) + num(b),
131
+
132
+ '&': (a, b) => toStr(a) + toStr(b),
133
+
134
+ '-': (a, b) => num(a) - num(b),
135
+
136
+ '/': (a, b) => num(a) / num(b),
137
+
138
+ 'mod': (a, b) => {
139
+ return num(a) % num(b)
140
+ },
141
+
142
+ '<': (a, b) => relComp(a) < relComp(b),
143
+
144
+ '<=': (a, b) => relComp(a) <= relComp(b),
145
+
146
+ '>': (a, b) => relComp(a) > relComp(b),
147
+
148
+ '>=': (a, b) => relComp(a) >= relComp(b),
149
+
150
+ 'in': (a, b) => {
151
+ if (isSimple(a) && b != null && typeof b === 'object') {
152
+ return Object.hasOwn(b, a as any)
153
+ } else {
154
+ throw new TypeError(
155
+ `Cannot use "in" operator to search for ${prettyType(a)} key in ${prettyType(b)}`
156
+ )
157
+ }
158
+ },
159
+
160
+ '^': (a, b) => num(a) ** num(b),
161
+
162
+ 'and': (a, b) => bool(a) && bool(b),
163
+
164
+ 'or': (a, b) => bool(a) || bool(b)
165
+ }
166
+
167
+ interface ExpressionOperators {
168
+ unaryOperators: Record<UnaryExpression['operator'], (val: unknown) => unknown>
169
+ binaryOperators: Record<
170
+ BinaryExpression['operator'] | LogicalExpression['operator'],
171
+ (left: unknown, right: unknown) => unknown
172
+ >
173
+ }
174
+
175
+ const PIPE_LTR = '_'
176
+
177
+ export interface SourceLocation {
178
+ len: number
179
+ location: Location
180
+ }
181
+
182
+ export interface VisitResult {
183
+ code: string
184
+ offsets: SourceLocation[]
185
+ }
186
+
187
+ type Visit = (node: Expression) => VisitResult[]
188
+
189
+ const codePart = (
190
+ codePart: string,
191
+ ownerNode: { location: Location }
192
+ ): VisitResult => ({
193
+ code: codePart,
194
+ offsets: [{ len: codePart.length, location: ownerNode.location }]
195
+ })
196
+
197
+ const combineVisitResults = (parts: VisitResult[]) => {
198
+ return parts.reduce((res, it) => {
199
+ return {
200
+ code: res.code + it.code,
201
+ offsets: res.offsets.concat(it.offsets)
202
+ } as VisitResult
203
+ })
204
+ }
205
+
206
+ const visitors: {
207
+ [P in keyof ExpressionByType]: (
208
+ node: ExpressionByType[P],
209
+ visit: Visit
210
+ ) => VisitResult[]
211
+ } = {
212
+ Literal: node => {
213
+ const parts: VisitResult[] = [codePart(JSON.stringify(node.value), node)]
214
+
215
+ return parts
216
+ },
217
+
218
+ Identifier: node => {
219
+ if (node.name === PIPE_LTR) return [codePart(PIPE_LTR, node)]
220
+
221
+ const parts: VisitResult[] = [
222
+ codePart(`get(${JSON.stringify(node.name)})`, node)
223
+ ]
224
+
225
+ return parts
226
+ },
227
+
228
+ UnaryExpression: (node, visit) => {
229
+ const parts: VisitResult[] = [
230
+ codePart(`uop["${node.operator}"](`, node),
231
+ ...visit(node.argument),
232
+ codePart(')', node)
233
+ ]
234
+
235
+ return parts
236
+ },
237
+
238
+ BinaryExpression: (node, visit) => {
239
+ const parts: VisitResult[] = [
240
+ codePart(`bop["${node.operator}"](`, node),
241
+ ...visit(node.left),
242
+ codePart(',', node),
243
+ ...visit(node.right),
244
+ codePart(')', node)
245
+ ]
246
+
247
+ return parts
248
+ },
249
+
250
+ LogicalExpression: (node, visit) => {
251
+ const parts: VisitResult[] = [
252
+ codePart(`bop["${node.operator}"](`, node),
253
+ ...visit(node.left),
254
+ codePart(',', node),
255
+ ...visit(node.right),
256
+ codePart(')', node)
257
+ ]
258
+
259
+ return parts
260
+ },
261
+
262
+ ConditionalExpression: (node, visit) => {
263
+ const parts: VisitResult[] = [
264
+ codePart('(bool(', node),
265
+ ...visit(node.test),
266
+ codePart(')?', node),
267
+ ...visit(node.consequent),
268
+ codePart(':', node),
269
+ ...(node.alternate !== null
270
+ ? visit(node.alternate)
271
+ : [codePart('undefined', node)]),
272
+ codePart(')', node)
273
+ ]
274
+
275
+ return parts
276
+ },
277
+
278
+ ObjectExpression: (node, visit) => {
279
+ const innerObj = node.properties
280
+ .map((p): [VisitResult, VisitResult[]] => {
281
+ if (p.key.type === 'Identifier') {
282
+ return [codePart(p.key.name, p), visit(p.value)]
283
+ }
284
+ //
285
+ else if (p.key.type === 'Literal') {
286
+ // TODO look for ECMA spec
287
+ return [codePart(JSON.stringify(p.key.value), p), visit(p.value)]
288
+ }
289
+ //
290
+ else {
291
+ // TODO Restrict on parse step
292
+ // TODO Error with locations
293
+ throw new TypeError(`Incorrect object key type ${p.key.type}`)
294
+ }
295
+ })
296
+ .flatMap(([k, v]) => {
297
+ return [k, codePart(':', node), ...v, codePart(',', node)]
298
+ })
299
+
300
+ // remove last comma
301
+ if (innerObj.length > 1) {
302
+ innerObj.pop()
303
+ }
304
+
305
+ const parts: VisitResult[] = [
306
+ codePart('{', node),
307
+ ...innerObj,
308
+ codePart('}', node)
309
+ ]
310
+
311
+ return parts
312
+ },
313
+
314
+ ArrayExpression: (node, visit) => {
315
+ const innerArrParts = node.elements.flatMap(el => {
316
+ return el === null
317
+ ? [codePart(',', node)]
318
+ : [...visit(el), codePart(',', node)]
319
+ })
320
+
321
+ // remove last comma
322
+ if (innerArrParts.length > 1) {
323
+ innerArrParts.pop()
324
+ }
325
+
326
+ const parts: VisitResult[] = [
327
+ codePart('[', node),
328
+ ...innerArrParts,
329
+ codePart(']', node)
330
+ ]
331
+
332
+ return parts
333
+ },
334
+
335
+ MemberExpression: (node, visit) => {
336
+ const { computed, object, property } = node
337
+
338
+ // TODO Pass computed to prop?
339
+
340
+ const parts: VisitResult[] = [
341
+ codePart('prop(', node),
342
+ ...visit(object),
343
+ codePart(',', node),
344
+ ...(computed
345
+ ? visit(property)
346
+ : [codePart(JSON.stringify(property.name), property)]),
347
+ codePart(')', node)
348
+ ]
349
+
350
+ return parts
351
+ },
352
+
353
+ CallExpression: (node, visit) => {
354
+ const innerArgs =
355
+ node.arguments.length > 0
356
+ ? node.arguments.flatMap(arg => [...visit(arg), codePart(',', node)])
357
+ : null
358
+
359
+ // remove last comma
360
+ innerArgs?.pop()
361
+
362
+ const parts: VisitResult[] = [
363
+ codePart('call(', node),
364
+ ...visit(node.callee),
365
+ codePart(',', node),
366
+ ...(innerArgs === null
367
+ ? [codePart('null', node)]
368
+ : [codePart('[', node), ...innerArgs, codePart(']', node)]),
369
+ codePart(')', node)
370
+ ]
371
+
372
+ return parts
373
+ },
374
+
375
+ NullishCoalescingExpression: (node, visit) => {
376
+ const parts: VisitResult[] = [
377
+ codePart('(', node),
378
+ ...visit(node.left),
379
+ codePart('??', node),
380
+ ...visit(node.right),
381
+ codePart(')', node)
382
+ ]
383
+
384
+ return parts
385
+ },
386
+
387
+ PipeSequence: (node, visit) => {
388
+ const headCode = visit(node.head)
389
+
390
+ const tailsCodeArrInner = node.tail.flatMap(t => {
391
+ const opt = t.operator === '|?'
392
+
393
+ const tailParts: VisitResult[] = [
394
+ codePart(
395
+ `{opt:${opt},next:function(${PIPE_LTR}){return `,
396
+ t.expression
397
+ ),
398
+ ...visit(t.expression),
399
+ codePart(`}}`, t.expression),
400
+ codePart(`,`, t.expression)
401
+ ]
402
+
403
+ return tailParts
404
+ })
405
+
406
+ // remove last comma
407
+ tailsCodeArrInner.pop()
408
+
409
+ const parts: VisitResult[] = [
410
+ codePart('pipe(', node),
411
+ ...headCode,
412
+ codePart(',[', node),
413
+ ...tailsCodeArrInner,
414
+ codePart('])', node)
415
+ ]
416
+
417
+ return parts
418
+ }
419
+ }
420
+
421
+ const visit: (
422
+ node: Expression,
423
+ parentNode: Expression | null
424
+ ) => VisitResult[] = node => {
425
+ const nodeTypeVisitor = visitors[node.type]
426
+
427
+ if (nodeTypeVisitor === undefined) {
428
+ throw new Error(`No handler for node type - ${node.type}`)
429
+ }
430
+
431
+ const innerVisit: Visit = (childNode: Expression) => {
432
+ return visit(childNode, node)
433
+ }
434
+
435
+ // @ts-expect-error skip node is never
436
+ return nodeTypeVisitor(node, innerVisit)
437
+ }
438
+
439
+ export function traverse(tree: ExpressionStatement): VisitResult {
440
+ return combineVisitResults(visit(tree.expression, null))
441
+ }
442
+
443
+ function getExpressionErrorLocation(
444
+ colOffset: number,
445
+ locations: SourceLocation[]
446
+ ): Location | null {
447
+ var curCol = 0
448
+ for (const loc of locations) {
449
+ curCol += loc.len
450
+ if (curCol >= colOffset) return loc.location
451
+ }
452
+ return null
453
+ }
454
+
455
+ export type CompileOptions<Data, Globals> = Partial<
456
+ ContextHelpers<Data, Globals> & ExpressionOperators & { globals: Globals }
457
+ >
458
+
459
+ export function compile<Data = Record<string, unknown>, Globals = null>(
460
+ expression: string,
461
+ options?: CompileOptions<Data, Globals>
462
+ ): (data?: Data) => unknown {
463
+ const tree = parse(expression) as ExpressionStatement
464
+ const traverseResult = traverse(tree)
465
+
466
+ const { code: expressionCode, offsets } = traverseResult
467
+
468
+ const bootstrapCodeHead = [
469
+ `var bool = ctx.castToBoolean;`,
470
+ `var bop = ctx.binaryOperators;`,
471
+ `var uop = ctx.unaryOperators;`,
472
+ `var call = ctx.callFunction;`,
473
+ `var getIdentifierValue = ctx.getIdentifierValue;`,
474
+ `var prop = ctx.getProperty;`,
475
+ `var pipe = ctx.pipe;`,
476
+ `var globals = ctx.globals ?? null;`,
477
+ `return data => {`,
478
+ `var get = name => getIdentifierValue(name, globals, data);`,
479
+ `return `
480
+ ].join('')
481
+
482
+ const bootstrapCodeHeadLen = bootstrapCodeHead.length
483
+
484
+ const functionCode = bootstrapCodeHead + expressionCode + ';}'
485
+
486
+ const func = new Function('ctx', functionCode)({
487
+ ...defaultContextHelpers,
488
+ ...{
489
+ unaryOperators: defaultUnaryOperators,
490
+ binaryOperators: defaultBinaryOperators
491
+ },
492
+ ...options
493
+ }) as (data?: Data) => unknown
494
+
495
+ return function (data?: Data) {
496
+ try {
497
+ return func(data)
498
+ } catch (err) {
499
+ assert.ok(err instanceof Error)
500
+
501
+ const stackRows = err.stack?.split('\n').map(row => row.trim())
502
+
503
+ const evalRow = stackRows?.find(row => row.startsWith('at eval '))
504
+
505
+ if (evalRow === undefined) {
506
+ throw err
507
+ }
508
+
509
+ ERROR_STACK_REGEX.lastIndex = 0
510
+ const match = ERROR_STACK_REGEX.exec(evalRow)
511
+
512
+ if (match == null) {
513
+ throw err
514
+ }
515
+
516
+ const rowOffsetStr = match.groups?.['row']
517
+ const colOffsetStr = match.groups?.['col']
518
+
519
+ if (rowOffsetStr === undefined || colOffsetStr === undefined) {
520
+ throw err
521
+ }
522
+
523
+ const rowOffset = Number.parseInt(rowOffsetStr)
524
+ assert.equal(rowOffset, 3)
525
+
526
+ const colOffset = Number.parseInt(colOffsetStr)
527
+ const adjustedColOffset = colOffset - bootstrapCodeHeadLen
528
+ assert.ok(adjustedColOffset >= 0)
529
+
530
+ const errorLocation = getExpressionErrorLocation(
531
+ adjustedColOffset,
532
+ offsets
533
+ )
534
+
535
+ throw new ExpressionError(err, errorLocation)
536
+ }
537
+ }
538
+ }
package/src/errors.ts ADDED
@@ -0,0 +1,21 @@
1
+ import { Location } from './simplex-tree.js'
2
+
3
+ export class ExpressionError extends Error {
4
+ constructor(
5
+ error: Error,
6
+ public location: Location | null
7
+ ) {
8
+ super(error.message, { cause: error })
9
+ }
10
+ }
11
+
12
+ export class UnexpectedTypeError extends TypeError {
13
+ I18N_STRING = 'UNEXPECTED_TYPE'
14
+
15
+ constructor(
16
+ public expectedType: string,
17
+ public receivedType: string
18
+ ) {
19
+ super(`Expected ${expectedType}, but got ${receivedType} instead.`)
20
+ }
21
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './compiler.js'
2
+ export * from './errors.js'
3
+ export * from './simplex-tree.js'