eyeleng 1.0.8 → 1.0.9

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.
@@ -906,7 +906,7 @@
906
906
  peekN(n) { return this.tokens[this.pos + n] || this.tokens[this.tokens.length - 1]; }
907
907
  previous() { return this.tokens[this.pos - 1]; }
908
908
  strictGrammar() { return !!this.options.strictGrammar; }
909
- error(message, token = this.peek()) { return new SyntaxErrorWithLocation(message, token); }
909
+ error(message, token = this.peek()) { return new SyntaxErrorWithLocation(message, token && token.filename ? token : { ...token, filename: this.options.filename || '<input>' }); }
910
910
  }
911
911
 
912
912
 
@@ -1055,7 +1055,7 @@
1055
1055
 
1056
1056
  function current() { return source[i]; }
1057
1057
  function peek(n = 1) { return source[i + n]; }
1058
- function startsWith(text) { return source.slice(i, i + text.length) === text; }
1058
+ function startsWith(text) { return source.startsWith(text, i); }
1059
1059
  function advance() {
1060
1060
  const ch = source[i++];
1061
1061
  if (ch === '\n') { line += 1; column = 1; }
@@ -1063,7 +1063,7 @@
1063
1063
  return ch;
1064
1064
  }
1065
1065
  function token(type, value, startLine, startColumn, extra = {}) {
1066
- tokens.push({ type, value, line: startLine, column: startColumn, filename, ...extra });
1066
+ tokens.push({ type, value, line: startLine, column: startColumn, ...extra });
1067
1067
  }
1068
1068
  function syntax(message, startLine, startColumn) {
1069
1069
  throw new SyntaxErrorWithLocation(message, { line: startLine, column: startColumn, filename });
@@ -1071,19 +1071,21 @@
1071
1071
 
1072
1072
  function readNumericLiteral() {
1073
1073
  let value = '';
1074
- while (i < source.length && /[0-9]/.test(current())) value += advance();
1075
- if (current() === '.' && /[0-9]/.test(peek())) {
1076
- value += advance();
1077
- while (i < source.length && /[0-9]/.test(current())) value += advance();
1074
+ const start = i;
1075
+ while (i < source.length && isDigitCode(source.charCodeAt(i))) { i += 1; column += 1; }
1076
+ if (source[i] === '.' && isDigitCode(source.charCodeAt(i + 1))) {
1077
+ i += 1; column += 1;
1078
+ while (i < source.length && isDigitCode(source.charCodeAt(i))) { i += 1; column += 1; }
1078
1079
  }
1080
+ value = source.slice(start, i);
1079
1081
  if (current() === 'e' || current() === 'E') {
1080
1082
  const saveI = i;
1081
1083
  const saveLine = line;
1082
1084
  const saveColumn = column;
1083
1085
  let exponent = advance();
1084
1086
  if (current() === '+' || current() === '-') exponent += advance();
1085
- if (/[0-9]/.test(current())) {
1086
- while (i < source.length && /[0-9]/.test(current())) exponent += advance();
1087
+ if (isDigitCode(source.charCodeAt(i))) {
1088
+ while (i < source.length && isDigitCode(source.charCodeAt(i))) exponent += advance();
1087
1089
  value += exponent;
1088
1090
  } else {
1089
1091
  i = saveI;
@@ -1101,7 +1103,7 @@
1101
1103
  const length = esc === 'u' ? 4 : 8;
1102
1104
  let hex = '';
1103
1105
  for (let j = 0; j < length; j += 1) {
1104
- if (!/[0-9A-Fa-f]/.test(current() || '')) syntax(`Invalid \\${esc} escape`, startLine, startColumn);
1106
+ if (!isHexCode(source.charCodeAt(i))) syntax(`Invalid \\${esc} escape`, startLine, startColumn);
1105
1107
  hex += advance();
1106
1108
  }
1107
1109
  const codePoint = Number.parseInt(hex, 16);
@@ -1120,7 +1122,7 @@
1120
1122
  const length = esc === 'u' ? 4 : 8;
1121
1123
  let hex = '';
1122
1124
  for (let j = 0; j < length; j += 1) {
1123
- if (!/[0-9A-Fa-f]/.test(current() || '')) syntax(`Invalid \\${esc} escape`, startLine, startColumn);
1125
+ if (!isHexCode(source.charCodeAt(i))) syntax(`Invalid \\${esc} escape`, startLine, startColumn);
1124
1126
  hex += advance();
1125
1127
  }
1126
1128
  const codePoint = Number.parseInt(hex, 16);
@@ -1134,7 +1136,7 @@
1134
1136
 
1135
1137
  while (i < source.length) {
1136
1138
  const ch = current();
1137
- if (/\s/.test(ch)) { advance(); continue; }
1139
+ if (isWhitespaceCode(source.charCodeAt(i))) { advance(); continue; }
1138
1140
  if (ch === '#') {
1139
1141
  while (i < source.length && current() !== '\n') advance();
1140
1142
  continue;
@@ -1220,18 +1222,21 @@
1220
1222
  }
1221
1223
 
1222
1224
  if (ch === '@') {
1223
- let value = advance();
1224
- while (i < source.length && /[A-Za-z0-9-]/.test(current())) value += advance();
1225
+ const wordStart = i;
1226
+ advance();
1227
+ while (i < source.length && isLangTagCode(source.charCodeAt(i))) { i += 1; column += 1; }
1228
+ const value = source.slice(wordStart, i);
1225
1229
  if (!/^@[A-Za-z]+(?:-[A-Za-z0-9]+)*(?:--[A-Za-z]+)?$/.test(value)) syntax(`Invalid language tag ${value}`, startLine, startColumn);
1226
1230
  token('word', value, startLine, startColumn);
1227
1231
  continue;
1228
1232
  }
1229
1233
 
1230
1234
  if (ch === '?' || ch === '$') {
1231
- let value = advance();
1232
- while (i < source.length && /[A-Za-z0-9_\-]/.test(current())) value += advance();
1233
- if (value.length === 1) syntax('Expected variable name', startLine, startColumn);
1234
- token('variable', value.slice(1), startLine, startColumn);
1235
+ const varStart = i;
1236
+ advance();
1237
+ while (i < source.length && isVarNameCode(source.charCodeAt(i))) { i += 1; column += 1; }
1238
+ if (i - varStart === 1) syntax('Expected variable name', startLine, startColumn);
1239
+ token('variable', source.slice(varStart + 1, i), startLine, startColumn);
1235
1240
  continue;
1236
1241
  }
1237
1242
 
@@ -1258,24 +1263,27 @@
1258
1263
  continue;
1259
1264
  }
1260
1265
 
1261
- let value = '';
1266
+ const wordStart = i;
1262
1267
  while (i < source.length) {
1263
- const c = current();
1264
- if (c === '\\' && peek() !== undefined) {
1265
- value += advance();
1266
- value += advance();
1268
+ const c = source[i];
1269
+ if (c === '\\' && source[i + 1] !== undefined) {
1270
+ i += 2;
1271
+ column += 2;
1267
1272
  continue;
1268
1273
  }
1269
- if (/\s/.test(c) || '{}()[],;|'.includes(c) || '=<>+-*/!^~'.includes(c)) break;
1274
+ const code = source.charCodeAt(i);
1275
+ if (isWhitespaceCode(code) || '{}()[],;|'.includes(c) || '=<>+-*/!^~'.includes(c)) break;
1270
1276
  if (c === '.') {
1271
- const n = peek();
1272
- if (n === undefined || /\s/.test(n) || '{}()[],;|'.includes(n) || '=<>+-*/!^~'.includes(n)) break;
1277
+ const n = source[i + 1];
1278
+ if (n === undefined || isWhitespaceCode(n.charCodeAt(0)) || '{}()[],;|'.includes(n) || '=<>+-*/!^~'.includes(n)) break;
1273
1279
  }
1274
1280
  if (c === '#') break;
1275
- value += advance();
1281
+ i += 1;
1282
+ column += 1;
1276
1283
  }
1277
- if (value.length === 0) syntax(`Unexpected character ${JSON.stringify(ch)}`, startLine, startColumn);
1284
+ if (i === wordStart) syntax(`Unexpected character ${JSON.stringify(ch)}`, startLine, startColumn);
1278
1285
 
1286
+ const value = source.slice(wordStart, i);
1279
1287
  if (/^[+-]?(?:(?:\d+\.\d*|\.\d+)(?:[eE][+-]?\d+)?|\d+[eE][+-]?\d+|\d+)$/.test(value)) token('number', Number(value), startLine, startColumn);
1280
1288
  else token('word', value, startLine, startColumn);
1281
1289
  }
@@ -1284,11 +1292,32 @@
1284
1292
  return tokens;
1285
1293
  }
1286
1294
 
1295
+
1296
+ function isDigitCode(code) {
1297
+ return code >= 48 && code <= 57;
1298
+ }
1299
+
1300
+ function isHexCode(code) {
1301
+ return (code >= 48 && code <= 57) || (code >= 65 && code <= 70) || (code >= 97 && code <= 102);
1302
+ }
1303
+
1304
+ function isWhitespaceCode(code) {
1305
+ return code === 32 || code === 9 || code === 10 || code === 13 || code === 12;
1306
+ }
1307
+
1308
+ function isLangTagCode(code) {
1309
+ return (code >= 65 && code <= 90) || (code >= 97 && code <= 122) || (code >= 48 && code <= 57) || code === 45;
1310
+ }
1311
+
1312
+ function isVarNameCode(code) {
1313
+ return (code >= 65 && code <= 90) || (code >= 97 && code <= 122) || (code >= 48 && code <= 57) || code === 95 || code === 45;
1314
+ }
1315
+
1287
1316
  function startsNumericLiteral(source, i) {
1288
1317
  const ch = source[i];
1289
1318
  const next = source[i + 1];
1290
- if (/[0-9]/.test(ch)) return true;
1291
- if (ch === '.' && /[0-9]/.test(next)) return true;
1319
+ if (isDigitCode(ch.charCodeAt(0))) return true;
1320
+ if (ch === '.' && next !== undefined && isDigitCode(next.charCodeAt(0))) return true;
1292
1321
  return false;
1293
1322
  }
1294
1323
 
@@ -2918,11 +2947,13 @@
2918
2947
  }
2919
2948
 
2920
2949
  function variable(name) {
2921
- return { type: 'var', value: String(name).replace(/^[?$]/, '') };
2950
+ const value = String(name);
2951
+ return { type: 'var', value: value[0] === '?' || value[0] === '$' ? value.slice(1) : value };
2922
2952
  }
2923
2953
 
2924
2954
  function blankNode(value) {
2925
- return { type: 'blank', value: String(value).replace(/^_:/, '') };
2955
+ const label = String(value);
2956
+ return { type: 'blank', value: label.startsWith('_:') ? label.slice(2) : label };
2926
2957
  }
2927
2958
 
2928
2959
  function literal(value, datatype = null, lang = null, langDir = null) {
@@ -3177,6 +3208,8 @@
3177
3208
  const RDF_LANGSTRING = `${RDF_NS}langString`;
3178
3209
  const RDF_DIRLANGSTRING = `${RDF_NS}dirLangString`;
3179
3210
  const NUMERIC_DATATYPES = new Set([XSD_INTEGER, XSD_DECIMAL, XSD_DOUBLE]);
3211
+ const MAX_SAFE_INTEGER_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
3212
+ const MIN_SAFE_INTEGER_BIGINT = BigInt(Number.MIN_SAFE_INTEGER);
3180
3213
 
3181
3214
  // This table is intentionally shaped by the SHACL 1.2 Rules grammar production BuiltInCall.
3182
3215
  // Keys are the canonical spellings used by the draft; lookup is case-insensitive so examples
@@ -3336,7 +3369,7 @@
3336
3369
  }
3337
3370
 
3338
3371
  function fromIntegerResult(value) {
3339
- if (value <= BigInt(Number.MAX_SAFE_INTEGER) && value >= BigInt(Number.MIN_SAFE_INTEGER)) return Number(value);
3372
+ if (value <= MAX_SAFE_INTEGER_BIGINT && value >= MIN_SAFE_INTEGER_BIGINT) return Number(value);
3340
3373
  return value;
3341
3374
  }
3342
3375
 
@@ -4047,6 +4080,18 @@
4047
4080
  layerIndexes,
4048
4081
  analysis.dependency ? analysis.dependency.edges : [],
4049
4082
  );
4083
+ const baseContext = {
4084
+ ...evalOptions,
4085
+ maxIterations,
4086
+ inputKeys,
4087
+ inferred,
4088
+ trace,
4089
+ perRule,
4090
+ layer: 0,
4091
+ iteration: 0,
4092
+ startingIterations: 0,
4093
+ recursiveLayer: false,
4094
+ };
4050
4095
 
4051
4096
  for (let layerIndex = 0; layerIndex < layerIndexes.length; layerIndex += 1) {
4052
4097
  const layer = layerIndexes[layerIndex];
@@ -4056,30 +4101,17 @@
4056
4101
  if (runOnce.length > 0) {
4057
4102
  iterations += 1;
4058
4103
  for (const ruleIndex of runOnce) {
4059
- const added = applyRuleOnce(program, store, ruleIndex, {
4060
- ...evalOptions,
4061
- inputKeys,
4062
- inferred,
4063
- trace,
4064
- perRule,
4065
- layer: layerIndex + 1,
4066
- iteration: iterations,
4067
- });
4104
+ baseContext.layer = layerIndex + 1;
4105
+ baseContext.iteration = iterations;
4106
+ const added = applyRuleOnce(program, store, ruleIndex, baseContext);
4068
4107
  ruleApplications += added.applications;
4069
4108
  }
4070
4109
  }
4071
4110
 
4072
- const ordinaryResult = runRulesToFixpoint(program, store, ordinary, {
4073
- ...evalOptions,
4074
- maxIterations,
4075
- inputKeys,
4076
- inferred,
4077
- trace,
4078
- perRule,
4079
- layer: layerIndex + 1,
4080
- startingIterations: iterations,
4081
- recursiveLayer: recursiveLayerFlags[layerIndex],
4082
- });
4111
+ baseContext.layer = layerIndex + 1;
4112
+ baseContext.startingIterations = iterations;
4113
+ baseContext.recursiveLayer = recursiveLayerFlags[layerIndex];
4114
+ const ordinaryResult = runRulesToFixpoint(program, store, ordinary, baseContext);
4083
4115
  iterations = ordinaryResult.iterations;
4084
4116
  ruleApplications += ordinaryResult.ruleApplications;
4085
4117
  }
@@ -4110,10 +4142,8 @@
4110
4142
  const iteration = context.startingIterations + 1;
4111
4143
  let ruleApplications = 0;
4112
4144
  for (const ruleIndex of ruleIndexes) {
4113
- const applied = applyRuleOnce(program, store, ruleIndex, {
4114
- ...context,
4115
- iteration,
4116
- });
4145
+ context.iteration = iteration;
4146
+ const applied = applyRuleOnce(program, store, ruleIndex, context);
4117
4147
  ruleApplications += applied.applications;
4118
4148
  }
4119
4149
  return { iterations: iteration, ruleApplications };
@@ -4129,10 +4159,8 @@
4129
4159
  let addedInIteration = 0;
4130
4160
 
4131
4161
  for (const ruleIndex of ruleIndexes) {
4132
- const applied = applyRuleOnce(program, store, ruleIndex, {
4133
- ...context,
4134
- iteration: iterations,
4135
- });
4162
+ context.iteration = iterations;
4163
+ const applied = applyRuleOnce(program, store, ruleIndex, context);
4136
4164
  addedInIteration += applied.added;
4137
4165
  ruleApplications += applied.applications;
4138
4166
  }
@@ -4161,16 +4189,24 @@
4161
4189
  return flags;
4162
4190
  }
4163
4191
 
4192
+
4164
4193
  function applyRuleOnce(program, store, ruleIndex, context) {
4165
4194
  const rule = program.rules[ruleIndex];
4166
4195
  let applications = 0;
4167
4196
  let added = 0;
4168
- const seenBindings = new Set();
4197
+ const dedupeBindings = rule.body.some((clause) => clause.type === 'path');
4198
+ const seenBindings = dedupeBindings ? new Set() : null;
4169
4199
 
4170
- for (const binding of evaluateBodyStream(rule.body, store, {}, context)) {
4171
- const key = bindingKey(binding);
4172
- if (seenBindings.has(key)) continue;
4173
- seenBindings.add(key);
4200
+ const bodyBindings = rule.body.length === 1 && rule.body[0].type === 'triple'
4201
+ ? store.match(rule.body[0].triple, {})
4202
+ : evaluateBodyStream(rule.body, store, {}, context);
4203
+
4204
+ for (const binding of bodyBindings) {
4205
+ if (seenBindings) {
4206
+ const key = bindingKey(binding);
4207
+ if (seenBindings.has(key)) continue;
4208
+ seenBindings.add(key);
4209
+ }
4174
4210
  applications += 1;
4175
4211
  context.perRule[ruleIndex].applications += 1;
4176
4212
 
@@ -4289,7 +4325,7 @@
4289
4325
  "src/store.js": function (require, module, exports) {
4290
4326
  'use strict';
4291
4327
 
4292
- const { tripleKey, termKey, termEquals, cloneTerm } = require('./term.js');
4328
+ const { tripleKey, termKey, termEquals } = require('./term.js');
4293
4329
 
4294
4330
  class TripleStore {
4295
4331
  constructor(triples = []) {
@@ -4398,7 +4434,7 @@
4398
4434
  }
4399
4435
 
4400
4436
  function normalizeTriple(triple) {
4401
- return { s: cloneTerm(triple.s), p: cloneTerm(triple.p), o: cloneTerm(triple.o) };
4437
+ return { s: triple.s, p: triple.p, o: triple.o };
4402
4438
  }
4403
4439
 
4404
4440
  function bindingKey(binding) {
@@ -4558,9 +4594,7 @@
4558
4594
 
4559
4595
  program.rules.forEach((rule, index) => {
4560
4596
  const name = ruleName(rule, index);
4561
- const label = displayRuleName(name, program.prefixes || {});
4562
4597
  const bound = boundVariables(rule.body);
4563
- const positive = positiveVariables(rule.body);
4564
4598
  const head = new Set();
4565
4599
  for (const triple of rule.head) collectTripleVars(triple, head);
4566
4600
 
@@ -4570,7 +4604,7 @@
4570
4604
  code: 'unsafe-head-variable',
4571
4605
  severity: 'error',
4572
4606
  rule: name,
4573
- message: `${label} has unbound head variable ?${variable}`,
4607
+ message: `${displayRuleName(name, program.prefixes || {})} has unbound head variable ?${variable}`,
4574
4608
  });
4575
4609
  }
4576
4610
  }
@@ -4581,19 +4615,19 @@
4581
4615
  code: 'invalid-head-predicate',
4582
4616
  severity: 'error',
4583
4617
  rule: name,
4584
- message: `${label} has a non-IRI/non-variable predicate in the head`,
4618
+ message: `${displayRuleName(name, program.prefixes || {})} has a non-IRI/non-variable predicate in the head`,
4585
4619
  });
4586
4620
  }
4587
4621
  }
4588
4622
 
4589
- diagnostics.push(...sequentialWellFormednessDiagnostics(rule.body, name, label));
4623
+ diagnostics.push(...sequentialWellFormednessDiagnostics(rule.body, name, program.prefixes || {}));
4590
4624
 
4591
4625
  if (rule.runOnce && recursiveIndexes.has(index)) {
4592
4626
  diagnostics.push({
4593
4627
  code: 'recursive-assignment-rule',
4594
4628
  severity: 'warning',
4595
4629
  rule: name,
4596
- message: `${label} is a run-once rule in a recursive dependency cycle`,
4630
+ message: `${displayRuleName(name, program.prefixes || {})} is a run-once rule in a recursive dependency cycle`,
4597
4631
  });
4598
4632
  }
4599
4633
 
@@ -4949,7 +4983,7 @@
4949
4983
  return components;
4950
4984
  }
4951
4985
 
4952
- function sequentialWellFormednessDiagnostics(clauses, ruleNameValue, label) {
4986
+ function sequentialWellFormednessDiagnostics(clauses, ruleNameValue, prefixes = {}) {
4953
4987
  const diagnostics = [];
4954
4988
 
4955
4989
  function visit(items, initialBound, scopeLabel) {
@@ -4964,7 +4998,7 @@
4964
4998
  code: 'unbound-filter-variable',
4965
4999
  severity: 'error',
4966
5000
  rule: ruleNameValue,
4967
- message: `${label} FILTER uses ?${variable} before it is bound${scopeLabel}`,
5001
+ message: `${displayRuleName(ruleNameValue, prefixes)} FILTER uses ?${variable} before it is bound${scopeLabel}`,
4968
5002
  });
4969
5003
  }
4970
5004
  }
@@ -4974,7 +5008,7 @@
4974
5008
  code: 'assignment-variable-already-bound',
4975
5009
  severity: 'error',
4976
5010
  rule: ruleNameValue,
4977
- message: `${label} SET assigns ?${clause.variable}, but that variable is already bound${scopeLabel}`,
5011
+ message: `${displayRuleName(ruleNameValue, prefixes)} SET assigns ?${clause.variable}, but that variable is already bound${scopeLabel}`,
4978
5012
  });
4979
5013
  }
4980
5014
  for (const variable of expressionVariables(clause.expr)) {
@@ -4983,7 +5017,7 @@
4983
5017
  code: 'unbound-assignment-variable',
4984
5018
  severity: 'error',
4985
5019
  rule: ruleNameValue,
4986
- message: `${label} SET expression uses ?${variable} before it is bound${scopeLabel}`,
5020
+ message: `${displayRuleName(ruleNameValue, prefixes)} SET expression uses ?${variable} before it is bound${scopeLabel}`,
4987
5021
  });
4988
5022
  }
4989
5023
  }